From owner-svn-src-head@freebsd.org Tue Jan 26 15:22:06 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 14ED8A6E73F; Tue, 26 Jan 2016 15:22:06 +0000 (UTC) (envelope-from zbb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C8DA2E72; Tue, 26 Jan 2016 15:22:05 +0000 (UTC) (envelope-from zbb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u0QFM49U062674; Tue, 26 Jan 2016 15:22:04 GMT (envelope-from zbb@FreeBSD.org) Received: (from zbb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u0QFM4IN062671; Tue, 26 Jan 2016 15:22:04 GMT (envelope-from zbb@FreeBSD.org) Message-Id: <201601261522.u0QFM4IN062671@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: zbb set sender to zbb@FreeBSD.org using -f From: Zbigniew Bodek Date: Tue, 26 Jan 2016 15:22:04 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r294838 - in head/sys/contrib/alpine-hal: . eth X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 Jan 2016 15:22:06 -0000 Author: zbb Date: Tue Jan 26 15:22:04 2016 New Revision: 294838 URL: https://svnweb.freebsd.org/changeset/base/294838 Log: Import Annapurna Labs Alpine HAL for networking Files required for the NIC driver Import from vendor-sys/alpine-hal/2.7 SVN rev.: 294828 HAL version: 2.7 Obtained from: Semihalf Sponsored by: Annapurna Labs Added: head/sys/contrib/alpine-hal/al_hal_iofic.c (contents, props changed) head/sys/contrib/alpine-hal/al_hal_serdes.c (contents, props changed) head/sys/contrib/alpine-hal/al_hal_serdes.h (contents, props changed) head/sys/contrib/alpine-hal/al_hal_serdes_internal_regs.h (contents, props changed) head/sys/contrib/alpine-hal/al_hal_serdes_regs.h (contents, props changed) head/sys/contrib/alpine-hal/al_hal_udma.h (contents, props changed) head/sys/contrib/alpine-hal/al_hal_udma_config.c (contents, props changed) head/sys/contrib/alpine-hal/al_hal_udma_config.h (contents, props changed) head/sys/contrib/alpine-hal/al_hal_udma_debug.c (contents, props changed) head/sys/contrib/alpine-hal/al_hal_udma_debug.h (contents, props changed) head/sys/contrib/alpine-hal/al_hal_udma_iofic.c (contents, props changed) head/sys/contrib/alpine-hal/al_hal_udma_iofic.h (contents, props changed) head/sys/contrib/alpine-hal/al_hal_udma_iofic_regs.h (contents, props changed) head/sys/contrib/alpine-hal/al_hal_udma_main.c (contents, props changed) head/sys/contrib/alpine-hal/al_hal_udma_regs.h (contents, props changed) head/sys/contrib/alpine-hal/al_hal_udma_regs_gen.h (contents, props changed) head/sys/contrib/alpine-hal/al_hal_udma_regs_m2s.h (contents, props changed) head/sys/contrib/alpine-hal/al_hal_udma_regs_s2m.h (contents, props changed) head/sys/contrib/alpine-hal/eth/ head/sys/contrib/alpine-hal/eth/al_hal_an_lt_wrapper_regs.h (contents, props changed) head/sys/contrib/alpine-hal/eth/al_hal_eth.h (contents, props changed) head/sys/contrib/alpine-hal/eth/al_hal_eth_alu.h (contents, props changed) head/sys/contrib/alpine-hal/eth/al_hal_eth_ec_regs.h (contents, props changed) head/sys/contrib/alpine-hal/eth/al_hal_eth_kr.c (contents, props changed) head/sys/contrib/alpine-hal/eth/al_hal_eth_kr.h (contents, props changed) head/sys/contrib/alpine-hal/eth/al_hal_eth_mac_regs.h (contents, props changed) head/sys/contrib/alpine-hal/eth/al_hal_eth_main.c (contents, props changed) Added: head/sys/contrib/alpine-hal/al_hal_iofic.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/contrib/alpine-hal/al_hal_iofic.c Tue Jan 26 15:22:04 2016 (r294838) @@ -0,0 +1,291 @@ +/*- +******************************************************************************* +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. + +*******************************************************************************/ + +/** + * @{ + * @file al_hal_iofic.c + * + * @brief interrupt controller hal + * + */ + +#include "al_hal_iofic.h" +#include "al_hal_iofic_regs.h" + +/* + * configure the interrupt registers, interrupts will are kept masked + */ +int al_iofic_config(void __iomem *regs_base, int group, uint32_t flags) +{ + struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); + + al_assert(regs_base); + al_assert(group < AL_IOFIC_MAX_GROUPS); + + al_reg_write32(®s->ctrl[group].int_control_grp, flags); + + return 0; +} + +/* + * configure the moderation timer resolution for a given group + */ +int al_iofic_moder_res_config(void __iomem *regs_base, int group, + uint8_t resolution) + +{ + struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); + uint32_t reg; + + al_assert(regs_base); + al_assert(group < AL_IOFIC_MAX_GROUPS); + + reg = al_reg_read32(®s->ctrl[group].int_control_grp); + AL_REG_FIELD_SET(reg, + INT_CONTROL_GRP_MOD_RES_MASK, + INT_CONTROL_GRP_MOD_RES_SHIFT, + resolution); + al_reg_write32(®s->ctrl[group].int_control_grp, reg); + + return 0; +} + +/* + * configure the moderation timer interval for a given legacy interrupt group + */ +int al_iofic_legacy_moder_interval_config(void __iomem *regs_base, int group, + uint8_t interval) +{ + struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); + uint32_t reg; + + al_assert(regs_base); + al_assert(group < AL_IOFIC_MAX_GROUPS); + + reg = al_reg_read32(®s->ctrl[group].int_control_grp); + AL_REG_FIELD_SET(reg, + INT_CONTROL_GRP_MOD_INTV_MASK, + INT_CONTROL_GRP_MOD_INTV_SHIFT, + interval); + al_reg_write32(®s->ctrl[group].int_control_grp, reg); + + return 0; +} + + +/* + * configure the moderation timer interval for a given msix vector. + */ +int al_iofic_msix_moder_interval_config(void __iomem *regs_base, int group, + uint8_t vector, uint8_t interval) +{ + struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); + uint32_t reg; + + al_assert(regs_base); + al_assert(group < AL_IOFIC_MAX_GROUPS); + + reg = al_reg_read32(®s->grp_int_mod[group][vector].grp_int_mod_reg); + AL_REG_FIELD_SET(reg, + INT_MOD_INTV_MASK, + INT_MOD_INTV_SHIFT, + interval); + al_reg_write32(®s->grp_int_mod[group][vector].grp_int_mod_reg, reg); + + return 0; +} + +/* + * configure the vmid attributes for a given msix vector. + */ +int al_iofic_msix_vmid_attributes_config(void __iomem *regs_base, int group, + uint8_t vector, uint32_t vmid, uint8_t vmid_en) +{ + struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); + uint32_t reg = 0; + + al_assert(regs_base); + al_assert(group < AL_IOFIC_MAX_GROUPS); + + AL_REG_FIELD_SET(reg, + INT_MSIX_VMID_MASK, + INT_MSIX_VMID_SHIFT, + vmid); + AL_REG_BIT_VAL_SET(reg, + INT_MSIX_VMID_EN_SHIFT, + vmid_en); + + al_reg_write32(®s->grp_int_mod[group][vector].grp_int_vmid_reg, reg); + + return 0; +} + +/* + * return the offset of the unmask register for a given group + */ +uint32_t __iomem * al_iofic_unmask_offset_get(void __iomem *regs_base, int group) +{ + struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); + + al_assert(regs_base); + al_assert(group < AL_IOFIC_MAX_GROUPS); + + return ®s->ctrl[group].int_mask_clear_grp; +} + + +/* + * unmask specific interrupts for a given group + */ +void al_iofic_unmask(void __iomem *regs_base, int group, uint32_t mask) +{ + struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); + + al_assert(regs_base); + al_assert(group < AL_IOFIC_MAX_GROUPS); + + /* + * use the mask clear register, no need to read the mask register + * itself. write 0 to unmask, 1 has no effect + */ + al_reg_write32_relaxed(®s->ctrl[group].int_mask_clear_grp, ~mask); +} + +/* + * mask specific interrupts for a given group + */ +void al_iofic_mask(void __iomem *regs_base, int group, uint32_t mask) +{ + struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); + uint32_t reg; + + al_assert(regs_base); + al_assert(group < AL_IOFIC_MAX_GROUPS); + + reg = al_reg_read32(®s->ctrl[group].int_mask_grp); + + al_reg_write32(®s->ctrl[group].int_mask_grp, reg | mask); +} + +/* + * read the mask for a given group + */ +uint32_t al_iofic_read_mask(void __iomem *regs_base, int group) +{ + struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); + + al_assert(regs_base); + al_assert(group < AL_IOFIC_MAX_GROUPS); + + return al_reg_read32(®s->ctrl[group].int_mask_grp); +} + +/* + * read interrupt cause register for a given group + */ +uint32_t al_iofic_read_cause(void __iomem *regs_base, int group) +{ + struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); + + al_assert(regs_base); + al_assert(group < AL_IOFIC_MAX_GROUPS); + + return al_reg_read32(®s->ctrl[group].int_cause_grp); +} + +/* + * clear bits in the interrupt cause register for a given group + */ +void al_iofic_clear_cause(void __iomem *regs_base, int group, uint32_t mask) +{ + struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); + + al_assert(regs_base); + al_assert(group < AL_IOFIC_MAX_GROUPS); + + /* inverse mask, writing 1 has no effect */ + al_reg_write32(®s->ctrl[group].int_cause_grp, ~mask); +} + +/* + * Set the cause register for a given group + */ +void al_iofic_set_cause(void __iomem *regs_base, int group, uint32_t mask) +{ + struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); + + al_assert(regs_base); + al_assert(group < AL_IOFIC_MAX_GROUPS); + + al_reg_write32(®s->ctrl[group].int_cause_set_grp, mask); +} + + +/* + * unmask specific interrupts from aborting the udma a given group + */ +void al_iofic_abort_mask(void __iomem *regs_base, int group, uint32_t mask) +{ + struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); + + al_assert(regs_base); + al_assert(group < AL_IOFIC_MAX_GROUPS); + + al_reg_write32(®s->ctrl[group].int_abort_msk_grp, mask); + +} + +/* + * trigger all interrupts that are waiting for moderation timers to expire + */ +void al_iofic_interrupt_moderation_reset(void __iomem *regs_base, int group) +{ + struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); + uint32_t reg = 0; + + al_assert(regs_base); + al_assert(group < AL_IOFIC_MAX_GROUPS); + + al_assert(regs_base); + al_assert(group < AL_IOFIC_MAX_GROUPS); + + reg = al_reg_read32(®s->ctrl[group].int_control_grp); + reg |= INT_CONTROL_GRP_MOD_RST; + + al_reg_write32(®s->ctrl[group].int_control_grp, reg); +} + +/** @} end of interrupt controller group */ Added: head/sys/contrib/alpine-hal/al_hal_serdes.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/contrib/alpine-hal/al_hal_serdes.c Tue Jan 26 15:22:04 2016 (r294838) @@ -0,0 +1,3228 @@ +/*- +******************************************************************************* +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.h" +#include "al_hal_serdes_regs.h" +#include "al_hal_serdes_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 + + +/** + * Prototypes for _lane_ compatibility + */ +int al_serdes_lane_read( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + enum al_serdes_reg_type type, + uint16_t offset, + uint8_t *data); + +int al_serdes_lane_write( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + enum al_serdes_reg_type type, + uint16_t offset, + uint8_t data); + + +/** + * SERDES core reg/lane read + */ +static inline uint8_t al_serdes_grp_reg_read( + struct al_serdes_group_info *grp_info, + enum al_serdes_reg_page page, + enum al_serdes_reg_type type, + uint16_t offset); + +static inline uint8_t al_serdes_grp_lane_read( + struct al_serdes_group_info *grp_info, + enum al_serdes_lane page, + enum al_serdes_reg_type type, + uint16_t offset); + +/** + * SERDES core reg/lane write + */ +static inline void al_serdes_grp_reg_write( + struct al_serdes_group_info *grp_info, + enum al_serdes_reg_page page, + enum al_serdes_reg_type type, + uint16_t offset, + uint8_t data); + +static inline void al_serdes_grp_lane_write( + struct al_serdes_group_info *grp_info, + enum al_serdes_lane lane, + enum al_serdes_reg_type type, + uint16_t offset, + uint8_t data); + +/** + * SERDES core masked reg/lane write + */ +static inline void al_serdes_grp_reg_masked_write( + struct al_serdes_group_info *grp_info, + 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_group_info *grp_info, + 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_group_info *grp_info); + +/** + * 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_group_info *grp_info, + 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_group_info *grp_info); + + +static inline void al_serdes_grp_lane_masked_write( + struct al_serdes_group_info *grp_info, + enum al_serdes_lane lane, + enum al_serdes_reg_type type, + uint16_t offset, + uint8_t mask, + uint8_t data); + +/******************************************************************************/ +/******************************************************************************/ +int al_serdes_handle_init( + void __iomem *serdes_regs_base, + struct al_serdes_obj *obj) +{ + int i; + + al_dbg( + "%s(%p, %p)\n", + __func__, + serdes_regs_base, + obj); + + al_assert(serdes_regs_base); + + for (i = 0; i < AL_SRDS_NUM_GROUPS; i++) { + obj->grp_info[i].pobj = obj; + + obj->grp_info[i].regs_base = + &((struct al_serdes_regs *)serdes_regs_base)[i]; + } + + return 0; +} + +/******************************************************************************/ +/******************************************************************************/ +int al_serdes_reg_read( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + 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, %d, %u)\n", + __func__, + obj, + grp, + page, + type, + offset); + + al_assert(obj); + al_assert(data); + al_assert(((int)grp) >= AL_SRDS_GRP_A); + al_assert(((int)grp) <= AL_SRDS_GRP_D); + 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->grp_info[grp], + page, + type, + offset); + + al_dbg( + "%s: return(%u)\n", + __func__, + *data); + + return status; +} + +int al_serdes_lane_read( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + enum al_serdes_reg_type type, + uint16_t offset, + uint8_t *data) +{ + return al_serdes_reg_read(obj, grp, (enum al_serdes_reg_page)lane, type, + offset, data); +} +/******************************************************************************/ +/******************************************************************************/ +int al_serdes_reg_write( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + 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, %d, %u, %u)\n", + __func__, + obj, + grp, + page, + type, + offset, + data); + + al_assert(obj); + al_assert(((int)grp) >= AL_SRDS_GRP_A); + al_assert(((int)grp) <= AL_SRDS_GRP_D); + 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->grp_info[grp], + page, + type, + offset, + data); + + return status; +} + +int al_serdes_lane_write( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + enum al_serdes_reg_type type, + uint16_t offset, + uint8_t data) +{ + return al_serdes_reg_write(obj, grp, (enum al_serdes_reg_page)lane, + type, offset, data); +} +/******************************************************************************/ +/******************************************************************************/ +#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 +void al_serdes_bist_overrides_enable( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_rate rate) +{ + struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; + 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( + grp_info, + (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( + grp_info, + (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( + grp_info, + 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( + grp_info, + 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( + grp_info, + 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( + grp_info, + 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( + grp_info, + (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( + grp_info, + (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( + grp_info, + (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( + grp_info, + (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); + } +} + +/******************************************************************************/ +/******************************************************************************/ +void al_serdes_bist_overrides_disable( + struct al_serdes_obj *obj, + enum al_serdes_group grp) +{ + struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; + int i; + + al_serdes_grp_reg_masked_write( + grp_info, + 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( + grp_info, + (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( + grp_info, + (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); + } +} + +/******************************************************************************/ +/******************************************************************************/ +void al_serdes_rx_rate_change( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_rate rate) +{ + struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; + 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( + grp_info, + (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); + } +} + +/******************************************************************************/ +/******************************************************************************/ +void al_serdes_group_pm_set( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_pm pm) +{ + struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; + + 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(grp_info); + + al_serdes_grp_reg_masked_write( + grp_info, + 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(grp_info); +} + +/******************************************************************************/ +/******************************************************************************/ +void al_serdes_lane_rx_rate_change_sw_flow_en( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane) +{ + al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, 201, 0xfc); + al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, 202, 0xff); + al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, 203, 0xff); + al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, 204, 0xff); + al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, 205, 0x7f); + al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, 205, 0xff); +} + +/******************************************************************************/ +/******************************************************************************/ +void al_serdes_lane_rx_rate_change_sw_flow_dis( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane) +{ + al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, 205, 0x7f); +} + +/******************************************************************************/ +/******************************************************************************/ +void al_serdes_lane_pcie_rate_override_enable_set( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + al_bool en) +{ + struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; + + al_serdes_grp_reg_masked_write( + grp_info, + (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); +} + +/******************************************************************************/ +/******************************************************************************/ +al_bool al_serdes_lane_pcie_rate_override_is_enabled( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane) +{ + struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; + + return (al_serdes_grp_lane_read( + grp_info, + 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; +} + +/******************************************************************************/ +/******************************************************************************/ +enum al_serdes_pcie_rate al_serdes_lane_pcie_rate_get( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane) +{ + struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; + + return (al_serdes_grp_reg_read( + grp_info, + (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; +} + +/******************************************************************************/ +/******************************************************************************/ +void al_serdes_lane_pcie_rate_set( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + enum al_serdes_pcie_rate rate) +{ + struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; + + al_serdes_grp_reg_masked_write( + grp_info, + (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); +} + +/******************************************************************************/ +/******************************************************************************/ +void al_serdes_lane_pm_set( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + enum al_serdes_pm rx_pm, + enum al_serdes_pm tx_pm) +{ + struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; + *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***