Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 20 Sep 2016 08:56:24 +0000 (UTC)
From:      Wojciech Macek <wma@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org
Subject:   svn commit: r306016 - vendor-sys/alpine-hal/dist
Message-ID:  <201609200856.u8K8uOlu015151@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: wma
Date: Tue Sep 20 08:56:24 2016
New Revision: 306016
URL: https://svnweb.freebsd.org/changeset/base/306016

Log:
  Update Annapurna Alpine HAL
  
  alpine-hal SerDes file was omitted in the previous commit.
  Files added here.

Added:
  vendor-sys/alpine-hal/dist/al_hal_serdes_hssp.c
     - copied unchanged from r306015, vendor-sys/alpine-hal/dist/al_hal_serdes.c
Deleted:
  vendor-sys/alpine-hal/dist/al_hal_serdes.c

Copied: vendor-sys/alpine-hal/dist/al_hal_serdes_hssp.c (from r306015, vendor-sys/alpine-hal/dist/al_hal_serdes.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ vendor-sys/alpine-hal/dist/al_hal_serdes_hssp.c	Tue Sep 20 08:56:24 2016	(r306016, copy of r306015, vendor-sys/alpine-hal/dist/al_hal_serdes.c)
@@ -0,0 +1,3164 @@
+/*******************************************************************************
+Copyright (C) 2015 Annapurna Labs Ltd.
+
+This file may be licensed under the terms of the Annapurna Labs Commercial
+License Agreement.
+
+Alternatively, this file can be distributed under the terms of the GNU General
+Public License V2 as published by the Free Software Foundation and can be
+found at http://www.gnu.org/licenses/gpl-2.0.html
+
+Alternatively, redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the following conditions are
+met:
+
+    *     Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+    *     Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "al_hal_serdes_hssp.h"
+#include "al_hal_serdes_hssp_regs.h"
+#include "al_hal_serdes_hssp_internal_regs.h"
+
+#define SRDS_CORE_REG_ADDR(page, type, offset)\
+	(((page) << 13) | ((type) << 12) | (offset))
+
+/* Link Training configuration */
+#define AL_SERDES_TX_DEEMPH_SUM_MAX		0x1b
+
+/* c configurations */
+#define AL_SERDES_TX_DEEMPH_C_ZERO_MAX_VAL	0x1b
+#define AL_SERDES_TX_DEEMPH_C_ZERO_MIN_VAL	0
+#define AL_SERDES_TX_DEEMPH_C_ZERO_PRESET	AL_SERDES_TX_DEEMPH_C_ZERO_MAX_VAL
+
+/* c(+1) configurations */
+#define AL_SERDES_TX_DEEMPH_C_PLUS_MAX_VAL	0x9
+#define AL_SERDES_TX_DEEMPH_C_PLUS_MIN_VAL	0
+#define AL_SERDES_TX_DEEMPH_C_PLUS_PRESET	AL_SERDES_TX_DEEMPH_C_PLUS_MIN_VAL
+
+/* c(-1) configurations */
+#define AL_SERDES_TX_DEEMPH_C_MINUS_MAX_VAL	0x6
+#define AL_SERDES_TX_DEEMPH_C_MINUS_MIN_VAL	0
+#define AL_SERDES_TX_DEEMPH_C_MINUS_PRESET	AL_SERDES_TX_DEEMPH_C_MINUS_MIN_VAL
+
+/* Rx equal total delay = MDELAY * TRIES */
+#define AL_SERDES_RX_EQUAL_MDELAY		10
+#define AL_SERDES_RX_EQUAL_TRIES		50
+
+/* Rx eye calculation delay = MDELAY * TRIES */
+#define AL_SERDES_RX_EYE_CAL_MDELAY		50
+#define AL_SERDES_RX_EYE_CAL_TRIES		70
+
+#if (!defined(AL_SERDES_BASIC_SERVICES_ONLY)) || (AL_SERDES_BASIC_SERVICES_ONLY == 0)
+#define AL_SRDS_ADV_SRVC(func)			func
+#else
+static void al_serdes_hssp_stub_func(void)
+{
+	al_err("%s: not implemented service called!\n", __func__);
+}
+
+#define AL_SRDS_ADV_SRVC(func)			((typeof(func) *)al_serdes_hssp_stub_func)
+#endif
+
+/**
+ * SERDES core reg read
+ */
+static inline uint8_t al_serdes_grp_reg_read(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_reg_page		page,
+	enum al_serdes_reg_type		type,
+	uint16_t			offset);
+
+/**
+ * SERDES core reg write
+ */
+static inline void al_serdes_grp_reg_write(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_reg_page		page,
+	enum al_serdes_reg_type		type,
+	uint16_t			offset,
+	uint8_t				data);
+
+/**
+ * SERDES core masked reg write
+ */
+static inline void al_serdes_grp_reg_masked_write(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_reg_page		page,
+	enum al_serdes_reg_type		type,
+	uint16_t			offset,
+	uint8_t				mask,
+	uint8_t				data);
+
+/**
+ * Lane Rx rate change software flow disable
+ */
+static void _al_serdes_lane_rx_rate_change_sw_flow_dis(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_lane		lane);
+
+/**
+ * Group Rx rate change software flow enable if all conditions met
+ */
+static void al_serdes_group_rx_rate_change_sw_flow_dis(
+	struct al_serdes_grp_obj	*obj);
+
+/**
+ * Lane Rx rate change software flow enable if all conditions met
+ */
+static void _al_serdes_lane_rx_rate_change_sw_flow_en_cond(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_lane		lane);
+
+/**
+ * Group Rx rate change software flow enable if all conditions met
+ */
+static void al_serdes_group_rx_rate_change_sw_flow_en_cond(
+	struct al_serdes_grp_obj	*obj);
+
+/******************************************************************************/
+/******************************************************************************/
+static enum al_serdes_type al_serdes_hssp_type_get(void)
+{
+	return AL_SRDS_TYPE_HSSP;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static int al_serdes_reg_read(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_reg_page		page,
+	enum al_serdes_reg_type		type,
+	uint16_t			offset,
+	uint8_t				*data)
+{
+	int status = 0;
+
+	al_dbg(
+		"%s(%p, %d, %d, %u)\n",
+		__func__,
+		obj,
+		page,
+		type,
+		offset);
+
+	al_assert(obj);
+	al_assert(data);
+	al_assert(((int)page) >= AL_SRDS_REG_PAGE_0_LANE_0);
+	al_assert(((int)page) <= AL_SRDS_REG_PAGE_4_COMMON);
+	al_assert(((int)type) >= AL_SRDS_REG_TYPE_PMA);
+	al_assert(((int)type) <= AL_SRDS_REG_TYPE_PCS);
+
+	*data = al_serdes_grp_reg_read(
+		obj,
+		page,
+		type,
+		offset);
+
+	al_dbg(
+		"%s: return(%u)\n",
+		__func__,
+		*data);
+
+	return status;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static int al_serdes_reg_write(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_reg_page		page,
+	enum al_serdes_reg_type		type,
+	uint16_t			offset,
+	uint8_t				data)
+{
+	int status = 0;
+
+	al_dbg(
+		"%s(%p, %d, %d, %u, %u)\n",
+		__func__,
+		obj,
+		page,
+		type,
+		offset,
+		data);
+
+	al_assert(obj);
+	al_assert(((int)page) >= AL_SRDS_REG_PAGE_0_LANE_0);
+	al_assert(((int)page) <= AL_SRDS_REG_PAGE_0123_LANES_0123);
+	al_assert(((int)type) >= AL_SRDS_REG_TYPE_PMA);
+	al_assert(((int)type) <= AL_SRDS_REG_TYPE_PCS);
+
+	al_serdes_grp_reg_write(
+		obj,
+		page,
+		type,
+		offset,
+		data);
+
+	return status;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+#if (SERDES_IREG_FLD_PCSRX_DATAWIDTH_REG_NUM != SERDES_IREG_FLD_PCSTX_DATAWIDTH_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_PCSRX_DIVRATE_REG_NUM != SERDES_IREG_FLD_PCSTX_DIVRATE_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN_REG_NUM != SERDES_IREG_FLD_CMNPCS_LOCWREN_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN_REG_NUM != SERDES_IREG_FLD_CMNPCSBIST_LOCWREN_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN_REG_NUM != SERDES_IREG_FLD_CMNPCSPSTATE_LOCWREN_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM != SERDES_IREG_FLD_LB_LOCWREN_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM != SERDES_IREG_FLD_PCSRX_LOCWREN_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM != SERDES_IREG_FLD_PCSRXBIST_LOCWREN_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM != SERDES_IREG_FLD_PCSRXEQ_LOCWREN_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM != SERDES_IREG_FLD_PCSTX_LOCWREN_REG_NUM)
+#error "Wrong assumption!"
+#endif
+static void al_serdes_bist_overrides_enable(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_rate		rate)
+{
+	int i;
+
+	uint8_t rx_rate_val;
+	uint8_t tx_rate_val;
+
+	switch (rate) {
+	case AL_SRDS_RATE_1_8:
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_8;
+		tx_rate_val = SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_8;
+		break;
+	case AL_SRDS_RATE_1_4:
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_4;
+		tx_rate_val = SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_4;
+		break;
+	case AL_SRDS_RATE_1_2:
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_2;
+		tx_rate_val = SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_2;
+		break;
+	case AL_SRDS_RATE_FULL:
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_1;
+		tx_rate_val = SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_1;
+		break;
+	default:
+		al_err("%s: invalid rate (%d)\n",  __func__, rate);
+		al_assert(0);
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_1;
+		tx_rate_val = SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_1;
+	}
+
+	for (i = 0; i < AL_SRDS_NUM_LANES; i++) {
+		al_serdes_grp_reg_masked_write(
+			obj,
+			(enum al_serdes_reg_page)i,
+			AL_SRDS_REG_TYPE_PMA,
+			SERDES_IREG_FLD_PCSRX_DATAWIDTH_REG_NUM,
+			SERDES_IREG_FLD_PCSRX_DATAWIDTH_MASK |
+			SERDES_IREG_FLD_PCSTX_DATAWIDTH_MASK,
+			SERDES_IREG_FLD_PCSRX_DATAWIDTH_VAL_20 |
+			SERDES_IREG_FLD_PCSTX_DATAWIDTH_VAL_20);
+
+		al_serdes_grp_reg_masked_write(
+			obj,
+			(enum al_serdes_reg_page)i,
+			AL_SRDS_REG_TYPE_PMA,
+			SERDES_IREG_FLD_PCSRX_DIVRATE_REG_NUM,
+			SERDES_IREG_FLD_PCSRX_DIVRATE_MASK |
+			SERDES_IREG_FLD_PCSTX_DIVRATE_MASK,
+			rx_rate_val | tx_rate_val);
+	}
+
+	al_serdes_grp_reg_masked_write(
+		obj,
+		AL_SRDS_REG_PAGE_4_COMMON,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN_REG_NUM,
+		SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN |
+		SERDES_IREG_FLD_CMNPCS_LOCWREN |
+		SERDES_IREG_FLD_CMNPCSBIST_LOCWREN |
+		SERDES_IREG_FLD_CMNPCSPSTATE_LOCWREN,
+		0);
+
+	al_serdes_grp_reg_masked_write(
+		obj,
+		AL_SRDS_REG_PAGE_4_COMMON,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN_REG_NUM,
+		SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN |
+		SERDES_IREG_FLD_CMNPCS_LOCWREN |
+		SERDES_IREG_FLD_CMNPCSBIST_LOCWREN |
+		SERDES_IREG_FLD_CMNPCSPSTATE_LOCWREN,
+		0);
+
+	al_serdes_grp_reg_masked_write(
+		obj,
+		AL_SRDS_REG_PAGE_4_COMMON,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_PCS_LOCWREN_REG_NUM,
+		SERDES_IREG_FLD_PCS_LOCWREN,
+		0);
+
+	al_serdes_grp_reg_masked_write(
+		obj,
+		AL_SRDS_REG_PAGE_4_COMMON,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_CMNPCS_TXENABLE_REG_NUM,
+		SERDES_IREG_FLD_CMNPCS_TXENABLE,
+		SERDES_IREG_FLD_CMNPCS_TXENABLE);
+
+	for (i = 0; i < AL_SRDS_NUM_LANES; i++) {
+		al_serdes_grp_reg_masked_write(
+			obj,
+			(enum al_serdes_reg_page)i,
+			AL_SRDS_REG_TYPE_PMA,
+			SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM,
+			SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN |
+			SERDES_IREG_FLD_LB_LOCWREN |
+			SERDES_IREG_FLD_PCSRX_LOCWREN |
+			SERDES_IREG_FLD_PCSRXBIST_LOCWREN |
+			SERDES_IREG_FLD_PCSRXEQ_LOCWREN |
+			SERDES_IREG_FLD_PCSTX_LOCWREN,
+			0);
+
+		al_serdes_grp_reg_masked_write(
+			obj,
+			(enum al_serdes_reg_page)i,
+			AL_SRDS_REG_TYPE_PMA,
+			SERDES_IREG_FLD_PCSTXBIST_LOCWREN_REG_NUM,
+			SERDES_IREG_FLD_PCSTXBIST_LOCWREN,
+			0);
+
+		al_serdes_grp_reg_masked_write(
+			obj,
+			(enum al_serdes_reg_page)i,
+			AL_SRDS_REG_TYPE_PMA,
+			SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN_REG_NUM,
+			SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN,
+			0);
+
+		al_serdes_grp_reg_masked_write(
+			obj,
+			(enum al_serdes_reg_page)i,
+			AL_SRDS_REG_TYPE_PMA,
+			SERDES_IREG_FLD_RXLOCK2REF_OVREN_REG_NUM,
+			SERDES_IREG_FLD_RXLOCK2REF_OVREN,
+			SERDES_IREG_FLD_RXLOCK2REF_OVREN);
+	}
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static void al_serdes_bist_overrides_disable(
+	struct al_serdes_grp_obj	*obj)
+{
+	int i;
+
+	al_serdes_grp_reg_masked_write(
+		obj,
+		AL_SRDS_REG_PAGE_4_COMMON,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN_REG_NUM,
+		SERDES_IREG_FLD_CMNPCSBIST_LOCWREN,
+		SERDES_IREG_FLD_CMNPCSBIST_LOCWREN);
+
+	for (i = 0; i < AL_SRDS_NUM_LANES; i++) {
+		al_serdes_grp_reg_masked_write(
+			obj,
+			(enum al_serdes_reg_page)i,
+			AL_SRDS_REG_TYPE_PMA,
+			SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM,
+			SERDES_IREG_FLD_LB_LOCWREN |
+			SERDES_IREG_FLD_PCSRXBIST_LOCWREN,
+			SERDES_IREG_FLD_LB_LOCWREN |
+			SERDES_IREG_FLD_PCSRXBIST_LOCWREN);
+
+		al_serdes_grp_reg_masked_write(
+			obj,
+			(enum al_serdes_reg_page)i,
+			AL_SRDS_REG_TYPE_PMA,
+			SERDES_IREG_FLD_PCSTXBIST_LOCWREN_REG_NUM,
+			SERDES_IREG_FLD_PCSTXBIST_LOCWREN,
+			SERDES_IREG_FLD_PCSTXBIST_LOCWREN);
+	}
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static void al_serdes_rx_rate_change(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_rate		rate)
+{
+	int i;
+
+	uint8_t rx_rate_val;
+
+	switch (rate) {
+	case AL_SRDS_RATE_1_8:
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_8;
+		break;
+	case AL_SRDS_RATE_1_4:
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_4;
+		break;
+	case AL_SRDS_RATE_1_2:
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_2;
+		break;
+	case AL_SRDS_RATE_FULL:
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_1;
+		break;
+	default:
+		al_err("%s: invalid rate (%d)\n",  __func__, rate);
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_1;
+		break;
+	}
+
+	for (i = 0; i < AL_SRDS_NUM_LANES; i++) {
+		al_serdes_grp_reg_masked_write(
+				   obj,
+				   (enum al_serdes_reg_page)i,
+				   AL_SRDS_REG_TYPE_PMA,
+				   SERDES_IREG_FLD_PCSRX_DIVRATE_REG_NUM,
+				   SERDES_IREG_FLD_PCSRX_DIVRATE_MASK,
+				   rx_rate_val);
+	}
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static void al_serdes_group_pm_set(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_pm		pm)
+{
+	uint8_t pm_val;
+
+	switch (pm) {
+	case AL_SRDS_PM_PD:
+		pm_val = SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_PD;
+		break;
+	case AL_SRDS_PM_P2:
+		pm_val = SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P2;
+		break;
+	case AL_SRDS_PM_P1:
+		pm_val = SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P1;
+		break;
+	case AL_SRDS_PM_P0S:
+		pm_val = SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P0S;
+		break;
+	case AL_SRDS_PM_P0:
+		pm_val = SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P0;
+		break;
+	default:
+		al_err("%s: invalid power mode (%d)\n",  __func__, pm);
+		al_assert(0);
+		pm_val = SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P0;
+	}
+
+	if (pm == AL_SRDS_PM_PD)
+		al_serdes_group_rx_rate_change_sw_flow_dis(obj);
+
+	al_serdes_grp_reg_masked_write(
+		obj,
+		AL_SRDS_REG_PAGE_4_COMMON,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_REG_NUM,
+		SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_MASK,
+		pm_val);
+
+	if (pm != AL_SRDS_PM_PD)
+		al_serdes_group_rx_rate_change_sw_flow_en_cond(obj);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static void al_serdes_lane_rx_rate_change_sw_flow_en(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_lane	lane)
+{
+	al_serdes_reg_write(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 201, 0xfc);
+	al_serdes_reg_write(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 202, 0xff);
+	al_serdes_reg_write(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 203, 0xff);
+	al_serdes_reg_write(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 204, 0xff);
+	al_serdes_reg_write(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 205, 0x7f);
+	al_serdes_reg_write(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 205, 0xff);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static void al_serdes_lane_rx_rate_change_sw_flow_dis(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_lane		lane)
+{
+	al_serdes_reg_write(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 205, 0x7f);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static void al_serdes_lane_pcie_rate_override_enable_set(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_lane		lane,
+	al_bool				en)
+{
+	al_serdes_grp_reg_masked_write(
+		obj,
+		(enum al_serdes_reg_page)lane,
+		AL_SRDS_REG_TYPE_PCS,
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_ENA_REG_NUM,
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_ENA,
+		en ? SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_ENA : 0);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static al_bool al_serdes_lane_pcie_rate_override_is_enabled(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_lane		lane)
+{
+	return (al_serdes_grp_reg_read(
+		obj,
+		(enum al_serdes_reg_page)lane,
+		AL_SRDS_REG_TYPE_PCS,
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_ENA_REG_NUM) &
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_ENA) ? AL_TRUE : AL_FALSE;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static enum al_serdes_pcie_rate al_serdes_lane_pcie_rate_get(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_lane		lane)
+{
+	return (al_serdes_grp_reg_read(
+		obj,
+		(enum al_serdes_reg_page)lane,
+		AL_SRDS_REG_TYPE_PCS,
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_REG_NUM) &
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_MASK) >>
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_SHIFT;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static void al_serdes_lane_pcie_rate_set(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_lane		lane,
+	enum al_serdes_pcie_rate	rate)
+{
+	al_serdes_grp_reg_masked_write(
+		obj,
+		(enum al_serdes_reg_page)lane,
+		AL_SRDS_REG_TYPE_PCS,
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_REG_NUM,
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_MASK,
+		rate << SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_SHIFT);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static void al_serdes_lane_pm_set(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_lane		lane,
+	enum al_serdes_pm		rx_pm,
+	enum al_serdes_pm		tx_pm)
+{
+	uint8_t rx_pm_val;
+	uint8_t tx_pm_val;
+
+	switch (rx_pm) {
+	case AL_SRDS_PM_PD:
+		rx_pm_val = SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_PD;
+		break;
+	case AL_SRDS_PM_P2:
+		rx_pm_val = SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_P2;
+		break;
+	case AL_SRDS_PM_P1:
+		rx_pm_val = SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_P1;
+		break;
+	case AL_SRDS_PM_P0S:
+		rx_pm_val = SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_P0S;
+		break;
+	case AL_SRDS_PM_P0:
+		rx_pm_val = SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_P0;
+		break;
+	default:
+		al_err("%s: invalid rx power mode (%d)\n",  __func__, rx_pm);
+		al_assert(0);
+		rx_pm_val = SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_P0;
+	}
+
+	switch (tx_pm) {
+	case AL_SRDS_PM_PD:
+		tx_pm_val = SERDES_IREG_FLD_LANEPCSPSTATE_TX_VAL_PD;
+		break;
+	case AL_SRDS_PM_P2:
+		tx_pm_val = SERDES_IREG_FLD_LANEPCSPSTATE_TX_VAL_P2;
+		break;
+	case AL_SRDS_PM_P1:
+		tx_pm_val = SERDES_IREG_FLD_LANEPCSPSTATE_TX_VAL_P1;
+		break;
+	case AL_SRDS_PM_P0S:
+		tx_pm_val = SERDES_IREG_FLD_LANEPCSPSTATE_TX_VAL_P0S;
+		break;
+	case AL_SRDS_PM_P0:
+		tx_pm_val = SERDES_IREG_FLD_LANEPCSPSTATE_TX_VAL_P0;
+		break;
+	default:
+		al_err("%s: invalid tx power mode (%d)\n",  __func__, tx_pm);
+		al_assert(0);
+		tx_pm_val = SERDES_IREG_FLD_LANEPCSPSTATE_TX_VAL_P0;
+	}
+
+	if (rx_pm == AL_SRDS_PM_PD)
+		_al_serdes_lane_rx_rate_change_sw_flow_dis(obj, lane);
+
+	al_serdes_grp_reg_masked_write(
+		obj,
+		(enum al_serdes_reg_page)lane,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_LANEPCSPSTATE_RX_REG_NUM,
+		SERDES_IREG_FLD_LANEPCSPSTATE_RX_MASK,
+		rx_pm_val);
+
+	al_serdes_grp_reg_masked_write(
+		obj,
+		(enum al_serdes_reg_page)lane,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_LANEPCSPSTATE_TX_REG_NUM,
+		SERDES_IREG_FLD_LANEPCSPSTATE_TX_MASK,
+		tx_pm_val);
+
+	if (rx_pm != AL_SRDS_PM_PD)
+		_al_serdes_lane_rx_rate_change_sw_flow_en_cond(obj, lane);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static void al_serdes_pma_hard_reset_group(
+	struct al_serdes_grp_obj	*obj,
+	al_bool				enable)
+{
+	if (enable)
+		al_serdes_group_rx_rate_change_sw_flow_dis(obj);
+
+	/* Enable Hard Reset Override */
+	al_serdes_grp_reg_masked_write(
+		obj,
+		AL_SRDS_REG_PAGE_4_COMMON,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_SYNTH_REG_NUM,
+		SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_SYNTH_MASK,
+		SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_SYNTH_VAL_REGS);
+
+	/* Assert/Deassert Hard Reset Override */
+	al_serdes_grp_reg_masked_write(
+		obj,
+		AL_SRDS_REG_PAGE_4_COMMON,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_SYNTH_REG_NUM,
+		SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_SYNTH_MASK,
+		enable ?
+		SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_SYNTH_VAL_ASSERT :
+		SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_SYNTH_VAL_DEASSERT);
+
+	if (!enable)
+		al_serdes_group_rx_rate_change_sw_flow_en_cond(obj);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static void al_serdes_pma_hard_reset_lane(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_lane		lane,
+	al_bool				enable)
+{
+	if (enable)
+		_al_serdes_lane_rx_rate_change_sw_flow_dis(obj, lane);
+
+	/* Enable Hard Reset Override */
+	al_serdes_grp_reg_masked_write(
+		obj,
+		(enum al_serdes_reg_page)lane,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_REG_NUM,
+		SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_MASK,
+		SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_VAL_REGS);
+
+	/* Assert/Deassert Hard Reset Override */
+	al_serdes_grp_reg_masked_write(
+		obj,
+		(enum al_serdes_reg_page)lane,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_REG_NUM,
+		SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_MASK,
+		enable ?
+		SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_VAL_ASSERT :
+		SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_VAL_DEASSERT);
+
+	if (!enable)
+		_al_serdes_lane_rx_rate_change_sw_flow_en_cond(obj, lane);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+#if	(SERDES_IREG_FLD_LB_RX2TXUNTIMEDEN_REG_NUM !=\
+	SERDES_IREG_FLD_LB_TX2RXBUFTIMEDEN_REG_NUM) ||\
+	(SERDES_IREG_FLD_LB_TX2RXBUFTIMEDEN_REG_NUM !=\
+	SERDES_IREG_FLD_LB_TX2RXIOTIMEDEN_REG_NUM) ||\
+	(SERDES_IREG_FLD_LB_TX2RXIOTIMEDEN_REG_NUM !=\
+	 SERDES_IREG_FLD_LB_PARRX2TXTIMEDEN_REG_NUM) ||\
+	(SERDES_IREG_FLD_LB_PARRX2TXTIMEDEN_REG_NUM !=\
+	 SERDES_IREG_FLD_LB_CDRCLK2TXEN_REG_NUM)
+#error Wrong assumption
+#endif
+
+static void al_serdes_loopback_control(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_lane		lane,
+	enum al_serdes_lb_mode		mode)
+{
+	uint8_t val = 0;
+
+	switch (mode) {
+	case AL_SRDS_LB_MODE_OFF:
+		break;
+	case AL_SRDS_LB_MODE_PMA_IO_UN_TIMED_RX_TO_TX:
+		val = SERDES_IREG_FLD_LB_RX2TXUNTIMEDEN;
+		break;
+	case AL_SRDS_LB_MODE_PMA_INTERNALLY_BUFFERED_SERIAL_TX_TO_RX:
+		val = SERDES_IREG_FLD_LB_TX2RXBUFTIMEDEN;
+		break;
+	case AL_SRDS_LB_MODE_PMA_SERIAL_TX_IO_TO_RX_IO:
+		val = SERDES_IREG_FLD_LB_TX2RXIOTIMEDEN;
+		break;
+	case AL_SRDS_LB_MODE_PMA_PARALLEL_RX_TO_TX:
+		val = SERDES_IREG_FLD_LB_PARRX2TXTIMEDEN |
+			SERDES_IREG_FLD_LB_CDRCLK2TXEN;
+		break;
+	default:
+		al_err("%s: invalid mode (%d)\n",  __func__, mode);
+		al_assert(0);
+	}
+
+	al_serdes_grp_reg_masked_write(
+		obj,
+		(enum al_serdes_reg_page)lane,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_LB_RX2TXUNTIMEDEN_REG_NUM,
+		SERDES_IREG_FLD_LB_RX2TXUNTIMEDEN |
+		SERDES_IREG_FLD_LB_TX2RXBUFTIMEDEN |
+		SERDES_IREG_FLD_LB_TX2RXIOTIMEDEN |
+		SERDES_IREG_FLD_LB_PARRX2TXTIMEDEN |
+		SERDES_IREG_FLD_LB_CDRCLK2TXEN,
+		val);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static void al_serdes_bist_pattern_select(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_bist_pattern	pattern,
+	uint8_t				*user_data)
+{
+	uint8_t val = 0;
+
+	switch (pattern) {
+	case AL_SRDS_BIST_PATTERN_USER:
+		al_assert(user_data);
+		val = SERDES_IREG_FLD_CMNPCSBIST_MODESEL_VAL_USER;
+		break;
+	case AL_SRDS_BIST_PATTERN_PRBS7:
+		val = SERDES_IREG_FLD_CMNPCSBIST_MODESEL_VAL_PRBS7;
+		break;
+	case AL_SRDS_BIST_PATTERN_PRBS23:
+		val = SERDES_IREG_FLD_CMNPCSBIST_MODESEL_VAL_PRBS23;
+		break;
+	case AL_SRDS_BIST_PATTERN_PRBS31:
+		val = SERDES_IREG_FLD_CMNPCSBIST_MODESEL_VAL_PRBS31;
+		break;
+	case AL_SRDS_BIST_PATTERN_CLK1010:
+		val = SERDES_IREG_FLD_CMNPCSBIST_MODESEL_VAL_CLK1010;
+		break;
+	default:
+		al_err("%s: invalid pattern (%d)\n", __func__, pattern);
+		al_assert(0);
+	}
+
+	if (pattern == AL_SRDS_BIST_PATTERN_USER) {
+		int i;
+
+		for (i = 0; i < SERDES_IREG_FLD_TX_BIST_PAT_NUM_BYTES; i++)
+			al_serdes_grp_reg_write(
+				obj,
+				AL_SRDS_REG_PAGE_4_COMMON,
+				AL_SRDS_REG_TYPE_PMA,
+				SERDES_IREG_FLD_TX_BIST_PAT_REG_NUM(i),
+				user_data[i]);
+	}
+
+	al_serdes_grp_reg_masked_write(
+		obj,
+		AL_SRDS_REG_PAGE_4_COMMON,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_CMNPCSBIST_MODESEL_REG_NUM,
+		SERDES_IREG_FLD_CMNPCSBIST_MODESEL_MASK,
+		val);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static void al_serdes_bist_tx_enable(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_lane		lane,
+	al_bool				enable)
+{
+	al_serdes_grp_reg_masked_write(
+		obj,
+		(enum al_serdes_reg_page)lane,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_PCSTXBIST_EN_REG_NUM,
+		SERDES_IREG_FLD_PCSTXBIST_EN,
+		enable ? SERDES_IREG_FLD_PCSTXBIST_EN : 0);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static void al_serdes_bist_tx_err_inject(
+	struct al_serdes_grp_obj	*obj)
+{
+	al_serdes_grp_reg_masked_write(
+		obj,
+		AL_SRDS_REG_PAGE_4_COMMON,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_TXBIST_BITERROR_EN_REG_NUM,
+		SERDES_IREG_FLD_TXBIST_BITERROR_EN,
+		SERDES_IREG_FLD_TXBIST_BITERROR_EN);
+
+	al_serdes_grp_reg_masked_write(
+		obj,
+		AL_SRDS_REG_PAGE_4_COMMON,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_TXBIST_BITERROR_EN_REG_NUM,
+		SERDES_IREG_FLD_TXBIST_BITERROR_EN,
+		0);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static void al_serdes_bist_rx_enable(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_lane		lane,
+	al_bool				enable)
+{
+	al_serdes_grp_reg_masked_write(
+		obj,
+		(enum al_serdes_reg_page)lane,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_PCSRXBIST_EN_REG_NUM,
+		SERDES_IREG_FLD_PCSRXBIST_EN,
+		enable ? SERDES_IREG_FLD_PCSRXBIST_EN : 0);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+#if	(SERDES_IREG_FLD_RXBIST_ERRCOUNT_OVERFLOW_REG_NUM !=\
+	SERDES_IREG_FLD_RXBIST_RXLOCKED_REG_NUM)
+#error Wrong assumption
+#endif
+
+static void al_serdes_bist_rx_status(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_lane		lane,
+	al_bool				*is_locked,
+	al_bool				*err_cnt_overflow,
+	uint32_t			*err_cnt)
+{
+	uint8_t status_reg_val;
+	uint16_t err_cnt_msb_reg_val;
+	uint16_t err_cnt_lsb_reg_val;
+
+	status_reg_val = al_serdes_grp_reg_read(
+		obj,
+		(enum al_serdes_reg_page)lane,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_RXBIST_RXLOCKED_REG_NUM);
+
+	err_cnt_msb_reg_val = al_serdes_grp_reg_read(
+		obj,
+		(enum al_serdes_reg_page)lane,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_RXBIST_ERRCOUNT_MSB_REG_NUM);
+
+	err_cnt_lsb_reg_val = al_serdes_grp_reg_read(
+		obj,
+		(enum al_serdes_reg_page)lane,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_RXBIST_ERRCOUNT_LSB_REG_NUM);
+
+	*is_locked =
+		(status_reg_val & SERDES_IREG_FLD_RXBIST_RXLOCKED) ?
+		AL_TRUE : AL_FALSE;
+
+	*err_cnt_overflow =
+		(status_reg_val & SERDES_IREG_FLD_RXBIST_ERRCOUNT_OVERFLOW) ?
+		AL_TRUE : AL_FALSE;
+
+	*err_cnt = (err_cnt_msb_reg_val << 8) + err_cnt_lsb_reg_val;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static inline uint8_t al_serdes_grp_reg_read(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_reg_page		page,
+	enum al_serdes_reg_type		type,
+	uint16_t			offset)
+{
+	struct al_serdes_regs __iomem	*regs_base = obj->regs_base;
+
+	al_reg_write32(
+		&regs_base->gen.reg_addr,
+		SRDS_CORE_REG_ADDR(page, type, offset));
+
+	return al_reg_read32(&regs_base->gen.reg_data);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static inline void al_serdes_grp_reg_write(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_reg_page		page,
+	enum al_serdes_reg_type		type,
+	uint16_t			offset,
+	uint8_t				data)
+{
+	struct al_serdes_regs __iomem	*regs_base = obj->regs_base;
+
+	al_reg_write32(
+		&regs_base->gen.reg_addr,
+		SRDS_CORE_REG_ADDR(page, type, offset));
+
+	al_reg_write32(&regs_base->gen.reg_data, data);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static inline void al_serdes_ns_delay(int cnt)
+{
+	al_udelay((cnt + 999) / 1000);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+static inline void al_serdes_grp_reg_masked_write(
+	struct al_serdes_grp_obj	*obj,
+	enum al_serdes_reg_page		page,
+	enum al_serdes_reg_type		type,
+	uint16_t			offset,
+	uint8_t				mask,
+	uint8_t				data)
+{
+	uint8_t val;
+	enum al_serdes_reg_page	start_page = page;
+	enum al_serdes_reg_page	end_page   = page;
+	enum al_serdes_reg_page	iter_page;
+
+	if (page == AL_SRDS_REG_PAGE_0123_LANES_0123) {

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201609200856.u8K8uOlu015151>