svn commit: r306017 - vendor-sys/alpine-hal/2.7a
Wojciech Macek
wma at FreeBSD.org
Tue Sep 20 08:56:51 UTC 2016
Author: wma
Date: Tue Sep 20 08:56:50 2016
New Revision: 306017
URL: https://svnweb.freebsd.org/changeset/base/306017
Log:
Update Annapurna Alpine HAL
alpine-hal SerDes file was omitted in the previous commit.
Files added here.
Added:
vendor-sys/alpine-hal/2.7a/al_hal_serdes_hssp.c
- copied unchanged from r306016, vendor-sys/alpine-hal/2.7a/al_hal_serdes.c
Deleted:
vendor-sys/alpine-hal/2.7a/al_hal_serdes.c
Copied: vendor-sys/alpine-hal/2.7a/al_hal_serdes_hssp.c (from r306016, vendor-sys/alpine-hal/2.7a/al_hal_serdes.c)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ vendor-sys/alpine-hal/2.7a/al_hal_serdes_hssp.c Tue Sep 20 08:56:50 2016 (r306017, copy of r306016, vendor-sys/alpine-hal/2.7a/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(
+ ®s_base->gen.reg_addr,
+ SRDS_CORE_REG_ADDR(page, type, offset));
+
+ return al_reg_read32(®s_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(
+ ®s_base->gen.reg_addr,
+ SRDS_CORE_REG_ADDR(page, type, offset));
+
+ al_reg_write32(®s_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 ***
More information about the svn-src-all
mailing list