From 3098c7f4883d83f28e887bc376250a6d2806ab20 Mon Sep 17 00:00:00 2001 From: Zbigniew Bodek Date: Tue, 26 Jan 2016 14:45:25 +0000 Subject: [PATCH 001/109] Update alpine-hal/dist/ accordingly after r294828 alpine-hal/dist was omitted in the previous commit. Files added here. HAL version: 2.7 Obtained from: Semihalf Sponsored by: Annapurna Labs --- al_hal_iofic.c | 291 ++ al_hal_serdes.c | 3228 +++++++++++++++++++ al_hal_serdes.h | 1125 +++++++ al_hal_serdes_internal_regs.h | 750 +++++ al_hal_serdes_regs.h | 495 +++ al_hal_udma.h | 672 ++++ al_hal_udma_config.c | 1373 ++++++++ al_hal_udma_config.h | 755 +++++ al_hal_udma_debug.c | 497 +++ al_hal_udma_debug.h | 134 + al_hal_udma_iofic.c | 151 + al_hal_udma_iofic.h | 614 ++++ al_hal_udma_iofic_regs.h | 66 + al_hal_udma_main.c | 618 ++++ al_hal_udma_regs.h | 104 + al_hal_udma_regs_gen.h | 414 +++ al_hal_udma_regs_m2s.h | 1159 +++++++ al_hal_udma_regs_s2m.h | 998 ++++++ eth/al_hal_an_lt_wrapper_regs.h | 264 ++ eth/al_hal_eth.h | 2381 ++++++++++++++ eth/al_hal_eth_alu.h | 95 + eth/al_hal_eth_ec_regs.h | 3362 ++++++++++++++++++++ eth/al_hal_eth_kr.c | 1030 ++++++ eth/al_hal_eth_kr.h | 372 +++ eth/al_hal_eth_mac_regs.h | 1809 +++++++++++ eth/al_hal_eth_main.c | 5260 +++++++++++++++++++++++++++++++ 26 files changed, 28017 insertions(+) create mode 100644 al_hal_iofic.c create mode 100644 al_hal_serdes.c create mode 100644 al_hal_serdes.h create mode 100644 al_hal_serdes_internal_regs.h create mode 100644 al_hal_serdes_regs.h create mode 100644 al_hal_udma.h create mode 100644 al_hal_udma_config.c create mode 100644 al_hal_udma_config.h create mode 100644 al_hal_udma_debug.c create mode 100644 al_hal_udma_debug.h create mode 100644 al_hal_udma_iofic.c create mode 100644 al_hal_udma_iofic.h create mode 100644 al_hal_udma_iofic_regs.h create mode 100644 al_hal_udma_main.c create mode 100644 al_hal_udma_regs.h create mode 100644 al_hal_udma_regs_gen.h create mode 100644 al_hal_udma_regs_m2s.h create mode 100644 al_hal_udma_regs_s2m.h create mode 100644 eth/al_hal_an_lt_wrapper_regs.h create mode 100644 eth/al_hal_eth.h create mode 100644 eth/al_hal_eth_alu.h create mode 100644 eth/al_hal_eth_ec_regs.h create mode 100644 eth/al_hal_eth_kr.c create mode 100644 eth/al_hal_eth_kr.h create mode 100644 eth/al_hal_eth_mac_regs.h create mode 100644 eth/al_hal_eth_main.c diff --git a/al_hal_iofic.c b/al_hal_iofic.c new file mode 100644 index 00000000000..28467f2e3b8 --- /dev/null +++ b/al_hal_iofic.c @@ -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 */ diff --git a/al_hal_serdes.c b/al_hal_serdes.c new file mode 100644 index 00000000000..bb34d13c765 --- /dev/null +++ b/al_hal_serdes.c @@ -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]; + + 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(grp_info, lane); + + al_serdes_grp_reg_masked_write( + grp_info, + (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( + grp_info, + (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(grp_info, lane); +} + +/******************************************************************************/ +/******************************************************************************/ +void al_serdes_pma_hard_reset_group( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + al_bool enable) +{ + struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; + + if (enable) + al_serdes_group_rx_rate_change_sw_flow_dis(grp_info); + + /* Enable Hard Reset Override */ + al_serdes_grp_reg_masked_write( + grp_info, + 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( + grp_info, + 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(grp_info); +} + +/******************************************************************************/ +/******************************************************************************/ +void al_serdes_pma_hard_reset_lane( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + al_bool enable) +{ + struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; + + if (enable) + _al_serdes_lane_rx_rate_change_sw_flow_dis(grp_info, lane); + + /* Enable Hard Reset Override */ + al_serdes_grp_reg_masked_write( + grp_info, + (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( + grp_info, + (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(grp_info, 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 + +void al_serdes_loopback_control( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + enum al_serdes_lb_mode mode) +{ + struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; + 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( + grp_info, + (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); +} + +/******************************************************************************/ +/******************************************************************************/ +void al_serdes_bist_pattern_select( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_bist_pattern pattern, + uint8_t *user_data) +{ + struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; + 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( + grp_info, + 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( + grp_info, + 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); +} + +/******************************************************************************/ +/******************************************************************************/ +void al_serdes_bist_tx_enable( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + al_bool enable) +{ + 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_PMA, + SERDES_IREG_FLD_PCSTXBIST_EN_REG_NUM, + SERDES_IREG_FLD_PCSTXBIST_EN, + enable ? SERDES_IREG_FLD_PCSTXBIST_EN : 0); +} + +/******************************************************************************/ +/******************************************************************************/ +void al_serdes_bist_tx_err_inject( + struct al_serdes_obj *obj, + enum al_serdes_group grp) +{ + struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; + + al_serdes_grp_reg_masked_write( + grp_info, + 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( + grp_info, + 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); +} + +/******************************************************************************/ +/******************************************************************************/ +void al_serdes_bist_rx_enable( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + al_bool enable) +{ + 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_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 + +void al_serdes_bist_rx_status( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + al_bool *is_locked, + al_bool *err_cnt_overflow, + uint16_t *err_cnt) +{ + struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; + 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( + grp_info, + (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( + grp_info, + (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( + grp_info, + (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_group_info *grp_info, + enum al_serdes_reg_page page, + enum al_serdes_reg_type type, + uint16_t offset) +{ + al_reg_write32( + &grp_info->regs_base->gen.reg_addr, + SRDS_CORE_REG_ADDR(page, type, offset)); + + return al_reg_read32(&grp_info->regs_base->gen.reg_data); +} + +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) +{ + return al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)page, + type, offset); +} + +/******************************************************************************/ +/******************************************************************************/ +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) +{ + al_reg_write32( + &grp_info->regs_base->gen.reg_addr, + SRDS_CORE_REG_ADDR(page, type, offset)); + + al_reg_write32(&grp_info->regs_base->gen.reg_data, 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) +{ + al_serdes_grp_reg_write(grp_info, (enum al_serdes_reg_page)lane, + type, offset, 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_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) +{ + 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) { + start_page = AL_SRDS_REG_PAGE_0_LANE_0; + end_page = AL_SRDS_REG_PAGE_3_LANE_3; + } + + for(iter_page = start_page; iter_page <= end_page; ++iter_page) { + val = al_serdes_grp_reg_read(grp_info, iter_page, type, offset); + val &= ~mask; + val |= data; + al_serdes_grp_reg_write(grp_info, iter_page, type, offset, val); + } +} + +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) +{ + al_serdes_grp_reg_masked_write(grp_info, (enum al_serdes_reg_page)lane, + type, offset, mask, data); +} + +/******************************************************************************/ +/******************************************************************************/ +static void _al_serdes_lane_rx_rate_change_sw_flow_dis( + struct al_serdes_group_info *grp_info, + enum al_serdes_lane lane) +{ + al_bool lane_sw_flow_enabled; + + al_assert(lane != AL_SRDS_LANES_0123); + + lane_sw_flow_enabled = + (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, 201) == 0xfc) && + (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, 202) == 0xff) && + (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, 203) == 0xff) && + (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, 204) == 0xff) && + (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, 205) == 0xff); + + /** + * Disable the Rx rate change software flow by clearing bit 7 of lane PMA register 205 + * (RSTPDOVR_RX_OVREN) + */ + if (lane_sw_flow_enabled) { + al_dbg("%s(%d): actually disabling\n", __func__, lane); + al_serdes_grp_reg_masked_write(grp_info, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, 205, 0x80, 0x00); + } +} + +/******************************************************************************/ +/******************************************************************************/ +static void al_serdes_group_rx_rate_change_sw_flow_dis( + struct al_serdes_group_info *grp_info) +{ + int lane; + + for (lane = AL_SRDS_LANE_0; lane < AL_SRDS_NUM_LANES; lane++) + _al_serdes_lane_rx_rate_change_sw_flow_dis(grp_info, lane); +} + +/******************************************************************************/ +/******************************************************************************/ +static void _al_serdes_lane_rx_rate_change_sw_flow_en_cond( + struct al_serdes_group_info *grp_info, + enum al_serdes_lane lane) +{ + al_bool lane_sw_flow_almost_enabled; + al_bool group_reset_enabled; + al_bool lane_reset_enabled; + al_bool group_pd_enabled; + al_bool lane_pd_enabled; + + al_assert(lane != AL_SRDS_LANES_0123); + + lane_sw_flow_almost_enabled = + (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, 201) == 0xfc) && + (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, 202) == 0xff) && + (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, 203) == 0xff) && + (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, 204) == 0xff) && + (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, 205) == 0x7f); + + group_reset_enabled = + ((al_serdes_grp_reg_read( + grp_info, 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) && + ((al_serdes_grp_reg_read( + grp_info, 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) == + SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_SYNTH_VAL_ASSERT); + + lane_reset_enabled = + ((al_serdes_grp_reg_read( + grp_info, (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) && + ((al_serdes_grp_reg_read( + grp_info, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_REG_NUM) & + SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_MASK) == + SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_VAL_ASSERT); + + group_pd_enabled = + (al_serdes_grp_reg_read( + 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) == + SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_PD; + + lane_pd_enabled = + (al_serdes_grp_reg_read( + grp_info, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_LANEPCSPSTATE_RX_REG_NUM) & + SERDES_IREG_FLD_LANEPCSPSTATE_RX_MASK) == + SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_PD; + + /** + * Enable the Rx rate change software flow by setting bit 7 of lane PMA register 205 + * (RSTPDOVR_RX_OVREN) + */ + if (lane_sw_flow_almost_enabled && !group_reset_enabled && !lane_reset_enabled && + !group_pd_enabled && !lane_pd_enabled) { + al_dbg("%s(%d): actually enabling\n", __func__, lane); + + al_serdes_ns_delay(500); + al_serdes_grp_reg_masked_write(grp_info, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, 205, 0x80, 0x80); + } +} + +/******************************************************************************/ +/******************************************************************************/ +static void al_serdes_group_rx_rate_change_sw_flow_en_cond( + struct al_serdes_group_info *grp_info) +{ + int lane; + + for (lane = AL_SRDS_LANE_0; lane < AL_SRDS_NUM_LANES; lane++) + _al_serdes_lane_rx_rate_change_sw_flow_en_cond(grp_info, lane); +} + +/******************************************************************************/ +/******************************************************************************/ +int al_serdes_eye_measure_run( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + uint32_t timeout, + unsigned int *value) +{ + uint32_t reg = 0; + uint32_t i; + struct serdes_lane *lane_regs; + + lane_regs = &obj->grp_info[grp].regs_base->lane[lane]; + + al_reg_write32(&lane_regs->ictl_multi_rxeq, + SERDES_LANE_ICTL_MULTI_RXEQ_START_L_A); + + for (i = 0 ; i < timeout ; i++) { + reg = al_reg_read32(&lane_regs->octl_multi); + + if (reg & SERDES_LANE_OCTL_MULTI_RXEQ_DONE_L_A) + break; + + al_msleep(10); + } + + if (i == timeout) { + al_err("%s: measure eye failed on timeout\n", __func__); + return -ETIMEDOUT; + } + + *value = al_reg_read32(&lane_regs->odat_multi_rxeq); + + al_reg_write32(&lane_regs->ictl_multi_rxeq, 0); + + return 0; +} + +/******************************************************************************/ +/******************************************************************************/ +int al_serdes_eye_diag_sample( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + unsigned int x, + int y, + unsigned int timeout, + unsigned int *value) +{ + enum al_serdes_reg_page page = (enum al_serdes_reg_page)lane; + struct al_serdes_group_info *grp_info; + uint32_t i; + uint8_t sample_count_orig_msb; + uint8_t sample_count_orig_lsb; + + 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); + + grp_info = &obj->grp_info[grp]; + + /* Obtain sample count by reading RXCALROAMEYEMEAS_COUNT */ + sample_count_orig_msb = al_serdes_grp_reg_read(grp_info, + AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_MSB_REG_NUM); + sample_count_orig_lsb = al_serdes_grp_reg_read(grp_info, + AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_LSB_REG_NUM); + + /* Set sample count to ~100000 samples */ + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_MSB_REG_NUM, 0x13); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_LSB_REG_NUM, 0x88); + + /* BER Contour Overwrite */ + al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN_REG_NUM, + SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN, + 0); + al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN_REG_NUM, + SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN, + 0); + al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM, + SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN, + 0); + + /* RXROAM_XORBITSEL = 0x1 or 0x0 */ + al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXROAM_XORBITSEL_REG_NUM, + SERDES_IREG_FLD_RXROAM_XORBITSEL, + SERDES_IREG_FLD_RXROAM_XORBITSEL_2ND); + + /* Set X */ + al_serdes_grp_reg_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMXADJUST_REG_NUM, x); + + /* Set Y */ + al_serdes_grp_reg_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMYADJUST_REG_NUM, + y < 32 ? 31 - y : y + 1); + + /* Start Measurement by setting RXCALROAMEYEMEASIN_CYCLEEN = 0x1 */ + al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMEYEMEASIN_CYCLEEN_REG_NUM, + SERDES_IREG_FLD_RXCALROAMEYEMEASIN_CYCLEEN_START, + SERDES_IREG_FLD_RXCALROAMEYEMEASIN_CYCLEEN_START); + + /* Check RXCALROAMEYEMEASDONE Signal (Polling Until 0x1) */ + for (i = 0 ; i < timeout ; i++) { + if (al_serdes_grp_reg_read(grp_info, page, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMEYEMEASDONE_REG_NUM) & + SERDES_IREG_FLD_RXCALROAMEYEMEASDONE) + break; + al_udelay(1); + } + if (i == timeout) { + al_err("%s: eye diagram sampling timed out!\n", __func__); + return -ETIMEDOUT; + } + + /* Stop Measurement by setting RXCALROAMEYEMEASIN_CYCLEEN = 0x0 */ + al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMEYEMEASIN_CYCLEEN_REG_NUM, + SERDES_IREG_FLD_RXCALROAMEYEMEASIN_CYCLEEN_START, + 0); + + /* Obtain Error Counts by reading RXCALROAMEYEMEAS_ACC */ + *value = ((unsigned int)al_serdes_grp_reg_read(grp_info, page, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMEYEMEAS_ACC_MSB_REG_NUM)) << 8 | + al_serdes_grp_reg_read(grp_info, page, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMEYEMEAS_ACC_LSB_REG_NUM); + + /* BER Contour Overwrite */ + al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN_REG_NUM, + SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN, + SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN); + al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN_REG_NUM, + SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN, + SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN); + al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM, + SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN, + SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN); + + /* Restore sample count */ + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_MSB_REG_NUM, + sample_count_orig_msb); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_LSB_REG_NUM, + sample_count_orig_lsb); + + return 0; +} + +/******************************************************************************/ +/******************************************************************************/ +static void al_serdes_tx_deemph_set( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + uint32_t c_zero, + uint32_t c_plus_1, + uint32_t c_minus_1) +{ + al_serdes_grp_lane_masked_write( + &obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_TX_DRV_1_REG_NUM, + SERDES_IREG_TX_DRV_1_LEVN_MASK, + ((c_zero + c_plus_1 + c_minus_1) + << SERDES_IREG_TX_DRV_1_LEVN_SHIFT)); + + al_serdes_grp_lane_masked_write( + &obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_TX_DRV_2_REG_NUM, + SERDES_IREG_TX_DRV_2_LEVNM1_MASK, + (c_plus_1 << SERDES_IREG_TX_DRV_2_LEVNM1_SHIFT)); + + al_serdes_grp_lane_masked_write( + &obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_TX_DRV_3_REG_NUM, + SERDES_IREG_TX_DRV_3_LEVNP1_MASK, + (c_minus_1 << SERDES_IREG_TX_DRV_3_LEVNP1_SHIFT)); +} + +static void al_serdes_tx_deemph_get( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + uint32_t *c_zero, + uint32_t *c_plus_1, + uint32_t *c_minus_1) +{ + uint32_t reg = 0; + + reg = al_serdes_grp_lane_read( + &obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_TX_DRV_2_REG_NUM); + + *c_plus_1 = ((reg & SERDES_IREG_TX_DRV_2_LEVNM1_MASK) >> + SERDES_IREG_TX_DRV_2_LEVNM1_SHIFT); + + reg = al_serdes_grp_lane_read( + &obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_TX_DRV_3_REG_NUM); + + *c_minus_1 = ((reg & SERDES_IREG_TX_DRV_3_LEVNP1_MASK) >> + SERDES_IREG_TX_DRV_3_LEVNP1_SHIFT); + + reg = al_serdes_grp_lane_read( + &obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_TX_DRV_1_REG_NUM); + + *c_zero = (((reg & SERDES_IREG_TX_DRV_1_LEVN_MASK) >> + SERDES_IREG_TX_DRV_1_LEVN_SHIFT) - *c_plus_1 - *c_minus_1); +} + +al_bool al_serdes_tx_deemph_inc( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + enum al_serdes_tx_deemph_param param) +{ + al_bool ret = AL_TRUE; + uint32_t c0; + uint32_t c1; + uint32_t c_1; + + al_serdes_tx_deemph_get(obj, grp, lane, &c0, &c1, &c_1); + + al_dbg("%s: current txdeemph: c0 = 0x%x c1 = 0x%x c-1 = 0x%x\n", + __func__, c0, c1, c_1); + + switch (param) { + case AL_SERDES_TX_DEEMP_C_ZERO: + + if (c0 == AL_SERDES_TX_DEEMPH_C_ZERO_MAX_VAL) + return AL_FALSE; + + c0++; + + break; + case AL_SERDES_TX_DEEMP_C_PLUS: + + if (c1 == AL_SERDES_TX_DEEMPH_C_PLUS_MAX_VAL) + return AL_FALSE; + + c1++; + + break; + case AL_SERDES_TX_DEEMP_C_MINUS: + + if (c_1 == AL_SERDES_TX_DEEMPH_C_MINUS_MAX_VAL) + return AL_FALSE; + + c_1++; + + break; + } + + if ((c0 + c1 + c_1) > AL_SERDES_TX_DEEMPH_SUM_MAX) { + al_dbg("%s: sum of all tx de-emphasis over the max limit\n", + __func__); + + return AL_FALSE; + } + + al_dbg("%s: new txdeemph: c0 = 0x%x c1 = 0x%x c-1 = 0x%x\n", + __func__, c0, c1, c_1); + + al_serdes_tx_deemph_set(obj, grp, lane, c0, c1, c_1); + + return ret; +} + +al_bool al_serdes_tx_deemph_dec( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + enum al_serdes_tx_deemph_param param) +{ + al_bool ret = AL_TRUE; + uint32_t c0; + uint32_t c1; + uint32_t c_1; + + al_serdes_tx_deemph_get(obj, grp, lane, &c0, &c1, &c_1); + + al_dbg("%s: current txdeemph: c0 = 0x%x c1 = 0x%x c-1 = 0x%x\n", + __func__, c0, c1, c_1); + + switch (param) { + case AL_SERDES_TX_DEEMP_C_ZERO: + + if (c0 == AL_SERDES_TX_DEEMPH_C_ZERO_MIN_VAL) + return AL_FALSE; + + c0--; + + break; + case AL_SERDES_TX_DEEMP_C_PLUS: + + if (c1 == AL_SERDES_TX_DEEMPH_C_PLUS_MIN_VAL) + return AL_FALSE; + + c1--; + + break; + case AL_SERDES_TX_DEEMP_C_MINUS: + + if (c_1 == AL_SERDES_TX_DEEMPH_C_MINUS_MIN_VAL) + return AL_FALSE; + + c_1--; + + break; + } + + al_dbg("%s: new txdeemph: c0 = 0x%x c1 = 0x%x c-1 = 0x%x\n", + __func__, c0, c1, c_1); + + al_serdes_tx_deemph_set(obj, grp, lane, c0, c1, c_1); + + return ret; +} + +void al_serdes_tx_deemph_preset( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane) +{ + uint32_t c0; + uint32_t c1; + uint32_t c_1; + + c0 = AL_SERDES_TX_DEEMPH_C_ZERO_PRESET; + + c1 = AL_SERDES_TX_DEEMPH_C_PLUS_PRESET; + + c_1 = AL_SERDES_TX_DEEMPH_C_MINUS_PRESET; + + al_dbg("preset: new txdeemph: c0 = 0x%x c1 = 0x%x c-1 = 0x%x\n", + c0, c1, c_1); + + al_serdes_tx_deemph_set(obj, grp, lane, c0, c1, c_1); +} + +al_bool al_serdes_signal_is_detected( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane) +{ + uint32_t reg = 0; + + reg = al_serdes_grp_lane_read( + &obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXRANDET_REG_NUM); + + return ((reg & SERDES_IREG_FLD_RXRANDET_STAT) ? AL_TRUE : AL_FALSE); +} + +void al_serdes_tx_advanced_params_set(struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + struct al_serdes_adv_tx_params *params) +{ + uint8_t reg = 0; + + if(!params->override) { + al_serdes_grp_lane_masked_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN_REG_NUM, + SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN, + SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN); + + return; + } + + al_serdes_grp_lane_masked_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN_REG_NUM, + SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN, + 0); + + AL_REG_FIELD_SET(reg, + SERDES_IREG_TX_DRV_1_HLEV_MASK, + SERDES_IREG_TX_DRV_1_HLEV_SHIFT, + params->amp); + + AL_REG_FIELD_SET(reg, + SERDES_IREG_TX_DRV_1_LEVN_MASK, + SERDES_IREG_TX_DRV_1_LEVN_SHIFT, + params->total_driver_units); + + al_serdes_grp_lane_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_TX_DRV_1_REG_NUM, + reg); + + reg = 0; + AL_REG_FIELD_SET(reg, + SERDES_IREG_TX_DRV_2_LEVNM1_MASK, + SERDES_IREG_TX_DRV_2_LEVNM1_SHIFT, + params->c_plus_1); + + AL_REG_FIELD_SET(reg, + SERDES_IREG_TX_DRV_2_LEVNM2_MASK, + SERDES_IREG_TX_DRV_2_LEVNM2_SHIFT, + params->c_plus_2); + + al_serdes_grp_lane_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_TX_DRV_2_REG_NUM, + reg); + + reg = 0; + AL_REG_FIELD_SET(reg, + SERDES_IREG_TX_DRV_3_LEVNP1_MASK, + SERDES_IREG_TX_DRV_3_LEVNP1_SHIFT, + params->c_minus_1); + + AL_REG_FIELD_SET(reg, + SERDES_IREG_TX_DRV_3_SLEW_MASK, + SERDES_IREG_TX_DRV_3_SLEW_SHIFT, + params->slew_rate); + + al_serdes_grp_lane_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_TX_DRV_3_REG_NUM, + reg); + +} + +void al_serdes_tx_advanced_params_get(struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + struct al_serdes_adv_tx_params *tx_params) +{ + uint8_t reg_val = 0; + + al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_TX_DRV_1_REG_NUM, + ®_val); + tx_params->amp = (reg_val & SERDES_IREG_TX_DRV_1_HLEV_MASK) >> + SERDES_IREG_TX_DRV_1_HLEV_SHIFT; + tx_params->total_driver_units = (reg_val & + SERDES_IREG_TX_DRV_1_LEVN_MASK) >> + SERDES_IREG_TX_DRV_1_LEVN_SHIFT; + + al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_TX_DRV_2_REG_NUM, + ®_val); + tx_params->c_plus_1 = (reg_val & SERDES_IREG_TX_DRV_2_LEVNM1_MASK) >> + SERDES_IREG_TX_DRV_2_LEVNM1_SHIFT; + tx_params->c_plus_2 = (reg_val & SERDES_IREG_TX_DRV_2_LEVNM2_MASK) >> + SERDES_IREG_TX_DRV_2_LEVNM2_SHIFT; + + al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_TX_DRV_3_REG_NUM, + ®_val); + tx_params->c_minus_1 = (reg_val & SERDES_IREG_TX_DRV_3_LEVNP1_MASK) >> + SERDES_IREG_TX_DRV_3_LEVNP1_SHIFT; + tx_params->slew_rate = (reg_val & SERDES_IREG_TX_DRV_3_SLEW_MASK) >> + SERDES_IREG_TX_DRV_3_SLEW_SHIFT; + + al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN_REG_NUM, + ®_val); + tx_params->override = ((reg_val & SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN) == 0); +} + + +void al_serdes_rx_advanced_params_set(struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + struct al_serdes_adv_rx_params *params) +{ + uint8_t reg = 0; + + if(!params->override) { + al_serdes_grp_lane_masked_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN_REG_NUM, + SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN, + SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN); + + return; + } + + al_serdes_grp_lane_masked_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN_REG_NUM, + SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN, + 0); + + AL_REG_FIELD_SET(reg, + SERDES_IREG_RX_CALEQ_1_DCGAIN_MASK, + SERDES_IREG_RX_CALEQ_1_DCGAIN_SHIFT, + params->dcgain); + + AL_REG_FIELD_SET(reg, + SERDES_IREG_RX_CALEQ_1_DFEPSTAP3DB_MASK, + SERDES_IREG_RX_CALEQ_1_DFEPSTAP3DB_SHIFT, + params->dfe_3db_freq); + + al_serdes_grp_lane_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_RX_CALEQ_1_REG_NUM, + reg); + + reg = 0; + AL_REG_FIELD_SET(reg, + SERDES_IREG_RX_CALEQ_2_DFEPSTAPGAIN_MASK, + SERDES_IREG_RX_CALEQ_2_DFEPSTAPGAIN_SHIFT, + params->dfe_gain); + + AL_REG_FIELD_SET(reg, + SERDES_IREG_RX_CALEQ_2_DFETAP1GAIN_MASK, + SERDES_IREG_RX_CALEQ_2_DFETAP1GAIN_SHIFT, + params->dfe_first_tap_ctrl); + + al_serdes_grp_lane_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_RX_CALEQ_2_REG_NUM, + reg); + + reg = 0; + AL_REG_FIELD_SET(reg, + SERDES_IREG_RX_CALEQ_3_DFETAP2GAIN_MASK, + SERDES_IREG_RX_CALEQ_3_DFETAP2GAIN_SHIFT, + params->dfe_secound_tap_ctrl); + + AL_REG_FIELD_SET(reg, + SERDES_IREG_RX_CALEQ_3_DFETAP3GAIN_MASK, + SERDES_IREG_RX_CALEQ_3_DFETAP3GAIN_SHIFT, + params->dfe_third_tap_ctrl); + + al_serdes_grp_lane_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_RX_CALEQ_3_REG_NUM, + reg); + + reg = 0; + AL_REG_FIELD_SET(reg, + SERDES_IREG_RX_CALEQ_4_DFETAP4GAIN_MASK, + SERDES_IREG_RX_CALEQ_4_DFETAP4GAIN_SHIFT, + params->dfe_fourth_tap_ctrl); + + AL_REG_FIELD_SET(reg, + SERDES_IREG_RX_CALEQ_4_LOFREQAGCGAIN_MASK, + SERDES_IREG_RX_CALEQ_4_LOFREQAGCGAIN_SHIFT, + params->low_freq_agc_gain); + + al_serdes_grp_lane_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_RX_CALEQ_4_REG_NUM, + reg); + + reg = 0; + AL_REG_FIELD_SET(reg, + SERDES_IREG_RX_CALEQ_5_PRECAL_CODE_SEL_MASK, + SERDES_IREG_RX_CALEQ_5_PRECAL_CODE_SEL_SHIFT, + params->precal_code_sel); + + AL_REG_FIELD_SET(reg, + SERDES_IREG_RX_CALEQ_5_HIFREQAGCCAP_MASK, + SERDES_IREG_RX_CALEQ_5_HIFREQAGCCAP_SHIFT, + params->high_freq_agc_boost); + + al_serdes_grp_lane_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_RX_CALEQ_5_REG_NUM, + reg); +} + +static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_info) +{ + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXEQ_LOOKUP_CODE_EN_REG_NUM, + SERDES_IREG_FLD_RXEQ_LOOKUP_CODE_EN_MASK, + (0x1 << SERDES_IREG_FLD_RXEQ_LOOKUP_CODE_EN_SHIFT)); + + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXEQ_LOOKUP_LASTCODE_REG_NUM, + SERDES_IREG_FLD_RXEQ_LOOKUP_LASTCODE_MASK, + (0 << SERDES_IREG_FLD_RXEQ_LOOKUP_LASTCODE_SHIFT)); + + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXEQ_COARSE_RUN1_MASK_REG_NUM, + SERDES_IREG_FLD_RXEQ_COARSE_RUN1_MASK_MASK, + (0x2 << SERDES_IREG_FLD_RXEQ_COARSE_RUN1_MASK_SHIFT)); + + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXEQ_COARSE_RUN2_MASK_REG_NUM, + SERDES_IREG_FLD_RXEQ_COARSE_RUN2_MASK_MASK, + (0 << SERDES_IREG_FLD_RXEQ_COARSE_RUN2_MASK_SHIFT)); + + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXEQ_COARSE_STEP_REG_NUM, + SERDES_IREG_FLD_RXEQ_COARSE_STEP_MASK, + (0x1 << SERDES_IREG_FLD_RXEQ_COARSE_STEP_SHIFT)); + + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXEQ_COARSE_ITER_NUM_REG_NUM, + SERDES_IREG_FLD_RXEQ_COARSE_ITER_NUM_MASK, + (0x1 << SERDES_IREG_FLD_RXEQ_COARSE_ITER_NUM_SHIFT)); + + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXEQ_FINE_RUN1_MASK_REG_NUM, + SERDES_IREG_FLD_RXEQ_FINE_RUN1_MASK_MASK, + (0xf0 << SERDES_IREG_FLD_RXEQ_FINE_RUN1_MASK_SHIFT)); + + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXEQ_FINE_RUN2_MASK_REG_NUM, + SERDES_IREG_FLD_RXEQ_FINE_RUN2_MASK_MASK, + (0 << SERDES_IREG_FLD_RXEQ_FINE_RUN2_MASK_SHIFT)); + + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXEQ_FINE_STEP_REG_NUM, + SERDES_IREG_FLD_RXEQ_FINE_STEP_MASK, + (1 << SERDES_IREG_FLD_RXEQ_FINE_STEP_SHIFT)); + + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXEQ_FINE_ITER_NUM_REG_NUM, + SERDES_IREG_FLD_RXEQ_FINE_ITER_NUM_MASK, + (0x8 << SERDES_IREG_FLD_RXEQ_FINE_ITER_NUM_SHIFT)); + + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD1_REG_NUM, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD1_MASK, + (0 << SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD1_SHIFT)); + + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD2_REG_NUM, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD2_MASK, + (0x64 << SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD2_SHIFT)); + + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_REG_NUM, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_MASK, + (0x3 << SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_SHIFT)); + + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_REG_NUM, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_MASK, + (0x1 << SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_SHIFT)); + + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_REG_NUM, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_MASK, + (3 << SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_SHIFT)); + + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_REG_NUM, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_MASK, + (1 << SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_SHIFT)); + + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_MSB_REG_NUM, + SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_MSB_MASK, + (0xc << SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_MSB_SHIFT)); + + al_serdes_grp_reg_masked_write( + grp_info, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_LSB_REG_NUM, + SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_LSB_MASK, + (0xcc << SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_LSB_SHIFT)); +} + +struct al_serdes_mode_rx_tx_inv_state { + al_bool restore; + uint32_t pipe_rst; + uint32_t ipd_multi[AL_SRDS_NUM_LANES]; + uint8_t inv_value[AL_SRDS_NUM_LANES]; +}; + +static void al_serdes_mode_rx_tx_inv_state_save( + struct al_serdes_group_info *grp_info, + struct al_serdes_mode_rx_tx_inv_state *state) +{ + if (al_reg_read32(&grp_info->regs_base->gen.irst) & SERDES_GEN_IRST_POR_B_A) { + int i; + + state->restore = AL_TRUE; + state->pipe_rst = al_reg_read32(&grp_info->regs_base->gen.irst); + + for (i = 0; i < AL_SRDS_NUM_LANES; i++) { + state->inv_value[i] = al_serdes_grp_reg_read( + grp_info, + i, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_POLARITY_RX_REG_NUM); + state->ipd_multi[i] = + al_reg_read32(&grp_info->regs_base->lane[i].ipd_multi); + } + } else { + state->restore = AL_FALSE; + } +} + +static void al_serdes_mode_rx_tx_inv_state_restore( + struct al_serdes_group_info *grp_info, + struct al_serdes_mode_rx_tx_inv_state *state) +{ + if (state->restore) { + int i; + + for (i = 0; i < AL_SRDS_NUM_LANES; i++) { + al_serdes_grp_reg_write( + grp_info, + i, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_POLARITY_RX_REG_NUM, + state->inv_value[i]); + al_reg_write32( + &grp_info->regs_base->lane[i].ipd_multi, state->ipd_multi[i]); + al_reg_write32_masked( + &grp_info->regs_base->gen.irst, + (SERDES_GEN_IRST_PIPE_RST_L0_B_A_SEL >> i) | + (SERDES_GEN_IRST_PIPE_RST_L0_B_A >> i), + state->pipe_rst); + } + } +} + +void al_serdes_mode_set_sgmii( + struct al_serdes_obj *obj, + enum al_serdes_group grp) +{ + struct al_serdes_group_info *grp_info; + struct al_serdes_mode_rx_tx_inv_state rx_tx_inv_state; + + al_assert(obj); + al_assert(((int)grp) >= AL_SRDS_GRP_A); + al_assert(((int)grp) <= AL_SRDS_GRP_D); + + grp_info = &obj->grp_info[grp]; + + al_serdes_mode_rx_tx_inv_state_save(grp_info, &rx_tx_inv_state); + + al_reg_write32(&grp_info->regs_base->gen.irst, 0x000000); + al_reg_write32(&grp_info->regs_base->lane[0].ictl_multi, 0x10110010); + al_reg_write32(&grp_info->regs_base->lane[1].ictl_multi, 0x10110010); + al_reg_write32(&grp_info->regs_base->lane[2].ictl_multi, 0x10110010); + al_reg_write32(&grp_info->regs_base->lane[3].ictl_multi, 0x10110010); + al_reg_write32(&grp_info->regs_base->gen.ipd_multi_synth , 0x0001); + al_reg_write32(&grp_info->regs_base->lane[0].ipd_multi, 0x0003); + al_reg_write32(&grp_info->regs_base->lane[1].ipd_multi, 0x0003); + al_reg_write32(&grp_info->regs_base->lane[2].ipd_multi, 0x0003); + al_reg_write32(&grp_info->regs_base->lane[3].ipd_multi, 0x0003); + al_reg_write32(&grp_info->regs_base->gen.ictl_pcs , 0); + al_reg_write32(&grp_info->regs_base->gen.irst, 0x001000); + al_serdes_ns_delay(800); + al_reg_write32(&grp_info->regs_base->gen.irst, 0x000000); + al_serdes_ns_delay(500); + al_reg_write32(&grp_info->regs_base->gen.irst, 0x001000); + al_serdes_ns_delay(500); + + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 101, 183); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 102, 183); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 103, 12); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 104, 12); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 105, 26); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 106, 26); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 107, 2); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 108, 2); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 109, 17); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 110, 13); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 101, 153); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 102, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 103, 108); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 104, 183); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 105, 183); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 106, 12); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 107, 12); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 108, 26); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 109, 26); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 110, 7); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 111, 12); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 112, 8); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 113, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 114, 8); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 115, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 116, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 117, 179); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 118, 246); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 119, 208); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 120, 239); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 121, 251); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 122, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 123, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 124, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 125, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 126, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 127, 211); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 128, 211); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 129, 226); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 130, 239); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 131, 251); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 132, 251); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 133, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 134, 239); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 135, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 136, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 137, 211); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 138, 211); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 139, 226); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 140, 239); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 141, 251); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 142, 251); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 143, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 144, 239); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 145, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 146, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 147, 251); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 148, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 149, 63); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 150, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 151, 100); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 152, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 153, 4); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 154, 2); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 155, 5); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 156, 5); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 157, 4); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 158, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 159, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 160, 8); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 161, 4); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 162, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 163, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 164, 4); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0_LANE_0, + AL_SRDS_REG_TYPE_PMA, 7, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_1_LANE_1, + AL_SRDS_REG_TYPE_PMA, 7, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_2_LANE_2, + AL_SRDS_REG_TYPE_PMA, 7, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_3_LANE_3, + AL_SRDS_REG_TYPE_PMA, 7, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 13, 16); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 48, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 49, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 54, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 55, 180); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 93, 2); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 165, 3); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 41, 6); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 354, 3); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 355, 58); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 356, 9); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 357, 3); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 358, 62); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 359, 12); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 701, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 87, 0x1f); + + al_serdes_common_cfg_eth(grp_info); + + al_serdes_mode_rx_tx_inv_state_restore(grp_info, &rx_tx_inv_state); + + al_reg_write32(&grp_info->regs_base->gen.irst, 0x0011F0); + al_serdes_ns_delay(500); +} + +void al_serdes_mode_set_kr( + struct al_serdes_obj *obj, + enum al_serdes_group grp) +{ + struct al_serdes_group_info *grp_info; + struct al_serdes_mode_rx_tx_inv_state rx_tx_inv_state; + + al_assert(obj); + al_assert(((int)grp) >= AL_SRDS_GRP_A); + al_assert(((int)grp) <= AL_SRDS_GRP_D); + + grp_info = &obj->grp_info[grp]; + + al_serdes_mode_rx_tx_inv_state_save(grp_info, &rx_tx_inv_state); + + al_reg_write32(&grp_info->regs_base->gen.irst, 0x000000); + al_reg_write32(&grp_info->regs_base->lane[0].ictl_multi, 0x30330030); + al_reg_write32(&grp_info->regs_base->lane[1].ictl_multi, 0x30330030); + al_reg_write32(&grp_info->regs_base->lane[2].ictl_multi, 0x30330030); + al_reg_write32(&grp_info->regs_base->lane[3].ictl_multi, 0x30330030); + al_reg_write32(&grp_info->regs_base->gen.ipd_multi_synth , 0x0001); + al_reg_write32(&grp_info->regs_base->lane[0].ipd_multi, 0x0003); + al_reg_write32(&grp_info->regs_base->lane[1].ipd_multi, 0x0003); + al_reg_write32(&grp_info->regs_base->lane[2].ipd_multi, 0x0003); + al_reg_write32(&grp_info->regs_base->lane[3].ipd_multi, 0x0003); + al_reg_write32(&grp_info->regs_base->gen.ictl_pcs , 0); + al_reg_write32(&grp_info->regs_base->gen.irst, 0x001000); + al_serdes_ns_delay(800); + al_reg_write32(&grp_info->regs_base->gen.irst, 0x000000); + al_serdes_ns_delay(500); + al_reg_write32(&grp_info->regs_base->gen.irst, 0x001000); + al_serdes_ns_delay(500); + + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 101, 189); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 102, 189); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 103, 6); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 104, 6); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 105, 27); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 106, 27); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 107, 1); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 108, 1); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 109, 119); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 110, 5); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 101, 170); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 102, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 103, 108); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 104, 189); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 105, 189); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 106, 6); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 107, 6); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 108, 27); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 109, 27); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 110, 7); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 111, 12); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 112, 16); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 113, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 114, 16); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 115, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 116, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 117, 179); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 118, 246); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 119, 208); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 120, 239); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 121, 251); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 122, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 123, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 124, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 125, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 126, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 127, 211); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 128, 211); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 129, 226); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 130, 239); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 131, 251); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 132, 251); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 133, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 134, 239); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 135, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 136, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 137, 211); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 138, 211); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 139, 226); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 140, 239); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 141, 251); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 142, 251); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 143, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 144, 239); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 145, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 146, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 147, 251); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 148, 255); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 149, 63); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 150, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 151, 50); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 152, 17); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 153, 2); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 154, 1); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 155, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 156, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 157, 4); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 158, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 159, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 160, 8); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 161, 4); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 162, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 163, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 164, 4); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0_LANE_0, + AL_SRDS_REG_TYPE_PMA, 7, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_1_LANE_1, + AL_SRDS_REG_TYPE_PMA, 7, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_2_LANE_2, + AL_SRDS_REG_TYPE_PMA, 7, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_3_LANE_3, + AL_SRDS_REG_TYPE_PMA, 7, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 13, 16); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 48, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 49, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 54, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 55, 149); /*Was 182*/ + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 93, 2); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 165, 3); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 41, 6); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 354, 3); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 355, 58); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 356, 9); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 357, 3); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 358, 62); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, 359, 12); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 701, 0); + al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + AL_SRDS_REG_TYPE_PMA, 87, 0x1f); + + al_serdes_common_cfg_eth(grp_info); + + al_serdes_mode_rx_tx_inv_state_restore(grp_info, &rx_tx_inv_state); + + al_reg_write32(&grp_info->regs_base->gen.irst, 0x0011F0); + al_serdes_ns_delay(500); +} + +void al_serdes_rx_advanced_params_get(struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + struct al_serdes_adv_rx_params* rx_params) +{ + uint8_t temp_val; + + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_RX_CALEQ_1_REG_NUM, + &temp_val); + rx_params->dcgain = (temp_val & SERDES_IREG_RX_CALEQ_1_DCGAIN_MASK) >> + SERDES_IREG_RX_CALEQ_1_DCGAIN_SHIFT; + rx_params->dfe_3db_freq = (temp_val & + SERDES_IREG_RX_CALEQ_1_DFEPSTAP3DB_MASK) >> + SERDES_IREG_RX_CALEQ_1_DFEPSTAP3DB_SHIFT; + + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_RX_CALEQ_2_REG_NUM, + &temp_val); + rx_params->dfe_gain = (temp_val & + SERDES_IREG_RX_CALEQ_2_DFEPSTAPGAIN_MASK) >> + SERDES_IREG_RX_CALEQ_2_DFEPSTAPGAIN_SHIFT; + rx_params->dfe_first_tap_ctrl = (temp_val & + SERDES_IREG_RX_CALEQ_2_DFETAP1GAIN_MASK) >> + SERDES_IREG_RX_CALEQ_2_DFETAP1GAIN_SHIFT; + + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_RX_CALEQ_3_REG_NUM, + &temp_val); + rx_params->dfe_secound_tap_ctrl = (temp_val & + SERDES_IREG_RX_CALEQ_3_DFETAP2GAIN_MASK) >> + SERDES_IREG_RX_CALEQ_3_DFETAP2GAIN_SHIFT; + rx_params->dfe_third_tap_ctrl = (temp_val & + SERDES_IREG_RX_CALEQ_3_DFETAP3GAIN_MASK) >> + SERDES_IREG_RX_CALEQ_3_DFETAP3GAIN_SHIFT; + + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_RX_CALEQ_4_REG_NUM, + &temp_val); + rx_params->dfe_fourth_tap_ctrl = (temp_val & + SERDES_IREG_RX_CALEQ_4_DFETAP4GAIN_MASK) >> + SERDES_IREG_RX_CALEQ_4_DFETAP4GAIN_SHIFT; + rx_params->low_freq_agc_gain = (temp_val & + SERDES_IREG_RX_CALEQ_4_LOFREQAGCGAIN_MASK) >> + SERDES_IREG_RX_CALEQ_4_LOFREQAGCGAIN_SHIFT; + + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_RX_CALEQ_5_REG_NUM, + &temp_val); + rx_params->precal_code_sel = (temp_val & + SERDES_IREG_RX_CALEQ_5_PRECAL_CODE_SEL_MASK) >> + SERDES_IREG_RX_CALEQ_5_PRECAL_CODE_SEL_SHIFT; + rx_params->high_freq_agc_boost = (temp_val & + SERDES_IREG_RX_CALEQ_5_HIFREQAGCCAP_MASK) >> + SERDES_IREG_RX_CALEQ_5_HIFREQAGCCAP_SHIFT; + + al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN_REG_NUM, + &temp_val); + rx_params->override = ((temp_val & SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN) == 0); +} + +#if ( SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN_REG_NUM != \ + SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN_REG_NUM || \ + SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN_REG_NUM != \ + SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN_REG_NUM) +#error Wrong assumption +#endif +int al_serdes_rx_equalization( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane) +{ + uint8_t serdes_ireg_fld_rxcalroamyadjust_locwren_val; + uint8_t serdes_ireg_fld_rxroam_xorbitsel_val; + uint8_t serdes_ireg_fld_pcsrxeq_locwren_val; + uint8_t serdes_ireg_fld_rxcal_locwren_val; + uint8_t temp_val; + uint8_t done; + + int test_score; + int i; + + /* + * Make sure Roam Eye mechanism is not overridden + * Lane SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN = 1, + * so Rx 4-Point Eye process is not overridden + * Lane SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN = 1, + * so Eye Roam latch is not overridden + * Lane SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN = 1, + * so Eye Roam latch 'X adjust' is not overridden + * Lane SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN = 1, + * so Eye Roam latch 'Y adjust' is not overridden + * Lane SERDES_IREG_FLD_RXROAM_XORBITSEL = 0/1, + * so Eye Roamlatch works on the right Eye position (XORBITSEL) + * For most cases 0 is needed, but sometimes 1 is needed. + * I couldn't sort out why is this so the code uses a global + * XORBITSELmode variable, set by the user (GUI). Default is 0. + * control must be internal. At the end we restore original setting + */ + + /* save current values for restoring them later in the end */ + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM, + &serdes_ireg_fld_rxcal_locwren_val); + + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM, + &serdes_ireg_fld_rxcalroamyadjust_locwren_val ); + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXROAM_XORBITSEL_REG_NUM, + &serdes_ireg_fld_rxroam_xorbitsel_val ); + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_PCSRXEQ_LOCWREN_REG_NUM, + &serdes_ireg_fld_pcsrxeq_locwren_val ); + + /* + * Set Bits: + * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN + * SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN + * SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN + * to return 4pt-RxEye and EyeRoam Latch to internal logic + * + * clear bit SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN + * AGC/DFE controlled via PMA registers + */ + temp_val = serdes_ireg_fld_rxcal_locwren_val; + temp_val |= SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN; + temp_val |= SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN; + temp_val |= SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN; + temp_val |= SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN; + + al_serdes_lane_write( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM, + temp_val ); + + /* + * Set bit SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN + * to return EyeRoam Latch Y to internal logic + */ + temp_val = serdes_ireg_fld_rxcalroamyadjust_locwren_val | + SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN; + al_serdes_lane_write( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM, + temp_val ); + + /* + * Clear Bit: SERDES_IREG_FLD_RXROAM_XORBITSEL + * so XORBITSEL=0, needed for the Eye mapping. + */ + temp_val = serdes_ireg_fld_rxroam_xorbitsel_val & + ~SERDES_IREG_FLD_RXROAM_XORBITSEL; + al_serdes_lane_write( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXROAM_XORBITSEL_REG_NUM, + temp_val ); + + /* + * Take Control from int.pin over RxEQ process. + * Clear Bit SERDES_IREG_FLD_PCSRXEQ_LOCWREN + * to override RxEQ via PMA + */ + temp_val = serdes_ireg_fld_pcsrxeq_locwren_val & + ~SERDES_IREG_FLD_PCSRXEQ_LOCWREN; + al_serdes_lane_write( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_PCSRXEQ_LOCWREN_REG_NUM, + temp_val ); + + + /* + * Start/Stop RxEQ Cal is via PCSRXEQ_START: 1=START. 0=STOP. + * Clear Bit SERDES_IREG_FLD_PCSRXEQ_START + * to start fresh from Stop + */ + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_PCSRXEQ_START_REG_NUM, + &temp_val ); + temp_val &= ~SERDES_IREG_FLD_PCSRXEQ_START; + al_serdes_lane_write( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_PCSRXEQ_START_REG_NUM, + temp_val ); + + /* Set Bit SERDES_IREG_FLD_PCSRXEQ_START + * to begin Rx Eq Cal */ + temp_val |= SERDES_IREG_FLD_PCSRXEQ_START; + al_serdes_lane_write( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_PCSRXEQ_START_REG_NUM, + temp_val ); + + /* Poll on RxEq Cal completion. SERDES_IREG_FLD_RXEQ_DONE. 1=Done. */ + for( i = 0; i < AL_SERDES_RX_EQUAL_TRIES; ++i ) { + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMEYEMEASDONE_REG_NUM, + &done ); + done &= SERDES_IREG_FLD_RXEQ_DONE; + + /* Check if RxEQ Cal is done */ + if (done) + break; + al_msleep(AL_SERDES_RX_EQUAL_MDELAY); + } + + if (!done) { + al_err("%s: Timeout!\n", __func__); + return -1; + } + + /* Stop the RxEQ process. */ + temp_val &= ~SERDES_IREG_FLD_PCSRXEQ_START; + al_serdes_lane_write( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_PCSRXEQ_START_REG_NUM, + temp_val ); + /* Get score */ + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_RXEQ_BEST_EYE_MSB_VAL_REG_NUM, + &temp_val ); + test_score = (int)( (temp_val & 0xFF) << 6 ); + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_RXEQ_BEST_EYE_LSB_VAL_REG_NUM, + &temp_val ); + test_score += (int)(temp_val & SERDES_IREG_RXEQ_BEST_EYE_LSB_VAL_MASK); + + /* Restore start values */ + al_serdes_lane_write( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM, + serdes_ireg_fld_rxcal_locwren_val); + al_serdes_lane_write( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM, + serdes_ireg_fld_rxcalroamyadjust_locwren_val ); + al_serdes_lane_write( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXROAM_XORBITSEL_REG_NUM, + serdes_ireg_fld_rxroam_xorbitsel_val ); + al_serdes_lane_write( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_PCSRXEQ_LOCWREN_REG_NUM, + serdes_ireg_fld_pcsrxeq_locwren_val ); + + return test_score; +} + +#if ( SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM != \ + SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN_REG_NUM || \ + SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM != \ + SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN_REG_NUM || \ + SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM != \ + SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN_REG_NUM) +#error Wrong assumption +#endif +int al_serdes_calc_eye_size( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + int* width, + int* height) +{ + uint8_t rxcaleyediagfsm_x_y_valweight_val; + uint8_t rxcaleyediagfsm_xvalcoarse_val; + uint8_t rxcaleyediagfsm_xvalfine_val; + uint8_t rxcaleyediagfsm_yvalcoarse_val; + uint8_t rxcaleyediagfsm_yvalfine_val; + uint8_t rxlock2ref_locwren_val; + uint8_t rxcal_locwren_val; + uint8_t rxcalroamyadjust_locwren_val; + uint8_t rxlock2ref_ovren_val; + + int i; + uint8_t status; + uint8_t reg_value; + + /* Save Registers */ + al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXLOCK2REF_LOCWREN_REG_NUM, + &rxlock2ref_locwren_val); + al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM, + &rxcal_locwren_val); + al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM, + &rxcalroamyadjust_locwren_val); + al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXLOCK2REF_OVREN_REG_NUM, + &rxlock2ref_ovren_val); + + al_serdes_reg_read(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_X_Y_VALWEIGHT_REG_NUM, + &rxcaleyediagfsm_x_y_valweight_val); + al_serdes_reg_read(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_REG_NUM, + &rxcaleyediagfsm_xvalcoarse_val); + al_serdes_reg_read(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_REG_NUM, + &rxcaleyediagfsm_xvalfine_val); + al_serdes_reg_read(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_REG_NUM, + &rxcaleyediagfsm_yvalcoarse_val); + al_serdes_reg_read(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_REG_NUM, + &rxcaleyediagfsm_yvalfine_val); + + /* + * Clear Bit: + * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN + * to override RxEQ via PMA + * Set Bits: + * SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN, + * SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN + * to keep Eye Diag Roam controlled internally + */ + al_serdes_grp_lane_masked_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM, + SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN | + SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN | + SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN, + SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN | + SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN); + /* + * Set Bit: + * SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN + * to keep Eye Diag Roam controlled internally + */ + al_serdes_grp_lane_masked_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM, + SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN, + SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN); + + /* + * Clear Bit: + * SERDES_IREG_FLD_RXROAM_XORBITSEL, + * so XORBITSEL=0, needed for the Eye mapping + * Set Bit: + * SERDES_IREG_FLD_RXLOCK2REF_OVREN, + * so RXLOCK2REF_OVREN=1, keeping lock to data, preventing data hit + */ + al_serdes_grp_lane_masked_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXROAM_XORBITSEL_REG_NUM, + SERDES_IREG_FLD_RXLOCK2REF_OVREN | + SERDES_IREG_FLD_RXROAM_XORBITSEL, + SERDES_IREG_FLD_RXLOCK2REF_OVREN); + + + /* + * Clear Bit: + * SERDES_IREG_FLD_RXLOCK2REF_LOCWREN, + * so RXLOCK2REF_LOCWREN=0, to override control + */ + al_serdes_grp_lane_masked_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXLOCK2REF_LOCWREN_REG_NUM, + SERDES_IREG_FLD_RXLOCK2REF_LOCWREN, + 0); + + /* Width Calculation */ + + /* Return Value = 0*Y + 1*X */ + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_X_Y_VALWEIGHT_REG_NUM, + 0x01); + /* X coarse scan step = 3 */ + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_REG_NUM, + 0x03); + /* X fine scan step = 1 */ + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_REG_NUM, + 0x01); + /* Y coarse scan step = 0 */ + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_REG_NUM, + 0x00); + /* Y fine scan step = 0 */ + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_REG_NUM, + 0x00); + + /* + * Set Bit: + * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, + * to start Eye measurement + */ + al_serdes_grp_lane_masked_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START_REG_NUM, + SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, + SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START); + + for( i = 0; i < AL_SERDES_RX_EYE_CAL_TRIES; ++i ) { + /* Check if RxEQ Cal is done */ + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_DONE_REG_NUM, + &status ); + if (status & SERDES_IREG_FLD_RXCALEYEDIAGFSM_DONE) + break; + al_msleep(AL_SERDES_RX_EYE_CAL_MDELAY); + } + + if (status & SERDES_IREG_FLD_RXCALEYEDIAGFSM_ERR) { + al_err("%s: eye measure error!\n", __func__); + return -1; + } + + if (!(status & SERDES_IREG_FLD_RXCALEYEDIAGFSM_DONE)) { + al_err("%s: eye measure timeout!\n", __func__); + return -1; + } + + /* Read Eye Opening Metrics, Bits: + * SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB, + * SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB + */ + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_MSB_REG_NUM, + ®_value ); + *width = reg_value << 6; + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB_REG_NUM, + ®_value ); + *width =+ reg_value & SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB_MAKE; + + /* + * Clear Bit: + * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, + * to stop Eye measurement + */ + al_serdes_grp_lane_masked_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START_REG_NUM, + SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, + 0); + + /* Height Calculation */ + + /* Return Value = 1*Y + 0*X */ + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_X_Y_VALWEIGHT_REG_NUM, + 0x10); + /* X coarse scan step = 0 */ + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_REG_NUM, + 0x00); + /* X fine scan step = 0 */ + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_REG_NUM, + 0x00); + /* Y coarse scan step = 3 */ + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_REG_NUM, + 0x03); + /* Y fine scan step = 1 */ + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_REG_NUM, + 0x01); + + /* + * Set Bit: + * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, + * to start Eye measurement + */ + al_serdes_grp_lane_masked_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START_REG_NUM, + SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, + SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START); + + for( i = 0; i < AL_SERDES_RX_EYE_CAL_TRIES; ++i ) { + /* Check if RxEQ Cal is done */ + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_DONE_REG_NUM, + &status ); + if (status & SERDES_IREG_FLD_RXCALEYEDIAGFSM_DONE) + break; + al_msleep(AL_SERDES_RX_EYE_CAL_MDELAY); + } + + if (status & SERDES_IREG_FLD_RXCALEYEDIAGFSM_ERR) { + al_err("%s: eye measure error!\n", __func__); + return -1; + } + + if (!(status & SERDES_IREG_FLD_RXCALEYEDIAGFSM_DONE)) { + al_err("%s: eye measure timeout!\n", __func__); + return -1; + } + + /* Read Eye Opening Metrics, Bits: + * SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB, + * SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB + */ + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_MSB_REG_NUM, + ®_value ); + *height = reg_value << 6; + al_serdes_lane_read( + obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB_REG_NUM, + ®_value ); + *height =+ reg_value & SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB_MAKE; + + /* + * Clear Bit: + * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, + * to stop Eye measurement + */ + al_serdes_grp_lane_masked_write(&obj->grp_info[grp], + lane, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START_REG_NUM, + SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, + 0); + + /* Restore Registers */ + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_X_Y_VALWEIGHT_REG_NUM, + rxcaleyediagfsm_x_y_valweight_val); + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_REG_NUM, + rxcaleyediagfsm_xvalcoarse_val); + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_REG_NUM, + rxcaleyediagfsm_xvalfine_val); + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_REG_NUM, + rxcaleyediagfsm_yvalcoarse_val); + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_REG_NUM, + rxcaleyediagfsm_yvalfine_val); + + al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXLOCK2REF_LOCWREN_REG_NUM, + rxlock2ref_locwren_val); + al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM, + rxcal_locwren_val); + al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM, + rxcalroamyadjust_locwren_val); + al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXLOCK2REF_OVREN_REG_NUM, + rxlock2ref_ovren_val); + return 0; +} + +void al_serdes_sris_config( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + struct al_serdes_sris_params *params) +{ + struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; + + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_PPMDRIFTCOUNT1_REG_NUM, + (params->ppm_drift_count & AL_FIELD_MASK(7, 0)) >> 0); + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_PPMDRIFTCOUNT2_REG_NUM, + (params->ppm_drift_count & AL_FIELD_MASK(15, 8)) >> 8); + + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_PPMDRIFTMAX1_REG_NUM, + (params->ppm_drift_max & AL_FIELD_MASK(7, 0)) >> 0); + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_PPMDRIFTMAX2_REG_NUM, + (params->ppm_drift_max & AL_FIELD_MASK(15, 8)) >> 8); + + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_SYNTHPPMDRIFTMAX1_REG_NUM, + (params->synth_ppm_drift_max & AL_FIELD_MASK(7, 0)) >> 0); + al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_SYNTHPPMDRIFTMAX2_REG_NUM, + (params->synth_ppm_drift_max & AL_FIELD_MASK(15, 8)) >> 8); + + al_serdes_grp_reg_masked_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PCS, + SERDES_IREG_FLD_PCS_EBUF_FULL_D2R1_REG_NUM, + SERDES_IREG_FLD_PCS_EBUF_FULL_D2R1_REG_MASK, + (params->full_d2r1) + << SERDES_IREG_FLD_PCS_EBUF_FULL_D2R1_REG_SHIFT); + + al_serdes_grp_reg_masked_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PCS, + SERDES_IREG_FLD_PCS_EBUF_FULL_PCIE_G3_REG_NUM, + SERDES_IREG_FLD_PCS_EBUF_FULL_PCIE_G3_REG_MASK, + (params->full_pcie_g3) + << SERDES_IREG_FLD_PCS_EBUF_FULL_PCIE_G3_REG_SHIFT); + + al_serdes_grp_reg_masked_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PCS, + SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_D2R1_REG_NUM, + SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_D2R1_REG_MASK, + (params->rd_threshold_d2r1) + << SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_D2R1_REG_SHIFT); + + al_serdes_grp_reg_masked_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PCS, + SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_PCIE_G3_REG_NUM, + SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_PCIE_G3_REG_MASK, + (params->rd_threshold_pcie_g3) + << SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_PCIE_G3_REG_SHIFT); +} diff --git a/al_hal_serdes.h b/al_hal_serdes.h new file mode 100644 index 00000000000..37aec839b2f --- /dev/null +++ b/al_hal_serdes.h @@ -0,0 +1,1125 @@ +/*- +******************************************************************************* +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. + +*******************************************************************************/ + +/** + * @defgroup group_serdes_api API + * SerDes HAL driver API + * @ingroup group_serdes SerDes + * @{ + * + * @file al_hal_serdes.h + * + * @brief Header file for the SerDes HAL driver + * + */ + +#ifndef __AL_HAL_SERDES_H__ +#define __AL_HAL_SERDES_H__ + +#include "al_hal_common.h" + +/* *INDENT-OFF* */ +#ifdef __cplusplus +extern "C" { +#endif +/* *INDENT-ON* */ + +struct al_serdes_obj; + +enum al_serdes_group { + AL_SRDS_GRP_A = 0, + AL_SRDS_GRP_B, + AL_SRDS_GRP_C, + AL_SRDS_GRP_D, + + AL_SRDS_NUM_GROUPS, +}; + +struct al_serdes_group_info { + /* + * Group parent object - filled automatically by al_serdes_handle_init + */ + struct al_serdes_obj *pobj; + + /* + * Group specific register base - filled automatically by + * al_sedres_handle_init + */ + struct al_serdes_regs __iomem *regs_base; +}; + +struct al_serdes_obj { + struct al_serdes_group_info grp_info[AL_SRDS_NUM_GROUPS]; +}; + +enum al_serdes_reg_page { + AL_SRDS_REG_PAGE_0_LANE_0 = 0, + AL_SRDS_REG_PAGE_1_LANE_1, + AL_SRDS_REG_PAGE_2_LANE_2, + AL_SRDS_REG_PAGE_3_LANE_3, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_PAGE_0123_LANES_0123 = 7, +}; + +enum al_serdes_reg_type { + AL_SRDS_REG_TYPE_PMA = 0, + AL_SRDS_REG_TYPE_PCS, +}; + +enum al_serdes_lane { + AL_SRDS_LANE_0 = AL_SRDS_REG_PAGE_0_LANE_0, + AL_SRDS_LANE_1 = AL_SRDS_REG_PAGE_1_LANE_1, + AL_SRDS_LANE_2 = AL_SRDS_REG_PAGE_2_LANE_2, + AL_SRDS_LANE_3 = AL_SRDS_REG_PAGE_3_LANE_3, + + AL_SRDS_NUM_LANES, + AL_SRDS_LANES_0123 = AL_SRDS_REG_PAGE_0123_LANES_0123, +}; + +/** Serdes loopback mode */ +enum al_serdes_lb_mode { + /** No loopback */ + AL_SRDS_LB_MODE_OFF, + + /** + * Transmits the untimed, partial equalized RX signal out the transmit + * IO pins. + * No clock used (untimed) + */ + AL_SRDS_LB_MODE_PMA_IO_UN_TIMED_RX_TO_TX, + + /** + * Loops back the TX serializer output into the CDR. + * CDR recovered bit clock used (without attenuation) + */ + AL_SRDS_LB_MODE_PMA_INTERNALLY_BUFFERED_SERIAL_TX_TO_RX, + + /** + * Loops back the TX driver IO signal to the RX IO pins + * CDR recovered bit clock used (only through IO) + */ + AL_SRDS_LB_MODE_PMA_SERIAL_TX_IO_TO_RX_IO, + + /** + * Parallel loopback from the PMA receive lane data ports, to the + * transmit lane data ports + * CDR recovered bit clock used + */ + AL_SRDS_LB_MODE_PMA_PARALLEL_RX_TO_TX, + + /** Loops received data after elastic buffer to transmit path */ + AL_SRDS_LB_MODE_PCS_PIPE, + + /** Loops TX data (to PMA) to RX path (instead of PMA data) */ + AL_SRDS_LB_MODE_PCS_NEAR_END, + + /** Loops receive data prior to interface block to transmit path */ + AL_SRDS_LB_MODE_PCS_FAR_END, +}; + +/** Serdes BIST pattern */ +enum al_serdes_bist_pattern { + AL_SRDS_BIST_PATTERN_USER, + AL_SRDS_BIST_PATTERN_PRBS7, + AL_SRDS_BIST_PATTERN_PRBS23, + AL_SRDS_BIST_PATTERN_PRBS31, + AL_SRDS_BIST_PATTERN_CLK1010, +}; + +/** SerDes group rate */ +enum al_serdes_rate { + AL_SRDS_RATE_1_8, + AL_SRDS_RATE_1_4, + AL_SRDS_RATE_1_2, + AL_SRDS_RATE_FULL, +}; + +/** SerDes power mode */ +enum al_serdes_pm { + AL_SRDS_PM_PD, + AL_SRDS_PM_P2, + AL_SRDS_PM_P1, + AL_SRDS_PM_P0S, + AL_SRDS_PM_P0, +}; + +/** SerDes PCIe Rate - values are important for proper behavior */ +enum al_serdes_pcie_rate { + AL_SRDS_PCIE_RATE_GEN1 = 0, + AL_SRDS_PCIE_RATE_GEN2, + AL_SRDS_PCIE_RATE_GEN3, +}; + +/** + * Initializes a SERDES object + * + * @param serdes_regs_base + * The SERDES register file base pointer + * + * @param obj + * An allocated, non initialized object context + * + * + * @return 0 if no error found. + * + */ +int al_serdes_handle_init( + void __iomem *serdes_regs_base, + struct al_serdes_obj *obj); + +/** + * SERDES register read + * + * Reads a SERDES register + * + * @param obj + * The object context + * + * @param grp + * The SERDES group + * + * @param page + * The SERDES register page within the group + * + * @param type + * The SERDES register type (PMA /PCS) + * + * @param offset + * The SERDES register offset (0 - 4095) + * + * @param data + * The read data + * + * + * @return 0 if no error found. + * + */ +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); + +/** + * SERDES register write + * + * Writes a SERDES register + * + * @param obj + * The object context + * + * @param grp + * The SERDES group + * + * @param page + * The SERDES register page within the group + * + * @param type + * The SERDES register type (PMA /PCS) + * + * @param offset + * The SERDES register offset (0 - 4095) + * + * @param data + * The data to write + * + * + * @return 0 if no error found. + * + */ +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); + +/** + * Enable BIST required overrides + * + * @param obj + * The object context + * @param grp + * The SERDES group + * @param rate + * The required speed rate + */ +void al_serdes_bist_overrides_enable( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_rate rate); + +/** + * Disable BIST required overrides + * + * @param obj + * The object context + * @param grp + * The SERDES group + * @param rate + * The required speed rate + */ +void al_serdes_bist_overrides_disable( + struct al_serdes_obj *obj, + enum al_serdes_group grp); + +/** + * Rx rate change + * + * @param obj + * The object context + * @param grp + * The SERDES group + * @param rate + * The Rx required rate + */ +void al_serdes_rx_rate_change( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_rate rate); + +/** + * SERDES lane Rx rate change software flow enable + * + * @param obj + * The object context + * @param grp + * The SERDES group + * @param lane + * The SERDES lane within the group + */ +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); + +/** + * SERDES lane Rx rate change software flow disable + * + * @param obj + * The object context + * @param grp + * The SERDES group + * @param lane + * The SERDES lane within the group + */ +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); + +/** + * PCIe lane rate override check + * + * @param obj + * The object context + * @param grp + * The SERDES group + * @param lane + * The SERDES lane within the group + * @returns AL_TRUE if the override is enabled + */ +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); + +/** + * PCIe lane rate override control + * + * @param obj + * The object context + * @param grp + * The SERDES group + * @param lane + * The SERDES lane within the group + * @param en + * Enable/disable + */ +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); + +/** + * PCIe lane rate get + * + * @param obj + * The object context + * @param grp + * The SERDES group + * @param lane + * The SERDES lane within the group + */ +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); + +/** + * PCIe lane rate set + * + * @param obj + * The object context + * @param grp + * The SERDES group + * @param lane + * The SERDES lane within the group + * @param rate + * The required rate + */ +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); + +/** + * SERDES group power mode control + * + * @param obj + * The object context + * @param grp + * The SERDES group + * @param pm + * The required power mode + */ +void al_serdes_group_pm_set( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_pm pm); + +/** + * SERDES lane power mode control + * + * @param obj + * The object context + * @param grp + * The SERDES group + * @param lane + * The SERDES lane within the group + * @param rx_pm + * The required RX power mode + * @param tx_pm + * The required TX power mode + */ +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); + +/** + * SERDES group PMA hard reset + * + * Controls Serdes group PMA hard reset + * + * @param obj + * The object context + * + * @param grp + * The SERDES group + * + * @param enable + * Enable/disable hard reset + */ +void al_serdes_pma_hard_reset_group( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + al_bool enable); + +/** + * SERDES lane PMA hard reset + * + * Controls Serdes lane PMA hard reset + * + * @param obj + * The object context + * + * @param grp + * The SERDES group + * + * @param lane + * The SERDES lane within the group + * + * @param enable + * Enable/disable hard reset + */ +void al_serdes_pma_hard_reset_lane( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + al_bool enable); + +/** + * SERDES loopback control + * + * Controls the loopback + * + * @param obj + * The object context + * + * @param grp + * The SERDES group + * + * @param lane + * The SERDES lane within the group + * + * @param mode + * The requested loopback mode + * + */ +void al_serdes_loopback_control( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + enum al_serdes_lb_mode mode); + +/** + * SERDES BIST pattern selection + * + * Selects the BIST pattern to be used + * + * @param obj + * The object context + * + * @param grp + * The SERDES group + * + * @param pattern + * The pattern to set + * + * @param user_data + * The pattern user data (when pattern == AL_SRDS_BIST_PATTERN_USER) + * 80 bits (8 bytes array) + * + */ +void al_serdes_bist_pattern_select( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_bist_pattern pattern, + uint8_t *user_data); + +/** + * SERDES BIST TX Enable + * + * Enables/disables TX BIST per lane + * + * @param obj + * The object context + * + * @param grp + * The SERDES group + * + * @param lane + * The SERDES lane within the group + * + * @param enable + * Enable or disable TX BIST + */ +void al_serdes_bist_tx_enable( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + al_bool enable); + +/** + * SERDES BIST TX single bit error injection + * + * Injects single bit error during a TX BIST + * + * @param obj + * The object context + * + * @param grp + * The SERDES group + */ +void al_serdes_bist_tx_err_inject( + struct al_serdes_obj *obj, + enum al_serdes_group grp); + +/** + * SERDES BIST RX Enable + * + * Enables/disables RX BIST per lane + * + * @param obj + * The object context + * + * @param grp + * The SERDES group + * + * @param lane + * The SERDES lane within the group + * + * @param enable + * Enable or disable TX BIST + */ +void al_serdes_bist_rx_enable( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + al_bool enable); + +/** + * SERDES BIST RX status + * + * Checks the RX BIST status for a specific SERDES lane + * + * @param obj + * The object context + * + * @param grp + * The SERDES group + * + * @param lane + * The SERDES lane within the group + * + * @param is_locked + * An indication whether RX BIST is locked + * + * @param err_cnt_overflow + * An indication whether error count overflow occured + * + * @param err_cnt + * Current bit error count + */ +void al_serdes_bist_rx_status( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + al_bool *is_locked, + al_bool *err_cnt_overflow, + uint16_t *err_cnt); + +/** + * SERDES Digital Test Bus + * + * Samples the digital test bus of a specific SERDES lane + * + * @param obj + * The object context + * + * @param grp + * The SERDES group + * + * @param lane + * The SERDES lane within the group + * + * @param sel + * The selected sampling group (0 - 31) + * + * @param sampled_data + * The sampled data (5 bytes array) + * + * + * @return 0 if no error found. + * + */ +int al_serdes_digital_test_bus( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + uint8_t sel, + uint8_t *sampled_data); + + +/* KR link training */ +/** + * Set the tx de-emphasis to preset values + * + * @param obj The object context + * + * @param grp The SERDES group + * + * @param lane The SERDES lane within the group + * + */ +void al_serdes_tx_deemph_preset( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane); + +/** + * Tx de-emphasis parameters + */ +enum al_serdes_tx_deemph_param { + AL_SERDES_TX_DEEMP_C_ZERO, /*< c(0) */ + AL_SERDES_TX_DEEMP_C_PLUS, /*< c(1) */ + AL_SERDES_TX_DEEMP_C_MINUS, /*< c(-1) */ +}; + +/** + * Increase tx de-emphasis param. + * + * @param obj The object context + * + * @param grp The SERDES group + * + * @param lane The SERDES lane within the group + * + * @param param which tx de-emphasis to change + * + * @return false in case max is reached. true otherwise. + */ +al_bool al_serdes_tx_deemph_inc( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + enum al_serdes_tx_deemph_param param); + +/** + * Decrease tx de-emphasis param. + * + * @param obj The object context + * + * @param grp The SERDES group + * + * @param lane The SERDES lane within the group + * + * @param param which tx de-emphasis to change + * + * @return false in case min is reached. true otherwise. + */ +al_bool al_serdes_tx_deemph_dec( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + enum al_serdes_tx_deemph_param param); + +/** + * run Rx eye measurement. + * + * @param obj The object context + * + * @param grp The SERDES group + * + * @param lane The SERDES lane within the group + * + * @param timeout timeout in uSec + * + * @param value Rx eye measurement value + * (0 - completely closed eye, 0xffff - completely open eye). + * + * @return 0 if no error found. + */ +int al_serdes_eye_measure_run( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + uint32_t timeout, + unsigned int *value); + +/** + * Eye diagram single sampling + * + * @param obj The object context + * + * @param grp The SERDES group + * + * @param lane The SERDES lane within the group + * + * @param x Sampling X position (0 - 63 --> -1.00 UI ... 1.00 UI) + * + * @param y Sampling Y position (0 - 62 --> 500mV ... -500mV) + * + * @param timeout timeout in uSec + * + * @param value Eye diagram sample value (BER - 0x0000 - 0xffff) + * + * @return 0 if no error found. + */ +int al_serdes_eye_diag_sample( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + unsigned int x, + int y, + unsigned int timeout, + unsigned int *value); + +/** + * Check if signal is detected + * + * @param obj The object context + * + * @param grp The SERDES group + * + * @param lane The SERDES lane within the group + * + * @return true if signal is detected. false otherwise. + */ +al_bool al_serdes_signal_is_detected( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane); + + +struct al_serdes_adv_tx_params { + /* + * select the input values location. + * When set to true the values will be taken from the internal registers + * that will be override with the next following parameters. + * When set to false the values will be taken from external pins (the + * other parameters in this case is not needed) + */ + al_bool override; + /* + * Transmit Amplitude control signal. Used to define the full-scale + * maximum swing of the driver. + * 000 - Not Supported + * 001 - 952mVdiff-pkpk + * 010 - 1024mVdiff-pkpk + * 011 - 1094mVdiff-pkpk + * 100 - 1163mVdiff-pkpk + * 101 - 1227mVdiff-pkpk + * 110 - 1283mVdiff-pkpk + * 111 - 1331mVdiff-pkpk + */ + uint8_t amp; + /* Defines the total number of driver units allocated in the driver */ + uint8_t total_driver_units; + /* Defines the total number of driver units allocated to the + * first post-cursor (C+1) tap. */ + uint8_t c_plus_1; + /* Defines the total number of driver units allocated to the + * second post-cursor (C+2) tap. */ + uint8_t c_plus_2; + /* Defines the total number of driver units allocated to the + * first pre-cursor (C-1) tap. */ + uint8_t c_minus_1; + /* TX driver Slew Rate control: + * 00 - 31ps + * 01 - 33ps + * 10 - 68ps + * 11 - 170ps + */ + uint8_t slew_rate; +}; + +struct al_serdes_adv_rx_params { + /* + * select the input values location. + * When set to true the values will be taken from the internal registers + * that will be override with the next following parameters. + * When set to false the values will be taken based in the equalization + * results (the other parameters in this case is not needed) + */ + al_bool override; + /* RX agc high frequency dc gain: + * -3'b000: -3dB + * -3'b001: -2.5dB + * -3'b010: -2dB + * -3'b011: -1.5dB + * -3'b100: -1dB + * -3'b101: -0.5dB + * -3'b110: -0dB + * -3'b111: 0.5dB + */ + uint8_t dcgain; + /* DFE post-shaping tap 3dB frequency + * -3'b000: 684MHz + * -3'b001: 576MHz + * -3'b010: 514MHz + * -3'b011: 435MHz + * -3'b100: 354MHz + * -3'b101: 281MHz + * -3'b110: 199MHz + * -3'b111: 125MHz + */ + uint8_t dfe_3db_freq; + /* DFE post-shaping tap gain + * 0: no pulse shaping tap + * 1: -24mVpeak + * 2: -45mVpeak + * 3: -64mVpeak + * 4: -80mVpeak + * 5: -93mVpeak + * 6: -101mVpeak + * 7: -105mVpeak + */ + uint8_t dfe_gain; + /* DFE first tap gain control + * -4'b0000: +1mVpeak + * -4'b0001: +10mVpeak + * .... + * -4'b0110: +55mVpeak + * -4'b0111: +64mVpeak + * -4'b1000: -1mVpeak + * -4'b1001: -10mVpeak + * .... + * -4'b1110: -55mVpeak + * -4'b1111: -64mVpeak + */ + uint8_t dfe_first_tap_ctrl; + /* DFE second tap gain control + * -4'b0000: +0mVpeak + * -4'b0001: +9mVpeak + * .... + * -4'b0110: +46mVpeak + * -4'b0111: +53mVpeak + * -4'b1000: -0mVpeak + * -4'b1001: -9mVpeak + * .... + * -4'b1110: -46mVpeak + * -4'b1111: -53mVpeak + */ + uint8_t dfe_secound_tap_ctrl; + /* DFE third tap gain control + * -4'b0000: +0mVpeak + * -4'b0001: +7mVpeak + * .... + * -4'b0110: +38mVpeak + * -4'b0111: +44mVpeak + * -4'b1000: -0mVpeak + * -4'b1001: -7mVpeak + * .... + * -4'b1110: -38mVpeak + * -4'b1111: -44mVpeak + */ + uint8_t dfe_third_tap_ctrl; + /* DFE fourth tap gain control + * -4'b0000: +0mVpeak + * -4'b0001: +6mVpeak + * .... + * -4'b0110: +29mVpeak + * -4'b0111: +33mVpeak + * -4'b1000: -0mVpeak + * -4'b1001: -6mVpeak + * .... + * -4'b1110: -29mVpeak + * -4'b1111: -33mVpeak + */ + uint8_t dfe_fourth_tap_ctrl; + /* Low frequency agc gain (att) select + * -3'b000: Disconnected + * -3'b001: -18.5dB + * -3'b010: -12.5dB + * -3'b011: -9dB + * -3'b100: -6.5dB + * -3'b101: -4.5dB + * -3'b110: -2.9dB + * -3'b111: -1.6dB + */ + uint8_t low_freq_agc_gain; + /* Provides a RX Equalizer pre-hint, prior to beginning + * adaptive equalization */ + uint8_t precal_code_sel; + /* High frequency agc boost control + * Min d0: Boost ~4dB + * Max d31: Boost ~20dB + */ + uint8_t high_freq_agc_boost; +}; + +/** + * configure tx advanced parameters + * + * @param obj The object context + * + * @param grp The SERDES group + * + * @param lane The SERDES lane within the group + * + * @param params pointer to the tx parameters + */ +void al_serdes_tx_advanced_params_set(struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + struct al_serdes_adv_tx_params *params); + +/** + * read tx advanced parameters + * + * @param obj The object context + * + * @param grp The SERDES group + * + * @param lane The SERDES lane within the group + * + * @param params pointer to the tx parameters + */ +void al_serdes_tx_advanced_params_get(struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + struct al_serdes_adv_tx_params *params); + +/** + * configure rx advanced parameters + * + * @param obj The object context + * + * @param grp The SERDES group + * + * @param lane The SERDES lane within the group + * + * @param params pointer to the rx parameters + */ +void al_serdes_rx_advanced_params_set(struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + struct al_serdes_adv_rx_params *params); + +/** + * read rx advanced parameters + * + * @param obj The object context + * + * @param grp The SERDES group + * + * @param lane The SERDES lane within the group + * + * @param params pointer to the rx parameters + */ +void al_serdes_rx_advanced_params_get(struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + struct al_serdes_adv_rx_params* params); + +/** + * Switch entire SerDes group to SGMII mode based on 156.25 Mhz reference clock + * + * @param obj The object context + * + * @param grp The SERDES group + */ +void al_serdes_mode_set_sgmii( + struct al_serdes_obj *obj, + enum al_serdes_group grp); + +/** + * Switch entire SerDes group to KR mode based on 156.25 Mhz reference clock + * + * @param obj The object context + * + * @param grp The SERDES group + */ +void al_serdes_mode_set_kr( + struct al_serdes_obj *obj, + enum al_serdes_group grp); + +/** + * performs SerDes HW equalization test and update equalization parameters + * + * @param obj the object context + * + * @param grp the SERDES group + * + * @param lane The SERDES lane within the group + */ +int al_serdes_rx_equalization( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane); + +/** + * performs Rx equalization and compute the width and height of the eye + * + * @param obj the object context + * + * @param grp the SERDES group + * + * @param lane The SERDES lane within the group + * + * @param width the output width of the eye + * + * @param height the output height of the eye + */ +int al_serdes_calc_eye_size( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + enum al_serdes_lane lane, + int* width, + int* height); + +/** + * SRIS parameters + */ +struct al_serdes_sris_params { + /* Controls the frequency accuracy threshold (ppm) for lock detection CDR */ + uint16_t ppm_drift_count; + /* Controls the frequency accuracy threshold (ppm) for lock detection in the CDR */ + uint16_t ppm_drift_max; + /* Controls the frequency accuracy threshold (ppm) for lock detection in PLL */ + uint16_t synth_ppm_drift_max; + /* Elastic buffer full threshold for PCIE modes: GEN1/GEN2 */ + uint8_t full_d2r1; + /* Elastic buffer full threshold for PCIE modes: GEN3 */ + uint8_t full_pcie_g3; + /* Elastic buffer midpoint threshold. + * Sets the depth of the buffer while in PCIE mode, GEN1/GEN2 + */ + uint8_t rd_threshold_d2r1; + /* Elastic buffer midpoint threshold. + * Sets the depth of the buffer while in PCIE mode, GEN3 + */ + uint8_t rd_threshold_pcie_g3; +}; + +/** + * SRIS: Separate Refclk Independent SSC (Spread Spectrum Clocking) + * Currently available only for PCIe interfaces. + * When working with local Refclk, same SRIS configuration in both serdes sides + * (EP and RC in PCIe interface) is required. + * + * performs SRIS configuration according to params + * + * @param obj the object context + * + * @param grp the SERDES group + * + * @param params the SRIS parameters + */ +void al_serdes_sris_config( + struct al_serdes_obj *obj, + enum al_serdes_group grp, + struct al_serdes_sris_params *params); + +/* *INDENT-OFF* */ +#ifdef __cplusplus +} +#endif + +/* *INDENT-ON* */ +#endif /* __AL_SRDS__ */ + +/** @} end of SERDES group */ + diff --git a/al_hal_serdes_internal_regs.h b/al_hal_serdes_internal_regs.h new file mode 100644 index 00000000000..8f53469bc4c --- /dev/null +++ b/al_hal_serdes_internal_regs.h @@ -0,0 +1,750 @@ +/*- +******************************************************************************* +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. + +*******************************************************************************/ +#ifndef __AL_SERDES_INTERNAL_REGS_H__ +#define __AL_SERDES_INTERNAL_REGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * Per lane register fields + ******************************************************************************/ +/* + * RX and TX lane hard reset + * 0 - Hard reset is asserted + * 1 - Hard reset is de-asserted + */ +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_REG_NUM 2 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_MASK 0x01 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_VAL_ASSERT 0x00 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_VAL_DEASSERT 0x01 + +/* + * RX and TX lane hard reset control + * 0 - Hard reset is taken from the interface pins + * 1 - Hard reset is taken from registers + */ +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_REG_NUM 2 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_MASK 0x02 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_VAL_IFACE 0x00 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_VAL_REGS 0x02 + +/* RX lane power state control */ +#define SERDES_IREG_FLD_LANEPCSPSTATE_RX_REG_NUM 3 +#define SERDES_IREG_FLD_LANEPCSPSTATE_RX_MASK 0x1f +#define SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_PD 0x01 +#define SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_P2 0x02 +#define SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_P1 0x04 +#define SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_P0S 0x08 +#define SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_P0 0x10 + +/* TX lane power state control */ +#define SERDES_IREG_FLD_LANEPCSPSTATE_TX_REG_NUM 4 +#define SERDES_IREG_FLD_LANEPCSPSTATE_TX_MASK 0x1f +#define SERDES_IREG_FLD_LANEPCSPSTATE_TX_VAL_PD 0x01 +#define SERDES_IREG_FLD_LANEPCSPSTATE_TX_VAL_P2 0x02 +#define SERDES_IREG_FLD_LANEPCSPSTATE_TX_VAL_P1 0x04 +#define SERDES_IREG_FLD_LANEPCSPSTATE_TX_VAL_P0S 0x08 +#define SERDES_IREG_FLD_LANEPCSPSTATE_TX_VAL_P0 0x10 + +/* RX lane word width */ +#define SERDES_IREG_FLD_PCSRX_DATAWIDTH_REG_NUM 5 +#define SERDES_IREG_FLD_PCSRX_DATAWIDTH_MASK 0x07 +#define SERDES_IREG_FLD_PCSRX_DATAWIDTH_VAL_8 0x00 +#define SERDES_IREG_FLD_PCSRX_DATAWIDTH_VAL_10 0x01 +#define SERDES_IREG_FLD_PCSRX_DATAWIDTH_VAL_16 0x02 +#define SERDES_IREG_FLD_PCSRX_DATAWIDTH_VAL_20 0x03 +#define SERDES_IREG_FLD_PCSRX_DATAWIDTH_VAL_32 0x04 +#define SERDES_IREG_FLD_PCSRX_DATAWIDTH_VAL_40 0x05 + +/* TX lane word width */ +#define SERDES_IREG_FLD_PCSTX_DATAWIDTH_REG_NUM 5 +#define SERDES_IREG_FLD_PCSTX_DATAWIDTH_MASK 0x70 +#define SERDES_IREG_FLD_PCSTX_DATAWIDTH_VAL_8 0x00 +#define SERDES_IREG_FLD_PCSTX_DATAWIDTH_VAL_10 0x10 +#define SERDES_IREG_FLD_PCSTX_DATAWIDTH_VAL_16 0x20 +#define SERDES_IREG_FLD_PCSTX_DATAWIDTH_VAL_20 0x30 +#define SERDES_IREG_FLD_PCSTX_DATAWIDTH_VAL_32 0x40 +#define SERDES_IREG_FLD_PCSTX_DATAWIDTH_VAL_40 0x50 + +/* RX lane rate select */ +#define SERDES_IREG_FLD_PCSRX_DIVRATE_REG_NUM 6 +#define SERDES_IREG_FLD_PCSRX_DIVRATE_MASK 0x07 +#define SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_8 0x00 +#define SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_4 0x01 +#define SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_2 0x02 +#define SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_1 0x03 + +/* TX lane rate select */ +#define SERDES_IREG_FLD_PCSTX_DIVRATE_REG_NUM 6 +#define SERDES_IREG_FLD_PCSTX_DIVRATE_MASK 0x70 +#define SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_8 0x00 +#define SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_4 0x10 +#define SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_2 0x20 +#define SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_1 0x30 + +/* + * PMA serial RX-to-TX loop-back enable (from AGC to IO Driver). Serial receive + * to transmit loopback: 0 - Disables loopback 1 - Transmits the untimed, + * partial equalized RX signal out the transmit IO pins + */ +#define SERDES_IREG_FLD_LB_RX2TXUNTIMEDEN_REG_NUM 7 +#define SERDES_IREG_FLD_LB_RX2TXUNTIMEDEN 0x10 + +/* + * PMA TX-to-RX buffered serial loop-back enable (bypasses IO Driver). Serial + * transmit to receive buffered loopback: 0 - Disables loopback 1 - Loops back + * the TX serializer output into the CDR + */ +#define SERDES_IREG_FLD_LB_TX2RXBUFTIMEDEN_REG_NUM 7 +#define SERDES_IREG_FLD_LB_TX2RXBUFTIMEDEN 0x20 + +/* + * PMA TX-to-RX I/O serial loop-back enable (loop back done directly from TX to + * RX pads). Serial IO loopback from the transmit lane IO pins to the receive + * lane IO pins: 0 - Disables loopback 1 - Loops back the driver IO signal to + * the RX IO pins + */ +#define SERDES_IREG_FLD_LB_TX2RXIOTIMEDEN_REG_NUM 7 +#define SERDES_IREG_FLD_LB_TX2RXIOTIMEDEN 0x40 + +/* + * PMA Parallel RX-to-TX loop-back enable. Parallel loopback from the PMA + * receive lane 20-bit data ports, to the transmit lane 20-bit data ports 0 - + * Disables loopback 1 - Loops back the 20-bit receive data port to the + * transmitter + */ +#define SERDES_IREG_FLD_LB_PARRX2TXTIMEDEN_REG_NUM 7 +#define SERDES_IREG_FLD_LB_PARRX2TXTIMEDEN 0x80 + +/* + * PMA CDR recovered-clock loopback enable; asserted when PARRX2TXTIMEDEN is 1. + * Transmit bit clock select: 0 - Selects synthesizer bit clock for transmit 1 + * - Selects CDR clock for transmit + */ +#define SERDES_IREG_FLD_LB_CDRCLK2TXEN_REG_NUM 7 +#define SERDES_IREG_FLD_LB_CDRCLK2TXEN 0x01 + +/* Receive lane BIST enable. Active High */ +#define SERDES_IREG_FLD_PCSRXBIST_EN_REG_NUM 8 +#define SERDES_IREG_FLD_PCSRXBIST_EN 0x01 + +/* TX lane BIST enable. Active High */ +#define SERDES_IREG_FLD_PCSTXBIST_EN_REG_NUM 8 +#define SERDES_IREG_FLD_PCSTXBIST_EN 0x02 + +/* + * RX BIST completion signal 0 - Indicates test is not completed 1 - Indicates + * the test has completed, and will remain high until a new test is initiated + */ +#define SERDES_IREG_FLD_RXBIST_DONE_REG_NUM 8 +#define SERDES_IREG_FLD_RXBIST_DONE 0x04 + +/* + * RX BIST error count overflow indicator. Indicates an overflow in the number + * of byte errors identified during the course of the test. This word is stable + * to sample when *_DONE_* signal has asserted + */ +#define SERDES_IREG_FLD_RXBIST_ERRCOUNT_OVERFLOW_REG_NUM 8 +#define SERDES_IREG_FLD_RXBIST_ERRCOUNT_OVERFLOW 0x08 + +/* + * RX BIST locked indicator 0 - Indicates BIST is not word locked and error + * comparisons have not begun yet 1 - Indicates BIST is word locked and error + * comparisons have begun + */ +#define SERDES_IREG_FLD_RXBIST_RXLOCKED_REG_NUM 8 +#define SERDES_IREG_FLD_RXBIST_RXLOCKED 0x10 + +/* + * RX BIST error count word. Indicates the number of byte errors identified + * during the course of the test. This word is stable to sample when *_DONE_* + * signal has asserted + */ +#define SERDES_IREG_FLD_RXBIST_ERRCOUNT_MSB_REG_NUM 9 +#define SERDES_IREG_FLD_RXBIST_ERRCOUNT_LSB_REG_NUM 10 + +/* Tx params */ +#define SERDES_IREG_TX_DRV_1_REG_NUM 21 +#define SERDES_IREG_TX_DRV_1_HLEV_MASK 0x7 +#define SERDES_IREG_TX_DRV_1_HLEV_SHIFT 0 +#define SERDES_IREG_TX_DRV_1_LEVN_MASK 0xf8 +#define SERDES_IREG_TX_DRV_1_LEVN_SHIFT 3 + +#define SERDES_IREG_TX_DRV_2_REG_NUM 22 +#define SERDES_IREG_TX_DRV_2_LEVNM1_MASK 0xf +#define SERDES_IREG_TX_DRV_2_LEVNM1_SHIFT 0 +#define SERDES_IREG_TX_DRV_2_LEVNM2_MASK 0x30 +#define SERDES_IREG_TX_DRV_2_LEVNM2_SHIFT 4 + +#define SERDES_IREG_TX_DRV_3_REG_NUM 23 +#define SERDES_IREG_TX_DRV_3_LEVNP1_MASK 0x7 +#define SERDES_IREG_TX_DRV_3_LEVNP1_SHIFT 0 +#define SERDES_IREG_TX_DRV_3_SLEW_MASK 0x18 +#define SERDES_IREG_TX_DRV_3_SLEW_SHIFT 3 + +/* Rx params */ +#define SERDES_IREG_RX_CALEQ_1_REG_NUM 24 +#define SERDES_IREG_RX_CALEQ_1_DCGAIN_MASK 0x7 +#define SERDES_IREG_RX_CALEQ_1_DCGAIN_SHIFT 0 +/* DFE post-shaping tap 3dB frequency */ +#define SERDES_IREG_RX_CALEQ_1_DFEPSTAP3DB_MASK 0x38 +#define SERDES_IREG_RX_CALEQ_1_DFEPSTAP3DB_SHIFT 3 + +#define SERDES_IREG_RX_CALEQ_2_REG_NUM 25 +/* DFE post-shaping tap gain */ +#define SERDES_IREG_RX_CALEQ_2_DFEPSTAPGAIN_MASK 0x7 +#define SERDES_IREG_RX_CALEQ_2_DFEPSTAPGAIN_SHIFT 0 +/* DFE first tap gain control */ +#define SERDES_IREG_RX_CALEQ_2_DFETAP1GAIN_MASK 0x78 +#define SERDES_IREG_RX_CALEQ_2_DFETAP1GAIN_SHIFT 3 + +#define SERDES_IREG_RX_CALEQ_3_REG_NUM 26 +#define SERDES_IREG_RX_CALEQ_3_DFETAP2GAIN_MASK 0xf +#define SERDES_IREG_RX_CALEQ_3_DFETAP2GAIN_SHIFT 0 +#define SERDES_IREG_RX_CALEQ_3_DFETAP3GAIN_MASK 0xf0 +#define SERDES_IREG_RX_CALEQ_3_DFETAP3GAIN_SHIFT 4 + +#define SERDES_IREG_RX_CALEQ_4_REG_NUM 27 +#define SERDES_IREG_RX_CALEQ_4_DFETAP4GAIN_MASK 0xf +#define SERDES_IREG_RX_CALEQ_4_DFETAP4GAIN_SHIFT 0 +#define SERDES_IREG_RX_CALEQ_4_LOFREQAGCGAIN_MASK 0x70 +#define SERDES_IREG_RX_CALEQ_4_LOFREQAGCGAIN_SHIFT 4 + +#define SERDES_IREG_RX_CALEQ_5_REG_NUM 28 +#define SERDES_IREG_RX_CALEQ_5_PRECAL_CODE_SEL_MASK 0x7 +#define SERDES_IREG_RX_CALEQ_5_PRECAL_CODE_SEL_SHIFT 0 +#define SERDES_IREG_RX_CALEQ_5_HIFREQAGCCAP_MASK 0xf8 +#define SERDES_IREG_RX_CALEQ_5_HIFREQAGCCAP_SHIFT 3 + +/* RX lane best eye point measurement result */ +#define SERDES_IREG_RXEQ_BEST_EYE_MSB_VAL_REG_NUM 29 +#define SERDES_IREG_RXEQ_BEST_EYE_LSB_VAL_REG_NUM 30 +#define SERDES_IREG_RXEQ_BEST_EYE_LSB_VAL_MASK 0x3F + +/* + * Adaptive RX Equalization enable + * 0 - Disables adaptive RX equalization. + * 1 - Enables adaptive RX equalization. + */ +#define SERDES_IREG_FLD_PCSRXEQ_START_REG_NUM 31 +#define SERDES_IREG_FLD_PCSRXEQ_START (1 << 0) + +/* + * Enables an eye diagram measurement + * within the PHY. + * 0 - Disables eye diagram measurement + * 1 - Enables eye diagram measurement + */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START_REG_NUM 31 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START (1 << 1) + + +/* + * RX lane single roam eye point measurement start signal. + * If asserted, single measurement at fix XADJUST and YADJUST is started. + */ +#define SERDES_IREG_FLD_RXCALROAMEYEMEASIN_CYCLEEN_REG_NUM 31 +#define SERDES_IREG_FLD_RXCALROAMEYEMEASIN_CYCLEEN_START (1 << 2) + + +/* + * PHY Eye diagram measurement status + * signal + * 0 - Indicates eye diagram results are not + * valid for sampling + * 1 - Indicates eye diagram is complete and + * results are valid for sampling + */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_DONE_REG_NUM 32 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_DONE (1 << 0) + +/* + * Eye diagram error signal. Indicates if the + * measurement was invalid because the eye + * diagram was interrupted by the link entering + * electrical idle. + * 0 - Indicates eye diagram is valid + * 1- Indicates an error occurred, and the eye + * diagram measurement should be re-run + */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_ERR_REG_NUM 32 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_ERR (1 << 1) + +/* + * PHY Adaptive Equalization status + * 0 - Indicates Adaptive Equalization results are not valid for sampling + * 1 - Indicates Adaptive Equalization is complete and results are valid for + * sampling + */ +#define SERDES_IREG_FLD_RXCALROAMEYEMEASDONE_REG_NUM 32 +#define SERDES_IREG_FLD_RXCALROAMEYEMEASDONE (1 << 2) + +/* + * + * PHY Adaptive Equalization Status Signal + * 0 – Indicates adaptive equalization results + * are not valid for sampling + * 1 – Indicates adaptive equalization is + * complete and results are valid for sampling. + */ +#define SERDES_IREG_FLD_RXEQ_DONE_REG_NUM 32 +#define SERDES_IREG_FLD_RXEQ_DONE (1 << 3) + + +/* + * 7-bit eye diagram time adjust control + * - 6-bits per UI + * - spans 2 UI + */ +#define SERDES_IREG_FLD_RXCALROAMXADJUST_REG_NUM 33 + +/* 6-bit eye diagram voltage adjust control - spans +/-300mVdiff */ +#define SERDES_IREG_FLD_RXCALROAMYADJUST_REG_NUM 34 + +/* + * Eye diagram status signal. Safe for + * sampling when *DONE* signal has + * asserted + * 14'h0000 - Completely Closed Eye + * 14'hFFFF - Completely Open Eye + */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_MSB_REG_NUM 35 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_MSB_MAKE 0xFF +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_MSB_SHIFT 0 + +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB_REG_NUM 36 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB_MAKE 0x3F +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB_SHIFT 0 + +/* + * RX lane single roam eye point measurement result. + * If 0, eye is open at current XADJUST and YADJUST settings. + */ +#define SERDES_IREG_FLD_RXCALROAMEYEMEAS_ACC_MSB_REG_NUM 37 +#define SERDES_IREG_FLD_RXCALROAMEYEMEAS_ACC_LSB_REG_NUM 38 + +/* + * Override enable for CDR lock to reference clock + * 0 - CDR is always locked to reference + * 1 - CDR operation mode (Lock2Reference or Lock2data are controlled internally + * depending on the incoming signal and ppm status) + */ +#define SERDES_IREG_FLD_RXLOCK2REF_OVREN_REG_NUM 39 +#define SERDES_IREG_FLD_RXLOCK2REF_OVREN (1 << 1) + +/* + * Selects Eye to capture based on edge + * 0 - Capture 1st Eye in Eye Diagram + * 1 - Capture 2nd Eye in Eye Diagram measurement + */ +#define SERDES_IREG_FLD_RXROAM_XORBITSEL_REG_NUM 39 +#define SERDES_IREG_FLD_RXROAM_XORBITSEL (1 << 2) +#define SERDES_IREG_FLD_RXROAM_XORBITSEL_1ST 0 +#define SERDES_IREG_FLD_RXROAM_XORBITSEL_2ND (1 << 2) + +/* + * RX Signal detect. 0 indicates no signal, 1 indicates signal detected. + */ +#define SERDES_IREG_FLD_RXRANDET_REG_NUM 41 +#define SERDES_IREG_FLD_RXRANDET_STAT 0x20 + +/* + * RX data polarity inversion control: + * 1'b0: no inversion + * 1'b1: invert polarity + */ +#define SERDES_IREG_FLD_POLARITY_RX_REG_NUM 46 +#define SERDES_IREG_FLD_POLARITY_RX_INV (1 << 0) + +/* + * TX data polarity inversion control: + * 1'b0: no inversion + * 1'b1: invert polarity + */ +#define SERDES_IREG_FLD_POLARITY_TX_REG_NUM 46 +#define SERDES_IREG_FLD_POLARITY_TX_INV (1 << 1) + +/* LANEPCSPSTATE* override enable (Active low) */ +#define SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM 85 +#define SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN (1 << 0) + +/* LB* override enable (Active low) */ +#define SERDES_IREG_FLD_LB_LOCWREN_REG_NUM 85 +#define SERDES_IREG_FLD_LB_LOCWREN (1 << 1) + +/* PCSRX* override enable (Active low) */ +#define SERDES_IREG_FLD_PCSRX_LOCWREN_REG_NUM 85 +#define SERDES_IREG_FLD_PCSRX_LOCWREN (1 << 4) + +/* PCSRXBIST* override enable (Active low) */ +#define SERDES_IREG_FLD_PCSRXBIST_LOCWREN_REG_NUM 85 +#define SERDES_IREG_FLD_PCSRXBIST_LOCWREN (1 << 5) + +/* PCSRXEQ* override enable (Active low) */ +#define SERDES_IREG_FLD_PCSRXEQ_LOCWREN_REG_NUM 85 +#define SERDES_IREG_FLD_PCSRXEQ_LOCWREN (1 << 6) + +/* PCSTX* override enable (Active low) */ +#define SERDES_IREG_FLD_PCSTX_LOCWREN_REG_NUM 85 +#define SERDES_IREG_FLD_PCSTX_LOCWREN (1 << 7) + +/* + * group registers: + * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN, + * SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN + * SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN + */ +#define SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM 86 + +/* PCSTXBIST* override enable (Active low) */ +#define SERDES_IREG_FLD_PCSTXBIST_LOCWREN_REG_NUM 86 +#define SERDES_IREG_FLD_PCSTXBIST_LOCWREN (1 << 0) + +/* Override RX_CALCEQ through the internal registers (Active low) */ +#define SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN_REG_NUM 86 +#define SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN (1 << 3) + +#define SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN_REG_NUM 86 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN (1 << 4) + + +/* RXCALROAMEYEMEASIN* override enable - Active Low */ +#define SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN_REG_NUM 86 +#define SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN (1 << 6) + +/* RXCALROAMXADJUST* override enable - Active Low */ +#define SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN_REG_NUM 86 +#define SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN (1 << 7) + +/* RXCALROAMYADJUST* override enable - Active Low */ +#define SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM 87 +#define SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN (1 << 0) + +/* RXCDRCALFOSC* override enable. Active Low */ +#define SERDES_IREG_FLD_RXCDRCALFOSC_LOCWREN_REG_NUM 87 +#define SERDES_IREG_FLD_RXCDRCALFOSC_LOCWREN (1 << 1) + +/* Over-write enable for RXEYEDIAGFSM_INITXVAL */ +#define SERDES_IREG_FLD_RXEYEDIAGFSM_LOCWREN_REG_NUM 87 +#define SERDES_IREG_FLD_RXEYEDIAGFSM_LOCWREN (1 << 2) + +/* Over-write enable for CMNCLKGENMUXSEL_TXINTERNAL */ +#define SERDES_IREG_FLD_RXTERMHIZ_LOCWREN_REG_NUM 87 +#define SERDES_IREG_FLD_RXTERMHIZ_LOCWREN (1 << 3) + +/* TXCALTCLKDUTY* override enable. Active Low */ +#define SERDES_IREG_FLD_TXCALTCLKDUTY_LOCWREN_REG_NUM 87 +#define SERDES_IREG_FLD_TXCALTCLKDUTY_LOCWREN (1 << 4) + +/* Override TX_DRV through the internal registers (Active low) */ +#define SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN_REG_NUM 87 +#define SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN (1 << 5) + +/******************************************************************************* + * Common lane register fields - PMA + ******************************************************************************/ +/* + * Common lane hard reset control + * 0 - Hard reset is taken from the interface pins + * 1 - Hard reset is taken from registers + */ +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_SYNTH_REG_NUM 2 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_SYNTH_MASK 0x01 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_SYNTH_VAL_IFACE 0x00 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_SYNTH_VAL_REGS 0x01 + +/* + * Common lane hard reset + * 0 - Hard reset is asserted + * 1 - Hard reset is de-asserted + */ +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_SYNTH_REG_NUM 2 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_SYNTH_MASK 0x02 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_SYNTH_VAL_ASSERT 0x00 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_SYNTH_VAL_DEASSERT 0x02 + +/* Synth power state control */ +#define SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_REG_NUM 3 +#define SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_MASK 0x1f +#define SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_PD 0x01 +#define SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P2 0x02 +#define SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P1 0x04 +#define SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P0S 0x08 +#define SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P0 0x10 + +/* Transmit datapath FIFO enable (Active High) */ +#define SERDES_IREG_FLD_CMNPCS_TXENABLE_REG_NUM 8 +#define SERDES_IREG_FLD_CMNPCS_TXENABLE (1 << 2) + +/* + * RX lost of signal detector enable + * - 0 - disable + * - 1 - enable + */ +#define SERDES_IREG_FLD_RXLOSDET_ENABLE_REG_NUM 13 +#define SERDES_IREG_FLD_RXLOSDET_ENABLE AL_BIT(4) + +/* Signal Detect Threshold Level */ +#define SERDES_IREG_FLD_RXELECIDLE_SIGDETTHRESH_REG_NUM 15 +#define SERDES_IREG_FLD_RXELECIDLE_SIGDETTHRESH_MASK AL_FIELD_MASK(2, 0) + +/* LOS Detect Threshold Level */ +#define SERDES_IREG_FLD_RXLOSDET_THRESH_REG_NUM 15 +#define SERDES_IREG_FLD_RXLOSDET_THRESH_MASK AL_FIELD_MASK(4, 3) +#define SERDES_IREG_FLD_RXLOSDET_THRESH_SHIFT 3 + +#define SERDES_IREG_FLD_RXEQ_COARSE_ITER_NUM_REG_NUM 30 +#define SERDES_IREG_FLD_RXEQ_COARSE_ITER_NUM_MASK 0x7f +#define SERDES_IREG_FLD_RXEQ_COARSE_ITER_NUM_SHIFT 0 + +#define SERDES_IREG_FLD_RXEQ_FINE_ITER_NUM_REG_NUM 31 +#define SERDES_IREG_FLD_RXEQ_FINE_ITER_NUM_MASK 0x7f +#define SERDES_IREG_FLD_RXEQ_FINE_ITER_NUM_SHIFT 0 + +#define SERDES_IREG_FLD_RXEQ_COARSE_RUN1_MASK_REG_NUM 32 +#define SERDES_IREG_FLD_RXEQ_COARSE_RUN1_MASK_MASK 0xff +#define SERDES_IREG_FLD_RXEQ_COARSE_RUN1_MASK_SHIFT 0 + +#define SERDES_IREG_FLD_RXEQ_COARSE_RUN2_MASK_REG_NUM 33 +#define SERDES_IREG_FLD_RXEQ_COARSE_RUN2_MASK_MASK 0x1 +#define SERDES_IREG_FLD_RXEQ_COARSE_RUN2_MASK_SHIFT 0 + +#define SERDES_IREG_FLD_RXEQ_COARSE_STEP_REG_NUM 33 +#define SERDES_IREG_FLD_RXEQ_COARSE_STEP_MASK 0x3e +#define SERDES_IREG_FLD_RXEQ_COARSE_STEP_SHIFT 1 + +#define SERDES_IREG_FLD_RXEQ_FINE_RUN1_MASK_REG_NUM 34 +#define SERDES_IREG_FLD_RXEQ_FINE_RUN1_MASK_MASK 0xff +#define SERDES_IREG_FLD_RXEQ_FINE_RUN1_MASK_SHIFT 0 + +#define SERDES_IREG_FLD_RXEQ_FINE_RUN2_MASK_REG_NUM 35 +#define SERDES_IREG_FLD_RXEQ_FINE_RUN2_MASK_MASK 0x1 +#define SERDES_IREG_FLD_RXEQ_FINE_RUN2_MASK_SHIFT 0 + +#define SERDES_IREG_FLD_RXEQ_FINE_STEP_REG_NUM 35 +#define SERDES_IREG_FLD_RXEQ_FINE_STEP_MASK 0x3e +#define SERDES_IREG_FLD_RXEQ_FINE_STEP_SHIFT 1 + +#define SERDES_IREG_FLD_RXEQ_LOOKUP_CODE_EN_REG_NUM 36 +#define SERDES_IREG_FLD_RXEQ_LOOKUP_CODE_EN_MASK 0xff +#define SERDES_IREG_FLD_RXEQ_LOOKUP_CODE_EN_SHIFT 0 + +#define SERDES_IREG_FLD_RXEQ_LOOKUP_LASTCODE_REG_NUM 37 +#define SERDES_IREG_FLD_RXEQ_LOOKUP_LASTCODE_MASK 0x7 +#define SERDES_IREG_FLD_RXEQ_LOOKUP_LASTCODE_SHIFT 0 + +#define SERDES_IREG_FLD_RXEQ_DCGAIN_LUP0_REG_NUM 43 +#define SERDES_IREG_FLD_RXEQ_DCGAIN_LUP0_MASK 0x7 +#define SERDES_IREG_FLD_RXEQ_DCGAIN_LUP0_SHIFT 0 + +#define SERDES_IREG_FLD_TX_BIST_PAT_REG_NUM(byte_num) (56 + (byte_num)) +#define SERDES_IREG_FLD_TX_BIST_PAT_NUM_BYTES 10 + +/* + * Selects the transmit BIST mode: + * 0 - Uses the 80-bit internal memory pattern (w/ OOB) + * 1 - Uses a 27 PRBS pattern + * 2 - Uses a 223 PRBS pattern + * 3 - Uses a 231 PRBS pattern + * 4 - Uses a 1010 clock pattern + * 5 and above - Reserved + */ +#define SERDES_IREG_FLD_CMNPCSBIST_MODESEL_REG_NUM 80 +#define SERDES_IREG_FLD_CMNPCSBIST_MODESEL_MASK 0x07 +#define SERDES_IREG_FLD_CMNPCSBIST_MODESEL_VAL_USER 0x00 +#define SERDES_IREG_FLD_CMNPCSBIST_MODESEL_VAL_PRBS7 0x01 +#define SERDES_IREG_FLD_CMNPCSBIST_MODESEL_VAL_PRBS23 0x02 +#define SERDES_IREG_FLD_CMNPCSBIST_MODESEL_VAL_PRBS31 0x03 +#define SERDES_IREG_FLD_CMNPCSBIST_MODESEL_VAL_CLK1010 0x04 + +/* Single-Bit error injection enable (on posedge) */ +#define SERDES_IREG_FLD_TXBIST_BITERROR_EN_REG_NUM 80 +#define SERDES_IREG_FLD_TXBIST_BITERROR_EN 0x20 + +/* CMNPCIEGEN3* override enable (Active Low) */ +#define SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN_REG_NUM 95 +#define SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN (1 << 2) + +/* CMNPCS* override enable (Active Low) */ +#define SERDES_IREG_FLD_CMNPCS_LOCWREN_REG_NUM 95 +#define SERDES_IREG_FLD_CMNPCS_LOCWREN (1 << 3) + +/* CMNPCSBIST* override enable (Active Low) */ +#define SERDES_IREG_FLD_CMNPCSBIST_LOCWREN_REG_NUM 95 +#define SERDES_IREG_FLD_CMNPCSBIST_LOCWREN (1 << 4) + +/* CMNPCSPSTATE* override enable (Active Low) */ +#define SERDES_IREG_FLD_CMNPCSPSTATE_LOCWREN_REG_NUM 95 +#define SERDES_IREG_FLD_CMNPCSPSTATE_LOCWREN (1 << 5) + +/* PCS_EN* override enable (Active Low) */ +#define SERDES_IREG_FLD_PCS_LOCWREN_REG_NUM 96 +#define SERDES_IREG_FLD_PCS_LOCWREN (1 << 3) + +/* Eye diagram sample count */ +#define SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_MSB_REG_NUM 150 +#define SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_MSB_MASK 0xff +#define SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_MSB_SHIFT 0 + +#define SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_LSB_REG_NUM 151 +#define SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_LSB_MASK 0xff +#define SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_LSB_SHIFT 0 + +/* override control */ +#define SERDES_IREG_FLD_RXLOCK2REF_LOCWREN_REG_NUM 230 +#define SERDES_IREG_FLD_RXLOCK2REF_LOCWREN 1 << 0 + +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD1_REG_NUM 623 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD1_MASK 0xff +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD1_SHIFT 0 + +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD2_REG_NUM 624 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD2_MASK 0xff +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD2_SHIFT 0 + +/* X and Y coefficient return value */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_X_Y_VALWEIGHT_REG_NUM 626 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALWEIGHT_MASK 0x0F +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALWEIGHT_SHIFT 0 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALWEIGHT_MASK 0xF0 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALWEIGHT_SHIFT 4 + +/* X coarse scan step */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_REG_NUM 627 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_MASK 0x7F +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_SHIFT 0 + +/* X fine scan step */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_REG_NUM 628 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_MASK 0x7F +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_SHIFT 0 + +/* Y coarse scan step */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_REG_NUM 629 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_MASK 0x0F +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_SHIFT 0 + +/* Y fine scan step */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_REG_NUM 630 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_MASK 0x0F +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_SHIFT 0 + +#define SERDES_IREG_FLD_PPMDRIFTCOUNT1_REG_NUM 157 + +#define SERDES_IREG_FLD_PPMDRIFTCOUNT2_REG_NUM 158 + +#define SERDES_IREG_FLD_PPMDRIFTMAX1_REG_NUM 159 + +#define SERDES_IREG_FLD_PPMDRIFTMAX2_REG_NUM 160 + +#define SERDES_IREG_FLD_SYNTHPPMDRIFTMAX1_REG_NUM 163 + +#define SERDES_IREG_FLD_SYNTHPPMDRIFTMAX2_REG_NUM 164 + +/******************************************************************************* + * Common lane register fields - PCS + ******************************************************************************/ +#define SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_REG_NUM 3 +#define SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_MASK AL_FIELD_MASK(5, 4) +#define SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_SHIFT 4 + +#define SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_ENA_REG_NUM 6 +#define SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_ENA AL_BIT(2) + +#define SERDES_IREG_FLD_PCS_EBUF_FULL_D2R1_REG_NUM 18 +#define SERDES_IREG_FLD_PCS_EBUF_FULL_D2R1_REG_MASK 0x1F +#define SERDES_IREG_FLD_PCS_EBUF_FULL_D2R1_REG_SHIFT 0 + +#define SERDES_IREG_FLD_PCS_EBUF_FULL_PCIE_G3_REG_NUM 19 +#define SERDES_IREG_FLD_PCS_EBUF_FULL_PCIE_G3_REG_MASK 0x7C +#define SERDES_IREG_FLD_PCS_EBUF_FULL_PCIE_G3_REG_SHIFT 2 + +#define SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_D2R1_REG_NUM 20 +#define SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_D2R1_REG_MASK 0x1F +#define SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_D2R1_REG_SHIFT 0 + +#define SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_PCIE_G3_REG_NUM 21 +#define SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_PCIE_G3_REG_MASK 0x7C +#define SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_PCIE_G3_REG_SHIFT 2 + +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_ITER_NUM_REG_NUM 22 +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_ITER_NUM_MASK 0x7f +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_ITER_NUM_SHIFT 0 + +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_ITER_NUM_REG_NUM 34 +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_ITER_NUM_MASK 0x7f +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_ITER_NUM_SHIFT 0 + +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_RUN1_MASK_REG_NUM 23 +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_RUN1_MASK_MASK 0xff +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_RUN1_MASK_SHIFT 0 + +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_RUN2_MASK_REG_NUM 22 +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_RUN2_MASK_MASK 0x80 +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_RUN2_MASK_SHIFT 7 + +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_STEP_REG_NUM 24 +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_STEP_MASK 0x3e +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_STEP_SHIFT 1 + +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_RUN1_MASK_REG_NUM 35 +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_RUN1_MASK_MASK 0xff +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_RUN1_MASK_SHIFT 0 + +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_RUN2_MASK_REG_NUM 34 +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_RUN2_MASK_MASK 0x80 +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_RUN2_MASK_SHIFT 7 + +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_STEP_REG_NUM 36 +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_STEP_MASK 0x1f +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_STEP_SHIFT 0 + +#define SERDES_IREG_FLD_PCS_RXEQ_LOOKUP_CODE_EN_REG_NUM 37 +#define SERDES_IREG_FLD_PCS_RXEQ_LOOKUP_CODE_EN_MASK 0xff +#define SERDES_IREG_FLD_PCS_RXEQ_LOOKUP_CODE_EN_SHIFT 0 + +#define SERDES_IREG_FLD_PCS_RXEQ_LOOKUP_LASTCODE_REG_NUM 36 +#define SERDES_IREG_FLD_PCS_RXEQ_LOOKUP_LASTCODE_MASK 0xe0 +#define SERDES_IREG_FLD_PCS_RXEQ_LOOKUP_LASTCODE_SHIFT 5 + +#ifdef __cplusplus +} +#endif + +#endif /* __AL_serdes_REG_H */ + diff --git a/al_hal_serdes_regs.h b/al_hal_serdes_regs.h new file mode 100644 index 00000000000..1af7a918e21 --- /dev/null +++ b/al_hal_serdes_regs.h @@ -0,0 +1,495 @@ +/*- +******************************************************************************* +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_serdes_regs.h + * + * @brief ... registers + * + */ + +#ifndef __AL_HAL_SERDES_REGS_H__ +#define __AL_HAL_SERDES_REGS_H__ + +#include "al_hal_plat_types.h" + +#ifdef __cplusplus +extern "C" { +#endif +/* +* Unit Registers +*/ + +struct serdes_gen { + /* [0x0] SerDes Registers Version */ + uint32_t version; + uint32_t rsrvd_0[3]; + /* [0x10] SerDes register file address */ + uint32_t reg_addr; + /* [0x14] SerDes register file data */ + uint32_t reg_data; + uint32_t rsrvd_1[2]; + /* [0x20] SerDes control */ + uint32_t ictl_multi_bist; + /* [0x24] SerDes control */ + uint32_t ictl_pcs; + /* [0x28] SerDes control */ + uint32_t ictl_pma; + uint32_t rsrvd_2; + /* [0x30] SerDes control */ + uint32_t ipd_multi_synth; + /* [0x34] SerDes control */ + uint32_t irst; + /* [0x38] SerDes control */ + uint32_t octl_multi_synthready; + /* [0x3c] SerDes control */ + uint32_t octl_multi_synthstatus; + /* [0x40] SerDes control */ + uint32_t clk_out; + uint32_t rsrvd[47]; +}; +struct serdes_lane { + uint32_t rsrvd1[4]; + /* [0x10] SerDes status */ + uint32_t octl_pma; + /* [0x14] SerDes control */ + uint32_t ictl_multi_andme; + /* [0x18] SerDes control */ + uint32_t ictl_multi_lb; + /* [0x1c] SerDes control */ + uint32_t ictl_multi_rxbist; + /* [0x20] SerDes control */ + uint32_t ictl_multi_txbist; + /* [0x24] SerDes control */ + uint32_t ictl_multi; + /* [0x28] SerDes control */ + uint32_t ictl_multi_rxeq; + /* [0x2c] SerDes control */ + uint32_t ictl_multi_rxeq_l_low; + /* [0x30] SerDes control */ + uint32_t ictl_multi_rxeq_l_high; + /* [0x34] SerDes control */ + uint32_t ictl_multi_rxeyediag; + /* [0x38] SerDes control */ + uint32_t ictl_multi_txdeemph; + /* [0x3c] SerDes control */ + uint32_t ictl_multi_txmargin; + /* [0x40] SerDes control */ + uint32_t ictl_multi_txswing; + /* [0x44] SerDes control */ + uint32_t idat_multi; + /* [0x48] SerDes control */ + uint32_t ipd_multi; + /* [0x4c] SerDes control */ + uint32_t octl_multi_rxbist; + /* [0x50] SerDes control */ + uint32_t octl_multi; + /* [0x54] SerDes control */ + uint32_t octl_multi_rxeyediag; + /* [0x58] SerDes control */ + uint32_t odat_multi_rxbist; + /* [0x5c] SerDes control */ + uint32_t odat_multi_rxeq; + /* [0x60] SerDes control */ + uint32_t multi_rx_dvalid; + /* [0x64] SerDes control */ + uint32_t reserved; + uint32_t rsrvd[6]; +}; + +struct al_serdes_regs { + uint32_t rsrvd_0[64]; + struct serdes_gen gen; /* [0x100] */ + struct serdes_lane lane[4]; /* [0x200] */ +}; + + +/* +* Registers Fields +*/ + + +/**** version register ****/ +/* Revision number (Minor) */ +#define SERDES_GEN_VERSION_RELEASE_NUM_MINOR_MASK 0x000000FF +#define SERDES_GEN_VERSION_RELEASE_NUM_MINOR_SHIFT 0 +/* Revision number (Major) */ +#define SERDES_GEN_VERSION_RELEASE_NUM_MAJOR_MASK 0x0000FF00 +#define SERDES_GEN_VERSION_RELEASE_NUM_MAJOR_SHIFT 8 +/* Date of release */ +#define SERDES_GEN_VERSION_DATE_DAY_MASK 0x001F0000 +#define SERDES_GEN_VERSION_DATE_DAY_SHIFT 16 +/* Month of release */ +#define SERDES_GEN_VERSION_DATA_MONTH_MASK 0x01E00000 +#define SERDES_GEN_VERSION_DATA_MONTH_SHIFT 21 +/* Year of release (starting from 2000) */ +#define SERDES_GEN_VERSION_DATE_YEAR_MASK 0x3E000000 +#define SERDES_GEN_VERSION_DATE_YEAR_SHIFT 25 +/* Reserved */ +#define SERDES_GEN_VERSION_RESERVED_MASK 0xC0000000 +#define SERDES_GEN_VERSION_RESERVED_SHIFT 30 + +/**** reg_addr register ****/ +/* Address value */ +#define SERDES_GEN_REG_ADDR_VAL_MASK 0x0000FFFF +#define SERDES_GEN_REG_ADDR_VAL_SHIFT 0 + +/**** reg_data register ****/ +/* Data value */ +#define SERDES_GEN_REG_DATA_VAL_MASK 0x000000FF +#define SERDES_GEN_REG_DATA_VAL_SHIFT 0 + +/**** ICTL_MULTI_BIST register ****/ + +#define SERDES_GEN_ICTL_MULTI_BIST_MODESEL_NT_MASK 0x00000007 +#define SERDES_GEN_ICTL_MULTI_BIST_MODESEL_NT_SHIFT 0 + +/**** ICTL_PCS register ****/ + +#define SERDES_GEN_ICTL_PCS_EN_NT (1 << 0) + +/**** ICTL_PMA register ****/ + +#define SERDES_GEN_ICTL_PMA_REF_SEL_NT_MASK 0x00000007 +#define SERDES_GEN_ICTL_PMA_REF_SEL_NT_SHIFT 0 + +#define SERDES_GEN_ICTL_PMA_REF_SEL_NT_REF \ + (0 << (SERDES_GEN_ICTL_PMA_REF_SEL_NT_SHIFT)) +#define SERDES_GEN_ICTL_PMA_REF_SEL_NT_R2L \ + (3 << (SERDES_GEN_ICTL_PMA_REF_SEL_NT_SHIFT)) +#define SERDES_GEN_ICTL_PMA_REF_SEL_NT_L2R \ + (4 << (SERDES_GEN_ICTL_PMA_REF_SEL_NT_SHIFT)) + +#define SERDES_GEN_ICTL_PMA_REFBUSRIGHT2LEFT_MODE_NT_MASK 0x00000070 +#define SERDES_GEN_ICTL_PMA_REFBUSRIGHT2LEFT_MODE_NT_SHIFT 4 + +#define SERDES_GEN_ICTL_PMA_REFBUSRIGHT2LEFT_MODE_NT_0 \ + (0 << (SERDES_GEN_ICTL_PMA_REFBUSRIGHT2LEFT_MODE_NT_SHIFT)) +#define SERDES_GEN_ICTL_PMA_REFBUSRIGHT2LEFT_MODE_NT_REF \ + (2 << (SERDES_GEN_ICTL_PMA_REFBUSRIGHT2LEFT_MODE_NT_SHIFT)) +#define SERDES_GEN_ICTL_PMA_REFBUSRIGHT2LEFT_MODE_NT_R2L \ + (3 << (SERDES_GEN_ICTL_PMA_REFBUSRIGHT2LEFT_MODE_NT_SHIFT)) + +#define SERDES_GEN_ICTL_PMA_REFBUSLEFT2RIGHT_MODE_NT_MASK 0x00000700 +#define SERDES_GEN_ICTL_PMA_REFBUSLEFT2RIGHT_MODE_NT_SHIFT 8 + +#define SERDES_GEN_ICTL_PMA_REFBUSLEFT2RIGHT_MODE_NT_0 \ + (0 << (SERDES_GEN_ICTL_PMA_REFBUSLEFT2RIGHT_MODE_NT_SHIFT)) +#define SERDES_GEN_ICTL_PMA_REFBUSLEFT2RIGHT_MODE_NT_REF \ + (2 << (SERDES_GEN_ICTL_PMA_REFBUSLEFT2RIGHT_MODE_NT_SHIFT)) +#define SERDES_GEN_ICTL_PMA_REFBUSLEFT2RIGHT_MODE_NT_L2R \ + (3 << (SERDES_GEN_ICTL_PMA_REFBUSLEFT2RIGHT_MODE_NT_SHIFT)) + +#define SERDES_GEN_ICTL_PMA_TXENABLE_A_SRC (1 << 11) +#define SERDES_GEN_ICTL_PMA_TXENABLE_A_SRC_THIS (0 << 11) +#define SERDES_GEN_ICTL_PMA_TXENABLE_A_SRC_MASTER (1 << 11) + +#define SERDES_GEN_ICTL_PMA_TXENABLE_A (1 << 12) + +#define SERDES_GEN_ICTL_PMA_SYNTHCKBYPASSEN_NT (1 << 13) + +/**** IPD_MULTI_SYNTH register ****/ + +#define SERDES_GEN_IPD_MULTI_SYNTH_B (1 << 0) + +/**** IRST register ****/ + +#define SERDES_GEN_IRST_PIPE_RST_L3_B_A (1 << 0) + +#define SERDES_GEN_IRST_PIPE_RST_L2_B_A (1 << 1) + +#define SERDES_GEN_IRST_PIPE_RST_L1_B_A (1 << 2) + +#define SERDES_GEN_IRST_PIPE_RST_L0_B_A (1 << 3) + +#define SERDES_GEN_IRST_MULTI_HARD_TXRX_L3_B_A (1 << 4) + +#define SERDES_GEN_IRST_MULTI_HARD_TXRX_L2_B_A (1 << 5) + +#define SERDES_GEN_IRST_MULTI_HARD_TXRX_L1_B_A (1 << 6) + +#define SERDES_GEN_IRST_MULTI_HARD_TXRX_L0_B_A (1 << 7) + +#define SERDES_GEN_IRST_MULTI_HARD_SYNTH_B_A (1 << 8) + +#define SERDES_GEN_IRST_POR_B_A (1 << 12) + +#define SERDES_GEN_IRST_PIPE_RST_L3_B_A_SEL (1 << 16) + +#define SERDES_GEN_IRST_PIPE_RST_L2_B_A_SEL (1 << 17) + +#define SERDES_GEN_IRST_PIPE_RST_L1_B_A_SEL (1 << 18) + +#define SERDES_GEN_IRST_PIPE_RST_L0_B_A_SEL (1 << 19) + +#define SERDES_GEN_IRST_MULTI_HARD_TXRX_L3_B_A_SEL (1 << 20) + +#define SERDES_GEN_IRST_MULTI_HARD_TXRX_L2_B_A_SEL (1 << 21) + +#define SERDES_GEN_IRST_MULTI_HARD_TXRX_L1_B_A_SEL (1 << 22) + +#define SERDES_GEN_IRST_MULTI_HARD_TXRX_L0_B_A_SEL (1 << 23) + +/**** OCTL_MULTI_SYNTHREADY register ****/ + +#define SERDES_GEN_OCTL_MULTI_SYNTHREADY_A (1 << 0) + +/**** OCTL_MULTI_SYNTHSTATUS register ****/ + +#define SERDES_GEN_OCTL_MULTI_SYNTHSTATUS_A (1 << 0) + +/**** clk_out register ****/ + +#define SERDES_GEN_CLK_OUT_SEL_MASK 0x0000003F +#define SERDES_GEN_CLK_OUT_SEL_SHIFT 0 + +/**** OCTL_PMA register ****/ + +#define SERDES_LANE_OCTL_PMA_TXSTATUS_L_A (1 << 0) + +/**** ICTL_MULTI_ANDME register ****/ + +#define SERDES_LANE_ICTL_MULTI_ANDME_EN_L_A (1 << 0) + +#define SERDES_LANE_ICTL_MULTI_ANDME_EN_L_A_SEL (1 << 1) + +/**** ICTL_MULTI_LB register ****/ + +#define SERDES_LANE_ICTL_MULTI_LB_TX2RXIOTIMEDEN_L_NT (1 << 0) + +#define SERDES_LANE_ICTL_MULTI_LB_TX2RXBUFTIMEDEN_L_NT (1 << 1) + +#define SERDES_LANE_ICTL_MULTI_LB_RX2TXUNTIMEDEN_L_NT (1 << 2) + +#define SERDES_LANE_ICTL_MULTI_LB_PARRX2TXTIMEDEN_L_NT (1 << 3) + +#define SERDES_LANE_ICTL_MULTI_LB_CDRCLK2TXEN_L_NT (1 << 4) + +#define SERDES_LANE_ICTL_MULTI_LB_TX2RXBUFTIMEDEN_L_NT_SEL (1 << 8) + +#define SERDES_LANE_ICTL_MULTI_LB_RX2TXUNTIMEDEN_L_NT_SEL (1 << 9) + +/**** ICTL_MULTI_RXBIST register ****/ + +#define SERDES_LANE_ICTL_MULTI_RXBIST_EN_L_A (1 << 0) + +/**** ICTL_MULTI_TXBIST register ****/ + +#define SERDES_LANE_ICTL_MULTI_TXBIST_EN_L_A (1 << 0) + +/**** ICTL_MULTI register ****/ + +#define SERDES_LANE_ICTL_MULTI_PSTATE_L_MASK 0x00000003 +#define SERDES_LANE_ICTL_MULTI_PSTATE_L_SHIFT 0 + +#define SERDES_LANE_ICTL_MULTI_PSTATE_L_SEL (1 << 2) + +#define SERDES_LANE_ICTL_MULTI_RXDATAWIDTH_L_MASK 0x00000070 +#define SERDES_LANE_ICTL_MULTI_RXDATAWIDTH_L_SHIFT 4 + +#define SERDES_LANE_ICTL_MULTI_RXOVRCDRLOCK2DATAEN_L_A (1 << 8) + +#define SERDES_LANE_ICTL_MULTI_RXOVRCDRLOCK2DATA_L_A (1 << 9) + +#define SERDES_LANE_ICTL_MULTI_TXBEACON_L_A (1 << 12) + +#define SERDES_LANE_ICTL_MULTI_TXDETECTRXREQ_L_A (1 << 13) + +#define SERDES_LANE_ICTL_MULTI_RXRATE_L_MASK 0x00070000 +#define SERDES_LANE_ICTL_MULTI_RXRATE_L_SHIFT 16 + +#define SERDES_LANE_ICTL_MULTI_RXRATE_L_SEL (1 << 19) + +#define SERDES_LANE_ICTL_MULTI_TXRATE_L_MASK 0x00700000 +#define SERDES_LANE_ICTL_MULTI_TXRATE_L_SHIFT 20 + +#define SERDES_LANE_ICTL_MULTI_TXRATE_L_SEL (1 << 23) + +#define SERDES_LANE_ICTL_MULTI_TXAMP_L_MASK 0x07000000 +#define SERDES_LANE_ICTL_MULTI_TXAMP_L_SHIFT 24 + +#define SERDES_LANE_ICTL_MULTI_TXAMP_EN_L (1 << 27) + +#define SERDES_LANE_ICTL_MULTI_TXDATAWIDTH_L_MASK 0x70000000 +#define SERDES_LANE_ICTL_MULTI_TXDATAWIDTH_L_SHIFT 28 + +/**** ICTL_MULTI_RXEQ register ****/ + +#define SERDES_LANE_ICTL_MULTI_RXEQ_EN_L (1 << 0) + +#define SERDES_LANE_ICTL_MULTI_RXEQ_START_L_A (1 << 1) + +#define SERDES_LANE_ICTL_MULTI_RXEQ_PRECAL_CODE_SEL_MASK 0x00000070 +#define SERDES_LANE_ICTL_MULTI_RXEQ_PRECAL_CODE_SEL_SHIFT 4 + +/**** ICTL_MULTI_RXEQ_L_high register ****/ + +#define SERDES_LANE_ICTL_MULTI_RXEQ_L_HIGH_VAL (1 << 0) + +/**** ICTL_MULTI_RXEYEDIAG register ****/ + +#define SERDES_LANE_ICTL_MULTI_RXEYEDIAG_START_L_A (1 << 0) + +/**** ICTL_MULTI_TXDEEMPH register ****/ + +#define SERDES_LANE_ICTL_MULTI_TXDEEMPH_L_MASK 0x0003FFFF +#define SERDES_LANE_ICTL_MULTI_TXDEEMPH_L_SHIFT 0 + +#define SERDES_LANE_ICTL_MULTI_TXDEEMPH_C_ZERO_MASK 0x7c0 +#define SERDES_LANE_ICTL_MULTI_TXDEEMPH_C_ZERO_SHIFT 6 +#define SERDES_LANE_ICTL_MULTI_TXDEEMPH_C_PLUS_MASK 0xf000 +#define SERDES_LANE_ICTL_MULTI_TXDEEMPH_C_PLUS_SHIFT 12 +#define SERDES_LANE_ICTL_MULTI_TXDEEMPH_C_MINUS_MASK 0x7 +#define SERDES_LANE_ICTL_MULTI_TXDEEMPH_C_MINUS_SHIFT 0 + +/**** ICTL_MULTI_TXMARGIN register ****/ + +#define SERDES_LANE_ICTL_MULTI_TXMARGIN_L_MASK 0x00000007 +#define SERDES_LANE_ICTL_MULTI_TXMARGIN_L_SHIFT 0 + +/**** ICTL_MULTI_TXSWING register ****/ + +#define SERDES_LANE_ICTL_MULTI_TXSWING_L (1 << 0) + +/**** IDAT_MULTI register ****/ + +#define SERDES_LANE_IDAT_MULTI_TXELECIDLE_L_MASK 0x0000000F +#define SERDES_LANE_IDAT_MULTI_TXELECIDLE_L_SHIFT 0 + +#define SERDES_LANE_IDAT_MULTI_TXELECIDLE_L_SEL (1 << 4) + +/**** IPD_MULTI register ****/ + +#define SERDES_LANE_IPD_MULTI_TX_L_B (1 << 0) + +#define SERDES_LANE_IPD_MULTI_RX_L_B (1 << 1) + +/**** OCTL_MULTI_RXBIST register ****/ + +#define SERDES_LANE_OCTL_MULTI_RXBIST_DONE_L_A (1 << 0) + +#define SERDES_LANE_OCTL_MULTI_RXBIST_RXLOCKED_L_A (1 << 1) + +/**** OCTL_MULTI register ****/ + +#define SERDES_LANE_OCTL_MULTI_RXCDRLOCK2DATA_L_A (1 << 0) + +#define SERDES_LANE_OCTL_MULTI_RXEQ_DONE_L_A (1 << 1) + +#define SERDES_LANE_OCTL_MULTI_RXREADY_L_A (1 << 2) + +#define SERDES_LANE_OCTL_MULTI_RXSTATUS_L_A (1 << 3) + +#define SERDES_LANE_OCTL_MULTI_TXREADY_L_A (1 << 4) + +#define SERDES_LANE_OCTL_MULTI_TXDETECTRXSTAT_L_A (1 << 5) + +#define SERDES_LANE_OCTL_MULTI_TXDETECTRXACK_L_A (1 << 6) + +#define SERDES_LANE_OCTL_MULTI_RXSIGNALDETECT_L_A (1 << 7) + +/**** OCTL_MULTI_RXEYEDIAG register ****/ + +#define SERDES_LANE_OCTL_MULTI_RXEYEDIAG_STAT_L_A_MASK 0x00003FFF +#define SERDES_LANE_OCTL_MULTI_RXEYEDIAG_STAT_L_A_SHIFT 0 + +#define SERDES_LANE_OCTL_MULTI_RXEYEDIAG_DONE_L_A (1 << 16) + +#define SERDES_LANE_OCTL_MULTI_RXEYEDIAG_ERR_L_A (1 << 17) + +/**** ODAT_MULTI_RXBIST register ****/ + +#define SERDES_LANE_ODAT_MULTI_RXBIST_ERRCOUNT_L_A_MASK 0x0000FFFF +#define SERDES_LANE_ODAT_MULTI_RXBIST_ERRCOUNT_L_A_SHIFT 0 + +#define SERDES_LANE_ODAT_MULTI_RXBIST_ERRCOUNT_OVERFLOW_L_A (1 << 16) + +/**** ODAT_MULTI_RXEQ register ****/ + +#define SERDES_LANE_ODAT_MULTI_RXEQ_BEST_EYE_VAL_L_A_MASK 0x00003FFF +#define SERDES_LANE_ODAT_MULTI_RXEQ_BEST_EYE_VAL_L_A_SHIFT 0 + +/**** MULTI_RX_DVALID register ****/ + +#define SERDES_LANE_MULTI_RX_DVALID_MASK_CDR_LOCK (1 << 0) + +#define SERDES_LANE_MULTI_RX_DVALID_MASK_SIGNALDETECT (1 << 1) + +#define SERDES_LANE_MULTI_RX_DVALID_MASK_TX_READY (1 << 2) + +#define SERDES_LANE_MULTI_RX_DVALID_MASK_RX_READY (1 << 3) + +#define SERDES_LANE_MULTI_RX_DVALID_MASK_SYNT_READY (1 << 4) + +#define SERDES_LANE_MULTI_RX_DVALID_MASK_RX_ELECIDLE (1 << 5) + +#define SERDES_LANE_MULTI_RX_DVALID_MUX_SEL_MASK 0x00FF0000 +#define SERDES_LANE_MULTI_RX_DVALID_MUX_SEL_SHIFT 16 + +#define SERDES_LANE_MULTI_RX_DVALID_PS_00_SEL (1 << 24) + +#define SERDES_LANE_MULTI_RX_DVALID_PS_00_VAL (1 << 25) + +#define SERDES_LANE_MULTI_RX_DVALID_PS_01_SEL (1 << 26) + +#define SERDES_LANE_MULTI_RX_DVALID_PS_01_VAL (1 << 27) + +#define SERDES_LANE_MULTI_RX_DVALID_PS_10_SEL (1 << 28) + +#define SERDES_LANE_MULTI_RX_DVALID_PS_10_VAL (1 << 29) + +#define SERDES_LANE_MULTI_RX_DVALID_PS_11_SEL (1 << 30) + +#define SERDES_LANE_MULTI_RX_DVALID_PS_11_VAL (1 << 31) + +/**** reserved register ****/ + +#define SERDES_LANE_RESERVED_OUT_MASK 0x000000FF +#define SERDES_LANE_RESERVED_OUT_SHIFT 0 + +#define SERDES_LANE_RESERVED_IN_MASK 0x00FF0000 +#define SERDES_LANE_RESERVED_IN_SHIFT 16 + +#ifdef __cplusplus +} +#endif + +#endif /* __AL_HAL_serdes_REGS_H__ */ + +/** @} end of ... group */ + + diff --git a/al_hal_udma.h b/al_hal_udma.h new file mode 100644 index 00000000000..a1bdb4fe8db --- /dev/null +++ b/al_hal_udma.h @@ -0,0 +1,672 @@ +/*- +******************************************************************************* +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. + +*******************************************************************************/ + +/** + * @defgroup group_udma_api API + * @ingroup group_udma + * UDMA API + * @{ + * @} + * + * @defgroup group_udma_main UDMA Main + * @ingroup group_udma_api + * UDMA main API + * @{ + * @file al_hal_udma.h + * + * @brief C Header file for the Universal DMA HAL driver + * + */ + +#ifndef __AL_HAL_UDMA_H__ +#define __AL_HAL_UDMA_H__ + +#include "al_hal_common.h" +#include "al_hal_udma_regs.h" + +/* *INDENT-OFF* */ +#ifdef __cplusplus +extern "C" { +#endif +/* *INDENT-ON* */ + +#define DMA_MAX_Q 4 +#define AL_UDMA_MIN_Q_SIZE 4 +#define AL_UDMA_MAX_Q_SIZE (1 << 16) /* hw can do more, but we limit it */ + +/* Default Max number of descriptors supported per action */ +#define AL_UDMA_DEFAULT_MAX_ACTN_DESCS 16 + +#define AL_UDMA_REV_ID_0 0 +#define AL_UDMA_REV_ID_1 1 +#define AL_UDMA_REV_ID_2 2 + +#define DMA_RING_ID_MASK 0x3 +/* New registers ?? */ +/* Statistics - TBD */ + +/** UDMA submission descriptor */ +union al_udma_desc { + /* TX */ + struct { + uint32_t len_ctrl; + uint32_t meta_ctrl; + uint64_t buf_ptr; + } tx; + /* TX Meta, used by upper layer */ + struct { + uint32_t len_ctrl; + uint32_t meta_ctrl; + uint32_t meta1; + uint32_t meta2; + } tx_meta; + /* RX */ + struct { + uint32_t len_ctrl; + uint32_t buf2_ptr_lo; + uint64_t buf1_ptr; + } rx; +} __packed_a16; + +/* TX desc length and control fields */ + +#define AL_M2S_DESC_CONCAT AL_BIT(31) /* concatenate */ +#define AL_M2S_DESC_DMB AL_BIT(30) + /** Data Memory Barrier */ +#define AL_M2S_DESC_NO_SNOOP_H AL_BIT(29) +#define AL_M2S_DESC_INT_EN AL_BIT(28) /** enable interrupt */ +#define AL_M2S_DESC_LAST AL_BIT(27) +#define AL_M2S_DESC_FIRST AL_BIT(26) +#define AL_M2S_DESC_RING_ID_SHIFT 24 +#define AL_M2S_DESC_RING_ID_MASK (0x3 << AL_M2S_DESC_RING_ID_SHIFT) +#define AL_M2S_DESC_META_DATA AL_BIT(23) +#define AL_M2S_DESC_DUMMY AL_BIT(22) /* for Metdata only */ +#define AL_M2S_DESC_LEN_ADJ_SHIFT 20 +#define AL_M2S_DESC_LEN_ADJ_MASK (0x7 << AL_M2S_DESC_LEN_ADJ_SHIFT) +#define AL_M2S_DESC_LEN_SHIFT 0 +#define AL_M2S_DESC_LEN_MASK (0xfffff << AL_M2S_DESC_LEN_SHIFT) + +#define AL_S2M_DESC_DUAL_BUF AL_BIT(31) +#define AL_S2M_DESC_NO_SNOOP_H AL_BIT(29) +#define AL_S2M_DESC_INT_EN AL_BIT(28) /** enable interrupt */ +#define AL_S2M_DESC_RING_ID_SHIFT 24 +#define AL_S2M_DESC_RING_ID_MASK (0x3 << AL_S2M_DESC_RING_ID_SHIFT) +#define AL_S2M_DESC_LEN_SHIFT 0 +#define AL_S2M_DESC_LEN_MASK (0xffff << AL_S2M_DESC_LEN_SHIFT) +#define AL_S2M_DESC_LEN2_SHIFT 16 +#define AL_S2M_DESC_LEN2_MASK (0x3fff << AL_S2M_DESC_LEN2_SHIFT) +#define AL_S2M_DESC_LEN2_GRANULARITY_SHIFT 6 + +/* TX/RX descriptor VMID field (in the buffer address 64 bit field) */ +#define AL_UDMA_DESC_VMID_SHIFT 48 + +/** UDMA completion descriptor */ +union al_udma_cdesc { + /* TX completion */ + struct { + uint32_t ctrl_meta; + } al_desc_comp_tx; + /* RX completion */ + struct { + /* TBD */ + uint32_t ctrl_meta; + } al_desc_comp_rx; +} __packed_a4; + +/* TX/RX common completion desc ctrl_meta feilds */ +#define AL_UDMA_CDESC_ERROR AL_BIT(31) +#define AL_UDMA_CDESC_BUF1_USED AL_BIT(30) +#define AL_UDMA_CDESC_DDP AL_BIT(29) +#define AL_UDMA_CDESC_LAST AL_BIT(27) +#define AL_UDMA_CDESC_FIRST AL_BIT(26) +/* word 2 */ +#define AL_UDMA_CDESC_BUF2_USED AL_BIT(31) +#define AL_UDMA_CDESC_BUF2_LEN_SHIFT 16 +#define AL_UDMA_CDESC_BUF2_LEN_MASK AL_FIELD_MASK(29, 16) +/** Basic Buffer structure */ +struct al_buf { + al_phys_addr_t addr; /**< Buffer physical address */ + uint32_t len; /**< Buffer lenght in bytes */ +}; + +/** Block is a set of buffers that belong to same source or destination */ +struct al_block { + struct al_buf *bufs; /**< The buffers of the block */ + uint32_t num; /**< Number of buffers of the block */ + + /**< + * VMID to be assigned to the block descriptors + * Requires VMID in descriptor to be enabled for the specific UDMA + * queue. + */ + uint16_t vmid; +}; + +/** UDMA type */ +enum al_udma_type { + UDMA_TX, + UDMA_RX +}; + +/** UDMA state */ +enum al_udma_state { + UDMA_DISABLE = 0, + UDMA_IDLE, + UDMA_NORMAL, + UDMA_ABORT, + UDMA_RESET +}; + +extern const char *const al_udma_states_name[]; + +/** UDMA Q specific parameters from upper layer */ +struct al_udma_q_params { + uint32_t size; /**< ring size (in descriptors), submission and + * completion rings must have same size + */ + union al_udma_desc *desc_base; /**< cpu address for submission ring + * descriptors + */ + al_phys_addr_t desc_phy_base; /**< submission ring descriptors + * physical base address + */ +#ifdef __FreeBSD__ + bus_dma_tag_t desc_phy_base_tag; + bus_dmamap_t desc_phy_base_map; +#endif + uint8_t *cdesc_base; /**< completion descriptors pointer, NULL */ + /* means no completion update */ + al_phys_addr_t cdesc_phy_base; /**< completion descriptors ring + * physical base address + */ +#ifdef __FreeBSD__ + bus_dma_tag_t cdesc_phy_base_tag; + bus_dmamap_t cdesc_phy_base_map; +#endif + uint32_t cdesc_size; /**< size (in bytes) of a single dma completion + * descriptor + */ + + uint8_t adapter_rev_id; /**next_cdesc_idx - (udma_q->next_desc_idx + 1); + tmp &= udma_q->size_mask; + + return (uint32_t) tmp; +} + +/** + * check if queue has pending descriptors + * + * @param udma_q queue handle + * + * @return AL_TRUE if descriptors are submitted to completion ring and still + * not completed (with ack). AL_FALSE otherwise. + */ +static INLINE al_bool al_udma_is_empty(struct al_udma_q *udma_q) +{ + if (((udma_q->next_cdesc_idx - udma_q->next_desc_idx) & + udma_q->size_mask) == 0) + return AL_TRUE; + + return AL_FALSE; +} + +/** + * get next available descriptor + * @param udma_q queue handle + * + * @return pointer to the next available descriptor + */ +static INLINE union al_udma_desc *al_udma_desc_get(struct al_udma_q *udma_q) +{ + union al_udma_desc *desc; + uint16_t next_desc_idx; + + al_assert(udma_q); + + next_desc_idx = udma_q->next_desc_idx; + desc = udma_q->desc_base_ptr + next_desc_idx; + + next_desc_idx++; + + /* if reached end of queue, wrap around */ + udma_q->next_desc_idx = next_desc_idx & udma_q->size_mask; + + return desc; +} + +/** + * get ring id for the last allocated descriptor + * @param udma_q + * + * @return ring id for the last allocated descriptor + * this function must be called each time a new descriptor is allocated + * by the al_udma_desc_get(), unless ring id is ignored. + */ +static INLINE uint32_t al_udma_ring_id_get(struct al_udma_q *udma_q) +{ + uint32_t ring_id; + + al_assert(udma_q); + + ring_id = udma_q->desc_ring_id; + + /* calculate the ring id of the next desc */ + /* if next_desc points to first desc, then queue wrapped around */ + if (unlikely(udma_q->next_desc_idx) == 0) + udma_q->desc_ring_id = (udma_q->desc_ring_id + 1) & + DMA_RING_ID_MASK; + return ring_id; +} + +/* add DMA action - trigger the engine */ +/** + * add num descriptors to the submission queue. + * + * @param udma_q queue handle + * @param num number of descriptors to add to the queues ring. + * + * @return 0; + */ +static INLINE int al_udma_desc_action_add(struct al_udma_q *udma_q, + uint32_t num) +{ + uint32_t *addr; + + al_assert(udma_q); + al_assert((num > 0) && (num <= udma_q->size)); + + addr = &udma_q->q_regs->rings.drtp_inc; + /* make sure data written to the descriptors will be visible by the */ + /* DMA */ + al_local_data_memory_barrier(); + + /* + * As we explicitly invoke the synchronization function + * (al_data_memory_barrier()), then we can use the relaxed version. + */ + al_reg_write32_relaxed(addr, num); + + return 0; +} + +#define cdesc_is_first(flags) ((flags) & AL_UDMA_CDESC_FIRST) +#define cdesc_is_last(flags) ((flags) & AL_UDMA_CDESC_LAST) + +/** + * return pointer to the cdesc + offset desciptors. wrap around when needed. + * + * @param udma_q queue handle + * @param cdesc pointer that set by this function + * @param offset offset desciptors + * + */ +static INLINE volatile union al_udma_cdesc *al_cdesc_next( + struct al_udma_q *udma_q, + volatile union al_udma_cdesc *cdesc, + uint32_t offset) +{ + volatile uint8_t *tmp = (volatile uint8_t *) cdesc + offset * udma_q->cdesc_size; + al_assert(udma_q); + al_assert(cdesc); + + /* if wrap around */ + if (unlikely((tmp > udma_q->end_cdesc_ptr))) + return (union al_udma_cdesc *) + (udma_q->cdesc_base_ptr + + (tmp - udma_q->end_cdesc_ptr - udma_q->cdesc_size)); + + return (volatile union al_udma_cdesc *) tmp; +} + +/** + * check if the flags of the descriptor indicates that is new one + * the function uses the ring id from the descriptor flags to know whether it + * new one by comparing it with the curring ring id of the queue + * + * @param udma_q queue handle + * @param flags the flags of the completion descriptor + * + * @return AL_TRUE if the completion descriptor is new one. + * AL_FALSE if it old one. + */ +static INLINE al_bool al_udma_new_cdesc(struct al_udma_q *udma_q, + uint32_t flags) +{ + if (((flags & AL_M2S_DESC_RING_ID_MASK) >> AL_M2S_DESC_RING_ID_SHIFT) + == udma_q->comp_ring_id) + return AL_TRUE; + return AL_FALSE; +} + +/** + * get next completion descriptor + * this function will also increment the completion ring id when the ring wraps + * around + * + * @param udma_q queue handle + * @param cdesc current completion descriptor + * + * @return pointer to the completion descriptor that follows the one pointed by + * cdesc + */ +static INLINE volatile union al_udma_cdesc *al_cdesc_next_update( + struct al_udma_q *udma_q, + volatile union al_udma_cdesc *cdesc) +{ + /* if last desc, wrap around */ + if (unlikely(((volatile uint8_t *) cdesc == udma_q->end_cdesc_ptr))) { + udma_q->comp_ring_id = + (udma_q->comp_ring_id + 1) & DMA_RING_ID_MASK; + return (union al_udma_cdesc *) udma_q->cdesc_base_ptr; + } + return (volatile union al_udma_cdesc *) ((volatile uint8_t *) cdesc + udma_q->cdesc_size); +} + +/** + * get next completed packet from completion ring of the queue + * + * @param udma_q udma queue handle + * @param desc pointer that set by this function to the first descriptor + * note: desc is valid only when return value is not zero + * @return number of descriptors that belong to the packet. 0 means no completed + * full packet was found. + * If the descriptors found in the completion queue don't form full packet (no + * desc with LAST flag), then this function will do the following: + * (1) save the number of processed descriptors. + * (2) save last processed descriptor, so next time it called, it will resume + * from there. + * (3) return 0. + * note: the descriptors that belong to the completed packet will still be + * considered as used, that means the upper layer is safe to access those + * descriptors when this function returns. the al_udma_cdesc_ack() should be + * called to inform the udma driver that those descriptors are freed. + */ +uint32_t al_udma_cdesc_packet_get( + struct al_udma_q *udma_q, + volatile union al_udma_cdesc **desc); + +/** get completion descriptor pointer from its index */ +#define al_udma_cdesc_idx_to_ptr(udma_q, idx) \ + ((volatile union al_udma_cdesc *) ((udma_q)->cdesc_base_ptr + \ + (idx) * (udma_q)->cdesc_size)) + + +/** + * return number of all completed descriptors in the completion ring + * + * @param udma_q udma queue handle + * @param cdesc pointer that set by this function to the first descriptor + * note: desc is valid only when return value is not zero + * note: pass NULL if not interested + * @return number of descriptors. 0 means no completed descriptors were found. + * note: the descriptors that belong to the completed packet will still be + * considered as used, that means the upper layer is safe to access those + * descriptors when this function returns. the al_udma_cdesc_ack() should be + * called to inform the udma driver that those descriptors are freed. + */ +static INLINE uint32_t al_udma_cdesc_get_all( + struct al_udma_q *udma_q, + volatile union al_udma_cdesc **cdesc) +{ + uint16_t count = 0; + + al_assert(udma_q); + + udma_q->comp_head_idx = (uint16_t) + (al_reg_read32(&udma_q->q_regs->rings.crhp) & + 0xFFFF); + + count = (udma_q->comp_head_idx - udma_q->next_cdesc_idx) & + udma_q->size_mask; + + if (cdesc) + *cdesc = al_udma_cdesc_idx_to_ptr(udma_q, udma_q->next_cdesc_idx); + + return (uint32_t)count; +} + +/** + * acknowledge the driver that the upper layer completed processing completion + * descriptors + * + * @param udma_q udma queue handle + * @param num number of descriptors to acknowledge + * + * @return 0 + */ +static INLINE int al_udma_cdesc_ack(struct al_udma_q *udma_q, uint32_t num) +{ + al_assert(udma_q); + + udma_q->next_cdesc_idx += num; + udma_q->next_cdesc_idx &= udma_q->size_mask; + + return 0; +} + +/* *INDENT-OFF* */ +#ifdef __cplusplus +} +#endif +/* *INDENT-ON* */ + +#endif /* __AL_HAL_UDMA_H__ */ +/** @} end of UDMA group */ diff --git a/al_hal_udma_config.c b/al_hal_udma_config.c new file mode 100644 index 00000000000..a06f7898308 --- /dev/null +++ b/al_hal_udma_config.c @@ -0,0 +1,1373 @@ +/*- +******************************************************************************* +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_udma_config.c + * + * @brief Universal DMA HAL driver for configurations + * + */ + +#include +#include +#include + +/**************** Misc configurations *********************/ +/** Configure AXI generic configuration */ +int al_udma_axi_set(struct udma_gen_axi *axi_regs, + struct al_udma_axi_conf *axi) +{ + uint32_t reg; + + al_reg_write32(&axi_regs->cfg_1, axi->axi_timeout); + + reg = al_reg_read32(&axi_regs->cfg_2); + reg &= ~UDMA_GEN_AXI_CFG_2_ARB_PROMOTION_MASK; + reg |= axi->arb_promotion; + al_reg_write32(&axi_regs->cfg_2, reg); + + reg = al_reg_read32(&axi_regs->endian_cfg); + if (axi->swap_8_bytes == AL_TRUE) + reg |= UDMA_GEN_AXI_ENDIAN_CFG_SWAP_64B_EN; + else + reg &= ~UDMA_GEN_AXI_ENDIAN_CFG_SWAP_64B_EN; + + if (axi->swap_s2m_data == AL_TRUE) + reg |= UDMA_GEN_AXI_ENDIAN_CFG_SWAP_S2M_DATA; + else + reg &= ~UDMA_GEN_AXI_ENDIAN_CFG_SWAP_S2M_DATA; + + if (axi->swap_s2m_desc == AL_TRUE) + reg |= UDMA_GEN_AXI_ENDIAN_CFG_SWAP_S2M_DESC; + else + reg &= ~UDMA_GEN_AXI_ENDIAN_CFG_SWAP_S2M_DESC; + + if (axi->swap_m2s_data == AL_TRUE) + reg |= UDMA_GEN_AXI_ENDIAN_CFG_SWAP_M2S_DATA; + else + reg &= ~UDMA_GEN_AXI_ENDIAN_CFG_SWAP_M2S_DATA; + + if (axi->swap_m2s_desc == AL_TRUE) + reg |= UDMA_GEN_AXI_ENDIAN_CFG_SWAP_M2S_DESC; + else + reg &= ~UDMA_GEN_AXI_ENDIAN_CFG_SWAP_M2S_DESC; + + al_reg_write32(&axi_regs->endian_cfg, reg); + return 0; +} + +/* Configure UDMA AXI M2S configuration */ +/** Configure AXI M2S submaster */ +static int al_udma_m2s_axi_sm_set(struct al_udma_axi_submaster *m2s_sm, + uint32_t *cfg_1, uint32_t *cfg_2, + uint32_t *cfg_max_beats) +{ + uint32_t reg; + reg = al_reg_read32(cfg_1); + reg &= ~UDMA_AXI_M2S_COMP_WR_CFG_1_AWID_MASK; + reg |= m2s_sm->id & UDMA_AXI_M2S_COMP_WR_CFG_1_AWID_MASK; + reg &= ~UDMA_AXI_M2S_COMP_WR_CFG_1_AWCACHE_MASK; + reg |= (m2s_sm->cache_type << + UDMA_AXI_M2S_COMP_WR_CFG_1_AWCACHE_SHIFT) & + UDMA_AXI_M2S_COMP_WR_CFG_1_AWCACHE_MASK; + reg &= ~UDMA_AXI_M2S_COMP_WR_CFG_1_AWBURST_MASK; + reg |= (m2s_sm->burst << UDMA_AXI_M2S_COMP_WR_CFG_1_AWBURST_SHIFT) & + UDMA_AXI_M2S_COMP_WR_CFG_1_AWBURST_MASK; + al_reg_write32(cfg_1, reg); + + reg = al_reg_read32(cfg_2); + reg &= ~UDMA_AXI_M2S_COMP_WR_CFG_2_AWUSER_MASK; + reg |= m2s_sm->used_ext & UDMA_AXI_M2S_COMP_WR_CFG_2_AWUSER_MASK; + reg &= ~UDMA_AXI_M2S_COMP_WR_CFG_2_AWSIZE_MASK; + reg |= (m2s_sm->bus_size << + UDMA_AXI_M2S_COMP_WR_CFG_2_AWSIZE_SHIFT) & + UDMA_AXI_M2S_COMP_WR_CFG_2_AWSIZE_MASK; + reg &= ~UDMA_AXI_M2S_COMP_WR_CFG_2_AWQOS_MASK; + reg |= (m2s_sm->qos << UDMA_AXI_M2S_COMP_WR_CFG_2_AWQOS_SHIFT) & + UDMA_AXI_M2S_COMP_WR_CFG_2_AWQOS_MASK; + reg &= ~UDMA_AXI_M2S_COMP_WR_CFG_2_AWPROT_MASK; + reg |= (m2s_sm->prot << UDMA_AXI_M2S_COMP_WR_CFG_2_AWPROT_SHIFT) & + UDMA_AXI_M2S_COMP_WR_CFG_2_AWPROT_MASK; + al_reg_write32(cfg_2, reg); + + reg = al_reg_read32(cfg_max_beats); + reg &= ~UDMA_AXI_M2S_DESC_WR_CFG_1_MAX_AXI_BEATS_MASK; + reg |= m2s_sm->max_beats & + UDMA_AXI_M2S_DESC_WR_CFG_1_MAX_AXI_BEATS_MASK; + al_reg_write32(cfg_max_beats, reg); + + return 0; +} + +/** Configure UDMA AXI M2S configuration */ +int al_udma_m2s_axi_set(struct al_udma *udma, + struct al_udma_m2s_axi_conf *axi_m2s) +{ + uint32_t reg; + + al_udma_m2s_axi_sm_set(&axi_m2s->comp_write, + &udma->udma_regs->m2s.axi_m2s.comp_wr_cfg_1, + &udma->udma_regs->m2s.axi_m2s.comp_wr_cfg_2, + &udma->udma_regs->m2s.axi_m2s.desc_wr_cfg_1); + + al_udma_m2s_axi_sm_set(&axi_m2s->data_read, + &udma->udma_regs->m2s.axi_m2s.data_rd_cfg_1, + &udma->udma_regs->m2s.axi_m2s.data_rd_cfg_2, + &udma->udma_regs->m2s.axi_m2s.data_rd_cfg); + + al_udma_m2s_axi_sm_set(&axi_m2s->desc_read, + &udma->udma_regs->m2s.axi_m2s.desc_rd_cfg_1, + &udma->udma_regs->m2s.axi_m2s.desc_rd_cfg_2, + &udma->udma_regs->m2s.axi_m2s.desc_rd_cfg_3); + + reg = al_reg_read32(&udma->udma_regs->m2s.axi_m2s.data_rd_cfg); + if (axi_m2s->break_on_max_boundary == AL_TRUE) + reg |= UDMA_AXI_M2S_DATA_RD_CFG_ALWAYS_BREAK_ON_MAX_BOUDRY; + else + reg &= ~UDMA_AXI_M2S_DATA_RD_CFG_ALWAYS_BREAK_ON_MAX_BOUDRY; + al_reg_write32(&udma->udma_regs->m2s.axi_m2s.data_rd_cfg, reg); + + reg = al_reg_read32(&udma->udma_regs->m2s.axi_m2s.desc_wr_cfg_1); + reg &= ~UDMA_AXI_M2S_DESC_WR_CFG_1_MIN_AXI_BEATS_MASK; + reg |= (axi_m2s->min_axi_beats << + UDMA_AXI_M2S_DESC_WR_CFG_1_MIN_AXI_BEATS_SHIFT) & + UDMA_AXI_M2S_DESC_WR_CFG_1_MIN_AXI_BEATS_MASK; + al_reg_write32(&udma->udma_regs->m2s.axi_m2s.desc_wr_cfg_1, reg); + + reg = al_reg_read32(&udma->udma_regs->m2s.axi_m2s.ostand_cfg); + reg &= ~UDMA_AXI_M2S_OSTAND_CFG_MAX_DATA_RD_MASK; + reg |= axi_m2s->ostand_max_data_read & + UDMA_AXI_M2S_OSTAND_CFG_MAX_DATA_RD_MASK; + reg &= ~UDMA_AXI_M2S_OSTAND_CFG_MAX_DESC_RD_MASK; + reg |= (axi_m2s->ostand_max_desc_read << + UDMA_AXI_M2S_OSTAND_CFG_MAX_DESC_RD_SHIFT) & + UDMA_AXI_M2S_OSTAND_CFG_MAX_DESC_RD_MASK; + reg &= ~UDMA_AXI_M2S_OSTAND_CFG_MAX_COMP_REQ_MASK; + reg |= (axi_m2s->ostand_max_comp_req << + UDMA_AXI_M2S_OSTAND_CFG_MAX_COMP_REQ_SHIFT) & + UDMA_AXI_M2S_OSTAND_CFG_MAX_COMP_REQ_MASK; + reg &= ~UDMA_AXI_M2S_OSTAND_CFG_MAX_COMP_DATA_WR_MASK; + reg |= (axi_m2s->ostand_max_comp_write << + UDMA_AXI_M2S_OSTAND_CFG_MAX_COMP_DATA_WR_SHIFT) & + UDMA_AXI_M2S_OSTAND_CFG_MAX_COMP_DATA_WR_MASK; + al_reg_write32(&udma->udma_regs->m2s.axi_m2s.ostand_cfg, reg); + return 0; +} + +/** Configure AXI S2M submaster */ +static int al_udma_s2m_axi_sm_set(struct al_udma_axi_submaster *s2m_sm, + uint32_t *cfg_1, uint32_t *cfg_2, + uint32_t *cfg_max_beats) +{ + uint32_t reg; + reg = al_reg_read32(cfg_1); + reg &= ~UDMA_AXI_S2M_COMP_WR_CFG_1_AWID_MASK; + reg |= s2m_sm->id & UDMA_AXI_S2M_COMP_WR_CFG_1_AWID_MASK; + reg &= ~UDMA_AXI_S2M_COMP_WR_CFG_1_AWCACHE_MASK; + reg |= (s2m_sm->cache_type << + UDMA_AXI_S2M_COMP_WR_CFG_1_AWCACHE_SHIFT) & + UDMA_AXI_S2M_COMP_WR_CFG_1_AWCACHE_MASK; + reg &= ~UDMA_AXI_S2M_COMP_WR_CFG_1_AWBURST_MASK; + reg |= (s2m_sm->burst << UDMA_AXI_S2M_COMP_WR_CFG_1_AWBURST_SHIFT) & + UDMA_AXI_S2M_COMP_WR_CFG_1_AWBURST_MASK; + al_reg_write32(cfg_1, reg); + + reg = al_reg_read32(cfg_2); + reg &= ~UDMA_AXI_S2M_COMP_WR_CFG_2_AWUSER_MASK; + reg |= s2m_sm->used_ext & UDMA_AXI_S2M_COMP_WR_CFG_2_AWUSER_MASK; + reg &= ~UDMA_AXI_S2M_COMP_WR_CFG_2_AWSIZE_MASK; + reg |= (s2m_sm->bus_size << UDMA_AXI_S2M_COMP_WR_CFG_2_AWSIZE_SHIFT) & + UDMA_AXI_S2M_COMP_WR_CFG_2_AWSIZE_MASK; + reg &= ~UDMA_AXI_S2M_COMP_WR_CFG_2_AWQOS_MASK; + reg |= (s2m_sm->qos << UDMA_AXI_S2M_COMP_WR_CFG_2_AWQOS_SHIFT) & + UDMA_AXI_S2M_COMP_WR_CFG_2_AWQOS_MASK; + reg &= ~UDMA_AXI_S2M_COMP_WR_CFG_2_AWPROT_MASK; + reg |= (s2m_sm->prot << UDMA_AXI_S2M_COMP_WR_CFG_2_AWPROT_SHIFT) & + UDMA_AXI_S2M_COMP_WR_CFG_2_AWPROT_MASK; + al_reg_write32(cfg_2, reg); + + reg = al_reg_read32(cfg_max_beats); + reg &= ~UDMA_AXI_S2M_DESC_WR_CFG_1_MAX_AXI_BEATS_MASK; + reg |= s2m_sm->max_beats & + UDMA_AXI_S2M_DESC_WR_CFG_1_MAX_AXI_BEATS_MASK; + al_reg_write32(cfg_max_beats, reg); + + return 0; +} + +/** Configure UDMA AXI S2M configuration */ +int al_udma_s2m_axi_set(struct al_udma *udma, + struct al_udma_s2m_axi_conf *axi_s2m) +{ + + uint32_t reg; + + al_udma_s2m_axi_sm_set(&axi_s2m->data_write, + &udma->udma_regs->s2m.axi_s2m.data_wr_cfg_1, + &udma->udma_regs->s2m.axi_s2m.data_wr_cfg_2, + &udma->udma_regs->s2m.axi_s2m.data_wr_cfg); + + al_udma_s2m_axi_sm_set(&axi_s2m->desc_read, + &udma->udma_regs->s2m.axi_s2m.desc_rd_cfg_4, + &udma->udma_regs->s2m.axi_s2m.desc_rd_cfg_5, + &udma->udma_regs->s2m.axi_s2m.desc_rd_cfg_3); + + al_udma_s2m_axi_sm_set(&axi_s2m->comp_write, + &udma->udma_regs->s2m.axi_s2m.comp_wr_cfg_1, + &udma->udma_regs->s2m.axi_s2m.comp_wr_cfg_2, + &udma->udma_regs->s2m.axi_s2m.desc_wr_cfg_1); + + reg = al_reg_read32(&udma->udma_regs->s2m.axi_s2m.desc_rd_cfg_3); + if (axi_s2m->break_on_max_boundary == AL_TRUE) + reg |= UDMA_AXI_S2M_DESC_RD_CFG_3_ALWAYS_BREAK_ON_MAX_BOUDRY; + else + reg &= ~UDMA_AXI_S2M_DESC_RD_CFG_3_ALWAYS_BREAK_ON_MAX_BOUDRY; + al_reg_write32(&udma->udma_regs->s2m.axi_s2m.desc_rd_cfg_3, reg); + + reg = al_reg_read32(&udma->udma_regs->s2m.axi_s2m.desc_wr_cfg_1); + reg &= ~UDMA_AXI_S2M_DESC_WR_CFG_1_MIN_AXI_BEATS_MASK; + reg |= (axi_s2m->min_axi_beats << + UDMA_AXI_S2M_DESC_WR_CFG_1_MIN_AXI_BEATS_SHIFT) & + UDMA_AXI_S2M_DESC_WR_CFG_1_MIN_AXI_BEATS_MASK; + al_reg_write32(&udma->udma_regs->s2m.axi_s2m.desc_wr_cfg_1, reg); + + reg = al_reg_read32(&udma->udma_regs->s2m.axi_s2m.ostand_cfg_rd); + reg &= ~UDMA_AXI_S2M_OSTAND_CFG_RD_MAX_DESC_RD_OSTAND_MASK; + reg |= axi_s2m->ostand_max_desc_read & + UDMA_AXI_S2M_OSTAND_CFG_RD_MAX_DESC_RD_OSTAND_MASK; + + reg &= ~UDMA_AXI_S2M_OSTAND_CFG_RD_MAX_STREAM_ACK_MASK; + reg |= (axi_s2m->ack_fifo_depth << + UDMA_AXI_S2M_OSTAND_CFG_RD_MAX_STREAM_ACK_SHIFT) & + UDMA_AXI_S2M_OSTAND_CFG_RD_MAX_STREAM_ACK_MASK; + + al_reg_write32(&udma->udma_regs->s2m.axi_s2m.ostand_cfg_rd, reg); + + reg = al_reg_read32(&udma->udma_regs->s2m.axi_s2m.ostand_cfg_wr); + reg &= ~UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_DATA_WR_OSTAND_MASK; + reg |= axi_s2m->ostand_max_data_req & + UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_DATA_WR_OSTAND_MASK; + reg &= ~UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_DATA_BEATS_WR_OSTAND_MASK; + reg |= (axi_s2m->ostand_max_data_write << + UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_DATA_BEATS_WR_OSTAND_SHIFT) & + UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_DATA_BEATS_WR_OSTAND_MASK; + reg &= ~UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_COMP_REQ_MASK; + reg |= (axi_s2m->ostand_max_comp_req << + UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_COMP_REQ_SHIFT) & + UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_COMP_REQ_MASK; + reg &= ~UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_COMP_DATA_WR_OSTAND_MASK; + reg |= (axi_s2m->ostand_max_comp_write << + UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_COMP_DATA_WR_OSTAND_SHIFT) & + UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_COMP_DATA_WR_OSTAND_MASK; + al_reg_write32(&udma->udma_regs->s2m.axi_s2m.ostand_cfg_wr, reg); + return 0; +} + +/** M2S packet len configuration */ +int al_udma_m2s_packet_size_cfg_set(struct al_udma *udma, + struct al_udma_m2s_pkt_len_conf *conf) +{ + uint32_t reg = al_reg_read32(&udma->udma_regs->m2s.m2s.cfg_len); + uint32_t max_supported_size = UDMA_M2S_CFG_LEN_MAX_PKT_SIZE_MASK; + + al_assert(udma->type == UDMA_TX); + + if (conf->encode_64k_as_zero == AL_TRUE) + max_supported_size += 1; /* 64K */ + + if (conf->max_pkt_size > max_supported_size) { + al_err("udma [%s]: requested max_pkt_size (0x%x) exceeds the" + "supported limit (0x%x)\n", udma->name, + conf->max_pkt_size, max_supported_size); + return -EINVAL; + } + + reg &= ~UDMA_M2S_CFG_LEN_ENCODE_64K; + if (conf->encode_64k_as_zero == AL_TRUE) + reg |= UDMA_M2S_CFG_LEN_ENCODE_64K; + else + reg &= ~UDMA_M2S_CFG_LEN_ENCODE_64K; + + reg &= ~UDMA_M2S_CFG_LEN_MAX_PKT_SIZE_MASK; + reg |= conf->max_pkt_size; + + al_reg_write32(&udma->udma_regs->m2s.m2s.cfg_len, reg); + return 0; +} + +/** Report Error - to be used for abort */ +void al_udma_err_report(struct al_udma *udma __attribute__((__unused__))) +{ + return; +} + +/** Statistics - TBD */ +void al_udma_stats_get(struct al_udma *udma __attribute__((__unused__))) +{ + return; +} + +/** Configure UDMA M2S descriptor prefetch */ +int al_udma_m2s_pref_set(struct al_udma *udma, + struct al_udma_m2s_desc_pref_conf *conf) +{ + uint32_t reg; + + reg = al_reg_read32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_1); + reg &= ~UDMA_M2S_RD_DESC_PREF_CFG_1_FIFO_DEPTH_MASK; + reg |= conf->desc_fifo_depth; + al_reg_write32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_1, reg); + + reg = al_reg_read32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_2); + + if (conf->sch_mode == SRR) + reg |= UDMA_M2S_RD_DESC_PREF_CFG_2_PREF_FORCE_RR; + else if (conf->sch_mode == STRICT) + reg &= ~UDMA_M2S_RD_DESC_PREF_CFG_2_PREF_FORCE_RR; + else { + al_err("udma [%s]: requested descriptor preferch arbiter " + "mode (%d) is invalid\n", udma->name, conf->sch_mode); + return -EINVAL; + } + reg &= ~UDMA_M2S_RD_DESC_PREF_CFG_2_MAX_DESC_PER_PKT_MASK; + reg |= conf->max_desc_per_packet & + UDMA_M2S_RD_DESC_PREF_CFG_2_MAX_DESC_PER_PKT_MASK; + al_reg_write32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_2, reg); + + reg = al_reg_read32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_3); + reg &= ~UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_MASK; + reg |= conf->min_burst_below_thr & + UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_MASK; + + reg &= ~UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_MASK; + reg |=(conf->min_burst_above_thr << + UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_SHIFT) & + UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_MASK; + + reg &= ~UDMA_M2S_RD_DESC_PREF_CFG_3_PREF_THR_MASK; + reg |= (conf->pref_thr << + UDMA_M2S_RD_DESC_PREF_CFG_3_PREF_THR_SHIFT) & + UDMA_M2S_RD_DESC_PREF_CFG_3_PREF_THR_MASK; + + al_reg_write32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_3, reg); + + reg = al_reg_read32(&udma->udma_regs->m2s.m2s_rd.data_cfg); + reg &= ~UDMA_M2S_RD_DATA_CFG_DATA_FIFO_DEPTH_MASK; + reg |= conf->data_fifo_depth & + UDMA_M2S_RD_DATA_CFG_DATA_FIFO_DEPTH_MASK; + + reg &= ~UDMA_M2S_RD_DATA_CFG_MAX_PKT_LIMIT_MASK; + reg |= (conf->max_pkt_limit + << UDMA_M2S_RD_DATA_CFG_MAX_PKT_LIMIT_SHIFT) & + UDMA_M2S_RD_DATA_CFG_MAX_PKT_LIMIT_MASK; + al_reg_write32(&udma->udma_regs->m2s.m2s_rd.data_cfg, reg); + + return 0; +} + +/** Ger the M2S UDMA descriptor prefetch */ +int al_udma_m2s_pref_get(struct al_udma *udma, + struct al_udma_m2s_desc_pref_conf *conf) +{ + uint32_t reg; + + reg = al_reg_read32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_1); + conf->desc_fifo_depth = + AL_REG_FIELD_GET(reg, UDMA_M2S_RD_DESC_PREF_CFG_1_FIFO_DEPTH_MASK, + UDMA_M2S_RD_DESC_PREF_CFG_1_FIFO_DEPTH_SHIFT); + + reg = al_reg_read32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_2); + if (reg & UDMA_M2S_RD_DESC_PREF_CFG_2_MAX_DESC_PER_PKT_MASK) + conf->sch_mode = SRR; + else + conf->sch_mode = STRICT; + conf->max_desc_per_packet = + AL_REG_FIELD_GET(reg, + UDMA_M2S_RD_DESC_PREF_CFG_2_MAX_DESC_PER_PKT_MASK, + UDMA_M2S_RD_DESC_PREF_CFG_2_MAX_DESC_PER_PKT_SHIFT); + + reg = al_reg_read32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_3); + + conf->min_burst_below_thr = + AL_REG_FIELD_GET(reg, + UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_MASK, + UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_SHIFT); + + conf->min_burst_above_thr = + AL_REG_FIELD_GET(reg, + UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_MASK, + UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_SHIFT); + + conf->pref_thr = AL_REG_FIELD_GET(reg, + UDMA_M2S_RD_DESC_PREF_CFG_3_PREF_THR_MASK, + UDMA_M2S_RD_DESC_PREF_CFG_3_PREF_THR_SHIFT); + return 0; +} + +/* set max descriptors */ +int al_udma_m2s_max_descs_set(struct al_udma *udma, uint8_t max_descs) +{ + uint32_t pref_thr = max_descs; + uint32_t min_burst_above_thr = 4; + al_assert(max_descs <= AL_UDMA_M2S_MAX_ALLOWED_DESCS_PER_PACKET); + al_assert(max_descs > 0); + + /* increase min_burst_above_thr so larger burst can be used to fetch + * descriptors */ + if (pref_thr >= 8) + min_burst_above_thr = 8; + else { + /* don't set prefetch threshold too low so we can have the + * min_burst_above_thr >= 4 */ + pref_thr = 4; + } + + al_reg_write32_masked(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_2, + UDMA_M2S_RD_DESC_PREF_CFG_2_MAX_DESC_PER_PKT_MASK, + max_descs << UDMA_M2S_RD_DESC_PREF_CFG_2_MAX_DESC_PER_PKT_SHIFT); + + al_reg_write32_masked(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_3, + UDMA_M2S_RD_DESC_PREF_CFG_3_PREF_THR_MASK | + UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_MASK, + (pref_thr << UDMA_M2S_RD_DESC_PREF_CFG_3_PREF_THR_SHIFT) | + (min_burst_above_thr << UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_SHIFT)); + + return 0; +} + +/* set s2m max descriptors */ +int al_udma_s2m_max_descs_set(struct al_udma *udma, uint8_t max_descs) +{ + uint32_t pref_thr = max_descs; + uint32_t min_burst_above_thr = 4; + al_assert(max_descs <= AL_UDMA_S2M_MAX_ALLOWED_DESCS_PER_PACKET); + al_assert(max_descs > 0); + + /* increase min_burst_above_thr so larger burst can be used to fetch + * descriptors */ + if (pref_thr >= 8) + min_burst_above_thr = 8; + else + /* don't set prefetch threshold too low so we can have the + * min_burst_above_thr >= 4 */ + pref_thr = 4; + + al_reg_write32_masked(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_3, + UDMA_S2M_RD_DESC_PREF_CFG_3_PREF_THR_MASK | + UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_MASK, + (pref_thr << UDMA_S2M_RD_DESC_PREF_CFG_3_PREF_THR_SHIFT) | + (min_burst_above_thr << UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_SHIFT)); + + return 0; +} + +int al_udma_s2m_full_line_write_set(struct al_udma *udma, al_bool enable) +{ + uint32_t val = 0; + + if (enable == AL_TRUE) { + val = UDMA_S2M_WR_DATA_CFG_2_FULL_LINE_MODE; + al_info("udma [%s]: full line write enabled\n", udma->name); + } + + al_reg_write32_masked(&udma->udma_regs->s2m.s2m_wr.data_cfg_2, + UDMA_S2M_WR_DATA_CFG_2_FULL_LINE_MODE, + val); + return 0; +} + +/** Configure S2M UDMA descriptor prefetch */ +int al_udma_s2m_pref_set(struct al_udma *udma, + struct al_udma_s2m_desc_pref_conf *conf) +{ + uint32_t reg; + + reg = al_reg_read32(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_1); + reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_1_FIFO_DEPTH_MASK; + reg |= conf->desc_fifo_depth; + al_reg_write32(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_1, reg); + + reg = al_reg_read32(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_2); + + if (conf->sch_mode == SRR) + reg |= UDMA_S2M_RD_DESC_PREF_CFG_2_PREF_FORCE_RR; + else if (conf->sch_mode == STRICT) + reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_2_PREF_FORCE_RR; + else { + al_err("udma [%s]: requested descriptor preferch arbiter " + "mode (%d) is invalid\n", udma->name, conf->sch_mode); + return -EINVAL; + } + if (conf->q_promotion == AL_TRUE) + reg |= UDMA_S2M_RD_DESC_PREF_CFG_2_Q_PROMOTION; + else + reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_2_Q_PROMOTION; + + if (conf->force_promotion == AL_TRUE) + reg |= UDMA_S2M_RD_DESC_PREF_CFG_2_FORCE_PROMOTION; + else + reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_2_FORCE_PROMOTION; + + if (conf->en_pref_prediction == AL_TRUE) + reg |= UDMA_S2M_RD_DESC_PREF_CFG_2_EN_PREF_PREDICTION; + else + reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_2_EN_PREF_PREDICTION; + + reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_2_PROMOTION_TH_MASK; + reg |= (conf->promotion_th + << UDMA_S2M_RD_DESC_PREF_CFG_2_PROMOTION_TH_SHIFT) & + UDMA_S2M_RD_DESC_PREF_CFG_2_PROMOTION_TH_MASK; + + al_reg_write32(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_2, reg); + + reg = al_reg_read32(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_3); + reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_3_PREF_THR_MASK; + reg |= (conf->pref_thr << UDMA_S2M_RD_DESC_PREF_CFG_3_PREF_THR_SHIFT) & + UDMA_S2M_RD_DESC_PREF_CFG_3_PREF_THR_MASK; + + reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_MASK; + reg |= conf->min_burst_below_thr & + UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_MASK; + + reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_MASK; + reg |=(conf->min_burst_above_thr << + UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_SHIFT) & + UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_MASK; + + al_reg_write32(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_3, reg); + + reg = al_reg_read32(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_4); + reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_4_A_FULL_THR_MASK; + reg |= conf->a_full_thr & UDMA_S2M_RD_DESC_PREF_CFG_4_A_FULL_THR_MASK; + al_reg_write32(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_4, reg); + + + return 0; +} + +/* Configure S2M UDMA data write */ +int al_udma_s2m_data_write_set(struct al_udma *udma, + struct al_udma_s2m_data_write_conf *conf) +{ + uint32_t reg; + + reg = al_reg_read32(&udma->udma_regs->s2m.s2m_wr.data_cfg_1); + reg &= ~UDMA_S2M_WR_DATA_CFG_1_DATA_FIFO_DEPTH_MASK; + reg |= conf->data_fifo_depth & + UDMA_S2M_WR_DATA_CFG_1_DATA_FIFO_DEPTH_MASK; + reg &= ~UDMA_S2M_WR_DATA_CFG_1_MAX_PKT_LIMIT_MASK; + reg |= (conf->max_pkt_limit << + UDMA_S2M_WR_DATA_CFG_1_MAX_PKT_LIMIT_SHIFT) & + UDMA_S2M_WR_DATA_CFG_1_MAX_PKT_LIMIT_MASK; + reg &= ~UDMA_S2M_WR_DATA_CFG_1_FIFO_MARGIN_MASK; + reg |= (conf->fifo_margin << + UDMA_S2M_WR_DATA_CFG_1_FIFO_MARGIN_SHIFT) & + UDMA_S2M_WR_DATA_CFG_1_FIFO_MARGIN_MASK; + al_reg_write32(&udma->udma_regs->s2m.s2m_wr.data_cfg_1, reg); + + reg = al_reg_read32(&udma->udma_regs->s2m.s2m_wr.data_cfg_2); + reg &= ~UDMA_S2M_WR_DATA_CFG_2_DESC_WAIT_TIMER_MASK; + reg |= conf->desc_wait_timer & + UDMA_S2M_WR_DATA_CFG_2_DESC_WAIT_TIMER_MASK; + reg &= ~(UDMA_S2M_WR_DATA_CFG_2_DROP_IF_NO_DESC | + UDMA_S2M_WR_DATA_CFG_2_HINT_IF_NO_DESC | + UDMA_S2M_WR_DATA_CFG_2_WAIT_FOR_PREF | + UDMA_S2M_WR_DATA_CFG_2_FULL_LINE_MODE | + UDMA_S2M_WR_DATA_CFG_2_DIRECT_HDR_USE_BUF1); + reg |= conf->flags & + (UDMA_S2M_WR_DATA_CFG_2_DROP_IF_NO_DESC | + UDMA_S2M_WR_DATA_CFG_2_HINT_IF_NO_DESC | + UDMA_S2M_WR_DATA_CFG_2_WAIT_FOR_PREF | + UDMA_S2M_WR_DATA_CFG_2_FULL_LINE_MODE | + UDMA_S2M_WR_DATA_CFG_2_DIRECT_HDR_USE_BUF1); + al_reg_write32(&udma->udma_regs->s2m.s2m_wr.data_cfg_2, reg); + + return 0; +} + +/* Configure S2M UDMA completion */ +int al_udma_s2m_completion_set(struct al_udma *udma, + struct al_udma_s2m_completion_conf *conf) +{ + uint32_t reg = al_reg_read32(&udma->udma_regs->s2m.s2m_comp.cfg_1c); + reg &= ~UDMA_S2M_COMP_CFG_1C_DESC_SIZE_MASK; + reg |= conf->desc_size & UDMA_S2M_COMP_CFG_1C_DESC_SIZE_MASK; + if (conf->cnt_words == AL_TRUE) + reg |= UDMA_S2M_COMP_CFG_1C_CNT_WORDS; + else + reg &= ~UDMA_S2M_COMP_CFG_1C_CNT_WORDS; + if (conf->q_promotion == AL_TRUE) + reg |= UDMA_S2M_COMP_CFG_1C_Q_PROMOTION; + else + reg &= ~UDMA_S2M_COMP_CFG_1C_Q_PROMOTION; + if (conf->force_rr == AL_TRUE) + reg |= UDMA_S2M_COMP_CFG_1C_FORCE_RR; + else + reg &= ~UDMA_S2M_COMP_CFG_1C_FORCE_RR; + reg &= ~UDMA_S2M_COMP_CFG_1C_Q_FREE_MIN_MASK; + reg |= (conf->q_free_min << UDMA_S2M_COMP_CFG_1C_Q_FREE_MIN_SHIFT) & + UDMA_S2M_COMP_CFG_1C_Q_FREE_MIN_MASK; + al_reg_write32(&udma->udma_regs->s2m.s2m_comp.cfg_1c, reg); + + reg = al_reg_read32(&udma->udma_regs->s2m.s2m_comp.cfg_2c); + reg &= ~UDMA_S2M_COMP_CFG_2C_COMP_FIFO_DEPTH_MASK; + reg |= conf->comp_fifo_depth + & UDMA_S2M_COMP_CFG_2C_COMP_FIFO_DEPTH_MASK; + reg &= ~UDMA_S2M_COMP_CFG_2C_UNACK_FIFO_DEPTH_MASK; + reg |= (conf->unack_fifo_depth + << UDMA_S2M_COMP_CFG_2C_UNACK_FIFO_DEPTH_SHIFT) & + UDMA_S2M_COMP_CFG_2C_UNACK_FIFO_DEPTH_MASK; + al_reg_write32(&udma->udma_regs->s2m.s2m_comp.cfg_2c, reg); + + al_reg_write32(&udma->udma_regs->s2m.s2m_comp.cfg_application_ack, + conf->timeout); + return 0; +} + +/** Configure the M2S UDMA scheduling mode */ +int al_udma_m2s_sc_set(struct al_udma *udma, + struct al_udma_m2s_dwrr_conf *sched) +{ + uint32_t reg = al_reg_read32(&udma->udma_regs->m2s.m2s_dwrr.cfg_sched); + + if (sched->enable_dwrr == AL_TRUE) + reg |= UDMA_M2S_DWRR_CFG_SCHED_EN_DWRR; + else + reg &= ~UDMA_M2S_DWRR_CFG_SCHED_EN_DWRR; + + if (sched->pkt_mode == AL_TRUE) + reg |= UDMA_M2S_DWRR_CFG_SCHED_PKT_MODE_EN; + else + reg &= ~UDMA_M2S_DWRR_CFG_SCHED_PKT_MODE_EN; + + reg &= ~UDMA_M2S_DWRR_CFG_SCHED_WEIGHT_INC_MASK; + reg |= sched->weight << UDMA_M2S_DWRR_CFG_SCHED_WEIGHT_INC_SHIFT; + reg &= ~UDMA_M2S_DWRR_CFG_SCHED_INC_FACTOR_MASK; + reg |= sched->inc_factor << UDMA_M2S_DWRR_CFG_SCHED_INC_FACTOR_SHIFT; + al_reg_write32(&udma->udma_regs->m2s.m2s_dwrr.cfg_sched, reg); + + reg = al_reg_read32(&udma->udma_regs->m2s.m2s_dwrr.ctrl_deficit_cnt); + reg &= ~UDMA_M2S_DWRR_CTRL_DEFICIT_CNT_INIT_MASK; + reg |= sched->deficit_init_val; + al_reg_write32(&udma->udma_regs->m2s.m2s_dwrr.ctrl_deficit_cnt, reg); + + return 0; +} + +/** Configure the M2S UDMA rate limitation */ +int al_udma_m2s_rlimit_set(struct al_udma *udma, + struct al_udma_m2s_rlimit_mode *mode) +{ + uint32_t reg = al_reg_read32( + &udma->udma_regs->m2s.m2s_rate_limiter.gen_cfg); + + if (mode->pkt_mode_en == AL_TRUE) + reg |= UDMA_M2S_RATE_LIMITER_GEN_CFG_PKT_MODE_EN; + else + reg &= ~UDMA_M2S_RATE_LIMITER_GEN_CFG_PKT_MODE_EN; + reg &= ~UDMA_M2S_RATE_LIMITER_GEN_CFG_SHORT_CYCLE_SIZE_MASK; + reg |= mode->short_cycle_sz & + UDMA_M2S_RATE_LIMITER_GEN_CFG_SHORT_CYCLE_SIZE_MASK; + al_reg_write32(&udma->udma_regs->m2s.m2s_rate_limiter.gen_cfg, reg); + + reg = al_reg_read32(&udma->udma_regs->m2s.m2s_rate_limiter.ctrl_token); + reg &= ~UDMA_M2S_RATE_LIMITER_CTRL_TOKEN_RST_MASK; + reg |= mode->token_init_val & + UDMA_M2S_RATE_LIMITER_CTRL_TOKEN_RST_MASK; + al_reg_write32(&udma->udma_regs->m2s.m2s_rate_limiter.ctrl_token, reg); + + return 0; +} + +int al_udma_m2s_rlimit_reset(struct al_udma *udma) +{ + uint32_t reg = al_reg_read32( + &udma->udma_regs->m2s.m2s_rate_limiter.ctrl_cycle_cnt); + reg |= UDMA_M2S_RATE_LIMITER_CTRL_CYCLE_CNT_RST; + al_reg_write32(&udma->udma_regs->m2s.m2s_rate_limiter.ctrl_cycle_cnt, + reg); + return 0; +} + +/** Configure the Stream/Q rate limitation */ +static int al_udma_common_rlimit_set(struct udma_rlimit_common *regs, + struct al_udma_m2s_rlimit_cfg *conf) +{ + uint32_t reg = al_reg_read32(®s->cfg_1s); + /* mask max burst size, and enable/pause control bits */ + reg &= ~UDMA_M2S_STREAM_RATE_LIMITER_CFG_1S_MAX_BURST_SIZE_MASK; + reg &= ~UDMA_M2S_STREAM_RATE_LIMITER_CFG_1S_EN; + reg &= ~UDMA_M2S_STREAM_RATE_LIMITER_CFG_1S_PAUSE; + reg |= conf->max_burst_sz & + UDMA_M2S_STREAM_RATE_LIMITER_CFG_1S_MAX_BURST_SIZE_MASK; + al_reg_write32(®s->cfg_1s, reg); + + reg = al_reg_read32(®s->cfg_cycle); + reg &= ~UDMA_M2S_STREAM_RATE_LIMITER_CFG_CYCLE_LONG_CYCLE_SIZE_MASK; + reg |= conf->long_cycle_sz & + UDMA_M2S_STREAM_RATE_LIMITER_CFG_CYCLE_LONG_CYCLE_SIZE_MASK; + al_reg_write32(®s->cfg_cycle, reg); + + reg = al_reg_read32(®s->cfg_token_size_1); + reg &= ~UDMA_M2S_STREAM_RATE_LIMITER_CFG_TOKEN_SIZE_1_LONG_CYCLE_MASK; + reg |= conf->long_cycle & + UDMA_M2S_STREAM_RATE_LIMITER_CFG_TOKEN_SIZE_1_LONG_CYCLE_MASK; + al_reg_write32(®s->cfg_token_size_1, reg); + + reg = al_reg_read32(®s->cfg_token_size_2); + reg &= ~UDMA_M2S_STREAM_RATE_LIMITER_CFG_TOKEN_SIZE_2_SHORT_CYCLE_MASK; + reg |= conf->short_cycle & + UDMA_M2S_STREAM_RATE_LIMITER_CFG_TOKEN_SIZE_2_SHORT_CYCLE_MASK; + al_reg_write32(®s->cfg_token_size_2, reg); + + reg = al_reg_read32(®s->mask); + reg &= ~0xf; /* only bits 0-3 defined */ + reg |= conf->mask & 0xf; + al_reg_write32(®s->mask, reg); + + return 0; +} + +static int al_udma_common_rlimit_act(struct udma_rlimit_common *regs, + enum al_udma_m2s_rlimit_action act) +{ + uint32_t reg; + + switch (act) { + case AL_UDMA_STRM_RLIMIT_ENABLE: + reg = al_reg_read32(®s->cfg_1s); + reg |= UDMA_M2S_STREAM_RATE_LIMITER_CFG_1S_EN; + al_reg_write32(®s->cfg_1s, reg); + break; + case AL_UDMA_STRM_RLIMIT_PAUSE: + reg = al_reg_read32(®s->cfg_1s); + reg |= UDMA_M2S_STREAM_RATE_LIMITER_CFG_1S_PAUSE; + al_reg_write32(®s->cfg_1s, reg); + break; + case AL_UDMA_STRM_RLIMIT_RESET: + reg = al_reg_read32(®s->sw_ctrl); + reg |= UDMA_M2S_STREAM_RATE_LIMITER_SW_CTRL_RST_TOKEN_CNT; + al_reg_write32(®s->sw_ctrl, reg); + break; + default: + return -EINVAL; + } + return 0; +} + +/** Configure the M2S Stream rate limitation */ +int al_udma_m2s_strm_rlimit_set(struct al_udma *udma, + struct al_udma_m2s_rlimit_cfg *conf) +{ + struct udma_rlimit_common *rlimit_regs = + &udma->udma_regs->m2s.m2s_stream_rate_limiter.rlimit; + + return al_udma_common_rlimit_set(rlimit_regs, conf); +} + +int al_udma_m2s_strm_rlimit_act(struct al_udma *udma, + enum al_udma_m2s_rlimit_action act) +{ + struct udma_rlimit_common *rlimit_regs = + &udma->udma_regs->m2s.m2s_stream_rate_limiter.rlimit; + + if (al_udma_common_rlimit_act(rlimit_regs, act) == -EINVAL) { + al_err("udma [%s]: udma stream rate limit invalid action " + "(%d)\n", udma->name, act); + return -EINVAL; + } + return 0; +} + +/** Configure the M2S UDMA Q rate limitation */ +int al_udma_m2s_q_rlimit_set(struct al_udma_q *udma_q, + struct al_udma_m2s_rlimit_cfg *conf) +{ + struct udma_rlimit_common *rlimit_regs = &udma_q->q_regs->m2s_q.rlimit; + + return al_udma_common_rlimit_set(rlimit_regs, conf); +} + +int al_udma_m2s_q_rlimit_act(struct al_udma_q *udma_q, + enum al_udma_m2s_rlimit_action act) +{ + struct udma_rlimit_common *rlimit_regs = &udma_q->q_regs->m2s_q.rlimit; + + if (al_udma_common_rlimit_act(rlimit_regs, act) == -EINVAL) { + al_err("udma [%s %d]: udma stream rate limit invalid action " + "(%d)\n", + udma_q->udma->name, udma_q->qid, act); + return -EINVAL; + } + return 0; +} + +/** Configure the M2S UDMA Q scheduling mode */ +int al_udma_m2s_q_sc_set(struct al_udma_q *udma_q, + struct al_udma_m2s_q_dwrr_conf *conf) +{ + uint32_t reg = al_reg_read32(&udma_q->q_regs->m2s_q.dwrr_cfg_1); + + reg &= ~UDMA_M2S_Q_DWRR_CFG_1_MAX_DEFICIT_CNT_SIZE_MASK; + reg |= conf->max_deficit_cnt_sz & + UDMA_M2S_Q_DWRR_CFG_1_MAX_DEFICIT_CNT_SIZE_MASK; + if (conf->strict == AL_TRUE) + reg |= UDMA_M2S_Q_DWRR_CFG_1_STRICT; + else + reg &= ~UDMA_M2S_Q_DWRR_CFG_1_STRICT; + al_reg_write32(&udma_q->q_regs->m2s_q.dwrr_cfg_1, reg); + + reg = al_reg_read32(&udma_q->q_regs->m2s_q.dwrr_cfg_2); + reg &= ~UDMA_M2S_Q_DWRR_CFG_2_Q_QOS_MASK; + reg |= (conf->axi_qos << UDMA_M2S_Q_DWRR_CFG_2_Q_QOS_SHIFT) & + UDMA_M2S_Q_DWRR_CFG_2_Q_QOS_MASK; + reg &= ~UDMA_M2S_Q_DWRR_CFG_2_Q_QOS_MASK; + reg |= conf->q_qos & UDMA_M2S_Q_DWRR_CFG_2_Q_QOS_MASK; + al_reg_write32(&udma_q->q_regs->m2s_q.dwrr_cfg_2, reg); + + reg = al_reg_read32(&udma_q->q_regs->m2s_q.dwrr_cfg_3); + reg &= ~UDMA_M2S_Q_DWRR_CFG_3_WEIGHT_MASK; + reg |= conf->weight & UDMA_M2S_Q_DWRR_CFG_3_WEIGHT_MASK; + al_reg_write32(&udma_q->q_regs->m2s_q.dwrr_cfg_3, reg); + + return 0; +} + +int al_udma_m2s_q_sc_pause(struct al_udma_q *udma_q, al_bool set) +{ + uint32_t reg = al_reg_read32(&udma_q->q_regs->m2s_q.dwrr_cfg_1); + + if (set == AL_TRUE) + reg |= UDMA_M2S_Q_DWRR_CFG_1_PAUSE; + else + reg &= ~UDMA_M2S_Q_DWRR_CFG_1_PAUSE; + al_reg_write32(&udma_q->q_regs->m2s_q.dwrr_cfg_1, reg); + + return 0; +} + +int al_udma_m2s_q_sc_reset(struct al_udma_q *udma_q) +{ + uint32_t reg = al_reg_read32(&udma_q->q_regs->m2s_q.dwrr_sw_ctrl); + + reg |= UDMA_M2S_Q_DWRR_SW_CTRL_RST_CNT; + al_reg_write32(&udma_q->q_regs->m2s_q.dwrr_sw_ctrl, reg); + + return 0; +} + +/** M2S UDMA completion and application timeouts */ +int al_udma_m2s_comp_timeouts_set(struct al_udma *udma, + struct al_udma_m2s_comp_timeouts *conf) +{ + uint32_t reg = al_reg_read32(&udma->udma_regs->m2s.m2s_comp.cfg_1c); + + if (conf->sch_mode == SRR) + reg |= UDMA_M2S_COMP_CFG_1C_FORCE_RR; + else if (conf->sch_mode == STRICT) + reg &= ~UDMA_M2S_COMP_CFG_1C_FORCE_RR; + else { + al_err("udma [%s]: requested completion descriptor preferch " + "arbiter mode (%d) is invalid\n", + udma->name, conf->sch_mode); + return -EINVAL; + } + if (conf->enable_q_promotion == AL_TRUE) + reg |= UDMA_M2S_COMP_CFG_1C_Q_PROMOTION; + else + reg &= ~UDMA_M2S_COMP_CFG_1C_Q_PROMOTION; + reg &= ~UDMA_M2S_COMP_CFG_1C_COMP_FIFO_DEPTH_MASK; + reg |= + conf->comp_fifo_depth << UDMA_M2S_COMP_CFG_1C_COMP_FIFO_DEPTH_SHIFT; + + reg &= ~UDMA_M2S_COMP_CFG_1C_UNACK_FIFO_DEPTH_MASK; + reg |= conf->unack_fifo_depth + << UDMA_M2S_COMP_CFG_1C_UNACK_FIFO_DEPTH_SHIFT; + al_reg_write32(&udma->udma_regs->m2s.m2s_comp.cfg_1c, reg); + + al_reg_write32(&udma->udma_regs->m2s.m2s_comp.cfg_coal + , conf->coal_timeout); + + reg = al_reg_read32(&udma->udma_regs->m2s.m2s_comp.cfg_application_ack); + reg &= ~UDMA_M2S_COMP_CFG_APPLICATION_ACK_TOUT_MASK; + reg |= conf->app_timeout << UDMA_M2S_COMP_CFG_APPLICATION_ACK_TOUT_SHIFT; + al_reg_write32(&udma->udma_regs->m2s.m2s_comp.cfg_application_ack, reg); + return 0; +} + +int al_udma_m2s_comp_timeouts_get(struct al_udma *udma, + struct al_udma_m2s_comp_timeouts *conf) +{ + uint32_t reg = al_reg_read32(&udma->udma_regs->m2s.m2s_comp.cfg_1c); + + if (reg & UDMA_M2S_COMP_CFG_1C_FORCE_RR) + conf->sch_mode = SRR; + else + conf->sch_mode = STRICT; + + if (reg & UDMA_M2S_COMP_CFG_1C_Q_PROMOTION) + conf->enable_q_promotion = AL_TRUE; + else + conf->enable_q_promotion = AL_FALSE; + + conf->comp_fifo_depth = + AL_REG_FIELD_GET(reg, + UDMA_M2S_COMP_CFG_1C_COMP_FIFO_DEPTH_MASK, + UDMA_M2S_COMP_CFG_1C_COMP_FIFO_DEPTH_SHIFT); + conf->unack_fifo_depth = + AL_REG_FIELD_GET(reg, + UDMA_M2S_COMP_CFG_1C_UNACK_FIFO_DEPTH_MASK, + UDMA_M2S_COMP_CFG_1C_UNACK_FIFO_DEPTH_SHIFT); + + conf->coal_timeout = al_reg_read32( + &udma->udma_regs->m2s.m2s_comp.cfg_coal); + + reg = al_reg_read32( + &udma->udma_regs->m2s.m2s_comp.cfg_application_ack); + + conf->app_timeout = + AL_REG_FIELD_GET(reg, + UDMA_M2S_COMP_CFG_APPLICATION_ACK_TOUT_MASK, + UDMA_M2S_COMP_CFG_APPLICATION_ACK_TOUT_SHIFT); + + return 0; +} + +/** + * S2M UDMA configure no descriptors behaviour + */ +int al_udma_s2m_no_desc_cfg_set(struct al_udma *udma, al_bool drop_packet, al_bool gen_interrupt, uint32_t wait_for_desc_timeout) +{ + uint32_t reg; + + reg = al_reg_read32(&udma->udma_regs->s2m.s2m_wr.data_cfg_2); + + if ((drop_packet == AL_TRUE) && (wait_for_desc_timeout == 0)) { + al_err("udam [%s]: setting timeout to 0 will cause the udma to wait forever instead of dropping the packet", udma->name); + return -EINVAL; + } + + if (drop_packet == AL_TRUE) + reg |= UDMA_S2M_WR_DATA_CFG_2_DROP_IF_NO_DESC; + else + reg &= ~UDMA_S2M_WR_DATA_CFG_2_DROP_IF_NO_DESC; + + if (gen_interrupt == AL_TRUE) + reg |= UDMA_S2M_WR_DATA_CFG_2_HINT_IF_NO_DESC; + else + reg &= ~UDMA_S2M_WR_DATA_CFG_2_HINT_IF_NO_DESC; + + AL_REG_FIELD_SET(reg, UDMA_S2M_WR_DATA_CFG_2_DESC_WAIT_TIMER_MASK, UDMA_S2M_WR_DATA_CFG_2_DESC_WAIT_TIMER_SHIFT, wait_for_desc_timeout); + + al_reg_write32(&udma->udma_regs->s2m.s2m_wr.data_cfg_2, reg); + + return 0; +} + +/* S2M UDMA configure a queue's completion update */ +int al_udma_s2m_q_compl_updade_config(struct al_udma_q *udma_q, al_bool enable) +{ + uint32_t reg = al_reg_read32(&udma_q->q_regs->s2m_q.comp_cfg); + + if (enable == AL_TRUE) + reg |= UDMA_S2M_Q_COMP_CFG_EN_COMP_RING_UPDATE; + else + reg &= ~UDMA_S2M_Q_COMP_CFG_EN_COMP_RING_UPDATE; + + al_reg_write32(&udma_q->q_regs->s2m_q.comp_cfg, reg); + + return 0; +} + +/* S2M UDMA configure a queue's completion descriptors coalescing */ +int al_udma_s2m_q_compl_coal_config(struct al_udma_q *udma_q, al_bool enable, uint32_t + coal_timeout) +{ + uint32_t reg = al_reg_read32(&udma_q->q_regs->s2m_q.comp_cfg); + + if (enable == AL_TRUE) + reg &= ~UDMA_S2M_Q_COMP_CFG_DIS_COMP_COAL; + else + reg |= UDMA_S2M_Q_COMP_CFG_DIS_COMP_COAL; + + al_reg_write32(&udma_q->q_regs->s2m_q.comp_cfg, reg); + + al_reg_write32(&udma_q->q_regs->s2m_q.comp_cfg_2, coal_timeout); + return 0; +} + +/* S2M UDMA configure completion descriptors write burst parameters */ +int al_udma_s2m_compl_desc_burst_config(struct al_udma *udma, uint16_t + burst_size) +{ + if ((burst_size != 64) && (burst_size != 128) && (burst_size != 256)) { + al_err("%s: invalid burst_size value (%d)\n", __func__, + burst_size); + return -EINVAL; + } + + /* convert burst size from bytes to beats (16 byte) */ + burst_size = burst_size / 16; + al_reg_write32_masked(&udma->udma_regs->s2m.axi_s2m.desc_wr_cfg_1, + UDMA_AXI_S2M_DESC_WR_CFG_1_MIN_AXI_BEATS_MASK | + UDMA_AXI_S2M_DESC_WR_CFG_1_MAX_AXI_BEATS_MASK, + burst_size << UDMA_AXI_S2M_DESC_WR_CFG_1_MIN_AXI_BEATS_SHIFT | + burst_size << UDMA_AXI_S2M_DESC_WR_CFG_1_MAX_AXI_BEATS_SHIFT); + return 0; +} + +/* S2M UDMA configure a queue's completion descriptors header split */ +int al_udma_s2m_q_compl_hdr_split_config(struct al_udma_q *udma_q, al_bool enable, + al_bool force_hdr_split, uint32_t hdr_len) +{ + uint32_t reg = al_reg_read32(&udma_q->q_regs->s2m_q.pkt_cfg); + + reg &= ~UDMA_S2M_Q_PKT_CFG_HDR_SPLIT_SIZE_MASK; + reg &= ~UDMA_S2M_Q_PKT_CFG_EN_HDR_SPLIT; + reg &= ~UDMA_S2M_Q_PKT_CFG_FORCE_HDR_SPLIT; + + if (enable == AL_TRUE) { + reg |= hdr_len & UDMA_S2M_Q_PKT_CFG_HDR_SPLIT_SIZE_MASK; + reg |= UDMA_S2M_Q_PKT_CFG_EN_HDR_SPLIT; + + if (force_hdr_split == AL_TRUE) + reg |= UDMA_S2M_Q_PKT_CFG_FORCE_HDR_SPLIT; + } + + al_reg_write32(&udma_q->q_regs->s2m_q.pkt_cfg, reg); + + return 0; +} + +/* S2M UDMA per queue completion configuration */ +int al_udma_s2m_q_comp_set(struct al_udma_q *udma_q, + struct al_udma_s2m_q_comp_conf *conf) +{ + uint32_t reg = al_reg_read32(&udma_q->q_regs->s2m_q.comp_cfg); + if (conf->en_comp_ring_update == AL_TRUE) + reg |= UDMA_S2M_Q_COMP_CFG_EN_COMP_RING_UPDATE; + else + reg &= ~UDMA_S2M_Q_COMP_CFG_EN_COMP_RING_UPDATE; + + if (conf->dis_comp_coal == AL_TRUE) + reg |= UDMA_S2M_Q_COMP_CFG_DIS_COMP_COAL; + else + reg &= ~UDMA_S2M_Q_COMP_CFG_DIS_COMP_COAL; + + al_reg_write32(&udma_q->q_regs->s2m_q.comp_cfg, reg); + + al_reg_write32(&udma_q->q_regs->s2m_q.comp_cfg_2, conf->comp_timer); + + reg = al_reg_read32(&udma_q->q_regs->s2m_q.pkt_cfg); + + reg &= ~UDMA_S2M_Q_PKT_CFG_HDR_SPLIT_SIZE_MASK; + reg |= conf->hdr_split_size & UDMA_S2M_Q_PKT_CFG_HDR_SPLIT_SIZE_MASK; + if (conf->force_hdr_split == AL_TRUE) + reg |= UDMA_S2M_Q_PKT_CFG_FORCE_HDR_SPLIT; + else + reg &= ~UDMA_S2M_Q_PKT_CFG_FORCE_HDR_SPLIT; + if (conf->en_hdr_split == AL_TRUE) + reg |= UDMA_S2M_Q_PKT_CFG_EN_HDR_SPLIT; + else + reg &= ~UDMA_S2M_Q_PKT_CFG_EN_HDR_SPLIT; + + al_reg_write32(&udma_q->q_regs->s2m_q.pkt_cfg, reg); + + reg = al_reg_read32(&udma_q->q_regs->s2m_q.qos_cfg); + reg &= ~UDMA_S2M_QOS_CFG_Q_QOS_MASK; + reg |= conf->q_qos & UDMA_S2M_QOS_CFG_Q_QOS_MASK; + al_reg_write32(&udma_q->q_regs->s2m_q.qos_cfg, reg); + + return 0; +} + +/* UDMA VMID control configuration */ +void al_udma_gen_vmid_conf_set( + struct unit_regs *unit_regs, + struct al_udma_gen_vmid_conf *conf) +{ + unsigned int rev_id; + + al_reg_write32_masked( + &unit_regs->gen.vmid.cfg_vmid_0, + UDMA_GEN_VMID_CFG_VMID_0_TX_Q_VMID_DESC_EN_MASK | + UDMA_GEN_VMID_CFG_VMID_0_TX_Q_VMID_QUEUE_EN_MASK | + UDMA_GEN_VMID_CFG_VMID_0_RX_Q_VMID_DESC_EN_MASK | + UDMA_GEN_VMID_CFG_VMID_0_RX_Q_VMID_QUEUE_EN_MASK, + (((conf->tx_q_conf[0].desc_en << 0) | + (conf->tx_q_conf[1].desc_en << 1) | + (conf->tx_q_conf[2].desc_en << 2) | + (conf->tx_q_conf[3].desc_en << 3)) << + UDMA_GEN_VMID_CFG_VMID_0_TX_Q_VMID_DESC_EN_SHIFT) | + (((conf->tx_q_conf[0].queue_en << 0) | + (conf->tx_q_conf[1].queue_en << 1) | + (conf->tx_q_conf[2].queue_en << 2) | + (conf->tx_q_conf[3].queue_en << 3)) << + UDMA_GEN_VMID_CFG_VMID_0_TX_Q_VMID_QUEUE_EN_SHIFT) | + (((conf->rx_q_conf[0].desc_en << 0) | + (conf->rx_q_conf[1].desc_en << 1) | + (conf->rx_q_conf[2].desc_en << 2) | + (conf->rx_q_conf[3].desc_en << 3)) << + UDMA_GEN_VMID_CFG_VMID_0_RX_Q_VMID_DESC_EN_SHIFT) | + (((conf->rx_q_conf[0].queue_en << 0) | + (conf->rx_q_conf[1].queue_en << 1) | + (conf->rx_q_conf[2].queue_en << 2) | + (conf->rx_q_conf[3].queue_en << 3)) << + UDMA_GEN_VMID_CFG_VMID_0_RX_Q_VMID_QUEUE_EN_SHIFT)); + + /* VMID per queue */ + al_reg_write32( + &unit_regs->gen.vmid.cfg_vmid_1, + (conf->tx_q_conf[0].vmid << + UDMA_GEN_VMID_CFG_VMID_1_TX_Q_0_VMID_SHIFT) | + (conf->tx_q_conf[1].vmid << + UDMA_GEN_VMID_CFG_VMID_1_TX_Q_1_VMID_SHIFT)); + + al_reg_write32( + &unit_regs->gen.vmid.cfg_vmid_2, + (conf->tx_q_conf[2].vmid << + UDMA_GEN_VMID_CFG_VMID_2_TX_Q_2_VMID_SHIFT) | + (conf->tx_q_conf[3].vmid << + UDMA_GEN_VMID_CFG_VMID_2_TX_Q_3_VMID_SHIFT)); + + al_reg_write32( + &unit_regs->gen.vmid.cfg_vmid_3, + (conf->rx_q_conf[0].vmid << + UDMA_GEN_VMID_CFG_VMID_3_RX_Q_0_VMID_SHIFT) | + (conf->rx_q_conf[1].vmid << + UDMA_GEN_VMID_CFG_VMID_3_RX_Q_1_VMID_SHIFT)); + + al_reg_write32( + &unit_regs->gen.vmid.cfg_vmid_4, + (conf->rx_q_conf[2].vmid << + UDMA_GEN_VMID_CFG_VMID_4_RX_Q_2_VMID_SHIFT) | + (conf->rx_q_conf[3].vmid << + UDMA_GEN_VMID_CFG_VMID_4_RX_Q_3_VMID_SHIFT)); + + /* VMADDR per queue */ + rev_id = al_udma_get_revision(unit_regs); + if (rev_id >= AL_UDMA_REV_ID_REV2) { + al_reg_write32( + &unit_regs->gen.vmaddr.cfg_vmaddr_0, + (conf->tx_q_conf[0].vmaddr << + UDMA_GEN_VMADDR_CFG_VMADDR_0_TX_Q_0_VMADDR_SHIFT) | + (conf->tx_q_conf[1].vmaddr << + UDMA_GEN_VMADDR_CFG_VMADDR_0_TX_Q_1_VMADDR_SHIFT)); + + al_reg_write32( + &unit_regs->gen.vmaddr.cfg_vmaddr_1, + (conf->tx_q_conf[2].vmaddr << + UDMA_GEN_VMADDR_CFG_VMADDR_1_TX_Q_2_VMADDR_SHIFT) | + (conf->tx_q_conf[3].vmaddr << + UDMA_GEN_VMADDR_CFG_VMADDR_1_TX_Q_3_VMADDR_SHIFT)); + + al_reg_write32( + &unit_regs->gen.vmaddr.cfg_vmaddr_2, + (conf->rx_q_conf[0].vmaddr << + UDMA_GEN_VMADDR_CFG_VMADDR_2_RX_Q_0_VMADDR_SHIFT) | + (conf->rx_q_conf[1].vmaddr << + UDMA_GEN_VMADDR_CFG_VMADDR_2_RX_Q_1_VMADDR_SHIFT)); + + al_reg_write32( + &unit_regs->gen.vmaddr.cfg_vmaddr_3, + (conf->rx_q_conf[2].vmaddr << + UDMA_GEN_VMADDR_CFG_VMADDR_3_RX_Q_2_VMADDR_SHIFT) | + (conf->rx_q_conf[3].vmaddr << + UDMA_GEN_VMADDR_CFG_VMADDR_3_RX_Q_3_VMADDR_SHIFT)); + } +} + +/* UDMA VMID MSIX control configuration */ +void al_udma_gen_vmid_msix_conf_set( + struct unit_regs *unit_regs, + struct al_udma_gen_vmid_msix_conf *conf) +{ + al_reg_write32_masked( + &unit_regs->gen.vmid.cfg_vmid_0, + UDMA_GEN_VMID_CFG_VMID_0_MSIX_VMID_ACCESS_EN | + UDMA_GEN_VMID_CFG_VMID_0_MSIX_VMID_SEL, + (conf->access_en ? UDMA_GEN_VMID_CFG_VMID_0_MSIX_VMID_ACCESS_EN : 0) | + (conf->sel ? UDMA_GEN_VMID_CFG_VMID_0_MSIX_VMID_SEL : 0)); +} + +/* UDMA VMID control advanced Tx queue configuration */ +void al_udma_gen_vmid_advanced_tx_q_conf( + struct al_udma_q *q, + struct al_udma_gen_vmid_advanced_tx_q_conf *conf) +{ + struct udma_gen_regs *gen_regs = q->udma->gen_regs; + struct udma_gen_vmpr *vmpr = &gen_regs->vmpr[q->qid]; + + al_reg_write32_masked( + &vmpr->cfg_vmpr_0, + UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_HISEL_MASK | + UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_DATA_VMID_EN | + UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_PREF_VMID_EN | + UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_CMPL_VMID_EN, + conf->tx_q_addr_hi_sel | + ((conf->tx_q_data_vmid_en == AL_TRUE) ? + UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_DATA_VMID_EN : 0) | + ((conf->tx_q_prefetch_vmid_en == AL_TRUE) ? + UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_PREF_VMID_EN : 0) | + ((conf->tx_q_compl_vmid_en == AL_TRUE) ? + UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_CMPL_VMID_EN : 0)); + + al_reg_write32( + &vmpr->cfg_vmpr_1, + conf->tx_q_addr_hi); + + al_reg_write32_masked( + &vmpr->cfg_vmpr_2, + UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_PREF_VMID_MASK | + UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_CMPL_VMID_MASK, + (conf->tx_q_prefetch_vmid << + UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_PREF_VMID_SHIFT) | + (conf->tx_q_compl_vmid << + UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_CMPL_VMID_SHIFT)); + + al_reg_write32_masked( + &vmpr->cfg_vmpr_3, + UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_VMID_MASK | + UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_VMID_SEL_MASK, + (conf->tx_q_data_vmid << + UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_VMID_SHIFT) | + (conf->tx_q_data_vmid_mask << + UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_VMID_SEL_SHIFT)); +} + +/** UDMA VMID control advanced Rx queue configuration */ +void al_udma_gen_vmid_advanced_rx_q_conf( + struct al_udma_q *q, + struct al_udma_gen_vmid_advanced_rx_q_conf *conf) +{ + struct udma_gen_regs *gen_regs = q->udma->gen_regs; + struct udma_gen_vmpr *vmpr = &gen_regs->vmpr[q->qid]; + + al_reg_write32_masked( + &vmpr->cfg_vmpr_4, + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF1_HISEL_MASK | + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF1_VMID_EN | + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_HISEL_MASK | + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_VMID_EN | + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_DDP_HISEL_MASK | + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_DDP_VMID_EN | + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_PREF_VMID_EN | + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_CMPL_VMID_EN, + (conf->rx_q_addr_hi_sel << + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF1_HISEL_SHIFT) | + ((conf->rx_q_data_vmid_en == AL_TRUE) ? + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF1_VMID_EN : 0) | + (conf->rx_q_data_buff2_addr_hi_sel << + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_HISEL_SHIFT) | + ((conf->rx_q_data_buff2_vmid_en == AL_TRUE) ? + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_VMID_EN : 0) | + (conf->rx_q_ddp_addr_hi_sel << + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_DDP_HISEL_SHIFT) | + ((conf->rx_q_ddp_vmid_en == AL_TRUE) ? + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_DDP_VMID_EN : 0) | + ((conf->rx_q_prefetch_vmid_en == AL_TRUE) ? + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_PREF_VMID_EN : 0) | + ((conf->rx_q_compl_vmid_en == AL_TRUE) ? + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_CMPL_VMID_EN : 0)); + + al_reg_write32_masked( + &vmpr->cfg_vmpr_6, + UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_PREF_VMID_MASK | + UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_CMPL_VMID_MASK, + (conf->rx_q_prefetch_vmid << + UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_PREF_VMID_SHIFT) | + (conf->rx_q_compl_vmid << + UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_CMPL_VMID_SHIFT)); + + al_reg_write32_masked( + &vmpr->cfg_vmpr_7, + UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_VMID_MASK | + UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_VMID_SEL_MASK, + (conf->rx_q_data_vmid << + UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_VMID_SHIFT) | + (conf->rx_q_data_vmid_mask << + UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_VMID_SEL_SHIFT)); + + al_reg_write32_masked( + &vmpr->cfg_vmpr_8, + UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_VMID_MASK | + UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_VMID_SEL_MASK, + (conf->rx_q_data_buff2_vmid << + UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_VMID_SHIFT) | + (conf->rx_q_data_buff2_mask << + UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_VMID_SEL_SHIFT)); + + al_reg_write32_masked( + &vmpr->cfg_vmpr_9, + UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_VMID_MASK | + UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_VMID_SEL_MASK, + (conf->rx_q_ddp_vmid << + UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_VMID_SHIFT) | + (conf->rx_q_ddp_mask << + UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_VMID_SEL_SHIFT)); + + al_reg_write32( + &vmpr->cfg_vmpr_10, + conf->rx_q_addr_hi); + + al_reg_write32( + &vmpr->cfg_vmpr_11, + conf->rx_q_data_buff2_addr_hi); + + al_reg_write32( + &vmpr->cfg_vmpr_12, + conf->rx_q_ddp_addr_hi); +} + +/* UDMA header split buffer 2 Rx queue configuration */ +void al_udma_gen_hdr_split_buff2_rx_q_conf( + struct al_udma_q *q, + struct al_udma_gen_hdr_split_buff2_q_conf *conf) +{ + struct udma_gen_regs *gen_regs = q->udma->gen_regs; + struct udma_gen_vmpr *vmpr = &gen_regs->vmpr[q->qid]; + + al_reg_write32_masked( + &vmpr->cfg_vmpr_4, + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_MSB_ADDR_SEL_MASK, + conf->add_msb_sel << + UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_MSB_ADDR_SEL_SHIFT); + + al_reg_write32( + &vmpr->cfg_vmpr_5, + conf->addr_msb); +} + diff --git a/al_hal_udma_config.h b/al_hal_udma_config.h new file mode 100644 index 00000000000..b742e1824c9 --- /dev/null +++ b/al_hal_udma_config.h @@ -0,0 +1,755 @@ +/*- +******************************************************************************* +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. + +*******************************************************************************/ + +/** + * @defgroup group_udma_config UDMA Config + * @ingroup group_udma_api + * UDMA Config API + * @{ + * @file al_hal_udma_config.h + * + * @brief C Header file for the Universal DMA HAL driver for configuration APIs + * + */ + +#ifndef __AL_HAL_UDMA_CONFIG_H__ +#define __AL_HAL_UDMA_CONFIG_H__ + +#include + + +/* *INDENT-OFF* */ +#ifdef __cplusplus +extern "C" { +#endif +/* *INDENT-ON* */ + +/** Scheduling mode */ +enum al_udma_sch_mode { + STRICT, /* Strict */ + SRR, /* Simple Sound Rubin */ + DWRR /* Deficit Weighted Round Rubin */ +}; + +/** AXI configuration */ +struct al_udma_axi_conf { + uint32_t axi_timeout; /* Timeout for AXI transactions */ + uint8_t arb_promotion; /* arbitration promotion */ + al_bool swap_8_bytes; /* enable 8 bytes swap instead of 4 bytes */ + al_bool swap_s2m_data; + al_bool swap_s2m_desc; + al_bool swap_m2s_data; + al_bool swap_m2s_desc; +}; + +/** UDMA AXI M2S configuration */ +struct al_udma_axi_submaster { + uint8_t id; /* AXI ID */ + uint8_t cache_type; + uint8_t burst; + uint16_t used_ext; + uint8_t bus_size; + uint8_t qos; + uint8_t prot; + uint8_t max_beats; +}; + +/** UDMA AXI M2S configuration */ +struct al_udma_m2s_axi_conf { + struct al_udma_axi_submaster comp_write; + struct al_udma_axi_submaster data_read; + struct al_udma_axi_submaster desc_read; + al_bool break_on_max_boundary; /* Data read break on max boundary */ + uint8_t min_axi_beats; /* Minimum burst for writing completion desc. */ + uint8_t ostand_max_data_read; + uint8_t ostand_max_desc_read; + uint8_t ostand_max_comp_req; + uint8_t ostand_max_comp_write; +}; + +/** UDMA AXI S2M configuration */ +struct al_udma_s2m_axi_conf { + struct al_udma_axi_submaster data_write; + struct al_udma_axi_submaster desc_read; + struct al_udma_axi_submaster comp_write; + al_bool break_on_max_boundary; /* Data read break on max boundary */ + uint8_t min_axi_beats; /* Minimum burst for writing completion desc. */ + uint8_t ostand_max_data_req; + uint8_t ostand_max_data_write; + uint8_t ostand_max_comp_req; + uint8_t ostand_max_comp_write; + uint8_t ostand_max_desc_read; + uint8_t ack_fifo_depth; /* size of the stream application ack fifo */ +}; + +/** M2S error logging */ +struct al_udma_err_log { + uint32_t error_status; + uint32_t header[4]; +}; + +/** M2S max packet size configuration */ +struct al_udma_m2s_pkt_len_conf { + uint32_t max_pkt_size; + al_bool encode_64k_as_zero; +}; + +/** M2S Descriptor Prefetch configuration */ +struct al_udma_m2s_desc_pref_conf { + uint8_t desc_fifo_depth; + enum al_udma_sch_mode sch_mode; /* Scheduling mode + * (either strict or RR) */ + + uint8_t max_desc_per_packet; /* max number of descriptors to + * prefetch */ + /* in one burst (5b) */ + uint8_t pref_thr; + uint8_t min_burst_above_thr; /* min burst size when fifo above + * pref_thr (4b) + */ + uint8_t min_burst_below_thr; /* min burst size when fifo below + * pref_thr (4b) + */ + uint8_t max_pkt_limit; /* maximum number of packets in the data + * read FIFO, defined based on header + * FIFO size + */ + uint16_t data_fifo_depth; /* maximum number of data beats in the + * data read FIFO, + * defined based on header FIFO size + */ +}; + +/** S2M Descriptor Prefetch configuration */ +struct al_udma_s2m_desc_pref_conf { + uint8_t desc_fifo_depth; + enum al_udma_sch_mode sch_mode; /* Scheduling mode * + * (either strict or RR) + */ + + al_bool q_promotion; /* enable promotion */ + al_bool force_promotion; /* force promotion */ + al_bool en_pref_prediction; /* enable prefetch prediction */ + uint8_t promotion_th; /* Threshold for queue promotion */ + + uint8_t pref_thr; + uint8_t min_burst_above_thr; /* min burst size when fifo above + * pref_thr (4b) + */ + uint8_t min_burst_below_thr; /* min burst size when fifo below + * pref_thr (4b) + */ + uint8_t a_full_thr; /* almost full threshold */ +}; + +/** S2M Data write configuration */ +struct al_udma_s2m_data_write_conf { + uint16_t data_fifo_depth; /* maximum number of data beats in the + * data write FIFO, defined based on + * header FIFO size + */ + uint8_t max_pkt_limit; /* maximum number of packets in the + * data write FIFO,defined based on + * header FIFO size + */ + uint8_t fifo_margin; + uint32_t desc_wait_timer; /* waiting time for the host to write + * new descriptor to the queue + * (for the current packet in process) + */ + uint32_t flags; /* bitwise of flags of s2m + * data_cfg_2 register + */ +}; + +/** S2M Completion configuration */ +struct al_udma_s2m_completion_conf { + uint8_t desc_size; /* Size of completion descriptor + * in words + */ + al_bool cnt_words; /* Completion fifo in use counter: + * AL_TRUE words, AL_FALS descriptors + */ + al_bool q_promotion; /* Enable promotion of the current + * unack in progress */ + /* in the completion write scheduler */ + al_bool force_rr; /* force RR arbitration in the + * scheduler + */ + // uint8_t ack_fifo_depth; /* size of the stream application ack fifo */ + uint8_t q_free_min; /* minimum number of free completion + * entries + */ + /* to qualify for promotion */ + + uint16_t comp_fifo_depth; /* Size of completion fifo in words */ + uint16_t unack_fifo_depth; /* Size of unacked fifo in descs */ + uint32_t timeout; /* Ack timout from stream interface */ +}; + +/** M2S UDMA DWRR configuration */ +struct al_udma_m2s_dwrr_conf { + al_bool enable_dwrr; + uint8_t inc_factor; + uint8_t weight; + al_bool pkt_mode; + uint32_t deficit_init_val; +}; + +/** M2S DMA Rate Limitation mode */ +struct al_udma_m2s_rlimit_mode { + al_bool pkt_mode_en; + uint16_t short_cycle_sz; + uint32_t token_init_val; +}; + +/** M2S Stream/Q Rate Limitation */ +struct al_udma_m2s_rlimit_cfg { + uint32_t max_burst_sz; /* maximum number of accumulated bytes in the + * token counter + */ + uint16_t long_cycle_sz; /* number of short cycles between token fill */ + uint32_t long_cycle; /* number of bits to add in each long cycle */ + uint32_t short_cycle; /* number of bits to add in each cycle */ + uint32_t mask; /* mask the different types of rate limiters */ +}; + +enum al_udma_m2s_rlimit_action { + AL_UDMA_STRM_RLIMIT_ENABLE, + AL_UDMA_STRM_RLIMIT_PAUSE, + AL_UDMA_STRM_RLIMIT_RESET +}; + +/** M2S UDMA Q scheduling configuration */ +struct al_udma_m2s_q_dwrr_conf { + uint32_t max_deficit_cnt_sz; /*maximum number of accumulated bytes + * in the deficit counter + */ + al_bool strict; /* bypass DWRR */ + uint8_t axi_qos; + uint16_t q_qos; + uint8_t weight; +}; + +/** M2S UDMA / UDMA Q scheduling configuration */ +struct al_udma_m2s_sc { + enum al_udma_sch_mode sch_mode; /* Scheduling Mode */ + struct al_udma_m2s_dwrr_conf dwrr; /* DWRR configuration */ +}; + +/** UDMA / UDMA Q rate limitation configuration */ +struct al_udma_m2s_rlimit { + struct al_udma_m2s_rlimit_mode rlimit_mode; + /* rate limitation enablers */ +#if 0 + struct al_udma_tkn_bkt_conf token_bkt; /* Token Bucket configuration */ +#endif +}; + +/** UDMA Data read configuration */ +struct al_udma_m2s_data_rd_conf { + uint8_t max_rd_d_beats; /* max burst size for reading data + * (in AXI beats-128b) (5b) + */ + uint8_t max_rd_d_out_req; /* max number of outstanding data + * read requests (6b) + */ + uint16_t max_rd_d_out_beats; /* max num. of data read beats (10b) */ +}; + +/** M2S UDMA completion and application timeouts */ +struct al_udma_m2s_comp_timeouts { + enum al_udma_sch_mode sch_mode; /* Scheduling mode + * (either strict or RR) + */ + al_bool enable_q_promotion; + uint8_t unack_fifo_depth; /* unacked desc fifo size */ + uint8_t comp_fifo_depth; /* desc fifo size */ + uint32_t coal_timeout; /* (24b) */ + uint32_t app_timeout; /* (24b) */ +}; + +/** S2M UDMA per queue completion configuration */ +struct al_udma_s2m_q_comp_conf { + al_bool dis_comp_coal; /* disable completion coalescing */ + al_bool en_comp_ring_update; /* enable writing completion descs */ + uint32_t comp_timer; /* completion coalescing timer */ + al_bool en_hdr_split; /* enable header split */ + al_bool force_hdr_split; /* force header split */ + uint16_t hdr_split_size; /* size used for the header split */ + uint8_t q_qos; /* queue QoS */ +}; + +/** UDMA per queue VMID control configuration */ +struct al_udma_gen_vmid_q_conf { + /* Enable usage of the VMID per queue according to 'vmid' */ + al_bool queue_en; + + /* Enable usage of the VMID from the descriptor buffer address 63:48 */ + al_bool desc_en; + + /* VMID to be applied when 'queue_en' is asserted */ + uint16_t vmid; + + /* VMADDR to be applied to msbs when 'desc_en' is asserted. + * Relevant for revisions >= AL_UDMA_REV_ID_REV2 */ + uint16_t vmaddr; +}; + +/** UDMA VMID control configuration */ +struct al_udma_gen_vmid_conf { + /* TX queue configuration */ + struct al_udma_gen_vmid_q_conf tx_q_conf[DMA_MAX_Q]; + + /* RX queue configuration */ + struct al_udma_gen_vmid_q_conf rx_q_conf[DMA_MAX_Q]; +}; + +/** UDMA VMID MSIX control configuration */ +struct al_udma_gen_vmid_msix_conf { + /* Enable write to all VMID_n registers in the MSI-X Controller */ + al_bool access_en; + + /* use VMID_n [7:0] from MSI-X Controller for MSI-X message */ + al_bool sel; +}; + +/** UDMA per Tx queue advanced VMID control configuration */ +struct al_udma_gen_vmid_advanced_tx_q_conf { + /********************************************************************** + * Tx Data VMID + **********************************************************************/ + /* Tx data VMID enable */ + al_bool tx_q_data_vmid_en; + + /* + * For Tx data reads, replacement bits for the original address. + * The number of bits replaced is determined according to + * 'tx_q_addr_hi_sel' + */ + unsigned int tx_q_addr_hi; + + /* + * For Tx data reads, 6 bits serving the number of bits taken from the + * extra register on account of bits coming from the original address + * field. + * When 'tx_q_addr_hi_sel'=32 all of 'tx_q_addr_hi' will be taken. + * When 'tx_q_addr_hi_sel'=0 none of it will be taken, and when any + * value in between, it will start from the MSB bit and sweep down as + * many bits as needed. For example if 'tx_q_addr_hi_sel'=8, the final + * address [63:56] will carry 'tx_q_addr_hi'[31:24] while [55:32] will + * carry the original buffer address[55:32]. + */ + unsigned int tx_q_addr_hi_sel; + + /* + * Tx data read VMID + * Masked per bit with 'tx_q_data_vmid_mask' + */ + unsigned int tx_q_data_vmid; + + /* + * Tx data read VMID mask + * Each '1' selects from the buffer address, each '0' selects from + * 'tx_q_data_vmid' + */ + unsigned int tx_q_data_vmid_mask; + + /********************************************************************** + * Tx prefetch VMID + **********************************************************************/ + /* Tx prefetch VMID enable */ + al_bool tx_q_prefetch_vmid_en; + + /* Tx prefetch VMID */ + unsigned int tx_q_prefetch_vmid; + + /********************************************************************** + * Tx completion VMID + **********************************************************************/ + /* Tx completion VMID enable */ + al_bool tx_q_compl_vmid_en; + + /* Tx completion VMID */ + unsigned int tx_q_compl_vmid; +}; + +/** UDMA per Rx queue advanced VMID control configuration */ +struct al_udma_gen_vmid_advanced_rx_q_conf { + /********************************************************************** + * Rx Data VMID + **********************************************************************/ + /* Rx data VMID enable */ + al_bool rx_q_data_vmid_en; + + /* + * For Rx data writes, replacement bits for the original address. + * The number of bits replaced is determined according to + * 'rx_q_addr_hi_sel' + */ + unsigned int rx_q_addr_hi; + + /* + * For Rx data writes, 6 bits serving the number of bits taken from the + * extra register on account of bits coming from the original address + * field. + */ + unsigned int rx_q_addr_hi_sel; + + /* + * Rx data write VMID + * Masked per bit with 'rx_q_data_vmid_mask' + */ + unsigned int rx_q_data_vmid; + + /* Rx data write VMID mask */ + unsigned int rx_q_data_vmid_mask; + + /********************************************************************** + * Rx Data Buffer 2 VMID + **********************************************************************/ + /* Rx data buff2 VMID enable */ + al_bool rx_q_data_buff2_vmid_en; + + /* + * For Rx data buff2 writes, replacement bits for the original address. + * The number of bits replaced is determined according to + * 'rx_q_data_buff2_addr_hi_sel' + */ + unsigned int rx_q_data_buff2_addr_hi; + + /* + * For Rx data buff2 writes, 6 bits serving the number of bits taken + * from the extra register on account of bits coming from the original + * address field. + */ + unsigned int rx_q_data_buff2_addr_hi_sel; + + /* + * Rx data buff2 write VMID + * Masked per bit with 'rx_q_data_buff2_mask' + */ + unsigned int rx_q_data_buff2_vmid; + + /* Rx data buff2 write VMID mask */ + unsigned int rx_q_data_buff2_mask; + + /********************************************************************** + * Rx DDP VMID + **********************************************************************/ + /* Rx DDP write VMID enable */ + al_bool rx_q_ddp_vmid_en; + + /* + * For Rx DDP writes, replacement bits for the original address. + * The number of bits replaced is determined according to + * 'rx_q_ddp_addr_hi_sel' + */ + unsigned int rx_q_ddp_addr_hi; + + /* + * For Rx DDP writes, 6 bits serving the number of bits taken from the + * extra register on account of bits coming from the original address + * field. + */ + unsigned int rx_q_ddp_addr_hi_sel; + + /* + * Rx DDP write VMID + * Masked per bit with 'rx_q_ddp_mask' + */ + unsigned int rx_q_ddp_vmid; + + /* Rx DDP write VMID mask */ + unsigned int rx_q_ddp_mask; + + /********************************************************************** + * Rx prefetch VMID + **********************************************************************/ + /* Rx prefetch VMID enable */ + al_bool rx_q_prefetch_vmid_en; + + /* Rx prefetch VMID */ + unsigned int rx_q_prefetch_vmid; + + /********************************************************************** + * Rx completion VMID + **********************************************************************/ + /* Rx completion VMID enable */ + al_bool rx_q_compl_vmid_en; + + /* Rx completion VMID */ + unsigned int rx_q_compl_vmid; +}; + +/** + * Header split, buffer 2 per queue configuration + * When header split is enabled, Buffer_2 is used as an address for the header + * data. Buffer_2 is defined as 32-bits in the RX descriptor and it is defined + * that the MSB ([63:32]) of Buffer_1 is used as address [63:32] for the header + * address. + */ +struct al_udma_gen_hdr_split_buff2_q_conf { + /* + * MSB of the 64-bit address (bits [63:32]) that can be used for header + * split for this queue + */ + unsigned int addr_msb; + + /* + * Determine how to select the MSB (bits [63:32]) of the address when + * header split is enabled (4 bits, one per byte) + * - Bits [3:0]: + * [0] – selector for bits [39:32] + * [1] – selector for bits [47:40] + * [2] – selector for bits [55:48] + * [3] – selector for bits [63:55] + * - Bit value: + * 0 – Use Buffer_1 (legacy operation) + * 1 – Use the queue configuration 'addr_msb' + */ + unsigned int add_msb_sel; +}; + +/* Report Error - to be used for abort */ +void al_udma_err_report(struct al_udma *udma); + +/* Statistics - TBD */ +void al_udma_stats_get(struct al_udma *udma); + +/* Misc configurations */ +/* Configure AXI configuration */ +int al_udma_axi_set(struct udma_gen_axi *axi_regs, + struct al_udma_axi_conf *axi); + +/* Configure UDMA AXI M2S configuration */ +int al_udma_m2s_axi_set(struct al_udma *udma, + struct al_udma_m2s_axi_conf *axi_m2s); + +/* Configure UDMA AXI S2M configuration */ +int al_udma_s2m_axi_set(struct al_udma *udma, + struct al_udma_s2m_axi_conf *axi_s2m); + +/* Configure M2S packet len */ +int al_udma_m2s_packet_size_cfg_set(struct al_udma *udma, + struct al_udma_m2s_pkt_len_conf *conf); + +/* Configure M2S UDMA descriptor prefetch */ +int al_udma_m2s_pref_set(struct al_udma *udma, + struct al_udma_m2s_desc_pref_conf *conf); +int al_udma_m2s_pref_get(struct al_udma *udma, + struct al_udma_m2s_desc_pref_conf *conf); + +/* set m2s packet's max descriptors (including meta descriptors) */ +#define AL_UDMA_M2S_MAX_ALLOWED_DESCS_PER_PACKET 31 +int al_udma_m2s_max_descs_set(struct al_udma *udma, uint8_t max_descs); + +/* set s2m packets' max descriptors */ +#define AL_UDMA_S2M_MAX_ALLOWED_DESCS_PER_PACKET 31 +int al_udma_s2m_max_descs_set(struct al_udma *udma, uint8_t max_descs); + + +/* Configure S2M UDMA descriptor prefetch */ +int al_udma_s2m_pref_set(struct al_udma *udma, + struct al_udma_s2m_desc_pref_conf *conf); +int al_udma_m2s_pref_get(struct al_udma *udma, + struct al_udma_m2s_desc_pref_conf *conf); + +/* Configure S2M UDMA data write */ +int al_udma_s2m_data_write_set(struct al_udma *udma, + struct al_udma_s2m_data_write_conf *conf); + +/* Configure the s2m full line write feature */ +int al_udma_s2m_full_line_write_set(struct al_udma *umda, al_bool enable); + +/* Configure S2M UDMA completion */ +int al_udma_s2m_completion_set(struct al_udma *udma, + struct al_udma_s2m_completion_conf *conf); + +/* Configure the M2S UDMA scheduling mode */ +int al_udma_m2s_sc_set(struct al_udma *udma, + struct al_udma_m2s_dwrr_conf *sched); + +/* Configure the M2S UDMA rate limitation */ +int al_udma_m2s_rlimit_set(struct al_udma *udma, + struct al_udma_m2s_rlimit_mode *mode); +int al_udma_m2s_rlimit_reset(struct al_udma *udma); + +/* Configure the M2S Stream rate limitation */ +int al_udma_m2s_strm_rlimit_set(struct al_udma *udma, + struct al_udma_m2s_rlimit_cfg *conf); +int al_udma_m2s_strm_rlimit_act(struct al_udma *udma, + enum al_udma_m2s_rlimit_action act); + +/* Configure the M2S UDMA Q rate limitation */ +int al_udma_m2s_q_rlimit_set(struct al_udma_q *udma_q, + struct al_udma_m2s_rlimit_cfg *conf); +int al_udma_m2s_q_rlimit_act(struct al_udma_q *udma_q, + enum al_udma_m2s_rlimit_action act); + +/* Configure the M2S UDMA Q scheduling mode */ +int al_udma_m2s_q_sc_set(struct al_udma_q *udma_q, + struct al_udma_m2s_q_dwrr_conf *conf); +int al_udma_m2s_q_sc_pause(struct al_udma_q *udma_q, al_bool set); +int al_udma_m2s_q_sc_reset(struct al_udma_q *udma_q); + +/* M2S UDMA completion and application timeouts */ +int al_udma_m2s_comp_timeouts_set(struct al_udma *udma, + struct al_udma_m2s_comp_timeouts *conf); +int al_udma_m2s_comp_timeouts_get(struct al_udma *udma, + struct al_udma_m2s_comp_timeouts *conf); + +/* UDMA get revision */ +static INLINE unsigned int al_udma_get_revision(struct unit_regs __iomem *unit_regs) +{ + return (al_reg_read32(&unit_regs->gen.dma_misc.revision) + & UDMA_GEN_DMA_MISC_REVISION_PROGRAMMING_ID_MASK) >> + UDMA_GEN_DMA_MISC_REVISION_PROGRAMMING_ID_SHIFT; +} + +/** + * S2M UDMA Configure the expected behavior of Rx/S2M UDMA when there are no Rx Descriptors. + * + * @param udma + * @param drop_packet when set to true, the UDMA will drop packet. + * @param gen_interrupt when set to true, the UDMA will generate + * no_desc_hint interrupt when a packet received and the UDMA + * doesn't find enough free descriptors for it. + * @param wait_for_desc_timeout timeout in SB cycles to wait for new + * descriptors before dropping the packets. + * Notes: + * - The hint interrupt is raised immediately without waiting + * for new descs. + * - value 0 means wait for ever. + * + * Notes: + * - When get_interrupt is set, the API won't program the iofic to unmask this + * interrupt, in this case the callee should take care for doing that unmask + * using the al_udma_iofic_config() API. + * + * - The hardware's default configuration is: no drop packet, generate hint + * interrupt. + * - This API must be called once and before enabling the UDMA + * + * @return 0 if no error found. + */ +int al_udma_s2m_no_desc_cfg_set(struct al_udma *udma, al_bool drop_packet, al_bool gen_interrupt, uint32_t wait_for_desc_timeout); + +/** + * S2M UDMA configure a queue's completion update + * + * @param q_udma + * @param enable set to true to enable completion update + * + * completion update better be disabled for tx queues as those descriptors + * doesn't carry useful information, thus disabling it saves DMA accesses. + * + * @return 0 if no error found. + */ +int al_udma_s2m_q_compl_updade_config(struct al_udma_q *udma_q, al_bool enable); + +/** + * S2M UDMA configure a queue's completion descriptors coalescing + * + * @param q_udma + * @param enable set to true to enable completion coalescing + * @param coal_timeout in South Bridge cycles. + * + * @return 0 if no error found. + */ +int al_udma_s2m_q_compl_coal_config(struct al_udma_q *udma_q, al_bool enable, uint32_t coal_timeout); + +/** + * S2M UDMA configure completion descriptors write burst parameters + * + * @param udma + * @param burst_size completion descriptors write burst size in bytes. + * + * @return 0 if no error found. + */int al_udma_s2m_compl_desc_burst_config(struct al_udma *udma, uint16_t + burst_size); + +/** + * S2M UDMA configure a queue's completion header split + * + * @param q_udma + * @param enable set to true to enable completion header split + * @param force_hdr_split the header split length will be taken from the queue configuration + * @param hdr_len header split length. + * + * @return 0 if no error found. + */ +int al_udma_s2m_q_compl_hdr_split_config(struct al_udma_q *udma_q, + al_bool enable, + al_bool force_hdr_split, + uint32_t hdr_len); + +/* S2M UDMA per queue completion configuration */ +int al_udma_s2m_q_comp_set(struct al_udma_q *udma_q, + struct al_udma_s2m_q_comp_conf *conf); + +/** UDMA VMID control configuration */ +void al_udma_gen_vmid_conf_set( + struct unit_regs __iomem *unit_regs, + struct al_udma_gen_vmid_conf *conf); + +/** UDMA VMID MSIX control configuration */ +void al_udma_gen_vmid_msix_conf_set( + struct unit_regs __iomem *unit_regs, + struct al_udma_gen_vmid_msix_conf *conf); + +/** UDMA VMID control advanced Tx queue configuration */ +void al_udma_gen_vmid_advanced_tx_q_conf( + struct al_udma_q *q, + struct al_udma_gen_vmid_advanced_tx_q_conf *conf); + +/** UDMA VMID control advanced Rx queue configuration */ +void al_udma_gen_vmid_advanced_rx_q_conf( + struct al_udma_q *q, + struct al_udma_gen_vmid_advanced_rx_q_conf *conf); + +/** UDMA header split buffer 2 Rx queue configuration */ +void al_udma_gen_hdr_split_buff2_rx_q_conf( + struct al_udma_q *q, + struct al_udma_gen_hdr_split_buff2_q_conf *conf); + +/* *INDENT-OFF* */ +#ifdef __cplusplus +} +#endif +/* *INDENT-ON* */ +/** @} end of UDMA config group */ +#endif /* __AL_HAL_UDMA_CONFIG_H__ */ diff --git a/al_hal_udma_debug.c b/al_hal_udma_debug.c new file mode 100644 index 00000000000..c6b9bf4b9bf --- /dev/null +++ b/al_hal_udma_debug.c @@ -0,0 +1,497 @@ +/*- +******************************************************************************* +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_udma_debug.c + * + * @brief Universal DMA HAL driver for debug + * + */ + +#define DEBUG + +#include +#include +#include + +static void al_udma_regs_m2s_axi_print(struct al_udma *udma) +{ + al_dbg("M2S AXI regs:\n"); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, axi_m2s, comp_wr_cfg_1); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, axi_m2s, comp_wr_cfg_2); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, axi_m2s, data_rd_cfg_1); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, axi_m2s, data_rd_cfg_2); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, axi_m2s, desc_rd_cfg_1); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, axi_m2s, desc_rd_cfg_2); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, axi_m2s, data_rd_cfg); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, axi_m2s, desc_rd_cfg_3); + + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, axi_m2s, desc_wr_cfg_1); + AL_UDMA_PRINT_REG_FIELD(udma, " ", "\n", "%d", m2s, axi_m2s, + desc_wr_cfg_1, + max_axi_beats, + UDMA_AXI_M2S_DESC_WR_CFG_1_MAX_AXI_BEATS); + AL_UDMA_PRINT_REG_FIELD(udma, " ", "\n", "%d", m2s, axi_m2s, + desc_wr_cfg_1, + min_axi_beats, + UDMA_AXI_M2S_DESC_WR_CFG_1_MIN_AXI_BEATS); + + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, axi_m2s, ostand_cfg); +} + +static void al_udma_regs_m2s_general_print(struct al_udma *udma) +{ + al_dbg("M2S general regs:\n"); + + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s, state); + AL_UDMA_PRINT_REG_FIELD(udma, " ", "\n", "%d", m2s, m2s, state, + comp_ctrl, + UDMA_M2S_STATE_COMP_CTRL); + AL_UDMA_PRINT_REG_FIELD(udma, " ", "\n", "%d", m2s, m2s, state, + stream_if, + UDMA_M2S_STATE_STREAM_IF); + AL_UDMA_PRINT_REG_FIELD(udma, " ", "\n", "%d", m2s, m2s, state, + rd_ctrl, + UDMA_M2S_STATE_DATA_RD_CTRL); + AL_UDMA_PRINT_REG_FIELD(udma, " ", "\n", "%d", m2s, m2s, state, + desc_pref, + UDMA_M2S_STATE_DESC_PREF); + + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s, err_log_mask); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s, log_0); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s, log_1); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s, log_2); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s, log_3); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s, data_fifo_status); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s, header_fifo_status); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s, unack_fifo_status); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s, check_en); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s, fifo_en); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s, cfg_len); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s, stream_cfg); +} + +static void al_udma_regs_m2s_rd_print(struct al_udma *udma) +{ + al_dbg("M2S read regs:\n"); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_rd, desc_pref_cfg_1); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_rd, desc_pref_cfg_2); + + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_rd, desc_pref_cfg_3); + AL_UDMA_PRINT_REG_FIELD(udma, " ", "\n", "%d", m2s, m2s_rd, + desc_pref_cfg_3, + min_burst_below_thr, + UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR); + AL_UDMA_PRINT_REG_FIELD(udma, " ", "\n", "%d", m2s, m2s_rd, + desc_pref_cfg_3, + min_burst_above_thr, + UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR); + AL_UDMA_PRINT_REG_FIELD(udma, " ", "\n", "%d", m2s, m2s_rd, + desc_pref_cfg_3, + pref_thr, + UDMA_M2S_RD_DESC_PREF_CFG_3_PREF_THR); + + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_rd, data_cfg); +} + +static void al_udma_regs_m2s_dwrr_print(struct al_udma *udma) +{ + al_dbg("M2S DWRR regs:\n"); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_dwrr, cfg_sched); +} + +static void al_udma_regs_m2s_rate_limiter_print(struct al_udma *udma) +{ + al_dbg("M2S rate limiter regs:\n"); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_rate_limiter, gen_cfg); +} + +static void al_udma_regs_m2s_stream_rate_limiter_print(struct al_udma *udma) +{ + al_dbg("M2S stream rate limiter regs:\n"); + + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_stream_rate_limiter, + rlimit.cfg_1s); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_stream_rate_limiter, + rlimit.cfg_cycle); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_stream_rate_limiter, + rlimit.cfg_token_size_1); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_stream_rate_limiter, + rlimit.cfg_token_size_2); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_stream_rate_limiter, + rlimit.mask); +} + +static void al_udma_regs_m2s_comp_print(struct al_udma *udma) +{ + al_dbg("M2S completion regs:\n"); + + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_comp, cfg_1c); + + AL_UDMA_PRINT_REG_FIELD(udma, " ", "\n", "%d", m2s, m2s_comp, cfg_1c, + comp_fifo_depth, + UDMA_M2S_COMP_CFG_1C_COMP_FIFO_DEPTH); + AL_UDMA_PRINT_REG_FIELD(udma, " ", "\n", "%d", m2s, m2s_comp, cfg_1c, + unack_fifo_depth, + UDMA_M2S_COMP_CFG_1C_UNACK_FIFO_DEPTH); + AL_UDMA_PRINT_REG_BIT(udma, " ", "\n", m2s, m2s_comp, cfg_1c, + q_promotion, + UDMA_M2S_COMP_CFG_1C_Q_PROMOTION); + AL_UDMA_PRINT_REG_BIT(udma, " ", "\n", m2s, m2s_comp, cfg_1c, + force_rr, + UDMA_M2S_COMP_CFG_1C_FORCE_RR); + AL_UDMA_PRINT_REG_FIELD(udma, " ", "\n", "%d", m2s, m2s_comp, cfg_1c, + q_free_min, + UDMA_M2S_COMP_CFG_1C_Q_FREE_MIN); + + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_comp, cfg_coal); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_comp, cfg_application_ack); +} + +static void al_udma_regs_m2s_stat_print(struct al_udma *udma) +{ + al_dbg("M2S statistics regs:\n"); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_stat, cfg_st); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_stat, tx_pkt); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_stat, tx_bytes_low); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_stat, tx_bytes_high); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_stat, prefed_desc); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_stat, comp_pkt); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_stat, comp_desc); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_stat, ack_pkts); +} + +static void al_udma_regs_m2s_feature_print(struct al_udma *udma) +{ + al_dbg("M2S feature regs:\n"); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_feature, reg_1); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_feature, reg_3); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_feature, reg_4); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_feature, reg_5); +} + +static void al_udma_regs_m2s_q_print(struct al_udma *udma, uint32_t qid) +{ + al_dbg("M2S Q[%d] status regs:\n", qid); + al_reg_write32(&udma->udma_regs->m2s.m2s.indirect_ctrl, qid); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s, sel_pref_fifo_status); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s, sel_comp_fifo_status); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s, sel_rate_limit_status); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s, sel_dwrr_status); + + al_dbg("M2S Q[%d] regs:\n", qid); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], cfg); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], status); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], tdrbp_low); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], tdrbp_high); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], tdrl); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], tdrhp); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], tdrtp); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], tdcp); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], tcrbp_low); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], tcrbp_high); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], tcrhp); + + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], rlimit.cfg_1s); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], rlimit.cfg_cycle); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], + rlimit.cfg_token_size_1); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], + rlimit.cfg_token_size_2); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], rlimit.mask); + + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], dwrr_cfg_1); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], dwrr_cfg_2); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], dwrr_cfg_3); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], comp_cfg); + AL_UDMA_PRINT_REG(udma, " ", "\n", m2s, m2s_q[qid], q_tx_pkt); +} + +static void al_udma_regs_s2m_axi_print(struct al_udma *udma) +{ + al_dbg("S2M AXI regs:\n"); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, axi_s2m, data_wr_cfg_1); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, axi_s2m, data_wr_cfg_2); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, axi_s2m, desc_rd_cfg_4); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, axi_s2m, desc_rd_cfg_5); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, axi_s2m, comp_wr_cfg_1); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, axi_s2m, comp_wr_cfg_2); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, axi_s2m, data_wr_cfg); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, axi_s2m, desc_rd_cfg_3); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, axi_s2m, desc_wr_cfg_1); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, axi_s2m, ostand_cfg_rd); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, axi_s2m, ostand_cfg_wr); +} + +static void al_udma_regs_s2m_general_print(struct al_udma *udma) +{ + al_dbg("S2M general regs:\n"); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m, state); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m, err_log_mask); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m, log_0); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m, log_1); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m, log_2); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m, log_3); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m, s_data_fifo_status); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m, s_header_fifo_status); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m, axi_data_fifo_status); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m, unack_fifo_status); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m, check_en); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m, fifo_en); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m, stream_cfg); +} + +static void al_udma_regs_s2m_rd_print(struct al_udma *udma) +{ + al_dbg("S2M read regs:\n"); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_rd, desc_pref_cfg_1); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_rd, desc_pref_cfg_2); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_rd, desc_pref_cfg_3); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_rd, desc_pref_cfg_4); +} + +static void al_udma_regs_s2m_wr_print(struct al_udma *udma) +{ + al_dbg("S2M write regs:\n"); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_wr, data_cfg_1); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_wr, data_cfg_1); +} + +static void al_udma_regs_s2m_comp_print(struct al_udma *udma) +{ + al_dbg("S2M completion regs:\n"); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_comp, cfg_1c); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_comp, cfg_2c); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_comp, cfg_application_ack); +} + +static void al_udma_regs_s2m_stat_print(struct al_udma *udma) +{ + al_dbg("S2M statistics regs:\n"); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_stat, drop_pkt); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_stat, rx_bytes_low); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_stat, rx_bytes_high); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_stat, prefed_desc); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_stat, comp_pkt); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_stat, comp_desc); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_stat, ack_pkts); +} + +static void al_udma_regs_s2m_feature_print(struct al_udma *udma) +{ + al_dbg("S2M feature regs:\n"); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_feature, reg_1); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_feature, reg_3); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_feature, reg_4); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_feature, reg_5); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_feature, reg_6); +} + +static void al_udma_regs_s2m_q_print(struct al_udma *udma, uint32_t qid) +{ + al_dbg("S2M Q[%d] status regs:\n", qid); + al_reg_write32(&udma->udma_regs->m2s.m2s.indirect_ctrl, qid); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m, sel_pref_fifo_status); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m, sel_comp_fifo_status); + + al_dbg("S2M Q[%d] regs:\n", qid); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_q[qid], cfg); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_q[qid], status); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_q[qid], rdrbp_low); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_q[qid], rdrbp_high); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_q[qid], rdrl); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_q[qid], rdrhp); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_q[qid], rdrtp); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_q[qid], rdcp); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_q[qid], rcrbp_low); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_q[qid], rcrbp_high); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_q[qid], rcrhp); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_q[qid], rcrhp_internal); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_q[qid], comp_cfg); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_q[qid], comp_cfg_2); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_q[qid], pkt_cfg); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_q[qid], qos_cfg); + AL_UDMA_PRINT_REG(udma, " ", "\n", s2m, s2m_q[qid], q_rx_pkt); +} + +void al_udma_regs_print(struct al_udma *udma, unsigned int mask) +{ + uint32_t i; + + if (!udma) + return; + + if (udma->type == UDMA_TX) { + if (mask & AL_UDMA_DEBUG_AXI) + al_udma_regs_m2s_axi_print(udma); + if (mask & AL_UDMA_DEBUG_GENERAL) + al_udma_regs_m2s_general_print(udma); + if (mask & AL_UDMA_DEBUG_READ) + al_udma_regs_m2s_rd_print(udma); + if (mask & AL_UDMA_DEBUG_DWRR) + al_udma_regs_m2s_dwrr_print(udma); + if (mask & AL_UDMA_DEBUG_RATE_LIMITER) + al_udma_regs_m2s_rate_limiter_print(udma); + if (mask & AL_UDMA_DEBUG_STREAM_RATE_LIMITER) + al_udma_regs_m2s_stream_rate_limiter_print(udma); + if (mask & AL_UDMA_DEBUG_COMP) + al_udma_regs_m2s_comp_print(udma); + if (mask & AL_UDMA_DEBUG_STAT) + al_udma_regs_m2s_stat_print(udma); + if (mask & AL_UDMA_DEBUG_FEATURE) + al_udma_regs_m2s_feature_print(udma); + for (i = 0; i < DMA_MAX_Q; i++) { + if (mask & AL_UDMA_DEBUG_QUEUE(i)) + al_udma_regs_m2s_q_print(udma, i); + } + } else { + if (mask & AL_UDMA_DEBUG_AXI) + al_udma_regs_s2m_axi_print(udma); + if (mask & AL_UDMA_DEBUG_GENERAL) + al_udma_regs_s2m_general_print(udma); + if (mask & AL_UDMA_DEBUG_READ) + al_udma_regs_s2m_rd_print(udma); + if (mask & AL_UDMA_DEBUG_WRITE) + al_udma_regs_s2m_wr_print(udma); + if (mask & AL_UDMA_DEBUG_COMP) + al_udma_regs_s2m_comp_print(udma); + if (mask & AL_UDMA_DEBUG_STAT) + al_udma_regs_s2m_stat_print(udma); + if (mask & AL_UDMA_DEBUG_FEATURE) + al_udma_regs_s2m_feature_print(udma); + for (i = 0; i < DMA_MAX_Q; i++) { + if (mask & AL_UDMA_DEBUG_QUEUE(i)) + al_udma_regs_s2m_q_print(udma, i); + } + } +} + +void al_udma_q_struct_print(struct al_udma *udma, uint32_t qid) +{ + struct al_udma_q *queue; + + if (!udma) + return; + + if (qid >= DMA_MAX_Q) + return; + + queue = &udma->udma_q[qid]; + + al_dbg("Q[%d] struct:\n", qid); + al_dbg(" size_mask = 0x%08x\n", (uint32_t)queue->size_mask); + al_dbg(" q_regs = %p\n", queue->q_regs); + al_dbg(" desc_base_ptr = %p\n", queue->desc_base_ptr); + al_dbg(" next_desc_idx = %d\n", (uint16_t)queue->next_desc_idx); + al_dbg(" desc_ring_id = %d\n", (uint32_t)queue->desc_ring_id); + al_dbg(" cdesc_base_ptr = %p\n", queue->cdesc_base_ptr); + al_dbg(" cdesc_size = %d\n", (uint32_t)queue->cdesc_size); + al_dbg(" next_cdesc_idx = %d\n", (uint16_t)queue->next_cdesc_idx); + al_dbg(" end_cdesc_ptr = %p\n", queue->end_cdesc_ptr); + al_dbg(" comp_head_idx = %d\n", (uint16_t)queue->comp_head_idx); + al_dbg(" comp_head_ptr = %p\n", queue->comp_head_ptr); + al_dbg(" pkt_crnt_descs = %d\n", (uint32_t)queue->pkt_crnt_descs); + al_dbg(" comp_ring_id = %d\n", (uint32_t)queue->comp_ring_id); + al_dbg(" desc_phy_base = 0x%016llx\n", (uint64_t)queue->desc_phy_base); + al_dbg(" cdesc_phy_base = 0x%016llx\n", + (uint64_t)queue->cdesc_phy_base); + al_dbg(" flags = 0x%08x\n", (uint32_t)queue->flags); + al_dbg(" size = %d\n", (uint32_t)queue->size); + al_dbg(" status = %d\n", (uint32_t)queue->status); + al_dbg(" udma = %p\n", queue->udma); + al_dbg(" qid = %d\n", (uint32_t)queue->qid); +} + +void al_udma_ring_print(struct al_udma *udma, uint32_t qid, + enum al_udma_ring_type rtype) +{ + struct al_udma_q *queue; + uint32_t desc_size; + void *base_ptr; + uint32_t i; + + if (!udma) + return; + + if (qid >= DMA_MAX_Q) + return; + + queue = &udma->udma_q[qid]; + if (rtype == AL_RING_SUBMISSION) { + base_ptr = queue->desc_base_ptr; + desc_size = sizeof(union al_udma_desc); + if (base_ptr) + al_dbg("Q[%d] submission ring pointers:\n", qid); + else { + al_dbg("Q[%d] submission ring is not allocated\n", qid); + return; + } + } else { + base_ptr = queue->cdesc_base_ptr; + desc_size = queue->cdesc_size; + if (base_ptr) + al_dbg("Q[%d] completion ring pointers:\n", qid); + else { + al_dbg("Q[%d] completion ring is not allocated\n", qid); + return; + } + } + + for (i = 0; i < queue->size; i++) { + uint32_t *curr_addr = (void*)((uint32_t)base_ptr + i * desc_size); + if (desc_size == 16) + al_dbg("[%04d](%p): %08x %08x %08x %08x\n", + i, + curr_addr, + (uint32_t)*curr_addr, + (uint32_t)*(curr_addr+1), + (uint32_t)*(curr_addr+2), + (uint32_t)*(curr_addr+3)); + else if (desc_size == 8) + al_dbg("[%04d](%p): %08x %08x\n", + i, + curr_addr, + (uint32_t)*curr_addr, + (uint32_t)*(curr_addr+1)); + else if (desc_size == 4) + al_dbg("[%04d](%p): %08x\n", + i, + curr_addr, + (uint32_t)*curr_addr); + else + break; + } +} diff --git a/al_hal_udma_debug.h b/al_hal_udma_debug.h new file mode 100644 index 00000000000..7bd1d972917 --- /dev/null +++ b/al_hal_udma_debug.h @@ -0,0 +1,134 @@ +/*- +******************************************************************************* +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. + +*******************************************************************************/ + +/** + * @defgroup group_udma_debug UDMA Debug + * @ingroup group_udma_api + * UDMA Debug + * @{ + * @file al_hal_udma_debug.h + * + * @brief C Header file for the Universal DMA HAL driver for debug APIs + * + */ + +#ifndef __AL_HAL_UDMA_DEBUG_H__ +#define __AL_HAL_UDMA_DEBUG_H__ + +#include + +/* *INDENT-OFF* */ +#ifdef __cplusplus +extern "C" { +#endif +/* *INDENT-ON* */ + +/* UDMA register print helper macros */ +#define AL_UDMA_PRINT_REG(UDMA, PREFIX, POSTFIX, TYPE, GROUP, REG) \ + al_dbg(PREFIX #REG " = 0x%08x" POSTFIX, al_reg_read32( \ + &(UDMA->udma_regs->TYPE.GROUP.REG))) + +#define AL_UDMA_PRINT_REG_FIELD( \ + UDMA, PREFIX, POSTFIX, FMT, TYPE, GROUP, REG, LBL, FIELD) \ + al_dbg(PREFIX #LBL " = " FMT POSTFIX, al_reg_read32( \ + &(UDMA->udma_regs->TYPE.GROUP.REG)) \ + & FIELD ## _MASK >> FIELD ## _SHIFT) + +#define AL_UDMA_PRINT_REG_BIT( \ + UDMA, PREFIX, POSTFIX, TYPE, GROUP, REG, LBL, FIELD) \ + al_dbg(PREFIX #LBL " = %d" POSTFIX, ((al_reg_read32( \ + &(UDMA->udma_regs->TYPE.GROUP.REG)) \ + & FIELD) != 0)) + +/* UDMA register print mask definitions */ +#define AL_UDMA_DEBUG_QUEUE(n) AL_BIT(n) +#define AL_UDMA_DEBUG_AXI AL_BIT(DMA_MAX_Q) +#define AL_UDMA_DEBUG_GENERAL AL_BIT(DMA_MAX_Q + 1) +#define AL_UDMA_DEBUG_READ AL_BIT(DMA_MAX_Q + 2) +#define AL_UDMA_DEBUG_WRITE AL_BIT(DMA_MAX_Q + 3) +#define AL_UDMA_DEBUG_DWRR AL_BIT(DMA_MAX_Q + 4) +#define AL_UDMA_DEBUG_RATE_LIMITER AL_BIT(DMA_MAX_Q + 5) +#define AL_UDMA_DEBUG_STREAM_RATE_LIMITER AL_BIT(DMA_MAX_Q + 6) +#define AL_UDMA_DEBUG_COMP AL_BIT(DMA_MAX_Q + 7) +#define AL_UDMA_DEBUG_STAT AL_BIT(DMA_MAX_Q + 8) +#define AL_UDMA_DEBUG_FEATURE AL_BIT(DMA_MAX_Q + 9) +#define AL_UDMA_DEBUG_ALL 0xFFFFFFFF + +/* Debug functions */ + +/** + * Print udma registers according to the provided mask + * + * @param udma udma data structure + * @param mask mask that specifies which registers groups to print + * e.g. AL_UDMA_DEBUG_AXI prints AXI registers, AL_UDMA_DEBUG_ALL prints all + * registers + */ +void al_udma_regs_print(struct al_udma *udma, unsigned int mask); + +/** + * Print udma queue software structure + * + * @param udma udma data structure + * @param qid queue index + */ +void al_udma_q_struct_print(struct al_udma *udma, uint32_t qid); + +/** UDMA ring type */ +enum al_udma_ring_type { + AL_RING_SUBMISSION, + AL_RING_COMPLETION +}; + +/** + * Print the ring entries for the specified queue index and ring type + * (submission/completion) + * + * @param udma udma data structure + * @param qid queue index + * @param rtype udma ring type + */ +void al_udma_ring_print(struct al_udma *udma, uint32_t qid, + enum al_udma_ring_type rtype); + + +/* *INDENT-OFF* */ +#ifdef __cplusplus +} +#endif +/* *INDENT-ON* */ +#endif /* __AL_HAL_UDMA_DEBUG_H__ */ +/** @} end of UDMA debug group */ diff --git a/al_hal_udma_iofic.c b/al_hal_udma_iofic.c new file mode 100644 index 00000000000..d6ba485296c --- /dev/null +++ b/al_hal_udma_iofic.c @@ -0,0 +1,151 @@ +/*- +******************************************************************************* +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_udma_iofic.c + * + * @brief unit interrupts configurations + * + */ + +#include "al_hal_udma_iofic.h" +#include "al_hal_udma_regs.h" + +/* + * configure the interrupt registers, interrupts will are kept masked + */ +static int al_udma_main_iofic_config(struct al_iofic_regs __iomem *base, + enum al_iofic_mode mode) +{ + switch (mode) { + case AL_IOFIC_MODE_LEGACY: + al_iofic_config(base, AL_INT_GROUP_A, + INT_CONTROL_GRP_SET_ON_POSEDGE | + INT_CONTROL_GRP_MASK_MSI_X | + INT_CONTROL_GRP_CLEAR_ON_READ); + al_iofic_config(base, AL_INT_GROUP_B, + INT_CONTROL_GRP_CLEAR_ON_READ | + INT_CONTROL_GRP_MASK_MSI_X); + al_iofic_config(base, AL_INT_GROUP_C, + INT_CONTROL_GRP_CLEAR_ON_READ | + INT_CONTROL_GRP_MASK_MSI_X); + al_iofic_config(base, AL_INT_GROUP_D, + INT_CONTROL_GRP_SET_ON_POSEDGE | + INT_CONTROL_GRP_MASK_MSI_X | + INT_CONTROL_GRP_CLEAR_ON_READ); + break; + case AL_IOFIC_MODE_MSIX_PER_Q: + al_iofic_config(base, AL_INT_GROUP_A, + INT_CONTROL_GRP_SET_ON_POSEDGE | + INT_CONTROL_GRP_AUTO_MASK | + INT_CONTROL_GRP_AUTO_CLEAR); + al_iofic_config(base, AL_INT_GROUP_B, + INT_CONTROL_GRP_AUTO_CLEAR | + INT_CONTROL_GRP_AUTO_MASK | + INT_CONTROL_GRP_CLEAR_ON_READ); + al_iofic_config(base, AL_INT_GROUP_C, + INT_CONTROL_GRP_AUTO_CLEAR | + INT_CONTROL_GRP_AUTO_MASK | + INT_CONTROL_GRP_CLEAR_ON_READ); + al_iofic_config(base, AL_INT_GROUP_D, + INT_CONTROL_GRP_SET_ON_POSEDGE | + INT_CONTROL_GRP_CLEAR_ON_READ | + INT_CONTROL_GRP_MASK_MSI_X); + break; + case AL_IOFIC_MODE_MSIX_PER_GROUP: + al_iofic_config(base, AL_INT_GROUP_A, + INT_CONTROL_GRP_SET_ON_POSEDGE | + INT_CONTROL_GRP_AUTO_CLEAR | + INT_CONTROL_GRP_AUTO_MASK); + al_iofic_config(base, AL_INT_GROUP_B, + INT_CONTROL_GRP_CLEAR_ON_READ | + INT_CONTROL_GRP_MASK_MSI_X); + al_iofic_config(base, AL_INT_GROUP_C, + INT_CONTROL_GRP_CLEAR_ON_READ | + INT_CONTROL_GRP_MASK_MSI_X); + al_iofic_config(base, AL_INT_GROUP_D, + INT_CONTROL_GRP_SET_ON_POSEDGE | + INT_CONTROL_GRP_CLEAR_ON_READ | + INT_CONTROL_GRP_MASK_MSI_X); + break; + default: + al_err("%s: invalid mode (%d)\n", __func__, mode); + return -EINVAL; + } + + al_dbg("%s: base.%p mode %d\n", __func__, base, mode); + return 0; +} + +/* + * configure the UDMA interrupt registers, interrupts are kept masked + */ +int al_udma_iofic_config(struct unit_regs __iomem *regs, enum al_iofic_mode mode, + uint32_t m2s_errors_disable, + uint32_t m2s_aborts_disable, + uint32_t s2m_errors_disable, + uint32_t s2m_aborts_disable) +{ + int rc; + + rc = al_udma_main_iofic_config(®s->gen.interrupt_regs.main_iofic, mode); + if (rc != 0) + return rc; + + al_iofic_unmask(®s->gen.interrupt_regs.secondary_iofic_ctrl, AL_INT_GROUP_A, ~m2s_errors_disable); + al_iofic_abort_mask(®s->gen.interrupt_regs.secondary_iofic_ctrl, AL_INT_GROUP_A, m2s_aborts_disable); + + al_iofic_unmask(®s->gen.interrupt_regs.secondary_iofic_ctrl, AL_INT_GROUP_B, ~s2m_errors_disable); + al_iofic_abort_mask(®s->gen.interrupt_regs.secondary_iofic_ctrl, AL_INT_GROUP_B, s2m_aborts_disable); + + al_dbg("%s base.%p mode %d\n", __func__, regs, mode); + return 0; +} + +/* + * return the offset of the unmask register for a given group + */ +uint32_t __iomem * al_udma_iofic_unmask_offset_get( + struct unit_regs __iomem *regs, + enum al_udma_iofic_level level, + int group) +{ + al_assert(al_udma_iofic_level_and_group_valid(level, group)); + return al_iofic_unmask_offset_get(al_udma_iofic_reg_base_get(regs, level), group); +} + +/** @} end of UDMA group */ diff --git a/al_hal_udma_iofic.h b/al_hal_udma_iofic.h new file mode 100644 index 00000000000..9e795004837 --- /dev/null +++ b/al_hal_udma_iofic.h @@ -0,0 +1,614 @@ +/*- +******************************************************************************* +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. + +*******************************************************************************/ + +/** + * @defgroup group_udma_interrupts UDMA I/O Fabric Interrupt Controller + * @ingroup group_udma_api + * UDMA IOFIC API + * @{ + * @file al_hal_udma_iofic.h + * + * @brief C Header file for programming the interrupt controller that found + * in UDMA based units. These APIs rely and use some the Interrupt controller + * API under al_hal_iofic.h + */ + +#ifndef __AL_HAL_UDMA_IOFIC_H__ +#define __AL_HAL_UDMA_IOFIC_H__ + +#include +#include +#include + +/* *INDENT-OFF* */ +#ifdef __cplusplus +extern "C" { +#endif +/* *INDENT-ON* */ + +/** + * Interrupt Mode + * This is the interrupt mode for the primary interrupt level The secondary + * interrupt level does not have mode and it is always a level sensitive + * interrupt that is reflected in group D of the primary. + */ +enum al_iofic_mode { + AL_IOFIC_MODE_LEGACY, /**< level-sensitive interrupt wire */ + AL_IOFIC_MODE_MSIX_PER_Q, /**< per UDMA queue MSI-X interrupt */ + AL_IOFIC_MODE_MSIX_PER_GROUP +}; + +/** interrupt controller level (primary/secondary) */ +enum al_udma_iofic_level { + AL_UDMA_IOFIC_LEVEL_PRIMARY, + AL_UDMA_IOFIC_LEVEL_SECONDARY +}; + +/* + * The next four groups represents the standard 4 groups in the primary + * interrupt controller of each bus-master unit in the I/O Fabric. + * The first two groups can be used when accessing the secondary interrupt + * controller as well. + */ +#define AL_INT_GROUP_A 0 /**< summary of the below events */ +#define AL_INT_GROUP_B 1 /**< RX completion queues */ +#define AL_INT_GROUP_C 2 /**< TX completion queues */ +#define AL_INT_GROUP_D 3 /**< Misc */ + +/******************************************************************************* + * Primary interrupt controller, group A bits + ******************************************************************************/ +/* Group A bits which are just summary bits of GROUP B, C and D */ +#define AL_INT_GROUP_A_GROUP_B_SUM AL_BIT(0) +#define AL_INT_GROUP_A_GROUP_C_SUM AL_BIT(1) +#define AL_INT_GROUP_A_GROUP_D_SUM AL_BIT(2) + +/******************************************************************************* + * MSIX entry indices + ******************************************************************************/ +/** MSIX entry index for summary of group D in group A */ +#define AL_INT_MSIX_GROUP_A_SUM_D_IDX 2 +/** MSIX entry index for RX completion queue 0 */ +#define AL_INT_MSIX_RX_COMPLETION_START 3 + +/******************************************************************************* + * Primary interrupt controller, group D bits + ******************************************************************************/ +#define AL_INT_GROUP_D_CROSS_MAIL_BOXES \ + (AL_BIT(0) | AL_BIT(1) | AL_BIT(2) | AL_BIT(3)) +/** Summary of secondary interrupt controller, group A) */ +#define AL_INT_GROUP_D_M2S AL_BIT(8) +/** Summary of secondary interrupt controller, group B) */ +#define AL_INT_GROUP_D_S2M AL_BIT(9) +#define AL_INT_GROUP_D_SW_TIMER_INT AL_BIT(10) +#define AL_INT_GROUP_D_APP_EXT_INT AL_BIT(11) +#define AL_INT_GROUP_D_ALL \ + AL_INT_GROUP_D_CROSS_MAIL_BOXES | \ + AL_INT_GROUP_D_M2S | \ + AL_INT_GROUP_D_S2M | \ + AL_INT_GROUP_D_SW_TIMER_INT | \ + AL_INT_GROUP_D_APP_EXT_INT + +/* + * Until this point, all description above is for Groups A/B/C/D in the PRIMARY + * Interrupt controller. + * Following are definitions related to the secondary interrupt controller with + * two cause registers (group A and group B) that covers UDMA M2S/S2M errors. + * Secondary interrupt controller summary bits are not mapped to the Processor + * GIC directly, rather they are represented in Group D of the primary interrupt + * controller. + */ + +/****************************************************************************** + * Secondary interrupt Controller, Group A, which holds the TX (M2S) error + * interrupt bits + ******************************************************************************/ + +/** + * MSIx response + * MSIX Bus generator response error, the Bus response received with error indication + */ +#define AL_INT_2ND_GROUP_A_M2S_MSIX_RESP AL_BIT(27) +/** + * MSIx timeout MSIX Bus generator timeout error. + * The generator didn't receive bus response for the MSIx write transaction. + */ +#define AL_INT_2ND_GROUP_A_M2S_MSIX_TO AL_BIT(26) +/** Prefetch header buffer parity error */ +#define AL_INT_2ND_GROUP_A_M2S_PREFETCH_HDR_PARITY AL_BIT(25) +/** Prefetch descriptor buffer parity error */ +#define AL_INT_2ND_GROUP_A_M2S_PREFETCH_DESC_PARITY AL_BIT(24) +/** Data buffer parity error */ +#define AL_INT_2ND_GROUP_A_M2S_DATA_PARITY AL_BIT(23) +/** Data header buffer parity error */ +#define AL_INT_2ND_GROUP_A_M2S_HDR_PARITY AL_BIT(22) +/** Completion coalescing buffer parity error */ +#define AL_INT_2ND_GROUP_A_M2S_COMPL_COAL_PARITY AL_BIT(21) +/** UNACK packets buffer parity error */ +#define AL_INT_2ND_GROUP_A_M2S_UNACK_PKT_PARITY AL_BIT(20) +/** ACK packets buffer parity error */ +#define AL_INT_2ND_GROUP_A_M2S_ACK_PKT_PARITY AL_BIT(19) +/** AXI data buffer parity error */ +#define AL_INT_2ND_GROUP_A_M2S_AX_DATA_PARITY AL_BIT(18) +/** + * Prefetch Ring ID error + * A wrong RingId was received while prefetching submission descriptor. This + * could indicate a software bug or hardware failure, unless the UDMA is + * working in a mode to ignore RingId (the al_udma_iofic_config() API can be + * used to configure the UDMA to ignore the Ring ID check) + */ +#define AL_INT_2ND_GROUP_A_M2S_PREFETCH_RING_ID AL_BIT(17) +/** + * Prefetch last + * Error in last bit indication of the descriptor + * Descriptor with Last bit asserted is read from the queue to the prefetch + * FIFO when the prefetch engine is not in a middle of packet processing (a + * descriptor with First bit asserted should be read first to indicate start of + * packet) + */ +#define AL_INT_2ND_GROUP_A_M2S_PREFETCH_LAST AL_BIT(16) +/** + * Prefetch first + * Error in first bit indication of the descriptor + * Descriptor with First bit asserted is read from the queue to the prefetch + * FIFO while the prefetch engine is in a middle of packet processing ( a + * descriptor with Last bit asserted should be read to indicate end of packet + * before starting a new one) + */ +#define AL_INT_2ND_GROUP_A_M2S_PREFETCH_FIRST AL_BIT(15) +/** + * Prefetch max descriptors + * Number of descriptors per packet exceeds the configurable maximum + * descriptors per packet. This could indicate a software bug or a hardware + * failure. (The al_udma_m2s_max_descs_set() API is used to configure the + * maximum descriptors per packet) + */ +#define AL_INT_2ND_GROUP_A_M2S_PREFETCH_MAX_DESC AL_BIT(14) +/** + * Packet length + * Packet length exceeds the configurable maximum packet size. The + * al_udma_m2s_packet_size_cfg_set() API is used to configure the maximum + * packet size) + */ +#define AL_INT_2ND_GROUP_A_M2S_PKT_LEN AL_BIT(13) +/** + * Prefetch AXI timeout + * Bus request to I/O Fabric timeout error + */ +#define AL_INT_2ND_GROUP_A_M2S_PREFETCH_AXI_TO AL_BIT(12) +/** + * Prefetch AXI response + * Bus response from I/O Fabric error + */ +#define AL_INT_2ND_GROUP_A_M2S_PREFETCH_AXI_RESP AL_BIT(11) +/** + * Prefetch AXI parity + * Bus parity error on descriptor being prefetched + */ +#define AL_INT_2ND_GROUP_A_M2S_PREFETCH_AXI_PARITY AL_BIT(10) +/** + * Data AXI timeout + * Bus request to I/O Fabric timeout error + */ +#define AL_INT_2ND_GROUP_A_M2S_DATA_AXI_TO AL_BIT(9) +/** + * Data AXI response + * Bus response from I/O Fabric error + */ +#define AL_INT_2ND_GROUP_A_M2S_DATA_AXI_RESP AL_BIT(8) +/** + * Data AXI parity + * Bus parity error on data being read + */ +#define AL_INT_2ND_GROUP_A_M2S_DATA_AXI_PARITY AL_BIT(7) +/** + * Completion AXI timeout + * Bus request to I/O Fabric timeout error + */ +#define AL_INT_2ND_GROUP_A_M2S_CONPL_AXI_TO AL_BIT(6) +/** + * Completion AXI response + * Bus response from I/O Fabric error + */ +#define AL_INT_2ND_GROUP_A_M2S_COMPL_AXI_RESP AL_BIT(5) +/** + * Completion AXI parity + * Bus generator internal SRAM parity error + */ +#define AL_INT_2ND_GROUP_A_M2S_COMP_AXI_PARITY AL_BIT(4) +/** + * Stream timeout + * Application stream interface timeout indicating a failure at the Application + * layer (RAID, Ethernet etc) + */ +#define AL_INT_2ND_GROUP_A_M2S_STRM_TO AL_BIT(3) +/** + * Stream response + * Application stream interface response error indicating a failure at the + * Application layer (RAID, Ethernet etc) + */ +#define AL_INT_2ND_GROUP_A_M2S_STRM_RESP AL_BIT(2) +/** + * Stream parity + * Application stream interface parity error indicating a failure at the + * Application layer (RAID, Ethernet etc) + */ +#define AL_INT_2ND_GROUP_A_M2S_STRM_PARITY AL_BIT(1) +/** + * Stream completion mismatch + * Application stream interface, packet serial mismatch error indicating a + * failure at the Application layer (RAID, Ethernet etc) + */ +#define AL_INT_2ND_GROUP_A_M2S_STRM_COMPL_MISMATCH AL_BIT(0) + +/******************************************************************************* + * Secondary interrupt Controller, Group B, which holds the RX (S2M) error + * interrupt bits + ******************************************************************************/ + +/** Prefetch descriptor buffer parity error */ +#define AL_INT_2ND_GROUP_B_S2M_PREFETCH_DESC_PARITY AL_BIT(30) +/** Completion coalescing buffer parity error */ +#define AL_INT_2ND_GROUP_B_S2M_COMPL_COAL_PARITY AL_BIT(29) +/** PRE-UNACK packets buffer parity error */ +#define AL_INT_2ND_GROUP_B_S2M_PRE_UNACK_PKT_PARITY AL_BIT(28) +/** UNACK packets buffer parity error */ +#define AL_INT_2ND_GROUP_B_S2M_UNACK_PKT_PARITY AL_BIT(27) +/** Data buffer parity error */ +#define AL_INT_2ND_GROUP_B_S2M_DATA_PARITY AL_BIT(26) +/** Data header buffer parity error */ +#define AL_INT_2ND_GROUP_B_S2M_DATA_HDR_PARITY AL_BIT(25) +/** + * Packet length + * Application stream interface, Data counter length mismatch with metadata + * packet length indicating a failure at the Application layer (RAID, Ethernet + * etc) + */ +#define AL_INT_2ND_GROUP_B_S2M_PKT_LEN AL_BIT(24) +/** + * Stream last + * Application stream interface, error in Last bit indication, this error is + * asserted when a 'last' indication is asserted on the stream interface + * (between the application and the UDMA) when the interface is not in the + * middle of packet, meaning that there was no 'first' indication before. This + * indicates a failure at the application layer. + */ +#define AL_INT_2ND_GROUP_B_S2M_STRM_LAST AL_BIT(23) +/** + * Stream first + * Application stream interface error in first bit indication, this error is + * asserted when a 'first' indication is asserted on the stream interface + * (between the application and the UDMA) when the interface is in the middle + * of packet, meaning that there was a 'first' indication before and the UDMA + * is waiting for a 'last' indication to end the packet. This indicates a + * failure at the application layer. + */ +#define AL_INT_2ND_GROUP_B_S2M_STRM_FIRST AL_BIT(22) +/** + * Stream data + * Application stream interface, error indication during data transaction + */ +#define AL_INT_2ND_GROUP_B_S2M_STRM_DATA AL_BIT(21) +/** + * Stream Data parity + * Application stream interface, parity error during data transaction + */ +#define AL_INT_2ND_GROUP_B_S2M_STRM_DATA_PARITY AL_BIT(20) +/** + * Stream Header error + * Application stream interface, error indication during header transaction + */ +#define AL_INT_2ND_GROUP_B_S2M_STRM_HDR AL_BIT(19) +/** + * Stream Header parity + * Application stream interface, parity error during header transaction + */ +#define AL_INT_2ND_GROUP_B_S2M_STRM_HDR_PARITY AL_BIT(18) +/** + * Completion UNACK + * Completion write, UNACK timeout due to completion FIFO back pressure + */ +#define AL_INT_2ND_GROUP_B_S2M_COMPL_UNACK AL_BIT(17) +/** + * Completion stream + * Completion write, UNACK timeout due to stream ACK FIFO back pressure + */ +#define AL_INT_2ND_GROUP_B_S2M_COMPL_STRM AL_BIT(16) +/** + * Completion AXI timeout + * Bus request to I/O Fabric timeout error + */ +#define AL_INT_2ND_GROUP_B_S2M_COMPL_AXI_TO AL_BIT(15) +/** + * Completion AXI response + * Bus response from I/O Fabric error + */ +#define AL_INT_2ND_GROUP_B_S2M_COMPL_AXI_RESP AL_BIT(14) +/** + * Completion AXI parity + * Completion Bus generator internal SRAM parity error + */ +#define AL_INT_2ND_GROUP_B_S2M_COMPL_AXI_PARITY AL_BIT(13) +/** + * Prefetch saturate + * Prefetch engine, packet length counter saturated (32 bit) , this is caused + * by an error at the application layer which sends packet data without + * 'last'/'first' indication. + */ +#define AL_INT_2ND_GROUP_B_S2M_PREFETCH_SAT AL_BIT(12) +/** + * Prefetch ring ID + * Prefetch engine, Ring ID is not matching the expected RingID. This could + * indicate a software bug or hardware failure, unless the UDMA is working in a + * mode to ignore RingId (the al_udma_iofic_config() API can be used to + * configure the UDMA to ignore the Ring ID check) + */ +#define AL_INT_2ND_GROUP_B_S2M_PREFETCH_RING_ID AL_BIT(11) +/** + * Prefetch AXI timeout + * Bus request to I/O Fabric timeout error + */ +#define AL_INT_2ND_GROUP_B_S2M_PREFETCH_AXI_TO AL_BIT(10) +/** + * Prefetch AXI response + * Bus response from I/O Fabric error + */ +#define AL_INT_2ND_GROUP_B_S2M_PREFETCH_AXI_RESP AL_BIT(9) +/** + * Prefetch AXI parity + * Bus parity error on descriptor being prefetched + */ +#define AL_INT_2ND_GROUP_B_S2M_PREFETCH_AXI_PARITY AL_BIT(8) +/** + * No descriptors hint + * Data write, Hint to the SW that there are not enough descriptors in the + * queue for the current received packet. This is considered a hint and not an + * error, as it could be a normal situation in certain application. The S2M + * UDMA behavior when it runs out of Rx Descriptor is controlled by driver + * which can use this hint to add more descriptors to the Rx queue. + */ +#define AL_INT_2ND_GROUP_B_S2M_NO_DESC_HINT AL_BIT(7) +/** + * No descriptors timeout + * Data write, Timeout indication when there are not enough descriptors for the + * current packet and the timeout expires. The S2M UDMA behavior when it runs + * out of Rx Descriptor is controlled by driver which can use this hint to add + * more descriptors to the Rx queue. The al_udma_s2m_no_desc_cfg_set() is used + * to configure theUDMA S2M timeout and behavior when there are no Rx + * descriptors for the received packet. + */ +#define AL_INT_2ND_GROUP_B_S2M_NO_DESC_TO AL_BIT(6) +/** + * Promotion indication + * Data write, the data write engine checks the queue number of the two packets + * at the head of the data FIFO, the data write engine notify the prefetch + * engine to promote these queue numbers in the prefetch scheduler to make sure + * that these queue will have RX descriptors for these packets. This error + * indicates that the prefetch promotion didn't work for the second packet in + * the FIFO. This is an indication used for system debug and not an error. + */ +#define AL_INT_2ND_GROUP_B_S2M_PROM_IND AL_BIT(5) +/** + * Header split ignored + * Data write, The application requested header split but the buffer descriptor + * doesn't include a second buffer for the header + */ +#define AL_INT_2ND_GROUP_B_S2M_HDR_SPLT_IGNORED AL_BIT(4) +/** + * Header split length + * Data write, The application requested header split and the length of the + * second buffer allocated for the header is not enough for the requested + * header length. The remaining of the header is written to buffer 1 (data + * buffer). + */ +#define AL_INT_2ND_GROUP_B_S2M_HDR_SPLT_LEN AL_BIT(3) +/** + * Data AXI timeout + * Bus request to I/O Fabric timeout error + */ +#define AL_INT_2ND_GROUP_B_S2M_DATA_AXI_TO AL_BIT(2) +/** + * Data AXI response + * Bus response from I/O Fabric error + */ +#define AL_INT_2ND_GROUP_B_S2M_DATA_AXI_RESP AL_BIT(1) +/** + * Data AXI parity + * Bus parity error on data being read + */ +#define AL_INT_2ND_GROUP_B_S2M_DATA_AXI_PARITY AL_BIT(0) + +/******************************************************************************* + * Configurations + ******************************************************************************/ + +/** + * Configure the UDMA interrupt controller registers, interrupts will are kept + * masked. + * This is a static setting that should be called while initialized the + * interrupt controller within a given UDMA, and should not be modified during + * runtime unless the UDMA is completely disabled. The first argument sets the + * interrupt and MSIX modes. The m2s/s2m errors/abort are a set of bit-wise + * masks to define the behaviour of the UDMA once an error happens: The _abort + * will put the UDMA in abort state once an error happens The _error bitmask + * will indicate and error in the secondary cause register but will not abort. + * The bit-mask that the _errors_disable and _aborts_disable are described in + * 'AL_INT_2ND_GROUP_A_*' and 'AL_INT_2ND_GROUP_B_*' + * + * @param regs pointer to unit registers + * @param mode interrupt scheme mode (legacy, MSI-X..) + * @param m2s_errors_disable + * This is a bit-wise mask, to indicate which one of the error causes in + * secondary interrupt group_A should generate an interrupt. When a bit is + * set, the error cause is ignored. + * Recommended value: 0 (enable all errors). + * @param m2s_aborts_disable + * This is a bit-wise mask, to indicate which one of the error causes in + * secondary interrupt group_A should automatically put the UDMA in + * abort state. When a bit is set, the error cause does cause an abort. + * Recommended value: 0 (enable all aborts). + * @param s2m_errors_disable + * This is a bit-wise mask, to indicate which one of the error causes in + * secondary interrupt group_A should generate an interrupt. When a bit is + * set, the error cause is ignored. + * Recommended value: 0xE0 (disable hint errors). + * @param s2m_aborts_disable + * This is a bit-wise mask, to indicate which one of the error causes in + * secondary interrupt group_A should automatically put the UDMA in + * abort state. When a bit is set, the error cause does cause an abort. + * Recommended value: 0xE0 (disable hint aborts). + * + * @return 0 on success. -EINVAL otherwise. + */ +int al_udma_iofic_config(struct unit_regs __iomem *regs, + enum al_iofic_mode mode, + uint32_t m2s_errors_disable, + uint32_t m2s_aborts_disable, + uint32_t s2m_errors_disable, + uint32_t s2m_aborts_disable); +/** + * return the offset of the unmask register for a given group. + * this function can be used when the upper layer wants to directly + * access the unmask regiter and bypass the al_udma_iofic_unmask() API. + * + * @param regs pointer to udma registers + * @param level the interrupt controller level (primary / secondary) + * @param group the interrupt group ('AL_INT_GROUP_*') + * @return the offset of the unmask register. + */ +uint32_t __iomem * al_udma_iofic_unmask_offset_get( + struct unit_regs __iomem *regs, + enum al_udma_iofic_level level, + int group); + +/** + * Get the interrupt controller base address for either the primary or secondary + * interrupt controller + * + * @param regs pointer to udma unit registers + * @param level the interrupt controller level (primary / secondary) + * + * @returns The interrupt controller base address + * + */ +static INLINE void __iomem *al_udma_iofic_reg_base_get( + struct unit_regs __iomem *regs, + enum al_udma_iofic_level level) +{ + void __iomem *iofic_regs = (level == AL_UDMA_IOFIC_LEVEL_PRIMARY) ? + (void __iomem *)®s->gen.interrupt_regs.main_iofic : + (void __iomem *)®s->gen.interrupt_regs.secondary_iofic_ctrl; + + return iofic_regs; +} + +/** + * Check the interrupt controller level/group validity + * + * @param level the interrupt controller level (primary / secondary) + * @param group the interrupt group ('AL_INT_GROUP_*') + * + * @returns 0 - invalid, 1 - valid + * + */ +static INLINE int al_udma_iofic_level_and_group_valid( + enum al_udma_iofic_level level, + int group) +{ + if (((level == AL_UDMA_IOFIC_LEVEL_PRIMARY) && (group >= 0) && (group < 4)) || + ((level == AL_UDMA_IOFIC_LEVEL_SECONDARY) && (group >= 0) && (group < 2))) + return 1; + + return 0; +} +/** + * unmask specific interrupts for a given group + * this functions uses the interrupt mask clear register to guarantee atomicity + * it's safe to call it while the mask is changed by the HW (auto mask) or another cpu. + * + * @param regs pointer to udma unit registers + * @param level the interrupt controller level (primary / secondary) + * @param group the interrupt group ('AL_INT_GROUP_*') + * @param mask bitwise of interrupts to unmask, set bits will be unmasked. + */ +static INLINE void al_udma_iofic_unmask( + struct unit_regs __iomem *regs, + enum al_udma_iofic_level level, + int group, + uint32_t mask) +{ + al_assert(al_udma_iofic_level_and_group_valid(level, group)); + al_iofic_unmask(al_udma_iofic_reg_base_get(regs, level), group, mask); +} + +/** + * mask specific interrupts for a given group + * this functions modifies interrupt mask register, the callee must make sure + * the mask is not changed by another cpu. + * + * @param regs pointer to udma unit registers + * @param level the interrupt controller level (primary / secondary) + * @param group the interrupt group ('AL_INT_GROUP_*') + * @param mask bitwise of interrupts to mask, set bits will be masked. + */ +static INLINE void al_udma_iofic_mask( + struct unit_regs __iomem *regs, + enum al_udma_iofic_level level, + int group, + uint32_t mask) +{ + al_assert(al_udma_iofic_level_and_group_valid(level, group)); + al_iofic_mask(al_udma_iofic_reg_base_get(regs, level), group, mask); +} + +/** + * read interrupt cause register for a given group + * this will clear the set bits if the Clear on Read mode enabled. + * @param regs pointer to udma unit registers + * @param level the interrupt controller level (primary / secondary) + * @param group the interrupt group ('AL_INT_GROUP_*') + */ +static INLINE uint32_t al_udma_iofic_read_cause( + struct unit_regs __iomem *regs, + enum al_udma_iofic_level level, + int group) +{ + al_assert(al_udma_iofic_level_and_group_valid(level, group)); + return al_iofic_read_cause(al_udma_iofic_reg_base_get(regs, level), group); +} + +#endif +/** @} end of UDMA group */ diff --git a/al_hal_udma_iofic_regs.h b/al_hal_udma_iofic_regs.h new file mode 100644 index 00000000000..8e53aa673cc --- /dev/null +++ b/al_hal_udma_iofic_regs.h @@ -0,0 +1,66 @@ +/*- +******************************************************************************* +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. + +*******************************************************************************/ + + +#ifndef __AL_HAL_UDMA_IOFIC_REG_H +#define __AL_HAL_UDMA_IOFIC_REG_H + +#include "al_hal_iofic_regs.h" +#ifdef __cplusplus +extern "C" { +#endif + +/** This structure covers all interrupt registers of a given UDMA, which is + * built of an al_iofic_regs, which is the common I/O Fabric Interrupt + * controller (IOFIC), and additional two interrupts groups dedicated for the + * application-specific engine attached to the UDMA, the interrupt summary + * of those two groups routed to gourp D of the main controller. + */ +struct udma_iofic_regs { + struct al_iofic_regs main_iofic; + uint32_t rsrvd1[(0x1c00) >> 2]; + struct al_iofic_grp_ctrl secondary_iofic_ctrl[2]; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __AL_HAL_UDMA_IOFIC_REG_H */ + + + + diff --git a/al_hal_udma_main.c b/al_hal_udma_main.c new file mode 100644 index 00000000000..6e9919b3596 --- /dev/null +++ b/al_hal_udma_main.c @@ -0,0 +1,618 @@ +/*- +******************************************************************************* +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_udma_main.c + * + * @brief Universal DMA HAL driver for main functions (initialization, data path) + * + */ + +#include +#include + +#define AL_UDMA_Q_RST_TOUT 10000 /* Queue reset timeout [uSecs] */ + +#define UDMA_STATE_IDLE 0x0 +#define UDMA_STATE_NORMAL 0x1 +#define UDMA_STATE_ABORT 0x2 +#define UDMA_STATE_RESERVED 0x3 + +const char *const al_udma_states_name[] = { + "Disable", + "Idle", + "Normal", + "Abort", + "Reset" +}; + +#define AL_UDMA_INITIAL_RING_ID 1 + +/* dma_q flags */ +#define AL_UDMA_Q_FLAGS_IGNORE_RING_ID AL_BIT(0) +#define AL_UDMA_Q_FLAGS_NO_COMP_UPDATE AL_BIT(1) +#define AL_UDMA_Q_FLAGS_EN_COMP_COAL AL_BIT(2) + + +static void al_udma_set_defaults(struct al_udma *udma) +{ + uint32_t tmp; + uint8_t rev_id = udma->rev_id; + + if (udma->type == UDMA_TX) { + struct unit_regs* tmp_unit_regs = + (struct unit_regs*)udma->udma_regs; + + /* Setting the data fifo depth to 4K (256 strips of 16B) + * This allows the UDMA to have 16 outstanding writes */ + if (rev_id >= AL_UDMA_REV_ID_2) { + al_reg_write32_masked(&tmp_unit_regs->m2s.m2s_rd.data_cfg, + UDMA_M2S_RD_DATA_CFG_DATA_FIFO_DEPTH_MASK, + 256 << UDMA_M2S_RD_DATA_CFG_DATA_FIFO_DEPTH_SHIFT); + } + + if (rev_id == AL_UDMA_REV_ID_0) + /* disable AXI timeout for M0*/ + al_reg_write32(&tmp_unit_regs->gen.axi.cfg_1, 0); + else + /* set AXI timeout to 1M (~2.6 ms) */ + al_reg_write32(&tmp_unit_regs->gen.axi.cfg_1, 1000000); + + al_reg_write32(&tmp_unit_regs->m2s.m2s_comp.cfg_application_ack + , 0); /* Ack time out */ + + + if (rev_id == AL_UDMA_REV_ID_0) { + tmp = al_reg_read32(&udma->udma_regs->m2s.axi_m2s.desc_wr_cfg_1); + tmp &= ~UDMA_AXI_M2S_DESC_WR_CFG_1_MAX_AXI_BEATS_MASK; + tmp |= 4 << UDMA_AXI_M2S_DESC_WR_CFG_1_MAX_AXI_BEATS_SHIFT; + al_reg_write32(&udma->udma_regs->m2s.axi_m2s.desc_wr_cfg_1 + , tmp); + } + + } + if (udma->type == UDMA_RX) { + al_reg_write32( + &udma->udma_regs->s2m.s2m_comp.cfg_application_ack, 0); + /* Ack time out */ + + } +} +/** + * misc queue configurations + * + * @param udma_q udma queue data structure + * + * @return 0 + */ +static int al_udma_q_config(struct al_udma_q *udma_q) +{ + uint32_t *reg_addr; + uint32_t val; + + if (udma_q->udma->type == UDMA_TX) { + reg_addr = &udma_q->q_regs->m2s_q.rlimit.mask; + + val = al_reg_read32(reg_addr); + // enable DMB + val &= ~UDMA_M2S_Q_RATE_LIMIT_MASK_INTERNAL_PAUSE_DMB; + al_reg_write32(reg_addr, val); + } + return 0; +} + +/** + * set the queue's completion configuration register + * + * @param udma_q udma queue data structure + * + * @return 0 + */ +static int al_udma_q_config_compl(struct al_udma_q *udma_q) +{ + uint32_t *reg_addr; + uint32_t val; + + if (udma_q->udma->type == UDMA_TX) + reg_addr = &udma_q->q_regs->m2s_q.comp_cfg; + else + reg_addr = &udma_q->q_regs->s2m_q.comp_cfg; + + val = al_reg_read32(reg_addr); + + if (udma_q->flags & AL_UDMA_Q_FLAGS_NO_COMP_UPDATE) + val &= ~UDMA_M2S_Q_COMP_CFG_EN_COMP_RING_UPDATE; + else + val |= UDMA_M2S_Q_COMP_CFG_EN_COMP_RING_UPDATE; + + if (udma_q->flags & AL_UDMA_Q_FLAGS_EN_COMP_COAL) + val &= ~UDMA_M2S_Q_COMP_CFG_DIS_COMP_COAL; + else + val |= UDMA_M2S_Q_COMP_CFG_DIS_COMP_COAL; + + al_reg_write32(reg_addr, val); + + /* set the completion queue size */ + if (udma_q->udma->type == UDMA_RX) { + val = al_reg_read32( + &udma_q->udma->udma_regs->s2m.s2m_comp.cfg_1c); + val &= ~UDMA_S2M_COMP_CFG_1C_DESC_SIZE_MASK; + /* the register expects it to be in words */ + val |= (udma_q->cdesc_size >> 2) + & UDMA_S2M_COMP_CFG_1C_DESC_SIZE_MASK; + al_reg_write32(&udma_q->udma->udma_regs->s2m.s2m_comp.cfg_1c + , val); + } + return 0; +} + +/** + * reset the queues pointers (Head, Tail, etc) and set the base addresses + * + * @param udma_q udma queue data structure + */ +static int al_udma_q_set_pointers(struct al_udma_q *udma_q) +{ + /* reset the descriptors ring pointers */ + /* assert descriptor base address aligned. */ + al_assert((AL_ADDR_LOW(udma_q->desc_phy_base) & + ~UDMA_M2S_Q_TDRBP_LOW_ADDR_MASK) == 0); + al_reg_write32(&udma_q->q_regs->rings.drbp_low, + AL_ADDR_LOW(udma_q->desc_phy_base)); + al_reg_write32(&udma_q->q_regs->rings.drbp_high, + AL_ADDR_HIGH(udma_q->desc_phy_base)); + + al_reg_write32(&udma_q->q_regs->rings.drl, udma_q->size); + + /* if completion ring update disabled */ + if (udma_q->cdesc_base_ptr == NULL) { + udma_q->flags |= AL_UDMA_Q_FLAGS_NO_COMP_UPDATE; + } else { + /* reset the completion descriptors ring pointers */ + /* assert completion base address aligned. */ + al_assert((AL_ADDR_LOW(udma_q->cdesc_phy_base) & + ~UDMA_M2S_Q_TCRBP_LOW_ADDR_MASK) == 0); + al_reg_write32(&udma_q->q_regs->rings.crbp_low, + AL_ADDR_LOW(udma_q->cdesc_phy_base)); + al_reg_write32(&udma_q->q_regs->rings.crbp_high, + AL_ADDR_HIGH(udma_q->cdesc_phy_base)); + } + al_udma_q_config_compl(udma_q); + return 0; +} + +/** + * enable/disable udma queue + * + * @param udma_q udma queue data structure + * @param enable none zero value enables the queue, zero means disable + * + * @return 0 + */ +static int al_udma_q_enable(struct al_udma_q *udma_q, int enable) +{ + uint32_t reg = al_reg_read32(&udma_q->q_regs->rings.cfg); + + if (enable) { + reg |= (UDMA_M2S_Q_CFG_EN_PREF | UDMA_M2S_Q_CFG_EN_SCHEDULING); + udma_q->status = AL_QUEUE_ENABLED; + } else { + reg &= ~(UDMA_M2S_Q_CFG_EN_PREF | UDMA_M2S_Q_CFG_EN_SCHEDULING); + udma_q->status = AL_QUEUE_DISABLED; + } + al_reg_write32(&udma_q->q_regs->rings.cfg, reg); + return 0; +} + + +/************************ API functions ***************************************/ + +/* Initializations functions */ +/* + * Initialize the udma engine + */ +int al_udma_init(struct al_udma *udma, struct al_udma_params *udma_params) +{ + int i; + + al_assert(udma); + + if (udma_params->num_of_queues > DMA_MAX_Q) { + al_err("udma: invalid num_of_queues parameter\n"); + return -EINVAL; + } + + udma->type = udma_params->type; + udma->num_of_queues = udma_params->num_of_queues; + udma->gen_regs = &udma_params->udma_regs_base->gen; + + if (udma->type == UDMA_TX) + udma->udma_regs = (union udma_regs *)&udma_params->udma_regs_base->m2s; + else + udma->udma_regs = (union udma_regs *)&udma_params->udma_regs_base->s2m; + + udma->rev_id = al_udma_get_revision(udma_params->udma_regs_base); + + if (udma_params->name == NULL) + udma->name = ""; + else + udma->name = udma_params->name; + + udma->state = UDMA_DISABLE; + for (i = 0; i < DMA_MAX_Q; i++) { + udma->udma_q[i].status = AL_QUEUE_NOT_INITIALIZED; + } + /* initialize configuration registers to correct values */ + al_udma_set_defaults(udma); + al_dbg("udma [%s] initialized. base %p\n", udma->name, + udma->udma_regs); + return 0; +} + +/* + * Initialize the udma queue data structure + */ +int al_udma_q_init(struct al_udma *udma, uint32_t qid, + struct al_udma_q_params *q_params) +{ + struct al_udma_q *udma_q; + + al_assert(udma); + al_assert(q_params); + + if (qid >= udma->num_of_queues) { + al_err("udma: invalid queue id (%d)\n", qid); + return -EINVAL; + } + + if (udma->udma_q[qid].status == AL_QUEUE_ENABLED) { + al_err("udma: queue (%d) already enabled!\n", qid); + return -EIO; + } + + if (q_params->size < AL_UDMA_MIN_Q_SIZE) { + al_err("udma: queue (%d) size too small\n", qid); + return -EINVAL; + } + + if (q_params->size > AL_UDMA_MAX_Q_SIZE) { + al_err("udma: queue (%d) size too large\n", qid); + return -EINVAL; + } + + if (q_params->size & (q_params->size - 1)) { + al_err("udma: queue (%d) size (%d) must be power of 2\n", + q_params->size, qid); + return -EINVAL; + } + + udma_q = &udma->udma_q[qid]; + /* set the queue's regs base address */ + if (udma->type == UDMA_TX) + udma_q->q_regs = (union udma_q_regs __iomem *) + &udma->udma_regs->m2s.m2s_q[qid]; + else + udma_q->q_regs = (union udma_q_regs __iomem *) + &udma->udma_regs->s2m.s2m_q[qid]; + + udma_q->adapter_rev_id = q_params->adapter_rev_id; + udma_q->size = q_params->size; + udma_q->size_mask = q_params->size - 1; + udma_q->desc_base_ptr = q_params->desc_base; + udma_q->desc_phy_base = q_params->desc_phy_base; + udma_q->cdesc_base_ptr = q_params->cdesc_base; + udma_q->cdesc_phy_base = q_params->cdesc_phy_base; + udma_q->cdesc_size = q_params->cdesc_size; + + udma_q->next_desc_idx = 0; + udma_q->next_cdesc_idx = 0; + udma_q->end_cdesc_ptr = (uint8_t *) udma_q->cdesc_base_ptr + + (udma_q->size - 1) * udma_q->cdesc_size; + udma_q->comp_head_idx = 0; + udma_q->comp_head_ptr = (union al_udma_cdesc *)udma_q->cdesc_base_ptr; + udma_q->desc_ring_id = AL_UDMA_INITIAL_RING_ID; + udma_q->comp_ring_id = AL_UDMA_INITIAL_RING_ID; +#if 0 + udma_q->desc_ctrl_bits = AL_UDMA_INITIAL_RING_ID << + AL_M2S_DESC_RING_ID_SHIFT; +#endif + udma_q->pkt_crnt_descs = 0; + udma_q->flags = 0; + udma_q->status = AL_QUEUE_DISABLED; + udma_q->udma = udma; + udma_q->qid = qid; + + /* start hardware configuration: */ + al_udma_q_config(udma_q); + /* reset the queue pointers */ + al_udma_q_set_pointers(udma_q); + + /* enable the q */ + al_udma_q_enable(udma_q, 1); + + al_dbg("udma [%s %d]: %s q init. size 0x%x\n" + " desc ring info: phys base 0x%llx virt base %p\n" + " cdesc ring info: phys base 0x%llx virt base %p " + "entry size 0x%x", + udma_q->udma->name, udma_q->qid, + udma->type == UDMA_TX ? "Tx" : "Rx", + q_params->size, + (unsigned long long)q_params->desc_phy_base, + q_params->desc_base, + (unsigned long long)q_params->cdesc_phy_base, + q_params->cdesc_base, + q_params->cdesc_size); + + return 0; +} + +/* + * Reset a udma queue + */ +int al_udma_q_reset(struct al_udma_q *udma_q) +{ + unsigned int remaining_time = AL_UDMA_Q_RST_TOUT; + uint32_t *status_reg; + uint32_t *dcp_reg; + uint32_t *crhp_reg; + uint32_t *q_sw_ctrl_reg; + + al_assert(udma_q); + + /* De-assert scheduling and prefetch */ + al_udma_q_enable(udma_q, 0); + + /* Wait for scheduling and prefetch to stop */ + status_reg = &udma_q->q_regs->rings.status; + + while (remaining_time) { + uint32_t status = al_reg_read32(status_reg); + + if (!(status & (UDMA_M2S_Q_STATUS_PREFETCH | + UDMA_M2S_Q_STATUS_SCHEDULER))) + break; + + remaining_time--; + al_udelay(1); + } + + if (!remaining_time) { + al_err("udma [%s %d]: %s timeout waiting for prefetch and " + "scheduler disable\n", udma_q->udma->name, udma_q->qid, + __func__); + return -ETIMEDOUT; + } + + /* Wait for the completion queue to reach to the same pointer as the + * prefetch stopped at ([TR]DCP == [TR]CRHP) */ + dcp_reg = &udma_q->q_regs->rings.dcp; + crhp_reg = &udma_q->q_regs->rings.crhp; + + while (remaining_time) { + uint32_t dcp = al_reg_read32(dcp_reg); + uint32_t crhp = al_reg_read32(crhp_reg); + + if (dcp == crhp) + break; + + remaining_time--; + al_udelay(1); + }; + + if (!remaining_time) { + al_err("udma [%s %d]: %s timeout waiting for dcp==crhp\n", + udma_q->udma->name, udma_q->qid, __func__); + return -ETIMEDOUT; + } + + /* Assert the queue reset */ + if (udma_q->udma->type == UDMA_TX) + q_sw_ctrl_reg = &udma_q->q_regs->m2s_q.q_sw_ctrl; + else + q_sw_ctrl_reg = &udma_q->q_regs->s2m_q.q_sw_ctrl; + + al_reg_write32(q_sw_ctrl_reg, UDMA_M2S_Q_SW_CTRL_RST_Q); + + return 0; +} + +/* + * return (by reference) a pointer to a specific queue date structure. + */ +int al_udma_q_handle_get(struct al_udma *udma, uint32_t qid, + struct al_udma_q **q_handle) +{ + + al_assert(udma); + al_assert(q_handle); + + if (unlikely(qid >= udma->num_of_queues)) { + al_err("udma [%s]: invalid queue id (%d)\n", udma->name, qid); + return -EINVAL; + } + *q_handle = &udma->udma_q[qid]; + return 0; +} + +/* + * Change the UDMA's state + */ +int al_udma_state_set(struct al_udma *udma, enum al_udma_state state) +{ + uint32_t reg; + + al_assert(udma != NULL); + if (state == udma->state) + al_dbg("udma [%s]: requested state identical to " + "current state (%d)\n", udma->name, state); + + al_dbg("udma [%s]: change state from (%s) to (%s)\n", + udma->name, al_udma_states_name[udma->state], + al_udma_states_name[state]); + + reg = 0; + switch (state) { + case UDMA_DISABLE: + reg |= UDMA_M2S_CHANGE_STATE_DIS; + break; + case UDMA_NORMAL: + reg |= UDMA_M2S_CHANGE_STATE_NORMAL; + break; + case UDMA_ABORT: + reg |= UDMA_M2S_CHANGE_STATE_ABORT; + break; + default: + al_err("udma: invalid state (%d)\n", state); + return -EINVAL; + } + + if (udma->type == UDMA_TX) + al_reg_write32(&udma->udma_regs->m2s.m2s.change_state, reg); + else + al_reg_write32(&udma->udma_regs->s2m.s2m.change_state, reg); + + udma->state = state; + return 0; +} + +/* + * return the current UDMA hardware state + */ +enum al_udma_state al_udma_state_get(struct al_udma *udma) +{ + uint32_t state_reg; + uint32_t comp_ctrl; + uint32_t stream_if; + uint32_t data_rd; + uint32_t desc_pref; + + if (udma->type == UDMA_TX) + state_reg = al_reg_read32(&udma->udma_regs->m2s.m2s.state); + else + state_reg = al_reg_read32(&udma->udma_regs->s2m.s2m.state); + + comp_ctrl = AL_REG_FIELD_GET(state_reg, + UDMA_M2S_STATE_COMP_CTRL_MASK, + UDMA_M2S_STATE_COMP_CTRL_SHIFT); + stream_if = AL_REG_FIELD_GET(state_reg, + UDMA_M2S_STATE_STREAM_IF_MASK, + UDMA_M2S_STATE_STREAM_IF_SHIFT); + data_rd = AL_REG_FIELD_GET(state_reg, + UDMA_M2S_STATE_DATA_RD_CTRL_MASK, + UDMA_M2S_STATE_DATA_RD_CTRL_SHIFT); + desc_pref = AL_REG_FIELD_GET(state_reg, + UDMA_M2S_STATE_DESC_PREF_MASK, + UDMA_M2S_STATE_DESC_PREF_SHIFT); + + al_assert(comp_ctrl != UDMA_STATE_RESERVED); + al_assert(stream_if != UDMA_STATE_RESERVED); + al_assert(data_rd != UDMA_STATE_RESERVED); + al_assert(desc_pref != UDMA_STATE_RESERVED); + + /* if any of the states is abort then return abort */ + if ((comp_ctrl == UDMA_STATE_ABORT) || (stream_if == UDMA_STATE_ABORT) + || (data_rd == UDMA_STATE_ABORT) + || (desc_pref == UDMA_STATE_ABORT)) + return UDMA_ABORT; + + /* if any of the states is normal then return normal */ + if ((comp_ctrl == UDMA_STATE_NORMAL) + || (stream_if == UDMA_STATE_NORMAL) + || (data_rd == UDMA_STATE_NORMAL) + || (desc_pref == UDMA_STATE_NORMAL)) + return UDMA_NORMAL; + + return UDMA_IDLE; +} + +/* + * Action handling + */ + +/* + * get next completed packet from completion ring of the queue + */ +uint32_t al_udma_cdesc_packet_get( + struct al_udma_q *udma_q, + volatile union al_udma_cdesc **cdesc) +{ + uint32_t count; + volatile union al_udma_cdesc *curr; + uint32_t comp_flags; + + /* this function requires the completion ring update */ + al_assert(!(udma_q->flags & AL_UDMA_Q_FLAGS_NO_COMP_UPDATE)); + + /* comp_head points to the last comp desc that was processed */ + curr = udma_q->comp_head_ptr; + comp_flags = swap32_from_le(curr->al_desc_comp_tx.ctrl_meta); + + /* check if the completion descriptor is new */ + if (unlikely(al_udma_new_cdesc(udma_q, comp_flags) == AL_FALSE)) + return 0; + /* if new desc found, increment the current packets descriptors */ + count = udma_q->pkt_crnt_descs + 1; + while (!cdesc_is_last(comp_flags)) { + curr = al_cdesc_next_update(udma_q, curr); + comp_flags = swap32_from_le(curr->al_desc_comp_tx.ctrl_meta); + if (unlikely(al_udma_new_cdesc(udma_q, comp_flags) + == AL_FALSE)) { + /* the current packet here doesn't have all */ + /* descriptors completed. log the current desc */ + /* location and number of completed descriptors so */ + /* far. then return */ + udma_q->pkt_crnt_descs = count; + udma_q->comp_head_ptr = curr; + return 0; + } + count++; + /* check against max descs per packet. */ + al_assert(count <= udma_q->size); + } + /* return back the first descriptor of the packet */ + *cdesc = al_udma_cdesc_idx_to_ptr(udma_q, udma_q->next_cdesc_idx); + udma_q->pkt_crnt_descs = 0; + udma_q->comp_head_ptr = al_cdesc_next_update(udma_q, curr); + + al_dbg("udma [%s %d]: packet completed. first desc %p (ixd 0x%x)" + " descs %d\n", udma_q->udma->name, udma_q->qid, *cdesc, + udma_q->next_cdesc_idx, count); + + return count; +} + +/** @} end of UDMA group */ diff --git a/al_hal_udma_regs.h b/al_hal_udma_regs.h new file mode 100644 index 00000000000..ed37215ae44 --- /dev/null +++ b/al_hal_udma_regs.h @@ -0,0 +1,104 @@ +/*- +******************************************************************************* +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_udma_regs.h + * + * @brief udma registers definition + * + * + */ +#ifndef __AL_HAL_UDMA_REG_H +#define __AL_HAL_UDMA_REG_H + +#include "al_hal_udma_regs_m2s.h" +#include "al_hal_udma_regs_s2m.h" +#include "al_hal_udma_regs_gen.h" + +#define AL_UDMA_REV_ID_REV0 0 +#define AL_UDMA_REV_ID_REV1 1 +#define AL_UDMA_REV_ID_REV2 2 + +#ifdef __cplusplus +extern "C" { +#endif + +/** UDMA registers, either m2s or s2m */ +union udma_regs { + struct udma_m2s_regs m2s; + struct udma_s2m_regs s2m; +}; + +struct unit_regs { + struct udma_m2s_regs m2s; + uint32_t rsrvd0[(0x10000 - sizeof(struct udma_m2s_regs)) >> 2]; + struct udma_s2m_regs s2m; + uint32_t rsrvd1[((0x1C000 - 0x10000) - sizeof(struct udma_s2m_regs)) >> 2]; + struct udma_gen_regs gen; +}; + +/** UDMA submission and completion registers, M2S and S2M UDMAs have same stucture */ +struct udma_rings_regs { + uint32_t rsrvd0[8]; + uint32_t cfg; /* Descriptor ring configuration */ + uint32_t status; /* Descriptor ring status and information */ + uint32_t drbp_low; /* Descriptor Ring Base Pointer [31:4] */ + uint32_t drbp_high; /* Descriptor Ring Base Pointer [63:32] */ + uint32_t drl; /* Descriptor Ring Length[23:2] */ + uint32_t drhp; /* Descriptor Ring Head Pointer */ + uint32_t drtp_inc; /* Descriptor Tail Pointer increment */ + uint32_t drtp; /* Descriptor Tail Pointer */ + uint32_t dcp; /* Descriptor Current Pointer */ + uint32_t crbp_low; /* Completion Ring Base Pointer [31:4] */ + uint32_t crbp_high; /* Completion Ring Base Pointer [63:32] */ + uint32_t crhp; /* Completion Ring Head Pointer */ + uint32_t crhp_internal; /* Completion Ring Head Pointer internal, before AX ... */ +}; + +/** M2S and S2M generic structure of Q registers */ +union udma_q_regs { + struct udma_rings_regs rings; + struct udma_m2s_q m2s_q; + struct udma_s2m_q s2m_q; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __AL_HAL_UDMA_REG_H */ +/** @} end of UDMA group */ diff --git a/al_hal_udma_regs_gen.h b/al_hal_udma_regs_gen.h new file mode 100644 index 00000000000..89f94b85a56 --- /dev/null +++ b/al_hal_udma_regs_gen.h @@ -0,0 +1,414 @@ +/*- +******************************************************************************* +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_udma_regs_gen.h + * + * @brief C Header file for the UDMA general registers + * + */ + +#ifndef __AL_HAL_UDMA_GEN_REG_H +#define __AL_HAL_UDMA_GEN_REG_H + +#include "al_hal_udma_iofic_regs.h" + +#ifdef __cplusplus +extern "C" { +#endif +/* +* Unit Registers +*/ + + + +struct udma_gen_dma_misc { + /* [0x0] Reserved register for the interrupt controller */ + uint32_t int_cfg; + /* [0x4] Revision register */ + uint32_t revision; + /* [0x8] Reserved for future use */ + uint32_t general_cfg_1; + /* [0xc] Reserved for future use */ + uint32_t general_cfg_2; + /* [0x10] Reserved for future use */ + uint32_t general_cfg_3; + /* [0x14] Reserved for future use */ + uint32_t general_cfg_4; + /* [0x18] General timer configuration */ + uint32_t general_cfg_5; + uint32_t rsrvd[57]; +}; +struct udma_gen_mailbox { + /* + * [0x0] Mailbox interrupt generator. + * Generates interrupt to neighbor DMA + */ + uint32_t interrupt; + /* [0x4] Mailbox message data out */ + uint32_t msg_out; + /* [0x8] Mailbox message data in */ + uint32_t msg_in; + uint32_t rsrvd[13]; +}; +struct udma_gen_axi { + /* [0x0] Configuration of the AXI masters */ + uint32_t cfg_1; + /* [0x4] Configuration of the AXI masters */ + uint32_t cfg_2; + /* [0x8] Configuration of the AXI masters. Endianess configuration */ + uint32_t endian_cfg; + uint32_t rsrvd[61]; +}; +struct udma_gen_sram_ctrl { + /* [0x0] Timing configuration */ + uint32_t timing; +}; +struct udma_gen_vmid { + /* [0x0] VMID control */ + uint32_t cfg_vmid_0; + /* [0x4] TX queue 0/1 VMID */ + uint32_t cfg_vmid_1; + /* [0x8] TX queue 2/3 VMID */ + uint32_t cfg_vmid_2; + /* [0xc] RX queue 0/1 VMID */ + uint32_t cfg_vmid_3; + /* [0x10] RX queue 2/3 VMID */ + uint32_t cfg_vmid_4; +}; +struct udma_gen_vmaddr { + /* [0x0] TX queue 0/1 VMADDR */ + uint32_t cfg_vmaddr_0; + /* [0x4] TX queue 2/3 VMADDR */ + uint32_t cfg_vmaddr_1; + /* [0x8] RX queue 0/1 VMADDR */ + uint32_t cfg_vmaddr_2; + /* [0xc] RX queue 2/3 VMADDR */ + uint32_t cfg_vmaddr_3; +}; +struct udma_gen_vmpr { + /* [0x0] TX VMPR control */ + uint32_t cfg_vmpr_0; + /* [0x4] TX VMPR Address High Regsiter */ + uint32_t cfg_vmpr_1; + /* [0x8] TX queue VMID values */ + uint32_t cfg_vmpr_2; + /* [0xc] TX queue VMID values */ + uint32_t cfg_vmpr_3; + /* [0x10] RX VMPR control */ + uint32_t cfg_vmpr_4; + /* [0x14] RX VMPR Buffer2 MSB address */ + uint32_t cfg_vmpr_5; + /* [0x18] RX queue VMID values */ + uint32_t cfg_vmpr_6; + /* [0x1c] RX queue BUF1 VMID values */ + uint32_t cfg_vmpr_7; + /* [0x20] RX queue BUF2 VMID values */ + uint32_t cfg_vmpr_8; + /* [0x24] RX queue Direct Data Placement VMID values */ + uint32_t cfg_vmpr_9; + /* [0x28] RX VMPR BUF1 Address High Regsiter */ + uint32_t cfg_vmpr_10; + /* [0x2c] RX VMPR BUF2 Address High Regsiter */ + uint32_t cfg_vmpr_11; + /* [0x30] RX VMPR DDP Address High Regsiter */ + uint32_t cfg_vmpr_12; + uint32_t rsrvd[3]; +}; + +struct udma_gen_regs { + struct udma_iofic_regs interrupt_regs; /* [0x0000] */ + struct udma_gen_dma_misc dma_misc; /* [0x2080] */ + struct udma_gen_mailbox mailbox[4]; /* [0x2180] */ + struct udma_gen_axi axi; /* [0x2280] */ + struct udma_gen_sram_ctrl sram_ctrl[25]; /* [0x2380] */ + uint32_t rsrvd_1[2]; + struct udma_gen_vmid vmid; /* [0x23ec] */ + struct udma_gen_vmaddr vmaddr; /* [0x2400] */ + uint32_t rsrvd_2[252]; + struct udma_gen_vmpr vmpr[4]; /* [0x2800] */ +}; + + +/* +* Registers Fields +*/ + + +/**** int_cfg register ****/ +/* + * MSIX data width + * 1 - 64 bit + * 0 – 32 bit + */ +#define UDMA_GEN_DMA_MISC_INT_CFG_MSIX_64 (1 << 0) +/* General configuration */ +#define UDMA_GEN_DMA_MISC_INT_CFG_RESERVED_3_1_MASK 0x0000000E +#define UDMA_GEN_DMA_MISC_INT_CFG_RESERVED_3_1_SHIFT 1 +/* MSIx AXI QoS */ +#define UDMA_GEN_DMA_MISC_INT_CFG_MSIX_AXI_QOS_MASK 0x00000070 +#define UDMA_GEN_DMA_MISC_INT_CFG_MSIX_AXI_QOS_SHIFT 4 + +#define UDMA_GEN_DMA_MISC_INT_CFG_RESERVED_31_7_MASK 0xFFFFFF80 +#define UDMA_GEN_DMA_MISC_INT_CFG_RESERVED_31_7_SHIFT 7 + +/**** revision register ****/ +/* Design programming interface revision ID */ +#define UDMA_GEN_DMA_MISC_REVISION_PROGRAMMING_ID_MASK 0x00000FFF +#define UDMA_GEN_DMA_MISC_REVISION_PROGRAMMING_ID_SHIFT 0 +/* Design minor revision ID */ +#define UDMA_GEN_DMA_MISC_REVISION_MINOR_ID_MASK 0x00FFF000 +#define UDMA_GEN_DMA_MISC_REVISION_MINOR_ID_SHIFT 12 +/* Design major revision ID */ +#define UDMA_GEN_DMA_MISC_REVISION_MAJOR_ID_MASK 0xFF000000 +#define UDMA_GEN_DMA_MISC_REVISION_MAJOR_ID_SHIFT 24 + +/**** Interrupt register ****/ +/* Generate interrupt to another DMA */ +#define UDMA_GEN_MAILBOX_INTERRUPT_SET (1 << 0) + +/**** cfg_2 register ****/ +/* + * Enable arbitration promotion. + * Increment master priority after configured number of arbitration cycles + */ +#define UDMA_GEN_AXI_CFG_2_ARB_PROMOTION_MASK 0x0000000F +#define UDMA_GEN_AXI_CFG_2_ARB_PROMOTION_SHIFT 0 + +/**** endian_cfg register ****/ +/* Swap M2S descriptor read and completion descriptor write. */ +#define UDMA_GEN_AXI_ENDIAN_CFG_SWAP_M2S_DESC (1 << 0) +/* Swap M2S data read. */ +#define UDMA_GEN_AXI_ENDIAN_CFG_SWAP_M2S_DATA (1 << 1) +/* Swap S2M descriptor read and completion descriptor write. */ +#define UDMA_GEN_AXI_ENDIAN_CFG_SWAP_S2M_DESC (1 << 2) +/* Swap S2M data write. */ +#define UDMA_GEN_AXI_ENDIAN_CFG_SWAP_S2M_DATA (1 << 3) +/* + * Swap 32 or 64 bit mode: + * 0 - Swap groups of 4 bytes + * 1 - Swap groups of 8 bytes + */ +#define UDMA_GEN_AXI_ENDIAN_CFG_SWAP_64B_EN (1 << 4) + +/**** timing register ****/ +/* Write margin */ +#define UDMA_GEN_SRAM_CTRL_TIMING_RMA_MASK 0x0000000F +#define UDMA_GEN_SRAM_CTRL_TIMING_RMA_SHIFT 0 +/* Write margin enable */ +#define UDMA_GEN_SRAM_CTRL_TIMING_RMEA (1 << 8) +/* Read margin */ +#define UDMA_GEN_SRAM_CTRL_TIMING_RMB_MASK 0x000F0000 +#define UDMA_GEN_SRAM_CTRL_TIMING_RMB_SHIFT 16 +/* Read margin enable */ +#define UDMA_GEN_SRAM_CTRL_TIMING_RMEB (1 << 24) + +/**** cfg_vmid_0 register ****/ +/* For M2S queues 3:0, enable usage of the VMID from the buffer address 63:56 */ +#define UDMA_GEN_VMID_CFG_VMID_0_TX_Q_VMID_DESC_EN_MASK 0x0000000F +#define UDMA_GEN_VMID_CFG_VMID_0_TX_Q_VMID_DESC_EN_SHIFT 0 +/* + * For M2S queues 3:0, enable usage of the VMID from the configuration register + * (cfg_vmid_1/2 used for M2S queue_x) + */ +#define UDMA_GEN_VMID_CFG_VMID_0_TX_Q_VMID_QUEUE_EN_MASK 0x000000F0 +#define UDMA_GEN_VMID_CFG_VMID_0_TX_Q_VMID_QUEUE_EN_SHIFT 4 +/* use VMID_n [7:0] from MSI-X Controller for MSI-X message */ +#define UDMA_GEN_VMID_CFG_VMID_0_MSIX_VMID_SEL (1 << 8) +/* Enable write to all VMID_n registers in the MSI-X Controller */ +#define UDMA_GEN_VMID_CFG_VMID_0_MSIX_VMID_ACCESS_EN (1 << 9) +/* For S2M queues 3:0, enable usage of the VMID from the buffer address 63:56 */ +#define UDMA_GEN_VMID_CFG_VMID_0_RX_Q_VMID_DESC_EN_MASK 0x000F0000 +#define UDMA_GEN_VMID_CFG_VMID_0_RX_Q_VMID_DESC_EN_SHIFT 16 +/* + * For S2M queues 3:0, enable usage of the VMID from the configuration register + * (cfg_vmid_3/4 used for M2S queue_x) + */ +#define UDMA_GEN_VMID_CFG_VMID_0_RX_Q_VMID_QUEUE_EN_MASK 0x00F00000 +#define UDMA_GEN_VMID_CFG_VMID_0_RX_Q_VMID_QUEUE_EN_SHIFT 20 + +/**** cfg_vmid_1 register ****/ +/* TX queue 0 VMID value */ +#define UDMA_GEN_VMID_CFG_VMID_1_TX_Q_0_VMID_MASK 0x0000FFFF +#define UDMA_GEN_VMID_CFG_VMID_1_TX_Q_0_VMID_SHIFT 0 +/* TX queue 1 VMID value */ +#define UDMA_GEN_VMID_CFG_VMID_1_TX_Q_1_VMID_MASK 0xFFFF0000 +#define UDMA_GEN_VMID_CFG_VMID_1_TX_Q_1_VMID_SHIFT 16 + +/**** cfg_vmid_2 register ****/ +/* TX queue 2 VMID value */ +#define UDMA_GEN_VMID_CFG_VMID_2_TX_Q_2_VMID_MASK 0x0000FFFF +#define UDMA_GEN_VMID_CFG_VMID_2_TX_Q_2_VMID_SHIFT 0 +/* TX queue 3 VMID value */ +#define UDMA_GEN_VMID_CFG_VMID_2_TX_Q_3_VMID_MASK 0xFFFF0000 +#define UDMA_GEN_VMID_CFG_VMID_2_TX_Q_3_VMID_SHIFT 16 + +/**** cfg_vmid_3 register ****/ +/* RX queue 0 VMID value */ +#define UDMA_GEN_VMID_CFG_VMID_3_RX_Q_0_VMID_MASK 0x0000FFFF +#define UDMA_GEN_VMID_CFG_VMID_3_RX_Q_0_VMID_SHIFT 0 +/* RX queue 1 VMID value */ +#define UDMA_GEN_VMID_CFG_VMID_3_RX_Q_1_VMID_MASK 0xFFFF0000 +#define UDMA_GEN_VMID_CFG_VMID_3_RX_Q_1_VMID_SHIFT 16 + +/**** cfg_vmid_4 register ****/ +/* RX queue 2 VMID value */ +#define UDMA_GEN_VMID_CFG_VMID_4_RX_Q_2_VMID_MASK 0x0000FFFF +#define UDMA_GEN_VMID_CFG_VMID_4_RX_Q_2_VMID_SHIFT 0 +/* RX queue 3 VMID value */ +#define UDMA_GEN_VMID_CFG_VMID_4_RX_Q_3_VMID_MASK 0xFFFF0000 +#define UDMA_GEN_VMID_CFG_VMID_4_RX_Q_3_VMID_SHIFT 16 + +/**** cfg_vmaddr_0 register ****/ +/* TX queue 0 VMADDR value */ +#define UDMA_GEN_VMADDR_CFG_VMADDR_0_TX_Q_0_VMADDR_MASK 0x0000FFFF +#define UDMA_GEN_VMADDR_CFG_VMADDR_0_TX_Q_0_VMADDR_SHIFT 0 +/* TX queue 1 VMADDR value */ +#define UDMA_GEN_VMADDR_CFG_VMADDR_0_TX_Q_1_VMADDR_MASK 0xFFFF0000 +#define UDMA_GEN_VMADDR_CFG_VMADDR_0_TX_Q_1_VMADDR_SHIFT 16 + +/**** cfg_vmaddr_1 register ****/ +/* TX queue 2 VMADDR value */ +#define UDMA_GEN_VMADDR_CFG_VMADDR_1_TX_Q_2_VMADDR_MASK 0x0000FFFF +#define UDMA_GEN_VMADDR_CFG_VMADDR_1_TX_Q_2_VMADDR_SHIFT 0 +/* TX queue 3 VMADDR value */ +#define UDMA_GEN_VMADDR_CFG_VMADDR_1_TX_Q_3_VMADDR_MASK 0xFFFF0000 +#define UDMA_GEN_VMADDR_CFG_VMADDR_1_TX_Q_3_VMADDR_SHIFT 16 + +/**** cfg_vmaddr_2 register ****/ +/* RX queue 0 VMADDR value */ +#define UDMA_GEN_VMADDR_CFG_VMADDR_2_RX_Q_0_VMADDR_MASK 0x0000FFFF +#define UDMA_GEN_VMADDR_CFG_VMADDR_2_RX_Q_0_VMADDR_SHIFT 0 +/* RX queue 1 VMADDR value */ +#define UDMA_GEN_VMADDR_CFG_VMADDR_2_RX_Q_1_VMADDR_MASK 0xFFFF0000 +#define UDMA_GEN_VMADDR_CFG_VMADDR_2_RX_Q_1_VMADDR_SHIFT 16 + +/**** cfg_vmaddr_3 register ****/ +/* RX queue 2 VMADDR value */ +#define UDMA_GEN_VMADDR_CFG_VMADDR_3_RX_Q_2_VMADDR_MASK 0x0000FFFF +#define UDMA_GEN_VMADDR_CFG_VMADDR_3_RX_Q_2_VMADDR_SHIFT 0 +/* RX queue 3 VMADDR value */ +#define UDMA_GEN_VMADDR_CFG_VMADDR_3_RX_Q_3_VMADDR_MASK 0xFFFF0000 +#define UDMA_GEN_VMADDR_CFG_VMADDR_3_RX_Q_3_VMADDR_SHIFT 16 + +/**** cfg_vmpr_0 register ****/ +/* TX High Address Select Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_HISEL_MASK 0x0000003F +#define UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_HISEL_SHIFT 0 +/* TX Data VMID Enable Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_DATA_VMID_EN (1 << 7) +/* TX Prefetch VMID Enable Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_PREF_VMID_EN (1 << 28) +/* TX Completions VMID Enable Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_CMPL_VMID_EN (1 << 29) + +/**** cfg_vmpr_2 register ****/ +/* TX queue Prefetch VMID */ +#define UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_PREF_VMID_MASK 0x0000FFFF +#define UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_PREF_VMID_SHIFT 0 +/* TX queue Completion VMID */ +#define UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_CMPL_VMID_MASK 0xFFFF0000 +#define UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_CMPL_VMID_SHIFT 16 + +/**** cfg_vmpr_3 register ****/ +/* TX queue Data VMID */ +#define UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_VMID_MASK 0x0000FFFF +#define UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_VMID_SHIFT 0 +/* TX queue Data VMID select */ +#define UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_VMID_SEL_MASK 0xFFFF0000 +#define UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_VMID_SEL_SHIFT 16 + +/**** cfg_vmpr_4 register ****/ +/* RX Data Buffer1 - High Address Select Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF1_HISEL_MASK 0x0000003F +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF1_HISEL_SHIFT 0 +/* RX Data Buffer1 VMID Enable Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF1_VMID_EN (1 << 7) +/* RX Data Buffer2 - High Address Select Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_HISEL_MASK 0x00003F00 +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_HISEL_SHIFT 8 +/* RX Data Buffer2 VMID Enable Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_VMID_EN (1 << 15) +/* RX Direct Data Placement - High Address Select Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_DDP_HISEL_MASK 0x003F0000 +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_DDP_HISEL_SHIFT 16 +/* RX Direct Data Placement VMID Enable Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_DDP_VMID_EN (1 << 23) +/* RX Buffer 2 MSB address word selects per bytes, per queue */ +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_MSB_ADDR_SEL_MASK 0x0F000000 +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_MSB_ADDR_SEL_SHIFT 24 +/* RX Prefetch VMID Enable Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_PREF_VMID_EN (1 << 28) +/* RX Completions VMID Enable Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_CMPL_VMID_EN (1 << 29) + +/**** cfg_vmpr_6 register ****/ +/* RX queue Prefetch VMID */ +#define UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_PREF_VMID_MASK 0x0000FFFF +#define UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_PREF_VMID_SHIFT 0 +/* RX queue Completion VMID */ +#define UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_CMPL_VMID_MASK 0xFFFF0000 +#define UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_CMPL_VMID_SHIFT 16 + +/**** cfg_vmpr_7 register ****/ +/* RX queue Data Buffer 1 VMID */ +#define UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_VMID_MASK 0x0000FFFF +#define UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_VMID_SHIFT 0 +/* RX queue Data Buffer 1 VMID select */ +#define UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_VMID_SEL_MASK 0xFFFF0000 +#define UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_VMID_SEL_SHIFT 16 + +/**** cfg_vmpr_8 register ****/ +/* RX queue Data Buffer 2 VMID */ +#define UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_VMID_MASK 0x0000FFFF +#define UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_VMID_SHIFT 0 +/* RX queue Data Buffer 2 VMID select */ +#define UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_VMID_SEL_MASK 0xFFFF0000 +#define UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_VMID_SEL_SHIFT 16 + +/**** cfg_vmpr_9 register ****/ +/* RX queue DDP VMID */ +#define UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_VMID_MASK 0x0000FFFF +#define UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_VMID_SHIFT 0 +/* RX queue DDP VMID select */ +#define UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_VMID_SEL_MASK 0xFFFF0000 +#define UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_VMID_SEL_SHIFT 16 + +#ifdef __cplusplus +} +#endif + +#endif /* __AL_HAL_UDMA_GEN_REG_H */ diff --git a/al_hal_udma_regs_m2s.h b/al_hal_udma_regs_m2s.h new file mode 100644 index 00000000000..06cea8db8f6 --- /dev/null +++ b/al_hal_udma_regs_m2s.h @@ -0,0 +1,1159 @@ +/*- +******************************************************************************* +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_udma_regs_m2s.h + * + * @brief C Header file for the UDMA M2S registers + * + */ + +#ifndef __AL_HAL_UDMA_M2S_REG_H +#define __AL_HAL_UDMA_M2S_REG_H + +#include "al_hal_plat_types.h" + +#ifdef __cplusplus +extern "C" { +#endif +/* +* Unit Registers +*/ + + + +struct udma_axi_m2s { + /* [0x0] Completion write master configuration */ + uint32_t comp_wr_cfg_1; + /* [0x4] Completion write master configuration */ + uint32_t comp_wr_cfg_2; + /* [0x8] Data read master configuration */ + uint32_t data_rd_cfg_1; + /* [0xc] Data read master configuration */ + uint32_t data_rd_cfg_2; + /* [0x10] Descriptor read master configuration */ + uint32_t desc_rd_cfg_1; + /* [0x14] Descriptor read master configuration */ + uint32_t desc_rd_cfg_2; + /* [0x18] Data read master configuration */ + uint32_t data_rd_cfg; + /* [0x1c] Descriptors read master configuration */ + uint32_t desc_rd_cfg_3; + /* [0x20] Descriptors write master configuration (completion) */ + uint32_t desc_wr_cfg_1; + /* [0x24] AXI outstanding configuration */ + uint32_t ostand_cfg; + uint32_t rsrvd[54]; +}; +struct udma_m2s { + /* + * [0x0] DMA state. + * 00 - No pending tasks + * 01 – Normal (active) + * 10 – Abort (error condition) + * 11 – Reserved + */ + uint32_t state; + /* [0x4] CPU request to change DMA state */ + uint32_t change_state; + uint32_t rsrvd_0; + /* + * [0xc] M2S DMA error log mask. + * Each error has an interrupt controller cause bit. + * This register determines if these errors cause the M2S DMA to log the + * error condition. + * 0 - Log is enabled. + * 1 - Log is masked. + */ + uint32_t err_log_mask; + uint32_t rsrvd_1; + /* + * [0x14] DMA header log. + * Sample the packet header that caused the error. + */ + uint32_t log_0; + /* + * [0x18] DMA header log. + * Sample the packet header that caused the error. + */ + uint32_t log_1; + /* + * [0x1c] DMA header log. + * Sample the packet header that caused the error. + */ + uint32_t log_2; + /* + * [0x20] DMA header log. + * Sample the packet header that caused the error. + */ + uint32_t log_3; + /* [0x24] DMA clear error log */ + uint32_t clear_err_log; + /* [0x28] M2S data FIFO status */ + uint32_t data_fifo_status; + /* [0x2c] M2S header FIFO status */ + uint32_t header_fifo_status; + /* [0x30] M2S unack FIFO status */ + uint32_t unack_fifo_status; + /* [0x34] Select queue for debug */ + uint32_t indirect_ctrl; + /* + * [0x38] M2S prefetch FIFO status. + * Status of the selected queue in M2S_indirect_ctrl + */ + uint32_t sel_pref_fifo_status; + /* + * [0x3c] M2S completion FIFO status. + * Status of the selected queue in M2S_indirect_ctrl + */ + uint32_t sel_comp_fifo_status; + /* + * [0x40] M2S rate limit status. + * Status of the selected queue in M2S_indirect_ctrl + */ + uint32_t sel_rate_limit_status; + /* + * [0x44] M2S DWRR scheduler status. + * Status of the selected queue in M2S_indirect_ctrl + */ + uint32_t sel_dwrr_status; + /* [0x48] M2S state machine and FIFO clear control */ + uint32_t clear_ctrl; + /* [0x4c] Misc Check enable */ + uint32_t check_en; + /* [0x50] M2S FIFO enable control, internal */ + uint32_t fifo_en; + /* [0x54] M2S packet length configuration */ + uint32_t cfg_len; + /* [0x58] Stream interface configuration */ + uint32_t stream_cfg; + uint32_t rsrvd[41]; +}; +struct udma_m2s_rd { + /* [0x0] M2S descriptor prefetch configuration */ + uint32_t desc_pref_cfg_1; + /* [0x4] M2S descriptor prefetch configuration */ + uint32_t desc_pref_cfg_2; + /* [0x8] M2S descriptor prefetch configuration */ + uint32_t desc_pref_cfg_3; + uint32_t rsrvd_0; + /* [0x10] Data burst read configuration */ + uint32_t data_cfg; + uint32_t rsrvd[11]; +}; +struct udma_m2s_dwrr { + /* [0x0] Tx DMA DWRR scheduler configuration */ + uint32_t cfg_sched; + /* [0x4] Token bucket rate limit control */ + uint32_t ctrl_deficit_cnt; + uint32_t rsrvd[14]; +}; +struct udma_m2s_rate_limiter { + /* [0x0] Token bucket rate limit configuration */ + uint32_t gen_cfg; + /* + * [0x4] Token bucket rate limit control. + * Controls the cycle counters. + */ + uint32_t ctrl_cycle_cnt; + /* + * [0x8] Token bucket rate limit control. + * Controls the token bucket counter. + */ + uint32_t ctrl_token; + uint32_t rsrvd[13]; +}; + +struct udma_rlimit_common { + /* [0x0] Token bucket configuration */ + uint32_t cfg_1s; + /* [0x4] Token bucket rate limit configuration */ + uint32_t cfg_cycle; + /* [0x8] Token bucket rate limit configuration */ + uint32_t cfg_token_size_1; + /* [0xc] Token bucket rate limit configuration */ + uint32_t cfg_token_size_2; + /* [0x10] Token bucket rate limit configuration */ + uint32_t sw_ctrl; + /* + * [0x14] Mask the different types of rate limiter. + * 0 - Rate limit is active. + * 1 - Rate limit is masked. + */ + uint32_t mask; +}; + +struct udma_m2s_stream_rate_limiter { + struct udma_rlimit_common rlimit; + uint32_t rsrvd[10]; +}; +struct udma_m2s_comp { + /* [0x0] Completion controller configuration */ + uint32_t cfg_1c; + /* [0x4] Completion controller coalescing configuration */ + uint32_t cfg_coal; + /* [0x8] Completion controller application acknowledge configuration */ + uint32_t cfg_application_ack; + uint32_t rsrvd[61]; +}; +struct udma_m2s_stat { + /* [0x0] Statistics counters configuration */ + uint32_t cfg_st; + /* [0x4] Counting number of descriptors with First-bit set. */ + uint32_t tx_pkt; + /* + * [0x8] Counting the net length of the data buffers [64-bit] + * Should be read before tx_bytes_high + */ + uint32_t tx_bytes_low; + /* + * [0xc] Counting the net length of the data buffers [64-bit], + * Should be read after tx_bytes_low (value is sampled when reading + * Should be read before tx_bytes_low + */ + uint32_t tx_bytes_high; + /* [0x10] Total number of descriptors read from the host memory */ + uint32_t prefed_desc; + /* [0x14] Number of packets read from the unack FIFO */ + uint32_t comp_pkt; + /* [0x18] Number of descriptors written into the completion ring */ + uint32_t comp_desc; + /* + * [0x1c] Number of acknowledged packets. + * (acknowledge received from the stream interface) + */ + uint32_t ack_pkts; + uint32_t rsrvd[56]; +}; +struct udma_m2s_feature { + /* + * [0x0] M2S Feature register. + * M2S instantiation parameters + */ + uint32_t reg_1; + /* [0x4] Reserved M2S feature register */ + uint32_t reg_2; + /* + * [0x8] M2S Feature register. + * M2S instantiation parameters + */ + uint32_t reg_3; + /* + * [0xc] M2S Feature register. + * M2S instantiation parameters + */ + uint32_t reg_4; + /* + * [0x10] M2S Feature register. + * M2S instantiation parameters + */ + uint32_t reg_5; + uint32_t rsrvd[59]; +}; +struct udma_m2s_q { + uint32_t rsrvd_0[8]; + /* [0x20] M2S descriptor ring configuration */ + uint32_t cfg; + /* [0x24] M2S descriptor ring status and information */ + uint32_t status; + /* [0x28] TX Descriptor Ring Base Pointer [31:4] */ + uint32_t tdrbp_low; + /* [0x2c] TX Descriptor Ring Base Pointer [63:32] */ + uint32_t tdrbp_high; + /* + * [0x30] TX Descriptor Ring Length[23:2] + */ + uint32_t tdrl; + /* [0x34] TX Descriptor Ring Head Pointer */ + uint32_t tdrhp; + /* [0x38] Tx Descriptor Tail Pointer increment */ + uint32_t tdrtp_inc; + /* [0x3c] Tx Descriptor Tail Pointer */ + uint32_t tdrtp; + /* [0x40] TX Descriptor Current Pointer */ + uint32_t tdcp; + /* [0x44] Tx Completion Ring Base Pointer [31:4] */ + uint32_t tcrbp_low; + /* [0x48] TX Completion Ring Base Pointer [63:32] */ + uint32_t tcrbp_high; + /* [0x4c] TX Completion Ring Head Pointer */ + uint32_t tcrhp; + /* + * [0x50] Tx Completion Ring Head Pointer internal (Before the + * coalescing FIFO) + */ + uint32_t tcrhp_internal; + uint32_t rsrvd_1[3]; + /* [0x60] Rate limit configuration */ + struct udma_rlimit_common rlimit; + uint32_t rsrvd_2[2]; + /* [0x80] DWRR scheduler configuration */ + uint32_t dwrr_cfg_1; + /* [0x84] DWRR scheduler configuration */ + uint32_t dwrr_cfg_2; + /* [0x88] DWRR scheduler configuration */ + uint32_t dwrr_cfg_3; + /* [0x8c] DWRR scheduler software control */ + uint32_t dwrr_sw_ctrl; + uint32_t rsrvd_3[4]; + /* [0xa0] Completion controller configuration */ + uint32_t comp_cfg; + uint32_t rsrvd_4[3]; + /* [0xb0] SW control */ + uint32_t q_sw_ctrl; + uint32_t rsrvd_5[3]; + /* [0xc0] Number of M2S Tx packets after the scheduler */ + uint32_t q_tx_pkt; + uint32_t rsrvd[975]; +}; + +struct udma_m2s_regs { + uint32_t rsrvd_0[64]; + struct udma_axi_m2s axi_m2s; /* [0x100] */ + struct udma_m2s m2s; /* [0x200] */ + struct udma_m2s_rd m2s_rd; /* [0x300] */ + struct udma_m2s_dwrr m2s_dwrr; /* [0x340] */ + struct udma_m2s_rate_limiter m2s_rate_limiter; /* [0x380] */ + struct udma_m2s_stream_rate_limiter m2s_stream_rate_limiter; /* [0x3c0] */ + struct udma_m2s_comp m2s_comp; /* [0x400] */ + struct udma_m2s_stat m2s_stat; /* [0x500] */ + struct udma_m2s_feature m2s_feature; /* [0x600] */ + uint32_t rsrvd_1[576]; + struct udma_m2s_q m2s_q[4]; /* [0x1000] */ +}; + + +/* +* Registers Fields +*/ + + +/**** comp_wr_cfg_1 register ****/ +/* AXI write ID (AWID) */ +#define UDMA_AXI_M2S_COMP_WR_CFG_1_AWID_MASK 0x000000FF +#define UDMA_AXI_M2S_COMP_WR_CFG_1_AWID_SHIFT 0 +/* Cache Type */ +#define UDMA_AXI_M2S_COMP_WR_CFG_1_AWCACHE_MASK 0x000F0000 +#define UDMA_AXI_M2S_COMP_WR_CFG_1_AWCACHE_SHIFT 16 +/* Burst type */ +#define UDMA_AXI_M2S_COMP_WR_CFG_1_AWBURST_MASK 0x03000000 +#define UDMA_AXI_M2S_COMP_WR_CFG_1_AWBURST_SHIFT 24 + +/**** comp_wr_cfg_2 register ****/ +/* User extension */ +#define UDMA_AXI_M2S_COMP_WR_CFG_2_AWUSER_MASK 0x000FFFFF +#define UDMA_AXI_M2S_COMP_WR_CFG_2_AWUSER_SHIFT 0 +/* Bus size, 128-bit */ +#define UDMA_AXI_M2S_COMP_WR_CFG_2_AWSIZE_MASK 0x00700000 +#define UDMA_AXI_M2S_COMP_WR_CFG_2_AWSIZE_SHIFT 20 +/* + * AXI Master QoS. + * Used for arbitration between AXI masters + */ +#define UDMA_AXI_M2S_COMP_WR_CFG_2_AWQOS_MASK 0x07000000 +#define UDMA_AXI_M2S_COMP_WR_CFG_2_AWQOS_SHIFT 24 +/* Protection Type */ +#define UDMA_AXI_M2S_COMP_WR_CFG_2_AWPROT_MASK 0x70000000 +#define UDMA_AXI_M2S_COMP_WR_CFG_2_AWPROT_SHIFT 28 + +/**** data_rd_cfg_1 register ****/ +/* AXI read ID (ARID) */ +#define UDMA_AXI_M2S_DATA_RD_CFG_1_ARID_MASK 0x000000FF +#define UDMA_AXI_M2S_DATA_RD_CFG_1_ARID_SHIFT 0 +/* Cache Type */ +#define UDMA_AXI_M2S_DATA_RD_CFG_1_ARCACHE_MASK 0x000F0000 +#define UDMA_AXI_M2S_DATA_RD_CFG_1_ARCACHE_SHIFT 16 +/* Burst type */ +#define UDMA_AXI_M2S_DATA_RD_CFG_1_ARBURST_MASK 0x03000000 +#define UDMA_AXI_M2S_DATA_RD_CFG_1_ARBURST_SHIFT 24 + +/**** data_rd_cfg_2 register ****/ +/* User extension */ +#define UDMA_AXI_M2S_DATA_RD_CFG_2_ARUSER_MASK 0x000FFFFF +#define UDMA_AXI_M2S_DATA_RD_CFG_2_ARUSER_SHIFT 0 +/* Bus size, 128-bit */ +#define UDMA_AXI_M2S_DATA_RD_CFG_2_ARSIZE_MASK 0x00700000 +#define UDMA_AXI_M2S_DATA_RD_CFG_2_ARSIZE_SHIFT 20 +/* + * AXI Master QoS. + * Used for arbitration between AXI masters + */ +#define UDMA_AXI_M2S_DATA_RD_CFG_2_ARQOS_MASK 0x07000000 +#define UDMA_AXI_M2S_DATA_RD_CFG_2_ARQOS_SHIFT 24 +/* Protection Type */ +#define UDMA_AXI_M2S_DATA_RD_CFG_2_ARPROT_MASK 0x70000000 +#define UDMA_AXI_M2S_DATA_RD_CFG_2_ARPROT_SHIFT 28 + +/**** desc_rd_cfg_1 register ****/ +/* AXI read ID (ARID) */ +#define UDMA_AXI_M2S_DESC_RD_CFG_1_ARID_MASK 0x000000FF +#define UDMA_AXI_M2S_DESC_RD_CFG_1_ARID_SHIFT 0 +/* Cache Type */ +#define UDMA_AXI_M2S_DESC_RD_CFG_1_ARCACHE_MASK 0x000F0000 +#define UDMA_AXI_M2S_DESC_RD_CFG_1_ARCACHE_SHIFT 16 +/* Burst type */ +#define UDMA_AXI_M2S_DESC_RD_CFG_1_ARBURST_MASK 0x03000000 +#define UDMA_AXI_M2S_DESC_RD_CFG_1_ARBURST_SHIFT 24 + +/**** desc_rd_cfg_2 register ****/ +/* User extension */ +#define UDMA_AXI_M2S_DESC_RD_CFG_2_ARUSER_MASK 0x000FFFFF +#define UDMA_AXI_M2S_DESC_RD_CFG_2_ARUSER_SHIFT 0 +/* Bus size, 128-bit */ +#define UDMA_AXI_M2S_DESC_RD_CFG_2_ARSIZE_MASK 0x00700000 +#define UDMA_AXI_M2S_DESC_RD_CFG_2_ARSIZE_SHIFT 20 +/* + * AXI Master QoS + * Used for arbitration between AXI masters + */ +#define UDMA_AXI_M2S_DESC_RD_CFG_2_ARQOS_MASK 0x07000000 +#define UDMA_AXI_M2S_DESC_RD_CFG_2_ARQOS_SHIFT 24 +/* Protection Type */ +#define UDMA_AXI_M2S_DESC_RD_CFG_2_ARPROT_MASK 0x70000000 +#define UDMA_AXI_M2S_DESC_RD_CFG_2_ARPROT_SHIFT 28 + +/**** data_rd_cfg register ****/ +/* + * Defines the maximum number of AXI beats for a single AXI burst. + * This value is used for a burst split decision. + */ +#define UDMA_AXI_M2S_DATA_RD_CFG_MAX_AXI_BEATS_MASK 0x000000FF +#define UDMA_AXI_M2S_DATA_RD_CFG_MAX_AXI_BEATS_SHIFT 0 +/* + * Enable breaking data read request. + * Aligned to max_AXI_beats when the total read size is less than max_AXI_beats + */ +#define UDMA_AXI_M2S_DATA_RD_CFG_ALWAYS_BREAK_ON_MAX_BOUDRY (1 << 16) + +/**** desc_rd_cfg_3 register ****/ +/* + * Defines the maximum number of AXI beats for a single AXI burst. + * This value is used for a burst split decision. + * Maximum burst size for reading data( in AXI beats, 128-bits) + * (default – 16 beats, 256 bytes) + */ +#define UDMA_AXI_M2S_DESC_RD_CFG_3_MAX_AXI_BEATS_MASK 0x000000FF +#define UDMA_AXI_M2S_DESC_RD_CFG_3_MAX_AXI_BEATS_SHIFT 0 +/* + * Enable breaking descriptor read request. + * Aligned to max_AXI_beats when the total read size is less than max_AXI_beats. + */ +#define UDMA_AXI_M2S_DESC_RD_CFG_3_ALWAYS_BREAK_ON_MAX_BOUDRY (1 << 16) + +/**** desc_wr_cfg_1 register ****/ +/* + * Defines the maximum number of AXI beats for a single AXI burst. + * This value is used for a burst split decision. + */ +#define UDMA_AXI_M2S_DESC_WR_CFG_1_MAX_AXI_BEATS_MASK 0x000000FF +#define UDMA_AXI_M2S_DESC_WR_CFG_1_MAX_AXI_BEATS_SHIFT 0 +/* + * Minimum burst for writing completion descriptors. + * Defined in AXI beats + * 4 Descriptors per beat. + * Value must be aligned to cache lines (64 bytes). + * Default value is 2 cache lines, 32 descriptors, 8 beats. + */ +#define UDMA_AXI_M2S_DESC_WR_CFG_1_MIN_AXI_BEATS_MASK 0x00FF0000 +#define UDMA_AXI_M2S_DESC_WR_CFG_1_MIN_AXI_BEATS_SHIFT 16 + +/**** ostand_cfg register ****/ +/* Maximum number of outstanding data reads to the AXI (AXI transactions) */ +#define UDMA_AXI_M2S_OSTAND_CFG_MAX_DATA_RD_MASK 0x0000003F +#define UDMA_AXI_M2S_OSTAND_CFG_MAX_DATA_RD_SHIFT 0 +/* + * Maximum number of outstanding descriptor reads to the AXI (AXI transactions) + */ +#define UDMA_AXI_M2S_OSTAND_CFG_MAX_DESC_RD_MASK 0x00003F00 +#define UDMA_AXI_M2S_OSTAND_CFG_MAX_DESC_RD_SHIFT 8 +/* + * Maximum number of outstanding descriptor writes to the AXI (AXI transactions) + */ +#define UDMA_AXI_M2S_OSTAND_CFG_MAX_COMP_REQ_MASK 0x003F0000 +#define UDMA_AXI_M2S_OSTAND_CFG_MAX_COMP_REQ_SHIFT 16 +/* + * Maximum number of outstanding data beats for descriptor write to AXI (AXI + * beats) + */ +#define UDMA_AXI_M2S_OSTAND_CFG_MAX_COMP_DATA_WR_MASK 0xFF000000 +#define UDMA_AXI_M2S_OSTAND_CFG_MAX_COMP_DATA_WR_SHIFT 24 + +/**** state register ****/ +/* Completion control */ +#define UDMA_M2S_STATE_COMP_CTRL_MASK 0x00000003 +#define UDMA_M2S_STATE_COMP_CTRL_SHIFT 0 +/* Stream interface */ +#define UDMA_M2S_STATE_STREAM_IF_MASK 0x00000030 +#define UDMA_M2S_STATE_STREAM_IF_SHIFT 4 +/* Data read control */ +#define UDMA_M2S_STATE_DATA_RD_CTRL_MASK 0x00000300 +#define UDMA_M2S_STATE_DATA_RD_CTRL_SHIFT 8 +/* Descriptor prefetch */ +#define UDMA_M2S_STATE_DESC_PREF_MASK 0x00003000 +#define UDMA_M2S_STATE_DESC_PREF_SHIFT 12 + +/**** change_state register ****/ +/* Start normal operation */ +#define UDMA_M2S_CHANGE_STATE_NORMAL (1 << 0) +/* Stop normal operation */ +#define UDMA_M2S_CHANGE_STATE_DIS (1 << 1) +/* + * Stop all machines. + * (Prefetch, scheduling, completion and stream interface) + */ +#define UDMA_M2S_CHANGE_STATE_ABORT (1 << 2) + +/**** err_log_mask register ****/ +/* + * Mismatch of packet serial number. + * (between first packet in the unacknowledged FIFO and received ack from the + * stream) + */ +#define UDMA_M2S_ERR_LOG_MASK_COMP_PKT_MISMATCH (1 << 0) +/* Parity error */ +#define UDMA_M2S_ERR_LOG_MASK_STREAM_AXI_PARITY (1 << 1) +/* AXI response error */ +#define UDMA_M2S_ERR_LOG_MASK_STREAM_AXI_RESPONSE (1 << 2) +/* AXI timeout (ack not received) */ +#define UDMA_M2S_ERR_LOG_MASK_STREAM_AXI_TOUT (1 << 3) +/* Parity error */ +#define UDMA_M2S_ERR_LOG_MASK_COMP_AXI_PARITY (1 << 4) +/* AXI response error */ +#define UDMA_M2S_ERR_LOG_MASK_COMP_AXI_RESPONSE (1 << 5) +/* AXI timeout */ +#define UDMA_M2S_ERR_LOG_MASK_COMP_AXI_TOUT (1 << 6) +/* Parity error */ +#define UDMA_M2S_ERR_LOG_MASK_DATA_AXI_PARITY (1 << 7) +/* AXI response error */ +#define UDMA_M2S_ERR_LOG_MASK_DATA_AXI_RESPONSE (1 << 8) +/* AXI timeout */ +#define UDMA_M2S_ERR_LOG_MASK_DATA_AXI_TOUT (1 << 9) +/* Parity error */ +#define UDMA_M2S_ERR_LOG_MASK_PREF_AXI_PARITY (1 << 10) +/* AXI response error */ +#define UDMA_M2S_ERR_LOG_MASK_PREF_AXI_RESPONSE (1 << 11) +/* AXI timeout */ +#define UDMA_M2S_ERR_LOG_MASK_PREF_AXI_TOUT (1 << 12) +/* Packet length error */ +#define UDMA_M2S_ERR_LOG_MASK_PREF_PKT_LEN_OVERFLOW (1 << 13) +/* Maximum number of descriptors per packet error */ +#define UDMA_M2S_ERR_LOG_MASK_PREF_MAX_DESC_CNT (1 << 14) +/* Error in first bit indication of the descriptor */ +#define UDMA_M2S_ERR_LOG_MASK_PREF_FIRST (1 << 15) +/* Error in last bit indication of the descriptor */ +#define UDMA_M2S_ERR_LOG_MASK_PREF_LAST (1 << 16) +/* Ring_ID error */ +#define UDMA_M2S_ERR_LOG_MASK_PREF_RING_ID (1 << 17) +/* Data buffer parity error */ +#define UDMA_M2S_ERR_LOG_MASK_DATA_BUFF_PARITY (1 << 18) +/* Internal error */ +#define UDMA_M2S_ERR_LOG_MASK_INTERNAL_MASK 0xFFF80000 +#define UDMA_M2S_ERR_LOG_MASK_INTERNAL_SHIFT 19 + +/**** clear_err_log register ****/ +/* Clear error log */ +#define UDMA_M2S_CLEAR_ERR_LOG_CLEAR (1 << 0) + +/**** data_fifo_status register ****/ +/* FIFO used indication */ +#define UDMA_M2S_DATA_FIFO_STATUS_USED_MASK 0x0000FFFF +#define UDMA_M2S_DATA_FIFO_STATUS_USED_SHIFT 0 +/* FIFO empty indication */ +#define UDMA_M2S_DATA_FIFO_STATUS_EMPTY (1 << 24) +/* FIFO full indication */ +#define UDMA_M2S_DATA_FIFO_STATUS_FULL (1 << 28) + +/**** header_fifo_status register ****/ +/* FIFO used indication */ +#define UDMA_M2S_HEADER_FIFO_STATUS_USED_MASK 0x0000FFFF +#define UDMA_M2S_HEADER_FIFO_STATUS_USED_SHIFT 0 +/* FIFO empty indication */ +#define UDMA_M2S_HEADER_FIFO_STATUS_EMPTY (1 << 24) +/* FIFO full indication */ +#define UDMA_M2S_HEADER_FIFO_STATUS_FULL (1 << 28) + +/**** unack_fifo_status register ****/ +/* FIFO used indication */ +#define UDMA_M2S_UNACK_FIFO_STATUS_USED_MASK 0x0000FFFF +#define UDMA_M2S_UNACK_FIFO_STATUS_USED_SHIFT 0 +/* FIFO empty indication */ +#define UDMA_M2S_UNACK_FIFO_STATUS_EMPTY (1 << 24) +/* FIFO full indication */ +#define UDMA_M2S_UNACK_FIFO_STATUS_FULL (1 << 28) + +/**** indirect_ctrl register ****/ +/* Selected queue for status read */ +#define UDMA_M2S_INDIRECT_CTRL_Q_NUM_MASK 0x00000FFF +#define UDMA_M2S_INDIRECT_CTRL_Q_NUM_SHIFT 0 + +/**** sel_pref_fifo_status register ****/ +/* FIFO used indication */ +#define UDMA_M2S_SEL_PREF_FIFO_STATUS_USED_MASK 0x0000FFFF +#define UDMA_M2S_SEL_PREF_FIFO_STATUS_USED_SHIFT 0 +/* FIFO empty indication */ +#define UDMA_M2S_SEL_PREF_FIFO_STATUS_EMPTY (1 << 24) +/* FIFO full indication */ +#define UDMA_M2S_SEL_PREF_FIFO_STATUS_FULL (1 << 28) + +/**** sel_comp_fifo_status register ****/ +/* FIFO used indication */ +#define UDMA_M2S_SEL_COMP_FIFO_STATUS_USED_MASK 0x0000FFFF +#define UDMA_M2S_SEL_COMP_FIFO_STATUS_USED_SHIFT 0 +/* FIFO empty indication */ +#define UDMA_M2S_SEL_COMP_FIFO_STATUS_EMPTY (1 << 24) +/* FIFO full indication */ +#define UDMA_M2S_SEL_COMP_FIFO_STATUS_FULL (1 << 28) + +/**** sel_rate_limit_status register ****/ +/* Token counter */ +#define UDMA_M2S_SEL_RATE_LIMIT_STATUS_TOKEN_CNT_MASK 0x00FFFFFF +#define UDMA_M2S_SEL_RATE_LIMIT_STATUS_TOKEN_CNT_SHIFT 0 + +/**** sel_dwrr_status register ****/ +/* Deficit counter */ +#define UDMA_M2S_SEL_DWRR_STATUS_DEFICIT_CNT_MASK 0x00FFFFFF +#define UDMA_M2S_SEL_DWRR_STATUS_DEFICIT_CNT_SHIFT 0 + +/**** cfg_len register ****/ +/* Maximum packet size for the M2S */ +#define UDMA_M2S_CFG_LEN_MAX_PKT_SIZE_MASK 0x000FFFFF +#define UDMA_M2S_CFG_LEN_MAX_PKT_SIZE_SHIFT 0 +/* + * Length encoding for 64K. + * 0 - length 0x0000 = 0 + * 1 - length 0x0000 = 64k + */ +#define UDMA_M2S_CFG_LEN_ENCODE_64K (1 << 24) + +/**** stream_cfg register ****/ +/* + * Disables the stream interface operation. + * Changing to 1 stops at the end of packet transmission. + */ +#define UDMA_M2S_STREAM_CFG_DISABLE (1 << 0) +/* + * Configuration of the stream FIFO read control. + * 0 - Cut through + * 1 - Threshold based + */ +#define UDMA_M2S_STREAM_CFG_RD_MODE (1 << 1) +/* Minimum number of beats to start packet transmission. */ +#define UDMA_M2S_STREAM_CFG_RD_TH_MASK 0x0003FF00 +#define UDMA_M2S_STREAM_CFG_RD_TH_SHIFT 8 + +/**** desc_pref_cfg_1 register ****/ +/* Size of the descriptor prefetch FIFO (in descriptors) */ +#define UDMA_M2S_RD_DESC_PREF_CFG_1_FIFO_DEPTH_MASK 0x000000FF +#define UDMA_M2S_RD_DESC_PREF_CFG_1_FIFO_DEPTH_SHIFT 0 + +/**** desc_pref_cfg_2 register ****/ +/* Maximum number of descriptors per packet */ +#define UDMA_M2S_RD_DESC_PREF_CFG_2_MAX_DESC_PER_PKT_MASK 0x0000001F +#define UDMA_M2S_RD_DESC_PREF_CFG_2_MAX_DESC_PER_PKT_SHIFT 0 +/* + * Force RR arbitration in the prefetch arbiter. + * 0 -Standard arbitration based on queue QoS + * 1 - Force Round Robin arbitration + */ +#define UDMA_M2S_RD_DESC_PREF_CFG_2_PREF_FORCE_RR (1 << 16) + +/**** desc_pref_cfg_3 register ****/ +/* + * Minimum descriptor burst size when prefetch FIFO level is below the + * descriptor prefetch threshold + * (must be 1) + */ +#define UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_MASK 0x0000000F +#define UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_SHIFT 0 +/* + * Minimum descriptor burst size when prefetch FIFO level is above the + * descriptor prefetch threshold + */ +#define UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_MASK 0x000000F0 +#define UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_SHIFT 4 +/* + * Descriptor fetch threshold. + * Used as a threshold to determine the allowed minimum descriptor burst size. + * (Must be at least max_desc_per_pkt) + */ +#define UDMA_M2S_RD_DESC_PREF_CFG_3_PREF_THR_MASK 0x0000FF00 +#define UDMA_M2S_RD_DESC_PREF_CFG_3_PREF_THR_SHIFT 8 + +/**** data_cfg register ****/ +/* + * Maximum number of data beats in the data read FIFO. + * Defined based on data FIFO size + * (default FIFO size 2KB → 128 beats) + */ +#define UDMA_M2S_RD_DATA_CFG_DATA_FIFO_DEPTH_MASK 0x000003FF +#define UDMA_M2S_RD_DATA_CFG_DATA_FIFO_DEPTH_SHIFT 0 +/* + * Maximum number of packets in the data read FIFO. + * Defined based on header FIFO size + */ +#define UDMA_M2S_RD_DATA_CFG_MAX_PKT_LIMIT_MASK 0x00FF0000 +#define UDMA_M2S_RD_DATA_CFG_MAX_PKT_LIMIT_SHIFT 16 + +/**** cfg_sched register ****/ +/* + * Enable the DWRR scheduler. + * If this bit is 0, queues with same QoS will be served with RR scheduler. + */ +#define UDMA_M2S_DWRR_CFG_SCHED_EN_DWRR (1 << 0) +/* + * Scheduler operation mode. + * 0 - Byte mode + * 1 - Packet mode + */ +#define UDMA_M2S_DWRR_CFG_SCHED_PKT_MODE_EN (1 << 4) +/* + * Enable incrementing the weight factor between DWRR iterations. + * 00 - Don't increase the increment factor. + * 01 - Increment once + * 10 - Increment exponential + * 11 - Reserved + */ +#define UDMA_M2S_DWRR_CFG_SCHED_WEIGHT_INC_MASK 0x00000300 +#define UDMA_M2S_DWRR_CFG_SCHED_WEIGHT_INC_SHIFT 8 +/* + * Increment factor power of 2. + * 7 --> 128 bytes + * This is the factor used to multiply the weight. + */ +#define UDMA_M2S_DWRR_CFG_SCHED_INC_FACTOR_MASK 0x000F0000 +#define UDMA_M2S_DWRR_CFG_SCHED_INC_FACTOR_SHIFT 16 + +/**** ctrl_deficit_cnt register ****/ +/* + * Init value for the deficit counter. + * Initializes the deficit counters of all queues to this value any time this + * register is written. + */ +#define UDMA_M2S_DWRR_CTRL_DEFICIT_CNT_INIT_MASK 0x00FFFFFF +#define UDMA_M2S_DWRR_CTRL_DEFICIT_CNT_INIT_SHIFT 0 + +/**** gen_cfg register ****/ +/* Size of the basic token fill cycle, system clock cycles */ +#define UDMA_M2S_RATE_LIMITER_GEN_CFG_SHORT_CYCLE_SIZE_MASK 0x0000FFFF +#define UDMA_M2S_RATE_LIMITER_GEN_CFG_SHORT_CYCLE_SIZE_SHIFT 0 +/* + * Rate limiter operation mode. + * 0 - Byte mode + * 1 - Packet mode + */ +#define UDMA_M2S_RATE_LIMITER_GEN_CFG_PKT_MODE_EN (1 << 24) + +/**** ctrl_cycle_cnt register ****/ +/* Reset the short and long cycle counters. */ +#define UDMA_M2S_RATE_LIMITER_CTRL_CYCLE_CNT_RST (1 << 0) + +/**** ctrl_token register ****/ +/* + * Init value for the token counter. + * Initializes the token counters of all queues to this value any time this + * register is written. + */ +#define UDMA_M2S_RATE_LIMITER_CTRL_TOKEN_RST_MASK 0x00FFFFFF +#define UDMA_M2S_RATE_LIMITER_CTRL_TOKEN_RST_SHIFT 0 + +/**** cfg_1s register ****/ +/* Maximum number of accumulated bytes in the token counter */ +#define UDMA_M2S_STREAM_RATE_LIMITER_CFG_1S_MAX_BURST_SIZE_MASK 0x00FFFFFF +#define UDMA_M2S_STREAM_RATE_LIMITER_CFG_1S_MAX_BURST_SIZE_SHIFT 0 +/* Enable the rate limiter. */ +#define UDMA_M2S_STREAM_RATE_LIMITER_CFG_1S_EN (1 << 24) +/* Stop token fill. */ +#define UDMA_M2S_STREAM_RATE_LIMITER_CFG_1S_PAUSE (1 << 25) + +/**** cfg_cycle register ****/ +/* Number of short cycles between token fills */ +#define UDMA_M2S_STREAM_RATE_LIMITER_CFG_CYCLE_LONG_CYCLE_SIZE_MASK 0x0000FFFF +#define UDMA_M2S_STREAM_RATE_LIMITER_CFG_CYCLE_LONG_CYCLE_SIZE_SHIFT 0 + +/**** cfg_token_size_1 register ****/ +/* Number of bits to add in each long cycle */ +#define UDMA_M2S_STREAM_RATE_LIMITER_CFG_TOKEN_SIZE_1_LONG_CYCLE_MASK 0x0007FFFF +#define UDMA_M2S_STREAM_RATE_LIMITER_CFG_TOKEN_SIZE_1_LONG_CYCLE_SHIFT 0 + +/**** cfg_token_size_2 register ****/ +/* Number of bits to add in each short cycle */ +#define UDMA_M2S_STREAM_RATE_LIMITER_CFG_TOKEN_SIZE_2_SHORT_CYCLE_MASK 0x0007FFFF +#define UDMA_M2S_STREAM_RATE_LIMITER_CFG_TOKEN_SIZE_2_SHORT_CYCLE_SHIFT 0 + +/**** sw_ctrl register ****/ +/* Reset the token bucket counter. */ +#define UDMA_M2S_STREAM_RATE_LIMITER_SW_CTRL_RST_TOKEN_CNT (1 << 0) + +/**** mask register ****/ +/* Mask the external rate limiter. */ +#define UDMA_M2S_STREAM_RATE_LIMITER_MASK_EXTERNAL_RATE_LIMITER (1 << 0) +/* Mask the internal rate limiter. */ +#define UDMA_M2S_STREAM_RATE_LIMITER_MASK_INTERNAL_RATE_LIMITER (1 << 1) +/* Mask the external application pause interface. */ +#define UDMA_M2S_STREAM_RATE_LIMITER_MASK_EXTERNAL_PAUSE (1 << 3) + +/**** cfg_1c register ****/ +/* + * Completion FIFO size + * (descriptors per queue) + */ +#define UDMA_M2S_COMP_CFG_1C_COMP_FIFO_DEPTH_MASK 0x000000FF +#define UDMA_M2S_COMP_CFG_1C_COMP_FIFO_DEPTH_SHIFT 0 +/* + * Unacknowledged FIFO size. + * (descriptors) + */ +#define UDMA_M2S_COMP_CFG_1C_UNACK_FIFO_DEPTH_MASK 0x0001FF00 +#define UDMA_M2S_COMP_CFG_1C_UNACK_FIFO_DEPTH_SHIFT 8 +/* + * Enable promotion. + * Enable the promotion of the current queue in progress for the completion + * write scheduler. + */ +#define UDMA_M2S_COMP_CFG_1C_Q_PROMOTION (1 << 24) +/* Force RR arbitration in the completion arbiter */ +#define UDMA_M2S_COMP_CFG_1C_FORCE_RR (1 << 25) +/* Minimum number of free completion entries to qualify for promotion */ +#define UDMA_M2S_COMP_CFG_1C_Q_FREE_MIN_MASK 0xF0000000 +#define UDMA_M2S_COMP_CFG_1C_Q_FREE_MIN_SHIFT 28 + +/**** cfg_application_ack register ****/ +/* + * Acknowledge timeout timer. + * ACK from the application through the stream interface) + */ +#define UDMA_M2S_COMP_CFG_APPLICATION_ACK_TOUT_MASK 0x00FFFFFF +#define UDMA_M2S_COMP_CFG_APPLICATION_ACK_TOUT_SHIFT 0 + +/**** cfg_st register ****/ +/* Use additional length value for all statistics counters. */ +#define UDMA_M2S_STAT_CFG_ST_USE_EXTRA_LEN (1 << 0) + +/**** reg_1 register ****/ +/* + * Read the size of the descriptor prefetch FIFO + * (descriptors). + */ +#define UDMA_M2S_FEATURE_REG_1_DESC_PREFERCH_FIFO_DEPTH_MASK 0x000000FF +#define UDMA_M2S_FEATURE_REG_1_DESC_PREFERCH_FIFO_DEPTH_SHIFT 0 + +/**** reg_3 register ****/ +/* + * Maximum number of data beats in the data read FIFO. + * Defined based on data FIFO size + * (default FIFO size 2KB → 128 beats) + */ +#define UDMA_M2S_FEATURE_REG_3_DATA_FIFO_DEPTH_MASK 0x000003FF +#define UDMA_M2S_FEATURE_REG_3_DATA_FIFO_DEPTH_SHIFT 0 +/* + * Maximum number of packets in the data read FIFO. + * Defined based on header FIFO size + */ +#define UDMA_M2S_FEATURE_REG_3_DATA_RD_MAX_PKT_LIMIT_MASK 0x00FF0000 +#define UDMA_M2S_FEATURE_REG_3_DATA_RD_MAX_PKT_LIMIT_SHIFT 16 + +/**** reg_4 register ****/ +/* + * Size of the completion FIFO of each queue + * (words) + */ +#define UDMA_M2S_FEATURE_REG_4_COMP_FIFO_DEPTH_MASK 0x000000FF +#define UDMA_M2S_FEATURE_REG_4_COMP_FIFO_DEPTH_SHIFT 0 +/* Size of the unacknowledged FIFO (descriptors) */ +#define UDMA_M2S_FEATURE_REG_4_COMP_UNACK_FIFO_DEPTH_MASK 0x0001FF00 +#define UDMA_M2S_FEATURE_REG_4_COMP_UNACK_FIFO_DEPTH_SHIFT 8 + +/**** reg_5 register ****/ +/* Maximum number of outstanding data reads to AXI */ +#define UDMA_M2S_FEATURE_REG_5_MAX_DATA_RD_OSTAND_MASK 0x0000003F +#define UDMA_M2S_FEATURE_REG_5_MAX_DATA_RD_OSTAND_SHIFT 0 +/* Maximum number of outstanding descriptor reads to AXI */ +#define UDMA_M2S_FEATURE_REG_5_MAX_DESC_RD_OSTAND_MASK 0x00003F00 +#define UDMA_M2S_FEATURE_REG_5_MAX_DESC_RD_OSTAND_SHIFT 8 +/* + * Maximum number of outstanding descriptor writes to AXI. + * (AXI transactions) + */ +#define UDMA_M2S_FEATURE_REG_5_MAX_COMP_REQ_MASK 0x003F0000 +#define UDMA_M2S_FEATURE_REG_5_MAX_COMP_REQ_SHIFT 16 +/* + * Maximum number of outstanding data beats for descriptor write to AXI. + * (AXI beats) + */ +#define UDMA_M2S_FEATURE_REG_5_MAX_COMP_DATA_WR_OSTAND_MASK 0xFF000000 +#define UDMA_M2S_FEATURE_REG_5_MAX_COMP_DATA_WR_OSTAND_SHIFT 24 + +/**** cfg register ****/ +/* + * Length offset to be used for each packet from this queue. + * (length offset is used for the scheduler and rate limiter). + */ +#define UDMA_M2S_Q_CFG_PKT_LEN_OFFSET_MASK 0x0000FFFF +#define UDMA_M2S_Q_CFG_PKT_LEN_OFFSET_SHIFT 0 +/* + * Enable operation of this queue. + * Start prefetch. + */ +#define UDMA_M2S_Q_CFG_EN_PREF (1 << 16) +/* + * Enable operation of this queue. + * Start scheduling. + */ +#define UDMA_M2S_Q_CFG_EN_SCHEDULING (1 << 17) +/* Allow prefetch of less than minimum prefetch burst size. */ +#define UDMA_M2S_Q_CFG_ALLOW_LT_MIN_PREF (1 << 20) +/* Configure the AXI AWCACHE for completion write. */ +#define UDMA_M2S_Q_CFG_AXI_AWCACHE_COMP_MASK 0x0F000000 +#define UDMA_M2S_Q_CFG_AXI_AWCACHE_COMP_SHIFT 24 +/* + * AXI QoS for the selected queue. + * This value is used in AXI transactions associated with this queue and the + * prefetch and completion arbiters. + */ +#define UDMA_M2S_Q_CFG_AXI_QOS_MASK 0x70000000 +#define UDMA_M2S_Q_CFG_AXI_QOS_SHIFT 28 + +/**** status register ****/ +/* Indicates how many entries are used in the queue */ +#define UDMA_M2S_Q_STATUS_Q_USED_MASK 0x01FFFFFF +#define UDMA_M2S_Q_STATUS_Q_USED_SHIFT 0 +/* + * prefetch status + * 0 – prefetch operation is stopped + * 1 – prefetch is operational + */ +#define UDMA_M2S_Q_STATUS_PREFETCH (1 << 28) +/* + * Queue scheduler status + * 0 – queue is not active and not participating in scheduling + * 1 – queue is active and participating in the scheduling process + */ +#define UDMA_M2S_Q_STATUS_SCHEDULER (1 << 29) +/* Queue is suspended due to DMB */ +#define UDMA_M2S_Q_STATUS_Q_DMB (1 << 30) +/* + * Queue full indication. + * (used by the host when head pointer equals tail pointer). + */ +#define UDMA_M2S_Q_STATUS_Q_FULL (1 << 31) +/* + * M2S Descriptor Ring Base address [31:4]. + * Value of the base address of the M2S descriptor ring + * [3:0] - 0 - 16B alignment is enforced + * ([11:4] should be 0 for 4KB alignment) + */ +#define UDMA_M2S_Q_TDRBP_LOW_ADDR_MASK 0xFFFFFFF0 +#define UDMA_M2S_Q_TDRBP_LOW_ADDR_SHIFT 4 + +/**** TDRL register ****/ +/* + * Length of the descriptor ring. + * (descriptors) + * Associated with the ring base address, ends at maximum burst size alignment. + */ +#define UDMA_M2S_Q_TDRL_OFFSET_MASK 0x00FFFFFF +#define UDMA_M2S_Q_TDRL_OFFSET_SHIFT 0 + +/**** TDRHP register ****/ +/* + * Relative offset of the next descriptor that needs to be read into the + * prefetch FIFO. + * Incremented when the DMA reads valid descriptors from the host memory to the + * prefetch FIFO. + * Note that this is the offset in # of descriptors and not in byte address. + */ +#define UDMA_M2S_Q_TDRHP_OFFSET_MASK 0x00FFFFFF +#define UDMA_M2S_Q_TDRHP_OFFSET_SHIFT 0 +/* Ring ID */ +#define UDMA_M2S_Q_TDRHP_RING_ID_MASK 0xC0000000 +#define UDMA_M2S_Q_TDRHP_RING_ID_SHIFT 30 + +/**** TDRTP_inc register ****/ +/* Increments the value in Q_TDRTP (descriptors) */ +#define UDMA_M2S_Q_TDRTP_INC_VAL_MASK 0x00FFFFFF +#define UDMA_M2S_Q_TDRTP_INC_VAL_SHIFT 0 + +/**** TDRTP register ****/ +/* + * Relative offset of the next free descriptor in the host memory. + * Note that this is the offset in # of descriptors and not in byte address. + */ +#define UDMA_M2S_Q_TDRTP_OFFSET_MASK 0x00FFFFFF +#define UDMA_M2S_Q_TDRTP_OFFSET_SHIFT 0 +/* Ring ID */ +#define UDMA_M2S_Q_TDRTP_RING_ID_MASK 0xC0000000 +#define UDMA_M2S_Q_TDRTP_RING_ID_SHIFT 30 + +/**** TDCP register ****/ +/* + * Relative offset of the first descriptor in the prefetch FIFO. + * This is the next descriptor that will be read by the scheduler. + */ +#define UDMA_M2S_Q_TDCP_OFFSET_MASK 0x00FFFFFF +#define UDMA_M2S_Q_TDCP_OFFSET_SHIFT 0 +/* Ring ID */ +#define UDMA_M2S_Q_TDCP_RING_ID_MASK 0xC0000000 +#define UDMA_M2S_Q_TDCP_RING_ID_SHIFT 30 +/* + * M2S Descriptor Ring Base address [31:4]. + * Value of the base address of the M2S descriptor ring + * [3:0] - 0 - 16B alignment is enforced + * ([11:4] should be 0 for 4KB alignment) + * NOTE: + * Length of the descriptor ring (in descriptors) associated with the ring base + * address. Ends at maximum burst size alignment. + */ +#define UDMA_M2S_Q_TCRBP_LOW_ADDR_MASK 0xFFFFFFF0 +#define UDMA_M2S_Q_TCRBP_LOW_ADDR_SHIFT 4 + +/**** TCRHP register ****/ +/* + * Relative offset of the next descriptor that needs to be updated by the + * completion controller. + * Note: This is in descriptors and not in byte address. + */ +#define UDMA_M2S_Q_TCRHP_OFFSET_MASK 0x00FFFFFF +#define UDMA_M2S_Q_TCRHP_OFFSET_SHIFT 0 +/* Ring ID */ +#define UDMA_M2S_Q_TCRHP_RING_ID_MASK 0xC0000000 +#define UDMA_M2S_Q_TCRHP_RING_ID_SHIFT 30 + +/**** TCRHP_internal register ****/ +/* + * Relative offset of the next descriptor that needs to be updated by the + * completion controller. + * Note: This is in descriptors and not in byte address. + */ +#define UDMA_M2S_Q_TCRHP_INTERNAL_OFFSET_MASK 0x00FFFFFF +#define UDMA_M2S_Q_TCRHP_INTERNAL_OFFSET_SHIFT 0 +/* Ring ID */ +#define UDMA_M2S_Q_TCRHP_INTERNAL_RING_ID_MASK 0xC0000000 +#define UDMA_M2S_Q_TCRHP_INTERNAL_RING_ID_SHIFT 30 + +/**** rate_limit_cfg_1 register ****/ +/* Maximum number of accumulated bytes in the token counter. */ +#define UDMA_M2S_Q_RATE_LIMIT_CFG_1_MAX_BURST_SIZE_MASK 0x00FFFFFF +#define UDMA_M2S_Q_RATE_LIMIT_CFG_1_MAX_BURST_SIZE_SHIFT 0 +/* Enable the rate limiter. */ +#define UDMA_M2S_Q_RATE_LIMIT_CFG_1_EN (1 << 24) +/* Stop token fill. */ +#define UDMA_M2S_Q_RATE_LIMIT_CFG_1_PAUSE (1 << 25) + +/**** rate_limit_cfg_cycle register ****/ +/* Number of short cycles between token fills */ +#define UDMA_M2S_Q_RATE_LIMIT_CFG_CYCLE_LONG_CYCLE_SIZE_MASK 0x0000FFFF +#define UDMA_M2S_Q_RATE_LIMIT_CFG_CYCLE_LONG_CYCLE_SIZE_SHIFT 0 + +/**** rate_limit_cfg_token_size_1 register ****/ +/* Number of bits to add in each long cycle */ +#define UDMA_M2S_Q_RATE_LIMIT_CFG_TOKEN_SIZE_1_LONG_CYCLE_MASK 0x0007FFFF +#define UDMA_M2S_Q_RATE_LIMIT_CFG_TOKEN_SIZE_1_LONG_CYCLE_SHIFT 0 + +/**** rate_limit_cfg_token_size_2 register ****/ +/* Number of bits to add in each cycle */ +#define UDMA_M2S_Q_RATE_LIMIT_CFG_TOKEN_SIZE_2_SHORT_CYCLE_MASK 0x0007FFFF +#define UDMA_M2S_Q_RATE_LIMIT_CFG_TOKEN_SIZE_2_SHORT_CYCLE_SHIFT 0 + +/**** rate_limit_sw_ctrl register ****/ +/* Reset the token bucket counter. */ +#define UDMA_M2S_Q_RATE_LIMIT_SW_CTRL_RST_TOKEN_CNT (1 << 0) + +/**** rate_limit_mask register ****/ +/* Mask the external rate limiter. */ +#define UDMA_M2S_Q_RATE_LIMIT_MASK_EXTERNAL_RATE_LIMITER (1 << 0) +/* Mask the internal rate limiter. */ +#define UDMA_M2S_Q_RATE_LIMIT_MASK_INTERNAL_RATE_LIMITER (1 << 1) +/* + * Mask the internal pause mechanism for DMB. + * (Data Memory Barrier). + */ +#define UDMA_M2S_Q_RATE_LIMIT_MASK_INTERNAL_PAUSE_DMB (1 << 2) +/* Mask the external application pause interface. */ +#define UDMA_M2S_Q_RATE_LIMIT_MASK_EXTERNAL_PAUSE (1 << 3) + +/**** dwrr_cfg_1 register ****/ +/* Maximum number of accumulated bytes in the deficit counter */ +#define UDMA_M2S_Q_DWRR_CFG_1_MAX_DEFICIT_CNT_SIZE_MASK 0x00FFFFFF +#define UDMA_M2S_Q_DWRR_CFG_1_MAX_DEFICIT_CNT_SIZE_SHIFT 0 +/* Bypass the DWRR. */ +#define UDMA_M2S_Q_DWRR_CFG_1_STRICT (1 << 24) +/* Stop deficit counter increment. */ +#define UDMA_M2S_Q_DWRR_CFG_1_PAUSE (1 << 25) + +/**** dwrr_cfg_2 register ****/ +/* + * Value for the queue QoS. + * Queues with the same QoS value are scheduled with RR/DWRR. + * Only LOG(number of queues) is used. + */ +#define UDMA_M2S_Q_DWRR_CFG_2_Q_QOS_MASK 0x000000FF +#define UDMA_M2S_Q_DWRR_CFG_2_Q_QOS_SHIFT 0 + +/**** dwrr_cfg_3 register ****/ +/* Queue weight */ +#define UDMA_M2S_Q_DWRR_CFG_3_WEIGHT_MASK 0x000000FF +#define UDMA_M2S_Q_DWRR_CFG_3_WEIGHT_SHIFT 0 + +/**** dwrr_sw_ctrl register ****/ +/* Reset the DWRR deficit counter. */ +#define UDMA_M2S_Q_DWRR_SW_CTRL_RST_CNT (1 << 0) + +/**** comp_cfg register ****/ +/* Enable writing to the completion ring */ +#define UDMA_M2S_Q_COMP_CFG_EN_COMP_RING_UPDATE (1 << 0) +/* Disable the completion coalescing function. */ +#define UDMA_M2S_Q_COMP_CFG_DIS_COMP_COAL (1 << 1) + +/**** q_sw_ctrl register ****/ +/* + * Reset the DMB hardware barrier + * (enable queue operation). + */ +#define UDMA_M2S_Q_SW_CTRL_RST_DMB (1 << 0) +/* Reset the tail pointer hardware. */ +#define UDMA_M2S_Q_SW_CTRL_RST_TAIL_PTR (1 << 1) +/* Reset the head pointer hardware. */ +#define UDMA_M2S_Q_SW_CTRL_RST_HEAD_PTR (1 << 2) +/* Reset the current pointer hardware. */ +#define UDMA_M2S_Q_SW_CTRL_RST_CURRENT_PTR (1 << 3) +/* Reset the queue */ +#define UDMA_M2S_Q_SW_CTRL_RST_Q (1 << 8) + +#ifdef __cplusplus +} +#endif + +#endif /* __AL_HAL_UDMA_M2S_REG_H */ diff --git a/al_hal_udma_regs_s2m.h b/al_hal_udma_regs_s2m.h new file mode 100644 index 00000000000..4b3149b97ae --- /dev/null +++ b/al_hal_udma_regs_s2m.h @@ -0,0 +1,998 @@ +/*- +******************************************************************************* +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_udma_regs_s2m.h + * + * @brief C Header file for the UDMA S2M registers + * + */ + +#ifndef __AL_HAL_UDMA_S2M_REG_H +#define __AL_HAL_UDMA_S2M_REG_H + +#include "al_hal_plat_types.h" + +#ifdef __cplusplus +extern "C" { +#endif +/* +* Unit Registers +*/ + + + +struct udma_axi_s2m { + /* [0x0] Data write master configuration */ + uint32_t data_wr_cfg_1; + /* [0x4] Data write master configuration */ + uint32_t data_wr_cfg_2; + /* [0x8] Descriptor read master configuration */ + uint32_t desc_rd_cfg_4; + /* [0xc] Descriptor read master configuration */ + uint32_t desc_rd_cfg_5; + /* [0x10] Completion write master configuration */ + uint32_t comp_wr_cfg_1; + /* [0x14] Completion write master configuration */ + uint32_t comp_wr_cfg_2; + /* [0x18] Data write master configuration */ + uint32_t data_wr_cfg; + /* [0x1c] Descriptors read master configuration */ + uint32_t desc_rd_cfg_3; + /* [0x20] Completion descriptors write master configuration */ + uint32_t desc_wr_cfg_1; + /* [0x24] AXI outstanding read configuration */ + uint32_t ostand_cfg_rd; + /* [0x28] AXI outstanding write configuration */ + uint32_t ostand_cfg_wr; + uint32_t rsrvd[53]; +}; +struct udma_s2m { + /* + * [0x0] DMA state + * 00 - No pending tasks + * 01 – Normal (active) + * 10 – Abort (error condition) + * 11 – Reserved + */ + uint32_t state; + /* [0x4] CPU request to change DMA state */ + uint32_t change_state; + uint32_t rsrvd_0; + /* + * [0xc] S2M DMA error log mask. + * Each error has an interrupt controller cause bit. + * This register determines if these errors cause the S2M DMA to log the + * error condition. + * 0 - Log is enable + * 1 - Log is masked. + */ + uint32_t err_log_mask; + uint32_t rsrvd_1; + /* + * [0x14] DMA header log + * Sample the packet header that caused the error + */ + uint32_t log_0; + /* + * [0x18] DMA header log + * Sample the packet header that caused the error. + */ + uint32_t log_1; + /* + * [0x1c] DMA header log + * Sample the packet header that caused the error. + */ + uint32_t log_2; + /* + * [0x20] DMA header log + * Sample the packet header that caused the error + */ + uint32_t log_3; + /* [0x24] DMA clear error log */ + uint32_t clear_err_log; + /* [0x28] S2M stream data FIFO status */ + uint32_t s_data_fifo_status; + /* [0x2c] S2M stream header FIFO status */ + uint32_t s_header_fifo_status; + /* [0x30] S2M AXI data FIFO status */ + uint32_t axi_data_fifo_status; + /* [0x34] S2M unack FIFO status */ + uint32_t unack_fifo_status; + /* [0x38] Select queue for debug */ + uint32_t indirect_ctrl; + /* + * [0x3c] S2M prefetch FIFO status. + * Status of the selected queue in S2M_indirect_ctrl + */ + uint32_t sel_pref_fifo_status; + /* + * [0x40] S2M completion FIFO status. + * Status of the selected queue in S2M_indirect_ctrl + */ + uint32_t sel_comp_fifo_status; + /* [0x44] S2M state machine and FIFO clear control */ + uint32_t clear_ctrl; + /* [0x48] S2M Misc Check enable */ + uint32_t check_en; + /* [0x4c] S2M FIFO enable control, internal */ + uint32_t fifo_en; + /* [0x50] Stream interface configuration */ + uint32_t stream_cfg; + uint32_t rsrvd[43]; +}; +struct udma_s2m_rd { + /* [0x0] S2M descriptor prefetch configuration */ + uint32_t desc_pref_cfg_1; + /* [0x4] S2M descriptor prefetch configuration */ + uint32_t desc_pref_cfg_2; + /* [0x8] S2M descriptor prefetch configuration */ + uint32_t desc_pref_cfg_3; + /* [0xc] S2M descriptor prefetch configuration */ + uint32_t desc_pref_cfg_4; + uint32_t rsrvd[12]; +}; +struct udma_s2m_wr { + /* [0x0] Stream data FIFO configuration */ + uint32_t data_cfg_1; + /* [0x4] Data write configuration */ + uint32_t data_cfg_2; + uint32_t rsrvd[14]; +}; +struct udma_s2m_comp { + /* [0x0] Completion controller configuration */ + uint32_t cfg_1c; + /* [0x4] Completion controller configuration */ + uint32_t cfg_2c; + uint32_t rsrvd_0; + /* [0xc] Completion controller application acknowledge configuration */ + uint32_t cfg_application_ack; + uint32_t rsrvd[12]; +}; +struct udma_s2m_stat { + uint32_t rsrvd_0; + /* [0x4] Number of dropped packets */ + uint32_t drop_pkt; + /* + * [0x8] Counting the net length of the data buffers [64-bit] + * Should be read before rx_bytes_high + */ + uint32_t rx_bytes_low; + /* + * [0xc] Counting the net length of the data buffers [64-bit] + * Should be read after tx_bytes_low (value is sampled when reading + * Should be read before rx_bytes_low + */ + uint32_t rx_bytes_high; + /* [0x10] Total number of descriptors read from the host memory */ + uint32_t prefed_desc; + /* [0x14] Number of packets written into the completion ring */ + uint32_t comp_pkt; + /* [0x18] Number of descriptors written into the completion ring */ + uint32_t comp_desc; + /* + * [0x1c] Number of acknowledged packets. + * (acknowledge sent to the stream interface) + */ + uint32_t ack_pkts; + uint32_t rsrvd[56]; +}; +struct udma_s2m_feature { + /* + * [0x0] S2M Feature register + * S2M instantiation parameters + */ + uint32_t reg_1; + /* [0x4] Reserved S2M feature register */ + uint32_t reg_2; + /* + * [0x8] S2M Feature register + * S2M instantiation parameters + */ + uint32_t reg_3; + /* + * [0xc] S2M Feature register. + * S2M instantiation parameters. + */ + uint32_t reg_4; + /* + * [0x10] S2M Feature register. + * S2M instantiation parameters. + */ + uint32_t reg_5; + /* [0x14] S2M Feature register. S2M instantiation parameters. */ + uint32_t reg_6; + uint32_t rsrvd[58]; +}; +struct udma_s2m_q { + uint32_t rsrvd_0[8]; + /* [0x20] S2M Descriptor ring configuration */ + uint32_t cfg; + /* [0x24] S2M Descriptor ring status and information */ + uint32_t status; + /* [0x28] Rx Descriptor Ring Base Pointer [31:4] */ + uint32_t rdrbp_low; + /* [0x2c] Rx Descriptor Ring Base Pointer [63:32] */ + uint32_t rdrbp_high; + /* + * [0x30] Rx Descriptor Ring Length[23:2] + */ + uint32_t rdrl; + /* [0x34] RX Descriptor Ring Head Pointer */ + uint32_t rdrhp; + /* [0x38] Rx Descriptor Tail Pointer increment */ + uint32_t rdrtp_inc; + /* [0x3c] Rx Descriptor Tail Pointer */ + uint32_t rdrtp; + /* [0x40] RX Descriptor Current Pointer */ + uint32_t rdcp; + /* [0x44] Rx Completion Ring Base Pointer [31:4] */ + uint32_t rcrbp_low; + /* [0x48] Rx Completion Ring Base Pointer [63:32] */ + uint32_t rcrbp_high; + /* [0x4c] Rx Completion Ring Head Pointer */ + uint32_t rcrhp; + /* + * [0x50] RX Completion Ring Head Pointer internal. + * (Before the coalescing FIFO) + */ + uint32_t rcrhp_internal; + /* [0x54] Completion controller configuration for the queue */ + uint32_t comp_cfg; + /* [0x58] Completion controller configuration for the queue */ + uint32_t comp_cfg_2; + /* [0x5c] Packet handler configuration */ + uint32_t pkt_cfg; + /* [0x60] Queue QoS configuration */ + uint32_t qos_cfg; + /* [0x64] DMB software control */ + uint32_t q_sw_ctrl; + /* [0x68] Number of S2M Rx packets after completion */ + uint32_t q_rx_pkt; + uint32_t rsrvd[997]; +}; + +struct udma_s2m_regs { + uint32_t rsrvd_0[64]; + struct udma_axi_s2m axi_s2m; /* [0x100] */ + struct udma_s2m s2m; /* [0x200] */ + struct udma_s2m_rd s2m_rd; /* [0x300] */ + struct udma_s2m_wr s2m_wr; /* [0x340] */ + struct udma_s2m_comp s2m_comp; /* [0x380] */ + uint32_t rsrvd_1[80]; + struct udma_s2m_stat s2m_stat; /* [0x500] */ + struct udma_s2m_feature s2m_feature; /* [0x600] */ + uint32_t rsrvd_2[576]; + struct udma_s2m_q s2m_q[4]; /* [0x1000] */ +}; + + +/* +* Registers Fields +*/ + + +/**** data_wr_cfg_1 register ****/ +/* AXI write ID (AWID) */ +#define UDMA_AXI_S2M_DATA_WR_CFG_1_AWID_MASK 0x000000FF +#define UDMA_AXI_S2M_DATA_WR_CFG_1_AWID_SHIFT 0 +/* Cache Type */ +#define UDMA_AXI_S2M_DATA_WR_CFG_1_AWCACHE_MASK 0x000F0000 +#define UDMA_AXI_S2M_DATA_WR_CFG_1_AWCACHE_SHIFT 16 +/* Burst type */ +#define UDMA_AXI_S2M_DATA_WR_CFG_1_AWBURST_MASK 0x03000000 +#define UDMA_AXI_S2M_DATA_WR_CFG_1_AWBURST_SHIFT 24 + +/**** data_wr_cfg_2 register ****/ +/* User extension */ +#define UDMA_AXI_S2M_DATA_WR_CFG_2_AWUSER_MASK 0x000FFFFF +#define UDMA_AXI_S2M_DATA_WR_CFG_2_AWUSER_SHIFT 0 +/* Bus size, 128-bit */ +#define UDMA_AXI_S2M_DATA_WR_CFG_2_AWSIZE_MASK 0x00700000 +#define UDMA_AXI_S2M_DATA_WR_CFG_2_AWSIZE_SHIFT 20 +/* + * AXI Master QoS. + * Used for arbitration between AXI masters + */ +#define UDMA_AXI_S2M_DATA_WR_CFG_2_AWQOS_MASK 0x07000000 +#define UDMA_AXI_S2M_DATA_WR_CFG_2_AWQOS_SHIFT 24 +/* Protection Type */ +#define UDMA_AXI_S2M_DATA_WR_CFG_2_AWPROT_MASK 0x70000000 +#define UDMA_AXI_S2M_DATA_WR_CFG_2_AWPROT_SHIFT 28 + +/**** desc_rd_cfg_4 register ****/ +/* AXI read ID (ARID) */ +#define UDMA_AXI_S2M_DESC_RD_CFG_4_ARID_MASK 0x000000FF +#define UDMA_AXI_S2M_DESC_RD_CFG_4_ARID_SHIFT 0 +/* Cache Type */ +#define UDMA_AXI_S2M_DESC_RD_CFG_4_ARCACHE_MASK 0x000F0000 +#define UDMA_AXI_S2M_DESC_RD_CFG_4_ARCACHE_SHIFT 16 +/* Burst type */ +#define UDMA_AXI_S2M_DESC_RD_CFG_4_ARBURST_MASK 0x03000000 +#define UDMA_AXI_S2M_DESC_RD_CFG_4_ARBURST_SHIFT 24 + +/**** desc_rd_cfg_5 register ****/ +/* User extension */ +#define UDMA_AXI_S2M_DESC_RD_CFG_5_ARUSER_MASK 0x000FFFFF +#define UDMA_AXI_S2M_DESC_RD_CFG_5_ARUSER_SHIFT 0 +/* Bus size, 128-bit */ +#define UDMA_AXI_S2M_DESC_RD_CFG_5_ARSIZE_MASK 0x00700000 +#define UDMA_AXI_S2M_DESC_RD_CFG_5_ARSIZE_SHIFT 20 +/* + * AXI Master QoS. + * Used for arbitration between AXI masters + */ +#define UDMA_AXI_S2M_DESC_RD_CFG_5_ARQOS_MASK 0x07000000 +#define UDMA_AXI_S2M_DESC_RD_CFG_5_ARQOS_SHIFT 24 +/* Protection Type */ +#define UDMA_AXI_S2M_DESC_RD_CFG_5_ARPROT_MASK 0x70000000 +#define UDMA_AXI_S2M_DESC_RD_CFG_5_ARPROT_SHIFT 28 + +/**** comp_wr_cfg_1 register ****/ +/* AXI write ID (AWID) */ +#define UDMA_AXI_S2M_COMP_WR_CFG_1_AWID_MASK 0x000000FF +#define UDMA_AXI_S2M_COMP_WR_CFG_1_AWID_SHIFT 0 +/* Cache Type */ +#define UDMA_AXI_S2M_COMP_WR_CFG_1_AWCACHE_MASK 0x000F0000 +#define UDMA_AXI_S2M_COMP_WR_CFG_1_AWCACHE_SHIFT 16 +/* Burst type */ +#define UDMA_AXI_S2M_COMP_WR_CFG_1_AWBURST_MASK 0x03000000 +#define UDMA_AXI_S2M_COMP_WR_CFG_1_AWBURST_SHIFT 24 + +/**** comp_wr_cfg_2 register ****/ +/* User extension */ +#define UDMA_AXI_S2M_COMP_WR_CFG_2_AWUSER_MASK 0x000FFFFF +#define UDMA_AXI_S2M_COMP_WR_CFG_2_AWUSER_SHIFT 0 +/* Bus size, 128-bit */ +#define UDMA_AXI_S2M_COMP_WR_CFG_2_AWSIZE_MASK 0x00700000 +#define UDMA_AXI_S2M_COMP_WR_CFG_2_AWSIZE_SHIFT 20 +/* + * AXI Master QoS. + * Used for arbitration between AXI masters + */ +#define UDMA_AXI_S2M_COMP_WR_CFG_2_AWQOS_MASK 0x07000000 +#define UDMA_AXI_S2M_COMP_WR_CFG_2_AWQOS_SHIFT 24 +/* Protection Type */ +#define UDMA_AXI_S2M_COMP_WR_CFG_2_AWPROT_MASK 0x70000000 +#define UDMA_AXI_S2M_COMP_WR_CFG_2_AWPROT_SHIFT 28 + +/**** data_wr_cfg register ****/ +/* + * Defines the maximum number of AXI beats for a single AXI burst. This value is + * used for the burst split decision. + */ +#define UDMA_AXI_S2M_DATA_WR_CFG_MAX_AXI_BEATS_MASK 0x000000FF +#define UDMA_AXI_S2M_DATA_WR_CFG_MAX_AXI_BEATS_SHIFT 0 + +/**** desc_rd_cfg_3 register ****/ +/* + * Defines the maximum number of AXI beats for a single AXI burst. This value is + * used for the burst split decision. + */ +#define UDMA_AXI_S2M_DESC_RD_CFG_3_MAX_AXI_BEATS_MASK 0x000000FF +#define UDMA_AXI_S2M_DESC_RD_CFG_3_MAX_AXI_BEATS_SHIFT 0 +/* + * Enables breaking descriptor read request. + * Aligned to max_AXI_beats when the total read size is less than max_AXI_beats. + */ +#define UDMA_AXI_S2M_DESC_RD_CFG_3_ALWAYS_BREAK_ON_MAX_BOUDRY (1 << 16) + +/**** desc_wr_cfg_1 register ****/ +/* + * Defines the maximum number of AXI beats for a single AXI burst. This value is + * used for the burst split decision. + */ +#define UDMA_AXI_S2M_DESC_WR_CFG_1_MAX_AXI_BEATS_MASK 0x000000FF +#define UDMA_AXI_S2M_DESC_WR_CFG_1_MAX_AXI_BEATS_SHIFT 0 +/* + * Minimum burst for writing completion descriptors. + * (AXI beats). + * Value must be aligned to cache lines (64 bytes). + * Default value is 2 cache lines, 8 beats. + */ +#define UDMA_AXI_S2M_DESC_WR_CFG_1_MIN_AXI_BEATS_MASK 0x00FF0000 +#define UDMA_AXI_S2M_DESC_WR_CFG_1_MIN_AXI_BEATS_SHIFT 16 + +/**** ostand_cfg_rd register ****/ +/* + * Maximum number of outstanding descriptor reads to the AXI. + * (AXI transactions). + */ +#define UDMA_AXI_S2M_OSTAND_CFG_RD_MAX_DESC_RD_OSTAND_MASK 0x0000003F +#define UDMA_AXI_S2M_OSTAND_CFG_RD_MAX_DESC_RD_OSTAND_SHIFT 0 +/* Maximum number of outstanding stream acknowledges. */ +#define UDMA_AXI_S2M_OSTAND_CFG_RD_MAX_STREAM_ACK_MASK 0x001F0000 +#define UDMA_AXI_S2M_OSTAND_CFG_RD_MAX_STREAM_ACK_SHIFT 16 + +/**** ostand_cfg_wr register ****/ +/* + * Maximum number of outstanding data writes to the AXI. + * (AXI transactions). + */ +#define UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_DATA_WR_OSTAND_MASK 0x0000003F +#define UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_DATA_WR_OSTAND_SHIFT 0 +/* + * Maximum number of outstanding data beats for data write to AXI. + * (AXI beats). + */ +#define UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_DATA_BEATS_WR_OSTAND_MASK 0x0000FF00 +#define UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_DATA_BEATS_WR_OSTAND_SHIFT 8 +/* + * Maximum number of outstanding descriptor writes to the AXI. + * (AXI transactions). + */ +#define UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_COMP_REQ_MASK 0x003F0000 +#define UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_COMP_REQ_SHIFT 16 +/* + * Maximum number of outstanding data beats for descriptor write to AXI. + * (AXI beats). + */ +#define UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_COMP_DATA_WR_OSTAND_MASK 0xFF000000 +#define UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_COMP_DATA_WR_OSTAND_SHIFT 24 + +/**** state register ****/ + +#define UDMA_S2M_STATE_COMP_CTRL_MASK 0x00000003 +#define UDMA_S2M_STATE_COMP_CTRL_SHIFT 0 + +#define UDMA_S2M_STATE_STREAM_IF_MASK 0x00000030 +#define UDMA_S2M_STATE_STREAM_IF_SHIFT 4 + +#define UDMA_S2M_STATE_DATA_WR_CTRL_MASK 0x00000300 +#define UDMA_S2M_STATE_DATA_WR_CTRL_SHIFT 8 + +#define UDMA_S2M_STATE_DESC_PREF_MASK 0x00003000 +#define UDMA_S2M_STATE_DESC_PREF_SHIFT 12 + +#define UDMA_S2M_STATE_AXI_WR_DATA_MASK 0x00030000 +#define UDMA_S2M_STATE_AXI_WR_DATA_SHIFT 16 + +/**** change_state register ****/ +/* Start normal operation */ +#define UDMA_S2M_CHANGE_STATE_NORMAL (1 << 0) +/* Stop normal operation */ +#define UDMA_S2M_CHANGE_STATE_DIS (1 << 1) +/* + * Stop all machines. + * (Prefetch, scheduling, completion and stream interface) + */ +#define UDMA_S2M_CHANGE_STATE_ABORT (1 << 2) + +/**** clear_err_log register ****/ +/* Clear error log */ +#define UDMA_S2M_CLEAR_ERR_LOG_CLEAR (1 << 0) + +/**** s_data_fifo_status register ****/ +/* FIFO used indication */ +#define UDMA_S2M_S_DATA_FIFO_STATUS_USED_MASK 0x0000FFFF +#define UDMA_S2M_S_DATA_FIFO_STATUS_USED_SHIFT 0 +/* FIFO empty indication */ +#define UDMA_S2M_S_DATA_FIFO_STATUS_EMPTY (1 << 24) +/* FIFO full indication */ +#define UDMA_S2M_S_DATA_FIFO_STATUS_FULL (1 << 28) + +/**** s_header_fifo_status register ****/ +/* FIFO used indication */ +#define UDMA_S2M_S_HEADER_FIFO_STATUS_USED_MASK 0x0000FFFF +#define UDMA_S2M_S_HEADER_FIFO_STATUS_USED_SHIFT 0 +/* FIFO empty indication */ +#define UDMA_S2M_S_HEADER_FIFO_STATUS_EMPTY (1 << 24) +/* FIFO full indication */ +#define UDMA_S2M_S_HEADER_FIFO_STATUS_FULL (1 << 28) + +/**** axi_data_fifo_status register ****/ +/* FIFO used indication */ +#define UDMA_S2M_AXI_DATA_FIFO_STATUS_USED_MASK 0x0000FFFF +#define UDMA_S2M_AXI_DATA_FIFO_STATUS_USED_SHIFT 0 +/* FIFO empty indication */ +#define UDMA_S2M_AXI_DATA_FIFO_STATUS_EMPTY (1 << 24) +/* FIFO full indication */ +#define UDMA_S2M_AXI_DATA_FIFO_STATUS_FULL (1 << 28) + +/**** unack_fifo_status register ****/ +/* FIFO used indication */ +#define UDMA_S2M_UNACK_FIFO_STATUS_USED_MASK 0x0000FFFF +#define UDMA_S2M_UNACK_FIFO_STATUS_USED_SHIFT 0 +/* FIFO empty indication */ +#define UDMA_S2M_UNACK_FIFO_STATUS_EMPTY (1 << 24) +/* FIFO full indication */ +#define UDMA_S2M_UNACK_FIFO_STATUS_FULL (1 << 28) + +/**** indirect_ctrl register ****/ +/* Selected queue for status read */ +#define UDMA_S2M_INDIRECT_CTRL_Q_NUM_MASK 0x00000FFF +#define UDMA_S2M_INDIRECT_CTRL_Q_NUM_SHIFT 0 + +/**** sel_pref_fifo_status register ****/ +/* FIFO used indication */ +#define UDMA_S2M_SEL_PREF_FIFO_STATUS_USED_MASK 0x0000FFFF +#define UDMA_S2M_SEL_PREF_FIFO_STATUS_USED_SHIFT 0 +/* FIFO empty indication */ +#define UDMA_S2M_SEL_PREF_FIFO_STATUS_EMPTY (1 << 24) +/* FIFO full indication */ +#define UDMA_S2M_SEL_PREF_FIFO_STATUS_FULL (1 << 28) + +/**** sel_comp_fifo_status register ****/ +/* FIFO used indication */ +#define UDMA_S2M_SEL_COMP_FIFO_STATUS_USED_MASK 0x0000FFFF +#define UDMA_S2M_SEL_COMP_FIFO_STATUS_USED_SHIFT 0 +/* Coalescing ACTIVE FSM state indication. */ +#define UDMA_S2M_SEL_COMP_FIFO_STATUS_COAL_ACTIVE_STATE_MASK 0x00300000 +#define UDMA_S2M_SEL_COMP_FIFO_STATUS_COAL_ACTIVE_STATE_SHIFT 20 +/* FIFO empty indication */ +#define UDMA_S2M_SEL_COMP_FIFO_STATUS_EMPTY (1 << 24) +/* FIFO full indication */ +#define UDMA_S2M_SEL_COMP_FIFO_STATUS_FULL (1 << 28) + +/**** stream_cfg register ****/ +/* + * Disables the stream interface operation. + * Changing to 1 stops at the end of packet reception. + */ +#define UDMA_S2M_STREAM_CFG_DISABLE (1 << 0) +/* + * Flush the stream interface operation. + * Changing to 1 stops at the end of packet reception and assert ready to the + * stream I/F. + */ +#define UDMA_S2M_STREAM_CFG_FLUSH (1 << 4) +/* Stop descriptor prefetch when the stream is disabled and the S2M is idle. */ +#define UDMA_S2M_STREAM_CFG_STOP_PREFETCH (1 << 8) + +/**** desc_pref_cfg_1 register ****/ +/* + * Size of the descriptor prefetch FIFO. + * (descriptors) + */ +#define UDMA_S2M_RD_DESC_PREF_CFG_1_FIFO_DEPTH_MASK 0x000000FF +#define UDMA_S2M_RD_DESC_PREF_CFG_1_FIFO_DEPTH_SHIFT 0 + +/**** desc_pref_cfg_2 register ****/ +/* Enable promotion of the current queue in progress */ +#define UDMA_S2M_RD_DESC_PREF_CFG_2_Q_PROMOTION (1 << 0) +/* Force promotion of the current queue in progress */ +#define UDMA_S2M_RD_DESC_PREF_CFG_2_FORCE_PROMOTION (1 << 1) +/* Enable prefetch prediction of next packet in line. */ +#define UDMA_S2M_RD_DESC_PREF_CFG_2_EN_PREF_PREDICTION (1 << 2) +/* + * Threshold for queue promotion. + * Queue is promoted for prefetch if there are less descriptors in the prefetch + * FIFO than the threshold + */ +#define UDMA_S2M_RD_DESC_PREF_CFG_2_PROMOTION_TH_MASK 0x0000FF00 +#define UDMA_S2M_RD_DESC_PREF_CFG_2_PROMOTION_TH_SHIFT 8 +/* + * Force RR arbitration in the prefetch arbiter. + * 0 - Standard arbitration based on queue QoS + * 1 - Force round robin arbitration + */ +#define UDMA_S2M_RD_DESC_PREF_CFG_2_PREF_FORCE_RR (1 << 16) + +/**** desc_pref_cfg_3 register ****/ +/* + * Minimum descriptor burst size when prefetch FIFO level is below the + * descriptor prefetch threshold + * (must be 1) + */ +#define UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_MASK 0x0000000F +#define UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_SHIFT 0 +/* + * Minimum descriptor burst size when prefetch FIFO level is above the + * descriptor prefetch threshold + */ +#define UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_MASK 0x000000F0 +#define UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_SHIFT 4 +/* + * Descriptor fetch threshold. + * Used as a threshold to determine the allowed minimum descriptor burst size. + * (Must be at least "max_desc_per_pkt") + */ +#define UDMA_S2M_RD_DESC_PREF_CFG_3_PREF_THR_MASK 0x0000FF00 +#define UDMA_S2M_RD_DESC_PREF_CFG_3_PREF_THR_SHIFT 8 + +/**** desc_pref_cfg_4 register ****/ +/* + * Used as a threshold for generating almost FULL indication to the application + */ +#define UDMA_S2M_RD_DESC_PREF_CFG_4_A_FULL_THR_MASK 0x000000FF +#define UDMA_S2M_RD_DESC_PREF_CFG_4_A_FULL_THR_SHIFT 0 + +/**** data_cfg_1 register ****/ +/* + * Maximum number of data beats in the data write FIFO. + * Defined based on data FIFO size + * (default FIFO size 512B → 32 beats) + */ +#define UDMA_S2M_WR_DATA_CFG_1_DATA_FIFO_DEPTH_MASK 0x000003FF +#define UDMA_S2M_WR_DATA_CFG_1_DATA_FIFO_DEPTH_SHIFT 0 +/* + * Maximum number of packets in the data write FIFO. + * Defined based on header FIFO size + */ +#define UDMA_S2M_WR_DATA_CFG_1_MAX_PKT_LIMIT_MASK 0x00FF0000 +#define UDMA_S2M_WR_DATA_CFG_1_MAX_PKT_LIMIT_SHIFT 16 +/* + * Internal use + * Data FIFO margin + */ +#define UDMA_S2M_WR_DATA_CFG_1_FIFO_MARGIN_MASK 0xFF000000 +#define UDMA_S2M_WR_DATA_CFG_1_FIFO_MARGIN_SHIFT 24 + +/**** data_cfg_2 register ****/ +/* + * Drop timer. + * Waiting time for the host to write new descriptor to the queue + * (for the current packet in process) + */ +#define UDMA_S2M_WR_DATA_CFG_2_DESC_WAIT_TIMER_MASK 0x00FFFFFF +#define UDMA_S2M_WR_DATA_CFG_2_DESC_WAIT_TIMER_SHIFT 0 +/* + * Drop enable. + * Enable packet drop if there are no available descriptors in the system for + * this queue + */ +#define UDMA_S2M_WR_DATA_CFG_2_DROP_IF_NO_DESC (1 << 27) +/* + * Lack of descriptors hint. + * Generate interrupt when a packet is waiting but there are no available + * descriptors in the queue + */ +#define UDMA_S2M_WR_DATA_CFG_2_HINT_IF_NO_DESC (1 << 28) +/* + * Drop conditions + * Wait until a descriptor is available in the prefetch FIFO or the host before + * dropping packet. + * 1 - Drop if a descriptor is not available in the prefetch. + * 0 - Drop if a descriptor is not available in the system + */ +#define UDMA_S2M_WR_DATA_CFG_2_WAIT_FOR_PREF (1 << 29) +/* + * DRAM write optimization + * 0 - Data write with byte enable + * 1 - Data write is always in Full AXI bus width (128 bit) + */ +#define UDMA_S2M_WR_DATA_CFG_2_FULL_LINE_MODE (1 << 30) +/* + * Direct data write address + * 1 - Use buffer 1 instead of buffer 2 when direct data placement is used with + * header split. + * 0 - Use buffer 2 for the header. + */ +#define UDMA_S2M_WR_DATA_CFG_2_DIRECT_HDR_USE_BUF1 (1 << 31) + +/**** cfg_1c register ****/ +/* + * Completion descriptor size. + * (words) + */ +#define UDMA_S2M_COMP_CFG_1C_DESC_SIZE_MASK 0x0000000F +#define UDMA_S2M_COMP_CFG_1C_DESC_SIZE_SHIFT 0 +/* + * Completion queue counter configuration. + * Completion FIFO in use counter measured in words or descriptors + * 1 - Words + * 0 - Descriptors + */ +#define UDMA_S2M_COMP_CFG_1C_CNT_WORDS (1 << 8) +/* + * Enable promotion of the current queue in progress in the completion write + * scheduler. + */ +#define UDMA_S2M_COMP_CFG_1C_Q_PROMOTION (1 << 12) +/* Force RR arbitration in the completion arbiter */ +#define UDMA_S2M_COMP_CFG_1C_FORCE_RR (1 << 16) +/* Minimum number of free completion entries to qualify for promotion */ +#define UDMA_S2M_COMP_CFG_1C_Q_FREE_MIN_MASK 0xF0000000 +#define UDMA_S2M_COMP_CFG_1C_Q_FREE_MIN_SHIFT 28 + +/**** cfg_2c register ****/ +/* + * Completion FIFO size. + * (words per queue) + */ +#define UDMA_S2M_COMP_CFG_2C_COMP_FIFO_DEPTH_MASK 0x00000FFF +#define UDMA_S2M_COMP_CFG_2C_COMP_FIFO_DEPTH_SHIFT 0 +/* + * Unacknowledged FIFO size. + * (descriptors) + */ +#define UDMA_S2M_COMP_CFG_2C_UNACK_FIFO_DEPTH_MASK 0x0FFF0000 +#define UDMA_S2M_COMP_CFG_2C_UNACK_FIFO_DEPTH_SHIFT 16 + +/**** reg_1 register ****/ +/* + * Descriptor prefetch FIFO size + * (descriptors) + */ +#define UDMA_S2M_FEATURE_REG_1_DESC_PREFERCH_FIFO_DEPTH_MASK 0x000000FF +#define UDMA_S2M_FEATURE_REG_1_DESC_PREFERCH_FIFO_DEPTH_SHIFT 0 + +/**** reg_3 register ****/ +/* + * Maximum number of data beats in the data write FIFO. + * Defined based on data FIFO size + * (default FIFO size 512B →32 beats) + */ +#define UDMA_S2M_FEATURE_REG_3_DATA_FIFO_DEPTH_MASK 0x000003FF +#define UDMA_S2M_FEATURE_REG_3_DATA_FIFO_DEPTH_SHIFT 0 +/* + * Maximum number of packets in the data write FIFO. + * Defined based on header FIFO size + */ +#define UDMA_S2M_FEATURE_REG_3_DATA_WR_MAX_PKT_LIMIT_MASK 0x00FF0000 +#define UDMA_S2M_FEATURE_REG_3_DATA_WR_MAX_PKT_LIMIT_SHIFT 16 + +/**** reg_4 register ****/ +/* + * Completion FIFO size. + * (words per queue) + */ +#define UDMA_S2M_FEATURE_REG_4_COMP_FIFO_DEPTH_MASK 0x00000FFF +#define UDMA_S2M_FEATURE_REG_4_COMP_FIFO_DEPTH_SHIFT 0 +/* + * Unacknowledged FIFO size. + * (descriptors) + */ +#define UDMA_S2M_FEATURE_REG_4_COMP_UNACK_FIFO_DEPTH_MASK 0x0FFF0000 +#define UDMA_S2M_FEATURE_REG_4_COMP_UNACK_FIFO_DEPTH_SHIFT 16 + +/**** reg_5 register ****/ +/* Maximum number of outstanding data writes to the AXI */ +#define UDMA_S2M_FEATURE_REG_5_MAX_DATA_WR_OSTAND_MASK 0x0000003F +#define UDMA_S2M_FEATURE_REG_5_MAX_DATA_WR_OSTAND_SHIFT 0 +/* + * Maximum number of outstanding data beats for data write to AXI. + * (AXI beats) + */ +#define UDMA_S2M_FEATURE_REG_5_MAX_DATA_BEATS_WR_OSTAND_MASK 0x0000FF00 +#define UDMA_S2M_FEATURE_REG_5_MAX_DATA_BEATS_WR_OSTAND_SHIFT 8 +/* + * Maximum number of outstanding descriptor reads to the AXI. + * (AXI transactions) + */ +#define UDMA_S2M_FEATURE_REG_5_MAX_COMP_REQ_MASK 0x003F0000 +#define UDMA_S2M_FEATURE_REG_5_MAX_COMP_REQ_SHIFT 16 +/* + * Maximum number of outstanding data beats for descriptor write to AXI. + * (AXI beats) + */ +#define UDMA_S2M_FEATURE_REG_5_MAX_COMP_DATA_WR_OSTAND_MASK 0xFF000000 +#define UDMA_S2M_FEATURE_REG_5_MAX_COMP_DATA_WR_OSTAND_SHIFT 24 + +/**** reg_6 register ****/ +/* Maximum number of outstanding descriptor reads to the AXI */ +#define UDMA_S2M_FEATURE_REG_6_MAX_DESC_RD_OSTAND_MASK 0x0000003F +#define UDMA_S2M_FEATURE_REG_6_MAX_DESC_RD_OSTAND_SHIFT 0 +/* Maximum number of outstanding stream acknowledges */ +#define UDMA_S2M_FEATURE_REG_6_MAX_STREAM_ACK_MASK 0x001F0000 +#define UDMA_S2M_FEATURE_REG_6_MAX_STREAM_ACK_SHIFT 16 + +/**** cfg register ****/ +/* + * Configure the AXI AWCACHE + * for header write. + */ +#define UDMA_S2M_Q_CFG_AXI_AWCACHE_HDR_MASK 0x0000000F +#define UDMA_S2M_Q_CFG_AXI_AWCACHE_HDR_SHIFT 0 +/* + * Configure the AXI AWCACHE + * for data write. + */ +#define UDMA_S2M_Q_CFG_AXI_AWCACHE_DATA_MASK 0x000000F0 +#define UDMA_S2M_Q_CFG_AXI_AWCACHE_DATA_SHIFT 4 +/* + * Enable operation of this queue. + * Start prefetch. + */ +#define UDMA_S2M_Q_CFG_EN_PREF (1 << 16) +/* Enables the reception of packets from the stream to this queue */ +#define UDMA_S2M_Q_CFG_EN_STREAM (1 << 17) +/* Allow prefetch of less than minimum prefetch burst size. */ +#define UDMA_S2M_Q_CFG_ALLOW_LT_MIN_PREF (1 << 20) +/* + * Configure the AXI AWCACHE + * for completion descriptor write + */ +#define UDMA_S2M_Q_CFG_AXI_AWCACHE_COMP_MASK 0x0F000000 +#define UDMA_S2M_Q_CFG_AXI_AWCACHE_COMP_SHIFT 24 +/* + * AXI QoS + * This value is used in AXI transactions associated with this queue and the + * prefetch and completion arbiters. + */ +#define UDMA_S2M_Q_CFG_AXI_QOS_MASK 0x70000000 +#define UDMA_S2M_Q_CFG_AXI_QOS_SHIFT 28 + +/**** status register ****/ +/* Indicates how many entries are used in the Queue */ +#define UDMA_S2M_Q_STATUS_Q_USED_MASK 0x01FFFFFF +#define UDMA_S2M_Q_STATUS_Q_USED_SHIFT 0 +/* + * prefetch status + * 0 – prefetch operation is stopped + * 1 – prefetch is operational + */ +#define UDMA_S2M_Q_STATUS_PREFETCH (1 << 28) +/* + * Queue receive status + * 0 -queue RX operation is stopped + * 1 – RX queue is active and processing packets + */ +#define UDMA_S2M_Q_STATUS_RX (1 << 29) +/* + * Indicates if the queue is full. + * (Used by the host when head pointer equals tail pointer) + */ +#define UDMA_S2M_Q_STATUS_Q_FULL (1 << 31) +/* + * S2M Descriptor Ring Base address [31:4]. + * Value of the base address of the S2M descriptor ring + * [3:0] - 0 - 16B alignment is enforced + * ([11:4] should be 0 for 4KB alignment) + */ +#define UDMA_S2M_Q_RDRBP_LOW_ADDR_MASK 0xFFFFFFF0 +#define UDMA_S2M_Q_RDRBP_LOW_ADDR_SHIFT 4 + +/**** RDRL register ****/ +/* + * Length of the descriptor ring. + * (descriptors) + * Associated with the ring base address ends at maximum burst size alignment + */ +#define UDMA_S2M_Q_RDRL_OFFSET_MASK 0x00FFFFFF +#define UDMA_S2M_Q_RDRL_OFFSET_SHIFT 0 + +/**** RDRHP register ****/ +/* + * Relative offset of the next descriptor that needs to be read into the + * prefetch FIFO. + * Incremented when the DMA reads valid descriptors from the host memory to the + * prefetch FIFO. + * Note that this is the offset in # of descriptors and not in byte address. + */ +#define UDMA_S2M_Q_RDRHP_OFFSET_MASK 0x00FFFFFF +#define UDMA_S2M_Q_RDRHP_OFFSET_SHIFT 0 +/* Ring ID */ +#define UDMA_S2M_Q_RDRHP_RING_ID_MASK 0xC0000000 +#define UDMA_S2M_Q_RDRHP_RING_ID_SHIFT 30 + +/**** RDRTP_inc register ****/ +/* + * Increments the value in Q_RDRTP with the value written to this field in + * number of descriptors. + */ +#define UDMA_S2M_Q_RDRTP_INC_VAL_MASK 0x00FFFFFF +#define UDMA_S2M_Q_RDRTP_INC_VAL_SHIFT 0 + +/**** RDRTP register ****/ +/* + * Relative offset of the next free descriptor in the host memory. + * Note that this is the offset in # of descriptors and not in byte address. + */ +#define UDMA_S2M_Q_RDRTP_OFFSET_MASK 0x00FFFFFF +#define UDMA_S2M_Q_RDRTP_OFFSET_SHIFT 0 +/* Ring ID */ +#define UDMA_S2M_Q_RDRTP_RING_ID_MASK 0xC0000000 +#define UDMA_S2M_Q_RDRTP_RING_ID_SHIFT 30 + +/**** RDCP register ****/ +/* Relative offset of the first descriptor in the prefetch FIFO. */ +#define UDMA_S2M_Q_RDCP_OFFSET_MASK 0x00FFFFFF +#define UDMA_S2M_Q_RDCP_OFFSET_SHIFT 0 +/* Ring ID */ +#define UDMA_S2M_Q_RDCP_RING_ID_MASK 0xC0000000 +#define UDMA_S2M_Q_RDCP_RING_ID_SHIFT 30 +/* + * S2M Descriptor Ring Base address [31:4]. + * Value of the base address of the S2M descriptor ring + * [3:0] - 0 - 16B alignment is enforced + * ([11:4] Must be 0 for 4KB alignment) + * NOTE: + * Length of the descriptor ring (in descriptors) associated with the ring base + * address ends at maximum burst size alignment + */ +#define UDMA_S2M_Q_RCRBP_LOW_ADDR_MASK 0xFFFFFFF0 +#define UDMA_S2M_Q_RCRBP_LOW_ADDR_SHIFT 4 + +/**** RCRHP register ****/ +/* + * Relative offset of the next descriptor that needs to be updated by the + * completion controller. + * Note: This is in descriptors and not in byte address. + */ +#define UDMA_S2M_Q_RCRHP_OFFSET_MASK 0x00FFFFFF +#define UDMA_S2M_Q_RCRHP_OFFSET_SHIFT 0 +/* Ring ID */ +#define UDMA_S2M_Q_RCRHP_RING_ID_MASK 0xC0000000 +#define UDMA_S2M_Q_RCRHP_RING_ID_SHIFT 30 + +/**** RCRHP_internal register ****/ +/* + * Relative offset of the next descriptor that needs to be updated by the + * completion controller. + * Note: This is in descriptors and not in byte address. + */ +#define UDMA_S2M_Q_RCRHP_INTERNAL_OFFSET_MASK 0x00FFFFFF +#define UDMA_S2M_Q_RCRHP_INTERNAL_OFFSET_SHIFT 0 +/* Ring ID */ +#define UDMA_S2M_Q_RCRHP_INTERNAL_RING_ID_MASK 0xC0000000 +#define UDMA_S2M_Q_RCRHP_INTERNAL_RING_ID_SHIFT 30 + +/**** comp_cfg register ****/ +/* Enables writing to the completion ring. */ +#define UDMA_S2M_Q_COMP_CFG_EN_COMP_RING_UPDATE (1 << 0) +/* Disables the completion coalescing function. */ +#define UDMA_S2M_Q_COMP_CFG_DIS_COMP_COAL (1 << 1) +/* Reserved */ +#define UDMA_S2M_Q_COMP_CFG_FIRST_PKT_PROMOTION (1 << 2) +/* + * Buffer 2 location. + * Determines the position of the buffer 2 length in the S2M completion + * descriptor. + * 0 - WORD 1 [31:16] + * 1 - WORD 2 [31:16] + */ +#define UDMA_S2M_Q_COMP_CFG_BUF2_LEN_LOCATION (1 << 3) + +/**** pkt_cfg register ****/ +/* Header size. (bytes) */ +#define UDMA_S2M_Q_PKT_CFG_HDR_SPLIT_SIZE_MASK 0x0000FFFF +#define UDMA_S2M_Q_PKT_CFG_HDR_SPLIT_SIZE_SHIFT 0 +/* Force header split */ +#define UDMA_S2M_Q_PKT_CFG_FORCE_HDR_SPLIT (1 << 16) +/* Enable header split. */ +#define UDMA_S2M_Q_PKT_CFG_EN_HDR_SPLIT (1 << 17) + +/**** qos_cfg register ****/ +/* Queue QoS */ +#define UDMA_S2M_QOS_CFG_Q_QOS_MASK 0x000000FF +#define UDMA_S2M_QOS_CFG_Q_QOS_SHIFT 0 +/* Reset the tail pointer hardware. */ +#define UDMA_S2M_Q_SW_CTRL_RST_TAIL_PTR (1 << 1) +/* Reset the head pointer hardware. */ +#define UDMA_S2M_Q_SW_CTRL_RST_HEAD_PTR (1 << 2) +/* Reset the current pointer hardware. */ +#define UDMA_S2M_Q_SW_CTRL_RST_CURRENT_PTR (1 << 3) +/* Reset the prefetch FIFO */ +#define UDMA_S2M_Q_SW_CTRL_RST_PREFETCH (1 << 4) +/* Reset the queue */ +#define UDMA_S2M_Q_SW_CTRL_RST_Q (1 << 8) + +#ifdef __cplusplus +} +#endif + +#endif /* __AL_HAL_UDMA_S2M_REG_H */ diff --git a/eth/al_hal_an_lt_wrapper_regs.h b/eth/al_hal_an_lt_wrapper_regs.h new file mode 100644 index 00000000000..72b5cc66fb4 --- /dev/null +++ b/eth/al_hal_an_lt_wrapper_regs.h @@ -0,0 +1,264 @@ +/*- +******************************************************************************* +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_an_lt_wrapper_regs.h + * + * @brief ... registers + * + */ + +#ifndef __AL_HAL_AN_LT_wrapper_REGS_H__ +#define __AL_HAL_AN_LT_wrapper_REGS_H__ + +#include "al_hal_plat_types.h" + +#ifdef __cplusplus +extern "C" { +#endif +/* +* Unit Registers +*/ + + + +struct al_an_lt_wrapper_gen { + /* [0x0] AN LT wrapper Version */ + uint32_t version; + /* [0x4] AN LT general configuration */ + uint32_t cfg; + uint32_t rsrvd[14]; +}; +struct al_an_lt_wrapper_an_lt { + /* [0x0] AN LT register file address */ + uint32_t addr; + /* [0x4] PCS register file data */ + uint32_t data; + /* [0x8] AN LT control signals */ + uint32_t ctrl; + /* [0xc] AN LT status signals */ + uint32_t status; + uint32_t rsrvd[4]; +}; + +enum al_eth_an_lt_unit { + AL_ETH_AN_LT_UNIT_32_BIT = 0, + AL_ETH_AN_LT_UNIT_20_BIT = 1, + AL_ETH_AN_LT_UNIT_16_BIT = 2, +}; + +struct al_an_lt_wrapper_regs { + uint32_t rsrvd_0[64]; + struct al_an_lt_wrapper_gen gen; /* [0x100] */ + struct al_an_lt_wrapper_an_lt an_lt[3]; /* [0x140] */ +}; + + +/* +* Registers Fields +*/ + + +/**** version register ****/ +/* Revision number (Minor) */ +#define AN_LT_WRAPPER_GEN_VERSION_RELEASE_NUM_MINOR_MASK 0x000000FF +#define AN_LT_WRAPPER_GEN_VERSION_RELEASE_NUM_MINOR_SHIFT 0 +/* Revision number (Major) */ +#define AN_LT_WRAPPER_GEN_VERSION_RELEASE_NUM_MAJOR_MASK 0x0000FF00 +#define AN_LT_WRAPPER_GEN_VERSION_RELEASE_NUM_MAJOR_SHIFT 8 +/* Date of release */ +#define AN_LT_WRAPPER_GEN_VERSION_DATE_DAY_MASK 0x001F0000 +#define AN_LT_WRAPPER_GEN_VERSION_DATE_DAY_SHIFT 16 +/* Month of release */ +#define AN_LT_WRAPPER_GEN_VERSION_DATA_MONTH_MASK 0x01E00000 +#define AN_LT_WRAPPER_GEN_VERSION_DATA_MONTH_SHIFT 21 +/* Year of release (starting from 2000) */ +#define AN_LT_WRAPPER_GEN_VERSION_DATE_YEAR_MASK 0x3E000000 +#define AN_LT_WRAPPER_GEN_VERSION_DATE_YEAR_SHIFT 25 +/* Reserved */ +#define AN_LT_WRAPPER_GEN_VERSION_RESERVED_MASK 0xC0000000 +#define AN_LT_WRAPPER_GEN_VERSION_RESERVED_SHIFT 30 + +/**** cfg register ****/ +/* + * selection between different bus widths: + * 0 – 16 + * 1 – 20 + * 2 – 32 + * 3 – N/A + */ +#define AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK 0x00000003 +#define AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT 0 +/* + * selection between different bus widths: + * 0 – 16 + * 1 – 20 + * 2 – 32 + * 3 – N/A + */ +#define AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK 0x0000000C +#define AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT 2 +/* bypass the AN/LT block */ +#define AN_LT_WRAPPER_GEN_CFG_BYPASS_RX (1 << 4) +/* bypass the AN/LT block */ +#define AN_LT_WRAPPER_GEN_CFG_BYPASS_TX (1 << 5) + +/**** addr register ****/ +/* Address value */ +#define AN_LT_WRAPPER_AN_LT_ADDR_VAL_MASK 0x000007FF +#define AN_LT_WRAPPER_AN_LT_ADDR_VAL_SHIFT 0 + +/**** data register ****/ +/* Data value */ +#define AN_LT_WRAPPER_AN_LT_DATA_VAL_MASK 0x0000FFFF +#define AN_LT_WRAPPER_AN_LT_DATA_VAL_SHIFT 0 + +/**** ctrl register ****/ +/* + * Default Auto-Negotiation Enable. If ‘1’, the auto-negotiation process will + * start after reset de-assertion. The application can also start the + * auto-negotiation process by writing the KXAN_CONTROL.an_enable bit with ‘1’. + * Important: This signal is OR'ed with the KXAN_CONTROL.an_enable bit. Hence, + * when asserted (1) the application is unable to disable autonegotiation and + * writing the an_enable bit has no effect. + * Note: Even if enabled by this pin, the application must write the correct + * abilities in the KXAN_ABILITY_1/2/3 registers within 60ms from reset + * deassertion (break_link_timer). + */ +#define AN_LT_WRAPPER_AN_LT_CTRL_AN_ENA (1 << 0) +/* + * If set to 1, the Arbitration State Machine reached the TRANSMIT_DISABLE + * state. + */ +#define AN_LT_WRAPPER_AN_LT_CTRL_AN_DIS_TIMER (1 << 1) + +#define AN_LT_WRAPPER_AN_LT_CTRL_LINK_STATUS_KX (1 << 4) + +#define AN_LT_WRAPPER_AN_LT_CTRL_LINK_STATUS_KX4 (1 << 5) + +#define AN_LT_WRAPPER_AN_LT_CTRL_LINK_STATUS (1 << 6) +/* + * PHY LOS indication selection + * 0 - Select input from the SerDes + * 1 - Select register value from phy_los_in_def + */ +#define AN_LT_WRAPPER_AN_LT_CTRL_PHY_LOS_IN_SEL (1 << 8) +/* PHY LOS default value */ +#define AN_LT_WRAPPER_AN_LT_CTRL_PHY_LOS_IN_DEF (1 << 9) +/* PHY LOS polarity */ +#define AN_LT_WRAPPER_AN_LT_CTRL_PHY_LOS_IN_POL (1 << 10) +/* + * PHY LOS indication selection + * 0 – select AN output + * 1 - Select register value from phy_los_out_def + * 2 - Select input from the SerDes + * 3 – 0 + */ +#define AN_LT_WRAPPER_AN_LT_CTRL_PHY_LOS_OUT_SEL_MASK 0x00003000 +#define AN_LT_WRAPPER_AN_LT_CTRL_PHY_LOS_OUT_SEL_SHIFT 12 +/* PHY LOS default value */ +#define AN_LT_WRAPPER_AN_LT_CTRL_PHY_LOS_OUT_DEF (1 << 14) +/* PHY LOS polarity */ +#define AN_LT_WRAPPER_AN_LT_CTRL_PHY_LOS_OUT_POL (1 << 15) + +/**** status register ****/ +/* Auto-Negotiation Done. If ‘1’, the auto-negotiation process has completed. */ +#define AN_LT_WRAPPER_AN_LT_STATUS_AN_DONE (1 << 0) +/* + * If set to 1, auto-negotiation is enabled on the link. It represents the + * enable control bit KXAN_CONTROL.an_enable. When set to 1, the signals + * an_status/an_select are valid. + */ +#define AN_LT_WRAPPER_AN_LT_STATUS_AN_VAL (1 << 1) +/* + * If set to 0, auto-negotiation is in progress, if set to 1, the Arbitration + * State Machine reached the AN_GOOD_CHECK state (i.e. before autonegotiation is + * done, but the link no longer is used to transfer DME pages). Stays asserted + * also during AN_GOOD (autoneg done). + */ +#define AN_LT_WRAPPER_AN_LT_STATUS_AN_STATUS (1 << 2) +/* + * Selected Technology. Becomes valid when an_status is 1. + * The selection mode number (from 0 to 24) corresponds to the Technology + * Ability (A0-A24) from the ability pages (see 4.3.2.3 page 13). The mode + * selection is based on the matching technology abilities and priority. + * A value of 31 is an invalid setting that indicates that no common technology + * could be resolved. The application should then inspect the base page results + * to determine if the link is operable or not. + */ +#define AN_LT_WRAPPER_AN_LT_STATUS_AN_SELECT_MASK 0x000001F0 +#define AN_LT_WRAPPER_AN_LT_STATUS_AN_SELECT_SHIFT 4 +/* + * If set to 1, the Arbitration State Machine reached the TRANSMIT_DISABLE state + */ +#define AN_LT_WRAPPER_AN_LT_STATUS_AN_TR_DIS_STATUS (1 << 16) +/* + * FEC Enable. Asserts when autonegotiation base page exchange identified both + * link partners advertising FEC capability and at least one is requesting FEC. + * The signal stays constant following base page exchange until autonegotiation + * is disabled or restarted. + * Note: the information can also be extracted from the base page exchange or + * the BP_ETH_STATUS register. + */ +#define AN_LT_WRAPPER_AN_LT_STATUS_FEC_ENA (1 << 17) +/* + * Link Training Frame Lock. If set to 1 the training frame delineation has been + * acquired. + */ +#define AN_LT_WRAPPER_AN_LT_STATUS_LT_LOCK (1 << 20) +/* + * If set to 0, link-training is in progress, if set to 1, the training is + * completed and the PCS datapath has been enabled (phy_los_out no longer + * gated). + */ +#define AN_LT_WRAPPER_AN_LT_STATUS_LT_STATUS (1 << 21) +/* + * If set to 1, link-training is enabled on the link. It represents the enable + * control bit PMD Control.taining enable. When set to 1, the signal lt_status + * is valid + */ +#define AN_LT_WRAPPER_AN_LT_STATUS_LT_VAL (1 << 22) + +#ifdef __cplusplus +} +#endif + +#endif /* __AL_HAL_AN_LT_wrapper_REGS_H__ */ + +/** @} end of ... group */ + + diff --git a/eth/al_hal_eth.h b/eth/al_hal_eth.h new file mode 100644 index 00000000000..86108b0df4c --- /dev/null +++ b/eth/al_hal_eth.h @@ -0,0 +1,2381 @@ +/*- +******************************************************************************* +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. + +*******************************************************************************/ + +/** + * @defgroup group_eth_api API + * Ethernet Controller HAL driver API + * @ingroup group_eth + * @{ + * @file al_hal_eth.h + * + * @brief Header file for Unified GbE and 10GbE Ethernet Controllers This is a + * common header file that covers both Standard and Advanced Controller + * + * + */ + +#ifndef __AL_HAL_ETH_H__ +#define __AL_HAL_ETH_H__ + +#include "al_hal_common.h" +#include "al_hal_udma.h" +#include "al_hal_eth_alu.h" +#ifdef AL_ETH_EX +#include "al_hal_eth_ex.h" +#include "al_hal_eth_ex_internal.h" +#endif + +/* *INDENT-OFF* */ +#ifdef __cplusplus +extern "C" { +#endif +/* *INDENT-ON* */ + +#ifndef AL_ETH_PKT_MAX_BUFS +#ifndef AL_ETH_EX +#define AL_ETH_PKT_MAX_BUFS 19 +#else +#define AL_ETH_PKT_MAX_BUFS 29 +#endif +#endif + +#define AL_ETH_UDMA_TX_QUEUES 4 +#define AL_ETH_UDMA_RX_QUEUES 4 + +/* PCI Adapter Device/Revision ID */ +#define AL_ETH_DEV_ID_STANDARD 0x0001 +#define AL_ETH_DEV_ID_ADVANCED 0x0002 +#define AL_ETH_REV_ID_0 0 /* Alpine V1 Rev 0 */ +#define AL_ETH_REV_ID_1 1 /* Alpine V1 Rev 1 */ +#define AL_ETH_REV_ID_2 2 /* Alpine V2 basic */ +#define AL_ETH_REV_ID_3 3 /* Alpine V2 advanced */ + +/* PCI BARs */ +#define AL_ETH_UDMA_BAR 0 +#define AL_ETH_EC_BAR 4 +#define AL_ETH_MAC_BAR 2 + +#define AL_ETH_MAX_FRAME_LEN 10000 +#define AL_ETH_MIN_FRAME_LEN 60 + +#define AL_ETH_TSO_MSS_MAX_IDX 8 +#define AL_ETH_TSO_MSS_MIN_VAL 1 +/*TODO: update with correct value*/ +#define AL_ETH_TSO_MSS_MAX_VAL (AL_ETH_MAX_FRAME_LEN - 200) + +enum AL_ETH_PROTO_ID { + AL_ETH_PROTO_ID_UNKNOWN = 0, + AL_ETH_PROTO_ID_IPv4 = 8, + AL_ETH_PROTO_ID_IPv6 = 11, + AL_ETH_PROTO_ID_TCP = 12, + AL_ETH_PROTO_ID_UDP = 13, + AL_ETH_PROTO_ID_FCOE = 21, + AL_ETH_PROTO_ID_GRH = 22, /** RoCE l3 header */ + AL_ETH_PROTO_ID_BTH = 23, /** RoCE l4 header */ + AL_ETH_PROTO_ID_ANY = 32, /**< for sw usage only */ +}; +#define AL_ETH_PROTOCOLS_NUM (AL_ETH_PROTO_ID_ANY) + +enum AL_ETH_TX_TUNNEL_MODE { + AL_ETH_NO_TUNNELING = 0, + AL_ETH_TUNNEL_NO_UDP = 1, /* NVGRE / IP over IP */ + AL_ETH_TUNNEL_WITH_UDP = 3, /* VXLAN */ +}; + +#define AL_ETH_RX_THASH_TABLE_SIZE (1 << 8) +#define AL_ETH_RX_FSM_TABLE_SIZE (1 << 7) +#define AL_ETH_RX_CTRL_TABLE_SIZE (1 << 11) +#define AL_ETH_RX_HASH_KEY_NUM 10 +#define AL_ETH_FWD_MAC_NUM 32 +#define AL_ETH_FWD_MAC_HASH_NUM 256 +#define AL_ETH_FWD_PBITS_TABLE_NUM (1 << 3) +#define AL_ETH_FWD_PRIO_TABLE_NUM (1 << 3) +#define AL_ETH_FWD_VID_TABLE_NUM (1 << 12) +#define AL_ETH_FWD_DSCP_TABLE_NUM (1 << 8) +#define AL_ETH_FWD_TC_TABLE_NUM (1 << 8) + +/** MAC media mode */ +enum al_eth_mac_mode { + AL_ETH_MAC_MODE_RGMII, + AL_ETH_MAC_MODE_SGMII, + AL_ETH_MAC_MODE_SGMII_2_5G, + AL_ETH_MAC_MODE_10GbE_Serial, /**< Applies to XFI and KR modes */ + AL_ETH_MAC_MODE_10G_SGMII, /**< SGMII using the 10G MAC, don't use*/ + AL_ETH_MAC_MODE_XLG_LL_40G, /**< applies to 40G mode using the 40G low latency (LL) MAC */ + AL_ETH_MAC_MODE_KR_LL_25G, /**< applies to 25G mode using the 10/25G low latency (LL) MAC */ + AL_ETH_MAC_MODE_XLG_LL_50G /**< applies to 50G mode using the 40/50G low latency (LL) MAC */ +}; + +struct al_eth_capabilities { + al_bool speed_10_HD; + al_bool speed_10_FD; + al_bool speed_100_HD; + al_bool speed_100_FD; + al_bool speed_1000_HD; + al_bool speed_1000_FD; + al_bool speed_10000_HD; + al_bool speed_10000_FD; + al_bool pfc; /**< priority flow control */ + al_bool eee; /**< Energy Efficient Ethernet */ +}; + +/** interface type used for MDIO */ +enum al_eth_mdio_if { + AL_ETH_MDIO_IF_1G_MAC = 0, + AL_ETH_MDIO_IF_10G_MAC = 1 +}; + +/** MDIO protocol type */ +enum al_eth_mdio_type { + AL_ETH_MDIO_TYPE_CLAUSE_22 = 0, + AL_ETH_MDIO_TYPE_CLAUSE_45 = 1 +}; + +/** flow control mode */ +enum al_eth_flow_control_type { + AL_ETH_FLOW_CONTROL_TYPE_LINK_PAUSE, + AL_ETH_FLOW_CONTROL_TYPE_PFC +}; + +/** Tx to Rx switching decision type */ +enum al_eth_tx_switch_dec_type { + AL_ETH_TX_SWITCH_TYPE_MAC = 0, + AL_ETH_TX_SWITCH_TYPE_VLAN_TABLE = 1, + AL_ETH_TX_SWITCH_TYPE_VLAN_TABLE_AND_MAC = 2, + AL_ETH_TX_SWITCH_TYPE_BITMAP = 3 +}; + +/** Tx to Rx VLAN ID selection type */ +enum al_eth_tx_switch_vid_sel_type { + AL_ETH_TX_SWITCH_VID_SEL_TYPE_VLAN1 = 0, + AL_ETH_TX_SWITCH_VID_SEL_TYPE_VLAN2 = 1, + AL_ETH_TX_SWITCH_VID_SEL_TYPE_NEW_VLAN1 = 2, + AL_ETH_TX_SWITCH_VID_SEL_TYPE_NEW_VLAN2 = 3, + AL_ETH_TX_SWITCH_VID_SEL_TYPE_DEFAULT_VLAN1 = 4, + AL_ETH_TX_SWITCH_VID_SEL_TYPE_FINAL_VLAN1 = 5 +}; + +/** Rx descriptor configurations */ +/* Note: when selecting rx descriptor field to inner packet, then that field +* will be set according to inner packet when packet is tunneled, for non-tunneled +* packets, the field will be set according to the packets header */ + +/** selection of the LRO_context_value result in the Metadata */ +enum al_eth_rx_desc_lro_context_val_res { + AL_ETH_LRO_CONTEXT_VALUE = 0, /**< LRO_context_value */ + AL_ETH_L4_OFFSET = 1, /**< L4_offset */ +}; + +/** selection of the L4 offset in the Metadata */ +enum al_eth_rx_desc_l4_offset_sel { + AL_ETH_L4_OFFSET_OUTER = 0, /**< set L4 offset of the outer packet */ + AL_ETH_L4_OFFSET_INNER = 1, /**< set L4 offset of the inner packet */ +}; + +/** selection of the L4 checksum result in the Metadata */ +enum al_eth_rx_desc_l4_chk_res_sel { + AL_ETH_L4_INNER_CHK = 0, /**< L4 checksum */ + AL_ETH_L4_INNER_OUTER_CHK = 1, /**< Logic AND between outer and inner + L4 checksum result */ +}; + +/** selection of the L3 checksum result in the Metadata */ +enum al_eth_rx_desc_l3_chk_res_sel { + AL_ETH_L3_CHK_TYPE_0 = 0, /**< L3 checksum */ + AL_ETH_L3_CHK_TYPE_1 = 1, /**< L3 checksum or RoCE/FCoE CRC, + based on outer header */ + AL_ETH_L3_CHK_TYPE_2 = 2, /**< If tunnel exist = 0, + L3 checksum or RoCE/FCoE CRC, + based on outer header. + Else, + logic AND between outer L3 checksum + (Ipv4) and inner CRC (RoCE or FcoE) */ + AL_ETH_L3_CHK_TYPE_3 = 3, /**< combination of the L3 checksum result and + CRC result,based on the checksum and + RoCE/FCoE CRC input selections. */ +}; + +/** selection of the L3 protocol index in the Metadata */ +enum al_eth_rx_desc_l3_proto_idx_sel { + AL_ETH_L3_PROTO_IDX_OUTER = 0, /**< set L3 proto index of the outer packet */ + AL_ETH_L3_PROTO_IDX_INNER = 1, /**< set L3 proto index of the inner packet */ +}; + +/** selection of the L3 offset in the Metadata */ +enum al_eth_rx_desc_l3_offset_sel { + AL_ETH_L3_OFFSET_OUTER = 0, /**< set L3 offset of the outer packet */ + AL_ETH_L3_OFFSET_INNER = 1, /**< set L3 offset of the inner packet */ +}; + + +/** selection of the L4 protocol index in the Metadata */ +enum al_eth_rx_desc_l4_proto_idx_sel { + AL_ETH_L4_PROTO_IDX_OUTER = 0, /**< set L4 proto index of the outer packet */ + AL_ETH_L4_PROTO_IDX_INNER = 1, /**< set L4 proto index of the inner packet */ +}; + +/** selection of the frag indication in the Metadata */ +enum al_eth_rx_desc_frag_sel { + AL_ETH_FRAG_OUTER = 0, /**< set frag of the outer packet */ + AL_ETH_FRAG_INNER = 1, /**< set frag of the inner packet */ +}; + +/** Ethernet Rx completion descriptor */ +typedef struct { + uint32_t ctrl_meta; + uint32_t len; + uint32_t word2; + uint32_t word3; +} al_eth_rx_cdesc; + +/** Flow Contol parameters */ +struct al_eth_flow_control_params{ + enum al_eth_flow_control_type type; /**< flow control type */ + al_bool obay_enable; /**< stop tx when pause received */ + al_bool gen_enable; /**< generate pause frames */ + uint16_t rx_fifo_th_high; + uint16_t rx_fifo_th_low; + uint16_t quanta; + uint16_t quanta_th; + uint8_t prio_q_map[4][8]; /**< for each UDMA, defines the mapping between + * PFC priority and queues(in bit mask). + * same mapping used for obay and generation. + * for example: + * if prio_q_map[1][7] = 0xC, then TX queues 2 + * and 3 of UDMA 1 will be stopped when pause + * received with priority 7, also, when RX queues + * 2 and 3 of UDMA 1 become almost full, then + * pause frame with priority 7 will be sent. + * + *note: + * 1) if specific a queue is not used, the caller must + * make set the prio_q_map to 0 otherwise that queue + * will make the controller keep sending PAUSE packets. + * 2) queues of unused UDMA must be treated as above. + * 3) when working in LINK PAUSE mode, only entries at + * priority 0 will be considered. + */ +}; + +/* Packet Tx flags */ +#define AL_ETH_TX_FLAGS_TSO AL_BIT(7) /**< Enable TCP/UDP segmentation offloading */ +#define AL_ETH_TX_FLAGS_IPV4_L3_CSUM AL_BIT(13) /**< Enable IPv4 header checksum calculation */ +#define AL_ETH_TX_FLAGS_L4_CSUM AL_BIT(14) /**< Enable TCP/UDP checksum calculation */ +#define AL_ETH_TX_FLAGS_L4_PARTIAL_CSUM AL_BIT(17) /**< L4 partial checksum calculation */ +#define AL_ETH_TX_FLAGS_L2_MACSEC_PKT AL_BIT(16) /**< L2 Packet type 802_3 or 802_3_MACSEC, V2 */ +#define AL_ETH_TX_FLAGS_ENCRYPT AL_BIT(16) /**< Enable TX packet encryption, V3 */ +#define AL_ETH_TX_FLAGS_L2_DIS_FCS AL_BIT(15) /**< Disable CRC calculation*/ +#define AL_ETH_TX_FLAGS_TS AL_BIT(21) /**< Timestamp the packet */ + +#define AL_ETH_TX_FLAGS_INT AL_M2S_DESC_INT_EN +#define AL_ETH_TX_FLAGS_NO_SNOOP AL_M2S_DESC_NO_SNOOP_H + +/** this structure used for tx packet meta data */ +struct al_eth_meta_data{ + uint8_t store :1; /**< store the meta into the queues cache */ + uint8_t words_valid :4; /**< valid bit per word */ + + uint8_t vlan1_cfi_sel:2; + uint8_t vlan2_vid_sel:2; + uint8_t vlan2_cfi_sel:2; + uint8_t vlan2_pbits_sel:2; + uint8_t vlan2_ether_sel:2; + + uint16_t vlan1_new_vid:12; + uint8_t vlan1_new_cfi :1; + uint8_t vlan1_new_pbits :3; + uint16_t vlan2_new_vid:12; + uint8_t vlan2_new_cfi :1; + uint8_t vlan2_new_pbits :3; + + uint8_t l3_header_len; /**< in bytes */ + uint8_t l3_header_offset; + uint8_t l4_header_len; /**< in words(32-bits) */ + + /* rev 0 specific */ + uint8_t mss_idx_sel:3; /**< for TSO, select the register that holds the MSS */ + + /* rev 1 specific */ + uint8_t ts_index:4; /**< index of regiser where to store the tx timestamp */ + uint16_t mss_val :14; /**< for TSO, set the mss value */ + uint8_t outer_l3_offset; /**< for tunneling mode. up to 64 bytes */ + uint8_t outer_l3_len; /**< for tunneling mode. up to 128 bytes */ +}; + +/* Packet Rx flags when adding buffer to receive queue */ + +/**< + * VMID to be assigned to the packet descriptors + * Requires VMID in descriptor to be enabled for the specific UDMA + * queue. + */ +#define AL_ETH_RX_FLAGS_VMID_MASK AL_FIELD_MASK(15, 0) +#define AL_ETH_RX_FLAGS_NO_SNOOP AL_M2S_DESC_NO_SNOOP_H +#define AL_ETH_RX_FLAGS_INT AL_M2S_DESC_INT_EN +#define AL_ETH_RX_FLAGS_DUAL_BUF AL_BIT(31) + +/* Packet Rx flags set by HW when receiving packet */ +#define AL_ETH_RX_ERROR AL_BIT(16) /**< layer 2 errors (FCS, bad len, etc) */ +#define AL_ETH_RX_FLAGS_L4_CSUM_ERR AL_BIT(14) +#define AL_ETH_RX_FLAGS_L3_CSUM_ERR AL_BIT(13) + +/* Packet Rx flags - word 3 in Rx completion descriptor */ +#define AL_ETH_RX_FLAGS_CRC AL_BIT(31) +#define AL_ETH_RX_FLAGS_L3_CSUM_2 AL_BIT(30) +#define AL_ETH_RX_FLAGS_L4_CSUM_2 AL_BIT(29) +#define AL_ETH_RX_FLAGS_SW_SRC_PORT_SHIFT 13 +#define AL_ETH_RX_FLAGS_SW_SRC_PORT_MASK AL_FIELD_MASK(15, 13) +#define AL_ETH_RX_FLAGS_LRO_CONTEXT_VAL_SHIFT 3 +#define AL_ETH_RX_FLAGS_LRO_CONTEXT_VAL_MASK AL_FIELD_MASK(10, 3) +#define AL_ETH_RX_FLAGS_L4_OFFSET_SHIFT 3 +#define AL_ETH_RX_FLAGS_L4_OFFSET_MASK AL_FIELD_MASK(10, 3) +#define AL_ETH_RX_FLAGS_PRIORITY_SHIFT 0 +#define AL_ETH_RX_FLAGS_PRIORITY_MASK AL_FIELD_MASK(2, 0) + +/** packet structure. used for packet transmission and reception */ +struct al_eth_pkt{ + uint32_t flags; /**< see flags above, depends on context(tx or rx) */ + enum AL_ETH_PROTO_ID l3_proto_idx; + enum AL_ETH_PROTO_ID l4_proto_idx; + uint8_t source_vlan_count:2; + uint8_t vlan_mod_add_count:2; + uint8_t vlan_mod_del_count:2; + uint8_t vlan_mod_v1_ether_sel:2; + uint8_t vlan_mod_v1_vid_sel:2; + uint8_t vlan_mod_v1_pbits_sel:2; + + /* rev 1 specific */ + enum AL_ETH_TX_TUNNEL_MODE tunnel_mode; + enum AL_ETH_PROTO_ID outer_l3_proto_idx; /**< for tunneling mode */ + + /**< + * VMID to be assigned to the packet descriptors + * Requires VMID in descriptor to be enabled for the specific UDMA + * queue. + */ + uint16_t vmid; + + uint32_t rx_header_len; /**< header buffer length of rx packet, not used */ + struct al_eth_meta_data *meta; /**< if null, then no meta added */ +#ifdef AL_ETH_RX_DESC_RAW_GET + uint32_t rx_desc_raw[4]; +#endif + uint16_t rxhash; + uint16_t l3_offset; + +#ifdef AL_ETH_EX + struct al_eth_ext_metadata *ext_meta_data; +#endif + + uint8_t num_of_bufs; + struct al_buf bufs[AL_ETH_PKT_MAX_BUFS]; +}; + +struct al_ec_regs; + + +/** Ethernet Adapter private data structure used by this driver */ +struct al_hal_eth_adapter{ + uint8_t rev_id; /**tx_udma, qid, &udma_q); + + return al_udma_available_get(udma_q); +} + +/** + * prepare packet descriptors in tx queue. + * + * This functions prepares the descriptors for the given packet in the tx + * submission ring. the caller must call al_eth_tx_pkt_action() below + * in order to notify the hardware about the new descriptors. + * + * @param tx_dma_q pointer to UDMA tx queue + * @param pkt the packet to transmit + * + * @return number of descriptors used for this packet, 0 if no free + * room in the descriptors ring + */ +int al_eth_tx_pkt_prepare(struct al_udma_q *tx_dma_q, struct al_eth_pkt *pkt); + + +/** + * Trigger the DMA about previously added tx descriptors. + * + * @param tx_dma_q pointer to UDMA tx queue + * @param tx_descs number of descriptors to notify the DMA about. + * the tx_descs can be sum of descriptor numbers of multiple prepared packets, + * this way the caller can use this function to notify the DMA about multiple + * packets. + */ +void al_eth_tx_dma_action(struct al_udma_q *tx_dma_q, uint32_t tx_descs); + +/** + * get number of completed tx descriptors, upper layer should derive from + * this information which packets were completed. + * + * @param tx_dma_q pointer to UDMA tx queue + * + * @return number of completed tx descriptors. + */ +int al_eth_comp_tx_get(struct al_udma_q *tx_dma_q); + +/** + * configure a TSO MSS val + * + * the TSO MSS vals are preconfigured values for MSS stored in hardware and the + * packet could use them when not working in MSS explicit mode. + * @param adapter pointer to the private structure + * @param idx the mss index + * @param mss_val the MSS value + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_tso_mss_config(struct al_hal_eth_adapter *adapter, uint8_t idx, uint32_t mss_val); + +/* RX */ +/** + * Config the RX descriptor fields + * + * @param adapter pointer to the private structure + * @param lro_sel select LRO context or l4 offset + * @param l4_offset_sel select l4 offset source + * @param l4_sel select the l4 checksum result + * @param l3_sel select the l3 checksum result + * @param l3_proto_sel select the l3 protocol index source + * @param l4_proto_sel select the l4 protocol index source + * @param frag_sel select the frag indication source + */ +void al_eth_rx_desc_config( + struct al_hal_eth_adapter *adapter, + enum al_eth_rx_desc_lro_context_val_res lro_sel, + enum al_eth_rx_desc_l4_offset_sel l4_offset_sel, + enum al_eth_rx_desc_l3_offset_sel l3_offset_sel, + enum al_eth_rx_desc_l4_chk_res_sel l4_sel, + enum al_eth_rx_desc_l3_chk_res_sel l3_sel, + enum al_eth_rx_desc_l3_proto_idx_sel l3_proto_sel, + enum al_eth_rx_desc_l4_proto_idx_sel l4_proto_sel, + enum al_eth_rx_desc_frag_sel frag_sel); + +/** + * Configure RX header split + * + * @param adapter pointer to the private structure + * @param enable header split when AL_TRUE + * @param header_split_len length in bytes of the header split, this value used when + * CTRL TABLE header split len select is set to + * AL_ETH_CTRL_TABLE_HDR_SPLIT_LEN_SEL_REG, in this case the controller will + * store the first header_split_len bytes into buf2, then the rest (if any) into buf1. + * when CTRL_TABLE header split len select set to other value, then the header_len + * determined according to the parser, and the header_split_len parameter is not + * used. + * + * return 0 on success. otherwise on failure. + */ +int al_eth_rx_header_split_config(struct al_hal_eth_adapter *adapter, al_bool enable, uint32_t header_len); + +/** + * enable / disable header split in the udma queue. + * length will be taken from the udma configuration to enable different length per queue. + * + * @param adapter pointer to the private structure + * @param enable header split when AL_TRUE + * @param qid the queue id to enable/disable header split + * @param header_len in what len the udma will cut the header + * + * return 0 on success. + */ +int al_eth_rx_header_split_force_len_config(struct al_hal_eth_adapter *adapter, + al_bool enable, + uint32_t qid, + uint32_t header_len); + +/** + * add buffer to receive queue + * + * @param rx_dma_q pointer to UDMA rx queue + * @param buf pointer to data buffer + * @param flags bitwise of AL_ETH_RX_FLAGS + * @param header_buf this is not used for far and header_buf should be set to + * NULL. + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_rx_buffer_add(struct al_udma_q *rx_dma_q, + struct al_buf *buf, uint32_t flags, + struct al_buf *header_buf); + +/** + * notify the hw engine about rx descriptors that were added to the receive queue + * + * @param rx_dma_q pointer to UDMA rx queue + * @param descs_num number of rx descriptors + */ +void al_eth_rx_buffer_action(struct al_udma_q *rx_dma_q, + uint32_t descs_num); + +/** + * get packet from RX completion ring + * + * @param rx_dma_q pointer to UDMA rx queue + * @param pkt pointer to a packet data structure, this function fills this + * structure with the information about the received packet. the buffers + * structures filled only with the length of the data written into the buffer, + * the address fields are not updated as the upper layer can retrieve this + * information by itself because the hardware uses the buffers in the same order + * were those buffers inserted into the ring of the receive queue. + * this structure should be allocated by the caller function. + * + * @return return number of descriptors or 0 if no completed packet found. + */ + uint32_t al_eth_pkt_rx(struct al_udma_q *rx_dma_q, struct al_eth_pkt *pkt); + + +/* RX parser table */ +struct al_eth_epe_p_reg_entry { + uint32_t data; + uint32_t mask; + uint32_t ctrl; +}; + +struct al_eth_epe_control_entry { + uint32_t data[6]; +}; + +/** + * update rx parser entry + * + * @param adapter pointer to the private structure + * @param idx the protocol index to update + * @param reg_entry contents of parser register entry + * @param control entry contents of control table entry + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_rx_parser_entry_update(struct al_hal_eth_adapter *adapter, uint32_t idx, + struct al_eth_epe_p_reg_entry *reg_entry, + struct al_eth_epe_control_entry *control_entry); + +/* Flow Steering and filtering */ +int al_eth_thash_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint8_t udma, uint32_t queue); + +/* FSM table bits */ +/** FSM table has 7 bits input address: + * bits[2:0] are the outer packet's type (IPv4, TCP...) + * bits[5:3] are the inner packet's type + * bit[6] is set when packet is tunneled. + * + * The output of each entry: + * bits[1:0] - input selection: selects the input for the thash (2/4 tuple, inner/outer) + * bit[2] - selects whether to use thash output, or default values for the queue and udma + * bits[6:3] default UDMA mask: the UDMAs to select when bit 2 above was unset + * bits[9:5] defualt queue: the queue index to select when bit 2 above was unset + */ + +#define AL_ETH_FSM_ENTRY_IPV4_TCP 0 +#define AL_ETH_FSM_ENTRY_IPV4_UDP 1 +#define AL_ETH_FSM_ENTRY_IPV6_TCP 2 +#define AL_ETH_FSM_ENTRY_IPV6_UDP 3 +#define AL_ETH_FSM_ENTRY_IPV6_NO_UDP_TCP 4 +#define AL_ETH_FSM_ENTRY_IPV4_NO_UDP_TCP 5 +#define AL_ETH_FSM_ENTRY_IPV4_FRAGMENTED 6 +#define AL_ETH_FSM_ENTRY_NOT_IP 7 + +#define AL_ETH_FSM_ENTRY_OUTER(idx) ((idx) & 7) +#define AL_ETH_FSM_ENTRY_INNER(idx) (((idx) >> 3) & 7) +#define AL_ETH_FSM_ENTRY_TUNNELED(idx) (((idx) >> 6) & 1) + +/* FSM DATA format */ +#define AL_ETH_FSM_DATA_OUTER_2_TUPLE 0 +#define AL_ETH_FSM_DATA_OUTER_4_TUPLE 1 +#define AL_ETH_FSM_DATA_INNER_2_TUPLE 2 +#define AL_ETH_FSM_DATA_INNER_4_TUPLE 3 + +#define AL_ETH_FSM_DATA_HASH_SEL (1 << 2) + +#define AL_ETH_FSM_DATA_DEFAULT_Q_SHIFT 5 +#define AL_ETH_FSM_DATA_DEFAULT_UDMA_SHIFT 3 + +/* set fsm table entry */ +int al_eth_fsm_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint32_t entry); + +enum AL_ETH_FWD_CTRL_IDX_VLAN_TABLE_OUT { + AL_ETH_FWD_CTRL_IDX_VLAN_TABLE_OUT_0 = 0, + AL_ETH_FWD_CTRL_IDX_VLAN_TABLE_OUT_1 = 1, + AL_ETH_FWD_CTRL_IDX_VLAN_TABLE_OUT_ANY = 2, +}; + +enum AL_ETH_FWD_CTRL_IDX_TUNNEL { + AL_ETH_FWD_CTRL_IDX_TUNNEL_NOT_EXIST = 0, + AL_ETH_FWD_CTRL_IDX_TUNNEL_EXIST = 1, + AL_ETH_FWD_CTRL_IDX_TUNNEL_ANY = 2, +}; + +enum AL_ETH_FWD_CTRL_IDX_VLAN { + AL_ETH_FWD_CTRL_IDX_VLAN_NOT_EXIST = 0, + AL_ETH_FWD_CTRL_IDX_VLAN_EXIST = 1, + AL_ETH_FWD_CTRL_IDX_VLAN_ANY = 2, +}; + +enum AL_ETH_FWD_CTRL_IDX_MAC_TABLE { + AL_ETH_FWD_CTRL_IDX_MAC_TABLE_NO_MATCH = 0, + AL_ETH_FWD_CTRL_IDX_MAC_TABLE_MATCH = 1, + AL_ETH_FWD_CTRL_IDX_MAC_TABLE_ANY = 2, +}; + +enum AL_ETH_FWD_CTRL_IDX_MAC_DA_TYPE { + AL_ETH_FWD_CTRL_IDX_MAC_DA_TYPE_UC = 0, /**< unicast */ + AL_ETH_FWD_CTRL_IDX_MAC_DA_TYPE_MC = 1, /**< multicast */ + AL_ETH_FWD_CTRL_IDX_MAC_DA_TYPE_BC = 2, /**< broadcast */ + AL_ETH_FWD_CTRL_IDX_MAC_DA_TYPE_ANY = 4, /**< for sw usage */ +}; + +/** + * This structure defines the index or group of indeces within the control table. + * each field has special enum value (with _ANY postfix) that indicates all + * possible values of that field. + */ +struct al_eth_fwd_ctrl_table_index { + enum AL_ETH_FWD_CTRL_IDX_VLAN_TABLE_OUT vlan_table_out; + enum AL_ETH_FWD_CTRL_IDX_TUNNEL tunnel_exist; + enum AL_ETH_FWD_CTRL_IDX_VLAN vlan_exist; + enum AL_ETH_FWD_CTRL_IDX_MAC_TABLE mac_table_match; + enum AL_ETH_PROTO_ID protocol_id; + enum AL_ETH_FWD_CTRL_IDX_MAC_DA_TYPE mac_type; +}; + +enum AL_ETH_CTRL_TABLE_PRIO_SEL { + AL_ETH_CTRL_TABLE_PRIO_SEL_PBITS_TABLE = 0, + AL_ETH_CTRL_TABLE_PRIO_SEL_DSCP_TABLE = 1, + AL_ETH_CTRL_TABLE_PRIO_SEL_TC_TABLE = 2, + AL_ETH_CTRL_TABLE_PRIO_SEL_REG1 = 3, + AL_ETH_CTRL_TABLE_PRIO_SEL_REG2 = 4, + AL_ETH_CTRL_TABLE_PRIO_SEL_REG3 = 5, + AL_ETH_CTRL_TABLE_PRIO_SEL_REG4 = 6, + AL_ETH_CTRL_TABLE_PRIO_SEL_REG5 = 7, + AL_ETH_CTRL_TABLE_PRIO_SEL_REG6 = 7, + AL_ETH_CTRL_TABLE_PRIO_SEL_REG7 = 9, + AL_ETH_CTRL_TABLE_PRIO_SEL_REG8 = 10, + AL_ETH_CTRL_TABLE_PRIO_SEL_VAL_3 = 11, + AL_ETH_CTRL_TABLE_PRIO_SEL_VAL_0 = 12, +}; +/** where to select the initial queue from */ +enum AL_ETH_CTRL_TABLE_QUEUE_SEL_1 { + AL_ETH_CTRL_TABLE_QUEUE_SEL_1_PRIO_TABLE = 0, + AL_ETH_CTRL_TABLE_QUEUE_SEL_1_THASH_TABLE = 1, + AL_ETH_CTRL_TABLE_QUEUE_SEL_1_MAC_TABLE = 2, + AL_ETH_CTRL_TABLE_QUEUE_SEL_1_MHASH_TABLE = 3, + AL_ETH_CTRL_TABLE_QUEUE_SEL_1_REG1 = 4, + AL_ETH_CTRL_TABLE_QUEUE_SEL_1_REG2 = 5, + AL_ETH_CTRL_TABLE_QUEUE_SEL_1_REG3 = 6, + AL_ETH_CTRL_TABLE_QUEUE_SEL_1_REG4 = 7, + AL_ETH_CTRL_TABLE_QUEUE_SEL_1_VAL_3 = 12, + AL_ETH_CTRL_TABLE_QUEUE_SEL_1_VAL_0 = 13, +}; + +/** target queue will be built up from the priority and initial queue */ +enum AL_ETH_CTRL_TABLE_QUEUE_SEL_2 { + AL_ETH_CTRL_TABLE_QUEUE_SEL_2_PRIO_TABLE = 0, /**< target queue is the output of priority table */ + AL_ETH_CTRL_TABLE_QUEUE_SEL_2_PRIO = 1, /**< target queue is the priority */ + AL_ETH_CTRL_TABLE_QUEUE_SEL_2_PRIO_QUEUE = 2, /**< target queue is initial queue[0], priority[1] */ + AL_ETH_CTRL_TABLE_QUEUE_SEL_2_NO_PRIO = 3, /**< target queue is the initial */ +}; + +enum AL_ETH_CTRL_TABLE_UDMA_SEL { + AL_ETH_CTRL_TABLE_UDMA_SEL_THASH_TABLE = 0, + AL_ETH_CTRL_TABLE_UDMA_SEL_THASH_AND_VLAN = 1, + AL_ETH_CTRL_TABLE_UDMA_SEL_VLAN_TABLE = 2, + AL_ETH_CTRL_TABLE_UDMA_SEL_VLAN_AND_MAC = 3, + AL_ETH_CTRL_TABLE_UDMA_SEL_MAC_TABLE = 4, + AL_ETH_CTRL_TABLE_UDMA_SEL_MAC_AND_MHASH = 5, + AL_ETH_CTRL_TABLE_UDMA_SEL_MHASH_TABLE = 6, + AL_ETH_CTRL_TABLE_UDMA_SEL_REG1 = 7, + AL_ETH_CTRL_TABLE_UDMA_SEL_REG2 = 8, + AL_ETH_CTRL_TABLE_UDMA_SEL_REG3 = 9, + AL_ETH_CTRL_TABLE_UDMA_SEL_REG4 = 10, + AL_ETH_CTRL_TABLE_UDMA_SEL_REG5 = 11, + AL_ETH_CTRL_TABLE_UDMA_SEL_REG6 = 12, + AL_ETH_CTRL_TABLE_UDMA_SEL_REG7 = 13, + AL_ETH_CTRL_TABLE_UDMA_SEL_REG8 = 14, + AL_ETH_CTRL_TABLE_UDMA_SEL_VAL_0 = 15, +}; + +enum AL_ETH_CTRL_TABLE_HDR_SPLIT_LEN_SEL { + AL_ETH_CTRL_TABLE_HDR_SPLIT_LEN_SEL_0 = 0, + AL_ETH_CTRL_TABLE_HDR_SPLIT_LEN_SEL_REG = 1, /**< select header len from the hdr_split register (set by al_eth_rx_header_split_config())*/ + AL_ETH_CTRL_TABLE_HDR_SPLIT_LEN_SEL_OUTER_L3_OFFSET = 2, + AL_ETH_CTRL_TABLE_HDR_SPLIT_LEN_SEL_OUTER_L4_OFFSET = 3, + AL_ETH_CTRL_TABLE_HDR_SPLIT_LEN_SEL_TUNNEL_START_OFFSET = 4, + AL_ETH_CTRL_TABLE_HDR_SPLIT_LEN_SEL_INNER_L3_OFFSET = 5, + AL_ETH_CTRL_TABLE_HDR_SPLIT_LEN_SEL_INNER_L4_OFFSET = 6, +}; + +struct al_eth_fwd_ctrl_table_entry { + enum AL_ETH_CTRL_TABLE_PRIO_SEL prio_sel; + enum AL_ETH_CTRL_TABLE_QUEUE_SEL_1 queue_sel_1; /**< queue id source */ + enum AL_ETH_CTRL_TABLE_QUEUE_SEL_2 queue_sel_2; /**< mix queue id with priority */ + enum AL_ETH_CTRL_TABLE_UDMA_SEL udma_sel; + enum AL_ETH_CTRL_TABLE_HDR_SPLIT_LEN_SEL hdr_split_len_sel; + al_bool filter; /**< set to AL_TRUE to enable filtering */ +}; +/** + * Configure default control table entry + * + * @param adapter pointer to the private structure + * @param use_table set to AL_TRUE if control table is used, when set to AL_FALSE + * then control table will be bypassed and the entry value will be used. + * @param entry defines the value to be used when bypassing control table. + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_ctrl_table_def_set(struct al_hal_eth_adapter *adapter, + al_bool use_table, + struct al_eth_fwd_ctrl_table_entry *entry); + +/** + * Configure control table entry + * + * @param adapter pointer to the private structure + * @param index the entry index within the control table. + * @param entry the value to write to the control table entry + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_ctrl_table_set(struct al_hal_eth_adapter *adapter, + struct al_eth_fwd_ctrl_table_index *index, + struct al_eth_fwd_ctrl_table_entry *entry); + +int al_eth_ctrl_table_raw_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint32_t entry); +int al_eth_ctrl_table_def_raw_set(struct al_hal_eth_adapter *adapter, uint32_t val); + +/** + * Configure hash key initial registers + * Those registers define the initial key values, those values used for + * the THASH and MHASH hash functions. + * + * @param adapter pointer to the private structure + * @param idx the register index + * @param val the register value + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_hash_key_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint32_t val); + +struct al_eth_fwd_mac_table_entry { + uint8_t addr[6]; /**< byte 0 is the first byte seen on the wire */ + uint8_t mask[6]; + al_bool tx_valid; + uint8_t tx_target; + al_bool rx_valid; + uint8_t udma_mask; /**< target udma */ + uint8_t qid; /**< target queue */ + al_bool filter; /**< set to AL_TRUE to enable filtering */ +}; + +/** + * Configure mac table entry + * The HW traverse this table and looks for match from lowest index, + * when the packets MAC DA & mask == addr, and the valid bit is set, then match occurs. + * + * @param adapter pointer to the private structure + * @param idx the entry index within the mac table. + * @param entry the contents of the MAC table entry + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_fwd_mac_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, + struct al_eth_fwd_mac_table_entry *entry); + +int al_eth_fwd_mac_addr_raw_set(struct al_hal_eth_adapter *adapter, uint32_t idx, + uint32_t addr_lo, uint32_t addr_hi, uint32_t mask_lo, uint32_t mask_hi); +int al_eth_fwd_mac_ctrl_raw_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint32_t ctrl); + +int al_eth_mac_addr_store(void * __iomem ec_base, uint32_t idx, uint8_t *addr); +int al_eth_mac_addr_read(void * __iomem ec_base, uint32_t idx, uint8_t *addr); + +/** + * Configure pbits table entry + * The HW uses this table to translate between vlan pbits field to priority. + * The vlan pbits is used as the index of this table. + * + * @param adapter pointer to the private structure + * @param idx the entry index within the table. + * @param prio the priority to set for this entry + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_fwd_pbits_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint8_t prio); + +/** + * Configure priority table entry + * The HW uses this table to translate between priority to queue index. + * The priority is used as the index of this table. + * + * @param adapter pointer to the private structure + * @param prio the entry index within the table. + * @param qid the queue index to set for this entry (priority). + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_fwd_priority_table_set(struct al_hal_eth_adapter *adapter, uint8_t prio, uint8_t qid); + +/** + * Configure DSCP table entry + * The HW uses this table to translate between IPv4 DSCP field to priority. + * The IPv4 byte 1 (DSCP+ECN) used as index to this table. + * + * @param adapter pointer to the private structure + * @param idx the entry index within the table. + * @param prio the queue index to set for this entry (priority). + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_fwd_dscp_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint8_t prio); + +/** + * Configure TC table entry + * The HW uses this table to translate between IPv6 TC field to priority. + * The IPv6 TC used as index to this table. + * + * @param adapter pointer to the private structure + * @param idx the entry index within the table. + * @param prio the queue index to set for this entry (priority). + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_fwd_tc_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint8_t prio); + +/** + * Configure MAC HASH table entry + * The HW uses 8 bits from the hash result on the MAC DA as index to this table. + * + * @param adapter pointer to the private structure + * @param idx the entry index within the table. + * @param udma_mask the target udma to set for this entry. + * @param qid the target queue index to set for this entry. + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_fwd_mhash_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint8_t udma_mask, uint8_t qid); + +struct al_eth_fwd_vid_table_entry { + uint8_t control:1; /**< used as input for the control table */ + uint8_t filter:1; /**< set to 1 to enable filtering */ + uint8_t udma_mask:4; /**< target udmas */ +}; + +/** + * Configure default vlan table entry + * + * @param adapter pointer to the private structure + * @param use_table set to AL_TRUE if vlan table is used, when set to AL_FALSE + * then vid table will be bypassed and the default_entry value will be used. + * @param default_entry defines the value to be used when bypassing vid table. + * @param default_vlan defines the value will be used when untagget packet + * received. this value will be used only for steering and filtering control, + * the packet's data will not be changed. + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_fwd_vid_config_set(struct al_hal_eth_adapter *adapter, al_bool use_table, + struct al_eth_fwd_vid_table_entry *default_entry, + uint32_t default_vlan); +/** + * Configure vlan table entry + * + * @param adapter pointer to the private structure + * @param idx the entry index within the vlan table. The HW uses the vlan id + * field of the packet when accessing this table. + * @param entry the value to write to the vlan table entry + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_fwd_vid_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, + struct al_eth_fwd_vid_table_entry *entry); + + +/** + * Configure default UDMA register + * When the control table entry udma selection set to AL_ETH_CTRL_TABLE_UDMA_SEL_REG, + * then the target UDMA will be set according to the register n of the default + * UDMA registers. + * + * @param adapter pointer to the private structure + * @param idx the index of the default register. + * @param udma_mask the value of the register. + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_fwd_default_udma_config(struct al_hal_eth_adapter *adapter, uint32_t idx, + uint8_t udma_mask); + +/** + * Configure default queue register + * When the control table entry queue selection 1 set to AL_ETH_CTRL_TABLE_QUEUE_SEL_1_REG, + * then the target queue will be set according to the register n of the default + * queue registers. + * + * @param adapter pointer to the private structure + * @param idx the index of the default register. + * @param qid the value of the register. + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_fwd_default_queue_config(struct al_hal_eth_adapter *adapter, uint32_t idx, + uint8_t qid); + +/** + * Configure default priority register + * When the control table entry queue selection 1 set to AL_ETH_CTRL_TABLE_PRIO_SEL_1_REG, + * then the target priority will be set according to the register n of the default + * priority registers. + * + * @param adapter pointer to the private structure + * @param idx the index of the default register. + * @param prio the value of the register. + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_fwd_default_priority_config(struct al_hal_eth_adapter *adapter, uint32_t idx, + uint8_t prio); + + + +/* filter undetected MAC DA */ +#define AL_ETH_RFW_FILTER_UNDET_MAC (1 << 0) +/* filter specific MAC DA based on MAC table output */ +#define AL_ETH_RFW_FILTER_DET_MAC (1 << 1) +/* filter all tagged */ +#define AL_ETH_RFW_FILTER_TAGGED (1 << 2) +/* filter all untagged */ +#define AL_ETH_RFW_FILTER_UNTAGGED (1 << 3) +/* filter all broadcast */ +#define AL_ETH_RFW_FILTER_BC (1 << 4) +/* filter all multicast */ +#define AL_ETH_RFW_FILTER_MC (1 << 5) +/* filter packet based on parser drop */ +#define AL_ETH_RFW_FILTER_PARSE (1 << 6) +/* filter packet based on VLAN table output */ +#define AL_ETH_RFW_FILTER_VLAN_VID (1 << 7) +/* filter packet based on control table output */ +#define AL_ETH_RFW_FILTER_CTRL_TABLE (1 << 8) +/* filter packet based on protocol index */ +#define AL_ETH_RFW_FILTER_PROT_INDEX (1 << 9) +/* filter packet based on WoL decision */ +#define AL_ETH_RFW_FILTER_WOL (1 << 10) + + +struct al_eth_filter_params { + al_bool enable; + uint32_t filters; /**< bitmask of AL_ETH_RFW_FILTER.. for filters to enable */ + al_bool filter_proto[AL_ETH_PROTOCOLS_NUM]; /**< set AL_TRUE for protocols to filter */ +}; + +struct al_eth_filter_override_params { + uint32_t filters; /**< bitmask of AL_ETH_RFW_FILTER.. for filters to override */ + uint8_t udma; /**< target udma id */ + uint8_t qid; /**< target queue id */ +}; + +/** + * Configure the receive filters + * this function enables/disables filtering packets and which filtering + * types to apply. + * filters that indicated in tables (MAC table, VLAN and Control tables) + * are not configured by this function. This functions only enables/disables + * respecting the filter indication from those tables. + * + * @param adapter pointer to the private structure + * @param params the parameters passed from upper layer + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_filter_config(struct al_hal_eth_adapter *adapter, struct al_eth_filter_params *params); + +/** + * Configure the receive override filters + * This function controls whither to force forwarding filtered packets + * to a specific UDMA/queue. The override filters apply only for + * filters that enabled by al_eth_filter_config(). + * + * @param adapter pointer to the private structure + * @param params override config parameters + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_filter_override_config(struct al_hal_eth_adapter *adapter, + struct al_eth_filter_override_params *params); + + +int al_eth_switching_config_set(struct al_hal_eth_adapter *adapter, uint8_t udma_id, uint8_t forward_all_to_mac, uint8_t enable_int_switching, + enum al_eth_tx_switch_vid_sel_type vid_sel_type, + enum al_eth_tx_switch_dec_type uc_dec, + enum al_eth_tx_switch_dec_type mc_dec, + enum al_eth_tx_switch_dec_type bc_dec); +int al_eth_switching_default_bitmap_set(struct al_hal_eth_adapter *adapter, uint8_t udma_id, uint8_t udma_uc_bitmask, + uint8_t udma_mc_bitmask,uint8_t udma_bc_bitmask); +int al_eth_flow_control_config(struct al_hal_eth_adapter *adapter, struct al_eth_flow_control_params *params); + +struct al_eth_eee_params{ + uint8_t enable; + uint32_t tx_eee_timer; /**< time in cycles the interface delays prior to entering eee state */ + uint32_t min_interval; /**< minimum interval in cycles between two eee states */ + uint32_t stop_cnt; /**< time in cycles to stop Tx mac i/f after getting out of eee state */ +}; + +/** + * configure EEE mode + * @param adapter pointer to the private structure. + * @param params pointer to the eee input parameters. + * + * @return return 0 on success. otherwise on failure. + */ +int al_eth_eee_config(struct al_hal_eth_adapter *adapter, struct al_eth_eee_params *params); + +/** + * get EEE configuration + * @param adapter pointer to the private structure. + * @param params pointer to the eee output parameters. + * + * @return return 0 on success. otherwise on failure. + */ +int al_eth_eee_get(struct al_hal_eth_adapter *adapter, struct al_eth_eee_params *params); + +int al_eth_vlan_mod_config(struct al_hal_eth_adapter *adapter, uint8_t udma_id, uint16_t udma_etype, uint16_t vlan1_data, uint16_t vlan2_data); + +/* Timestamp + * This is a generic time-stamp mechanism that can be used as generic to + * time-stamp every received or transmit packet it can also support IEEE 1588v2 + * PTP time synchronization protocol. + * In addition to time-stamp, an internal system time is maintained. For + * further accuracy, the chip support transmit/receive clock synchronization + * including recovery of master clock from one of the ports and distributing it + * to the rest of the ports - that is outside the scope of the Ethernet + * Controller - please refer to Annapurna Labs Alpine Hardware Wiki + */ + +/* Timestamp management APIs */ + +/** + * prepare the adapter for timestamping packets. + * Rx timestamps requires using 8 words (8x4 bytes) rx completion descriptor + * size as the timestamp value added into word 4. + * + * This function should be called after al_eth_mac_config() and before + * enabling the queues. + * @param adapter pointer to the private structure. + * @return 0 on success. otherwise on failure. + */ +int al_eth_ts_init(struct al_hal_eth_adapter *adapter); + +/* Timestamp data path APIs */ + +/* + * This is the size of the on-chip array that keeps the time-stamp of the + * latest transmitted packets + */ +#define AL_ETH_PTH_TX_SAMPLES_NUM 16 + +/** + * read Timestamp sample value of previously transmitted packet. + * + * The adapter includes AL_ETH_PTH_TX_SAMPLES_NUM timestamp samples for tx + * packets, those samples shared for all the UDMAs and queues. the al_eth_pkt + * data structure includes the index of which sample to use for the packet + * to transmit. It's the caller's responsibility to manage those samples, + * for example, when using an index, the caller must make sure the packet + * is completed and the tx time is sampled before using that index for + * another packet. + * + * This function should be called after the completion indication of the + * tx packet. however, there is a little chance that the timestamp sample + * won't be updated yet, thus this function must be called again when it + * returns -EAGAIN. + * @param adapter pointer to the private structure. + * @param ts_index the index (out of 16) of the timestamp register + * @param timestamp the timestamp value in 2^18 femtoseconds resolution. + * @return -EAGAIN if the sample was not updated yet. 0 when the sample + * was updated and no errors found. + */ +int al_eth_tx_ts_val_get(struct al_hal_eth_adapter *adapter, uint8_t ts_index, + uint32_t *timestamp); + +/* Timestamp PTH (PTP Timestamp Handler) control and times management */ +/** structure for describing PTH epoch time */ +struct al_eth_pth_time { + uint32_t seconds; /**< seconds */ + uint64_t femto; /**< femto seconds */ +}; + +/** + * Read the systime value + * This API should not be used to get the timestamp of packets. + * The HW maintains 50 bits for the sub-seconds portion in femto resolution, + * but this function reads only the 32 MSB bits since the LSB provides + * sub-nanoseconds accuracy, which is not needed. + * @param adapter pointer to the private structure. + * @param systime pointer to structure where the time will be stored. + * @return 0 on success. otherwise on failure. + */ +int al_eth_pth_systime_read(struct al_hal_eth_adapter *adapter, + struct al_eth_pth_time *systime); + +/** + * Set the clock period to a given value. + * The systime will be incremented by this value on each posedge of the + * adapters internal clock which driven by the SouthBridge clock. + * @param adapter pointer to the private structure. + * @param clk_period the clock period in femto seconds. + * @return 0 on success. otherwise on failure. + */ +int al_eth_pth_clk_period_write(struct al_hal_eth_adapter *adapter, + uint64_t clk_period); + +/**< enum for methods when updating systime using triggers */ +enum al_eth_pth_update_method { + AL_ETH_PTH_UPDATE_METHOD_SET = 0, /**< Set the time in int/ext update time */ + AL_ETH_PTH_UPDATE_METHOD_INC = 1, /**< increment */ + AL_ETH_PTH_UPDATE_METHOD_DEC = 2, /**< decrement */ + AL_ETH_PTH_UPDATE_METHOD_ADD_TO_LAST = 3, /**< Set to last time + int/ext update time.*/ +}; + +/**< systime internal update trigger types */ +enum al_eth_pth_int_trig { + AL_ETH_PTH_INT_TRIG_OUT_PULSE_0 = 0, /**< use output pulse as trigger */ + AL_ETH_PTH_INT_TRIG_REG_WRITE = 1, /**< use the int update register + * write as a trigger + */ +}; + +/**< parameters for internal trigger update */ +struct al_eth_pth_int_update_params { + al_bool enable; /**< enable internal trigger update */ + enum al_eth_pth_update_method method; /**< internal trigger update + * method + */ + enum al_eth_pth_int_trig trigger; /**< which internal trigger to + * use + */ +}; + +/** + * Configure the systime internal update + * + * @param adapter pointer to the private structure. + * @param params the configuration of the internal update. + * @return 0 on success. otherwise on failure. + */ +int al_eth_pth_int_update_config(struct al_hal_eth_adapter *adapter, + struct al_eth_pth_int_update_params *params); + +/** + * set internal update time + * + * The update time used when updating the systime with + * internal update method. + * + * @param adapter pointer to the private structure. + * @param time the internal update time value + * @return 0 on success. otherwise on failure. + */ +int al_eth_pth_int_update_time_set(struct al_hal_eth_adapter *adapter, + struct al_eth_pth_time *time); + +/**< parameters for external trigger update */ +struct al_eth_pth_ext_update_params { + uint8_t triggers; /**< bitmask of external triggers to enable */ + enum al_eth_pth_update_method method; /**< external trigger update + * method + */ +}; + +/** + * Configure the systime external update. + * external update triggered by external signals such as GPIO or pulses + * from other eth controllers on the SoC. + * + * @param adapter pointer to the private structure. + * @param params the configuration of the external update. + * @return 0 on success. otherwise on failure. + */ +int al_eth_pth_ext_update_config(struct al_hal_eth_adapter *adapter, + struct al_eth_pth_ext_update_params *params); + +/** + * set external update time + * + * The update time used when updating the systime with + * external update method. + * @param adapter pointer to the private structure. + * @param time the external update time value + * @return 0 on success. otherwise on failure. + */ +int al_eth_pth_ext_update_time_set(struct al_hal_eth_adapter *adapter, + struct al_eth_pth_time *time); +/** + * set the read compensation delay + * + * When reading the systime, the HW adds this value to compensate + * read latency. + * + * @param adapter pointer to the private structure. + * @param subseconds the read latency delay in femto seconds. + * @return 0 on success. otherwise on failure. + */ +int al_eth_pth_read_compensation_set(struct al_hal_eth_adapter *adapter, + uint64_t subseconds); +/** + * set the internal write compensation delay + * + * When updating the systime due to an internal trigger's event, the HW adds + * this value to compensate latency. + * + * @param adapter pointer to the private structure. + * @param subseconds the write latency delay in femto seconds. + * @return 0 on success. otherwise on failure. + */ +int al_eth_pth_int_write_compensation_set(struct al_hal_eth_adapter *adapter, + uint64_t subseconds); + +/** + * set the external write compensation delay + * + * When updating the systime due to an external trigger's event, the HW adds + * this value to compensate pulse propagation latency. + * + * @param adapter pointer to the private structure. + * @param subseconds the write latency delay in femto seconds. + * @return 0 on success. otherwise on failure. + */ +int al_eth_pth_ext_write_compensation_set(struct al_hal_eth_adapter *adapter, + uint64_t subseconds); + +/** + * set the sync compensation delay + * + * When the adapter passes systime from PTH to MAC to do the packets + * timestamping, the sync compensation delay is added to systime value to + * compensate the latency between the PTH and the MAC. + * + * @param adapter pointer to the private structure. + * @param subseconds the sync latency delay in femto seconds. + * @return 0 on success. otherwise on failure. + */ +int al_eth_pth_sync_compensation_set(struct al_hal_eth_adapter *adapter, + uint64_t subseconds); + +#define AL_ETH_PTH_PULSE_OUT_NUM 8 +struct al_eth_pth_pulse_out_params { + uint8_t index; /**< id of the pulse (0..7) */ + al_bool enable; + al_bool periodic; /**< when true, generate periodic pulse (PPS) */ + uint8_t period_sec; /**< for periodic pulse, this is seconds + * portion of the period time + */ + uint32_t period_us; /**< this is microseconds portion of the + * period + */ + struct al_eth_pth_time start_time; /**< when to start pulse triggering */ + uint64_t pulse_width; /**< pulse width in femto seconds */ +}; + +/** + * Configure an output pulse + * This function configures an output pulse coming from the internal System + * Time. This is typically a 1Hhz pulse that is used to synchronize the + * rest of the components of the system. This API configure the Ethernet + * Controller pulse. An additional set up is required to configure the chip + * General Purpose I/O (GPIO) to enable the chip output pin. + * + * @param adapter pointer to the private structure. + * @param params output pulse configuration. + * @return 0 on success. otherwise on failure. + */ +int al_eth_pth_pulse_out_config(struct al_hal_eth_adapter *adapter, + struct al_eth_pth_pulse_out_params *params); + +/* link */ +struct al_eth_link_status { + al_bool link_up; +}; + +/** + * get link status + * + * this function should be used when no external phy is used to get + * information about the link + * + * @param adapter pointer to the private structure. + * @param status pointer to struct where to set link information + * + * @return return 0 on success. otherwise on failure. + */ +int al_eth_link_status_get(struct al_hal_eth_adapter *adapter, struct al_eth_link_status *status); + +/** + * Set LEDs to represent link status. + * + * @param adapter pointer to the private structure. + * @param link_is_up boolean indicating current link status. + * In case link is down the leds will be turned off. + * In case link is up the leds will be turned on, that means + * leds will be blinking on traffic and will be constantly lighting + * on inactive link + * @return return 0 on success. otherwise on failure. + */ +int al_eth_led_set(struct al_hal_eth_adapter *adapter, al_bool link_is_up); + +/* get statistics */ + +struct al_eth_mac_stats{ + /* sum the data and padding octets (i.e. without header and FCS) received with a valid frame. */ + uint64_t aOctetsReceivedOK; + /* sum of Payload and padding octets of frames transmitted without error*/ + uint64_t aOctetsTransmittedOK; + /* total number of packets received. Good and bad packets */ + uint32_t etherStatsPkts; + /* number of received unicast packets */ + uint32_t ifInUcastPkts; + /* number of received multicast packets */ + uint32_t ifInMulticastPkts; + /* number of received broadcast packets */ + uint32_t ifInBroadcastPkts; + /* Number of frames received with FIFO Overflow, CRC, Payload Length, Jabber and Oversized, Alignment or PHY/PCS error indication */ + uint32_t ifInErrors; + + /* number of transmitted unicast packets */ + uint32_t ifOutUcastPkts; + /* number of transmitted multicast packets */ + uint32_t ifOutMulticastPkts; + /* number of transmitted broadcast packets */ + uint32_t ifOutBroadcastPkts; + /* number of frames transmitted with FIFO Overflow, FIFO Underflow or Controller indicated error */ + uint32_t ifOutErrors; + + /* number of Frame received without error (Including Pause Frames). */ + uint32_t aFramesReceivedOK; + /* number of Frames transmitter without error (Including Pause Frames) */ + uint32_t aFramesTransmittedOK; + /* number of packets received with less than 64 octets */ + uint32_t etherStatsUndersizePkts; + /* Too short frames with CRC error, available only for RGMII and 1G Serial modes */ + uint32_t etherStatsFragments; + /* Too long frames with CRC error */ + uint32_t etherStatsJabbers; + /* packet that exceeds the valid maximum programmed frame length */ + uint32_t etherStatsOversizePkts; + /* number of frames received with a CRC error */ + uint32_t aFrameCheckSequenceErrors; + /* number of frames received with alignment error */ + uint32_t aAlignmentErrors; + /* number of dropped packets due to FIFO overflow */ + uint32_t etherStatsDropEvents; + /* number of transmitted pause frames. */ + uint32_t aPAUSEMACCtrlFramesTransmitted; + /* number of received pause frames. */ + uint32_t aPAUSEMACCtrlFramesReceived; + /* frame received exceeded the maximum length programmed with register FRM_LGTH, available only for 10G modes */ + uint32_t aFrameTooLongErrors; + /* received frame with bad length/type (between 46 and 0x600 or less + * than 46 for packets longer than 64), available only for 10G modes */ + uint32_t aInRangeLengthErrors; + /* Valid VLAN tagged frames transmitted */ + uint32_t VLANTransmittedOK; + /* Valid VLAN tagged frames received */ + uint32_t VLANReceivedOK; + /* Total number of octets received. Good and bad packets */ + uint32_t etherStatsOctets; + + /* packets of 64 octets length is received (good and bad frames are counted) */ + uint32_t etherStatsPkts64Octets; + /* Frames (good and bad) with 65 to 127 octets */ + uint32_t etherStatsPkts65to127Octets; + /* Frames (good and bad) with 128 to 255 octets */ + uint32_t etherStatsPkts128to255Octets; + /* Frames (good and bad) with 256 to 511 octets */ + uint32_t etherStatsPkts256to511Octets; + /* Frames (good and bad) with 512 to 1023 octets */ + uint32_t etherStatsPkts512to1023Octets; + /* Frames (good and bad) with 1024 to 1518 octets */ + uint32_t etherStatsPkts1024to1518Octets; + /* frames with 1519 bytes to the maximum length programmed in the register FRAME_LENGTH. */ + uint32_t etherStatsPkts1519toX; + + uint32_t eee_in; + uint32_t eee_out; +}; + +/** + * get mac statistics + * @param adapter pointer to the private structure. + * @param stats pointer to structure that will be filled with statistics. + * + * @return return 0 on success. otherwise on failure. + */ +int al_eth_mac_stats_get(struct al_hal_eth_adapter *adapter, struct al_eth_mac_stats *stats); + +struct al_eth_ec_stats{ + /* Rx Frequency adjust FIFO input packets */ + uint32_t faf_in_rx_pkt; + /* Rx Frequency adjust FIFO input short error packets */ + uint32_t faf_in_rx_short; + /* Rx Frequency adjust FIFO input long error packets */ + uint32_t faf_in_rx_long; + /* Rx Frequency adjust FIFO output packets */ + uint32_t faf_out_rx_pkt; + /* Rx Frequency adjust FIFO output short error packets */ + uint32_t faf_out_rx_short; + /* Rx Frequency adjust FIFO output long error packets */ + uint32_t faf_out_rx_long; + /* Rx Frequency adjust FIFO output drop packets */ + uint32_t faf_out_drop; + /* Number of packets written into the Rx FIFO (without FIFO error indication) */ + uint32_t rxf_in_rx_pkt; + /* Number of error packets written into the Rx FIFO (with FIFO error indication, */ + /* FIFO full indication during packet reception) */ + uint32_t rxf_in_fifo_err; + /* Number of packets read from Rx FIFO 1 */ + uint32_t lbf_in_rx_pkt; + /* Number of packets read from Rx FIFO 2 (loopback FIFO) */ + uint32_t lbf_in_fifo_err; + /* Rx FIFO output drop packets from FIFO 1 */ + uint32_t rxf_out_rx_1_pkt; + /* Rx FIFO output drop packets from FIFO 2 (loop back) */ + uint32_t rxf_out_rx_2_pkt; + /* Rx FIFO output drop packets from FIFO 1 */ + uint32_t rxf_out_drop_1_pkt; + /* Rx FIFO output drop packets from FIFO 2 (loop back) */ + uint32_t rxf_out_drop_2_pkt; + /* Rx Parser 1, input packet counter */ + uint32_t rpe_1_in_rx_pkt; + /* Rx Parser 1, output packet counter */ + uint32_t rpe_1_out_rx_pkt; + /* Rx Parser 2, input packet counter */ + uint32_t rpe_2_in_rx_pkt; + /* Rx Parser 2, output packet counter */ + uint32_t rpe_2_out_rx_pkt; + /* Rx Parser 3 (MACsec), input packet counter */ + uint32_t rpe_3_in_rx_pkt; + /* Rx Parser 3 (MACsec), output packet counter */ + uint32_t rpe_3_out_rx_pkt; + /* Tx parser, input packet counter */ + uint32_t tpe_in_tx_pkt; + /* Tx parser, output packet counter */ + uint32_t tpe_out_tx_pkt; + /* Tx packet modification, input packet counter */ + uint32_t tpm_tx_pkt; + /* Tx forwarding input packet counter */ + uint32_t tfw_in_tx_pkt; + /* Tx forwarding input packet counter */ + uint32_t tfw_out_tx_pkt; + /* Rx forwarding input packet counter */ + uint32_t rfw_in_rx_pkt; + /* Rx Forwarding, packet with VLAN command drop indication */ + uint32_t rfw_in_vlan_drop; + /* Rx Forwarding, packets with parse drop indication */ + uint32_t rfw_in_parse_drop; + /* Rx Forwarding, multicast packets */ + uint32_t rfw_in_mc; + /* Rx Forwarding, broadcast packets */ + uint32_t rfw_in_bc; + /* Rx Forwarding, tagged packets */ + uint32_t rfw_in_vlan_exist; + /* Rx Forwarding, untagged packets */ + uint32_t rfw_in_vlan_nexist; + /* Rx Forwarding, packets with MAC address drop indication (from the MAC address table) */ + uint32_t rfw_in_mac_drop; + /* Rx Forwarding, packets with undetected MAC address */ + uint32_t rfw_in_mac_ndet_drop; + /* Rx Forwarding, packets with drop indication from the control table */ + uint32_t rfw_in_ctrl_drop; + /* Rx Forwarding, packets with L3_protocol_index drop indication */ + uint32_t rfw_in_prot_i_drop; + /* EEE, number of times the system went into EEE state */ + uint32_t eee_in; +}; + +/** + * get ec statistics + * @param adapter pointer to the private structure. + * @param stats pointer to structure that will be filled with statistics. + * + * @return return 0 on success. otherwise on failure. + */ +int al_eth_ec_stats_get(struct al_hal_eth_adapter *adapter, struct al_eth_ec_stats *stats); + +struct al_eth_ec_stat_udma{ + /* Rx forwarding output packet counter */ + uint32_t rfw_out_rx_pkt; + /* Rx forwarding output drop packet counter */ + uint32_t rfw_out_drop; + /* Multi-stream write, number of Rx packets */ + uint32_t msw_in_rx_pkt; + /* Multi-stream write, number of dropped packets at SOP, Q full indication */ + uint32_t msw_drop_q_full; + /* Multi-stream write, number of dropped packets at SOP */ + uint32_t msw_drop_sop; + /* Multi-stream write, number of dropped packets at EOP, */ + /*EOP was written with error indication (not all packet data was written) */ + uint32_t msw_drop_eop; + /* Multi-stream write, number of packets written to the stream FIFO with EOP and without packet loss */ + uint32_t msw_wr_eop; + /* Multi-stream write, number of packets read from the FIFO into the stream */ + uint32_t msw_out_rx_pkt; + /* Number of transmitted packets without TSO enabled */ + uint32_t tso_no_tso_pkt; + /* Number of transmitted packets with TSO enabled */ + uint32_t tso_tso_pkt; + /* Number of TSO segments that were generated */ + uint32_t tso_seg_pkt; + /* Number of TSO segments that required padding */ + uint32_t tso_pad_pkt; + /* Tx Packet modification, MAC SA spoof error */ + uint32_t tpm_tx_spoof; + /* Tx MAC interface, input packet counter */ + uint32_t tmi_in_tx_pkt; + /* Tx MAC interface, number of packets forwarded to the MAC */ + uint32_t tmi_out_to_mac; + /* Tx MAC interface, number of packets forwarded to the Rx data path */ + uint32_t tmi_out_to_rx; + /* Tx MAC interface, number of transmitted bytes */ + uint32_t tx_q0_bytes; + /* Tx MAC interface, number of transmitted bytes */ + uint32_t tx_q1_bytes; + /* Tx MAC interface, number of transmitted bytes */ + uint32_t tx_q2_bytes; + /* Tx MAC interface, number of transmitted bytes */ + uint32_t tx_q3_bytes; + /* Tx MAC interface, number of transmitted packets */ + uint32_t tx_q0_pkts; + /* Tx MAC interface, number of transmitted packets */ + uint32_t tx_q1_pkts; + /* Tx MAC interface, number of transmitted packets */ + uint32_t tx_q2_pkts; + /* Tx MAC interface, number of transmitted packets */ + uint32_t tx_q3_pkts; +}; + +/** + * get per_udma statistics + * @param adapter pointer to the private structure. + * @param idx udma_id value + * @param stats pointer to structure that will be filled with statistics. + * + * @return return 0 on success. otherwise on failure. + */ +int al_eth_ec_stat_udma_get(struct al_hal_eth_adapter *adapter, uint8_t idx, struct al_eth_ec_stat_udma *stats); + +/* trafic control */ + +/** + * perform Function Level Reset RMN + * + * Addressing RMN: 714 + * + * @param pci_read_config_u32 pointer to function that reads register from pci header + * @param pci_write_config_u32 pointer to function that writes register from pci header + * @param handle pointer passes to the above functions as first parameter + * @param mac_base base address of the MAC registers + * + * @return 0. + */ +int al_eth_flr_rmn(int (* pci_read_config_u32)(void *handle, int where, uint32_t *val), + int (* pci_write_config_u32)(void *handle, int where, uint32_t val), + void *handle, + void __iomem *mac_base); + +/** + * perform Function Level Reset RMN but restore registers that contain board specific data + * + * the data that save and restored is the board params and mac addresses + * + * @param pci_read_config_u32 pointer to function that reads register from pci header + * @param pci_write_config_u32 pointer to function that writes register from pci header + * @param handle pointer passes to the above functions as first parameter + * @param mac_base base address of the MAC registers + * @param ec_base base address of the Ethernet Controller registers + * @param mac_addresses_num number of mac addresses to restore + * + * @return 0. + */ +int al_eth_flr_rmn_restore_params(int (* pci_read_config_u32)(void *handle, int where, uint32_t *val), + int (* pci_write_config_u32)(void *handle, int where, uint32_t val), + void *handle, + void __iomem *mac_base, + void __iomem *ec_base, + int mac_addresses_num); + +/* board specific information (media type, phy address, etc.. */ + + +enum al_eth_board_media_type { + AL_ETH_BOARD_MEDIA_TYPE_AUTO_DETECT = 0, + AL_ETH_BOARD_MEDIA_TYPE_RGMII = 1, + AL_ETH_BOARD_MEDIA_TYPE_10GBASE_SR = 2, + AL_ETH_BOARD_MEDIA_TYPE_SGMII = 3, + AL_ETH_BOARD_MEDIA_TYPE_1000BASE_X = 4, + AL_ETH_BOARD_MEDIA_TYPE_AUTO_DETECT_AUTO_SPEED = 5, + AL_ETH_BOARD_MEDIA_TYPE_SGMII_2_5G = 6, + AL_ETH_BOARD_MEDIA_TYPE_NBASE_T = 7, +}; + +enum al_eth_board_mdio_freq { + AL_ETH_BOARD_MDIO_FREQ_2_5_MHZ = 0, + AL_ETH_BOARD_MDIO_FREQ_1_MHZ = 1, +}; + +enum al_eth_board_ext_phy_if { + AL_ETH_BOARD_PHY_IF_MDIO = 0, + AL_ETH_BOARD_PHY_IF_XMDIO = 1, + AL_ETH_BOARD_PHY_IF_I2C = 2, + +}; + +enum al_eth_board_auto_neg_mode { + AL_ETH_BOARD_AUTONEG_OUT_OF_BAND = 0, + AL_ETH_BOARD_AUTONEG_IN_BAND = 1, + +}; + +/* declare the 1G mac active speed when auto negotiation disabled */ +enum al_eth_board_1g_speed { + AL_ETH_BOARD_1G_SPEED_1000M = 0, + AL_ETH_BOARD_1G_SPEED_100M = 1, + AL_ETH_BOARD_1G_SPEED_10M = 2, +}; + +enum al_eth_retimer_channel { + AL_ETH_RETIMER_CHANNEL_A = 0, + AL_ETH_RETIMER_CHANNEL_B = 1, + AL_ETH_RETIMER_CHANNEL_C = 2, + AL_ETH_RETIMER_CHANNEL_D = 3, + AL_ETH_RETIMER_CHANNEL_MAX = 4 +}; + +/* list of supported retimers */ +enum al_eth_retimer_type { + AL_ETH_RETIMER_BR_210 = 0, + AL_ETH_RETIMER_BR_410 = 1, + + AL_ETH_RETIMER_TYPE_MAX = 4, +}; + +/** structure represents the board information. this info set by boot loader + * and read by OS driver. + */ +struct al_eth_board_params { + enum al_eth_board_media_type media_type; + al_bool phy_exist; /**< external phy exist */ + uint8_t phy_mdio_addr; /**< mdio address of external phy */ + al_bool sfp_plus_module_exist; /**< SFP+ module connected */ + al_bool autoneg_enable; /**< enable Auto-Negotiation */ + al_bool kr_lt_enable; /**< enable KR Link-Training */ + al_bool kr_fec_enable; /**< enable KR FEC */ + enum al_eth_board_mdio_freq mdio_freq; /**< MDIO frequency */ + uint8_t i2c_adapter_id; /**< identifier for the i2c adapter to use to access SFP+ module */ + enum al_eth_board_ext_phy_if phy_if; /**< phy interface */ + enum al_eth_board_auto_neg_mode an_mode; /**< auto-negotiation mode (in-band / out-of-band) */ + uint8_t serdes_grp; /**< serdes's group id */ + uint8_t serdes_lane; /**< serdes's lane id */ + enum al_eth_ref_clk_freq ref_clk_freq; /**< reference clock frequency */ + al_bool dont_override_serdes; /**< prevent override serdes parameters */ + al_bool force_1000_base_x; /**< set mac to 1000 base-x mode (instead sgmii) */ + al_bool an_disable; /**< disable auto negotiation */ + enum al_eth_board_1g_speed speed; /**< port speed if AN disabled */ + al_bool half_duplex; /**< force half duplex if AN disabled */ + al_bool fc_disable; /**< disable flow control */ + al_bool retimer_exist; /**< retimer is exist on the board */ + uint8_t retimer_bus_id; /**< in what i2c bus the retimer is on */ + uint8_t retimer_i2c_addr; /**< i2c address of the retimer */ + enum al_eth_retimer_channel retimer_channel; /**< what channel connected to this port */ + al_bool dac; /**< assume direct attached cable is connected if auto detect is off or failed */ + uint8_t dac_len; /**< assume this cable length if auto detect is off or failed */ + enum al_eth_retimer_type retimer_type; /**< the type of the specific retimer */ +}; + +/** + * set board parameter of the eth port + * this function used to set the board parameters into scratchpad + * registers. those paramters can be read later by OS driver. + * + * @param mac_base the virtual address of the mac registers (PCI BAR 2) + * @param params pointer to structure the includes the paramters + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_board_params_set(void * __iomem mac_base, struct al_eth_board_params *params); + +/** + * get board parameter of the eth port + * this function used to get the board parameters from scratchpad + * registers. + * + * @param mac_base the virtual address of the mac registers (PCI BAR 2) + * @param params pointer to structure where the parameters will be stored. + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_board_params_get(void * __iomem mac_base, struct al_eth_board_params *params); + +/* + * Wake-On-Lan (WoL) + * + * The following few functions configure the Wake-On-Lan packet detection + * inside the Integrated Ethernet MAC. + * + * There are other alternative ways to set WoL, such using the + * external 1000Base-T transceiver to set WoL mode. + * + * These APIs do not set the system-wide power-state, nor responsible on the + * transition from Sleep to Normal power state. + * + * For system level considerations, please refer to Annapurna Labs Alpine Wiki. + */ +/* Interrupt enable WoL MAC DA Unicast detected packet */ +#define AL_ETH_WOL_INT_UNICAST AL_BIT(0) +/* Interrupt enable WoL L2 Multicast detected packet */ +#define AL_ETH_WOL_INT_MULTICAST AL_BIT(1) +/* Interrupt enable WoL L2 Broadcast detected packet */ +#define AL_ETH_WOL_INT_BROADCAST AL_BIT(2) +/* Interrupt enable WoL IPv4 detected packet */ +#define AL_ETH_WOL_INT_IPV4 AL_BIT(3) +/* Interrupt enable WoL IPv6 detected packet */ +#define AL_ETH_WOL_INT_IPV6 AL_BIT(4) +/* Interrupt enable WoL EtherType+MAC DA detected packet */ +#define AL_ETH_WOL_INT_ETHERTYPE_DA AL_BIT(5) +/* Interrupt enable WoL EtherType+L2 Broadcast detected packet */ +#define AL_ETH_WOL_INT_ETHERTYPE_BC AL_BIT(6) +/* Interrupt enable WoL parser detected packet */ +#define AL_ETH_WOL_INT_PARSER AL_BIT(7) +/* Interrupt enable WoL magic detected packet */ +#define AL_ETH_WOL_INT_MAGIC AL_BIT(8) +/* Interrupt enable WoL magic+password detected packet */ +#define AL_ETH_WOL_INT_MAGIC_PSWD AL_BIT(9) + +/* Forward enable WoL MAC DA Unicast detected packet */ +#define AL_ETH_WOL_FWRD_UNICAST AL_BIT(0) +/* Forward enable WoL L2 Multicast detected packet */ +#define AL_ETH_WOL_FWRD_MULTICAST AL_BIT(1) +/* Forward enable WoL L2 Broadcast detected packet */ +#define AL_ETH_WOL_FWRD_BROADCAST AL_BIT(2) +/* Forward enable WoL IPv4 detected packet */ +#define AL_ETH_WOL_FWRD_IPV4 AL_BIT(3) +/* Forward enable WoL IPv6 detected packet */ +#define AL_ETH_WOL_FWRD_IPV6 AL_BIT(4) +/* Forward enable WoL EtherType+MAC DA detected packet */ +#define AL_ETH_WOL_FWRD_ETHERTYPE_DA AL_BIT(5) +/* Forward enable WoL EtherType+L2 Broadcast detected packet */ +#define AL_ETH_WOL_FWRD_ETHERTYPE_BC AL_BIT(6) +/* Forward enable WoL parser detected packet */ +#define AL_ETH_WOL_FWRD_PARSER AL_BIT(7) + +struct al_eth_wol_params { + uint8_t *dest_addr; /**< 6 bytes array of destanation address for + magic packet detection */ + uint8_t *pswd; /**< 6 bytes array of the password to use */ + uint8_t *ipv4; /**< 4 bytes array of the ipv4 to use. + example: for ip = 192.168.1.2 + ipv4[0]=2, ipv4[1]=1, ipv4[2]=168, ipv4[3]=192 */ + uint8_t *ipv6; /** 16 bytes array of the ipv6 to use. + example: ip = 2607:f0d0:1002:0051:0000:0000:5231:1234 + ipv6[0]=34, ipv6[1]=12, ipv6[2]=31 .. */ + uint16_t ethr_type1; /**< first ethertype to use */ + uint16_t ethr_type2; /**< secound ethertype to use */ + uint16_t forward_mask; /**< bitmask of AL_ETH_WOL_FWRD_* of the packet + types needed to be forward. */ + uint16_t int_mask; /**< bitmask of AL_ETH_WOL_INT_* of the packet types + that will send interrupt to wake the system. */ +}; + +/** + * enable the wol mechanism + * set what type of packets will wake up the system and what type of packets + * neet to forward after the system is up + * + * beside this function wol filter also need to be set by + * calling al_eth_filter_config with AL_ETH_RFW_FILTER_WOL + * + * @param adapter pointer to the private structure + * @param wol the parameters needed to configure the wol + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_wol_enable( + struct al_hal_eth_adapter *adapter, + struct al_eth_wol_params *wol); + +/** + * Disable the WoL mechnism. + * + * @param adapter pointer to the private structure + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_wol_disable( + struct al_hal_eth_adapter *adapter); + +/** + * Configure tx fwd vlan table entry + * + * @param adapter pointer to the private structure + * @param idx the entry index within the vlan table. The HW uses the vlan id + * field of the packet when accessing this table. + * @param udma_mask vlan table value that indicates that the packet should be forward back to + * the udmas, through the Rx path (udma_mask is one-hot representation) + * @param fwd_to_mac vlan table value that indicates that the packet should be forward to mac + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_tx_fwd_vid_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint8_t udma_mask, al_bool fwd_to_mac); + +/** Tx Generic protocol detect Cam compare table entry */ +struct al_eth_tx_gpd_cam_entry { + enum AL_ETH_PROTO_ID l3_proto_idx; + enum AL_ETH_PROTO_ID l4_proto_idx; + enum AL_ETH_TX_TUNNEL_MODE tunnel_control; + uint8_t source_vlan_count:2; + uint8_t tx_gpd_cam_ctrl:1; + uint8_t l3_proto_idx_mask:5; + uint8_t l4_proto_idx_mask:5; + uint8_t tunnel_control_mask:3; + uint8_t source_vlan_count_mask:2; +}; + +/** Rx Generic protocol detect Cam compare table entry */ +struct al_eth_rx_gpd_cam_entry { + enum AL_ETH_PROTO_ID outer_l3_proto_idx; + enum AL_ETH_PROTO_ID outer_l4_proto_idx; + enum AL_ETH_PROTO_ID inner_l3_proto_idx; + enum AL_ETH_PROTO_ID inner_l4_proto_idx; + uint8_t parse_ctrl; + uint8_t outer_l3_len; + uint8_t l3_priority; + uint8_t l4_dst_port_lsb; + uint8_t rx_gpd_cam_ctrl:1; + uint8_t outer_l3_proto_idx_mask:5; + uint8_t outer_l4_proto_idx_mask:5; + uint8_t inner_l3_proto_idx_mask:5; + uint8_t inner_l4_proto_idx_mask:5; + uint8_t parse_ctrl_mask; + uint8_t outer_l3_len_mask; + uint8_t l3_priority_mask; + uint8_t l4_dst_port_lsb_mask; +}; + +enum AL_ETH_TX_GCP_ALU_OPSEL { + AL_ETH_TX_GCP_ALU_L3_OFFSET = 0, + AL_ETH_TX_GCP_ALU_OUTER_L3_OFFSET = 1, + AL_ETH_TX_GCP_ALU_L3_LEN = 2, + AL_ETH_TX_GCP_ALU_OUTER_L3_LEN = 3, + AL_ETH_TX_GCP_ALU_L4_OFFSET = 4, + AL_ETH_TX_GCP_ALU_L4_LEN = 5, + AL_ETH_TX_GCP_ALU_TABLE_VAL = 10 +}; + +enum AL_ETH_RX_GCP_ALU_OPSEL { + AL_ETH_RX_GCP_ALU_OUTER_L3_OFFSET = 0, + AL_ETH_RX_GCP_ALU_INNER_L3_OFFSET = 1, + AL_ETH_RX_GCP_ALU_OUTER_L4_OFFSET = 2, + AL_ETH_RX_GCP_ALU_INNER_L4_OFFSET = 3, + AL_ETH_RX_GCP_ALU_OUTER_L3_HDR_LEN_LAT = 4, + AL_ETH_RX_GCP_ALU_INNER_L3_HDR_LEN_LAT = 5, + AL_ETH_RX_GCP_ALU_OUTER_L3_HDR_LEN_SEL = 6, + AL_ETH_RX_GCP_ALU_INNER_L3_HDR_LEN_SEL = 7, + AL_ETH_RX_GCP_ALU_PARSE_RESULT_VECTOR_OFFSET_1 = 8, + AL_ETH_RX_GCP_ALU_PARSE_RESULT_VECTOR_OFFSET_2 = 9, + AL_ETH_RX_GCP_ALU_TABLE_VAL = 10 +}; + +/** Tx Generic crc prameters table entry */ + +struct al_eth_tx_gcp_table_entry { + uint8_t poly_sel:1; + uint8_t crc32_bit_comp:1; + uint8_t crc32_bit_swap:1; + uint8_t crc32_byte_swap:1; + uint8_t data_bit_swap:1; + uint8_t data_byte_swap:1; + uint8_t trail_size:4; + uint8_t head_size:8; + uint8_t head_calc:1; + uint8_t mask_polarity:1; + enum AL_ETH_ALU_OPCODE tx_alu_opcode_1; + enum AL_ETH_ALU_OPCODE tx_alu_opcode_2; + enum AL_ETH_ALU_OPCODE tx_alu_opcode_3; + enum AL_ETH_TX_GCP_ALU_OPSEL tx_alu_opsel_1; + enum AL_ETH_TX_GCP_ALU_OPSEL tx_alu_opsel_2; + enum AL_ETH_TX_GCP_ALU_OPSEL tx_alu_opsel_3; + enum AL_ETH_TX_GCP_ALU_OPSEL tx_alu_opsel_4; + uint32_t gcp_mask[6]; + uint32_t crc_init; + uint8_t gcp_table_res:7; + uint16_t alu_val:9; +}; + +/** Rx Generic crc prameters table entry */ + +struct al_eth_rx_gcp_table_entry { + uint8_t poly_sel:1; + uint8_t crc32_bit_comp:1; + uint8_t crc32_bit_swap:1; + uint8_t crc32_byte_swap:1; + uint8_t data_bit_swap:1; + uint8_t data_byte_swap:1; + uint8_t trail_size:4; + uint8_t head_size:8; + uint8_t head_calc:1; + uint8_t mask_polarity:1; + enum AL_ETH_ALU_OPCODE rx_alu_opcode_1; + enum AL_ETH_ALU_OPCODE rx_alu_opcode_2; + enum AL_ETH_ALU_OPCODE rx_alu_opcode_3; + enum AL_ETH_RX_GCP_ALU_OPSEL rx_alu_opsel_1; + enum AL_ETH_RX_GCP_ALU_OPSEL rx_alu_opsel_2; + enum AL_ETH_RX_GCP_ALU_OPSEL rx_alu_opsel_3; + enum AL_ETH_RX_GCP_ALU_OPSEL rx_alu_opsel_4; + uint32_t gcp_mask[6]; + uint32_t crc_init; + uint32_t gcp_table_res:27; + uint16_t alu_val:9; +}; + +/** Tx per_protocol_number crc & l3_checksum & l4_checksum command table entry */ + +struct al_eth_tx_crc_chksum_replace_cmd_for_protocol_num_entry { + al_bool crc_en_00; /*from Tx_buffer_descriptor: enable_l4_checksum is 0 ,enable_l3_checksum is 0 */ + al_bool crc_en_01; /*from Tx_buffer_descriptor: enable_l4_checksum is 0 ,enable_l3_checksum is 1 */ + al_bool crc_en_10; /*from Tx_buffer_descriptor: enable_l4_checksum is 1 ,enable_l3_checksum is 0 */ + al_bool crc_en_11; /*from Tx_buffer_descriptor: enable_l4_checksum is 1 ,enable_l3_checksum is 1 */ + al_bool l4_csum_en_00; /*from Tx_buffer_descriptor: enable_l4_checksum is 0 ,enable_l3_checksum is 0 */ + al_bool l4_csum_en_01; /*from Tx_buffer_descriptor: enable_l4_checksum is 0 ,enable_l3_checksum is 1 */ + al_bool l4_csum_en_10; /*from Tx_buffer_descriptor: enable_l4_checksum is 1 ,enable_l3_checksum is 0 */ + al_bool l4_csum_en_11; /*from Tx_buffer_descriptor: enable_l4_checksum is 1 ,enable_l3_checksum is 1 */ + al_bool l3_csum_en_00; /*from Tx_buffer_descriptor: enable_l4_checksum is 0 ,enable_l3_checksum is 0 */ + al_bool l3_csum_en_01; /*from Tx_buffer_descriptor: enable_l4_checksum is 0 ,enable_l3_checksum is 1 */ + al_bool l3_csum_en_10; /*from Tx_buffer_descriptor: enable_l4_checksum is 1 ,enable_l3_checksum is 0 */ + al_bool l3_csum_en_11; /*from Tx_buffer_descriptor: enable_l4_checksum is 1 ,enable_l3_checksum is 1 */ +}; + +/** + * Configure tx_gpd_entry + * + * @param adapter pointer to the private structure + * @param idx the entry index + * @param tx_gpd_entry entry data for the Tx protocol detect Cam compare table + * + * @return 0 on success. otherwise on failure. + * + */ +int al_eth_tx_protocol_detect_table_entry_set(struct al_hal_eth_adapter *adapter, uint32_t idx, + struct al_eth_tx_gpd_cam_entry *tx_gpd_entry); + +/** + * Configure tx_gcp_entry + * + * @param adapter pointer to the private structure + * @param idx the entry index + * @param tx_gcp_entry entry data for the Tx Generic crc prameters table + * + * @return 0 on success. otherwise on failure. + * + */ +int al_eth_tx_generic_crc_table_entry_set(struct al_hal_eth_adapter *adapter, uint32_t idx, + struct al_eth_tx_gcp_table_entry *tx_gcp_entry); + +/** + * Configure tx_crc_chksum_replace_cmd_entry + * + * @param adapter pointer to the private structure + * @param idx the entry index + * @param tx_replace_entry entry data for the Tx crc_&_l3_checksum_&_l4_checksum replace command table + * + * @return 0 on success. otherwise on failure. + * + */ +int al_eth_tx_crc_chksum_replace_cmd_entry_set(struct al_hal_eth_adapter *adapter, uint32_t idx, + struct al_eth_tx_crc_chksum_replace_cmd_for_protocol_num_entry *tx_replace_entry); + +/** + * Configure rx_gpd_entry + * + * @param adapter pointer to the private structure + * @param idx the entry index + * @param rx_gpd_entry entry data for the Tx protocol detect Cam compare table + * + * @return 0 on success. otherwise on failure. + * + */ +int al_eth_rx_protocol_detect_table_entry_set(struct al_hal_eth_adapter *adapter, uint32_t idx, + struct al_eth_rx_gpd_cam_entry *rx_gpd_entry); + +/** + * Configure rx_gcp_entry + * + * @param adapter pointer to the private structure + * @param idx the entry index + * @param rx_gpd_entry entry data for the Tx protocol detect Cam compare table + * @param rx_gcp_entry entry data for the Tx Generic crc prameters table + * + * @return 0 on success. otherwise on failure. + * + */ +int al_eth_rx_generic_crc_table_entry_set(struct al_hal_eth_adapter *adapter, uint32_t idx, + struct al_eth_rx_gcp_table_entry *rx_gcp_entry); + +/** + * Configure tx_gpd_table and regs + * + * @param adapter pointer to the private structure + * + */ +int al_eth_tx_protocol_detect_table_init(struct al_hal_eth_adapter *adapter); + +/** + * Configure crc_chksum_replace_cmd_table + * + * @param adapter pointer to the private structure + * + */ +int al_eth_tx_crc_chksum_replace_cmd_init(struct al_hal_eth_adapter *adapter); + +/** + * Configure tx_gcp_table and regs + * + * @param adapter pointer to the private structure + * + */ +int al_eth_tx_generic_crc_table_init(struct al_hal_eth_adapter *adapter); + +/** + * Configure rx_gpd_table and regs + * + * @param adapter pointer to the private structure + * + */ +int al_eth_rx_protocol_detect_table_init(struct al_hal_eth_adapter *adapter); + +/** + * Configure rx_gcp_table and regs + * + * @param adapter pointer to the private structure + * + */ +int al_eth_rx_generic_crc_table_init(struct al_hal_eth_adapter *adapter); + +#ifdef __cplusplus +} +#endif +/* *INDENT-ON* */ +#endif /* __AL_HAL_ETH_H__ */ +/** @} end of Ethernet group */ diff --git a/eth/al_hal_eth_alu.h b/eth/al_hal_eth_alu.h new file mode 100644 index 00000000000..2f5f1fa2301 --- /dev/null +++ b/eth/al_hal_eth_alu.h @@ -0,0 +1,95 @@ +/******************************************************************************* +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. + +*******************************************************************************/ + +/** + * @defgroup group_eth_alu_api API + * Ethernet Controller generic ALU API + * @ingroup group_eth + * @{ + * @file al_hal_eth_alu.h + * + * @brief Header file for control parameters for the generic ALU unit in the Ethernet Datapath for Advanced Ethernet port. + * + */ + +#ifndef __AL_HAL_ETH_ALU_H__ +#define __AL_HAL_ETH_ALU_H__ + +/* *INDENT-OFF* */ +#ifdef __cplusplus +extern "C" { +#endif +/* *INDENT-ON* */ + +enum AL_ETH_ALU_OPCODE +{ + AL_ALU_FWD_A = 0, + AL_ALU_ARITHMETIC_ADD = 1, + AL_ALU_ARITHMETIC_SUBTRACT = 2, + AL_ALU_BITWISE_AND = 3, + AL_ALU_BITWISE_OR = 4, + AL_ALU_SHIFT_RIGHT_A_BY_B = 5, + AL_ALU_SHIFT_LEFT_A_BY_B = 6, + AL_ALU_BITWISE_XOR = 7, + AL_ALU_FWD_INV_A = 16, + AL_ALU_ARITHMETIC_ADD_INV_A_AND_B = 17, + AL_ALU_ARITHMETIC_SUBTRACT_INV_A_AND_B = 18, + AL_ALU_BITWISE_AND_INV_A_AND_B = 19, + AL_ALU_BITWISE_OR_INV_A_AND_B = 20, + AL_ALU_SHIFT_RIGHT_INV_A_BY_B = 21, + AL_ALU_SHIFT_LEFT_INV_A_BY_B = 22, + AL_ALU_BITWISE_XOR_INV_A_AND_B = 23, + AL_ALU_ARITHMETIC_ADD_A_AND_INV_B = 33, + AL_ALU_ARITHMETIC_SUBTRACT_A_AND_INV_B = 34, + AL_ALU_BITWISE_AND_A_AND_INV_B = 35, + AL_ALU_BITWISE_OR_A_AND_INV_B = 36, + AL_ALU_SHIFT_RIGHT_A_BY_INV_B = 37, + AL_ALU_SHIFT_LEFT_A_BY_INV_B = 38, + AL_ALU_BITWISE_XOR_A_AND_INV_B = 39, + AL_ALU_ARITHMETIC_ADD_INV_A_AND_INV_B = 49, + AL_ALU_ARITHMETIC_SUBTRACT_INV_A_AND = 50, + AL_ALU_BITWISE_AND_INV_A_AND_INV_B = 51, + AL_ALU_BITWISE_OR_INV_A_AND_INV_B = 52, + AL_ALU_SHIFT_RIGHT_INV_A_BY_INV_B = 53, + AL_ALU_SHIFT_LEFT_INV_A_BY_INV_B = 54, + AL_ALU_BITWISE_XOR_INV_A_AND_INV_B = 55 +}; + +#ifdef __cplusplus +} +#endif +/* *INDENT-ON* */ +#endif /* __AL_HAL_ETH_ALU_H__ */ +/** @} end of Ethernet group */ diff --git a/eth/al_hal_eth_ec_regs.h b/eth/al_hal_eth_ec_regs.h new file mode 100644 index 00000000000..153e0d57a45 --- /dev/null +++ b/eth/al_hal_eth_ec_regs.h @@ -0,0 +1,3362 @@ +/*- +******************************************************************************* +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_eth_ec_regs.h + * + * @brief Ethernet controller registers + * + */ + +#ifndef __AL_HAL_EC_REG_H +#define __AL_HAL_EC_REG_H + +#include "al_hal_plat_types.h" + +#ifdef __cplusplus +extern "C" { +#endif +/* +* Unit Registers +*/ + + + +struct al_ec_gen { + /* [0x0] Ethernet controller Version */ + uint32_t version; + /* [0x4] Enable modules operation. */ + uint32_t en; + /* [0x8] Enable FIFO operation on the EC side. */ + uint32_t fifo_en; + /* [0xc] General L2 configuration for the Ethernet controlle ... */ + uint32_t l2; + /* [0x10] Configure protocol index values */ + uint32_t cfg_i; + /* [0x14] Configure protocol index values (extended protocols ... */ + uint32_t cfg_i_ext; + /* [0x18] Enable modules operation (extended operations). */ + uint32_t en_ext; + uint32_t rsrvd[9]; +}; +struct al_ec_mac { + /* [0x0] General configuration of the MAC side of the Ethern ... */ + uint32_t gen; + /* [0x4] Minimum packet size */ + uint32_t min_pkt; + /* [0x8] Maximum packet size */ + uint32_t max_pkt; + uint32_t rsrvd[13]; +}; +struct al_ec_rxf { + /* [0x0] Rx FIFO input controller configuration 1 */ + uint32_t cfg_1; + /* [0x4] Rx FIFO input controller configuration 2 */ + uint32_t cfg_2; + /* [0x8] Threshold to start reading packet from the Rx FIFO */ + uint32_t rd_fifo; + /* [0xc] Threshold to stop writing packet to the Rx FIFO */ + uint32_t wr_fifo; + /* [0x10] Threshold to stop writing packet to the loopback FI ... */ + uint32_t lb_fifo; + /* [0x14] Rx FIFO input controller loopback FIFO configuratio ... */ + uint32_t cfg_lb; + /* [0x18] Configuration for dropping packet at the FIFO outpu ... */ + uint32_t out_drop; + uint32_t rsrvd[25]; +}; +struct al_ec_epe { + /* [0x0] Ethernet parsing engine configuration 1 */ + uint32_t parse_cfg; + /* [0x4] Protocol index action table address */ + uint32_t act_table_addr; + /* [0x8] Protocol index action table data */ + uint32_t act_table_data_1; + /* [0xc] Protocol index action table data */ + uint32_t act_table_data_2; + /* [0x10] Protocol index action table data */ + uint32_t act_table_data_3; + /* [0x14] Protocol index action table data */ + uint32_t act_table_data_4; + /* [0x18] Protocol index action table data */ + uint32_t act_table_data_5; + /* [0x1c] Protocol index action table data */ + uint32_t act_table_data_6; + /* [0x20] Input result vector, default values for parser inpu ... */ + uint32_t res_def; + /* [0x24] Result input vector selection */ + uint32_t res_in; + uint32_t rsrvd[6]; +}; +struct al_ec_epe_res { + /* [0x0] Parser result vector pointer */ + uint32_t p1; + /* [0x4] Parser result vector pointer */ + uint32_t p2; + /* [0x8] Parser result vector pointer */ + uint32_t p3; + /* [0xc] Parser result vector pointer */ + uint32_t p4; + /* [0x10] Parser result vector pointer */ + uint32_t p5; + /* [0x14] Parser result vector pointer */ + uint32_t p6; + /* [0x18] Parser result vector pointer */ + uint32_t p7; + /* [0x1c] Parser result vector pointer */ + uint32_t p8; + /* [0x20] Parser result vector pointer */ + uint32_t p9; + /* [0x24] Parser result vector pointer */ + uint32_t p10; + /* [0x28] Parser result vector pointer */ + uint32_t p11; + /* [0x2c] Parser result vector pointer */ + uint32_t p12; + /* [0x30] Parser result vector pointer */ + uint32_t p13; + /* [0x34] Parser result vector pointer */ + uint32_t p14; + /* [0x38] Parser result vector pointer */ + uint32_t p15; + /* [0x3c] Parser result vector pointer */ + uint32_t p16; + /* [0x40] Parser result vector pointer */ + uint32_t p17; + /* [0x44] Parser result vector pointer */ + uint32_t p18; + /* [0x48] Parser result vector pointer */ + uint32_t p19; + /* [0x4c] Parser result vector pointer */ + uint32_t p20; + uint32_t rsrvd[12]; +}; +struct al_ec_epe_h { + /* [0x0] Header length, support for header length table for ... */ + uint32_t hdr_len; +}; +struct al_ec_epe_p { + /* [0x0] Data for comparison */ + uint32_t comp_data; + /* [0x4] Mask for comparison */ + uint32_t comp_mask; + /* [0x8] Compare control */ + uint32_t comp_ctrl; + uint32_t rsrvd[4]; +}; +struct al_ec_epe_a { + /* [0x0] Protocol index action register */ + uint32_t prot_act; +}; +struct al_ec_rfw { + /* [0x0] Tuple (4/2) Hash configuration */ + uint32_t thash_cfg_1; + /* [0x4] Tuple (4/2) Hash configuration */ + uint32_t thash_cfg_2; + /* [0x8] MAC Hash configuration */ + uint32_t mhash_cfg_1; + /* [0xc] MAC Hash configuration */ + uint32_t mhash_cfg_2; + /* [0x10] MAC Hash configuration */ + uint32_t hdr_split; + /* [0x14] Masking the errors described in register rxf_drop ... */ + uint32_t meta_err; + /* [0x18] Configuration for generating the MetaData for the R ... */ + uint32_t meta; + /* [0x1c] Configuration for generating the MetaData for the R ... */ + uint32_t filter; + /* [0x20] 4 tupple hash table address */ + uint32_t thash_table_addr; + /* [0x24] 4 tupple hash table data */ + uint32_t thash_table_data; + /* [0x28] MAC hash table address */ + uint32_t mhash_table_addr; + /* [0x2c] MAC hash table data */ + uint32_t mhash_table_data; + /* [0x30] VLAN table address */ + uint32_t vid_table_addr; + /* [0x34] VLAN table data */ + uint32_t vid_table_data; + /* [0x38] VLAN p-bits table address */ + uint32_t pbits_table_addr; + /* [0x3c] VLAN p-bits table data */ + uint32_t pbits_table_data; + /* [0x40] DSCP table address */ + uint32_t dscp_table_addr; + /* [0x44] DSCP table data */ + uint32_t dscp_table_data; + /* [0x48] TC table address */ + uint32_t tc_table_addr; + /* [0x4c] TC table data */ + uint32_t tc_table_data; + /* [0x50] Control table address */ + uint32_t ctrl_table_addr; + /* [0x54] Control table data */ + uint32_t ctrl_table_data; + /* [0x58] Forwarding output configuration */ + uint32_t out_cfg; + /* [0x5c] Flow steering mechanism, +Table address */ + uint32_t fsm_table_addr; + /* [0x60] Flow steering mechanism, +Table data */ + uint32_t fsm_table_data; + /* [0x64] Selection of data to be used in packet forwarding0 ... */ + uint32_t ctrl_sel; + /* [0x68] Default VLAN data, used for untagged packets */ + uint32_t default_vlan; + /* [0x6c] Default HASH output values */ + uint32_t default_hash; + /* [0x70] Default override values, if a packet was filtered b ... */ + uint32_t default_or; + /* [0x74] Latched information when a drop condition occurred */ + uint32_t drop_latch; + /* [0x78] Check sum calculation configuration */ + uint32_t checksum; + /* [0x7c] LRO offload engine configuration register */ + uint32_t lro_cfg_1; + /* [0x80] LRO offload engine Check rules configurations for I ... */ + uint32_t lro_check_ipv4; + /* [0x84] LRO offload engine IPv4 values configuration */ + uint32_t lro_ipv4; + /* [0x88] LRO offload engine Check rules configurations for I ... */ + uint32_t lro_check_ipv6; + /* [0x8c] LRO offload engine IPv6 values configuration */ + uint32_t lro_ipv6; + /* [0x90] LRO offload engine Check rules configurations for T ... */ + uint32_t lro_check_tcp; + /* [0x94] LRO offload engine IPv6 values configuration */ + uint32_t lro_tcp; + /* [0x98] LRO offload engine Check rules configurations for U ... */ + uint32_t lro_check_udp; + /* [0x9c] LRO offload engine Check rules configurations for U ... */ + uint32_t lro_check_l2; + /* [0xa0] LRO offload engine Check rules configurations for U ... */ + uint32_t lro_check_gen; + /* [0xa4] Rules for storing packet information into the cache ... */ + uint32_t lro_store; + /* [0xa8] VLAN table default */ + uint32_t vid_table_def; + /* [0xac] Control table default */ + uint32_t ctrl_table_def; + /* [0xb0] Additional configuration 0 */ + uint32_t cfg_a_0; + /* [0xb4] Tuple (4/2) Hash configuration (extended for RoCE a ... */ + uint32_t thash_cfg_3; + /* [0xb8] Tuple (4/2) Hash configuration , mask for the input ... */ + uint32_t thash_mask_outer_ipv6; + /* [0xbc] Tuple (4/2) Hash configuration , mask for the input ... */ + uint32_t thash_mask_outer; + /* [0xc0] Tuple (4/2) Hash configuration , mask for the input ... */ + uint32_t thash_mask_inner_ipv6; + /* [0xc4] Tuple (4/2) Hash configuration , mask for the input ... */ + uint32_t thash_mask_inner; + uint32_t rsrvd[10]; +}; +struct al_ec_rfw_udma { + /* [0x0] Per UDMA default configuration */ + uint32_t def_cfg; +}; +struct al_ec_rfw_hash { + /* [0x0] key configuration (320 bits) */ + uint32_t key; +}; +struct al_ec_rfw_priority { + /* [0x0] Priority to queue mapping configuration */ + uint32_t queue; +}; +struct al_ec_rfw_default { + /* [0x0] Default forwarding configuration options */ + uint32_t opt_1; +}; +struct al_ec_fwd_mac { + /* [0x0] MAC address data [31:0] */ + uint32_t data_l; + /* [0x4] MAC address data [15:0] */ + uint32_t data_h; + /* [0x8] MAC address mask [31:0] */ + uint32_t mask_l; + /* [0xc] MAC address mask [15:0] */ + uint32_t mask_h; + /* [0x10] MAC compare control */ + uint32_t ctrl; +}; +struct al_ec_msw { + /* [0x0] Configuration for unicast packets */ + uint32_t uc; + /* [0x4] Configuration for multicast packets */ + uint32_t mc; + /* [0x8] Configuration for broadcast packets */ + uint32_t bc; + uint32_t rsrvd[3]; +}; +struct al_ec_tso { + /* [0x0] Input configuration */ + uint32_t in_cfg; + /* [0x4] MetaData default cache table address */ + uint32_t cache_table_addr; + /* [0x8] MetaData default cache table data */ + uint32_t cache_table_data_1; + /* [0xc] MetaData default cache table data */ + uint32_t cache_table_data_2; + /* [0x10] MetaData default cache table data */ + uint32_t cache_table_data_3; + /* [0x14] MetaData default cache table data */ + uint32_t cache_table_data_4; + /* [0x18] TCP control bit operation for first segment */ + uint32_t ctrl_first; + /* [0x1c] TCP control bit operation for middle segments */ + uint32_t ctrl_middle; + /* [0x20] TCP control bit operation for last segment */ + uint32_t ctrl_last; + /* [0x24] Additional TSO configurations */ + uint32_t cfg_add_0; + /* [0x28] TSO configuration for tunnelled packets */ + uint32_t cfg_tunnel; + uint32_t rsrvd[13]; +}; +struct al_ec_tso_sel { + /* [0x0] MSS value */ + uint32_t mss; +}; +struct al_ec_tpe { + /* [0x0] Parsing configuration */ + uint32_t parse; + uint32_t rsrvd[15]; +}; +struct al_ec_tpm_udma { + /* [0x0] Default VLAN data */ + uint32_t vlan_data; + /* [0x4] UDMA MAC SA information for spoofing */ + uint32_t mac_sa_1; + /* [0x8] UDMA MAC SA information for spoofing */ + uint32_t mac_sa_2; +}; +struct al_ec_tpm_sel { + /* [0x0] Ethertype values for VLAN modification */ + uint32_t etype; +}; +struct al_ec_tfw { + /* [0x0] Tx FIFO Wr configuration */ + uint32_t tx_wr_fifo; + /* [0x4] VLAN table address */ + uint32_t tx_vid_table_addr; + /* [0x8] VLAN table data */ + uint32_t tx_vid_table_data; + /* [0xc] Tx FIFO Rd configuration */ + uint32_t tx_rd_fifo; + /* [0x10] Tx FIFO Rd configuration, checksum insertion */ + uint32_t tx_checksum; + /* [0x14] Tx forwarding general configuration register */ + uint32_t tx_gen; + /* [0x18] Tx spoofing configuration */ + uint32_t tx_spf; + /* [0x1c] TX data FIFO status */ + uint32_t data_fifo; + /* [0x20] Tx control FIFO status */ + uint32_t ctrl_fifo; + /* [0x24] Tx header FIFO status */ + uint32_t hdr_fifo; + uint32_t rsrvd[14]; +}; +struct al_ec_tfw_udma { + /* [0x0] Default GMDA output bitmap for unicast packet */ + uint32_t uc_udma; + /* [0x4] Default GMDA output bitmap for multicast packet */ + uint32_t mc_udma; + /* [0x8] Default GMDA output bitmap for broadcast packet */ + uint32_t bc_udma; + /* [0xc] Tx spoofing configuration */ + uint32_t spf_cmd; + /* [0x10] Forwarding decision control */ + uint32_t fwd_dec; + uint32_t rsrvd; +}; +struct al_ec_tmi { + /* [0x0] Forward packets back to the Rx data path for local ... */ + uint32_t tx_cfg; + uint32_t rsrvd[3]; +}; +struct al_ec_efc { + /* [0x0] Mask of pause_on [7:0] for the Ethernet controller ... */ + uint32_t ec_pause; + /* [0x4] Mask of Ethernet controller Almost Full indication ... */ + uint32_t ec_xoff; + /* [0x8] Mask for generating XON indication pulse */ + uint32_t xon; + /* [0xc] Mask for generating GPIO output XOFF indication fro ... */ + uint32_t gpio; + /* [0x10] Rx FIFO threshold for generating the Almost Full in ... */ + uint32_t rx_fifo_af; + /* [0x14] Rx FIFO threshold for generating the Almost Full in ... */ + uint32_t rx_fifo_hyst; + /* [0x18] Rx FIFO threshold for generating the Almost Full in ... */ + uint32_t stat; + /* [0x1c] XOFF timer for the 1G MACSets the interval (in SB_C ... */ + uint32_t xoff_timer_1g; + /* [0x20] PFC force flow control generation */ + uint32_t ec_pfc; + uint32_t rsrvd[3]; +}; +struct al_ec_fc_udma { + /* [0x0] Mask of "pause_on" [0] for all queues */ + uint32_t q_pause_0; + /* [0x4] Mask of "pause_on" [1] for all queues */ + uint32_t q_pause_1; + /* [0x8] Mask of "pause_on" [2] for all queues */ + uint32_t q_pause_2; + /* [0xc] Mask of "pause_on" [3] for all queues */ + uint32_t q_pause_3; + /* [0x10] Mask of "pause_on" [4] for all queues */ + uint32_t q_pause_4; + /* [0x14] Mask of "pause_on" [5] for all queues */ + uint32_t q_pause_5; + /* [0x18] Mask of "pause_on" [6] for all queues */ + uint32_t q_pause_6; + /* [0x1c] Mask of "pause_on" [7] for all queues */ + uint32_t q_pause_7; + /* [0x20] Mask of external GPIO input pause [0] for all queue ... */ + uint32_t q_gpio_0; + /* [0x24] Mask of external GPIO input pause [1] for all queue ... */ + uint32_t q_gpio_1; + /* [0x28] Mask of external GPIO input pause [2] for all queue ... */ + uint32_t q_gpio_2; + /* [0x2c] Mask of external GPIO input pause [3] for all queue ... */ + uint32_t q_gpio_3; + /* [0x30] Mask of external GPIO input [4] for all queues */ + uint32_t q_gpio_4; + /* [0x34] Mask of external GPIO input [5] for all queues */ + uint32_t q_gpio_5; + /* [0x38] Mask of external GPIO input [6] for all queues */ + uint32_t q_gpio_6; + /* [0x3c] Mask of external GPIO input [7] for all queues */ + uint32_t q_gpio_7; + /* [0x40] Mask of "pause_on" [7:0] for the UDMA stream inter ... */ + uint32_t s_pause; + /* [0x44] Mask of Rx Almost Full indication for generating XO ... */ + uint32_t q_xoff_0; + /* [0x48] Mask of Rx Almost Full indication for generating XO ... */ + uint32_t q_xoff_1; + /* [0x4c] Mask of Rx Almost Full indication for generating XO ... */ + uint32_t q_xoff_2; + /* [0x50] Mask of Rx Almost Full indication for generating XO ... */ + uint32_t q_xoff_3; + /* [0x54] Mask of Rx Almost Full indication for generating XO ... */ + uint32_t q_xoff_4; + /* [0x58] Mask of Rx Almost Full indication for generating XO ... */ + uint32_t q_xoff_5; + /* [0x5c] Mask of Rx Almost Full indication for generating XO ... */ + uint32_t q_xoff_6; + /* [0x60] Mask of Rx Almost Full indication for generating XO ... */ + uint32_t q_xoff_7; + uint32_t rsrvd[7]; +}; +struct al_ec_tpg_rpa_res { + /* [0x0] NOT used */ + uint32_t not_used; + uint32_t rsrvd[63]; +}; +struct al_ec_eee { + /* [0x0] EEE configuration */ + uint32_t cfg_e; + /* [0x4] Number of clocks to get into EEE mode. */ + uint32_t pre_cnt; + /* [0x8] Number of clocks to stop MAC EEE mode after getting ... */ + uint32_t post_cnt; + /* [0xc] Number of clocks to stop the Tx MAC interface after ... */ + uint32_t stop_cnt; + /* [0x10] EEE status */ + uint32_t stat_eee; + uint32_t rsrvd[59]; +}; +struct al_ec_stat { + /* [0x0] Rx Frequency adjust FIFO input packets */ + uint32_t faf_in_rx_pkt; + /* [0x4] Rx Frequency adjust FIFO input short error packets */ + uint32_t faf_in_rx_short; + /* [0x8] Rx Frequency adjust FIFO input long error packets */ + uint32_t faf_in_rx_long; + /* [0xc] Rx Frequency adjust FIFO output packets */ + uint32_t faf_out_rx_pkt; + /* [0x10] Rx Frequency adjust FIFO output short error packets ... */ + uint32_t faf_out_rx_short; + /* [0x14] Rx Frequency adjust FIFO output long error packets */ + uint32_t faf_out_rx_long; + /* [0x18] Rx Frequency adjust FIFO output drop packets */ + uint32_t faf_out_drop; + /* [0x1c] Number of packets written into the Rx FIFO (without ... */ + uint32_t rxf_in_rx_pkt; + /* [0x20] Number of error packets written into the Rx FIFO (w ... */ + uint32_t rxf_in_fifo_err; + /* [0x24] Number of packets written into the loopback FIFO (w ... */ + uint32_t lbf_in_rx_pkt; + /* [0x28] Number of error packets written into the loopback F ... */ + uint32_t lbf_in_fifo_err; + /* [0x2c] Number of packets read from Rx FIFO 1 */ + uint32_t rxf_out_rx_1_pkt; + /* [0x30] Number of packets read from Rx FIFO 2 (loopback FIF ... */ + uint32_t rxf_out_rx_2_pkt; + /* [0x34] Rx FIFO output drop packets from FIFO 1 */ + uint32_t rxf_out_drop_1_pkt; + /* [0x38] Rx FIFO output drop packets from FIFO 2 (loopback) */ + uint32_t rxf_out_drop_2_pkt; + /* [0x3c] Rx Parser 1, input packet counter */ + uint32_t rpe_1_in_rx_pkt; + /* [0x40] Rx Parser 1, output packet counter */ + uint32_t rpe_1_out_rx_pkt; + /* [0x44] Rx Parser 2, input packet counter */ + uint32_t rpe_2_in_rx_pkt; + /* [0x48] Rx Parser 2, output packet counter */ + uint32_t rpe_2_out_rx_pkt; + /* [0x4c] Rx Parser 3 (MACsec), input packet counter */ + uint32_t rpe_3_in_rx_pkt; + /* [0x50] Rx Parser 3 (MACsec), output packet counter */ + uint32_t rpe_3_out_rx_pkt; + /* [0x54] Tx parser, input packet counter */ + uint32_t tpe_in_tx_pkt; + /* [0x58] Tx parser, output packet counter */ + uint32_t tpe_out_tx_pkt; + /* [0x5c] Tx packet modification, input packet counter */ + uint32_t tpm_tx_pkt; + /* [0x60] Tx forwarding input packet counter */ + uint32_t tfw_in_tx_pkt; + /* [0x64] Tx forwarding input packet counter */ + uint32_t tfw_out_tx_pkt; + /* [0x68] Rx forwarding input packet counter */ + uint32_t rfw_in_rx_pkt; + /* [0x6c] Rx Forwarding, packet with VLAN command drop indica ... */ + uint32_t rfw_in_vlan_drop; + /* [0x70] Rx Forwarding, packets with parse drop indication */ + uint32_t rfw_in_parse_drop; + /* [0x74] Rx Forwarding, multicast packets */ + uint32_t rfw_in_mc; + /* [0x78] Rx Forwarding, broadcast packets */ + uint32_t rfw_in_bc; + /* [0x7c] Rx Forwarding, tagged packets */ + uint32_t rfw_in_vlan_exist; + /* [0x80] Rx Forwarding, untagged packets */ + uint32_t rfw_in_vlan_nexist; + /* [0x84] Rx Forwarding, packets with MAC address drop indica ... */ + uint32_t rfw_in_mac_drop; + /* [0x88] Rx Forwarding, packets with undetected MAC address */ + uint32_t rfw_in_mac_ndet_drop; + /* [0x8c] Rx Forwarding, packets with drop indication from th ... */ + uint32_t rfw_in_ctrl_drop; + /* [0x90] Rx Forwarding, packets with L3_protocol_index drop ... */ + uint32_t rfw_in_prot_i_drop; + /* [0x94] EEE, number of times the system went into EEE state ... */ + uint32_t eee_in; + uint32_t rsrvd[90]; +}; +struct al_ec_stat_udma { + /* [0x0] Rx forwarding output packet counter */ + uint32_t rfw_out_rx_pkt; + /* [0x4] Rx forwarding output drop packet counter */ + uint32_t rfw_out_drop; + /* [0x8] Multi-stream write, number of Rx packets */ + uint32_t msw_in_rx_pkt; + /* [0xc] Multi-stream write, number of dropped packets at SO ... */ + uint32_t msw_drop_q_full; + /* [0x10] Multi-stream write, number of dropped packets at SO ... */ + uint32_t msw_drop_sop; + /* [0x14] Multi-stream write, number of dropped packets at EO ... */ + uint32_t msw_drop_eop; + /* [0x18] Multi-stream write, number of packets written to th ... */ + uint32_t msw_wr_eop; + /* [0x1c] Multi-stream write, number of packets read from the ... */ + uint32_t msw_out_rx_pkt; + /* [0x20] Number of transmitted packets without TSO enabled */ + uint32_t tso_no_tso_pkt; + /* [0x24] Number of transmitted packets with TSO enabled */ + uint32_t tso_tso_pkt; + /* [0x28] Number of TSO segments that were generated */ + uint32_t tso_seg_pkt; + /* [0x2c] Number of TSO segments that required padding */ + uint32_t tso_pad_pkt; + /* [0x30] Tx Packet modification, MAC SA spoof error */ + uint32_t tpm_tx_spoof; + /* [0x34] Tx MAC interface, input packet counter */ + uint32_t tmi_in_tx_pkt; + /* [0x38] Tx MAC interface, number of packets forwarded to th ... */ + uint32_t tmi_out_to_mac; + /* [0x3c] Tx MAC interface, number of packets forwarded to th ... */ + uint32_t tmi_out_to_rx; + /* [0x40] Tx MAC interface, number of transmitted bytes */ + uint32_t tx_q0_bytes; + /* [0x44] Tx MAC interface, number of transmitted bytes */ + uint32_t tx_q1_bytes; + /* [0x48] Tx MAC interface, number of transmitted bytes */ + uint32_t tx_q2_bytes; + /* [0x4c] Tx MAC interface, number of transmitted bytes */ + uint32_t tx_q3_bytes; + /* [0x50] Tx MAC interface, number of transmitted packets */ + uint32_t tx_q0_pkts; + /* [0x54] Tx MAC interface, number of transmitted packets */ + uint32_t tx_q1_pkts; + /* [0x58] Tx MAC interface, number of transmitted packets */ + uint32_t tx_q2_pkts; + /* [0x5c] Tx MAC interface, number of transmitted packets */ + uint32_t tx_q3_pkts; + uint32_t rsrvd[40]; +}; +struct al_ec_msp { + /* [0x0] Ethernet parsing engine configuration 1 */ + uint32_t p_parse_cfg; + /* [0x4] Protocol index action table address */ + uint32_t p_act_table_addr; + /* [0x8] Protocol index action table data */ + uint32_t p_act_table_data_1; + /* [0xc] Protocol index action table data */ + uint32_t p_act_table_data_2; + /* [0x10] Protocol index action table data */ + uint32_t p_act_table_data_3; + /* [0x14] Protocol index action table data */ + uint32_t p_act_table_data_4; + /* [0x18] Protocol index action table data */ + uint32_t p_act_table_data_5; + /* [0x1c] Protocol index action table data */ + uint32_t p_act_table_data_6; + /* [0x20] Input result vector, default values for parser inpu ... */ + uint32_t p_res_def; + /* [0x24] Result input vector selection */ + uint32_t p_res_in; + uint32_t rsrvd[6]; +}; +struct al_ec_msp_p { + /* [0x0] Header length, support for header length table for ... */ + uint32_t h_hdr_len; +}; +struct al_ec_msp_c { + /* [0x0] Data for comparison */ + uint32_t p_comp_data; + /* [0x4] Mask for comparison */ + uint32_t p_comp_mask; + /* [0x8] Compare control */ + uint32_t p_comp_ctrl; + uint32_t rsrvd[4]; +}; +struct al_ec_wol { + /* [0x0] WoL enable configuration,Packet forwarding and inte ... */ + uint32_t wol_en; + /* [0x4] Password for magic_password packet detection - bits ... */ + uint32_t magic_pswd_l; + /* [0x8] Password for magic+password packet detection - 47: ... */ + uint32_t magic_pswd_h; + /* [0xc] Configured L3 Destination IP address for WoL IPv6 p ... */ + uint32_t ipv6_dip_word0; + /* [0x10] Configured L3 Destination IP address for WoL IPv6 p ... */ + uint32_t ipv6_dip_word1; + /* [0x14] Configured L3 Destination IP address for WoL IPv6 p ... */ + uint32_t ipv6_dip_word2; + /* [0x18] Configured L3 Destination IP address for WoL IPv6 p ... */ + uint32_t ipv6_dip_word3; + /* [0x1c] Configured L3 Destination IP address for WoL IPv4 p ... */ + uint32_t ipv4_dip; + /* [0x20] Configured EtherType for WoL EtherType_da/EtherType ... */ + uint32_t ethertype; + uint32_t rsrvd[7]; +}; +struct al_ec_pth { + /* [0x0] System time counter (Time of Day) */ + uint32_t system_time_seconds; + /* [0x4] System time subseconds in a second (MSBs) */ + uint32_t system_time_subseconds_msb; + /* [0x8] System time subseconds in a second (LSBs) */ + uint32_t system_time_subseconds_lsb; + /* [0xc] Clock period in femtoseconds (MSB) */ + uint32_t clock_period_msb; + /* [0x10] Clock period in femtoseconds (LSB) */ + uint32_t clock_period_lsb; + /* [0x14] Control register for internal updates to the system ... */ + uint32_t int_update_ctrl; + /* [0x18] Value to update system_time_seconds with */ + uint32_t int_update_seconds; + /* [0x1c] Value to update system_time_subseconds_msb with */ + uint32_t int_update_subseconds_msb; + /* [0x20] Value to update system_time_subseconds_lsb with */ + uint32_t int_update_subseconds_lsb; + /* [0x24] Control register for external updates to the system ... */ + uint32_t ext_update_ctrl; + /* [0x28] Value to update system_time_seconds with */ + uint32_t ext_update_seconds; + /* [0x2c] Value to update system_time_subseconds_msb with */ + uint32_t ext_update_subseconds_msb; + /* [0x30] Value to update system_time_subseconds_lsb with */ + uint32_t ext_update_subseconds_lsb; + /* [0x34] This value represents the APB transaction delay fro ... */ + uint32_t read_compensation_subseconds_msb; + /* [0x38] This value represents the APB transaction delay fro ... */ + uint32_t read_compensation_subseconds_lsb; + /* [0x3c] This value is used for two purposes:1 */ + uint32_t int_write_compensation_subseconds_msb; + /* [0x40] This value is used for two purposes:1 */ + uint32_t int_write_compensation_subseconds_lsb; + /* [0x44] This value represents the number of cycles it for a ... */ + uint32_t ext_write_compensation_subseconds_msb; + /* [0x48] This value represents the number of cycles it for a ... */ + uint32_t ext_write_compensation_subseconds_lsb; + /* [0x4c] Value to be added to system_time before transferrin ... */ + uint32_t sync_compensation_subseconds_msb; + /* [0x50] Value to be added to system_time before transferrin ... */ + uint32_t sync_compensation_subseconds_lsb; + uint32_t rsrvd[11]; +}; +struct al_ec_pth_egress { + /* [0x0] Control register for egress trigger #k */ + uint32_t trigger_ctrl; + /* [0x4] threshold for next egress trigger (#k) - secondsWri ... */ + uint32_t trigger_seconds; + /* [0x8] Threshold for next egress trigger (#k) - subseconds ... */ + uint32_t trigger_subseconds_msb; + /* [0xc] threshold for next egress trigger (#k) - subseconds ... */ + uint32_t trigger_subseconds_lsb; + /* [0x10] External output pulse width (subseconds_msb)(Atomic ... */ + uint32_t pulse_width_subseconds_msb; + /* [0x14] External output pulse width (subseconds_lsb)(Atomic ... */ + uint32_t pulse_width_subseconds_lsb; + uint32_t rsrvd[2]; +}; +struct al_ec_pth_db { + /* [0x0] timestamp[k], in resolution of 2^18 femtosec =~ 0 */ + uint32_t ts; + /* [0x4] Timestamp entry is valid */ + uint32_t qual; + uint32_t rsrvd[4]; +}; +struct al_ec_gen_v3 { + /* [0x0] Bypass enable */ + uint32_t bypass; + /* [0x4] Rx Completion descriptor */ + uint32_t rx_comp_desc; + /* [0x8] general configuration */ + uint32_t conf; + uint32_t rsrvd[13]; +}; +struct al_ec_tfw_v3 { + /* [0x0] Generic protocol detect Cam compare table address */ + uint32_t tx_gpd_cam_addr; + /* [0x4] Tx Generic protocol detect Cam compare data_1 (low) ... */ + uint32_t tx_gpd_cam_data_1; + /* [0x8] Tx Generic protocol detect Cam compare data_2 (high ... */ + uint32_t tx_gpd_cam_data_2; + /* [0xc] Tx Generic protocol detect Cam compare mask_1 (low) ... */ + uint32_t tx_gpd_cam_mask_1; + /* [0x10] Tx Generic protocol detect Cam compare mask_1 (high ... */ + uint32_t tx_gpd_cam_mask_2; + /* [0x14] Tx Generic protocol detect Cam compare control */ + uint32_t tx_gpd_cam_ctrl; + /* [0x18] Tx Generic crc parameters legacy */ + uint32_t tx_gcp_legacy; + /* [0x1c] Tx Generic crc prameters table address */ + uint32_t tx_gcp_table_addr; + /* [0x20] Tx Generic crc prameters table general */ + uint32_t tx_gcp_table_gen; + /* [0x24] Tx Generic crc parametrs tabel mask word 1 */ + uint32_t tx_gcp_table_mask_1; + /* [0x28] Tx Generic crc parametrs tabel mask word 2 */ + uint32_t tx_gcp_table_mask_2; + /* [0x2c] Tx Generic crc parametrs tabel mask word 3 */ + uint32_t tx_gcp_table_mask_3; + /* [0x30] Tx Generic crc parametrs tabel mask word 4 */ + uint32_t tx_gcp_table_mask_4; + /* [0x34] Tx Generic crc parametrs tabel mask word 5 */ + uint32_t tx_gcp_table_mask_5; + /* [0x38] Tx Generic crc parametrs tabel mask word 6 */ + uint32_t tx_gcp_table_mask_6; + /* [0x3c] Tx Generic crc parametrs tabel crc init */ + uint32_t tx_gcp_table_crc_init; + /* [0x40] Tx Generic crc parametrs tabel result configuration ... */ + uint32_t tx_gcp_table_res; + /* [0x44] Tx Generic crc parameters table alu opcode */ + uint32_t tx_gcp_table_alu_opcode; + /* [0x48] Tx Generic crc parameters table alu opsel */ + uint32_t tx_gcp_table_alu_opsel; + /* [0x4c] Tx Generic crc parameters table alu constant value */ + uint32_t tx_gcp_table_alu_val; + /* [0x50] Tx CRC/Checksum replace */ + uint32_t crc_csum_replace; + /* [0x54] CRC/Checksum replace table address */ + uint32_t crc_csum_replace_table_addr; + /* [0x58] CRC/Checksum replace table */ + uint32_t crc_csum_replace_table; + uint32_t rsrvd[9]; +}; + +struct al_ec_rfw_v3 { + /* [0x0] Rx Generic protocol detect Cam compare table addres ... */ + uint32_t rx_gpd_cam_addr; + /* [0x4] Rx Generic protocol detect Cam compare data_1 (low) ... */ + uint32_t rx_gpd_cam_data_1; + /* [0x8] Rx Generic protocol detect Cam compare data_2 (high ... */ + uint32_t rx_gpd_cam_data_2; + /* [0xc] Rx Generic protocol detect Cam compare mask_1 (low) ... */ + uint32_t rx_gpd_cam_mask_1; + /* [0x10] Rx Generic protocol detect Cam compare mask_1 (high ... */ + uint32_t rx_gpd_cam_mask_2; + /* [0x14] Rx Generic protocol detect Cam compare control */ + uint32_t rx_gpd_cam_ctrl; + /* [0x18] Generic protocol detect Parser result vector pointe ... */ + uint32_t gpd_p1; + /* [0x1c] Generic protocol detect Parser result vector pointe ... */ + uint32_t gpd_p2; + /* [0x20] Generic protocol detect Parser result vector pointe ... */ + uint32_t gpd_p3; + /* [0x24] Generic protocol detect Parser result vector pointe ... */ + uint32_t gpd_p4; + /* [0x28] Generic protocol detect Parser result vector pointe ... */ + uint32_t gpd_p5; + /* [0x2c] Generic protocol detect Parser result vector pointe ... */ + uint32_t gpd_p6; + /* [0x30] Generic protocol detect Parser result vector pointe ... */ + uint32_t gpd_p7; + /* [0x34] Generic protocol detect Parser result vector pointe ... */ + uint32_t gpd_p8; + /* [0x38] Rx Generic crc parameters legacy */ + uint32_t rx_gcp_legacy; + /* [0x3c] Rx Generic crc prameters table address */ + uint32_t rx_gcp_table_addr; + /* [0x40] Rx Generic crc prameters table general */ + uint32_t rx_gcp_table_gen; + /* [0x44] Rx Generic crc parametrs tabel mask word 1 */ + uint32_t rx_gcp_table_mask_1; + /* [0x48] Rx Generic crc parametrs tabel mask word 2 */ + uint32_t rx_gcp_table_mask_2; + /* [0x4c] Rx Generic crc parametrs tabel mask word 3 */ + uint32_t rx_gcp_table_mask_3; + /* [0x50] Rx Generic crc parametrs tabel mask word 4 */ + uint32_t rx_gcp_table_mask_4; + /* [0x54] Rx Generic crc parametrs tabel mask word 5 */ + uint32_t rx_gcp_table_mask_5; + /* [0x58] Rx Generic crc parametrs tabel mask word 6 */ + uint32_t rx_gcp_table_mask_6; + /* [0x5c] Rx Generic crc parametrs tabel crc init */ + uint32_t rx_gcp_table_crc_init; + /* [0x60] Rx Generic crc parametrs tabel result configuration ... */ + uint32_t rx_gcp_table_res; + /* [0x64] Rx Generic crc parameters table alu opcode */ + uint32_t rx_gcp_table_alu_opcode; + /* [0x68] Rx Generic crc parameters table alu opsel */ + uint32_t rx_gcp_table_alu_opsel; + /* [0x6c] Rx Generic crc parameters table alu constant value ... */ + uint32_t rx_gcp_table_alu_val; + /* [0x70] Generic crc engin parameters alu Parser result vect ... */ + uint32_t rx_gcp_alu_p1; + /* [0x74] Generic crc engine parameters alu Parser result vec ... */ + uint32_t rx_gcp_alu_p2; + /* [0x78] Header split control table address */ + uint32_t hs_ctrl_table_addr; + /* [0x7c] Header split control table */ + uint32_t hs_ctrl_table; + /* [0x80] Header split control alu opcode */ + uint32_t hs_ctrl_table_alu_opcode; + /* [0x84] Header split control alu opsel */ + uint32_t hs_ctrl_table_alu_opsel; + /* [0x88] Header split control alu constant value */ + uint32_t hs_ctrl_table_alu_val; + /* [0x8c] Header split control configuration */ + uint32_t hs_ctrl_cfg; + /* [0x90] Header split control alu Parser result vector point ... */ + uint32_t hs_ctrl_alu_p1; + /* [0x94] Header split control alu Parser result vector point ... */ + uint32_t hs_ctrl_alu_p2; + uint32_t rsrvd[26]; +}; +struct al_ec_crypto { + /* [0x0] Tx inline crypto configuration */ + uint32_t tx_config; + /* [0x4] Rx inline crypto configuration */ + uint32_t rx_config; + /* [0x8] reserved FFU */ + uint32_t tx_override; + /* [0xc] reserved FFU */ + uint32_t rx_override; + /* [0x10] inline XTS alpha [31:0] */ + uint32_t xts_alpha_1; + /* [0x14] inline XTS alpha [63:32] */ + uint32_t xts_alpha_2; + /* [0x18] inline XTS alpha [95:64] */ + uint32_t xts_alpha_3; + /* [0x1c] inline XTS alpha [127:96] */ + uint32_t xts_alpha_4; + /* [0x20] inline XTS sector ID increment [31:0] */ + uint32_t xts_sector_id_1; + /* [0x24] inline XTS sector ID increment [63:32] */ + uint32_t xts_sector_id_2; + /* [0x28] inline XTS sector ID increment [95:64] */ + uint32_t xts_sector_id_3; + /* [0x2c] inline XTS sector ID increment [127:96] */ + uint32_t xts_sector_id_4; + /* [0x30] IV formation configuration */ + uint32_t tx_enc_iv_construction; + /* [0x34] IV formation configuration */ + uint32_t rx_enc_iv_construction; + /* [0x38] IV formation configuration */ + uint32_t rx_enc_iv_map; + /* + [0x3c] effectively shorten shift-registers used for + eop-pkt-trim, in order to improve performance. + Each value must be built of consecutive 1's (bypassed regs), + and then consecutive 0's (non-bypassed regs) + */ + uint32_t tx_pkt_trim_len; + /* + [0x40] effectively shorten shift-registers used for + eop-pkt-trim, in order to improve performance. + Each value must be built of consecutive 1's (bypassed regs), + and then consecutive 0's (non-bypassed regs) + */ + uint32_t rx_pkt_trim_len; + /* [0x44] reserved FFU */ + uint32_t tx_reserved; + /* [0x48] reserved FFU */ + uint32_t rx_reserved; + uint32_t rsrvd[13]; +}; +struct al_ec_crypto_perf_cntr { + /* [0x0] */ + uint32_t total_tx_pkts; + /* [0x4] */ + uint32_t total_rx_pkts; + /* [0x8] */ + uint32_t total_tx_secured_pkts; + /* [0xc] */ + uint32_t total_rx_secured_pkts; + /* [0x10] */ + uint32_t total_tx_secured_pkts_cipher_mode; + /* [0x14] */ + uint32_t total_tx_secured_pkts_cipher_mode_cmpr; + /* [0x18] */ + uint32_t total_rx_secured_pkts_cipher_mode; + /* [0x1c] */ + uint32_t total_rx_secured_pkts_cipher_mode_cmpr; + /* [0x20] */ + uint32_t total_tx_secured_bytes_low; + /* [0x24] */ + uint32_t total_tx_secured_bytes_high; + /* [0x28] */ + uint32_t total_rx_secured_bytes_low; + /* [0x2c] */ + uint32_t total_rx_secured_bytes_high; + /* [0x30] */ + uint32_t total_tx_sign_calcs; + /* [0x34] */ + uint32_t total_rx_sign_calcs; + /* [0x38] */ + uint32_t total_tx_sign_errs; + /* [0x3c] */ + uint32_t total_rx_sign_errs; +}; +struct al_ec_crypto_tx_tid { + /* [0x0] tid_default_entry */ + uint32_t def_val; +}; + +struct al_ec_regs { + uint32_t rsrvd_0[32]; + struct al_ec_gen gen; /* [0x80] */ + struct al_ec_mac mac; /* [0xc0] */ + struct al_ec_rxf rxf; /* [0x100] */ + struct al_ec_epe epe[2]; /* [0x180] */ + struct al_ec_epe_res epe_res; /* [0x200] */ + struct al_ec_epe_h epe_h[32]; /* [0x280] */ + struct al_ec_epe_p epe_p[32]; /* [0x300] */ + struct al_ec_epe_a epe_a[32]; /* [0x680] */ + struct al_ec_rfw rfw; /* [0x700] */ + struct al_ec_rfw_udma rfw_udma[4]; /* [0x7f0] */ + struct al_ec_rfw_hash rfw_hash[10]; /* [0x800] */ + struct al_ec_rfw_priority rfw_priority[8]; /* [0x828] */ + struct al_ec_rfw_default rfw_default[8]; /* [0x848] */ + struct al_ec_fwd_mac fwd_mac[32]; /* [0x868] */ + struct al_ec_msw msw; /* [0xae8] */ + struct al_ec_tso tso; /* [0xb00] */ + struct al_ec_tso_sel tso_sel[8]; /* [0xb60] */ + struct al_ec_tpe tpe; /* [0xb80] */ + struct al_ec_tpm_udma tpm_udma[4]; /* [0xbc0] */ + struct al_ec_tpm_sel tpm_sel[4]; /* [0xbf0] */ + struct al_ec_tfw tfw; /* [0xc00] */ + struct al_ec_tfw_udma tfw_udma[4]; /* [0xc60] */ + struct al_ec_tmi tmi; /* [0xcc0] */ + struct al_ec_efc efc; /* [0xcd0] */ + struct al_ec_fc_udma fc_udma[4]; /* [0xd00] */ + struct al_ec_tpg_rpa_res tpg_rpa_res; /* [0xf00] */ + struct al_ec_eee eee; /* [0x1000] */ + struct al_ec_stat stat; /* [0x1100] */ + struct al_ec_stat_udma stat_udma[4]; /* [0x1300] */ + struct al_ec_msp msp; /* [0x1700] */ + struct al_ec_msp_p msp_p[32]; /* [0x1740] */ + struct al_ec_msp_c msp_c[32]; /* [0x17c0] */ + uint32_t rsrvd_1[16]; + struct al_ec_wol wol; /* [0x1b80] */ + uint32_t rsrvd_2[80]; + struct al_ec_pth pth; /* [0x1d00] */ + struct al_ec_pth_egress pth_egress[8]; /* [0x1d80] */ + struct al_ec_pth_db pth_db[16]; /* [0x1e80] */ + uint32_t rsrvd_3[416]; + struct al_ec_gen_v3 gen_v3; /* [0x2680] */ + struct al_ec_tfw_v3 tfw_v3; /* [0x26c0] */ + struct al_ec_rfw_v3 rfw_v3; /* [0x2740] */ + struct al_ec_crypto crypto; /* [0x2840] */ + struct al_ec_crypto_perf_cntr crypto_perf_cntr[2]; /* [0x28c0] */ + uint32_t rsrvd_4[48]; + struct al_ec_crypto_tx_tid crypto_tx_tid[8]; /* [0x2a00] */ +}; + + +/* +* Registers Fields +*/ + + +/**** version register ****/ +/* Revision number (Minor) */ +#define EC_GEN_VERSION_RELEASE_NUM_MINOR_MASK 0x000000FF +#define EC_GEN_VERSION_RELEASE_NUM_MINOR_SHIFT 0 +/* Revision number (Major) */ +#define EC_GEN_VERSION_RELEASE_NUM_MAJOR_MASK 0x0000FF00 +#define EC_GEN_VERSION_RELEASE_NUM_MAJOR_SHIFT 8 +/* Day of release */ +#define EC_GEN_VERSION_DATE_DAY_MASK 0x001F0000 +#define EC_GEN_VERSION_DATE_DAY_SHIFT 16 +/* Month of release */ +#define EC_GEN_VERSION_DATA_MONTH_MASK 0x01E00000 +#define EC_GEN_VERSION_DATA_MONTH_SHIFT 21 +/* Year of release (starting from 2000) */ +#define EC_GEN_VERSION_DATE_YEAR_MASK 0x3E000000 +#define EC_GEN_VERSION_DATE_YEAR_SHIFT 25 +/* Reserved */ +#define EC_GEN_VERSION_RESERVED_MASK 0xC0000000 +#define EC_GEN_VERSION_RESERVED_SHIFT 30 + +/**** en register ****/ +/* Enable Frequency adjust FIFO input controller operation. */ +#define EC_GEN_EN_FAF_IN (1 << 0) +/* Enable Frequency adjust FIFO output controller operation. */ +#define EC_GEN_EN_FAF_OUT (1 << 1) +/* Enable Rx FIFO input controller 1 operation. */ +#define EC_GEN_EN_RXF_IN (1 << 2) +/* Enable Rx FIFO output controller operation. */ +#define EC_GEN_EN_RXF_OUT (1 << 3) +/* Enable Rx forwarding input controller operation. */ +#define EC_GEN_EN_RFW_IN (1 << 4) +/* Enable Rx forwarding output controller operation. */ +#define EC_GEN_EN_RFW_OUT (1 << 5) +/* Enable Rx multi-stream write controller operation. */ +#define EC_GEN_EN_MSW_IN (1 << 6) +/* Enable Rx first parsing engine output operation. */ +#define EC_GEN_EN_RPE_1_OUT (1 << 7) +/* Enable Rx first parsing engine input operation. */ +#define EC_GEN_EN_RPE_1_IN (1 << 8) +/* Enable Rx second parsing engine output operation. */ +#define EC_GEN_EN_RPE_2_OUT (1 << 9) +/* Enable Rx second parsing engine input operation. */ +#define EC_GEN_EN_RPE_2_IN (1 << 10) +/* Enable Rx MACsec parsing engine output operation. */ +#define EC_GEN_EN_RPE_3_OUT (1 << 11) +/* Enable Rx MACsec parsing engine input operation. */ +#define EC_GEN_EN_RPE_3_IN (1 << 12) +/* Enable Loopback FIFO input controller 1 operation. */ +#define EC_GEN_EN_LBF_IN (1 << 13) +/* Enable Rx packet analyzer operation. */ +#define EC_GEN_EN_RPA (1 << 14) + +#define EC_GEN_EN_RESERVED_15 (1 << 15) +/* Enable Tx stream interface operation. */ +#define EC_GEN_EN_TSO (1 << 16) +/* Enable Tx parser input controller operation. */ +#define EC_GEN_EN_TPE_IN (1 << 17) +/* Enable Tx parser output controller operation. */ +#define EC_GEN_EN_TPE_OUT (1 << 18) +/* Enable Tx packet modification operation. */ +#define EC_GEN_EN_TPM (1 << 19) +/* Enable Tx forwarding input controller operation. */ +#define EC_GEN_EN_TFW_IN (1 << 20) +/* Enable Tx forwarding output controller operation. */ +#define EC_GEN_EN_TFW_OUT (1 << 21) +/* Enable Tx MAC interface controller operation. */ +#define EC_GEN_EN_TMI (1 << 22) +/* Enable Tx packet generator operation. */ +#define EC_GEN_EN_TPG (1 << 23) + +#define EC_GEN_EN_RESERVED_31_MASK 0xFF000000 +#define EC_GEN_EN_RESERVED_31_SHIFT 24 + +/**** fifo_en register ****/ +/* Enable Frequency adjust FIFO operation (input). */ +#define EC_GEN_FIFO_EN_FAF_IN (1 << 0) +/* Enable Frequency adjust FIFO operation (output). */ +#define EC_GEN_FIFO_EN_FAF_OUT (1 << 1) +/* Enable Rx FIFO operation. */ +#define EC_GEN_FIFO_EN_RX_FIFO (1 << 2) +/* Enable Rx forwarding FIFO operation. */ +#define EC_GEN_FIFO_EN_RFW_FIFO (1 << 3) +/* Enable Rx multi-stream write FIFO operation */ +#define EC_GEN_FIFO_EN_MSW_FIFO (1 << 4) +/* Enable Rx first parser FIFO operation. */ +#define EC_GEN_FIFO_EN_RPE_1_FIFO (1 << 5) +/* Enable Rx second parser FIFO operation. */ +#define EC_GEN_FIFO_EN_RPE_2_FIFO (1 << 6) +/* Enable Rx MACsec parser FIFO operation. */ +#define EC_GEN_FIFO_EN_RPE_3_FIFO (1 << 7) +/* Enable Loopback FIFO operation. */ +#define EC_GEN_FIFO_EN_LB_FIFO (1 << 8) + +#define EC_GEN_FIFO_EN_RESERVED_15_9_MASK 0x0000FE00 +#define EC_GEN_FIFO_EN_RESERVED_15_9_SHIFT 9 +/* Enable Tx parser FIFO operation. */ +#define EC_GEN_FIFO_EN_TPE_FIFO (1 << 16) +/* Enable Tx forwarding FIFO operation. */ +#define EC_GEN_FIFO_EN_TFW_FIFO (1 << 17) + +#define EC_GEN_FIFO_EN_RESERVED_31_18_MASK 0xFFFC0000 +#define EC_GEN_FIFO_EN_RESERVED_31_18_SHIFT 18 + +/**** l2 register ****/ +/* Size of a 802.3 Ethernet header (DA+SA) */ +#define EC_GEN_L2_SIZE_802_3_MASK 0x0000003F +#define EC_GEN_L2_SIZE_802_3_SHIFT 0 +/* Size of a 802.3 + MACsec 8 byte header */ +#define EC_GEN_L2_SIZE_802_3_MS_8_MASK 0x00003F00 +#define EC_GEN_L2_SIZE_802_3_MS_8_SHIFT 8 +/* Offset of the L2 header from the beginning of the packet. */ +#define EC_GEN_L2_OFFSET_MASK 0x7F000000 +#define EC_GEN_L2_OFFSET_SHIFT 24 + +/**** cfg_i register ****/ +/* IPv4 protocol index */ +#define EC_GEN_CFG_I_IPV4_INDEX_MASK 0x0000001F +#define EC_GEN_CFG_I_IPV4_INDEX_SHIFT 0 +/* IPv6 protocol index */ +#define EC_GEN_CFG_I_IPV6_INDEX_MASK 0x000003E0 +#define EC_GEN_CFG_I_IPV6_INDEX_SHIFT 5 +/* TCP protocol index */ +#define EC_GEN_CFG_I_TCP_INDEX_MASK 0x00007C00 +#define EC_GEN_CFG_I_TCP_INDEX_SHIFT 10 +/* UDP protocol index */ +#define EC_GEN_CFG_I_UDP_INDEX_MASK 0x000F8000 +#define EC_GEN_CFG_I_UDP_INDEX_SHIFT 15 +/* MACsec with 8 bytes SecTAG */ +#define EC_GEN_CFG_I_MACSEC_8_INDEX_MASK 0x01F00000 +#define EC_GEN_CFG_I_MACSEC_8_INDEX_SHIFT 20 +/* MACsec with 16 bytes SecTAG */ +#define EC_GEN_CFG_I_MACSEC_16_INDEX_MASK 0x3E000000 +#define EC_GEN_CFG_I_MACSEC_16_INDEX_SHIFT 25 + +/**** cfg_i_ext register ****/ +/* FcoE protocol index */ +#define EC_GEN_CFG_I_EXT_FCOE_INDEX_MASK 0x0000001F +#define EC_GEN_CFG_I_EXT_FCOE_INDEX_SHIFT 0 +/* RoCE protocol index */ +#define EC_GEN_CFG_I_EXT_ROCE_INDEX_L3_1_MASK 0x000003E0 +#define EC_GEN_CFG_I_EXT_ROCE_INDEX_L3_1_SHIFT 5 +/* RoCE protocol index */ +#define EC_GEN_CFG_I_EXT_ROCE_INDEX_L3_2_MASK 0x00007C00 +#define EC_GEN_CFG_I_EXT_ROCE_INDEX_L3_2_SHIFT 10 +/* RoCE protocol index */ +#define EC_GEN_CFG_I_EXT_ROCE_INDEX_L4_MASK 0x000F8000 +#define EC_GEN_CFG_I_EXT_ROCE_INDEX_L4_SHIFT 15 + +/**** en_ext register ****/ +/* Enable Usage of Ethernet port memories for testing */ +#define EC_GEN_EN_EXT_MEM_FOR_TEST_MASK 0x0000000F +#define EC_GEN_EN_EXT_MEM_FOR_TEST_SHIFT 0 +#define EC_GEN_EN_EXT_MEM_FOR_TEST_VAL_EN \ + (0xa << EC_GEN_EN_EXT_MEM_FOR_TEST_SHIFT) +#define EC_GEN_EN_EXT_MEM_FOR_TEST_VAL_DIS \ + (0x0 << EC_GEN_EN_EXT_MEM_FOR_TEST_SHIFT) +/* Enable MAC loop back (Rx --> Tx, after MAC layer) for 802 */ +#define EC_GEN_EN_EXT_MAC_LB (1 << 4) +/* CRC forward value for the MAC Tx when working in loopback mod ... */ +#define EC_GEN_EN_EXT_MAC_LB_CRC_FWD (1 << 5) +/* Ready signal configuration when in loopback mode:00 - Ready f ... */ +#define EC_GEN_EN_EXT_MAC_LB_READY_CFG_MASK 0x000000C0 +#define EC_GEN_EN_EXT_MAC_LB_READY_CFG_SHIFT 6 +/* Bypass the PTH completion update. */ +#define EC_GEN_EN_EXT_PTH_COMPLETION_BYPASS (1 << 16) +/* Selection between the 1G and 10G MAC: +0 - 1G +1 - 10G */ +#define EC_GEN_EN_EXT_PTH_1_10_SEL (1 << 17) +/* avoid timestamping every pkt in 1G */ +#define EC_GEN_EN_EXT_PTH_CFG_1G_TIMESTAMP_OPT (1 << 18) +/* Selection between descriptor caching options (WORD selection) ... */ +#define EC_GEN_EN_EXT_CACHE_WORD_SPLIT (1 << 20) + +/**** gen register ****/ +/* Enable swap of input byte order */ +#define EC_MAC_GEN_SWAP_IN_BYTE (1 << 0) + +/**** min_pkt register ****/ +/* Minimum packet size */ +#define EC_MAC_MIN_PKT_SIZE_MASK 0x000FFFFF +#define EC_MAC_MIN_PKT_SIZE_SHIFT 0 + +/**** max_pkt register ****/ +/* Maximum packet size */ +#define EC_MAC_MAX_PKT_SIZE_MASK 0x000FFFFF +#define EC_MAC_MAX_PKT_SIZE_SHIFT 0 + +/**** cfg_1 register ****/ +/* Drop packet at the ingress0 - Packets are not dropped at the ... */ +#define EC_RXF_CFG_1_DROP_AT_INGRESS (1 << 0) +/* Accept packet criteria at start of packet indication */ +#define EC_RXF_CFG_1_SOP_ACCEPT (1 << 1) +/* Select the arbiter between Rx packets and Tx packets (packets ... */ +#define EC_RXF_CFG_1_ARB_SEL (1 << 2) +/* Arbiter priority when strict priority is selected in arb_sel0 ... */ +#define EC_RXF_CFG_1_ARB_P (1 << 3) +/* Force loopback operation */ +#define EC_RXF_CFG_1_FORCE_LB (1 << 4) +/* Forwarding selection between Rx path and/or packet analyzer */ +#define EC_RXF_CFG_1_FWD_SEL_MASK 0x00000300 +#define EC_RXF_CFG_1_FWD_SEL_SHIFT 8 + +/**** cfg_2 register ****/ +/* FIFO USED threshold for accepting new packets, low threshold ... */ +#define EC_RXF_CFG_2_FIFO_USED_TH_L_MASK 0x0000FFFF +#define EC_RXF_CFG_2_FIFO_USED_TH_L_SHIFT 0 +/* FIFO USED threshold for accepting new packets, high threshold ... */ +#define EC_RXF_CFG_2_FIFO_USED_TH_H_MASK 0xFFFF0000 +#define EC_RXF_CFG_2_FIFO_USED_TH_H_SHIFT 16 + +/**** rd_fifo register ****/ +/* Minimum number of entries in the data FIFO to start reading p ... */ +#define EC_RXF_RD_FIFO_TH_DATA_MASK 0x0000FFFF +#define EC_RXF_RD_FIFO_TH_DATA_SHIFT 0 +/* Enable cut through operation */ +#define EC_RXF_RD_FIFO_EN_CUT_TH (1 << 16) + +/**** wr_fifo register ****/ + +#define EC_RXF_WR_FIFO_TH_DATA_MASK 0x0000FFFF +#define EC_RXF_WR_FIFO_TH_DATA_SHIFT 0 + +#define EC_RXF_WR_FIFO_TH_INFO_MASK 0xFFFF0000 +#define EC_RXF_WR_FIFO_TH_INFO_SHIFT 16 + +/**** lb_fifo register ****/ + +#define EC_RXF_LB_FIFO_TH_DATA_MASK 0x0000FFFF +#define EC_RXF_LB_FIFO_TH_DATA_SHIFT 0 + +#define EC_RXF_LB_FIFO_TH_INFO_MASK 0xFFFF0000 +#define EC_RXF_LB_FIFO_TH_INFO_SHIFT 16 + +/**** cfg_lb register ****/ +/* FIFO USED threshold for accepting new packets */ +#define EC_RXF_CFG_LB_FIFO_USED_TH_INT_MASK 0x0000FFFF +#define EC_RXF_CFG_LB_FIFO_USED_TH_INT_SHIFT 0 +/* FIFO USED threshold for generating ready for the Tx path */ +#define EC_RXF_CFG_LB_FIFO_USED_TH_EXT_MASK 0xFFFF0000 +#define EC_RXF_CFG_LB_FIFO_USED_TH_EXT_SHIFT 16 + +/**** out_drop register ****/ + +#define EC_RXF_OUT_DROP_MAC_ERR (1 << 0) + +#define EC_RXF_OUT_DROP_MAC_COL (1 << 1) + +#define EC_RXF_OUT_DROP_MAC_DEC (1 << 2) + +#define EC_RXF_OUT_DROP_MAC_LEN (1 << 3) + +#define EC_RXF_OUT_DROP_MAC_PHY (1 << 4) + +#define EC_RXF_OUT_DROP_MAC_FIFO (1 << 5) + +#define EC_RXF_OUT_DROP_MAC_FCS (1 << 6) + +#define EC_RXF_OUT_DROP_MAC_ETYPE (1 << 7) + +#define EC_RXF_OUT_DROP_EC_LEN (1 << 8) + +#define EC_RXF_OUT_DROP_EC_FIFO (1 << 9) + +/**** parse_cfg register ****/ +/* MAX number of beats for packet parsing */ +#define EC_EPE_PARSE_CFG_MAX_BEATS_MASK 0x000000FF +#define EC_EPE_PARSE_CFG_MAX_BEATS_SHIFT 0 +/* MAX number of parsing iterations for packet parsing */ +#define EC_EPE_PARSE_CFG_MAX_ITER_MASK 0x0000FF00 +#define EC_EPE_PARSE_CFG_MAX_ITER_SHIFT 8 + +/**** act_table_addr register ****/ +/* Address for accessing the table */ +#define EC_EPE_ACT_TABLE_ADDR_VAL_MASK 0x0000001F +#define EC_EPE_ACT_TABLE_ADDR_VAL_SHIFT 0 + +/**** act_table_data_1 register ****/ +/* Table data[5:0] - Offset to next protocol [bytes][6] - Next p ... */ +#define EC_EPE_ACT_TABLE_DATA_1_VAL_MASK 0x03FFFFFF +#define EC_EPE_ACT_TABLE_DATA_1_VAL_SHIFT 0 + +/**** act_table_data_2 register ****/ +/* Table Data [8:0] - Offset to data in the packet [bits][17:9] ... */ +#define EC_EPE_ACT_TABLE_DATA_2_VAL_MASK 0x1FFFFFFF +#define EC_EPE_ACT_TABLE_DATA_2_VAL_SHIFT 0 + +/**** act_table_data_3 register ****/ +/* Table Data [8:0] - Offset to data in the packet [bits] [17:9 ... */ +#define EC_EPE_ACT_TABLE_DATA_3_VAL_MASK 0x1FFFFFFF +#define EC_EPE_ACT_TABLE_DATA_3_VAL_SHIFT 0 + +/**** act_table_data_4 register ****/ +/* Table data[7:0] - Offset to header length location in the pac ... */ +#define EC_EPE_ACT_TABLE_DATA_4_VAL_MASK 0x0FFFFFFF +#define EC_EPE_ACT_TABLE_DATA_4_VAL_SHIFT 0 + +/**** act_table_data_6 register ****/ +/* Table data[0] - WR header length[10:1] - Write header length ... */ +#define EC_EPE_ACT_TABLE_DATA_6_VAL_MASK 0x007FFFFF +#define EC_EPE_ACT_TABLE_DATA_6_VAL_SHIFT 0 + +/**** res_in register ****/ +/* Selector for input parse_en0 - Input vector1 - Default value ... */ +#define EC_EPE_RES_IN_SEL_PARSE_EN (1 << 0) +/* Selector for input protocol_index 0 - Input vector 1 - Defaul ... */ +#define EC_EPE_RES_IN_SEL_PROT_INDEX (1 << 1) +/* Selector for input hdr_offset 0 - Input vector 1 - Default va ... */ +#define EC_EPE_RES_IN_SEL_HDR_OFFSET (1 << 2) + +/**** p1 register ****/ +/* Location of the input protocol index in the parser result vec ... */ +#define EC_EPE_RES_P1_IN_PROT_INDEX_MASK 0x000003FF +#define EC_EPE_RES_P1_IN_PROT_INDEX_SHIFT 0 + +/**** p2 register ****/ +/* Location of the input offset in the parser result vector */ +#define EC_EPE_RES_P2_IN_OFFSET_MASK 0x000003FF +#define EC_EPE_RES_P2_IN_OFFSET_SHIFT 0 + +/**** p3 register ****/ +/* Location of the input parse enable in the parser result vecto ... */ +#define EC_EPE_RES_P3_IN_PARSE_EN_MASK 0x000003FF +#define EC_EPE_RES_P3_IN_PARSE_EN_SHIFT 0 + +/**** p4 register ****/ +/* Location of the control bits in the parser result vector */ +#define EC_EPE_RES_P4_CTRL_BITS_MASK 0x000003FF +#define EC_EPE_RES_P4_CTRL_BITS_SHIFT 0 + +/**** p5 register ****/ +/* Location of the MAC DA in the parser result vector */ +#define EC_EPE_RES_P5_DA_MASK 0x000003FF +#define EC_EPE_RES_P5_DA_SHIFT 0 + +/**** p6 register ****/ +/* Location of the MAC SA in the parser result vector */ +#define EC_EPE_RES_P6_SA_MASK 0x000003FF +#define EC_EPE_RES_P6_SA_SHIFT 0 + +/**** p7 register ****/ +/* Location of the first VLAN in the parser result vector */ +#define EC_EPE_RES_P7_VLAN_1_MASK 0x000003FF +#define EC_EPE_RES_P7_VLAN_1_SHIFT 0 + +/**** p8 register ****/ +/* Location of the second VLAN in the parser result vector */ +#define EC_EPE_RES_P8_VLAN_2_MASK 0x000003FF +#define EC_EPE_RES_P8_VLAN_2_SHIFT 0 + +/**** p9 register ****/ +/* Location of the L3 protocol index in the parser result vector ... */ +#define EC_EPE_RES_P9_L3_PROT_INDEX_MASK 0x000003FF +#define EC_EPE_RES_P9_L3_PROT_INDEX_SHIFT 0 + +/**** p10 register ****/ +/* Location of the L3 offset in the parser result vector */ +#define EC_EPE_RES_P10_L3_OFFSET_MASK 0x000003FF +#define EC_EPE_RES_P10_L3_OFFSET_SHIFT 0 + +/**** p11 register ****/ +/* Location of the L3 SIP in the parser result vector */ +#define EC_EPE_RES_P11_L3_SIP_MASK 0x000003FF +#define EC_EPE_RES_P11_L3_SIP_SHIFT 0 + +/**** p12 register ****/ +/* Location of the L3 DIP in the parser result vector */ +#define EC_EPE_RES_P12_L3_DIP_MASK 0x000003FF +#define EC_EPE_RES_P12_L3_DIP_SHIFT 0 + +/**** p13 register ****/ +/* Location of the L3 priority in the parser result vector */ +#define EC_EPE_RES_P13_L3_PRIORITY_MASK 0x000003FF +#define EC_EPE_RES_P13_L3_PRIORITY_SHIFT 0 + +/**** p14 register ****/ +/* Location of the L3 header length in the parser result vector */ +#define EC_EPE_RES_P14_L3_HDR_LEN_MASK 0x000003FF +#define EC_EPE_RES_P14_L3_HDR_LEN_SHIFT 0 + +/**** p15 register ****/ +/* Location of the L4 protocol index in the parser result vector ... */ +#define EC_EPE_RES_P15_L4_PROT_INDEX_MASK 0x000003FF +#define EC_EPE_RES_P15_L4_PROT_INDEX_SHIFT 0 + +/**** p16 register ****/ +/* Location of the L4 source port in the parser result vector */ +#define EC_EPE_RES_P16_L4_SRC_PORT_MASK 0x000003FF +#define EC_EPE_RES_P16_L4_SRC_PORT_SHIFT 0 + +/**** p17 register ****/ +/* Location of the L4 destination port in the parser result vect ... */ +#define EC_EPE_RES_P17_L4_DST_PORT_MASK 0x000003FF +#define EC_EPE_RES_P17_L4_DST_PORT_SHIFT 0 + +/**** p18 register ****/ +/* Location of the L4 offset in the parser result vector */ +#define EC_EPE_RES_P18_L4_OFFSET_MASK 0x000003FF +#define EC_EPE_RES_P18_L4_OFFSET_SHIFT 0 + +/**** p19 register ****/ +/* Location of the Ether type in the parser result vector when w ... */ +#define EC_EPE_RES_P19_WOL_ETYPE_MASK 0x000003FF +#define EC_EPE_RES_P19_WOL_ETYPE_SHIFT 0 + +/**** p20 register ****/ +/* Location of the RoCE QP number field in the parser result vec ... */ +#define EC_EPE_RES_P20_ROCE_QPN_MASK 0x000003FF +#define EC_EPE_RES_P20_ROCE_QPN_SHIFT 0 + +/**** hdr_len register ****/ +/* Value for selecting table 1 */ +#define EC_EPE_H_HDR_LEN_TABLE_1_MASK 0x000000FF +#define EC_EPE_H_HDR_LEN_TABLE_1_SHIFT 0 +/* Value for selecting table 2 */ +#define EC_EPE_H_HDR_LEN_TABLE_2_MASK 0x00FF0000 +#define EC_EPE_H_HDR_LEN_TABLE_2_SHIFT 16 + +/**** comp_data register ****/ +/* Data 1 for comparison */ +#define EC_EPE_P_COMP_DATA_DATA_1_MASK 0x0000FFFF +#define EC_EPE_P_COMP_DATA_DATA_1_SHIFT 0 +/* Data 2 for comparison +[18:16] - Stage +[24:19] - Branch ID */ +#define EC_EPE_P_COMP_DATA_DATA_2_MASK 0x01FF0000 +#define EC_EPE_P_COMP_DATA_DATA_2_SHIFT 16 + +/**** comp_mask register ****/ +/* Data 1 for comparison */ +#define EC_EPE_P_COMP_MASK_DATA_1_MASK 0x0000FFFF +#define EC_EPE_P_COMP_MASK_DATA_1_SHIFT 0 +/* Data 2 for comparison +[18:16] - Stage +[24:19] - Branch ID */ +#define EC_EPE_P_COMP_MASK_DATA_2_MASK 0x01FF0000 +#define EC_EPE_P_COMP_MASK_DATA_2_SHIFT 16 + +/**** comp_ctrl register ****/ +/* Output result value */ +#define EC_EPE_P_COMP_CTRL_RES_MASK 0x0000001F +#define EC_EPE_P_COMP_CTRL_RES_SHIFT 0 +/* Compare command for the data_1 field00 - Compare01 - <=10 - > ... */ +#define EC_EPE_P_COMP_CTRL_CMD_1_MASK 0x00030000 +#define EC_EPE_P_COMP_CTRL_CMD_1_SHIFT 16 +/* Compare command for the data_2 field 00 - Compare 01 - <= 10 ... */ +#define EC_EPE_P_COMP_CTRL_CMD_2_MASK 0x000C0000 +#define EC_EPE_P_COMP_CTRL_CMD_2_SHIFT 18 +/* Entry is valid */ +#define EC_EPE_P_COMP_CTRL_VALID (1 << 31) + +/**** prot_act register ****/ +/* Drop indication for the selected protocol index */ +#define EC_EPE_A_PROT_ACT_DROP (1 << 0) +/* Mapping value Used when mapping the entire protocol index ran ... */ +#define EC_EPE_A_PROT_ACT_MAP_MASK 0x00000F00 +#define EC_EPE_A_PROT_ACT_MAP_SHIFT 8 + +/**** thash_cfg_1 register ****/ +/* Hash function output selection:000 - [7:0]001 - [15:8]010 - [ ... */ +#define EC_RFW_THASH_CFG_1_OUT_SEL_MASK 0x00000007 +#define EC_RFW_THASH_CFG_1_OUT_SEL_SHIFT 0 +/* Selects between hash functions00 - toeplitz01 - CRC-3210 - 0x ... */ +#define EC_RFW_THASH_CFG_1_FUNC_SEL_MASK 0x00000300 +#define EC_RFW_THASH_CFG_1_FUNC_SEL_SHIFT 8 +/* Enable SIP/DIP swap if SIP= 5. */ +#define EC_RFW_LRO_CHECK_IPV4_IHL_1 (1 << 2) +/* Compare to previous packet. */ +#define EC_RFW_LRO_CHECK_IPV4_IHL_2 (1 << 3) +/* Compare DSCP to previous packet. */ +#define EC_RFW_LRO_CHECK_IPV4_DSCP (1 << 4) +/* Check that Total length >= lro_ipv4_tlen_val. */ +#define EC_RFW_LRO_CHECK_IPV4_TLEN (1 << 5) +/* Compare to previous packet value +1. */ +#define EC_RFW_LRO_CHECK_IPV4_ID (1 << 6) +/* Compare to lro_ipv4_flags_val with lro_ipv4_flags_mask_0. */ +#define EC_RFW_LRO_CHECK_IPV4_FLAGS_0 (1 << 7) +/* Compare to previous packet flags with lro_ipv4_flags_mask_1. */ +#define EC_RFW_LRO_CHECK_IPV4_FLAGS_1 (1 << 8) +/* Verify that the fragment offset field is 0. */ +#define EC_RFW_LRO_CHECK_IPV4_FRAG (1 << 9) +/* Verify that the TTL value >0. */ +#define EC_RFW_LRO_CHECK_IPV4_TTL_0 (1 << 10) +/* Compare TTL value to previous packet. */ +#define EC_RFW_LRO_CHECK_IPV4_TTL_1 (1 << 11) +/* Compare to previous packet protocol field. */ +#define EC_RFW_LRO_CHECK_IPV4_PROT_0 (1 << 12) +/* Verify that the protocol is TCP or UDP. */ +#define EC_RFW_LRO_CHECK_IPV4_PROT_1 (1 << 13) +/* Verify that the check sum is correct. */ +#define EC_RFW_LRO_CHECK_IPV4_CHECKSUM (1 << 14) +/* Compare SIP to previous packet. */ +#define EC_RFW_LRO_CHECK_IPV4_SIP (1 << 15) +/* Compare DIP to previous packet. */ +#define EC_RFW_LRO_CHECK_IPV4_DIP (1 << 16) + +/**** lro_ipv4 register ****/ +/* Total length minimum value */ +#define EC_RFW_LRO_IPV4_TLEN_VAL_MASK 0x0000FFFF +#define EC_RFW_LRO_IPV4_TLEN_VAL_SHIFT 0 +/* Flags value */ +#define EC_RFW_LRO_IPV4_FLAGS_VAL_MASK 0x00070000 +#define EC_RFW_LRO_IPV4_FLAGS_VAL_SHIFT 16 +/* Flags mask */ +#define EC_RFW_LRO_IPV4_FLAGS_MASK_0_MASK 0x00380000 +#define EC_RFW_LRO_IPV4_FLAGS_MASK_0_SHIFT 19 +/* Flags mask */ +#define EC_RFW_LRO_IPV4_FLAGS_MASK_1_MASK 0x01C00000 +#define EC_RFW_LRO_IPV4_FLAGS_MASK_1_SHIFT 22 +/* Version value */ +#define EC_RFW_LRO_IPV4_VER_MASK 0xF0000000 +#define EC_RFW_LRO_IPV4_VER_SHIFT 28 + +/**** lro_check_ipv6 register ****/ +/* Check version field */ +#define EC_RFW_LRO_CHECK_IPV6_VER (1 << 0) +/* Compare TC to previous packet. */ +#define EC_RFW_LRO_CHECK_IPV6_TC (1 << 1) +/* Compare flow label field to previous packet. */ +#define EC_RFW_LRO_CHECK_IPV6_FLOW (1 << 2) +/* Check that Total length >= lro_ipv6_pen_val. */ +#define EC_RFW_LRO_CHECK_IPV6_PLEN (1 << 3) +/* Compare to previous packet next header field. */ +#define EC_RFW_LRO_CHECK_IPV6_NEXT_0 (1 << 4) +/* Verify that the next header is TCP or UDP. */ +#define EC_RFW_LRO_CHECK_IPV6_NEXT_1 (1 << 5) +/* Verify that hop limit is >0. */ +#define EC_RFW_LRO_CHECK_IPV6_HOP_0 (1 << 6) +/* Compare hop limit to previous packet. */ +#define EC_RFW_LRO_CHECK_IPV6_HOP_1 (1 << 7) +/* Compare SIP to previous packet. */ +#define EC_RFW_LRO_CHECK_IPV6_SIP (1 << 8) +/* Compare DIP to previous packet. */ +#define EC_RFW_LRO_CHECK_IPV6_DIP (1 << 9) + +/**** lro_ipv6 register ****/ +/* Payload length minimum value */ +#define EC_RFW_LRO_IPV6_PLEN_VAL_MASK 0x0000FFFF +#define EC_RFW_LRO_IPV6_PLEN_VAL_SHIFT 0 +/* Version value */ +#define EC_RFW_LRO_IPV6_VER_MASK 0x0F000000 +#define EC_RFW_LRO_IPV6_VER_SHIFT 24 + +/**** lro_check_tcp register ****/ +/* Compare to previous packet. */ +#define EC_RFW_LRO_CHECK_TCP_SRC_PORT (1 << 0) +/* Compare to previous packet. */ +#define EC_RFW_LRO_CHECK_TCP_DST_PORT (1 << 1) +/* If (SYN == 1), don't check */ +#define EC_RFW_LRO_CHECK_TCP_SN (1 << 2) +/* Check data offset field == 5. */ +#define EC_RFW_LRO_CHECK_TCP_OFFSET_0 (1 << 3) +/* Check data offset field >= 5. */ +#define EC_RFW_LRO_CHECK_TCP_OFFSET_1 (1 << 4) +/* Compare to previous packet. */ +#define EC_RFW_LRO_CHECK_TCP_OFFSET_2 (1 << 5) +/* Compare reserved field to lro_tcp_res. */ +#define EC_RFW_LRO_CHECK_TCP_RES (1 << 6) +/* Compare to lro_tcp_ecn_val and lro_tcp_ecn_mask_0. */ +#define EC_RFW_LRO_CHECK_TCP_ECN_0 (1 << 7) +/* Compare to previous packet ECN field with lro_tcp_ecn_mask_1 */ +#define EC_RFW_LRO_CHECK_TCP_ECN_1 (1 << 8) +/* Compare to lro_tcp_ctrl_val and lro_tcp_ctrl_mask_0. */ +#define EC_RFW_LRO_CHECK_TCP_CTRL_0 (1 << 9) +/* Compare to previous packet ECN field with lro_tcp_ctrl_mask_1 */ +#define EC_RFW_LRO_CHECK_TCP_CTRL_1 (1 << 10) +/* Verify that check sum is correct. */ +#define EC_RFW_LRO_CHECK_TCP_CHECKSUM (1 << 11) + +/**** lro_tcp register ****/ +/* Reserved field default value */ +#define EC_RFW_LRO_TCP_RES_MASK 0x00000007 +#define EC_RFW_LRO_TCP_RES_SHIFT 0 +/* ECN field value */ +#define EC_RFW_LRO_TCP_ECN_VAL_MASK 0x00000038 +#define EC_RFW_LRO_TCP_ECN_VAL_SHIFT 3 +/* ECN field mask */ +#define EC_RFW_LRO_TCP_ECN_MASK_0_MASK 0x000001C0 +#define EC_RFW_LRO_TCP_ECN_MASK_0_SHIFT 6 +/* ECN field mask */ +#define EC_RFW_LRO_TCP_ECN_MASK_1_MASK 0x00000E00 +#define EC_RFW_LRO_TCP_ECN_MASK_1_SHIFT 9 +/* Control field value */ +#define EC_RFW_LRO_TCP_CTRL_VAL_MASK 0x0003F000 +#define EC_RFW_LRO_TCP_CTRL_VAL_SHIFT 12 +/* Control field mask */ +#define EC_RFW_LRO_TCP_CTRL_MASK_0_MASK 0x00FC0000 +#define EC_RFW_LRO_TCP_CTRL_MASK_0_SHIFT 18 +/* Control field mask */ +#define EC_RFW_LRO_TCP_CTRL_MASK_1_MASK 0x3F000000 +#define EC_RFW_LRO_TCP_CTRL_MASK_1_SHIFT 24 + +/**** lro_check_udp register ****/ +/* Compare to previous packet. */ +#define EC_RFW_LRO_CHECK_UDP_SRC_PORT (1 << 0) +/* Compare to previous packet. */ +#define EC_RFW_LRO_CHECK_UDP_DST_PORT (1 << 1) +/* Verify that check sum is correct. */ +#define EC_RFW_LRO_CHECK_UDP_CHECKSUM (1 << 2) + +/**** lro_check_l2 register ****/ +/* Compare to previous packet. */ +#define EC_RFW_LRO_CHECK_L2_MAC_DA (1 << 0) +/* Compare to previous packet. */ +#define EC_RFW_LRO_CHECK_L2_MAC_SA (1 << 1) +/* Compare to previous packet. */ +#define EC_RFW_LRO_CHECK_L2_VLAN_1_EXIST (1 << 2) +/* Compare to previous packet. */ +#define EC_RFW_LRO_CHECK_L2_VLAN_1_VID (1 << 3) +/* Compare to previous packet. */ +#define EC_RFW_LRO_CHECK_L2_VLAN_1_CFI (1 << 4) +/* Compare to previous packet. */ +#define EC_RFW_LRO_CHECK_L2_VLAN_1_PBITS (1 << 5) +/* Compare to previous packet. */ +#define EC_RFW_LRO_CHECK_L2_VLAN_2_EXIST (1 << 6) +/* Compare to previous packet. */ +#define EC_RFW_LRO_CHECK_L2_VLAN_2_VID (1 << 7) +/* Compare to previous packet. */ +#define EC_RFW_LRO_CHECK_L2_VLAN_2_CFI (1 << 8) +/* Compare to previous packet. */ +#define EC_RFW_LRO_CHECK_L2_VLAN_2_PBITS (1 << 9) +/* Verify that the FCS is correct. */ +#define EC_RFW_LRO_CHECK_L2_FCS (1 << 10) + +/**** lro_check_gen register ****/ +/* Compare to previous packet */ +#define EC_RFW_LRO_CHECK_GEN_UDMA (1 << 0) +/* Compare to previous packet */ +#define EC_RFW_LRO_CHECK_GEN_QUEUE (1 << 1) + +/**** lro_store register ****/ +/* Store packet information if protocol match. */ +#define EC_RFW_LRO_STORE_IPV4 (1 << 0) +/* Store packet information if protocol match. */ +#define EC_RFW_LRO_STORE_IPV6 (1 << 1) +/* Store packet information if protocol match. */ +#define EC_RFW_LRO_STORE_TCP (1 << 2) +/* Store packet information if protocol match. */ +#define EC_RFW_LRO_STORE_UDP (1 << 3) +/* Store packet if IPv4 flags match the register value with mask */ +#define EC_RFW_LRO_STORE_IPV4_FLAGS_VAL_MASK 0x00000070 +#define EC_RFW_LRO_STORE_IPV4_FLAGS_VAL_SHIFT 4 +/* Mask for IPv4 flags */ +#define EC_RFW_LRO_STORE_IPV4_FLAGS_MASK_MASK 0x00000380 +#define EC_RFW_LRO_STORE_IPV4_FLAGS_MASK_SHIFT 7 +/* Store packet if TCP control and ECN match the register value ... */ +#define EC_RFW_LRO_STORE_TCP_CTRL_VAL_MASK 0x0007FC00 +#define EC_RFW_LRO_STORE_TCP_CTRL_VAL_SHIFT 10 +/* Mask for TCP control */ +#define EC_RFW_LRO_STORE_TCP_CTRL_MASK_MASK 0x0FF80000 +#define EC_RFW_LRO_STORE_TCP_CTRL_MASK_SHIFT 19 + +/**** vid_table_def register ****/ +/* Table default data (valid only after configuring the table ad ... */ +#define EC_RFW_VID_TABLE_DEF_VAL_MASK 0x0000003F +#define EC_RFW_VID_TABLE_DEF_VAL_SHIFT 0 +/* Default data selection +0 - Default value +1 - Table data out */ +#define EC_RFW_VID_TABLE_DEF_SEL (1 << 6) + +/**** ctrl_table_def register ****/ +/* Control table output for selecting the forwarding MUXs [3:0] ... */ +#define EC_RFW_CTRL_TABLE_DEF_VAL_MASK 0x000FFFFF +#define EC_RFW_CTRL_TABLE_DEF_VAL_SHIFT 0 +/* Default data selection 0 - Default value 1 - Table data out ... */ +#define EC_RFW_CTRL_TABLE_DEF_SEL (1 << 20) + +/**** cfg_a_0 register ****/ +/* Selection of the L3 checksum result in the Metadata00 - L3 ch ... */ +#define EC_RFW_CFG_A_0_META_L3_CHK_RES_SEL_MASK 0x00000003 +#define EC_RFW_CFG_A_0_META_L3_CHK_RES_SEL_SHIFT 0 +/* Selection of the L4 checksum result in the Metadata0 - L4 che ... */ +#define EC_RFW_CFG_A_0_META_L4_CHK_RES_SEL (1 << 2) +/* Selection of the LRO_context_value result in the Metadata0 - ... */ +#define EC_RFW_CFG_A_0_LRO_CONTEXT_SEL (1 << 4) + +/**** thash_cfg_3 register ****/ +/* Enable Hash value for RoCE packets in outer packet. */ +#define EC_RFW_THASH_CFG_3_ENABLE_OUTER_ROCE (1 << 0) +/* Enable Hash value for RoCE packets in inner packet. */ +#define EC_RFW_THASH_CFG_3_ENABLE_INNER_ROCE (1 << 1) +/* Enable Hash value for FcoE packets in outer packet. */ +#define EC_RFW_THASH_CFG_3_ENABLE_OUTER_FCOE (1 << 2) +/* Enable Hash value for FcoE packets in inner packet. */ +#define EC_RFW_THASH_CFG_3_ENABLE_INNER_FCOE (1 << 3) + +/**** thash_mask_outer_ipv6 register ****/ +/* IPv6 source IP address */ +#define EC_RFW_THASH_MASK_OUTER_IPV6_SRC_MASK 0x0000FFFF +#define EC_RFW_THASH_MASK_OUTER_IPV6_SRC_SHIFT 0 +/* IPv6 destination IP address */ +#define EC_RFW_THASH_MASK_OUTER_IPV6_DST_MASK 0xFFFF0000 +#define EC_RFW_THASH_MASK_OUTER_IPV6_DST_SHIFT 16 + +/**** thash_mask_outer register ****/ +/* IPv4 source IP address */ +#define EC_RFW_THASH_MASK_OUTER_IPV4_SRC_MASK 0x0000000F +#define EC_RFW_THASH_MASK_OUTER_IPV4_SRC_SHIFT 0 +/* IPv4 destination IP address */ +#define EC_RFW_THASH_MASK_OUTER_IPV4_DST_MASK 0x000000F0 +#define EC_RFW_THASH_MASK_OUTER_IPV4_DST_SHIFT 4 +/* TCP source port */ +#define EC_RFW_THASH_MASK_OUTER_TCP_SRC_PORT_MASK 0x00000300 +#define EC_RFW_THASH_MASK_OUTER_TCP_SRC_PORT_SHIFT 8 +/* TCP destination port */ +#define EC_RFW_THASH_MASK_OUTER_TCP_DST_PORT_MASK 0x00000C00 +#define EC_RFW_THASH_MASK_OUTER_TCP_DST_PORT_SHIFT 10 +/* UDP source port */ +#define EC_RFW_THASH_MASK_OUTER_UDP_SRC_PORT_MASK 0x00003000 +#define EC_RFW_THASH_MASK_OUTER_UDP_SRC_PORT_SHIFT 12 +/* UDP destination port */ +#define EC_RFW_THASH_MASK_OUTER_UDP_DST_PORT_MASK 0x0000C000 +#define EC_RFW_THASH_MASK_OUTER_UDP_DST_PORT_SHIFT 14 + +/**** thash_mask_inner_ipv6 register ****/ +/* IPv6 source IP address */ +#define EC_RFW_THASH_MASK_INNER_IPV6_SRC_MASK 0x0000FFFF +#define EC_RFW_THASH_MASK_INNER_IPV6_SRC_SHIFT 0 +/* IPv6 destination IP address */ +#define EC_RFW_THASH_MASK_INNER_IPV6_DST_MASK 0xFFFF0000 +#define EC_RFW_THASH_MASK_INNER_IPV6_DST_SHIFT 16 + +/**** thash_mask_inner register ****/ +/* IPv4 source IP address */ +#define EC_RFW_THASH_MASK_INNER_IPV4_SRC_MASK 0x0000000F +#define EC_RFW_THASH_MASK_INNER_IPV4_SRC_SHIFT 0 +/* IPv4 destination IP address */ +#define EC_RFW_THASH_MASK_INNER_IPV4_DST_MASK 0x000000F0 +#define EC_RFW_THASH_MASK_INNER_IPV4_DST_SHIFT 4 +/* TCP source port */ +#define EC_RFW_THASH_MASK_INNER_TCP_SRC_PORT_MASK 0x00000300 +#define EC_RFW_THASH_MASK_INNER_TCP_SRC_PORT_SHIFT 8 +/* TCP destination port */ +#define EC_RFW_THASH_MASK_INNER_TCP_DST_PORT_MASK 0x00000C00 +#define EC_RFW_THASH_MASK_INNER_TCP_DST_PORT_SHIFT 10 +/* UDP source port */ +#define EC_RFW_THASH_MASK_INNER_UDP_SRC_PORT_MASK 0x00003000 +#define EC_RFW_THASH_MASK_INNER_UDP_SRC_PORT_SHIFT 12 +/* UDP destination port */ +#define EC_RFW_THASH_MASK_INNER_UDP_DST_PORT_MASK 0x0000C000 +#define EC_RFW_THASH_MASK_INNER_UDP_DST_PORT_SHIFT 14 + +/**** def_cfg register ****/ +/* Number of padding bytes to add at the beginning of each Ether ... */ +#define EC_RFW_UDMA_DEF_CFG_RX_PAD_MASK 0x0000003F +#define EC_RFW_UDMA_DEF_CFG_RX_PAD_SHIFT 0 + +/**** queue register ****/ +/* Mapping between priority and queue number */ +#define EC_RFW_PRIORITY_QUEUE_MAP_MASK 0x00000003 +#define EC_RFW_PRIORITY_QUEUE_MAP_SHIFT 0 + +/**** opt_1 register ****/ +/* Default UDMA for forwarding */ +#define EC_RFW_DEFAULT_OPT_1_UDMA_MASK 0x0000000F +#define EC_RFW_DEFAULT_OPT_1_UDMA_SHIFT 0 +/* Default priority for forwarding */ +#define EC_RFW_DEFAULT_OPT_1_PRIORITY_MASK 0x00000700 +#define EC_RFW_DEFAULT_OPT_1_PRIORITY_SHIFT 8 +/* Default queue for forwarding */ +#define EC_RFW_DEFAULT_OPT_1_QUEUE_MASK 0x00030000 +#define EC_RFW_DEFAULT_OPT_1_QUEUE_SHIFT 16 + +/**** data_h register ****/ +/* MAC address data */ +#define EC_FWD_MAC_DATA_H_VAL_MASK 0x0000FFFF +#define EC_FWD_MAC_DATA_H_VAL_SHIFT 0 + +/**** mask_h register ****/ +/* MAC address mask */ +#define EC_FWD_MAC_MASK_H_VAL_MASK 0x0000FFFF +#define EC_FWD_MAC_MASK_H_VAL_SHIFT 0 + +/**** ctrl register ****/ +/* Control value for Rx forwarding engine[0] - Drop indication[2 ... */ +#define EC_FWD_MAC_CTRL_RX_VAL_MASK 0x000001FF +#define EC_FWD_MAC_CTRL_RX_VAL_SHIFT 0 + +/* Drop indication */ +#define EC_FWD_MAC_CTRL_RX_VAL_DROP (1 << 0) + +/* control table command input */ +#define EC_FWD_MAC_CTRL_RX_VAL_CTRL_CMD_MASK 0x00000006 +#define EC_FWD_MAC_CTRL_RX_VAL_CTRL_CMD_SHIFT 1 + +/* UDMA selection */ +#define EC_FWD_MAC_CTRL_RX_VAL_UDMA_MASK 0x000000078 +#define EC_FWD_MAC_CTRL_RX_VAL_UDMA_SHIFT 3 + +/* queue number */ +#define EC_FWD_MAC_CTRL_RX_VAL_QID_MASK 0x00000180 +#define EC_FWD_MAC_CTRL_RX_VAL_QID_SHIFT 7 + +/* Entry is valid for Rx forwarding engine. */ +#define EC_FWD_MAC_CTRL_RX_VALID (1 << 15) +/* Control value for Tx forwarding engine */ +#define EC_FWD_MAC_CTRL_TX_VAL_MASK 0x001F0000 +#define EC_FWD_MAC_CTRL_TX_VAL_SHIFT 16 +/* Entry is valid for Tx forwarding engine. */ +#define EC_FWD_MAC_CTRL_TX_VALID (1 << 31) + +/**** uc register ****/ +/* timer max value for waiting for a stream to be ready to accep ... */ +#define EC_MSW_UC_TIMER_MASK 0x0000FFFF +#define EC_MSW_UC_TIMER_SHIFT 0 +/* Drop packet if target queue in the UDMA is full */ +#define EC_MSW_UC_Q_FULL_DROP_MASK 0x000F0000 +#define EC_MSW_UC_Q_FULL_DROP_SHIFT 16 +/* Drop packet if timer expires. */ +#define EC_MSW_UC_TIMER_DROP_MASK 0x0F000000 +#define EC_MSW_UC_TIMER_DROP_SHIFT 24 + +/**** mc register ****/ +/* Timer max value for waiting for a stream to be ready to accep ... */ +#define EC_MSW_MC_TIMER_MASK 0x0000FFFF +#define EC_MSW_MC_TIMER_SHIFT 0 +/* Drop packet if target queue in UDMA is full. */ +#define EC_MSW_MC_Q_FULL_DROP_MASK 0x000F0000 +#define EC_MSW_MC_Q_FULL_DROP_SHIFT 16 +/* Drop packet if timer expires. */ +#define EC_MSW_MC_TIMER_DROP_MASK 0x0F000000 +#define EC_MSW_MC_TIMER_DROP_SHIFT 24 + +/**** bc register ****/ +/* Timer max value for waiting for a stream to be ready to accep ... */ +#define EC_MSW_BC_TIMER_MASK 0x0000FFFF +#define EC_MSW_BC_TIMER_SHIFT 0 +/* Drop packet if target queue in UDMA is full. */ +#define EC_MSW_BC_Q_FULL_DROP_MASK 0x000F0000 +#define EC_MSW_BC_Q_FULL_DROP_SHIFT 16 +/* Drop packet if timer expires. */ +#define EC_MSW_BC_TIMER_DROP_MASK 0x0F000000 +#define EC_MSW_BC_TIMER_DROP_SHIFT 24 + +/**** in_cfg register ****/ +/* Swap input bytes order */ +#define EC_TSO_IN_CFG_SWAP_BYTES (1 << 0) +/* Selects strict priority or round robin scheduling between GDM ... */ +#define EC_TSO_IN_CFG_SEL_SP_RR (1 << 1) +/* Selects scheduler numbering direction */ +#define EC_TSO_IN_CFG_SEL_SCH_DIR (1 << 2) +/* Minimum L2 packet size (not including FCS) */ +#define EC_TSO_IN_CFG_L2_MIN_SIZE_MASK 0x00007F00 +#define EC_TSO_IN_CFG_L2_MIN_SIZE_SHIFT 8 +/* Swap input bytes order */ +#define EC_TSO_IN_CFG_SP_INIT_VAL_MASK 0x000F0000 +#define EC_TSO_IN_CFG_SP_INIT_VAL_SHIFT 16 + +/**** cache_table_addr register ****/ +/* Address for accessing the table */ +#define EC_TSO_CACHE_TABLE_ADDR_VAL_MASK 0x0000000F +#define EC_TSO_CACHE_TABLE_ADDR_VAL_SHIFT 0 + +/**** ctrl_first register ****/ +/* Data to be written into the control BIS. */ +#define EC_TSO_CTRL_FIRST_DATA_MASK 0x000001FF +#define EC_TSO_CTRL_FIRST_DATA_SHIFT 0 +/* Mask for control bits */ +#define EC_TSO_CTRL_FIRST_MASK_MASK 0x01FF0000 +#define EC_TSO_CTRL_FIRST_MASK_SHIFT 16 + +/**** ctrl_middle register ****/ +/* Data to be written into the control BIS. */ +#define EC_TSO_CTRL_MIDDLE_DATA_MASK 0x000001FF +#define EC_TSO_CTRL_MIDDLE_DATA_SHIFT 0 +/* Mask for the control bits */ +#define EC_TSO_CTRL_MIDDLE_MASK_MASK 0x01FF0000 +#define EC_TSO_CTRL_MIDDLE_MASK_SHIFT 16 + +/**** ctrl_last register ****/ +/* Data to be written into the control BIS. */ +#define EC_TSO_CTRL_LAST_DATA_MASK 0x000001FF +#define EC_TSO_CTRL_LAST_DATA_SHIFT 0 +/* Mask for the control bits */ +#define EC_TSO_CTRL_LAST_MASK_MASK 0x01FF0000 +#define EC_TSO_CTRL_LAST_MASK_SHIFT 16 + +/**** cfg_add_0 register ****/ +/* MSS selection option:0 - MSS value is selected using MSS_sel ... */ +#define EC_TSO_CFG_ADD_0_MSS_SEL (1 << 0) + +/**** cfg_tunnel register ****/ +/* Enable TSO with tunnelling */ +#define EC_TSO_CFG_TUNNEL_EN_TUNNEL_TSO (1 << 0) +/* Enable outer UDP checksum update */ +#define EC_TSO_CFG_TUNNEL_EN_UDP_CHKSUM (1 << 8) +/* Enable outer UDP length update */ +#define EC_TSO_CFG_TUNNEL_EN_UDP_LEN (1 << 9) +/* Enable outer Ip6 length update */ +#define EC_TSO_CFG_TUNNEL_EN_IPV6_PLEN (1 << 10) +/* Enable outer IPv4 checksum update */ +#define EC_TSO_CFG_TUNNEL_EN_IPV4_CHKSUM (1 << 11) +/* Enable outer IPv4 Identification update */ +#define EC_TSO_CFG_TUNNEL_EN_IPV4_IDEN (1 << 12) +/* Enable outer IPv4 length update */ +#define EC_TSO_CFG_TUNNEL_EN_IPV4_TLEN (1 << 13) + +/**** mss register ****/ +/* MSS value */ +#define EC_TSO_SEL_MSS_VAL_MASK 0x000FFFFF +#define EC_TSO_SEL_MSS_VAL_SHIFT 0 + +/**** parse register ****/ +/* Max number of bus beats for parsing */ +#define EC_TPE_PARSE_MAX_BEATS_MASK 0x0000FFFF +#define EC_TPE_PARSE_MAX_BEATS_SHIFT 0 + +/**** vlan_data register ****/ +/* UDMA default VLAN 1 data */ +#define EC_TPM_UDMA_VLAN_DATA_DEF_1_MASK 0x0000FFFF +#define EC_TPM_UDMA_VLAN_DATA_DEF_1_SHIFT 0 +/* UDMA default VLAN 2 data */ +#define EC_TPM_UDMA_VLAN_DATA_DEF_2_MASK 0xFFFF0000 +#define EC_TPM_UDMA_VLAN_DATA_DEF_2_SHIFT 16 + +/**** mac_sa_2 register ****/ +/* MAC source address data [47:32] */ +#define EC_TPM_UDMA_MAC_SA_2_H_VAL_MASK 0x0000FFFF +#define EC_TPM_UDMA_MAC_SA_2_H_VAL_SHIFT 0 +/* Drop indication for MAC SA spoofing0 – Don't drop */ +#define EC_TPM_UDMA_MAC_SA_2_DROP (1 << 16) +/* Replace indication for MAC SA spoofing 0 - Don't replace */ +#define EC_TPM_UDMA_MAC_SA_2_REPLACE (1 << 17) + +/**** etype register ****/ +/* Ether type value */ +#define EC_TPM_SEL_ETYPE_VAL_MASK 0x0000FFFF +#define EC_TPM_SEL_ETYPE_VAL_SHIFT 0 + +/**** tx_wr_fifo register ****/ +/* Max data beats that can be used in the Tx FIFO */ +#define EC_TFW_TX_WR_FIFO_DATA_TH_MASK 0x0000FFFF +#define EC_TFW_TX_WR_FIFO_DATA_TH_SHIFT 0 +/* Max packets that can be stored in the Tx FIFO */ +#define EC_TFW_TX_WR_FIFO_INFO_TH_MASK 0xFFFF0000 +#define EC_TFW_TX_WR_FIFO_INFO_TH_SHIFT 16 + +/**** tx_vid_table_addr register ****/ +/* Address for accessing the table */ +#define EC_TFW_TX_VID_TABLE_ADDR_VAL_MASK 0x00000FFF +#define EC_TFW_TX_VID_TABLE_ADDR_VAL_SHIFT 0 + +/**** tx_vid_table_data register ****/ +/* Table data (valid only after configuring the table address re ... */ +#define EC_TFW_TX_VID_TABLE_DATA_VAL_MASK 0x0000001F +#define EC_TFW_TX_VID_TABLE_DATA_VAL_SHIFT 0 + +/**** tx_rd_fifo register ****/ +/* Read data threshold when cut through mode is enabled. */ +#define EC_TFW_TX_RD_FIFO_READ_TH_MASK 0x0000FFFF +#define EC_TFW_TX_RD_FIFO_READ_TH_SHIFT 0 +/* Enable cut through operation of the Tx FIFO. */ +#define EC_TFW_TX_RD_FIFO_EN_CUT_THROUGH (1 << 16) + +/**** tx_checksum register ****/ +/* Enable L3 checksum insertion. */ +#define EC_TFW_TX_CHECKSUM_L3_EN (1 << 0) +/* Enable L4 checksum insertion. */ +#define EC_TFW_TX_CHECKSUM_L4_EN (1 << 1) +/* Enable L4 checksum when L3 fragmentation is detected. */ +#define EC_TFW_TX_CHECKSUM_L4_FRAG_EN (1 << 2) + +/**** tx_gen register ****/ +/* Force forward of all Tx packets to MAC. */ +#define EC_TFW_TX_GEN_FWD_ALL_TO_MAC (1 << 0) +/* Select the Packet generator as the source of Tx packets0 - Tx ... */ +#define EC_TFW_TX_GEN_SELECT_PKT_GEN (1 << 1) + +/**** tx_spf register ****/ +/* Select the VID for spoofing check:[0] - Packet VID[1] - Forwa ... */ +#define EC_TFW_TX_SPF_VID_SEL (1 << 0) + +/**** data_fifo register ****/ +/* FIFO used value (number of entries) */ +#define EC_TFW_DATA_FIFO_USED_MASK 0x0000FFFF +#define EC_TFW_DATA_FIFO_USED_SHIFT 0 +/* FIFO FULL status */ +#define EC_TFW_DATA_FIFO_FULL (1 << 16) +/* FIFO EMPTY status */ +#define EC_TFW_DATA_FIFO_EMPTY (1 << 17) + +/**** ctrl_fifo register ****/ +/* FIFO used value (number of entries) */ +#define EC_TFW_CTRL_FIFO_USED_MASK 0x0000FFFF +#define EC_TFW_CTRL_FIFO_USED_SHIFT 0 +/* FIFO FULL status */ +#define EC_TFW_CTRL_FIFO_FULL (1 << 16) +/* FIFO EMPTY status */ +#define EC_TFW_CTRL_FIFO_EMPTY (1 << 17) + +/**** hdr_fifo register ****/ +/* FIFO used value (number of entries) */ +#define EC_TFW_HDR_FIFO_USED_MASK 0x0000FFFF +#define EC_TFW_HDR_FIFO_USED_SHIFT 0 +/* FIFO FULL status */ +#define EC_TFW_HDR_FIFO_FULL (1 << 16) +/* FIFO EMPTY status */ +#define EC_TFW_HDR_FIFO_EMPTY (1 << 17) + +/**** uc_udma register ****/ +/* Default UDMA bitmap +(MSB represents physical port) */ +#define EC_TFW_UDMA_UC_UDMA_DEF_MASK 0x0000001F +#define EC_TFW_UDMA_UC_UDMA_DEF_SHIFT 0 + +/**** mc_udma register ****/ +/* Default UDMA bitmap (MSB represents physical port.) */ +#define EC_TFW_UDMA_MC_UDMA_DEF_MASK 0x0000001F +#define EC_TFW_UDMA_MC_UDMA_DEF_SHIFT 0 + +/**** bc_udma register ****/ +/* Default UDMA bitmap (MSB represents physical port.) */ +#define EC_TFW_UDMA_BC_UDMA_DEF_MASK 0x0000001F +#define EC_TFW_UDMA_BC_UDMA_DEF_SHIFT 0 + +/**** spf_cmd register ****/ +/* Command for the VLAN spoofing00 – Ignore mismatch */ +#define EC_TFW_UDMA_SPF_CMD_VID_MASK 0x00000003 +#define EC_TFW_UDMA_SPF_CMD_VID_SHIFT 0 +/* Command for VLAN spoofing 00 - Ignore mismatch */ +#define EC_TFW_UDMA_SPF_CMD_MAC_MASK 0x0000000C +#define EC_TFW_UDMA_SPF_CMD_MAC_SHIFT 2 + +/**** fwd_dec register ****/ +/* Forwarding decision control:[0] – Enable internal switch */ +#define EC_TFW_UDMA_FWD_DEC_CTRL_MASK 0x000003FF +#define EC_TFW_UDMA_FWD_DEC_CTRL_SHIFT 0 + +/**** tx_cfg register ****/ +/* Swap output byte order */ +#define EC_TMI_TX_CFG_SWAP_BYTES (1 << 0) +/* Enable forwarding to the Rx data path. */ +#define EC_TMI_TX_CFG_EN_FWD_TO_RX (1 << 1) +/* Force forwarding all packets to the MAC. */ +#define EC_TMI_TX_CFG_FORCE_FWD_MAC (1 << 2) +/* Force forwarding all packets to the MAC. */ +#define EC_TMI_TX_CFG_FORCE_FWD_RX (1 << 3) +/* Force loop back operation */ +#define EC_TMI_TX_CFG_FORCE_LB (1 << 4) + +/**** ec_pause register ****/ +/* Mask of pause_on [7:0] */ +#define EC_EFC_EC_PAUSE_MASK_MAC_MASK 0x000000FF +#define EC_EFC_EC_PAUSE_MASK_MAC_SHIFT 0 +/* Mask of GPIO input [7:0] */ +#define EC_EFC_EC_PAUSE_MASK_GPIO_MASK 0x0000FF00 +#define EC_EFC_EC_PAUSE_MASK_GPIO_SHIFT 8 + +/**** ec_xoff register ****/ +/* Mask 1 for XOFF [7:0] +Mask 1 for Almost Full indication, */ +#define EC_EFC_EC_XOFF_MASK_1_MASK 0x000000FF +#define EC_EFC_EC_XOFF_MASK_1_SHIFT 0 +/* Mask 2 for XOFF [7:0] Mask 2 for sampled Almost Full indicati ... */ +#define EC_EFC_EC_XOFF_MASK_2_MASK 0x0000FF00 +#define EC_EFC_EC_XOFF_MASK_2_SHIFT 8 + +/**** xon register ****/ +/* Mask 1 for generating XON pulse, masking XOFF [0] */ +#define EC_EFC_XON_MASK_1 (1 << 0) +/* Mask 2 for generating XON pulse, masking Almost Full indicati ... */ +#define EC_EFC_XON_MASK_2 (1 << 1) + +/**** gpio register ****/ +/* Mask for generating GPIO output XOFF indication from XOFF[0] */ +#define EC_EFC_GPIO_MASK_1 (1 << 0) + +/**** rx_fifo_af register ****/ +/* Threshold */ +#define EC_EFC_RX_FIFO_AF_TH_MASK 0x0000FFFF +#define EC_EFC_RX_FIFO_AF_TH_SHIFT 0 + +/**** rx_fifo_hyst register ****/ +/* Threshold low */ +#define EC_EFC_RX_FIFO_HYST_TH_LOW_MASK 0x0000FFFF +#define EC_EFC_RX_FIFO_HYST_TH_LOW_SHIFT 0 +/* Threshold high */ +#define EC_EFC_RX_FIFO_HYST_TH_HIGH_MASK 0xFFFF0000 +#define EC_EFC_RX_FIFO_HYST_TH_HIGH_SHIFT 16 + +/**** stat register ****/ +/* 10G MAC PFC mode, input from the 10 MAC */ +#define EC_EFC_STAT_PFC_MODE (1 << 0) + +/**** ec_pfc register ****/ +/* Force PFC flow control */ +#define EC_EFC_EC_PFC_FORCE_MASK 0x000000FF +#define EC_EFC_EC_PFC_FORCE_SHIFT 0 + +/**** q_pause_0 register ****/ +/* [i] – Mask for Q[i] */ +#define EC_FC_UDMA_Q_PAUSE_0_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_PAUSE_0_MASK_SHIFT 0 + +/**** q_pause_1 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_PAUSE_1_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_PAUSE_1_MASK_SHIFT 0 + +/**** q_pause_2 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_PAUSE_2_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_PAUSE_2_MASK_SHIFT 0 + +/**** q_pause_3 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_PAUSE_3_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_PAUSE_3_MASK_SHIFT 0 + +/**** q_pause_4 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_PAUSE_4_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_PAUSE_4_MASK_SHIFT 0 + +/**** q_pause_5 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_PAUSE_5_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_PAUSE_5_MASK_SHIFT 0 + +/**** q_pause_6 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_PAUSE_6_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_PAUSE_6_MASK_SHIFT 0 + +/**** q_pause_7 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_PAUSE_7_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_PAUSE_7_MASK_SHIFT 0 + +/**** q_gpio_0 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_GPIO_0_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_GPIO_0_MASK_SHIFT 0 + +/**** q_gpio_1 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_GPIO_1_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_GPIO_1_MASK_SHIFT 0 + +/**** q_gpio_2 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_GPIO_2_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_GPIO_2_MASK_SHIFT 0 + +/**** q_gpio_3 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_GPIO_3_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_GPIO_3_MASK_SHIFT 0 + +/**** q_gpio_4 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_GPIO_4_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_GPIO_4_MASK_SHIFT 0 + +/**** q_gpio_5 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_GPIO_5_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_GPIO_5_MASK_SHIFT 0 + +/**** q_gpio_6 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_GPIO_6_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_GPIO_6_MASK_SHIFT 0 + +/**** q_gpio_7 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_GPIO_7_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_GPIO_7_MASK_SHIFT 0 + +/**** s_pause register ****/ +/* Mask of pause_on [7:0] */ +#define EC_FC_UDMA_S_PAUSE_MASK_MAC_MASK 0x000000FF +#define EC_FC_UDMA_S_PAUSE_MASK_MAC_SHIFT 0 +/* Mask of GPIO input [7:0] */ +#define EC_FC_UDMA_S_PAUSE_MASK_GPIO_MASK 0x0000FF00 +#define EC_FC_UDMA_S_PAUSE_MASK_GPIO_SHIFT 8 + +/**** q_xoff_0 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_XOFF_0_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_XOFF_0_MASK_SHIFT 0 + +/**** q_xoff_1 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_XOFF_1_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_XOFF_1_MASK_SHIFT 0 + +/**** q_xoff_2 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_XOFF_2_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_XOFF_2_MASK_SHIFT 0 + +/**** q_xoff_3 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_XOFF_3_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_XOFF_3_MASK_SHIFT 0 + +/**** q_xoff_4 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_XOFF_4_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_XOFF_4_MASK_SHIFT 0 + +/**** q_xoff_5 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_XOFF_5_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_XOFF_5_MASK_SHIFT 0 + +/**** q_xoff_6 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_XOFF_6_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_XOFF_6_MASK_SHIFT 0 + +/**** q_xoff_7 register ****/ +/* [i] - Mask for Q[i] */ +#define EC_FC_UDMA_Q_XOFF_7_MASK_MASK 0x0000000F +#define EC_FC_UDMA_Q_XOFF_7_MASK_SHIFT 0 + +/**** cfg_e register ****/ +/* Use MAC Tx FIFO empty status for EEE control. */ +#define EC_EEE_CFG_E_USE_MAC_TX_FIFO (1 << 0) +/* Use MAC Rx FIFO empty status for EEE control. */ +#define EC_EEE_CFG_E_USE_MAC_RX_FIFO (1 << 1) +/* Use Ethernet controller Tx FIFO empty status for EEE control */ +#define EC_EEE_CFG_E_USE_EC_TX_FIFO (1 << 2) +/* Use Ethernet controller Rx FIFO empty status for EEE control */ +#define EC_EEE_CFG_E_USE_EC_RX_FIFO (1 << 3) +/* Enable Low power signalling. */ +#define EC_EEE_CFG_E_ENABLE (1 << 4) +/* Mask output to MAC. */ +#define EC_EEE_CFG_E_MASK_MAC_EEE (1 << 8) +/* Mask output to stop MAC interface. */ +#define EC_EEE_CFG_E_MASK_EC_TMI_STOP (1 << 9) + +/**** stat_eee register ****/ +/* EEE state */ +#define EC_EEE_STAT_EEE_STATE_MASK 0x0000000F +#define EC_EEE_STAT_EEE_STATE_SHIFT 0 +/* EEE detected */ +#define EC_EEE_STAT_EEE_DET (1 << 4) + +/**** p_parse_cfg register ****/ +/* MAX number of beats for packet parsing */ +#define EC_MSP_P_PARSE_CFG_MAX_BEATS_MASK 0x000000FF +#define EC_MSP_P_PARSE_CFG_MAX_BEATS_SHIFT 0 +/* MAX number of parsing iterations for packet parsing */ +#define EC_MSP_P_PARSE_CFG_MAX_ITER_MASK 0x0000FF00 +#define EC_MSP_P_PARSE_CFG_MAX_ITER_SHIFT 8 + +/**** p_act_table_addr register ****/ +/* Address for accessing the table */ +#define EC_MSP_P_ACT_TABLE_ADDR_VAL_MASK 0x0000001F +#define EC_MSP_P_ACT_TABLE_ADDR_VAL_SHIFT 0 + +/**** p_act_table_data_1 register ****/ +/* Table data[5:0] - Offset to next protocol [bytes] [6] - Next ... */ +#define EC_MSP_P_ACT_TABLE_DATA_1_VAL_MASK 0x03FFFFFF +#define EC_MSP_P_ACT_TABLE_DATA_1_VAL_SHIFT 0 + +/**** p_act_table_data_2 register ****/ +/* Table data [8:0] - Offset to data in the packet [bits][17:9] ... */ +#define EC_MSP_P_ACT_TABLE_DATA_2_VAL_MASK 0x1FFFFFFF +#define EC_MSP_P_ACT_TABLE_DATA_2_VAL_SHIFT 0 + +/**** p_act_table_data_3 register ****/ +/* Table data [8:0] - Offset to data in the packet [bits] [17 ... */ +#define EC_MSP_P_ACT_TABLE_DATA_3_VAL_MASK 0x1FFFFFFF +#define EC_MSP_P_ACT_TABLE_DATA_3_VAL_SHIFT 0 + +/**** p_act_table_data_4 register ****/ +/* Table data [7:0] - Offset to the header length location in th ... */ +#define EC_MSP_P_ACT_TABLE_DATA_4_VAL_MASK 0x0FFFFFFF +#define EC_MSP_P_ACT_TABLE_DATA_4_VAL_SHIFT 0 + +/**** p_act_table_data_6 register ****/ +/* Table data [0] - Wr header length [10:1] - Write header lengt ... */ +#define EC_MSP_P_ACT_TABLE_DATA_6_VAL_MASK 0x007FFFFF +#define EC_MSP_P_ACT_TABLE_DATA_6_VAL_SHIFT 0 + +/**** p_res_in register ****/ +/* Selector for input parse_en 0 - Input vector 1 - Default valu ... */ +#define EC_MSP_P_RES_IN_SEL_PARSE_EN (1 << 0) +/* Selector for input protocol_index 0 - Input vector 1 - Defa ... */ +#define EC_MSP_P_RES_IN_SEL_PROT_INDEX (1 << 1) +/* Selector for input hdr_offset 0 - Input vector 1 - Default v ... */ +#define EC_MSP_P_RES_IN_SEL_HDR_OFFSET (1 << 2) + +/**** h_hdr_len register ****/ +/* Value for selecting table 1 */ +#define EC_MSP_P_H_HDR_LEN_TABLE_1_MASK 0x000000FF +#define EC_MSP_P_H_HDR_LEN_TABLE_1_SHIFT 0 +/* Value for selecting table 2 */ +#define EC_MSP_P_H_HDR_LEN_TABLE_2_MASK 0x00FF0000 +#define EC_MSP_P_H_HDR_LEN_TABLE_2_SHIFT 16 + +/**** p_comp_data register ****/ +/* Data 1 for comparison */ +#define EC_MSP_C_P_COMP_DATA_DATA_1_MASK 0x0000FFFF +#define EC_MSP_C_P_COMP_DATA_DATA_1_SHIFT 0 +/* Data 2 for comparison +[18:16] - Stage +[24:19] - Branch ID */ +#define EC_MSP_C_P_COMP_DATA_DATA_2_MASK 0x01FF0000 +#define EC_MSP_C_P_COMP_DATA_DATA_2_SHIFT 16 + +/**** p_comp_mask register ****/ +/* Data 1 for comparison */ +#define EC_MSP_C_P_COMP_MASK_DATA_1_MASK 0x0000FFFF +#define EC_MSP_C_P_COMP_MASK_DATA_1_SHIFT 0 +/* Data 2 for comparison +[18:16] - Stage +[24:19] - Branch ID */ +#define EC_MSP_C_P_COMP_MASK_DATA_2_MASK 0x01FF0000 +#define EC_MSP_C_P_COMP_MASK_DATA_2_SHIFT 16 + +/**** p_comp_ctrl register ****/ +/* Output result value */ +#define EC_MSP_C_P_COMP_CTRL_RES_MASK 0x0000001F +#define EC_MSP_C_P_COMP_CTRL_RES_SHIFT 0 +/* Compare command for the data_1 field 00 - Compare 01 - <= 10 ... */ +#define EC_MSP_C_P_COMP_CTRL_CMD_1_MASK 0x00030000 +#define EC_MSP_C_P_COMP_CTRL_CMD_1_SHIFT 16 +/* Compare command for the data_2 field 00 - Compare 01 - <= 10 ... */ +#define EC_MSP_C_P_COMP_CTRL_CMD_2_MASK 0x000C0000 +#define EC_MSP_C_P_COMP_CTRL_CMD_2_SHIFT 18 +/* Entry is valid */ +#define EC_MSP_C_P_COMP_CTRL_VALID (1 << 31) + +/**** wol_en register ****/ +/* Interrupt enable WoL MAC DA Unicast detected packet */ +#define EC_WOL_WOL_EN_INTRPT_EN_UNICAST (1 << 0) +/* Interrupt enable WoL L2 Multicast detected packet */ +#define EC_WOL_WOL_EN_INTRPT_EN_MULTICAST (1 << 1) +/* Interrupt enable WoL L2 Broadcast detected packet */ +#define EC_WOL_WOL_EN_INTRPT_EN_BROADCAST (1 << 2) +/* Interrupt enable WoL IPv4 detected packet */ +#define EC_WOL_WOL_EN_INTRPT_EN_IPV4 (1 << 3) +/* Interrupt enable WoL IPv6 detected packet */ +#define EC_WOL_WOL_EN_INTRPT_EN_IPV6 (1 << 4) +/* Interrupt enable WoL EtherType+MAC DA detected packet */ +#define EC_WOL_WOL_EN_INTRPT_EN_ETHERTYPE_DA (1 << 5) +/* Interrupt enable WoL EtherType+L2 Broadcast detected packet */ +#define EC_WOL_WOL_EN_INTRPT_EN_ETHERTYPE_BC (1 << 6) +/* Interrupt enable WoL parser detected packet */ +#define EC_WOL_WOL_EN_INTRPT_EN_PARSER (1 << 7) +/* Interrupt enable WoL magic detected packet */ +#define EC_WOL_WOL_EN_INTRPT_EN_MAGIC (1 << 8) +/* Interrupt enable WoL magic+password detected packet */ +#define EC_WOL_WOL_EN_INTRPT_EN_MAGIC_PSWD (1 << 9) +/* Forward enable WoL MAC DA Unicast detected packet */ +#define EC_WOL_WOL_EN_FWRD_EN_UNICAST (1 << 16) +/* Forward enable WoL L2 Multicast detected packet */ +#define EC_WOL_WOL_EN_FWRD_EN_MULTICAST (1 << 17) +/* Forward enable WoL L2 Broadcast detected packet */ +#define EC_WOL_WOL_EN_FWRD_EN_BROADCAST (1 << 18) +/* Forward enable WoL IPv4 detected packet */ +#define EC_WOL_WOL_EN_FWRD_EN_IPV4 (1 << 19) +/* Forward enable WoL IPv6 detected packet */ +#define EC_WOL_WOL_EN_FWRD_EN_IPV6 (1 << 20) +/* Forward enable WoL EtherType+MAC DA detected packet */ +#define EC_WOL_WOL_EN_FWRD_EN_ETHERTYPE_DA (1 << 21) +/* Forward enable WoL EtherType+L2 Broadcast detected packet */ +#define EC_WOL_WOL_EN_FWRD_EN_ETHERTYPE_BC (1 << 22) +/* Forward enable WoL parser detected packet */ +#define EC_WOL_WOL_EN_FWRD_EN_PARSER (1 << 23) + +/**** magic_pswd_h register ****/ +/* Password for magic_password packet detection - bits 47:32 */ +#define EC_WOL_MAGIC_PSWD_H_VAL_MASK 0x0000FFFF +#define EC_WOL_MAGIC_PSWD_H_VAL_SHIFT 0 + +/**** ethertype register ****/ +/* Configured EtherType 1 for WoL EtherType_da/EtherType_bc pack ... */ +#define EC_WOL_ETHERTYPE_VAL_1_MASK 0x0000FFFF +#define EC_WOL_ETHERTYPE_VAL_1_SHIFT 0 +/* Configured EtherType 2 for WoL EtherType_da/EtherType_bc pack ... */ +#define EC_WOL_ETHERTYPE_VAL_2_MASK 0xFFFF0000 +#define EC_WOL_ETHERTYPE_VAL_2_SHIFT 16 + +#define EC_PTH_SYSTEM_TIME_SUBSECONDS_LSB_VAL_MASK 0xFFFFC000 +#define EC_PTH_SYSTEM_TIME_SUBSECONDS_LSB_VAL_SHIFT 14 + +#define EC_PTH_CLOCK_PERIOD_LSB_VAL_MASK 0xFFFFC000 +#define EC_PTH_CLOCK_PERIOD_LSB_VAL_SHIFT 14 + +/**** int_update_ctrl register ****/ +/* This field chooses between two methods for SW to update the s ... */ +#define EC_PTH_INT_UPDATE_CTRL_UPDATE_TRIG (1 << 0) +/* 3'b000 - Set system time according to the value in {int_updat ... */ +#define EC_PTH_INT_UPDATE_CTRL_UPDATE_METHOD_MASK 0x0000000E +#define EC_PTH_INT_UPDATE_CTRL_UPDATE_METHOD_SHIFT 1 +/* 1'b1 - Next update writes to system_time_subseconds1'b0 - Nex ... */ +#define EC_PTH_INT_UPDATE_CTRL_SUBSECOND_MASK (1 << 4) +/* 1'b1 - Next update writes to system_time_seconds1'b0 - Next u ... */ +#define EC_PTH_INT_UPDATE_CTRL_SECOND_MASK (1 << 5) +/* Enabling / disabling the internal ingress trigger (ingress_tr ... */ +#define EC_PTH_INT_UPDATE_CTRL_INT_TRIG_EN (1 << 16) +/* Determines if internal ingress trigger (ingress_trigger #0) s ... */ +#define EC_PTH_INT_UPDATE_CTRL_PULSE_LEVEL_N (1 << 17) +/* Internal ingress trigger polarity (ingress_trigger #0)1'b0 - ... */ +#define EC_PTH_INT_UPDATE_CTRL_POLARITY (1 << 18) + +/**** int_update_subseconds_lsb register ****/ + +#define EC_PTH_INT_UPDATE_SUBSECONDS_LSB_RESERVED_13_0_MASK 0x00003FFF +#define EC_PTH_INT_UPDATE_SUBSECONDS_LSB_RESERVED_13_0_SHIFT 0 + +#define EC_PTH_INT_UPDATE_SUBSECONDS_LSB_VAL_MASK 0xFFFFC000 +#define EC_PTH_INT_UPDATE_SUBSECONDS_LSB_VAL_SHIFT 14 +/* 3'b000 - Set system time according to the value in {int_updat ... */ +#define EC_PTH_EXT_UPDATE_CTRL_UPDATE_METHOD_MASK 0x0000000E +#define EC_PTH_EXT_UPDATE_CTRL_UPDATE_METHOD_SHIFT 1 +/* 1'b1 - next update writes to system_time_subseconds1'b0 - nex ... */ +#define EC_PTH_EXT_UPDATE_CTRL_SUBSECOND_MASK (1 << 4) +/* 1'b1 - Next update writes to system_time_seconds1'b0 - Next u ... */ +#define EC_PTH_EXT_UPDATE_CTRL_SECOND_MASK (1 << 5) +/* Enabling / disabling the external ingress triggers (ingress_t ... */ +#define EC_PTH_EXT_UPDATE_CTRL_EXT_TRIG_EN_MASK 0x00001F00 +#define EC_PTH_EXT_UPDATE_CTRL_EXT_TRIG_EN_SHIFT 8 +/* Determines if external ingress triggers (ingress_triggers #1- ... */ +#define EC_PTH_EXT_UPDATE_CTRL_PULSE_LEVEL_N_MASK 0x001F0000 +#define EC_PTH_EXT_UPDATE_CTRL_PULSE_LEVEL_N_SHIFT 16 +/* bit-field configurations of external ingress trigger polarity ... */ +#define EC_PTH_EXT_UPDATE_CTRL_POLARITY_MASK 0x1F000000 +#define EC_PTH_EXT_UPDATE_CTRL_POLARITY_SHIFT 24 + +/**** ext_update_subseconds_lsb register ****/ + +#define EC_PTH_EXT_UPDATE_SUBSECONDS_LSB_RESERVED_13_0_MASK 0x00003FFF +#define EC_PTH_EXT_UPDATE_SUBSECONDS_LSB_RESERVED_13_0_SHIFT 0 + +#define EC_PTH_EXT_UPDATE_SUBSECONDS_LSB_VAL_MASK 0xFFFFC000 +#define EC_PTH_EXT_UPDATE_SUBSECONDS_LSB_VAL_SHIFT 14 + +#define EC_PTH_READ_COMPENSATION_SUBSECONDS_LSB_VAL_MASK 0xFFFFC000 +#define EC_PTH_READ_COMPENSATION_SUBSECONDS_LSB_VAL_SHIFT 14 + +#define EC_PTH_INT_WRITE_COMPENSATION_SUBSECONDS_LSB_VAL_MASK 0xFFFFC000 +#define EC_PTH_INT_WRITE_COMPENSATION_SUBSECONDS_LSB_VAL_SHIFT 14 + +#define EC_PTH_EXT_WRITE_COMPENSATION_SUBSECONDS_LSB_VAL_MASK 0xFFFFC000 +#define EC_PTH_EXT_WRITE_COMPENSATION_SUBSECONDS_LSB_VAL_SHIFT 14 + +#define EC_PTH_SYNC_COMPENSATION_SUBSECONDS_LSB_VAL_MASK 0xFFFFC000 +#define EC_PTH_SYNC_COMPENSATION_SUBSECONDS_LSB_VAL_SHIFT 14 + +/**** trigger_ctrl register ****/ +/* Enabling / disabling the egress trigger1'b1 - Enabled1'b0 - D ... */ +#define EC_PTH_EGRESS_TRIGGER_CTRL_EN (1 << 0) +/* Configuration that determines if the egress trigger is a peri ... */ +#define EC_PTH_EGRESS_TRIGGER_CTRL_PERIODIC (1 << 1) +/* Configuration of egress trigger polarity */ +#define EC_PTH_EGRESS_TRIGGER_CTRL_POLARITY (1 << 2) +/* If the pulse is marked as periodic (see periodic field), this ... */ +#define EC_PTH_EGRESS_TRIGGER_CTRL_PERIOD_SUBSEC_MASK 0x00FFFFF0 +#define EC_PTH_EGRESS_TRIGGER_CTRL_PERIOD_SUBSEC_SHIFT 4 +/* If the pulse is marked as periodic (see periodic field), this ... */ +#define EC_PTH_EGRESS_TRIGGER_CTRL_PERIOD_SEC_MASK 0xFF000000 +#define EC_PTH_EGRESS_TRIGGER_CTRL_PERIOD_SEC_SHIFT 24 + +/**** trigger_subseconds_lsb register ****/ + +#define EC_PTH_EGRESS_TRIGGER_SUBSECONDS_LSB_RESERVED_13_0_MASK 0x00003FFF +#define EC_PTH_EGRESS_TRIGGER_SUBSECONDS_LSB_RESERVED_13_0_SHIFT 0 + +#define EC_PTH_EGRESS_TRIGGER_SUBSECONDS_LSB_VAL_MASK 0xFFFFC000 +#define EC_PTH_EGRESS_TRIGGER_SUBSECONDS_LSB_VAL_SHIFT 14 + +/**** pulse_width_subseconds_lsb register ****/ + +#define EC_PTH_EGRESS_PULSE_WIDTH_SUBSECONDS_LSB_RESERVED_13_0_MASK 0x00003FFF +#define EC_PTH_EGRESS_PULSE_WIDTH_SUBSECONDS_LSB_RESERVED_13_0_SHIFT 0 + +#define EC_PTH_EGRESS_PULSE_WIDTH_SUBSECONDS_LSB_VAL_MASK 0xFFFFC000 +#define EC_PTH_EGRESS_PULSE_WIDTH_SUBSECONDS_LSB_VAL_SHIFT 14 + +/**** qual register ****/ + +#define EC_PTH_DB_QUAL_TS_VALID (1 << 0) + +#define EC_PTH_DB_QUAL_RESERVED_31_1_MASK 0xFFFFFFFE +#define EC_PTH_DB_QUAL_RESERVED_31_1_SHIFT 1 + +/**** rx_comp_desc register ****/ +/* Selection for word0[13]:0- legacy SR-A01- per generic protoco ... */ +#define EC_GEN_V3_RX_COMP_DESC_W0_L3_CKS_RES_SEL (1 << 0) +/* Selection for word0[14]:0- legacy SR-A01- per generic protoco ... */ +#define EC_GEN_V3_RX_COMP_DESC_W0_L4_CKS_RES_SEL (1 << 1) +/* Selection for word3[29]:0-macsec decryption status[13] (legac ... */ +#define EC_GEN_V3_RX_COMP_DESC_W3_DEC_STAT_13_L4_CKS_RES_SEL (1 << 8) +/* Selection for word3[30]:0-macsec decryption status[14] (legac ... */ +#define EC_GEN_V3_RX_COMP_DESC_W3_DEC_STAT_14_L3_CKS_RES_SEL (1 << 9) +/* Selection for word3[31]:0-macsec decryption status[15] (legac ... */ +#define EC_GEN_V3_RX_COMP_DESC_W3_DEC_STAT_15_CRC_RES_SEL (1 << 10) +/* Selection for word 0 [6:5], source VLAN count0- source vlan c ... */ +#define EC_GEN_V3_RX_COMP_DESC_W0_SRC_VLAN_CNT (1 << 12) +/* Selection for word 0 [4:0], l3 protocol index0- l3 protocol ... */ +#define EC_GEN_V3_RX_COMP_DESC_W0_L3_PROT_INDEX (1 << 13) +/* Selection for word 1 [31:16], lP fragment checksum0- IP frag ... */ +#define EC_GEN_V3_RX_COMP_DESC_W1_IP_FRAG_CHECKSUM (1 << 14) +/* Selection for word 2 [15:9], L3 offset0- LL3 offset1- CRC re ... */ +#define EC_GEN_V3_RX_COMP_DESC_W2_L3_OFFSET (1 << 15) +/* Selection for word 2 [8:0], tunnel offset0- tunnel offset1- ... */ +#define EC_GEN_V3_RX_COMP_DESC_W2_TUNNEL_OFFSET (1 << 16) + +/**** conf register ****/ +/* Valid signal configuration when in loopback mode:00 - valid f ... */ +#define EC_GEN_V3_CONF_MAC_LB_EC_OUT_S_VALID_CFG_MASK 0x00000003 +#define EC_GEN_V3_CONF_MAC_LB_EC_OUT_S_VALID_CFG_SHIFT 0 +/* Valid signal configuration when in loopback mode:00 – valid f ... */ +#define EC_GEN_V3_CONF_MAC_LB_EC_IN_S_VALID_CFG_MASK 0x0000000C +#define EC_GEN_V3_CONF_MAC_LB_EC_IN_S_VALID_CFG_SHIFT 2 + +/**** tx_gpd_cam_addr register ****/ +/* Cam compare table address */ +#define EC_TFW_V3_TX_GPD_CAM_ADDR_VAL_MASK 0x0000001F +#define EC_TFW_V3_TX_GPD_CAM_ADDR_VAL_SHIFT 0 +/* cam entry is valid */ +#define EC_TFW_V3_TX_GPD_CAM_CTRL_VALID (1 << 31) + +/**** tx_gcp_legacy register ****/ +/* 0-choose parameters from table1- choose legacy crce roce para ... */ +#define EC_TFW_V3_TX_GCP_LEGACY_PARAM_SEL (1 << 0) + +/**** tx_gcp_table_addr register ****/ +/* parametrs table address */ +#define EC_TFW_V3_TX_GCP_TABLE_ADDR_VAL_MASK 0x0000001F +#define EC_TFW_V3_TX_GCP_TABLE_ADDR_VAL_SHIFT 0 + +/**** tx_gcp_table_gen register ****/ +/* polynomial selcet +0-crc32(0x104C11DB7) +1-crc32c(0x11EDC6F41) */ +#define EC_TFW_V3_TX_GCP_TABLE_GEN_POLY_SEL (1 << 0) +/* Enable bit complement on crc result */ +#define EC_TFW_V3_TX_GCP_TABLE_GEN_CRC32_BIT_COMP (1 << 1) +/* Enable bit swap on crc result */ +#define EC_TFW_V3_TX_GCP_TABLE_GEN_CRC32_BIT_SWAP (1 << 2) +/* Enable byte swap on crc result */ +#define EC_TFW_V3_TX_GCP_TABLE_GEN_CRC32_BYTE_SWAP (1 << 3) +/* Enable bit swap on input data */ +#define EC_TFW_V3_TX_GCP_TABLE_GEN_DATA_BIT_SWAP (1 << 4) +/* Enable byte swap on input data */ +#define EC_TFW_V3_TX_GCP_TABLE_GEN_DATA_BYTE_SWAP (1 << 5) +/* Number of bytes in trailer which are not part of crc calculat ... */ +#define EC_TFW_V3_TX_GCP_TABLE_GEN_TRAIL_SIZE_MASK 0x000003C0 +#define EC_TFW_V3_TX_GCP_TABLE_GEN_TRAIL_SIZE_SHIFT 6 +/* Number of bytes in header which are not part of crc calculati ... */ +#define EC_TFW_V3_TX_GCP_TABLE_GEN_HEAD_SIZE_MASK 0x00FF0000 +#define EC_TFW_V3_TX_GCP_TABLE_GEN_HEAD_SIZE_SHIFT 16 +/* corrected offset calculation0- subtract head_size (roce)1- ad ... */ +#define EC_TFW_V3_TX_GCP_TABLE_GEN_HEAD_CALC (1 << 24) +/* 0-replace masked bits with 01-replace masked bits with 1 (roc ... */ +#define EC_TFW_V3_TX_GCP_TABLE_GEN_MASK_POLARITY (1 << 25) + +/**** tx_gcp_table_res register ****/ +/* Not in use */ +#define EC_TFW_V3_TX_GCP_TABLE_RES_SEL_MASK 0x0000001F +#define EC_TFW_V3_TX_GCP_TABLE_RES_SEL_SHIFT 0 +/* Not in use */ +#define EC_TFW_V3_TX_GCP_TABLE_RES_EN (1 << 5) +/* Not in use */ +#define EC_TFW_V3_TX_GCP_TABLE_RES_DEF (1 << 6) + +/**** tx_gcp_table_alu_opcode register ****/ +/* first opcode +e.g. (A op1 B) op3 (C op2 D) */ +#define EC_TFW_V3_TX_GCP_TABLE_ALU_OPCODE_OPCODE_1_MASK 0x0000003F +#define EC_TFW_V3_TX_GCP_TABLE_ALU_OPCODE_OPCODE_1_SHIFT 0 +/* second opcode +e.g. (A op1 B) op3 (C op2 D) */ +#define EC_TFW_V3_TX_GCP_TABLE_ALU_OPCODE_OPCODE_2_MASK 0x00000FC0 +#define EC_TFW_V3_TX_GCP_TABLE_ALU_OPCODE_OPCODE_2_SHIFT 6 +/* third opcode +e.g. (A op1 B) op3 (C op2 D) */ +#define EC_TFW_V3_TX_GCP_TABLE_ALU_OPCODE_OPCODE_3_MASK 0x0003F000 +#define EC_TFW_V3_TX_GCP_TABLE_ALU_OPCODE_OPCODE_3_SHIFT 12 + +/**** tx_gcp_table_alu_opsel register ****/ +/* frst opsel, input selection */ +#define EC_TFW_V3_TX_GCP_TABLE_ALU_OPSEL_OPSEL_1_MASK 0x0000000F +#define EC_TFW_V3_TX_GCP_TABLE_ALU_OPSEL_OPSEL_1_SHIFT 0 +/* second opsel, input selection */ +#define EC_TFW_V3_TX_GCP_TABLE_ALU_OPSEL_OPSEL_2_MASK 0x000000F0 +#define EC_TFW_V3_TX_GCP_TABLE_ALU_OPSEL_OPSEL_2_SHIFT 4 +/* third opsel, input selction */ +#define EC_TFW_V3_TX_GCP_TABLE_ALU_OPSEL_OPSEL_3_MASK 0x00000F00 +#define EC_TFW_V3_TX_GCP_TABLE_ALU_OPSEL_OPSEL_3_SHIFT 8 +/* fourth opsel, input selction */ +#define EC_TFW_V3_TX_GCP_TABLE_ALU_OPSEL_OPSEL_4_MASK 0x0000F000 +#define EC_TFW_V3_TX_GCP_TABLE_ALU_OPSEL_OPSEL_4_SHIFT 12 + +/**** tx_gcp_table_alu_val register ****/ +/* value for alu input */ +#define EC_TFW_V3_TX_GCP_TABLE_ALU_VAL_VAL_MASK 0x000001FF +#define EC_TFW_V3_TX_GCP_TABLE_ALU_VAL_VAL_SHIFT 0 + +/**** crc_csum_replace register ****/ +/* 0- use table +1- legacy SR-A0 */ +#define EC_TFW_V3_CRC_CSUM_REPLACE_L3_CSUM_LEGACY_SEL (1 << 0) +/* 0- use table +1- legacy SR-A0 */ +#define EC_TFW_V3_CRC_CSUM_REPLACE_L4_CSUM_LEGACY_SEL (1 << 1) +/* 0- use table +1- legacy SR-A0 */ +#define EC_TFW_V3_CRC_CSUM_REPLACE_CRC_LEGACY_SEL (1 << 2) + +/**** crc_csum_replace_table_addr register ****/ +/* parametrs table address */ +#define EC_TFW_V3_CRC_CSUM_REPLACE_TABLE_ADDR_VAL_MASK 0x0000007F +#define EC_TFW_V3_CRC_CSUM_REPLACE_TABLE_ADDR_VAL_SHIFT 0 + +/**** crc_csum_replace_table register ****/ +/* L3 Checksum replace enable */ +#define EC_TFW_V3_CRC_CSUM_REPLACE_TABLE_L3_CSUM_EN (1 << 0) +/* L4 Checksum replace enable */ +#define EC_TFW_V3_CRC_CSUM_REPLACE_TABLE_L4_CSUM_EN (1 << 1) +/* CRC replace enable */ +#define EC_TFW_V3_CRC_CSUM_REPLACE_TABLE_CRC_EN (1 << 2) + +/**** rx_gpd_cam_addr register ****/ +/* Cam compare table address */ +#define EC_RFW_V3_RX_GPD_CAM_ADDR_VAL_MASK 0x0000001F +#define EC_RFW_V3_RX_GPD_CAM_ADDR_VAL_SHIFT 0 +/* cam entry is valid */ +#define EC_RFW_V3_RX_GPD_CAM_CTRL_VALID (1 << 31) + +/**** gpd_p1 register ****/ +/* Location in bytes of the gpd cam data1 in the parser result v ... */ +#define EC_RFW_V3_GPD_P1_OFFSET_MASK 0x000003FF +#define EC_RFW_V3_GPD_P1_OFFSET_SHIFT 0 + +/**** gpd_p2 register ****/ +/* Location in bytes of the gpd cam data2 in the parser result v ... */ +#define EC_RFW_V3_GPD_P2_OFFSET_MASK 0x000003FF +#define EC_RFW_V3_GPD_P2_OFFSET_SHIFT 0 + +/**** gpd_p3 register ****/ +/* Location in bytes of the gpd cam data3 in the parser result v ... */ +#define EC_RFW_V3_GPD_P3_OFFSET_MASK 0x000003FF +#define EC_RFW_V3_GPD_P3_OFFSET_SHIFT 0 + +/**** gpd_p4 register ****/ +/* Location in bytes of the gpd cam data4 in the parser result v ... */ +#define EC_RFW_V3_GPD_P4_OFFSET_MASK 0x000003FF +#define EC_RFW_V3_GPD_P4_OFFSET_SHIFT 0 + +/**** gpd_p5 register ****/ +/* Location in bytes of the gpd cam data5 in the parser result v ... */ +#define EC_RFW_V3_GPD_P5_OFFSET_MASK 0x000003FF +#define EC_RFW_V3_GPD_P5_OFFSET_SHIFT 0 + +/**** gpd_p6 register ****/ +/* Location in bytes of the gpd cam data6 in the parser result v ... */ +#define EC_RFW_V3_GPD_P6_OFFSET_MASK 0x000003FF +#define EC_RFW_V3_GPD_P6_OFFSET_SHIFT 0 + +/**** gpd_p7 register ****/ +/* Location in bytes of the gpd cam data7 in the parser result v ... */ +#define EC_RFW_V3_GPD_P7_OFFSET_MASK 0x000003FF +#define EC_RFW_V3_GPD_P7_OFFSET_SHIFT 0 + +/**** gpd_p8 register ****/ +/* Location in bytes of the gpd cam data8 in the parser result v ... */ +#define EC_RFW_V3_GPD_P8_OFFSET_MASK 0x000003FF +#define EC_RFW_V3_GPD_P8_OFFSET_SHIFT 0 + +/**** rx_gcp_legacy register ****/ +/* 0-choose parameters from table1- choose legacy crce roce para ... */ +#define EC_RFW_V3_RX_GCP_LEGACY_PARAM_SEL (1 << 0) + +/**** rx_gcp_table_addr register ****/ +/* parametrs table address */ +#define EC_RFW_V3_RX_GCP_TABLE_ADDR_VAL_MASK 0x0000001F +#define EC_RFW_V3_RX_GCP_TABLE_ADDR_VAL_SHIFT 0 + +/**** rx_gcp_table_gen register ****/ +/* polynomial selcet +0-crc32(0x104C11DB7) +1-crc32c(0x11EDC6F41) */ +#define EC_RFW_V3_RX_GCP_TABLE_GEN_POLY_SEL (1 << 0) +/* Enable bit complement on crc result */ +#define EC_RFW_V3_RX_GCP_TABLE_GEN_CRC32_BIT_COMP (1 << 1) +/* Enable bit swap on crc result */ +#define EC_RFW_V3_RX_GCP_TABLE_GEN_CRC32_BIT_SWAP (1 << 2) +/* Enable byte swap on crc result */ +#define EC_RFW_V3_RX_GCP_TABLE_GEN_CRC32_BYTE_SWAP (1 << 3) +/* Enable bit swap on input data */ +#define EC_RFW_V3_RX_GCP_TABLE_GEN_DATA_BIT_SWAP (1 << 4) +/* Enable byte swap on input data */ +#define EC_RFW_V3_RX_GCP_TABLE_GEN_DATA_BYTE_SWAP (1 << 5) +/* Number of bytes in trailer which are not part of crc calculat ... */ +#define EC_RFW_V3_RX_GCP_TABLE_GEN_TRAIL_SIZE_MASK 0x000003C0 +#define EC_RFW_V3_RX_GCP_TABLE_GEN_TRAIL_SIZE_SHIFT 6 +/* Number of bytes in header which are not part of crc calculati ... */ +#define EC_RFW_V3_RX_GCP_TABLE_GEN_HEAD_SIZE_MASK 0x00FF0000 +#define EC_RFW_V3_RX_GCP_TABLE_GEN_HEAD_SIZE_SHIFT 16 +/* corrected offset calculation0- subtract head_size (roce)1- ad ... */ +#define EC_RFW_V3_RX_GCP_TABLE_GEN_HEAD_CALC (1 << 24) +/* 0-replace masked bits with 01-replace masked bits with 1 (roc ... */ +#define EC_RFW_V3_RX_GCP_TABLE_GEN_MASK_POLARITY (1 << 25) + +/**** rx_gcp_table_res register ****/ +/* Bit mask for crc/checksum result options for metadata W0[13][ ... */ +#define EC_RFW_V3_RX_GCP_TABLE_RES_SEL_0_MASK 0x0000001F +#define EC_RFW_V3_RX_GCP_TABLE_RES_SEL_0_SHIFT 0 +/* Bit mask for crc/checksum result options for metadata W0[14][ ... */ +#define EC_RFW_V3_RX_GCP_TABLE_RES_SEL_1_MASK 0x000003E0 +#define EC_RFW_V3_RX_GCP_TABLE_RES_SEL_1_SHIFT 5 +/* Bit mask for crc/checksum result options for metadata W3[29][ ... */ +#define EC_RFW_V3_RX_GCP_TABLE_RES_SEL_2_MASK 0x00007C00 +#define EC_RFW_V3_RX_GCP_TABLE_RES_SEL_2_SHIFT 10 +/* Bit mask for crc/checksum result options for metadata W3[30][ ... */ +#define EC_RFW_V3_RX_GCP_TABLE_RES_SEL_3_MASK 0x000F8000 +#define EC_RFW_V3_RX_GCP_TABLE_RES_SEL_3_SHIFT 15 +/* Bit mask for crc/checksum result options for metadata W3[31][ ... */ +#define EC_RFW_V3_RX_GCP_TABLE_RES_SEL_4_MASK 0x01F00000 +#define EC_RFW_V3_RX_GCP_TABLE_RES_SEL_4_SHIFT 20 +/* enable crc result check */ +#define EC_RFW_V3_RX_GCP_TABLE_RES_EN (1 << 25) +/* default value for crc check for non-crc protocol */ +#define EC_RFW_V3_RX_GCP_TABLE_RES_DEF (1 << 26) + +/**** rx_gcp_table_alu_opcode register ****/ +/* first opcode +e.g. (A op1 B) op3 (C op2 D) */ +#define EC_RFW_V3_RX_GCP_TABLE_ALU_OPCODE_OPCODE_1_MASK 0x0000003F +#define EC_RFW_V3_RX_GCP_TABLE_ALU_OPCODE_OPCODE_1_SHIFT 0 +/* second opcode +e.g. (A op1 B) op3 (C op2 D) */ +#define EC_RFW_V3_RX_GCP_TABLE_ALU_OPCODE_OPCODE_2_MASK 0x00000FC0 +#define EC_RFW_V3_RX_GCP_TABLE_ALU_OPCODE_OPCODE_2_SHIFT 6 +/* third opcode +e.g. (A op1 B) op3 (C op2 D) */ +#define EC_RFW_V3_RX_GCP_TABLE_ALU_OPCODE_OPCODE_3_MASK 0x0003F000 +#define EC_RFW_V3_RX_GCP_TABLE_ALU_OPCODE_OPCODE_3_SHIFT 12 + +/**** rx_gcp_table_alu_opsel register ****/ +/* frst opsel, input selection */ +#define EC_RFW_V3_RX_GCP_TABLE_ALU_OPSEL_OPSEL_1_MASK 0x0000000F +#define EC_RFW_V3_RX_GCP_TABLE_ALU_OPSEL_OPSEL_1_SHIFT 0 +/* second opsel, input selection */ +#define EC_RFW_V3_RX_GCP_TABLE_ALU_OPSEL_OPSEL_2_MASK 0x000000F0 +#define EC_RFW_V3_RX_GCP_TABLE_ALU_OPSEL_OPSEL_2_SHIFT 4 +/* third opsel, input selction */ +#define EC_RFW_V3_RX_GCP_TABLE_ALU_OPSEL_OPSEL_3_MASK 0x00000F00 +#define EC_RFW_V3_RX_GCP_TABLE_ALU_OPSEL_OPSEL_3_SHIFT 8 +/* fourth opsel, input selction */ +#define EC_RFW_V3_RX_GCP_TABLE_ALU_OPSEL_OPSEL_4_MASK 0x0000F000 +#define EC_RFW_V3_RX_GCP_TABLE_ALU_OPSEL_OPSEL_4_SHIFT 12 + +/**** rx_gcp_table_alu_val register ****/ +/* value for alu input */ +#define EC_RFW_V3_RX_GCP_TABLE_ALU_VAL_VAL_MASK 0x000001FF +#define EC_RFW_V3_RX_GCP_TABLE_ALU_VAL_VAL_SHIFT 0 + +/**** rx_gcp_alu_p1 register ****/ +/* Location in bytes of field 1 in the parser result vector */ +#define EC_RFW_V3_RX_GCP_ALU_P1_OFFSET_MASK 0x000003FF +#define EC_RFW_V3_RX_GCP_ALU_P1_OFFSET_SHIFT 0 +/* Right shift for field 1 in the parser result vector */ +#define EC_RFW_V3_RX_GCP_ALU_P1_SHIFT_MASK 0x000F0000 +#define EC_RFW_V3_RX_GCP_ALU_P1_SHIFT_SHIFT 16 + +/**** rx_gcp_alu_p2 register ****/ +/* Location in bytes of field 2 in the parser result vector */ +#define EC_RFW_V3_RX_GCP_ALU_P2_OFFSET_MASK 0x000003FF +#define EC_RFW_V3_RX_GCP_ALU_P2_OFFSET_SHIFT 0 +/* Right shift for field 2 in the parser result vector */ +#define EC_RFW_V3_RX_GCP_ALU_P2_SHIFT_MASK 0x000F0000 +#define EC_RFW_V3_RX_GCP_ALU_P2_SHIFT_SHIFT 16 + +/**** hs_ctrl_table_addr register ****/ +/* Header split control table address */ +#define EC_RFW_V3_HS_CTRL_TABLE_ADDR_VAL_MASK 0x000000FF +#define EC_RFW_V3_HS_CTRL_TABLE_ADDR_VAL_SHIFT 0 + +/**** hs_ctrl_table register ****/ +/* Header split length select */ +#define EC_RFW_V3_HS_CTRL_TABLE_SEL_MASK 0x00000003 +#define EC_RFW_V3_HS_CTRL_TABLE_SEL_SHIFT 0 +/* enable header split */ +#define EC_RFW_V3_HS_CTRL_TABLE_ENABLE (1 << 2) + +/**** hs_ctrl_table_alu_opcode register ****/ +/* first opcode +e.g. (A op1 B) op3 (C op2 D) */ +#define EC_RFW_V3_HS_CTRL_TABLE_ALU_OPCODE_OPCODE_1_MASK 0x0000003F +#define EC_RFW_V3_HS_CTRL_TABLE_ALU_OPCODE_OPCODE_1_SHIFT 0 +/* second opcode +e.g. (A op1 B) op3 (C op2 D) */ +#define EC_RFW_V3_HS_CTRL_TABLE_ALU_OPCODE_OPCODE_2_MASK 0x00000FC0 +#define EC_RFW_V3_HS_CTRL_TABLE_ALU_OPCODE_OPCODE_2_SHIFT 6 +/* third opcode +e.g. (A op1 B) op3 (C op2 D) */ +#define EC_RFW_V3_HS_CTRL_TABLE_ALU_OPCODE_OPCODE_3_MASK 0x0003F000 +#define EC_RFW_V3_HS_CTRL_TABLE_ALU_OPCODE_OPCODE_3_SHIFT 12 + +/**** hs_ctrl_table_alu_opsel register ****/ +/* frst opsel, input selection */ +#define EC_RFW_V3_HS_CTRL_TABLE_ALU_OPSEL_OPSEL_1_MASK 0x0000000F +#define EC_RFW_V3_HS_CTRL_TABLE_ALU_OPSEL_OPSEL_1_SHIFT 0 +/* second opsel, input selection */ +#define EC_RFW_V3_HS_CTRL_TABLE_ALU_OPSEL_OPSEL_2_MASK 0x000000F0 +#define EC_RFW_V3_HS_CTRL_TABLE_ALU_OPSEL_OPSEL_2_SHIFT 4 +/* third opsel, input selction */ +#define EC_RFW_V3_HS_CTRL_TABLE_ALU_OPSEL_OPSEL_3_MASK 0x00000F00 +#define EC_RFW_V3_HS_CTRL_TABLE_ALU_OPSEL_OPSEL_3_SHIFT 8 +/* fourth opsel, input selction */ +#define EC_RFW_V3_HS_CTRL_TABLE_ALU_OPSEL_OPSEL_4_MASK 0x0000F000 +#define EC_RFW_V3_HS_CTRL_TABLE_ALU_OPSEL_OPSEL_4_SHIFT 12 + +/**** hs_ctrl_table_alu_val register ****/ +/* value for alu input */ +#define EC_RFW_V3_HS_CTRL_TABLE_ALU_VAL_VAL_MASK 0x0000FFFF +#define EC_RFW_V3_HS_CTRL_TABLE_ALU_VAL_VAL_SHIFT 0 + +/**** hs_ctrl_cfg register ****/ +/* Header split enable static selction0 – legacy1 – header split ... */ +#define EC_RFW_V3_HS_CTRL_CFG_ENABLE_SEL (1 << 0) +/* Header split length static selction0 – legacy1 – header split ... */ +#define EC_RFW_V3_HS_CTRL_CFG_LENGTH_SEL (1 << 1) + +/**** hs_ctrl_alu_p1 register ****/ +/* Location in bytes of field 1 in the parser result vector */ +#define EC_RFW_V3_HS_CTRL_ALU_P1_OFFSET_MASK 0x000003FF +#define EC_RFW_V3_HS_CTRL_ALU_P1_OFFSET_SHIFT 0 +/* Right shift for field 1 in the parser result vector */ +#define EC_RFW_V3_HS_CTRL_ALU_P1_SHIFT_MASK 0x000F0000 +#define EC_RFW_V3_HS_CTRL_ALU_P1_SHIFT_SHIFT 16 + +/**** hs_ctrl_alu_p2 register ****/ +/* Location in bytes of field 2 in the parser result vector */ +#define EC_RFW_V3_HS_CTRL_ALU_P2_OFFSET_MASK 0x000003FF +#define EC_RFW_V3_HS_CTRL_ALU_P2_OFFSET_SHIFT 0 +/* Right shift for field 2 in the parser result vector */ +#define EC_RFW_V3_HS_CTRL_ALU_P2_SHIFT_MASK 0x000F0000 +#define EC_RFW_V3_HS_CTRL_ALU_P2_SHIFT_SHIFT 16 + +/**** tx_config register ****/ +/* [0] pre increment word swap[1] pre increment byte swap[2] pre ... */ +#define EC_CRYPTO_TX_CONFIG_TWEAK_ENDIANITY_SWAP_MASK 0x0000003F +#define EC_CRYPTO_TX_CONFIG_TWEAK_ENDIANITY_SWAP_SHIFT 0 +/* [0] pre encryption word swap[1] pre encryption byte swap[2] p ... */ +#define EC_CRYPTO_TX_CONFIG_DATA_ENDIANITY_SWAP_MASK 0x00003F00 +#define EC_CRYPTO_TX_CONFIG_DATA_ENDIANITY_SWAP_SHIFT 8 +/* direction flip, used in order to use same TID entry for both TX & RX traffic */ +#define EC_CRYPTO_TX_CONFIG_CRYPTO_DIR_FLIP (1 << 14) +/* Enabling pipe line optimization */ +#define EC_CRYPTO_TX_CONFIG_PIPE_CALC_EN (1 << 16) +/* enable performance counters */ +#define EC_CRYPTO_TX_CONFIG_PERF_CNT_EN (1 << 17) +/* [0] pre aes word swap[1] pre aes byte swap[2] pre aes bit swa ... */ +#define EC_CRYPTO_TX_CONFIG_AES_ENDIANITY_SWAP_MASK 0x03F00000 +#define EC_CRYPTO_TX_CONFIG_AES_ENDIANITY_SWAP_SHIFT 20 +/* [0] pre aes key word swap[1] pre aes key byte swap[2] pre aes ... */ +#define EC_CRYPTO_TX_CONFIG_AES_KEY_ENDIANITY_SWAP_MASK 0xFC000000 +#define EC_CRYPTO_TX_CONFIG_AES_KEY_ENDIANITY_SWAP_SHIFT 26 + +/**** rx_config register ****/ +/* [0] pre increment word swap[1] pre increment byte swap[2] pre ... */ +#define EC_CRYPTO_RX_CONFIG_TWEAK_ENDIANITY_SWAP_MASK 0x0000003F +#define EC_CRYPTO_RX_CONFIG_TWEAK_ENDIANITY_SWAP_SHIFT 0 +/* [0] pre encryption word swap[1] pre encryption byte swap[2] p ... */ +#define EC_CRYPTO_RX_CONFIG_DATA_ENDIANITY_SWAP_MASK 0x00003F00 +#define EC_CRYPTO_RX_CONFIG_DATA_ENDIANITY_SWAP_SHIFT 8 +/* direction flip, used in order to use same TID entry for both TX & RX traffic */ +#define EC_CRYPTO_RX_CONFIG_CRYPTO_DIR_FLIP (1 << 14) +/* Enabling pipe line optimization */ +#define EC_CRYPTO_RX_CONFIG_PIPE_CALC_EN (1 << 16) +/* enable performance counters */ +#define EC_CRYPTO_RX_CONFIG_PERF_CNT_EN (1 << 17) +/* [0] pre aes word swap[1] pre aes byte swap[2] pre aes bit swa ... */ +#define EC_CRYPTO_RX_CONFIG_AES_ENDIANITY_SWAP_MASK 0x03F00000 +#define EC_CRYPTO_RX_CONFIG_AES_ENDIANITY_SWAP_SHIFT 20 +/* [0] data aes key word swap[1] data aes key byte swap[2] data ... */ +#define EC_CRYPTO_RX_CONFIG_AES_KEY_ENDIANITY_SWAP_MASK 0xFC000000 +#define EC_CRYPTO_RX_CONFIG_AES_KEY_ENDIANITY_SWAP_SHIFT 26 + +/**** tx_override register ****/ +/* all transactions are encrypted */ +#define EC_CRYPTO_TX_OVERRIDE_ENCRYPT_ONLY (1 << 0) +/* all transactions are decrypted */ +#define EC_CRYPTO_TX_OVERRIDE_DECRYPT_ONLY (1 << 1) +/* all pkts use IV */ +#define EC_CRYPTO_TX_OVERRIDE_ALWAYS_DRIVE_IV (1 << 2) +/* no pkt uses IV */ +#define EC_CRYPTO_TX_OVERRIDE_NEVER_DRIVE_IV (1 << 3) +/* all pkts perform authentication calculation */ +#define EC_CRYPTO_TX_OVERRIDE_ALWAYS_PERFORM_SIGN (1 << 4) +/* no pkt performs authentication calculation */ +#define EC_CRYPTO_TX_OVERRIDE_NEVER_PERFORM_SIGN (1 << 5) +/* all pkts perform encryption calculation */ +#define EC_CRYPTO_TX_OVERRIDE_ALWAYS_PERFORM_ENC (1 << 6) +/* no pkt performs encryption calculation */ +#define EC_CRYPTO_TX_OVERRIDE_NEVER_PERFORM_ENC (1 << 7) +/* Enforce pkt trimming +bit[0] relates to metadata_pkt_trim +bit[1] relates to trailer_pkt_trime +bit[2] relates to sign_trim +bit[3] relates to aes_padding_trim */ +#define EC_CRYPTO_TX_OVERRIDE_ALWAYS_BYPASS_PKT_TRIM_MASK 0x00000F00 +#define EC_CRYPTO_TX_OVERRIDE_ALWAYS_BYPASS_PKT_TRIM_SHIFT 8 +/* Enforce no pkt trimming +bit[0] relates to metadata_pkt_trim +bit[1] relates to trailer_pkt_trime +bit[2] relates to sign_trim +bit[3] relates to aes_padding_trim */ +#define EC_CRYPTO_TX_OVERRIDE_NEVER_BYPASS_PKT_TRIM_MASK 0x0000F000 +#define EC_CRYPTO_TX_OVERRIDE_NEVER_BYPASS_PKT_TRIM_SHIFT 12 +/* chicken bit to disable metadata handling optimization */ +#define EC_CRYPTO_TX_OVERRIDE_EXPLICIT_METADATA_STAGE (1 << 16) + +/**** rx_override register ****/ +/* all transactions are encrypted */ +#define EC_CRYPTO_RX_OVERRIDE_ENCRYPT_ONLY (1 << 0) +/* all transactions are decrypted */ +#define EC_CRYPTO_RX_OVERRIDE_DECRYPT_ONLY (1 << 1) +/* all pkts use IV */ +#define EC_CRYPTO_RX_OVERRIDE_ALWAYS_DRIVE_IV (1 << 2) +/* no pkt uses IV */ +#define EC_CRYPTO_RX_OVERRIDE_NEVER_DRIVE_IV (1 << 3) +/* all pkts perform authentication calculation */ +#define EC_CRYPTO_RX_OVERRIDE_ALWAYS_PERFORM_SIGN (1 << 4) +/* no pkt performs authentication calculation */ +#define EC_CRYPTO_RX_OVERRIDE_NEVER_PERFORM_SIGN (1 << 5) +/* all pkts perform encryption calculation */ +#define EC_CRYPTO_RX_OVERRIDE_ALWAYS_PERFORM_ENC (1 << 6) +/* no pkt performs encryption calculation */ +#define EC_CRYPTO_RX_OVERRIDE_NEVER_PERFORM_ENC (1 << 7) +/* Enforce pkt trimming +bit[0] relates to metadata_pkt_trim +bit[1] relates to trailer_pkt_trime +bit[2] relates to sign_trim +bit[3] relates to aes_padding_trim */ +#define EC_CRYPTO_RX_OVERRIDE_ALWAYS_BYPASS_PKT_TRIM_MASK 0x00000F00 +#define EC_CRYPTO_RX_OVERRIDE_ALWAYS_BYPASS_PKT_TRIM_SHIFT 8 +/* Enforce no pkt trimming +bit[0] relates to metadata_pkt_trim +bit[1] relates to trailer_pkt_trime +bit[2] relates to sign_trim +bit[3] relates to aes_padding_trim */ +#define EC_CRYPTO_RX_OVERRIDE_NEVER_BYPASS_PKT_TRIM_MASK 0x0000F000 +#define EC_CRYPTO_RX_OVERRIDE_NEVER_BYPASS_PKT_TRIM_SHIFT 12 +/* bit enable for writing to rx_cmpl metadata info */ +#define EC_CRYPTO_RX_OVERRIDE_META_DATA_WRITE_EN_MASK 0x00070000 +#define EC_CRYPTO_RX_OVERRIDE_META_DATA_WRITE_EN_SHIFT 16 +/* chicken bit to disable metadata handling optimization */ +#define EC_CRYPTO_RX_OVERRIDE_EXPLICIT_METADATA_STAGE (1 << 19) +/* crypto metadata offset in the rx cmpl_desc */ +#define EC_CRYPTO_RX_OVERRIDE_META_DATA_BASE_MASK 0x07F00000 +#define EC_CRYPTO_RX_OVERRIDE_META_DATA_BASE_SHIFT 20 + +/**** tx_enc_iv_construction register ****/ +/* for each IV byte, select between src1 & src2. Src1 & src2 ... */ +#define EC_CRYPTO_TX_ENC_IV_CONSTRUCTION_MUX_SEL_MASK 0x0000FFFF +#define EC_CRYPTO_TX_ENC_IV_CONSTRUCTION_MUX_SEL_SHIFT 0 +/* configure meaning of mux_sel=1'b0 (2'b00 – zeros, 2'b01 f... */ +#define EC_CRYPTO_TX_ENC_IV_CONSTRUCTION_MAP_0_MASK 0x00030000 +#define EC_CRYPTO_TX_ENC_IV_CONSTRUCTION_MAP_0_SHIFT 16 +/* configure meaning of mux_sel=1'b1 (2'b00 – zeros, 2'b01 ... */ +#define EC_CRYPTO_TX_ENC_IV_CONSTRUCTION_MAP_1_MASK 0x000C0000 +#define EC_CRYPTO_TX_ENC_IV_CONSTRUCTION_MAP_1_SHIFT 18 +/* Per-byte mux select taken from Crypto table (otherwise ... */ +#define EC_CRYPTO_TX_ENC_IV_CONSTRUCTION_SEL_FROM_TABLE (1 << 20) +/* [0] word swap en +[1] byte swap en +[2] bit swap en */ +#define EC_CRYPTO_TX_ENC_IV_CONSTRUCTION_ENDIANITY_SWAP_MASK 0x00E00000 +#define EC_CRYPTO_TX_ENC_IV_CONSTRUCTION_ENDIANITY_SWAP_SHIFT 21 + +/**** rx_enc_iv_construction register ****/ +/* for each IV byte, select between src1 & src2. Src1 & src2 ... */ +#define EC_CRYPTO_RX_ENC_IV_CONSTRUCTION_MUX_SEL_MASK 0x0000FFFF +#define EC_CRYPTO_RX_ENC_IV_CONSTRUCTION_MUX_SEL_SHIFT 0 +/* configure meaning of mux_sel=1'b0 (2'b00 – zeros, 2'b01 – ... */ +#define EC_CRYPTO_RX_ENC_IV_CONSTRUCTION_MAP_0_MASK 0x00030000 +#define EC_CRYPTO_RX_ENC_IV_CONSTRUCTION_MAP_0_SHIFT 16 +/* configure meaning of mux_sel=1'b1 (2'b00 – zeros, 2'b01 – ... */ +#define EC_CRYPTO_RX_ENC_IV_CONSTRUCTION_MAP_1_MASK 0x000C0000 +#define EC_CRYPTO_RX_ENC_IV_CONSTRUCTION_MAP_1_SHIFT 18 +/* Per-byte mux select taken from Crypto table (otherwise from ... */ +#define EC_CRYPTO_RX_ENC_IV_CONSTRUCTION_SEL_FROM_TABLE (1 << 20) +/* [0] word swap en +[1] byte swap en +[2] bit swap en */ +#define EC_CRYPTO_RX_ENC_IV_CONSTRUCTION_ENDIANITY_SWAP_MASK 0x00E00000 +#define EC_CRYPTO_RX_ENC_IV_CONSTRUCTION_ENDIANITY_SWAP_SHIFT 21 + +/**** rx_enc_iv_map register ****/ +/* [0] word swap en +[1] byte swap en +[2] bit swap en */ +#define EC_CRYPTO_RX_ENC_IV_MAP_FIELD_EXTRACT_0_OFFSET_MASK 0x0000001F +#define EC_CRYPTO_RX_ENC_IV_MAP_FIELD_EXTRACT_0_OFFSET_SHIFT 0 +/* number of valid bytes in word, as generated by field extract ... */ +#define EC_CRYPTO_RX_ENC_IV_MAP_FIELD_EXTRACT_0_LENGTH_MASK 0x000000E0 +#define EC_CRYPTO_RX_ENC_IV_MAP_FIELD_EXTRACT_0_LENGTH_SHIFT 5 +/* [0] word swap en +[1] byte swap en +[2] bit swap en */ +#define EC_CRYPTO_RX_ENC_IV_MAP_FIELD_EXTRACT_1_OFFSET_MASK 0x00001F00 +#define EC_CRYPTO_RX_ENC_IV_MAP_FIELD_EXTRACT_1_OFFSET_SHIFT 8 +/* number of valid bytes in word, as generated by field extract ... */ +#define EC_CRYPTO_RX_ENC_IV_MAP_FIELD_EXTRACT_1_LENGTH_MASK 0x0000E000 +#define EC_CRYPTO_RX_ENC_IV_MAP_FIELD_EXTRACT_1_LENGTH_SHIFT 13 +/* [0] word swap en +[1] byte swap en +[2] bit swap en */ +#define EC_CRYPTO_RX_ENC_IV_MAP_FIELD_EXTRACT_2_OFFSET_MASK 0x001F0000 +#define EC_CRYPTO_RX_ENC_IV_MAP_FIELD_EXTRACT_2_OFFSET_SHIFT 16 +/* number of valid bytes in word, as generated by field extract ... */ +#define EC_CRYPTO_RX_ENC_IV_MAP_FIELD_EXTRACT_2_LENGTH_MASK 0x00E00000 +#define EC_CRYPTO_RX_ENC_IV_MAP_FIELD_EXTRACT_2_LENGTH_SHIFT 21 +/* [0] word swap en +[1] byte swap en +[2] bit swap en */ +#define EC_CRYPTO_RX_ENC_IV_MAP_FIELD_EXTRACT_3_OFFSET_MASK 0x1F000000 +#define EC_CRYPTO_RX_ENC_IV_MAP_FIELD_EXTRACT_3_OFFSET_SHIFT 24 +/* number of valid bytes in word, as generated by field extract ... */ +#define EC_CRYPTO_RX_ENC_IV_MAP_FIELD_EXTRACT_3_LENGTH_MASK 0xE0000000 +#define EC_CRYPTO_RX_ENC_IV_MAP_FIELD_EXTRACT_3_LENGTH_SHIFT 29 + +/**** tx_pkt_trim_len register ****/ +/* metadata shift-reg length */ +#define EC_CRYPTO_TX_PKT_TRIM_LEN_META_MASK 0x00000007 +#define EC_CRYPTO_TX_PKT_TRIM_LEN_META_SHIFT 0 +/* pkt trailer shift-reg length */ +#define EC_CRYPTO_TX_PKT_TRIM_LEN_TRAIL_MASK 0x000000F0 +#define EC_CRYPTO_TX_PKT_TRIM_LEN_TRAIL_SHIFT 4 +/* sign shift-reg length */ +#define EC_CRYPTO_TX_PKT_TRIM_LEN_SIGN_MASK 0x00000300 +#define EC_CRYPTO_TX_PKT_TRIM_LEN_SIGN_SHIFT 8 +/* crypto padding shift-reg length */ +#define EC_CRYPTO_TX_PKT_TRIM_LEN_CRYPTO_PADDING_MASK 0x00003000 +#define EC_CRYPTO_TX_PKT_TRIM_LEN_CRYPTO_PADDING_SHIFT 12 +/* hardware chooses shift-registers configurations automatically – no need for sw configuration */ +#define EC_CRYPTO_TX_PKT_TRIM_LEN_AUTO_MODE (1 << 16) + +/**** rx_pkt_trim_len register ****/ +/* metadata shift-reg length */ +#define EC_CRYPTO_RX_PKT_TRIM_LEN_META_MASK 0x00000007 +#define EC_CRYPTO_RX_PKT_TRIM_LEN_META_SHIFT 0 +/* pkt trailer shift-reg length */ +#define EC_CRYPTO_RX_PKT_TRIM_LEN_TRAIL_MASK 0x000000F0 +#define EC_CRYPTO_RX_PKT_TRIM_LEN_TRAIL_SHIFT 4 +/* sign shift-reg length */ +#define EC_CRYPTO_RX_PKT_TRIM_LEN_SIGN_MASK 0x00000300 +#define EC_CRYPTO_RX_PKT_TRIM_LEN_SIGN_SHIFT 8 +/* crypto padding shift-reg length */ +#define EC_CRYPTO_RX_PKT_TRIM_LEN_CRYPTO_PADDING_MASK 0x00003000 +#define EC_CRYPTO_RX_PKT_TRIM_LEN_CRYPTO_PADDING_SHIFT 12 +/* hardware chooses shift-registers configurations automatically – no need for sw configuration */ +#define EC_CRYPTO_RX_PKT_TRIM_LEN_AUTO_MODE (1 << 16) + +/**** total_tx_secured_pkts_cipher_mode_cmpr register ****/ + +#define EC_CRYPTO_PERF_CNTR_TOTAL_TX_SECURED_PKTS_CIPHER_MODE_CMPR_MODE_MASK 0x0000000F +#define EC_CRYPTO_PERF_CNTR_TOTAL_TX_SECURED_PKTS_CIPHER_MODE_CMPR_MODE_SHIFT 0 + +/**** total_rx_secured_pkts_cipher_mode_cmpr register ****/ + +#define EC_CRYPTO_PERF_CNTR_TOTAL_RX_SECURED_PKTS_CIPHER_MODE_CMPR_MODE_MASK 0x0000000F +#define EC_CRYPTO_PERF_CNTR_TOTAL_RX_SECURED_PKTS_CIPHER_MODE_CMPR_MODE_SHIFT 0 + +#ifdef __cplusplus +} +#endif + +#endif /* __AL_HAL_EC_REG_H */ + +/** @} end of ... group */ + + diff --git a/eth/al_hal_eth_kr.c b/eth/al_hal_eth_kr.c new file mode 100644 index 00000000000..14ef797eb00 --- /dev/null +++ b/eth/al_hal_eth_kr.c @@ -0,0 +1,1030 @@ +/*- +******************************************************************************* +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. + +*******************************************************************************/ +/** + * Ethernet + * @{ + * @file al_hal_eth_kr.c + * + * @brief KR HAL driver for main functions (auto-neg, Link Training) + * + */ + +#include "al_hal_eth_kr.h" +#include "al_hal_eth_mac_regs.h" +#include "al_hal_an_lt_wrapper_regs.h" + +enum al_eth_lt_unit_rev { + AL_ETH_LT_UNIT_REV_1 = 0, + AL_ETH_LT_UNIT_REV_2, + + AL_ETH_LT_UNIT_REV_MAX +}; + +enum al_eth_an_lt_regs_ids { + AL_ETH_KR_AN_CONTROL = 0, + AL_ETH_KR_AN_STATUS, + AL_ETH_KR_AN_ADV0, + AL_ETH_KR_AN_ADV1, + AL_ETH_KR_AN_ADV2, + AL_ETH_KR_AN_REM_ADV0, + AL_ETH_KR_AN_REM_ADV1, + AL_ETH_KR_AN_REM_ADV2, + AL_ETH_KR_PMD_CONTROL, + AL_ETH_KR_PMD_STATUS, + AL_ETH_KR_PMD_LP_COEF_UP, + AL_ETH_KR_PMD_LP_STATUS_REPORT, + AL_ETH_KR_PMD_LD_COEF_UP, + AL_ETH_KR_PMD_LD_STATUS_REPORT, + AL_ETH_KR_AN_XNP_ADV0, + AL_ETH_KR_AN_XNP_ADV1, + AL_ETH_KR_AN_XNP_ADV2, + AL_ETH_KR_AN_REM_XNP_ADV0, + AL_ETH_KR_AN_REM_XNP_ADV1, + AL_ETH_KR_AN_REM_XNP_ADV2, +}; + +static uint32_t al_eth_an_lt_regs_addr[][AL_ETH_LT_UNIT_REV_MAX] = { + [AL_ETH_KR_AN_CONTROL] = {0 , 0x0}, + [AL_ETH_KR_AN_STATUS] = {1 , 0x4}, + [AL_ETH_KR_AN_ADV0] = {16 , 0x8}, + [AL_ETH_KR_AN_ADV1] = {17 , 0xc}, + [AL_ETH_KR_AN_ADV2] = {18 , 0x10}, + [AL_ETH_KR_AN_REM_ADV0] = {19 , 0x14}, + [AL_ETH_KR_AN_REM_ADV1] = {20 , 0x18}, + [AL_ETH_KR_AN_REM_ADV2] = {21 , 0x1c}, + [AL_ETH_KR_PMD_CONTROL] = {150, 0x400}, + [AL_ETH_KR_PMD_STATUS] = {151, 0x404}, + [AL_ETH_KR_PMD_LP_COEF_UP] = {152, 0x408}, + [AL_ETH_KR_PMD_LP_STATUS_REPORT] = {153, 0x40c}, + [AL_ETH_KR_PMD_LD_COEF_UP] = {154, 0x410}, + [AL_ETH_KR_PMD_LD_STATUS_REPORT] = {155, 0x414}, + [AL_ETH_KR_AN_XNP_ADV0] = {22 , 0x24}, + [AL_ETH_KR_AN_XNP_ADV1] = {23 , 0x28}, + [AL_ETH_KR_AN_XNP_ADV2] = {24 , 0x2c}, + [AL_ETH_KR_AN_REM_XNP_ADV0] = {25 , 0x30}, + [AL_ETH_KR_AN_REM_XNP_ADV1] = {26 , 0x34}, + [AL_ETH_KR_AN_REM_XNP_ADV2] = {27 , 0x38}, +}; + + +/* + * AN(Auto Negotiation) registers + * (read / write indirect with al_eth_an_reg_read/write) + */ +#define AL_ETH_KR_AN_CONTROL_RESTART AL_BIT(9) +#define AL_ETH_KR_AN_CONTROL_ENABLE AL_BIT(12) +#define AL_ETH_KR_AN_CONTROL_NP_ENABLE AL_BIT(13) + +#define AL_ETH_KR_AN_STATUS_COMPLETED AL_BIT(5) +#define AL_ETH_KR_AN_STATUS_BASE_PAGE_RECEIVED AL_BIT(6) +#define AL_ETH_KR_AN_STATUS_CHECK_MASK 0xFF0A +#define AL_ETH_KR_AN_STATUS_CHECK_NO_ERROR 0x0008 + +/* AN advertising registers parsing */ +/* register 1 */ +#define AL_ETH_KR_AN_ADV1_SEL_FIELD_MASK 0x001f +#define AL_ETH_KR_AN_ADV1_SEL_FIELD_SHIFT 0 +#define AL_ETH_KR_AN_ADV1_ECHOED_NONCE_MASK 0x03e0 +#define AL_ETH_KR_AN_ADV1_ECHOED_NONCE_SHIFT 5 +#define AL_ETH_KR_AN_ADV1_CAPABILITY_MASK 0x1c00 +#define AL_ETH_KR_AN_ADV1_CAPABILITY_SHIFT 10 +#define AL_ETH_KR_AN_ADV1_REM_FAULT_MASK 0x2000 +#define AL_ETH_KR_AN_ADV1_REM_FAULT_SHIFT 13 +#define AL_ETH_KR_AN_ADV1_ACK_MASK 0x4000 +#define AL_ETH_KR_AN_ADV1_ACK_SHIFT 14 +#define AL_ETH_KR_AN_ADV1_NEXT_PAGE_MASK 0x8000 +#define AL_ETH_KR_AN_ADV1_NEXT_PAGE_SHIFT 15 +/* register 2 */ +#define AL_ETH_KR_AN_ADV2_TX_NONCE_MASK 0x001f +#define AL_ETH_KR_AN_ADV2_TX_NONCE_SHIFT 0 +#define AL_ETH_KR_AN_ADV2_TECH_MASK 0xffe0 +#define AL_ETH_KR_AN_ADV2_TECH_SHIFT 5 +/* register 3 */ +/* TECH field in the third register is extended to the field in the second + * register and it is currently reserved (should be always 0) */ +#define AL_ETH_KR_AN_ADV3_TECH_MASK 0x1fff +#define AL_ETH_KR_AN_ADV3_TECH_SHIFT 0 +#define AL_ETH_KR_AN_ADV3_FEC_MASK 0xc000 +#define AL_ETH_KR_AN_ADV3_FEC_SHIFT 14 + +/* Next Page Fields */ +/* register 1 */ +#define AL_ETH_KR_AN_NP_ADV1_DATA1_MASK 0x07ff +#define AL_ETH_KR_AN_NP_ADV1_DATA1_SHIFT 0 +#define AL_ETH_KR_AN_NP_ADV1_TOGGLE_MASK 0x0800 +#define AL_ETH_KR_AN_NP_ADV1_TOGGLE_SHIFT 11 +#define AL_ETH_KR_AN_NP_ADV1_ACK2_MASK 0x1000 +#define AL_ETH_KR_AN_NP_ADV1_ACK2_SHIFT 12 +#define AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_MASK 0x2000 +#define AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_SHIFT 13 +#define AL_ETH_KR_AN_NP_ADV1_NP_MASK 0x8000 +#define AL_ETH_KR_AN_NP_ADV1_NP_SHIFT 15 + +/* + * LT(Link Training) registers + * (read / write indirect with al_eth_pma_reg_read/write) + */ +#define AL_ETH_KR_PMD_CONTROL_RESTART 0 +#define AL_ETH_KR_PMD_CONTROL_ENABLE 1 + +#define AL_ETH_KR_PMD_STATUS_RECEIVER_COMPLETED_SHIFT 0 +#define AL_ETH_KR_PMD_STATUS_RECEIVER_FRAME_LOCK_SHIFT 1 +#define AL_ETH_KR_PMD_STATUS_RECEIVER_START_UP_PROTO_PROG_SHIFT 2 +#define AL_ETH_KR_PMD_STATUS_FAILURE_SHIFT 3 + +#define AL_ETH_KR_PMD_LP_COEF_UP_MINUS_MASK 0x0003 +#define AL_ETH_KR_PMD_LP_COEF_UP_MINUS_SHIFT 0 +#define AL_ETH_KR_PMD_LP_COEF_UP_ZERO_MASK 0x000C +#define AL_ETH_KR_PMD_LP_COEF_UP_ZERO_SHIFT 2 +#define AL_ETH_KR_PMD_LP_COEF_UP_PLUS_MASK 0x0030 +#define AL_ETH_KR_PMD_LP_COEF_UP_PLUS_SHIFT 4 +#define AL_ETH_KR_PMD_LP_COEF_UP_INITIALIZE_SHIFT 12 +#define AL_ETH_KR_PMD_LP_COEF_UP_PRESET_SHIFT 13 + +#define AL_ETH_KR_PMD_LP_STATUS_REPORT_MINUS_MASK 0x0003 +#define AL_ETH_KR_PMD_LP_STATUS_REPORT_MINUS_SHIFT 0 +#define AL_ETH_KR_PMD_LP_STATUS_REPORT_ZERO_MASK 0x000C +#define AL_ETH_KR_PMD_LP_STATUS_REPORT_ZERO_SHIFT 2 +#define AL_ETH_KR_PMD_LP_STATUS_REPORT_PLUS_MASK 0x0030 +#define AL_ETH_KR_PMD_LP_STATUS_REPORT_PLUS_SHIFT 4 +#define AL_ETH_KR_PMD_LP_STATUS_RECEIVER_READY_SHIFT 15 + +#define AL_ETH_KR_PMD_LD_COEF_UP_MINUS_MASK 0x0003 +#define AL_ETH_KR_PMD_LD_COEF_UP_MINUS_SHIFT 0 +#define AL_ETH_KR_PMD_LD_COEF_UP_ZERO_MASK 0x000C +#define AL_ETH_KR_PMD_LD_COEF_UP_ZERO_SHIFT 2 +#define AL_ETH_KR_PMD_LD_COEF_UP_PLUS_MASK 0x0030 +#define AL_ETH_KR_PMD_LD_COEF_UP_PLUS_SHIFT 4 +#define AL_ETH_KR_PMD_LD_COEF_UP_INITIALIZE_SHIFT 12 +#define AL_ETH_KR_PMD_LD_COEF_UP_PRESET_SHIFT 13 + +#define AL_ETH_KR_PMD_LD_STATUS_REPORT_MINUS_MASK 0x0003 +#define AL_ETH_KR_PMD_LD_STATUS_REPORT_MINUS_SHIFT 0 +#define AL_ETH_KR_PMD_LD_STATUS_REPORT_ZERO_MASK 0x000C +#define AL_ETH_KR_PMD_LD_STATUS_REPORT_ZERO_SHIFT 2 +#define AL_ETH_KR_PMD_LD_STATUS_REPORT_PLUS_MASK 0x0030 +#define AL_ETH_KR_PMD_LD_STATUS_REPORT_PLUS_SHIFT 4 +#define AL_ETH_KR_PMD_LD_STATUS_REPORT_RECEIVER_READY_SHIFT 15 + + +enum al_eth_an_lt_regs { + AL_ETH_AN_REGS, + AL_ETH_LT_REGS, +}; + +static uint16_t al_eth_an_lt_reg_read( + struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_regs_ids reg_id, + enum al_eth_an_lt_regs an_lt, + enum al_eth_an_lt_lane lane) +{ + uint32_t val; + uint16_t reg_addr; + + if (adapter->rev_id < AL_ETH_REV_ID_3) { + al_assert(lane == AL_ETH_AN__LT_LANE_0); + + reg_addr = al_eth_an_lt_regs_addr[reg_id][AL_ETH_LT_UNIT_REV_1]; + if (an_lt == AL_ETH_AN_REGS) { + al_reg_write32(&adapter->mac_regs_base->kr.an_addr, reg_addr); + val = al_reg_read32(&adapter->mac_regs_base->kr.an_data); + } else { + al_reg_write32(&adapter->mac_regs_base->kr.pma_addr, reg_addr); + val = al_reg_read32(&adapter->mac_regs_base->kr.pma_data); + } + } else { + struct al_an_lt_wrapper_regs *regs = NULL; + + reg_addr = al_eth_an_lt_regs_addr[reg_id][AL_ETH_LT_UNIT_REV_2]; + + switch (lane) { + case AL_ETH_AN__LT_LANE_0: + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr, + (uintptr_t)®s->an_lt[adapter->curr_lt_unit].addr); + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_data, + reg_addr); + + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr, + (uintptr_t)®s->an_lt[adapter->curr_lt_unit].data); + val = al_reg_read32(&adapter->mac_regs_base->gen_v3.an_lt_0_data); + break; + case AL_ETH_AN__LT_LANE_1: + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr, + (uintptr_t)®s->an_lt[adapter->curr_lt_unit].addr); + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_data, + reg_addr); + + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr, + (uintptr_t)®s->an_lt[adapter->curr_lt_unit].data); + val = al_reg_read32(&adapter->mac_regs_base->gen_v3.an_lt_1_data); + break; + case AL_ETH_AN__LT_LANE_2: + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr, + (uintptr_t)®s->an_lt[adapter->curr_lt_unit].addr); + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_data, + reg_addr); + + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr, + (uintptr_t)®s->an_lt[adapter->curr_lt_unit].data); + val = al_reg_read32(&adapter->mac_regs_base->gen_v3.an_lt_2_data); + break; + case AL_ETH_AN__LT_LANE_3: + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr, + (uintptr_t)®s->an_lt[adapter->curr_lt_unit].addr); + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_data, + reg_addr); + + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr, + (uintptr_t)®s->an_lt[adapter->curr_lt_unit].data); + val = al_reg_read32(&adapter->mac_regs_base->gen_v3.an_lt_3_data); + break; + default: + al_err("%s: Unknown Lane %d\n", __func__, lane); + return 0; + } + } + + + al_dbg("[%s]: %s - (%s) lane %d, reg %d, val 0x%x", adapter->name, __func__, + (an_lt == AL_ETH_AN_REGS) ? "AN" : "LT", lane, reg_addr, val); + + return (uint16_t)val; +} + +static void al_eth_an_lt_reg_write( + struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_regs_ids reg_id, + enum al_eth_an_lt_regs an_lt, + enum al_eth_an_lt_lane lane, + uint16_t val) +{ + uint16_t reg_addr; + + if (adapter->rev_id < AL_ETH_REV_ID_3) { + reg_addr = al_eth_an_lt_regs_addr[reg_id][AL_ETH_LT_UNIT_REV_1]; + if (an_lt == AL_ETH_AN_REGS) { + al_reg_write32(&adapter->mac_regs_base->kr.an_addr, reg_addr); + al_reg_write32(&adapter->mac_regs_base->kr.an_data, val); + } else { + al_reg_write32(&adapter->mac_regs_base->kr.pma_addr, reg_addr); + al_reg_write32(&adapter->mac_regs_base->kr.pma_data, val); + } + } else { + struct al_an_lt_wrapper_regs *regs = NULL; + + reg_addr = al_eth_an_lt_regs_addr[reg_id][AL_ETH_LT_UNIT_REV_2]; + + switch (lane) { + case AL_ETH_AN__LT_LANE_0: + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr, + (uintptr_t)®s->an_lt[adapter->curr_lt_unit].addr); + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_data, + reg_addr); + + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr, + (uintptr_t)®s->an_lt[adapter->curr_lt_unit].data); + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_data, + val); + break; + case AL_ETH_AN__LT_LANE_1: + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr, + (uintptr_t)®s->an_lt[adapter->curr_lt_unit].addr); + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_data, + reg_addr); + + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr, + (uintptr_t)®s->an_lt[adapter->curr_lt_unit].data); + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_data, + val); + break; + case AL_ETH_AN__LT_LANE_2: + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr, + (uintptr_t)®s->an_lt[adapter->curr_lt_unit].addr); + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_data, + reg_addr); + + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr, + (uintptr_t)®s->an_lt[adapter->curr_lt_unit].data); + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_data, + val); + break; + case AL_ETH_AN__LT_LANE_3: + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr, + (uintptr_t)®s->an_lt[adapter->curr_lt_unit].addr); + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_data, + reg_addr); + + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr, + (uintptr_t)®s->an_lt[adapter->curr_lt_unit].data); + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_data, + val); + break; + default: + al_err("%s: Unknown Lane %d\n", __func__, lane); + return; + } + } + + + al_dbg("[%s]: %s - (%s) lane %d, reg %d, val 0x%x", adapter->name, __func__, + (an_lt == AL_ETH_AN_REGS) ? "AN" : "LT", lane, reg_addr, val); +} + +static void al_eth_an_lt_unit_config(struct al_hal_eth_adapter *adapter) +{ + struct al_an_lt_wrapper_regs *regs = NULL; + uint32_t cfg_lane_0 = (AN_LT_WRAPPER_GEN_CFG_BYPASS_RX | AN_LT_WRAPPER_GEN_CFG_BYPASS_TX); + uint32_t cfg_lane_1 = (AN_LT_WRAPPER_GEN_CFG_BYPASS_RX | AN_LT_WRAPPER_GEN_CFG_BYPASS_TX); + uint32_t cfg_lane_2 = (AN_LT_WRAPPER_GEN_CFG_BYPASS_RX | AN_LT_WRAPPER_GEN_CFG_BYPASS_TX); + uint32_t cfg_lane_3 = (AN_LT_WRAPPER_GEN_CFG_BYPASS_RX | AN_LT_WRAPPER_GEN_CFG_BYPASS_TX); + + switch (adapter->mac_mode) { + case AL_ETH_MAC_MODE_10GbE_Serial: + cfg_lane_0 = 0; + AL_REG_FIELD_SET(cfg_lane_0, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT, + AL_ETH_AN_LT_UNIT_20_BIT); + AL_REG_FIELD_SET(cfg_lane_0, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT, + AL_ETH_AN_LT_UNIT_20_BIT); + + adapter->curr_lt_unit = AL_ETH_AN_LT_UNIT_20_BIT; + + break; + case AL_ETH_MAC_MODE_KR_LL_25G: + cfg_lane_0 = 0; + AL_REG_FIELD_SET(cfg_lane_0, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT, + AL_ETH_AN_LT_UNIT_32_BIT); + AL_REG_FIELD_SET(cfg_lane_0, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT, + AL_ETH_AN_LT_UNIT_32_BIT); + + adapter->curr_lt_unit = AL_ETH_AN_LT_UNIT_32_BIT; + + break; + case AL_ETH_MAC_MODE_XLG_LL_40G: + cfg_lane_0 = 0; + AL_REG_FIELD_SET(cfg_lane_0, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT, + AL_ETH_AN_LT_UNIT_16_BIT); + AL_REG_FIELD_SET(cfg_lane_0, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT, + AL_ETH_AN_LT_UNIT_16_BIT); + + cfg_lane_1 = 0; + AL_REG_FIELD_SET(cfg_lane_1, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT, + AL_ETH_AN_LT_UNIT_16_BIT); + AL_REG_FIELD_SET(cfg_lane_1, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT, + AL_ETH_AN_LT_UNIT_16_BIT); + + cfg_lane_2 = 0; + AL_REG_FIELD_SET(cfg_lane_2, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT, + AL_ETH_AN_LT_UNIT_16_BIT); + AL_REG_FIELD_SET(cfg_lane_2, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT, + AL_ETH_AN_LT_UNIT_16_BIT); + + cfg_lane_3 = 0; + AL_REG_FIELD_SET(cfg_lane_3, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT, + AL_ETH_AN_LT_UNIT_16_BIT); + AL_REG_FIELD_SET(cfg_lane_3, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT, + AL_ETH_AN_LT_UNIT_16_BIT); + + adapter->curr_lt_unit = AL_ETH_AN_LT_UNIT_16_BIT; + + break; + case AL_ETH_MAC_MODE_XLG_LL_50G: + cfg_lane_0 = 0; + AL_REG_FIELD_SET(cfg_lane_0, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT, + AL_ETH_AN_LT_UNIT_32_BIT); + AL_REG_FIELD_SET(cfg_lane_0, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT, + AL_ETH_AN_LT_UNIT_32_BIT); + + cfg_lane_1 = 0; + AL_REG_FIELD_SET(cfg_lane_1, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT, + AL_ETH_AN_LT_UNIT_32_BIT); + AL_REG_FIELD_SET(cfg_lane_1, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK, + AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT, + AL_ETH_AN_LT_UNIT_32_BIT); + + adapter->curr_lt_unit = AL_ETH_AN_LT_UNIT_32_BIT; + + break; + default: + al_err("%s: Unknown mac_mode\n", __func__); + return; + } + + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr, + (uintptr_t)®s->gen.cfg); + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_data, + cfg_lane_0); + + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr, + (uintptr_t)®s->gen.cfg); + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_data, + cfg_lane_1); + + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr, + (uintptr_t)®s->gen.cfg); + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_data, + cfg_lane_2); + + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr, + (uintptr_t)®s->gen.cfg); + al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_data, + cfg_lane_3); +} + +void al_eth_lp_coeff_up_get( + struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane, + struct al_eth_kr_coef_up_data *lpcoeff) +{ + uint16_t reg; + + reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_LP_COEF_UP, AL_ETH_LT_REGS, lane); + + lpcoeff->preset = + (AL_REG_BIT_GET( + reg, AL_ETH_KR_PMD_LP_COEF_UP_PRESET_SHIFT) != 0); + + lpcoeff->initialize = + (AL_REG_BIT_GET( + reg, AL_ETH_KR_PMD_LP_COEF_UP_INITIALIZE_SHIFT) != 0); + + lpcoeff->c_minus = AL_REG_FIELD_GET(reg, + AL_ETH_KR_PMD_LP_COEF_UP_MINUS_MASK, + AL_ETH_KR_PMD_LP_COEF_UP_MINUS_SHIFT); + + lpcoeff->c_zero = AL_REG_FIELD_GET(reg, + AL_ETH_KR_PMD_LP_COEF_UP_ZERO_MASK, + AL_ETH_KR_PMD_LP_COEF_UP_ZERO_SHIFT); + + lpcoeff->c_plus = AL_REG_FIELD_GET(reg, + AL_ETH_KR_PMD_LP_COEF_UP_PLUS_MASK, + AL_ETH_KR_PMD_LP_COEF_UP_PLUS_SHIFT); +} + +void al_eth_lp_status_report_get( + struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane, + struct al_eth_kr_status_report_data *status) +{ + uint16_t reg; + + reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_LP_STATUS_REPORT, AL_ETH_LT_REGS, lane); + + status->c_minus = AL_REG_FIELD_GET(reg, + AL_ETH_KR_PMD_LP_STATUS_REPORT_MINUS_MASK, + AL_ETH_KR_PMD_LP_STATUS_REPORT_MINUS_SHIFT); + + status->c_zero = AL_REG_FIELD_GET(reg, + AL_ETH_KR_PMD_LP_STATUS_REPORT_ZERO_MASK, + AL_ETH_KR_PMD_LP_STATUS_REPORT_ZERO_SHIFT); + + status->c_plus = AL_REG_FIELD_GET(reg, + AL_ETH_KR_PMD_LP_STATUS_REPORT_PLUS_MASK, + AL_ETH_KR_PMD_LP_STATUS_REPORT_PLUS_SHIFT); + + status->receiver_ready = + (AL_REG_BIT_GET( + reg, AL_ETH_KR_PMD_LP_STATUS_RECEIVER_READY_SHIFT) != 0); + +} + +void al_eth_ld_coeff_up_set( + struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane, + struct al_eth_kr_coef_up_data *ldcoeff) +{ + uint16_t reg = 0; + + if (ldcoeff->preset) + AL_REG_BIT_SET(reg, AL_ETH_KR_PMD_LD_COEF_UP_PRESET_SHIFT); + + if (ldcoeff->initialize) + AL_REG_BIT_SET(reg, AL_ETH_KR_PMD_LD_COEF_UP_INITIALIZE_SHIFT); + + AL_REG_FIELD_SET(reg, + AL_ETH_KR_PMD_LD_COEF_UP_MINUS_MASK, + AL_ETH_KR_PMD_LD_COEF_UP_MINUS_SHIFT, + ldcoeff->c_minus); + + AL_REG_FIELD_SET(reg, + AL_ETH_KR_PMD_LD_COEF_UP_ZERO_MASK, + AL_ETH_KR_PMD_LD_COEF_UP_ZERO_SHIFT, + ldcoeff->c_zero); + + AL_REG_FIELD_SET(reg, + AL_ETH_KR_PMD_LD_COEF_UP_PLUS_MASK, + AL_ETH_KR_PMD_LD_COEF_UP_PLUS_SHIFT, + ldcoeff->c_plus); + + al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_LD_COEF_UP, AL_ETH_LT_REGS, lane, reg); +} + +void al_eth_ld_status_report_set( + struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane, + struct al_eth_kr_status_report_data *status) +{ + uint16_t reg = 0; + + AL_REG_FIELD_SET(reg, + AL_ETH_KR_PMD_LD_STATUS_REPORT_MINUS_MASK, + AL_ETH_KR_PMD_LD_STATUS_REPORT_MINUS_SHIFT, + status->c_minus); + + AL_REG_FIELD_SET(reg, + AL_ETH_KR_PMD_LD_STATUS_REPORT_ZERO_MASK, + AL_ETH_KR_PMD_LD_STATUS_REPORT_ZERO_SHIFT, + status->c_zero); + + AL_REG_FIELD_SET(reg, + AL_ETH_KR_PMD_LD_STATUS_REPORT_PLUS_MASK, + AL_ETH_KR_PMD_LD_STATUS_REPORT_PLUS_SHIFT, + status->c_plus); + + if (status->receiver_ready) + AL_REG_BIT_SET(reg, + AL_ETH_KR_PMD_LD_STATUS_REPORT_RECEIVER_READY_SHIFT); + + al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_LD_STATUS_REPORT, AL_ETH_LT_REGS, lane, reg); +} + +al_bool al_eth_kr_receiver_frame_lock_get(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane) +{ + uint16_t reg; + + reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane); + + return (AL_REG_BIT_GET(reg, + AL_ETH_KR_PMD_STATUS_RECEIVER_FRAME_LOCK_SHIFT) != 0); +} + +al_bool al_eth_kr_startup_proto_prog_get(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane) +{ + uint16_t reg; + + reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane); + + return (AL_REG_BIT_GET( + reg, AL_ETH_KR_PMD_STATUS_RECEIVER_START_UP_PROTO_PROG_SHIFT) != 0); +} + +al_bool al_eth_kr_training_status_fail_get(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane) +{ + uint16_t reg; + + reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane); + + return (AL_REG_BIT_GET(reg, AL_ETH_KR_PMD_STATUS_FAILURE_SHIFT) != 0); +} + +void al_eth_receiver_ready_set(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane) +{ + al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane, 1); +} + +/*************************** auto negotiation *********************************/ +static int al_eth_kr_an_validate_adv(struct al_hal_eth_adapter *adapter, + struct al_eth_an_adv *an_adv) +{ + al_assert(adapter); + + if (an_adv == NULL) + return 0; + + if (an_adv->selector_field != 1) { + al_err("[%s]: %s failed on selector_field (%d)\n", + adapter->name, __func__, an_adv->selector_field); + return -EINVAL; + } + + if (an_adv->capability & AL_BIT(2)) { + al_err("[%s]: %s failed on capability bit 2 (%d)\n", + adapter->name, __func__, an_adv->capability); + return -EINVAL; + } + + if (an_adv->remote_fault) { + al_err("[%s]: %s failed on remote_fault (%d)\n", + adapter->name, __func__, an_adv->remote_fault); + return -EINVAL; + } + + if (an_adv->acknowledge) { + al_err("[%s]: %s failed on acknowledge (%d)\n", + adapter->name, __func__, an_adv->acknowledge); + return -EINVAL; + } + + return 0; +} + +static int al_eth_kr_an_write_adv(struct al_hal_eth_adapter *adapter, + struct al_eth_an_adv *an_adv) +{ + uint16_t reg; + + if(an_adv == NULL) + return 0; + + reg = 0; + AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV1_SEL_FIELD_MASK, + AL_ETH_KR_AN_ADV1_SEL_FIELD_SHIFT, + an_adv->selector_field); + + AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV1_ECHOED_NONCE_MASK, + AL_ETH_KR_AN_ADV1_ECHOED_NONCE_SHIFT, + an_adv->echoed_nonce); + + AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV1_CAPABILITY_MASK, + AL_ETH_KR_AN_ADV1_CAPABILITY_SHIFT, + an_adv->capability); + + AL_REG_BIT_VAL_SET(reg, AL_ETH_KR_AN_ADV1_REM_FAULT_SHIFT, + an_adv->remote_fault); + + AL_REG_BIT_VAL_SET(reg, AL_ETH_KR_AN_ADV1_ACK_SHIFT, + an_adv->acknowledge); + + AL_REG_BIT_VAL_SET(reg, AL_ETH_KR_AN_ADV1_NEXT_PAGE_SHIFT, + an_adv->next_page); + + al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_ADV0, AL_ETH_AN_REGS, + AL_ETH_AN__LT_LANE_0, reg); + + reg = 0; + AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV2_TX_NONCE_MASK, + AL_ETH_KR_AN_ADV2_TX_NONCE_SHIFT, + an_adv->transmitted_nonce); + + AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV2_TECH_MASK, + AL_ETH_KR_AN_ADV2_TECH_SHIFT, + an_adv->technology); + + al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_ADV1, AL_ETH_AN_REGS, + AL_ETH_AN__LT_LANE_0, reg); + + reg = 0; + AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV3_TECH_MASK, + AL_ETH_KR_AN_ADV3_TECH_SHIFT, + an_adv->technology >> 11); + + AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV3_FEC_MASK, + AL_ETH_KR_AN_ADV3_FEC_SHIFT, + an_adv->fec_capability); + + al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_ADV2, AL_ETH_AN_REGS, + AL_ETH_AN__LT_LANE_0, reg); + + return 0; +} + +void al_eth_kr_an_read_adv(struct al_hal_eth_adapter *adapter, + struct al_eth_an_adv *an_adv) +{ + int16_t reg; + + al_assert(an_adv != NULL); + + + reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_REM_ADV0, + AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0); + + an_adv->selector_field = AL_REG_FIELD_GET(reg, + AL_ETH_KR_AN_ADV1_SEL_FIELD_MASK, + AL_ETH_KR_AN_ADV1_SEL_FIELD_SHIFT); + + an_adv->echoed_nonce = AL_REG_FIELD_GET(reg, + AL_ETH_KR_AN_ADV1_ECHOED_NONCE_MASK, + AL_ETH_KR_AN_ADV1_ECHOED_NONCE_SHIFT); + + an_adv->capability = AL_REG_FIELD_GET(reg, + AL_ETH_KR_AN_ADV1_CAPABILITY_MASK, + AL_ETH_KR_AN_ADV1_CAPABILITY_SHIFT); + + an_adv->remote_fault = AL_REG_BIT_GET(reg, + AL_ETH_KR_AN_ADV1_REM_FAULT_SHIFT); + + an_adv->acknowledge = AL_REG_BIT_GET(reg, + AL_ETH_KR_AN_ADV1_ACK_SHIFT); + + an_adv->next_page = AL_REG_BIT_GET(reg, + AL_ETH_KR_AN_ADV1_NEXT_PAGE_SHIFT); + + + reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_REM_ADV1, + AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0); + + an_adv->transmitted_nonce = AL_REG_FIELD_GET(reg, + AL_ETH_KR_AN_ADV2_TX_NONCE_MASK, + AL_ETH_KR_AN_ADV2_TX_NONCE_SHIFT); + + an_adv->technology = AL_REG_FIELD_GET(reg, + AL_ETH_KR_AN_ADV2_TECH_MASK, + AL_ETH_KR_AN_ADV2_TECH_SHIFT); + + + reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_REM_ADV2, + AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0); + + an_adv->technology |= (AL_REG_FIELD_GET(reg, + AL_ETH_KR_AN_ADV3_TECH_MASK, + AL_ETH_KR_AN_ADV3_TECH_SHIFT) << 11); + + an_adv->fec_capability = AL_REG_FIELD_GET(reg, + AL_ETH_KR_AN_ADV3_FEC_MASK, + AL_ETH_KR_AN_ADV3_FEC_SHIFT); +} + +int al_eth_kr_next_page_read(struct al_hal_eth_adapter *adapter, + struct al_eth_an_np *np) +{ + uint16_t reg; + + reg = al_eth_an_lt_reg_read(adapter, + AL_ETH_KR_AN_REM_XNP_ADV0, + AL_ETH_AN_REGS, + AL_ETH_AN__LT_LANE_0); + + np->unformatted_code_field = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_DATA1_MASK, + AL_ETH_KR_AN_NP_ADV1_DATA1_SHIFT); + + np->toggle = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_TOGGLE_MASK, + AL_ETH_KR_AN_NP_ADV1_TOGGLE_SHIFT); + + np->ack2 = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_ACK2_MASK, + AL_ETH_KR_AN_NP_ADV1_ACK2_SHIFT); + + np->msg_page = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_MASK, + AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_SHIFT); + + np->next_page = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_NP_MASK, + AL_ETH_KR_AN_NP_ADV1_NP_SHIFT); + + np->unformatted_code_field1 = al_eth_an_lt_reg_read(adapter, + AL_ETH_KR_AN_REM_XNP_ADV1, + AL_ETH_AN_REGS, + AL_ETH_AN__LT_LANE_0); + np->unformatted_code_field2 = al_eth_an_lt_reg_read(adapter, + AL_ETH_KR_AN_REM_XNP_ADV2, + AL_ETH_AN_REGS, + AL_ETH_AN__LT_LANE_0); + + return 0; +} + +int al_eth_kr_next_page_write(struct al_hal_eth_adapter *adapter, + struct al_eth_an_np *np) +{ + uint16_t reg = 0; + + AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_DATA1_MASK, + AL_ETH_KR_AN_NP_ADV1_DATA1_SHIFT, + np->unformatted_code_field); + AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_TOGGLE_MASK, + AL_ETH_KR_AN_NP_ADV1_TOGGLE_SHIFT, + np->toggle); + AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_ACK2_MASK, + AL_ETH_KR_AN_NP_ADV1_ACK2_SHIFT, + np->ack2); + AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_MASK, + AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_SHIFT, + np->msg_page); + AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_NP_MASK, + AL_ETH_KR_AN_NP_ADV1_NP_SHIFT, + np->next_page); + + al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_XNP_ADV0, AL_ETH_AN_REGS, + AL_ETH_AN__LT_LANE_0, reg); + + al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_XNP_ADV1, AL_ETH_AN_REGS, + AL_ETH_AN__LT_LANE_0, np->unformatted_code_field1); + al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_XNP_ADV2, AL_ETH_AN_REGS, + AL_ETH_AN__LT_LANE_0, np->unformatted_code_field2); + + return 0; +} + +int al_eth_kr_an_init(struct al_hal_eth_adapter *adapter, + struct al_eth_an_adv *an_adv) +{ + int rc; + + if (adapter->rev_id > AL_ETH_REV_ID_2) + al_eth_an_lt_unit_config(adapter); + + rc = al_eth_kr_an_validate_adv(adapter, an_adv); + if (rc) + return rc; + + rc = al_eth_kr_an_write_adv(adapter, an_adv); + if (rc) + return rc; + + /* clear status */ + al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_STATUS, AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0); + + al_dbg("[%s]: autonegotiation initialized successfully", adapter->name); + return 0; +} + +int al_eth_kr_an_start(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane, + al_bool next_page_enable, + al_bool lt_enable) +{ + uint16_t control = AL_ETH_KR_AN_CONTROL_ENABLE | AL_ETH_KR_AN_CONTROL_RESTART; + + al_dbg("Eth [%s]: enable autonegotiation. lt_en %s", + adapter->name, (lt_enable == AL_TRUE) ? "yes" : "no"); + + al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_CONTROL, AL_ETH_LT_REGS, + lane, AL_BIT(AL_ETH_KR_PMD_CONTROL_RESTART)); + + if (next_page_enable == AL_TRUE) + control |= AL_ETH_KR_AN_CONTROL_NP_ENABLE; + + al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_CONTROL, AL_ETH_AN_REGS, + lane, control); + + if (lt_enable == AL_TRUE) { + al_eth_kr_lt_initialize(adapter, lane); + } + + return 0; +} + +void al_eth_kr_an_stop(struct al_hal_eth_adapter *adapter) +{ + al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_CONTROL, AL_ETH_AN_REGS, + AL_ETH_AN__LT_LANE_0, 0); +} + +void al_eth_kr_an_status_check(struct al_hal_eth_adapter *adapter, + al_bool *page_received, + al_bool *an_completed, + al_bool *error) +{ + uint16_t reg; + + reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_STATUS, + AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0); + + if ((reg & AL_ETH_KR_AN_STATUS_CHECK_MASK) != + AL_ETH_KR_AN_STATUS_CHECK_NO_ERROR) { + al_err("[%s]: %s AN_STATUS (0x%x) indicated error\n", + adapter->name, __func__, reg); + + *error = AL_TRUE; + } + + if (reg & AL_ETH_KR_AN_STATUS_BASE_PAGE_RECEIVED) + *page_received = AL_TRUE; + else + *page_received = AL_FALSE; + + if (reg & AL_ETH_KR_AN_STATUS_COMPLETED) + *an_completed = AL_TRUE; + else + *an_completed = AL_FALSE; +} + + +/****************************** KR Link Training *****************************/ +void al_eth_kr_lt_restart(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane) +{ + al_dbg("[%s]: KR LT Restart Link Training.\n", adapter->name); + + al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_CONTROL, AL_ETH_LT_REGS, + lane, (AL_BIT(AL_ETH_KR_PMD_CONTROL_ENABLE) | + AL_BIT(AL_ETH_KR_PMD_CONTROL_RESTART))); +} + +void al_eth_kr_lt_stop(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane) +{ + al_dbg("[%s]: KR LT Stop Link Training.\n", adapter->name); + + al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_CONTROL, AL_ETH_LT_REGS, + lane, AL_BIT(AL_ETH_KR_PMD_CONTROL_RESTART)); +} + +void al_eth_kr_lt_initialize(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane) +{ + al_dbg("[%s]: KR LT Initialize.\n", adapter->name); + + /* Reset LT state machine */ + al_eth_kr_lt_stop(adapter, lane); + + /* clear receiver status */ + al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane, 0); + + /* Coefficient Update to all zero (no command, hold) */ + al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_LD_COEF_UP, AL_ETH_LT_REGS, lane, 0); + /* Coefficient Status to all zero (not_updated) */ + al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_LD_STATUS_REPORT, AL_ETH_LT_REGS, lane, 0); + + /* start */ + al_eth_kr_lt_restart(adapter, lane); +} + +al_bool al_eth_kr_lt_frame_lock_wait(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane, + uint32_t timeout) +{ + uint32_t loop; + uint16_t reg = 0; + + for (loop = 0; loop < timeout; loop++) { + reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane); + + if (AL_REG_BIT_GET(reg, AL_ETH_KR_PMD_STATUS_FAILURE_SHIFT)) { + al_info("[%s]: Failed on Training Failure." + " loops %d PMD STATUS 0x%04x\n", + adapter->name, loop, reg); + + return AL_FALSE; + } + if (AL_REG_BIT_GET(reg, + AL_ETH_KR_PMD_STATUS_RECEIVER_FRAME_LOCK_SHIFT)) { + al_dbg("[%s]: Frame lock received." + " loops %d PMD STATUS 0x%04x\n", + adapter->name, loop, reg); + + return AL_TRUE; + } + al_udelay(1); + } + al_info("[%s]: Failed on timeout. PMD STATUS 0x%04x\n", + adapter->name, reg); + + return AL_FALSE; +} diff --git a/eth/al_hal_eth_kr.h b/eth/al_hal_eth_kr.h new file mode 100644 index 00000000000..c8b69460aaa --- /dev/null +++ b/eth/al_hal_eth_kr.h @@ -0,0 +1,372 @@ +/*- +******************************************************************************* +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. + +*******************************************************************************/ +/** + * @defgroup group_eth_kr_api API + * Ethernet KR auto-neg and link-training driver API + * @ingroup group_eth + * @{ + * @file al_hal_eth_kr.h + * + * @brief Header file for KR driver + * + * + */ + +#ifndef __AL_HAL_ETH_KR_H__ +#define __AL_HAL_ETH_KR_H__ + +#include "al_hal_eth.h" + +/* *INDENT-OFF* */ +#ifdef __cplusplus +extern "C" { +#endif +/* *INDENT-ON* */ + +/* AN (Auto-negotiation) Advertisement Registers */ +struct al_eth_an_adv { + /* constant value defining 802.3ap support. + * The suggested value is 0x01.*/ + uint8_t selector_field; + /* Contains arbitrary data. */ + uint8_t echoed_nonce; + /* pause capability. */ + uint8_t capability; + /* Set to 1 to indicate a Remote Fault condition. + * Set to 0 to indicate normal operation.*/ + uint8_t remote_fault; + /* Should always be set to 0. */ + uint8_t acknowledge; + /* Set to 1 to indicate that the device has next pages to send. + * Set to 0 to indicate that that device has no next pages to send. */ + uint8_t next_page; + /* Must be set to an arbitrary value. + * Two devices must have a different nonce for autonegotiation to + * operate (a loopback will not allow autonegotiation to complete). */ + uint8_t transmitted_nonce; + uint32_t technology; +#define AL_ETH_AN_TECH_1000BASE_KX AL_BIT(0) +#define AL_ETH_AN_TECH_10GBASE_KX4 AL_BIT(1) +#define AL_ETH_AN_TECH_10GBASE_KR AL_BIT(2) +#define AL_ETH_AN_TECH_40GBASE_KR4 AL_BIT(3) +#define AL_ETH_AN_TECH_40GBASE_CR4 AL_BIT(4) +#define AL_ETH_AN_TECH_100GBASE_CR AL_BIT(5) + uint8_t fec_capability; +}; + +/* AN next page fields */ +struct al_eth_an_np { + /* These bits can be used as message code field or unformatted code field. + * When msg_page is true, these bits represent message code field. + * Predefined message code field Code Field should be used as specified in the standard + * 802.3ap. + * For the null message code the value is 0x01. + */ + uint16_t unformatted_code_field; + /* Flag to keep track of the state of the local device's Toggle bit. + * Initial value is taken from base page. Set to 0. + */ + al_bool toggle; + /* Acknowledge 2 is used to indicate that the receiver is able to act on the information + * (or perform the task) defined in the message. + */ + al_bool ack2; + al_bool msg_page; + /* If the device does not have any more Next Pages to send, set to AL_FALSE */ + al_bool next_page; + uint16_t unformatted_code_field1; + uint16_t unformatted_code_field2; +}; + +enum al_eth_kr_cl72_cstate { + C72_CSTATE_NOT_UPDATED = 0, + C72_CSTATE_UPDATED = 1, + C72_CSTATE_MIN = 2, + C72_CSTATE_MAX = 3, +}; + +enum al_eth_kr_cl72_coef_op { + AL_PHY_KR_COEF_UP_HOLD = 0, + AL_PHY_KR_COEF_UP_INC = 1, + AL_PHY_KR_COEF_UP_DEC = 2, + AL_PHY_KR_COEF_UP_RESERVED = 3 +}; + +struct al_eth_kr_coef_up_data { + enum al_eth_kr_cl72_coef_op c_zero; + enum al_eth_kr_cl72_coef_op c_plus; + enum al_eth_kr_cl72_coef_op c_minus; + al_bool preset; + al_bool initialize; +}; + +struct al_eth_kr_status_report_data { + enum al_eth_kr_cl72_cstate c_zero; + enum al_eth_kr_cl72_cstate c_plus; + enum al_eth_kr_cl72_cstate c_minus; + al_bool receiver_ready; +}; + +enum al_eth_an_lt_lane { + AL_ETH_AN__LT_LANE_0, + AL_ETH_AN__LT_LANE_1, + AL_ETH_AN__LT_LANE_2, + AL_ETH_AN__LT_LANE_3, +}; + +/** + * get the last received coefficient update message from the link partner + * + * @param adapter pointer to the private structure + * @param lane lane number + * @param lpcoeff coeff update received + * + */ +void al_eth_lp_coeff_up_get( + struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane, + struct al_eth_kr_coef_up_data *lpcoeff); + +/** + * get the last received status report message from the link partner + * + * @param adapter pointer to the private structure + * @param lane lane number + * @param status status report received + * + */ +void al_eth_lp_status_report_get( + struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane, + struct al_eth_kr_status_report_data *status); + +/** + * set the coefficient data for the next message that will be sent to lp + * + * @param adapter pointer to the private structure + * @param lane lane number + * @param ldcoeff coeff update to send + * + */ +void al_eth_ld_coeff_up_set( + struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane, + struct al_eth_kr_coef_up_data *ldcoeff); + +/** + * set the status report message for the next message that will be sent to lp + * + * @param adapter pointer to the private structure + * @param lane lane number + * @param status status report to send + * + */ +void al_eth_ld_status_report_set( + struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane, + struct al_eth_kr_status_report_data *status); + +/** + * get the receiver frame lock status + * + * @param adapter pointer to the private structure + * @param lane lane number + * + * @return true if Training frame delineation is detected, otherwise false. + */ +al_bool al_eth_kr_receiver_frame_lock_get(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane); + +/** + * get the start up protocol progress status + * + * @param adapter pointer to the private structure + * @param lane lane number + * + * @return true if the startup protocol is in progress. + */ +al_bool al_eth_kr_startup_proto_prog_get(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane); + +/** + * indicate the receiver is ready (the link training is completed) + * + * @param adapter pointer to the private structure + * @param lane lane number + * + */ +void al_eth_receiver_ready_set(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane); + +/** + * read Training failure status. + * + * @param adapter pointer to the private structure + * @param lane lane number + * + *@return true if Training failure has been detected. + */ +al_bool al_eth_kr_training_status_fail_get(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane); + +/****************************** auto negotiation *******************************/ +/** + * Initialize Auto-negotiation + * - Program Ability Registers (Advertisement Registers) + * - Clear Status latches + * @param adapter pointer to the private structure + * @param an_adv pointer to the AN Advertisement Registers structure + * when NULL, the registers will not be updated. + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_kr_an_init(struct al_hal_eth_adapter *adapter, + struct al_eth_an_adv *an_adv); + +/** + * Enable/Restart Auto-negotiation + * + * @param adapter pointer to the private structure + * @param lane lane number + * @param lt_enable initialize link training as well + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_kr_an_start(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane, + al_bool next_page_enable, + al_bool lt_enable); + + +int al_eth_kr_next_page_write(struct al_hal_eth_adapter *adapter, + struct al_eth_an_np *np); + +int al_eth_kr_next_page_read(struct al_hal_eth_adapter *adapter, + struct al_eth_an_np *np); + +/** + * Stop Auto-negotiation + * + * Stopping the auto-negotiation will prevent the mac from sending the last page + * to the link partner in case it start the AN again. It must be called after + * link training is completed or the software will lose sync with the HW state + * machine + * + * @param adapter pointer to the private structure + * + */ +void al_eth_kr_an_stop(struct al_hal_eth_adapter *adapter); + +/** + * Check Auto-negotiation event done + * + * @param adapter pointer to the private structure + * @param page_received Set to true if the AN page received indication is set. + * Set to false otherwise. + * @param an_completed Set to true of the AN completed indication is set. + * Set to false otherwise. + * @param error Set to true if any error encountered + * + */ +void al_eth_kr_an_status_check(struct al_hal_eth_adapter *adapter, + al_bool *page_received, + al_bool *an_completed, + al_bool *error); + +/** + * Read the remote auto-negotiation advertising. + * This function is safe to called after al_eth_kr_an_status_check returned + * with page_received set. + * + * @param adapter pointer to the private structure + * @param an_adv pointer to the AN Advertisement Registers structure + * + */ +void al_eth_kr_an_read_adv(struct al_hal_eth_adapter *adapter, + struct al_eth_an_adv *an_adv); + +/****************************** link training **********************************/ +/** + * Initialize Link-training. + * Clear the status register and set the local coefficient update and status + * to zero. + * + * @param adapter pointer to the private structure + * @param lane lane number + * + */ +void al_eth_kr_lt_initialize(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane); + +/** + * Wait for frame lock. + * + * @param adapter pointer to the private structure + * @param lane lane number + * @param timeout timeout in usec. + * + * @return true if frame lock received. false otherwise. + */ +al_bool al_eth_kr_lt_frame_lock_wait(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane, + uint32_t timeout); + +/** + * reset the 10GBase- KR startup protocol and begin its operation + * + * @param adapter pointer to the private structure + * @param lane lane number + * + */ +void al_eth_kr_lt_restart(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane); + +/** + * reset the 10GBase- KR startup protocol and end its operation + * + * @param adapter pointer to the private structure + * @param lane lane number + * + */ +void al_eth_kr_lt_stop(struct al_hal_eth_adapter *adapter, + enum al_eth_an_lt_lane lane); + +#ifdef __cplusplus +} +#endif +/* *INDENT-ON* */ +#endif /*__AL_HAL_ETH_KR_H__*/ +/** @} end of Ethernet kr group */ diff --git a/eth/al_hal_eth_mac_regs.h b/eth/al_hal_eth_mac_regs.h new file mode 100644 index 00000000000..a2dc745ffde --- /dev/null +++ b/eth/al_hal_eth_mac_regs.h @@ -0,0 +1,1809 @@ +/*- +******************************************************************************* +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_eth_mac_regs.h + * + * @brief Ethernet MAC registers + * + */ + +#ifndef __AL_HAL_ETH_MAC_REGS_H__ +#define __AL_HAL_ETH_MAC_REGS_H__ + +#include "al_hal_plat_types.h" + +#ifdef __cplusplus +extern "C" { +#endif +/* +* Unit Registers +*/ + +struct al_eth_mac_1g { + /* [0x0] */ + uint32_t rev; + uint32_t scratch; + uint32_t cmd_cfg; + uint32_t mac_0; + /* [0x10] */ + uint32_t mac_1; + uint32_t frm_len; + uint32_t pause_quant; + uint32_t rx_section_empty; + /* [0x20] */ + uint32_t rx_section_full; + uint32_t tx_section_empty; + uint32_t tx_section_full; + uint32_t rx_almost_empty; + /* [0x30] */ + uint32_t rx_almost_full; + uint32_t tx_almost_empty; + uint32_t tx_almost_full; + uint32_t mdio_addr0; + /* [0x40] */ + uint32_t mdio_addr1; + uint32_t Reserved[5]; + /* [0x58] */ + uint32_t reg_stat; + uint32_t tx_ipg_len; + /* [0x60] */ + uint32_t Reserved1[104]; + /* [0x200] */ + uint32_t phy_regs_base; + uint32_t Reserved2[127]; +}; + +struct al_eth_mac_10g { + /* [0x0] */ + uint32_t rev; + uint32_t scratch; + uint32_t cmd_cfg; + uint32_t mac_0; + /* [0x10] */ + uint32_t mac_1; + uint32_t frm_len; + uint32_t Reserved; + uint32_t rx_fifo_sections; + /* [0x20] */ + uint32_t tx_fifo_sections; + uint32_t rx_fifo_almost_f_e; + uint32_t tx_fifo_almost_f_e; + uint32_t hashtable_load; + /* [0x30] */ + uint32_t mdio_cfg_status; + uint16_t mdio_cmd; + uint16_t reserved1; + uint16_t mdio_data; + uint16_t reserved2; + uint16_t mdio_regaddr; + uint16_t reserved3; + /* [0x40] */ + uint32_t status; + uint32_t tx_ipg_len; + uint32_t Reserved1[3]; + /* [0x54] */ + uint32_t cl01_pause_quanta; + uint32_t cl23_pause_quanta; + uint32_t cl45_pause_quanta; + /* [0x60] */ + uint32_t cl67_pause_quanta; + uint32_t cl01_quanta_thresh; + uint32_t cl23_quanta_thresh; + uint32_t cl45_quanta_thresh; + /* [0x70] */ + uint32_t cl67_quanta_thresh; + uint32_t rx_pause_status; + uint32_t Reserved2; + uint32_t ts_timestamp; + /* [0x80] */ + + uint32_t Reserved3[160]; + + /* [0x300] */ + uint32_t control; + uint32_t status_reg; + uint32_t phy_id[2]; + /* [0x310] */ + uint32_t dev_ability; + uint32_t partner_ability; + uint32_t an_expansion; + uint32_t device_np; + /* [0x320] */ + uint32_t partner_np; + uint32_t Reserved4[9]; + + /* [0x348] */ + uint32_t link_timer_lo; + uint32_t link_timer_hi; + /* [0x350] */ + uint32_t if_mode; + + uint32_t Reserved5[43]; +}; + +struct al_eth_mac_gen { + /* [0x0] Ethernet Controller Version */ + uint32_t version; + uint32_t rsrvd_0[2]; + /* [0xc] MAC selection configuration */ + uint32_t cfg; + /* [0x10] 10/100/1000 MAC external configuration */ + uint32_t mac_1g_cfg; + /* [0x14] 10/100/1000 MAC status */ + uint32_t mac_1g_stat; + /* [0x18] RGMII external configuration */ + uint32_t rgmii_cfg; + /* [0x1c] RGMII status */ + uint32_t rgmii_stat; + /* [0x20] 1/2.5/10G MAC external configuration */ + uint32_t mac_10g_cfg; + /* [0x24] 1/2.5/10G MAC status */ + uint32_t mac_10g_stat; + /* [0x28] XAUI PCS configuration */ + uint32_t xaui_cfg; + /* [0x2c] XAUI PCS status */ + uint32_t xaui_stat; + /* [0x30] RXAUI PCS configuration */ + uint32_t rxaui_cfg; + /* [0x34] RXAUI PCS status */ + uint32_t rxaui_stat; + /* [0x38] Signal detect configuration */ + uint32_t sd_cfg; + /* [0x3c] MDIO control register for MDIO interface 1 */ + uint32_t mdio_ctrl_1; + /* [0x40] MDIO information register for MDIO interface 1 */ + uint32_t mdio_1; + /* [0x44] MDIO control register for MDIO interface 2 */ + uint32_t mdio_ctrl_2; + /* [0x48] MDIO information register for MDIO interface 2 */ + uint32_t mdio_2; + /* [0x4c] XGMII 32 to 64 data FIFO control */ + uint32_t xgmii_dfifo_32_64; + /* [0x50] Reserved 1 out */ + uint32_t mac_res_1_out; + /* [0x54] XGMII 64 to 32 data FIFO control */ + uint32_t xgmii_dfifo_64_32; + /* [0x58] Reserved 1 in */ + uint32_t mac_res_1_in; + /* [0x5c] SerDes TX FIFO control */ + uint32_t sd_fifo_ctrl; + /* [0x60] SerDes TX FIFO status */ + uint32_t sd_fifo_stat; + /* [0x64] SerDes in/out selection */ + uint32_t mux_sel; + /* [0x68] Clock configuration */ + uint32_t clk_cfg; + uint32_t rsrvd_1; + /* [0x70] LOS and SD selection */ + uint32_t los_sel; + /* [0x74] RGMII selection configuration */ + uint32_t rgmii_sel; + /* [0x78] Ethernet LED configuration */ + uint32_t led_cfg; + uint32_t rsrvd[33]; +}; +struct al_eth_mac_kr { + /* [0x0] PCS register file address */ + uint32_t pcs_addr; + /* [0x4] PCS register file data */ + uint32_t pcs_data; + /* [0x8] AN register file address */ + uint32_t an_addr; + /* [0xc] AN register file data */ + uint32_t an_data; + /* [0x10] PMA register file address */ + uint32_t pma_addr; + /* [0x14] PMA register file data */ + uint32_t pma_data; + /* [0x18] MTIP register file address */ + uint32_t mtip_addr; + /* [0x1c] MTIP register file data */ + uint32_t mtip_data; + /* [0x20] KR PCS config */ + uint32_t pcs_cfg; + /* [0x24] KR PCS status */ + uint32_t pcs_stat; + uint32_t rsrvd[54]; +}; +struct al_eth_mac_sgmii { + /* [0x0] PCS register file address */ + uint32_t reg_addr; + /* [0x4] PCS register file data */ + uint32_t reg_data; + /* [0x8] PCS clock divider configuration */ + uint32_t clk_div; + /* [0xc] PCS Status */ + uint32_t link_stat; + uint32_t rsrvd[60]; +}; +struct al_eth_mac_stat { + /* [0x0] Receive rate matching error */ + uint32_t match_fault; + /* [0x4] EEE, number of times the MAC went into low power mode */ + uint32_t eee_in; + /* [0x8] EEE, number of times the MAC went out of low power mode */ + uint32_t eee_out; + /* + * [0xc] 40G PCS, + * FEC corrected error indication + */ + uint32_t v3_pcs_40g_ll_cerr_0; + /* + * [0x10] 40G PCS, + * FEC corrected error indication + */ + uint32_t v3_pcs_40g_ll_cerr_1; + /* + * [0x14] 40G PCS, + * FEC corrected error indication + */ + uint32_t v3_pcs_40g_ll_cerr_2; + /* + * [0x18] 40G PCS, + * FEC corrected error indication + */ + uint32_t v3_pcs_40g_ll_cerr_3; + /* + * [0x1c] 40G PCS, + * FEC uncorrectable error indication + */ + uint32_t v3_pcs_40g_ll_ncerr_0; + /* + * [0x20] 40G PCS, + * FEC uncorrectable error indication + */ + uint32_t v3_pcs_40g_ll_ncerr_1; + /* + * [0x24] 40G PCS, + * FEC uncorrectable error indication + */ + uint32_t v3_pcs_40g_ll_ncerr_2; + /* + * [0x28] 40G PCS, + * FEC uncorrectable error indication + */ + uint32_t v3_pcs_40g_ll_ncerr_3; + /* + * [0x2c] 10G_LL PCS, + * FEC corrected error indication + */ + uint32_t v3_pcs_10g_ll_cerr; + /* + * [0x30] 10G_LL PCS, + * FEC uncorrectable error indication + */ + uint32_t v3_pcs_10g_ll_ncerr; + uint32_t rsrvd[51]; +}; +struct al_eth_mac_stat_lane { + /* [0x0] Character error */ + uint32_t char_err; + /* [0x4] Disparity error */ + uint32_t disp_err; + /* [0x8] Comma detection */ + uint32_t pat; + uint32_t rsrvd[13]; +}; +struct al_eth_mac_gen_v3 { + /* [0x0] ASYNC FIFOs control */ + uint32_t afifo_ctrl; + /* [0x4] TX ASYNC FIFO configuration */ + uint32_t tx_afifo_cfg_1; + /* [0x8] TX ASYNC FIFO configuration */ + uint32_t tx_afifo_cfg_2; + /* [0xc] TX ASYNC FIFO configuration */ + uint32_t tx_afifo_cfg_3; + /* [0x10] TX ASYNC FIFO configuration */ + uint32_t tx_afifo_cfg_4; + /* [0x14] TX ASYNC FIFO configuration */ + uint32_t tx_afifo_cfg_5; + /* [0x18] RX ASYNC FIFO configuration */ + uint32_t rx_afifo_cfg_1; + /* [0x1c] RX ASYNC FIFO configuration */ + uint32_t rx_afifo_cfg_2; + /* [0x20] RX ASYNC FIFO configuration */ + uint32_t rx_afifo_cfg_3; + /* [0x24] RX ASYNC FIFO configuration */ + uint32_t rx_afifo_cfg_4; + /* [0x28] RX ASYNC FIFO configuration */ + uint32_t rx_afifo_cfg_5; + /* [0x2c] MAC selection configuration */ + uint32_t mac_sel; + /* [0x30] 10G LL MAC configuration */ + uint32_t mac_10g_ll_cfg; + /* [0x34] 10G LL MAC control */ + uint32_t mac_10g_ll_ctrl; + /* [0x38] 10G LL PCS configuration */ + uint32_t pcs_10g_ll_cfg; + /* [0x3c] 10G LL PCS status */ + uint32_t pcs_10g_ll_status; + /* [0x40] 40G LL PCS configuration */ + uint32_t pcs_40g_ll_cfg; + /* [0x44] 40G LL PCS status */ + uint32_t pcs_40g_ll_status; + /* [0x48] PCS 40G register file address */ + uint32_t pcs_40g_ll_addr; + /* [0x4c] PCS 40G register file data */ + uint32_t pcs_40g_ll_data; + /* [0x50] 40G LL MAC configuration */ + uint32_t mac_40g_ll_cfg; + /* [0x54] 40G LL MAC status */ + uint32_t mac_40g_ll_status; + /* [0x58] Preamble configuration (high [55:32]) */ + uint32_t preamble_cfg_high; + /* [0x5c] Preamble configuration (low [31:0]) */ + uint32_t preamble_cfg_low; + /* [0x60] MAC 40G register file address */ + uint32_t mac_40g_ll_addr; + /* [0x64] MAC 40G register file data */ + uint32_t mac_40g_ll_data; + /* [0x68] 40G LL MAC control */ + uint32_t mac_40g_ll_ctrl; + /* [0x6c] PCS 40G register file address */ + uint32_t pcs_40g_fec_91_ll_addr; + /* [0x70] PCS 40G register file data */ + uint32_t pcs_40g_fec_91_ll_data; + /* [0x74] 40G LL PCS EEE configuration */ + uint32_t pcs_40g_ll_eee_cfg; + /* [0x78] 40G LL PCS EEE status */ + uint32_t pcs_40g_ll_eee_status; + /* + * [0x7c] SERDES 32-bit interface shift configuration (when swap is + * enabled) + */ + uint32_t serdes_32_tx_shift; + /* + * [0x80] SERDES 32-bit interface shift configuration (when swap is + * enabled) + */ + uint32_t serdes_32_rx_shift; + /* + * [0x84] SERDES 32-bit interface bit selection + */ + uint32_t serdes_32_tx_sel; + /* + * [0x88] SERDES 32-bit interface bit selection + */ + uint32_t serdes_32_rx_sel; + /* [0x8c] AN/LT wrapper control */ + uint32_t an_lt_ctrl; + /* [0x90] AN/LT wrapper register file address */ + uint32_t an_lt_0_addr; + /* [0x94] AN/LT wrapper register file data */ + uint32_t an_lt_0_data; + /* [0x98] AN/LT wrapper register file address */ + uint32_t an_lt_1_addr; + /* [0x9c] AN/LT wrapper register file data */ + uint32_t an_lt_1_data; + /* [0xa0] AN/LT wrapper register file address */ + uint32_t an_lt_2_addr; + /* [0xa4] AN/LT wrapper register file data */ + uint32_t an_lt_2_data; + /* [0xa8] AN/LT wrapper register file address */ + uint32_t an_lt_3_addr; + /* [0xac] AN/LT wrapper register file data */ + uint32_t an_lt_3_data; + /* [0xb0] External SERDES control */ + uint32_t ext_serdes_ctrl; + /* [0xb4] spare bits */ + uint32_t spare; + uint32_t rsrvd[18]; +}; + +struct al_eth_mac_regs { + struct al_eth_mac_1g mac_1g; /* [0x000] */ + struct al_eth_mac_10g mac_10g; /* [0x400] */ + uint32_t rsrvd_0[64]; /* [0x800] */ + struct al_eth_mac_gen gen; /* [0x900] */ + struct al_eth_mac_kr kr; /* [0xa00] */ + struct al_eth_mac_sgmii sgmii; /* [0xb00] */ + struct al_eth_mac_stat stat; /* [0xc00] */ + struct al_eth_mac_stat_lane stat_lane[4]; /* [0xd00] */ + struct al_eth_mac_gen_v3 gen_v3; /* [0xe00] */ +}; + + +/* +* Registers Fields +*/ + +/**** control register (1G mac) ****/ +/* enable Half Duplex */ +#define AL_ETH_1G_MAC_CTRL_HD_EN (1 << 10) +/* enable 1G speed */ +#define AL_ETH_1G_MAC_CTRL_1G_SPD (1 << 3) +/* enable 10M speed */ +#define AL_ETH_1G_MAC_CTRL_10M_SPD (1 << 25) + + +/**** 10G MAC register ****/ +/* mdio_cfg_status */ +#define ETH_10G_MAC_MDIO_CFG_HOLD_TIME_MASK 0x0000001c +#define ETH_10G_MAC_MDIO_CFG_HOLD_TIME_SHIFT 2 + +#define ETH_10G_MAC_MDIO_CFG_HOLD_TIME_1_CLK 0 +#define ETH_10G_MAC_MDIO_CFG_HOLD_TIME_3_CLK 1 +#define ETH_10G_MAC_MDIO_CFG_HOLD_TIME_5_CLK 2 +#define ETH_10G_MAC_MDIO_CFG_HOLD_TIME_7_CLK 3 +#define ETH_10G_MAC_MDIO_CFG_HOLD_TIME_9_CLK 4 +#define ETH_10G_MAC_MDIO_CFG_HOLD_TIME_11_CLK 5 +#define ETH_10G_MAC_MDIO_CFG_HOLD_TIME_13_CLK 6 +#define ETH_10G_MAC_MDIO_CFG_HOLD_TIME_15_CLK 7 + +/**** version register ****/ +/* Revision number (Minor) */ +#define ETH_MAC_GEN_VERSION_RELEASE_NUM_MINOR_MASK 0x000000FF +#define ETH_MAC_GEN_VERSION_RELEASE_NUM_MINOR_SHIFT 0 +/* Revision number (Major) */ +#define ETH_MAC_GEN_VERSION_RELEASE_NUM_MAJOR_MASK 0x0000FF00 +#define ETH_MAC_GEN_VERSION_RELEASE_NUM_MAJOR_SHIFT 8 +/* Date of release */ +#define ETH_MAC_GEN_VERSION_DATE_DAY_MASK 0x001F0000 +#define ETH_MAC_GEN_VERSION_DATE_DAY_SHIFT 16 +/* Month of release */ +#define ETH_MAC_GEN_VERSION_DATA_MONTH_MASK 0x01E00000 +#define ETH_MAC_GEN_VERSION_DATA_MONTH_SHIFT 21 +/* Year of release (starting from 2000) */ +#define ETH_MAC_GEN_VERSION_DATE_YEAR_MASK 0x3E000000 +#define ETH_MAC_GEN_VERSION_DATE_YEAR_SHIFT 25 +/* Reserved */ +#define ETH_MAC_GEN_VERSION_RESERVED_MASK 0xC0000000 +#define ETH_MAC_GEN_VERSION_RESERVED_SHIFT 30 + +/**** cfg register ****/ +/* + * Selects between the 10/100/1000 MAC and the 1/2.5/10G MAC: + * 0 - 10/100/1000 + * 1 - 1/2.5/10G + */ +#define ETH_MAC_GEN_CFG_MAC_1_10 (1 << 0) +/* + * Selects the operation mode of the 1/2.5/10G MAC: + * 00 - 1/2.5G SGMII + * 01 - 10G XAUI/RXAUI + * 10 – 10G KR + * 11 – Reserved + */ +#define ETH_MAC_GEN_CFG_XGMII_SGMII_MASK 0x00000006 +#define ETH_MAC_GEN_CFG_XGMII_SGMII_SHIFT 1 +/* + * Selects the operation mode of the PCS: + * 0 - XAUI + * 1 - RXAUI + */ +#define ETH_MAC_GEN_CFG_XAUI_RXAUI (1 << 3) +/* Swap bits of TBI (SGMII mode) interface */ +#define ETH_MAC_GEN_CFG_SWAP_TBI_RX (1 << 4) +/* + * Determines the offset of the TBI bus on the SerDes interface: + * 0 - LSB + * 1 - MSB + */ +#define ETH_MAC_GEN_CFG_TBI_MSB_RX (1 << 5) +/* + * Selects the SGMII PCS/MAC: + * 0 – 10G MAC with SGMII + * 1 – 1G MAC with SGMII + */ +#define ETH_MAC_GEN_CFG_SGMII_SEL (1 << 6) +/* + * Selects between RGMII and SGMII for the 1G MAC: + * 0 – RGMII + * 1 – SGMII + */ +#define ETH_MAC_GEN_CFG_RGMII_SGMII_SEL (1 << 7) +/* Swap bits of TBI (SGMII mode) interface */ +#define ETH_MAC_GEN_CFG_SWAP_TBI_TX (1 << 8) +/* + * Determines the offset of the TBI bus on the SerDes interface: + * 0 - LSB + * 1 - MSB + */ +#define ETH_MAC_GEN_CFG_TBI_MSB_TX (1 << 9) +/* + * Selection between the MDIO from 10/100/1000 MAC or the 1/2.5/10G MAC + * 0 - 10/100/1000 + * 1 - 1/2.5/10G + */ +#define ETH_MAC_GEN_CFG_MDIO_1_10 (1 << 10) +/* + * Swap MDC output + * 0 – Normal + * 1 – Flipped + */ +#define ETH_MAC_GEN_CFG_MDIO_POL (1 << 11) +/* Swap bits on SerDes interface */ +#define ETH_MAC_GEN_CFG_SWAP_SERDES_RX_MASK 0x000F0000 +#define ETH_MAC_GEN_CFG_SWAP_SERDES_RX_SHIFT 16 +/* Swap bits on SerDes interface */ +#define ETH_MAC_GEN_CFG_SWAP_SERDES_TX_MASK 0x0F000000 +#define ETH_MAC_GEN_CFG_SWAP_SERDES_TX_SHIFT 24 + +/**** mac_1g_cfg register ****/ +/* + * Selection of the input for the "set_1000" input of the Ethernet 10/100/1000 + * MAC: + * 0 - From RGMII converter (automatic speed selection) + * 1 - From register set_1000_def + */ +#define ETH_MAC_GEN_MAC_1G_CFG_SET_1000_SEL (1 << 0) +/* Default value for the 10/100/1000 MAC "set_1000" input */ +#define ETH_MAC_GEN_MAC_1G_CFG_SET_1000_DEF (1 << 1) +/* + * Selection of the input for the "set_10" input of the Ethernet 10/100/1000 + * MAC: + * 0 - From RGMII converter (automatic speed selection) + * 1 - From register set_10_def + */ +#define ETH_MAC_GEN_MAC_1G_CFG_SET_10_SEL (1 << 4) +/* Default value for the 10/100/1000 MAC "set_10" input */ +#define ETH_MAC_GEN_MAC_1G_CFG_SET_10_DEF (1 << 5) +/* Transmit low power enable */ +#define ETH_MAC_GEN_MAC_1G_CFG_LOWP_ENA (1 << 8) +/* + * Enable magic packet mode: + * 0 - Sleep mode + * 1 - Normal operation + */ +#define ETH_MAC_GEN_MAC_1G_CFG_SLEEPN (1 << 9) +/* Swap ff_tx_crc input */ +#define ETH_MAC_GEN_MAC_1G_CFG_SWAP_FF_TX_CRC (1 << 12) + +/**** mac_1g_stat register ****/ +/* Status of the en_10 output form the 10/100/1000 MAC */ +#define ETH_MAC_GEN_MAC_1G_STAT_EN_10 (1 << 0) +/* Status of the eth_mode output from th 10/100/1000 MAC */ +#define ETH_MAC_GEN_MAC_1G_STAT_ETH_MODE (1 << 1) +/* Status of the lowp output from the 10/100/1000 MAC */ +#define ETH_MAC_GEN_MAC_1G_STAT_LOWP (1 << 4) +/* Status of the wakeup output from the 10/100/1000 MAC */ +#define ETH_MAC_GEN_MAC_1G_STAT_WAKEUP (1 << 5) + +/**** rgmii_cfg register ****/ +/* + * Selection of the input for the "set_1000" input of the RGMII converter + * 0 - From MAC + * 1 - From register set_1000_def (automatic speed selection) + */ +#define ETH_MAC_GEN_RGMII_CFG_SET_1000_SEL (1 << 0) +/* Default value for the RGMII converter "set_1000" input */ +#define ETH_MAC_GEN_RGMII_CFG_SET_1000_DEF (1 << 1) +/* + * Selection of the input for the "set_10" input of the RGMII converter: + * 0 - From MAC + * 1 - From register set_10_def (automatic speed selection) + */ +#define ETH_MAC_GEN_RGMII_CFG_SET_10_SEL (1 << 4) +/* Default value for the 10/100/1000 MAC "set_10" input */ +#define ETH_MAC_GEN_RGMII_CFG_SET_10_DEF (1 << 5) +/* Enable automatic speed selection (based on PHY in-band status information) */ +#define ETH_MAC_GEN_RGMII_CFG_ENA_AUTO (1 << 8) +/* Force full duplex, only valid when ena_auto is '1'. */ +#define ETH_MAC_GEN_RGMII_CFG_SET_FD (1 << 9) + +/**** rgmii_stat register ****/ +/* + * Status of the speed output form the RGMII converter + * 00 - 10 Mbps + * 01 - 100 Mbps + * 10 - 1000 Mbps + * 11 - Reserved + */ +#define ETH_MAC_GEN_RGMII_STAT_SPEED_MASK 0x00000003 +#define ETH_MAC_GEN_RGMII_STAT_SPEED_SHIFT 0 +/* + * Link indication from the RGMII converter (valid only if the external PHY + * supports in-band status signaling) + */ +#define ETH_MAC_GEN_RGMII_STAT_LINK (1 << 4) +/* + * Full duplex indication from the RGMII converter (valid only if the external + * PHY supports in-band status signaling) + */ +#define ETH_MAC_GEN_RGMII_STAT_DUP (1 << 5) + +/**** mac_10g_cfg register ****/ +/* Instruct the XGMII to transmit local fault. */ +#define ETH_MAC_GEN_MAC_10G_CFG_TX_LOC_FAULT (1 << 0) +/* Instruct the XGMII to transmit remote fault. */ +#define ETH_MAC_GEN_MAC_10G_CFG_TX_REM_FAULT (1 << 1) +/* Instruct the XGMII to transmit link fault. */ +#define ETH_MAC_GEN_MAC_10G_CFG_TX_LI_FAULT (1 << 2) +/* + * Synchronous reset for the PCS layer. Can be used after SerDes lock assertion + * to reset the PCS state machine. + */ +#define ETH_MAC_GEN_MAC_10G_CFG_SG_SRESET (1 << 3) +/* + * PHY LOS indication selection + * 00 - Select register value from phy_los_def + * 01 - Select input from the SerDes + * 10 - Select input from GPIO + * 11 - Select inverted input from GPIO + */ +#define ETH_MAC_GEN_MAC_10G_CFG_PHY_LOS_SEL_MASK 0x00000030 +#define ETH_MAC_GEN_MAC_10G_CFG_PHY_LOS_SEL_SHIFT 4 +/* + * Default value for PHY LOS indication. Reflects the LOS indication from the + * SerDes. ('0' if not used) + */ +#define ETH_MAC_GEN_MAC_10G_CFG_PHY_LOS_DEF (1 << 6) +/* Reverse polarity of the LOS signal from the SerDes */ +#define ETH_MAC_GEN_MAC_10G_CFG_PHY_LOS_POL (1 << 7) +/* Transmit low power enable */ +#define ETH_MAC_GEN_MAC_10G_CFG_LOWP_ENA (1 << 8) +/* Swap ff_tx_crc input */ +#define ETH_MAC_GEN_MAC_10G_CFG_SWAP_FF_TX_CRC (1 << 12) + +/**** mac_10g_stat register ****/ +/* XGMII RS detects local fault */ +#define ETH_MAC_GEN_MAC_10G_STAT_LOC_FAULT (1 << 0) +/* XGMII RS detects remote fault */ +#define ETH_MAC_GEN_MAC_10G_STAT_REM_FAULT (1 << 1) +/* XGMII RS detects link fault */ +#define ETH_MAC_GEN_MAC_10G_STAT_LI_FAULT (1 << 2) +/* PFC mode */ +#define ETH_MAC_GEN_MAC_10G_STAT_PFC_MODE (1 << 3) + +#define ETH_MAC_GEN_MAC_10G_STAT_SG_ENA (1 << 4) + +#define ETH_MAC_GEN_MAC_10G_STAT_SG_ANDONE (1 << 5) + +#define ETH_MAC_GEN_MAC_10G_STAT_SG_SYNC (1 << 6) + +#define ETH_MAC_GEN_MAC_10G_STAT_SG_SPEED_MASK 0x00000180 +#define ETH_MAC_GEN_MAC_10G_STAT_SG_SPEED_SHIFT 7 +/* Status of the lowp output form the 1/2.5/10G MAC */ +#define ETH_MAC_GEN_MAC_10G_STAT_LOWP (1 << 9) +/* Status of the ts_avail output from th 1/2.5/10G MAC */ +#define ETH_MAC_GEN_MAC_10G_STAT_TS_AVAIL (1 << 10) +/* Transmit pause indication */ +#define ETH_MAC_GEN_MAC_10G_STAT_PAUSE_ON_MASK 0xFF000000 +#define ETH_MAC_GEN_MAC_10G_STAT_PAUSE_ON_SHIFT 24 + +/**** xaui_cfg register ****/ +/* Increase rate matching FIFO threshold */ +#define ETH_MAC_GEN_XAUI_CFG_JUMBO_EN (1 << 0) + +/**** xaui_stat register ****/ +/* Lane alignment status */ +#define ETH_MAC_GEN_XAUI_STAT_ALIGN_DONE (1 << 0) +/* Lane synchronization */ +#define ETH_MAC_GEN_XAUI_STAT_SYNC_MASK 0x000000F0 +#define ETH_MAC_GEN_XAUI_STAT_SYNC_SHIFT 4 +/* Code group alignment indication */ +#define ETH_MAC_GEN_XAUI_STAT_CG_ALIGN_MASK 0x00000F00 +#define ETH_MAC_GEN_XAUI_STAT_CG_ALIGN_SHIFT 8 + +/**** rxaui_cfg register ****/ +/* Increase rate matching FIFO threshold */ +#define ETH_MAC_GEN_RXAUI_CFG_JUMBO_EN (1 << 0) +/* Scrambler enable */ +#define ETH_MAC_GEN_RXAUI_CFG_SRBL_EN (1 << 1) +/* Disparity calculation across lanes enabled */ +#define ETH_MAC_GEN_RXAUI_CFG_DISP_ACROSS_LANE (1 << 2) + +/**** rxaui_stat register ****/ +/* Lane alignment status */ +#define ETH_MAC_GEN_RXAUI_STAT_ALIGN_DONE (1 << 0) +/* Lane synchronization */ +#define ETH_MAC_GEN_RXAUI_STAT_SYNC_MASK 0x000000F0 +#define ETH_MAC_GEN_RXAUI_STAT_SYNC_SHIFT 4 +/* Code group alignment indication */ +#define ETH_MAC_GEN_RXAUI_STAT_CG_ALIGN_MASK 0x00000F00 +#define ETH_MAC_GEN_RXAUI_STAT_CG_ALIGN_SHIFT 8 + +/**** sd_cfg register ****/ +/* + * Signal detect selection + * 0 - from register + * 1 - from SerDes + */ +#define ETH_MAC_GEN_SD_CFG_SEL_MASK 0x0000000F +#define ETH_MAC_GEN_SD_CFG_SEL_SHIFT 0 +/* Signal detect value */ +#define ETH_MAC_GEN_SD_CFG_VAL_MASK 0x000000F0 +#define ETH_MAC_GEN_SD_CFG_VAL_SHIFT 4 +/* Signal detect revers polarity (reverse polarity of signal from the SerDes */ +#define ETH_MAC_GEN_SD_CFG_POL_MASK 0x00000F00 +#define ETH_MAC_GEN_SD_CFG_POL_SHIFT 8 + +/**** mdio_ctrl_1 register ****/ +/* + * Available indication + * 0 - The port was available and it is captured by this Ethernet controller. + * 1 - The port is used by another Ethernet controller. + */ +#define ETH_MAC_GEN_MDIO_CTRL_1_AVAIL (1 << 0) + +/**** mdio_1 register ****/ +/* Current Ethernet interface number that controls the MDIO port */ +#define ETH_MAC_GEN_MDIO_1_INFO_MASK 0x000000FF +#define ETH_MAC_GEN_MDIO_1_INFO_SHIFT 0 + +/**** mdio_ctrl_2 register ****/ +/* + * Available indication + * 0 - The port was available and it is captured by this Ethernet controller. + * 1 - The port is used by another Ethernet controller. + */ +#define ETH_MAC_GEN_MDIO_CTRL_2_AVAIL (1 << 0) + +/**** mdio_2 register ****/ +/* Current Ethernet interface number that controls the MDIO port */ +#define ETH_MAC_GEN_MDIO_2_INFO_MASK 0x000000FF +#define ETH_MAC_GEN_MDIO_2_INFO_SHIFT 0 + +/**** xgmii_dfifo_32_64 register ****/ +/* FIFO enable */ +#define ETH_MAC_GEN_XGMII_DFIFO_32_64_ENABLE (1 << 0) +/* Read Write command every 2 cycles */ +#define ETH_MAC_GEN_XGMII_DFIFO_32_64_RW_2_CYCLES (1 << 1) +/* Swap LSB MSB when creating wider bus */ +#define ETH_MAC_GEN_XGMII_DFIFO_32_64_SWAP_LSB_MSB (1 << 2) +/* Software reset */ +#define ETH_MAC_GEN_XGMII_DFIFO_32_64_SW_RESET (1 << 4) +/* Read threshold */ +#define ETH_MAC_GEN_XGMII_DFIFO_32_64_READ_TH_MASK 0x0000FF00 +#define ETH_MAC_GEN_XGMII_DFIFO_32_64_READ_TH_SHIFT 8 +/* FIFO used */ +#define ETH_MAC_GEN_XGMII_DFIFO_32_64_USED_MASK 0x00FF0000 +#define ETH_MAC_GEN_XGMII_DFIFO_32_64_USED_SHIFT 16 + +/**** xgmii_dfifo_64_32 register ****/ +/* FIFO enable */ +#define ETH_MAC_GEN_XGMII_DFIFO_64_32_ENABLE (1 << 0) +/* Read Write command every 2 cycles */ +#define ETH_MAC_GEN_XGMII_DFIFO_64_32_RW_2_CYCLES (1 << 1) +/* Swap LSB MSB when creating wider bus */ +#define ETH_MAC_GEN_XGMII_DFIFO_64_32_SWAP_LSB_MSB (1 << 2) +/* Software reset */ +#define ETH_MAC_GEN_XGMII_DFIFO_64_32_SW_RESET (1 << 4) +/* Read threshold */ +#define ETH_MAC_GEN_XGMII_DFIFO_64_32_READ_TH_MASK 0x0000FF00 +#define ETH_MAC_GEN_XGMII_DFIFO_64_32_READ_TH_SHIFT 8 +/* FIFO used */ +#define ETH_MAC_GEN_XGMII_DFIFO_64_32_USED_MASK 0x00FF0000 +#define ETH_MAC_GEN_XGMII_DFIFO_64_32_USED_SHIFT 16 + +/**** sd_fifo_ctrl register ****/ +/* FIFO enable */ +#define ETH_MAC_GEN_SD_FIFO_CTRL_ENABLE_MASK 0x0000000F +#define ETH_MAC_GEN_SD_FIFO_CTRL_ENABLE_SHIFT 0 +/* Software reset */ +#define ETH_MAC_GEN_SD_FIFO_CTRL_SW_RESET_MASK 0x000000F0 +#define ETH_MAC_GEN_SD_FIFO_CTRL_SW_RESET_SHIFT 4 +/* Read threshold */ +#define ETH_MAC_GEN_SD_FIFO_CTRL_READ_TH_MASK 0x0000FF00 +#define ETH_MAC_GEN_SD_FIFO_CTRL_READ_TH_SHIFT 8 + +/**** sd_fifo_stat register ****/ +/* FIFO 0 used */ +#define ETH_MAC_GEN_SD_FIFO_STAT_USED_0_MASK 0x000000FF +#define ETH_MAC_GEN_SD_FIFO_STAT_USED_0_SHIFT 0 +/* FIFO 1 used */ +#define ETH_MAC_GEN_SD_FIFO_STAT_USED_1_MASK 0x0000FF00 +#define ETH_MAC_GEN_SD_FIFO_STAT_USED_1_SHIFT 8 +/* FIFO 2 used */ +#define ETH_MAC_GEN_SD_FIFO_STAT_USED_2_MASK 0x00FF0000 +#define ETH_MAC_GEN_SD_FIFO_STAT_USED_2_SHIFT 16 +/* FIFO 3 used */ +#define ETH_MAC_GEN_SD_FIFO_STAT_USED_3_MASK 0xFF000000 +#define ETH_MAC_GEN_SD_FIFO_STAT_USED_3_SHIFT 24 + +/**** mux_sel register ****/ +/* + * SGMII input selection selector + * 00 – SerDes 0 + * 01 – SerDes 1 + * 10 – SerDes 2 + * 11 – SerDes 3 + */ +#define ETH_MAC_GEN_MUX_SEL_SGMII_IN_MASK 0x00000003 +#define ETH_MAC_GEN_MUX_SEL_SGMII_IN_SHIFT 0 +/* + * RXAUI Lane 0 Input + * 00 – SerDes 0 + * 01 – SerDes 1 + * 10 – SerDes 2 + * 11 – SerDes 3 + */ +#define ETH_MAC_GEN_MUX_SEL_RXAUI_0_IN_MASK 0x0000000C +#define ETH_MAC_GEN_MUX_SEL_RXAUI_0_IN_SHIFT 2 +/* + * RXAUI Lane 1 Input + * 00 – SERDES 0 + * 01 – SERDES 1 + * 10 – SERDES 2 + * 11 – SERDES 3 + */ +#define ETH_MAC_GEN_MUX_SEL_RXAUI_1_IN_MASK 0x00000030 +#define ETH_MAC_GEN_MUX_SEL_RXAUI_1_IN_SHIFT 4 +/* + * XAUI Lane 0 Input + * 00 – SERDES 0 + * 01 – SERDES 1 + * 10 – SERDES 2 + * 11 – SERDES 3 + */ +#define ETH_MAC_GEN_MUX_SEL_XAUI_0_IN_MASK 0x000000C0 +#define ETH_MAC_GEN_MUX_SEL_XAUI_0_IN_SHIFT 6 +/* + * XAUI Lane 1 Input + * 00 – SERDES 0 + * 01 – SERDES 1 + * 10 – SERDES 2 + * 11 – SERDES 3 + */ +#define ETH_MAC_GEN_MUX_SEL_XAUI_1_IN_MASK 0x00000300 +#define ETH_MAC_GEN_MUX_SEL_XAUI_1_IN_SHIFT 8 +/* + * XAUI Lane 2 Input + * 00 – SERDES 0 + * 01 – SERDES 1 + * 10 – SERDES 2 + * 11 – SERDES 3 + */ +#define ETH_MAC_GEN_MUX_SEL_XAUI_2_IN_MASK 0x00000C00 +#define ETH_MAC_GEN_MUX_SEL_XAUI_2_IN_SHIFT 10 +/* + * XAUI Lane 3 Input + * 00 – SERDES 0 + * 01 – SERDES 1 + * 10 – SERDES 2 + * 11 – SERDES 3 + */ +#define ETH_MAC_GEN_MUX_SEL_XAUI_3_IN_MASK 0x00003000 +#define ETH_MAC_GEN_MUX_SEL_XAUI_3_IN_SHIFT 12 +/* + * KR PCS Input + * 00 - SERDES 0 + * 01 - SERDES 1 + * 10 - SERDES 2 + * 11 - SERDES 3 + */ +#define ETH_MAC_GEN_MUX_SEL_KR_IN_MASK 0x0000C000 +#define ETH_MAC_GEN_MUX_SEL_KR_IN_SHIFT 14 +/* + * SerDes 0 input selection (TX) + * 000 – XAUI lane 0 + * 001 – XAUI lane 1 + * 010 – XAUI lane 2 + * 011 – XAUI lane 3 + * 100 – RXAUI lane 0 + * 101 – RXAUI lane 1 + * 110 – SGMII + * 111 – KR + */ +#define ETH_MAC_GEN_MUX_SEL_SERDES_0_TX_MASK 0x00070000 +#define ETH_MAC_GEN_MUX_SEL_SERDES_0_TX_SHIFT 16 +/* + * SERDES 1 input selection (Tx) + * 000 – XAUI lane 0 + * 001 – XAUI lane 1 + * 010 – XAUI lane 2 + * 011 – XAUI lane 3 + * 100 – RXAUI lane 0 + * 101 – RXAUI lane 1 + * 110 – SGMII + * 111 – KR + */ +#define ETH_MAC_GEN_MUX_SEL_SERDES_1_TX_MASK 0x00380000 +#define ETH_MAC_GEN_MUX_SEL_SERDES_1_TX_SHIFT 19 +/* + * SerDes 2 input selection (Tx) + * 000 – XAUI lane 0 + * 001 – XAUI lane 1 + * 010 – XAUI lane 2 + * 011 – XAUI lane 3 + * 100 – RXAUI lane 0 + * 101 – RXAUI lane 1 + * 110 – SGMII + * 111 – KR + */ +#define ETH_MAC_GEN_MUX_SEL_SERDES_2_TX_MASK 0x01C00000 +#define ETH_MAC_GEN_MUX_SEL_SERDES_2_TX_SHIFT 22 +/* + * SerDes 3 input selection (Tx) + * 000 – XAUI lane 0 + * 001 – XAUI lane 1 + * 010 – XAUI lane 2 + * 011 – XAUI lane 3 + * 100 – RXAUI lane 0 + * 101 – RXAUI lane 1 + * 110 – SGMII + * 111 – KR + */ +#define ETH_MAC_GEN_MUX_SEL_SERDES_3_TX_MASK 0x0E000000 +#define ETH_MAC_GEN_MUX_SEL_SERDES_3_TX_SHIFT 25 + +/**** clk_cfg register ****/ +/* + * Rx/Tx lane 0 clock MUX select + * must be aligned with data selector MUXs) + * 0 – SerDes 0 clock + * 0 – SerDes 1 clock + * 2 – SerDes 2 clock + * 3 – SerDes 3 clock + */ +#define ETH_MAC_GEN_CLK_CFG_LANE_0_CLK_SEL_MASK 0x00000003 +#define ETH_MAC_GEN_CLK_CFG_LANE_0_CLK_SEL_SHIFT 0 +/* + * Rx/Tx lane 0 clock MUX select must be aligned with data selector MUXs) + * 0 - SerDes 0 clock + * 1 - SerDes 1 clock + * 2 - SerDes 2 clock + * 3 - SerDes 3 clock + */ +#define ETH_MAC_GEN_CLK_CFG_LANE_1_CLK_SEL_MASK 0x00000030 +#define ETH_MAC_GEN_CLK_CFG_LANE_1_CLK_SEL_SHIFT 4 +/* + * RX/TX lane 0 clock MUX select (should be aligned with data selector MUXs) + * 0 - SERDES 0 clock + * 1 - SERDES 1 clock + * 2 - SERDES 2 clock + * 3 - SERDES 3 clock + */ +#define ETH_MAC_GEN_CLK_CFG_LANE_2_CLK_SEL_MASK 0x00000300 +#define ETH_MAC_GEN_CLK_CFG_LANE_2_CLK_SEL_SHIFT 8 +/* + * Rx/Tx lane 0 clock MUX select must be aligned with data selector MUXs) + * 0 - SerDes 0 clock + * 1 - SerDes 1 clock + * 2 - SerDes 2 clock + * 3 - SerDes 3 clock + */ +#define ETH_MAC_GEN_CLK_CFG_LANE_3_CLK_SEL_MASK 0x00003000 +#define ETH_MAC_GEN_CLK_CFG_LANE_3_CLK_SEL_SHIFT 12 +/* + * MAC GMII Rx clock MUX select must be aligned with data selector MUXs) + * 0 – RGMII + * 1 – SGMII + */ +#define ETH_MAC_GEN_CLK_CFG_GMII_RX_CLK_SEL (1 << 16) +/* + * MAC GMII Tx clock MUX select (should be aligned with data selector MUXs) + * 0 - RGMII + * 1 - SGMII + */ +#define ETH_MAC_GEN_CLK_CFG_GMII_TX_CLK_SEL (1 << 18) +/* + * Tx clock MUX select, + * Selects the internal clock for the Tx data path + * 0 – SerDes[0] TX DWORD CLK REF (for RXAUI and SGMII) + * 1 – SerDes[0] TX WORD CLK REF (for XAUI and KR) + */ +#define ETH_MAC_GEN_CLK_CFG_TX_CLK_SEL (1 << 28) +/* + * Rxclock MUX select + * Selects the internal clock for the Rx data path + * 0 – XGMII TX CLK 32 LOCAL (for XAUI and RXAUI and KR) + * 1 – SerDes[0] RX DWORD CLK GENERATED (125M) + * (for SGMII) + */ +#define ETH_MAC_GEN_CLK_CFG_RX_CLK_SEL (1 << 30) + +/**** los_sel register ****/ +/* + * Selected LOS/SD select + * 00 – SerDes 0 + * 01 – SerDes 1 + * 10 – SerDes 2 + * 11 – SerDes 3 + */ +#define ETH_MAC_GEN_LOS_SEL_LANE_0_SEL_MASK 0x00000003 +#define ETH_MAC_GEN_LOS_SEL_LANE_0_SEL_SHIFT 0 +/* + * Selected LOS/SD select + * 00 - SerDes 0 + * 01 - SerDes 1 + * 10 - SerDes 2 + * 11 - SerDes 3 + */ +#define ETH_MAC_GEN_LOS_SEL_LANE_1_SEL_MASK 0x00000030 +#define ETH_MAC_GEN_LOS_SEL_LANE_1_SEL_SHIFT 4 +/* + * Selected LOS/SD select + * 00 - SerDes 0 + * 01 - SerDes 1 + * 10 - SerDes 2 + * 11 - SerDes 3 + */ +#define ETH_MAC_GEN_LOS_SEL_LANE_2_SEL_MASK 0x00000300 +#define ETH_MAC_GEN_LOS_SEL_LANE_2_SEL_SHIFT 8 +/* + * Selected LOS/SD select + * 00 - SerDes 0 + * 01 - SerDes 1 + * 10 - SerDes 2 + * 11 - SerDes 3 + */ +#define ETH_MAC_GEN_LOS_SEL_LANE_3_SEL_MASK 0x00003000 +#define ETH_MAC_GEN_LOS_SEL_LANE_3_SEL_SHIFT 12 + +/**** rgmii_sel register ****/ +/* Swap [3:0] input with [7:4] */ +#define ETH_MAC_GEN_RGMII_SEL_RX_SWAP_3_0 (1 << 0) +/* Swap [4] input with [9] */ +#define ETH_MAC_GEN_RGMII_SEL_RX_SWAP_4 (1 << 1) +/* Swap [7:4] input with [3:0] */ +#define ETH_MAC_GEN_RGMII_SEL_RX_SWAP_7_3 (1 << 2) +/* Swap [9] input with [4] */ +#define ETH_MAC_GEN_RGMII_SEL_RX_SWAP_9 (1 << 3) +/* Swap [3:0] input with [7:4] */ +#define ETH_MAC_GEN_RGMII_SEL_TX_SWAP_3_0 (1 << 4) +/* Swap [4] input with [9] */ +#define ETH_MAC_GEN_RGMII_SEL_TX_SWAP_4 (1 << 5) +/* Swap [7:4] input with [3:0] */ +#define ETH_MAC_GEN_RGMII_SEL_TX_SWAP_7_3 (1 << 6) +/* Swap [9] input with [4] */ +#define ETH_MAC_GEN_RGMII_SEL_TX_SWAP_9 (1 << 7) + +/**** led_cfg register ****/ +/* + * LED source selection: + * 0 – Default reg + * 1 – Rx activity + * 2 – Tx activity + * 3 – Rx | Tx activity + * 4-9 – SGMII LEDs + */ +#define ETH_MAC_GEN_LED_CFG_SEL_MASK 0x0000000F +#define ETH_MAC_GEN_LED_CFG_SEL_SHIFT 0 + +/* turn the led on/off based on default value field (ETH_MAC_GEN_LED_CFG_DEF) */ +#define ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG 0 +#define ETH_MAC_GEN_LED_CFG_SEL_RX_ACTIVITY_DEPRECIATED 1 +#define ETH_MAC_GEN_LED_CFG_SEL_TX_ACTIVITY_DEPRECIATED 2 +#define ETH_MAC_GEN_LED_CFG_SEL_RX_TX_ACTIVITY_DEPRECIATED 3 +#define ETH_MAC_GEN_LED_CFG_SEL_LINK_ACTIVITY 10 + +/* LED default value */ +#define ETH_MAC_GEN_LED_CFG_DEF (1 << 4) +/* LED signal polarity */ +#define ETH_MAC_GEN_LED_CFG_POL (1 << 5) +/* + * activity timer (MSB) + * 32 bit timer @SB clock + */ +#define ETH_MAC_GEN_LED_CFG_ACT_TIMER_MASK 0x00FF0000 +#define ETH_MAC_GEN_LED_CFG_ACT_TIMER_SHIFT 16 +/* + * activity timer (MSB) + * 32 bit timer @SB clock + */ +#define ETH_MAC_GEN_LED_CFG_BLINK_TIMER_MASK 0xFF000000 +#define ETH_MAC_GEN_LED_CFG_BLINK_TIMER_SHIFT 24 + +/**** pcs_addr register ****/ +/* Address value */ +#define ETH_MAC_KR_PCS_ADDR_VAL_MASK 0x0000FFFF +#define ETH_MAC_KR_PCS_ADDR_VAL_SHIFT 0 + +/**** pcs_data register ****/ +/* Data value */ +#define ETH_MAC_KR_PCS_DATA_VAL_MASK 0x0000FFFF +#define ETH_MAC_KR_PCS_DATA_VAL_SHIFT 0 + +/**** an_addr register ****/ +/* Address value */ +#define ETH_MAC_KR_AN_ADDR_VAL_MASK 0x0000FFFF +#define ETH_MAC_KR_AN_ADDR_VAL_SHIFT 0 + +/**** an_data register ****/ +/* Data value */ +#define ETH_MAC_KR_AN_DATA_VAL_MASK 0x0000FFFF +#define ETH_MAC_KR_AN_DATA_VAL_SHIFT 0 + +/**** pma_addr register ****/ +/* Dddress value */ +#define ETH_MAC_KR_PMA_ADDR_VAL_MASK 0x0000FFFF +#define ETH_MAC_KR_PMA_ADDR_VAL_SHIFT 0 + +/**** pma_data register ****/ +/* Data value */ +#define ETH_MAC_KR_PMA_DATA_VAL_MASK 0x0000FFFF +#define ETH_MAC_KR_PMA_DATA_VAL_SHIFT 0 + +/**** mtip_addr register ****/ +/* Address value */ +#define ETH_MAC_KR_MTIP_ADDR_VAL_MASK 0x0000FFFF +#define ETH_MAC_KR_MTIP_ADDR_VAL_SHIFT 0 + +/**** mtip_data register ****/ +/* Data value */ +#define ETH_MAC_KR_MTIP_DATA_VAL_MASK 0x0000FFFF +#define ETH_MAC_KR_MTIP_DATA_VAL_SHIFT 0 + +/**** pcs_cfg register ****/ +/* Enable Auto-Negotiation after Reset */ +#define ETH_MAC_KR_PCS_CFG_STRAP_AN_ENA (1 << 0) +/* + * Signal detect selector for the EEE + * 0 – Register default value + * 1 – SerDes value + */ +#define ETH_MAC_KR_PCS_CFG_EEE_SD_SEL (1 << 4) +/* Signal detect default value for the EEE */ +#define ETH_MAC_KR_PCS_CFG_EEE_DEF_VAL (1 << 5) +/* Signal detect polarity reversal for the EEE */ +#define ETH_MAC_KR_PCS_CFG_EEE_SD_POL (1 << 6) +/* EEE timer value */ +#define ETH_MAC_KR_PCS_CFG_EEE_TIMER_VAL_MASK 0x0000FF00 +#define ETH_MAC_KR_PCS_CFG_EEE_TIMER_VAL_SHIFT 8 +/* + * Selects source for the enable SerDes DME signal + * 0 – Register value + * 1 – PCS output + */ +#define ETH_MAC_KR_PCS_CFG_DME_SEL (1 << 16) +/* DME default value */ +#define ETH_MAC_KR_PCS_CFG_DME_VAL (1 << 17) +/* DME default polarity reversal when selecting PCS output */ +#define ETH_MAC_KR_PCS_CFG_DME_POL (1 << 18) + +/**** pcs_stat register ****/ +/* Link enable by the Auto-Negotiation */ +#define ETH_MAC_KR_PCS_STAT_AN_LINK_CONTROL_MASK 0x0000003F +#define ETH_MAC_KR_PCS_STAT_AN_LINK_CONTROL_SHIFT 0 +/* Block lock */ +#define ETH_MAC_KR_PCS_STAT_BLOCK_LOCK (1 << 8) +/* hi BER */ +#define ETH_MAC_KR_PCS_STAT_HI_BER (1 << 9) + +#define ETH_MAC_KR_PCS_STAT_RX_WAKE_ERR (1 << 16) + +#define ETH_MAC_KR_PCS_STAT_PMA_TXMODE_ALERT (1 << 17) + +#define ETH_MAC_KR_PCS_STAT_PMA_TXMODE_QUIET (1 << 18) + +#define ETH_MAC_KR_PCS_STAT_PMA_RXMODE_QUIET (1 << 19) + +#define ETH_MAC_KR_PCS_STAT_RX_LPI_ACTIVE (1 << 20) + +#define ETH_MAC_KR_PCS_STAT_TX_LPI_ACTIVE (1 << 21) + +/**** reg_addr register ****/ +/* Address value */ +#define ETH_MAC_SGMII_REG_ADDR_VAL_MASK 0x0000001F +#define ETH_MAC_SGMII_REG_ADDR_VAL_SHIFT 0 + +#define ETH_MAC_SGMII_REG_ADDR_CTRL_REG 0x0 +#define ETH_MAC_SGMII_REG_ADDR_IF_MODE_REG 0x14 + +/**** reg_data register ****/ +/* Data value */ +#define ETH_MAC_SGMII_REG_DATA_VAL_MASK 0x0000FFFF +#define ETH_MAC_SGMII_REG_DATA_VAL_SHIFT 0 + +#define ETH_MAC_SGMII_REG_DATA_CTRL_AN_ENABLE (1 << 12) +#define ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_EN (1 << 0) +#define ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_AN (1 << 1) +#define ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_SPEED_MASK 0xC +#define ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_SPEED_SHIFT 2 +#define ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_SPEED_10 0x0 +#define ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_SPEED_100 0x1 +#define ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_SPEED_1000 0x2 +#define ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_DUPLEX (1 << 4) + +/**** clk_div register ****/ +/* Value for 1000M selection */ +#define ETH_MAC_SGMII_CLK_DIV_VAL_1000_MASK 0x000000FF +#define ETH_MAC_SGMII_CLK_DIV_VAL_1000_SHIFT 0 +/* Value for 100M selection */ +#define ETH_MAC_SGMII_CLK_DIV_VAL_100_MASK 0x0000FF00 +#define ETH_MAC_SGMII_CLK_DIV_VAL_100_SHIFT 8 +/* Value for 10M selection */ +#define ETH_MAC_SGMII_CLK_DIV_VAL_10_MASK 0x00FF0000 +#define ETH_MAC_SGMII_CLK_DIV_VAL_10_SHIFT 16 +/* Bypass PCS selection */ +#define ETH_MAC_SGMII_CLK_DIV_BYPASS (1 << 24) +/* + * Divider selection when bypass field is '1', one hot + * 001 – 1000M + * 010 – 100M + * 100 – 10M + */ +#define ETH_MAC_SGMII_CLK_DIV_SEL_MASK 0x0E000000 +#define ETH_MAC_SGMII_CLK_DIV_SEL_SHIFT 25 + +/**** link_stat register ****/ + +#define ETH_MAC_SGMII_LINK_STAT_SET_1000 (1 << 0) + +#define ETH_MAC_SGMII_LINK_STAT_SET_100 (1 << 1) + +#define ETH_MAC_SGMII_LINK_STAT_SET_10 (1 << 2) + +#define ETH_MAC_SGMII_LINK_STAT_LED_AN (1 << 3) + +#define ETH_MAC_SGMII_LINK_STAT_HD_ENA (1 << 4) + +#define ETH_MAC_SGMII_LINK_STAT_LED_LINK (1 << 5) + +/**** afifo_ctrl register ****/ +/* enable tx input operation */ +#define ETH_MAC_GEN_V3_AFIFO_CTRL_EN_TX_IN (1 << 0) +/* enable tx output operation */ +#define ETH_MAC_GEN_V3_AFIFO_CTRL_EN_TX_OUT (1 << 1) +/* enable rx input operation */ +#define ETH_MAC_GEN_V3_AFIFO_CTRL_EN_RX_IN (1 << 4) +/* enable rx output operation */ +#define ETH_MAC_GEN_V3_AFIFO_CTRL_EN_RX_OUT (1 << 5) +/* enable tx FIFO input operation */ +#define ETH_MAC_GEN_V3_AFIFO_CTRL_EN_TX_FIFO_IN (1 << 8) +/* enable tx FIFO output operation */ +#define ETH_MAC_GEN_V3_AFIFO_CTRL_EN_TX_FIFO_OUT (1 << 9) +/* enable rx FIFO input operation */ +#define ETH_MAC_GEN_V3_AFIFO_CTRL_EN_RX_FIFO_IN (1 << 12) +/* enable rx FIFO output operation */ +#define ETH_MAC_GEN_V3_AFIFO_CTRL_EN_RX_FIFO_OUT (1 << 13) + +/**** tx_afifo_cfg_1 register ****/ +/* minimum packet size configuration */ +#define ETH_MAC_GEN_V3_TX_AFIFO_CFG_1_MIN_PKT_SIZE_MASK 0x0000FFFF +#define ETH_MAC_GEN_V3_TX_AFIFO_CFG_1_MIN_PKT_SIZE_SHIFT 0 + +/**** tx_afifo_cfg_2 register ****/ +/* maximum packet size configuration */ +#define ETH_MAC_GEN_V3_TX_AFIFO_CFG_2_MAX_PKT_SIZE_MASK 0x0000FFFF +#define ETH_MAC_GEN_V3_TX_AFIFO_CFG_2_MAX_PKT_SIZE_SHIFT 0 + +/**** tx_afifo_cfg_3 register ****/ +/* input bus width */ +#define ETH_MAC_GEN_V3_TX_AFIFO_CFG_3_INPUT_BUS_W_MASK 0x0000FFFF +#define ETH_MAC_GEN_V3_TX_AFIFO_CFG_3_INPUT_BUS_W_SHIFT 0 +/* input bus width divide factor */ +#define ETH_MAC_GEN_V3_TX_AFIFO_CFG_3_INPUT_BUS_W_F_MASK 0xFFFF0000 +#define ETH_MAC_GEN_V3_TX_AFIFO_CFG_3_INPUT_BUS_W_F_SHIFT 16 + +/**** tx_afifo_cfg_4 register ****/ +/* output bus width */ +#define ETH_MAC_GEN_V3_TX_AFIFO_CFG_4_OUTPUT_BUS_W_MASK 0x0000FFFF +#define ETH_MAC_GEN_V3_TX_AFIFO_CFG_4_OUTPUT_BUS_W_SHIFT 0 +/* output bus width divide factor */ +#define ETH_MAC_GEN_V3_TX_AFIFO_CFG_4_OUTPUT_BUS_W_F_MASK 0xFFFF0000 +#define ETH_MAC_GEN_V3_TX_AFIFO_CFG_4_OUTPUT_BUS_W_F_SHIFT 16 + +/**** tx_afifo_cfg_5 register ****/ +/* + * determines if the input bus is valid/read or “write enableâ€. + * 0 – write enable + * 1 – valid/ready + */ +#define ETH_MAC_GEN_V3_TX_AFIFO_CFG_5_INPUT_BUS_VALID_RDY (1 << 0) +/* + * determines if the output bus is valid/read or “write enableâ€. + * 0 – write enable + * 1 – valid/ready + */ +#define ETH_MAC_GEN_V3_TX_AFIFO_CFG_5_OUTPUT_BUS_VALID_RDY (1 << 1) +/* Swap input bus bytes */ +#define ETH_MAC_GEN_V3_TX_AFIFO_CFG_5_INPUT_BUS_SWAP_BYTES (1 << 4) +/* Swap output bus bytes */ +#define ETH_MAC_GEN_V3_TX_AFIFO_CFG_5_OUTPUT_BUS_SWAP_BYTES (1 << 5) +/* + * output clock select + * 0 – mac_ll_tx_clk + * 1 – clk_mac_sys_clk + */ +#define ETH_MAC_GEN_V3_TX_AFIFO_CFG_5_OUTPUT_CLK_SEL (1 << 8) + +/**** rx_afifo_cfg_1 register ****/ +/* minimum packet size configuration */ +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_1_MIN_PKT_SIZE_MASK 0x0000FFFF +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_1_MIN_PKT_SIZE_SHIFT 0 + +/**** rx_afifo_cfg_2 register ****/ +/* maximum packet size configuration */ +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_2_MAX_PKT_SIZE_MASK 0x0000FFFF +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_2_MAX_PKT_SIZE_SHIFT 0 + +/**** rx_afifo_cfg_3 register ****/ +/* input bus width */ +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_3_INPUT_BUS_W_MASK 0x0000FFFF +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_3_INPUT_BUS_W_SHIFT 0 +/* input bus width divide factor */ +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_3_INPUT_BUS_W_F_MASK 0xFFFF0000 +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_3_INPUT_BUS_W_F_SHIFT 16 + +/**** rx_afifo_cfg_4 register ****/ +/* output bus width */ +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_4_OUTPUT_BUS_W_MASK 0x0000FFFF +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_4_OUTPUT_BUS_W_SHIFT 0 +/* output bus width divide factor */ +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_4_OUTPUT_BUS_W_F_MASK 0xFFFF0000 +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_4_OUTPUT_BUS_W_F_SHIFT 16 + +/**** rx_afifo_cfg_5 register ****/ +/* + * determines if the input bus is valid/read or “write enableâ€. + * 0 – write enable + * 1 – valid/ready + */ +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_5_INPUT_BUS_VALID_RDY (1 << 0) +/* + * determines if the output bus is valid/read or “write enableâ€. + * 0 – write enable + * 1 – valid/ready + */ +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_5_OUTPUT_BUS_VALID_RDY (1 << 1) +/* Swap input bus bytes */ +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_5_INPUT_BUS_SWAP_BYTES (1 << 4) +/* Swap output bus bytes */ +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_5_OUTPUT_BUS_SWAP_BYTES (1 << 5) +/* + * input clock select + * 0 – mac_ll_rx_clk + * 1 – clk_serdes_int_0_tx_dword_ref + * 2 – clk_mac_sys_clk + * 3 – mac_ll_tx_clk + */ +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_5_INPUT_CLK_SEL_MASK 0x00000300 +#define ETH_MAC_GEN_V3_RX_AFIFO_CFG_5_INPUT_CLK_SEL_SHIFT 8 + +/**** mac_sel register ****/ +/* + * Select the MAC that is connected to the SGMII PCS. + * 0 – 1G MAC + * 1 – 10G MAC + */ +#define ETH_MAC_GEN_V3_MAC_SEL_MAC_10G_SGMII (1 << 0) +/* + * Select between the 10G and 40G MAC + * 0 – 10G MAC + * 1 – 40G MAC + */ +#define ETH_MAC_GEN_V3_MAC_SEL_MAC_10G_40G (1 << 4) + +/**** mac_10g_ll_cfg register ****/ +/* + * select between 10G (KR PCS) and 1G (SGMII) mode. + * 0 – 10G + * 1 – 1G + */ +#define ETH_MAC_GEN_V3_MAC_10G_LL_CFG_MODE_1G (1 << 0) +/* enable Magic packet detection in the MAC (all other packets are dropped) */ +#define ETH_MAC_GEN_V3_MAC_10G_LL_CFG_MAGIC_ENA (1 << 5) + +/**** mac_10g_ll_ctrl register ****/ +/* Force the MAC to stop TX transmission after low power mode. */ +#define ETH_MAC_GEN_V3_MAC_10G_LL_CTRL_LPI_TXHOLD (1 << 0) + +/**** pcs_10g_ll_cfg register ****/ +/* RX FEC Enable */ +#define ETH_MAC_GEN_V3_PCS_10G_LL_CFG_FEC_EN_RX (1 << 0) +/* TX FEC enable */ +#define ETH_MAC_GEN_V3_PCS_10G_LL_CFG_FEC_EN_TX (1 << 1) +/* + * RX FEC error propagation enable, + * (debug, always 0) + */ +#define ETH_MAC_GEN_V3_PCS_10G_LL_CFG_FEC_ERR_ENA (1 << 2) +/* + * Gearbox configuration: + * 00 -16 + * 01 – 20 + * 10 – 32 + * 11 – reserved + */ +#define ETH_MAC_GEN_V3_PCS_10G_LL_CFG_TX_GB_CFG_MASK 0x00000030 +#define ETH_MAC_GEN_V3_PCS_10G_LL_CFG_TX_GB_CFG_SHIFT 4 +/* + * Gearbox configuration: + * 00 -16 + * 01 – 20 + * 10 – 32 + * 11 – reserved + */ +#define ETH_MAC_GEN_V3_PCS_10G_LL_CFG_RX_GB_CFG_MASK 0x000000C0 +#define ETH_MAC_GEN_V3_PCS_10G_LL_CFG_RX_GB_CFG_SHIFT 6 + +/**** pcs_10g_ll_status register ****/ +/* FEC locked indication */ +#define ETH_MAC_GEN_V3_PCS_10G_LL_STATUS_FEC_LOCKED (1 << 0) + +/**** pcs_40g_ll_cfg register ****/ +/* RX FEC Enable */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_CFG_FEC_EN_RX_MASK 0x0000000F +#define ETH_MAC_GEN_V3_PCS_40G_LL_CFG_FEC_EN_RX_SHIFT 0 +/* TX FEC enable */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_CFG_FEC_EN_TX_MASK 0x000000F0 +#define ETH_MAC_GEN_V3_PCS_40G_LL_CFG_FEC_EN_TX_SHIFT 4 +/* + * RX FEC error propagation enable, + * (debug, always 0) + */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_CFG_FEC_ERR_EN_MASK 0x00000F00 +#define ETH_MAC_GEN_V3_PCS_40G_LL_CFG_FEC_ERR_EN_SHIFT 8 +/* + * SERDES width, 16 bit enable + * 1 – 16 + * 2 – 32 + */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_CFG_SD_16B (1 << 12) +/* FEC 91 enable */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_CFG_FEC91_ENA (1 << 13) +/* + * PHY LOS indication selection + * 00 - Select register value from phy_los_def + * 01 - Select input from the SerDes + * 10 - Select input from GPIO + * 11 - Select inverted input from GPIO + */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_CFG_PHY_LOS_SEL_MASK 0x00030000 +#define ETH_MAC_GEN_V3_PCS_40G_LL_CFG_PHY_LOS_SEL_SHIFT 16 +/* PHY LOS default value */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_CFG_PHY_LOS_DEF (1 << 18) +/* PHY LOS polarity */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_CFG_PHY_LOS_POL (1 << 19) +/* + * Energy detect indication selection + * 00 - Select register value from phy_los_def + * 01 - Select input from the SerDes + * 10 - Select input from GPIO + * 11 - Select inverted input from GPIO + */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_CFG_ENERGY_DETECT_SEL_MASK 0x00300000 +#define ETH_MAC_GEN_V3_PCS_40G_LL_CFG_ENERGY_DETECT_SEL_SHIFT 20 +/* Energy detect default value */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_CFG_ENERGY_DETECT_DEF (1 << 22) +/* Energy detect polarity */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_CFG_ENERGY_DETECT_POL (1 << 23) + +/**** pcs_40g_ll_status register ****/ +/* Block lock */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_STATUS_BLOCK_LOCK_MASK 0x0000000F +#define ETH_MAC_GEN_V3_PCS_40G_LL_STATUS_BLOCK_LOCK_SHIFT 0 +/* align done */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_STATUS_ALIGN_DONE (1 << 4) +/* high BER */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_STATUS_HIGH_BER (1 << 8) +/* FEC locked indication */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_STATUS_FEC_LOCKED_MASK 0x0000F000 +#define ETH_MAC_GEN_V3_PCS_40G_LL_STATUS_FEC_LOCKED_SHIFT 12 + +/**** pcs_40g_ll_addr register ****/ +/* Address value */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_ADDR_VAL_MASK 0x0001FFFF +#define ETH_MAC_GEN_V3_PCS_40G_LL_ADDR_VAL_SHIFT 0 + +/**** pcs_40g_ll_data register ****/ +/* Data value */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_DATA_VAL_MASK 0x0000FFFF +#define ETH_MAC_GEN_V3_PCS_40G_LL_DATA_VAL_SHIFT 0 + +/**** mac_40g_ll_cfg register ****/ +/* change TX CRC polarity */ +#define ETH_MAC_GEN_V3_MAC_40G_LL_CFG_SWAP_FF_TX_CRC (1 << 0) +/* force TX remote fault */ +#define ETH_MAC_GEN_V3_MAC_40G_LL_CFG_TX_REM_FAULT (1 << 4) +/* force TX local fault */ +#define ETH_MAC_GEN_V3_MAC_40G_LL_CFG_TX_LOC_FAULT (1 << 5) +/* force TX Link fault */ +#define ETH_MAC_GEN_V3_MAC_40G_LL_CFG_TX_LI_FAULT (1 << 6) +/* + * PHY LOS indication selection + * 00 - Select register value from phy_los_def + * 01 - Select input from the SerDes + * 10 - Select input from GPIO + * 11 - Select inverted input from GPIO + */ +#define ETH_MAC_GEN_V3_MAC_40G_LL_CFG_PHY_LOS_SEL_MASK 0x00000300 +#define ETH_MAC_GEN_V3_MAC_40G_LL_CFG_PHY_LOS_SEL_SHIFT 8 +/* PHY LOS default value */ +#define ETH_MAC_GEN_V3_MAC_40G_LL_CFG_PHY_LOS_DEF (1 << 10) +/* PHY LOS polarity */ +#define ETH_MAC_GEN_V3_MAC_40G_LL_CFG_PHY_LOS_POL (1 << 11) + +/**** mac_40g_ll_status register ****/ +/* pause on indication */ +#define ETH_MAC_GEN_V3_MAC_40G_LL_STATUS_PAUSE_ON_MASK 0x000000FF +#define ETH_MAC_GEN_V3_MAC_40G_LL_STATUS_PAUSE_ON_SHIFT 0 +/* local fault indication received */ +#define ETH_MAC_GEN_V3_MAC_40G_LL_STATUS_LOC_FAULT (1 << 8) +/* remote fault indication received */ +#define ETH_MAC_GEN_V3_MAC_40G_LL_STATUS_REM_FAULT (1 << 9) +/* Link fault indication */ +#define ETH_MAC_GEN_V3_MAC_40G_LL_STATUS_LI_FAULT (1 << 10) + +/**** preamble_cfg_high register ****/ +/* preamble value */ +#define ETH_MAC_GEN_V3_PREAMBLE_CFG_HIGH_VAL_MASK 0x00FFFFFF +#define ETH_MAC_GEN_V3_PREAMBLE_CFG_HIGH_VAL_SHIFT 0 + +/**** mac_40g_ll_addr register ****/ +/* Address value */ +#define ETH_MAC_GEN_V3_MAC_40G_LL_ADDR_VAL_MASK 0x000003FF +#define ETH_MAC_GEN_V3_MAC_40G_LL_ADDR_VAL_SHIFT 0 + +/**** mac_40g_ll_ctrl register ****/ +/* Force the MAC to stop TX transmission after low power mode. */ +#define ETH_MAC_GEN_V3_MAC_40G_LL_CTRL_LPI_TXHOLD (1 << 0) + +#define ETH_MAC_GEN_V3_MAC_40G_LL_CTRL_REG_LOWP_ENA (1 << 1) + +/**** pcs_40g_fec_91_ll_addr register ****/ +/* Address value */ +#define ETH_MAC_GEN_V3_PCS_40G_FEC_91_LL_ADDR_VAL_MASK 0x000001FF +#define ETH_MAC_GEN_V3_PCS_40G_FEC_91_LL_ADDR_VAL_SHIFT 0 + +/**** pcs_40g_fec_91_ll_data register ****/ +/* Data value */ +#define ETH_MAC_GEN_V3_PCS_40G_FEC_91_LL_DATA_VAL_MASK 0x0000FFFF +#define ETH_MAC_GEN_V3_PCS_40G_FEC_91_LL_DATA_VAL_SHIFT 0 + +/**** pcs_40g_ll_eee_cfg register ****/ +/* Low power timer configuration */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_EEE_CFG_TIMER_VAL_MASK 0x000000FF +#define ETH_MAC_GEN_V3_PCS_40G_LL_EEE_CFG_TIMER_VAL_SHIFT 0 +/* Low power Fast wake */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_EEE_CFG_LPI_FW (1 << 8) + +/**** pcs_40g_ll_eee_status register ****/ +/* TX LPI mode */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_EEE_STATUS_TX_LPI_MODE_MASK 0x00000003 +#define ETH_MAC_GEN_V3_PCS_40G_LL_EEE_STATUS_TX_LPI_MODE_SHIFT 0 +/* TX LPI state */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_EEE_STATUS_TX_LPI_STATE_MASK 0x00000070 +#define ETH_MAC_GEN_V3_PCS_40G_LL_EEE_STATUS_TX_LPI_STATE_SHIFT 4 +/* TX LPI mode */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_EEE_STATUS_RX_LPI_MODE (1 << 8) +/* TX LPI state */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_EEE_STATUS_RX_LPI_STATE_MASK 0x00007000 +#define ETH_MAC_GEN_V3_PCS_40G_LL_EEE_STATUS_RX_LPI_STATE_SHIFT 12 +/* TX LPI active */ +#define ETH_MAC_GEN_V3_PCS_40G_LL_EEE_STATUS_RX_LPI_ACTIVE (1 << 15) + +/**** serdes_32_tx_shift register ****/ +/* bit shift */ +#define ETH_MAC_GEN_V3_SERDES_32_TX_SHIFT_SERDES_0_MASK 0x0000001F +#define ETH_MAC_GEN_V3_SERDES_32_TX_SHIFT_SERDES_0_SHIFT 0 +/* bit shift */ +#define ETH_MAC_GEN_V3_SERDES_32_TX_SHIFT_SERDES_1_MASK 0x000003E0 +#define ETH_MAC_GEN_V3_SERDES_32_TX_SHIFT_SERDES_1_SHIFT 5 +/* bit shift */ +#define ETH_MAC_GEN_V3_SERDES_32_TX_SHIFT_SERDES_2_MASK 0x00007C00 +#define ETH_MAC_GEN_V3_SERDES_32_TX_SHIFT_SERDES_2_SHIFT 10 +/* bit shift */ +#define ETH_MAC_GEN_V3_SERDES_32_TX_SHIFT_SERDES_3_MASK 0x000F8000 +#define ETH_MAC_GEN_V3_SERDES_32_TX_SHIFT_SERDES_3_SHIFT 15 + +/**** serdes_32_rx_shift register ****/ +/* bit shift */ +#define ETH_MAC_GEN_V3_SERDES_32_RX_SHIFT_SERDES_0_MASK 0x0000001F +#define ETH_MAC_GEN_V3_SERDES_32_RX_SHIFT_SERDES_0_SHIFT 0 +/* bit shift */ +#define ETH_MAC_GEN_V3_SERDES_32_RX_SHIFT_SERDES_1_MASK 0x000003E0 +#define ETH_MAC_GEN_V3_SERDES_32_RX_SHIFT_SERDES_1_SHIFT 5 +/* bit shift */ +#define ETH_MAC_GEN_V3_SERDES_32_RX_SHIFT_SERDES_2_MASK 0x00007C00 +#define ETH_MAC_GEN_V3_SERDES_32_RX_SHIFT_SERDES_2_SHIFT 10 +/* bit shift */ +#define ETH_MAC_GEN_V3_SERDES_32_RX_SHIFT_SERDES_3_MASK 0x000F8000 +#define ETH_MAC_GEN_V3_SERDES_32_RX_SHIFT_SERDES_3_SHIFT 15 + +/**** serdes_32_tx_sel register ****/ +/* + * 0 – directly from serdes + * 1 – swapped + * 2 – swapped with shift + * 3 - legacy (based on gen cfg register) + */ +#define ETH_MAC_GEN_V3_SERDES_32_TX_SEL_SERDES_0_MASK 0x00000003 +#define ETH_MAC_GEN_V3_SERDES_32_TX_SEL_SERDES_0_SHIFT 0 +/* + * 0 – directly from serdes + * 1 – swapped + * 2 – swapped with shift + * 3 - legacy (based on gen cfg register) + */ +#define ETH_MAC_GEN_V3_SERDES_32_TX_SEL_SERDES_1_MASK 0x00000030 +#define ETH_MAC_GEN_V3_SERDES_32_TX_SEL_SERDES_1_SHIFT 4 +/* + * 0 – directly from serdes + * 1 – swapped + * 2 – swapped with shift + * 3 - legacy (based on gen cfg register) + */ +#define ETH_MAC_GEN_V3_SERDES_32_TX_SEL_SERDES_2_MASK 0x00000300 +#define ETH_MAC_GEN_V3_SERDES_32_TX_SEL_SERDES_2_SHIFT 8 +/* + * 0 – directly from serdes + * 1 – swapped + * 2 – swapped with shift + * 3 - legacy (based on gen cfg register) + */ +#define ETH_MAC_GEN_V3_SERDES_32_TX_SEL_SERDES_3_MASK 0x00003000 +#define ETH_MAC_GEN_V3_SERDES_32_TX_SEL_SERDES_3_SHIFT 12 + +/**** serdes_32_rx_sel register ****/ +/* + * 0 – directly from serdes + * 1 – swapped + * 2 – swapped with shift + * 3 - legacy (based on gen cfg register) + */ +#define ETH_MAC_GEN_V3_SERDES_32_RX_SEL_SERDES_0_MASK 0x00000003 +#define ETH_MAC_GEN_V3_SERDES_32_RX_SEL_SERDES_0_SHIFT 0 +/* + * 0 – directly from serdes + * 1 – swapped + * 2 – swapped with shift + * 3 - legacy (based on gen cfg register) + */ +#define ETH_MAC_GEN_V3_SERDES_32_RX_SEL_SERDES_1_MASK 0x00000030 +#define ETH_MAC_GEN_V3_SERDES_32_RX_SEL_SERDES_1_SHIFT 4 +/* + * 0 – directly from serdes + * 1 – swapped + * 2 – swapped with shift + * 3 - legacy (based on gen cfg register) + */ +#define ETH_MAC_GEN_V3_SERDES_32_RX_SEL_SERDES_2_MASK 0x00000300 +#define ETH_MAC_GEN_V3_SERDES_32_RX_SEL_SERDES_2_SHIFT 8 +/* + * 0 – directly from serdes + * 1 – swapped + * 2 – swapped with shift + * 3 - legacy (based on gen cfg register) + */ +#define ETH_MAC_GEN_V3_SERDES_32_RX_SEL_SERDES_3_MASK 0x00003000 +#define ETH_MAC_GEN_V3_SERDES_32_RX_SEL_SERDES_3_SHIFT 12 + +/**** an_lt_ctrl register ****/ +/* reset lane [3:0] */ +#define ETH_MAC_GEN_V3_AN_LT_CTRL_SW_RESET_MASK 0x0000000F +#define ETH_MAC_GEN_V3_AN_LT_CTRL_SW_RESET_SHIFT 0 + +/* PHY LOS indication input selection + * 0 - from serdes + * 1 - from an_lt + */ +#define ETH_MAC_GEN_V3_AN_LT_CTRL_PHY_LOS_SEL_LANE_0 (1 << 8) +/* PHY LOS indication input selection + * 0 - from serdes + * 1 - from an_lt + */ +#define ETH_MAC_GEN_V3_AN_LT_CTRL_PHY_LOS_SEL_LANE_1 (1 << 9) +/* PHY LOS indication input selection + * 0 - from serdes + * 1 - from an_lt + */ +#define ETH_MAC_GEN_V3_AN_LT_CTRL_PHY_LOS_SEL_LANE_2 (1 << 10) +/* PHY LOS indication input selection + * 0 - from serdes + * 1 - from an_lt + */ +#define ETH_MAC_GEN_V3_AN_LT_CTRL_PHY_LOS_SEL_LANE_3 (1 << 11) + +/**** an_lt_0_addr register ****/ +/* Address value */ +#define ETH_MAC_GEN_V3_AN_LT_0_ADDR_VAL_MASK 0x0000FFFF +#define ETH_MAC_GEN_V3_AN_LT_0_ADDR_VAL_SHIFT 0 + +/**** an_lt_1_addr register ****/ +/* Address value */ +#define ETH_MAC_GEN_V3_AN_LT_1_ADDR_VAL_MASK 0x0000FFFF +#define ETH_MAC_GEN_V3_AN_LT_1_ADDR_VAL_SHIFT 0 + +/**** an_lt_2_addr register ****/ +/* Address value */ +#define ETH_MAC_GEN_V3_AN_LT_2_ADDR_VAL_MASK 0x0000FFFF +#define ETH_MAC_GEN_V3_AN_LT_2_ADDR_VAL_SHIFT 0 + +/**** an_lt_3_addr register ****/ +/* Address value */ +#define ETH_MAC_GEN_V3_AN_LT_3_ADDR_VAL_MASK 0x0000FFFF +#define ETH_MAC_GEN_V3_AN_LT_3_ADDR_VAL_SHIFT 0 + +/**** ext_serdes_ctrl register ****/ +/* + * Lane 0, SERDES selection: + * 0 – 10G SERDES, lane 0 + * 1 – 25G SERDES, lane 0 + */ +#define ETH_MAC_GEN_V3_EXT_SERDES_CTRL_LANE_0_SEL_25_10 (1 << 0) +/* + * Lane 1, SERDES selection: + * 0 – 10G SERDES, lane 1 + * 1 – 25G SERDES, lane 1 + */ +#define ETH_MAC_GEN_V3_EXT_SERDES_CTRL_LANE_1_SEL_25_10 (1 << 1) +/* + * Lane 2, SERDES selection: + * 0 – 10G SERDES, lane 2 + * 1 – 25G SERDES, lane 0 + */ +#define ETH_MAC_GEN_V3_EXT_SERDES_CTRL_LANE_2_SEL_25_10 (1 << 2) +/* + * Lane 3, SERDES selection: + * 0 – 10G SERDES, lane 3 + * 1 – 25G SERDES, lane 1 + */ +#define ETH_MAC_GEN_V3_EXT_SERDES_CTRL_LANE_3_SEL_25_10 (1 << 3) + +/* Lane 0 Rx, 25G 40bit-32bit gearshitf sw reset */ +#define ETH_MAC_GEN_V3_EXT_SERDES_CTRL_LANE_0_RX_25_GS_SW_RESET (1 << 4) +/* Lane 0 Tx, 25G 40bit-32bit gearshitf sw reset */ +#define ETH_MAC_GEN_V3_EXT_SERDES_CTRL_LANE_0_TX_25_GS_SW_RESET (1 << 5) +/* Lane 1 Rx, 25G 40bit-32bit gearshitf sw reset */ +#define ETH_MAC_GEN_V3_EXT_SERDES_CTRL_LANE_1_RX_25_GS_SW_RESET (1 << 6) +/* Lane 1 Tx, 25G 40bit-32bit gearshitf sw reset */ +#define ETH_MAC_GEN_V3_EXT_SERDES_CTRL_LANE_1_TX_25_GS_SW_RESET (1 << 7) +/* SerDes 25G gear shift Tx lane selector */ +#define ETH_MAC_GEN_V3_EXT_SERDES_CTRL_SRDS25_GS_TX_LANE_CLK_SEL (1 << 8) + +/*** MAC Core registers addresses ***/ +/* command config */ +#define ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR 0x00000008 +#define ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_TX_ENA (1 << 0) +#define ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_RX_ENA (1 << 1) +#define ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_PFC_MODE (1 << 19) + +/* frame length */ +#define ETH_MAC_GEN_V3_MAC_40G_FRM_LENGTH_ADDR 0x00000014 + +#define ETH_MAC_GEN_V3_MAC_40G_CL01_PAUSE_QUANTA_ADDR 0x00000054 +#define ETH_MAC_GEN_V3_MAC_40G_CL23_PAUSE_QUANTA_ADDR 0x00000058 +#define ETH_MAC_GEN_V3_MAC_40G_CL45_PAUSE_QUANTA_ADDR 0x0000005C +#define ETH_MAC_GEN_V3_MAC_40G_CL67_PAUSE_QUANTA_ADDR 0x00000060 +#define ETH_MAC_GEN_V3_MAC_40G_CL01_QUANTA_THRESH_ADDR 0x00000064 +#define ETH_MAC_GEN_V3_MAC_40G_CL23_QUANTA_THRESH_ADDR 0x00000068 +#define ETH_MAC_GEN_V3_MAC_40G_CL45_QUANTA_THRESH_ADDR 0x0000006C +#define ETH_MAC_GEN_V3_MAC_40G_CL67_QUANTA_THRESH_ADDR 0x00000070 + +/* spare */ +#define ETH_MAC_GEN_V3_SPARE_CHICKEN_DISABLE_TIMESTAMP_STRETCH (1 << 0) + +/*** PCS Core registers addresses ***/ +/* 40g control/status */ +#define ETH_MAC_GEN_V3_PCS_40G_CONTROL_STATUS_ADDR 0x00000000 +/* 10g control_1 */ +#define ETH_MAC_KR_PCS_CONTROL_1_ADDR 0x00000000 + +#define ETH_MAC_KR_AN_MILLISECONDS_COUNTER_ADDR 0x00008000 +#define ETH_MAC_AN_LT_MILLISECONDS_COUNTER_ADDR 0x00000020 + +#ifdef __cplusplus +} +#endif + +#endif /* __AL_HAL_ETH_MAC_REGS_H__ */ + +/** @} end of Ethernet group */ diff --git a/eth/al_hal_eth_main.c b/eth/al_hal_eth_main.c new file mode 100644 index 00000000000..b3a5c70b1f0 --- /dev/null +++ b/eth/al_hal_eth_main.c @@ -0,0 +1,5260 @@ +/*- +******************************************************************************* +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_eth_main.c + * + * @brief XG Ethernet unit HAL driver for main functions (initialization, data path) + * + */ + +#include "al_hal_eth.h" +#include +#include +#include +#include "al_hal_eth_ec_regs.h" +#include "al_hal_eth_mac_regs.h" +#include +#ifdef AL_ETH_EX +#include "al_hal_eth_ex_internal.h" +#endif + +/* Number of xfi_txclk cycles that accumulate into 100ns */ +#define ETH_MAC_KR_PCS_CFG_EEE_TIMER_VAL 52 + +#define AL_ETH_TX_PKT_UDMA_FLAGS (AL_ETH_TX_FLAGS_NO_SNOOP | \ + AL_ETH_TX_FLAGS_INT) + +#define AL_ETH_TX_PKT_META_FLAGS (AL_ETH_TX_FLAGS_IPV4_L3_CSUM | \ + AL_ETH_TX_FLAGS_L4_CSUM | \ + AL_ETH_TX_FLAGS_L4_PARTIAL_CSUM | \ + AL_ETH_TX_FLAGS_L2_MACSEC_PKT | \ + AL_ETH_TX_FLAGS_L2_DIS_FCS |\ + AL_ETH_TX_FLAGS_TSO |\ + AL_ETH_TX_FLAGS_TS) + +#define AL_ETH_TX_SRC_VLAN_CNT_MASK 3 +#define AL_ETH_TX_SRC_VLAN_CNT_SHIFT 5 +#define AL_ETH_TX_L4_PROTO_IDX_MASK 0x1F +#define AL_ETH_TX_L4_PROTO_IDX_SHIFT 8 +#define AL_ETH_TX_TUNNEL_MODE_SHIFT 18 +#define AL_ETH_TX_OUTER_L3_PROTO_SHIFT 20 +#define AL_ETH_TX_VLAN_MOD_ADD_SHIFT 22 +#define AL_ETH_TX_VLAN_MOD_DEL_SHIFT 24 +#define AL_ETH_TX_VLAN_MOD_E_SEL_SHIFT 26 +#define AL_ETH_TX_VLAN_MOD_VID_SEL_SHIFT 28 +#define AL_ETH_TX_VLAN_MOD_PBIT_SEL_SHIFT 30 + +/* tx Meta Descriptor defines */ +#define AL_ETH_TX_META_STORE (1 << 21) +#define AL_ETH_TX_META_L3_LEN_MASK 0xff +#define AL_ETH_TX_META_L3_OFF_MASK 0xff +#define AL_ETH_TX_META_L3_OFF_SHIFT 8 +#define AL_ETH_TX_META_MSS_LSB_VAL_SHIFT 22 +#define AL_ETH_TX_META_MSS_MSB_TS_VAL_SHIFT 16 +#define AL_ETH_TX_META_OUTER_L3_LEN_MASK 0x1f +#define AL_ETH_TX_META_OUTER_L3_LEN_SHIFT 24 +#define AL_ETH_TX_META_OUTER_L3_OFF_HIGH_MASK 0x18 +#define AL_ETH_TX_META_OUTER_L3_OFF_HIGH_SHIFT 10 +#define AL_ETH_TX_META_OUTER_L3_OFF_LOW_MASK 0x07 +#define AL_ETH_TX_META_OUTER_L3_OFF_LOW_SHIFT 29 + +/* tx Meta Descriptor defines - MacSec */ +#define AL_ETH_TX_MACSEC_SIGN_SHIFT 0 /* Sign TX pkt */ +#define AL_ETH_TX_MACSEC_ENCRYPT_SHIFT 1 /* Encrypt TX pkt */ +#define AL_ETH_TX_MACSEC_AN_LSB_SHIFT 2 /* Association Number */ +#define AL_ETH_TX_MACSEC_AN_MSB_SHIFT 3 +#define AL_ETH_TX_MACSEC_SC_LSB_SHIFT 4 /* Secured Channel */ +#define AL_ETH_TX_MACSEC_SC_MSB_SHIFT 9 +#define AL_ETH_TX_MACSEC_SECURED_PYLD_LEN_LSB_SHIFT 10 /* Secure Payload Length (0x3FFF for non-SL packets) */ +#define AL_ETH_TX_MACSEC_SECURED_PYLD_LEN_MSB_SHIFT 23 + +/* Rx Descriptor defines */ +#define AL_ETH_RX_L3_PROTO_IDX_MASK 0x1F +#define AL_ETH_RX_SRC_VLAN_CNT_MASK 3 +#define AL_ETH_RX_SRC_VLAN_CNT_SHIFT 5 +#define AL_ETH_RX_L4_PROTO_IDX_MASK 0x1F +#define AL_ETH_RX_L4_PROTO_IDX_SHIFT 8 + +#define AL_ETH_RX_L3_OFFSET_SHIFT 9 +#define AL_ETH_RX_L3_OFFSET_MASK (0x7f << AL_ETH_RX_L3_OFFSET_SHIFT) +#define AL_ETH_RX_HASH_SHIFT 16 +#define AL_ETH_RX_HASH_MASK (0xffff << AL_ETH_RX_HASH_SHIFT) + +#define ETH_MAC_GEN_LED_CFG_BLINK_TIMER_VAL 5 +#define ETH_MAC_GEN_LED_CFG_ACT_TIMER_VAL 7 + +/* Tx VID Table*/ +#define AL_ETH_TX_VLAN_TABLE_UDMA_MASK 0xF +#define AL_ETH_TX_VLAN_TABLE_FWD_TO_MAC (1 << 4) + +/* tx gpd defines */ +#define AL_ETH_TX_GPD_L3_PROTO_MASK 0x1f +#define AL_ETH_TX_GPD_L3_PROTO_SHIFT 0 +#define AL_ETH_TX_GPD_L4_PROTO_MASK 0x1f +#define AL_ETH_TX_GPD_L4_PROTO_SHIFT 5 +#define AL_ETH_TX_GPD_TUNNEL_CTRL_MASK 0x7 +#define AL_ETH_TX_GPD_TUNNEL_CTRL_SHIFT 10 +#define AL_ETH_TX_GPD_SRC_VLAN_CNT_MASK 0x3 +#define AL_ETH_TX_GPD_SRC_VLAN_CNT_SHIFT 13 +#define AL_ETH_TX_GPD_CAM_DATA_2_SHIFT 32 +#define AL_ETH_TX_GPD_CAM_MASK_2_SHIFT 32 +#define AL_ETH_TX_GPD_CAM_CTRL_VALID_SHIFT 31 + +/* tx gcp defines */ +#define AL_ETH_TX_GCP_POLY_SEL_MASK 0x1 +#define AL_ETH_TX_GCP_POLY_SEL_SHIFT 0 +#define AL_ETH_TX_GCP_CRC32_BIT_COMP_MASK 0x1 +#define AL_ETH_TX_GCP_CRC32_BIT_COMP_SHIFT 1 +#define AL_ETH_TX_GCP_CRC32_BIT_SWAP_MASK 0x1 +#define AL_ETH_TX_GCP_CRC32_BIT_SWAP_SHIFT 2 +#define AL_ETH_TX_GCP_CRC32_BYTE_SWAP_MASK 0x1 +#define AL_ETH_TX_GCP_CRC32_BYTE_SWAP_SHIFT 3 +#define AL_ETH_TX_GCP_DATA_BIT_SWAP_MASK 0x1 +#define AL_ETH_TX_GCP_DATA_BIT_SWAP_SHIFT 4 +#define AL_ETH_TX_GCP_DATA_BYTE_SWAP_MASK 0x1 +#define AL_ETH_TX_GCP_DATA_BYTE_SWAP_SHIFT 5 +#define AL_ETH_TX_GCP_TRAIL_SIZE_MASK 0xF +#define AL_ETH_TX_GCP_TRAIL_SIZE_SHIFT 6 +#define AL_ETH_TX_GCP_HEAD_SIZE_MASK 0xFF +#define AL_ETH_TX_GCP_HEAD_SIZE_SHIFT 16 +#define AL_ETH_TX_GCP_HEAD_CALC_MASK 0x1 +#define AL_ETH_TX_GCP_HEAD_CALC_SHIFT 24 +#define AL_ETH_TX_GCP_MASK_POLARITY_MASK 0x1 +#define AL_ETH_TX_GCP_MASK_POLARITY_SHIFT 25 + +#define AL_ETH_TX_GCP_OPCODE_1_MASK 0x3F +#define AL_ETH_TX_GCP_OPCODE_1_SHIFT 0 +#define AL_ETH_TX_GCP_OPCODE_2_MASK 0x3F +#define AL_ETH_TX_GCP_OPCODE_2_SHIFT 6 +#define AL_ETH_TX_GCP_OPCODE_3_MASK 0x3F +#define AL_ETH_TX_GCP_OPCODE_3_SHIFT 12 +#define AL_ETH_TX_GCP_OPSEL_1_MASK 0xF +#define AL_ETH_TX_GCP_OPSEL_1_SHIFT 0 +#define AL_ETH_TX_GCP_OPSEL_2_MASK 0xF +#define AL_ETH_TX_GCP_OPSEL_2_SHIFT 4 +#define AL_ETH_TX_GCP_OPSEL_3_MASK 0xF +#define AL_ETH_TX_GCP_OPSEL_3_SHIFT 8 +#define AL_ETH_TX_GCP_OPSEL_4_MASK 0xF +#define AL_ETH_TX_GCP_OPSEL_4_SHIFT 12 + +/* Tx crc_chksum_replace defines */ +#define L4_CHECKSUM_DIS_AND_L3_CHECKSUM_DIS 0x00 +#define L4_CHECKSUM_DIS_AND_L3_CHECKSUM_EN 0x20 +#define L4_CHECKSUM_EN_AND_L3_CHECKSUM_DIS 0x40 +#define L4_CHECKSUM_EN_AND_L3_CHECKSUM_EN 0x60 + +/* rx gpd defines */ +#define AL_ETH_RX_GPD_OUTER_L3_PROTO_MASK 0x1f +#define AL_ETH_RX_GPD_OUTER_L3_PROTO_SHIFT (3 + 0) +#define AL_ETH_RX_GPD_OUTER_L4_PROTO_MASK 0x1f +#define AL_ETH_RX_GPD_OUTER_L4_PROTO_SHIFT (3 + 8) +#define AL_ETH_RX_GPD_INNER_L3_PROTO_MASK 0x1f +#define AL_ETH_RX_GPD_INNER_L3_PROTO_SHIFT (3 + 16) +#define AL_ETH_RX_GPD_INNER_L4_PROTO_MASK 0x1f +#define AL_ETH_RX_GPD_INNER_L4_PROTO_SHIFT (3 + 24) +#define AL_ETH_RX_GPD_OUTER_PARSE_CTRL_MASK 0xFF +#define AL_ETH_RX_GPD_OUTER_PARSE_CTRL_SHIFT 32 +#define AL_ETH_RX_GPD_INNER_PARSE_CTRL_MASK 0xFF +#define AL_ETH_RX_GPD_INNER_PARSE_CTRL_SHIFT 40 +#define AL_ETH_RX_GPD_L3_PRIORITY_MASK 0xFF +#define AL_ETH_RX_GPD_L3_PRIORITY_SHIFT 48 +#define AL_ETH_RX_GPD_L4_DST_PORT_LSB_MASK 0xFF +#define AL_ETH_RX_GPD_L4_DST_PORT_LSB_SHIFT 56 +#define AL_ETH_RX_GPD_CAM_DATA_2_SHIFT 32 +#define AL_ETH_RX_GPD_CAM_MASK_2_SHIFT 32 +#define AL_ETH_RX_GPD_CAM_CTRL_VALID_SHIFT 31 + +#define AL_ETH_RX_GPD_PARSE_RESULT_OUTER_L3_PROTO_IDX_OFFSET (106 + 5) +#define AL_ETH_RX_GPD_PARSE_RESULT_OUTER_L4_PROTO_IDX_OFFSET (106 + 10) +#define AL_ETH_RX_GPD_PARSE_RESULT_INNER_L3_PROTO_IDX_OFFSET (0 + 5) +#define AL_ETH_RX_GPD_PARSE_RESULT_INNER_L4_PROTO_IDX_OFFSET (0 + 10) +#define AL_ETH_RX_GPD_PARSE_RESULT_OUTER_PARSE_CTRL (106 + 4) +#define AL_ETH_RX_GPD_PARSE_RESULT_INNER_PARSE_CTRL 4 +#define AL_ETH_RX_GPD_PARSE_RESULT_L3_PRIORITY (106 + 13) +#define AL_ETH_RX_GPD_PARSE_RESULT_OUTER_L4_DST_PORT_LSB (106 + 65) + +/* rx gcp defines */ +#define AL_ETH_RX_GCP_POLY_SEL_MASK 0x1 +#define AL_ETH_RX_GCP_POLY_SEL_SHIFT 0 +#define AL_ETH_RX_GCP_CRC32_BIT_COMP_MASK 0x1 +#define AL_ETH_RX_GCP_CRC32_BIT_COMP_SHIFT 1 +#define AL_ETH_RX_GCP_CRC32_BIT_SWAP_MASK 0x1 +#define AL_ETH_RX_GCP_CRC32_BIT_SWAP_SHIFT 2 +#define AL_ETH_RX_GCP_CRC32_BYTE_SWAP_MASK 0x1 +#define AL_ETH_RX_GCP_CRC32_BYTE_SWAP_SHIFT 3 +#define AL_ETH_RX_GCP_DATA_BIT_SWAP_MASK 0x1 +#define AL_ETH_RX_GCP_DATA_BIT_SWAP_SHIFT 4 +#define AL_ETH_RX_GCP_DATA_BYTE_SWAP_MASK 0x1 +#define AL_ETH_RX_GCP_DATA_BYTE_SWAP_SHIFT 5 +#define AL_ETH_RX_GCP_TRAIL_SIZE_MASK 0xF +#define AL_ETH_RX_GCP_TRAIL_SIZE_SHIFT 6 +#define AL_ETH_RX_GCP_HEAD_SIZE_MASK 0xFF +#define AL_ETH_RX_GCP_HEAD_SIZE_SHIFT 16 +#define AL_ETH_RX_GCP_HEAD_CALC_MASK 0x1 +#define AL_ETH_RX_GCP_HEAD_CALC_SHIFT 24 +#define AL_ETH_RX_GCP_MASK_POLARITY_MASK 0x1 +#define AL_ETH_RX_GCP_MASK_POLARITY_SHIFT 25 + +#define AL_ETH_RX_GCP_OPCODE_1_MASK 0x3F +#define AL_ETH_RX_GCP_OPCODE_1_SHIFT 0 +#define AL_ETH_RX_GCP_OPCODE_2_MASK 0x3F +#define AL_ETH_RX_GCP_OPCODE_2_SHIFT 6 +#define AL_ETH_RX_GCP_OPCODE_3_MASK 0x3F +#define AL_ETH_RX_GCP_OPCODE_3_SHIFT 12 +#define AL_ETH_RX_GCP_OPSEL_1_MASK 0xF +#define AL_ETH_RX_GCP_OPSEL_1_SHIFT 0 +#define AL_ETH_RX_GCP_OPSEL_2_MASK 0xF +#define AL_ETH_RX_GCP_OPSEL_2_SHIFT 4 +#define AL_ETH_RX_GCP_OPSEL_3_MASK 0xF +#define AL_ETH_RX_GCP_OPSEL_3_SHIFT 8 +#define AL_ETH_RX_GCP_OPSEL_4_MASK 0xF +#define AL_ETH_RX_GCP_OPSEL_4_SHIFT 12 + +#define AL_ETH_MDIO_DELAY_PERIOD 1 /* micro seconds to wait when polling mdio status */ +#define AL_ETH_MDIO_DELAY_COUNT 150 /* number of times to poll */ +#define AL_ETH_S2M_UDMA_COMP_COAL_TIMEOUT 200 /* Rx descriptors coalescing timeout in SB clocks */ + +#define AL_ETH_EPE_ENTRIES_NUM 26 +static struct al_eth_epe_p_reg_entry al_eth_epe_p_regs[AL_ETH_EPE_ENTRIES_NUM] = { + { 0x0, 0x0, 0x0 }, + { 0x0, 0x0, 0x1 }, + { 0x0, 0x0, 0x2 }, + { 0x0, 0x0, 0x3 }, + { 0x18100, 0xFFFFF, 0x80000004 }, + { 0x188A8, 0xFFFFF, 0x80000005 }, + { 0x99100, 0xFFFFF, 0x80000006 }, + { 0x98100, 0xFFFFF, 0x80000007 }, + { 0x10800, 0x7FFFF, 0x80000008 }, + { 0x20000, 0x73FFF, 0x80000009 }, + { 0x20000, 0x70000, 0x8000000A }, + { 0x186DD, 0x7FFFF, 0x8000000B }, + { 0x30600, 0x7FF00, 0x8000000C }, + { 0x31100, 0x7FF00, 0x8000000D }, + { 0x32F00, 0x7FF00, 0x8000000E }, + { 0x32900, 0x7FF00, 0x8000000F }, + { 0x105DC, 0x7FFFF, 0x80010010 }, + { 0x188E5, 0x7FFFF, 0x80000011 }, + { 0x72000, 0x72000, 0x80000012 }, + { 0x70000, 0x72000, 0x80000013 }, + { 0x46558, 0x7FFFF, 0x80000001 }, + { 0x18906, 0x7FFFF, 0x80000015 }, + { 0x18915, 0x7FFFF, 0x80000016 }, + { 0x31B00, 0x7FF00, 0x80000017 }, + { 0x30400, 0x7FF00, 0x80000018 }, + { 0x0, 0x0, 0x8000001F } +}; + + +static struct al_eth_epe_control_entry al_eth_epe_control_table[AL_ETH_EPE_ENTRIES_NUM] = { + {{ 0x2800000, 0x0, 0x0, 0x0, 0x1, 0x400000 }}, + {{ 0x280004C, 0x746000, 0xA46030, 0xE00000, 0x2, 0x400000 }}, + {{ 0x2800054, 0x746000, 0xA46030, 0x1600000, 0x2, 0x400000 }}, + {{ 0x280005C, 0x746000, 0xA46030, 0x1E00000, 0x2, 0x400000 }}, + {{ 0x2800042, 0xD42000, 0x0, 0x400000, 0x1010412, 0x400000 }}, + {{ 0x2800042, 0xD42000, 0x0, 0x400000, 0x1010412, 0x400000 }}, + {{ 0x2800042, 0xE42000, 0x0, 0x400000, 0x2020002, 0x400000 }}, + {{ 0x2800042, 0xE42000, 0x0, 0x400000, 0x2020002, 0x400000 }}, + {{ 0x280B046, 0x0, 0x6C1008, 0x0, 0x4, 0x406800 }}, + {{ 0x2800049, 0xF44060, 0x1744080, 0x14404, 0x6, 0x400011 }}, + {{ 0x2015049, 0xF44060, 0x1744080, 0x14404, 0x8080007, 0x400011 }}, + {{ 0x280B046, 0xF60040, 0x6C1004, 0x2800000, 0x6, 0x406811 }}, + {{ 0x2815042, 0x1F42000, 0x2042010, 0x1414460, 0x10100009, 0x40B800 }}, + {{ 0x2815042, 0x1F42000, 0x2042010, 0x800000, 0x10100009, 0x40B800 }}, + {{ 0x280B042, 0x0, 0x0, 0x430400, 0x4040009, 0x0 }}, + {{ 0x2815580, 0x0, 0x0, 0x0, 0x4040005, 0x0 }}, + {{ 0x280B000, 0x0, 0x0, 0x0, 0x1, 0x400000 }}, + {{ 0x2800040, 0x174E000, 0x0, 0x0, 0xE, 0x406800 }}, + {{ 0x280B000, 0x0, 0x0, 0x600000, 0x1, 0x406800 }}, + {{ 0x280B000, 0x0, 0x0, 0xE00000, 0x1, 0x406800 }}, + {{ 0x2800000, 0x0, 0x0, 0x0, 0x1, 0x400000 }}, + {{ 0x280B046, 0x0, 0x0, 0x2800000, 0x7, 0x400000 }}, + {{ 0x280B046, 0xF60040, 0x6C1004, 0x2800000, 0x6, 0x406811 }}, + {{ 0x2815042, 0x1F43028, 0x2000000, 0xC00000, 0x10100009, 0x40B800 }}, + {{ 0x2815400, 0x0, 0x0, 0x0, 0x4040005, 0x0 }}, + {{ 0x2800000, 0x0, 0x0, 0x0, 0x1, 0x400000 }} +}; + + +#define AL_ETH_IS_1G_MAC(mac_mode) (((mac_mode) == AL_ETH_MAC_MODE_RGMII) || ((mac_mode) == AL_ETH_MAC_MODE_SGMII)) +#define AL_ETH_IS_10G_MAC(mac_mode) (((mac_mode) == AL_ETH_MAC_MODE_10GbE_Serial) || \ + ((mac_mode) == AL_ETH_MAC_MODE_10G_SGMII) || \ + ((mac_mode) == AL_ETH_MAC_MODE_SGMII_2_5G)) +#define AL_ETH_IS_25G_MAC(mac_mode) ((mac_mode) == AL_ETH_MAC_MODE_KR_LL_25G) + +static const char *al_eth_mac_mode_str(enum al_eth_mac_mode mode) +{ + switch(mode) { + case AL_ETH_MAC_MODE_RGMII: + return "RGMII"; + case AL_ETH_MAC_MODE_SGMII: + return "SGMII"; + case AL_ETH_MAC_MODE_SGMII_2_5G: + return "SGMII_2_5G"; + case AL_ETH_MAC_MODE_10GbE_Serial: + return "KR"; + case AL_ETH_MAC_MODE_KR_LL_25G: + return "KR_LL_25G"; + case AL_ETH_MAC_MODE_10G_SGMII: + return "10G_SGMII"; + case AL_ETH_MAC_MODE_XLG_LL_40G: + return "40G_LL"; + case AL_ETH_MAC_MODE_XLG_LL_50G: + return "50G_LL"; + default: + return "N/A"; + } +} + +/** + * change and wait udma state + * + * @param dma the udma to change its state + * @param new_state + * + * @return 0 on success. otherwise on failure. + */ +static int al_udma_state_set_wait(struct al_udma *dma, enum al_udma_state new_state) +{ + enum al_udma_state state; + enum al_udma_state expected_state = new_state; + int count = 1000; + int rc; + + rc = al_udma_state_set(dma, new_state); + if (rc != 0) { + al_warn("[%s] warn: failed to change state, error %d\n", dma->name, rc); + return rc; + } + + if ((new_state == UDMA_NORMAL) || (new_state == UDMA_DISABLE)) + expected_state = UDMA_IDLE; + + do { + state = al_udma_state_get(dma); + if (state == expected_state) + break; + al_udelay(1); + if (count-- == 0) { + al_warn("[%s] warn: dma state didn't change to %s\n", + dma->name, al_udma_states_name[new_state]); + return -ETIMEDOUT; + } + } while (1); + return 0; +} + +static void al_eth_epe_entry_set(struct al_hal_eth_adapter *adapter, uint32_t idx, + struct al_eth_epe_p_reg_entry *reg_entry, + struct al_eth_epe_control_entry *control_entry) +{ + al_reg_write32(&adapter->ec_regs_base->epe_p[idx].comp_data, reg_entry->data); + al_reg_write32(&adapter->ec_regs_base->epe_p[idx].comp_mask, reg_entry->mask); + al_reg_write32(&adapter->ec_regs_base->epe_p[idx].comp_ctrl, reg_entry->ctrl); + + al_reg_write32(&adapter->ec_regs_base->msp_c[idx].p_comp_data, reg_entry->data); + al_reg_write32(&adapter->ec_regs_base->msp_c[idx].p_comp_mask, reg_entry->mask); + al_reg_write32(&adapter->ec_regs_base->msp_c[idx].p_comp_ctrl, reg_entry->ctrl); + + /*control table 0*/ + al_reg_write32(&adapter->ec_regs_base->epe[0].act_table_addr, idx); + al_reg_write32(&adapter->ec_regs_base->epe[0].act_table_data_6, + control_entry->data[5]); + al_reg_write32(&adapter->ec_regs_base->epe[0].act_table_data_2, + control_entry->data[1]); + al_reg_write32(&adapter->ec_regs_base->epe[0].act_table_data_3, + control_entry->data[2]); + al_reg_write32(&adapter->ec_regs_base->epe[0].act_table_data_4, + control_entry->data[3]); + al_reg_write32(&adapter->ec_regs_base->epe[0].act_table_data_5, + control_entry->data[4]); + al_reg_write32(&adapter->ec_regs_base->epe[0].act_table_data_1, + control_entry->data[0]); + + /*control table 1*/ + al_reg_write32(&adapter->ec_regs_base->epe[1].act_table_addr, idx); + al_reg_write32(&adapter->ec_regs_base->epe[1].act_table_data_6, + control_entry->data[5]); + al_reg_write32(&adapter->ec_regs_base->epe[1].act_table_data_2, + control_entry->data[1]); + al_reg_write32(&adapter->ec_regs_base->epe[1].act_table_data_3, + control_entry->data[2]); + al_reg_write32(&adapter->ec_regs_base->epe[1].act_table_data_4, + control_entry->data[3]); + al_reg_write32(&adapter->ec_regs_base->epe[1].act_table_data_5, + control_entry->data[4]); + al_reg_write32(&adapter->ec_regs_base->epe[1].act_table_data_1, + control_entry->data[0]); +} + +static void al_eth_epe_init(struct al_hal_eth_adapter *adapter) +{ + int idx; + + if (adapter->enable_rx_parser == 0) { + al_dbg("eth [%s]: disable rx parser\n", adapter->name); + + al_reg_write32(&adapter->ec_regs_base->epe[0].res_def, 0x08000000); + al_reg_write32(&adapter->ec_regs_base->epe[0].res_in, 0x7); + + al_reg_write32(&adapter->ec_regs_base->epe[1].res_def, 0x08000000); + al_reg_write32(&adapter->ec_regs_base->epe[1].res_in, 0x7); + + return; + } + al_dbg("eth [%s]: enable rx parser\n", adapter->name); + for (idx = 0; idx < AL_ETH_EPE_ENTRIES_NUM; idx++) + al_eth_epe_entry_set(adapter, idx, &al_eth_epe_p_regs[idx], &al_eth_epe_control_table[idx]); + + al_reg_write32(&adapter->ec_regs_base->epe[0].res_def, 0x08000080); + al_reg_write32(&adapter->ec_regs_base->epe[0].res_in, 0x7); + + al_reg_write32(&adapter->ec_regs_base->epe[1].res_def, 0x08000080); + al_reg_write32(&adapter->ec_regs_base->epe[1].res_in, 0); + + /* header length as function of 4 bits value, for GRE, when C bit is set, the header len should be increase by 4*/ + al_reg_write32(&adapter->ec_regs_base->epe_h[8].hdr_len, (4 << 16) | 4); + + /* select the outer information when writing the rx descriptor (l3 protocol index etc) */ + al_reg_write32(&adapter->ec_regs_base->rfw.meta, EC_RFW_META_L3_LEN_CALC); + + al_reg_write32(&adapter->ec_regs_base->rfw.checksum, EC_RFW_CHECKSUM_HDR_SEL); +} + +/** + * read 40G MAC registers (indirect access) + * + * @param adapter pointer to the private structure + * @param reg_addr address in the an registers + * + * @return the register value + */ +static uint32_t al_eth_40g_mac_reg_read( + struct al_hal_eth_adapter *adapter, + uint32_t reg_addr) +{ + uint32_t val; + + /* indirect access */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_addr, reg_addr); + val = al_reg_read32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_data); + + al_dbg("[%s]: %s - reg %d. val 0x%x", + adapter->name, __func__, reg_addr, val); + + return val; +} + +/** + * write 40G MAC registers (indirect access) + * + * @param adapter pointer to the private structure + * @param reg_addr address in the an registers + * @param reg_data value to write to the register + * + */ +static void al_eth_40g_mac_reg_write( + struct al_hal_eth_adapter *adapter, + uint32_t reg_addr, + uint32_t reg_data) +{ + /* indirect access */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_addr, reg_addr); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_data, reg_data); + + al_dbg("[%s]: %s - reg %d. val 0x%x", + adapter->name, __func__, reg_addr, reg_data); +} + +/** + * read 40G PCS registers (indirect access) + * + * @param adapter pointer to the private structure + * @param reg_addr address in the an registers + * + * @return the register value + */ +static uint32_t al_eth_40g_pcs_reg_read( + struct al_hal_eth_adapter *adapter, + uint32_t reg_addr) +{ + uint32_t val; + + /* indirect access */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_addr, reg_addr); + val = al_reg_read32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_data); + + al_dbg("[%s]: %s - reg %d. val 0x%x", + adapter->name, __func__, reg_addr, val); + + return val; +} + +/** + * write 40G PCS registers (indirect access) + * + * @param adapter pointer to the private structure + * @param reg_addr address in the an registers + * @param reg_data value to write to the register + * + */ +static void al_eth_40g_pcs_reg_write( + struct al_hal_eth_adapter *adapter, + uint32_t reg_addr, + uint32_t reg_data) +{ + /* indirect access */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_addr, reg_addr); + al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_data, reg_data); + + al_dbg("[%s]: %s - reg %d. val 0x%x", + adapter->name, __func__, reg_addr, reg_data); +} + +/*****************************API Functions **********************************/ +/*adapter management */ +/** + * initialize the ethernet adapter's DMA + */ +int al_eth_adapter_init(struct al_hal_eth_adapter *adapter, struct al_eth_adapter_params *params) +{ + struct al_udma_params udma_params; + struct al_udma_m2s_pkt_len_conf conf; + int i; + uint32_t reg; + int rc; + + al_dbg("eth [%s]: initialize controller's UDMA. id = %d\n", params->name, params->udma_id); + al_dbg("eth [%s]: UDMA base regs: %p\n", params->name, params->udma_regs_base); + al_dbg("eth [%s]: EC base regs: %p\n", params->name, params->ec_regs_base); + al_dbg("eth [%s]: MAC base regs: %p\n", params->name, params->mac_regs_base); + al_dbg("eth [%s]: enable_rx_parser: %x\n", params->name, params->enable_rx_parser); + + adapter->name = params->name; + adapter->rev_id = params->rev_id; + adapter->udma_id = params->udma_id; + adapter->udma_regs_base = params->udma_regs_base; + adapter->ec_regs_base = (struct al_ec_regs __iomem*)params->ec_regs_base; + adapter->mac_regs_base = (struct al_eth_mac_regs __iomem*)params->mac_regs_base; + adapter->unit_regs = (struct unit_regs __iomem *)params->udma_regs_base; + adapter->enable_rx_parser = params->enable_rx_parser; + adapter->ec_ints_base = (void __iomem *)((uint32_t)adapter->ec_regs_base + 0x1c00); + adapter->mac_ints_base = (void __iomem *)((uint32_t)adapter->mac_regs_base + 0x800); + + /* initialize Tx udma */ + udma_params.udma_regs_base = adapter->unit_regs; + udma_params.type = UDMA_TX; + udma_params.num_of_queues = AL_ETH_UDMA_TX_QUEUES; + udma_params.name = "eth tx"; + rc = al_udma_init(&adapter->tx_udma, &udma_params); + + if (rc != 0) { + al_err("failed to initialize %s, error %d\n", + udma_params.name, rc); + return rc; + } + rc = al_udma_state_set_wait(&adapter->tx_udma, UDMA_NORMAL); + if (rc != 0) { + al_err("[%s]: failed to change state, error %d\n", + udma_params.name, rc); + return rc; + } + /* initialize Rx udma */ + udma_params.udma_regs_base = adapter->unit_regs; + udma_params.type = UDMA_RX; + udma_params.num_of_queues = AL_ETH_UDMA_RX_QUEUES; + udma_params.name = "eth rx"; + rc = al_udma_init(&adapter->rx_udma, &udma_params); + + if (rc != 0) { + al_err("failed to initialize %s, error %d\n", + udma_params.name, rc); + return rc; + } + + rc = al_udma_state_set_wait(&adapter->rx_udma, UDMA_NORMAL); + if (rc != 0) { + al_err("[%s]: failed to change state, error %d\n", + udma_params.name, rc); + return rc; + } + al_dbg("eth [%s]: controller's UDMA successfully initialized\n", + params->name); + + /* set max packet size to 1M (for TSO) */ + conf.encode_64k_as_zero = AL_TRUE; + conf.max_pkt_size = 0xfffff; + al_udma_m2s_packet_size_cfg_set(&adapter->tx_udma, &conf); + + /* set m2s (tx) max descriptors to max data buffers number and one for + * meta descriptor + */ + al_udma_m2s_max_descs_set(&adapter->tx_udma, AL_ETH_PKT_MAX_BUFS + 1); + + /* set s2m (rx) max descriptors to max data buffers */ + al_udma_s2m_max_descs_set(&adapter->rx_udma, AL_ETH_PKT_MAX_BUFS); + + /* set s2m burst lenght when writing completion descriptors to 64 bytes + */ + al_udma_s2m_compl_desc_burst_config(&adapter->rx_udma, 64); + + /* if pointer to ec regs provided, then init the tx meta cache of this udma*/ + if (adapter->ec_regs_base != NULL) { + // INIT TX CACHE TABLE: + for (i = 0; i < 4; i++) { + al_reg_write32(&adapter->ec_regs_base->tso.cache_table_addr, i + (adapter->udma_id * 4)); + al_reg_write32(&adapter->ec_regs_base->tso.cache_table_data_1, 0x00000000); + al_reg_write32(&adapter->ec_regs_base->tso.cache_table_data_2, 0x00000000); + al_reg_write32(&adapter->ec_regs_base->tso.cache_table_data_3, 0x00000000); + al_reg_write32(&adapter->ec_regs_base->tso.cache_table_data_4, 0x00000000); + } + } + // only udma 0 allowed to init ec + if (adapter->udma_id != 0) { + return 0; + } + /* enable Ethernet controller: */ + /* enable internal machines*/ + al_reg_write32(&adapter->ec_regs_base->gen.en, 0xffffffff); + al_reg_write32(&adapter->ec_regs_base->gen.fifo_en, 0xffffffff); + + if (adapter->rev_id > AL_ETH_REV_ID_0) { + /* enable A0 descriptor structure */ + al_reg_write32_masked(&adapter->ec_regs_base->gen.en_ext, + EC_GEN_EN_EXT_CACHE_WORD_SPLIT, + EC_GEN_EN_EXT_CACHE_WORD_SPLIT); + + /* use mss value in the descriptor */ + al_reg_write32(&adapter->ec_regs_base->tso.cfg_add_0, + EC_TSO_CFG_ADD_0_MSS_SEL); + + /* enable tunnel TSO */ + al_reg_write32(&adapter->ec_regs_base->tso.cfg_tunnel, + (EC_TSO_CFG_TUNNEL_EN_TUNNEL_TSO | + EC_TSO_CFG_TUNNEL_EN_UDP_CHKSUM | + EC_TSO_CFG_TUNNEL_EN_UDP_LEN | + EC_TSO_CFG_TUNNEL_EN_IPV6_PLEN | + EC_TSO_CFG_TUNNEL_EN_IPV4_CHKSUM | + EC_TSO_CFG_TUNNEL_EN_IPV4_IDEN | + EC_TSO_CFG_TUNNEL_EN_IPV4_TLEN)); + } + + /* swap input byts from MAC RX */ + al_reg_write32(&adapter->ec_regs_base->mac.gen, 0x00000001); + /* swap output bytes to MAC TX*/ + al_reg_write32(&adapter->ec_regs_base->tmi.tx_cfg, EC_TMI_TX_CFG_EN_FWD_TO_RX|EC_TMI_TX_CFG_SWAP_BYTES); + + /* TODO: check if we need this line*/ + al_reg_write32(&adapter->ec_regs_base->tfw_udma[0].fwd_dec, 0x000003fb); + + /* RFW configuration: default 0 */ + al_reg_write32(&adapter->ec_regs_base->rfw_default[0].opt_1, 0x00000001); + + /* VLAN table address*/ + al_reg_write32(&adapter->ec_regs_base->rfw.vid_table_addr, 0x00000000); + /* VLAN table data*/ + al_reg_write32(&adapter->ec_regs_base->rfw.vid_table_data, 0x00000000); + /* HASH config (select toeplitz and bits 7:0 of the thash result, enable + * symmetric hash) */ + al_reg_write32(&adapter->ec_regs_base->rfw.thash_cfg_1, + EC_RFW_THASH_CFG_1_ENABLE_IP_SWAP | + EC_RFW_THASH_CFG_1_ENABLE_PORT_SWAP); + + al_eth_epe_init(adapter); + + /* disable TSO padding and use mac padding instead */ + reg = al_reg_read32(&adapter->ec_regs_base->tso.in_cfg); + reg &= ~0x7F00; /*clear bits 14:8 */ + al_reg_write32(&adapter->ec_regs_base->tso.in_cfg, reg); + + return 0; +} + +/*****************************API Functions **********************************/ +/*adapter management */ +/** + * enable the ec and mac interrupts + */ +int al_eth_ec_mac_ints_config(struct al_hal_eth_adapter *adapter) +{ + + al_dbg("eth [%s]: enable ethernet and mac interrupts\n", adapter->name); + + // only udma 0 allowed to init ec + if (adapter->udma_id != 0) + return -EPERM; + + /* enable mac ints */ + al_iofic_config(adapter->ec_ints_base, AL_INT_GROUP_A, + INT_CONTROL_GRP_SET_ON_POSEDGE | INT_CONTROL_GRP_CLEAR_ON_READ); + al_iofic_config(adapter->ec_ints_base, AL_INT_GROUP_B, + INT_CONTROL_GRP_SET_ON_POSEDGE | INT_CONTROL_GRP_CLEAR_ON_READ); + al_iofic_config(adapter->ec_ints_base, AL_INT_GROUP_C, + INT_CONTROL_GRP_SET_ON_POSEDGE | INT_CONTROL_GRP_CLEAR_ON_READ); + al_iofic_config(adapter->ec_ints_base, AL_INT_GROUP_D, + INT_CONTROL_GRP_SET_ON_POSEDGE | INT_CONTROL_GRP_CLEAR_ON_READ); + + /* unmask MAC int */ + al_iofic_unmask(adapter->ec_ints_base, AL_INT_GROUP_A, 8); + + /* enable ec interrupts */ + al_iofic_config(adapter->mac_ints_base, AL_INT_GROUP_A, + INT_CONTROL_GRP_SET_ON_POSEDGE | INT_CONTROL_GRP_CLEAR_ON_READ); + al_iofic_config(adapter->mac_ints_base, AL_INT_GROUP_B, + INT_CONTROL_GRP_SET_ON_POSEDGE | INT_CONTROL_GRP_CLEAR_ON_READ); + al_iofic_config(adapter->mac_ints_base, AL_INT_GROUP_C, + INT_CONTROL_GRP_SET_ON_POSEDGE | INT_CONTROL_GRP_CLEAR_ON_READ); + al_iofic_config(adapter->mac_ints_base, AL_INT_GROUP_D, + INT_CONTROL_GRP_SET_ON_POSEDGE | INT_CONTROL_GRP_CLEAR_ON_READ); + + /* eee active */ + al_iofic_unmask(adapter->mac_ints_base, AL_INT_GROUP_B, AL_BIT(14)); + + al_iofic_unmask(adapter->unit_regs, AL_INT_GROUP_D, AL_BIT(11)); + return 0; +} + +/** + * ec and mac interrupt service routine + * read and print asserted interrupts + * + * @param adapter pointer to the private structure + * + * @return 0 on success. otherwise on failure. + */ +int al_eth_ec_mac_isr(struct al_hal_eth_adapter *adapter) +{ + uint32_t cause; + al_dbg("[%s]: ethernet interrupts handler\n", adapter->name); + + // only udma 0 allowed to init ec + if (adapter->udma_id != 0) + return -EPERM; + + /* read ec cause */ + cause = al_iofic_read_cause(adapter->ec_ints_base, AL_INT_GROUP_A); + al_dbg("[%s]: ethernet group A cause 0x%08x\n", adapter->name, cause); + if (cause & 1) + { + cause = al_iofic_read_cause(adapter->mac_ints_base, AL_INT_GROUP_A); + al_dbg("[%s]: mac group A cause 0x%08x\n", adapter->name, cause); + + cause = al_iofic_read_cause(adapter->mac_ints_base, AL_INT_GROUP_B); + al_dbg("[%s]: mac group B cause 0x%08x\n", adapter->name, cause); + + cause = al_iofic_read_cause(adapter->mac_ints_base, AL_INT_GROUP_C); + al_dbg("[%s]: mac group C cause 0x%08x\n", adapter->name, cause); + + cause = al_iofic_read_cause(adapter->mac_ints_base, AL_INT_GROUP_D); + al_dbg("[%s]: mac group D cause 0x%08x\n", adapter->name, cause); + } + cause = al_iofic_read_cause(adapter->ec_ints_base, AL_INT_GROUP_B); + al_dbg("[%s]: ethernet group B cause 0x%08x\n", adapter->name, cause); + cause = al_iofic_read_cause(adapter->ec_ints_base, AL_INT_GROUP_C); + al_dbg("[%s]: ethernet group C cause 0x%08x\n", adapter->name, cause); + cause = al_iofic_read_cause(adapter->ec_ints_base, AL_INT_GROUP_D); + al_dbg("[%s]: ethernet group D cause 0x%08x\n", adapter->name, cause); + + return 0; +} + +/** + * stop the DMA of the ethernet adapter + */ +int al_eth_adapter_stop(struct al_hal_eth_adapter *adapter) +{ + int rc; + + al_dbg("eth [%s]: stop controller's UDMA\n", adapter->name); + + /* disable Tx dma*/ + rc = al_udma_state_set_wait(&adapter->tx_udma, UDMA_DISABLE); + if (rc != 0) { + al_warn("[%s] warn: failed to change state, error %d\n", + adapter->tx_udma.name, rc); + return rc; + } + + al_dbg("eth [%s]: controller's TX UDMA stopped\n", + adapter->name); + /* disable Rx dma*/ + rc = al_udma_state_set_wait(&adapter->rx_udma, UDMA_DISABLE); + if (rc != 0) { + al_warn("[%s] warn: failed to change state, error %d\n", + adapter->rx_udma.name, rc); + return rc; + } + + al_dbg("eth [%s]: controller's RX UDMA stopped\n", + adapter->name); + return 0; +} + +int al_eth_adapter_reset(struct al_hal_eth_adapter *adapter) +{ + al_dbg("eth [%s]: reset controller's UDMA\n", adapter->name); + + return -EPERM; +} + +/* Q management */ +/** + * Configure and enable a queue ring + */ +int al_eth_queue_config(struct al_hal_eth_adapter *adapter, enum al_udma_type type, uint32_t qid, + struct al_udma_q_params *q_params) +{ + struct al_udma *udma; + int rc; + + al_dbg("eth [%s]: config UDMA %s queue %d\n", adapter->name, + type == UDMA_TX ? "Tx" : "Rx", qid); + + if (type == UDMA_TX) { + udma = &adapter->tx_udma; + } else { + udma = &adapter->rx_udma; + } + + q_params->adapter_rev_id = adapter->rev_id; + + rc = al_udma_q_init(udma, qid, q_params); + + if (rc) + return rc; + + if (type == UDMA_RX) { + rc = al_udma_s2m_q_compl_coal_config(&udma->udma_q[qid], + AL_TRUE, AL_ETH_S2M_UDMA_COMP_COAL_TIMEOUT); + + al_assert(q_params->cdesc_size <= 32); + + if (q_params->cdesc_size > 16) + al_reg_write32_masked(&adapter->ec_regs_base->rfw.out_cfg, + EC_RFW_OUT_CFG_META_CNT_MASK, 2); + } + return rc; +} + +int al_eth_queue_enable(struct al_hal_eth_adapter *adapter __attribute__((__unused__)), + enum al_udma_type type __attribute__((__unused__)), + uint32_t qid __attribute__((__unused__))) +{ + return -EPERM; +} +int al_eth_queue_disable(struct al_hal_eth_adapter *adapter __attribute__((__unused__)), + enum al_udma_type type __attribute__((__unused__)), + uint32_t qid __attribute__((__unused__))) +{ + return -EPERM; +} + +/* MAC layer */ +int al_eth_rx_pkt_limit_config(struct al_hal_eth_adapter *adapter, uint32_t min_rx_len, uint32_t max_rx_len) +{ + al_assert(max_rx_len <= AL_ETH_MAX_FRAME_LEN); + + /* EC minimum packet length [bytes] in RX */ + al_reg_write32(&adapter->ec_regs_base->mac.min_pkt, min_rx_len); + /* EC maximum packet length [bytes] in RX */ + al_reg_write32(&adapter->ec_regs_base->mac.max_pkt, max_rx_len); + + if (adapter->rev_id > AL_ETH_REV_ID_2) { + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_1, min_rx_len); + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_2, max_rx_len); + } + + /* configure the MAC's max rx length, add 16 bytes so the packet get + * trimmed by the EC/Async_fifo rather by the MAC + */ + if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) + al_reg_write32(&adapter->mac_regs_base->mac_1g.frm_len, max_rx_len + 16); + else if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) + /* 10G MAC control register */ + al_reg_write32(&adapter->mac_regs_base->mac_10g.frm_len, (max_rx_len + 16)); + else + al_eth_40g_mac_reg_write(adapter, ETH_MAC_GEN_V3_MAC_40G_FRM_LENGTH_ADDR, (max_rx_len + 16)); + + return 0; +} + +/* configure the mac media type. */ +int al_eth_mac_config(struct al_hal_eth_adapter *adapter, enum al_eth_mac_mode mode) +{ + switch(mode) { + case AL_ETH_MAC_MODE_RGMII: + al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x40003210); + + /* 1G MAC control register */ + /* bit[0] - TX_ENA - zeroed by default. Should be asserted by al_eth_mac_start + * bit[1] - RX_ENA - zeroed by default. Should be asserted by al_eth_mac_start + * bit[3] - ETH_SPEED - zeroed to enable 10/100 Mbps Ethernet + * bit[4] - PROMIS_EN - asserted to enable MAC promiscuous mode + * bit[23] - CNTL_FRM-ENA - asserted to enable control frames + * bit[24] - NO_LGTH_CHECK - asserted to disable length checks, which is done in the controller + */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.cmd_cfg, 0x01800010); + + /* RX_SECTION_EMPTY, */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.rx_section_empty, 0x00000000); + /* RX_SECTION_FULL, */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.rx_section_full, 0x0000000c); /* must be larger than almost empty */ + /* RX_ALMOST_EMPTY, */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.rx_almost_empty, 0x00000008); + /* RX_ALMOST_FULL, */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.rx_almost_full, 0x00000008); + + + /* TX_SECTION_EMPTY, */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.tx_section_empty, 0x00000008); /* 8 ? */ + /* TX_SECTION_FULL, 0 - store and forward, */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.tx_section_full, 0x0000000c); + /* TX_ALMOST_EMPTY, */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.tx_almost_empty, 0x00000008); + /* TX_ALMOST_FULL, */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.tx_almost_full, 0x00000008); + + /* XAUI MAC control register */ + al_reg_write32(&adapter->mac_regs_base->gen.cfg, 0x00000000); + + /* 1G MACSET 1G */ + /* taking sel_1000/sel_10 inputs from rgmii PHY, and not from register. + * disabling magic_packets detection in mac */ + al_reg_write32(&adapter->mac_regs_base->gen.mac_1g_cfg, 0x00000002); + /* RGMII set 1G */ + al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x00063910); + al_reg_write32(&adapter->mac_regs_base->gen.rgmii_sel, 0xF); + break; + case AL_ETH_MAC_MODE_SGMII: + if (adapter->rev_id > AL_ETH_REV_ID_2) { + /* configure and enable the ASYNC FIFO between the MACs and the EC */ + /* TX min packet size */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037); + /* TX max packet size */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800); + /* TX input bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_3, 0x00000080); + /* TX output bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_4, 0x00030020); + /* TX Valid/ready configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_5, 0x00000121); + /* RX min packet size */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_1, 0x00000040); */ + /* RX max packet size */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_2, 0x00002800); */ + /* RX input bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_3, 0x00030020); + /* RX output bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_4, 0x00000080); + /* RX Valid/ready configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_5, 0x00000212); + /* V3 additional MAC selection */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_sel, 0x00000000); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_cfg, 0x00000001); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_ctrl, 0x00000000); + al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_10g_ll_cfg, 0x00000000); + /* ASYNC FIFO ENABLE */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.afifo_ctrl, 0x00003333); + /* Timestamp_configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.spare, + ETH_MAC_GEN_V3_SPARE_CHICKEN_DISABLE_TIMESTAMP_STRETCH); + } + + al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x40053210); + + /* 1G MAC control register */ + /* bit[0] - TX_ENA - zeroed by default. Should be asserted by al_eth_mac_start + * bit[1] - RX_ENA - zeroed by default. Should be asserted by al_eth_mac_start + * bit[3] - ETH_SPEED - zeroed to enable 10/100 Mbps Ethernet + * bit[4] - PROMIS_EN - asserted to enable MAC promiscuous mode + * bit[23] - CNTL_FRM-ENA - asserted to enable control frames + * bit[24] - NO_LGTH_CHECK - asserted to disable length checks, which is done in the controller + */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.cmd_cfg, 0x01800010); + + /* RX_SECTION_EMPTY, */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.rx_section_empty, 0x00000000); + /* RX_SECTION_FULL, */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.rx_section_full, 0x0000000c); /* must be larger than almost empty */ + /* RX_ALMOST_EMPTY, */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.rx_almost_empty, 0x00000008); + /* RX_ALMOST_FULL, */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.rx_almost_full, 0x00000008); + + + /* TX_SECTION_EMPTY, */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.tx_section_empty, 0x00000008); /* 8 ? */ + /* TX_SECTION_FULL, 0 - store and forward, */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.tx_section_full, 0x0000000c); + /* TX_ALMOST_EMPTY, */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.tx_almost_empty, 0x00000008); + /* TX_ALMOST_FULL, */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.tx_almost_full, 0x00000008); + + /* XAUI MAC control register */ + al_reg_write32(&adapter->mac_regs_base->gen.cfg, 0x000000c0); + + /* 1G MACSET 1G */ + /* taking sel_1000/sel_10 inputs from rgmii_converter, and not from register. + * disabling magic_packets detection in mac */ + al_reg_write32(&adapter->mac_regs_base->gen.mac_1g_cfg, 0x00000002); + /* SerDes configuration */ + al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x00063910); + al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x000004f0); + al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x00000401); + + // FAST AN -- Testing only +#ifdef AL_HAL_ETH_FAST_AN + al_reg_write32(&adapter->mac_regs_base->sgmii.reg_addr, 0x00000012); + al_reg_write32(&adapter->mac_regs_base->sgmii.reg_data, 0x00000040); + al_reg_write32(&adapter->mac_regs_base->sgmii.reg_addr, 0x00000013); + al_reg_write32(&adapter->mac_regs_base->sgmii.reg_data, 0x00000000); +#endif + + /* Setting PCS i/f mode to SGMII (instead of default 1000Base-X) */ + al_reg_write32(&adapter->mac_regs_base->sgmii.reg_addr, 0x00000014); + al_reg_write32(&adapter->mac_regs_base->sgmii.reg_data, 0x0000000b); + /* setting dev_ability to have speed of 1000Mb, [11:10] = 2'b10 */ + al_reg_write32(&adapter->mac_regs_base->sgmii.reg_addr, 0x00000004); + al_reg_write32(&adapter->mac_regs_base->sgmii.reg_data, 0x000009A0); + al_reg_write32_masked(&adapter->mac_regs_base->gen.led_cfg, + ETH_MAC_GEN_LED_CFG_SEL_MASK, + ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG); + break; + + case AL_ETH_MAC_MODE_SGMII_2_5G: + if (adapter->rev_id > AL_ETH_REV_ID_2) { + /* configure and enable the ASYNC FIFO between the MACs and the EC */ + /* TX min packet size */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037); + /* TX max packet size */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800); + /* TX input bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_3, 0x00000080); + /* TX output bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_4, 0x00030020); + /* TX Valid/ready configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_5, 0x00000023); + /* RX input bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_3, 0x00030020); + /* RX output bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_4, 0x00000080); + /* RX Valid/ready configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_5, 0x00000012); + /* V3 additional MAC selection */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_sel, 0x00000000); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_cfg, 0x00000000); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_ctrl, 0x00000000); + al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_10g_ll_cfg, 0x00000050); + /* ASYNC FIFO ENABLE */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.afifo_ctrl, 0x00003333); + } + + /* MAC register file */ + al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x01022830); + /* XAUI MAC control register */ + al_reg_write32(&adapter->mac_regs_base->gen.cfg, 0x00000001); + al_reg_write32(&adapter->mac_regs_base->mac_10g.if_mode, 0x00000028); + al_reg_write32(&adapter->mac_regs_base->mac_10g.control, 0x00001140); + /* RXAUI MAC control register */ + al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_32_64, 0x00000401); +/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_out, 0x00000401); */ + al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_64_32, 0x00000401); +/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_in, 0x00000401); */ + al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, + ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x00063910); + al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x40003210); + al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x000004f0); + al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x00000401); + + al_reg_write32_masked(&adapter->mac_regs_base->gen.led_cfg, + ETH_MAC_GEN_LED_CFG_SEL_MASK, + ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG); + break; + + case AL_ETH_MAC_MODE_10GbE_Serial: + if (adapter->rev_id > AL_ETH_REV_ID_2) { + /* configure and enable the ASYNC FIFO between the MACs and the EC */ + /* TX min packet size */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037); + /* TX max packet size */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800); + /* TX input bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_3, 0x00000080); + /* TX output bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_4, 0x00030020); + /* TX Valid/ready configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_5, 0x00000023); + /* RX min packet size */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_1, 0x00000040); */ + /* RX max packet size */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_2, 0x00002800); */ + /* RX input bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_3, 0x00030020); + /* RX output bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_4, 0x00000080); + /* RX Valid/ready configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_5, 0x00000012); + /* V3 additional MAC selection */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_sel, 0x00000000); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_cfg, 0x00000000); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_ctrl, 0x00000000); + al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_10g_ll_cfg, 0x00000050); + /* ASYNC FIFO ENABLE */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.afifo_ctrl, 0x00003333); + } + + /* MAC register file */ + al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x01022810); + /* XAUI MAC control register */ + al_reg_write32(&adapter->mac_regs_base->gen.cfg, 0x00000005); + /* RXAUI MAC control register */ + al_reg_write32(&adapter->mac_regs_base->gen.rxaui_cfg, 0x00000007); + al_reg_write32(&adapter->mac_regs_base->gen.sd_cfg, 0x000001F1); + al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_32_64, 0x00000401); +/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_out, 0x00000401); */ + al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_64_32, 0x00000401); +/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_in, 0x00000401); */ + al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, + ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x00073910); + al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x10003210); + al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x000004f0); + al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x00000401); + + al_reg_write32_masked(&adapter->mac_regs_base->gen.led_cfg, + ETH_MAC_GEN_LED_CFG_SEL_MASK, + ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG); + break; + + case AL_ETH_MAC_MODE_KR_LL_25G: + /* select 25G SERDES lane 0 and lane 1 */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.ext_serdes_ctrl, 0x03821101); + if (adapter->rev_id > AL_ETH_REV_ID_2) { + /* configure and enable the ASYNC FIFO between the MACs and the EC */ + /* TX min packet size */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037); + /* TX max packet size */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800); + /* TX input bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_3, 0x00000080); + /* TX output bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_4, 0x00030020); + /* TX Valid/ready configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_5, 0x00000023); + /* RX min packet size */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_1, 0x00000040); */ + /* RX max packet size */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_2, 0x00002800); */ + /* RX input bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_3, 0x00030020); + /* RX output bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_4, 0x00000080); + /* RX Valid/ready configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_5, 0x00000012); + /* V3 additional MAC selection */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_sel, 0x00000000); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_cfg, 0x00000000); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_ctrl, 0x00000000); + al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_10g_ll_cfg, 0x000000a0); + /* ASYNC FIFO ENABLE */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.afifo_ctrl, 0x00003333); + } + + /* MAC register file */ + al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x01022810); + /* XAUI MAC control register */ + al_reg_write32(&adapter->mac_regs_base->gen.cfg, 0x00000005); + /* RXAUI MAC control register */ + al_reg_write32(&adapter->mac_regs_base->gen.rxaui_cfg, 0x00000007); + al_reg_write32(&adapter->mac_regs_base->gen.sd_cfg, 0x000001F1); + al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_32_64, 0x00000401); +/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_out, 0x00000401); */ + al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_64_32, 0x00000401); +/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_in, 0x00000401); */ + al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, + ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x00073910); + al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x10003210); + al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x000004f0); + al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x00000401); + + al_reg_write32_masked(&adapter->mac_regs_base->gen.led_cfg, + ETH_MAC_GEN_LED_CFG_SEL_MASK, + ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG); + break; + + case AL_ETH_MAC_MODE_10G_SGMII: + /* MAC register file */ + al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x01022810); + + /* XAUI MAC control register */ + al_reg_write32(&adapter->mac_regs_base->gen.cfg, 0x00000001); + + al_reg_write32(&adapter->mac_regs_base->mac_10g.if_mode, 0x0000002b); + al_reg_write32(&adapter->mac_regs_base->mac_10g.control, 0x00009140); + // FAST AN -- Testing only +#ifdef AL_HAL_ETH_FAST_AN + al_reg_write32(&adapter->mac_regs_base->mac_10g.link_timer_lo, 0x00000040); + al_reg_write32(&adapter->mac_regs_base->mac_10g.link_timer_hi, 0x00000000); +#endif + + /* RXAUI MAC control register */ + al_reg_write32(&adapter->mac_regs_base->gen.rxaui_cfg, 0x00000007); + al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_32_64, 0x00000401); +/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_out, 0x00000401); */ + al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_64_32, 0x00000401); +/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_in, 0x00000401); */ + al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, + ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x00063910); + al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x40003210); + al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x00000401); + + al_reg_write32_masked(&adapter->mac_regs_base->gen.led_cfg, + ETH_MAC_GEN_LED_CFG_SEL_MASK, + ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG); + break; + + case AL_ETH_MAC_MODE_XLG_LL_40G: + /* configure and enable the ASYNC FIFO between the MACs and the EC */ + /* TX min packet size */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037); + /* TX max packet size */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800); + /* TX input bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_3, 0x00000080); + /* TX output bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_4, 0x00010040); + /* TX Valid/ready configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_5, 0x00000023); + /* RX min packet size */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_1, 0x00000040); */ + /* RX max packet size */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_2, 0x00002800); */ + /* RX input bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_3, 0x00010040); + /* RX output bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_4, 0x00000080); + /* RX Valid/ready configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_5, 0x00000112); + /* V3 additional MAC selection */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_sel, 0x00000010); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_cfg, 0x00000000); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_ctrl, 0x00000000); + al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_10g_ll_cfg, 0x00000000); + /* ASYNC FIFO ENABLE */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.afifo_ctrl, 0x00003333); + + /* cmd_cfg */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_addr, 0x00000008); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_data, 0x01022810); + /* speed_ability //Read-Only */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_addr, 0x00000008); */ + /* 40G capable */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_data, 0x00000002); */ + +#ifdef AL_HAL_ETH_FAST_AN + al_eth_40g_pcs_reg_write(adapter, 0x00010004, 1023); + al_eth_40g_pcs_reg_write(adapter, 0x00000000, 0xA04c); + al_eth_40g_pcs_reg_write(adapter, 0x00000000, 0x204c); + +#endif + + /* XAUI MAC control register */ + al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, + ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x06883910); + al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x0000040f); + + /* MAC register file */ +/* al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x01022810); */ + /* XAUI MAC control register */ + al_reg_write32(&adapter->mac_regs_base->gen.cfg, 0x00000005); + /* RXAUI MAC control register */ + al_reg_write32(&adapter->mac_regs_base->gen.rxaui_cfg, 0x00000007); + al_reg_write32(&adapter->mac_regs_base->gen.sd_cfg, 0x000001F1); + al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_32_64, 0x00000401); +/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_out, 0x00000401); */ + al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_64_32, 0x00000401); +/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_in, 0x00000401); */ +/* al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x00073910); *//* XLG_LL_40G change */ + al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x10003210); +/* al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x000004f0); *//* XLG_LL_40G change */ +/* al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x00000401); *//* XLG_LL_40G change */ + + al_reg_write32_masked(&adapter->mac_regs_base->gen.led_cfg, + ETH_MAC_GEN_LED_CFG_SEL_MASK, + ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG); + break; + + case AL_ETH_MAC_MODE_XLG_LL_50G: + + /* configure and enable the ASYNC FIFO between the MACs and the EC */ + /* TX min packet size */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037); + /* TX max packet size */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800); + /* TX input bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_3, 0x00000080); + /* TX output bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_4, 0x00010040); + /* TX Valid/ready configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_5, 0x00000023); + /* RX min packet size */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_1, 0x00000040); */ + /* RX max packet size */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_2, 0x00002800); */ + /* RX input bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_3, 0x00010040); + /* RX output bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_4, 0x00000080); + /* RX Valid/ready configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_5, 0x00000112); + /* V3 additional MAC selection */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_sel, 0x00000010); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_cfg, 0x00000000); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_ctrl, 0x00000000); + al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_10g_ll_cfg, 0x00000000); + /* ASYNC FIFO ENABLE */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.afifo_ctrl, 0x00003333); + + /* cmd_cfg */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_addr, 0x00000008); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_data, 0x01022810); + /* speed_ability //Read-Only */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_addr, 0x00000008); */ + /* 40G capable */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_data, 0x00000002); */ + + /* select the 25G serdes for lanes 0/1 */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.ext_serdes_ctrl, 0x0382110F); + /* configure the PCS to work with 2 lanes */ + /* configure which two of the 4 PCS Lanes (VL) are combined to one RXLAUI lane */ + /* use VL 0-2 for RXLAUI lane 0, use VL 1-3 for RXLAUI lane 1 */ + al_eth_40g_pcs_reg_write(adapter, 0x00010008, 0x0d81); + /* configure the PCS to work 32 bit interface */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_cfg, 0x00440000); + + +#ifdef AL_HAL_ETH_FAST_AN + al_eth_40g_pcs_reg_write(adapter, 0x00010004, 1023); + al_eth_40g_pcs_reg_write(adapter, 0x00000000, 0xA04c); + al_eth_40g_pcs_reg_write(adapter, 0x00000000, 0x204c); +#endif + + /* XAUI MAC control register */ + al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x06883910); + al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x0000040f); + + /* MAC register file */ +/* al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x01022810); */ + /* XAUI MAC control register */ + al_reg_write32(&adapter->mac_regs_base->gen.cfg, 0x00000005); + /* RXAUI MAC control register */ + al_reg_write32(&adapter->mac_regs_base->gen.rxaui_cfg, 0x00000007); + al_reg_write32(&adapter->mac_regs_base->gen.sd_cfg, 0x000001F1); + al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_32_64, 0x00000401); +/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_out, 0x00000401); */ + al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_64_32, 0x00000401); +/* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_in, 0x00000401); */ +/* al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x00073910); *//* XLG_LL_40G change */ + al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x10003210); +/* al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x000004f0); *//* XLG_LL_40G change */ +/* al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x00000401); *//* XLG_LL_40G change */ + + al_reg_write32_masked(&adapter->mac_regs_base->gen.led_cfg, + ETH_MAC_GEN_LED_CFG_SEL_MASK, + ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG); + break; + + + default: + al_err("Eth: unsupported MAC mode %d", mode); + return -EPERM; + } + adapter->mac_mode = mode; + al_info("configured MAC to %s mode:\n", al_eth_mac_mode_str(mode)); + + return 0; +} + +/* start the mac */ +int al_eth_mac_start(struct al_hal_eth_adapter *adapter) +{ + if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) { + /* 1G MAC control register */ + al_reg_write32_masked(&adapter->mac_regs_base->mac_1g.cmd_cfg, 0x3, 0x3); + } else if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) { + /* 10G MAC control register */ + al_reg_write32_masked(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x3, 0x3); + } else { + uint32_t cmd_cfg; + + cmd_cfg = al_eth_40g_mac_reg_read(adapter, ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR); + + cmd_cfg |= (ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_TX_ENA | + ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_RX_ENA); + + al_eth_40g_mac_reg_write(adapter, ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR, cmd_cfg); + } + + return 0; +} + +/* stop the mac */ +int al_eth_mac_stop(struct al_hal_eth_adapter *adapter) +{ + if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) + /* 1G MAC control register */ + al_reg_write32(&adapter->mac_regs_base->mac_1g.cmd_cfg, 0x0); + else if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) + /* 10G MAC control register */ + al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x0); + else + al_eth_40g_mac_reg_write(adapter, ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR, 0); + + return 0; +} + +int al_eth_capabilities_get(struct al_hal_eth_adapter *adapter, struct al_eth_capabilities *caps) +{ + al_assert(caps); + + caps->speed_10_HD = AL_FALSE; + caps->speed_10_FD = AL_FALSE; + caps->speed_100_HD = AL_FALSE; + caps->speed_100_FD = AL_FALSE; + caps->speed_1000_HD = AL_FALSE; + caps->speed_1000_FD = AL_FALSE; + caps->speed_10000_HD = AL_FALSE; + caps->speed_10000_FD = AL_FALSE; + caps->pfc = AL_FALSE; + caps->eee = AL_FALSE; + + switch (adapter->mac_mode) { + case AL_ETH_MAC_MODE_RGMII: + case AL_ETH_MAC_MODE_SGMII: + caps->speed_10_HD = AL_TRUE; + caps->speed_10_FD = AL_TRUE; + caps->speed_100_HD = AL_TRUE; + caps->speed_100_FD = AL_TRUE; + caps->speed_1000_FD = AL_TRUE; + caps->eee = AL_TRUE; + break; + case AL_ETH_MAC_MODE_10GbE_Serial: + caps->speed_10000_FD = AL_TRUE; + caps->pfc = AL_TRUE; + break; + default: + al_err("Eth: unsupported MAC mode %d", adapter->mac_mode); + return -EPERM; + } + return 0; +} + +/* update link speed and duplex mode */ +int al_eth_mac_link_config(struct al_hal_eth_adapter *adapter, + al_bool force_1000_base_x, + al_bool an_enable, + uint32_t speed, + al_bool full_duplex) +{ + uint32_t mac_ctrl; + uint32_t sgmii_ctrl = 0; + uint32_t sgmii_if_mode = 0; + uint32_t rgmii_ctrl = 0; + + if (!AL_ETH_IS_1G_MAC(adapter->mac_mode)) { + al_err("eth [%s]: this function not supported in this mac mode.\n", + adapter->name); + return -EINVAL; + } + + if ((adapter->mac_mode != AL_ETH_MAC_MODE_RGMII) && (an_enable)) { + /* + * an_enable is not relevant to RGMII mode. + * in AN mode speed and duplex aren't relevant. + */ + al_info("eth [%s]: set auto negotiation to enable\n", adapter->name); + } else { + al_info("eth [%s]: set link speed to %dMbps. %s duplex.\n", adapter->name, + speed, full_duplex == AL_TRUE ? "full" : "half"); + + if ((speed != 10) && (speed != 100) && (speed != 1000)) { + al_err("eth [%s]: bad speed parameter (%d).\n", + adapter->name, speed); + return -EINVAL; + } + if ((speed == 1000) && (full_duplex == AL_FALSE)) { + al_err("eth [%s]: half duplex in 1Gbps is not supported.\n", + adapter->name); + return -EINVAL; + } + } + + mac_ctrl = al_reg_read32(&adapter->mac_regs_base->mac_1g.cmd_cfg); + + if (adapter->mac_mode == AL_ETH_MAC_MODE_SGMII) { + al_reg_write32(&adapter->mac_regs_base->sgmii.reg_addr, + ETH_MAC_SGMII_REG_ADDR_CTRL_REG); + sgmii_ctrl = al_reg_read32(&adapter->mac_regs_base->sgmii.reg_data); + /* + * in case bit 0 is off in sgmii_if_mode register all the other + * bits are ignored. + */ + if (force_1000_base_x == AL_FALSE) + sgmii_if_mode = ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_EN; + + if (an_enable == AL_TRUE) { + sgmii_if_mode |= ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_AN; + sgmii_ctrl |= ETH_MAC_SGMII_REG_DATA_CTRL_AN_ENABLE; + } else { + sgmii_ctrl &= ~(ETH_MAC_SGMII_REG_DATA_CTRL_AN_ENABLE); + } + } + + if (adapter->mac_mode == AL_ETH_MAC_MODE_RGMII) { + /* + * Use the speed provided by the MAC instead of the PHY + */ + rgmii_ctrl = al_reg_read32(&adapter->mac_regs_base->gen.rgmii_cfg); + + AL_REG_MASK_CLEAR(rgmii_ctrl, ETH_MAC_GEN_RGMII_CFG_ENA_AUTO); + AL_REG_MASK_CLEAR(rgmii_ctrl, ETH_MAC_GEN_RGMII_CFG_SET_1000_SEL); + AL_REG_MASK_CLEAR(rgmii_ctrl, ETH_MAC_GEN_RGMII_CFG_SET_10_SEL); + + al_reg_write32(&adapter->mac_regs_base->gen.rgmii_cfg, rgmii_ctrl); + } + + if (full_duplex == AL_TRUE) { + AL_REG_MASK_CLEAR(mac_ctrl, AL_ETH_1G_MAC_CTRL_HD_EN); + } else { + AL_REG_MASK_SET(mac_ctrl, AL_ETH_1G_MAC_CTRL_HD_EN); + sgmii_if_mode |= ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_DUPLEX; + } + + if (speed == 1000) { + AL_REG_MASK_SET(mac_ctrl, AL_ETH_1G_MAC_CTRL_1G_SPD); + sgmii_if_mode |= ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_SPEED_1000; + } else { + AL_REG_MASK_CLEAR(mac_ctrl, AL_ETH_1G_MAC_CTRL_1G_SPD); + if (speed == 10) { + AL_REG_MASK_SET(mac_ctrl, AL_ETH_1G_MAC_CTRL_10M_SPD); + } else { + sgmii_if_mode |= ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_SPEED_100; + AL_REG_MASK_CLEAR(mac_ctrl, AL_ETH_1G_MAC_CTRL_10M_SPD); + } + } + + if (adapter->mac_mode == AL_ETH_MAC_MODE_SGMII) { + al_reg_write32(&adapter->mac_regs_base->sgmii.reg_addr, + ETH_MAC_SGMII_REG_ADDR_IF_MODE_REG); + al_reg_write32(&adapter->mac_regs_base->sgmii.reg_data, + sgmii_if_mode); + + al_reg_write32(&adapter->mac_regs_base->sgmii.reg_addr, + ETH_MAC_SGMII_REG_ADDR_CTRL_REG); + al_reg_write32(&adapter->mac_regs_base->sgmii.reg_data, + sgmii_ctrl); + } + + al_reg_write32(&adapter->mac_regs_base->mac_1g.cmd_cfg, mac_ctrl); + + return 0; +} + +int al_eth_mac_loopback_config(struct al_hal_eth_adapter *adapter, int enable) +{ + const char *state = (enable) ? "enable" : "disable"; + + al_dbg("eth [%s]: loopback %s\n", adapter->name, state); + if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) { + uint32_t reg; + reg = al_reg_read32(&adapter->mac_regs_base->mac_1g.cmd_cfg); + if (enable) + reg |= AL_BIT(15); + else + reg &= ~AL_BIT(15); + al_reg_write32(&adapter->mac_regs_base->mac_1g.cmd_cfg, reg); + } else if ((AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) + && (adapter->rev_id == AL_ETH_REV_ID_3)) { + uint32_t reg; + al_reg_write16( + (uint16_t *)&adapter->mac_regs_base->kr.pcs_addr, ETH_MAC_KR_PCS_CONTROL_1_ADDR); + reg = al_reg_read16( + (uint16_t *)&adapter->mac_regs_base->kr.pcs_data); + if (enable) + reg |= AL_BIT(14); + else + reg &= ~AL_BIT(14); + al_reg_write16( + (uint16_t *)&adapter->mac_regs_base->kr.pcs_addr, ETH_MAC_KR_PCS_CONTROL_1_ADDR); + al_reg_write16( + (uint16_t *)&adapter->mac_regs_base->kr.pcs_data, reg); + } else if (adapter->mac_mode == AL_ETH_MAC_MODE_XLG_LL_40G || + (adapter->mac_mode == AL_ETH_MAC_MODE_XLG_LL_50G)) { + uint32_t reg; + reg = al_eth_40g_pcs_reg_read(adapter, ETH_MAC_GEN_V3_PCS_40G_CONTROL_STATUS_ADDR); + if (enable) + reg |= AL_BIT(14); + else + reg &= ~AL_BIT(14); + al_eth_40g_pcs_reg_write(adapter, ETH_MAC_GEN_V3_PCS_40G_CONTROL_STATUS_ADDR, reg); + } else { + al_err("Eth: mac loopback not supported in this mode %d", adapter->mac_mode); + return -EPERM; + } + return 0; +} + +/* MDIO */ +int al_eth_mdio_config( + struct al_hal_eth_adapter *adapter, + enum al_eth_mdio_type mdio_type, + al_bool shared_mdio_if, + enum al_eth_ref_clk_freq ref_clk_freq, + unsigned int mdio_clk_freq_khz) +{ + enum al_eth_mdio_if mdio_if = AL_ETH_MDIO_IF_10G_MAC; + const char *if_name = (mdio_if == AL_ETH_MDIO_IF_1G_MAC) ? "10/100/1G MAC" : "10G MAC"; + const char *type_name = (mdio_type == AL_ETH_MDIO_TYPE_CLAUSE_22) ? "Clause 22" : "Clause 45"; + const char *shared_name = (shared_mdio_if == AL_TRUE) ? "Yes" : "No"; + + unsigned int ref_clk_freq_khz; + uint32_t val; + + al_dbg("eth [%s]: mdio config: interface %s. type %s. shared: %s\n", adapter->name, if_name, type_name, shared_name); + adapter->shared_mdio_if = shared_mdio_if; + + val = al_reg_read32(&adapter->mac_regs_base->gen.cfg); + al_dbg("eth [%s]: mdio config: 10G mac \n", adapter->name); + + switch(mdio_if) + { + case AL_ETH_MDIO_IF_1G_MAC: + val &= ~AL_BIT(10); + break; + case AL_ETH_MDIO_IF_10G_MAC: + val |= AL_BIT(10); + break; + } + al_reg_write32(&adapter->mac_regs_base->gen.cfg, val); + adapter->mdio_if = mdio_if; + + + if (mdio_if == AL_ETH_MDIO_IF_10G_MAC) + { + val = al_reg_read32(&adapter->mac_regs_base->mac_10g.mdio_cfg_status); + switch(mdio_type) + { + case AL_ETH_MDIO_TYPE_CLAUSE_22: + val &= ~AL_BIT(6); + break; + case AL_ETH_MDIO_TYPE_CLAUSE_45: + val |= AL_BIT(6); + break; + } + + /* set clock div to get 'mdio_clk_freq_khz' */ + switch (ref_clk_freq) { + default: + al_err("eth [%s]: %s: invalid reference clock frequency" + " (%d)\n", + adapter->name, __func__, ref_clk_freq); + case AL_ETH_REF_FREQ_375_MHZ: + ref_clk_freq_khz = 375000; + break; + case AL_ETH_REF_FREQ_187_5_MHZ: + ref_clk_freq_khz = 187500; + break; + case AL_ETH_REF_FREQ_250_MHZ: + ref_clk_freq_khz = 250000; + break; + case AL_ETH_REF_FREQ_500_MHZ: + ref_clk_freq_khz = 500000; + break; + case AL_ETH_REF_FREQ_428_MHZ: + ref_clk_freq_khz = 428000; + break; + }; + + val &= ~(0x1FF << 7); + val |= (ref_clk_freq_khz / (2 * mdio_clk_freq_khz)) << 7; + AL_REG_FIELD_SET(val, ETH_10G_MAC_MDIO_CFG_HOLD_TIME_MASK, + ETH_10G_MAC_MDIO_CFG_HOLD_TIME_SHIFT, + ETH_10G_MAC_MDIO_CFG_HOLD_TIME_7_CLK); + al_reg_write32(&adapter->mac_regs_base->mac_10g.mdio_cfg_status, val); + }else{ + if(mdio_type != AL_ETH_MDIO_TYPE_CLAUSE_22) { + al_err("eth [%s] mdio type not supported for this interface\n", + adapter->name); + return -EINVAL; + } + } + adapter->mdio_type = mdio_type; + + return 0; +} + +static int al_eth_mdio_1g_mac_read(struct al_hal_eth_adapter *adapter, + uint32_t phy_addr __attribute__((__unused__)), + uint32_t reg, uint16_t *val) +{ + *val = al_reg_read32( + &adapter->mac_regs_base->mac_1g.phy_regs_base + reg); + return 0; +} + +static int al_eth_mdio_1g_mac_write(struct al_hal_eth_adapter *adapter, + uint32_t phy_addr __attribute__((__unused__)), + uint32_t reg, uint16_t val) +{ + al_reg_write32( + &adapter->mac_regs_base->mac_1g.phy_regs_base + reg, val); + return 0; +} + +static int al_eth_mdio_10g_mac_wait_busy(struct al_hal_eth_adapter *adapter) +{ + int count = 0; + uint32_t mdio_cfg_status; + + do { + mdio_cfg_status = al_reg_read32(&adapter->mac_regs_base->mac_10g.mdio_cfg_status); +/* + if (mdio_cfg_status & AL_BIT(1)){ //error + al_err(" %s mdio read failed on error. phy_addr 0x%x reg 0x%x\n", + udma_params.name, phy_addr, reg); + return -EIO; + }*/ + if (mdio_cfg_status & AL_BIT(0)){ + if (count > 0) + al_dbg("eth [%s] mdio: still busy!\n", adapter->name); + }else{ + return 0; + } + al_udelay(AL_ETH_MDIO_DELAY_PERIOD); + }while(count++ < AL_ETH_MDIO_DELAY_COUNT); + + return -ETIMEDOUT; +} + +static int al_eth_mdio_10g_mac_type22( + struct al_hal_eth_adapter *adapter, + int read, uint32_t phy_addr, uint32_t reg, uint16_t *val) +{ + int rc; + const char *op = (read == 1) ? "read":"write"; + uint32_t mdio_cfg_status; + uint16_t mdio_cmd; + + //wait if the HW is busy + rc = al_eth_mdio_10g_mac_wait_busy(adapter); + if (rc) { + al_err(" eth [%s] mdio %s failed. HW is busy\n", adapter->name, op); + return rc; + } + + mdio_cmd = (uint16_t)(0x1F & reg); + mdio_cmd |= (0x1F & phy_addr) << 5; + + if (read) + mdio_cmd |= AL_BIT(15); //READ command + + al_reg_write16(&adapter->mac_regs_base->mac_10g.mdio_cmd, + mdio_cmd); + if (!read) + al_reg_write16(&adapter->mac_regs_base->mac_10g.mdio_data, + *val); + + //wait for the busy to clear + rc = al_eth_mdio_10g_mac_wait_busy(adapter); + if (rc != 0) { + al_err(" %s mdio %s failed on timeout\n", adapter->name, op); + return -ETIMEDOUT; + } + + mdio_cfg_status = al_reg_read32(&adapter->mac_regs_base->mac_10g.mdio_cfg_status); + + if (mdio_cfg_status & AL_BIT(1)){ //error + al_err(" %s mdio %s failed on error. phy_addr 0x%x reg 0x%x\n", + adapter->name, op, phy_addr, reg); + return -EIO; + } + if (read) + *val = al_reg_read16( + (uint16_t *)&adapter->mac_regs_base->mac_10g.mdio_data); + return 0; +} + +static int al_eth_mdio_10g_mac_type45( + struct al_hal_eth_adapter *adapter, + int read, uint32_t port_addr, uint32_t device, uint32_t reg, uint16_t *val) +{ + int rc; + const char *op = (read == 1) ? "read":"write"; + uint32_t mdio_cfg_status; + uint16_t mdio_cmd; + + //wait if the HW is busy + rc = al_eth_mdio_10g_mac_wait_busy(adapter); + if (rc) { + al_err(" %s mdio %s failed. HW is busy\n", adapter->name, op); + return rc; + } + // set command register + mdio_cmd = (uint16_t)(0x1F & device); + mdio_cmd |= (0x1F & port_addr) << 5; + al_reg_write16(&adapter->mac_regs_base->mac_10g.mdio_cmd, + mdio_cmd); + + // send address frame + al_reg_write16(&adapter->mac_regs_base->mac_10g.mdio_regaddr, reg); + //wait for the busy to clear + rc = al_eth_mdio_10g_mac_wait_busy(adapter); + if (rc) { + al_err(" %s mdio %s (address frame) failed on timeout\n", adapter->name, op); + return rc; + } + + // if read, write again to the command register with READ bit set + if (read) { + mdio_cmd |= AL_BIT(15); //READ command + al_reg_write16( + (uint16_t *)&adapter->mac_regs_base->mac_10g.mdio_cmd, + mdio_cmd); + } else { + al_reg_write16( + (uint16_t *)&adapter->mac_regs_base->mac_10g.mdio_data, + *val); + } + //wait for the busy to clear + rc = al_eth_mdio_10g_mac_wait_busy(adapter); + if (rc) { + al_err(" %s mdio %s failed on timeout\n", adapter->name, op); + return rc; + } + + mdio_cfg_status = al_reg_read32(&adapter->mac_regs_base->mac_10g.mdio_cfg_status); + + if (mdio_cfg_status & AL_BIT(1)){ //error + al_err(" %s mdio %s failed on error. port 0x%x, device 0x%x reg 0x%x\n", + adapter->name, op, port_addr, device, reg); + return -EIO; + } + if (read) + *val = al_reg_read16( + (uint16_t *)&adapter->mac_regs_base->mac_10g.mdio_data); + return 0; +} + +/** + * acquire mdio interface ownership + * when mdio interface shared between multiple eth controllers, this function waits until the ownership granted for this controller. + * this function does nothing when the mdio interface is used only by this controller. + * + * @param adapter + * @return 0 on success, -ETIMEDOUT on timeout. + */ +static int al_eth_mdio_lock(struct al_hal_eth_adapter *adapter) +{ + int count = 0; + uint32_t mdio_ctrl_1; + + if (adapter->shared_mdio_if == AL_FALSE) + return 0; /* nothing to do when interface is not shared */ + + do { + mdio_ctrl_1 = al_reg_read32(&adapter->mac_regs_base->gen.mdio_ctrl_1); +/* + if (mdio_cfg_status & AL_BIT(1)){ //error + al_err(" %s mdio read failed on error. phy_addr 0x%x reg 0x%x\n", + udma_params.name, phy_addr, reg); + return -EIO; + }*/ + if (mdio_ctrl_1 & AL_BIT(0)){ + if (count > 0) + al_dbg("eth %s mdio interface still busy!\n", adapter->name); + }else{ + return 0; + } + al_udelay(AL_ETH_MDIO_DELAY_PERIOD); + }while(count++ < (AL_ETH_MDIO_DELAY_COUNT * 4)); + al_err(" %s mdio failed to take ownership. MDIO info reg: 0x%08x\n", + adapter->name, al_reg_read32(&adapter->mac_regs_base->gen.mdio_1)); + + return -ETIMEDOUT; +} + +/** + * free mdio interface ownership + * when mdio interface shared between multiple eth controllers, this function releases the ownership granted for this controller. + * this function does nothing when the mdio interface is used only by this controller. + * + * @param adapter + * @return 0. + */ +static int al_eth_mdio_free(struct al_hal_eth_adapter *adapter) +{ + if (adapter->shared_mdio_if == AL_FALSE) + return 0; /* nothing to do when interface is not shared */ + + al_reg_write32(&adapter->mac_regs_base->gen.mdio_ctrl_1, 0); + + /* + * Addressing RMN: 2917 + * + * RMN description: + * The HW spin-lock is stateless and doesn't maintain any scheduling + * policy. + * + * Software flow: + * After getting the lock wait 2 times the delay period in order to give + * the other port chance to take the lock and prevent starvation. + * This is not scalable to more than two ports. + */ + al_udelay(2 * AL_ETH_MDIO_DELAY_PERIOD); + + return 0; +} + +int al_eth_mdio_read(struct al_hal_eth_adapter *adapter, uint32_t phy_addr, uint32_t device, uint32_t reg, uint16_t *val) +{ + int rc; + rc = al_eth_mdio_lock(adapter); + + /*"interface ownership taken"*/ + if (rc) + return rc; + + if (adapter->mdio_if == AL_ETH_MDIO_IF_1G_MAC) + rc = al_eth_mdio_1g_mac_read(adapter, phy_addr, reg, val); + else + if (adapter->mdio_type == AL_ETH_MDIO_TYPE_CLAUSE_22) + rc = al_eth_mdio_10g_mac_type22(adapter, 1, phy_addr, reg, val); + else + rc = al_eth_mdio_10g_mac_type45(adapter, 1, phy_addr, device, reg, val); + + al_eth_mdio_free(adapter); + al_dbg("eth mdio read: phy_addr %x, device %x, reg %x val %x\n", phy_addr, device, reg, *val); + return rc; +} + +int al_eth_mdio_write(struct al_hal_eth_adapter *adapter, uint32_t phy_addr, uint32_t device, uint32_t reg, uint16_t val) +{ + int rc; + al_dbg("eth mdio write: phy_addr %x, device %x, reg %x, val %x\n", phy_addr, device, reg, val); + rc = al_eth_mdio_lock(adapter); + /* interface ownership taken */ + if (rc) + return rc; + + if (adapter->mdio_if == AL_ETH_MDIO_IF_1G_MAC) + rc = al_eth_mdio_1g_mac_write(adapter, phy_addr, reg, val); + else + if (adapter->mdio_type == AL_ETH_MDIO_TYPE_CLAUSE_22) + rc = al_eth_mdio_10g_mac_type22(adapter, 0, phy_addr, reg, &val); + else + rc = al_eth_mdio_10g_mac_type45(adapter, 0, phy_addr, device, reg, &val); + + al_eth_mdio_free(adapter); + return rc; +} + +static void al_dump_tx_desc(union al_udma_desc *tx_desc) +{ + uint32_t *ptr = (uint32_t *)tx_desc; + al_dbg("eth tx desc:\n"); + al_dbg("0x%08x\n", *(ptr++)); + al_dbg("0x%08x\n", *(ptr++)); + al_dbg("0x%08x\n", *(ptr++)); + al_dbg("0x%08x\n", *(ptr++)); +} + +static void +al_dump_tx_pkt(struct al_udma_q *tx_dma_q, struct al_eth_pkt *pkt) +{ + const char *tso = (pkt->flags & AL_ETH_TX_FLAGS_TSO) ? "TSO" : ""; + const char *l3_csum = (pkt->flags & AL_ETH_TX_FLAGS_IPV4_L3_CSUM) ? "L3 CSUM" : ""; + const char *l4_csum = (pkt->flags & AL_ETH_TX_FLAGS_L4_CSUM) ? + ((pkt->flags & AL_ETH_TX_FLAGS_L4_PARTIAL_CSUM) ? "L4 PARTIAL CSUM" : "L4 FULL CSUM") : ""; + const char *fcs = (pkt->flags & AL_ETH_TX_FLAGS_L2_DIS_FCS) ? "Disable FCS" : ""; + const char *ptp = (pkt->flags & AL_ETH_TX_FLAGS_TS) ? "TX_PTP" : ""; + const char *l3_proto_name = "unknown"; + const char *l4_proto_name = "unknown"; + const char *outer_l3_proto_name = "N/A"; + const char *tunnel_mode = ((pkt->tunnel_mode & AL_ETH_TUNNEL_WITH_UDP) == + AL_ETH_TUNNEL_WITH_UDP) ? + "TUNNEL_WITH_UDP" : + ((pkt->tunnel_mode & AL_ETH_TUNNEL_NO_UDP) == + AL_ETH_TUNNEL_NO_UDP) ? + "TUNNEL_NO_UDP" : ""; + uint32_t total_len = 0; + int i; + + al_dbg("[%s %d]: flags: %s %s %s %s %s %s\n", tx_dma_q->udma->name, tx_dma_q->qid, + tso, l3_csum, l4_csum, fcs, ptp, tunnel_mode); + + switch (pkt->l3_proto_idx) { + case AL_ETH_PROTO_ID_IPv4: + l3_proto_name = "IPv4"; + break; + case AL_ETH_PROTO_ID_IPv6: + l3_proto_name = "IPv6"; + break; + default: + l3_proto_name = "unknown"; + break; + } + + switch (pkt->l4_proto_idx) { + case AL_ETH_PROTO_ID_TCP: + l4_proto_name = "TCP"; + break; + case AL_ETH_PROTO_ID_UDP: + l4_proto_name = "UDP"; + break; + default: + l4_proto_name = "unknown"; + break; + } + + switch (pkt->outer_l3_proto_idx) { + case AL_ETH_PROTO_ID_IPv4: + outer_l3_proto_name = "IPv4"; + break; + case AL_ETH_PROTO_ID_IPv6: + outer_l3_proto_name = "IPv6"; + break; + default: + outer_l3_proto_name = "N/A"; + break; + } + + al_dbg("[%s %d]: L3 proto: %d (%s). L4 proto: %d (%s). Outer_L3 proto: %d (%s). vlan source count %d. mod add %d. mod del %d\n", + tx_dma_q->udma->name, tx_dma_q->qid, pkt->l3_proto_idx, + l3_proto_name, pkt->l4_proto_idx, l4_proto_name, + pkt->outer_l3_proto_idx, outer_l3_proto_name, + pkt->source_vlan_count, pkt->vlan_mod_add_count, + pkt->vlan_mod_del_count); + + if (pkt->meta) { + const char * store = pkt->meta->store ? "Yes" : "No"; + + al_dbg("[%s %d]: tx pkt with meta data. words valid %x\n", + tx_dma_q->udma->name, tx_dma_q->qid, + pkt->meta->words_valid); + if (tx_dma_q->adapter_rev_id == AL_ETH_REV_ID_0) + al_dbg("[%s %d]: meta: store to cache %s. l3 hdr len %d. l3 hdr offset %d. l4 hdr len %d. mss sel %d\n" + , tx_dma_q->udma->name, tx_dma_q->qid, store, + pkt->meta->l3_header_len, pkt->meta->l3_header_offset, + pkt->meta->l4_header_len, + pkt->meta->mss_idx_sel); + else { + const char *ptp_val = (pkt->flags & AL_ETH_TX_FLAGS_TS) ? "Yes" : "No"; + al_dbg("[%s %d]: meta: store to cache %s. l3 hdr len %d. l3 hdr offset %d. l4 hdr len %d. mss val %d ts_index %d ts_val:%s\n" + , tx_dma_q->udma->name, tx_dma_q->qid, store, + pkt->meta->l3_header_len, pkt->meta->l3_header_offset, + pkt->meta->l4_header_len, pkt->meta->mss_val, + pkt->meta->ts_index, ptp_val); + al_dbg("outer_l3_hdr_offset %d. outer_l3_len %d.\n", + pkt->meta->outer_l3_offset, pkt->meta->outer_l3_len); + } + } + + al_dbg("[%s %d]: num of bufs: %d\n", tx_dma_q->udma->name, tx_dma_q->qid, + pkt->num_of_bufs); + for (i = 0; i < pkt->num_of_bufs; i++) { + al_dbg("eth [%s %d]: buf[%d]: len 0x%08x. address 0x%016llx\n", tx_dma_q->udma->name, tx_dma_q->qid, + i, pkt->bufs[i].len, (unsigned long long)pkt->bufs[i].addr); + total_len += pkt->bufs[i].len; + } + al_dbg("[%s %d]: total len: 0x%08x\n", tx_dma_q->udma->name, tx_dma_q->qid, total_len); + +} + +/* TX */ +/** + * add packet to transmission queue + */ +int al_eth_tx_pkt_prepare(struct al_udma_q *tx_dma_q, struct al_eth_pkt *pkt) +{ + union al_udma_desc *tx_desc; + uint32_t tx_descs; + uint32_t flags = AL_M2S_DESC_FIRST | + AL_M2S_DESC_CONCAT | + (pkt->flags & AL_ETH_TX_FLAGS_INT); + uint64_t vmid = ((uint64_t)pkt->vmid) << AL_UDMA_DESC_VMID_SHIFT; + uint32_t meta_ctrl; + uint32_t ring_id; + int buf_idx; + + al_dbg("[%s %d]: new tx pkt\n", tx_dma_q->udma->name, tx_dma_q->qid); + + al_dump_tx_pkt(tx_dma_q, pkt); + + tx_descs = pkt->num_of_bufs; + if (pkt->meta) { + tx_descs += 1; + } +#ifdef AL_ETH_EX + al_assert((pkt->ext_meta_data == NULL) || (tx_dma_q->adapter_rev_id > AL_ETH_REV_ID_2)); + + tx_descs += al_eth_ext_metadata_needed_descs(pkt->ext_meta_data); + al_dbg("[%s %d]: %d Descriptors: ext_meta (%d). meta (%d). buffer (%d) ", + tx_dma_q->udma->name, tx_dma_q->qid, tx_descs, + al_eth_ext_metadata_needed_descs(pkt->ext_meta_data), + (pkt->meta != NULL), pkt->num_of_bufs); +#endif + + if (unlikely(al_udma_available_get(tx_dma_q) < tx_descs)) { + al_dbg("[%s %d]: failed to allocate (%d) descriptors", + tx_dma_q->udma->name, tx_dma_q->qid, tx_descs); + return 0; + } + +#ifdef AL_ETH_EX + if (pkt->ext_meta_data != NULL) { + al_eth_ext_metadata_create(tx_dma_q, &flags, pkt->ext_meta_data); + flags &= ~(AL_M2S_DESC_FIRST | AL_ETH_TX_FLAGS_INT); + } +#endif + + if (pkt->meta) { + uint32_t meta_word_0 = 0; + uint32_t meta_word_1 = 0; + uint32_t meta_word_2 = 0; + uint32_t meta_word_3 = 0; + + meta_word_0 |= flags | AL_M2S_DESC_META_DATA; + meta_word_0 &= ~AL_M2S_DESC_CONCAT; + flags &= ~(AL_M2S_DESC_FIRST | AL_ETH_TX_FLAGS_INT); + + tx_desc = al_udma_desc_get(tx_dma_q); + /* get ring id, and clear FIRST and Int flags */ + ring_id = al_udma_ring_id_get(tx_dma_q) << + AL_M2S_DESC_RING_ID_SHIFT; + + meta_word_0 |= ring_id; + meta_word_0 |= pkt->meta->words_valid << 12; + + if (pkt->meta->store) + meta_word_0 |= AL_ETH_TX_META_STORE; + + if (pkt->meta->words_valid & 1) { + meta_word_0 |= pkt->meta->vlan1_cfi_sel; + meta_word_0 |= pkt->meta->vlan2_vid_sel << 2; + meta_word_0 |= pkt->meta->vlan2_cfi_sel << 4; + meta_word_0 |= pkt->meta->vlan2_pbits_sel << 6; + meta_word_0 |= pkt->meta->vlan2_ether_sel << 8; + } + + if (pkt->meta->words_valid & 2) { + meta_word_1 = pkt->meta->vlan1_new_vid; + meta_word_1 |= pkt->meta->vlan1_new_cfi << 12; + meta_word_1 |= pkt->meta->vlan1_new_pbits << 13; + meta_word_1 |= pkt->meta->vlan2_new_vid << 16; + meta_word_1 |= pkt->meta->vlan2_new_cfi << 28; + meta_word_1 |= pkt->meta->vlan2_new_pbits << 29; + } + + if (pkt->meta->words_valid & 4) { + meta_word_2 = pkt->meta->l3_header_len & AL_ETH_TX_META_L3_LEN_MASK; + meta_word_2 |= (pkt->meta->l3_header_offset & AL_ETH_TX_META_L3_OFF_MASK) << + AL_ETH_TX_META_L3_OFF_SHIFT; + meta_word_2 |= (pkt->meta->l4_header_len & 0x3f) << 16; + + if (tx_dma_q->adapter_rev_id == AL_ETH_REV_ID_0) { + meta_word_2 |= (pkt->meta->mss_idx_sel & 7) << 24; + } else { + uint32_t l3_offset; + + if (unlikely(pkt->flags & AL_ETH_TX_FLAGS_TS)) + meta_word_0 |= pkt->meta->ts_index << AL_ETH_TX_META_MSS_MSB_TS_VAL_SHIFT; + else + meta_word_0 |= (((pkt->meta->mss_val & 0x3c00) >> 10) + << AL_ETH_TX_META_MSS_MSB_TS_VAL_SHIFT); + meta_word_2 |= ((pkt->meta->mss_val & 0x03ff) + << AL_ETH_TX_META_MSS_LSB_VAL_SHIFT); + + /* + * move from bytes to multiplication of 2 as the HW + * expect to get it + */ + l3_offset = (pkt->meta->outer_l3_offset >> 1); + + meta_word_0 |= + (((l3_offset & + AL_ETH_TX_META_OUTER_L3_OFF_HIGH_MASK) >> 3) + << AL_ETH_TX_META_OUTER_L3_OFF_HIGH_SHIFT); + + meta_word_3 |= + ((l3_offset & + AL_ETH_TX_META_OUTER_L3_OFF_LOW_MASK) + << AL_ETH_TX_META_OUTER_L3_OFF_LOW_SHIFT); + + /* + * shift right 2 bits to work in multiplication of 4 + * as the HW expect to get it + */ + meta_word_3 |= + (((pkt->meta->outer_l3_len >> 2) & + AL_ETH_TX_META_OUTER_L3_LEN_MASK) + << AL_ETH_TX_META_OUTER_L3_LEN_SHIFT); + } + } + + tx_desc->tx_meta.len_ctrl = swap32_to_le(meta_word_0); + tx_desc->tx_meta.meta_ctrl = swap32_to_le(meta_word_1); + tx_desc->tx_meta.meta1 = swap32_to_le(meta_word_2); + tx_desc->tx_meta.meta2 = swap32_to_le(meta_word_3); + al_dump_tx_desc(tx_desc); + } + + meta_ctrl = pkt->flags & AL_ETH_TX_PKT_META_FLAGS; + + /* L4_PARTIAL_CSUM without L4_CSUM is invalid option */ + al_assert((pkt->flags & (AL_ETH_TX_FLAGS_L4_CSUM|AL_ETH_TX_FLAGS_L4_PARTIAL_CSUM)) != + AL_ETH_TX_FLAGS_L4_PARTIAL_CSUM); + + /* TSO packets can't have Timestamp enabled */ + al_assert((pkt->flags & (AL_ETH_TX_FLAGS_TSO|AL_ETH_TX_FLAGS_TS)) != + (AL_ETH_TX_FLAGS_TSO|AL_ETH_TX_FLAGS_TS)); + + meta_ctrl |= pkt->l3_proto_idx; + meta_ctrl |= pkt->l4_proto_idx << AL_ETH_TX_L4_PROTO_IDX_SHIFT; + meta_ctrl |= pkt->source_vlan_count << AL_ETH_TX_SRC_VLAN_CNT_SHIFT; + meta_ctrl |= pkt->vlan_mod_add_count << AL_ETH_TX_VLAN_MOD_ADD_SHIFT; + meta_ctrl |= pkt->vlan_mod_del_count << AL_ETH_TX_VLAN_MOD_DEL_SHIFT; + meta_ctrl |= pkt->vlan_mod_v1_ether_sel << AL_ETH_TX_VLAN_MOD_E_SEL_SHIFT; + meta_ctrl |= pkt->vlan_mod_v1_vid_sel << AL_ETH_TX_VLAN_MOD_VID_SEL_SHIFT; + meta_ctrl |= pkt->vlan_mod_v1_pbits_sel << AL_ETH_TX_VLAN_MOD_PBIT_SEL_SHIFT; + +#ifdef AL_ETH_EX + if ((pkt->ext_meta_data != NULL) && (pkt->ext_meta_data->tx_crypto_data != NULL)) + meta_ctrl |= AL_ETH_TX_FLAGS_ENCRYPT; +#endif + + if (tx_dma_q->adapter_rev_id > AL_ETH_REV_ID_0) { + meta_ctrl |= pkt->tunnel_mode << AL_ETH_TX_TUNNEL_MODE_SHIFT; + if (pkt->outer_l3_proto_idx == AL_ETH_PROTO_ID_IPv4) + meta_ctrl |= 1 << AL_ETH_TX_OUTER_L3_PROTO_SHIFT; + } + + flags |= pkt->flags & AL_ETH_TX_PKT_UDMA_FLAGS; + for(buf_idx = 0; buf_idx < pkt->num_of_bufs; buf_idx++ ) { + uint32_t flags_len = flags; + + tx_desc = al_udma_desc_get(tx_dma_q); + /* get ring id, and clear FIRST and Int flags */ + ring_id = al_udma_ring_id_get(tx_dma_q) << + AL_M2S_DESC_RING_ID_SHIFT; + + flags_len |= ring_id; + + if (buf_idx == (pkt->num_of_bufs - 1)) + flags_len |= AL_M2S_DESC_LAST; + + /* clear First and Int flags */ + flags &= AL_ETH_TX_FLAGS_NO_SNOOP; + flags |= AL_M2S_DESC_CONCAT; + + flags_len |= pkt->bufs[buf_idx].len & AL_M2S_DESC_LEN_MASK; + tx_desc->tx.len_ctrl = swap32_to_le(flags_len); + if (buf_idx == 0) + tx_desc->tx.meta_ctrl = swap32_to_le(meta_ctrl); + tx_desc->tx.buf_ptr = swap64_to_le( + pkt->bufs[buf_idx].addr | vmid); + al_dump_tx_desc(tx_desc); + } + + al_dbg("[%s %d]: pkt descriptors written into the tx queue. descs num (%d)\n", + tx_dma_q->udma->name, tx_dma_q->qid, tx_descs); + + return tx_descs; +} + + +void al_eth_tx_dma_action(struct al_udma_q *tx_dma_q, uint32_t tx_descs) +{ + /* add tx descriptors */ + al_udma_desc_action_add(tx_dma_q, tx_descs); +} + +/** + * get number of completed tx descriptors, upper layer should derive from + */ +int al_eth_comp_tx_get(struct al_udma_q *tx_dma_q) +{ + int rc; + + rc = al_udma_cdesc_get_all(tx_dma_q, NULL); + if (rc != 0) { + al_udma_cdesc_ack(tx_dma_q, rc); + al_dbg("[%s %d]: tx completion: descs (%d)\n", + tx_dma_q->udma->name, tx_dma_q->qid, rc); + } + + return rc; +} + +/** + * configure the TSO MSS val + */ +int al_eth_tso_mss_config(struct al_hal_eth_adapter *adapter, uint8_t idx, uint32_t mss_val) +{ + + al_assert(idx <= 8); /*valid MSS index*/ + al_assert(mss_val <= AL_ETH_TSO_MSS_MAX_VAL); /*valid MSS val*/ + al_assert(mss_val >= AL_ETH_TSO_MSS_MIN_VAL); /*valid MSS val*/ + + al_reg_write32(&adapter->ec_regs_base->tso_sel[idx].mss, mss_val); + return 0; +} + + +/* RX */ +/** + * config the rx descriptor fields + */ +void al_eth_rx_desc_config( + struct al_hal_eth_adapter *adapter, + enum al_eth_rx_desc_lro_context_val_res lro_sel, + enum al_eth_rx_desc_l4_offset_sel l4_offset_sel, + enum al_eth_rx_desc_l3_offset_sel l3_offset_sel, + enum al_eth_rx_desc_l4_chk_res_sel l4_sel, + enum al_eth_rx_desc_l3_chk_res_sel l3_sel, + enum al_eth_rx_desc_l3_proto_idx_sel l3_proto_sel, + enum al_eth_rx_desc_l4_proto_idx_sel l4_proto_sel, + enum al_eth_rx_desc_frag_sel frag_sel) +{ + uint32_t reg_val = 0; + + reg_val |= (lro_sel == AL_ETH_L4_OFFSET) ? + EC_RFW_CFG_A_0_LRO_CONTEXT_SEL : 0; + + reg_val |= (l4_sel == AL_ETH_L4_INNER_OUTER_CHK) ? + EC_RFW_CFG_A_0_META_L4_CHK_RES_SEL : 0; + + reg_val |= l3_sel << EC_RFW_CFG_A_0_META_L3_CHK_RES_SEL_SHIFT; + + al_reg_write32(&adapter->ec_regs_base->rfw.cfg_a_0, reg_val); + + reg_val = al_reg_read32(&adapter->ec_regs_base->rfw.meta); + if (l3_proto_sel == AL_ETH_L3_PROTO_IDX_INNER) + reg_val |= EC_RFW_META_L3_PROT_SEL; + else + reg_val &= ~EC_RFW_META_L3_PROT_SEL; + + if (l4_proto_sel == AL_ETH_L4_PROTO_IDX_INNER) + reg_val |= EC_RFW_META_L4_PROT_SEL; + else + reg_val &= ~EC_RFW_META_L4_PROT_SEL; + + if (l4_offset_sel == AL_ETH_L4_OFFSET_INNER) + reg_val |= EC_RFW_META_L4_OFFSET_SEL; + else + reg_val &= ~EC_RFW_META_L4_OFFSET_SEL; + + if (l3_offset_sel == AL_ETH_L3_OFFSET_INNER) + reg_val |= EC_RFW_META_L3_OFFSET_SEL; + else + reg_val &= ~EC_RFW_META_L3_OFFSET_SEL; + + if (frag_sel == AL_ETH_FRAG_INNER) + reg_val |= EC_RFW_META_FRAG_SEL; + else + reg_val &= ~EC_RFW_META_FRAG_SEL; + + + al_reg_write32(&adapter->ec_regs_base->rfw.meta, reg_val); +} + +/** + * Configure RX header split + */ +int al_eth_rx_header_split_config(struct al_hal_eth_adapter *adapter, al_bool enable, uint32_t header_len) +{ + uint32_t reg; + + if (adapter->rev_id < AL_ETH_REV_ID_1) { + al_err("[%s]: header split feature not supported by this revision\n", adapter->name); + return -EINVAL; + } + reg = al_reg_read32(&adapter->ec_regs_base->rfw.hdr_split); + if (enable == AL_TRUE) + reg |= EC_RFW_HDR_SPLIT_EN; + else + reg &= ~EC_RFW_HDR_SPLIT_EN; + + AL_REG_FIELD_SET(reg, EC_RFW_HDR_SPLIT_DEF_LEN_MASK, EC_RFW_HDR_SPLIT_DEF_LEN_SHIFT, header_len); + al_reg_write32(&adapter->ec_regs_base->rfw.hdr_split, reg); + return 0; +} + + +/** + * enable / disable header split in the udma queue. + * length will be taken from the udma configuration to enable different length per queue. + */ +int al_eth_rx_header_split_force_len_config(struct al_hal_eth_adapter *adapter, + al_bool enable, + uint32_t qid, + uint32_t header_len) +{ + al_udma_s2m_q_compl_hdr_split_config(&(adapter->rx_udma.udma_q[qid]), enable, + AL_TRUE, header_len); + + return 0; +} + + +/** + * add buffer to receive queue + */ +int al_eth_rx_buffer_add(struct al_udma_q *rx_dma_q, + struct al_buf *buf, uint32_t flags, + struct al_buf *header_buf) +{ + uint64_t vmid = ((uint64_t)flags & AL_ETH_RX_FLAGS_VMID_MASK) << + AL_UDMA_DESC_VMID_SHIFT; + uint32_t flags_len = flags & ~AL_ETH_RX_FLAGS_VMID_MASK; + union al_udma_desc *rx_desc; + + al_dbg("[%s %d]: add rx buffer.\n", rx_dma_q->udma->name, rx_dma_q->qid); + +#if 1 + if (unlikely(al_udma_available_get(rx_dma_q) < 1)) { + al_dbg("[%s]: rx q (%d) has no enough free descriptor", + rx_dma_q->udma->name, rx_dma_q->qid); + return -ENOSPC; + } +#endif + rx_desc = al_udma_desc_get(rx_dma_q); + + flags_len |= al_udma_ring_id_get(rx_dma_q) << AL_S2M_DESC_RING_ID_SHIFT; + flags_len |= buf->len & AL_S2M_DESC_LEN_MASK; + + if (flags & AL_S2M_DESC_DUAL_BUF) { + al_assert(header_buf != NULL); /*header valid in dual buf */ + al_assert((rx_dma_q->udma->rev_id >= AL_UDMA_REV_ID_2) || + (AL_ADDR_HIGH(buf->addr) == AL_ADDR_HIGH(header_buf->addr))); + + flags_len |= ((header_buf->len >> AL_S2M_DESC_LEN2_GRANULARITY_SHIFT) + << AL_S2M_DESC_LEN2_SHIFT) & AL_S2M_DESC_LEN2_MASK; + rx_desc->rx.buf2_ptr_lo = swap32_to_le(AL_ADDR_LOW(header_buf->addr)); + } + rx_desc->rx.len_ctrl = swap32_to_le(flags_len); + rx_desc->rx.buf1_ptr = swap64_to_le(buf->addr | vmid); + + return 0; +} + +/** + * notify the hw engine about rx descriptors that were added to the receive queue + */ +void al_eth_rx_buffer_action(struct al_udma_q *rx_dma_q, uint32_t descs_num) +{ + al_dbg("[%s]: update the rx engine tail pointer: queue %d. descs %d\n", + rx_dma_q->udma->name, rx_dma_q->qid, descs_num); + + /* add rx descriptor */ + al_udma_desc_action_add(rx_dma_q, descs_num); +} + +/** + * get packet from RX completion ring + */ +uint32_t al_eth_pkt_rx(struct al_udma_q *rx_dma_q, + struct al_eth_pkt *pkt) +{ + volatile union al_udma_cdesc *cdesc; + volatile al_eth_rx_cdesc *rx_desc; + uint32_t i; + uint32_t rc; + + rc = al_udma_cdesc_packet_get(rx_dma_q, &cdesc); + if (rc == 0) + return 0; + + al_assert(rc <= AL_ETH_PKT_MAX_BUFS); + + al_dbg("[%s]: fetch rx packet: queue %d.\n", + rx_dma_q->udma->name, rx_dma_q->qid); + + pkt->rx_header_len = 0; + for (i = 0; i < rc; i++) { + uint32_t buf1_len, buf2_len; + + /* get next descriptor */ + rx_desc = (volatile al_eth_rx_cdesc *)al_cdesc_next(rx_dma_q, cdesc, i); + + buf1_len = swap32_from_le(rx_desc->len); + + if ((i == 0) && (swap32_from_le(rx_desc->word2) & + AL_UDMA_CDESC_BUF2_USED)) { + buf2_len = swap32_from_le(rx_desc->word2); + pkt->rx_header_len = (buf2_len & AL_S2M_DESC_LEN2_MASK) >> + AL_S2M_DESC_LEN2_SHIFT; + } + if ((swap32_from_le(rx_desc->ctrl_meta) & AL_UDMA_CDESC_BUF1_USED) && + ((swap32_from_le(rx_desc->ctrl_meta) & AL_UDMA_CDESC_DDP) == 0)) + pkt->bufs[i].len = buf1_len & AL_S2M_DESC_LEN_MASK; + else + pkt->bufs[i].len = 0; + } + /* get flags from last desc */ + pkt->flags = swap32_from_le(rx_desc->ctrl_meta); +#ifdef AL_ETH_RX_DESC_RAW_GET + pkt->rx_desc_raw[0] = pkt->flags; + pkt->rx_desc_raw[1] = swap32_from_le(rx_desc->len); + pkt->rx_desc_raw[2] = swap32_from_le(rx_desc->word2); + pkt->rx_desc_raw[3] = swap32_from_le(rx_desc->word3); +#endif + /* update L3/L4 proto index */ + pkt->l3_proto_idx = pkt->flags & AL_ETH_RX_L3_PROTO_IDX_MASK; + pkt->l4_proto_idx = (pkt->flags >> AL_ETH_RX_L4_PROTO_IDX_SHIFT) & + AL_ETH_RX_L4_PROTO_IDX_MASK; + pkt->rxhash = (swap32_from_le(rx_desc->len) & AL_ETH_RX_HASH_MASK) >> + AL_ETH_RX_HASH_SHIFT; + pkt->l3_offset = (swap32_from_le(rx_desc->word2) & AL_ETH_RX_L3_OFFSET_MASK) >> AL_ETH_RX_L3_OFFSET_SHIFT; + + al_udma_cdesc_ack(rx_dma_q, rc); + return rc; +} + + +int al_eth_rx_parser_entry_update(struct al_hal_eth_adapter *adapter, uint32_t idx, + struct al_eth_epe_p_reg_entry *reg_entry, + struct al_eth_epe_control_entry *control_entry) +{ + al_eth_epe_entry_set(adapter, idx, reg_entry, control_entry); + return 0; +} + +#define AL_ETH_THASH_UDMA_SHIFT 0 +#define AL_ETH_THASH_UDMA_MASK (0xF << AL_ETH_THASH_UDMA_SHIFT) + +#define AL_ETH_THASH_Q_SHIFT 4 +#define AL_ETH_THASH_Q_MASK (0x3 << AL_ETH_THASH_Q_SHIFT) + +int al_eth_thash_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint8_t udma, uint32_t queue) +{ + uint32_t entry; + al_assert(idx < AL_ETH_RX_THASH_TABLE_SIZE); /*valid THASH index*/ + + entry = (udma << AL_ETH_THASH_UDMA_SHIFT) & AL_ETH_THASH_UDMA_MASK; + entry |= (queue << AL_ETH_THASH_Q_SHIFT) & AL_ETH_THASH_Q_MASK; + + al_reg_write32(&adapter->ec_regs_base->rfw.thash_table_addr, idx); + al_reg_write32(&adapter->ec_regs_base->rfw.thash_table_data, entry); + return 0; +} + +int al_eth_fsm_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint32_t entry) +{ + + al_assert(idx < AL_ETH_RX_FSM_TABLE_SIZE); /*valid FSM index*/ + + + al_reg_write32(&adapter->ec_regs_base->rfw.fsm_table_addr, idx); + al_reg_write32(&adapter->ec_regs_base->rfw.fsm_table_data, entry); + return 0; +} + +static uint32_t al_eth_fwd_ctrl_entry_to_val(struct al_eth_fwd_ctrl_table_entry *entry) +{ + uint32_t val = 0; + AL_REG_FIELD_SET(val, AL_FIELD_MASK(3,0), 0, entry->prio_sel); + AL_REG_FIELD_SET(val, AL_FIELD_MASK(7,4), 4, entry->queue_sel_1); + AL_REG_FIELD_SET(val, AL_FIELD_MASK(9,8), 8, entry->queue_sel_2); + AL_REG_FIELD_SET(val, AL_FIELD_MASK(13,10), 10, entry->udma_sel); + AL_REG_FIELD_SET(val, AL_FIELD_MASK(17,15), 15, entry->hdr_split_len_sel); + if (entry->hdr_split_len_sel != AL_ETH_CTRL_TABLE_HDR_SPLIT_LEN_SEL_0) + val |= AL_BIT(18); + AL_REG_BIT_VAL_SET(val, 19, !!(entry->filter == AL_TRUE)); + + return val; +} + +static int al_eth_ctrl_index_match(struct al_eth_fwd_ctrl_table_index *index, uint32_t i) { + if ((index->vlan_table_out != AL_ETH_FWD_CTRL_IDX_VLAN_TABLE_OUT_ANY) + && (index->vlan_table_out != AL_REG_BIT_GET(i, 0))) + return 0; + if ((index->tunnel_exist != AL_ETH_FWD_CTRL_IDX_TUNNEL_ANY) + && (index->tunnel_exist != AL_REG_BIT_GET(i, 1))) + return 0; + if ((index->vlan_exist != AL_ETH_FWD_CTRL_IDX_VLAN_ANY) + && (index->vlan_exist != AL_REG_BIT_GET(i, 2))) + return 0; + if ((index->mac_table_match != AL_ETH_FWD_CTRL_IDX_MAC_TABLE_ANY) + && (index->mac_table_match != AL_REG_BIT_GET(i, 3))) + return 0; + if ((index->protocol_id != AL_ETH_PROTO_ID_ANY) + && (index->protocol_id != AL_REG_FIELD_GET(i, AL_FIELD_MASK(8,4),4))) + return 0; + if ((index->mac_type != AL_ETH_FWD_CTRL_IDX_MAC_DA_TYPE_ANY) + && (index->mac_type != AL_REG_FIELD_GET(i, AL_FIELD_MASK(10,9),9))) + return 0; + return 1; +} + +int al_eth_ctrl_table_set(struct al_hal_eth_adapter *adapter, + struct al_eth_fwd_ctrl_table_index *index, + struct al_eth_fwd_ctrl_table_entry *entry) +{ + uint32_t val = al_eth_fwd_ctrl_entry_to_val(entry); + uint32_t i; + + for (i = 0; i < AL_ETH_RX_CTRL_TABLE_SIZE; i++) { + if (al_eth_ctrl_index_match(index, i)) { + al_reg_write32(&adapter->ec_regs_base->rfw.ctrl_table_addr, i); + al_reg_write32(&adapter->ec_regs_base->rfw.ctrl_table_data, val); + } + } + return 0; +} + +int al_eth_ctrl_table_def_set(struct al_hal_eth_adapter *adapter, + al_bool use_table, + struct al_eth_fwd_ctrl_table_entry *entry) +{ + uint32_t val = al_eth_fwd_ctrl_entry_to_val(entry); + + if (use_table) + val |= EC_RFW_CTRL_TABLE_DEF_SEL; + + al_reg_write32(&adapter->ec_regs_base->rfw.ctrl_table_def, val); + + return 0; +} + +int al_eth_ctrl_table_raw_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint32_t entry) +{ + + al_assert(idx < AL_ETH_RX_CTRL_TABLE_SIZE); /* valid CTRL index */ + + + al_reg_write32(&adapter->ec_regs_base->rfw.ctrl_table_addr, idx); + al_reg_write32(&adapter->ec_regs_base->rfw.ctrl_table_data, entry); + return 0; +} + +int al_eth_ctrl_table_def_raw_set(struct al_hal_eth_adapter *adapter, uint32_t val) +{ + al_reg_write32(&adapter->ec_regs_base->rfw.ctrl_table_def, val); + + return 0; +} + +int al_eth_hash_key_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint32_t val) +{ + + al_assert(idx < AL_ETH_RX_HASH_KEY_NUM); /*valid CTRL index*/ + + al_reg_write32(&adapter->ec_regs_base->rfw_hash[idx].key, val); + + return 0; +} + +static uint32_t al_eth_fwd_mac_table_entry_to_val(struct al_eth_fwd_mac_table_entry *entry) +{ + uint32_t val = 0; + + val |= (entry->filter == AL_TRUE) ? EC_FWD_MAC_CTRL_RX_VAL_DROP : 0; + val |= ((entry->udma_mask << EC_FWD_MAC_CTRL_RX_VAL_UDMA_SHIFT) & + EC_FWD_MAC_CTRL_RX_VAL_UDMA_MASK); + + val |= ((entry->qid << EC_FWD_MAC_CTRL_RX_VAL_QID_SHIFT) & + EC_FWD_MAC_CTRL_RX_VAL_QID_MASK); + + val |= (entry->rx_valid == AL_TRUE) ? EC_FWD_MAC_CTRL_RX_VALID : 0; + + val |= ((entry->tx_target << EC_FWD_MAC_CTRL_TX_VAL_SHIFT) & + EC_FWD_MAC_CTRL_TX_VAL_MASK); + + val |= (entry->tx_valid == AL_TRUE) ? EC_FWD_MAC_CTRL_TX_VALID : 0; + + return val; +} + +int al_eth_fwd_mac_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, + struct al_eth_fwd_mac_table_entry *entry) +{ + uint32_t val; + + al_assert(idx < AL_ETH_FWD_MAC_NUM); /*valid FWD MAC index */ + + val = (entry->addr[2] << 24) | (entry->addr[3] << 16) | + (entry->addr[4] << 8) | entry->addr[5]; + al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].data_l, val); + val = (entry->addr[0] << 8) | entry->addr[1]; + al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].data_h, val); + val = (entry->mask[2] << 24) | (entry->mask[3] << 16) | + (entry->mask[4] << 8) | entry->mask[5]; + al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].mask_l, val); + val = (entry->mask[0] << 8) | entry->mask[1]; + al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].mask_h, val); + + val = al_eth_fwd_mac_table_entry_to_val(entry); + al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].ctrl, val); + return 0; +} + + + +int al_eth_fwd_mac_addr_raw_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint32_t addr_lo, uint32_t addr_hi, uint32_t mask_lo, uint32_t mask_hi) +{ + al_assert(idx < AL_ETH_FWD_MAC_NUM); /*valid FWD MAC index */ + + al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].data_l, addr_lo); + al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].data_h, addr_hi); + al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].mask_l, mask_lo); + al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].mask_h, mask_hi); + + return 0; +} + +int al_eth_fwd_mac_ctrl_raw_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint32_t ctrl) +{ + al_assert(idx < AL_ETH_FWD_MAC_NUM); /*valid FWD MAC index */ + + al_reg_write32(&adapter->ec_regs_base->fwd_mac[idx].ctrl, ctrl); + + return 0; +} + +int al_eth_mac_addr_store(void * __iomem ec_base, uint32_t idx, uint8_t *addr) +{ + struct al_ec_regs __iomem *ec_regs_base = (struct al_ec_regs __iomem*)ec_base; + uint32_t val; + + al_assert(idx < AL_ETH_FWD_MAC_NUM); /*valid FWD MAC index */ + + val = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5]; + al_reg_write32(&ec_regs_base->fwd_mac[idx].data_l, val); + val = (addr[0] << 8) | addr[1]; + al_reg_write32(&ec_regs_base->fwd_mac[idx].data_h, val); + return 0; +} + +int al_eth_mac_addr_read(void * __iomem ec_base, uint32_t idx, uint8_t *addr) +{ + struct al_ec_regs __iomem *ec_regs_base = (struct al_ec_regs __iomem*)ec_base; + uint32_t addr_lo = al_reg_read32(&ec_regs_base->fwd_mac[idx].data_l); + uint16_t addr_hi = al_reg_read32(&ec_regs_base->fwd_mac[idx].data_h); + + addr[5] = addr_lo & 0xff; + addr[4] = (addr_lo >> 8) & 0xff; + addr[3] = (addr_lo >> 16) & 0xff; + addr[2] = (addr_lo >> 24) & 0xff; + addr[1] = addr_hi & 0xff; + addr[0] = (addr_hi >> 8) & 0xff; + return 0; +} + +int al_eth_fwd_mhash_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint8_t udma_mask, uint8_t qid) +{ + uint32_t val = 0; + al_assert(idx < AL_ETH_FWD_MAC_HASH_NUM); /* valid MHASH index */ + + AL_REG_FIELD_SET(val, AL_FIELD_MASK(3,0), 0, udma_mask); + AL_REG_FIELD_SET(val, AL_FIELD_MASK(5,4), 4, qid); + + al_reg_write32(&adapter->ec_regs_base->rfw.mhash_table_addr, idx); + al_reg_write32(&adapter->ec_regs_base->rfw.mhash_table_data, val); + return 0; +} +static uint32_t al_eth_fwd_vid_entry_to_val(struct al_eth_fwd_vid_table_entry *entry) +{ + uint32_t val = 0; + AL_REG_BIT_VAL_SET(val, 0, entry->control); + AL_REG_BIT_VAL_SET(val, 1, entry->filter); + AL_REG_FIELD_SET(val, AL_FIELD_MASK(5,2), 2, entry->udma_mask); + + return val; +} + +int al_eth_fwd_vid_config_set(struct al_hal_eth_adapter *adapter, al_bool use_table, + struct al_eth_fwd_vid_table_entry *default_entry, + uint32_t default_vlan) +{ + uint32_t reg; + + reg = al_eth_fwd_vid_entry_to_val(default_entry); + if (use_table) + reg |= EC_RFW_VID_TABLE_DEF_SEL; + else + reg &= ~EC_RFW_VID_TABLE_DEF_SEL; + al_reg_write32(&adapter->ec_regs_base->rfw.vid_table_def, reg); + al_reg_write32(&adapter->ec_regs_base->rfw.default_vlan, default_vlan); + + return 0; +} + +int al_eth_fwd_vid_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, + struct al_eth_fwd_vid_table_entry *entry) +{ + uint32_t val; + al_assert(idx < AL_ETH_FWD_VID_TABLE_NUM); /* valid VID index */ + + val = al_eth_fwd_vid_entry_to_val(entry); + al_reg_write32(&adapter->ec_regs_base->rfw.vid_table_addr, idx); + al_reg_write32(&adapter->ec_regs_base->rfw.vid_table_data, val); + return 0; +} + +int al_eth_fwd_pbits_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint8_t prio) +{ + + al_assert(idx < AL_ETH_FWD_PBITS_TABLE_NUM); /* valid PBIT index */ + al_assert(prio < AL_ETH_FWD_PRIO_TABLE_NUM); /* valid PRIO index */ + al_reg_write32(&adapter->ec_regs_base->rfw.pbits_table_addr, idx); + al_reg_write32(&adapter->ec_regs_base->rfw.pbits_table_data, prio); + return 0; +} + +int al_eth_fwd_priority_table_set(struct al_hal_eth_adapter *adapter, uint8_t prio, uint8_t qid) +{ + al_assert(prio < AL_ETH_FWD_PRIO_TABLE_NUM); /* valid PRIO index */ + + al_reg_write32(&adapter->ec_regs_base->rfw_priority[prio].queue, qid); + return 0; +} + + +int al_eth_fwd_dscp_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint8_t prio) +{ + + al_assert(idx < AL_ETH_FWD_DSCP_TABLE_NUM); /* valid DSCP index */ + + + al_reg_write32(&adapter->ec_regs_base->rfw.dscp_table_addr, idx); + al_reg_write32(&adapter->ec_regs_base->rfw.dscp_table_data, prio); + return 0; +} + +int al_eth_fwd_tc_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, uint8_t prio) +{ + + al_assert(idx < AL_ETH_FWD_TC_TABLE_NUM); /* valid TC index */ + + + al_reg_write32(&adapter->ec_regs_base->rfw.tc_table_addr, idx); + al_reg_write32(&adapter->ec_regs_base->rfw.tc_table_data, prio); + return 0; +} + +/** Configure default UDMA register */ +int al_eth_fwd_default_udma_config(struct al_hal_eth_adapter *adapter, uint32_t idx, + uint8_t udma_mask) +{ + al_reg_write32_masked(&adapter->ec_regs_base->rfw_default[idx].opt_1, + EC_RFW_DEFAULT_OPT_1_UDMA_MASK, + udma_mask << EC_RFW_DEFAULT_OPT_1_UDMA_SHIFT); + return 0; +} + +/** Configure default queue register */ +int al_eth_fwd_default_queue_config(struct al_hal_eth_adapter *adapter, uint32_t idx, + uint8_t qid) +{ + al_reg_write32_masked(&adapter->ec_regs_base->rfw_default[idx].opt_1, + EC_RFW_DEFAULT_OPT_1_QUEUE_MASK, + qid << EC_RFW_DEFAULT_OPT_1_QUEUE_SHIFT); + return 0; +} + +/** Configure default priority register */ +int al_eth_fwd_default_priority_config(struct al_hal_eth_adapter *adapter, uint32_t idx, + uint8_t prio) +{ + al_reg_write32_masked(&adapter->ec_regs_base->rfw_default[idx].opt_1, + EC_RFW_DEFAULT_OPT_1_PRIORITY_MASK, + prio << EC_RFW_DEFAULT_OPT_1_PRIORITY_SHIFT); + return 0; +} + +int al_eth_switching_config_set(struct al_hal_eth_adapter *adapter, uint8_t udma_id, uint8_t forward_all_to_mac, uint8_t enable_int_switching, + enum al_eth_tx_switch_vid_sel_type vid_sel_type, + enum al_eth_tx_switch_dec_type uc_dec, + enum al_eth_tx_switch_dec_type mc_dec, + enum al_eth_tx_switch_dec_type bc_dec) +{ + uint32_t reg; + + if (udma_id == 0) { + reg = al_reg_read32(&adapter->ec_regs_base->tfw.tx_gen); + if (forward_all_to_mac) + reg |= EC_TFW_TX_GEN_FWD_ALL_TO_MAC; + else + reg &= ~EC_TFW_TX_GEN_FWD_ALL_TO_MAC; + al_reg_write32(&adapter->ec_regs_base->tfw.tx_gen, reg); + } + + reg = enable_int_switching; + reg |= (vid_sel_type & 7) << 1; + reg |= (bc_dec & 3) << 4; + reg |= (mc_dec & 3) << 6; + reg |= (uc_dec & 3) << 8; + al_reg_write32(&adapter->ec_regs_base->tfw_udma[udma_id].fwd_dec, reg); + + return 0; +} + +#define AL_ETH_RFW_FILTER_SUPPORTED(rev_id) \ + (AL_ETH_RFW_FILTER_UNDET_MAC | \ + AL_ETH_RFW_FILTER_DET_MAC | \ + AL_ETH_RFW_FILTER_TAGGED | \ + AL_ETH_RFW_FILTER_UNTAGGED | \ + AL_ETH_RFW_FILTER_BC | \ + AL_ETH_RFW_FILTER_MC | \ + AL_ETH_RFW_FILTER_VLAN_VID | \ + AL_ETH_RFW_FILTER_CTRL_TABLE | \ + AL_ETH_RFW_FILTER_PROT_INDEX | \ + ((rev_id > AL_ETH_REV_ID_0) ? ((AL_ETH_RFW_FILTER_WOL) | (AL_ETH_RFW_FILTER_PARSE)) : 0)) + +/* Configure the receive filters */ +int al_eth_filter_config(struct al_hal_eth_adapter *adapter, struct al_eth_filter_params *params) +{ + uint32_t reg; + + al_assert(params); /* valid params pointer */ + + if (params->filters & ~(AL_ETH_RFW_FILTER_SUPPORTED(adapter->rev_id))) { + al_err("[%s]: unsupported filter options (0x%08x)\n", adapter->name, params->filters); + return -EINVAL; + } + + reg = al_reg_read32(&adapter->ec_regs_base->rfw.out_cfg); + if (params->enable == AL_TRUE) + AL_REG_MASK_SET(reg, EC_RFW_OUT_CFG_DROP_EN); + else + AL_REG_MASK_CLEAR(reg, EC_RFW_OUT_CFG_DROP_EN); + al_reg_write32(&adapter->ec_regs_base->rfw.out_cfg, reg); + + al_reg_write32_masked( + &adapter->ec_regs_base->rfw.filter, + AL_ETH_RFW_FILTER_SUPPORTED(adapter->rev_id), + params->filters); + if (params->filters & AL_ETH_RFW_FILTER_PROT_INDEX) { + int i; + for (i = 0; i < AL_ETH_PROTOCOLS_NUM; i++) { + reg = al_reg_read32(&adapter->ec_regs_base->epe_a[i].prot_act); + if (params->filter_proto[i] == AL_TRUE) + AL_REG_MASK_SET(reg, EC_EPE_A_PROT_ACT_DROP); + else + AL_REG_MASK_CLEAR(reg, EC_EPE_A_PROT_ACT_DROP); + al_reg_write32(&adapter->ec_regs_base->epe_a[i].prot_act, reg); + } + } + return 0; +} + +/* Configure the receive override filters */ +int al_eth_filter_override_config(struct al_hal_eth_adapter *adapter, + struct al_eth_filter_override_params *params) +{ + uint32_t reg; + + al_assert(params); /* valid params pointer */ + + if (params->filters & ~(AL_ETH_RFW_FILTER_SUPPORTED(adapter->rev_id))) { + al_err("[%s]: unsupported override filter options (0x%08x)\n", adapter->name, params->filters); + return -EINVAL; + } + + al_reg_write32_masked( + &adapter->ec_regs_base->rfw.filter, + AL_ETH_RFW_FILTER_SUPPORTED(adapter->rev_id) << 16, + params->filters << 16); + + reg = al_reg_read32(&adapter->ec_regs_base->rfw.default_or); + AL_REG_FIELD_SET(reg, EC_RFW_DEFAULT_OR_UDMA_MASK, EC_RFW_DEFAULT_OR_UDMA_SHIFT, params->udma); + AL_REG_FIELD_SET(reg, EC_RFW_DEFAULT_OR_QUEUE_MASK, EC_RFW_DEFAULT_OR_QUEUE_SHIFT, params->qid); + al_reg_write32(&adapter->ec_regs_base->rfw.default_or, reg); + return 0; +} + + + +int al_eth_switching_default_bitmap_set(struct al_hal_eth_adapter *adapter, uint8_t udma_id, uint8_t udma_uc_bitmask, + uint8_t udma_mc_bitmask,uint8_t udma_bc_bitmask) +{ + al_reg_write32(&adapter->ec_regs_base->tfw_udma[udma_id].uc_udma, udma_uc_bitmask); + al_reg_write32(&adapter->ec_regs_base->tfw_udma[udma_id].mc_udma, udma_mc_bitmask); + al_reg_write32(&adapter->ec_regs_base->tfw_udma[udma_id].bc_udma, udma_bc_bitmask); + + return 0; +} + +int al_eth_flow_control_config(struct al_hal_eth_adapter *adapter, struct al_eth_flow_control_params *params) +{ + uint32_t reg; + int i; + al_assert(params); /* valid params pointer */ + + switch(params->type){ + case AL_ETH_FLOW_CONTROL_TYPE_LINK_PAUSE: + al_dbg("[%s]: config flow control to link pause mode.\n", adapter->name); + + /* config the mac */ + if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) { + /* set quanta value */ + al_reg_write32( + &adapter->mac_regs_base->mac_1g.pause_quant, + params->quanta); + al_reg_write32( + &adapter->ec_regs_base->efc.xoff_timer_1g, + params->quanta_th); + + } else if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) { + /* set quanta value */ + al_reg_write32( + &adapter->mac_regs_base->mac_10g.cl01_pause_quanta, + params->quanta); + /* set quanta threshold value */ + al_reg_write32( + &adapter->mac_regs_base->mac_10g.cl01_quanta_thresh, + params->quanta_th); + } else { + /* set quanta value */ + al_eth_40g_mac_reg_write(adapter, + ETH_MAC_GEN_V3_MAC_40G_CL01_PAUSE_QUANTA_ADDR, + params->quanta); + /* set quanta threshold value */ + al_eth_40g_mac_reg_write(adapter, + ETH_MAC_GEN_V3_MAC_40G_CL01_QUANTA_THRESH_ADDR, + params->quanta_th); + } + + if (params->obay_enable == AL_TRUE) + /* Tx path FIFO, unmask pause_on from MAC when PAUSE packet received */ + al_reg_write32(&adapter->ec_regs_base->efc.ec_pause, 1); + else + al_reg_write32(&adapter->ec_regs_base->efc.ec_pause, 0); + + + /* Rx path */ + if (params->gen_enable == AL_TRUE) + /* enable generating xoff from ec fifo almost full indication in hysteresis mode */ + al_reg_write32(&adapter->ec_regs_base->efc.ec_xoff, 1 << EC_EFC_EC_XOFF_MASK_2_SHIFT); + else + al_reg_write32(&adapter->ec_regs_base->efc.ec_xoff, 0); + + if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) + /* in 1G mode, enable generating xon from ec fifo in hysteresis mode*/ + al_reg_write32(&adapter->ec_regs_base->efc.xon, EC_EFC_XON_MASK_2 | EC_EFC_XON_MASK_1); + + /* set hysteresis mode thresholds */ + al_reg_write32(&adapter->ec_regs_base->efc.rx_fifo_hyst, params->rx_fifo_th_low | (params->rx_fifo_th_high << EC_EFC_RX_FIFO_HYST_TH_HIGH_SHIFT)); + + for (i = 0; i < 4; i++) { + if (params->obay_enable == AL_TRUE) + /* Tx path UDMA, unmask pause_on for all queues */ + al_reg_write32(&adapter->ec_regs_base->fc_udma[i].q_pause_0, + params->prio_q_map[i][0]); + else + al_reg_write32(&adapter->ec_regs_base->fc_udma[i].q_pause_0, 0); + + if (params->gen_enable == AL_TRUE) + /* Rx path UDMA, enable generating xoff from UDMA queue almost full indication */ + al_reg_write32(&adapter->ec_regs_base->fc_udma[i].q_xoff_0, params->prio_q_map[i][0]); + else + al_reg_write32(&adapter->ec_regs_base->fc_udma[i].q_xoff_0, 0); + } + break; + case AL_ETH_FLOW_CONTROL_TYPE_PFC: + al_dbg("[%s]: config flow control to PFC mode.\n", adapter->name); + al_assert(!AL_ETH_IS_1G_MAC(adapter->mac_mode)); /* pfc not available for RGMII mode */; + + for (i = 0; i < 4; i++) { + int prio; + for (prio = 0; prio < 8; prio++) { + if (params->obay_enable == AL_TRUE) + /* Tx path UDMA, unmask pause_on for all queues */ + al_reg_write32(&adapter->ec_regs_base->fc_udma[i].q_pause_0 + prio, + params->prio_q_map[i][prio]); + else + al_reg_write32(&adapter->ec_regs_base->fc_udma[i].q_pause_0 + prio, + 0); + + if (params->gen_enable == AL_TRUE) + al_reg_write32(&adapter->ec_regs_base->fc_udma[i].q_xoff_0 + prio, + params->prio_q_map[i][prio]); + else + al_reg_write32(&adapter->ec_regs_base->fc_udma[i].q_xoff_0 + prio, + 0); + } + } + + /* Rx path */ + /* enable generating xoff from ec fifo almost full indication in hysteresis mode */ + if (params->gen_enable == AL_TRUE) + al_reg_write32(&adapter->ec_regs_base->efc.ec_xoff, 0xFF << EC_EFC_EC_XOFF_MASK_2_SHIFT); + else + al_reg_write32(&adapter->ec_regs_base->efc.ec_xoff, 0); + + /* set hysteresis mode thresholds */ + al_reg_write32(&adapter->ec_regs_base->efc.rx_fifo_hyst, params->rx_fifo_th_low | (params->rx_fifo_th_high << EC_EFC_RX_FIFO_HYST_TH_HIGH_SHIFT)); + + if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) { + /* config the 10g_mac */ + /* set quanta value (same value for all prios) */ + reg = params->quanta | (params->quanta << 16); + al_reg_write32( + &adapter->mac_regs_base->mac_10g.cl01_pause_quanta, reg); + al_reg_write32( + &adapter->mac_regs_base->mac_10g.cl23_pause_quanta, reg); + al_reg_write32( + &adapter->mac_regs_base->mac_10g.cl45_pause_quanta, reg); + al_reg_write32( + &adapter->mac_regs_base->mac_10g.cl67_pause_quanta, reg); + /* set quanta threshold value (same value for all prios) */ + reg = params->quanta_th | (params->quanta_th << 16); + al_reg_write32( + &adapter->mac_regs_base->mac_10g.cl01_quanta_thresh, reg); + al_reg_write32( + &adapter->mac_regs_base->mac_10g.cl23_quanta_thresh, reg); + al_reg_write32( + &adapter->mac_regs_base->mac_10g.cl45_quanta_thresh, reg); + al_reg_write32( + &adapter->mac_regs_base->mac_10g.cl67_quanta_thresh, reg); + + /* enable PFC in the 10g_MAC */ + reg = al_reg_read32(&adapter->mac_regs_base->mac_10g.cmd_cfg); + reg |= 1 << 19; + al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, reg); + } else { + /* config the 40g_mac */ + /* set quanta value (same value for all prios) */ + reg = params->quanta | (params->quanta << 16); + al_eth_40g_mac_reg_write(adapter, + ETH_MAC_GEN_V3_MAC_40G_CL01_PAUSE_QUANTA_ADDR, reg); + al_eth_40g_mac_reg_write(adapter, + ETH_MAC_GEN_V3_MAC_40G_CL23_PAUSE_QUANTA_ADDR, reg); + al_eth_40g_mac_reg_write(adapter, + ETH_MAC_GEN_V3_MAC_40G_CL45_PAUSE_QUANTA_ADDR, reg); + al_eth_40g_mac_reg_write(adapter, + ETH_MAC_GEN_V3_MAC_40G_CL67_PAUSE_QUANTA_ADDR, reg); + /* set quanta threshold value (same value for all prios) */ + reg = params->quanta_th | (params->quanta_th << 16); + al_eth_40g_mac_reg_write(adapter, + ETH_MAC_GEN_V3_MAC_40G_CL01_QUANTA_THRESH_ADDR, reg); + al_eth_40g_mac_reg_write(adapter, + ETH_MAC_GEN_V3_MAC_40G_CL23_QUANTA_THRESH_ADDR, reg); + al_eth_40g_mac_reg_write(adapter, + ETH_MAC_GEN_V3_MAC_40G_CL45_QUANTA_THRESH_ADDR, reg); + al_eth_40g_mac_reg_write(adapter, + ETH_MAC_GEN_V3_MAC_40G_CL67_QUANTA_THRESH_ADDR, reg); + + /* enable PFC in the 40g_MAC */ + reg = al_reg_read32(&adapter->mac_regs_base->mac_10g.cmd_cfg); + reg |= 1 << 19; + al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, reg); + reg = al_eth_40g_mac_reg_read(adapter, ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR); + + reg |= ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_PFC_MODE; + + al_eth_40g_mac_reg_write(adapter, ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR, reg); + } + + break; + default: + al_err("[%s]: unsupported flow control type %d\n", adapter->name, params->type); + return -EINVAL; + + } + return 0; +} + +int al_eth_vlan_mod_config(struct al_hal_eth_adapter *adapter, uint8_t udma_id, uint16_t udma_etype, uint16_t vlan1_data, uint16_t vlan2_data) +{ + al_dbg("[%s]: config vlan modification registers. udma id %d.\n", adapter->name, udma_id); + + al_reg_write32(&adapter->ec_regs_base->tpm_sel[udma_id].etype, udma_etype); + al_reg_write32(&adapter->ec_regs_base->tpm_udma[udma_id].vlan_data, vlan1_data | (vlan2_data << 16)); + + return 0; +} + +int al_eth_eee_get(struct al_hal_eth_adapter *adapter, struct al_eth_eee_params *params) +{ + uint32_t reg; + + al_dbg("[%s]: getting eee.\n", adapter->name); + + reg = al_reg_read32(&adapter->ec_regs_base->eee.cfg_e); + params->enable = (reg & EC_EEE_CFG_E_ENABLE) ? AL_TRUE : AL_FALSE; + + params->tx_eee_timer = al_reg_read32(&adapter->ec_regs_base->eee.pre_cnt); + params->min_interval = al_reg_read32(&adapter->ec_regs_base->eee.post_cnt); + params->stop_cnt = al_reg_read32(&adapter->ec_regs_base->eee.stop_cnt); + + return 0; +} + + +int al_eth_eee_config(struct al_hal_eth_adapter *adapter, struct al_eth_eee_params *params) +{ + uint32_t reg; + al_dbg("[%s]: config eee.\n", adapter->name); + + if (params->enable == 0) { + al_dbg("[%s]: disable eee.\n", adapter->name); + al_reg_write32(&adapter->ec_regs_base->eee.cfg_e, 0); + return 0; + } + if (AL_ETH_IS_10G_MAC(adapter->mac_mode)) { + reg = ETH_MAC_KR_PCS_CFG_EEE_TIMER_VAL << ETH_MAC_KR_PCS_CFG_EEE_TIMER_VAL_SHIFT; + al_reg_write32_masked( + &adapter->mac_regs_base->kr.pcs_cfg, + ETH_MAC_KR_PCS_CFG_EEE_TIMER_VAL_MASK, reg); + } + + al_reg_write32(&adapter->ec_regs_base->eee.pre_cnt, params->tx_eee_timer); + al_reg_write32(&adapter->ec_regs_base->eee.post_cnt, params->min_interval); + al_reg_write32(&adapter->ec_regs_base->eee.stop_cnt, params->stop_cnt); + + reg = EC_EEE_CFG_E_MASK_EC_TMI_STOP | EC_EEE_CFG_E_MASK_MAC_EEE | + EC_EEE_CFG_E_ENABLE | + EC_EEE_CFG_E_USE_EC_TX_FIFO | EC_EEE_CFG_E_USE_EC_RX_FIFO; + + /* + * Addressing RMN: 3732 + * + * RMN description: + * When the HW get into eee mode, it can't transmit any pause packet + * (when flow control policy is enabled). + * In such case, the HW has no way to handle extreme pushback from + * the Rx_path fifos. + * + * Software flow: + * Configure RX_FIFO empty as eee mode term. + * That way, nothing will prevent pause packet transmittion in + * case of extreme pushback from the Rx_path fifos. + * + */ + + al_reg_write32(&adapter->ec_regs_base->eee.cfg_e, reg); + + return 0; +} + +/* Timestamp */ +/* prepare the adapter for doing Timestamps for Rx packets. */ +int al_eth_ts_init(struct al_hal_eth_adapter *adapter) +{ + uint32_t reg; + + /*TODO: + * return error when: + * - working in 1G mode and MACSEC enabled + * - RX completion descriptor is not 8 words + */ + reg = al_reg_read32(&adapter->ec_regs_base->gen.en_ext); + if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) + reg &= ~EC_GEN_EN_EXT_PTH_1_10_SEL; + else + reg |= EC_GEN_EN_EXT_PTH_1_10_SEL; + /* + * set completion bypass so tx timestamps won't be inserted to tx cmpl + * (in order to disable unverified flow) + */ + reg |= EC_GEN_EN_EXT_PTH_COMPLETION_BYPASS; + al_reg_write32(&adapter->ec_regs_base->gen.en_ext, reg); + + /*TODO: add the following when we have updated regs file: + * reg_rfw_out_cfg_timestamp_sample_out + 0 (default) – use the timestamp from the SOP info (10G MAC) + 1 – use the timestamp from the EOP (1G MAC) (noly when MACSEC is disabled) + */ + return 0; +} + +/* read Timestamp sample value of previously transmitted packet. */ +int al_eth_tx_ts_val_get(struct al_hal_eth_adapter *adapter, uint8_t ts_index, + uint32_t *timestamp) +{ + al_assert(ts_index < AL_ETH_PTH_TX_SAMPLES_NUM); + + /* in 1G mode, only indexes 1-7 are allowed*/ + if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) { + al_assert(ts_index <= 7); + al_assert(ts_index >= 1); + } + + /*TODO: check if sample is valid */ + *timestamp = al_reg_read32(&adapter->ec_regs_base->pth_db[ts_index].ts); + return 0; +} + +/* Read the systime value */ +int al_eth_pth_systime_read(struct al_hal_eth_adapter *adapter, + struct al_eth_pth_time *systime) +{ + uint32_t reg; + + /* first we must read the subseconds MSB so the seconds register will be + * shadowed + */ + reg = al_reg_read32(&adapter->ec_regs_base->pth.system_time_subseconds_msb); + systime->femto = (uint64_t)reg << 18; + reg = al_reg_read32(&adapter->ec_regs_base->pth.system_time_seconds); + systime->seconds = reg; + + return 0; +} + +/* Set the clock period to a given value. */ +int al_eth_pth_clk_period_write(struct al_hal_eth_adapter *adapter, + uint64_t clk_period) +{ + uint32_t reg; + /* first write the LSB so it will be shadowed */ + /* bits 31:14 of the clock period lsb register contains bits 17:0 of the + * period. + */ + reg = (clk_period & AL_BIT_MASK(18)) << EC_PTH_CLOCK_PERIOD_LSB_VAL_SHIFT; + al_reg_write32(&adapter->ec_regs_base->pth.clock_period_lsb, reg); + reg = clk_period >> 18; + al_reg_write32(&adapter->ec_regs_base->pth.clock_period_msb, reg); + + return 0; +} + +/* Configure the systime internal update */ +int al_eth_pth_int_update_config(struct al_hal_eth_adapter *adapter, + struct al_eth_pth_int_update_params *params) +{ + uint32_t reg; + + reg = al_reg_read32(&adapter->ec_regs_base->pth.int_update_ctrl); + if (params->enable == AL_FALSE) { + reg &= ~EC_PTH_INT_UPDATE_CTRL_INT_TRIG_EN; + } else { + reg |= EC_PTH_INT_UPDATE_CTRL_INT_TRIG_EN; + AL_REG_FIELD_SET(reg, EC_PTH_INT_UPDATE_CTRL_UPDATE_METHOD_MASK, + EC_PTH_INT_UPDATE_CTRL_UPDATE_METHOD_SHIFT, + params->method); + if (params->trigger == AL_ETH_PTH_INT_TRIG_REG_WRITE) + reg |= EC_PTH_INT_UPDATE_CTRL_UPDATE_TRIG; + else + reg &= ~EC_PTH_INT_UPDATE_CTRL_UPDATE_TRIG; + } + al_reg_write32(&adapter->ec_regs_base->pth.int_update_ctrl, reg); + return 0; +} +/* set internal update time */ +int al_eth_pth_int_update_time_set(struct al_hal_eth_adapter *adapter, + struct al_eth_pth_time *time) +{ + uint32_t reg; + + al_reg_write32(&adapter->ec_regs_base->pth.int_update_seconds, + time->seconds); + reg = time->femto & AL_BIT_MASK(18); + reg = reg << EC_PTH_INT_UPDATE_SUBSECONDS_LSB_VAL_SHIFT; + al_reg_write32(&adapter->ec_regs_base->pth.int_update_subseconds_lsb, + reg); + reg = time->femto >> 18; + al_reg_write32(&adapter->ec_regs_base->pth.int_update_subseconds_msb, + reg); + + return 0; +} + +/* Configure the systime external update */ +int al_eth_pth_ext_update_config(struct al_hal_eth_adapter *adapter, + struct al_eth_pth_ext_update_params * params) +{ + uint32_t reg; + + reg = al_reg_read32(&adapter->ec_regs_base->pth.int_update_ctrl); + AL_REG_FIELD_SET(reg, EC_PTH_INT_UPDATE_CTRL_UPDATE_METHOD_MASK, + EC_PTH_INT_UPDATE_CTRL_UPDATE_METHOD_SHIFT, + params->method); + + AL_REG_FIELD_SET(reg, EC_PTH_EXT_UPDATE_CTRL_EXT_TRIG_EN_MASK, + EC_PTH_EXT_UPDATE_CTRL_EXT_TRIG_EN_SHIFT, + params->triggers); + al_reg_write32(&adapter->ec_regs_base->pth.int_update_ctrl, reg); + return 0; +} + +/* set external update time */ +int al_eth_pth_ext_update_time_set(struct al_hal_eth_adapter *adapter, + struct al_eth_pth_time *time) +{ + uint32_t reg; + + al_reg_write32(&adapter->ec_regs_base->pth.ext_update_seconds, + time->seconds); + reg = time->femto & AL_BIT_MASK(18); + reg = reg << EC_PTH_EXT_UPDATE_SUBSECONDS_LSB_VAL_SHIFT; + al_reg_write32(&adapter->ec_regs_base->pth.ext_update_subseconds_lsb, + reg); + reg = time->femto >> 18; + al_reg_write32(&adapter->ec_regs_base->pth.ext_update_subseconds_msb, + reg); + + return 0; +}; + +/* set the read compensation delay */ +int al_eth_pth_read_compensation_set(struct al_hal_eth_adapter *adapter, + uint64_t subseconds) +{ + uint32_t reg; + + /* first write to lsb to ensure atomicity */ + reg = (subseconds & AL_BIT_MASK(18)) << EC_PTH_READ_COMPENSATION_SUBSECONDS_LSB_VAL_SHIFT; + al_reg_write32(&adapter->ec_regs_base->pth.read_compensation_subseconds_lsb, reg); + + reg = subseconds >> 18; + al_reg_write32(&adapter->ec_regs_base->pth.read_compensation_subseconds_msb, reg); + return 0; +} + +/* set the internal write compensation delay */ +int al_eth_pth_int_write_compensation_set(struct al_hal_eth_adapter *adapter, + uint64_t subseconds) +{ + uint32_t reg; + + /* first write to lsb to ensure atomicity */ + reg = (subseconds & AL_BIT_MASK(18)) << EC_PTH_INT_WRITE_COMPENSATION_SUBSECONDS_LSB_VAL_SHIFT; + al_reg_write32(&adapter->ec_regs_base->pth.int_write_compensation_subseconds_lsb, reg); + + reg = subseconds >> 18; + al_reg_write32(&adapter->ec_regs_base->pth.int_write_compensation_subseconds_msb, reg); + return 0; +} + +/* set the external write compensation delay */ +int al_eth_pth_ext_write_compensation_set(struct al_hal_eth_adapter *adapter, + uint64_t subseconds) +{ + uint32_t reg; + + /* first write to lsb to ensure atomicity */ + reg = (subseconds & AL_BIT_MASK(18)) << EC_PTH_EXT_WRITE_COMPENSATION_SUBSECONDS_LSB_VAL_SHIFT; + al_reg_write32(&adapter->ec_regs_base->pth.ext_write_compensation_subseconds_lsb, reg); + + reg = subseconds >> 18; + al_reg_write32(&adapter->ec_regs_base->pth.ext_write_compensation_subseconds_msb, reg); + return 0; +} + +/* set the sync compensation delay */ +int al_eth_pth_sync_compensation_set(struct al_hal_eth_adapter *adapter, + uint64_t subseconds) +{ + uint32_t reg; + + /* first write to lsb to ensure atomicity */ + reg = (subseconds & AL_BIT_MASK(18)) << EC_PTH_SYNC_COMPENSATION_SUBSECONDS_LSB_VAL_SHIFT; + al_reg_write32(&adapter->ec_regs_base->pth.sync_compensation_subseconds_lsb, reg); + + reg = subseconds >> 18; + al_reg_write32(&adapter->ec_regs_base->pth.sync_compensation_subseconds_msb, reg); + return 0; +} + +/* Configure an output pulse */ +int al_eth_pth_pulse_out_config(struct al_hal_eth_adapter *adapter, + struct al_eth_pth_pulse_out_params *params) +{ + uint32_t reg; + + if (params->index >= AL_ETH_PTH_PULSE_OUT_NUM) { + al_err("eth [%s] PTH out pulse index out of range\n", + adapter->name); + return -EINVAL; + } + reg = al_reg_read32(&adapter->ec_regs_base->pth_egress[params->index].trigger_ctrl); + if (params->enable == AL_FALSE) { + reg &= ~EC_PTH_EGRESS_TRIGGER_CTRL_EN; + } else { + reg |= EC_PTH_EGRESS_TRIGGER_CTRL_EN; + if (params->periodic == AL_FALSE) + reg &= ~EC_PTH_EGRESS_TRIGGER_CTRL_PERIODIC; + else + reg |= EC_PTH_EGRESS_TRIGGER_CTRL_PERIODIC; + + AL_REG_FIELD_SET(reg, EC_PTH_EGRESS_TRIGGER_CTRL_PERIOD_SUBSEC_MASK, + EC_PTH_EGRESS_TRIGGER_CTRL_PERIOD_SUBSEC_SHIFT, + params->period_us); + AL_REG_FIELD_SET(reg, EC_PTH_EGRESS_TRIGGER_CTRL_PERIOD_SEC_MASK, + EC_PTH_EGRESS_TRIGGER_CTRL_PERIOD_SEC_SHIFT, + params->period_sec); + } + al_reg_write32(&adapter->ec_regs_base->pth_egress[params->index].trigger_ctrl, reg); + + /* set trigger time */ + al_reg_write32(&adapter->ec_regs_base->pth_egress[params->index].trigger_seconds, + params->start_time.seconds); + reg = params->start_time.femto & AL_BIT_MASK(18); + reg = reg << EC_PTH_EGRESS_TRIGGER_SUBSECONDS_LSB_VAL_SHIFT; + al_reg_write32(&adapter->ec_regs_base->pth_egress[params->index].trigger_subseconds_lsb, + reg); + reg = params->start_time.femto >> 18; + al_reg_write32(&adapter->ec_regs_base->pth_egress[params->index].trigger_subseconds_msb, + reg); + + /* set pulse width */ + reg = params->pulse_width & AL_BIT_MASK(18); + reg = reg << EC_PTH_EGRESS_PULSE_WIDTH_SUBSECONDS_LSB_VAL_SHIFT; + al_reg_write32(&adapter->ec_regs_base->pth_egress[params->index].pulse_width_subseconds_lsb, reg); + + reg = params->pulse_width >> 18; + al_reg_write32(&adapter->ec_regs_base->pth_egress[params->index].pulse_width_subseconds_msb, reg); + + return 0; +} + +/** get link status */ +int al_eth_link_status_get(struct al_hal_eth_adapter *adapter, + struct al_eth_link_status *status) +{ + uint32_t reg; + + if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) { + reg = al_reg_read32(&adapter->mac_regs_base->gen.mac_10g_stat); + + status->link_up = AL_TRUE; + + if (reg & (ETH_MAC_GEN_MAC_10G_STAT_LOC_FAULT | + ETH_MAC_GEN_MAC_10G_STAT_REM_FAULT)) + status->link_up = AL_FALSE; + + } else if (adapter->mac_mode == AL_ETH_MAC_MODE_SGMII) { + al_reg_write32(&adapter->mac_regs_base->sgmii.reg_addr, 1); + /* + * This register is latched low so need to read twice to get + * the current link status + */ + reg = al_reg_read32(&adapter->mac_regs_base->sgmii.reg_data); + reg = al_reg_read32(&adapter->mac_regs_base->sgmii.reg_data); + + status->link_up = AL_FALSE; + + if (reg & AL_BIT(2)) + status->link_up = AL_TRUE; + + reg = al_reg_read32(&adapter->mac_regs_base->sgmii.link_stat); + + if ((reg & AL_BIT(3)) == 0) + status->link_up = AL_FALSE; + + } else if (adapter->mac_mode == AL_ETH_MAC_MODE_RGMII) { + reg = al_reg_read32(&adapter->mac_regs_base->gen.rgmii_stat); + + status->link_up = AL_FALSE; + + if (reg & AL_BIT(4)) + status->link_up = AL_TRUE; + + } else if ((adapter->mac_mode == AL_ETH_MAC_MODE_XLG_LL_40G) || + (adapter->mac_mode == AL_ETH_MAC_MODE_XLG_LL_50G)) { + reg = al_reg_read32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_status); + + status->link_up = AL_FALSE; + + if ((reg & 0x1F) == 0x1F) { + reg = al_reg_read32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_status); + if ((reg & (ETH_MAC_GEN_V3_MAC_40G_LL_STATUS_REM_FAULT | +ETH_MAC_GEN_V3_MAC_40G_LL_STATUS_LOC_FAULT)) == 0) + status->link_up = AL_TRUE; + } + + } else { + /* not implemented yet */ + return -EPERM; + } + + al_dbg("[%s]: mac %s port. link_status: %s.\n", adapter->name, + al_eth_mac_mode_str(adapter->mac_mode), + (status->link_up == AL_TRUE) ? "LINK_UP" : "LINK_DOWN"); + + return 0; +} + +/** set LED mode and value */ +int al_eth_led_set(struct al_hal_eth_adapter *adapter, al_bool link_is_up) +{ + uint32_t reg = 0; + uint32_t mode = ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG; + + if (link_is_up) + mode = ETH_MAC_GEN_LED_CFG_SEL_LINK_ACTIVITY; + + AL_REG_FIELD_SET(reg, ETH_MAC_GEN_LED_CFG_SEL_MASK, + ETH_MAC_GEN_LED_CFG_SEL_SHIFT, mode); + + AL_REG_FIELD_SET(reg, ETH_MAC_GEN_LED_CFG_BLINK_TIMER_MASK, + ETH_MAC_GEN_LED_CFG_BLINK_TIMER_SHIFT, + ETH_MAC_GEN_LED_CFG_BLINK_TIMER_VAL); + + AL_REG_FIELD_SET(reg, ETH_MAC_GEN_LED_CFG_ACT_TIMER_MASK, + ETH_MAC_GEN_LED_CFG_ACT_TIMER_SHIFT, + ETH_MAC_GEN_LED_CFG_ACT_TIMER_VAL); + + al_reg_write32(&adapter->mac_regs_base->gen.led_cfg, reg); + + return 0; +} + +/* get statistics */ +int al_eth_mac_stats_get(struct al_hal_eth_adapter *adapter, struct al_eth_mac_stats *stats) +{ + al_assert(stats); + + if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) { + void __iomem *mac_1g_regs_base = &adapter->mac_regs_base->mac_1g; + + stats->ifInUcastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x90)); + stats->ifInMulticastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x94)); + stats->ifInBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x98)); + stats->etherStatsPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xb4)); + stats->ifOutUcastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xa0)); + stats->ifOutMulticastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xa4)); + stats->ifOutBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xa8)); + stats->ifInErrors = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x88)); + stats->ifOutErrors = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x8c)); + + stats->aFramesReceivedOK = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x6c)); + stats->aFramesTransmittedOK = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x68)); + + stats->aOctetsReceivedOK = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x7c)); + stats->aOctetsTransmittedOK = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x78)); + + stats->etherStatsUndersizePkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xB8)); + stats->etherStatsFragments = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xE0)); + stats->etherStatsJabbers = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xDC)); + stats->etherStatsOversizePkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xBC)); + + stats->aFrameCheckSequenceErrors = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x70)); + stats->aAlignmentErrors = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x74)); + stats->etherStatsDropEvents = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xAC)); + + stats->aPAUSEMACCtrlFramesTransmitted = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x80)); + stats->aPAUSEMACCtrlFramesReceived = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x84)); + stats->aFrameTooLongErrors = 0; /* N/A */ + stats->aInRangeLengthErrors = 0; /* N/A */ + stats->VLANTransmittedOK = 0; /* N/A */ + stats->VLANReceivedOK = 0; /* N/A */ + stats->etherStatsOctets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xB0)); + + stats->etherStatsPkts64Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xC0)); + stats->etherStatsPkts65to127Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xC4)); + stats->etherStatsPkts128to255Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xC8)); + stats->etherStatsPkts256to511Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xCC)); + stats->etherStatsPkts512to1023Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xD0)); + stats->etherStatsPkts1024to1518Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xD4)); + stats->etherStatsPkts1519toX = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xD8)); + } else if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) { + if (adapter->rev_id < AL_ETH_REV_ID_3) { + void __iomem *mac_10g_regs_base = &adapter->mac_regs_base->mac_10g; + uint64_t octets; + + stats->ifInUcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xE0)); + stats->ifInMulticastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xE8)); + stats->ifInBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xF0)); + stats->etherStatsPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x130)); + stats->ifOutUcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x108)); + stats->ifOutMulticastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x110)); + stats->ifOutBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x118)); + stats->ifInErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x190)); + stats->ifOutErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xf8)); + + stats->aFramesReceivedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x88)); + stats->aFramesTransmittedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x80)); + /* aOctetsReceivedOK = ifInOctets - 18 * aFramesReceivedOK - 4 * VLANReceivedOK */ + octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xD8)); + octets |= (uint64_t)(al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xDC))) << 32; + octets -= 18 * stats->aFramesReceivedOK; + octets -= 4 * al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xC8)); + stats->aOctetsReceivedOK = octets; + + /* aOctetsTransmittedOK = ifOutOctets - 18 * aFramesTransmittedOK - 4 * VLANTransmittedOK */ + octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xD0)); + octets |= (uint64_t)(al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xD4))) << 32; + octets -= 18 * stats->aFramesTransmittedOK; + octets -= 4 * al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xC0)); + stats->aOctetsTransmittedOK = octets; + + stats->etherStatsUndersizePkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x138)); + stats->etherStatsFragments = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x188)); + stats->etherStatsJabbers = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x180)); + stats->etherStatsOversizePkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x178)); + + stats->aFrameCheckSequenceErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x90)); + stats->aAlignmentErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x98)); + stats->etherStatsDropEvents = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x120)); + + stats->aPAUSEMACCtrlFramesTransmitted = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xA0)); + stats->aPAUSEMACCtrlFramesReceived = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xA8)); + stats->aFrameTooLongErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xB0)); + stats->aInRangeLengthErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xB8)); + stats->VLANTransmittedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xC0)); + stats->VLANReceivedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xC8)); + stats->etherStatsOctets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x128)); + + stats->etherStatsPkts64Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x140)); + stats->etherStatsPkts65to127Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x148)); + stats->etherStatsPkts128to255Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x150)); + stats->etherStatsPkts256to511Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x158)); + stats->etherStatsPkts512to1023Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x160)); + stats->etherStatsPkts1024to1518Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x168)); + stats->etherStatsPkts1519toX = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x170)); + } else { + void __iomem *mac_10g_regs_base = &adapter->mac_regs_base->mac_10g; + uint64_t octets; + /* TODO - change to 64 bit */ + stats->ifInUcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x140)); + stats->ifInMulticastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x148)); + stats->ifInBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x150)); + stats->etherStatsPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x160)); + stats->ifOutUcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x240)); + stats->ifOutMulticastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x248)); + stats->ifOutBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x250)); + stats->ifInErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x138)); + stats->ifOutErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x238)); + + stats->aFramesReceivedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x120)); /*frames_ok*/ + stats->aFramesTransmittedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x220)); /*frames_ok*/ + /* aOctetsReceivedOK = ifInOctets - 18 * aFramesReceivedOK - 4 * VLANReceivedOK */ + octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x108)); /*OctetsOK*/ + octets |= (uint64_t)(al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x10C))) << 32; + octets -= 18 * stats->aFramesReceivedOK; + octets -= 4 * al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x130)); /*VLANOK*/ + stats->aOctetsReceivedOK = octets; + + /* aOctetsTransmittedOK = ifOutOctets - 18 * aFramesTransmittedOK - 4 * VLANTransmittedOK */ + octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x208)); /*OctetsOK*/ + octets |= (uint64_t)(al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x20c))) << 32; + octets -= 18 * stats->aFramesTransmittedOK; + octets -= 4 * al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x230)); /*VLANOK*/ + stats->aOctetsTransmittedOK = octets; + + stats->etherStatsUndersizePkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x168)); + stats->etherStatsFragments = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x1b8)); + stats->etherStatsJabbers = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x1b0)); + stats->etherStatsOversizePkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x1a8)); + + stats->aFrameCheckSequenceErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x128)); /* CRCErrors */ + /* stats->aAlignmentErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x98)); */ /* not implemented */ + stats->etherStatsDropEvents = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x158)); + } + } else { + uint64_t octets; + /* TODO - change to 64 bit */ + stats->ifInUcastPkts = al_eth_40g_mac_reg_read(adapter, 0x140); + stats->ifInMulticastPkts = al_eth_40g_mac_reg_read(adapter, 0x148); + stats->ifInBroadcastPkts = al_eth_40g_mac_reg_read(adapter, 0x150); + stats->etherStatsPkts = al_eth_40g_mac_reg_read(adapter, 0x160); + stats->ifOutUcastPkts = al_eth_40g_mac_reg_read(adapter, 0x240); + stats->ifOutMulticastPkts = al_eth_40g_mac_reg_read(adapter, 0x248); + stats->ifOutBroadcastPkts = al_eth_40g_mac_reg_read(adapter, 0x250); + stats->ifInErrors = al_eth_40g_mac_reg_read(adapter, 0x138); + stats->ifOutErrors = al_eth_40g_mac_reg_read(adapter, 0x238); + stats->aFramesReceivedOK = al_eth_40g_mac_reg_read(adapter, 0x120); + stats->aFramesTransmittedOK = al_eth_40g_mac_reg_read(adapter, 0x220); + + /* aOctetsReceivedOK = ifInOctets - 18 * aFramesReceivedOK - 4 * VLANReceivedOK */ + octets = al_eth_40g_mac_reg_read(adapter, 0x100); + octets |= (uint64_t)(al_eth_40g_mac_reg_read(adapter, 0x104)) << 32; + octets -= 18 * stats->aFramesReceivedOK; + octets -= 4 * al_eth_40g_mac_reg_read(adapter, 0x130); /*VLANOK*/ + stats->aOctetsTransmittedOK = octets; + + /* aOctetsTransmittedOK = ifOutOctets - 18 * aFramesTransmittedOK - 4 * VLANTransmittedOK */ + octets = al_eth_40g_mac_reg_read(adapter, 0x200); + octets |= (uint64_t)(al_eth_40g_mac_reg_read(adapter, 0x204)) << 32; + octets -= 18 * stats->aFramesReceivedOK; + octets -= 4 * al_eth_40g_mac_reg_read(adapter, 0x230); /*VLANOK*/ + stats->aOctetsReceivedOK = octets; + + stats->etherStatsUndersizePkts = al_eth_40g_mac_reg_read(adapter, 0x168); + stats->etherStatsFragments = al_eth_40g_mac_reg_read(adapter, 0x1b8); + stats->etherStatsJabbers = al_eth_40g_mac_reg_read(adapter, 0x1b0); + stats->etherStatsOversizePkts = al_eth_40g_mac_reg_read(adapter, 0x1a8); + stats->aFrameCheckSequenceErrors = al_eth_40g_mac_reg_read(adapter, 0x128); + stats->aAlignmentErrors = al_eth_40g_mac_reg_read(adapter, 0x110); + stats->etherStatsDropEvents = al_eth_40g_mac_reg_read(adapter, 0x158); + } + + stats->eee_in = al_reg_read32(&adapter->mac_regs_base->stat.eee_in); + stats->eee_out = al_reg_read32(&adapter->mac_regs_base->stat.eee_out); + +/* stats->etherStatsPkts = 1; */ + return 0; +} + +/** +* read ec_stat_counters +*/ +int al_eth_ec_stats_get(struct al_hal_eth_adapter *adapter, struct al_eth_ec_stats *stats) +{ + al_assert(stats); + stats->faf_in_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.faf_in_rx_pkt); + stats->faf_in_rx_short = al_reg_read32(&adapter->ec_regs_base->stat.faf_in_rx_short); + stats->faf_in_rx_long = al_reg_read32(&adapter->ec_regs_base->stat.faf_in_rx_long); + stats->faf_out_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.faf_out_rx_pkt); + stats->faf_out_rx_short = al_reg_read32(&adapter->ec_regs_base->stat.faf_out_rx_short); + stats->faf_out_rx_long = al_reg_read32(&adapter->ec_regs_base->stat.faf_out_rx_long); + stats->faf_out_drop = al_reg_read32(&adapter->ec_regs_base->stat.faf_out_drop); + stats->rxf_in_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rxf_in_rx_pkt); + stats->rxf_in_fifo_err = al_reg_read32(&adapter->ec_regs_base->stat.rxf_in_fifo_err); + stats->lbf_in_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.lbf_in_rx_pkt); + stats->lbf_in_fifo_err = al_reg_read32(&adapter->ec_regs_base->stat.lbf_in_fifo_err); + stats->rxf_out_rx_1_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rxf_out_rx_1_pkt); + stats->rxf_out_rx_2_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rxf_out_rx_2_pkt); + stats->rxf_out_drop_1_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rxf_out_drop_1_pkt); + stats->rxf_out_drop_2_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rxf_out_drop_2_pkt); + stats->rpe_1_in_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rpe_1_in_rx_pkt); + stats->rpe_1_out_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rpe_1_out_rx_pkt); + stats->rpe_2_in_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rpe_2_in_rx_pkt); + stats->rpe_2_out_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rpe_2_out_rx_pkt); + stats->rpe_3_in_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rpe_3_in_rx_pkt); + stats->rpe_3_out_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rpe_3_out_rx_pkt); + stats->tpe_in_tx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.tpe_in_tx_pkt); + stats->tpe_out_tx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.tpe_out_tx_pkt); + stats->tpm_tx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.tpm_tx_pkt); + stats->tfw_in_tx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.tfw_in_tx_pkt); + stats->tfw_out_tx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.tfw_out_tx_pkt); + stats->rfw_in_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_rx_pkt); + stats->rfw_in_vlan_drop = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_vlan_drop); + stats->rfw_in_parse_drop = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_parse_drop); + stats->rfw_in_mc = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_mc); + stats->rfw_in_bc = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_bc); + stats->rfw_in_vlan_exist = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_vlan_exist); + stats->rfw_in_vlan_nexist = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_vlan_nexist); + stats->rfw_in_mac_drop = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_mac_drop); + stats->rfw_in_mac_ndet_drop = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_mac_ndet_drop); + stats->rfw_in_ctrl_drop = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_ctrl_drop); + stats->rfw_in_prot_i_drop = al_reg_read32(&adapter->ec_regs_base->stat.rfw_in_prot_i_drop); + stats->eee_in = al_reg_read32(&adapter->ec_regs_base->stat.eee_in); + return 0; +} + +/** + * read per_udma_counters + */ +int al_eth_ec_stat_udma_get(struct al_hal_eth_adapter *adapter, uint8_t idx, struct al_eth_ec_stat_udma *stats) +{ + + al_assert(idx <= 3); /*valid udma_id*/ + al_assert(stats); + stats->rfw_out_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].rfw_out_rx_pkt); + stats->rfw_out_drop = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].rfw_out_drop); + stats->msw_in_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].msw_in_rx_pkt); + stats->msw_drop_q_full = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].msw_drop_q_full); + stats->msw_drop_sop = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].msw_drop_sop); + stats->msw_drop_eop = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].msw_drop_eop); + stats->msw_wr_eop = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].msw_wr_eop); + stats->msw_out_rx_pkt = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].msw_out_rx_pkt); + stats->tso_no_tso_pkt = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tso_no_tso_pkt); + stats->tso_tso_pkt = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tso_tso_pkt); + stats->tso_seg_pkt = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tso_seg_pkt); + stats->tso_pad_pkt = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tso_pad_pkt); + stats->tpm_tx_spoof = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tpm_tx_spoof); + stats->tmi_in_tx_pkt = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tmi_in_tx_pkt); + stats->tmi_out_to_mac = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tmi_out_to_mac); + stats->tmi_out_to_rx = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tmi_out_to_rx); + stats->tx_q0_bytes = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tx_q0_bytes); + stats->tx_q1_bytes = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tx_q1_bytes); + stats->tx_q2_bytes = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tx_q2_bytes); + stats->tx_q3_bytes = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tx_q3_bytes); + stats->tx_q0_pkts = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tx_q0_pkts); + stats->tx_q1_pkts = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tx_q1_pkts); + stats->tx_q2_pkts = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tx_q2_pkts); + stats->tx_q3_pkts = al_reg_read32(&adapter->ec_regs_base->stat_udma[idx].tx_q3_pkts); + return 0; +} + +/* Traffic control */ + + +int al_eth_flr_rmn(int (* pci_read_config_u32)(void *handle, int where, uint32_t *val), + int (* pci_write_config_u32)(void *handle, int where, uint32_t val), + void *handle, + void __iomem *mac_base) +{ + struct al_eth_mac_regs __iomem *mac_regs_base = + (struct al_eth_mac_regs __iomem *)mac_base; + uint32_t cfg_reg_store[6]; + uint32_t reg; + uint32_t mux_sel; + int i = 0; + + (*pci_read_config_u32)(handle, AL_ADAPTER_GENERIC_CONTROL_0, ®); + + /* reset 1G mac */ + AL_REG_MASK_SET(reg, AL_ADAPTER_GENERIC_CONTROL_0_ETH_RESET_1GMAC); + (*pci_write_config_u32)(handle, AL_ADAPTER_GENERIC_CONTROL_0, reg); + al_udelay(1000); + /* don't reset 1G mac */ + AL_REG_MASK_CLEAR(reg, AL_ADAPTER_GENERIC_CONTROL_0_ETH_RESET_1GMAC); + /* prevent 1G mac reset on FLR */ + AL_REG_MASK_CLEAR(reg, AL_ADAPTER_GENERIC_CONTROL_0_ETH_RESET_1GMAC_ON_FLR); + /* prevent adapter reset */ + (*pci_write_config_u32)(handle, AL_ADAPTER_GENERIC_CONTROL_0, reg); + + mux_sel = al_reg_read32(&mac_regs_base->gen.mux_sel); + + /* save pci register that get reset due to flr*/ + (*pci_read_config_u32)(handle, AL_PCI_COMMAND, &cfg_reg_store[i++]); + (*pci_read_config_u32)(handle, 0xC, &cfg_reg_store[i++]); + (*pci_read_config_u32)(handle, 0x10, &cfg_reg_store[i++]); + (*pci_read_config_u32)(handle, 0x18, &cfg_reg_store[i++]); + (*pci_read_config_u32)(handle, 0x20, &cfg_reg_store[i++]); + (*pci_read_config_u32)(handle, 0x110, &cfg_reg_store[i++]); + + /* do flr */ + (*pci_write_config_u32)(handle, AL_PCI_EXP_CAP_BASE + AL_PCI_EXP_DEVCTL, AL_PCI_EXP_DEVCTL_BCR_FLR); + al_udelay(1000); + /* restore command */ + i = 0; + (*pci_write_config_u32)(handle, AL_PCI_COMMAND, cfg_reg_store[i++]); + (*pci_write_config_u32)(handle, 0xC, cfg_reg_store[i++]); + (*pci_write_config_u32)(handle, 0x10, cfg_reg_store[i++]); + (*pci_write_config_u32)(handle, 0x18, cfg_reg_store[i++]); + (*pci_write_config_u32)(handle, 0x20, cfg_reg_store[i++]); + (*pci_write_config_u32)(handle, 0x110, cfg_reg_store[i++]); + + al_reg_write32_masked(&mac_regs_base->gen.mux_sel, ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, mux_sel); + + /* set SGMII clock to 125MHz */ + al_reg_write32(mac_base + 0xB08, 0x03320501); + + /* reset 1G mac */ + AL_REG_MASK_SET(reg, AL_ADAPTER_GENERIC_CONTROL_0_ETH_RESET_1GMAC); + (*pci_write_config_u32)(handle, AL_ADAPTER_GENERIC_CONTROL_0, reg); + + al_udelay(1000); + + /* clear 1G mac reset */ + AL_REG_MASK_CLEAR(reg, AL_ADAPTER_GENERIC_CONTROL_0_ETH_RESET_1GMAC); + (*pci_write_config_u32)(handle, AL_ADAPTER_GENERIC_CONTROL_0, reg); + + /* reset SGMII mac clock to default */ + al_reg_write32(mac_base + 0xB08, 0x00320501); + al_udelay(1000); + /* reset async fifo */ + reg = al_reg_read32((void*)((uint32_t)mac_base + 0x95c)); + AL_REG_MASK_SET(reg, 0xF0); + al_reg_write32((void*)((uint32_t)mac_base + 0x95c), reg); + reg = al_reg_read32((void*)((uint32_t)mac_base + 0x95c)); + AL_REG_MASK_CLEAR(reg, 0xF0); + al_reg_write32((void*)((uint32_t)mac_base + 0x95c), reg); + + return 0; +} + +int al_eth_flr_rmn_restore_params(int (* pci_read_config_u32)(void *handle, int where, uint32_t *val), + int (* pci_write_config_u32)(void *handle, int where, uint32_t val), + void *handle, + void __iomem *mac_base, + void __iomem *ec_base, + int mac_addresses_num + ) +{ + struct al_eth_board_params params = { .media_type = 0 }; + uint8_t mac_addr[6]; + int rc; + + /* not implemented yet */ + if (mac_addresses_num > 1) + return -EPERM; + + /* save board params so we restore it after reset */ + al_eth_board_params_get(mac_base, ¶ms); + al_eth_mac_addr_read(ec_base, 0, mac_addr); + + rc = al_eth_flr_rmn(pci_read_config_u32, pci_write_config_u32, handle, mac_base); + al_eth_board_params_set(mac_base, ¶ms); + al_eth_mac_addr_store(ec_base, 0, mac_addr); + + return rc; +} + +/* board params register 1 */ +#define AL_HAL_ETH_MEDIA_TYPE_MASK (AL_FIELD_MASK(3, 0)) +#define AL_HAL_ETH_MEDIA_TYPE_SHIFT 0 +#define AL_HAL_ETH_EXT_PHY_SHIFT 4 +#define AL_HAL_ETH_PHY_ADDR_MASK (AL_FIELD_MASK(9, 5)) +#define AL_HAL_ETH_PHY_ADDR_SHIFT 5 +#define AL_HAL_ETH_SFP_EXIST_SHIFT 10 +#define AL_HAL_ETH_AN_ENABLE_SHIFT 11 +#define AL_HAL_ETH_KR_LT_ENABLE_SHIFT 12 +#define AL_HAL_ETH_KR_FEC_ENABLE_SHIFT 13 +#define AL_HAL_ETH_MDIO_FREQ_MASK (AL_FIELD_MASK(15, 14)) +#define AL_HAL_ETH_MDIO_FREQ_SHIFT 14 +#define AL_HAL_ETH_I2C_ADAPTER_ID_MASK (AL_FIELD_MASK(19, 16)) +#define AL_HAL_ETH_I2C_ADAPTER_ID_SHIFT 16 +#define AL_HAL_ETH_EXT_PHY_IF_MASK (AL_FIELD_MASK(21, 20)) +#define AL_HAL_ETH_EXT_PHY_IF_SHIFT 20 +#define AL_HAL_ETH_AUTO_NEG_MODE_SHIFT 22 +#define AL_HAL_ETH_SERDES_GRP_MASK (AL_FIELD_MASK(26, 25)) +#define AL_HAL_ETH_SERDES_GRP_SHIFT 25 +#define AL_HAL_ETH_SERDES_LANE_MASK (AL_FIELD_MASK(28, 27)) +#define AL_HAL_ETH_SERDES_LANE_SHIFT 27 +#define AL_HAL_ETH_REF_CLK_FREQ_MASK (AL_FIELD_MASK(31, 29)) +#define AL_HAL_ETH_REF_CLK_FREQ_SHIFT 29 + +/* board params register 2 */ +#define AL_HAL_ETH_DONT_OVERRIDE_SERDES_SHIFT 0 +#define AL_HAL_ETH_1000_BASE_X_SHIFT 1 +#define AL_HAL_ETH_1G_AN_DISABLE_SHIFT 2 +#define AL_HAL_ETH_1G_SPEED_MASK (AL_FIELD_MASK(4, 3)) +#define AL_HAL_ETH_1G_SPEED_SHIFT 3 +#define AL_HAL_ETH_1G_HALF_DUPLEX_SHIFT 5 +#define AL_HAL_ETH_1G_FC_DISABLE_SHIFT 6 +#define AL_HAL_ETH_RETIMER_EXIST_SHIFT 7 +#define AL_HAL_ETH_RETIMER_BUS_ID_MASK (AL_FIELD_MASK(11, 8)) +#define AL_HAL_ETH_RETIMER_BUS_ID_SHIFT 8 +#define AL_HAL_ETH_RETIMER_I2C_ADDR_MASK (AL_FIELD_MASK(18, 12)) +#define AL_HAL_ETH_RETIMER_I2C_ADDR_SHIFT 12 +#define AL_HAL_ETH_RETIMER_CHANNEL_SHIFT 19 +#define AL_HAL_ETH_DAC_LENGTH_MASK (AL_FIELD_MASK(23, 20)) +#define AL_HAL_ETH_DAC_LENGTH_SHIFT 20 +#define AL_HAL_ETH_DAC_SHIFT 24 +#define AL_HAL_ETH_RETIMER_TYPE_MASK (AL_FIELD_MASK(26, 25)) +#define AL_HAL_ETH_RETIMER_TYPE_SHIFT 25 +#define AL_HAL_ETH_RETIMER_CHANNEL_2_SHIFT 27 + +int al_eth_board_params_set(void * __iomem mac_base, struct al_eth_board_params *params){ + uint32_t reg = 0; + + /* ************* Setting Board params register 1 **************** */ + AL_REG_FIELD_SET(reg, AL_HAL_ETH_MEDIA_TYPE_MASK, + AL_HAL_ETH_MEDIA_TYPE_SHIFT, params->media_type); + AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_EXT_PHY_SHIFT, params->phy_exist == AL_TRUE); + AL_REG_FIELD_SET(reg, AL_HAL_ETH_PHY_ADDR_MASK, + AL_HAL_ETH_PHY_ADDR_SHIFT, params->phy_mdio_addr); + + AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_SFP_EXIST_SHIFT, params->sfp_plus_module_exist == AL_TRUE); + + AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_AN_ENABLE_SHIFT, params->autoneg_enable == AL_TRUE); + AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_KR_LT_ENABLE_SHIFT, params->kr_lt_enable == AL_TRUE); + AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_KR_FEC_ENABLE_SHIFT, params->kr_fec_enable == AL_TRUE); + AL_REG_FIELD_SET(reg, AL_HAL_ETH_MDIO_FREQ_MASK, + AL_HAL_ETH_MDIO_FREQ_SHIFT, params->mdio_freq); + AL_REG_FIELD_SET(reg, AL_HAL_ETH_I2C_ADAPTER_ID_MASK, + AL_HAL_ETH_I2C_ADAPTER_ID_SHIFT, params->i2c_adapter_id); + AL_REG_FIELD_SET(reg, AL_HAL_ETH_EXT_PHY_IF_MASK, + AL_HAL_ETH_EXT_PHY_IF_SHIFT, params->phy_if); + + AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_AUTO_NEG_MODE_SHIFT, + params->an_mode == AL_ETH_BOARD_AUTONEG_IN_BAND); + + AL_REG_FIELD_SET(reg, AL_HAL_ETH_SERDES_GRP_MASK, + AL_HAL_ETH_SERDES_GRP_SHIFT, params->serdes_grp); + AL_REG_FIELD_SET(reg, AL_HAL_ETH_SERDES_LANE_MASK, + AL_HAL_ETH_SERDES_LANE_SHIFT, params->serdes_lane); + + AL_REG_FIELD_SET(reg, AL_HAL_ETH_REF_CLK_FREQ_MASK, + AL_HAL_ETH_REF_CLK_FREQ_SHIFT, params->ref_clk_freq); + + al_assert(reg != 0); + + al_reg_write32(mac_base + 0x4, reg); + + /* ************* Setting Board params register 2 **************** */ + reg = 0; + AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_DONT_OVERRIDE_SERDES_SHIFT, + params->dont_override_serdes == AL_TRUE); + + AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_1000_BASE_X_SHIFT, + params->force_1000_base_x == AL_TRUE); + + AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_1G_AN_DISABLE_SHIFT, + params->an_disable == AL_TRUE); + + AL_REG_FIELD_SET(reg, AL_HAL_ETH_1G_SPEED_MASK, + AL_HAL_ETH_1G_SPEED_SHIFT, params->speed); + + AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_1G_HALF_DUPLEX_SHIFT, + params->half_duplex == AL_TRUE); + + AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_1G_FC_DISABLE_SHIFT, + params->fc_disable == AL_TRUE); + + AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_RETIMER_EXIST_SHIFT, params->retimer_exist == AL_TRUE); + AL_REG_FIELD_SET(reg, AL_HAL_ETH_RETIMER_BUS_ID_MASK, + AL_HAL_ETH_RETIMER_BUS_ID_SHIFT, params->retimer_bus_id); + AL_REG_FIELD_SET(reg, AL_HAL_ETH_RETIMER_I2C_ADDR_MASK, + AL_HAL_ETH_RETIMER_I2C_ADDR_SHIFT, params->retimer_i2c_addr); + + AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_RETIMER_CHANNEL_SHIFT, + ((params->retimer_channel == AL_ETH_RETIMER_CHANNEL_B) || + (params->retimer_channel == AL_ETH_RETIMER_CHANNEL_D))); + + AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_RETIMER_CHANNEL_2_SHIFT, + ((params->retimer_channel == AL_ETH_RETIMER_CHANNEL_C) || + (params->retimer_channel == AL_ETH_RETIMER_CHANNEL_D))); + + AL_REG_FIELD_SET(reg, AL_HAL_ETH_DAC_LENGTH_MASK, + AL_HAL_ETH_DAC_LENGTH_SHIFT, params->dac_len); + AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_DAC_SHIFT, params->dac); + + AL_REG_FIELD_SET(reg, AL_HAL_ETH_RETIMER_TYPE_MASK, + AL_HAL_ETH_RETIMER_TYPE_SHIFT, params->retimer_type); + + al_reg_write32(mac_base + 0x404, reg); + return 0; +} + +int al_eth_board_params_get(void * __iomem mac_base, struct al_eth_board_params *params){ + uint32_t reg = al_reg_read32((void*)((uint32_t)mac_base + 0x4)); + + /* check if the register was initialized, 0 is not a valid value */ + if (reg == 0) + return -ENOENT; + + /* ************* Getting Board params register 1 **************** */ + params->media_type = AL_REG_FIELD_GET(reg, AL_HAL_ETH_MEDIA_TYPE_MASK, + AL_HAL_ETH_MEDIA_TYPE_SHIFT); + if (AL_REG_BIT_GET(reg, AL_HAL_ETH_EXT_PHY_SHIFT)) + params->phy_exist = AL_TRUE; + else + params->phy_exist = AL_FALSE; + + params->phy_mdio_addr = AL_REG_FIELD_GET(reg, AL_HAL_ETH_PHY_ADDR_MASK, + AL_HAL_ETH_PHY_ADDR_SHIFT); + + if (AL_REG_BIT_GET(reg, AL_HAL_ETH_SFP_EXIST_SHIFT)) + params->sfp_plus_module_exist = AL_TRUE; + else + params->sfp_plus_module_exist = AL_FALSE; + + if (AL_REG_BIT_GET(reg, AL_HAL_ETH_AN_ENABLE_SHIFT)) + params->autoneg_enable = AL_TRUE; + else + params->autoneg_enable = AL_FALSE; + + if (AL_REG_BIT_GET(reg, AL_HAL_ETH_KR_LT_ENABLE_SHIFT)) + params->kr_lt_enable = AL_TRUE; + else + params->kr_lt_enable = AL_FALSE; + + if (AL_REG_BIT_GET(reg, AL_HAL_ETH_KR_FEC_ENABLE_SHIFT)) + params->kr_fec_enable = AL_TRUE; + else + params->kr_fec_enable = AL_FALSE; + + params->mdio_freq = AL_REG_FIELD_GET(reg, + AL_HAL_ETH_MDIO_FREQ_MASK, + AL_HAL_ETH_MDIO_FREQ_SHIFT); + + params->i2c_adapter_id = AL_REG_FIELD_GET(reg, + AL_HAL_ETH_I2C_ADAPTER_ID_MASK, + AL_HAL_ETH_I2C_ADAPTER_ID_SHIFT); + + params->phy_if = AL_REG_FIELD_GET(reg, + AL_HAL_ETH_EXT_PHY_IF_MASK, + AL_HAL_ETH_EXT_PHY_IF_SHIFT); + + if (AL_REG_BIT_GET(reg, AL_HAL_ETH_AUTO_NEG_MODE_SHIFT)) + params->an_mode = AL_TRUE; + else + params->an_mode = AL_FALSE; + + params->serdes_grp = AL_REG_FIELD_GET(reg, + AL_HAL_ETH_SERDES_GRP_MASK, + AL_HAL_ETH_SERDES_GRP_SHIFT); + + params->serdes_lane = AL_REG_FIELD_GET(reg, + AL_HAL_ETH_SERDES_LANE_MASK, + AL_HAL_ETH_SERDES_LANE_SHIFT); + + params->ref_clk_freq = AL_REG_FIELD_GET(reg, + AL_HAL_ETH_REF_CLK_FREQ_MASK, + AL_HAL_ETH_REF_CLK_FREQ_SHIFT); + + /* ************* Getting Board params register 2 **************** */ + reg = al_reg_read32((void*)((uint32_t)mac_base + 0x404)); + if (AL_REG_BIT_GET(reg, AL_HAL_ETH_DONT_OVERRIDE_SERDES_SHIFT)) + params->dont_override_serdes = AL_TRUE; + else + params->dont_override_serdes = AL_FALSE; + + if (AL_REG_BIT_GET(reg, AL_HAL_ETH_1000_BASE_X_SHIFT)) + params->force_1000_base_x = AL_TRUE; + else + params->force_1000_base_x = AL_FALSE; + + if (AL_REG_BIT_GET(reg, AL_HAL_ETH_1G_AN_DISABLE_SHIFT)) + params->an_disable = AL_TRUE; + else + params->an_disable = AL_FALSE; + + params->speed = AL_REG_FIELD_GET(reg, + AL_HAL_ETH_1G_SPEED_MASK, + AL_HAL_ETH_1G_SPEED_SHIFT); + + if (AL_REG_BIT_GET(reg, AL_HAL_ETH_1G_HALF_DUPLEX_SHIFT)) + params->half_duplex = AL_TRUE; + else + params->half_duplex = AL_FALSE; + + if (AL_REG_BIT_GET(reg, AL_HAL_ETH_1G_FC_DISABLE_SHIFT)) + params->fc_disable = AL_TRUE; + else + params->fc_disable = AL_FALSE; + + if (AL_REG_BIT_GET(reg, AL_HAL_ETH_RETIMER_EXIST_SHIFT)) + params->retimer_exist = AL_TRUE; + else + params->retimer_exist = AL_FALSE; + + params->retimer_bus_id = AL_REG_FIELD_GET(reg, + AL_HAL_ETH_RETIMER_BUS_ID_MASK, + AL_HAL_ETH_RETIMER_BUS_ID_SHIFT); + params->retimer_i2c_addr = AL_REG_FIELD_GET(reg, + AL_HAL_ETH_RETIMER_I2C_ADDR_MASK, + AL_HAL_ETH_RETIMER_I2C_ADDR_SHIFT); + + params->retimer_channel = + ((AL_REG_BIT_GET(reg, AL_HAL_ETH_RETIMER_CHANNEL_SHIFT)) | + (AL_REG_BIT_GET(reg, AL_HAL_ETH_RETIMER_CHANNEL_2_SHIFT) << 1)); + + params->dac_len = AL_REG_FIELD_GET(reg, + AL_HAL_ETH_DAC_LENGTH_MASK, + AL_HAL_ETH_DAC_LENGTH_SHIFT); + + if (AL_REG_BIT_GET(reg, AL_HAL_ETH_DAC_SHIFT)) + params->dac = AL_TRUE; + else + params->dac = AL_FALSE; + + params->retimer_type = AL_REG_FIELD_GET(reg, + AL_HAL_ETH_RETIMER_TYPE_MASK, + AL_HAL_ETH_RETIMER_TYPE_SHIFT); + + return 0; +} + +/* Wake-On-Lan (WoL) */ +static inline void al_eth_byte_arr_to_reg( + uint32_t *reg, uint8_t *arr, unsigned int num_bytes) +{ + uint32_t mask = 0xff; + unsigned int i; + + al_assert(num_bytes <= 4); + + *reg = 0; + + for (i = 0 ; i < num_bytes ; i++) { + AL_REG_FIELD_SET(*reg, mask, (sizeof(uint8_t) * i), arr[i]); + mask = mask << sizeof(uint8_t); + } +} + +int al_eth_wol_enable( + struct al_hal_eth_adapter *adapter, + struct al_eth_wol_params *wol) +{ + uint32_t reg = 0; + + if (wol->int_mask & AL_ETH_WOL_INT_MAGIC_PSWD) { + al_assert(wol->pswd != NULL); + + al_eth_byte_arr_to_reg(®, &wol->pswd[0], 4); + al_reg_write32(&adapter->ec_regs_base->wol.magic_pswd_l, reg); + + al_eth_byte_arr_to_reg(®, &wol->pswd[4], 2); + al_reg_write32(&adapter->ec_regs_base->wol.magic_pswd_h, reg); + } + + if (wol->int_mask & AL_ETH_WOL_INT_IPV4) { + al_assert(wol->ipv4 != NULL); + + al_eth_byte_arr_to_reg(®, &wol->ipv4[0], 4); + al_reg_write32(&adapter->ec_regs_base->wol.ipv4_dip, reg); + } + + if (wol->int_mask & AL_ETH_WOL_INT_IPV6) { + al_assert(wol->ipv6 != NULL); + + al_eth_byte_arr_to_reg(®, &wol->ipv6[0], 4); + al_reg_write32(&adapter->ec_regs_base->wol.ipv6_dip_word0, reg); + + al_eth_byte_arr_to_reg(®, &wol->ipv6[4], 4); + al_reg_write32(&adapter->ec_regs_base->wol.ipv6_dip_word1, reg); + + al_eth_byte_arr_to_reg(®, &wol->ipv6[8], 4); + al_reg_write32(&adapter->ec_regs_base->wol.ipv6_dip_word2, reg); + + al_eth_byte_arr_to_reg(®, &wol->ipv6[12], 4); + al_reg_write32(&adapter->ec_regs_base->wol.ipv6_dip_word3, reg); + } + + if (wol->int_mask & + (AL_ETH_WOL_INT_ETHERTYPE_BC | AL_ETH_WOL_INT_ETHERTYPE_DA)) { + + reg = ((uint32_t)wol->ethr_type2 << 16); + reg |= wol->ethr_type1; + + al_reg_write32(&adapter->ec_regs_base->wol.ethertype, reg); + } + + /* make sure we dont forwarding packets without interrupt */ + al_assert((wol->forward_mask | wol->int_mask) == wol->int_mask); + + reg = ((uint32_t)wol->forward_mask << 16); + reg |= wol->int_mask; + al_reg_write32(&adapter->ec_regs_base->wol.wol_en, reg); + + return 0; +} + +int al_eth_wol_disable( + struct al_hal_eth_adapter *adapter) +{ + al_reg_write32(&adapter->ec_regs_base->wol.wol_en, 0); + + return 0; +} + +int al_eth_tx_fwd_vid_table_set(struct al_hal_eth_adapter *adapter, uint32_t idx, + uint8_t udma_mask, al_bool fwd_to_mac) +{ + uint32_t val = 0; + al_assert(idx < AL_ETH_FWD_VID_TABLE_NUM); /* valid VID index */ + AL_REG_FIELD_SET(val, AL_ETH_TX_VLAN_TABLE_UDMA_MASK, 0, udma_mask); + AL_REG_FIELD_SET(val, AL_ETH_TX_VLAN_TABLE_FWD_TO_MAC, 4, fwd_to_mac); + + al_reg_write32(&adapter->ec_regs_base->tfw.tx_vid_table_addr, idx); + al_reg_write32(&adapter->ec_regs_base->tfw.tx_vid_table_data, val); + return 0; +} + +int al_eth_tx_protocol_detect_table_entry_set(struct al_hal_eth_adapter *adapter, uint32_t idx, + struct al_eth_tx_gpd_cam_entry *tx_gpd_entry) +{ + uint64_t gpd_data; + uint64_t gpd_mask; + + gpd_data = ((uint64_t)tx_gpd_entry->l3_proto_idx & AL_ETH_TX_GPD_L3_PROTO_MASK) << + AL_ETH_TX_GPD_L3_PROTO_SHIFT; + gpd_data |= ((uint64_t)tx_gpd_entry->l4_proto_idx & AL_ETH_TX_GPD_L4_PROTO_MASK) << + AL_ETH_TX_GPD_L4_PROTO_SHIFT; + gpd_data |= ((uint64_t)tx_gpd_entry->tunnel_control & AL_ETH_TX_GPD_TUNNEL_CTRL_MASK) << + AL_ETH_TX_GPD_TUNNEL_CTRL_SHIFT; + gpd_data |= ((uint64_t)tx_gpd_entry->source_vlan_count & AL_ETH_TX_GPD_SRC_VLAN_CNT_MASK) << + AL_ETH_TX_GPD_SRC_VLAN_CNT_SHIFT; + gpd_mask = ((uint64_t)tx_gpd_entry->l3_proto_idx_mask & AL_ETH_TX_GPD_L3_PROTO_MASK) << + AL_ETH_TX_GPD_L3_PROTO_SHIFT; + gpd_mask |= ((uint64_t)tx_gpd_entry->l4_proto_idx_mask & AL_ETH_TX_GPD_L4_PROTO_MASK) << + AL_ETH_TX_GPD_L4_PROTO_SHIFT; + gpd_mask |= ((uint64_t)tx_gpd_entry->tunnel_control_mask & AL_ETH_TX_GPD_TUNNEL_CTRL_MASK) << + AL_ETH_TX_GPD_TUNNEL_CTRL_SHIFT; + gpd_mask |= ((uint64_t)tx_gpd_entry->source_vlan_count_mask & AL_ETH_TX_GPD_SRC_VLAN_CNT_MASK) << + AL_ETH_TX_GPD_SRC_VLAN_CNT_SHIFT; + + /* Tx Generic protocol detect Cam compare table */ + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gpd_cam_addr, idx); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gpd_cam_ctrl, + (uint32_t)((tx_gpd_entry->tx_gpd_cam_ctrl) << AL_ETH_TX_GPD_CAM_CTRL_VALID_SHIFT)); + al_dbg("al_eth_tx_generic_crc_entry_set, line [%d], tx_gpd_cam_ctrl: %#x", idx, tx_gpd_entry->tx_gpd_cam_ctrl); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gpd_cam_mask_2, + (uint32_t)(gpd_mask >> AL_ETH_TX_GPD_CAM_MASK_2_SHIFT)); + al_dbg("al_eth_tx_generic_crc_entry_set, line [%d], tx_gpd_cam_mask_2: %#x", idx, (uint32_t)(gpd_mask >> AL_ETH_TX_GPD_CAM_MASK_2_SHIFT)); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gpd_cam_mask_1, + (uint32_t)(gpd_mask)); + al_dbg("al_eth_tx_generic_crc_entry_set, line [%d], tx_gpd_cam_mask_1: %#x", idx, (uint32_t)(gpd_mask)); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gpd_cam_data_2, + (uint32_t)(gpd_data >> AL_ETH_TX_GPD_CAM_DATA_2_SHIFT)); + al_dbg("al_eth_tx_generic_crc_entry_set, line [%d], tx_gpd_cam_data_2: %#x", idx, (uint32_t)(gpd_data >> AL_ETH_TX_GPD_CAM_DATA_2_SHIFT)); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gpd_cam_data_1, + (uint32_t)(gpd_data)); + al_dbg("al_eth_tx_generic_crc_entry_set, line [%d], tx_gpd_cam_data_1: %#x", idx, (uint32_t)(gpd_data)); + return 0; +} + +int al_eth_tx_generic_crc_table_entry_set(struct al_hal_eth_adapter *adapter, uint32_t idx, + struct al_eth_tx_gcp_table_entry *tx_gcp_entry) +{ + uint32_t gcp_table_gen; + uint32_t tx_alu_opcode; + uint32_t tx_alu_opsel; + + gcp_table_gen = (tx_gcp_entry->poly_sel & AL_ETH_TX_GCP_POLY_SEL_MASK) << + AL_ETH_TX_GCP_POLY_SEL_SHIFT; + gcp_table_gen |= (tx_gcp_entry->crc32_bit_comp & AL_ETH_TX_GCP_CRC32_BIT_COMP_MASK) << + AL_ETH_TX_GCP_CRC32_BIT_COMP_SHIFT; + gcp_table_gen |= (tx_gcp_entry->crc32_bit_swap & AL_ETH_TX_GCP_CRC32_BIT_SWAP_MASK) << + AL_ETH_TX_GCP_CRC32_BIT_SWAP_SHIFT; + gcp_table_gen |= (tx_gcp_entry->crc32_byte_swap & AL_ETH_TX_GCP_CRC32_BYTE_SWAP_MASK) << + AL_ETH_TX_GCP_CRC32_BYTE_SWAP_SHIFT; + gcp_table_gen |= (tx_gcp_entry->data_bit_swap & AL_ETH_TX_GCP_DATA_BIT_SWAP_MASK) << + AL_ETH_TX_GCP_DATA_BIT_SWAP_SHIFT; + gcp_table_gen |= (tx_gcp_entry->data_byte_swap & AL_ETH_TX_GCP_DATA_BYTE_SWAP_MASK) << + AL_ETH_TX_GCP_DATA_BYTE_SWAP_SHIFT; + gcp_table_gen |= (tx_gcp_entry->trail_size & AL_ETH_TX_GCP_TRAIL_SIZE_MASK) << + AL_ETH_TX_GCP_TRAIL_SIZE_SHIFT; + gcp_table_gen |= (tx_gcp_entry->head_size & AL_ETH_TX_GCP_HEAD_SIZE_MASK) << + AL_ETH_TX_GCP_HEAD_SIZE_SHIFT; + gcp_table_gen |= (tx_gcp_entry->head_calc & AL_ETH_TX_GCP_HEAD_CALC_MASK) << + AL_ETH_TX_GCP_HEAD_CALC_SHIFT; + gcp_table_gen |= (tx_gcp_entry->mask_polarity & AL_ETH_TX_GCP_MASK_POLARITY_MASK) << + AL_ETH_TX_GCP_MASK_POLARITY_SHIFT; + al_dbg("al_eth_tx_generic_crc_entry_set, line [%d], gcp_table_gen: %#x", idx, gcp_table_gen); + + tx_alu_opcode = (tx_gcp_entry->tx_alu_opcode_1 & AL_ETH_TX_GCP_OPCODE_1_MASK) << + AL_ETH_TX_GCP_OPCODE_1_SHIFT; + tx_alu_opcode |= (tx_gcp_entry->tx_alu_opcode_2 & AL_ETH_TX_GCP_OPCODE_2_MASK) << + AL_ETH_TX_GCP_OPCODE_2_SHIFT; + tx_alu_opcode |= (tx_gcp_entry->tx_alu_opcode_3 & AL_ETH_TX_GCP_OPCODE_3_MASK) << + AL_ETH_TX_GCP_OPCODE_3_SHIFT; + tx_alu_opsel = (tx_gcp_entry->tx_alu_opsel_1 & AL_ETH_TX_GCP_OPSEL_1_MASK) << + AL_ETH_TX_GCP_OPSEL_1_SHIFT; + tx_alu_opsel |= (tx_gcp_entry->tx_alu_opsel_2 & AL_ETH_TX_GCP_OPSEL_2_MASK) << + AL_ETH_TX_GCP_OPSEL_2_SHIFT; + tx_alu_opsel |= (tx_gcp_entry->tx_alu_opsel_3 & AL_ETH_TX_GCP_OPSEL_3_MASK) << + AL_ETH_TX_GCP_OPSEL_3_SHIFT; + tx_alu_opsel |= (tx_gcp_entry->tx_alu_opsel_4 & AL_ETH_TX_GCP_OPSEL_4_MASK) << + AL_ETH_TX_GCP_OPSEL_4_SHIFT; + + /* Tx Generic crc prameters table general */ + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_addr, idx); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_gen, + gcp_table_gen); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_mask_1, + tx_gcp_entry->gcp_mask[0]); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_mask_2, + tx_gcp_entry->gcp_mask[1]); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_mask_3, + tx_gcp_entry->gcp_mask[2]); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_mask_4, + tx_gcp_entry->gcp_mask[3]); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_mask_5, + tx_gcp_entry->gcp_mask[4]); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_mask_6, + tx_gcp_entry->gcp_mask[5]); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_crc_init, + tx_gcp_entry->crc_init); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_res, + tx_gcp_entry->gcp_table_res); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_alu_opcode, + tx_alu_opcode); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_alu_opsel, + tx_alu_opsel); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_table_alu_val, + tx_gcp_entry->alu_val); + return 0; +} + +int al_eth_tx_crc_chksum_replace_cmd_entry_set(struct al_hal_eth_adapter *adapter, uint32_t idx, + struct al_eth_tx_crc_chksum_replace_cmd_for_protocol_num_entry *tx_replace_entry) +{ + uint32_t replace_table_address; + uint32_t tx_replace_cmd; + + /* Tx crc_chksum_replace_cmd */ + replace_table_address = L4_CHECKSUM_DIS_AND_L3_CHECKSUM_DIS | idx; + tx_replace_cmd = (uint32_t)(tx_replace_entry->l3_csum_en_00) << 0; + tx_replace_cmd |= (uint32_t)(tx_replace_entry->l4_csum_en_00) << 1; + tx_replace_cmd |= (uint32_t)(tx_replace_entry->crc_en_00) << 2; + al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace_table_addr, replace_table_address); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace_table, + tx_replace_cmd); + replace_table_address = L4_CHECKSUM_DIS_AND_L3_CHECKSUM_EN | idx; + tx_replace_cmd = (uint32_t)(tx_replace_entry->l3_csum_en_01) << 0; + tx_replace_cmd |= (uint32_t)(tx_replace_entry->l4_csum_en_01) << 1; + tx_replace_cmd |= (uint32_t)(tx_replace_entry->crc_en_01) << 2; + al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace_table_addr, replace_table_address); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace_table, + tx_replace_cmd); + replace_table_address = L4_CHECKSUM_EN_AND_L3_CHECKSUM_DIS | idx; + tx_replace_cmd = (uint32_t)(tx_replace_entry->l3_csum_en_10) << 0; + tx_replace_cmd |= (uint32_t)(tx_replace_entry->l4_csum_en_10) << 1; + tx_replace_cmd |= (uint32_t)(tx_replace_entry->crc_en_10) << 2; + al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace_table_addr, replace_table_address); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace_table, + tx_replace_cmd); + replace_table_address = L4_CHECKSUM_EN_AND_L3_CHECKSUM_EN | idx; + tx_replace_cmd = (uint32_t)(tx_replace_entry->l3_csum_en_11) << 0; + tx_replace_cmd |= (uint32_t)(tx_replace_entry->l4_csum_en_11) << 1; + tx_replace_cmd |= (uint32_t)(tx_replace_entry->crc_en_11) << 2; + al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace_table_addr, replace_table_address); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace_table, + tx_replace_cmd); + + return 0; +} + +int al_eth_rx_protocol_detect_table_entry_set(struct al_hal_eth_adapter *adapter, uint32_t idx, + struct al_eth_rx_gpd_cam_entry *rx_gpd_entry) +{ + uint64_t gpd_data; + uint64_t gpd_mask; + + gpd_data = ((uint64_t)rx_gpd_entry->outer_l3_proto_idx & AL_ETH_RX_GPD_OUTER_L3_PROTO_MASK) << + AL_ETH_RX_GPD_OUTER_L3_PROTO_SHIFT; + gpd_data |= ((uint64_t)rx_gpd_entry->outer_l4_proto_idx & AL_ETH_RX_GPD_OUTER_L4_PROTO_MASK) << + AL_ETH_RX_GPD_OUTER_L4_PROTO_SHIFT; + gpd_data |= ((uint64_t)rx_gpd_entry->inner_l3_proto_idx & AL_ETH_RX_GPD_INNER_L3_PROTO_MASK) << + AL_ETH_RX_GPD_INNER_L3_PROTO_SHIFT; + gpd_data |= ((uint64_t)rx_gpd_entry->inner_l4_proto_idx & AL_ETH_RX_GPD_INNER_L4_PROTO_MASK) << + AL_ETH_RX_GPD_INNER_L4_PROTO_SHIFT; + gpd_data |= ((uint64_t)rx_gpd_entry->parse_ctrl & AL_ETH_RX_GPD_OUTER_PARSE_CTRL_MASK) << + AL_ETH_RX_GPD_OUTER_PARSE_CTRL_SHIFT; + gpd_data |= ((uint64_t)rx_gpd_entry->outer_l3_len & AL_ETH_RX_GPD_INNER_PARSE_CTRL_MASK) << + AL_ETH_RX_GPD_INNER_PARSE_CTRL_SHIFT; + gpd_data |= ((uint64_t)rx_gpd_entry->l3_priority & AL_ETH_RX_GPD_L3_PRIORITY_MASK) << + AL_ETH_RX_GPD_L3_PRIORITY_SHIFT; + gpd_data |= ((uint64_t)rx_gpd_entry->l4_dst_port_lsb & AL_ETH_RX_GPD_L4_DST_PORT_LSB_MASK) << + AL_ETH_RX_GPD_L4_DST_PORT_LSB_SHIFT; + + gpd_mask = ((uint64_t)rx_gpd_entry->outer_l3_proto_idx_mask & AL_ETH_RX_GPD_OUTER_L3_PROTO_MASK) << + AL_ETH_RX_GPD_OUTER_L3_PROTO_SHIFT; + gpd_mask |= ((uint64_t)rx_gpd_entry->outer_l4_proto_idx_mask & AL_ETH_RX_GPD_OUTER_L4_PROTO_MASK) << + AL_ETH_RX_GPD_OUTER_L4_PROTO_SHIFT; + gpd_mask |= ((uint64_t)rx_gpd_entry->inner_l3_proto_idx_mask & AL_ETH_RX_GPD_INNER_L3_PROTO_MASK) << + AL_ETH_RX_GPD_INNER_L3_PROTO_SHIFT; + gpd_mask |= ((uint64_t)rx_gpd_entry->inner_l4_proto_idx_mask & AL_ETH_RX_GPD_INNER_L4_PROTO_MASK) << + AL_ETH_RX_GPD_INNER_L4_PROTO_SHIFT; + gpd_mask |= ((uint64_t)rx_gpd_entry->parse_ctrl_mask & AL_ETH_RX_GPD_OUTER_PARSE_CTRL_MASK) << + AL_ETH_RX_GPD_OUTER_PARSE_CTRL_SHIFT; + gpd_mask |= ((uint64_t)rx_gpd_entry->outer_l3_len_mask & AL_ETH_RX_GPD_INNER_PARSE_CTRL_MASK) << + AL_ETH_RX_GPD_INNER_PARSE_CTRL_SHIFT; + gpd_mask |= ((uint64_t)rx_gpd_entry->l3_priority_mask & AL_ETH_RX_GPD_L3_PRIORITY_MASK) << + AL_ETH_RX_GPD_L3_PRIORITY_SHIFT; + gpd_mask |= ((uint64_t)rx_gpd_entry->l4_dst_port_lsb_mask & AL_ETH_RX_GPD_L4_DST_PORT_LSB_MASK) << + AL_ETH_RX_GPD_L4_DST_PORT_LSB_SHIFT; + + /* Rx Generic protocol detect Cam compare table */ + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gpd_cam_addr, idx); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gpd_cam_ctrl, + (uint32_t)((rx_gpd_entry->rx_gpd_cam_ctrl) << AL_ETH_RX_GPD_CAM_CTRL_VALID_SHIFT)); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gpd_cam_mask_2, + (uint32_t)(gpd_mask >> AL_ETH_RX_GPD_CAM_MASK_2_SHIFT)); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gpd_cam_mask_1, + (uint32_t)(gpd_mask)); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gpd_cam_data_2, + (uint32_t)(gpd_data >> AL_ETH_RX_GPD_CAM_DATA_2_SHIFT)); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gpd_cam_data_1, + (uint32_t)(gpd_data)); + return 0; +} + +int al_eth_rx_generic_crc_table_entry_set(struct al_hal_eth_adapter *adapter, uint32_t idx, + struct al_eth_rx_gcp_table_entry *rx_gcp_entry) +{ + uint32_t gcp_table_gen; + uint32_t rx_alu_opcode; + uint32_t rx_alu_opsel; + + gcp_table_gen = (rx_gcp_entry->poly_sel & AL_ETH_RX_GCP_POLY_SEL_MASK) << + AL_ETH_RX_GCP_POLY_SEL_SHIFT; + gcp_table_gen |= (rx_gcp_entry->crc32_bit_comp & AL_ETH_RX_GCP_CRC32_BIT_COMP_MASK) << + AL_ETH_RX_GCP_CRC32_BIT_COMP_SHIFT; + gcp_table_gen |= (rx_gcp_entry->crc32_bit_swap & AL_ETH_RX_GCP_CRC32_BIT_SWAP_MASK) << + AL_ETH_RX_GCP_CRC32_BIT_SWAP_SHIFT; + gcp_table_gen |= (rx_gcp_entry->crc32_byte_swap & AL_ETH_RX_GCP_CRC32_BYTE_SWAP_MASK) << + AL_ETH_RX_GCP_CRC32_BYTE_SWAP_SHIFT; + gcp_table_gen |= (rx_gcp_entry->data_bit_swap & AL_ETH_RX_GCP_DATA_BIT_SWAP_MASK) << + AL_ETH_RX_GCP_DATA_BIT_SWAP_SHIFT; + gcp_table_gen |= (rx_gcp_entry->data_byte_swap & AL_ETH_RX_GCP_DATA_BYTE_SWAP_MASK) << + AL_ETH_RX_GCP_DATA_BYTE_SWAP_SHIFT; + gcp_table_gen |= (rx_gcp_entry->trail_size & AL_ETH_RX_GCP_TRAIL_SIZE_MASK) << + AL_ETH_RX_GCP_TRAIL_SIZE_SHIFT; + gcp_table_gen |= (rx_gcp_entry->head_size & AL_ETH_RX_GCP_HEAD_SIZE_MASK) << + AL_ETH_RX_GCP_HEAD_SIZE_SHIFT; + gcp_table_gen |= (rx_gcp_entry->head_calc & AL_ETH_RX_GCP_HEAD_CALC_MASK) << + AL_ETH_RX_GCP_HEAD_CALC_SHIFT; + gcp_table_gen |= (rx_gcp_entry->mask_polarity & AL_ETH_RX_GCP_MASK_POLARITY_MASK) << + AL_ETH_RX_GCP_MASK_POLARITY_SHIFT; + + rx_alu_opcode = (rx_gcp_entry->rx_alu_opcode_1 & AL_ETH_RX_GCP_OPCODE_1_MASK) << + AL_ETH_RX_GCP_OPCODE_1_SHIFT; + rx_alu_opcode |= (rx_gcp_entry->rx_alu_opcode_2 & AL_ETH_RX_GCP_OPCODE_2_MASK) << + AL_ETH_RX_GCP_OPCODE_2_SHIFT; + rx_alu_opcode |= (rx_gcp_entry->rx_alu_opcode_3 & AL_ETH_RX_GCP_OPCODE_3_MASK) << + AL_ETH_RX_GCP_OPCODE_3_SHIFT; + rx_alu_opsel = (rx_gcp_entry->rx_alu_opsel_1 & AL_ETH_RX_GCP_OPSEL_1_MASK) << + AL_ETH_RX_GCP_OPSEL_1_SHIFT; + rx_alu_opsel |= (rx_gcp_entry->rx_alu_opsel_2 & AL_ETH_RX_GCP_OPSEL_2_MASK) << + AL_ETH_RX_GCP_OPSEL_2_SHIFT; + rx_alu_opsel |= (rx_gcp_entry->rx_alu_opsel_3 & AL_ETH_RX_GCP_OPSEL_3_MASK) << + AL_ETH_RX_GCP_OPSEL_3_SHIFT; + rx_alu_opsel |= (rx_gcp_entry->rx_alu_opsel_4 & AL_ETH_RX_GCP_OPSEL_4_MASK) << + AL_ETH_RX_GCP_OPSEL_4_SHIFT; + + /* Rx Generic crc prameters table general */ + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_addr, idx); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_gen, + gcp_table_gen); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_mask_1, + rx_gcp_entry->gcp_mask[0]); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_mask_2, + rx_gcp_entry->gcp_mask[1]); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_mask_3, + rx_gcp_entry->gcp_mask[2]); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_mask_4, + rx_gcp_entry->gcp_mask[3]); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_mask_5, + rx_gcp_entry->gcp_mask[4]); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_mask_6, + rx_gcp_entry->gcp_mask[5]); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_crc_init, + rx_gcp_entry->crc_init); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_res, + rx_gcp_entry->gcp_table_res); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_alu_opcode, + rx_alu_opcode); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_alu_opsel, + rx_alu_opsel); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_table_alu_val, + rx_gcp_entry->alu_val); + return 0; +} + + +#define AL_ETH_TX_GENERIC_CRC_ENTRIES_NUM 9 +#define AL_ETH_RX_PROTOCOL_DETECT_ENTRIES_NUM 32 + +static struct al_eth_tx_gpd_cam_entry +al_eth_generic_tx_crc_gpd[AL_ETH_TX_GENERIC_CRC_ENTRIES_NUM] = { + + /* [0] roce (with grh, bth) */ + {22, 0, 0, 0, 1, + 0x1f, 0x0, 0x0, 0x0, }, + /* [1] fcoe */ + {21, 0, 0, 0, 1, + 0x1f, 0x0, 0x0, 0x0, }, + /* [2] routable_roce that is refered as l4_protocol, over IPV4 (and udp) */ + {8, 23, 0, 0, 1, + 0x1f, 0x1f, 0x0, 0x0, }, + /* [3] routable_roce that is refered as l4_protocol, over IPV6 (and udp) */ + {11, 23, 0, 0, 1, + 0x1f, 0x1f, 0x0, 0x0, }, + /* [4] routable_roce that is refered as tunneled_packet, over outer IPV4 and udp */ + {23, 0, 5, 0, 1, + 0x1f, 0x0, 0x5, 0x0, }, + /* [5] routable_roce that is refered as tunneled_packet, over outer IPV6 and udp */ + {23, 0, 3, 0, 1, + 0x1f, 0x0, 0x5, 0x0 }, + /* [6] GENERIC_STORAGE_READ over IPV4 (and udp) */ + {8, 2, 0, 0, 1, + 0x1f, 0x1f, 0x0, 0x0, }, + /* [7] GENERIC_STORAGE_READ over IPV6 (and udp) */ + {11, 2, 0, 0, 1, + 0x1f, 0x1f, 0x0, 0x0, }, + /* [8] default match */ + {0, 0, 0, 0, 1, + 0x0, 0x0, 0x0, 0x0 } +}; + +static struct al_eth_tx_gcp_table_entry +al_eth_generic_tx_crc_gcp[AL_ETH_TX_GENERIC_CRC_ENTRIES_NUM] = { + + /* [0] roce (with grh, bth) */ + {0, 1, 1, 0, 1, + 0, 4, 8, 0, 1, + 0, 0, 0, 0, 0, + 0, 0, {0xffff7f03, 0x00000000, 0x00000000, + 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x0, + 0}, + /* [1] fcoe */ + {0, 1, 0, 0, 1, + 0, 8, 14, 1, 1, + 0, 0, 0, 0, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x0, + 0}, + /* [2] routable_roce that is refered as l4_protocol, over IPV4 (and udp) */ + {0, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 0, 0, 0, 0, 0, + 0, 0, {0x3000cf00, 0x00000f00, 0xc0000000, + 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x0, + 0}, + /* [3] routable_roce that is refered as l4_protocol, over IPV6 (and udp) */ + {0, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 0, 0, 0, 0, 0, + 0, 0, {0x7f030000, 0x00000000, 0x00000003, + 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x0, + 0}, + /* [4] routable_roce that is refered as tunneled_packet, over outer IPV4 and udp */ + {0, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 2, 0, 0, 0, 10, + 0, 0, {0x3000cf00, 0x00000f00, 0xc0000000, + 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x0, + 28}, + /* [5] routable_roce that is refered as tunneled_packet, over outer IPV6 and udp */ + {0, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 2, 0, 0, 0, 10, + 0, 0, {0x7f030000, 0x00000000, 0x00000003, + 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x0, + 48}, + /* [6] GENERIC_STORAGE_READ over IPV4 (and udp) */ + {1, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 1, 0, 1, 0, 2, + 10, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x0, + 8}, + /* [7] GENERIC_STORAGE_READ over IPV6 (and udp) */ + {1, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 1, 0, 1, 0, 2, + 10, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x0, + 8}, + /* [8] default match */ + {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x0, + 0} +}; + +static struct al_eth_tx_crc_chksum_replace_cmd_for_protocol_num_entry +al_eth_tx_crc_chksum_replace_cmd[AL_ETH_TX_GENERIC_CRC_ENTRIES_NUM] = { + + /* [0] roce (with grh, bth) */ + {0,1,0,1, 0,0,0,0, 0,0,0,0}, + /* [1] fcoe */ + {0,1,0,1, 0,0,0,0, 0,0,0,0}, + /* [2] routable_roce that is refered as l4_protocol, over IPV4 (and udp) */ + {0,0,1,1, 0,0,0,0, 0,1,0,1}, + /* [3] routable_roce that is refered as l4_protocol, over IPV6 (and udp) */ + {0,0,1,1, 0,0,0,0, 0,0,0,0}, + /* [4] routable_roce that is refered as tunneled_packet, over outer IPV4 and udp */ + {0,1,0,1, 0,0,0,0, 0,0,0,0}, + /* [5] routable_roce that is refered as tunneled_packet, over outer IPV6 and udp */ + {0,1,0,1, 0,0,0,0, 0,0,0,0}, + /* [6] GENERIC_STORAGE_READ over IPV4 (and udp) */ + {0,0,1,1, 0,0,0,0, 0,1,0,1}, + /* [7] GENERIC_STORAGE_READ over IPV6 (and udp) */ + {0,0,1,1, 0,0,0,0, 0,0,0,0}, + /* [8] default match */ + {0,0,0,0, 0,0,1,1, 0,1,0,1} +}; + +static struct al_eth_rx_gpd_cam_entry +al_eth_generic_rx_crc_gpd[AL_ETH_RX_PROTOCOL_DETECT_ENTRIES_NUM] = { + + /* [0] roce (with grh, bth) */ + {22, 0, 0, 0, + 0, 0, 0, 0, 1, + 0x1f, 0x0, 0x0, 0x0, + 0x4, 0x0, 0x0, 0x0}, + /* [1] fcoe */ + {21, 0, 0, 0, + 0, 0, 0, 0, 1, + 0x1f, 0x0, 0x0, 0x0, + 0x4, 0x0, 0x0, 0x0}, + /* [2] routable_roce that is refered as l4_protocol, over IPV4 (and udp) */ + {8, 23, 0, 0, + 0, 0, 0, 0, 1, + 0x1f, 0x1f, 0x0, 0x0, + 0x4, 0x0, 0x0, 0x0}, + /* [3] routable_roce that is refered as l4_protocol, over IPV6 (and udp) */ + {11, 23, 0, 0, + 0, 0, 0, 0, 1, + 0x1f, 0x1f, 0x0, 0x0, + 0x4, 0x0, 0x0, 0x0}, + /* [4] routable_roce that is refered as tunneled_packet, over outer IPV4 and udp */ + {8, 13, 23, 0, + 0, 0, 0, 0, 1, + 0x1f, 0x1f, 0x1f, 0x0, + 0x4, 0x0, 0x0, 0x0}, + /* [5] routable_roce that is refered as tunneled_packet, over outer IPV6 and udp */ + {11, 13, 23, 0, + 0, 0, 0, 0, 1, + 0x1f, 0x1f, 0x1f, 0x0, + 0x4, 0x0, 0x0, 0x0}, + /* [6] tunneled roce (with grh, bth) over GRE over IPV4 */ + {8, 0, 22, 0, + 4, 0, 0, 0, 1, + 0x1f, 0x0, 0x1f, 0x0, + 0x4, 0x0, 0x0, 0x0}, + /* [7] tunneled roce (with grh, bth) over GRE over IPV6 */ + {11, 0, 22, 0, + 4, 0, 0, 0, 1, + 0x1f, 0x0, 0x1f, 0x0, + 0x4, 0x0, 0x0, 0x0}, + /* [8] tunneled fcoe over IPV4 */ + {8, 0, 21, 0, + 4, 0, 0, 0, 1, + 0x1f, 0x0, 0x1f, 0x0, + 0x4, 0x0, 0x0, 0x0}, + /* [9] tunneled fcoe over IPV6 */ + {11, 0, 21, 0, + 4, 0, 0, 0, 1, + 0x1f, 0x0, 0x1f, 0x0, + 0x4, 0x0, 0x0, 0x0}, + /* [10] tunneled routable_roce that is refered as l4_protocol, over IPV4 (and udp) over IPV4 */ + {8, 0, 8, 23, + 4, 0, 0, 0, 1, + 0x1f, 0x0, 0x1f, 0x1f, + 0x4, 0x0, 0x0, 0x0}, + /* [11] tunneled routable_roce that is refered as l4_protocol, over IPV4 (and udp) over IPV6 */ + {11, 0, 8, 23, + 4, 0, 0, 0, 1, + 0x1f, 0x0, 0x1f, 0x1f, + 0x4, 0x0, 0x0, 0x0}, + /* [12] tunneled routable_roce that is refered as l4_protocol, over IPV6 (and udp) over IPV4 */ + {8, 0, 11, 23, + 4, 0, 0, 0, 1, + 0x1f, 0x0, 0x1f, 0x1f, + 0x4, 0x0, 0x0, 0x0}, + /* [13] tunneled routable_roce that is refered as l4_protocol, over IPV6 (and udp) over IPV6 */ + {11, 0, 11, 23, + 4, 0, 0, 0, 1, + 0x1f, 0x0, 0x1f, 0x1f, + 0x4, 0x0, 0x0, 0x0}, + /* [14] l3_pkt - IPV4 */ + {8, 0, 0, 0, + 0, 0, 0, 0, 1, + 0x1f, 0x1f, 0x0, 0x0, + 0x4, 0x0, 0x0, 0x0}, + /* [15] l4_hdr over IPV4 */ + {8, 12, 0, 0, + 0, 0, 0, 0, 1, + 0x1f, 0x1e, 0x0, 0x0, + 0x4, 0x0, 0x0, 0x0}, + /* [16] l3_pkt - IPV6 */ + {11, 0, 0, 0, + 0, 0, 0, 0, 1, + 0x1f, 0x1f, 0x0, 0x0, + 0x4, 0x0, 0x0, 0x0}, + /* [17] l4_hdr over IPV6 */ + {11, 12, 0, 0, + 0, 0, 0, 0, 1, + 0x1f, 0x1e, 0x0, 0x0, + 0x4, 0x0, 0x0, 0x0}, + /* [18] IPV4 over IPV4 */ + {8, 0, 8, 0, + 4, 0, 0, 0, 1, + 0x1f, 0x0, 0x1f, 0x1f, + 0x4, 0x0, 0x0, 0x0}, + /* [19] l4_hdr over IPV4 over IPV4 */ + {8, 0, 8, 12, + 4, 0, 0, 0, 1, + 0x1f, 0x0, 0x1f, 0x1e, + 0x4, 0x0, 0x0, 0x0}, + /* [20] IPV4 over IPV6 */ + {11, 0, 8, 0, + 4, 0, 0, 0, 1, + 0x1f, 0x0, 0x1f, 0x1f, + 0x4, 0x0, 0x0, 0x0}, + /* [21] l4_hdr over IPV4 over IPV6 */ + {11, 0, 8, 12, + 4, 0, 0, 0, 1, + 0x1f, 0x0, 0x1f, 0x1e, + 0x4, 0x0, 0x0, 0x0}, + /* [22] IPV6 over IPV4 */ + {8, 0, 11, 0, + 4, 0, 0, 0, 1, + 0x1f, 0x0, 0x1f, 0x1f, + 0x4, 0x0, 0x0, 0x0}, + /* [23] l4_hdr over IPV6 over IPV4 */ + {8, 0, 11, 12, + 4, 0, 0, 0, 1, + 0x1f, 0x0, 0x1f, 0x1e, + 0x4, 0x0, 0x0, 0x0}, + /* [24] IPV6 over IPV6 */ + {11, 0, 11, 0, + 4, 0, 0, 0, 1, + 0x1f, 0x0, 0x1f, 0x1f, + 0x4, 0x0, 0x0, 0x0}, + /* [25] l4_hdr over IPV6 over IPV6 */ + {11, 0, 11, 12, + 4, 0, 0, 0, 1, + 0x1f, 0x0, 0x1f, 0x1e, + 0x4, 0x0, 0x0, 0x0}, + /* [26] GENERIC_STORAGE_READ, over IPV4 (and udp) */ + {8, 2, 0, 0, + 0, 0, 0, 0, 1, + 0x1f, 0x1f, 0x0, 0x0, + 0x4, 0x0, 0x0, 0x0}, + /* [27] GENERIC_STORAGE_READ, over IPV6 (and udp) */ + {11, 2, 0, 0, + 0, 0, 0, 0, 1, + 0x1f, 0x1f, 0x0, 0x0, + 0x4, 0x0, 0x0, 0x0}, + /* [28] tunneled GENERIC_STORAGE_READ over IPV4 (and udp) over IPV4/IPV6 */ + {8, 0, 8, 2, + 4, 0, 0, 0, 1, + 0x18, 0x0, 0x1f, 0x1f, + 0x4, 0x0, 0x0, 0x0}, + /* [29] tunneled GENERIC_STORAGE_READ over IPV6 (and udp) over IPV4/IPV6 */ + {8, 0, 11, 2, + 4, 0, 0, 0, 1, + 0x18, 0x0, 0x1f, 0x1f, + 0x4, 0x0, 0x0, 0x0}, + /* [30] tunneled L2 over GRE over IPV4 */ + {8, 0, 0, 0, + 4, 0, 0, 0, 1, + 0x1f, 0x0, 0x1f, 0x0, + 0x4, 0x0, 0x0, 0x0}, + /* [31] default match */ + {0, 0, 0, 0, + 0, 0, 0, 0, 1, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0} +}; + +static struct al_eth_rx_gcp_table_entry +al_eth_generic_rx_crc_gcp[AL_ETH_RX_PROTOCOL_DETECT_ENTRIES_NUM] = { + + /* [0] roce (with grh, bth) */ + {0, 1, 1, 0, 1, + 0, 4, 8, 0, 1, + 0, 0, 0, 0, 0, + 0, 0, {0xffff7f03, 0x00000000, 0x00000000, + 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000010, + 0}, + /* [1] fcoe */ + {0, 1, 0, 0, 1, + 0, 8, 14, 1, 1, + 0, 0, 0, 0, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000010, + 0}, + /* [2] routable_roce that is refered as l4_protocol, over IPV4 (and udp) */ + {0, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 0, 0, 0, 0, 0, + 0, 0, {0x3000cf00, 0x00000f00, 0xc0000000, + 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000011, + 0}, + /* [3] routable_roce that is refered as l4_protocol, over IPV6 (and udp) */ + {0, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 0, 0, 0, 0, 0, + 0, 0, {0x7f030000, 0x00000000, 0x00000003, + 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000010, + 0}, + /* [4] routable_roce that is refered as tunneled_packet, over outer IPV4 and udp */ + {0, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 2, 0, 0, 0, 10, + 0, 0, {0x3000cf00, 0x00000f00, 0xc0000000, + 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x0302201c, + 28}, + /* [5] routable_roce that is refered as tunneled_packet, over outer IPV6 and udp */ + {0, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 2, 0, 0, 0, 10, + 0, 0, {0x7f030000, 0x00000000, 0x00000003, + 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x03002018, + 48}, + /* [6] tunneled roce (with grh, bth) over IPV4 */ + {0, 1, 1, 0, 1, + 0, 4, 8, 0, 1, + 0, 0, 0, 1, 0, + 0, 0, {0xffff7f03, 0x00000000, 0x00000000, + 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x03020014, + 0}, + /* [7] tunneled roce (with grh, bth) over IPV6 */ + {0, 1, 1, 0, 1, + 0, 4, 8, 0, 1, + 0, 0, 0, 1, 0, + 0, 0, {0xffff7f03, 0x00000000, 0x00000000, + 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000010, + 0}, + /* [8] tunneled fcoe over IPV4 */ + {0, 1, 0, 0, 1, + 0, 8, 14, 1, 1, + 0, 0, 0, 1, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03020014, + 0}, + /* [9] tunneled fcoe over IPV6 */ + {0, 1, 0, 0, 1, + 0, 8, 14, 1, 1, + 0, 0, 0, 1, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000010, + 0}, + /* [10] tunneled routable_roce that is refered as l4_protocol, over IPV4 (and udp) over IPV4 */ + {0, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 0, 0, 0, 1, 0, + 0, 0, {0x3000cf00, 0x00000f00, 0xc0000000, + 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03020015, + 0}, + /* [11] tunneled routable_roce that is refered as l4_protocol, over IPV4 (and udp) over IPV6 */ + {0, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 0, 0, 0, 1, 0, + 0, 0, {0x3000cf00, 0x00000f00, 0xc0000000, + 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000011, + 0}, + /* [12] tunneled routable_roce that is refered as l4_protocol, over IPV6 (and udp) over IPV4 */ + {0, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 0, 0, 0, 1, 0, + 0, 0, {0x7f030000, 0x00000000, 0x00000003, + 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x03020014, + 0}, + /* [13] tunneled routable_roce that is refered as l4_protocol, over IPV6 (and udp) over IPV6 */ + {0, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 0, 0, 0, 1, 0, + 0, 0, {0x7f030000, 0x00000000, 0x00000003, + 0x00c00000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000010, + 0}, + /* [14] l3_pkt - IPV4 */ + {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00000001, + 0}, + /* [15] l4_hdr over IPV4 */ + {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00000003, + 0}, + /* [16] l3_pkt - IPV6 */ + {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00000000, + 0}, + /* [17] l4_hdr over IPV6 */ + {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00000002, + 0}, + /* [18] IPV4 over IPV4 */ + {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00020005, + 0}, + /* [19] l4_hdr over IPV4 over IPV4 */ + {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00020007, + 0}, + /* [20] IPV4 over IPV6 */ + {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00000001, + 0}, + /* [21] l4_hdr over IPV4 over IPV6 */ + {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00000003, + 0}, + /* [22] IPV6 over IPV4 */ + {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00020004, + 0}, + /* [23] l4_hdr over IPV6 over IPV4 */ + {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00020006, + 0}, + /* [24] IPV6 over IPV6 */ + {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00000000, + 0}, + /* [25] l4_hdr over IPV6 over IPV6 */ + {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00000002, + 0}, + /* [26] GENERIC_STORAGE_READ, over IPV4 (and udp) */ + {1, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 0, 0, 0, 2, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000011, + 0}, + /* [27] GENERIC_STORAGE_READ, over IPV6 (and udp) */ + {1, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 0, 0, 0, 2, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000010, + 0}, + /* [28] tunneled GENERIC_STORAGE_READ over IPV4 (and udp) over IPV4/IPV6 */ + {1, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 0, 0, 0, 3, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000011, + 0}, + /* [29] tunneled GENERIC_STORAGE_READ over IPV6 (and udp) over IPV4/IPV6 */ + {1, 1, 1, 0, 1, + 0, 4, 0, 0, 1, + 0, 0, 0, 3, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0xffffffff, 0x03000010, + 0}, + /* [30] tunneled L2 over GRE over IPV4 */ + {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x00020004, + 0}, + /* [31] default match */ + {0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, {0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000}, 0x00000000, 0x0, + 0} +}; + +int al_eth_tx_protocol_detect_table_init(struct al_hal_eth_adapter *adapter) +{ + int idx; + al_assert((adapter->rev_id > AL_ETH_REV_ID_2)); + + for (idx = 0; idx < AL_ETH_TX_GENERIC_CRC_ENTRIES_NUM; idx++) + al_eth_tx_protocol_detect_table_entry_set(adapter, idx, + &al_eth_generic_tx_crc_gpd[idx]); + + return 0; +} + +int al_eth_tx_generic_crc_table_init(struct al_hal_eth_adapter *adapter) +{ + int idx; + al_assert((adapter->rev_id > AL_ETH_REV_ID_2)); + + al_dbg("eth [%s]: enable tx_generic_crc\n", adapter->name); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.tx_gcp_legacy, 0x0); + al_reg_write32(&adapter->ec_regs_base->tfw_v3.crc_csum_replace, 0x0); + for (idx = 0; idx < AL_ETH_TX_GENERIC_CRC_ENTRIES_NUM; idx++) + al_eth_tx_generic_crc_table_entry_set(adapter, idx, + &al_eth_generic_tx_crc_gcp[idx]); + + return 0; +} + +int al_eth_tx_crc_chksum_replace_cmd_init(struct al_hal_eth_adapter *adapter) +{ + int idx; + al_assert((adapter->rev_id > AL_ETH_REV_ID_2)); + + for (idx = 0; idx < AL_ETH_TX_GENERIC_CRC_ENTRIES_NUM; idx++) + al_eth_tx_crc_chksum_replace_cmd_entry_set(adapter, idx, + &al_eth_tx_crc_chksum_replace_cmd[idx]); + + return 0; +} + +int al_eth_rx_protocol_detect_table_init(struct al_hal_eth_adapter *adapter) +{ + int idx; + al_assert((adapter->rev_id > AL_ETH_REV_ID_2)); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.gpd_p1, + AL_ETH_RX_GPD_PARSE_RESULT_OUTER_L3_PROTO_IDX_OFFSET); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.gpd_p2, + AL_ETH_RX_GPD_PARSE_RESULT_OUTER_L4_PROTO_IDX_OFFSET); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.gpd_p3, + AL_ETH_RX_GPD_PARSE_RESULT_INNER_L3_PROTO_IDX_OFFSET); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.gpd_p4, + AL_ETH_RX_GPD_PARSE_RESULT_INNER_L4_PROTO_IDX_OFFSET); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.gpd_p5, + AL_ETH_RX_GPD_PARSE_RESULT_OUTER_PARSE_CTRL); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.gpd_p6, + AL_ETH_RX_GPD_PARSE_RESULT_INNER_PARSE_CTRL); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.gpd_p7, + AL_ETH_RX_GPD_PARSE_RESULT_L3_PRIORITY); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.gpd_p8, + AL_ETH_RX_GPD_PARSE_RESULT_OUTER_L4_DST_PORT_LSB); + + for (idx = 0; idx < AL_ETH_RX_PROTOCOL_DETECT_ENTRIES_NUM; idx++) + al_eth_rx_protocol_detect_table_entry_set(adapter, idx, + &al_eth_generic_rx_crc_gpd[idx]); + return 0; +} + +int al_eth_rx_generic_crc_table_init(struct al_hal_eth_adapter *adapter) + { + int idx; + uint32_t val; + + al_assert((adapter->rev_id > AL_ETH_REV_ID_2)); + + al_dbg("eth [%s]: enable rx_generic_crc\n", adapter->name); + al_reg_write32(&adapter->ec_regs_base->rfw_v3.rx_gcp_legacy, 0x0); + + for (idx = 0; idx < AL_ETH_RX_PROTOCOL_DETECT_ENTRIES_NUM; idx++) + al_eth_rx_generic_crc_table_entry_set(adapter, idx, + &al_eth_generic_rx_crc_gcp[idx]); + + val = EC_GEN_V3_RX_COMP_DESC_W3_DEC_STAT_15_CRC_RES_SEL | + EC_GEN_V3_RX_COMP_DESC_W3_DEC_STAT_14_L3_CKS_RES_SEL | + EC_GEN_V3_RX_COMP_DESC_W3_DEC_STAT_13_L4_CKS_RES_SEL | + EC_GEN_V3_RX_COMP_DESC_W0_L3_CKS_RES_SEL; + al_reg_write32_masked(&adapter->ec_regs_base->gen_v3.rx_comp_desc, + val, val); + return 0; +} + +/** @} end of Ethernet group */ + From dc3155c1be5fbd19266af0a7e1c567b3369ff512 Mon Sep 17 00:00:00 2001 From: Luiz Otavio O Souza Date: Mon, 5 Sep 2016 18:42:21 +0000 Subject: [PATCH 002/109] Revert r305119, move the control module register data to am335x_scm.h and fix if_cpsw.c to include the correct header. Discussed with: bz --- sys/arm/ti/am335x/am335x_scm.h | 2 ++ sys/arm/ti/cpsw/if_cpsw.c | 9 +++++---- sys/arm/ti/cpsw/if_cpswreg.h | 3 --- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sys/arm/ti/am335x/am335x_scm.h b/sys/arm/ti/am335x/am335x_scm.h index 642620881f7..6116be063ad 100644 --- a/sys/arm/ti/am335x/am335x_scm.h +++ b/sys/arm/ti/am335x/am335x_scm.h @@ -42,6 +42,8 @@ #define SCM_USB_STS0 0x624 #define SCM_USB_CTRL1 0x628 #define SCM_USB_STS1 0x62C +#define SCM_MAC_ID0_LO 0x630 +#define SCM_MAC_ID0_HI 0x634 #define SCM_PWMSS_CTRL 0x664 #endif /* __AM335X_SCM_H__ */ diff --git a/sys/arm/ti/cpsw/if_cpsw.c b/sys/arm/ti/cpsw/if_cpsw.c index 038d2d2089c..27f187c05d6 100644 --- a/sys/arm/ti/cpsw/if_cpsw.c +++ b/sys/arm/ti/cpsw/if_cpsw.c @@ -78,6 +78,9 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include + #include #include @@ -87,8 +90,6 @@ __FBSDID("$FreeBSD$"); #include "if_cpswreg.h" #include "if_cpswvar.h" - -#include #include "miibus_if.h" @@ -1019,14 +1020,14 @@ cpswp_attach(device_t dev) IFQ_SET_READY(&ifp->if_snd); /* Get high part of MAC address from control module (mac_id[0|1]_hi) */ - ti_scm_reg_read_4(CPSW_MAC_ID0_HI + sc->unit * 8, ®); + ti_scm_reg_read_4(SCM_MAC_ID0_HI + sc->unit * 8, ®); mac_addr[0] = reg & 0xFF; mac_addr[1] = (reg >> 8) & 0xFF; mac_addr[2] = (reg >> 16) & 0xFF; mac_addr[3] = (reg >> 24) & 0xFF; /* Get low part of MAC address from control module (mac_id[0|1]_lo) */ - ti_scm_reg_read_4(CPSW_MAC_ID0_LO + sc->unit * 8, ®); + ti_scm_reg_read_4(SCM_MAC_ID0_LO + sc->unit * 8, ®); mac_addr[4] = reg & 0xFF; mac_addr[5] = (reg >> 8) & 0xFF; diff --git a/sys/arm/ti/cpsw/if_cpswreg.h b/sys/arm/ti/cpsw/if_cpswreg.h index c6f3e89c425..bea6f1904e3 100644 --- a/sys/arm/ti/cpsw/if_cpswreg.h +++ b/sys/arm/ti/cpsw/if_cpswreg.h @@ -46,9 +46,6 @@ #define CPSW_PORT_P_SA_LO(p) (CPSW_PORT_OFFSET + 0x120 + ((p-1) * 0x100)) #define CPSW_PORT_P_SA_HI(p) (CPSW_PORT_OFFSET + 0x124 + ((p-1) * 0x100)) -#define CPSW_MAC_ID0_LO 0x0630 -#define CPSW_MAC_ID0_HI 0x0634 - #define CPSW_CPDMA_OFFSET 0x0800 #define CPSW_CPDMA_TX_CONTROL (CPSW_CPDMA_OFFSET + 0x04) #define CPSW_CPDMA_TX_TEARDOWN (CPSW_CPDMA_OFFSET + 0x08) From 5aaa3bc3b94bf5e1e1cc7b9c1ccd294408f52b2f Mon Sep 17 00:00:00 2001 From: Navdeep Parhar Date: Mon, 5 Sep 2016 19:37:47 +0000 Subject: [PATCH 003/109] cxgbe/t4_tom: toepcb should be all-zero on allocation because the code that cleans up on failure assumes that non-NULL values indicate initialized items. Sponsored by: Chelsio Communications --- sys/dev/cxgbe/tom/t4_connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/cxgbe/tom/t4_connect.c b/sys/dev/cxgbe/tom/t4_connect.c index f550723cb21..9eb63551fb2 100644 --- a/sys/dev/cxgbe/tom/t4_connect.c +++ b/sys/dev/cxgbe/tom/t4_connect.c @@ -332,7 +332,7 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt, else DONT_OFFLOAD_ACTIVE_OPEN(ENOTSUP); - toep = alloc_toepcb(vi, -1, -1, M_NOWAIT); + toep = alloc_toepcb(vi, -1, -1, M_NOWAIT | M_ZERO); if (toep == NULL) DONT_OFFLOAD_ACTIVE_OPEN(ENOMEM); From c57ee45ba9953238a0ef78d3db005be5b5c338e5 Mon Sep 17 00:00:00 2001 From: Andriy Voskoboinyk Date: Mon, 5 Sep 2016 19:42:35 +0000 Subject: [PATCH 004/109] rum: do not restart device when protmode / rtsthreshold is changed. --- sys/dev/usb/wlan/if_rum.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c index 86bb97cc90d..bab18a61e41 100644 --- a/sys/dev/usb/wlan/if_rum.c +++ b/sys/dev/usb/wlan/if_rum.c @@ -2692,6 +2692,8 @@ rum_reset(struct ieee80211vap *vap, u_long cmd) switch (cmd) { case IEEE80211_IOC_POWERSAVE: + case IEEE80211_IOC_PROTMODE: + case IEEE80211_IOC_RTSTHRESHOLD: error = 0; break; case IEEE80211_IOC_POWERSAVESLEEP: From fb88110c095a0532d85db93b2c04b874d94524a9 Mon Sep 17 00:00:00 2001 From: "Landon J. Fuller" Date: Mon, 5 Sep 2016 21:48:16 +0000 Subject: [PATCH 005/109] bhnd(4): Add device classes for USB host/dev/dual-mode controller cores. Approved by: adrian (mentor, implicit) --- sys/dev/bhnd/bhnd_subr.c | 14 +++++++------- sys/dev/bhnd/bhnd_types.h | 5 ++++- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/sys/dev/bhnd/bhnd_subr.c b/sys/dev/bhnd/bhnd_subr.c index e939286f3db..51dfb40da99 100644 --- a/sys/dev/bhnd/bhnd_subr.c +++ b/sys/dev/bhnd/bhnd_subr.c @@ -71,7 +71,7 @@ static const struct bhnd_core_desc { BHND_CDESC(BCM, MIPS, CPU, "MIPS Core"), BHND_CDESC(BCM, ENET, ENET_MAC, "Fast Ethernet MAC"), BHND_CDESC(BCM, CODEC, OTHER, "V.90 Modem Codec"), - BHND_CDESC(BCM, USB, OTHER, "USB 1.1 Device/Host Controller"), + BHND_CDESC(BCM, USB, USB_DUAL, "USB 1.1 Device/Host Controller"), BHND_CDESC(BCM, ADSL, OTHER, "ADSL Core"), BHND_CDESC(BCM, ILINE100, OTHER, "iLine100 HPNA"), BHND_CDESC(BCM, IPSEC, OTHER, "IPsec Accelerator"), @@ -86,10 +86,10 @@ static const struct bhnd_core_desc { BHND_CDESC(BCM, BPHY, WLAN_PHY, "802.11b PHY"), BHND_CDESC(BCM, GPHY, WLAN_PHY, "802.11g PHY"), BHND_CDESC(BCM, MIPS33, CPU, "MIPS3302 Core"), - BHND_CDESC(BCM, USB11H, OTHER, "USB 1.1 Host Controller"), - BHND_CDESC(BCM, USB11D, OTHER, "USB 1.1 Device Core"), - BHND_CDESC(BCM, USB20H, OTHER, "USB 2.0 Host Controller"), - BHND_CDESC(BCM, USB20D, OTHER, "USB 2.0 Device Core"), + BHND_CDESC(BCM, USB11H, USB_HOST, "USB 1.1 Host Controller"), + BHND_CDESC(BCM, USB11D, USB_DEV, "USB 1.1 Device Controller"), + BHND_CDESC(BCM, USB20H, USB_HOST, "USB 2.0 Host Controller"), + BHND_CDESC(BCM, USB20D, USB_DEV, "USB 2.0 Device Controller"), BHND_CDESC(BCM, SDIOH, OTHER, "SDIO Host Controller"), BHND_CDESC(BCM, ROBO, OTHER, "RoboSwitch"), BHND_CDESC(BCM, ATA100, OTHER, "Parallel ATA Controller"), @@ -130,8 +130,8 @@ static const struct bhnd_core_desc { BHND_CDESC(BCM, NS_PCIE2, PCIE, "PCIe Bridge (Gen2)"), BHND_CDESC(BCM, NS_DMA, OTHER, "DMA engine"), BHND_CDESC(BCM, NS_SDIO, OTHER, "SDIO 3.0 Host Controller"), - BHND_CDESC(BCM, NS_USB20H, OTHER, "USB 2.0 Host Controller"), - BHND_CDESC(BCM, NS_USB30H, OTHER, "USB 3.0 Host Controller"), + BHND_CDESC(BCM, NS_USB20H, USB_HOST, "USB 2.0 Host Controller"), + BHND_CDESC(BCM, NS_USB30H, USB_HOST, "USB 3.0 Host Controller"), BHND_CDESC(BCM, NS_A9JTAG, OTHER, "ARM Cortex A9 JTAG Interface"), BHND_CDESC(BCM, NS_DDR23_MEMC, MEMC, "Denali DDR2/DD3 Memory Controller"), BHND_CDESC(BCM, NS_ROM, NVRAM, "System ROM"), diff --git a/sys/dev/bhnd/bhnd_types.h b/sys/dev/bhnd/bhnd_types.h index 49387080703..ffdbf1a4748 100644 --- a/sys/dev/bhnd/bhnd_types.h +++ b/sys/dev/bhnd/bhnd_types.h @@ -57,8 +57,11 @@ typedef enum { BHND_DEVCLASS_SOC_BRIDGE, /**< interconnect host bridge */ BHND_DEVCLASS_EROM, /**< bus device enumeration ROM */ BHND_DEVCLASS_NVRAM, /**< nvram/flash controller */ - BHND_DEVCLASS_OTHER, /**< other / unknown */ + BHND_DEVCLASS_USB_HOST, /**< USB host controller */ + BHND_DEVCLASS_USB_DEV, /**< USB device controller */ + BHND_DEVCLASS_USB_DUAL, /**< USB host/device controller */ + BHND_DEVCLASS_OTHER = 1000, /**< other / unknown */ BHND_DEVCLASS_INVALID /**< no/invalid class */ } bhnd_devclass_t; From 7d6162806bfe372f9b893254dae805e5dab2dd6a Mon Sep 17 00:00:00 2001 From: "Landon J. Fuller" Date: Mon, 5 Sep 2016 21:55:27 +0000 Subject: [PATCH 006/109] bwn(4): ignore BCM4321's unpopulated USB11 host controller core. Broadcom Intensi-fi chipsets provided a common set of IP cores; on PCI/PCIe devices, the USB11 host controller is left floating. Approved by: adrian (mentor, implicit) --- sys/dev/bwn/if_bwn_pci.c | 11 ++++++++--- sys/dev/bwn/if_bwn_pcivar.h | 7 +++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/sys/dev/bwn/if_bwn_pci.c b/sys/dev/bwn/if_bwn_pci.c index 59687832e19..f49213c7192 100644 --- a/sys/dev/bwn/if_bwn_pci.c +++ b/sys/dev/bwn/if_bwn_pci.c @@ -84,10 +84,12 @@ static const struct bwn_pci_device siba_devices[] = { BWN_BCM_DEV(BCM4318_D11A, "BCM4318 802.11a", BWN_QUIRK_UNTESTED|BWN_QUIRK_WLAN_DUALCORE), - BWN_BCM_DEV(BCM4321_D11N, "BCM4321 802.11n Dual-Band", 0), - BWN_BCM_DEV(BCM4321_D11N2G, "BCM4321 802.11n 2GHz", 0), + BWN_BCM_DEV(BCM4321_D11N, "BCM4321 802.11n Dual-Band", + BWN_QUIRK_USBH_UNPOPULATED), + BWN_BCM_DEV(BCM4321_D11N2G, "BCM4321 802.11n 2GHz", + BWN_QUIRK_USBH_UNPOPULATED), BWN_BCM_DEV(BCM4321_D11N2G, "BCM4321 802.11n 5GHz", - BWN_QUIRK_UNTESTED), + BWN_QUIRK_UNTESTED|BWN_QUIRK_USBH_UNPOPULATED), BWN_BCM_DEV(BCM4322_D11N, "BCM4322 802.11n Dual-Band", 0), BWN_BCM_DEV(BCM4322_D11N2G, "BCM4322 802.11n 2GHz", @@ -263,6 +265,9 @@ bwn_pci_is_core_disabled(device_t dev, device_t child, case BHND_DEVCLASS_ENET_MAC: case BHND_DEVCLASS_ENET_PHY: return ((sc->quirks & BWN_QUIRK_ENET_HW_UNPOPULATED) != 0); + + case BHND_DEVCLASS_USB_HOST: + return ((sc->quirks & BWN_QUIRK_USBH_UNPOPULATED) != 0); default: return (false); diff --git a/sys/dev/bwn/if_bwn_pcivar.h b/sys/dev/bwn/if_bwn_pcivar.h index c34ad12ac0c..92f7ab39cda 100644 --- a/sys/dev/bwn/if_bwn_pcivar.h +++ b/sys/dev/bwn/if_bwn_pcivar.h @@ -68,6 +68,13 @@ enum { * this quirk to treat these cores as unpopulated. */ BWN_QUIRK_ENET_HW_UNPOPULATED = 1<<2, + + /** + * Some PCI/PCIe "Intensi-fi" chipsets shipped with floating USB + * host controller cores; set this quirk to treat these cores as + * unpopulated. + */ + BWN_QUIRK_USBH_UNPOPULATED = 1<<3, }; /* PCI device descriptor */ From 824b48eff36156b1d9adbb7372b26f2b853fb310 Mon Sep 17 00:00:00 2001 From: "Landon J. Fuller" Date: Mon, 5 Sep 2016 22:11:46 +0000 Subject: [PATCH 007/109] bhnd(4): Implement backplane interrupt handling. This adds bhnd(4) bus-level support for querying backplane interrupt vector routing, and delegating machine/bridge-specific interrupt handling to the concrete bhnd(4) driver implementation. On bhndb(4) bridged PCI devices, we provide the PCI/MSI interrupt directly to attached cores. On MIPS devices, we report a backplane interrupt count of 0, effectively disabling the bus-level interrupt assignment. This allows mips/broadcom to temporarily continue using hard-coded MIPS IRQs until bhnd_mips PIC support is implemented. Reviewed by: mizhka Approved by: adrian (mentor, implicit) --- sys/dev/bhnd/bcma/bcma.c | 82 +++++++++++++++ sys/dev/bhnd/bcma/bcma_dmp.h | 111 ++++++++++++++------ sys/dev/bhnd/bcma/bcmavar.h | 3 + sys/dev/bhnd/bhnd.c | 9 +- sys/dev/bhnd/bhnd.h | 39 +++++++ sys/dev/bhnd/bhnd_bus_if.m | 95 ++++++++++++++++- sys/dev/bhnd/bhnd_nexus.c | 9 ++ sys/dev/bhnd/bhndb/bhnd_bhndb.c | 8 ++ sys/dev/bhnd/bhndb/bhndb.c | 139 +++++++++++-------------- sys/dev/bhnd/bhndb/bhndb_pci.c | 77 ++++++++++++++ sys/dev/bhnd/bhndb/bhndb_pcivar.h | 8 ++ sys/dev/bhnd/cores/pmu/bhnd_pmu_subr.c | 8 +- sys/dev/bhnd/siba/siba.c | 67 ++++++++++++ sys/dev/bhnd/siba/siba_bhndb.c | 1 - sys/dev/bhnd/siba/sibareg.h | 2 + sys/dev/bhnd/siba/sibavar.h | 3 + sys/dev/bwn/bwn_mac.c | 60 +++++++---- 17 files changed, 584 insertions(+), 137 deletions(-) diff --git a/sys/dev/bhnd/bcma/bcma.c b/sys/dev/bhnd/bcma/bcma.c index 8d4b6e2ec71..434bbfc57c6 100644 --- a/sys/dev/bhnd/bcma/bcma.c +++ b/sys/dev/bhnd/bcma/bcma.c @@ -41,8 +41,11 @@ __FBSDID("$FreeBSD$"); #include "bcmavar.h" +#include "bcma_dmp.h" + #include "bcma_eromreg.h" #include "bcma_eromvar.h" + #include /* RID used when allocating EROM table */ @@ -434,6 +437,70 @@ bcma_get_region_addr(device_t dev, device_t child, bhnd_port_type port_type, return (ENOENT); } +/** + * Default bcma(4) bus driver implementation of BHND_BUS_GET_INTR_COUNT(). + * + * This implementation consults @p child's agent register block, + * returning the number of interrupt output lines routed to @p child. + */ +int +bcma_get_intr_count(device_t dev, device_t child) +{ + struct bcma_devinfo *dinfo; + uint32_t dmpcfg, oobw; + + dinfo = device_get_ivars(child); + + /* Agent block must be mapped */ + if (dinfo->res_agent == NULL) + return (0); + + /* Agent must support OOB */ + dmpcfg = bhnd_bus_read_4(dinfo->res_agent, BCMA_DMP_CONFIG); + if (!BCMA_DMP_GET_FLAG(dmpcfg, BCMA_DMP_CFG_OOB)) + return (0); + + /* Return OOB width as interrupt count */ + oobw = bhnd_bus_read_4(dinfo->res_agent, + BCMA_DMP_OOB_OUTWIDTH(BCMA_OOB_BANK_INTR)); + if (oobw > BCMA_OOB_NUM_SEL) { + device_printf(dev, "ignoring invalid OOBOUTWIDTH for core %u: " + "%#x\n", BCMA_DINFO_COREIDX(dinfo), oobw); + return (0); + } + + return (oobw); +} + +/** + * Default bcma(4) bus driver implementation of BHND_BUS_GET_CORE_IVEC(). + * + * This implementation consults @p child's agent register block, + * returning the interrupt output line routed to @p child, at OOB selector + * @p intr. + */ +int +bcma_get_core_ivec(device_t dev, device_t child, u_int intr, uint32_t *ivec) +{ + struct bcma_devinfo *dinfo; + uint32_t oobsel; + + dinfo = device_get_ivars(child); + + /* Interrupt ID must be valid. */ + if (intr >= bcma_get_intr_count(dev, child)) + return (ENXIO); + + /* Fetch OOBSEL busline value */ + KASSERT(dinfo->res_agent != NULL, ("missing agent registers")); + oobsel = bhnd_bus_read_4(dinfo->res_agent, BCMA_DMP_OOBSELOUT( + BCMA_OOB_BANK_INTR, intr)); + *ivec = (oobsel >> BCMA_DMP_OOBSEL_SHIFT(intr)) & + BCMA_DMP_OOBSEL_BUSLINE_MASK; + + return (0); +} + static struct bhnd_devinfo * bcma_alloc_bhnd_dinfo(device_t dev) { @@ -475,6 +542,8 @@ bcma_add_children(device_t bus) /* Add all cores. */ bcma_erom = (struct bcma_erom *)erom; while ((error = bcma_erom_next_corecfg(bcma_erom, &corecfg)) == 0) { + int nintr; + /* Add the child device */ child = BUS_ADD_CHILD(bus, 0, NULL, -1); if (child == NULL) { @@ -494,6 +563,17 @@ bcma_add_children(device_t bus) if ((error = bcma_dinfo_alloc_agent(bus, child, dinfo))) goto cleanup; + /* Assign interrupts */ + nintr = bhnd_get_intr_count(child); + for (int rid = 0; rid < nintr; rid++) { + error = BHND_BUS_ASSIGN_INTR(bus, child, rid); + if (error) { + device_printf(bus, "failed to assign interrupt " + "%d to core %u: %d\n", rid, + BCMA_DINFO_COREIDX(dinfo), error); + } + } + /* If pins are floating or the hardware is otherwise * unpopulated, the device shouldn't be used. */ if (bhnd_is_hw_disabled(child)) @@ -544,6 +624,8 @@ static device_method_t bcma_methods[] = { DEVMETHOD(bhnd_bus_get_port_rid, bcma_get_port_rid), DEVMETHOD(bhnd_bus_decode_port_rid, bcma_decode_port_rid), DEVMETHOD(bhnd_bus_get_region_addr, bcma_get_region_addr), + DEVMETHOD(bhnd_bus_get_intr_count, bcma_get_intr_count), + DEVMETHOD(bhnd_bus_get_core_ivec, bcma_get_core_ivec), DEVMETHOD_END }; diff --git a/sys/dev/bhnd/bcma/bcma_dmp.h b/sys/dev/bhnd/bcma/bcma_dmp.h index b65e90e19c3..ae5f8dcb549 100644 --- a/sys/dev/bhnd/bcma/bcma_dmp.h +++ b/sys/dev/bhnd/bcma/bcma_dmp.h @@ -37,8 +37,18 @@ * in the proprietary "NIC-301 Interconnect Device Management (PL368)" * errata publication, available to licensees as part of ARM's * CoreLink Controllers and Peripherals Engineering Errata. + * + * As such, the exact interpretation of these register definitions is + * unconfirmed, and may be incorrect. */ +#define BCMA_DMP_GET_FLAG(_value, _flag) \ + (((_value) & _flag) != 0) +#define BCMA_DMP_GET_BITS(_value, _field) \ + ((_value & _field ## _MASK) >> _field ## _SHIFT) +#define BHND_DMP_SET_BITS(_value, _field) \ + (((_value) << _field ## _SHIFT) & _field ## _MASK) + /* Out-of-band Router registers */ #define BCMA_OOB_BUSCONFIG 0x020 #define BCMA_OOB_STATUSA 0x100 @@ -71,23 +81,36 @@ #define BCMA_OOB_ITOPOOBC 0xf38 #define BCMA_OOB_ITOPOOBD 0xf3c -/* DMP wrapper registers */ -#define BCMA_DMP_OOBSELINA30 0x000 -#define BCMA_DMP_OOBSELINA74 0x004 -#define BCMA_DMP_OOBSELINB30 0x020 -#define BCMA_DMP_OOBSELINB74 0x024 -#define BCMA_DMP_OOBSELINC30 0x040 -#define BCMA_DMP_OOBSELINC74 0x044 -#define BCMA_DMP_OOBSELIND30 0x060 -#define BCMA_DMP_OOBSELIND74 0x064 -#define BCMA_DMP_OOBSELOUTA30 0x100 -#define BCMA_DMP_OOBSELOUTA74 0x104 -#define BCMA_DMP_OOBSELOUTB30 0x120 -#define BCMA_DMP_OOBSELOUTB74 0x124 -#define BCMA_DMP_OOBSELOUTC30 0x140 -#define BCMA_DMP_OOBSELOUTC74 0x144 -#define BCMA_DMP_OOBSELOUTD30 0x160 -#define BCMA_DMP_OOBSELOUTD74 0x164 +/* Common definitions */ +#define BCMA_OOB_NUM_BANKS 4 /**< number of OOB banks (A, B, C, D) */ +#define BCMA_OOB_NUM_SEL 8 /**< number of OOB selectors per bank */ +#define BCMA_OOB_NUM_BUSLINES 32 /**< number of bus lines managed by OOB core */ + +#define BCMA_OOB_BANKA 0 /**< bank A index */ +#define BCMA_OOB_BANKB 1 /**< bank B index */ +#define BCMA_OOB_BANKC 2 /**< bank C index */ +#define BCMA_OOB_BANKD 3 /**< bank D index */ + +/** OOB bank used for interrupt lines */ +#define BCMA_OOB_BANK_INTR BCMA_OOB_BANKA + +/* DMP agent registers */ +#define BCMA_DMP_OOBSELINA30 0x000 /**< A0-A3 input selectors */ +#define BCMA_DMP_OOBSELINA74 0x004 /**< A4-A7 input selectors */ +#define BCMA_DMP_OOBSELINB30 0x020 /**< B0-B3 input selectors */ +#define BCMA_DMP_OOBSELINB74 0x024 /**< B4-B7 input selectors */ +#define BCMA_DMP_OOBSELINC30 0x040 /**< C0-C3 input selectors */ +#define BCMA_DMP_OOBSELINC74 0x044 /**< C4-C7 input selectors */ +#define BCMA_DMP_OOBSELIND30 0x060 /**< D0-D3 input selectors */ +#define BCMA_DMP_OOBSELIND74 0x064 /**< D4-D7 input selectors */ +#define BCMA_DMP_OOBSELOUTA30 0x100 /**< A0-A3 output selectors */ +#define BCMA_DMP_OOBSELOUTA74 0x104 /**< A4-A7 output selectors */ +#define BCMA_DMP_OOBSELOUTB30 0x120 /**< B0-B3 output selectors */ +#define BCMA_DMP_OOBSELOUTB74 0x124 /**< B4-B7 output selectors */ +#define BCMA_DMP_OOBSELOUTC30 0x140 /**< C0-C3 output selectors */ +#define BCMA_DMP_OOBSELOUTC74 0x144 /**< C4-C7 output selectors */ +#define BCMA_DMP_OOBSELOUTD30 0x160 /**< D0-D3 output selectors */ +#define BCMA_DMP_OOBSELOUTD74 0x164 /**< D4-D7 output selectors */ #define BCMA_DMP_OOBSYNCA 0x200 #define BCMA_DMP_OOBSELOUTAEN 0x204 #define BCMA_DMP_OOBSYNCB 0x220 @@ -109,18 +132,20 @@ #define BCMA_DMP_OOBDINWIDTH 0x364 #define BCMA_DMP_OOBDOUTWIDTH 0x368 -/* The exact interpretation of these bits is unverified; these - * are our best guesses as to their use */ -#define BCMA_DMP_OOBSEL_MASK 0xFF /**< OOBSEL config mask */ -#define BCMA_DMP_OOBSEL_0_MASK BCMA_DMP_OOBSEL_MASK -#define BCMA_DMP_OOBSEL_1_MASK BCMA_DMP_OOBSEL_MASK -#define BCMA_DMP_OOBSEL_2_MASK BCMA_DMP_OOBSEL_MASK -#define BCMA_DMP_OOBSEL_3_MASK BCMA_DMP_OOBSEL_MASK -#define BCMA_DMP_OOBSEL_0_SHIFT 0 /**< first OOBSEL config */ -#define BCMA_DMP_OOBSEL_1_SHIFT 8 /**< second OOBSEL config */ -#define BCMA_DMP_OOBSEL_2_SHIFT 16 /**< third OOBSEL config */ -#define BCMA_DMP_OOBSEL_3_SHIFT 24 /**< fouth OOBSEL config */ -#define BCMA_DMP_OOBSEL_EN (1 << 7) /**< enable bit */ +#define BCMA_DMP_OOBSEL(_base, _bank, _sel) \ + (_base + (_bank * 8) + (_sel >= 4 ? 4 : 0)) + +#define BCMA_DMP_OOBSELIN(_bank, _sel) \ + BCMA_DMP_OOBSEL(BCMA_DMP_OOBSELINA30, _bank, _sel) + +#define BCMA_DMP_OOBSELOUT(_bank, _sel) \ + BCMA_DMP_OOBSEL(BCMA_DMP_OOBSELOUTA30, _bank, _sel) + +#define BCMA_DMP_OOBSYNC(_bank) (BCMA_DMP_OOBSYNCA + (_bank * 8)) +#define BCMA_DMP_OOBSELOUT_EN(_bank) (BCMA_DMP_OOBSELOUTAEN + (_bank * 8)) +#define BCMA_DMP_OOB_EXTWIDTH(_bank) (BCMA_DMP_OOBAEXTWIDTH + (_bank * 12)) +#define BCMA_DMP_OOB_INWIDTH(_bank) (BCMA_DMP_OOBAINWIDTH + (_bank * 12)) +#define BCMA_DMP_OOB_OUTWIDTH(_bank) (BCMA_DMP_OOBAOUTWIDTH + (_bank * 12)) // This was inherited from Broadcom's aidmp.h header // Is it required for any of our use-cases? @@ -192,6 +217,34 @@ #define BCMA_DMP_COMPONENTID2 0xff8 #define BCMA_DMP_COMPONENTID3 0xffc + +/* OOBSEL(IN|OUT) */ +#define BCMA_DMP_OOBSEL_MASK 0xFF /**< OOB selector mask */ +#define BCMA_DMP_OOBSEL_EN (1<<7) /**< OOB selector enable bit */ +#define BCMA_DMP_OOBSEL_SHIFT(_sel) ((_sel % BCMA_OOB_NUM_SEL) * 8) +#define BCMA_DMP_OOBSEL_BUSLINE_MASK 0x7F /**< OOB selector bus line mask */ +#define BCMA_DMP_OOBSEL_BUSLINE_SHIFT 0 + +#define BCMA_DMP_OOBSEL_0_MASK BCMA_DMP_OOBSEL_MASK +#define BCMA_DMP_OOBSEL_1_MASK BCMA_DMP_OOBSEL_MASK +#define BCMA_DMP_OOBSEL_2_MASK BCMA_DMP_OOBSEL_MASK +#define BCMA_DMP_OOBSEL_3_MASK BCMA_DMP_OOBSEL_MASK + +#define BCMA_DMP_OOBSEL_4_MASK BCMA_DMP_OOBSEL_MASK +#define BCMA_DMP_OOBSEL_5_MASK BCMA_DMP_OOBSEL_MASK +#define BCMA_DMP_OOBSEL_6_MASK BCMA_DMP_OOBSEL_MASK +#define BCMA_DMP_OOBSEL_7_MASK BCMA_DMP_OOBSEL_MASK + +#define BCMA_DMP_OOBSEL_0_SHIFT BCMA_DMP_OOBSEL_SHIFT(0) +#define BCMA_DMP_OOBSEL_1_SHIFT BCMA_DMP_OOBSEL_SHIFT(1) +#define BCMA_DMP_OOBSEL_2_SHIFT BCMA_DMP_OOBSEL_SHIFT(2) +#define BCMA_DMP_OOBSEL_3_SHIFT BCMA_DMP_OOBSEL_SHIFT(3) + +#define BCMA_DMP_OOBSEL_4_SHIFT BCMA_DMP_OOBSEL_0_SHIFT +#define BCMA_DMP_OOBSEL_5_SHIFT BCMA_DMP_OOBSEL_1_SHIFT +#define BCMA_DMP_OOBSEL_6_SHIFT BCMA_DMP_OOBSEL_2_SHIFT +#define BCMA_DMP_OOBSEL_7_SHIFT BCMA_DMP_OOBSEL_3_SHIFT + /* resetctrl */ #define BMCA_DMP_RC_RESET 1 diff --git a/sys/dev/bhnd/bcma/bcmavar.h b/sys/dev/bhnd/bcma/bcmavar.h index 44806e691f7..8d1c08e5d4f 100644 --- a/sys/dev/bhnd/bcma/bcmavar.h +++ b/sys/dev/bhnd/bcma/bcmavar.h @@ -74,6 +74,9 @@ struct bcma_sport; int bcma_probe(device_t dev); int bcma_attach(device_t dev); int bcma_detach(device_t dev); +int bcma_get_intr_count(device_t dev, device_t child); +int bcma_get_core_ivec(device_t dev, device_t child, + u_int intr, uint32_t *ivec); int bcma_add_children(device_t bus); diff --git a/sys/dev/bhnd/bhnd.c b/sys/dev/bhnd/bhnd.c index c4232a1cbf3..63acead4875 100644 --- a/sys/dev/bhnd/bhnd.c +++ b/sys/dev/bhnd/bhnd.c @@ -925,9 +925,14 @@ bhnd_generic_print_child(device_t dev, device_t child) retval += bus_print_child_header(dev, child); rl = BUS_GET_RESOURCE_LIST(dev, child); + + if (rl != NULL) { retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx"); + + retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, + "%#jd"); } retval += printf(" at core %u", bhnd_get_core_index(child)); @@ -974,8 +979,10 @@ bhnd_generic_probe_nomatch(device_t dev, device_t child) bhnd_get_device_name(child)); rl = BUS_GET_RESOURCE_LIST(dev, child); - if (rl != NULL) + if (rl != NULL) { resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx"); + resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%#jd"); + } printf(" at core %u (no driver attached)\n", bhnd_get_core_index(child)); diff --git a/sys/dev/bhnd/bhnd.h b/sys/dev/bhnd/bhnd.h index cc0e28beb08..ea4d55d19b5 100644 --- a/sys/dev/bhnd/bhnd.h +++ b/sys/dev/bhnd/bhnd.h @@ -549,6 +549,45 @@ bhnd_read_board_info(device_t dev, struct bhnd_board_info *info) return (BHND_BUS_READ_BOARD_INFO(device_get_parent(dev), dev, info)); } +/** + * Return the number of interrupts to be assigned to @p child via + * BHND_BUS_ASSIGN_INTR(). + * + * @param dev A bhnd bus child device. + */ +static inline int +bhnd_get_intr_count(device_t dev) +{ + return (BHND_BUS_GET_INTR_COUNT(device_get_parent(dev), dev)); +} + +/** + * Return the backplane interrupt vector corresponding to @p dev's given + * @p intr number. + * + * @param dev A bhnd bus child device. + * @param intr The interrupt number being queried. This is equivalent to the + * bus resource ID for the interrupt. + * @param[out] ivec On success, the assigned hardware interrupt vector be + * written to this pointer. + * + * On bcma(4) devices, this returns the OOB bus line assigned to the + * interrupt. + * + * On siba(4) devices, this returns the target OCP slave flag number assigned + * to the interrupt. + * + * @retval 0 success + * @retval ENXIO If @p intr exceeds the number of interrupts available + * to @p child. + */ +static inline int +bhnd_get_core_ivec(device_t dev, u_int intr, uint32_t *ivec) +{ + return (BHND_BUS_GET_CORE_IVEC(device_get_parent(dev), dev, intr, + ivec)); +} + /** * Allocate and enable per-core PMU request handling for @p child. * diff --git a/sys/dev/bhnd/bhnd_bus_if.m b/sys/dev/bhnd/bhnd_bus_if.m index 446ed67afc2..b6a75c41531 100644 --- a/sys/dev/bhnd/bhnd_bus_if.m +++ b/sys/dev/bhnd/bhnd_bus_if.m @@ -1,5 +1,5 @@ #- -# Copyright (c) 2015 Landon Fuller +# Copyright (c) 2015-2016 Landon Fuller # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -96,7 +96,26 @@ CODE { { panic("bhnd_bus_read_boardinfo unimplemented"); } - + + static int + bhnd_bus_null_get_intr_count(device_t dev, device_t child) + { + panic("bhnd_bus_get_intr_count unimplemented"); + } + + static int + bhnd_bus_null_assign_intr(device_t dev, device_t child, int rid) + { + panic("bhnd_bus_assign_intr unimplemented"); + } + + static int + bhnd_bus_null_get_core_ivec(device_t dev, device_t child, u_int intr, + uint32_t *ivec) + { + panic("bhnd_bus_get_core_ivec unimplemented"); + } + static void bhnd_bus_null_child_added(device_t dev, device_t child) { @@ -349,6 +368,78 @@ METHOD void free_devinfo { struct bhnd_devinfo *dinfo; }; + +/** + * Return the number of interrupts to be assigned to @p child via + * BHND_BUS_ASSIGN_INTR(). + * + * @param dev The bhnd bus parent of @p child. + * @param child The bhnd device for which a count should be returned. + * + * @retval 0 If no interrupts should be assigned. + * @retval non-zero The count of interrupt resource IDs to be + * assigned, starting at rid 0. + */ +METHOD int get_intr_count { + device_t dev; + device_t child; +} DEFAULT bhnd_bus_null_get_intr_count; + +/** + * Assign an interrupt to @p child via bus_set_resource(). + * + * The default bus implementation of this method should assign backplane + * interrupt values to @p child. + * + * Bridge-attached bus implementations may instead override standard + * interconnect IRQ assignment, providing IRQs inherited from the parent bus. + * + * TODO: Once we can depend on INTRNG, investigate replacing this with a + * bridge-level interrupt controller. + * + * @param dev The bhnd bus parent of @p child. + * @param child The bhnd device to which an interrupt should be assigned. + * @param rid The interrupt resource ID to be assigned. + * + * @retval 0 If an interrupt was assigned. + * @retval non-zero If assigning an interrupt otherwise fails, a regular + * unix error code will be returned. + */ +METHOD int assign_intr { + device_t dev; + device_t child; + int rid; +} DEFAULT bhnd_bus_null_assign_intr; + +/** + * Return the backplane interrupt vector corresponding to @p child's given + * @p intr number. + * + * @param dev The bhnd bus parent of @p child. + * @param child The bhnd device for which the assigned interrupt vector should + * be queried. + * @param intr The interrupt number being queried. This is equivalent to the + * bus resource ID for the interrupt. + * @param[out] ivec On success, the assigned hardware interrupt vector be + * written to this pointer. + * + * On bcma(4) devices, this returns the OOB bus line assigned to the + * interrupt. + * + * On siba(4) devices, this returns the target OCP slave flag number assigned + * to the interrupt. + * + * @retval 0 success + * @retval ENXIO If @p intr exceeds the number of interrupts available + * to @p child. + */ +METHOD int get_core_ivec { + device_t dev; + device_t child; + u_int intr; + uint32_t *ivec; +} DEFAULT bhnd_bus_null_get_core_ivec; + /** * Notify a bhnd bus that a child was added. * diff --git a/sys/dev/bhnd/bhnd_nexus.c b/sys/dev/bhnd/bhnd_nexus.c index 8828aa28e02..dc926a22105 100644 --- a/sys/dev/bhnd/bhnd_nexus.c +++ b/sys/dev/bhnd/bhnd_nexus.c @@ -122,6 +122,13 @@ bhnd_nexus_deactivate_resource(device_t dev, device_t child, return (0); } +static int +bhnd_nexus_get_intr_count(device_t dev, device_t child) +{ + // TODO: arch-specific interrupt handling. + return (0); +} + static device_method_t bhnd_nexus_methods[] = { /* bhnd interface */ DEVMETHOD(bhnd_bus_activate_resource, bhnd_nexus_activate_resource), @@ -129,6 +136,8 @@ static device_method_t bhnd_nexus_methods[] = { DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_nexus_is_hw_disabled), DEVMETHOD(bhnd_bus_get_attach_type, bhnd_nexus_get_attach_type), + DEVMETHOD(bhnd_bus_get_intr_count, bhnd_nexus_get_intr_count), + DEVMETHOD_END }; diff --git a/sys/dev/bhnd/bhndb/bhnd_bhndb.c b/sys/dev/bhnd/bhndb/bhnd_bhndb.c index 8a9f650bd15..12efb04c33a 100644 --- a/sys/dev/bhnd/bhndb/bhnd_bhndb.c +++ b/sys/dev/bhnd/bhndb/bhnd_bhndb.c @@ -93,6 +93,13 @@ bhnd_bhndb_find_hostb_device(device_t dev) return (bhnd_match_child(dev, &md)); } +static int +bhnd_bhndb_assign_intr(device_t dev, device_t child, int rid) +{ + /* Delegate to parent bridge */ + return (BHND_BUS_ASSIGN_INTR(device_get_parent(dev), child, rid)); +} + static bhnd_clksrc bhnd_bhndb_pwrctl_get_clksrc(device_t dev, device_t child, bhnd_clock clock) @@ -126,6 +133,7 @@ static device_method_t bhnd_bhndb_methods[] = { DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_bhndb_is_hw_disabled), DEVMETHOD(bhnd_bus_find_hostb_device, bhnd_bhndb_find_hostb_device), DEVMETHOD(bhnd_bus_read_board_info, bhnd_bhndb_read_board_info), + DEVMETHOD(bhnd_bus_assign_intr, bhnd_bhndb_assign_intr), DEVMETHOD(bhnd_bus_pwrctl_get_clksrc, bhnd_bhndb_pwrctl_get_clksrc), DEVMETHOD(bhnd_bus_pwrctl_gate_clock, bhnd_bhndb_pwrctl_gate_clock), diff --git a/sys/dev/bhnd/bhndb/bhndb.c b/sys/dev/bhnd/bhndb/bhndb.c index 8ce6b839b61..f9d8061a6de 100644 --- a/sys/dev/bhnd/bhndb/bhndb.c +++ b/sys/dev/bhnd/bhndb/bhndb.c @@ -993,7 +993,7 @@ bhndb_suspend_resource(device_t dev, device_t child, int type, sc = device_get_softc(dev); - // TODO: IRQs? + /* Non-MMIO resources (e.g. IRQs) are handled solely by our parent */ if (type != SYS_RES_MEMORY) return; @@ -1024,7 +1024,7 @@ bhndb_resume_resource(device_t dev, device_t child, int type, sc = device_get_softc(dev); - // TODO: IRQs? + /* Non-MMIO resources (e.g. IRQs) are handled solely by our parent */ if (type != SYS_RES_MEMORY) return (0); @@ -1040,7 +1040,6 @@ bhndb_resume_resource(device_t dev, device_t child, int type, rman_get_rid(r), r, NULL)); } - /** * Default bhndb(4) implementation of BUS_READ_IVAR(). */ @@ -1109,8 +1108,6 @@ bhndb_get_rman(struct bhndb_softc *sc, device_t child, int type) case SYS_RES_MEMORY: return (&sc->bus_res->br_mem_rman); case SYS_RES_IRQ: - // TODO - // return &sc->irq_rman; return (NULL); default: return (NULL); @@ -1233,6 +1230,15 @@ bhndb_alloc_resource(device_t dev, device_t child, int type, isdefault = RMAN_IS_DEFAULT_RANGE(start, end); rle = NULL; + /* Fetch the resource manager */ + rm = bhndb_get_rman(sc, child, type); + if (rm == NULL) { + /* Delegate to our parent device's bus; the requested + * resource type isn't handled locally. */ + return (BUS_ALLOC_RESOURCE(device_get_parent(sc->parent_dev), + child, type, rid, start, end, count, flags)); + } + /* Populate defaults */ if (!passthrough && isdefault) { /* Fetch the resource list entry. */ @@ -1263,11 +1269,6 @@ bhndb_alloc_resource(device_t dev, device_t child, int type, /* Validate resource addresses */ if (start > end || count > ((end - start) + 1)) return (NULL); - - /* Fetch the resource manager */ - rm = bhndb_get_rman(sc, child, type); - if (rm == NULL) - return (NULL); /* Make our reservation */ rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE, @@ -1310,12 +1311,21 @@ static int bhndb_release_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { + struct bhndb_softc *sc; struct resource_list_entry *rle; bool passthrough; int error; - + + sc = device_get_softc(dev); passthrough = (device_get_parent(child) != dev); + /* Delegate to our parent device's bus if the requested resource type + * isn't handled locally. */ + if (bhndb_get_rman(sc, child, type) == NULL) { + return (BUS_RELEASE_RESOURCE(device_get_parent(sc->parent_dev), + child, type, rid, r)); + } + /* Deactivate resources */ if (rman_get_flags(r) & RF_ACTIVE) { error = BUS_DEACTIVATE_RESOURCE(dev, child, type, rid, r); @@ -1352,15 +1362,18 @@ bhndb_adjust_resource(device_t dev, device_t child, int type, sc = device_get_softc(dev); error = 0; + /* Delegate to our parent device's bus if the requested resource type + * isn't handled locally. */ + rm = bhndb_get_rman(sc, child, type); + if (rm == NULL) { + return (BUS_ADJUST_RESOURCE(device_get_parent(sc->parent_dev), + child, type, r, start, end)); + } + /* Verify basic constraints */ if (end <= start) return (EINVAL); - /* Fetch resource manager */ - rm = bhndb_get_rman(sc, child, type); - if (rm == NULL) - return (ENXIO); - if (!rman_is_region_manager(r, rm)) return (ENXIO); @@ -1567,7 +1580,7 @@ bhndb_try_activate_resource(struct bhndb_softc *sc, device_t child, int type, BHNDB_LOCK_ASSERT(sc, MA_NOTOWNED); - // TODO - IRQs + /* Only MMIO resources can be mapped via register windows */ if (type != SYS_RES_MEMORY) return (ENXIO); @@ -1678,6 +1691,13 @@ bhndb_activate_resource(device_t dev, device_t child, int type, int rid, { struct bhndb_softc *sc = device_get_softc(dev); + /* Delegate directly to our parent device's bus if the requested + * resource type isn't handled locally. */ + if (bhndb_get_rman(sc, child, type) == NULL) { + return (BUS_ACTIVATE_RESOURCE(device_get_parent(sc->parent_dev), + child, type, rid, r)); + } + return (bhndb_try_activate_resource(sc, child, type, rid, r, NULL)); } @@ -1695,8 +1715,13 @@ bhndb_deactivate_resource(device_t dev, device_t child, int type, sc = device_get_softc(dev); - if ((rm = bhndb_get_rman(sc, child, type)) == NULL) - return (EINVAL); + /* Delegate directly to our parent device's bus if the requested + * resource type isn't handled locally. */ + rm = bhndb_get_rman(sc, child, type); + if (rm == NULL) { + return (BUS_DEACTIVATE_RESOURCE( + device_get_parent(sc->parent_dev), child, type, rid, r)); + } /* Mark inactive */ if ((error = rman_deactivate_resource(r))) @@ -1752,6 +1777,15 @@ bhndb_activate_bhnd_resource(device_t dev, device_t child, sc = device_get_softc(dev); + /* Delegate directly to BUS_ACTIVATE_RESOURCE() if the requested + * resource type isn't handled locally. */ + if (bhndb_get_rman(sc, child, type) == NULL) { + error = BUS_ACTIVATE_RESOURCE(dev, child, type, rid, r->res); + if (error == 0) + r->direct = true; + return (error); + } + r_start = rman_get_start(r->res); r_size = rman_get_size(r->res); @@ -1815,7 +1849,7 @@ bhndb_deactivate_bhnd_resource(device_t dev, device_t child, ("RF_ACTIVE not set on direct resource")); /* Perform deactivation */ - error = bus_deactivate_resource(child, type, rid, r->res); + error = BUS_DEACTIVATE_RESOURCE(dev, child, type, rid, r->res); if (!error) r->direct = false; @@ -2052,61 +2086,6 @@ bhndb_bus_barrier(device_t dev, device_t child, struct bhnd_resource *r, BHNDB_IO_COMMON_TEARDOWN(); } -/** - * Default bhndb(4) implementation of BUS_SETUP_INTR(). - */ -static int -bhndb_setup_intr(device_t dev, device_t child, struct resource *r, - int flags, driver_filter_t filter, driver_intr_t handler, void *arg, - void **cookiep) -{ - // TODO - return (EOPNOTSUPP); -} - -/** - * Default bhndb(4) implementation of BUS_TEARDOWN_INTR(). - */ -static int -bhndb_teardown_intr(device_t dev, device_t child, struct resource *r, - void *cookie) -{ - // TODO - return (EOPNOTSUPP); -} - -/** - * Default bhndb(4) implementation of BUS_CONFIG_INTR(). - */ -static int -bhndb_config_intr(device_t dev, int irq, enum intr_trigger trig, - enum intr_polarity pol) -{ - // TODO - return (EOPNOTSUPP); -} - -/** - * Default bhndb(4) implementation of BUS_BIND_INTR(). - */ -static int -bhndb_bind_intr(device_t dev, device_t child, struct resource *r, int cpu) -{ - // TODO - return (EOPNOTSUPP); -} - -/** - * Default bhndb(4) implementation of BUS_DESCRIBE_INTR(). - */ -static int -bhndb_describe_intr(device_t dev, device_t child, struct resource *irq, void *cookie, - const char *descr) -{ - // TODO - return (EOPNOTSUPP); -} - /** * Default bhndb(4) implementation of BUS_GET_DMA_TAG(). */ @@ -2138,11 +2117,11 @@ static device_method_t bhndb_methods[] = { DEVMETHOD(bus_activate_resource, bhndb_activate_resource), DEVMETHOD(bus_deactivate_resource, bhndb_deactivate_resource), - DEVMETHOD(bus_setup_intr, bhndb_setup_intr), - DEVMETHOD(bus_teardown_intr, bhndb_teardown_intr), - DEVMETHOD(bus_config_intr, bhndb_config_intr), - DEVMETHOD(bus_bind_intr, bhndb_bind_intr), - DEVMETHOD(bus_describe_intr, bhndb_describe_intr), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_config_intr, bus_generic_config_intr), + DEVMETHOD(bus_bind_intr, bus_generic_bind_intr), + DEVMETHOD(bus_describe_intr, bus_generic_describe_intr), DEVMETHOD(bus_get_dma_tag, bhndb_get_dma_tag), diff --git a/sys/dev/bhnd/bhndb/bhndb_pci.c b/sys/dev/bhnd/bhndb/bhndb_pci.c index 47237c8dc5c..60da43b914e 100644 --- a/sys/dev/bhnd/bhndb/bhndb_pci.c +++ b/sys/dev/bhnd/bhndb/bhndb_pci.c @@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$"); #include "bhndb_pcivar.h" #include "bhndb_private.h" +static int bhndb_pci_init_msi(struct bhndb_pci_softc *sc); static int bhndb_pci_add_children(struct bhndb_pci_softc *sc); static int bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc); @@ -78,6 +79,8 @@ static void bhndb_init_sromless_pci_config( static bus_addr_t bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc); static bus_size_t bhndb_pci_sprom_size(struct bhndb_pci_softc *sc); +#define BHNDB_PCI_MSI_COUNT 1 + /** * Default bhndb_pci implementation of device_probe(). * @@ -103,6 +106,33 @@ bhndb_pci_probe(device_t dev) return (BUS_PROBE_DEFAULT); } +/* Configure MSI interrupts */ +static int +bhndb_pci_init_msi(struct bhndb_pci_softc *sc) +{ + int error; + + /* Is MSI available? */ + if (pci_msi_count(sc->parent) < BHNDB_PCI_MSI_COUNT) + return (ENXIO); + + /* Allocate expected message count */ + sc->intr.msi_count = BHNDB_PCI_MSI_COUNT; + if ((error = pci_alloc_msi(sc->parent, &sc->intr.msi_count))) { + device_printf(sc->dev, "failed to allocate MSI interrupts: " + "%d\n", error); + return (error); + } + + if (sc->intr.msi_count < BHNDB_PCI_MSI_COUNT) + return (ENXIO); + + /* MSI uses resource IDs starting at 1 */ + sc->intr.intr_rid = 1; + + return (0); +} + static int bhndb_pci_attach(device_t dev) { @@ -114,6 +144,21 @@ bhndb_pci_attach(device_t dev) sc->parent = device_get_parent(dev); sc->set_regwin = bhndb_pci_compat_setregwin; + /* Enable PCI bus mastering */ + pci_enable_busmaster(sc->parent); + + /* Set up interrupt handling */ + if (bhndb_pci_init_msi(sc) == 0) { + device_printf(dev, "Using MSI interrupts on %s\n", + device_get_nameunit(sc->parent)); + } else { + device_printf(dev, "Using INTx interrupts on %s\n", + device_get_nameunit(sc->parent)); + sc->intr.intr_rid = 0; + } + + /* Determine our bridge device class */ + sc->pci_devclass = BHND_DEVCLASS_PCI; if (pci_find_cap(sc->parent, PCIY_EXPRESS, ®) == 0) sc->pci_devclass = BHND_DEVCLASS_PCIE; else @@ -153,6 +198,9 @@ bhndb_pci_attach(device_t dev) cleanup: device_delete_children(dev); bhndb_disable_pci_clocks(sc); + if (sc->intr.msi_count > 0) + pci_release_msi(dev); + pci_disable_busmaster(sc->parent); return (error); @@ -178,6 +226,10 @@ bhndb_pci_detach(device_t dev) if ((error = bhndb_disable_pci_clocks(sc))) return (error); + /* Release MSI interrupts */ + if (sc->intr.msi_count > 0) + pci_release_msi(dev); + /* Disable PCI bus mastering */ pci_disable_busmaster(sc->parent); @@ -679,6 +731,29 @@ bhndb_pci_pwrctl_ungate_clock(device_t dev, device_t child, return (bhndb_enable_pci_clocks(sc)); } +static int +bhndb_pci_assign_intr(device_t dev, device_t child, int rid) +{ + struct bhndb_pci_softc *sc; + rman_res_t start, count; + int error; + + sc = device_get_softc(dev); + + /* Is the rid valid? */ + if (rid >= bhnd_get_intr_count(child)) + return (EINVAL); + + /* Fetch our common PCI interrupt's start/count. */ + error = bus_get_resource(sc->parent, SYS_RES_IRQ, sc->intr.intr_rid, + &start, &count); + if (error) + return (error); + + /* Add to child's resource list */ + return (bus_set_resource(child, SYS_RES_IRQ, rid, start, count)); +} + static device_method_t bhndb_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, bhndb_pci_probe), @@ -688,6 +763,8 @@ static device_method_t bhndb_pci_methods[] = { DEVMETHOD(device_detach, bhndb_pci_detach), /* BHND interface */ + DEVMETHOD(bhnd_bus_assign_intr, bhndb_pci_assign_intr), + DEVMETHOD(bhnd_bus_pwrctl_get_clksrc, bhndb_pci_pwrctl_get_clksrc), DEVMETHOD(bhnd_bus_pwrctl_gate_clock, bhndb_pci_pwrctl_gate_clock), DEVMETHOD(bhnd_bus_pwrctl_ungate_clock, bhndb_pci_pwrctl_ungate_clock), diff --git a/sys/dev/bhnd/bhndb/bhndb_pcivar.h b/sys/dev/bhnd/bhndb/bhndb_pcivar.h index 7d7fcade881..344812ea050 100644 --- a/sys/dev/bhnd/bhndb/bhndb_pcivar.h +++ b/sys/dev/bhnd/bhndb/bhndb_pcivar.h @@ -48,11 +48,19 @@ struct bhndb_pci_softc; typedef int (*bhndb_pci_set_regwin_t)(struct bhndb_pci_softc *sc, const struct bhndb_regwin *rw, bhnd_addr_t addr); +/* bhndb_pci interrupt state */ +struct bhndb_pci_intr { + int msi_count; /**< MSI count, or 0 */ + int intr_rid; /**< interrupt resource ID.*/ +}; + struct bhndb_pci_softc { struct bhndb_softc bhndb; /**< parent softc */ device_t dev; /**< bridge device */ device_t parent; /**< parent PCI device */ bhnd_devclass_t pci_devclass; /**< PCI core's devclass */ + struct bhndb_pci_intr intr; /**< PCI interrupt config */ + bhndb_pci_set_regwin_t set_regwin; /**< regwin handler */ }; diff --git a/sys/dev/bhnd/cores/pmu/bhnd_pmu_subr.c b/sys/dev/bhnd/cores/pmu/bhnd_pmu_subr.c index db84bdc093e..bd10febff27 100644 --- a/sys/dev/bhnd/cores/pmu/bhnd_pmu_subr.c +++ b/sys/dev/bhnd/cores/pmu/bhnd_pmu_subr.c @@ -3395,14 +3395,14 @@ bhnd_pmu_radio_enable(struct bhnd_pmu_softc *sc, device_t d11core, bool enable) if (enable) { oobsel |= BHND_PMU_SET_BITS(BCMA_DMP_OOBSEL_EN, - BCMA_DMP_OOBSEL_1); + BCMA_DMP_OOBSEL_5); oobsel |= BHND_PMU_SET_BITS(BCMA_DMP_OOBSEL_EN, - BCMA_DMP_OOBSEL_2); + BCMA_DMP_OOBSEL_6); } else { oobsel &= ~BHND_PMU_SET_BITS(BCMA_DMP_OOBSEL_EN, - BCMA_DMP_OOBSEL_1); + BCMA_DMP_OOBSEL_5); oobsel &= ~BHND_PMU_SET_BITS(BCMA_DMP_OOBSEL_EN, - BCMA_DMP_OOBSEL_2); + BCMA_DMP_OOBSEL_6); } bhnd_write_config(d11core, BCMA_DMP_OOBSELOUTB74, oobsel, 4); diff --git a/sys/dev/bhnd/siba/siba.c b/sys/dev/bhnd/siba/siba.c index 552c1571209..678940ba872 100644 --- a/sys/dev/bhnd/siba/siba.c +++ b/sys/dev/bhnd/siba/siba.c @@ -373,6 +373,60 @@ siba_get_region_addr(device_t dev, device_t child, bhnd_port_type port_type, return (0); } +/** + * Default siba(4) bus driver implementation of BHND_BUS_GET_INTR_COUNT(). + * + * This implementation consults @p child's configuration block mapping, + * returning SIBA_CORE_NUM_INTR if a valid CFG0 block is mapped. + */ +int +siba_get_intr_count(device_t dev, device_t child) +{ + struct siba_devinfo *dinfo; + + /* delegate non-bus-attached devices to our parent */ + if (device_get_parent(child) != dev) + return (BHND_BUS_GET_INTR_COUNT(device_get_parent(dev), child)); + + dinfo = device_get_ivars(child); + + /* We can get/set interrupt sbflags on any core with a valid cfg0 + * block; whether the core actually makes use of it is another matter + * entirely */ + if (dinfo->cfg[0] == NULL) + return (0); + + return (SIBA_CORE_NUM_INTR); +} + +/** + * Default siba(4) bus driver implementation of BHND_BUS_GET_CORE_IVEC(). + * + * This implementation consults @p child's CFG0 register block, + * returning the interrupt flag assigned to @p child. + */ +int +siba_get_core_ivec(device_t dev, device_t child, u_int intr, uint32_t *ivec) +{ + struct siba_devinfo *dinfo; + uint32_t tpsflag; + + /* delegate non-bus-attached devices to our parent */ + if (device_get_parent(child) != dev) + return (BHND_BUS_GET_CORE_IVEC(device_get_parent(dev), child, + intr, ivec)); + + /* Must be a valid interrupt ID */ + if (intr >= siba_get_intr_count(dev, child)) + return (ENXIO); + + /* Fetch sbflag number */ + dinfo = device_get_ivars(child); + tpsflag = bhnd_bus_read_4(dinfo->cfg[0], SIBA_CFG0_TPSFLAG); + *ivec = SIBA_REG_GET(tpsflag, TPS_NUM0); + + return (0); +} /** * Register all address space mappings for @p di. @@ -538,6 +592,7 @@ siba_add_children(device_t dev) device_t child; uint32_t idhigh, idlow; rman_res_t r_count, r_end, r_start; + int nintr; /* Map the core's register block */ rid = 0; @@ -594,6 +649,16 @@ siba_add_children(device_t dev) if ((error = siba_map_cfg_resources(dev, dinfo))) goto cleanup; + /* Assign interrupts */ + nintr = bhnd_get_intr_count(child); + for (int rid = 0; rid < nintr; rid++) { + error = BHND_BUS_ASSIGN_INTR(dev, child, rid); + if (error) { + device_printf(dev, "failed to assign interrupt " + "%d to core %u: %d\n", rid, i, error); + } + } + /* If pins are floating or the hardware is otherwise * unpopulated, the device shouldn't be used. */ if (bhnd_is_hw_disabled(child)) @@ -639,6 +704,8 @@ static device_method_t siba_methods[] = { DEVMETHOD(bhnd_bus_get_port_rid, siba_get_port_rid), DEVMETHOD(bhnd_bus_decode_port_rid, siba_decode_port_rid), DEVMETHOD(bhnd_bus_get_region_addr, siba_get_region_addr), + DEVMETHOD(bhnd_bus_get_intr_count, siba_get_intr_count), + DEVMETHOD(bhnd_bus_get_core_ivec, siba_get_core_ivec), DEVMETHOD_END }; diff --git a/sys/dev/bhnd/siba/siba_bhndb.c b/sys/dev/bhnd/siba/siba_bhndb.c index 3f3eb2164b6..cfc1180ad93 100644 --- a/sys/dev/bhnd/siba/siba_bhndb.c +++ b/sys/dev/bhnd/siba/siba_bhndb.c @@ -273,7 +273,6 @@ siba_bhndb_wars_hwup(struct siba_softc *sc) return (0); } - static device_method_t siba_bhndb_methods[] = { /* Device interface */ DEVMETHOD(device_probe, siba_bhndb_probe), diff --git a/sys/dev/bhnd/siba/sibareg.h b/sys/dev/bhnd/siba/sibareg.h index f1b8ae06286..63a6d5bf28c 100644 --- a/sys/dev/bhnd/siba/sibareg.h +++ b/sys/dev/bhnd/siba/sibareg.h @@ -48,6 +48,7 @@ #define SIBA_ENUM_ADDR BHND_DEFAULT_CHIPC_ADDR /**< enumeration space */ #define SIBA_ENUM_SIZE 0x00100000 /**< size of the enumeration space */ #define SIBA_CORE_SIZE BHND_DEFAULT_CORE_SIZE /**< per-core register block size */ +#define SIBA_CORE_NUM_INTR 1 /**< number of per-core interrupt lines */ #define SIBA_MAX_CORES \ (SIBA_ENUM_SIZE/SIBA_CORE_SIZE) /**< Maximum number of cores */ @@ -119,6 +120,7 @@ /* sbtpsflag */ #define SIBA_TPS_NUM0_MASK 0x3f /* interrupt sbFlag # generated by this core */ +#define SIBA_TPS_NUM0_SHIFT 0 #define SIBA_TPS_F0EN0 0x40 /* interrupt is always sent on the backplane */ /* sbtmerrlog */ diff --git a/sys/dev/bhnd/siba/sibavar.h b/sys/dev/bhnd/siba/sibavar.h index 0b2e5bba211..fc2f26f5684 100644 --- a/sys/dev/bhnd/siba/sibavar.h +++ b/sys/dev/bhnd/siba/sibavar.h @@ -54,6 +54,9 @@ int siba_attach(device_t dev); int siba_detach(device_t dev); int siba_resume(device_t dev); int siba_suspend(device_t dev); +int siba_get_intr_count(device_t dev, device_t child); +int siba_get_core_ivec(device_t dev, device_t child, + u_int intr, uint32_t *ivec); uint16_t siba_get_bhnd_mfgid(uint16_t ocp_vendor); diff --git a/sys/dev/bwn/bwn_mac.c b/sys/dev/bwn/bwn_mac.c index 69ff1e54da3..f6c7575d9f7 100644 --- a/sys/dev/bwn/bwn_mac.c +++ b/sys/dev/bwn/bwn_mac.c @@ -47,16 +47,12 @@ __FBSDID("$FreeBSD$"); #include "bhnd_nvram_map.h" -static const struct resource_spec bwn_rspec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { -1, -1, 0 } -}; - -#define RSPEC_LEN (sizeof(bwn_rspec)/sizeof(bwn_rspec[0])) - struct bwn_softc { - struct resource_spec rspec[RSPEC_LEN]; - struct bhnd_resource *res[RSPEC_LEN-1]; + int mem_rid; + struct bhnd_resource *mem_res; + + int intr_rid; + struct resource *intr_res; }; static const struct bwn_device { @@ -89,28 +85,50 @@ static int bwn_attach(device_t dev) { struct bwn_softc *sc; - struct bhnd_resource *r; int error; sc = device_get_softc(dev); - memcpy(sc->rspec, bwn_rspec, sizeof(bwn_rspec)); - if ((error = bhnd_alloc_resources(dev, sc->rspec, sc->res))) - return (error); + /* Allocate device resources */ + sc->mem_rid = 0; + sc->mem_res = bhnd_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->mem_rid, RF_ACTIVE); + if (sc->mem_res == NULL) { + device_printf(dev, "failed to allocate device registers\n"); + error = ENXIO; + goto cleanup; + } - // XXX TODO - r = sc->res[0]; - device_printf(dev, "got rid=%d res=%p\n", sc->rspec[0].rid, r); + sc->intr_rid = 0; + sc->intr_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->intr_rid, + RF_ACTIVE|RF_SHAREABLE); + if (sc->intr_res == NULL) { + device_printf(dev, "failed to allocate device interrupt\n"); + error = ENXIO; + goto cleanup; + } + // TODO uint8_t macaddr[6]; error = bhnd_nvram_getvar_array(dev, BHND_NVAR_MACADDR, macaddr, sizeof(macaddr), BHND_NVRAM_TYPE_UINT8); if (error) - return (error); + device_printf(dev, "error fetching macaddr: %d\n", error); + else + device_printf(dev, "got macaddr %6D\n", macaddr, ":"); - device_printf(dev, "got macaddr %6D\n", macaddr, ":"); - return (0); + +cleanup: + if (sc->mem_res != NULL) + bhnd_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, + sc->mem_res); + + if (sc->intr_res != NULL) + bus_release_resource(dev, SYS_RES_IRQ, sc->intr_rid, + sc->intr_res); + + return (error); } static int @@ -119,7 +137,9 @@ bwn_detach(device_t dev) struct bwn_softc *sc; sc = device_get_softc(dev); - bhnd_release_resources(dev, sc->rspec, sc->res); + + bhnd_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem_res); + bus_release_resource(dev, SYS_RES_IRQ, sc->intr_rid, sc->intr_res); return (0); } From 48214203c49caa7d7853f22abcfb5c173a601a8a Mon Sep 17 00:00:00 2001 From: Navdeep Parhar Date: Mon, 5 Sep 2016 23:12:24 +0000 Subject: [PATCH 008/109] Fix send/recv limit mixup. --- sys/dev/iscsi/iscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/iscsi/iscsi.c b/sys/dev/iscsi/iscsi.c index 57b60bb8423..45b6d300f10 100644 --- a/sys/dev/iscsi/iscsi.c +++ b/sys/dev/iscsi/iscsi.c @@ -1366,7 +1366,7 @@ iscsi_ioctl_daemon_wait(struct iscsi_softc *sc, request->idr_limits.isl_max_recv_data_segment_length = idl.idl_max_recv_data_segment_length; request->idr_limits.isl_max_send_data_segment_length = - idl.idl_max_recv_data_segment_length; + idl.idl_max_send_data_segment_length; request->idr_limits.isl_max_burst_length = idl.idl_max_burst_length; request->idr_limits.isl_first_burst_length = From b8cc28b78238d8599090b47dbae059963c1f027b Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Tue, 6 Sep 2016 00:51:25 +0000 Subject: [PATCH 009/109] Install h_db to unbreak some of the lib/libc/db testcases after r305358 MFC after: 59 days X-MFC with: r305358 Reported by: Jenkins, rodrigc Sponsored by: EMC / Isilon Storage Division --- lib/libc/tests/db/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libc/tests/db/Makefile b/lib/libc/tests/db/Makefile index b8671adf68f..e9c76d26679 100644 --- a/lib/libc/tests/db/Makefile +++ b/lib/libc/tests/db/Makefile @@ -5,7 +5,7 @@ PACKAGE= tests BINDIR= ${TESTSDIR} PROGS= h_db -PROGS= h_lfsr +PROGS+= h_lfsr ${PACKAGE}FILES+= README From 7be8de4271d5cb5d441e2757912c1824f6c3dc3b Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Tue, 6 Sep 2016 01:07:12 +0000 Subject: [PATCH 010/109] Fix lib/libc/rpc test assumptions added in r305358 - Require root in the tcp/udp subtests (it's needed on FreeBSD when registering services). - Skip the tests if service registration fails. MFC after: 59 days X-MFC with: r305358 Reported by: Jenkins, rodrigc Sponsored by: EMC / Isilon Storage Division --- contrib/netbsd-tests/lib/libc/rpc/t_rpc.c | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/contrib/netbsd-tests/lib/libc/rpc/t_rpc.c b/contrib/netbsd-tests/lib/libc/rpc/t_rpc.c index 72bda8d4fb8..28a8763fcaa 100644 --- a/contrib/netbsd-tests/lib/libc/rpc/t_rpc.c +++ b/contrib/netbsd-tests/lib/libc/rpc/t_rpc.c @@ -24,6 +24,13 @@ __RCSID("$NetBSD: t_rpc.c,v 1.9 2015/11/27 13:59:40 christos Exp $"); return; \ } while(/*CONSTCOND*/0) +#ifdef __FreeBSD__ +#define SKIPXI(ev, msg, ...) do { \ + atf_tc_skip(msg, __VA_ARGS__); \ + return ev; \ +} while(/*CONSTCOND*/0) +#endif + #else #define ERRX(ev, msg, ...) errx(ev, msg, __VA_ARGS__) #define SKIPX(ev, msg, ...) errx(ev, msg, __VA_ARGS__) @@ -188,7 +195,13 @@ regtest(const char *hostname, const char *transp, const char *arg, int p) svc_fdset_init(p ? SVC_FDSET_POLL : 0); #endif if (!svc_create(server, PROGNUM, VERSNUM, transp)) +#ifdef __NetBSD__ ERRX(EXIT_FAILURE, "Cannot create server %d", num); +#else + { + SKIPXI(EXIT_FAILURE, "Cannot create server %d", num); + } +#endif switch ((pid = fork())) { case 0: @@ -335,6 +348,9 @@ ATF_TC(tcp); ATF_TC_HEAD(tcp, tc) { atf_tc_set_md_var(tc, "descr", "Checks svc tcp (select)"); +#ifdef __FreeBSD__ + atf_tc_set_md_var(tc, "require.user", "root"); +#endif } ATF_TC_BODY(tcp, tc) @@ -347,6 +363,9 @@ ATF_TC(udp); ATF_TC_HEAD(udp, tc) { atf_tc_set_md_var(tc, "descr", "Checks svc udp (select)"); +#ifdef __FreeBSD__ + atf_tc_set_md_var(tc, "require.user", "root"); +#endif } ATF_TC_BODY(udp, tc) @@ -359,6 +378,9 @@ ATF_TC(tcp_poll); ATF_TC_HEAD(tcp_poll, tc) { atf_tc_set_md_var(tc, "descr", "Checks svc tcp (poll)"); +#ifdef __FreeBSD__ + atf_tc_set_md_var(tc, "require.user", "root"); +#endif } ATF_TC_BODY(tcp_poll, tc) @@ -371,6 +393,9 @@ ATF_TC(udp_poll); ATF_TC_HEAD(udp_poll, tc) { atf_tc_set_md_var(tc, "descr", "Checks svc udp (poll)"); +#ifdef __FreeBSD__ + atf_tc_set_md_var(tc, "require.user", "root"); +#endif } ATF_TC_BODY(udp_poll, tc) From b3493578195208152dfbeaa5f41cc0648aa2f17d Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Tue, 6 Sep 2016 03:20:06 +0000 Subject: [PATCH 011/109] hyperv/hn: Stringent RNDIS packet message length/offset check. While I'm here, use definition in net/rndis.h MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7782 --- sys/dev/hyperv/netvsc/hv_rndis_filter.c | 215 +++++++++++++++++++----- sys/net/rndis.h | 14 +- 2 files changed, 181 insertions(+), 48 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.c b/sys/dev/hyperv/netvsc/hv_rndis_filter.c index 10e574b40d0..efa8638457b 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.c +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.c @@ -159,39 +159,22 @@ hv_rf_receive_indicate_status(struct hn_softc *sc, const void *data, int dlen) } static int -hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hn_recvinfo *info) +hn_rndis_rxinfo(const void *info_data, int info_dlen, struct hn_recvinfo *info) { - const struct rndis_pktinfo *pi; - uint32_t mask = 0, len; + const struct rndis_pktinfo *pi = info_data; + uint32_t mask = 0; - info->vlan_info = HN_NDIS_VLAN_INFO_INVALID; - info->csum_info = HN_NDIS_RXCSUM_INFO_INVALID; - info->hash_info = HN_NDIS_HASH_INFO_INVALID; - - if (rpkt->per_pkt_info_offset == 0) - return (0); - if (__predict_false(rpkt->per_pkt_info_offset & - (RNDIS_PKTINFO_ALIGN - 1))) - return (EINVAL); - if (__predict_false(rpkt->per_pkt_info_offset < - RNDIS_PACKET_MSG_OFFSET_MIN)) - return (EINVAL); - - pi = (const struct rndis_pktinfo *) - ((const uint8_t *)rpkt + rpkt->per_pkt_info_offset); - len = rpkt->per_pkt_info_length; - - while (len != 0) { + while (info_dlen != 0) { const void *data; uint32_t dlen; - if (__predict_false(len < sizeof(*pi))) + if (__predict_false(info_dlen < sizeof(*pi))) return (EINVAL); - if (__predict_false(len < pi->rm_size)) + if (__predict_false(info_dlen < pi->rm_size)) return (EINVAL); - len -= pi->rm_size; + info_dlen -= pi->rm_size; - if (__predict_false(pi->rm_size & (RNDIS_PKTINFO_ALIGN - 1))) + if (__predict_false(pi->rm_size & RNDIS_PKTINFO_SIZE_ALIGNMASK)) return (EINVAL); if (__predict_false(pi->rm_size < pi->rm_pktinfooffset)) return (EINVAL); @@ -249,43 +232,183 @@ next: return (0); } +static __inline bool +hn_rndis_check_overlap(int off, int len, int check_off, int check_len) +{ + + if (off < check_off) { + if (__predict_true(off + len <= check_off)) + return (false); + } else if (off > check_off) { + if (__predict_true(check_off + check_len <= off)) + return (false); + } + return (true); +} + /* * RNDIS filter receive data */ static void hv_rf_receive_data(struct hn_rx_ring *rxr, const void *data, int dlen) { - const rndis_msg *message = data; - const rndis_packet *rndis_pkt; - uint32_t data_offset; + const struct rndis_packet_msg *pkt; struct hn_recvinfo info; - - rndis_pkt = &message->msg.packet; + int data_off, pktinfo_off, data_len, pktinfo_len; /* - * Fixme: Handle multiple rndis pkt msgs that may be enclosed in this - * netvsc packet (ie tot_data_buf_len != message_length) + * Check length. */ + if (__predict_false(dlen < sizeof(*pkt))) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg\n"); + return; + } + pkt = data; - /* Remove rndis header, then pass data packet up the stack */ - data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset; - - dlen -= data_offset; - if (dlen < rndis_pkt->data_length) { - if_printf(rxr->hn_ifp, - "total length %u is less than data length %u\n", - dlen, rndis_pkt->data_length); + if (__predict_false(dlen < pkt->rm_len)) { + if_printf(rxr->hn_ifp, "truncated RNDIS packet msg, " + "dlen %d, msglen %u\n", dlen, pkt->rm_len); + return; + } + if (__predict_false(pkt->rm_len < + pkt->rm_datalen + pkt->rm_oobdatalen + pkt->rm_pktinfolen)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msglen, " + "msglen %u, data %u, oob %u, pktinfo %u\n", + pkt->rm_len, pkt->rm_datalen, pkt->rm_oobdatalen, + pkt->rm_pktinfolen); + return; + } + if (__predict_false(pkt->rm_datalen == 0)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, no data\n"); return; } - dlen = rndis_pkt->data_length; - data = (const uint8_t *)data + data_offset; + /* + * Check offests. + */ +#define IS_OFFSET_INVALID(ofs) \ + ((ofs) < RNDIS_PACKET_MSG_OFFSET_MIN || \ + ((ofs) & RNDIS_PACKET_MSG_OFFSET_ALIGNMASK)) - if (hv_rf_find_recvinfo(rndis_pkt, &info)) { - if_printf(rxr->hn_ifp, "recvinfo parsing failed\n"); + /* XXX Hyper-V does not meet data offset alignment requirement */ + if (__predict_false(pkt->rm_dataoffset < RNDIS_PACKET_MSG_OFFSET_MIN)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "data offset %u\n", pkt->rm_dataoffset); return; } - netvsc_recv(rxr, data, dlen, &info); + if (__predict_false(pkt->rm_oobdataoffset > 0 && + IS_OFFSET_INVALID(pkt->rm_oobdataoffset))) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "oob offset %u\n", pkt->rm_oobdataoffset); + return; + } + if (__predict_true(pkt->rm_pktinfooffset > 0) && + __predict_false(IS_OFFSET_INVALID(pkt->rm_pktinfooffset))) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "pktinfo offset %u\n", pkt->rm_pktinfooffset); + return; + } + +#undef IS_OFFSET_INVALID + + data_off = RNDIS_PACKET_MSG_OFFSET_ABS(pkt->rm_dataoffset); + data_len = pkt->rm_datalen; + pktinfo_off = RNDIS_PACKET_MSG_OFFSET_ABS(pkt->rm_pktinfooffset); + pktinfo_len = pkt->rm_pktinfolen; + + /* + * Check OOB coverage. + */ + if (__predict_false(pkt->rm_oobdatalen != 0)) { + int oob_off, oob_len; + + if_printf(rxr->hn_ifp, "got oobdata\n"); + oob_off = RNDIS_PACKET_MSG_OFFSET_ABS(pkt->rm_oobdataoffset); + oob_len = pkt->rm_oobdatalen; + + if (__predict_false(oob_off + oob_len > pkt->rm_len)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "oob overflow, msglen %u, oob abs %d len %d\n", + pkt->rm_len, oob_off, oob_len); + return; + } + + /* + * Check against data. + */ + if (hn_rndis_check_overlap(oob_off, oob_len, + data_off, data_len)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "oob overlaps data, oob abs %d len %d, " + "data abs %d len %d\n", + oob_off, oob_len, data_off, data_len); + return; + } + + /* + * Check against pktinfo. + */ + if (pktinfo_len != 0 && + hn_rndis_check_overlap(oob_off, oob_len, + pktinfo_off, pktinfo_len)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "oob overlaps pktinfo, oob abs %d len %d, " + "pktinfo abs %d len %d\n", + oob_off, oob_len, pktinfo_off, pktinfo_len); + return; + } + } + + /* + * Check per-packet-info coverage and find useful per-packet-info. + */ + info.vlan_info = HN_NDIS_VLAN_INFO_INVALID; + info.csum_info = HN_NDIS_RXCSUM_INFO_INVALID; + info.hash_info = HN_NDIS_HASH_INFO_INVALID; + if (__predict_true(pktinfo_len != 0)) { + bool overlap; + int error; + + if (__predict_false(pktinfo_off + pktinfo_len > pkt->rm_len)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "pktinfo overflow, msglen %u, " + "pktinfo abs %d len %d\n", + pkt->rm_len, pktinfo_off, pktinfo_len); + return; + } + + /* + * Check packet info coverage. + */ + overlap = hn_rndis_check_overlap(pktinfo_off, pktinfo_len, + data_off, data_len); + if (__predict_false(overlap)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "pktinfo overlap data, pktinfo abs %d len %d, " + "data abs %d len %d\n", + pktinfo_off, pktinfo_len, data_off, data_len); + return; + } + + /* + * Find useful per-packet-info. + */ + error = hn_rndis_rxinfo(((const uint8_t *)pkt) + pktinfo_off, + pktinfo_len, &info); + if (__predict_false(error)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg " + "pktinfo\n"); + return; + } + } + + if (__predict_false(data_off + data_len > pkt->rm_len)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "data overflow, msglen %u, data abs %d len %d\n", + pkt->rm_len, data_off, data_len); + return; + } + netvsc_recv(rxr, ((const uint8_t *)pkt) + data_off, data_len, &info); } /* @@ -565,7 +688,7 @@ hn_rndis_query(struct hn_softc *sc, uint32_t oid, * Check output data length and offset. */ /* ofs is the offset from the beginning of comp. */ - ofs = RNDIS_QUERY_COMP_INFOBUFABS(comp->rm_infobufoffset); + ofs = RNDIS_QUERY_COMP_INFOBUFOFFSET_ABS(comp->rm_infobufoffset); if (ofs < sizeof(*comp) || ofs + comp->rm_infobuflen > comp_len) { if_printf(sc->hn_ifp, "RNDIS query invalid comp ib off/len, " "%u/%u\n", comp->rm_infobufoffset, comp->rm_infobuflen); diff --git a/sys/net/rndis.h b/sys/net/rndis.h index fd0f2259573..2cd1a0d7158 100644 --- a/sys/net/rndis.h +++ b/sys/net/rndis.h @@ -127,6 +127,14 @@ struct rndis_packet_msg { (sizeof(struct rndis_packet_msg) - \ __offsetof(struct rndis_packet_msg, rm_dataoffset)) +/* Offset from the beginning of rndis_packet_msg. */ +#define RNDIS_PACKET_MSG_OFFSET_ABS(ofs) \ + ((ofs) + __offsetof(struct rndis_packet_msg, rm_dataoffset)) + +#define RNDIS_PACKET_MSG_OFFSET_ALIGN 4 +#define RNDIS_PACKET_MSG_OFFSET_ALIGNMASK \ + (RNDIS_PACKET_MSG_OFFSET_ALIGN - 1) + /* Per-packet-info for RNDIS data message */ struct rndis_pktinfo { uint32_t rm_size; @@ -137,7 +145,8 @@ struct rndis_pktinfo { #define RNDIS_PKTINFO_OFFSET \ __offsetof(struct rndis_pktinfo, rm_data[0]) -#define RNDIS_PKTINFO_ALIGN 4 +#define RNDIS_PKTINFO_SIZE_ALIGN 4 +#define RNDIS_PKTINFO_SIZE_ALIGNMASK (RNDIS_PKTINFO_SIZE_ALIGN - 1) #define NDIS_PKTINFO_TYPE_CSUM 0 #define NDIS_PKTINFO_TYPE_IPSEC 1 @@ -236,7 +245,8 @@ struct rndis_query_comp { uint32_t rm_infobufoffset; }; -#define RNDIS_QUERY_COMP_INFOBUFABS(ofs) \ +/* infobuf offset from the beginning of rndis_query_comp. */ +#define RNDIS_QUERY_COMP_INFOBUFOFFSET_ABS(ofs) \ ((ofs) + __offsetof(struct rndis_query_req, rm_rid)) /* Send a set object request. */ From 14ee29ba93f66026bfc9d8b81690dedb594ee229 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Tue, 6 Sep 2016 03:31:31 +0000 Subject: [PATCH 012/109] hyperv/hn: Fix VLAN tag setup for outgoing VLAN packets. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7785 --- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 6 ++++-- sys/dev/hyperv/netvsc/ndis.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index 76740eff9cd..9b33dc49fea 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -903,8 +903,10 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) rppi_vlan_info = (ndis_8021q_info *)((uint8_t *)rppi + rppi->per_packet_info_offset); - rppi_vlan_info->u1.s1.vlan_id = - m_head->m_pkthdr.ether_vtag & 0xfff; + rppi_vlan_info->u1.value = NDIS_VLAN_INFO_MAKE( + EVL_VLANOFTAG(m_head->m_pkthdr.ether_vtag), + EVL_PRIOFTAG(m_head->m_pkthdr.ether_vtag), + EVL_CFIOFTAG(m_head->m_pkthdr.ether_vtag)); } if (m_head->m_pkthdr.csum_flags & CSUM_TSO) { diff --git a/sys/dev/hyperv/netvsc/ndis.h b/sys/dev/hyperv/netvsc/ndis.h index 9e65b4f5a6a..c5c73c796ed 100644 --- a/sys/dev/hyperv/netvsc/ndis.h +++ b/sys/dev/hyperv/netvsc/ndis.h @@ -213,7 +213,7 @@ struct ndis_rssprm_toeplitz { #define NDIS_VLAN_INFO_CFI_MASK 0x0008 #define NDIS_VLAN_INFO_ID_MASK 0xfff0 #define NDIS_VLAN_INFO_MAKE(id, pri, cfi) \ - (((pri) & NVIS_VLAN_INFO_PRI_MASK) | \ + (((pri) & NDIS_VLAN_INFO_PRI_MASK) | \ (((cfi) & 0x1) << 3) | (((id) & 0xfff) << 4)) #define NDIS_VLAN_INFO_ID(inf) (((inf) & NDIS_VLAN_INFO_ID_MASK) >> 4) #define NDIS_VLAN_INFO_CFI(inf) (((inf) & NDIS_VLAN_INFO_CFI_MASK) >> 3) From 50002d3dfa767941fe24b3ad7e86bc10de4f8a35 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Tue, 6 Sep 2016 04:37:53 +0000 Subject: [PATCH 013/109] hyperv/hn: Avoid bit fields for LSOv2 setup. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7786 --- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 15 ++++++--------- sys/dev/hyperv/netvsc/ndis.h | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index 9b33dc49fea..c923d23b1f0 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -910,6 +910,7 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) } if (m_head->m_pkthdr.csum_flags & CSUM_TSO) { +#if defined(INET6) || defined(INET) rndis_tcp_tso_info *tso_info; struct ether_vlan_header *eh; int ether_len; @@ -929,8 +930,6 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) tso_info = (rndis_tcp_tso_info *)((uint8_t *)rppi + rppi->per_packet_info_offset); - tso_info->lso_v2_xmit.type = - RNDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE; #ifdef INET if (m_head->m_pkthdr.csum_flags & CSUM_IP_TSO) { @@ -940,13 +939,12 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) struct tcphdr *th = (struct tcphdr *)((caddr_t)ip + iph_len); - tso_info->lso_v2_xmit.ip_version = - RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV4; ip->ip_len = 0; ip->ip_sum = 0; - th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, htons(IPPROTO_TCP)); + tso_info->value = NDIS_LSO2_INFO_MAKEIPV4(0, + m_head->m_pkthdr.tso_segsz); } #endif #if defined(INET6) && defined(INET) @@ -958,14 +956,13 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) (m_head->m_data + ether_len); struct tcphdr *th = (struct tcphdr *)(ip6 + 1); - tso_info->lso_v2_xmit.ip_version = - RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV6; ip6->ip6_plen = 0; th->th_sum = in6_cksum_pseudo(ip6, 0, IPPROTO_TCP, 0); + tso_info->value = NDIS_LSO2_INFO_MAKEIPV6(0, + m_head->m_pkthdr.tso_segsz); } #endif - tso_info->lso_v2_xmit.tcp_header_offset = 0; - tso_info->lso_v2_xmit.mss = m_head->m_pkthdr.tso_segsz; +#endif /* INET6 || INET */ } else if (m_head->m_pkthdr.csum_flags & txr->hn_csum_assist) { rndis_tcp_ip_csum_info *csum_info; diff --git a/sys/dev/hyperv/netvsc/ndis.h b/sys/dev/hyperv/netvsc/ndis.h index c5c73c796ed..327402803ff 100644 --- a/sys/dev/hyperv/netvsc/ndis.h +++ b/sys/dev/hyperv/netvsc/ndis.h @@ -231,4 +231,21 @@ struct ndis_rssprm_toeplitz { #define NDIS_RXCSUM_INFO_TCPCS_INVAL 0x0080 #define NDIS_RXCSUM_INFO_IPCS_INVAL 0x0100 +/* LSOv2 */ +#define NDIS_LSO2_INFO_MSS_MASK 0x000fffff +#define NDIS_LSO2_INFO_THOFF_MASK 0x3ff00000 +#define NDIS_LSO2_INFO_ISLSO2 0x40000000 +#define NDIS_LSO2_INFO_ISIPV6 0x80000000 + +#define NDIS_LSO2_INFO_MAKE(thoff, mss) \ + ((((uint32_t)(mss)) & NDIS_LSO2_INFO_MSS_MASK) | \ + ((((uint32_t)(thoff)) & 0x3ff) << 20) | \ + NDIS_LSO2_INFO_ISLSO2) + +#define NDIS_LSO2_INFO_MAKEIPV4(thoff, mss) \ + NDIS_LSO2_INFO_MAKE((thoff), (mss)) + +#define NDIS_LSO2_INFO_MAKEIPV6(thoff, mss) \ + (NDIS_LSO2_INFO_MAKE((thoff), (mss)) | NDIS_LSO2_INFO_ISIPV6) + #endif /* !_NET_NDIS_H_ */ From 1a82707cd7770bfa4bfe2c91bf8c0fe9367c2d0e Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Tue, 6 Sep 2016 06:09:12 +0000 Subject: [PATCH 014/109] fix zfs pool creation accidentally broken by r305331 The upstream change introduced a new load state, SPA_LOAD_CREATE, and vdev_geom code needs to be aware of it. Tested by: cy MFC after: 1 week X-MFC with: r305331 --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c index 077983ca847..818052ba577 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c @@ -777,7 +777,8 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, if (vd->vdev_spa->spa_splitting_newspa || (vd->vdev_prevstate == VDEV_STATE_UNKNOWN && - vd->vdev_spa->spa_load_state == SPA_LOAD_NONE)) { + vd->vdev_spa->spa_load_state == SPA_LOAD_NONE || + vd->vdev_spa->spa_load_state == SPA_LOAD_CREATE)) { /* * We are dealing with a vdev that hasn't been previously * opened (since boot), and we are not loading an From c84bb70268a62ff1f25c61ffa9a34833357592d5 Mon Sep 17 00:00:00 2001 From: Andriy Voskoboinyk Date: Tue, 6 Sep 2016 06:40:59 +0000 Subject: [PATCH 015/109] rum: fix frame length checks in Rx path. Split usbd_xfer_status() check: - Check xfer length: must be longer, than Rx descriptor size. - Check frame size: must be shorter than xfer length. - Discard too short frames. Tested with WUSB54GC, STA/MONITOR modes. --- sys/dev/usb/wlan/if_rum.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c index bab18a61e41..a2fa351d370 100644 --- a/sys/dev/usb/wlan/if_rum.c +++ b/sys/dev/usb/wlan/if_rum.c @@ -1151,7 +1151,7 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) DPRINTFN(15, "rx done, actlen=%d\n", len); - if (len < (int)(RT2573_RX_DESC_SIZE + IEEE80211_MIN_LEN)) { + if (len < RT2573_RX_DESC_SIZE) { DPRINTF("%s: xfer too short %d\n", device_get_nameunit(sc->sc_dev), len); counter_u64_add(ic->ic_ierrors, 1); @@ -1165,6 +1165,20 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) rssi = rum_get_rssi(sc, sc->sc_rx_desc.rssi); flags = le32toh(sc->sc_rx_desc.flags); sc->last_rx_flags = flags; + if (len < ((flags >> 16) & 0xfff)) { + DPRINTFN(5, "%s: frame is truncated from %d to %d " + "bytes\n", device_get_nameunit(sc->sc_dev), + (flags >> 16) & 0xfff, len); + counter_u64_add(ic->ic_ierrors, 1); + goto tr_setup; + } + len = (flags >> 16) & 0xfff; + if (len < sizeof(struct ieee80211_frame_ack)) { + DPRINTFN(5, "%s: frame too short %d\n", + device_get_nameunit(sc->sc_dev), len); + counter_u64_add(ic->ic_ierrors, 1); + goto tr_setup; + } if (flags & RT2573_RX_CRC_ERROR) { /* * This should not happen since we did not @@ -1210,7 +1224,7 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) } /* finalize mbuf */ - m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff; + m->m_pkthdr.len = m->m_len = len; if (ieee80211_radiotap_active(ic)) { struct rum_rx_radiotap_header *tap = &sc->sc_rxtap; From cb5fe245b1c7d476e3839126a11ee4305484f7de Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Tue, 6 Sep 2016 08:45:29 +0000 Subject: [PATCH 016/109] Move tests/sys/kqueue/... to tests/sys/kqueue/libkqueue/... This is being done to clearly distinguish the libkqueue tests from the (soon to be imported) NetBSD tests. MFC after: 58 days Sponsored by: EMC / Isilon Storage Division --- ObsoleteFiles.inc | 3 +++ etc/mtree/BSD.tests.dist | 2 ++ tests/sys/kqueue/Makefile | 20 +----------------- tests/sys/kqueue/libkqueue/Makefile | 21 +++++++++++++++++++ .../kqueue/{ => libkqueue}/Makefile.depend | 0 tests/sys/kqueue/{ => libkqueue}/common.h | 0 tests/sys/kqueue/{ => libkqueue}/config.h | 0 .../sys/kqueue/{ => libkqueue}/kqueue_test.sh | 0 tests/sys/kqueue/{ => libkqueue}/main.c | 0 tests/sys/kqueue/{ => libkqueue}/proc.c | 0 tests/sys/kqueue/{ => libkqueue}/read.c | 0 tests/sys/kqueue/{ => libkqueue}/signal.c | 0 tests/sys/kqueue/{ => libkqueue}/timer.c | 0 tests/sys/kqueue/{ => libkqueue}/user.c | 0 tests/sys/kqueue/{ => libkqueue}/vnode.c | 0 15 files changed, 27 insertions(+), 19 deletions(-) create mode 100644 tests/sys/kqueue/libkqueue/Makefile rename tests/sys/kqueue/{ => libkqueue}/Makefile.depend (100%) rename tests/sys/kqueue/{ => libkqueue}/common.h (100%) rename tests/sys/kqueue/{ => libkqueue}/config.h (100%) rename tests/sys/kqueue/{ => libkqueue}/kqueue_test.sh (100%) rename tests/sys/kqueue/{ => libkqueue}/main.c (100%) rename tests/sys/kqueue/{ => libkqueue}/proc.c (100%) rename tests/sys/kqueue/{ => libkqueue}/read.c (100%) rename tests/sys/kqueue/{ => libkqueue}/signal.c (100%) rename tests/sys/kqueue/{ => libkqueue}/timer.c (100%) rename tests/sys/kqueue/{ => libkqueue}/user.c (100%) rename tests/sys/kqueue/{ => libkqueue}/vnode.c (100%) diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index bc89fefcd6c..d10165ca1ef 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,9 @@ # xargs -n1 | sort | uniq -d; # done +# 20160906: libkqueue tests moved to /usr/tests/sys/kqueue/libkqueue +OLD_FILES+=usr/tests/sys/kqueue/kqtest +OLD_FILES+=usr/tests/sys/kqueue/kqueue_test # 20160901: Remove digi(4) OLD_FILES+=usr/share/man/man4/digi.4.gz # 20160819: Remove ie(4) diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 27d52ca8556..331343fecdd 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -419,6 +419,8 @@ .. .. kqueue + libkqueue + .. .. mac bsdextended diff --git a/tests/sys/kqueue/Makefile b/tests/sys/kqueue/Makefile index 43277ca0c86..1c05443dd36 100644 --- a/tests/sys/kqueue/Makefile +++ b/tests/sys/kqueue/Makefile @@ -1,26 +1,8 @@ # $FreeBSD$ -# -# svn://mark.heily.com/libkqueue/trunk/test -# Last update: r114 -# -# libkqueue and test suite by Mark Heily -# - -TAP_TESTS_SH= kqueue_test TESTSDIR= ${TESTSBASE}/sys/kqueue BINDIR= ${TESTSDIR} -PROGS= kqtest - -SRCS.kqtest= \ - main.c \ - read.c \ - timer.c \ - vnode.c \ - proc.c \ - signal.c \ - user.c -WARNS?= 2 +TESTS_SUBDIRS+= libkqueue .include diff --git a/tests/sys/kqueue/libkqueue/Makefile b/tests/sys/kqueue/libkqueue/Makefile new file mode 100644 index 00000000000..94d198bf990 --- /dev/null +++ b/tests/sys/kqueue/libkqueue/Makefile @@ -0,0 +1,21 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/sys/kqueue/libkqueue +BINDIR= ${TESTSDIR} + +# libkqueue and test suite by Mark Heily +TAP_TESTS_SH= kqueue_test + +PROGS= kqtest + +SRCS.kqtest= \ + main.c \ + read.c \ + timer.c \ + vnode.c \ + proc.c \ + signal.c \ + user.c +WARNS?= 2 + +.include diff --git a/tests/sys/kqueue/Makefile.depend b/tests/sys/kqueue/libkqueue/Makefile.depend similarity index 100% rename from tests/sys/kqueue/Makefile.depend rename to tests/sys/kqueue/libkqueue/Makefile.depend diff --git a/tests/sys/kqueue/common.h b/tests/sys/kqueue/libkqueue/common.h similarity index 100% rename from tests/sys/kqueue/common.h rename to tests/sys/kqueue/libkqueue/common.h diff --git a/tests/sys/kqueue/config.h b/tests/sys/kqueue/libkqueue/config.h similarity index 100% rename from tests/sys/kqueue/config.h rename to tests/sys/kqueue/libkqueue/config.h diff --git a/tests/sys/kqueue/kqueue_test.sh b/tests/sys/kqueue/libkqueue/kqueue_test.sh similarity index 100% rename from tests/sys/kqueue/kqueue_test.sh rename to tests/sys/kqueue/libkqueue/kqueue_test.sh diff --git a/tests/sys/kqueue/main.c b/tests/sys/kqueue/libkqueue/main.c similarity index 100% rename from tests/sys/kqueue/main.c rename to tests/sys/kqueue/libkqueue/main.c diff --git a/tests/sys/kqueue/proc.c b/tests/sys/kqueue/libkqueue/proc.c similarity index 100% rename from tests/sys/kqueue/proc.c rename to tests/sys/kqueue/libkqueue/proc.c diff --git a/tests/sys/kqueue/read.c b/tests/sys/kqueue/libkqueue/read.c similarity index 100% rename from tests/sys/kqueue/read.c rename to tests/sys/kqueue/libkqueue/read.c diff --git a/tests/sys/kqueue/signal.c b/tests/sys/kqueue/libkqueue/signal.c similarity index 100% rename from tests/sys/kqueue/signal.c rename to tests/sys/kqueue/libkqueue/signal.c diff --git a/tests/sys/kqueue/timer.c b/tests/sys/kqueue/libkqueue/timer.c similarity index 100% rename from tests/sys/kqueue/timer.c rename to tests/sys/kqueue/libkqueue/timer.c diff --git a/tests/sys/kqueue/user.c b/tests/sys/kqueue/libkqueue/user.c similarity index 100% rename from tests/sys/kqueue/user.c rename to tests/sys/kqueue/libkqueue/user.c diff --git a/tests/sys/kqueue/vnode.c b/tests/sys/kqueue/libkqueue/vnode.c similarity index 100% rename from tests/sys/kqueue/vnode.c rename to tests/sys/kqueue/libkqueue/vnode.c From 8f2b5a546978f3c1d545b91a8e1888b0069f57e4 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Tue, 6 Sep 2016 08:50:21 +0000 Subject: [PATCH 017/109] Port contrib/netbsd-tests/kernel/kqueue/... as tests/sys/kqueue/... proc2_test must be skipped because the invariant tested (`ke.fflags & NOTE_TRACKERR`) doesn't pass. MFC after: 58 days Submitted by: kib (earlier form) Sponsored by: EMC / Isilon Storage Division Differential Revision: https://reviews.freebsd.org/D6172 --- contrib/netbsd-tests/kernel/kqueue/t_proc2.c | 3 +++ contrib/netbsd-tests/kernel/kqueue/t_proc3.c | 3 +++ contrib/netbsd-tests/kernel/kqueue/t_sig.c | 13 +++++++++++++ contrib/netbsd-tests/kernel/kqueue/t_vnode.c | 3 +++ tests/sys/kqueue/Makefile | 12 ++++++++++++ 5 files changed, 34 insertions(+) diff --git a/contrib/netbsd-tests/kernel/kqueue/t_proc2.c b/contrib/netbsd-tests/kernel/kqueue/t_proc2.c index e70fcb279d1..2d8d7f70f9d 100644 --- a/contrib/netbsd-tests/kernel/kqueue/t_proc2.c +++ b/contrib/netbsd-tests/kernel/kqueue/t_proc2.c @@ -34,6 +34,9 @@ __COPYRIGHT("@(#) Copyright (c) 2008\ The NetBSD Foundation, inc. All rights reserved."); __RCSID("$NetBSD: t_proc2.c,v 1.2 2015/01/14 22:22:32 christos Exp $"); +#ifdef __FreeBSD__ +#include +#endif #include #include #include diff --git a/contrib/netbsd-tests/kernel/kqueue/t_proc3.c b/contrib/netbsd-tests/kernel/kqueue/t_proc3.c index b77510becec..eac2f9ce984 100644 --- a/contrib/netbsd-tests/kernel/kqueue/t_proc3.c +++ b/contrib/netbsd-tests/kernel/kqueue/t_proc3.c @@ -32,6 +32,9 @@ #include __RCSID("$NetBSD: t_proc3.c,v 1.2 2015/01/14 22:22:32 christos Exp $"); +#ifdef __FreeBSD__ +#include +#endif #include #include #include diff --git a/contrib/netbsd-tests/kernel/kqueue/t_sig.c b/contrib/netbsd-tests/kernel/kqueue/t_sig.c index 4fc075847c8..8726fe98bb7 100644 --- a/contrib/netbsd-tests/kernel/kqueue/t_sig.c +++ b/contrib/netbsd-tests/kernel/kqueue/t_sig.c @@ -34,6 +34,9 @@ __COPYRIGHT("@(#) Copyright (c) 2008\ The NetBSD Foundation, inc. All rights reserved."); __RCSID("$NetBSD: t_sig.c,v 1.2 2010/11/03 16:10:20 christos Exp $"); +#ifdef __FreeBSD__ +#include +#endif #include #include #include @@ -60,9 +63,13 @@ ATF_TC_HEAD(sig, tc) ATF_TC_BODY(sig, tc) { struct timespec timeout; +#ifdef __NetBSD__ struct kfilter_mapping km; +#endif struct kevent event[1]; +#ifdef __NetBSD__ char namebuf[32]; +#endif pid_t pid, child; int kq, n, num, status; @@ -84,16 +91,22 @@ ATF_TC_BODY(sig, tc) RL(kq = kqueue()); +#ifdef __NetBSD__ (void)strlcpy(namebuf, "EVFILT_SIGNAL", sizeof(namebuf)); km.name = namebuf; RL(ioctl(kq, KFILTER_BYNAME, &km)); (void)printf("got %d as filter number for `%s'.\n", km.filter, km.name); +#endif /* ignore the signal to avoid taking it for real */ REQUIRE_LIBC(signal(SIGUSR1, SIG_IGN), SIG_ERR); event[0].ident = SIGUSR1; +#ifdef __NetBSD__ event[0].filter = km.filter; +#else + event[0].filter = EVFILT_SIGNAL; +#endif event[0].flags = EV_ADD | EV_ENABLE; RL(kevent(kq, event, 1, NULL, 0, NULL)); diff --git a/contrib/netbsd-tests/kernel/kqueue/t_vnode.c b/contrib/netbsd-tests/kernel/kqueue/t_vnode.c index e87c2b2c2d6..06ef683d8a3 100644 --- a/contrib/netbsd-tests/kernel/kqueue/t_vnode.c +++ b/contrib/netbsd-tests/kernel/kqueue/t_vnode.c @@ -1,3 +1,6 @@ +#ifdef __FreeBSD__ +#include +#endif #include #include #include diff --git a/tests/sys/kqueue/Makefile b/tests/sys/kqueue/Makefile index 1c05443dd36..40f892d36fb 100644 --- a/tests/sys/kqueue/Makefile +++ b/tests/sys/kqueue/Makefile @@ -1,8 +1,20 @@ # $FreeBSD$ +TESTSRC= ${SRCTOP}/contrib/netbsd-tests/kernel/kqueue + TESTSDIR= ${TESTSBASE}/sys/kqueue BINDIR= ${TESTSDIR} +NETBSD_ATF_TESTS_C= proc1_test +# XXX: fails `ke.fflags & NOTE_TRACKERR` invariant +#NETBSD_ATF_TESTS_C+= proc2_test +NETBSD_ATF_TESTS_C+= proc3_test +NETBSD_ATF_TESTS_C+= sig_test +NETBSD_ATF_TESTS_C+= vnode_test + +WARNS?= 3 + TESTS_SUBDIRS+= libkqueue +.include .include From 337b148e02af44ca9afb6d301ff6903d9bdcaf7f Mon Sep 17 00:00:00 2001 From: Xin LI Date: Tue, 6 Sep 2016 08:52:00 +0000 Subject: [PATCH 018/109] Ensure that we always open only files that is named by explicitly using shell redirections instead of having gzip(1) to decide what file to open. Issue reported in the "non-cryptanalytic attacks against freebsd update components" anonymous gist. Reviewed by: allanjude, emaste MFC after: 3 days Differential Revision: https://reviews.freebsd.org/D7653 --- usr.sbin/portsnap/portsnap/portsnap.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/usr.sbin/portsnap/portsnap/portsnap.sh b/usr.sbin/portsnap/portsnap/portsnap.sh index cba06d246d6..3dcf618ab53 100644 --- a/usr.sbin/portsnap/portsnap/portsnap.sh +++ b/usr.sbin/portsnap/portsnap/portsnap.sh @@ -651,7 +651,7 @@ fetch_index_sanity() { # Verify a list of files fetch_snapshot_verify() { while read F; do - if [ "`gunzip -c snap/${F} | ${SHA256} -q`" != ${F} ]; then + if [ "`gunzip -c < snap/${F}.gz | ${SHA256} -q`" != ${F} ]; then echo "snapshot corrupt." return 1 fi @@ -686,7 +686,7 @@ fetch_snapshot() { cut -f 2 -d '|' tINDEX.new | fetch_snapshot_verify || return 1 # Extract the index rm -f INDEX.new - gunzip -c snap/`look INDEX tINDEX.new | + gunzip -c < snap/`look INDEX tINDEX.new | cut -f 2 -d '|'`.gz > INDEX.new fetch_index_sanity || return 1 # Verify the snapshot contents @@ -782,7 +782,7 @@ fetch_update() { # Extract the index echo -n "Extracting index... " 1>${QUIETREDIR} - gunzip -c files/`look INDEX tINDEX.new | + gunzip -c < files/`look INDEX tINDEX.new | cut -f 2 -d '|'`.gz > INDEX.new fetch_index_sanity || return 1 @@ -902,7 +902,7 @@ extract_make_index() { echo -n "$1 not provided by portsnap server; " echo "$2 not being generated." else - gunzip -c "${WORKDIR}/files/`look $1 ${WORKDIR}/tINDEX | + gunzip -c < "${WORKDIR}/files/`look $1 ${WORKDIR}/tINDEX | cut -f 2 -d '|'`.gz" | cat - ${LOCALDESC} | ${MKINDEX} /dev/stdin > ${PORTSDIR}/$2 From 9afea60f98f7f3556dab137fa1b52a63db9ab170 Mon Sep 17 00:00:00 2001 From: Andriy Voskoboinyk Date: Tue, 6 Sep 2016 10:08:32 +0000 Subject: [PATCH 019/109] iwm: fix scanning for hidden SSIDs. Setup SSIDs in scan command so firmware will send direct probe request(s) while scanning. Tested by: dbkirk@gmail.com PR: 211519 MFC after: 1 week --- sys/dev/iwm/if_iwm_scan.c | 74 +++++++++++++++++++++------------------ sys/dev/iwm/if_iwmreg.h | 3 ++ 2 files changed, 42 insertions(+), 35 deletions(-) diff --git a/sys/dev/iwm/if_iwm_scan.c b/sys/dev/iwm/if_iwm_scan.c index 94f7125da42..6d17c121615 100644 --- a/sys/dev/iwm/if_iwm_scan.c +++ b/sys/dev/iwm/if_iwm_scan.c @@ -265,6 +265,7 @@ iwm_mvm_lmac_scan_fill_channels(struct iwm_softc *sc, struct iwm_scan_channel_cfg_lmac *chan, int n_ssids) { struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211_scan_state *ss = ic->ic_scan; struct ieee80211_channel *c; uint8_t nchan; int j; @@ -292,10 +293,11 @@ iwm_mvm_lmac_scan_fill_channels(struct iwm_softc *sc, chan->iter_count = htole16(1); chan->iter_interval = htole32(0); chan->flags = htole32(IWM_UNIFIED_SCAN_CHANNEL_PARTIAL); -#if 0 /* makes scanning while associated less useful */ - if (n_ssids != 0) - chan->flags |= htole32(1 << 1); /* select SSID 0 */ -#endif + chan->flags |= htole32(IWM_SCAN_CHANNEL_NSSIDS(n_ssids)); + /* XXX IEEE80211_SCAN_NOBCAST flag is never set. */ + if (!IEEE80211_IS_CHAN_PASSIVE(c) && + (!(ss->ss_flags & IEEE80211_SCAN_NOBCAST) || n_ssids != 0)) + chan->flags |= htole32(IWM_SCAN_CHANNEL_TYPE_ACTIVE); chan++; nchan++; } @@ -334,11 +336,7 @@ iwm_mvm_umac_scan_fill_channels(struct iwm_softc *sc, chan->channel_num = ieee80211_mhz2ieee(c->ic_freq, 0); chan->iter_count = 1; chan->iter_interval = htole16(0); - chan->flags = htole32(0); -#if 0 /* makes scanning while associated less useful */ - if (n_ssids != 0) - chan->flags = htole32(1 << 0); /* select SSID 0 */ -#endif + chan->flags = htole32(IWM_SCAN_CHANNEL_UMAC_NSSIDS(n_ssids)); chan++; nchan++; } @@ -355,13 +353,11 @@ iwm_mvm_fill_probe_req(struct iwm_softc *sc, struct iwm_scan_probe_req *preq) struct ieee80211_rateset *rs; size_t remain = sizeof(preq->buf); uint8_t *frm, *pos; - int ssid_len = 0; - const uint8_t *ssid = NULL; memset(preq, 0, sizeof(*preq)); /* Ensure enough space for header and SSID IE. */ - if (remain < sizeof(*wh) + 2 + ssid_len) + if (remain < sizeof(*wh) + 2) return ENOBUFS; /* @@ -378,7 +374,7 @@ iwm_mvm_fill_probe_req(struct iwm_softc *sc, struct iwm_scan_probe_req *preq) *(uint16_t *)&wh->i_seq[0] = 0; /* filled by HW */ frm = (uint8_t *)(wh + 1); - frm = ieee80211_add_ssid(frm, ssid, ssid_len); + frm = ieee80211_add_ssid(frm, NULL, 0); /* Tell the firmware where the MAC header is. */ preq->mac_header.offset = 0; @@ -544,11 +540,11 @@ iwm_mvm_umac_scan(struct iwm_softc *sc) .data = { NULL, }, .flags = IWM_CMD_SYNC, }; + struct ieee80211_scan_state *ss = sc->sc_ic.ic_scan; struct iwm_scan_req_umac *req; struct iwm_scan_req_umac_tail *tail; size_t req_len; - int ssid_len = 0; - const uint8_t *ssid = NULL; + uint8_t i, nssid; int ret; req_len = sizeof(struct iwm_scan_req_umac) + @@ -577,8 +573,9 @@ iwm_mvm_umac_scan(struct iwm_softc *sc) req->scan_priority = htole32(IWM_SCAN_PRIORITY_HIGH); req->ooc_priority = htole32(IWM_SCAN_PRIORITY_HIGH); + nssid = MIN(ss->ss_nssid, IWM_PROBE_OPTION_MAX); req->n_channels = iwm_mvm_umac_scan_fill_channels(sc, - (struct iwm_scan_channel_cfg_umac *)req->data, ssid_len != 0); + (struct iwm_scan_channel_cfg_umac *)req->data, nssid); req->general_flags = htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASS_ALL | IWM_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE | @@ -589,15 +586,19 @@ iwm_mvm_umac_scan(struct iwm_softc *sc) sc->sc_capa_n_scan_channels); /* Check if we're doing an active directed scan. */ - if (ssid_len != 0) { - tail->direct_scan[0].id = IEEE80211_ELEMID_SSID; - tail->direct_scan[0].len = ssid_len; - memcpy(tail->direct_scan[0].ssid, ssid, ssid_len); + for (i = 0; i < nssid; i++) { + tail->direct_scan[i].id = IEEE80211_ELEMID_SSID; + tail->direct_scan[i].len = MIN(ss->ss_ssid[i].len, + IEEE80211_NWID_LEN); + memcpy(tail->direct_scan[i].ssid, ss->ss_ssid[i].ssid, + tail->direct_scan[i].len); + /* XXX debug */ + } + if (nssid != 0) { req->general_flags |= htole32(IWM_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT); - } else { + } else req->general_flags |= htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASSIVE); - } if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT)) @@ -631,11 +632,11 @@ iwm_mvm_lmac_scan(struct iwm_softc *sc) .data = { NULL, }, .flags = IWM_CMD_SYNC, }; + struct ieee80211_scan_state *ss = sc->sc_ic.ic_scan; struct iwm_scan_req_lmac *req; size_t req_len; + uint8_t i, nssid; int ret; - int ssid_len = 0; - const uint8_t *ssid = NULL; IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "Handling ieee80211 scan request\n"); @@ -668,11 +669,6 @@ iwm_mvm_lmac_scan(struct iwm_softc *sc) req->scan_flags = htole32(IWM_MVM_LMAC_SCAN_FLAG_PASS_ALL | IWM_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE | IWM_MVM_LMAC_SCAN_FLAG_EXTENDED_DWELL); - if (ssid_len == 0) - req->scan_flags |= htole32(IWM_MVM_LMAC_SCAN_FLAG_PASSIVE); - else - req->scan_flags |= - htole32(IWM_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION); if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT)) req->scan_flags |= htole32(IWM_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED); @@ -698,15 +694,23 @@ iwm_mvm_lmac_scan(struct iwm_softc *sc) req->tx_cmd[1].sta_id = sc->sc_aux_sta.sta_id; /* Check if we're doing an active directed scan. */ - if (ssid_len != 0) { - req->direct_scan[0].id = IEEE80211_ELEMID_SSID; - req->direct_scan[0].len = ssid_len; - memcpy(req->direct_scan[0].ssid, ssid, ssid_len); + nssid = MIN(ss->ss_nssid, IWM_PROBE_OPTION_MAX); + for (i = 0; i < nssid; i++) { + req->direct_scan[i].id = IEEE80211_ELEMID_SSID; + req->direct_scan[i].len = MIN(ss->ss_ssid[i].len, + IEEE80211_NWID_LEN); + memcpy(req->direct_scan[i].ssid, ss->ss_ssid[i].ssid, + req->direct_scan[i].len); + /* XXX debug */ } + if (nssid != 0) { + req->scan_flags |= + htole32(IWM_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION); + } else + req->scan_flags |= htole32(IWM_MVM_LMAC_SCAN_FLAG_PASSIVE); req->n_channels = iwm_mvm_lmac_scan_fill_channels(sc, - (struct iwm_scan_channel_cfg_lmac *)req->data, - ssid_len != 0); + (struct iwm_scan_channel_cfg_lmac *)req->data, nssid); ret = iwm_mvm_fill_probe_req(sc, (struct iwm_scan_probe_req *)(req->data + diff --git a/sys/dev/iwm/if_iwmreg.h b/sys/dev/iwm/if_iwmreg.h index d1ed104099f..96a9e9eed9c 100644 --- a/sys/dev/iwm/if_iwmreg.h +++ b/sys/dev/iwm/if_iwmreg.h @@ -4766,6 +4766,7 @@ struct iwm_scd_txq_cfg_rsp { /* Masks for iwm_scan_channel.type flags */ #define IWM_SCAN_CHANNEL_TYPE_ACTIVE (1 << 0) +#define IWM_SCAN_CHANNEL_NSSIDS(x) (((1 << (x)) - 1) << 1) #define IWM_SCAN_CHANNEL_NARROW_BAND (1 << 22) /* Max number of IEs for direct SSID scans in a command */ @@ -5580,6 +5581,8 @@ enum iwm_umac_scan_general_flags { */ struct iwm_scan_channel_cfg_umac { uint32_t flags; +#define IWM_SCAN_CHANNEL_UMAC_NSSIDS(x) ((1 << (x)) - 1) + uint8_t channel_num; uint8_t iter_count; uint16_t iter_interval; From 2b2b1f42b90521c42b6fb56a3099c8614f612bce Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Tue, 6 Sep 2016 10:13:49 +0000 Subject: [PATCH 020/109] Teach acpidump how to parse ACPI 5.1 tables found on the development ThunderX units in the netperf cluster. Approved by: jkim Obtained from: ABT Systems Ltd MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D7252 --- usr.sbin/acpi/acpidump/acpi.c | 71 ++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/usr.sbin/acpi/acpidump/acpi.c b/usr.sbin/acpi/acpidump/acpi.c index 6d3f31a1938..8277179c3a8 100644 --- a/usr.sbin/acpi/acpidump/acpi.c +++ b/usr.sbin/acpi/acpidump/acpi.c @@ -355,6 +355,23 @@ acpi_print_mps_flags(uint16_t flags) printf("}\n"); } +static void +acpi_print_gicc_flags(uint32_t flags) +{ + + printf("\tFlags={Performance intr="); + if (flags & ACPI_MADT_PERFORMANCE_IRQ_MODE) + printf("edge"); + else + printf("level"); + printf(", VGIC intr="); + if (flags & ACPI_MADT_VGIC_IRQ_MODE) + printf("edge"); + else + printf("level"); + printf("}\n"); +} + static void acpi_print_intr(uint32_t intr, uint16_t mps_flags) { @@ -375,7 +392,12 @@ static const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override", "NMI", "Local APIC NMI", "Local APIC Override", "IO SAPIC", "Local SAPIC", "Platform Interrupt", - "Local X2APIC", "Local X2APIC NMI" }; + "Local X2APIC", "Local X2APIC NMI", + "GIC CPU Interface Structure", + "GIC Distributor Structure", + "GICv2m MSI Frame", + "GIC Redistributor Structure", + "GIC ITS Structure" }; static const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT", "Corrected Platform Error" }; @@ -393,6 +415,10 @@ acpi_print_madt(ACPI_SUBTABLE_HEADER *mp) ACPI_MADT_INTERRUPT_SOURCE *isrc; ACPI_MADT_LOCAL_X2APIC *x2apic; ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi; + ACPI_MADT_GENERIC_INTERRUPT *gicc; + ACPI_MADT_GENERIC_DISTRIBUTOR *gicd; + ACPI_MADT_GENERIC_REDISTRIBUTOR *gicr; + ACPI_MADT_GENERIC_TRANSLATOR *gict; if (mp->Type < sizeof(apic_types) / sizeof(apic_types[0])) printf("\tType=%s\n", apic_types[mp->Type]); @@ -464,6 +490,41 @@ acpi_print_madt(ACPI_SUBTABLE_HEADER *mp) acpi_print_cpu_uid(x2apic_nmi->Uid, NULL); acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags); break; + case ACPI_MADT_TYPE_GENERIC_INTERRUPT: + gicc = (ACPI_MADT_GENERIC_INTERRUPT *)mp; + acpi_print_cpu_uid(gicc->Uid, NULL); + printf("\tCPU INTERFACE=%x\n", gicc->CpuInterfaceNumber); + acpi_print_gicc_flags(gicc->Flags); + printf("\tParking Protocol Version=%x\n", gicc->ParkingVersion); + printf("\tPERF INTR=%d\n", gicc->PerformanceInterrupt); + printf("\tParked ADDR=%016jx\n", + (uintmax_t)gicc->ParkedAddress); + printf("\tBase ADDR=%016jx\n", (uintmax_t)gicc->BaseAddress); + printf("\tGICV=%016jx\n", (uintmax_t)gicc->GicvBaseAddress); + printf("\tGICH=%016jx\n", (uintmax_t)gicc->GichBaseAddress); + printf("\tVGIC INTR=%d\n", gicc->VgicInterrupt); + printf("\tGICR ADDR=%016jx\n", + (uintmax_t)gicc->GicrBaseAddress); + printf("\tMPIDR=%jx\n", (uintmax_t)gicc->ArmMpidr); + printf("\tEfficency Class=%d\n", (u_int)gicc->EfficiencyClass); + break; + case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR: + gicd = (ACPI_MADT_GENERIC_DISTRIBUTOR *)mp; + printf("\tGIC ID=%d\n", (u_int)gicd->GicId); + printf("\tBase ADDR=%016jx\n", (uintmax_t)gicd->BaseAddress); + printf("\tVector Base=%d\n", gicd->GlobalIrqBase); + printf("\tGIC VERSION=%d\n", (u_int)gicd->Version); + break; + case ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR: + gicr = (ACPI_MADT_GENERIC_REDISTRIBUTOR *)mp; + printf("\tBase ADDR=%016jx\n", (uintmax_t)gicr->BaseAddress); + printf("\tLength=%08x\n", gicr->Length); + break; + case ACPI_MADT_TYPE_GENERIC_TRANSLATOR: + gict = (ACPI_MADT_GENERIC_TRANSLATOR *)mp; + printf("\tGIC ITS ID=%d\n", gict->TranslationId); + printf("\tBase ADDR=%016jx\n", (uintmax_t)gict->BaseAddress); + break; } } @@ -1012,13 +1073,14 @@ acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp) printf("\tProximity Domain=%d\n", mp->ProximityDomain); } -static const char *srat_types[] = { "CPU", "Memory", "X2APIC" }; +static const char *srat_types[] = { "CPU", "Memory", "X2APIC", "GICC" }; static void acpi_print_srat(ACPI_SUBTABLE_HEADER *srat) { ACPI_SRAT_CPU_AFFINITY *cpu; ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic; + ACPI_SRAT_GICC_AFFINITY *gic; if (srat->Type < sizeof(srat_types) / sizeof(srat_types[0])) printf("\tType=%s\n", srat_types[srat->Type]); @@ -1041,6 +1103,11 @@ acpi_print_srat(ACPI_SUBTABLE_HEADER *srat) acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain, x2apic->Flags); break; + case ACPI_SRAT_TYPE_GICC_AFFINITY: + gic = (ACPI_SRAT_GICC_AFFINITY *)srat; + acpi_print_srat_cpu(gic->AcpiProcessorUid, gic->ProximityDomain, + gic->Flags); + break; } } From b7c89047803d823652d2283bf8cd05e4da306d34 Mon Sep 17 00:00:00 2001 From: Andriy Voskoboinyk Date: Tue, 6 Sep 2016 11:08:32 +0000 Subject: [PATCH 021/109] rtwn: fix firmware readiness check in rtwn_load_firmware(). --- sys/dev/rtwn/if_rtwn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/rtwn/if_rtwn.c b/sys/dev/rtwn/if_rtwn.c index 0a8f976a230..88c23b2346d 100644 --- a/sys/dev/rtwn/if_rtwn.c +++ b/sys/dev/rtwn/if_rtwn.c @@ -2204,7 +2204,7 @@ rtwn_load_firmware(struct rtwn_softc *sc) break; DELAY(50); } - if (ntries == 1000) { + if (ntries == 2000) { device_printf(sc->sc_dev, "timeout waiting for firmware readiness\n"); error = ETIMEDOUT; From 93ae47478c89894221b3d8bb1ec21952d5d01264 Mon Sep 17 00:00:00 2001 From: Andriy Voskoboinyk Date: Tue, 6 Sep 2016 12:00:16 +0000 Subject: [PATCH 022/109] rum: use m_get2() in Rx path. --- sys/dev/usb/wlan/if_rum.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c index a2fa351d370..924458159ab 100644 --- a/sys/dev/usb/wlan/if_rum.c +++ b/sys/dev/usb/wlan/if_rum.c @@ -1205,7 +1205,7 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) goto tr_setup; } - m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); + m = m_get2(len, M_NOWAIT, MT_DATA, M_PKTHDR); if (m == NULL) { DPRINTF("could not allocate mbuf\n"); counter_u64_add(ic->ic_ierrors, 1); From 68c6ae00add5f097f132bc944fcf602a5af43672 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Tue, 6 Sep 2016 13:34:10 +0000 Subject: [PATCH 023/109] bhnd: remove redundant ;s at the end of functions or switch statements --- sys/dev/bhnd/bhnd_subr.c | 6 +++--- sys/dev/bhnd/bhndb/bhndb.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sys/dev/bhnd/bhnd_subr.c b/sys/dev/bhnd/bhnd_subr.c index 51dfb40da99..31007695a36 100644 --- a/sys/dev/bhnd/bhnd_subr.c +++ b/sys/dev/bhnd/bhnd_subr.c @@ -833,7 +833,7 @@ bhnd_alloc_resources(device_t dev, struct resource_spec *rs, } return (0); -}; +} /** * Release bhnd(4) resources defined in @p rs from a parent bus. @@ -1657,7 +1657,7 @@ bhnd_bus_generic_activate_resource(device_t dev, device_t child, int type, } return (error); -}; +} /** * Helper function for implementing BHND_BUS_DEACTIVATE_RESOURCE(). @@ -1674,5 +1674,5 @@ bhnd_bus_generic_deactivate_resource(device_t dev, device_t child, child, type, rid, r)); return (EINVAL); -}; +} diff --git a/sys/dev/bhnd/bhndb/bhndb.c b/sys/dev/bhnd/bhndb/bhndb.c index f9d8061a6de..c5b08276caf 100644 --- a/sys/dev/bhnd/bhndb/bhndb.c +++ b/sys/dev/bhnd/bhndb/bhndb.c @@ -1101,7 +1101,7 @@ bhndb_get_rman(struct bhndb_softc *sc, device_t child, int type) return (NULL); default: return (NULL); - }; + } case BHNDB_ADDRSPACE_BRIDGED: switch (type) { @@ -1111,7 +1111,7 @@ bhndb_get_rman(struct bhndb_softc *sc, device_t child, int type) return (NULL); default: return (NULL); - }; + } } /* Quieten gcc */ @@ -1830,7 +1830,7 @@ bhndb_activate_bhnd_resource(device_t dev, device_t child, } return (error); -}; +} /** * Default bhndb(4) implementation of BHND_BUS_DEACTIVATE_RESOURCE(). @@ -1854,7 +1854,7 @@ bhndb_deactivate_bhnd_resource(device_t dev, device_t child, r->direct = false; return (error); -}; +} /** * Slow path for bhndb_io_resource(). From 25208b899945183857da501a98d924798de07b26 Mon Sep 17 00:00:00 2001 From: Wojciech Macek Date: Tue, 6 Sep 2016 14:26:41 +0000 Subject: [PATCH 024/109] Update Annapurna Alpine HAL to a newer version. HAL version: 2.7a --- al_hal_iofic.c | 18 +- al_hal_iofic.h | 10 +- al_hal_iofic_regs.h | 14 +- al_hal_nb_regs.h | 33 +- al_hal_pbs_regs.h | 133 +- al_hal_pcie.c | 606 ++-- al_hal_pcie.h | 417 ++- al_hal_pcie_axi_reg.h | 60 +- al_hal_pcie_interrupts.h | 10 +- al_hal_pcie_regs.h | 36 +- al_hal_pcie_w_reg.h | 2 +- al_hal_plat_services.h | 138 +- al_hal_plat_types.h | 18 - al_hal_reg_utils.h | 1 + al_hal_serdes.c | 1864 ++++++------ al_hal_serdes.h | 1125 -------- al_hal_serdes_25g.c | 1951 +++++++++++++ al_hal_serdes_25g.h | 74 + al_hal_serdes_25g_internal_regs.h | 4205 ++++++++++++++++++++++++++++ al_hal_serdes_25g_regs.h | 434 +++ al_hal_serdes_hssp.h | 87 + al_hal_serdes_hssp_internal_regs.h | 749 +++++ al_hal_serdes_hssp_regs.h | 494 ++++ al_hal_serdes_interface.h | 875 ++++++ al_hal_udma.h | 11 +- al_hal_udma_config.c | 333 +-- al_hal_udma_config.h | 265 +- al_hal_udma_debug.c | 8 +- al_hal_udma_iofic.h | 18 + al_hal_udma_main.c | 26 +- al_hal_udma_regs_gen.h | 319 +-- al_hal_unit_adapter_regs.h | 14 +- al_serdes.c | 59 + al_serdes.h | 78 + eth/al_hal_eth.h | 82 +- eth/al_hal_eth_mac_regs.h | 295 +- eth/al_hal_eth_main.c | 1004 +++++-- 37 files changed, 12326 insertions(+), 3540 deletions(-) create mode 100644 al_hal_serdes_25g.c create mode 100644 al_hal_serdes_25g.h create mode 100644 al_hal_serdes_25g_internal_regs.h create mode 100644 al_hal_serdes_25g_regs.h create mode 100644 al_hal_serdes_hssp.h create mode 100644 al_hal_serdes_hssp_internal_regs.h create mode 100644 al_hal_serdes_hssp_regs.h create mode 100644 al_hal_serdes_interface.h create mode 100644 al_serdes.c create mode 100644 al_serdes.h diff --git a/al_hal_iofic.c b/al_hal_iofic.c index 28467f2e3b8..b60a45f3002 100644 --- a/al_hal_iofic.c +++ b/al_hal_iofic.c @@ -129,10 +129,10 @@ int al_iofic_msix_moder_interval_config(void __iomem *regs_base, int group, } /* - * configure the vmid attributes for a given msix vector. + * configure the target-id 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) +int al_iofic_msix_tgtid_attributes_config(void __iomem *regs_base, int group, + uint8_t vector, uint32_t tgtid, uint8_t tgtid_en) { struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base); uint32_t reg = 0; @@ -141,14 +141,14 @@ int al_iofic_msix_vmid_attributes_config(void __iomem *regs_base, int group, al_assert(group < AL_IOFIC_MAX_GROUPS); AL_REG_FIELD_SET(reg, - INT_MSIX_VMID_MASK, - INT_MSIX_VMID_SHIFT, - vmid); + INT_MSIX_TGTID_MASK, + INT_MSIX_TGTID_SHIFT, + tgtid); AL_REG_BIT_VAL_SET(reg, - INT_MSIX_VMID_EN_SHIFT, - vmid_en); + INT_MSIX_TGTID_EN_SHIFT, + tgtid_en); - al_reg_write32(®s->grp_int_mod[group][vector].grp_int_vmid_reg, reg); + al_reg_write32(®s->grp_int_mod[group][vector].grp_int_tgtid_reg, reg); return 0; } diff --git a/al_hal_iofic.h b/al_hal_iofic.h index 5c19e0a1260..5b4a1dffb0e 100644 --- a/al_hal_iofic.h +++ b/al_hal_iofic.h @@ -117,17 +117,17 @@ int al_iofic_msix_moder_interval_config(void __iomem *regs_base, int group, uint8_t vector, uint8_t interval); /** -* configure the vmid attributes for a given msix vector. +* configure the tgtid attributes for a given msix vector. * * @param group the interrupt group * @param vector index -* @param vmid the vmid value -* @param vmid_en take vmid from the intc +* @param tgtid the target-id value +* @param tgtid_en take target-id from the intc * * @return 0 on success. -EINVAL otherwise. */ -int al_iofic_msix_vmid_attributes_config(void __iomem *regs_base, int group, - uint8_t vector, uint32_t vmid, uint8_t vmid_en); +int al_iofic_msix_tgtid_attributes_config(void __iomem *regs_base, int group, + uint8_t vector, uint32_t tgtid, uint8_t tgtid_en); /** * return the offset of the unmask register for a given group. diff --git a/al_hal_iofic_regs.h b/al_hal_iofic_regs.h index 81ba20fc967..3f1b5f88660 100644 --- a/al_hal_iofic_regs.h +++ b/al_hal_iofic_regs.h @@ -66,7 +66,7 @@ struct al_iofic_grp_ctrl { struct al_iofic_grp_mod { uint32_t grp_int_mod_reg; /* Interrupt moderation registerDedicated moderation in ... */ - uint32_t grp_int_vmid_reg; + uint32_t grp_int_tgtid_reg; }; struct al_iofic_regs { @@ -109,12 +109,12 @@ struct al_iofic_regs { #define INT_MOD_INTV_MASK 0x000000FF #define INT_MOD_INTV_SHIFT 0 -/**** grp_int_vmid_reg register ****/ -/* Interrupt vmid value registerDedicated reg ... */ -#define INT_MSIX_VMID_MASK 0x0000FFFF -#define INT_MSIX_VMID_SHIFT 0 -/* Interrupt vmid_en value registerDedicated reg ... */ -#define INT_MSIX_VMID_EN_SHIFT 31 +/**** grp_int_tgtid_reg register ****/ +/* Interrupt tgtid value registerDedicated reg ... */ +#define INT_MSIX_TGTID_MASK 0x0000FFFF +#define INT_MSIX_TGTID_SHIFT 0 +/* Interrupt tgtid_en value registerDedicated reg ... */ +#define INT_MSIX_TGTID_EN_SHIFT 31 #ifdef __cplusplus } diff --git a/al_hal_nb_regs.h b/al_hal_nb_regs.h index 9de3bd24686..29c5060d007 100644 --- a/al_hal_nb_regs.h +++ b/al_hal_nb_regs.h @@ -355,7 +355,7 @@ struct al_nb_nb_version { }; struct al_nb_sriov { /* [0x0] */ - uint32_t cpu_vmid[4]; + uint32_t cpu_tgtid[4]; uint32_t rsrvd[4]; }; struct al_nb_dram_channels { @@ -403,7 +403,7 @@ struct al_nb_push_packet { uint32_t pp_config; uint32_t rsrvd_0[3]; /* [0x10] */ - uint32_t pp_ext_awuser; + uint32_t pp_ext_attr; uint32_t rsrvd_1[3]; /* [0x20] */ uint32_t pp_base_low; @@ -411,7 +411,7 @@ struct al_nb_push_packet { uint32_t pp_base_high; uint32_t rsrvd_2[2]; /* [0x30] */ - uint32_t pp_sel_awuser; + uint32_t pp_sel_attr; uint32_t rsrvd[51]; }; @@ -853,8 +853,8 @@ Enables 4k hazard of post-barrier vs pre-barrier transactions. Otherwise, 64B ha This value is sampled into the CP15 Configuration Base Address Register (CBAR) at reset. */ #define NB_GLOBAL_LGIC_BASE_HIGH_BASE_39_32_MASK 0x000000FF #define NB_GLOBAL_LGIC_BASE_HIGH_BASE_39_32_SHIFT 0 -#define NB_GLOBAL_LGIC_BASE_HIGH_BASE_43_32_MASK_PKR 0x00000FFF -#define NB_GLOBAL_LGIC_BASE_HIGH_BASE_43_32_SHIFT_PKR 0 +#define NB_GLOBAL_LGIC_BASE_HIGH_BASE_43_32_MASK_ALPINE_V2 0x00000FFF +#define NB_GLOBAL_LGIC_BASE_HIGH_BASE_43_32_SHIFT_ALPINE_V2 0 /* GIC registers base [31:15]. This value is sampled into the CP15 Configuration Base Address Register (CBAR) at reset */ #define NB_GLOBAL_LGIC_BASE_LOW_BASED_31_15_MASK 0xFFFF8000 @@ -1055,9 +1055,9 @@ Other access types are hazard check against the pre-barrier requests. */ /* Disable counter (wait 1000 NB cycles) before applying PoS enable/disable configuration */ #define NB_GLOBAL_ACF_MISC_POS_CONFIG_CNT_DIS (1 << 14) /* Disable wr spliter A0 bug fixes */ -#define NB_GLOBAL_ACF_MISC_WRSPLT_ALPINE_M0_MODE (1 << 16) -/* Disable wr spliter PKR bug fixes */ -#define NB_GLOBAL_ACF_MISC_WRSPLT_ALPINE_A0_MODE (1 << 17) +#define NB_GLOBAL_ACF_MISC_WRSPLT_ALPINE_V1_M0_MODE (1 << 16) +/* Disable wr spliter ALPINE_V2 bug fixes */ +#define NB_GLOBAL_ACF_MISC_WRSPLT_ALPINE_V1_A0_MODE (1 << 17) /* Override the address parity calucation for write transactions going to IO-fabric */ #define NB_GLOBAL_ACF_MISC_NB_NIC_AWADDR_PAR_OVRD (1 << 18) /* Override the data parity calucation for write transactions going to IO-fabric */ @@ -1074,7 +1074,7 @@ Other access types are hazard check against the pre-barrier requests. */ #define NB_GLOBAL_ACF_MISC_CPU_DSB_FLUSH_DIS (1 << 26) /* Enable DMB flush request to NB to SB PoS when barrier is terminted inside the processor cluster */ #define NB_GLOBAL_ACF_MISC_CPU_DMB_FLUSH_DIS (1 << 27) -/* Peakrock only: remap CPU address above 40 bits to Slave Error +/* Alpine V2 only: remap CPU address above 40 bits to Slave Error INTERNAL */ #define NB_GLOBAL_ACF_MISC_ADDR43_40_REMAP_DIS (1 << 28) /* Enable CPU WriteUnique to WriteNoSnoop trasform */ @@ -1586,7 +1586,7 @@ enable - 0x1: Enable interrupt on overflow. */ /* Number of monitored events supported by the PMU. */ #define NB_MC_PMU_PMU_CONTROL_NUM_OF_EVENTS_MASK 0x00FC0000 #define NB_MC_PMU_PMU_CONTROL_NUM_OF_EVENTS_SHIFT 18 -#define NB_MC_PMU_PMU_CONTROL_NUM_OF_EVENTS_SHIFT_ALPINE 19 +#define NB_MC_PMU_PMU_CONTROL_NUM_OF_EVENTS_SHIFT_ALPINE_V1 19 /* Number of counters implemented by PMU. */ #define NB_MC_PMU_PMU_CONTROL_NUM_OF_CNTS_MASK 0x0F000000 #define NB_MC_PMU_PMU_CONTROL_NUM_OF_CNTS_SHIFT 24 @@ -1659,6 +1659,9 @@ Note: This field must be changed for larger counters. */ /* Revision number (Major) */ #define NB_NB_VERSION_VERSION_RELEASE_NUM_MAJOR_MASK 0x0000FF00 #define NB_NB_VERSION_VERSION_RELEASE_NUM_MAJOR_SHIFT 8 +#define NB_NB_VERSION_VERSION_RELEASE_NUM_MAJOR_VAL_ALPINE_V1 2 +#define NB_NB_VERSION_VERSION_RELEASE_NUM_MAJOR_VAL_ALPINE_V2 3 +#define NB_NB_VERSION_VERSION_RELEASE_NUM_MAJOR_VAL_ALPINE_V3 4 /* Date of release */ #define NB_NB_VERSION_VERSION_DATE_DAY_MASK 0x001F0000 #define NB_NB_VERSION_VERSION_DATE_DAY_SHIFT 16 @@ -1672,10 +1675,10 @@ Note: This field must be changed for larger counters. */ #define NB_NB_VERSION_VERSION_RESERVED_MASK 0xC0000000 #define NB_NB_VERSION_VERSION_RESERVED_SHIFT 30 -/**** cpu_vmid register ****/ -/* Target VMID */ -#define NB_SRIOV_CPU_VMID_VAL_MASK 0x000000FF -#define NB_SRIOV_CPU_VMID_VAL_SHIFT 0 +/**** cpu_tgtid register ****/ +/* Target-ID */ +#define NB_SRIOV_CPU_TGTID_VAL_MASK 0x000000FF +#define NB_SRIOV_CPU_TGTID_VAL_SHIFT 0 /**** DRAM_0_Control register ****/ /* Controller Idle @@ -1807,7 +1810,7 @@ Parity bits are still generated per transaction */ #define NB_PUSH_PACKET_PP_EXT_AWUSER_AWUSER_SHIFT 0 /**** pp_sel_awuser register ****/ -/* Select whether to use addr[63:48] or PP awmisc as vmid. +/* Select whether to use addr[63:48] or PP awmisc as tgtid. Each bit if set to 1 selects the corresponding address bit. Otherwise, selects the corersponding awmis bit. */ #define NB_PUSH_PACKET_PP_SEL_AWUSER_SEL_MASK 0x0000FFFF #define NB_PUSH_PACKET_PP_SEL_AWUSER_SEL_SHIFT 0 diff --git a/al_hal_pbs_regs.h b/al_hal_pbs_regs.h index b1f9c4f44d9..c8100e1ff1e 100644 --- a/al_hal_pbs_regs.h +++ b/al_hal_pbs_regs.h @@ -447,11 +447,12 @@ struct al_pbs_target_id_enforcement { }; struct al_pbs_regs { - struct al_pbs_unit unit; /* [0x0] */ -struct al_pbs_low_latency_sram_remap low_latency_sram_remap; -/* [0x250] */ - uint32_t rsrvd_0[88]; - struct al_pbs_target_id_enforcement target_id_enforcement; /* [0x400] */ + struct al_pbs_unit unit; /* [0x0] */ + struct al_pbs_low_latency_sram_remap low_latency_sram_remap; /* [0x250] */ + uint32_t rsrvd_0[24]; + uint32_t iofic_base; /* [0x300] */ + uint32_t rsrvd_1[63]; + struct al_pbs_target_id_enforcement target_id_enforcement; /* [0x400] */ }; @@ -849,50 +850,50 @@ struct al_pbs_low_latency_sram_remap low_latency_sram_remap; * 2'b01 - select pcie_b[0] * 2'b10 - select pcie_a[2] */ -#define PBS_UNIT_SERDES_MUX_PIPE_PKR_SELECT_OH_SERDES_2_MASK 0x00000003 -#define PBS_UNIT_SERDES_MUX_PIPE_PKR_SELECT_OH_SERDES_2_SHIFT 0 +#define PBS_UNIT_SERDES_MUX_PIPE_ALPINE_V2_SELECT_OH_SERDES_2_MASK 0x00000003 +#define PBS_UNIT_SERDES_MUX_PIPE_ALPINE_V2_SELECT_OH_SERDES_2_SHIFT 0 /* * 2'b01 - select pcie_b[1] * 2'b10 - select pcie_a[3] */ -#define PBS_UNIT_SERDES_MUX_PIPE_PKR_SELECT_OH_SERDES_3_MASK 0x00000030 -#define PBS_UNIT_SERDES_MUX_PIPE_PKR_SELECT_OH_SERDES_3_SHIFT 4 +#define PBS_UNIT_SERDES_MUX_PIPE_ALPINE_V2_SELECT_OH_SERDES_3_MASK 0x00000030 +#define PBS_UNIT_SERDES_MUX_PIPE_ALPINE_V2_SELECT_OH_SERDES_3_SHIFT 4 /* * 2'b01 - select pcie_b[0] * 2'b10 - select pcie_a[4] */ -#define PBS_UNIT_SERDES_MUX_PIPE_PKR_SELECT_OH_SERDES_4_MASK 0x00000300 -#define PBS_UNIT_SERDES_MUX_PIPE_PKR_SELECT_OH_SERDES_4_SHIFT 8 +#define PBS_UNIT_SERDES_MUX_PIPE_ALPINE_V2_SELECT_OH_SERDES_4_MASK 0x00000300 +#define PBS_UNIT_SERDES_MUX_PIPE_ALPINE_V2_SELECT_OH_SERDES_4_SHIFT 8 /* * 2'b01 - select pcie_b[1] * 2'b10 - select pcie_a[5] */ -#define PBS_UNIT_SERDES_MUX_PIPE_PKR_SELECT_OH_SERDES_5_MASK 0x00003000 -#define PBS_UNIT_SERDES_MUX_PIPE_PKR_SELECT_OH_SERDES_5_SHIFT 12 +#define PBS_UNIT_SERDES_MUX_PIPE_ALPINE_V2_SELECT_OH_SERDES_5_MASK 0x00003000 +#define PBS_UNIT_SERDES_MUX_PIPE_ALPINE_V2_SELECT_OH_SERDES_5_SHIFT 12 /* * 2'b01 - select pcie_b[2] * 2'b10 - select pcie_a[6] */ -#define PBS_UNIT_SERDES_MUX_PIPE_PKR_SELECT_OH_SERDES_6_MASK 0x00030000 -#define PBS_UNIT_SERDES_MUX_PIPE_PKR_SELECT_OH_SERDES_6_SHIFT 16 +#define PBS_UNIT_SERDES_MUX_PIPE_ALPINE_V2_SELECT_OH_SERDES_6_MASK 0x00030000 +#define PBS_UNIT_SERDES_MUX_PIPE_ALPINE_V2_SELECT_OH_SERDES_6_SHIFT 16 /* * 2'b01 - select pcie_b[3] * 2'b10 - select pcie_a[7] */ -#define PBS_UNIT_SERDES_MUX_PIPE_PKR_SELECT_OH_SERDES_7_MASK 0x00300000 -#define PBS_UNIT_SERDES_MUX_PIPE_PKR_SELECT_OH_SERDES_7_SHIFT 20 +#define PBS_UNIT_SERDES_MUX_PIPE_ALPINE_V2_SELECT_OH_SERDES_7_MASK 0x00300000 +#define PBS_UNIT_SERDES_MUX_PIPE_ALPINE_V2_SELECT_OH_SERDES_7_SHIFT 20 /* * 2'b01 - select pcie_d[0] * 2'b10 - select pcie_c[2] */ -#define PBS_UNIT_SERDES_MUX_PIPE_PKR_SELECT_OH_SERDES_10_MASK 0x03000000 -#define PBS_UNIT_SERDES_MUX_PIPE_PKR_SELECT_OH_SERDES_10_SHIFT 24 +#define PBS_UNIT_SERDES_MUX_PIPE_ALPINE_V2_SELECT_OH_SERDES_10_MASK 0x03000000 +#define PBS_UNIT_SERDES_MUX_PIPE_ALPINE_V2_SELECT_OH_SERDES_10_SHIFT 24 /* * 2'b01 - select pcie_d[1] * 2'b10 - select pcie_c[3] */ -#define PBS_UNIT_SERDES_MUX_PIPE_PKR_SELECT_OH_SERDES_11_MASK 0x30000000 -#define PBS_UNIT_SERDES_MUX_PIPE_PKR_SELECT_OH_SERDES_11_SHIFT 28 +#define PBS_UNIT_SERDES_MUX_PIPE_ALPINE_V2_SELECT_OH_SERDES_11_MASK 0x30000000 +#define PBS_UNIT_SERDES_MUX_PIPE_ALPINE_V2_SELECT_OH_SERDES_11_SHIFT 28 /**** dma_io_master_map register ****/ /* @@ -978,6 +979,14 @@ struct al_pbs_low_latency_sram_remap low_latency_sram_remap; #define PBS_UNIT_CFG_AXI_CONF_2_DBG_AWQOS_MASK 0x3C000000 #define PBS_UNIT_CFG_AXI_CONF_2_DBG_AWQOS_SHIFT 26 +/**** cfg_axi_conf_3 register ****/ +#define PBS_UNIT_CFG_AXI_CONF_3_TIMEOUT_LOW_MASK 0xFFFF +#define PBS_UNIT_CFG_AXI_CONF_3_TIMEOUT_LOW_SHIFT 0 +#define PBS_UNIT_CFG_AXI_CONF_3_TIMEOUT_HI_MASK 0xFF0000 +#define PBS_UNIT_CFG_AXI_CONF_3_TIMEOUT_HI_SHIFT 16 +#define PBS_UNIT_CFG_AXI_CONF_3_TIMEOUT_SPI_HI_MASK 0xFF000000 +#define PBS_UNIT_CFG_AXI_CONF_3_TIMEOUT_SPI_HI_SHIFT 24 + /**** spi_mst_conf_0 register ****/ /* * Sets the SPI master Configuration. For details see the SPI section in the @@ -1137,9 +1146,9 @@ struct al_pbs_low_latency_sram_remap low_latency_sram_remap; #define PBS_UNIT_CHIP_ID_DEV_ID_MASK 0xFFFF0000 #define PBS_UNIT_CHIP_ID_DEV_ID_SHIFT 16 -#define PBS_UNIT_CHIP_ID_DEV_ID_ALPINE 0 -#define PBS_UNIT_CHIP_ID_DEV_ID_PEAKROCK 1 -#define PBS_UNIT_CHIP_ID_DEV_ID_COYOTE 2 +#define PBS_UNIT_CHIP_ID_DEV_ID_ALPINE_V1 0 +#define PBS_UNIT_CHIP_ID_DEV_ID_ALPINE_V2 1 +#define PBS_UNIT_CHIP_ID_DEV_ID_ALPINE_V3 2 /**** uart0_conf_status register ****/ /* @@ -1420,56 +1429,56 @@ struct al_pbs_low_latency_sram_remap low_latency_sram_remap; * 2'b01 - select sata_b[0] * 2'b10 - select eth_a[0] */ -#define PBS_UNIT_SERDES_MUX_MULTI_0_PKR_SELECT_OH_SERDES_8_MASK 0x00000003 -#define PBS_UNIT_SERDES_MUX_MULTI_0_PKR_SELECT_OH_SERDES_8_SHIFT 0 +#define PBS_UNIT_SERDES_MUX_MULTI_0_ALPINE_V2_SELECT_OH_SERDES_8_MASK 0x00000003 +#define PBS_UNIT_SERDES_MUX_MULTI_0_ALPINE_V2_SELECT_OH_SERDES_8_SHIFT 0 /* * 3'b001 - select sata_b[1] * 3'b010 - select eth_b[0] * 3'b100 - select eth_a[1] */ -#define PBS_UNIT_SERDES_MUX_MULTI_0_PKR_SELECT_OH_SERDES_9_MASK 0x00000070 -#define PBS_UNIT_SERDES_MUX_MULTI_0_PKR_SELECT_OH_SERDES_9_SHIFT 4 +#define PBS_UNIT_SERDES_MUX_MULTI_0_ALPINE_V2_SELECT_OH_SERDES_9_MASK 0x00000070 +#define PBS_UNIT_SERDES_MUX_MULTI_0_ALPINE_V2_SELECT_OH_SERDES_9_SHIFT 4 /* * 3'b001 - select sata_b[2] * 3'b010 - select eth_c[0] * 3'b100 - select eth_a[2] */ -#define PBS_UNIT_SERDES_MUX_MULTI_0_PKR_SELECT_OH_SERDES_10_MASK 0x00000700 -#define PBS_UNIT_SERDES_MUX_MULTI_0_PKR_SELECT_OH_SERDES_10_SHIFT 8 +#define PBS_UNIT_SERDES_MUX_MULTI_0_ALPINE_V2_SELECT_OH_SERDES_10_MASK 0x00000700 +#define PBS_UNIT_SERDES_MUX_MULTI_0_ALPINE_V2_SELECT_OH_SERDES_10_SHIFT 8 /* * 3'b001 - select sata_b[3] * 3'b010 - select eth_d[0] * 3'b100 - select eth_a[3] */ -#define PBS_UNIT_SERDES_MUX_MULTI_0_PKR_SELECT_OH_SERDES_11_MASK 0x00007000 -#define PBS_UNIT_SERDES_MUX_MULTI_0_PKR_SELECT_OH_SERDES_11_SHIFT 12 +#define PBS_UNIT_SERDES_MUX_MULTI_0_ALPINE_V2_SELECT_OH_SERDES_11_MASK 0x00007000 +#define PBS_UNIT_SERDES_MUX_MULTI_0_ALPINE_V2_SELECT_OH_SERDES_11_SHIFT 12 /* * 2'b01 - select eth_a[0] * 2'b10 - select sata_a[0] */ -#define PBS_UNIT_SERDES_MUX_MULTI_0_PKR_SELECT_OH_SERDES_12_MASK 0x00030000 -#define PBS_UNIT_SERDES_MUX_MULTI_0_PKR_SELECT_OH_SERDES_12_SHIFT 16 +#define PBS_UNIT_SERDES_MUX_MULTI_0_ALPINE_V2_SELECT_OH_SERDES_12_MASK 0x00030000 +#define PBS_UNIT_SERDES_MUX_MULTI_0_ALPINE_V2_SELECT_OH_SERDES_12_SHIFT 16 /* * 3'b001 - select eth_b[0] * 3'b010 - select eth_c[1] * 3'b100 - select sata_a[1] */ -#define PBS_UNIT_SERDES_MUX_MULTI_0_PKR_SELECT_OH_SERDES_13_MASK 0x00700000 -#define PBS_UNIT_SERDES_MUX_MULTI_0_PKR_SELECT_OH_SERDES_13_SHIFT 20 +#define PBS_UNIT_SERDES_MUX_MULTI_0_ALPINE_V2_SELECT_OH_SERDES_13_MASK 0x00700000 +#define PBS_UNIT_SERDES_MUX_MULTI_0_ALPINE_V2_SELECT_OH_SERDES_13_SHIFT 20 /* * 3'b001 - select eth_a[0] * 3'b010 - select eth_c[2] * 3'b100 - select sata_a[2] */ -#define PBS_UNIT_SERDES_MUX_MULTI_0_PKR_SELECT_OH_SERDES_14_MASK 0x07000000 -#define PBS_UNIT_SERDES_MUX_MULTI_0_PKR_SELECT_OH_SERDES_14_SHIFT 24 +#define PBS_UNIT_SERDES_MUX_MULTI_0_ALPINE_V2_SELECT_OH_SERDES_14_MASK 0x07000000 +#define PBS_UNIT_SERDES_MUX_MULTI_0_ALPINE_V2_SELECT_OH_SERDES_14_SHIFT 24 /* * 3'b001 - select eth_d[0] * 3'b010 - select eth_c[3] * 3'b100 - select sata_a[3] */ -#define PBS_UNIT_SERDES_MUX_MULTI_0_PKR_SELECT_OH_SERDES_15_MASK 0x70000000 -#define PBS_UNIT_SERDES_MUX_MULTI_0_PKR_SELECT_OH_SERDES_15_SHIFT 28 +#define PBS_UNIT_SERDES_MUX_MULTI_0_ALPINE_V2_SELECT_OH_SERDES_15_MASK 0x70000000 +#define PBS_UNIT_SERDES_MUX_MULTI_0_ALPINE_V2_SELECT_OH_SERDES_15_SHIFT 28 /**** serdes_mux_multi_1 register ****/ /* SerDes one hot mux control. For details see datasheet. */ @@ -1632,62 +1641,62 @@ struct al_pbs_low_latency_sram_remap low_latency_sram_remap; * 2'b01 - eth_a[0] from serdes_8 * 2'b10 - eth_a[0] from serdes_14 */ -#define PBS_UNIT_SERDES_MUX_ETH_PKR_SELECT_OH_ETH_A_0_MASK 0x00000003 -#define PBS_UNIT_SERDES_MUX_ETH_PKR_SELECT_OH_ETH_A_0_SHIFT 0 +#define PBS_UNIT_SERDES_MUX_ETH_ALPINE_V2_SELECT_OH_ETH_A_0_MASK 0x00000003 +#define PBS_UNIT_SERDES_MUX_ETH_ALPINE_V2_SELECT_OH_ETH_A_0_SHIFT 0 /* * 2'b01 - eth_b[0] from serdes_9 * 2'b10 - eth_b[0] from serdes_13 */ -#define PBS_UNIT_SERDES_MUX_ETH_PKR_SELECT_OH_ETH_B_0_MASK 0x00000030 -#define PBS_UNIT_SERDES_MUX_ETH_PKR_SELECT_OH_ETH_B_0_SHIFT 4 +#define PBS_UNIT_SERDES_MUX_ETH_ALPINE_V2_SELECT_OH_ETH_B_0_MASK 0x00000030 +#define PBS_UNIT_SERDES_MUX_ETH_ALPINE_V2_SELECT_OH_ETH_B_0_SHIFT 4 /* * 2'b01 - eth_c[0] from serdes_10 * 2'b10 - eth_c[0] from serdes_12 */ -#define PBS_UNIT_SERDES_MUX_ETH_PKR_SELECT_OH_ETH_C_0_MASK 0x00000300 -#define PBS_UNIT_SERDES_MUX_ETH_PKR_SELECT_OH_ETH_C_0_SHIFT 8 +#define PBS_UNIT_SERDES_MUX_ETH_ALPINE_V2_SELECT_OH_ETH_C_0_MASK 0x00000300 +#define PBS_UNIT_SERDES_MUX_ETH_ALPINE_V2_SELECT_OH_ETH_C_0_SHIFT 8 /* * 2'b01 - eth_d[0] from serdes_11 * 2'b10 - eth_d[0] from serdes_15 */ -#define PBS_UNIT_SERDES_MUX_ETH_PKR_SELECT_OH_ETH_D_0_MASK 0x00003000 -#define PBS_UNIT_SERDES_MUX_ETH_PKR_SELECT_OH_ETH_D_0_SHIFT 12 +#define PBS_UNIT_SERDES_MUX_ETH_ALPINE_V2_SELECT_OH_ETH_D_0_MASK 0x00003000 +#define PBS_UNIT_SERDES_MUX_ETH_ALPINE_V2_SELECT_OH_ETH_D_0_SHIFT 12 /* which lane's is master clk */ -#define PBS_UNIT_SERDES_MUX_ETH_PKR_SELECT_OH_ETH_A_ICK_MASTER_MASK 0x00030000 -#define PBS_UNIT_SERDES_MUX_ETH_PKR_SELECT_OH_ETH_A_ICK_MASTER_SHIFT 16 +#define PBS_UNIT_SERDES_MUX_ETH_ALPINE_V2_SELECT_OH_ETH_A_ICK_MASTER_MASK 0x00030000 +#define PBS_UNIT_SERDES_MUX_ETH_ALPINE_V2_SELECT_OH_ETH_A_ICK_MASTER_SHIFT 16 /* which lane's is master clk */ -#define PBS_UNIT_SERDES_MUX_ETH_PKR_SELECT_OH_ETH_C_ICK_MASTER_MASK 0x00300000 -#define PBS_UNIT_SERDES_MUX_ETH_PKR_SELECT_OH_ETH_C_ICK_MASTER_SHIFT 20 +#define PBS_UNIT_SERDES_MUX_ETH_ALPINE_V2_SELECT_OH_ETH_C_ICK_MASTER_MASK 0x00300000 +#define PBS_UNIT_SERDES_MUX_ETH_ALPINE_V2_SELECT_OH_ETH_C_ICK_MASTER_SHIFT 20 /* enable xlaui on eth a */ -#define PBS_UNIT_SERDES_MUX_ETH_PKR_SELECT_OH_ETH_A_XLAUI_ENABLE (1 << 24) +#define PBS_UNIT_SERDES_MUX_ETH_ALPINE_V2_SELECT_OH_ETH_A_XLAUI_ENABLE (1 << 24) /* enable xlaui on eth c */ -#define PBS_UNIT_SERDES_MUX_ETH_PKR_SELECT_OH_ETH_C_XLAUI_ENABLE (1 << 28) +#define PBS_UNIT_SERDES_MUX_ETH_ALPINE_V2_SELECT_OH_ETH_C_XLAUI_ENABLE (1 << 28) /**** serdes_mux_pcie register ****/ /* * 2'b01 - select pcie_b[0] from serdes 2 * 2'b10 - select pcie_b[0] from serdes 4 */ -#define PBS_UNIT_SERDES_MUX_PCIE_PKR_SELECT_OH_PCIE_B_0_MASK 0x00000003 -#define PBS_UNIT_SERDES_MUX_PCIE_PKR_SELECT_OH_PCIE_B_0_SHIFT 0 +#define PBS_UNIT_SERDES_MUX_PCIE_ALPINE_V2_SELECT_OH_PCIE_B_0_MASK 0x00000003 +#define PBS_UNIT_SERDES_MUX_PCIE_ALPINE_V2_SELECT_OH_PCIE_B_0_SHIFT 0 /* * 2'b01 - select pcie_b[1] from serdes 3 * 2'b10 - select pcie_b[1] from serdes 5 */ -#define PBS_UNIT_SERDES_MUX_PCIE_PKR_SELECT_OH_PCIE_B_1_MASK 0x00000030 -#define PBS_UNIT_SERDES_MUX_PCIE_PKR_SELECT_OH_PCIE_B_1_SHIFT 4 +#define PBS_UNIT_SERDES_MUX_PCIE_ALPINE_V2_SELECT_OH_PCIE_B_1_MASK 0x00000030 +#define PBS_UNIT_SERDES_MUX_PCIE_ALPINE_V2_SELECT_OH_PCIE_B_1_SHIFT 4 /* * 2'b01 - select pcie_d[0] from serdes 10 * 2'b10 - select pcie_d[0] from serdes 12 */ -#define PBS_UNIT_SERDES_MUX_PCIE_PKR_SELECT_OH_PCIE_D_0_MASK 0x00000300 -#define PBS_UNIT_SERDES_MUX_PCIE_PKR_SELECT_OH_PCIE_D_0_SHIFT 8 +#define PBS_UNIT_SERDES_MUX_PCIE_ALPINE_V2_SELECT_OH_PCIE_D_0_MASK 0x00000300 +#define PBS_UNIT_SERDES_MUX_PCIE_ALPINE_V2_SELECT_OH_PCIE_D_0_SHIFT 8 /* * 2'b01 - select pcie_d[1] from serdes 11 * 2'b10 - select pcie_d[1] from serdes 13 */ -#define PBS_UNIT_SERDES_MUX_PCIE_PKR_SELECT_OH_PCIE_D_1_MASK 0x00003000 -#define PBS_UNIT_SERDES_MUX_PCIE_PKR_SELECT_OH_PCIE_D_1_SHIFT 12 +#define PBS_UNIT_SERDES_MUX_PCIE_ALPINE_V2_SELECT_OH_PCIE_D_1_MASK 0x00003000 +#define PBS_UNIT_SERDES_MUX_PCIE_ALPINE_V2_SELECT_OH_PCIE_D_1_SHIFT 12 /**** serdes_mux_sata register ****/ /* diff --git a/al_hal_pcie.c b/al_hal_pcie.c index 3a221d36573..0ef7bc01d76 100644 --- a/al_hal_pcie.c +++ b/al_hal_pcie.c @@ -96,6 +96,8 @@ __FBSDID("$FreeBSD$"); #define AL_PCIE_PARSE_LANES(v) (((1 << v) - 1) << \ PCIE_REVX_AXI_MISC_PCIE_GLOBAL_CONF_NOF_ACT_LANES_SHIFT) +#define AL_PCIE_FLR_DONE_INTERVAL 10 + /** * Static functions */ @@ -183,10 +185,6 @@ al_pcie_port_link_config( return -EINVAL; } - al_dbg("PCIe %d: link config: max speed gen %d, max lanes %d, reversal %s\n", - pcie_port->port_id, link_params->max_speed, - pcie_port->max_lanes, link_params->enable_reversal? "enable" : "disable"); - al_pcie_port_link_speed_ctrl_set(pcie_port, link_params->max_speed); /* Change Max Payload Size, if needed. @@ -220,12 +218,6 @@ al_pcie_port_link_config( (max_lanes + (max_lanes-1)) << PCIE_PORT_LINK_CTRL_LINK_CAPABLE_SHIFT); - /* TODO: add support for reversal mode */ - if (link_params->enable_reversal) { - al_err("PCIe %d: enabling reversal mode not implemented\n", - pcie_port->port_id); - return -ENOSYS; - } return 0; } @@ -364,12 +356,9 @@ al_pcie_rev_id_get( PBS_UNIT_CHIP_ID_DEV_ID_MASK, PBS_UNIT_CHIP_ID_DEV_ID_SHIFT); - if (chip_id_dev == PBS_UNIT_CHIP_ID_DEV_ID_ALPINE) { - rev_id = AL_REG_FIELD_GET( - chip_id, - PBS_UNIT_CHIP_ID_DEV_REV_ID_MASK, - PBS_UNIT_CHIP_ID_DEV_REV_ID_SHIFT); - } else if (chip_id_dev == PBS_UNIT_CHIP_ID_DEV_ID_PEAKROCK) { + if (chip_id_dev == PBS_UNIT_CHIP_ID_DEV_ID_ALPINE_V1) { + rev_id = AL_PCIE_REV_ID_1; + } else if (chip_id_dev == PBS_UNIT_CHIP_ID_DEV_ID_ALPINE_V2) { struct al_pcie_revx_regs __iomem *regs = (struct al_pcie_revx_regs __iomem *)pcie_reg_base; uint32_t dev_id; @@ -469,20 +458,6 @@ al_pcie_ib_hcrd_os_ob_reads_config_default( al_pcie_port_ib_hcrd_os_ob_reads_config(pcie_port, &ib_hcrd_os_ob_reads_config); }; -/** return AL_TRUE is link started (LTSSM enabled) and AL_FALSE otherwise */ -static al_bool -al_pcie_is_link_started(struct al_pcie_port *pcie_port) -{ - struct al_pcie_regs *regs = (struct al_pcie_regs *)pcie_port->regs; - - uint32_t port_init = al_reg_read32(regs->app.global_ctrl.port_init); - uint8_t ltssm_en = AL_REG_FIELD_GET(port_init, - PCIE_W_GLOBAL_CTRL_PORT_INIT_APP_LTSSM_EN_MASK, - PCIE_W_GLOBAL_CTRL_PORT_INIT_APP_LTSSM_EN_SHIFT); - - return ltssm_en; -} - /** return AL_TRUE if link is up, AL_FALSE otherwise */ static al_bool al_pcie_check_link( @@ -650,18 +625,6 @@ al_pcie_port_gen3_params_config(struct al_pcie_port *pcie_port, return 0; } -static int -al_pcie_port_tl_credits_config( - struct al_pcie_port *pcie_port, - const struct al_pcie_tl_credits_params *tl_credits __attribute__((__unused__))) -{ - al_err("PCIe %d: transport layer credits config not implemented\n", - pcie_port->port_id); - - return -ENOSYS; - -} - static int al_pcie_port_pf_params_config(struct al_pcie_pf *pcie_pf, const struct al_pcie_pf_config_params *pf_params) @@ -680,22 +643,21 @@ al_pcie_port_pf_params_config(struct al_pcie_pf *pcie_pf, regs->core_space[pf_num].pcie_pm_cap_base, AL_FIELD_MASK(26, 25) | AL_FIELD_MASK(31, 28), 0); - /* Disable FLR capability */ + /* Set/Clear FLR bit */ if (pf_params->cap_flr_dis) al_reg_write32_masked( regs->core_space[pf_num].pcie_dev_cap_base, - AL_BIT(28), 0); + AL_PCI_EXP_DEVCAP_FLR, 0); + else + al_reg_write32_masked( + regs->core_space[pcie_pf->pf_num].pcie_dev_cap_base, + AL_PCI_EXP_DEVCAP_FLR, AL_PCI_EXP_DEVCAP_FLR); /* Disable ASPM capability */ if (pf_params->cap_aspm_dis) { al_reg_write32_masked( regs->core_space[pf_num].pcie_cap_base + (AL_PCI_EXP_LNKCAP >> 2), AL_PCI_EXP_LNKCAP_ASPMS, 0); - } else if (pcie_port->rev_id == AL_PCIE_REV_ID_0) { - al_warn("%s: ASPM support is enabled, please disable it\n", - __func__); - ret = -EINVAL; - goto done; } if (!pf_params->bar_params_valid) { @@ -743,8 +705,9 @@ al_pcie_port_pf_params_config(struct al_pcie_pf *pcie_pf, if (params->memory_space) { if (size < AL_PCIE_MIN_MEMORY_BAR_SIZE) { - al_err("PCIe %d: memory BAR %d: size (0x%llx) less that minimal allowed value\n", - pcie_port->port_id, bar_idx, size); + al_err("PCIe %d: memory BAR %d: size (0x%jx) less that minimal allowed value\n", + pcie_port->port_id, bar_idx, + (uintmax_t)size); ret = -EINVAL; goto done; } @@ -756,8 +719,9 @@ al_pcie_port_pf_params_config(struct al_pcie_pf *pcie_pf, } if (size < AL_PCIE_MIN_IO_BAR_SIZE) { - al_err("PCIe %d: IO BAR %d: size (0x%llx) less that minimal allowed value\n", - pcie_port->port_id, bar_idx, size); + al_err("PCIe %d: IO BAR %d: size (0x%jx) less that minimal allowed value\n", + pcie_port->port_id, bar_idx, + (uintmax_t)size); ret = -EINVAL; goto done; } @@ -765,9 +729,9 @@ al_pcie_port_pf_params_config(struct al_pcie_pf *pcie_pf, /* size must be power of 2 */ if (size & (size - 1)) { - al_err("PCIe %d: BAR %d:size (0x%llx) must be " + al_err("PCIe %d: BAR %d:size (0x%jx) must be " "power of 2\n", - pcie_port->port_id, bar_idx, size); + pcie_port->port_id, bar_idx, (uintmax_t)size); ret = -EINVAL; goto done; } @@ -826,8 +790,7 @@ al_pcie_port_pf_params_config(struct al_pcie_pf *pcie_pf, } /* Open CPU generated msi and legacy interrupts in pcie wrapper logic */ - if ((pcie_port->rev_id == AL_PCIE_REV_ID_0) || - (pcie_port->rev_id == AL_PCIE_REV_ID_1)) { + if (pcie_port->rev_id == AL_PCIE_REV_ID_1) { al_reg_write32(regs->app.soc_int[pf_num].mask_inta_leg_0, (1 << 21)); } else if ((pcie_port->rev_id == AL_PCIE_REV_ID_2) || (pcie_port->rev_id == AL_PCIE_REV_ID_3)) { @@ -853,13 +816,7 @@ al_pcie_port_pf_params_config(struct al_pcie_pf *pcie_pf, * Restore the original value after the write to app.soc.mask_msi_leg_0 * register. */ - if (pcie_port->rev_id == AL_PCIE_REV_ID_0) { - uint32_t backup; - - backup = al_reg_read32(®s->app.int_grp_a->mask); - al_reg_write32(regs->app.soc_int[pf_num].mask_msi_leg_0, (1 << 22)); - al_reg_write32(®s->app.int_grp_a->mask, backup); - } else if (pcie_port->rev_id == AL_PCIE_REV_ID_1) { + if (pcie_port->rev_id == AL_PCIE_REV_ID_1) { al_reg_write32(regs->app.soc_int[pf_num].mask_msi_leg_0, (1 << 22)); } else if ((pcie_port->rev_id == AL_PCIE_REV_ID_2) || (pcie_port->rev_id == AL_PCIE_REV_ID_3)) { @@ -878,22 +835,6 @@ done: return ret; } -static void -al_pcie_port_features_config( - struct al_pcie_port *pcie_port, - const struct al_pcie_features *features) -{ - struct al_pcie_regs *regs = pcie_port->regs; - - al_assert(pcie_port->rev_id > AL_PCIE_REV_ID_0); - - al_reg_write32_masked( - ®s->app.ctrl_gen->features, - PCIE_W_CTRL_GEN_FEATURES_SATA_EP_MSI_FIX, - features->sata_ep_msi_fix ? - PCIE_W_CTRL_GEN_FEATURES_SATA_EP_MSI_FIX : 0); -} - static int al_pcie_port_sris_config( struct al_pcie_port *pcie_port, @@ -916,6 +857,9 @@ al_pcie_port_sris_config( switch (pcie_port->rev_id) { case AL_PCIE_REV_ID_3: + al_reg_write32_masked(®s->app.cfg_func_ext->cfg, + PCIE_W_CFG_FUNC_EXT_CFG_APP_SRIS_MODE, + PCIE_W_CFG_FUNC_EXT_CFG_APP_SRIS_MODE); case AL_PCIE_REV_ID_2: al_reg_write32_masked(regs->app.global_ctrl.sris_kp_counter, PCIE_W_GLOBAL_CTRL_SRIS_KP_COUNTER_VALUE_GEN3_SRIS_MASK | @@ -989,6 +933,34 @@ al_pcie_port_max_num_of_pfs_get(struct al_pcie_port *pcie_port) return 1; } +/** Enable ecrc generation in outbound atu (Addressing RMN: 5119) */ +static void al_pcie_ecrc_gen_ob_atu_enable(struct al_pcie_port *pcie_port, unsigned int pf_num) +{ + struct al_pcie_regs *regs = pcie_port->regs; + int max_ob_atu = (pcie_port->rev_id == AL_PCIE_REV_ID_3) ? + AL_PCIE_REV_3_ATU_NUM_OUTBOUND_REGIONS : AL_PCIE_REV_1_2_ATU_NUM_OUTBOUND_REGIONS; + int i; + for (i = 0; i < max_ob_atu; i++) { + al_bool enable = 0; + uint32_t reg = 0; + unsigned int func_num; + AL_REG_FIELD_SET(reg, 0xF, 0, i); + AL_REG_BIT_VAL_SET(reg, 31, AL_PCIE_ATU_DIR_OUTBOUND); + al_reg_write32(®s->port_regs->iatu.index, reg); + reg = al_reg_read32(®s->port_regs->iatu.cr2); + enable = AL_REG_BIT_GET(reg, 31) ? AL_TRUE : AL_FALSE; + reg = al_reg_read32(®s->port_regs->iatu.cr1); + func_num = AL_REG_FIELD_GET(reg, + PCIE_IATU_CR1_FUNC_NUM_MASK, + PCIE_IATU_CR1_FUNC_NUM_SHIFT); + if ((enable == AL_TRUE) && (pf_num == func_num)) { + /* Set TD bit */ + AL_REG_BIT_SET(reg, 8); + al_reg_write32(®s->port_regs->iatu.cr1, reg); + } + } +} + /******************************************************************************/ /***************************** API Implementation *****************************/ /******************************************************************************/ @@ -1025,12 +997,13 @@ al_pcie_port_handle_init( /* Zero all regs */ al_memset(pcie_port->regs, 0, sizeof(struct al_pcie_regs)); - if ((pcie_port->rev_id == AL_PCIE_REV_ID_0) || - (pcie_port->rev_id == AL_PCIE_REV_ID_1)) { + if (pcie_port->rev_id == AL_PCIE_REV_ID_1) { struct al_pcie_rev1_regs __iomem *regs = (struct al_pcie_rev1_regs __iomem *)pcie_reg_base; pcie_port->regs->axi.ctrl.global = ®s->axi.ctrl.global; + pcie_port->regs->axi.ctrl.master_rctl = ®s->axi.ctrl.master_rctl; + pcie_port->regs->axi.ctrl.master_ctl = ®s->axi.ctrl.master_ctl; pcie_port->regs->axi.ctrl.master_arctl = ®s->axi.ctrl.master_arctl; pcie_port->regs->axi.ctrl.master_awctl = ®s->axi.ctrl.master_awctl; pcie_port->regs->axi.ctrl.slv_ctl = ®s->axi.ctrl.slv_ctl; @@ -1059,20 +1032,21 @@ al_pcie_port_handle_init( pcie_port->regs->app.global_ctrl.pm_control = ®s->app.global_ctrl.pm_control; pcie_port->regs->app.global_ctrl.events_gen[0] = ®s->app.global_ctrl.events_gen; pcie_port->regs->app.debug = ®s->app.debug; + pcie_port->regs->app.soc_int[0].status_0 = ®s->app.soc_int.status_0; + pcie_port->regs->app.soc_int[0].status_1 = ®s->app.soc_int.status_1; + pcie_port->regs->app.soc_int[0].status_2 = ®s->app.soc_int.status_2; pcie_port->regs->app.soc_int[0].mask_inta_leg_0 = ®s->app.soc_int.mask_inta_leg_0; + pcie_port->regs->app.soc_int[0].mask_inta_leg_1 = ®s->app.soc_int.mask_inta_leg_1; + pcie_port->regs->app.soc_int[0].mask_inta_leg_2 = ®s->app.soc_int.mask_inta_leg_2; pcie_port->regs->app.soc_int[0].mask_msi_leg_0 = ®s->app.soc_int.mask_msi_leg_0; + pcie_port->regs->app.soc_int[0].mask_msi_leg_1 = ®s->app.soc_int.mask_msi_leg_1; + pcie_port->regs->app.soc_int[0].mask_msi_leg_2 = ®s->app.soc_int.mask_msi_leg_2; pcie_port->regs->app.ctrl_gen = ®s->app.ctrl_gen; pcie_port->regs->app.parity = ®s->app.parity; pcie_port->regs->app.atu.in_mask_pair = regs->app.atu.in_mask_pair; pcie_port->regs->app.atu.out_mask_pair = regs->app.atu.out_mask_pair; - - if (pcie_port->rev_id == AL_PCIE_REV_ID_0) { - pcie_port->regs->app.int_grp_a = ®s->app.int_grp_a_m0; - pcie_port->regs->app.int_grp_b = ®s->app.int_grp_b_m0; - } else { - pcie_port->regs->app.int_grp_a = ®s->app.int_grp_a; - pcie_port->regs->app.int_grp_b = ®s->app.int_grp_b; - } + pcie_port->regs->app.int_grp_a = ®s->app.int_grp_a; + pcie_port->regs->app.int_grp_b = ®s->app.int_grp_b; pcie_port->regs->core_space[0].config_header = regs->core_space.config_header; pcie_port->regs->core_space[0].pcie_pm_cap_base = ®s->core_space.pcie_pm_cap_base; @@ -1091,6 +1065,8 @@ al_pcie_port_handle_init( (struct al_pcie_rev2_regs __iomem *)pcie_reg_base; pcie_port->regs->axi.ctrl.global = ®s->axi.ctrl.global; + pcie_port->regs->axi.ctrl.master_rctl = ®s->axi.ctrl.master_rctl; + pcie_port->regs->axi.ctrl.master_ctl = ®s->axi.ctrl.master_ctl; pcie_port->regs->axi.ctrl.master_arctl = ®s->axi.ctrl.master_arctl; pcie_port->regs->axi.ctrl.master_awctl = ®s->axi.ctrl.master_awctl; pcie_port->regs->axi.ctrl.slv_ctl = ®s->axi.ctrl.slv_ctl; @@ -1100,6 +1076,10 @@ al_pcie_port_handle_init( pcie_port->regs->axi.ob_ctrl.io_start_h = ®s->axi.ob_ctrl.io_start_h; pcie_port->regs->axi.ob_ctrl.io_limit_l = ®s->axi.ob_ctrl.io_limit_l; pcie_port->regs->axi.ob_ctrl.io_limit_h = ®s->axi.ob_ctrl.io_limit_h; + pcie_port->regs->axi.ob_ctrl.tgtid_reg_ovrd = ®s->axi.ob_ctrl.tgtid_reg_ovrd; + pcie_port->regs->axi.ob_ctrl.addr_high_reg_ovrd_sel = ®s->axi.ob_ctrl.addr_high_reg_ovrd_sel; + pcie_port->regs->axi.ob_ctrl.addr_high_reg_ovrd_value = ®s->axi.ob_ctrl.addr_high_reg_ovrd_value; + pcie_port->regs->axi.ob_ctrl.addr_size_replace = ®s->axi.ob_ctrl.addr_size_replace; pcie_port->regs->axi.pcie_global.conf = ®s->axi.pcie_global.conf; pcie_port->regs->axi.conf.zero_lane0 = ®s->axi.conf.zero_lane0; pcie_port->regs->axi.conf.zero_lane1 = ®s->axi.conf.zero_lane1; @@ -1120,11 +1100,20 @@ al_pcie_port_handle_init( pcie_port->regs->app.global_ctrl.events_gen[0] = ®s->app.global_ctrl.events_gen; pcie_port->regs->app.global_ctrl.corr_err_sts_int = ®s->app.global_ctrl.pended_corr_err_sts_int; pcie_port->regs->app.global_ctrl.uncorr_err_sts_int = ®s->app.global_ctrl.pended_uncorr_err_sts_int; + pcie_port->regs->app.global_ctrl.sris_kp_counter = ®s->app.global_ctrl.sris_kp_counter_value; pcie_port->regs->app.debug = ®s->app.debug; pcie_port->regs->app.ap_user_send_msg = ®s->app.ap_user_send_msg; + pcie_port->regs->app.soc_int[0].status_0 = ®s->app.soc_int.status_0; + pcie_port->regs->app.soc_int[0].status_1 = ®s->app.soc_int.status_1; + pcie_port->regs->app.soc_int[0].status_2 = ®s->app.soc_int.status_2; + pcie_port->regs->app.soc_int[0].status_3 = ®s->app.soc_int.status_3; pcie_port->regs->app.soc_int[0].mask_inta_leg_0 = ®s->app.soc_int.mask_inta_leg_0; + pcie_port->regs->app.soc_int[0].mask_inta_leg_1 = ®s->app.soc_int.mask_inta_leg_1; + pcie_port->regs->app.soc_int[0].mask_inta_leg_2 = ®s->app.soc_int.mask_inta_leg_2; pcie_port->regs->app.soc_int[0].mask_inta_leg_3 = ®s->app.soc_int.mask_inta_leg_3; pcie_port->regs->app.soc_int[0].mask_msi_leg_0 = ®s->app.soc_int.mask_msi_leg_0; + pcie_port->regs->app.soc_int[0].mask_msi_leg_1 = ®s->app.soc_int.mask_msi_leg_1; + pcie_port->regs->app.soc_int[0].mask_msi_leg_2 = ®s->app.soc_int.mask_msi_leg_2; pcie_port->regs->app.soc_int[0].mask_msi_leg_3 = ®s->app.soc_int.mask_msi_leg_3; pcie_port->regs->app.ctrl_gen = ®s->app.ctrl_gen; pcie_port->regs->app.parity = ®s->app.parity; @@ -1150,6 +1139,8 @@ al_pcie_port_handle_init( struct al_pcie_rev3_regs __iomem *regs = (struct al_pcie_rev3_regs __iomem *)pcie_reg_base; pcie_port->regs->axi.ctrl.global = ®s->axi.ctrl.global; + pcie_port->regs->axi.ctrl.master_rctl = ®s->axi.ctrl.master_rctl; + pcie_port->regs->axi.ctrl.master_ctl = ®s->axi.ctrl.master_ctl; pcie_port->regs->axi.ctrl.master_arctl = ®s->axi.ctrl.master_arctl; pcie_port->regs->axi.ctrl.master_awctl = ®s->axi.ctrl.master_awctl; pcie_port->regs->axi.ctrl.slv_ctl = ®s->axi.ctrl.slv_ctl; @@ -1159,6 +1150,13 @@ al_pcie_port_handle_init( pcie_port->regs->axi.ob_ctrl.io_start_h = ®s->axi.ob_ctrl.io_start_h; pcie_port->regs->axi.ob_ctrl.io_limit_l = ®s->axi.ob_ctrl.io_limit_l; pcie_port->regs->axi.ob_ctrl.io_limit_h = ®s->axi.ob_ctrl.io_limit_h; + pcie_port->regs->axi.ob_ctrl.io_addr_mask_h = ®s->axi.ob_ctrl.io_addr_mask_h; + pcie_port->regs->axi.ob_ctrl.ar_msg_addr_mask_h = ®s->axi.ob_ctrl.ar_msg_addr_mask_h; + pcie_port->regs->axi.ob_ctrl.aw_msg_addr_mask_h = ®s->axi.ob_ctrl.aw_msg_addr_mask_h; + pcie_port->regs->axi.ob_ctrl.tgtid_reg_ovrd = ®s->axi.ob_ctrl.tgtid_reg_ovrd; + pcie_port->regs->axi.ob_ctrl.addr_high_reg_ovrd_sel = ®s->axi.ob_ctrl.addr_high_reg_ovrd_sel; + pcie_port->regs->axi.ob_ctrl.addr_high_reg_ovrd_value = ®s->axi.ob_ctrl.addr_high_reg_ovrd_value; + pcie_port->regs->axi.ob_ctrl.addr_size_replace = ®s->axi.ob_ctrl.addr_size_replace; pcie_port->regs->axi.pcie_global.conf = ®s->axi.pcie_global.conf; pcie_port->regs->axi.conf.zero_lane0 = ®s->axi.conf.zero_lane0; pcie_port->regs->axi.conf.zero_lane1 = ®s->axi.conf.zero_lane1; @@ -1213,9 +1211,17 @@ al_pcie_port_handle_init( pcie_port->regs->app.debug = ®s->app.debug; for (i = 0; i < AL_MAX_NUM_OF_PFS; i++) { + pcie_port->regs->app.soc_int[i].status_0 = ®s->app.soc_int_per_func[i].status_0; + pcie_port->regs->app.soc_int[i].status_1 = ®s->app.soc_int_per_func[i].status_1; + pcie_port->regs->app.soc_int[i].status_2 = ®s->app.soc_int_per_func[i].status_2; + pcie_port->regs->app.soc_int[i].status_3 = ®s->app.soc_int_per_func[i].status_3; pcie_port->regs->app.soc_int[i].mask_inta_leg_0 = ®s->app.soc_int_per_func[i].mask_inta_leg_0; + pcie_port->regs->app.soc_int[i].mask_inta_leg_1 = ®s->app.soc_int_per_func[i].mask_inta_leg_1; + pcie_port->regs->app.soc_int[i].mask_inta_leg_2 = ®s->app.soc_int_per_func[i].mask_inta_leg_2; pcie_port->regs->app.soc_int[i].mask_inta_leg_3 = ®s->app.soc_int_per_func[i].mask_inta_leg_3; pcie_port->regs->app.soc_int[i].mask_msi_leg_0 = ®s->app.soc_int_per_func[i].mask_msi_leg_0; + pcie_port->regs->app.soc_int[i].mask_msi_leg_1 = ®s->app.soc_int_per_func[i].mask_msi_leg_1; + pcie_port->regs->app.soc_int[i].mask_msi_leg_2 = ®s->app.soc_int_per_func[i].mask_msi_leg_2; pcie_port->regs->app.soc_int[i].mask_msi_leg_3 = ®s->app.soc_int_per_func[i].mask_msi_leg_3; } @@ -1224,6 +1230,7 @@ al_pcie_port_handle_init( pcie_port->regs->app.parity = ®s->app.parity; pcie_port->regs->app.atu.in_mask_pair = regs->app.atu.in_mask_pair; pcie_port->regs->app.atu.out_mask_pair = regs->app.atu.out_mask_pair; + pcie_port->regs->app.cfg_func_ext = ®s->app.cfg_func_ext; for (i = 0; i < AL_MAX_NUM_OF_PFS; i++) pcie_port->regs->app.status_per_func[i] = ®s->app.status_per_func[i]; @@ -1260,6 +1267,10 @@ al_pcie_port_handle_init( /* set maximum number of physical functions */ pcie_port->max_num_of_pfs = al_pcie_port_max_num_of_pfs_get(pcie_port); + /* Clear 'nof_p_hdr' & 'nof_np_hdr' to later know if they where changed by the user */ + pcie_port->ib_hcrd_config.nof_np_hdr = 0; + pcie_port->ib_hcrd_config.nof_p_hdr = 0; + al_dbg("pcie port handle initialized. port id: %d, rev_id %d, regs base %p\n", port_id, pcie_port->rev_id, pcie_reg_base); return 0; @@ -1294,6 +1305,12 @@ al_pcie_pf_handle_init( return 0; } +/** Get port revision ID */ +int al_pcie_port_rev_id_get(struct al_pcie_port *pcie_port) +{ + return pcie_port->rev_id; +} + /************************** Pre PCIe Port Enable API **************************/ /** configure pcie operating mode (root complex or endpoint) */ @@ -1346,7 +1363,7 @@ al_pcie_port_operating_mode_config( "EndPoint" : "Root Complex"); return 0; } - al_info("PCIe %d: set operating mode to %s\n", + al_dbg("PCIe %d: set operating mode to %s\n", pcie_port->port_id, (mode == AL_PCIE_OPERATING_MODE_EP) ? "EndPoint" : "Root Complex"); AL_REG_FIELD_SET(reg, PCIE_AXI_MISC_PCIE_GLOBAL_CONF_DEV_TYPE_MASK, @@ -1362,6 +1379,7 @@ int al_pcie_port_max_lanes_set(struct al_pcie_port *pcie_port, uint8_t lanes) { struct al_pcie_regs *regs = pcie_port->regs; + uint32_t active_lanes_val; if (al_pcie_port_is_enabled(pcie_port)) { al_err("PCIe %d: already enabled, cannot set max lanes\n", @@ -1370,7 +1388,7 @@ al_pcie_port_max_lanes_set(struct al_pcie_port *pcie_port, uint8_t lanes) } /* convert to bitmask format (4 ->'b1111, 2 ->'b11, 1 -> 'b1) */ - uint32_t active_lanes_val = AL_PCIE_PARSE_LANES(lanes); + active_lanes_val = AL_PCIE_PARSE_LANES(lanes); al_reg_write32_masked(regs->axi.pcie_global.conf, (pcie_port->rev_id == AL_PCIE_REV_ID_3) ? @@ -1387,11 +1405,7 @@ al_pcie_port_max_num_of_pfs_set( struct al_pcie_port *pcie_port, uint8_t max_num_of_pfs) { - if (al_pcie_port_is_enabled(pcie_port)) { - al_err("PCIe %d: already enabled, cannot set max num of PFs\n", - pcie_port->port_id); - return -EINVAL; - } + struct al_pcie_regs *regs = pcie_port->regs; if (pcie_port->rev_id == AL_PCIE_REV_ID_3) al_assert(max_num_of_pfs <= REV3_MAX_NUM_OF_PFS); @@ -1400,6 +1414,33 @@ al_pcie_port_max_num_of_pfs_set( pcie_port->max_num_of_pfs = max_num_of_pfs; + if (al_pcie_port_is_enabled(pcie_port) && (pcie_port->rev_id == AL_PCIE_REV_ID_3)) { + enum al_pcie_operating_mode op_mode = al_pcie_operating_mode_get(pcie_port); + + al_bool is_multi_pf = + ((op_mode == AL_PCIE_OPERATING_MODE_EP) && (pcie_port->max_num_of_pfs > 1)); + + /* Set maximum physical function numbers */ + al_reg_write32_masked( + ®s->port_regs->timer_ctrl_max_func_num, + PCIE_PORT_GEN3_MAX_FUNC_NUM, + pcie_port->max_num_of_pfs - 1); + + al_pcie_port_wr_to_ro_set(pcie_port, AL_TRUE); + + /** + * in EP mode, when we have more than 1 PF we need to assert + * multi-pf support so the host scan all PFs + */ + al_reg_write32_masked((uint32_t __iomem *) + (®s->core_space[0].config_header[0] + + (PCIE_BIST_HEADER_TYPE_BASE >> 2)), + PCIE_BIST_HEADER_TYPE_MULTI_FUNC_MASK, + is_multi_pf ? PCIE_BIST_HEADER_TYPE_MULTI_FUNC_MASK : 0); + + al_pcie_port_wr_to_ro_set(pcie_port, AL_FALSE); + } + return 0; } @@ -1503,6 +1544,28 @@ al_pcie_operating_mode_get( return AL_PCIE_OPERATING_MODE_UNKNOWN; } +/* PCIe AXI quality of service configuration */ +void al_pcie_axi_qos_config( + struct al_pcie_port *pcie_port, + unsigned int arqos, + unsigned int awqos) +{ + struct al_pcie_regs *regs = pcie_port->regs; + + al_assert(pcie_port); + al_assert(arqos <= PCIE_AXI_CTRL_MASTER_ARCTL_ARQOS_VAL_MAX); + al_assert(awqos <= PCIE_AXI_CTRL_MASTER_AWCTL_AWQOS_VAL_MAX); + + al_reg_write32_masked( + regs->axi.ctrl.master_arctl, + PCIE_AXI_CTRL_MASTER_ARCTL_ARQOS_MASK, + arqos << PCIE_AXI_CTRL_MASTER_ARCTL_ARQOS_SHIFT); + al_reg_write32_masked( + regs->axi.ctrl.master_awctl, + PCIE_AXI_CTRL_MASTER_AWCTL_AWQOS_MASK, + awqos << PCIE_AXI_CTRL_MASTER_AWCTL_AWQOS_SHIFT); +} + /**************************** PCIe Port Enable API ****************************/ /** Enable PCIe port (deassert reset) */ @@ -1518,17 +1581,19 @@ al_pcie_port_enable(struct al_pcie_port *pcie_port) /** * Set inbound header credit and outstanding outbound reads defaults + * if the port initiator doesn't set it. * Must be called before port enable (PCIE_EXIST) */ - al_pcie_ib_hcrd_os_ob_reads_config_default(pcie_port); + if ((pcie_port->ib_hcrd_config.nof_np_hdr == 0) || + (pcie_port->ib_hcrd_config.nof_p_hdr == 0)) + al_pcie_ib_hcrd_os_ob_reads_config_default(pcie_port); /* * Disable ATS capability * - must be done before core reset deasserted * - rev_id 0 - no effect, but no harm */ - if ((pcie_port->rev_id == AL_PCIE_REV_ID_0) || - (pcie_port->rev_id == AL_PCIE_REV_ID_1) || + if ((pcie_port->rev_id == AL_PCIE_REV_ID_1) || (pcie_port->rev_id == AL_PCIE_REV_ID_2)) { al_reg_write32_masked( regs->axi.ordering.pos_cntl, @@ -1679,26 +1744,8 @@ al_pcie_port_config(struct al_pcie_port *pcie_port, } if (pcie_port->rev_id == AL_PCIE_REV_ID_3) { - /* Set maximum physical function numbers */ - al_reg_write32_masked( - ®s->port_regs->timer_ctrl_max_func_num, - PCIE_PORT_GEN3_MAX_FUNC_NUM, - pcie_port->max_num_of_pfs - 1); - al_pcie_port_wr_to_ro_set(pcie_port, AL_TRUE); - /** - * in EP mode, when we have more than 1 PF we need to assert - * multi-pf support so the host scan all PFs - */ - if ((op_mode == AL_PCIE_OPERATING_MODE_EP) && (pcie_port->max_num_of_pfs > 1)) { - al_reg_write32_masked((uint32_t __iomem *) - (®s->core_space[0].config_header[0] + - (PCIE_BIST_HEADER_TYPE_BASE >> 2)), - PCIE_BIST_HEADER_TYPE_MULTI_FUNC_MASK, - PCIE_BIST_HEADER_TYPE_MULTI_FUNC_MASK); - } - /* Disable TPH next pointer */ for (i = 0; i < AL_MAX_NUM_OF_PFS; i++) { al_reg_write32_masked(regs->core_space[i].tph_cap_base, @@ -1713,6 +1760,8 @@ al_pcie_port_config(struct al_pcie_port *pcie_port, if (status) goto done; + al_pcie_port_max_num_of_pfs_set(pcie_port, pcie_port->max_num_of_pfs); + al_pcie_port_ram_parity_int_config(pcie_port, params->enable_ram_parity_int); al_pcie_port_axi_parity_int_config(pcie_port, params->enable_axi_parity_int); @@ -1734,14 +1783,6 @@ al_pcie_port_config(struct al_pcie_port *pcie_port, if (status) goto done; - if (params->tl_credits) - status = al_pcie_port_tl_credits_config(pcie_port, params->tl_credits); - if (status) - goto done; - - if (params->features) - al_pcie_port_features_config(pcie_port, params->features); - if (params->sris_params) status = al_pcie_port_sris_config(pcie_port, params->sris_params, params->link_params->max_speed); @@ -1904,6 +1945,19 @@ al_pcie_link_stop(struct al_pcie_port *pcie_port) return 0; } +/** return AL_TRUE is link started (LTSSM enabled) and AL_FALSE otherwise */ +al_bool al_pcie_is_link_started(struct al_pcie_port *pcie_port) +{ + struct al_pcie_regs *regs = (struct al_pcie_regs *)pcie_port->regs; + + uint32_t port_init = al_reg_read32(regs->app.global_ctrl.port_init); + uint8_t ltssm_en = AL_REG_FIELD_GET(port_init, + PCIE_W_GLOBAL_CTRL_PORT_INIT_APP_LTSSM_EN_MASK, + PCIE_W_GLOBAL_CTRL_PORT_INIT_APP_LTSSM_EN_SHIFT); + + return ltssm_en; +} + /* wait for link up indication */ int al_pcie_link_up_wait(struct al_pcie_port *pcie_port, uint32_t timeout_ms) @@ -1912,7 +1966,7 @@ al_pcie_link_up_wait(struct al_pcie_port *pcie_port, uint32_t timeout_ms) while (wait_count-- > 0) { if (al_pcie_check_link(pcie_port, NULL)) { - al_info("PCIe_%d: <<<<<<<<< Link up >>>>>>>>>\n", pcie_port->port_id); + al_dbg("PCIe_%d: <<<<<<<<< Link up >>>>>>>>>\n", pcie_port->port_id); return 0; } else al_dbg("PCIe_%d: No link up, %d attempts remaining\n", @@ -1920,7 +1974,7 @@ al_pcie_link_up_wait(struct al_pcie_port *pcie_port, uint32_t timeout_ms) al_udelay(AL_PCIE_LINKUP_WAIT_INTERVAL); } - al_info("PCIE_%d: link is not established in time\n", + al_dbg("PCIE_%d: link is not established in time\n", pcie_port->port_id); return ETIMEDOUT; @@ -1936,6 +1990,15 @@ al_pcie_link_status(struct al_pcie_port *pcie_port, al_assert(status); + if (!al_pcie_port_is_enabled(pcie_port)) { + al_dbg("PCIe %d: port not enabled, no link.\n", pcie_port->port_id); + status->link_up = AL_FALSE; + status->speed = AL_PCIE_LINK_SPEED_DEFAULT; + status->lanes = 0; + status->ltssm_state = 0; + return 0; + } + status->link_up = al_pcie_check_link(pcie_port, &status->ltssm_state); if (!status->link_up) { @@ -1962,7 +2025,7 @@ al_pcie_link_status(struct al_pcie_port *pcie_port, pcie_port->port_id, pcie_lnksta); } status->lanes = (pcie_lnksta & AL_PCI_EXP_LNKSTA_NLW) >> AL_PCI_EXP_LNKSTA_NLW_SHIFT; - al_info("PCIe %d: Link up. speed gen%d negotiated width %d\n", + al_dbg("PCIe %d: Link up. speed gen%d negotiated width %d\n", pcie_port->port_id, status->speed, status->lanes); return 0; @@ -2143,7 +2206,7 @@ al_pcie_port_snoop_config(struct al_pcie_port *pcie_port, al_bool enable_axi_sno struct al_pcie_regs *regs = pcie_port->regs; /* Set snoop mode */ - al_info("PCIE_%d: snoop mode %s\n", + al_dbg("PCIE_%d: snoop mode %s\n", pcie_port->port_id, enable_axi_snoop ? "enable" : "disable"); if (enable_axi_snoop) { @@ -2311,6 +2374,19 @@ al_pcie_app_req_retry_set( mask, (en == AL_TRUE) ? mask : 0); } +/* Check if deferring incoming configuration requests is enabled or not */ +al_bool al_pcie_app_req_retry_get_status(struct al_pcie_port *pcie_port) +{ + struct al_pcie_regs *regs = pcie_port->regs; + uint32_t pm_control; + uint32_t mask = (pcie_port->rev_id == AL_PCIE_REV_ID_3) ? + PCIE_W_REV3_GLOBAL_CTRL_PM_CONTROL_APP_REQ_RETRY_EN : + PCIE_W_REV1_2_GLOBAL_CTRL_PM_CONTROL_APP_REQ_RETRY_EN; + + pm_control = al_reg_read32(regs->app.global_ctrl.pm_control); + return (pm_control & mask) ? AL_TRUE : AL_FALSE; +} + /*************** Internal Address Translation Unit (ATU) API ******************/ /** program internal ATU region entry */ @@ -2345,6 +2421,7 @@ al_pcie_atu_region_set( if (!atu_region->enforce_ob_atu_region_set) { al_err("PCIe %d: setting OB iATU after link is started is not allowed\n", pcie_port->port_id); + al_assert(AL_FALSE); return -EINVAL; } else { al_info("PCIe %d: setting OB iATU even after link is started\n", @@ -2369,7 +2446,63 @@ al_pcie_atu_region_set( /* configure the limit, not needed when working in BAR match mode */ if (atu_region->match_mode == 0) { uint32_t limit_reg_val; - if (pcie_port->rev_id > AL_PCIE_REV_ID_0) { + uint32_t *limit_ext_reg = + (atu_region->direction == AL_PCIE_ATU_DIR_OUTBOUND) ? + ®s->app.atu.out_mask_pair[atu_region->index / 2] : + ®s->app.atu.in_mask_pair[atu_region->index / 2]; + uint32_t limit_ext_reg_mask = + (atu_region->index % 2) ? + PCIE_W_ATU_MASK_EVEN_ODD_ATU_MASK_40_32_ODD_MASK : + PCIE_W_ATU_MASK_EVEN_ODD_ATU_MASK_40_32_EVEN_MASK; + unsigned int limit_ext_reg_shift = + (atu_region->index % 2) ? + PCIE_W_ATU_MASK_EVEN_ODD_ATU_MASK_40_32_ODD_SHIFT : + PCIE_W_ATU_MASK_EVEN_ODD_ATU_MASK_40_32_EVEN_SHIFT; + uint64_t limit_sz_msk = + atu_region->limit - atu_region->base_addr; + uint32_t limit_ext_reg_val = (uint32_t)(((limit_sz_msk) >> + 32) & 0xFFFFFFFF); + + if (limit_ext_reg_val) { + limit_reg_val = (uint32_t)((limit_sz_msk) & 0xFFFFFFFF); + al_assert(limit_reg_val == 0xFFFFFFFF); + } else { + limit_reg_val = (uint32_t)(atu_region->limit & + 0xFFFFFFFF); + } + + al_reg_write32_masked( + limit_ext_reg, + limit_ext_reg_mask, + limit_ext_reg_val << limit_ext_reg_shift); + + al_reg_write32(®s->port_regs->iatu.limit_addr, + limit_reg_val); + } + + + /** + * Addressing RMN: 3186 + * + * RMN description: + * Bug in SNPS IP (versions 4.21 , 4.10a-ea02) + * In CFG request created via outbound atu (shift mode) bits [27:12] go to + * [31:16] , the shifting is correct , however the ATU leaves bit [15:12] + * to their original values, this is then transmited in the tlp . + * Those bits are currently reserved ,bit might be non-resv. in future generations . + * + * Software flow: + * Enable HW fix + * rev=REV1,REV2 set bit 15 in corresponding app_reg.atu.out_mask + * rev>REV2 set corresponding bit is app_reg.atu.reg_out_mask + */ + if ((atu_region->cfg_shift_mode == AL_TRUE) && + (atu_region->direction == AL_PCIE_ATU_DIR_OUTBOUND)) { + if (pcie_port->rev_id > AL_PCIE_REV_ID_2) { + al_reg_write32_masked(regs->app.atu.reg_out_mask, + 1 << (atu_region->index) , + 1 << (atu_region->index)); + } else { uint32_t *limit_ext_reg = (atu_region->direction == AL_PCIE_ATU_DIR_OUTBOUND) ? ®s->app.atu.out_mask_pair[atu_region->index / 2] : @@ -2382,29 +2515,12 @@ al_pcie_atu_region_set( (atu_region->index % 2) ? PCIE_W_ATU_MASK_EVEN_ODD_ATU_MASK_40_32_ODD_SHIFT : PCIE_W_ATU_MASK_EVEN_ODD_ATU_MASK_40_32_EVEN_SHIFT; - uint64_t limit_sz_msk = - atu_region->limit - atu_region->base_addr; - uint32_t limit_ext_reg_val = (uint32_t)(((limit_sz_msk) >> - 32) & 0xFFFFFFFF); - - if (limit_ext_reg_val) { - limit_reg_val = (uint32_t)((limit_sz_msk) & 0xFFFFFFFF); - al_assert(limit_reg_val == 0xFFFFFFFF); - } else { - limit_reg_val = (uint32_t)(atu_region->limit & - 0xFFFFFFFF); - } al_reg_write32_masked( - limit_ext_reg, - limit_ext_reg_mask, - limit_ext_reg_val << limit_ext_reg_shift); - } else { - limit_reg_val = (uint32_t)(atu_region->limit & 0xFFFFFFFF); + limit_ext_reg, + limit_ext_reg_mask, + (AL_BIT(15)) << limit_ext_reg_shift); } - - al_reg_write32(®s->port_regs->iatu.limit_addr, - limit_reg_val); } reg = 0; @@ -2505,7 +2621,22 @@ al_pcie_axi_io_config( PCIE_AXI_CTRL_SLV_CTRL_IO_BAR_EN); } -/************** Interrupt generation (Endpoint mode Only) API *****************/ +/************** Interrupt and Event generation (Endpoint mode Only) API *****************/ + +int al_pcie_pf_flr_done_gen(struct al_pcie_pf *pcie_pf) +{ + struct al_pcie_regs *regs = pcie_pf->pcie_port->regs; + unsigned int pf_num = pcie_pf->pf_num; + + al_reg_write32_masked(regs->app.global_ctrl.events_gen[pf_num], + PCIE_W_GLOBAL_CTRL_EVENTS_GEN_FLR_PF_DONE, + PCIE_W_GLOBAL_CTRL_EVENTS_GEN_FLR_PF_DONE); + al_udelay(AL_PCIE_FLR_DONE_INTERVAL); + al_reg_write32_masked(regs->app.global_ctrl.events_gen[pf_num], + PCIE_W_GLOBAL_CTRL_EVENTS_GEN_FLR_PF_DONE, 0); + return 0; +} + /** generate INTx Assert/DeAssert Message */ int @@ -2607,15 +2738,16 @@ al_pcie_msix_masked(struct al_pcie_pf *pcie_pf) } /******************** Advanced Error Reporting (AER) API **********************/ - -/** configure AER capability */ -int -al_pcie_aer_config( - struct al_pcie_pf *pcie_pf, - struct al_pcie_aer_params *params) +/************************* Auxiliary functions ********************************/ +/* configure AER capability */ +static int +al_pcie_aer_config_aux( + struct al_pcie_port *pcie_port, + unsigned int pf_num, + struct al_pcie_aer_params *params) { - struct al_pcie_regs *regs = pcie_pf->pcie_port->regs; - struct al_pcie_core_aer_regs *aer_regs = regs->core_space[pcie_pf->pf_num].aer; + struct al_pcie_regs *regs = pcie_port->regs; + struct al_pcie_core_aer_regs *aer_regs = regs->core_space[pf_num].aer; uint32_t reg_val; reg_val = al_reg_read32(&aer_regs->header); @@ -2641,8 +2773,22 @@ al_pcie_aer_config( (params->ecrc_gen_en ? PCIE_AER_CTRL_STAT_ECRC_GEN_EN : 0) | (params->ecrc_chk_en ? PCIE_AER_CTRL_STAT_ECRC_CHK_EN : 0)); + /** + * Addressing RMN: 5119 + * + * RMN description: + * ECRC generation for outbound request translated by iATU is effected + * by iATU setting instead of ecrc_gen_bit in AER + * + * Software flow: + * When enabling ECRC generation, set the outbound iATU to generate ECRC + */ + if (params->ecrc_gen_en == AL_TRUE) { + al_pcie_ecrc_gen_ob_atu_enable(pcie_port, pf_num); + } + al_reg_write32_masked( - regs->core_space[pcie_pf->pf_num].pcie_dev_ctrl_status, + regs->core_space[pf_num].pcie_dev_ctrl_status, PCIE_PORT_DEV_CTRL_STATUS_CORR_ERR_REPORT_EN | PCIE_PORT_DEV_CTRL_STATUS_NON_FTL_ERR_REPORT_EN | PCIE_PORT_DEV_CTRL_STATUS_FTL_ERR_REPORT_EN | @@ -2663,12 +2809,14 @@ al_pcie_aer_config( return 0; } -/** AER uncorretable errors get and clear */ -unsigned int -al_pcie_aer_uncorr_get_and_clear(struct al_pcie_pf *pcie_pf) +/** AER uncorrectable errors get and clear */ +static unsigned int +al_pcie_aer_uncorr_get_and_clear_aux( + struct al_pcie_port *pcie_port, + unsigned int pf_num) { - struct al_pcie_regs *regs = pcie_pf->pcie_port->regs; - struct al_pcie_core_aer_regs *aer_regs = regs->core_space[pcie_pf->pf_num].aer; + struct al_pcie_regs *regs = pcie_port->regs; + struct al_pcie_core_aer_regs *aer_regs = regs->core_space[pf_num].aer; uint32_t reg_val; reg_val = al_reg_read32(&aer_regs->uncorr_err_stat); @@ -2677,12 +2825,14 @@ al_pcie_aer_uncorr_get_and_clear(struct al_pcie_pf *pcie_pf) return reg_val; } -/** AER corretable errors get and clear */ -unsigned int -al_pcie_aer_corr_get_and_clear(struct al_pcie_pf *pcie_pf) +/** AER correctable errors get and clear */ +static unsigned int +al_pcie_aer_corr_get_and_clear_aux( + struct al_pcie_port *pcie_port, + unsigned int pf_num) { - struct al_pcie_regs *regs = pcie_pf->pcie_port->regs; - struct al_pcie_core_aer_regs *aer_regs = regs->core_space[pcie_pf->pf_num].aer; + struct al_pcie_regs *regs = pcie_port->regs; + struct al_pcie_core_aer_regs *aer_regs = regs->core_space[pf_num].aer; uint32_t reg_val; reg_val = al_reg_read32(&aer_regs->corr_err_stat); @@ -2696,19 +2846,123 @@ al_pcie_aer_corr_get_and_clear(struct al_pcie_pf *pcie_pf) #endif /** AER get the header for the TLP corresponding to a detected error */ -void -al_pcie_aer_err_tlp_hdr_get( - struct al_pcie_pf *pcie_pf, +static void +al_pcie_aer_err_tlp_hdr_get_aux( + struct al_pcie_port *pcie_port, + unsigned int pf_num, uint32_t hdr[AL_PCIE_AER_ERR_TLP_HDR_NUM_DWORDS]) { - struct al_pcie_regs *regs = pcie_pf->pcie_port->regs; - struct al_pcie_core_aer_regs *aer_regs = regs->core_space[pcie_pf->pf_num].aer; + struct al_pcie_regs *regs = pcie_port->regs; + struct al_pcie_core_aer_regs *aer_regs = regs->core_space[pf_num].aer; int i; for (i = 0; i < AL_PCIE_AER_ERR_TLP_HDR_NUM_DWORDS; i++) hdr[i] = al_reg_read32(&aer_regs->header_log[i]); } +/******************** EP AER functions **********************/ +/** configure EP physical function AER capability */ +int al_pcie_aer_config( + struct al_pcie_pf *pcie_pf, + struct al_pcie_aer_params *params) +{ + al_assert(pcie_pf); + al_assert(params); + + return al_pcie_aer_config_aux( + pcie_pf->pcie_port, pcie_pf->pf_num, params); +} + +/** EP physical function AER uncorrectable errors get and clear */ +unsigned int al_pcie_aer_uncorr_get_and_clear(struct al_pcie_pf *pcie_pf) +{ + al_assert(pcie_pf); + + return al_pcie_aer_uncorr_get_and_clear_aux( + pcie_pf->pcie_port, pcie_pf->pf_num); +} + +/** EP physical function AER correctable errors get and clear */ +unsigned int al_pcie_aer_corr_get_and_clear(struct al_pcie_pf *pcie_pf) +{ + al_assert(pcie_pf); + + return al_pcie_aer_corr_get_and_clear_aux( + pcie_pf->pcie_port, pcie_pf->pf_num); +} + +/** + * EP physical function AER get the header for + * the TLP corresponding to a detected error + * */ +void al_pcie_aer_err_tlp_hdr_get( + struct al_pcie_pf *pcie_pf, + uint32_t hdr[AL_PCIE_AER_ERR_TLP_HDR_NUM_DWORDS]) +{ + al_assert(pcie_pf); + al_assert(hdr); + + al_pcie_aer_err_tlp_hdr_get_aux( + pcie_pf->pcie_port, pcie_pf->pf_num, hdr); +} + +/******************** RC AER functions **********************/ +/** configure RC port AER capability */ +int al_pcie_port_aer_config( + struct al_pcie_port *pcie_port, + struct al_pcie_aer_params *params) +{ + al_assert(pcie_port); + al_assert(params); + + /** + * For RC mode there's no PFs (neither PF handles), + * therefore PF#0 is used + * */ + return al_pcie_aer_config_aux(pcie_port, 0, params); +} + +/** RC port AER uncorrectable errors get and clear */ +unsigned int al_pcie_port_aer_uncorr_get_and_clear( + struct al_pcie_port *pcie_port) +{ + al_assert(pcie_port); + + /** + * For RC mode there's no PFs (neither PF handles), + * therefore PF#0 is used + * */ + return al_pcie_aer_uncorr_get_and_clear_aux(pcie_port, 0); +} + +/** RC port AER correctable errors get and clear */ +unsigned int al_pcie_port_aer_corr_get_and_clear( + struct al_pcie_port *pcie_port) +{ + al_assert(pcie_port); + + /** + * For RC mode there's no PFs (neither PF handles), + * therefore PF#0 is used + * */ + return al_pcie_aer_corr_get_and_clear_aux(pcie_port, 0); +} + +/** RC port AER get the header for the TLP corresponding to a detected error */ +void al_pcie_port_aer_err_tlp_hdr_get( + struct al_pcie_port *pcie_port, + uint32_t hdr[AL_PCIE_AER_ERR_TLP_HDR_NUM_DWORDS]) +{ + al_assert(pcie_port); + al_assert(hdr); + + /** + * For RC mode there's no PFs (neither PF handles), + * therefore PF#0 is used + * */ + al_pcie_aer_err_tlp_hdr_get_aux(pcie_port, 0, hdr); +} + /********************** Loopback mode (RC and Endpoint modes) ************/ /** enter local pipe loopback mode */ diff --git a/al_hal_pcie.h b/al_hal_pcie.h index 1ddc8eb7074..a5db654e182 100644 --- a/al_hal_pcie.h +++ b/al_hal_pcie.h @@ -85,7 +85,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - Root Complex mode * - Set the Max Link Speed to Gen2 * - Set the max lanes width to 2 (x2) - * - Disable reversal mode * - Enable Snoops to support I/O Hardware cache coherency * - Enable pcie core RAM parity * - Enable pcie core AXI parity @@ -97,7 +96,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @code * - struct al_pcie_link_params link_params = { * AL_PCIE_LINK_SPEED_GEN2, - * AL_FALSE, // disable reversal mode * AL_PCIE_MPS_DEFAULT}; * * - struct al_pcie_port_config_params config_params = { @@ -162,14 +160,29 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /********************************* Constants **********************************/ /******************************************************************************/ -/** Inbound header credits sum - rev 0/1/2 */ -#define AL_PCIE_REV_1_2_IB_HCRD_SUM 97 -/** Inbound header credits sum - rev 3 */ -#define AL_PCIE_REV3_IB_HCRD_SUM 259 +/** + * PCIe Core revision IDs: + * ID_1: Alpine V1 + * ID_2: Alpine V2 x4 + * ID_3: Alpine V2 x8 + */ +#define AL_PCIE_REV_ID_1 1 +#define AL_PCIE_REV_ID_2 2 +#define AL_PCIE_REV_ID_3 3 /** Number of extended registers */ #define AL_PCIE_EX_REGS_NUM 40 +/******************************************************************************* + * The inbound flow control for headers is programmable per P, NP and CPL + * transactions types. The following parameters define the total number of + * available header flow controls for all types. + ******************************************************************************/ +/** Inbound header credits sum - rev1/2 */ +#define AL_PCIE_REV_1_2_IB_HCRD_SUM 97 +/** Inbound header credits sum - rev3 */ +#define AL_PCIE_REV3_IB_HCRD_SUM 259 + /******************************************************************************* * PCIe AER uncorrectable error bits * To be used with the following functions: @@ -232,9 +245,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** * al_pcie_ib_hcrd_config: data structure internally used in order to config * inbound posted/non-posted parameters. - * Note: it's required to have this structure in pcie_port handle since it has - * a state (required/not-required) which is determined by outbound - * outstanding configuration + * Note: this is a private member in pcie_port handle and MUST NOT be modified + * by the user. */ struct al_pcie_ib_hcrd_config { /* Internally used - see 'al_pcie_ib_hcrd_os_ob_reads_config' */ @@ -251,10 +263,6 @@ enum al_pcie_max_payload_size { AL_PCIE_MPS_DEFAULT, AL_PCIE_MPS_128 = 0, AL_PCIE_MPS_256 = 1, - AL_PCIE_MPS_512 = 2, - AL_PCIE_MPS_1024 = 3, - AL_PCIE_MPS_2048 = 4, - AL_PCIE_MPS_4096 = 5, }; /** @@ -271,10 +279,12 @@ struct al_pcie_port { void *ex_regs; void __iomem *pbs_regs; - /* Revision ID */ + /* Rev ID */ uint8_t rev_id; unsigned int port_id; uint8_t max_lanes; + + /* For EP mode only */ uint8_t max_num_of_pfs; /* Internally used */ @@ -284,6 +294,8 @@ struct al_pcie_port { /** * al_pcie_pf: the pf handle, a data structure used to handle PF specific * functionality. Initialized using "al_pcie_pf_handle_init()" + * + * Note: This structure should be used for EP mode only */ struct al_pcie_pf { unsigned int pf_num; @@ -318,15 +330,13 @@ struct al_pcie_max_capability { al_bool root_complex_mode_supported; enum al_pcie_link_speed max_speed; uint8_t max_lanes; - al_bool reversal_supported; uint8_t atu_regions_num; - uint32_t atu_min_size; + uint32_t atu_min_size; /* Size granularity: 4 Kbytes */ }; /** PCIe link related parameters */ struct al_pcie_link_params { - enum al_pcie_link_speed max_speed; - al_bool enable_reversal; + enum al_pcie_link_speed max_speed; enum al_pcie_max_payload_size max_payload_size; }; @@ -362,22 +372,22 @@ struct al_pcie_gen3_params { uint8_t local_fs; /* Low Frequency (LF) Value for Gen3 Transmit Equalization */ }; -/** Transport Layer credits parameters */ -struct al_pcie_tl_credits_params { -}; - -/** Various configuration features */ -struct al_pcie_features { - /** - * Enable MSI fix from the SATA to the PCIe EP - * Only valid for port 0, when enabled as EP - */ - al_bool sata_ep_msi_fix; -}; - /** * Inbound posted/non-posted header credits and outstanding outbound reads - * completion header configuration + * completion header configuration. + * + * This structure controls the resource partitioning of an important resource in + * the PCIe port. This resource includes the PCIe TLP headers coming on the PCIe + * port, and is shared between three types: + * - Inbound Non-posted, which are PCIe Reads as well as PCIe Config Cycles + * - Inbound Posted, i.e. PCIe Writes + * - Inbound Read-completion, which are the completions matching and outbound + * reads issued previously by the same core. + * The programmer need to take into consideration that a given outbound read + * request could be split on the return path into Ceiling[MPS_Size / 64] + 1 + * of Read Completions. + * Programmers are not expected to modify these setting except for rare cases, + * where a different ratio between Posted-Writes and Read-Completions is desired * * Constraints: * - nof_cpl_hdr + nof_np_hdr + nof_p_hdr == @@ -411,13 +421,26 @@ struct al_pcie_ib_hcrd_os_ob_reads_config { unsigned int nof_p_hdr; }; -/** PCIe Ack/Nak Latency and Replay timers */ +/** + * PCIe Ack/Nak Latency and Replay timers + * + * Note: Programmer is not expected to modify these values unless working in + * very slow external devices like low-end FPGA or hardware devices + * emulated in software + */ struct al_pcie_latency_replay_timers { uint16_t round_trip_lat_limit; uint16_t replay_timer_limit; }; -/* SRIS KP counter values */ +/** + * SRIS KP counter values + * + * Description: SRIS is PCI SIG ECN, that enables the two peers on a given PCIe + * link to run with Separate Reference clock with Independent Spread spectrum + * clock and requires inserting PCIe SKP symbols on the link in faster frequency + * that original PCIe spec + */ struct al_pcie_sris_params { /** set to AL_TRUE to use defaults and ignore the other parameters */ al_bool use_defaults; @@ -425,7 +448,23 @@ struct al_pcie_sris_params { uint16_t kp_counter_gen21; }; -/** Relaxed ordering params */ +/** + * Relaxed ordering params + * Enable ordering relaxations for applications that does not require + * enforcement of 'completion must not bypass posted' ordering rule. + * + * Recommendation: + * - For downstream port, set enable_tx_relaxed_ordering + * - For upstream port + * - set enable_rx_relaxed_ordering + * - set enable tx_relaxed_ordering for emulated EP. + * + * Defaults: + * - For Root-Complex: + * - tx_relaxed_ordering = AL_FALSE, rx_relaxed_ordering = AL_TRUE + * - For End-Point: + * - tx_relaxed_ordering = AL_TRUE, rx_relaxed_ordering = AL_FALSE + */ struct al_pcie_relaxed_ordering_params { al_bool enable_tx_relaxed_ordering; al_bool enable_rx_relaxed_ordering; @@ -445,20 +484,26 @@ struct al_pcie_port_config_params { struct al_pcie_latency_replay_timers *lat_rply_timers; struct al_pcie_gen2_params *gen2_params; struct al_pcie_gen3_params *gen3_params; - struct al_pcie_tl_credits_params *tl_credits; - struct al_pcie_features *features; - /* Sets all internal timers to Fast Mode for speeding up simulation.*/ + /* + * Sets all internal timers to Fast Mode for speeding up simulation. + * this varible should be set always to AL_FALSE unless user is running + * on simulation setup + */ al_bool fast_link_mode; /* - * when true, the PCI unit will return Slave Error/Decoding Error to the master unit in case - * of error. when false, the value 0xFFFFFFFF will be returned without error indication. + * when true, the PCI unit will return Slave Error/Decoding Error to any + * I/O Fabric master or Internal Processors in case of error. + * when false, the value 0xFFFFFFFF will be returned without error indication. */ al_bool enable_axi_slave_err_resp; struct al_pcie_sris_params *sris_params; struct al_pcie_relaxed_ordering_params *relaxed_ordering_params; }; -/** BAR register configuration parameters (Endpoint Mode only) */ +/** + * BAR register configuration parameters + * Note: This structure should be used for EP mode only + */ struct al_pcie_ep_bar_params { al_bool enable; al_bool memory_space; /**< memory or io */ @@ -467,12 +512,30 @@ struct al_pcie_ep_bar_params { uint64_t size; /* the bar size in bytes */ }; -/** PF config params (EP mode only) */ +/** + * PF config params (EP mode only) + * Note: This structure should be used for EP mode only + */ struct al_pcie_pf_config_params { + /** + * disable advertising D1 and D3hot state + * Recommended to be AL_TRUE + */ al_bool cap_d1_d3hot_dis; + /** + * disable advertising support for Function-Level-Reset + * Recommended to be AL_FALSE + */ al_bool cap_flr_dis; + /* + * disable advertising Advanced power management states + */ al_bool cap_aspm_dis; al_bool bar_params_valid; + /* + * Note: only bar_params[0], [2] and [4] can have memory_64_bit enabled + * and in such case, the next bar ([1], [3], or [5] respectively) is not used + */ struct al_pcie_ep_bar_params bar_params[6]; struct al_pcie_ep_bar_params exp_bar_params;/* expansion ROM BAR*/ }; @@ -481,7 +544,7 @@ struct al_pcie_pf_config_params { struct al_pcie_link_status { al_bool link_up; enum al_pcie_link_speed speed; - uint8_t lanes; + uint8_t lanes; /* Number of lanes */ uint8_t ltssm_state; }; @@ -491,18 +554,26 @@ struct al_pcie_lane_status { enum al_pcie_link_speed requested_speed; }; -/** PCIe MSIX capability configuration parameters */ +/** + * PCIe MSIX capability configuration parameters + * Note: This structure should be used for EP mode only + */ struct al_pcie_msix_params { + /* Number of entries - size can be up to: 2024 */ uint16_t table_size; uint16_t table_offset; uint8_t table_bar; uint16_t pba_offset; + /* which bar to use when calculating the PBA table address and adding offset to */ uint16_t pba_bar; }; /** PCIE AER capability parameters */ struct al_pcie_aer_params { - /** ECRC Generation Enable */ + /** ECRC Generation Enable + * while this feature is powerful, all known Chip-sets and processors + * do not support it as of 2015 + */ al_bool ecrc_gen_en; /** ECRC Check Enable */ al_bool ecrc_chk_en; @@ -562,6 +633,13 @@ int al_pcie_pf_handle_init( struct al_pcie_port *pcie_port, unsigned int pf_num); +/** + * Get port revision ID + * @param pcie_port pcie port handle + * @return Port rev_id + */ +int al_pcie_port_rev_id_get(struct al_pcie_port *pcie_port); + /************************** Pre PCIe Port Enable API **************************/ /** @@ -582,7 +660,8 @@ int al_pcie_port_operating_mode_config(struct al_pcie_port *pcie_port, * This function can be called only before enabling the controller using al_pcie_port_enable(). * * @param pcie_port pcie port handle - * @param lanes number of lanes + * @param lanes number of lanes (must be 1,2,4,8,16 and not any other value) + * * Note: this function must be called before any al_pcie_port_config() calls * * @return 0 if no error found. @@ -593,7 +672,12 @@ int al_pcie_port_max_lanes_set(struct al_pcie_port *pcie_port, uint8_t lanes); * Set maximum physical function numbers * @param pcie_port pcie port handle * @param max_num_of_pfs number of physical functions - * Note: this function must be called before any al_pcie_pf_config() calls + * + * Notes: + * - this function must be called before any al_pcie_pf_config() calls + * - exposed on a given PCIe Endpoint port + * - PCIe rev1/rev2 supports only single Endpoint + * - PCIe rev3 can support up to 4 */ int al_pcie_port_max_num_of_pfs_set( struct al_pcie_port *pcie_port, @@ -619,9 +703,27 @@ int al_pcie_port_ib_hcrd_os_ob_reads_config( enum al_pcie_operating_mode al_pcie_operating_mode_get( struct al_pcie_port *pcie_port); +/** + * PCIe AXI quality of service configuration + * + * @param pcie_port + * Initialized PCIe port handle + * @param arqos + * AXI read quality of service (0 - 15) + * @param awqos + * AXI write quality of service (0 - 15) + */ +void al_pcie_axi_qos_config( + struct al_pcie_port *pcie_port, + unsigned int arqos, + unsigned int awqos); + /**************************** PCIe Port Enable API ****************************/ -/** Enable PCIe unit (deassert reset) +/** + * Enable PCIe unit (deassert reset) + * This function only enables the port, without any configuration/link + * functionality. Should be called before starting any configuration/link API * * @param pcie_port pcie port handle * @@ -637,6 +739,8 @@ void al_pcie_port_disable(struct al_pcie_port *pcie_port); /** * Port memory shutdown/up + * Memory shutdown should be called for an unused ports for power-saving + * * Caution: This function can be called only when the controller is disabled * * @param pcie_port pcie port handle @@ -669,7 +773,7 @@ int al_pcie_port_config(struct al_pcie_port *pcie_port, const struct al_pcie_port_config_params *params); /** - * @brief Configure a specific PF (EP params, sriov params, ...) + * @brief Configure a specific PF * this function must be called before any datapath transactions * * @param pcie_pf pcie pf handle @@ -685,7 +789,8 @@ int al_pcie_pf_config( /** * @brief start pcie link - * + * This function starts the link and should be called only after port is enabled + * and pre port-enable and configurations are done * @param pcie_port pcie port handle * * @return 0 if no error found @@ -701,6 +806,14 @@ int al_pcie_link_start(struct al_pcie_port *pcie_port); */ int al_pcie_link_stop(struct al_pcie_port *pcie_port); +/** + * @brief check if pcie link is started + * Note that this function checks if link is started rather than link is up + * @param pcie_port pcie port handle + * @return AL_TRUE if link is started and AL_FALSE otherwise + */ +al_bool al_pcie_is_link_started(struct al_pcie_port *pcie_port); + /** * @brief trigger link-disable * @@ -753,6 +866,10 @@ void al_pcie_lane_status_get( /** * @brief trigger hot reset + * this function initiates In-Band reset while link is up. + * to initiate hot reset: call this function with AL_TRUE + * to exit from hos reset: call this function with AL_FALSE + * Note: This function should be called in RC mode only * * @param pcie_port pcie port handle * @param enable AL_TRUE to enable hot-reset and AL_FALSE to disable it @@ -766,6 +883,7 @@ int al_pcie_link_hot_reset(struct al_pcie_port *pcie_port, al_bool enable); * this function initiates Link retraining by directing the Physical Layer LTSSM * to the Recovery state. If the LTSSM is already in Recovery or Configuration, * re-entering Recovery is permitted but not required. + * Note: This function should be called in RC mode only * @param pcie_port pcie port handle * @@ -793,7 +911,9 @@ int al_pcie_link_change_width(struct al_pcie_port *pcie_port, uint8_t width); /************************** Snoop Configuration API ***************************/ /** - * @brief configure pcie port axi snoop + * @brief configure pcie port axi snoop + * This enable the inbound PCIe posted write data or the Read completion data to + * snoop the internal processor caches for I/O cache coherency * * @param pcie_port pcie port handle * @param enable_axi_snoop enable snoop. @@ -807,7 +927,10 @@ int al_pcie_port_snoop_config(struct al_pcie_port *pcie_port, /************************** Configuration Space API ***************************/ /** - * Configuration Space Access Through PCI-E_ECAM_Ext PASW (RC mode only) + * Configuration Space Access Through PCI-E_ECAM_Ext PASW + * This feature enables the internal processors to generate configuration cycles + * on the PCIe ports by writing to part of the processor memory space marked by + * the PCI-E_EXCAM_Ext address window */ /** @@ -852,6 +975,11 @@ void al_pcie_local_cfg_space_write( /** * @brief set target_bus and mask_target_bus + * + * Call this function with target_bus set to the required bus of the next + * outbound config access to be issued. No need to call that function if the + * next config access bus equals to the last one. + * * @param pcie_port pcie port handle * @param target_bus * @param mask_target_bus @@ -875,6 +1003,8 @@ int al_pcie_target_bus_get(struct al_pcie_port *pcie_port, /** * Set secondary bus number * + * Same as al_pcie_target_bus_set but with secondary bus + * * @param pcie_port pcie port handle * @param secbus pci secondary bus number * @@ -885,6 +1015,8 @@ int al_pcie_secondary_bus_set(struct al_pcie_port *pcie_port, uint8_t secbus); /** * Set subordinary bus number * + * Same as al_pcie_target_bus_set but with subordinary bus + * * @param pcie_port pcie port handle * @param subbus the highest bus number of all of the buses that can be reached * downstream of the PCIE instance. @@ -897,13 +1029,22 @@ int al_pcie_subordinary_bus_set(struct al_pcie_port *pcie_port,uint8_t subbus); * @brief Enable/disable deferring incoming configuration requests until * initialization is complete. When enabled, the core completes incoming * configuration requests with a Configuration Request Retry Status. - * Other incoming Requests complete with Unsupported Request status. + * Other incoming non-configuration Requests complete with Unsupported Request status. + * + * Note: This function should be used for EP mode only * * @param pcie_port pcie port handle * @param en enable/disable */ void al_pcie_app_req_retry_set(struct al_pcie_port *pcie_port, al_bool en); +/** + * @brief Check if deferring incoming configuration requests is enabled or not + * @param pcie_port pcie port handle + * @return AL_TRUE is it's enabled and AL_FALSE otherwise + */ +al_bool al_pcie_app_req_retry_get_status(struct al_pcie_port *pcie_port); + /*************** Internal Address Translation Unit (ATU) API ******************/ enum al_pcie_atu_dir { @@ -911,6 +1052,7 @@ enum al_pcie_atu_dir { AL_PCIE_ATU_DIR_INBOUND = 1, }; +/** decoding of the PCIe TLP Type as appears on the wire */ enum al_pcie_atu_tlp { AL_PCIE_TLP_TYPE_MEM = 0, AL_PCIE_TLP_TYPE_IO = 2, @@ -920,57 +1062,134 @@ enum al_pcie_atu_tlp { AL_PCIE_TLP_TYPE_RESERVED = 0x1f }; +/** default response types */ enum al_pcie_atu_response { AL_PCIE_RESPONSE_NORMAL = 0, - AL_PCIE_RESPONSE_UR = 1, - AL_PCIE_RESPONSE_CA = 2 + AL_PCIE_RESPONSE_UR = 1, /* UR == Unsupported Request */ + AL_PCIE_RESPONSE_CA = 2 /* CA == Completion Abort */ }; struct al_pcie_atu_region { + + /********************************************************************** + * General Parameters * + **********************************************************************/ + al_bool enable; /* outbound or inbound */ enum al_pcie_atu_dir direction; /* region index */ uint8_t index; + /* the 64-bit address that get matched with the 64-bit address incoming + * on the PCIe TLP + */ uint64_t base_addr; - /** limit marks the region's end address. only bits [39:0] are valid - * given the Alpine PoC maximum physical address space + /** + * limit marks the region's end address. + * For Alpine V1 (PCIe rev1): only bits [39:0] are valid + * For Alpine V2 (PCIe rev2/rev3): only bits [47:0] are valid + * an access is a hit in iATU if the: + * - address >= base_addr + * - address <= base_addr + limit */ uint64_t limit; - /** the address that matches will be translated to this address + offset + /** + * the address that matches (hit) will be translated to: + * target_addr + offset + * + * Exmaple: accessing (base_addr + 0x1000) will be translated to: + * (target_addr + 0x1000) in case limit >= 0x1000 */ uint64_t target_addr; + /** + * When the Invert feature is activated, an address match occurs when + * the untranslated address is not in the region bounded by the Base + * address and Limit address. Match occurs when the untranslated address + * is not in the region bounded by the base address and limit address + */ al_bool invert_matching; - /* pcie tlp type*/ + /** + * PCIe TLP type + * Can be: Mem, IO, CGF0, CFG1 or MSG + */ enum al_pcie_atu_tlp tlp_type; - /* pcie frame header attr field*/ + /** + * PCIe frame header attr field. + * When the address of a TLP is matched to this region, then the ATTR + * field of the TLP is changed to the value in this register. + */ uint8_t attr; + + /********************************************************************** + * Outbound specific Parameters * + **********************************************************************/ + /** - * outbound specific params + * PCIe Message code + * MSG TLPs (Message Code). When the address of an outbound TLP is + * matched to this region, and the translated TLP TYPE field is Msg + * then the message field of the TLP is changed to the value in this + * register. */ - /* pcie message code */ uint8_t msg_code; - al_bool cfg_shift_mode; /** - * inbound specific params + * CFG Shift Mode. This is useful for CFG transactions where the PCIe + * configuration mechanism maps bits [27:12] of the address to the + * bus/device and function number. This allows a CFG configuration space + * to be located in any 256MB window of your application memory space + * using a 28-bit effective address.Shifts bits [27:12] of the + * untranslated address to form bits [31:16] of the translated address. */ + al_bool cfg_shift_mode; + + /********************************************************************** + * Inbound specific Parameters * + **********************************************************************/ + uint8_t bar_number; - /* BAR match mode, used in EP for MEM and IO tlps*/ + /** + * Match Mode. Determines Inbound matching mode for TLPs. The mode + * depends on the type of TLP that is received as follows: + * MEM-I/O: 0 = Address Match Mode + * 1 = BAR Match Mode + * CFG0 : 0 = Routing ID Match Mode + * 1 = Accept Mode + * MSG : 0 = Address Match Mode + * 1 = Vendor ID Match Mode + */ uint8_t match_mode; /** - * For outbound: enables taking the function number of the translated - * TLP from the PCIe core. For inbound: enables ATU function match mode + * For outbound: + * - AL_TRUE : enables taking the function number of the translated TLP + * from the PCIe core + * - AL_FALSE: no function number is taken from PCIe core + * For inbound: + * - AL_TRUE : enables ATU function match mode + * - AL_FALSE: no function match mode applied to transactions + * * Note: this boolean is ignored in RC mode */ al_bool function_match_bypass_mode; /** * The function number to match/bypass (see previous parameter) - * Note: this parameter is ignored when previous param is FALSE + * Note: this parameter is ignored when previous parameter is AL_FALSE */ uint8_t function_match_bypass_mode_number; - /* response code */ + /** + * setting up what is the default response for an inbound transaction + * that matches the iATU + */ enum al_pcie_atu_response response; + /** + * Attr Match Enable. Ensures that a successful AT TLP field comparison + * match (see attr above) occurs for address translation to proceed + */ al_bool enable_attr_match_mode; + /** + * Message Code Match Enable(Msg TLPS). Ensures that a successful + * message Code TLP field comparison match (see Message msg_code)occurs + * (in MSG transactions) for address translation to proceed. + */ al_bool enable_msg_match_mode; /** * USE WITH CAUTION: setting this boolean to AL_TRUE allows setting the @@ -1008,7 +1227,11 @@ void al_pcie_atu_region_get_fields( /** * @brief Configure axi io bar. - * every hit to this bar will override size to 4 bytes. + * + * This is an EP feature, enabling PCIe IO transaction to be captured if it fits + * within start and end address, and then mapped to internal 4-byte + * memRead/memWrite. Every hit to this bar will override size to 4 bytes. + * * @param pcie_port pcie port handle * @param start the first address of the memory * @param end the last address of the memory @@ -1028,6 +1251,13 @@ enum al_pcie_legacy_int_type{ AL_PCIE_LEGACY_INTD }; + +/* @brief generate FLR_PF_DONE message + * @param pcie_pf pcie pf handle + * @return 0 if no error found + */ +int al_pcie_pf_flr_done_gen(struct al_pcie_pf *pcie_pf); + /** * @brief generate INTx Assert/DeAssert Message * @param pcie_pf pcie pf handle @@ -1075,7 +1305,7 @@ al_bool al_pcie_msix_masked(struct al_pcie_pf *pcie_pf); /******************** Advanced Error Reporting (AER) API **********************/ /** - * @brief configure AER capability + * @brief configure EP physical function AER capability * @param pcie_pf pcie pf handle * @param params AER capability configuration parameters * @return 0 if no error found @@ -1085,7 +1315,7 @@ int al_pcie_aer_config( struct al_pcie_aer_params *params); /** - * @brief AER uncorretable errors get and clear + * @brief EP physical function AER uncorrectable errors get and clear * @param pcie_pf pcie pf handle * @return bit mask of uncorrectable errors - see 'AL_PCIE_AER_UNCORR_*' for * details @@ -1093,7 +1323,7 @@ int al_pcie_aer_config( unsigned int al_pcie_aer_uncorr_get_and_clear(struct al_pcie_pf *pcie_pf); /** - * @brief AER corretable errors get and clear + * @brief EP physical function AER correctable errors get and clear * @param pcie_pf pcie pf handle * @return bit mask of correctable errors - see 'AL_PCIE_AER_CORR_*' for * details @@ -1101,7 +1331,8 @@ unsigned int al_pcie_aer_uncorr_get_and_clear(struct al_pcie_pf *pcie_pf); unsigned int al_pcie_aer_corr_get_and_clear(struct al_pcie_pf *pcie_pf); /** - * @brief AER get the header for the TLP corresponding to a detected error + * @brief EP physical function AER get the header for + * the TLP corresponding to a detected error * @param pcie_pf pcie pf handle * @param hdr pointer to an array for getting the header */ @@ -1109,6 +1340,44 @@ void al_pcie_aer_err_tlp_hdr_get( struct al_pcie_pf *pcie_pf, uint32_t hdr[AL_PCIE_AER_ERR_TLP_HDR_NUM_DWORDS]); +/** + * @brief configure RC port AER capability + * @param pcie_port pcie port handle + * @param params AER capability configuration parameters + * @return 0 if no error found + */ +int al_pcie_port_aer_config( + struct al_pcie_port *pcie_port, + struct al_pcie_aer_params *params); + +/** + * @brief RC port AER uncorrectable errors get and clear + * @param pcie_port pcie port handle + * @return bit mask of uncorrectable errors - see 'AL_PCIE_AER_UNCORR_*' for + * details + */ +unsigned int al_pcie_port_aer_uncorr_get_and_clear( + struct al_pcie_port *pcie_port); + +/** + * @brief RC port AER correctable errors get and clear + * @param pcie_port pcie port handle + * @return bit mask of correctable errors - see 'AL_PCIE_AER_CORR_*' for + * details + */ +unsigned int al_pcie_port_aer_corr_get_and_clear( + struct al_pcie_port *pcie_port); + +/** + * @brief RC port AER get the header for + * the TLP corresponding to a detected error + * @param pcie_port pcie port handle + * @param hdr pointer to an array for getting the header + */ +void al_pcie_port_aer_err_tlp_hdr_get( + struct al_pcie_port *pcie_port, + uint32_t hdr[AL_PCIE_AER_ERR_TLP_HDR_NUM_DWORDS]); + /******************** Loop-Back mode (RC and Endpoint modes) ******************/ /** diff --git a/al_hal_pcie_axi_reg.h b/al_hal_pcie_axi_reg.h index 04d4bfdbca3..b8e11645edd 100644 --- a/al_hal_pcie_axi_reg.h +++ b/al_hal_pcie_axi_reg.h @@ -72,7 +72,7 @@ struct al_pcie_rev1_2_axi_ctrl { /* [0x28] */ uint32_t dbi_ctl; /* [0x2c] */ - uint32_t vmid_mask; + uint32_t tgtid_mask; uint32_t rsrvd[4]; }; struct al_pcie_rev3_axi_ctrl { @@ -98,7 +98,7 @@ struct al_pcie_rev3_axi_ctrl { /* [0x28] */ uint32_t dbi_ctl; /* [0x2c] */ - uint32_t vmid_mask; + uint32_t tgtid_mask; }; struct al_pcie_rev1_axi_ob_ctrl { /* [0x0] */ @@ -145,10 +145,10 @@ struct al_pcie_rev2_axi_ob_ctrl { /* [0x24] */ uint32_t msg_limit_h; /* - * [0x28] this register override the VMID field in the AXUSER [19:4], + * [0x28] this register override the Target-ID field in the AXUSER [19:4], * for the AXI master port. */ - uint32_t vmid_reg_ovrd; + uint32_t tgtid_reg_ovrd; /* [0x2c] this register override the ADDR[63:32] AXI master port. */ uint32_t addr_high_reg_ovrd_value; /* [0x30] this register override the ADDR[63:32] AXI master port. */ @@ -196,10 +196,10 @@ struct al_pcie_rev3_axi_ob_ctrl { /* [0x40] */ uint32_t aw_msg_addr_mask_h; /* - * [0x44] this register override the VMID field in the AXUSER [19:4], + * [0x44] this register override the Target-ID field in the AXUSER [19:4], * for the AXI master port. */ - uint32_t vmid_reg_ovrd; + uint32_t tgtid_reg_ovrd; /* [0x48] this register override the ADDR[63:32] AXI master port. */ uint32_t addr_high_reg_ovrd_value; /* [0x4c] this register override the ADDR[63:32] AXI master port. */ @@ -783,9 +783,9 @@ struct al_pcie_rev3_axi_regs { /* arprot value */ #define PCIE_AXI_CTRL_MASTER_ARCTL_ARPROT_VALUE_MASK 0x000001C0 #define PCIE_AXI_CTRL_MASTER_ARCTL_ARPROT_VALUE_SHIFT 6 -/* vmid val */ -#define PCIE_AXI_CTRL_MASTER_ARCTL_VMID_VAL_MASK 0x01FFFE00 -#define PCIE_AXI_CTRL_MASTER_ARCTL_VMID_VAL_SHIFT 9 +/* tgtid val */ +#define PCIE_AXI_CTRL_MASTER_ARCTL_TGTID_VAL_MASK 0x01FFFE00 +#define PCIE_AXI_CTRL_MASTER_ARCTL_TGTID_VAL_SHIFT 9 /* IPA value */ #define PCIE_AXI_CTRL_MASTER_ARCTL_IPA_VAL (1 << 25) /* overide snoop inidcation, if not set take it from mstr_armisc ... */ @@ -797,6 +797,7 @@ snoop indication value when override */ arqos value */ #define PCIE_AXI_CTRL_MASTER_ARCTL_ARQOS_MASK 0xF0000000 #define PCIE_AXI_CTRL_MASTER_ARCTL_ARQOS_SHIFT 28 +#define PCIE_AXI_CTRL_MASTER_ARCTL_ARQOS_VAL_MAX 15 /**** Master_Awctl register ****/ /* override arcache */ @@ -809,9 +810,9 @@ arqos value */ /* awprot value */ #define PCIE_AXI_CTRL_MASTER_AWCTL_AWPROT_VALUE_MASK 0x000001C0 #define PCIE_AXI_CTRL_MASTER_AWCTL_AWPROT_VALUE_SHIFT 6 -/* vmid val */ -#define PCIE_AXI_CTRL_MASTER_AWCTL_VMID_VAL_MASK 0x01FFFE00 -#define PCIE_AXI_CTRL_MASTER_AWCTL_VMID_VAL_SHIFT 9 +/* tgtid val */ +#define PCIE_AXI_CTRL_MASTER_AWCTL_TGTID_VAL_MASK 0x01FFFE00 +#define PCIE_AXI_CTRL_MASTER_AWCTL_TGTID_VAL_SHIFT 9 /* IPA value */ #define PCIE_AXI_CTRL_MASTER_AWCTL_IPA_VAL (1 << 25) /* overide snoop inidcation, if not set take it from mstr_armisc ... */ @@ -823,6 +824,7 @@ snoop indication value when override */ awqos value */ #define PCIE_AXI_CTRL_MASTER_AWCTL_AWQOS_MASK 0xF0000000 #define PCIE_AXI_CTRL_MASTER_AWCTL_AWQOS_SHIFT 28 +#define PCIE_AXI_CTRL_MASTER_AWCTL_AWQOS_VAL_MAX 15 /**** slv_ctl register ****/ #define PCIE_AXI_CTRL_SLV_CTRL_IO_BAR_EN (1 << 6) @@ -888,17 +890,17 @@ awqos value */ #define PCIE_AXI_MISC_OB_CTRL_MSG_LIMIT_H_ADDR_MASK 0x000003FF #define PCIE_AXI_MISC_OB_CTRL_MSG_LIMIT_H_ADDR_SHIFT 0 -/**** vmid_reg_ovrd register ****/ +/**** tgtid_reg_ovrd register ****/ /* * select if to take the value from register or from address[63:48]: * 1'b1: register value. * 1'b0: from address[63:48] */ -#define PCIE_AXI_MISC_OB_CTRL_VMID_REG_OVRD_SEL_MASK 0x0000FFFF -#define PCIE_AXI_MISC_OB_CTRL_VMID_REG_OVRD_SEL_SHIFT 0 -/* vmid override value. */ -#define PCIE_AXI_MISC_OB_CTRL_VMID_REG_OVRD_VALUE_MASK 0xFFFF0000 -#define PCIE_AXI_MISC_OB_CTRL_VMID_REG_OVRD_VALUE_SHIFT 16 +#define PCIE_AXI_MISC_OB_CTRL_TGTID_REG_OVRD_SEL_MASK 0x0000FFFF +#define PCIE_AXI_MISC_OB_CTRL_TGTID_REG_OVRD_SEL_SHIFT 0 +/* tgtid override value. */ +#define PCIE_AXI_MISC_OB_CTRL_TGTID_REG_OVRD_VALUE_MASK 0xFFFF0000 +#define PCIE_AXI_MISC_OB_CTRL_TGTID_REG_OVRD_VALUE_SHIFT 16 /**** addr_size_replace register ****/ /* @@ -1255,17 +1257,17 @@ awqos value */ #define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_RSRVD_14_15_MASK 0x0000C000 #define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_RSRVD_14_15_SHIFT 14 /* choose the field from the axuser */ -#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_PF_VEC_VMID89_VEC_OVRD_FROM_AXUSER_MASK 0x00030000 -#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_PF_VEC_VMID89_VEC_OVRD_FROM_AXUSER_SHIFT 16 +#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_PF_VEC_TGTID89_VEC_OVRD_FROM_AXUSER_MASK 0x00030000 +#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_PF_VEC_TGTID89_VEC_OVRD_FROM_AXUSER_SHIFT 16 /* choose the field from register */ -#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_PF_VEC_VMID89_VEC_OVRD_FROM_REG_MASK 0x000C0000 -#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_PF_VEC_VMID89_VEC_OVRD_FROM_REG_SHIFT 18 +#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_PF_VEC_TGTID89_VEC_OVRD_FROM_REG_MASK 0x000C0000 +#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_PF_VEC_TGTID89_VEC_OVRD_FROM_REG_SHIFT 18 /* in case the field take from the address, offset field for each bit. */ -#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_PF_VEC_VMID89_VEC_ADDR_OFFSET_MASK 0x0FF00000 -#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_PF_VEC_VMID89_VEC_ADDR_OFFSET_SHIFT 20 +#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_PF_VEC_TGTID89_VEC_ADDR_OFFSET_MASK 0x0FF00000 +#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_PF_VEC_TGTID89_VEC_ADDR_OFFSET_SHIFT 20 /* register value override */ -#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_CFG_VMID89_VEC_OVRD_MASK 0x30000000 -#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_CFG_VMID89_VEC_OVRD_SHIFT 28 +#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_CFG_TGTID89_VEC_OVRD_MASK 0x30000000 +#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_CFG_TGTID89_VEC_OVRD_SHIFT 28 /* Rsrvd */ #define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_RSRVD_MASK 0xC0000000 #define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_2_RSRVD_SHIFT 30 @@ -1291,9 +1293,9 @@ awqos value */ #define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_3_RSRVD_SHIFT 30 /**** func_ctrl_4 register ****/ -/* When set take the corresponding bit address from vmid value. */ -#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_4_PF_VEC_MEM_ADDR54_63_SEL_VMID_MASK 0x000003FF -#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_4_PF_VEC_MEM_ADDR54_63_SEL_VMID_SHIFT 0 +/* When set take the corresponding bit address from tgtid value. */ +#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_4_PF_VEC_MEM_ADDR54_63_SEL_TGTID_MASK 0x000003FF +#define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_4_PF_VEC_MEM_ADDR54_63_SEL_TGTID_SHIFT 0 /* override value. */ #define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_4_PF_VEC_MEM_ADDR54_63_OVRD_MASK 0x000FFC00 #define PCIE_AXI_PF_AXI_ATTR_OVRD_FUNC_CTRL_4_PF_VEC_MEM_ADDR54_63_OVRD_SHIFT 10 diff --git a/al_hal_pcie_interrupts.h b/al_hal_pcie_interrupts.h index 357971ca63c..41e6496d2fe 100644 --- a/al_hal_pcie_interrupts.h +++ b/al_hal_pcie_interrupts.h @@ -81,7 +81,7 @@ enum al_pcie_app_int_grp_a { /** [RC only] Deassert_INTB received */ AL_PCIE_APP_INT_DEASSERT_INTB = AL_BIT(2), /** - * [RC only] Deassert_INTA received - there's a didcated GIC interrupt + * [RC only] Deassert_INTA received - there's a dedicated GIC interrupt * line that reflects the status of ASSERT/DEASSERT of INTA */ AL_PCIE_APP_INT_DEASSERT_INTA = AL_BIT(3), @@ -92,7 +92,7 @@ enum al_pcie_app_int_grp_a { /** [RC only] Assert_INTB received */ AL_PCIE_APP_INT_ASSERT_INTB = AL_BIT(6), /** - * [RC only] Assert_INTA received - there's a didcated GIC interrupt + * [RC only] Assert_INTA received - there's a dedicated GIC interrupt * line that reflects the status of ASSERT/DEASSERT of INTA */ AL_PCIE_APP_INT_ASSERT_INTA = AL_BIT(7), @@ -150,13 +150,13 @@ enum al_pcie_app_int_grp_b { AL_PCIE_APP_INT_GRP_B_FTL_ERR_MSG_RCVD = AL_BIT(5), /** * [RC/EP] Vendor Defined Message received - * Asserted when a vevdor message is received (with no data), buffers 2 + * Asserted when a vendor message is received (with no data), buffers 2 * messages only, and latch the headers in registers */ AL_PCIE_APP_INT_GRP_B_VNDR_MSG_A_RCVD = AL_BIT(6), /** * [RC/EP] Vendor Defined Message received - * Asserted when a vevdor message is received (with no data), buffers 2 + * Asserted when a vendor message is received (with no data), buffers 2 * messages only, and latch the headers in registers */ AL_PCIE_APP_INT_GRP_B_VNDR_MSG_B_RCVD = AL_BIT(7), @@ -166,7 +166,7 @@ enum al_pcie_app_int_grp_b { AL_PCIE_APP_INT_GRP_B_LNK_EQ_REQ = AL_BIT(13), /** [RC/EP] OB Vendor message request is granted by the PCIe core */ AL_PCIE_APP_INT_GRP_B_OB_VNDR_MSG_REQ_GRNT = AL_BIT(14), - /** [RC only] CPL timeout from the PCIe core indiication */ + /** [RC only] CPL timeout from the PCIe core indication */ AL_PCIE_APP_INT_GRP_B_CPL_TO = AL_BIT(15), /** [RC/EP] Slave Response Composer Lookup Error */ AL_PCIE_APP_INT_GRP_B_SLV_RESP_COMP_LKUP_ERR = AL_BIT(16), diff --git a/al_hal_pcie_regs.h b/al_hal_pcie_regs.h index 15c5735e279..09b99c5b905 100644 --- a/al_hal_pcie_regs.h +++ b/al_hal_pcie_regs.h @@ -51,18 +51,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "al_hal_pcie_w_reg_ex.h" #endif -/** - * Revision IDs: - * ID_0: SlickRock M0 - * ID_1: SlickRock A0 - * ID_2: PeakRock x4 - * ID_3: PeakRock x8 - */ -#define AL_PCIE_REV_ID_0 0 -#define AL_PCIE_REV_ID_1 1 -#define AL_PCIE_REV_ID_2 2 -#define AL_PCIE_REV_ID_3 3 - #define AL_PCIE_AXI_REGS_OFFSET 0x0 #define AL_PCIE_REV_1_2_APP_REGS_OFFSET 0x1000 #define AL_PCIE_REV_3_APP_REGS_OFFSET 0x2000 @@ -74,6 +62,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define REV3_MAX_NUM_LANES 8 #define AL_MAX_NUM_OF_LANES 8 /* the maximum between all Revisions */ +/** Number of outbound atu regions - rev 1/2 */ +#define AL_PCIE_REV_1_2_ATU_NUM_OUTBOUND_REGIONS 12 +/** Number of outbound atu regions - rev 3 */ +#define AL_PCIE_REV_3_ATU_NUM_OUTBOUND_REGIONS 16 + struct al_pcie_core_iatu_regs { uint32_t index; uint32_t cr1; @@ -253,8 +246,10 @@ struct al_pcie_rev3_regs { struct al_pcie_axi_ctrl { uint32_t *global; + uint32_t *master_rctl; uint32_t *master_arctl; uint32_t *master_awctl; + uint32_t *master_ctl; uint32_t *slv_ctl; }; @@ -265,6 +260,13 @@ struct al_pcie_axi_ob_ctrl { uint32_t *io_start_h; uint32_t *io_limit_l; uint32_t *io_limit_h; + uint32_t *io_addr_mask_h; /* Rev 3 only */ + uint32_t *ar_msg_addr_mask_h; /* Rev 3 only */ + uint32_t *aw_msg_addr_mask_h; /* Rev 3 only */ + uint32_t *tgtid_reg_ovrd; /* Rev 2/3 only */ + uint32_t *addr_high_reg_ovrd_value; /* Rev 2/3 only */ + uint32_t *addr_high_reg_ovrd_sel; /* Rev 2/3 only */ + uint32_t *addr_size_replace; /* Rev 2/3 only */ }; struct al_pcie_axi_pcie_global { @@ -352,14 +354,23 @@ struct al_pcie_w_global_ctrl { }; struct al_pcie_w_soc_int { + uint32_t *status_0; + uint32_t *status_1; + uint32_t *status_2; + uint32_t *status_3; /* Rev 2/3 only */ uint32_t *mask_inta_leg_0; + uint32_t *mask_inta_leg_1; + uint32_t *mask_inta_leg_2; uint32_t *mask_inta_leg_3; /* Rev 2/3 only */ uint32_t *mask_msi_leg_0; + uint32_t *mask_msi_leg_1; + uint32_t *mask_msi_leg_2; uint32_t *mask_msi_leg_3; /* Rev 2/3 only */ }; struct al_pcie_w_atu { uint32_t *in_mask_pair; uint32_t *out_mask_pair; + uint32_t *reg_out_mask; /* Rev 3 only */ }; struct al_pcie_w_regs { @@ -375,6 +386,7 @@ struct al_pcie_w_regs { struct al_pcie_revx_w_int_grp *int_grp_b; struct al_pcie_revx_w_int_grp *int_grp_c; struct al_pcie_revx_w_int_grp *int_grp_d; + struct al_pcie_rev3_w_cfg_func_ext *cfg_func_ext; /* Rev 3 only */ }; struct al_pcie_regs { diff --git a/al_hal_pcie_w_reg.h b/al_hal_pcie_w_reg.h index 44e9d952655..137dfbde13e 100644 --- a/al_hal_pcie_w_reg.h +++ b/al_hal_pcie_w_reg.h @@ -1498,7 +1498,7 @@ struct al_pcie_rev3_w_regs { } #endif -#endif /* __AL_HAL_PCIE_W_REG_H */ +#endif /* __AL_HAL_pcie_w_REG_H */ /** @} end of ... group */ diff --git a/al_hal_plat_services.h b/al_hal_plat_services.h index 217bb927f69..278a8fa71dd 100644 --- a/al_hal_plat_services.h +++ b/al_hal_plat_services.h @@ -66,10 +66,29 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include /* Prototypes for all the bus_space structure functions */ -bs_protos(generic); -bs_protos(generic_armv4); +uint8_t generic_bs_r_1(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t offset); + +uint16_t generic_bs_r_2(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t offset); + +uint32_t generic_bs_r_4(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t offset); + +void generic_bs_w_1(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t offset, uint8_t value); + +void generic_bs_w_2(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t offset, uint16_t value); + +void generic_bs_w_4(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t offset, uint32_t value); + +void generic_bs_w_8(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t offset, uint64_t value); #define __UNUSED __attribute__((unused)) @@ -79,6 +98,52 @@ extern "C" { #endif /* *INDENT-ON* */ +/** + * Make sure data will be visible by other masters (other CPUS and DMA). + * usually this is achieved by the ARM DMB instruction. + */ +static void al_data_memory_barrier(void); +static void al_smp_data_memory_barrier(void); + +/** + * Make sure data will be visible by DMA masters, no restriction for other cpus + */ +static inline void +al_data_memory_barrier(void) +{ +#ifndef __aarch64__ + dsb(); +#else + dsb(sy); +#endif +} + +/** + * Make sure data will be visible in order by other cpus masters. + */ +static inline void +al_smp_data_memory_barrier(void) +{ +#ifndef __aarch64__ + dmb(); +#else + dmb(ish); +#endif +} + +/** + * Make sure write data will be visible in order by other cpus masters. + */ +static inline void +al_local_data_memory_barrier(void) +{ +#ifndef __aarch64__ + dsb(); +#else + dsb(sy); +#endif +} + /* * WMA: This is a hack which allows not modifying the __iomem accessing HAL code. * On ARMv7, bus_handle holds the information about VA of accessed memory. It @@ -168,50 +233,66 @@ uint64_t al_reg_read64(uint64_t * offset); * @param offset register offset * @param val value to write to the register */ -#define al_reg_write8(l,v) do { dsb(); generic_bs_w_1(NULL, (bus_space_handle_t)l, 0, v); dmb(); } while (0) +#define al_reg_write8(l, v) do { \ + al_data_memory_barrier(); \ + generic_bs_w_1(NULL, (bus_space_handle_t)l, 0, v); \ + al_smp_data_memory_barrier(); \ +} while (0) /** * Write to MMIO 16 bits register * @param offset register offset * @param val value to write to the register */ -#define al_reg_write16(l,v) do { dsb(); generic_bs_w_2(NULL, (bus_space_handle_t)l, 0, v); dmb(); } while (0) +#define al_reg_write16(l, v) do { \ + al_data_memory_barrier(); \ + generic_bs_w_2(NULL, (bus_space_handle_t)l, 0, v); \ + al_smp_data_memory_barrier(); \ +} while (0) /** * Write to MMIO 32 bits register * @param offset register offset * @param val value to write to the register */ -#define al_reg_write32(l,v) do { dsb(); generic_bs_w_4(NULL, (bus_space_handle_t)l, 0, v); dmb(); } while (0) +#define al_reg_write32(l, v) do { \ + al_data_memory_barrier(); \ + generic_bs_w_4(NULL, (bus_space_handle_t)l, 0, v); \ + al_smp_data_memory_barrier(); \ +} while (0) /** * Write to MMIO 64 bits register * @param offset register offset * @param val value to write to the register */ -#define al_reg_write64(l,v) do { dsb(); generic_bs_w_8(NULL, (bus_space_handle_t)l, 0, v); dmb(); } while (0) +#define al_reg_write64(l, v) do { \ + al_data_memory_barrier(); \ + generic_bs_w_8(NULL, (bus_space_handle_t)l, 0, v); \ + al_smp_data_memory_barrier(); \ +} while (0) static inline uint8_t al_reg_read8(uint8_t *l) { - dsb(); + al_data_memory_barrier(); return (generic_bs_r_1(NULL, (bus_space_handle_t)l, 0)); } static inline uint16_t al_reg_read16(uint16_t *l) { - dsb(); + al_data_memory_barrier(); return (generic_bs_r_2(NULL, (bus_space_handle_t)l, 0)); } static inline uint32_t al_reg_read32(uint32_t *l) { - dsb(); + al_data_memory_barrier(); return (generic_bs_r_4(NULL, (bus_space_handle_t)l, 0)); } @@ -223,10 +304,8 @@ al_reg_read32(uint32_t *l) #define AL_DBG_LEVEL AL_DBG_LEVEL_ERR -extern struct mtx al_dbg_lock; - -#define AL_DBG_LOCK() mtx_lock_spin(&al_dbg_lock) -#define AL_DBG_UNLOCK() mtx_unlock_spin(&al_dbg_lock) +#define AL_DBG_LOCK() +#define AL_DBG_UNLOCK() /** * print message @@ -277,39 +356,6 @@ extern struct mtx al_dbg_lock; __FILE__, __LINE__, __func__, #COND); \ } while(AL_FALSE) -/** - * Make sure data will be visible by other masters (other CPUS and DMA). - * usually this is achieved by the ARM DMB instruction. - */ -static void al_data_memory_barrier(void); - -/** - * Make sure data will be visible by DMA masters, no restriction for other cpus - */ -static inline void -al_data_memory_barrier(void) -{ - dsb(); -} - -/** - * Make sure data will be visible in order by other cpus masters. - */ -static inline void -al_smp_data_memory_barrier(void) -{ - dsb(); -} - -/** - * Make sure write data will be visible in order by other cpus masters. - */ -static inline void -al_local_data_memory_barrier(void) -{ - dsb(); -} - /** * al_udelay - micro sec delay */ diff --git a/al_hal_plat_types.h b/al_hal_plat_types.h index 43896ae08f7..293fc3d703d 100644 --- a/al_hal_plat_types.h +++ b/al_hal_plat_types.h @@ -60,24 +60,6 @@ typedef int al_bool; /** boolean */ #define AL_TRUE 1 #define AL_FALSE 0 - -/* define types */ -#ifndef AL_HAVE_TYPES -typedef unsigned char uint8_t; /** unsigned 8 bits */ -typedef unsigned short uint16_t; /** unsigned 16 bits */ -typedef unsigned int uint32_t; /** unsigned 32 bits */ -typedef unsigned long long uint64_t; /** unsigned 64 bits */ - -typedef signed char int8_t; /** signed 8 bits */ -typedef short int int16_t; /** signed 16 bits */ -typedef signed int int32_t; /** signed 32 bits */ - -/** An unsigned int that is guaranteed to be the same size as a pointer */ -/** C99 standard */ -typedef unsigned long uintptr_t; -#endif - - /** in LPAE mode, the address address is 40 bit, we extend it to 64 bit */ typedef uint64_t al_phys_addr_t; diff --git a/al_hal_reg_utils.h b/al_hal_reg_utils.h index f29c3c5247b..42934ad35f4 100644 --- a/al_hal_reg_utils.h +++ b/al_hal_reg_utils.h @@ -57,6 +57,7 @@ extern "C" { /* *INDENT-ON* */ #define AL_BIT(b) (1UL << (b)) +#define AL_BIT_64(b) (1ULL << (b)) #define AL_ADDR_LOW(x) ((uint32_t)((al_phys_addr_t)(x))) #define AL_ADDR_HIGH(x) ((uint32_t)((((al_phys_addr_t)(x)) >> 16) >> 16)) diff --git a/al_hal_serdes.c b/al_hal_serdes.c index bb34d13c765..d45a9438eeb 100644 --- a/al_hal_serdes.c +++ b/al_hal_serdes.c @@ -1,5 +1,4 @@ -/*- -******************************************************************************* +/******************************************************************************* Copyright (C) 2015 Annapurna Labs Ltd. This file may be licensed under the terms of the Annapurna Labs Commercial @@ -34,9 +33,9 @@ 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" +#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)) @@ -67,64 +66,41 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #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 /** - * 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 + * SERDES core reg read */ static inline uint8_t al_serdes_grp_reg_read( - struct al_serdes_group_info *grp_info, + struct al_serdes_grp_obj *obj, 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 + * SERDES core reg write */ static inline void al_serdes_grp_reg_write( - struct al_serdes_group_info *grp_info, + struct al_serdes_grp_obj *obj, 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 + * SERDES core masked reg write */ static inline void al_serdes_grp_reg_masked_write( - struct al_serdes_group_info *grp_info, + struct al_serdes_grp_obj *obj, enum al_serdes_reg_page page, enum al_serdes_reg_type type, uint16_t offset, @@ -135,95 +111,63 @@ static inline void al_serdes_grp_reg_masked_write( * 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, + 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_group_info *grp_info); + 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_group_info *grp_info, + 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_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); + struct al_serdes_grp_obj *obj); /******************************************************************************/ /******************************************************************************/ -int al_serdes_handle_init( - void __iomem *serdes_regs_base, - struct al_serdes_obj *obj) +static enum al_serdes_type al_serdes_hssp_type_get(void) { - 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; + return AL_SRDS_TYPE_HSSP; } /******************************************************************************/ /******************************************************************************/ -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) +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, %d, %u)\n", + "%s(%p, %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], + obj, page, type, offset); @@ -236,49 +180,34 @@ int al_serdes_reg_read( 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) +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, %d, %u, %u)\n", + "%s(%p, %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], + obj, page, type, offset, @@ -287,17 +216,6 @@ int al_serdes_reg_write( 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) @@ -330,12 +248,10 @@ int al_serdes_lane_write( #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) +static void al_serdes_bist_overrides_enable( + struct al_serdes_grp_obj *obj, + enum al_serdes_rate rate) { - struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; int i; uint8_t rx_rate_val; @@ -367,7 +283,7 @@ void al_serdes_bist_overrides_enable( for (i = 0; i < AL_SRDS_NUM_LANES; i++) { al_serdes_grp_reg_masked_write( - grp_info, + obj, (enum al_serdes_reg_page)i, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PCSRX_DATAWIDTH_REG_NUM, @@ -377,7 +293,7 @@ void al_serdes_bist_overrides_enable( SERDES_IREG_FLD_PCSTX_DATAWIDTH_VAL_20); al_serdes_grp_reg_masked_write( - grp_info, + obj, (enum al_serdes_reg_page)i, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PCSRX_DIVRATE_REG_NUM, @@ -387,7 +303,7 @@ void al_serdes_bist_overrides_enable( } al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN_REG_NUM, @@ -398,7 +314,7 @@ void al_serdes_bist_overrides_enable( 0); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN_REG_NUM, @@ -409,7 +325,7 @@ void al_serdes_bist_overrides_enable( 0); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PCS_LOCWREN_REG_NUM, @@ -417,7 +333,7 @@ void al_serdes_bist_overrides_enable( 0); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_CMNPCS_TXENABLE_REG_NUM, @@ -426,7 +342,7 @@ void al_serdes_bist_overrides_enable( for (i = 0; i < AL_SRDS_NUM_LANES; i++) { al_serdes_grp_reg_masked_write( - grp_info, + obj, (enum al_serdes_reg_page)i, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM, @@ -439,7 +355,7 @@ void al_serdes_bist_overrides_enable( 0); al_serdes_grp_reg_masked_write( - grp_info, + obj, (enum al_serdes_reg_page)i, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PCSTXBIST_LOCWREN_REG_NUM, @@ -447,7 +363,7 @@ void al_serdes_bist_overrides_enable( 0); al_serdes_grp_reg_masked_write( - grp_info, + obj, (enum al_serdes_reg_page)i, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN_REG_NUM, @@ -455,7 +371,7 @@ void al_serdes_bist_overrides_enable( 0); al_serdes_grp_reg_masked_write( - grp_info, + obj, (enum al_serdes_reg_page)i, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXLOCK2REF_OVREN_REG_NUM, @@ -466,15 +382,13 @@ void al_serdes_bist_overrides_enable( /******************************************************************************/ /******************************************************************************/ -void al_serdes_bist_overrides_disable( - struct al_serdes_obj *obj, - enum al_serdes_group grp) +static void al_serdes_bist_overrides_disable( + struct al_serdes_grp_obj *obj) { - struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; int i; al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN_REG_NUM, @@ -483,7 +397,7 @@ void al_serdes_bist_overrides_disable( for (i = 0; i < AL_SRDS_NUM_LANES; i++) { al_serdes_grp_reg_masked_write( - grp_info, + obj, (enum al_serdes_reg_page)i, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM, @@ -493,7 +407,7 @@ void al_serdes_bist_overrides_disable( SERDES_IREG_FLD_PCSRXBIST_LOCWREN); al_serdes_grp_reg_masked_write( - grp_info, + obj, (enum al_serdes_reg_page)i, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PCSTXBIST_LOCWREN_REG_NUM, @@ -504,12 +418,10 @@ void al_serdes_bist_overrides_disable( /******************************************************************************/ /******************************************************************************/ -void al_serdes_rx_rate_change( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_rate rate) +static void al_serdes_rx_rate_change( + struct al_serdes_grp_obj *obj, + enum al_serdes_rate rate) { - struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; int i; uint8_t rx_rate_val; @@ -535,7 +447,7 @@ void al_serdes_rx_rate_change( for (i = 0; i < AL_SRDS_NUM_LANES; i++) { al_serdes_grp_reg_masked_write( - grp_info, + obj, (enum al_serdes_reg_page)i, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PCSRX_DIVRATE_REG_NUM, @@ -546,13 +458,10 @@ void al_serdes_rx_rate_change( /******************************************************************************/ /******************************************************************************/ -void al_serdes_group_pm_set( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_pm pm) +static void al_serdes_group_pm_set( + struct al_serdes_grp_obj *obj, + enum al_serdes_pm pm) { - struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; - uint8_t pm_val; switch (pm) { @@ -578,10 +487,10 @@ void al_serdes_group_pm_set( } if (pm == AL_SRDS_PM_PD) - al_serdes_group_rx_rate_change_sw_flow_dis(grp_info); + al_serdes_group_rx_rate_change_sw_flow_dis(obj); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_REG_NUM, @@ -589,46 +498,41 @@ void al_serdes_group_pm_set( pm_val); if (pm != AL_SRDS_PM_PD) - al_serdes_group_rx_rate_change_sw_flow_en_cond(grp_info); + al_serdes_group_rx_rate_change_sw_flow_en_cond(obj); } /******************************************************************************/ /******************************************************************************/ -void al_serdes_lane_rx_rate_change_sw_flow_en( - struct al_serdes_obj *obj, - enum al_serdes_group grp, +static void al_serdes_lane_rx_rate_change_sw_flow_en( + struct al_serdes_grp_obj *obj, 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); + 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); } /******************************************************************************/ /******************************************************************************/ -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) +static void al_serdes_lane_rx_rate_change_sw_flow_dis( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane) { - al_serdes_lane_write(obj, grp, 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, 0x7f); } /******************************************************************************/ /******************************************************************************/ -void al_serdes_lane_pcie_rate_override_enable_set( - struct al_serdes_obj *obj, - enum al_serdes_group grp, +static void al_serdes_lane_pcie_rate_override_enable_set( + struct al_serdes_grp_obj *obj, 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, + obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PCS, SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_ENA_REG_NUM, @@ -638,16 +542,13 @@ void al_serdes_lane_pcie_rate_override_enable_set( /******************************************************************************/ /******************************************************************************/ -al_bool al_serdes_lane_pcie_rate_override_is_enabled( - struct al_serdes_obj *obj, - enum al_serdes_group grp, +static al_bool al_serdes_lane_pcie_rate_override_is_enabled( + struct al_serdes_grp_obj *obj, 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, + 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; @@ -655,15 +556,12 @@ al_bool al_serdes_lane_pcie_rate_override_is_enabled( /******************************************************************************/ /******************************************************************************/ -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) +static enum al_serdes_pcie_rate al_serdes_lane_pcie_rate_get( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane) { - struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; - return (al_serdes_grp_reg_read( - grp_info, + obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PCS, SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_REG_NUM) & @@ -673,16 +571,13 @@ enum al_serdes_pcie_rate al_serdes_lane_pcie_rate_get( /******************************************************************************/ /******************************************************************************/ -void al_serdes_lane_pcie_rate_set( - struct al_serdes_obj *obj, - enum al_serdes_group grp, +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) { - struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; - al_serdes_grp_reg_masked_write( - grp_info, + obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PCS, SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_REG_NUM, @@ -692,15 +587,12 @@ void al_serdes_lane_pcie_rate_set( /******************************************************************************/ /******************************************************************************/ -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) +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) { - struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; - uint8_t rx_pm_val; uint8_t tx_pm_val; @@ -749,10 +641,10 @@ void al_serdes_lane_pm_set( } if (rx_pm == AL_SRDS_PM_PD) - _al_serdes_lane_rx_rate_change_sw_flow_dis(grp_info, lane); + _al_serdes_lane_rx_rate_change_sw_flow_dis(obj, lane); al_serdes_grp_reg_masked_write( - grp_info, + obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_LANEPCSPSTATE_RX_REG_NUM, @@ -760,7 +652,7 @@ void al_serdes_lane_pm_set( rx_pm_val); al_serdes_grp_reg_masked_write( - grp_info, + obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_LANEPCSPSTATE_TX_REG_NUM, @@ -768,24 +660,21 @@ void al_serdes_lane_pm_set( tx_pm_val); if (rx_pm != AL_SRDS_PM_PD) - _al_serdes_lane_rx_rate_change_sw_flow_en_cond(grp_info, lane); + _al_serdes_lane_rx_rate_change_sw_flow_en_cond(obj, lane); } /******************************************************************************/ /******************************************************************************/ -void al_serdes_pma_hard_reset_group( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - al_bool enable) +static void al_serdes_pma_hard_reset_group( + struct al_serdes_grp_obj *obj, + al_bool enable) { - struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; - if (enable) - al_serdes_group_rx_rate_change_sw_flow_dis(grp_info); + al_serdes_group_rx_rate_change_sw_flow_dis(obj); /* Enable Hard Reset Override */ al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_SYNTH_REG_NUM, @@ -794,7 +683,7 @@ void al_serdes_pma_hard_reset_group( /* Assert/Deassert Hard Reset Override */ al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_SYNTH_REG_NUM, @@ -804,25 +693,22 @@ void al_serdes_pma_hard_reset_group( SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_SYNTH_VAL_DEASSERT); if (!enable) - al_serdes_group_rx_rate_change_sw_flow_en_cond(grp_info); + al_serdes_group_rx_rate_change_sw_flow_en_cond(obj); } /******************************************************************************/ /******************************************************************************/ -void al_serdes_pma_hard_reset_lane( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - al_bool enable) +static void al_serdes_pma_hard_reset_lane( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + al_bool enable) { - struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; - if (enable) - _al_serdes_lane_rx_rate_change_sw_flow_dis(grp_info, lane); + _al_serdes_lane_rx_rate_change_sw_flow_dis(obj, lane); /* Enable Hard Reset Override */ al_serdes_grp_reg_masked_write( - grp_info, + obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_REG_NUM, @@ -831,7 +717,7 @@ void al_serdes_pma_hard_reset_lane( /* Assert/Deassert Hard Reset Override */ al_serdes_grp_reg_masked_write( - grp_info, + obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_REG_NUM, @@ -841,7 +727,7 @@ void al_serdes_pma_hard_reset_lane( SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_VAL_DEASSERT); if (!enable) - _al_serdes_lane_rx_rate_change_sw_flow_en_cond(grp_info, lane); + _al_serdes_lane_rx_rate_change_sw_flow_en_cond(obj, lane); } /******************************************************************************/ @@ -857,13 +743,11 @@ void al_serdes_pma_hard_reset_lane( #error Wrong assumption #endif -void al_serdes_loopback_control( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - enum al_serdes_lb_mode mode) +static void al_serdes_loopback_control( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + enum al_serdes_lb_mode mode) { - struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; uint8_t val = 0; switch (mode) { @@ -888,7 +772,7 @@ void al_serdes_loopback_control( } al_serdes_grp_reg_masked_write( - grp_info, + obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_LB_RX2TXUNTIMEDEN_REG_NUM, @@ -902,13 +786,11 @@ void al_serdes_loopback_control( /******************************************************************************/ /******************************************************************************/ -void al_serdes_bist_pattern_select( - struct al_serdes_obj *obj, - enum al_serdes_group grp, +static void al_serdes_bist_pattern_select( + struct al_serdes_grp_obj *obj, enum al_serdes_bist_pattern pattern, uint8_t *user_data) { - struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; uint8_t val = 0; switch (pattern) { @@ -938,7 +820,7 @@ void al_serdes_bist_pattern_select( for (i = 0; i < SERDES_IREG_FLD_TX_BIST_PAT_NUM_BYTES; i++) al_serdes_grp_reg_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_TX_BIST_PAT_REG_NUM(i), @@ -946,7 +828,7 @@ void al_serdes_bist_pattern_select( } al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_CMNPCSBIST_MODESEL_REG_NUM, @@ -956,16 +838,13 @@ void al_serdes_bist_pattern_select( /******************************************************************************/ /******************************************************************************/ -void al_serdes_bist_tx_enable( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - al_bool enable) +static void al_serdes_bist_tx_enable( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + al_bool enable) { - struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; - al_serdes_grp_reg_masked_write( - grp_info, + obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PCSTXBIST_EN_REG_NUM, @@ -975,14 +854,11 @@ void al_serdes_bist_tx_enable( /******************************************************************************/ /******************************************************************************/ -void al_serdes_bist_tx_err_inject( - struct al_serdes_obj *obj, - enum al_serdes_group grp) +static void al_serdes_bist_tx_err_inject( + struct al_serdes_grp_obj *obj) { - struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; - al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_TXBIST_BITERROR_EN_REG_NUM, @@ -990,7 +866,7 @@ void al_serdes_bist_tx_err_inject( SERDES_IREG_FLD_TXBIST_BITERROR_EN); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_TXBIST_BITERROR_EN_REG_NUM, @@ -1000,16 +876,13 @@ void al_serdes_bist_tx_err_inject( /******************************************************************************/ /******************************************************************************/ -void al_serdes_bist_rx_enable( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - al_bool enable) +static void al_serdes_bist_rx_enable( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + al_bool enable) { - struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; - al_serdes_grp_reg_masked_write( - grp_info, + obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PCSRXBIST_EN_REG_NUM, @@ -1024,33 +897,31 @@ void al_serdes_bist_rx_enable( #error Wrong assumption #endif -void al_serdes_bist_rx_status( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - al_bool *is_locked, - al_bool *err_cnt_overflow, - uint16_t *err_cnt) +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) { - struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; 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( - grp_info, + 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( - grp_info, + 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( - grp_info, + obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXBIST_ERRCOUNT_LSB_REG_NUM); @@ -1069,54 +940,36 @@ void al_serdes_bist_rx_status( /******************************************************************************/ /******************************************************************************/ static inline uint8_t al_serdes_grp_reg_read( - struct al_serdes_group_info *grp_info, + 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( - &grp_info->regs_base->gen.reg_addr, + ®s_base->gen.reg_addr, SRDS_CORE_REG_ADDR(page, type, offset)); - return al_reg_read32(&grp_info->regs_base->gen.reg_data); -} - -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) -{ - return al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)page, - type, offset); + return al_reg_read32(®s_base->gen.reg_data); } /******************************************************************************/ /******************************************************************************/ static inline void al_serdes_grp_reg_write( - struct al_serdes_group_info *grp_info, + 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( - &grp_info->regs_base->gen.reg_addr, + ®s_base->gen.reg_addr, SRDS_CORE_REG_ADDR(page, type, offset)); - al_reg_write32(&grp_info->regs_base->gen.reg_data, 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) -{ - al_serdes_grp_reg_write(grp_info, (enum al_serdes_reg_page)lane, - type, offset, data); + al_reg_write32(®s_base->gen.reg_data, data); } /******************************************************************************/ @@ -1129,7 +982,7 @@ static inline void al_serdes_ns_delay(int cnt) /******************************************************************************/ /******************************************************************************/ static inline void al_serdes_grp_reg_masked_write( - struct al_serdes_group_info *grp_info, + struct al_serdes_grp_obj *obj, enum al_serdes_reg_page page, enum al_serdes_reg_type type, uint16_t offset, @@ -1146,30 +999,18 @@ static inline void al_serdes_grp_reg_masked_write( end_page = AL_SRDS_REG_PAGE_3_LANE_3; } - for(iter_page = start_page; iter_page <= end_page; ++iter_page) { - val = al_serdes_grp_reg_read(grp_info, iter_page, type, offset); + for (iter_page = start_page; iter_page <= end_page; ++iter_page) { + val = al_serdes_grp_reg_read(obj, iter_page, type, offset); val &= ~mask; val |= data; - al_serdes_grp_reg_write(grp_info, iter_page, type, offset, val); + al_serdes_grp_reg_write(obj, iter_page, type, offset, val); } } -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) -{ - al_serdes_grp_reg_masked_write(grp_info, (enum al_serdes_reg_page)lane, - type, offset, mask, data); -} - /******************************************************************************/ /******************************************************************************/ static void _al_serdes_lane_rx_rate_change_sw_flow_dis( - struct al_serdes_group_info *grp_info, + struct al_serdes_grp_obj *obj, enum al_serdes_lane lane) { al_bool lane_sw_flow_enabled; @@ -1177,15 +1018,15 @@ static void _al_serdes_lane_rx_rate_change_sw_flow_dis( al_assert(lane != AL_SRDS_LANES_0123); lane_sw_flow_enabled = - (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + (al_serdes_grp_reg_read(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 201) == 0xfc) && - (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + (al_serdes_grp_reg_read(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 202) == 0xff) && - (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + (al_serdes_grp_reg_read(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 203) == 0xff) && - (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + (al_serdes_grp_reg_read(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 204) == 0xff) && - (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + (al_serdes_grp_reg_read(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 205) == 0xff); /** @@ -1194,7 +1035,7 @@ static void _al_serdes_lane_rx_rate_change_sw_flow_dis( */ if (lane_sw_flow_enabled) { al_dbg("%s(%d): actually disabling\n", __func__, lane); - al_serdes_grp_reg_masked_write(grp_info, (enum al_serdes_reg_page)lane, + al_serdes_grp_reg_masked_write(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 205, 0x80, 0x00); } } @@ -1202,18 +1043,18 @@ static void _al_serdes_lane_rx_rate_change_sw_flow_dis( /******************************************************************************/ /******************************************************************************/ static void al_serdes_group_rx_rate_change_sw_flow_dis( - struct al_serdes_group_info *grp_info) + struct al_serdes_grp_obj *obj) { int lane; for (lane = AL_SRDS_LANE_0; lane < AL_SRDS_NUM_LANES; lane++) - _al_serdes_lane_rx_rate_change_sw_flow_dis(grp_info, lane); + _al_serdes_lane_rx_rate_change_sw_flow_dis(obj, lane); } /******************************************************************************/ /******************************************************************************/ static void _al_serdes_lane_rx_rate_change_sw_flow_en_cond( - struct al_serdes_group_info *grp_info, + struct al_serdes_grp_obj *obj, enum al_serdes_lane lane) { al_bool lane_sw_flow_almost_enabled; @@ -1225,51 +1066,51 @@ static void _al_serdes_lane_rx_rate_change_sw_flow_en_cond( al_assert(lane != AL_SRDS_LANES_0123); lane_sw_flow_almost_enabled = - (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + (al_serdes_grp_reg_read(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 201) == 0xfc) && - (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + (al_serdes_grp_reg_read(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 202) == 0xff) && - (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + (al_serdes_grp_reg_read(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 203) == 0xff) && - (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + (al_serdes_grp_reg_read(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 204) == 0xff) && - (al_serdes_grp_reg_read(grp_info, (enum al_serdes_reg_page)lane, + (al_serdes_grp_reg_read(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 205) == 0x7f); group_reset_enabled = ((al_serdes_grp_reg_read( - grp_info, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, + 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) && ((al_serdes_grp_reg_read( - grp_info, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, + 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) == SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_SYNTH_VAL_ASSERT); lane_reset_enabled = ((al_serdes_grp_reg_read( - grp_info, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, + 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) && ((al_serdes_grp_reg_read( - grp_info, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, + 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) == SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_VAL_ASSERT); group_pd_enabled = (al_serdes_grp_reg_read( - grp_info, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, + 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) == SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_PD; lane_pd_enabled = (al_serdes_grp_reg_read( - grp_info, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, + 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) == SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_PD; @@ -1283,7 +1124,7 @@ static void _al_serdes_lane_rx_rate_change_sw_flow_en_cond( al_dbg("%s(%d): actually enabling\n", __func__, lane); al_serdes_ns_delay(500); - al_serdes_grp_reg_masked_write(grp_info, (enum al_serdes_reg_page)lane, + al_serdes_grp_reg_masked_write(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, 205, 0x80, 0x80); } } @@ -1291,33 +1132,34 @@ static void _al_serdes_lane_rx_rate_change_sw_flow_en_cond( /******************************************************************************/ /******************************************************************************/ static void al_serdes_group_rx_rate_change_sw_flow_en_cond( - struct al_serdes_group_info *grp_info) + struct al_serdes_grp_obj *obj) { int lane; for (lane = AL_SRDS_LANE_0; lane < AL_SRDS_NUM_LANES; lane++) - _al_serdes_lane_rx_rate_change_sw_flow_en_cond(grp_info, lane); + _al_serdes_lane_rx_rate_change_sw_flow_en_cond(obj, lane); } /******************************************************************************/ /******************************************************************************/ -int al_serdes_eye_measure_run( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - uint32_t timeout, - unsigned int *value) +static int al_serdes_eye_measure_run( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + uint32_t timeout, + unsigned int *value) { + struct al_serdes_grp_obj *grp_obj = obj; + struct al_serdes_regs __iomem *regs_base = grp_obj->regs_base; uint32_t reg = 0; uint32_t i; struct serdes_lane *lane_regs; - lane_regs = &obj->grp_info[grp].regs_base->lane[lane]; + lane_regs = ®s_base->lane[lane]; al_reg_write32(&lane_regs->ictl_multi_rxeq, SERDES_LANE_ICTL_MULTI_RXEQ_START_L_A); - for (i = 0 ; i < timeout ; i++) { + for (i = 0; i < timeout; i++) { reg = al_reg_read32(&lane_regs->octl_multi); if (reg & SERDES_LANE_OCTL_MULTI_RXEQ_DONE_L_A) @@ -1340,83 +1182,77 @@ int al_serdes_eye_measure_run( /******************************************************************************/ /******************************************************************************/ -int al_serdes_eye_diag_sample( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - unsigned int x, - int y, - unsigned int timeout, - unsigned int *value) +static int al_serdes_eye_diag_sample( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + unsigned int x, + int y, + unsigned int timeout, + unsigned int *value) { enum al_serdes_reg_page page = (enum al_serdes_reg_page)lane; - struct al_serdes_group_info *grp_info; uint32_t i; uint8_t sample_count_orig_msb; uint8_t sample_count_orig_lsb; 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); - grp_info = &obj->grp_info[grp]; - /* Obtain sample count by reading RXCALROAMEYEMEAS_COUNT */ - sample_count_orig_msb = al_serdes_grp_reg_read(grp_info, + sample_count_orig_msb = al_serdes_grp_reg_read(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_MSB_REG_NUM); - sample_count_orig_lsb = al_serdes_grp_reg_read(grp_info, + sample_count_orig_lsb = al_serdes_grp_reg_read(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_LSB_REG_NUM); /* Set sample count to ~100000 samples */ - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_MSB_REG_NUM, 0x13); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_LSB_REG_NUM, 0x88); /* BER Contour Overwrite */ - al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + al_serdes_grp_reg_masked_write(obj, page, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN_REG_NUM, SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN, 0); - al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + al_serdes_grp_reg_masked_write(obj, page, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN_REG_NUM, SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN, 0); - al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + al_serdes_grp_reg_masked_write(obj, page, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM, SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN, 0); /* RXROAM_XORBITSEL = 0x1 or 0x0 */ - al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + al_serdes_grp_reg_masked_write(obj, page, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXROAM_XORBITSEL_REG_NUM, SERDES_IREG_FLD_RXROAM_XORBITSEL, SERDES_IREG_FLD_RXROAM_XORBITSEL_2ND); /* Set X */ - al_serdes_grp_reg_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + al_serdes_grp_reg_write(obj, page, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMXADJUST_REG_NUM, x); /* Set Y */ - al_serdes_grp_reg_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + al_serdes_grp_reg_write(obj, page, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMYADJUST_REG_NUM, y < 32 ? 31 - y : y + 1); /* Start Measurement by setting RXCALROAMEYEMEASIN_CYCLEEN = 0x1 */ - al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + al_serdes_grp_reg_masked_write(obj, page, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMEYEMEASIN_CYCLEEN_REG_NUM, SERDES_IREG_FLD_RXCALROAMEYEMEASIN_CYCLEEN_START, SERDES_IREG_FLD_RXCALROAMEYEMEASIN_CYCLEEN_START); /* Check RXCALROAMEYEMEASDONE Signal (Polling Until 0x1) */ - for (i = 0 ; i < timeout ; i++) { - if (al_serdes_grp_reg_read(grp_info, page, AL_SRDS_REG_TYPE_PMA, + for (i = 0; i < timeout; i++) { + if (al_serdes_grp_reg_read(obj, page, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMEYEMEASDONE_REG_NUM) & SERDES_IREG_FLD_RXCALROAMEYEMEASDONE) break; @@ -1428,38 +1264,38 @@ int al_serdes_eye_diag_sample( } /* Stop Measurement by setting RXCALROAMEYEMEASIN_CYCLEEN = 0x0 */ - al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + al_serdes_grp_reg_masked_write(obj, page, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMEYEMEASIN_CYCLEEN_REG_NUM, SERDES_IREG_FLD_RXCALROAMEYEMEASIN_CYCLEEN_START, 0); /* Obtain Error Counts by reading RXCALROAMEYEMEAS_ACC */ - *value = ((unsigned int)al_serdes_grp_reg_read(grp_info, page, + *value = ((unsigned int)al_serdes_grp_reg_read(obj, page, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMEYEMEAS_ACC_MSB_REG_NUM)) << 8 | - al_serdes_grp_reg_read(grp_info, page, AL_SRDS_REG_TYPE_PMA, + al_serdes_grp_reg_read(obj, page, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMEYEMEAS_ACC_LSB_REG_NUM); /* BER Contour Overwrite */ - al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + al_serdes_grp_reg_masked_write(obj, page, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN_REG_NUM, SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN, SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN); - al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + al_serdes_grp_reg_masked_write(obj, page, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN_REG_NUM, SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN, SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN); - al_serdes_grp_reg_masked_write(grp_info, page, AL_SRDS_REG_TYPE_PMA, + al_serdes_grp_reg_masked_write(obj, page, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM, SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN, SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN); /* Restore sample count */ - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_MSB_REG_NUM, sample_count_orig_msb); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_LSB_REG_NUM, sample_count_orig_lsb); @@ -1470,33 +1306,32 @@ int al_serdes_eye_diag_sample( /******************************************************************************/ /******************************************************************************/ static void al_serdes_tx_deemph_set( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - uint32_t c_zero, - uint32_t c_plus_1, - uint32_t c_minus_1) + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + uint32_t c_zero, + uint32_t c_plus_1, + uint32_t c_minus_1) { - al_serdes_grp_lane_masked_write( - &obj->grp_info[grp], - lane, + al_serdes_grp_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_TX_DRV_1_REG_NUM, SERDES_IREG_TX_DRV_1_LEVN_MASK, ((c_zero + c_plus_1 + c_minus_1) << SERDES_IREG_TX_DRV_1_LEVN_SHIFT)); - al_serdes_grp_lane_masked_write( - &obj->grp_info[grp], - lane, + al_serdes_grp_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_TX_DRV_2_REG_NUM, SERDES_IREG_TX_DRV_2_LEVNM1_MASK, (c_plus_1 << SERDES_IREG_TX_DRV_2_LEVNM1_SHIFT)); - al_serdes_grp_lane_masked_write( - &obj->grp_info[grp], - lane, + al_serdes_grp_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_TX_DRV_3_REG_NUM, SERDES_IREG_TX_DRV_3_LEVNP1_MASK, @@ -1504,36 +1339,35 @@ static void al_serdes_tx_deemph_set( } static void al_serdes_tx_deemph_get( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - uint32_t *c_zero, - uint32_t *c_plus_1, - uint32_t *c_minus_1) + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + uint32_t *c_zero, + uint32_t *c_plus_1, + uint32_t *c_minus_1) { uint32_t reg = 0; - reg = al_serdes_grp_lane_read( - &obj->grp_info[grp], - lane, + reg = al_serdes_grp_reg_read( + obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_TX_DRV_2_REG_NUM); *c_plus_1 = ((reg & SERDES_IREG_TX_DRV_2_LEVNM1_MASK) >> SERDES_IREG_TX_DRV_2_LEVNM1_SHIFT); - reg = al_serdes_grp_lane_read( - &obj->grp_info[grp], - lane, + reg = al_serdes_grp_reg_read( + obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_TX_DRV_3_REG_NUM); *c_minus_1 = ((reg & SERDES_IREG_TX_DRV_3_LEVNP1_MASK) >> SERDES_IREG_TX_DRV_3_LEVNP1_SHIFT); - reg = al_serdes_grp_lane_read( - &obj->grp_info[grp], - lane, + reg = al_serdes_grp_reg_read( + obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_TX_DRV_1_REG_NUM); @@ -1541,18 +1375,17 @@ static void al_serdes_tx_deemph_get( SERDES_IREG_TX_DRV_1_LEVN_SHIFT) - *c_plus_1 - *c_minus_1); } -al_bool al_serdes_tx_deemph_inc( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - enum al_serdes_tx_deemph_param param) +static al_bool al_serdes_tx_deemph_inc( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + enum al_serdes_tx_deemph_param param) { al_bool ret = AL_TRUE; uint32_t c0; uint32_t c1; uint32_t c_1; - al_serdes_tx_deemph_get(obj, grp, lane, &c0, &c1, &c_1); + al_serdes_tx_deemph_get(obj, lane, &c0, &c1, &c_1); al_dbg("%s: current txdeemph: c0 = 0x%x c1 = 0x%x c-1 = 0x%x\n", __func__, c0, c1, c_1); @@ -1594,23 +1427,22 @@ al_bool al_serdes_tx_deemph_inc( al_dbg("%s: new txdeemph: c0 = 0x%x c1 = 0x%x c-1 = 0x%x\n", __func__, c0, c1, c_1); - al_serdes_tx_deemph_set(obj, grp, lane, c0, c1, c_1); + al_serdes_tx_deemph_set(obj, lane, c0, c1, c_1); return ret; } -al_bool al_serdes_tx_deemph_dec( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - enum al_serdes_tx_deemph_param param) +static al_bool al_serdes_tx_deemph_dec( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + enum al_serdes_tx_deemph_param param) { al_bool ret = AL_TRUE; uint32_t c0; uint32_t c1; uint32_t c_1; - al_serdes_tx_deemph_get(obj, grp, lane, &c0, &c1, &c_1); + al_serdes_tx_deemph_get(obj, lane, &c0, &c1, &c_1); al_dbg("%s: current txdeemph: c0 = 0x%x c1 = 0x%x c-1 = 0x%x\n", __func__, c0, c1, c_1); @@ -1645,15 +1477,14 @@ al_bool al_serdes_tx_deemph_dec( al_dbg("%s: new txdeemph: c0 = 0x%x c1 = 0x%x c-1 = 0x%x\n", __func__, c0, c1, c_1); - al_serdes_tx_deemph_set(obj, grp, lane, c0, c1, c_1); + al_serdes_tx_deemph_set(obj, lane, c0, c1, c_1); return ret; } -void al_serdes_tx_deemph_preset( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane) +static void al_serdes_tx_deemph_preset( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane) { uint32_t c0; uint32_t c1; @@ -1668,35 +1499,34 @@ void al_serdes_tx_deemph_preset( al_dbg("preset: new txdeemph: c0 = 0x%x c1 = 0x%x c-1 = 0x%x\n", c0, c1, c_1); - al_serdes_tx_deemph_set(obj, grp, lane, c0, c1, c_1); + al_serdes_tx_deemph_set(obj, lane, c0, c1, c_1); } -al_bool al_serdes_signal_is_detected( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane) +static al_bool al_serdes_signal_is_detected( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane) { uint32_t reg = 0; - reg = al_serdes_grp_lane_read( - &obj->grp_info[grp], - lane, + reg = al_serdes_grp_reg_read( + obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXRANDET_REG_NUM); return ((reg & SERDES_IREG_FLD_RXRANDET_STAT) ? AL_TRUE : AL_FALSE); } -void al_serdes_tx_advanced_params_set(struct al_serdes_obj *obj, - enum al_serdes_group grp, +static void al_serdes_tx_advanced_params_set(struct al_serdes_grp_obj *obj, enum al_serdes_lane lane, - struct al_serdes_adv_tx_params *params) + void *tx_params) { uint8_t reg = 0; + struct al_serdes_adv_tx_params *params = tx_params; - if(!params->override) { - al_serdes_grp_lane_masked_write(&obj->grp_info[grp], - lane, + if (!params->override) { + al_serdes_grp_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN_REG_NUM, SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN, @@ -1705,8 +1535,8 @@ void al_serdes_tx_advanced_params_set(struct al_serdes_obj *obj, return; } - al_serdes_grp_lane_masked_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN_REG_NUM, SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN, @@ -1722,8 +1552,8 @@ void al_serdes_tx_advanced_params_set(struct al_serdes_obj *obj, SERDES_IREG_TX_DRV_1_LEVN_SHIFT, params->total_driver_units); - al_serdes_grp_lane_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_TX_DRV_1_REG_NUM, reg); @@ -1739,8 +1569,8 @@ void al_serdes_tx_advanced_params_set(struct al_serdes_obj *obj, SERDES_IREG_TX_DRV_2_LEVNM2_SHIFT, params->c_plus_2); - al_serdes_grp_lane_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_TX_DRV_2_REG_NUM, reg); @@ -1756,63 +1586,67 @@ void al_serdes_tx_advanced_params_set(struct al_serdes_obj *obj, SERDES_IREG_TX_DRV_3_SLEW_SHIFT, params->slew_rate); - al_serdes_grp_lane_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_TX_DRV_3_REG_NUM, reg); } -void al_serdes_tx_advanced_params_get(struct al_serdes_obj *obj, - enum al_serdes_group grp, +static void al_serdes_tx_advanced_params_get(struct al_serdes_grp_obj *obj, enum al_serdes_lane lane, - struct al_serdes_adv_tx_params *tx_params) + void *tx_params) { + struct al_serdes_adv_tx_params *params = tx_params; uint8_t reg_val = 0; - al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read(obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_TX_DRV_1_REG_NUM, ®_val); - tx_params->amp = (reg_val & SERDES_IREG_TX_DRV_1_HLEV_MASK) >> + params->amp = (reg_val & SERDES_IREG_TX_DRV_1_HLEV_MASK) >> SERDES_IREG_TX_DRV_1_HLEV_SHIFT; - tx_params->total_driver_units = (reg_val & + params->total_driver_units = (reg_val & SERDES_IREG_TX_DRV_1_LEVN_MASK) >> SERDES_IREG_TX_DRV_1_LEVN_SHIFT; - al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read(obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_TX_DRV_2_REG_NUM, ®_val); - tx_params->c_plus_1 = (reg_val & SERDES_IREG_TX_DRV_2_LEVNM1_MASK) >> + params->c_plus_1 = (reg_val & SERDES_IREG_TX_DRV_2_LEVNM1_MASK) >> SERDES_IREG_TX_DRV_2_LEVNM1_SHIFT; - tx_params->c_plus_2 = (reg_val & SERDES_IREG_TX_DRV_2_LEVNM2_MASK) >> + params->c_plus_2 = (reg_val & SERDES_IREG_TX_DRV_2_LEVNM2_MASK) >> SERDES_IREG_TX_DRV_2_LEVNM2_SHIFT; - al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read(obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_TX_DRV_3_REG_NUM, ®_val); - tx_params->c_minus_1 = (reg_val & SERDES_IREG_TX_DRV_3_LEVNP1_MASK) >> + params->c_minus_1 = (reg_val & SERDES_IREG_TX_DRV_3_LEVNP1_MASK) >> SERDES_IREG_TX_DRV_3_LEVNP1_SHIFT; - tx_params->slew_rate = (reg_val & SERDES_IREG_TX_DRV_3_SLEW_MASK) >> + params->slew_rate = (reg_val & SERDES_IREG_TX_DRV_3_SLEW_MASK) >> SERDES_IREG_TX_DRV_3_SLEW_SHIFT; - al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read(obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN_REG_NUM, ®_val); - tx_params->override = ((reg_val & SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN) == 0); + params->override = ((reg_val & SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN) == 0); } -void al_serdes_rx_advanced_params_set(struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - struct al_serdes_adv_rx_params *params) +static void al_serdes_rx_advanced_params_set(struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + void *rx_params) { + struct al_serdes_adv_rx_params *params = rx_params; uint8_t reg = 0; - if(!params->override) { - al_serdes_grp_lane_masked_write(&obj->grp_info[grp], - lane, + if (!params->override) { + al_serdes_grp_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN_REG_NUM, SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN, @@ -1821,8 +1655,8 @@ void al_serdes_rx_advanced_params_set(struct al_serdes_obj *obj, return; } - al_serdes_grp_lane_masked_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN_REG_NUM, SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN, @@ -1838,8 +1672,8 @@ void al_serdes_rx_advanced_params_set(struct al_serdes_obj *obj, SERDES_IREG_RX_CALEQ_1_DFEPSTAP3DB_SHIFT, params->dfe_3db_freq); - al_serdes_grp_lane_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_RX_CALEQ_1_REG_NUM, reg); @@ -1855,8 +1689,8 @@ void al_serdes_rx_advanced_params_set(struct al_serdes_obj *obj, SERDES_IREG_RX_CALEQ_2_DFETAP1GAIN_SHIFT, params->dfe_first_tap_ctrl); - al_serdes_grp_lane_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_RX_CALEQ_2_REG_NUM, reg); @@ -1872,8 +1706,8 @@ void al_serdes_rx_advanced_params_set(struct al_serdes_obj *obj, SERDES_IREG_RX_CALEQ_3_DFETAP3GAIN_SHIFT, params->dfe_third_tap_ctrl); - al_serdes_grp_lane_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_RX_CALEQ_3_REG_NUM, reg); @@ -1889,8 +1723,8 @@ void al_serdes_rx_advanced_params_set(struct al_serdes_obj *obj, SERDES_IREG_RX_CALEQ_4_LOFREQAGCGAIN_SHIFT, params->low_freq_agc_gain); - al_serdes_grp_lane_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_RX_CALEQ_4_REG_NUM, reg); @@ -1906,17 +1740,17 @@ void al_serdes_rx_advanced_params_set(struct al_serdes_obj *obj, SERDES_IREG_RX_CALEQ_5_HIFREQAGCCAP_SHIFT, params->high_freq_agc_boost); - al_serdes_grp_lane_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_RX_CALEQ_5_REG_NUM, reg); } -static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_info) +static inline void al_serdes_common_cfg_eth(struct al_serdes_grp_obj *obj) { al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXEQ_LOOKUP_CODE_EN_REG_NUM, @@ -1924,7 +1758,7 @@ static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_inf (0x1 << SERDES_IREG_FLD_RXEQ_LOOKUP_CODE_EN_SHIFT)); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXEQ_LOOKUP_LASTCODE_REG_NUM, @@ -1932,7 +1766,7 @@ static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_inf (0 << SERDES_IREG_FLD_RXEQ_LOOKUP_LASTCODE_SHIFT)); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXEQ_COARSE_RUN1_MASK_REG_NUM, @@ -1940,7 +1774,7 @@ static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_inf (0x2 << SERDES_IREG_FLD_RXEQ_COARSE_RUN1_MASK_SHIFT)); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXEQ_COARSE_RUN2_MASK_REG_NUM, @@ -1948,7 +1782,7 @@ static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_inf (0 << SERDES_IREG_FLD_RXEQ_COARSE_RUN2_MASK_SHIFT)); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXEQ_COARSE_STEP_REG_NUM, @@ -1956,7 +1790,7 @@ static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_inf (0x1 << SERDES_IREG_FLD_RXEQ_COARSE_STEP_SHIFT)); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXEQ_COARSE_ITER_NUM_REG_NUM, @@ -1964,7 +1798,7 @@ static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_inf (0x1 << SERDES_IREG_FLD_RXEQ_COARSE_ITER_NUM_SHIFT)); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXEQ_FINE_RUN1_MASK_REG_NUM, @@ -1972,7 +1806,7 @@ static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_inf (0xf0 << SERDES_IREG_FLD_RXEQ_FINE_RUN1_MASK_SHIFT)); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXEQ_FINE_RUN2_MASK_REG_NUM, @@ -1980,7 +1814,7 @@ static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_inf (0 << SERDES_IREG_FLD_RXEQ_FINE_RUN2_MASK_SHIFT)); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXEQ_FINE_STEP_REG_NUM, @@ -1988,7 +1822,7 @@ static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_inf (1 << SERDES_IREG_FLD_RXEQ_FINE_STEP_SHIFT)); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXEQ_FINE_ITER_NUM_REG_NUM, @@ -1996,7 +1830,7 @@ static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_inf (0x8 << SERDES_IREG_FLD_RXEQ_FINE_ITER_NUM_SHIFT)); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD1_REG_NUM, @@ -2004,7 +1838,7 @@ static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_inf (0 << SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD1_SHIFT)); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD2_REG_NUM, @@ -2012,7 +1846,7 @@ static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_inf (0x64 << SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD2_SHIFT)); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_REG_NUM, @@ -2020,7 +1854,7 @@ static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_inf (0x3 << SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_SHIFT)); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_REG_NUM, @@ -2028,7 +1862,7 @@ static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_inf (0x1 << SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_SHIFT)); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_REG_NUM, @@ -2036,7 +1870,7 @@ static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_inf (3 << SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_SHIFT)); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_REG_NUM, @@ -2044,7 +1878,7 @@ static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_inf (1 << SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_SHIFT)); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_MSB_REG_NUM, @@ -2052,7 +1886,7 @@ static inline void al_serdes_common_cfg_eth(struct al_serdes_group_info *grp_inf (0xc << SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_MSB_SHIFT)); al_serdes_grp_reg_masked_write( - grp_info, + obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_LSB_REG_NUM, @@ -2068,23 +1902,25 @@ struct al_serdes_mode_rx_tx_inv_state { }; static void al_serdes_mode_rx_tx_inv_state_save( - struct al_serdes_group_info *grp_info, + struct al_serdes_grp_obj *obj, struct al_serdes_mode_rx_tx_inv_state *state) { - if (al_reg_read32(&grp_info->regs_base->gen.irst) & SERDES_GEN_IRST_POR_B_A) { + struct al_serdes_regs __iomem *regs_base = obj->regs_base; + + if (al_reg_read32(®s_base->gen.irst) & SERDES_GEN_IRST_POR_B_A) { int i; state->restore = AL_TRUE; - state->pipe_rst = al_reg_read32(&grp_info->regs_base->gen.irst); + state->pipe_rst = al_reg_read32(®s_base->gen.irst); for (i = 0; i < AL_SRDS_NUM_LANES; i++) { state->inv_value[i] = al_serdes_grp_reg_read( - grp_info, + obj, i, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_POLARITY_RX_REG_NUM); state->ipd_multi[i] = - al_reg_read32(&grp_info->regs_base->lane[i].ipd_multi); + al_reg_read32(®s_base->lane[i].ipd_multi); } } else { state->restore = AL_FALSE; @@ -2092,23 +1928,25 @@ static void al_serdes_mode_rx_tx_inv_state_save( } static void al_serdes_mode_rx_tx_inv_state_restore( - struct al_serdes_group_info *grp_info, + struct al_serdes_grp_obj *obj, struct al_serdes_mode_rx_tx_inv_state *state) { + struct al_serdes_regs __iomem *regs_base = obj->regs_base; + if (state->restore) { int i; for (i = 0; i < AL_SRDS_NUM_LANES; i++) { al_serdes_grp_reg_write( - grp_info, + obj, i, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_POLARITY_RX_REG_NUM, state->inv_value[i]); al_reg_write32( - &grp_info->regs_base->lane[i].ipd_multi, state->ipd_multi[i]); + ®s_base->lane[i].ipd_multi, state->ipd_multi[i]); al_reg_write32_masked( - &grp_info->regs_base->gen.irst, + ®s_base->gen.irst, (SERDES_GEN_IRST_PIPE_RST_L0_B_A_SEL >> i) | (SERDES_GEN_IRST_PIPE_RST_L0_B_A >> i), state->pipe_rst); @@ -2116,543 +1954,539 @@ static void al_serdes_mode_rx_tx_inv_state_restore( } } -void al_serdes_mode_set_sgmii( - struct al_serdes_obj *obj, - enum al_serdes_group grp) +static void al_serdes_mode_set_sgmii( + struct al_serdes_grp_obj *obj) { - struct al_serdes_group_info *grp_info; + struct al_serdes_grp_obj *grp_obj = obj; + struct al_serdes_regs __iomem *regs_base = grp_obj->regs_base; struct al_serdes_mode_rx_tx_inv_state rx_tx_inv_state; al_assert(obj); - al_assert(((int)grp) >= AL_SRDS_GRP_A); - al_assert(((int)grp) <= AL_SRDS_GRP_D); - grp_info = &obj->grp_info[grp]; + al_serdes_mode_rx_tx_inv_state_save(grp_obj, &rx_tx_inv_state); - al_serdes_mode_rx_tx_inv_state_save(grp_info, &rx_tx_inv_state); - - al_reg_write32(&grp_info->regs_base->gen.irst, 0x000000); - al_reg_write32(&grp_info->regs_base->lane[0].ictl_multi, 0x10110010); - al_reg_write32(&grp_info->regs_base->lane[1].ictl_multi, 0x10110010); - al_reg_write32(&grp_info->regs_base->lane[2].ictl_multi, 0x10110010); - al_reg_write32(&grp_info->regs_base->lane[3].ictl_multi, 0x10110010); - al_reg_write32(&grp_info->regs_base->gen.ipd_multi_synth , 0x0001); - al_reg_write32(&grp_info->regs_base->lane[0].ipd_multi, 0x0003); - al_reg_write32(&grp_info->regs_base->lane[1].ipd_multi, 0x0003); - al_reg_write32(&grp_info->regs_base->lane[2].ipd_multi, 0x0003); - al_reg_write32(&grp_info->regs_base->lane[3].ipd_multi, 0x0003); - al_reg_write32(&grp_info->regs_base->gen.ictl_pcs , 0); - al_reg_write32(&grp_info->regs_base->gen.irst, 0x001000); + al_reg_write32(®s_base->gen.irst, 0x000000); + al_reg_write32(®s_base->lane[0].ictl_multi, 0x10110010); + al_reg_write32(®s_base->lane[1].ictl_multi, 0x10110010); + al_reg_write32(®s_base->lane[2].ictl_multi, 0x10110010); + al_reg_write32(®s_base->lane[3].ictl_multi, 0x10110010); + al_reg_write32(®s_base->gen.ipd_multi_synth , 0x0001); + al_reg_write32(®s_base->lane[0].ipd_multi, 0x0003); + al_reg_write32(®s_base->lane[1].ipd_multi, 0x0003); + al_reg_write32(®s_base->lane[2].ipd_multi, 0x0003); + al_reg_write32(®s_base->lane[3].ipd_multi, 0x0003); + al_reg_write32(®s_base->gen.ictl_pcs , 0); + al_reg_write32(®s_base->gen.irst, 0x001000); al_serdes_ns_delay(800); - al_reg_write32(&grp_info->regs_base->gen.irst, 0x000000); + al_reg_write32(®s_base->gen.irst, 0x000000); al_serdes_ns_delay(500); - al_reg_write32(&grp_info->regs_base->gen.irst, 0x001000); + al_reg_write32(®s_base->gen.irst, 0x001000); al_serdes_ns_delay(500); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 101, 183); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 102, 183); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 103, 12); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 104, 12); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 105, 26); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 106, 26); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 107, 2); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 108, 2); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 109, 17); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 110, 13); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 101, 153); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 102, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 103, 108); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 104, 183); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 105, 183); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 106, 12); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 107, 12); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 108, 26); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 109, 26); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 110, 7); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 111, 12); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 112, 8); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 113, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 114, 8); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 115, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 116, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 117, 179); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 118, 246); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 119, 208); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 120, 239); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 121, 251); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 122, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 123, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 124, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 125, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 126, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 127, 211); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 128, 211); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 129, 226); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 130, 239); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 131, 251); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 132, 251); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 133, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 134, 239); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 135, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 136, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 137, 211); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 138, 211); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 139, 226); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 140, 239); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 141, 251); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 142, 251); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 143, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 144, 239); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 145, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 146, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 147, 251); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 148, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 149, 63); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 150, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 151, 100); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 152, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 153, 4); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 154, 2); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 155, 5); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 156, 5); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 157, 4); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 158, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 159, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 160, 8); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 161, 4); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 162, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 163, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 164, 4); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0_LANE_0, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0_LANE_0, AL_SRDS_REG_TYPE_PMA, 7, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_1_LANE_1, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_1_LANE_1, AL_SRDS_REG_TYPE_PMA, 7, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_2_LANE_2, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_2_LANE_2, AL_SRDS_REG_TYPE_PMA, 7, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_3_LANE_3, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_3_LANE_3, AL_SRDS_REG_TYPE_PMA, 7, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 13, 16); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 48, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 49, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 54, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 55, 180); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 93, 2); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 165, 3); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 41, 6); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 354, 3); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 355, 58); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 356, 9); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 357, 3); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 358, 62); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 359, 12); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 701, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 87, 0x1f); - al_serdes_common_cfg_eth(grp_info); + al_serdes_common_cfg_eth(obj); - al_serdes_mode_rx_tx_inv_state_restore(grp_info, &rx_tx_inv_state); + al_serdes_mode_rx_tx_inv_state_restore(grp_obj, &rx_tx_inv_state); + al_reg_write32(®s_base->gen.irst, 0x0011F0); - al_reg_write32(&grp_info->regs_base->gen.irst, 0x0011F0); al_serdes_ns_delay(500); } -void al_serdes_mode_set_kr( - struct al_serdes_obj *obj, - enum al_serdes_group grp) +static void al_serdes_mode_set_kr( + struct al_serdes_grp_obj *obj) { - struct al_serdes_group_info *grp_info; + struct al_serdes_grp_obj *grp_obj = obj; + struct al_serdes_regs __iomem *regs_base = grp_obj->regs_base; struct al_serdes_mode_rx_tx_inv_state rx_tx_inv_state; al_assert(obj); - al_assert(((int)grp) >= AL_SRDS_GRP_A); - al_assert(((int)grp) <= AL_SRDS_GRP_D); + al_serdes_mode_rx_tx_inv_state_save(grp_obj, &rx_tx_inv_state); - grp_info = &obj->grp_info[grp]; - - al_serdes_mode_rx_tx_inv_state_save(grp_info, &rx_tx_inv_state); - - al_reg_write32(&grp_info->regs_base->gen.irst, 0x000000); - al_reg_write32(&grp_info->regs_base->lane[0].ictl_multi, 0x30330030); - al_reg_write32(&grp_info->regs_base->lane[1].ictl_multi, 0x30330030); - al_reg_write32(&grp_info->regs_base->lane[2].ictl_multi, 0x30330030); - al_reg_write32(&grp_info->regs_base->lane[3].ictl_multi, 0x30330030); - al_reg_write32(&grp_info->regs_base->gen.ipd_multi_synth , 0x0001); - al_reg_write32(&grp_info->regs_base->lane[0].ipd_multi, 0x0003); - al_reg_write32(&grp_info->regs_base->lane[1].ipd_multi, 0x0003); - al_reg_write32(&grp_info->regs_base->lane[2].ipd_multi, 0x0003); - al_reg_write32(&grp_info->regs_base->lane[3].ipd_multi, 0x0003); - al_reg_write32(&grp_info->regs_base->gen.ictl_pcs , 0); - al_reg_write32(&grp_info->regs_base->gen.irst, 0x001000); + al_reg_write32(®s_base->gen.irst, 0x000000); + al_reg_write32(®s_base->lane[0].ictl_multi, 0x30330030); + al_reg_write32(®s_base->lane[1].ictl_multi, 0x30330030); + al_reg_write32(®s_base->lane[2].ictl_multi, 0x30330030); + al_reg_write32(®s_base->lane[3].ictl_multi, 0x30330030); + al_reg_write32(®s_base->gen.ipd_multi_synth , 0x0001); + al_reg_write32(®s_base->lane[0].ipd_multi, 0x0003); + al_reg_write32(®s_base->lane[1].ipd_multi, 0x0003); + al_reg_write32(®s_base->lane[2].ipd_multi, 0x0003); + al_reg_write32(®s_base->lane[3].ipd_multi, 0x0003); + al_reg_write32(®s_base->gen.ictl_pcs , 0); + al_reg_write32(®s_base->gen.irst, 0x001000); al_serdes_ns_delay(800); - al_reg_write32(&grp_info->regs_base->gen.irst, 0x000000); + al_reg_write32(®s_base->gen.irst, 0x000000); al_serdes_ns_delay(500); - al_reg_write32(&grp_info->regs_base->gen.irst, 0x001000); + al_reg_write32(®s_base->gen.irst, 0x001000); al_serdes_ns_delay(500); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 101, 189); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 102, 189); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 103, 6); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 104, 6); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 105, 27); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 106, 27); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 107, 1); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 108, 1); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 109, 119); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 110, 5); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 101, 170); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 102, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 103, 108); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 104, 189); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 105, 189); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 106, 6); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 107, 6); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 108, 27); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 109, 27); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 110, 7); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 111, 12); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 112, 16); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 113, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 114, 16); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 115, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 116, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 117, 179); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 118, 246); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 119, 208); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 120, 239); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 121, 251); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 122, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 123, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 124, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 125, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 126, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 127, 211); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 128, 211); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 129, 226); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 130, 239); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 131, 251); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 132, 251); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 133, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 134, 239); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 135, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 136, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 137, 211); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 138, 211); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 139, 226); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 140, 239); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 141, 251); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 142, 251); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 143, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 144, 239); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 145, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 146, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 147, 251); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 148, 255); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 149, 63); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 150, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 151, 50); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 152, 17); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 153, 2); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 154, 1); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 155, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 156, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 157, 4); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 158, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 159, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 160, 8); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 161, 4); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 162, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 163, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 164, 4); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0_LANE_0, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0_LANE_0, AL_SRDS_REG_TYPE_PMA, 7, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_1_LANE_1, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_1_LANE_1, AL_SRDS_REG_TYPE_PMA, 7, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_2_LANE_2, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_2_LANE_2, AL_SRDS_REG_TYPE_PMA, 7, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_3_LANE_3, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_3_LANE_3, AL_SRDS_REG_TYPE_PMA, 7, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 13, 16); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 48, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 49, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 54, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 55, 149); /*Was 182*/ - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 93, 2); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 165, 3); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 41, 6); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 354, 3); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 355, 58); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 356, 9); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 357, 3); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 358, 62); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, 359, 12); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 701, 0); - al_serdes_grp_reg_write(grp_info, AL_SRDS_REG_PAGE_0123_LANES_0123, + al_serdes_grp_reg_write(obj, AL_SRDS_REG_PAGE_0123_LANES_0123, AL_SRDS_REG_TYPE_PMA, 87, 0x1f); - al_serdes_common_cfg_eth(grp_info); + al_serdes_common_cfg_eth(obj); - al_serdes_mode_rx_tx_inv_state_restore(grp_info, &rx_tx_inv_state); + al_serdes_mode_rx_tx_inv_state_restore(grp_obj, &rx_tx_inv_state); - al_reg_write32(&grp_info->regs_base->gen.irst, 0x0011F0); + al_reg_write32(®s_base->gen.irst, 0x0011F0); al_serdes_ns_delay(500); } -void al_serdes_rx_advanced_params_get(struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - struct al_serdes_adv_rx_params* rx_params) +static void al_serdes_rx_advanced_params_get(struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + void *rx_params) { + struct al_serdes_adv_rx_params *params = rx_params; uint8_t temp_val; - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_RX_CALEQ_1_REG_NUM, &temp_val); - rx_params->dcgain = (temp_val & SERDES_IREG_RX_CALEQ_1_DCGAIN_MASK) >> + params->dcgain = (temp_val & SERDES_IREG_RX_CALEQ_1_DCGAIN_MASK) >> SERDES_IREG_RX_CALEQ_1_DCGAIN_SHIFT; - rx_params->dfe_3db_freq = (temp_val & + params->dfe_3db_freq = (temp_val & SERDES_IREG_RX_CALEQ_1_DFEPSTAP3DB_MASK) >> SERDES_IREG_RX_CALEQ_1_DFEPSTAP3DB_SHIFT; - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_RX_CALEQ_2_REG_NUM, &temp_val); - rx_params->dfe_gain = (temp_val & + params->dfe_gain = (temp_val & SERDES_IREG_RX_CALEQ_2_DFEPSTAPGAIN_MASK) >> SERDES_IREG_RX_CALEQ_2_DFEPSTAPGAIN_SHIFT; - rx_params->dfe_first_tap_ctrl = (temp_val & + params->dfe_first_tap_ctrl = (temp_val & SERDES_IREG_RX_CALEQ_2_DFETAP1GAIN_MASK) >> SERDES_IREG_RX_CALEQ_2_DFETAP1GAIN_SHIFT; - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_RX_CALEQ_3_REG_NUM, &temp_val); - rx_params->dfe_secound_tap_ctrl = (temp_val & + params->dfe_secound_tap_ctrl = (temp_val & SERDES_IREG_RX_CALEQ_3_DFETAP2GAIN_MASK) >> SERDES_IREG_RX_CALEQ_3_DFETAP2GAIN_SHIFT; - rx_params->dfe_third_tap_ctrl = (temp_val & + params->dfe_third_tap_ctrl = (temp_val & SERDES_IREG_RX_CALEQ_3_DFETAP3GAIN_MASK) >> SERDES_IREG_RX_CALEQ_3_DFETAP3GAIN_SHIFT; - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_RX_CALEQ_4_REG_NUM, &temp_val); - rx_params->dfe_fourth_tap_ctrl = (temp_val & + params->dfe_fourth_tap_ctrl = (temp_val & SERDES_IREG_RX_CALEQ_4_DFETAP4GAIN_MASK) >> SERDES_IREG_RX_CALEQ_4_DFETAP4GAIN_SHIFT; - rx_params->low_freq_agc_gain = (temp_val & + params->low_freq_agc_gain = (temp_val & SERDES_IREG_RX_CALEQ_4_LOFREQAGCGAIN_MASK) >> SERDES_IREG_RX_CALEQ_4_LOFREQAGCGAIN_SHIFT; - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_RX_CALEQ_5_REG_NUM, &temp_val); - rx_params->precal_code_sel = (temp_val & + params->precal_code_sel = (temp_val & SERDES_IREG_RX_CALEQ_5_PRECAL_CODE_SEL_MASK) >> SERDES_IREG_RX_CALEQ_5_PRECAL_CODE_SEL_SHIFT; - rx_params->high_freq_agc_boost = (temp_val & + params->high_freq_agc_boost = (temp_val & SERDES_IREG_RX_CALEQ_5_HIFREQAGCCAP_MASK) >> SERDES_IREG_RX_CALEQ_5_HIFREQAGCCAP_SHIFT; - al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read(obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN_REG_NUM, &temp_val); - rx_params->override = ((temp_val & SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN) == 0); + params->override = ((temp_val & SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN) == 0); } -#if ( SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN_REG_NUM != \ +#if (SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN_REG_NUM != \ SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN_REG_NUM || \ SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN_REG_NUM != \ SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN_REG_NUM) #error Wrong assumption #endif -int al_serdes_rx_equalization( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane) +static int al_serdes_rx_equalization( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane) { uint8_t serdes_ireg_fld_rxcalroamyadjust_locwren_val; uint8_t serdes_ireg_fld_rxroam_xorbitsel_val; @@ -2667,39 +2501,43 @@ int al_serdes_rx_equalization( /* * Make sure Roam Eye mechanism is not overridden * Lane SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN = 1, - * so Rx 4-Point Eye process is not overridden + * so Rx 4-Point Eye process is not overridden * Lane SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN = 1, - * so Eye Roam latch is not overridden + * so Eye Roam latch is not overridden * Lane SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN = 1, - * so Eye Roam latch 'X adjust' is not overridden + * so Eye Roam latch 'X adjust' is not overridden * Lane SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN = 1, - * so Eye Roam latch 'Y adjust' is not overridden + * so Eye Roam latch 'Y adjust' is not overridden * Lane SERDES_IREG_FLD_RXROAM_XORBITSEL = 0/1, - * so Eye Roamlatch works on the right Eye position (XORBITSEL) - * For most cases 0 is needed, but sometimes 1 is needed. - * I couldn't sort out why is this so the code uses a global + * so Eye Roamlatch works on the right Eye position (XORBITSEL) + * For most cases 0 is needed, but sometimes 1 is needed. + * I couldn't sort out why is this so the code uses a global * XORBITSELmode variable, set by the user (GUI). Default is 0. * control must be internal. At the end we restore original setting */ /* save current values for restoring them later in the end */ - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM, &serdes_ireg_fld_rxcal_locwren_val); - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM, - &serdes_ireg_fld_rxcalroamyadjust_locwren_val ); - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + &serdes_ireg_fld_rxcalroamyadjust_locwren_val); + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXROAM_XORBITSEL_REG_NUM, - &serdes_ireg_fld_rxroam_xorbitsel_val ); - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + &serdes_ireg_fld_rxroam_xorbitsel_val); + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PCSRXEQ_LOCWREN_REG_NUM, - &serdes_ireg_fld_pcsrxeq_locwren_val ); + &serdes_ireg_fld_pcsrxeq_locwren_val); /* * Set Bits: @@ -2717,10 +2555,11 @@ int al_serdes_rx_equalization( temp_val |= SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN; temp_val |= SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN; - al_serdes_lane_write( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM, - temp_val ); + temp_val); /* * Set bit SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN @@ -2728,10 +2567,11 @@ int al_serdes_rx_equalization( */ temp_val = serdes_ireg_fld_rxcalroamyadjust_locwren_val | SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN; - al_serdes_lane_write( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM, - temp_val ); + temp_val); /* * Clear Bit: SERDES_IREG_FLD_RXROAM_XORBITSEL @@ -2739,10 +2579,11 @@ int al_serdes_rx_equalization( */ temp_val = serdes_ireg_fld_rxroam_xorbitsel_val & ~SERDES_IREG_FLD_RXROAM_XORBITSEL; - al_serdes_lane_write( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXROAM_XORBITSEL_REG_NUM, - temp_val ); + temp_val); /* * Take Control from int.pin over RxEQ process. @@ -2751,10 +2592,11 @@ int al_serdes_rx_equalization( */ temp_val = serdes_ireg_fld_pcsrxeq_locwren_val & ~SERDES_IREG_FLD_PCSRXEQ_LOCWREN; - al_serdes_lane_write( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PCSRXEQ_LOCWREN_REG_NUM, - temp_val ); + temp_val); /* @@ -2762,30 +2604,34 @@ int al_serdes_rx_equalization( * Clear Bit SERDES_IREG_FLD_PCSRXEQ_START * to start fresh from Stop */ - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PCSRXEQ_START_REG_NUM, - &temp_val ); + &temp_val); temp_val &= ~SERDES_IREG_FLD_PCSRXEQ_START; - al_serdes_lane_write( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PCSRXEQ_START_REG_NUM, - temp_val ); + temp_val); /* Set Bit SERDES_IREG_FLD_PCSRXEQ_START * to begin Rx Eq Cal */ temp_val |= SERDES_IREG_FLD_PCSRXEQ_START; - al_serdes_lane_write( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PCSRXEQ_START_REG_NUM, - temp_val ); + temp_val); /* Poll on RxEq Cal completion. SERDES_IREG_FLD_RXEQ_DONE. 1=Done. */ - for( i = 0; i < AL_SERDES_RX_EQUAL_TRIES; ++i ) { - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + for (i = 0; i < AL_SERDES_RX_EQUAL_TRIES; ++i) { + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMEYEMEASDONE_REG_NUM, - &done ); + &done); done &= SERDES_IREG_FLD_RXEQ_DONE; /* Check if RxEQ Cal is done */ @@ -2801,44 +2647,51 @@ int al_serdes_rx_equalization( /* Stop the RxEQ process. */ temp_val &= ~SERDES_IREG_FLD_PCSRXEQ_START; - al_serdes_lane_write( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PCSRXEQ_START_REG_NUM, - temp_val ); + temp_val); /* Get score */ - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_RXEQ_BEST_EYE_MSB_VAL_REG_NUM, - &temp_val ); - test_score = (int)( (temp_val & 0xFF) << 6 ); - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + &temp_val); + test_score = (int)((temp_val & 0xFF) << 6); + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_RXEQ_BEST_EYE_LSB_VAL_REG_NUM, - &temp_val ); + &temp_val); test_score += (int)(temp_val & SERDES_IREG_RXEQ_BEST_EYE_LSB_VAL_MASK); /* Restore start values */ - al_serdes_lane_write( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM, serdes_ireg_fld_rxcal_locwren_val); - al_serdes_lane_write( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM, - serdes_ireg_fld_rxcalroamyadjust_locwren_val ); - al_serdes_lane_write( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + serdes_ireg_fld_rxcalroamyadjust_locwren_val); + al_serdes_reg_write( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXROAM_XORBITSEL_REG_NUM, - serdes_ireg_fld_rxroam_xorbitsel_val ); - al_serdes_lane_write( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + serdes_ireg_fld_rxroam_xorbitsel_val); + al_serdes_reg_write( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PCSRXEQ_LOCWREN_REG_NUM, - serdes_ireg_fld_pcsrxeq_locwren_val ); + serdes_ireg_fld_pcsrxeq_locwren_val); return test_score; } -#if ( SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM != \ +#if (SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM != \ SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN_REG_NUM || \ SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM != \ SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN_REG_NUM || \ @@ -2846,12 +2699,11 @@ int al_serdes_rx_equalization( SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN_REG_NUM) #error Wrong assumption #endif -int al_serdes_calc_eye_size( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - int* width, - int* height) +static int al_serdes_calc_eye_size( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + int *width, + int *height) { uint8_t rxcaleyediagfsm_x_y_valweight_val; uint8_t rxcaleyediagfsm_xvalcoarse_val; @@ -2868,51 +2720,55 @@ int al_serdes_calc_eye_size( uint8_t reg_value; /* Save Registers */ - al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read(obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXLOCK2REF_LOCWREN_REG_NUM, &rxlock2ref_locwren_val); - al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read(obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM, &rxcal_locwren_val); - al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read(obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM, &rxcalroamyadjust_locwren_val); - al_serdes_lane_read(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read(obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXLOCK2REF_OVREN_REG_NUM, &rxlock2ref_ovren_val); - al_serdes_reg_read(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_read(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_X_Y_VALWEIGHT_REG_NUM, &rxcaleyediagfsm_x_y_valweight_val); - al_serdes_reg_read(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_read(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_REG_NUM, &rxcaleyediagfsm_xvalcoarse_val); - al_serdes_reg_read(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_read(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_REG_NUM, &rxcaleyediagfsm_xvalfine_val); - al_serdes_reg_read(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_read(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_REG_NUM, &rxcaleyediagfsm_yvalcoarse_val); - al_serdes_reg_read(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_read(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_REG_NUM, &rxcaleyediagfsm_yvalfine_val); /* * Clear Bit: - * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN - * to override RxEQ via PMA + * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN + * to override RxEQ via PMA * Set Bits: - * SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN, - * SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN - * to keep Eye Diag Roam controlled internally + * SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN, + * SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN + * to keep Eye Diag Roam controlled internally */ - al_serdes_grp_lane_masked_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM, SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN | @@ -2922,11 +2778,11 @@ int al_serdes_calc_eye_size( SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN); /* * Set Bit: - * SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN - * to keep Eye Diag Roam controlled internally + * SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN + * to keep Eye Diag Roam controlled internally */ - al_serdes_grp_lane_masked_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM, SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN, @@ -2934,14 +2790,14 @@ int al_serdes_calc_eye_size( /* * Clear Bit: - * SERDES_IREG_FLD_RXROAM_XORBITSEL, - * so XORBITSEL=0, needed for the Eye mapping + * SERDES_IREG_FLD_RXROAM_XORBITSEL, + * so XORBITSEL=0, needed for the Eye mapping * Set Bit: * SERDES_IREG_FLD_RXLOCK2REF_OVREN, * so RXLOCK2REF_OVREN=1, keeping lock to data, preventing data hit */ - al_serdes_grp_lane_masked_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXROAM_XORBITSEL_REG_NUM, SERDES_IREG_FLD_RXLOCK2REF_OVREN | @@ -2951,11 +2807,11 @@ int al_serdes_calc_eye_size( /* * Clear Bit: - * SERDES_IREG_FLD_RXLOCK2REF_LOCWREN, - * so RXLOCK2REF_LOCWREN=0, to override control + * SERDES_IREG_FLD_RXLOCK2REF_LOCWREN, + * so RXLOCK2REF_LOCWREN=0, to override control */ - al_serdes_grp_lane_masked_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXLOCK2REF_LOCWREN_REG_NUM, SERDES_IREG_FLD_RXLOCK2REF_LOCWREN, @@ -2964,49 +2820,50 @@ int al_serdes_calc_eye_size( /* Width Calculation */ /* Return Value = 0*Y + 1*X */ - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_X_Y_VALWEIGHT_REG_NUM, 0x01); /* X coarse scan step = 3 */ - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_REG_NUM, 0x03); /* X fine scan step = 1 */ - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_REG_NUM, 0x01); /* Y coarse scan step = 0 */ - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_REG_NUM, 0x00); /* Y fine scan step = 0 */ - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_REG_NUM, 0x00); /* * Set Bit: - * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, - * to start Eye measurement + * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, + * to start Eye measurement */ - al_serdes_grp_lane_masked_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START_REG_NUM, SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START); - for( i = 0; i < AL_SERDES_RX_EYE_CAL_TRIES; ++i ) { + for(i = 0; i < AL_SERDES_RX_EYE_CAL_TRIES; ++i) { /* Check if RxEQ Cal is done */ - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_DONE_REG_NUM, - &status ); + &status); if (status & SERDES_IREG_FLD_RXCALEYEDIAGFSM_DONE) break; al_msleep(AL_SERDES_RX_EYE_CAL_MDELAY); @@ -3023,27 +2880,29 @@ int al_serdes_calc_eye_size( } /* Read Eye Opening Metrics, Bits: - * SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB, - * SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB + * SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB, + * SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB */ - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_MSB_REG_NUM, - ®_value ); + ®_value); *width = reg_value << 6; - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB_REG_NUM, - ®_value ); + ®_value); *width =+ reg_value & SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB_MAKE; /* * Clear Bit: - * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, - * to stop Eye measurement + * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, + * to stop Eye measurement */ - al_serdes_grp_lane_masked_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START_REG_NUM, SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, @@ -3052,38 +2911,38 @@ int al_serdes_calc_eye_size( /* Height Calculation */ /* Return Value = 1*Y + 0*X */ - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_X_Y_VALWEIGHT_REG_NUM, 0x10); /* X coarse scan step = 0 */ - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_REG_NUM, 0x00); /* X fine scan step = 0 */ - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_REG_NUM, 0x00); /* Y coarse scan step = 3 */ - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_REG_NUM, 0x03); /* Y fine scan step = 1 */ - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_REG_NUM, 0x01); /* * Set Bit: - * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, - * to start Eye measurement + * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, + * to start Eye measurement */ - al_serdes_grp_lane_masked_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START_REG_NUM, SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, @@ -3091,8 +2950,9 @@ int al_serdes_calc_eye_size( for( i = 0; i < AL_SERDES_RX_EYE_CAL_TRIES; ++i ) { /* Check if RxEQ Cal is done */ - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_DONE_REG_NUM, &status ); if (status & SERDES_IREG_FLD_RXCALEYEDIAGFSM_DONE) @@ -3111,118 +2971,194 @@ int al_serdes_calc_eye_size( } /* Read Eye Opening Metrics, Bits: - * SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB, - * SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB + * SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB, + * SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB */ - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_MSB_REG_NUM, ®_value ); *height = reg_value << 6; - al_serdes_lane_read( - obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_read( + obj, (enum al_serdes_reg_page)lane, + AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB_REG_NUM, ®_value ); *height =+ reg_value & SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB_MAKE; /* * Clear Bit: - * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, - * to stop Eye measurement + * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, + * to stop Eye measurement */ - al_serdes_grp_lane_masked_write(&obj->grp_info[grp], - lane, + al_serdes_grp_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START_REG_NUM, SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START, 0); /* Restore Registers */ - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_X_Y_VALWEIGHT_REG_NUM, rxcaleyediagfsm_x_y_valweight_val); - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_REG_NUM, rxcaleyediagfsm_xvalcoarse_val); - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_REG_NUM, rxcaleyediagfsm_xvalfine_val); - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_REG_NUM, rxcaleyediagfsm_yvalcoarse_val); - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_REG_NUM, rxcaleyediagfsm_yvalfine_val); - al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXLOCK2REF_LOCWREN_REG_NUM, rxlock2ref_locwren_val); - al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM, rxcal_locwren_val); - al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM, rxcalroamyadjust_locwren_val); - al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write(obj, (enum al_serdes_reg_page)lane, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_RXLOCK2REF_OVREN_REG_NUM, rxlock2ref_ovren_val); return 0; } -void al_serdes_sris_config( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - struct al_serdes_sris_params *params) +static void al_serdes_sris_config( + struct al_serdes_grp_obj *obj, + void *sris_params) { - struct al_serdes_group_info *grp_info = &obj->grp_info[grp]; + struct al_serdes_sris_params *params = sris_params; - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PPMDRIFTCOUNT1_REG_NUM, (params->ppm_drift_count & AL_FIELD_MASK(7, 0)) >> 0); - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PPMDRIFTCOUNT2_REG_NUM, (params->ppm_drift_count & AL_FIELD_MASK(15, 8)) >> 8); - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PPMDRIFTMAX1_REG_NUM, (params->ppm_drift_max & AL_FIELD_MASK(7, 0)) >> 0); - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_PPMDRIFTMAX2_REG_NUM, (params->ppm_drift_max & AL_FIELD_MASK(15, 8)) >> 8); - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_SYNTHPPMDRIFTMAX1_REG_NUM, (params->synth_ppm_drift_max & AL_FIELD_MASK(7, 0)) >> 0); - al_serdes_reg_write(obj, grp, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, + al_serdes_reg_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PMA, SERDES_IREG_FLD_SYNTHPPMDRIFTMAX2_REG_NUM, (params->synth_ppm_drift_max & AL_FIELD_MASK(15, 8)) >> 8); - al_serdes_grp_reg_masked_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PCS, + al_serdes_grp_reg_masked_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PCS, SERDES_IREG_FLD_PCS_EBUF_FULL_D2R1_REG_NUM, SERDES_IREG_FLD_PCS_EBUF_FULL_D2R1_REG_MASK, (params->full_d2r1) << SERDES_IREG_FLD_PCS_EBUF_FULL_D2R1_REG_SHIFT); - al_serdes_grp_reg_masked_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PCS, + al_serdes_grp_reg_masked_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PCS, SERDES_IREG_FLD_PCS_EBUF_FULL_PCIE_G3_REG_NUM, SERDES_IREG_FLD_PCS_EBUF_FULL_PCIE_G3_REG_MASK, (params->full_pcie_g3) << SERDES_IREG_FLD_PCS_EBUF_FULL_PCIE_G3_REG_SHIFT); - al_serdes_grp_reg_masked_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PCS, + al_serdes_grp_reg_masked_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PCS, SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_D2R1_REG_NUM, SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_D2R1_REG_MASK, (params->rd_threshold_d2r1) << SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_D2R1_REG_SHIFT); - al_serdes_grp_reg_masked_write(grp_info, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PCS, + al_serdes_grp_reg_masked_write(obj, AL_SRDS_REG_PAGE_4_COMMON, AL_SRDS_REG_TYPE_PCS, SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_PCIE_G3_REG_NUM, SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_PCIE_G3_REG_MASK, (params->rd_threshold_pcie_g3) << SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_PCIE_G3_REG_SHIFT); } + +/******************************************************************************/ +/******************************************************************************/ +static void al_serdes_dcgain_set( + struct al_serdes_grp_obj *obj, + uint8_t dcgain) +{ + al_serdes_grp_reg_masked_write(obj, + AL_SRDS_REG_PAGE_4_COMMON, + AL_SRDS_REG_TYPE_PMA, + SERDES_IREG_FLD_RXEQ_DCGAIN_LUP0_REG_NUM, + SERDES_IREG_FLD_RXEQ_DCGAIN_LUP0_MASK, + (dcgain << SERDES_IREG_FLD_RXEQ_DCGAIN_LUP0_SHIFT)); +} + + +/******************************************************************************/ +/******************************************************************************/ +int al_serdes_hssp_handle_init( + void __iomem *serdes_regs_base, + struct al_serdes_grp_obj *obj) +{ + al_dbg( + "%s(%p, %p)\n", + __func__, + serdes_regs_base, + obj); + + al_memset(obj, 0, sizeof(struct al_serdes_grp_obj)); + + obj->regs_base = (struct al_serdes_regs *)serdes_regs_base; + obj->type_get = al_serdes_hssp_type_get; + obj->reg_read = al_serdes_reg_read; + obj->reg_write = al_serdes_reg_write; + obj->bist_overrides_enable = AL_SRDS_ADV_SRVC(al_serdes_bist_overrides_enable); + obj->bist_overrides_disable = AL_SRDS_ADV_SRVC(al_serdes_bist_overrides_disable); + obj->rx_rate_change = AL_SRDS_ADV_SRVC(al_serdes_rx_rate_change); + obj->rx_rate_change_sw_flow_en = AL_SRDS_ADV_SRVC(al_serdes_lane_rx_rate_change_sw_flow_en); + obj->rx_rate_change_sw_flow_dis = + AL_SRDS_ADV_SRVC(al_serdes_lane_rx_rate_change_sw_flow_dis); + obj->pcie_rate_override_is_enabled = + AL_SRDS_ADV_SRVC(al_serdes_lane_pcie_rate_override_is_enabled); + obj->pcie_rate_override_enable_set = + AL_SRDS_ADV_SRVC(al_serdes_lane_pcie_rate_override_enable_set); + obj->pcie_rate_get = AL_SRDS_ADV_SRVC(al_serdes_lane_pcie_rate_get); + obj->pcie_rate_set = AL_SRDS_ADV_SRVC(al_serdes_lane_pcie_rate_set); + obj->group_pm_set = AL_SRDS_ADV_SRVC(al_serdes_group_pm_set); + obj->lane_pm_set = AL_SRDS_ADV_SRVC(al_serdes_lane_pm_set); + obj->pma_hard_reset_group = AL_SRDS_ADV_SRVC(al_serdes_pma_hard_reset_group); + obj->pma_hard_reset_lane = AL_SRDS_ADV_SRVC(al_serdes_pma_hard_reset_lane); + obj->loopback_control = AL_SRDS_ADV_SRVC(al_serdes_loopback_control); + obj->bist_pattern_select = AL_SRDS_ADV_SRVC(al_serdes_bist_pattern_select); + obj->bist_tx_enable = AL_SRDS_ADV_SRVC(al_serdes_bist_tx_enable); + obj->bist_tx_err_inject = AL_SRDS_ADV_SRVC(al_serdes_bist_tx_err_inject); + obj->bist_rx_enable = AL_SRDS_ADV_SRVC(al_serdes_bist_rx_enable); + obj->bist_rx_status = AL_SRDS_ADV_SRVC(al_serdes_bist_rx_status); + obj->tx_deemph_preset = AL_SRDS_ADV_SRVC(al_serdes_tx_deemph_preset); + obj->tx_deemph_inc = AL_SRDS_ADV_SRVC(al_serdes_tx_deemph_inc); + obj->tx_deemph_dec = AL_SRDS_ADV_SRVC(al_serdes_tx_deemph_dec); + obj->eye_measure_run = AL_SRDS_ADV_SRVC(al_serdes_eye_measure_run); + obj->eye_diag_sample = AL_SRDS_ADV_SRVC(al_serdes_eye_diag_sample); + obj->signal_is_detected = AL_SRDS_ADV_SRVC(al_serdes_signal_is_detected); + obj->tx_advanced_params_set = AL_SRDS_ADV_SRVC(al_serdes_tx_advanced_params_set); + obj->tx_advanced_params_get = AL_SRDS_ADV_SRVC(al_serdes_tx_advanced_params_get); + obj->rx_advanced_params_set = AL_SRDS_ADV_SRVC(al_serdes_rx_advanced_params_set); + obj->rx_advanced_params_get = AL_SRDS_ADV_SRVC(al_serdes_rx_advanced_params_get); + obj->mode_set_sgmii = AL_SRDS_ADV_SRVC(al_serdes_mode_set_sgmii); + obj->mode_set_kr = AL_SRDS_ADV_SRVC(al_serdes_mode_set_kr); + obj->rx_equalization = AL_SRDS_ADV_SRVC(al_serdes_rx_equalization); + obj->calc_eye_size = AL_SRDS_ADV_SRVC(al_serdes_calc_eye_size); + obj->sris_config = AL_SRDS_ADV_SRVC(al_serdes_sris_config); + obj->dcgain_set = AL_SRDS_ADV_SRVC(al_serdes_dcgain_set); + + return 0; +} diff --git a/al_hal_serdes.h b/al_hal_serdes.h index 37aec839b2f..e69de29bb2d 100644 --- a/al_hal_serdes.h +++ b/al_hal_serdes.h @@ -1,1125 +0,0 @@ -/*- -******************************************************************************* -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. - -*******************************************************************************/ - -/** - * @defgroup group_serdes_api API - * SerDes HAL driver API - * @ingroup group_serdes SerDes - * @{ - * - * @file al_hal_serdes.h - * - * @brief Header file for the SerDes HAL driver - * - */ - -#ifndef __AL_HAL_SERDES_H__ -#define __AL_HAL_SERDES_H__ - -#include "al_hal_common.h" - -/* *INDENT-OFF* */ -#ifdef __cplusplus -extern "C" { -#endif -/* *INDENT-ON* */ - -struct al_serdes_obj; - -enum al_serdes_group { - AL_SRDS_GRP_A = 0, - AL_SRDS_GRP_B, - AL_SRDS_GRP_C, - AL_SRDS_GRP_D, - - AL_SRDS_NUM_GROUPS, -}; - -struct al_serdes_group_info { - /* - * Group parent object - filled automatically by al_serdes_handle_init - */ - struct al_serdes_obj *pobj; - - /* - * Group specific register base - filled automatically by - * al_sedres_handle_init - */ - struct al_serdes_regs __iomem *regs_base; -}; - -struct al_serdes_obj { - struct al_serdes_group_info grp_info[AL_SRDS_NUM_GROUPS]; -}; - -enum al_serdes_reg_page { - AL_SRDS_REG_PAGE_0_LANE_0 = 0, - AL_SRDS_REG_PAGE_1_LANE_1, - AL_SRDS_REG_PAGE_2_LANE_2, - AL_SRDS_REG_PAGE_3_LANE_3, - AL_SRDS_REG_PAGE_4_COMMON, - AL_SRDS_REG_PAGE_0123_LANES_0123 = 7, -}; - -enum al_serdes_reg_type { - AL_SRDS_REG_TYPE_PMA = 0, - AL_SRDS_REG_TYPE_PCS, -}; - -enum al_serdes_lane { - AL_SRDS_LANE_0 = AL_SRDS_REG_PAGE_0_LANE_0, - AL_SRDS_LANE_1 = AL_SRDS_REG_PAGE_1_LANE_1, - AL_SRDS_LANE_2 = AL_SRDS_REG_PAGE_2_LANE_2, - AL_SRDS_LANE_3 = AL_SRDS_REG_PAGE_3_LANE_3, - - AL_SRDS_NUM_LANES, - AL_SRDS_LANES_0123 = AL_SRDS_REG_PAGE_0123_LANES_0123, -}; - -/** Serdes loopback mode */ -enum al_serdes_lb_mode { - /** No loopback */ - AL_SRDS_LB_MODE_OFF, - - /** - * Transmits the untimed, partial equalized RX signal out the transmit - * IO pins. - * No clock used (untimed) - */ - AL_SRDS_LB_MODE_PMA_IO_UN_TIMED_RX_TO_TX, - - /** - * Loops back the TX serializer output into the CDR. - * CDR recovered bit clock used (without attenuation) - */ - AL_SRDS_LB_MODE_PMA_INTERNALLY_BUFFERED_SERIAL_TX_TO_RX, - - /** - * Loops back the TX driver IO signal to the RX IO pins - * CDR recovered bit clock used (only through IO) - */ - AL_SRDS_LB_MODE_PMA_SERIAL_TX_IO_TO_RX_IO, - - /** - * Parallel loopback from the PMA receive lane data ports, to the - * transmit lane data ports - * CDR recovered bit clock used - */ - AL_SRDS_LB_MODE_PMA_PARALLEL_RX_TO_TX, - - /** Loops received data after elastic buffer to transmit path */ - AL_SRDS_LB_MODE_PCS_PIPE, - - /** Loops TX data (to PMA) to RX path (instead of PMA data) */ - AL_SRDS_LB_MODE_PCS_NEAR_END, - - /** Loops receive data prior to interface block to transmit path */ - AL_SRDS_LB_MODE_PCS_FAR_END, -}; - -/** Serdes BIST pattern */ -enum al_serdes_bist_pattern { - AL_SRDS_BIST_PATTERN_USER, - AL_SRDS_BIST_PATTERN_PRBS7, - AL_SRDS_BIST_PATTERN_PRBS23, - AL_SRDS_BIST_PATTERN_PRBS31, - AL_SRDS_BIST_PATTERN_CLK1010, -}; - -/** SerDes group rate */ -enum al_serdes_rate { - AL_SRDS_RATE_1_8, - AL_SRDS_RATE_1_4, - AL_SRDS_RATE_1_2, - AL_SRDS_RATE_FULL, -}; - -/** SerDes power mode */ -enum al_serdes_pm { - AL_SRDS_PM_PD, - AL_SRDS_PM_P2, - AL_SRDS_PM_P1, - AL_SRDS_PM_P0S, - AL_SRDS_PM_P0, -}; - -/** SerDes PCIe Rate - values are important for proper behavior */ -enum al_serdes_pcie_rate { - AL_SRDS_PCIE_RATE_GEN1 = 0, - AL_SRDS_PCIE_RATE_GEN2, - AL_SRDS_PCIE_RATE_GEN3, -}; - -/** - * Initializes a SERDES object - * - * @param serdes_regs_base - * The SERDES register file base pointer - * - * @param obj - * An allocated, non initialized object context - * - * - * @return 0 if no error found. - * - */ -int al_serdes_handle_init( - void __iomem *serdes_regs_base, - struct al_serdes_obj *obj); - -/** - * SERDES register read - * - * Reads a SERDES register - * - * @param obj - * The object context - * - * @param grp - * The SERDES group - * - * @param page - * The SERDES register page within the group - * - * @param type - * The SERDES register type (PMA /PCS) - * - * @param offset - * The SERDES register offset (0 - 4095) - * - * @param data - * The read data - * - * - * @return 0 if no error found. - * - */ -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); - -/** - * SERDES register write - * - * Writes a SERDES register - * - * @param obj - * The object context - * - * @param grp - * The SERDES group - * - * @param page - * The SERDES register page within the group - * - * @param type - * The SERDES register type (PMA /PCS) - * - * @param offset - * The SERDES register offset (0 - 4095) - * - * @param data - * The data to write - * - * - * @return 0 if no error found. - * - */ -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); - -/** - * Enable BIST required overrides - * - * @param obj - * The object context - * @param grp - * The SERDES group - * @param rate - * The required speed rate - */ -void al_serdes_bist_overrides_enable( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_rate rate); - -/** - * Disable BIST required overrides - * - * @param obj - * The object context - * @param grp - * The SERDES group - * @param rate - * The required speed rate - */ -void al_serdes_bist_overrides_disable( - struct al_serdes_obj *obj, - enum al_serdes_group grp); - -/** - * Rx rate change - * - * @param obj - * The object context - * @param grp - * The SERDES group - * @param rate - * The Rx required rate - */ -void al_serdes_rx_rate_change( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_rate rate); - -/** - * SERDES lane Rx rate change software flow enable - * - * @param obj - * The object context - * @param grp - * The SERDES group - * @param lane - * The SERDES lane within the group - */ -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); - -/** - * SERDES lane Rx rate change software flow disable - * - * @param obj - * The object context - * @param grp - * The SERDES group - * @param lane - * The SERDES lane within the group - */ -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); - -/** - * PCIe lane rate override check - * - * @param obj - * The object context - * @param grp - * The SERDES group - * @param lane - * The SERDES lane within the group - * @returns AL_TRUE if the override is enabled - */ -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); - -/** - * PCIe lane rate override control - * - * @param obj - * The object context - * @param grp - * The SERDES group - * @param lane - * The SERDES lane within the group - * @param en - * Enable/disable - */ -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); - -/** - * PCIe lane rate get - * - * @param obj - * The object context - * @param grp - * The SERDES group - * @param lane - * The SERDES lane within the group - */ -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); - -/** - * PCIe lane rate set - * - * @param obj - * The object context - * @param grp - * The SERDES group - * @param lane - * The SERDES lane within the group - * @param rate - * The required rate - */ -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); - -/** - * SERDES group power mode control - * - * @param obj - * The object context - * @param grp - * The SERDES group - * @param pm - * The required power mode - */ -void al_serdes_group_pm_set( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_pm pm); - -/** - * SERDES lane power mode control - * - * @param obj - * The object context - * @param grp - * The SERDES group - * @param lane - * The SERDES lane within the group - * @param rx_pm - * The required RX power mode - * @param tx_pm - * The required TX power mode - */ -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); - -/** - * SERDES group PMA hard reset - * - * Controls Serdes group PMA hard reset - * - * @param obj - * The object context - * - * @param grp - * The SERDES group - * - * @param enable - * Enable/disable hard reset - */ -void al_serdes_pma_hard_reset_group( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - al_bool enable); - -/** - * SERDES lane PMA hard reset - * - * Controls Serdes lane PMA hard reset - * - * @param obj - * The object context - * - * @param grp - * The SERDES group - * - * @param lane - * The SERDES lane within the group - * - * @param enable - * Enable/disable hard reset - */ -void al_serdes_pma_hard_reset_lane( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - al_bool enable); - -/** - * SERDES loopback control - * - * Controls the loopback - * - * @param obj - * The object context - * - * @param grp - * The SERDES group - * - * @param lane - * The SERDES lane within the group - * - * @param mode - * The requested loopback mode - * - */ -void al_serdes_loopback_control( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - enum al_serdes_lb_mode mode); - -/** - * SERDES BIST pattern selection - * - * Selects the BIST pattern to be used - * - * @param obj - * The object context - * - * @param grp - * The SERDES group - * - * @param pattern - * The pattern to set - * - * @param user_data - * The pattern user data (when pattern == AL_SRDS_BIST_PATTERN_USER) - * 80 bits (8 bytes array) - * - */ -void al_serdes_bist_pattern_select( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_bist_pattern pattern, - uint8_t *user_data); - -/** - * SERDES BIST TX Enable - * - * Enables/disables TX BIST per lane - * - * @param obj - * The object context - * - * @param grp - * The SERDES group - * - * @param lane - * The SERDES lane within the group - * - * @param enable - * Enable or disable TX BIST - */ -void al_serdes_bist_tx_enable( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - al_bool enable); - -/** - * SERDES BIST TX single bit error injection - * - * Injects single bit error during a TX BIST - * - * @param obj - * The object context - * - * @param grp - * The SERDES group - */ -void al_serdes_bist_tx_err_inject( - struct al_serdes_obj *obj, - enum al_serdes_group grp); - -/** - * SERDES BIST RX Enable - * - * Enables/disables RX BIST per lane - * - * @param obj - * The object context - * - * @param grp - * The SERDES group - * - * @param lane - * The SERDES lane within the group - * - * @param enable - * Enable or disable TX BIST - */ -void al_serdes_bist_rx_enable( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - al_bool enable); - -/** - * SERDES BIST RX status - * - * Checks the RX BIST status for a specific SERDES lane - * - * @param obj - * The object context - * - * @param grp - * The SERDES group - * - * @param lane - * The SERDES lane within the group - * - * @param is_locked - * An indication whether RX BIST is locked - * - * @param err_cnt_overflow - * An indication whether error count overflow occured - * - * @param err_cnt - * Current bit error count - */ -void al_serdes_bist_rx_status( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - al_bool *is_locked, - al_bool *err_cnt_overflow, - uint16_t *err_cnt); - -/** - * SERDES Digital Test Bus - * - * Samples the digital test bus of a specific SERDES lane - * - * @param obj - * The object context - * - * @param grp - * The SERDES group - * - * @param lane - * The SERDES lane within the group - * - * @param sel - * The selected sampling group (0 - 31) - * - * @param sampled_data - * The sampled data (5 bytes array) - * - * - * @return 0 if no error found. - * - */ -int al_serdes_digital_test_bus( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - uint8_t sel, - uint8_t *sampled_data); - - -/* KR link training */ -/** - * Set the tx de-emphasis to preset values - * - * @param obj The object context - * - * @param grp The SERDES group - * - * @param lane The SERDES lane within the group - * - */ -void al_serdes_tx_deemph_preset( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane); - -/** - * Tx de-emphasis parameters - */ -enum al_serdes_tx_deemph_param { - AL_SERDES_TX_DEEMP_C_ZERO, /*< c(0) */ - AL_SERDES_TX_DEEMP_C_PLUS, /*< c(1) */ - AL_SERDES_TX_DEEMP_C_MINUS, /*< c(-1) */ -}; - -/** - * Increase tx de-emphasis param. - * - * @param obj The object context - * - * @param grp The SERDES group - * - * @param lane The SERDES lane within the group - * - * @param param which tx de-emphasis to change - * - * @return false in case max is reached. true otherwise. - */ -al_bool al_serdes_tx_deemph_inc( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - enum al_serdes_tx_deemph_param param); - -/** - * Decrease tx de-emphasis param. - * - * @param obj The object context - * - * @param grp The SERDES group - * - * @param lane The SERDES lane within the group - * - * @param param which tx de-emphasis to change - * - * @return false in case min is reached. true otherwise. - */ -al_bool al_serdes_tx_deemph_dec( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - enum al_serdes_tx_deemph_param param); - -/** - * run Rx eye measurement. - * - * @param obj The object context - * - * @param grp The SERDES group - * - * @param lane The SERDES lane within the group - * - * @param timeout timeout in uSec - * - * @param value Rx eye measurement value - * (0 - completely closed eye, 0xffff - completely open eye). - * - * @return 0 if no error found. - */ -int al_serdes_eye_measure_run( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - uint32_t timeout, - unsigned int *value); - -/** - * Eye diagram single sampling - * - * @param obj The object context - * - * @param grp The SERDES group - * - * @param lane The SERDES lane within the group - * - * @param x Sampling X position (0 - 63 --> -1.00 UI ... 1.00 UI) - * - * @param y Sampling Y position (0 - 62 --> 500mV ... -500mV) - * - * @param timeout timeout in uSec - * - * @param value Eye diagram sample value (BER - 0x0000 - 0xffff) - * - * @return 0 if no error found. - */ -int al_serdes_eye_diag_sample( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - unsigned int x, - int y, - unsigned int timeout, - unsigned int *value); - -/** - * Check if signal is detected - * - * @param obj The object context - * - * @param grp The SERDES group - * - * @param lane The SERDES lane within the group - * - * @return true if signal is detected. false otherwise. - */ -al_bool al_serdes_signal_is_detected( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane); - - -struct al_serdes_adv_tx_params { - /* - * select the input values location. - * When set to true the values will be taken from the internal registers - * that will be override with the next following parameters. - * When set to false the values will be taken from external pins (the - * other parameters in this case is not needed) - */ - al_bool override; - /* - * Transmit Amplitude control signal. Used to define the full-scale - * maximum swing of the driver. - * 000 - Not Supported - * 001 - 952mVdiff-pkpk - * 010 - 1024mVdiff-pkpk - * 011 - 1094mVdiff-pkpk - * 100 - 1163mVdiff-pkpk - * 101 - 1227mVdiff-pkpk - * 110 - 1283mVdiff-pkpk - * 111 - 1331mVdiff-pkpk - */ - uint8_t amp; - /* Defines the total number of driver units allocated in the driver */ - uint8_t total_driver_units; - /* Defines the total number of driver units allocated to the - * first post-cursor (C+1) tap. */ - uint8_t c_plus_1; - /* Defines the total number of driver units allocated to the - * second post-cursor (C+2) tap. */ - uint8_t c_plus_2; - /* Defines the total number of driver units allocated to the - * first pre-cursor (C-1) tap. */ - uint8_t c_minus_1; - /* TX driver Slew Rate control: - * 00 - 31ps - * 01 - 33ps - * 10 - 68ps - * 11 - 170ps - */ - uint8_t slew_rate; -}; - -struct al_serdes_adv_rx_params { - /* - * select the input values location. - * When set to true the values will be taken from the internal registers - * that will be override with the next following parameters. - * When set to false the values will be taken based in the equalization - * results (the other parameters in this case is not needed) - */ - al_bool override; - /* RX agc high frequency dc gain: - * -3'b000: -3dB - * -3'b001: -2.5dB - * -3'b010: -2dB - * -3'b011: -1.5dB - * -3'b100: -1dB - * -3'b101: -0.5dB - * -3'b110: -0dB - * -3'b111: 0.5dB - */ - uint8_t dcgain; - /* DFE post-shaping tap 3dB frequency - * -3'b000: 684MHz - * -3'b001: 576MHz - * -3'b010: 514MHz - * -3'b011: 435MHz - * -3'b100: 354MHz - * -3'b101: 281MHz - * -3'b110: 199MHz - * -3'b111: 125MHz - */ - uint8_t dfe_3db_freq; - /* DFE post-shaping tap gain - * 0: no pulse shaping tap - * 1: -24mVpeak - * 2: -45mVpeak - * 3: -64mVpeak - * 4: -80mVpeak - * 5: -93mVpeak - * 6: -101mVpeak - * 7: -105mVpeak - */ - uint8_t dfe_gain; - /* DFE first tap gain control - * -4'b0000: +1mVpeak - * -4'b0001: +10mVpeak - * .... - * -4'b0110: +55mVpeak - * -4'b0111: +64mVpeak - * -4'b1000: -1mVpeak - * -4'b1001: -10mVpeak - * .... - * -4'b1110: -55mVpeak - * -4'b1111: -64mVpeak - */ - uint8_t dfe_first_tap_ctrl; - /* DFE second tap gain control - * -4'b0000: +0mVpeak - * -4'b0001: +9mVpeak - * .... - * -4'b0110: +46mVpeak - * -4'b0111: +53mVpeak - * -4'b1000: -0mVpeak - * -4'b1001: -9mVpeak - * .... - * -4'b1110: -46mVpeak - * -4'b1111: -53mVpeak - */ - uint8_t dfe_secound_tap_ctrl; - /* DFE third tap gain control - * -4'b0000: +0mVpeak - * -4'b0001: +7mVpeak - * .... - * -4'b0110: +38mVpeak - * -4'b0111: +44mVpeak - * -4'b1000: -0mVpeak - * -4'b1001: -7mVpeak - * .... - * -4'b1110: -38mVpeak - * -4'b1111: -44mVpeak - */ - uint8_t dfe_third_tap_ctrl; - /* DFE fourth tap gain control - * -4'b0000: +0mVpeak - * -4'b0001: +6mVpeak - * .... - * -4'b0110: +29mVpeak - * -4'b0111: +33mVpeak - * -4'b1000: -0mVpeak - * -4'b1001: -6mVpeak - * .... - * -4'b1110: -29mVpeak - * -4'b1111: -33mVpeak - */ - uint8_t dfe_fourth_tap_ctrl; - /* Low frequency agc gain (att) select - * -3'b000: Disconnected - * -3'b001: -18.5dB - * -3'b010: -12.5dB - * -3'b011: -9dB - * -3'b100: -6.5dB - * -3'b101: -4.5dB - * -3'b110: -2.9dB - * -3'b111: -1.6dB - */ - uint8_t low_freq_agc_gain; - /* Provides a RX Equalizer pre-hint, prior to beginning - * adaptive equalization */ - uint8_t precal_code_sel; - /* High frequency agc boost control - * Min d0: Boost ~4dB - * Max d31: Boost ~20dB - */ - uint8_t high_freq_agc_boost; -}; - -/** - * configure tx advanced parameters - * - * @param obj The object context - * - * @param grp The SERDES group - * - * @param lane The SERDES lane within the group - * - * @param params pointer to the tx parameters - */ -void al_serdes_tx_advanced_params_set(struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - struct al_serdes_adv_tx_params *params); - -/** - * read tx advanced parameters - * - * @param obj The object context - * - * @param grp The SERDES group - * - * @param lane The SERDES lane within the group - * - * @param params pointer to the tx parameters - */ -void al_serdes_tx_advanced_params_get(struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - struct al_serdes_adv_tx_params *params); - -/** - * configure rx advanced parameters - * - * @param obj The object context - * - * @param grp The SERDES group - * - * @param lane The SERDES lane within the group - * - * @param params pointer to the rx parameters - */ -void al_serdes_rx_advanced_params_set(struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - struct al_serdes_adv_rx_params *params); - -/** - * read rx advanced parameters - * - * @param obj The object context - * - * @param grp The SERDES group - * - * @param lane The SERDES lane within the group - * - * @param params pointer to the rx parameters - */ -void al_serdes_rx_advanced_params_get(struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - struct al_serdes_adv_rx_params* params); - -/** - * Switch entire SerDes group to SGMII mode based on 156.25 Mhz reference clock - * - * @param obj The object context - * - * @param grp The SERDES group - */ -void al_serdes_mode_set_sgmii( - struct al_serdes_obj *obj, - enum al_serdes_group grp); - -/** - * Switch entire SerDes group to KR mode based on 156.25 Mhz reference clock - * - * @param obj The object context - * - * @param grp The SERDES group - */ -void al_serdes_mode_set_kr( - struct al_serdes_obj *obj, - enum al_serdes_group grp); - -/** - * performs SerDes HW equalization test and update equalization parameters - * - * @param obj the object context - * - * @param grp the SERDES group - * - * @param lane The SERDES lane within the group - */ -int al_serdes_rx_equalization( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane); - -/** - * performs Rx equalization and compute the width and height of the eye - * - * @param obj the object context - * - * @param grp the SERDES group - * - * @param lane The SERDES lane within the group - * - * @param width the output width of the eye - * - * @param height the output height of the eye - */ -int al_serdes_calc_eye_size( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - enum al_serdes_lane lane, - int* width, - int* height); - -/** - * SRIS parameters - */ -struct al_serdes_sris_params { - /* Controls the frequency accuracy threshold (ppm) for lock detection CDR */ - uint16_t ppm_drift_count; - /* Controls the frequency accuracy threshold (ppm) for lock detection in the CDR */ - uint16_t ppm_drift_max; - /* Controls the frequency accuracy threshold (ppm) for lock detection in PLL */ - uint16_t synth_ppm_drift_max; - /* Elastic buffer full threshold for PCIE modes: GEN1/GEN2 */ - uint8_t full_d2r1; - /* Elastic buffer full threshold for PCIE modes: GEN3 */ - uint8_t full_pcie_g3; - /* Elastic buffer midpoint threshold. - * Sets the depth of the buffer while in PCIE mode, GEN1/GEN2 - */ - uint8_t rd_threshold_d2r1; - /* Elastic buffer midpoint threshold. - * Sets the depth of the buffer while in PCIE mode, GEN3 - */ - uint8_t rd_threshold_pcie_g3; -}; - -/** - * SRIS: Separate Refclk Independent SSC (Spread Spectrum Clocking) - * Currently available only for PCIe interfaces. - * When working with local Refclk, same SRIS configuration in both serdes sides - * (EP and RC in PCIe interface) is required. - * - * performs SRIS configuration according to params - * - * @param obj the object context - * - * @param grp the SERDES group - * - * @param params the SRIS parameters - */ -void al_serdes_sris_config( - struct al_serdes_obj *obj, - enum al_serdes_group grp, - struct al_serdes_sris_params *params); - -/* *INDENT-OFF* */ -#ifdef __cplusplus -} -#endif - -/* *INDENT-ON* */ -#endif /* __AL_SRDS__ */ - -/** @} end of SERDES group */ - diff --git a/al_hal_serdes_25g.c b/al_hal_serdes_25g.c new file mode 100644 index 00000000000..68767e557fd --- /dev/null +++ b/al_hal_serdes_25g.c @@ -0,0 +1,1951 @@ +/******************************************************************************* +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_25g.h" +#include "al_hal_serdes_25g_regs.h" +#include "al_hal_serdes_25g_internal_regs.h" + +#define AL_SERDES_MB_MAX_DATA_LEN 8 + +#define AL_SERDES_25G_WAIT_FOR_READY_TO 200 +#define AL_SERDES_25G_RESET_TO 100 +#define AL_SERDES_25G_RESET_NUM_RETRIES 5 + +#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 + +/******************************************************************************/ +/******************************************************************************/ +static enum al_serdes_type al_serdes_25g_type_get(void) +{ + return AL_SRDS_TYPE_25G; +} + +/******************************************************************************/ +/******************************************************************************/ +static int al_serdes_25g_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) +{ + struct al_serdes_c_regs __iomem *regs_base = obj->regs_base; + uint32_t addr = 0; + + al_dbg("%s(%p, %d, %d, %u)\n", __func__, obj, page, type, offset); + + al_assert(obj); + al_assert(data); + + switch (page) { + case AL_SRDS_REG_PAGE_TOP: + addr = (SERDES_25G_TOP_BASE + offset); + break; + case AL_SRDS_REG_PAGE_4_COMMON: + addr = (SERDES_25G_CM_BASE + offset); + break; + case AL_SRDS_REG_PAGE_0_LANE_0: + case AL_SRDS_REG_PAGE_1_LANE_1: + addr = (SERDES_25G_LANE_BASE + (page * SERDES_25G_LANE_SIZE) + offset); + break; + default: + al_err("%s: wrong serdes type %d\n", __func__, type); + return -1; + } + + al_reg_write32(®s_base->gen.reg_addr, addr); + *data = al_reg_read32(®s_base->gen.reg_data); + + al_dbg("%s: return(%u)\n", __func__, *data); + + return 0; +} + +static int al_serdes_25g_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_c_regs __iomem *regs_base = obj->regs_base; + uint32_t addr = 0; + + al_dbg("%s(%p, %d, %d, %u)\n", __func__, obj, page, type, offset); + + al_assert(obj); + + switch (page) { + case AL_SRDS_REG_PAGE_TOP: + addr = (SERDES_25G_TOP_BASE + offset); + break; + case AL_SRDS_REG_PAGE_4_COMMON: + addr = (SERDES_25G_CM_BASE + offset); + break; + case AL_SRDS_REG_PAGE_0_LANE_0: + case AL_SRDS_REG_PAGE_1_LANE_1: + addr = (SERDES_25G_LANE_BASE + (page * SERDES_25G_LANE_SIZE) + offset); + break; + default: + al_err("%s: wrong serdes type %d\n", __func__, type); + return -1; + } + + al_reg_write32(®s_base->gen.reg_addr, addr); + al_reg_write32(®s_base->gen.reg_data, (data | SERDES_C_GEN_REG_DATA_STRB_MASK)); + + al_dbg("%s: write(%u)\n", __func__, data); + + return 0; +} + +/******************************************************************************/ +/******************************************************************************/ +static int al_serdes_25g_reg_masked_read( + struct al_serdes_grp_obj *obj, + enum al_serdes_reg_page page, + uint16_t offset, + uint8_t mask, + uint8_t shift, + uint8_t *data) +{ + uint8_t val; + int status = 0; + + status = al_serdes_25g_reg_read(obj, page, 0, offset, &val); + if (status) + return status; + + *data = AL_REG_FIELD_GET(val, mask, shift); + + return 0; +} + +static int al_serdes_25g_reg_masked_write( + struct al_serdes_grp_obj *obj, + enum al_serdes_reg_page page, + uint16_t offset, + uint8_t mask, + uint8_t shift, + uint8_t data) +{ + uint8_t val; + int status = 0; + + status = al_serdes_25g_reg_read(obj, page, 0, offset, &val); + if (status) + return status; + + val &= (~mask); + val |= (data << shift); + return al_serdes_25g_reg_write(obj, page, 0, offset, val); +} + +/******************************************************************************/ +/******************************************************************************/ +#define SERDES_25G_MB_RESP_BYTES 16 +#define SERDES_25G_MB_TIMEOUT 5000000 /* uSec */ + +static int al_serdes_25g_mailbox_send_cmd( + struct al_serdes_grp_obj *obj, + uint8_t cmd, + uint8_t *data, + uint8_t data_len) +{ + uint8_t val; + int i; + uint32_t timeout = SERDES_25G_MB_TIMEOUT; + + if (data_len > AL_SERDES_MB_MAX_DATA_LEN) { + al_err("Cannot send command, data too long\n"); + return -1; + } + + /* Wait for CMD_FLAG to clear */ + while(1) { + al_serdes_25g_reg_read(obj, AL_SRDS_REG_PAGE_TOP, 0, + SERDES_25G_TOP_CMD_FLAG_ADDR, &val); + if (val == 0) + break; + + if (timeout == 0) { + al_err("%s: timeout occurred waiting to CMD_FLAG\n", __func__); + return -1; + } + + timeout--; + al_udelay(1); + } + + for (i = 0; i < data_len; i++) { + al_serdes_25g_reg_write(obj, AL_SRDS_REG_PAGE_TOP, 0, + (SERDES_25G_TOP_CMD_DATA0_ADDR + i), data[i]); + } + + /* this write will set CMD_FLAG automatically */ + al_serdes_25g_reg_write(obj, AL_SRDS_REG_PAGE_TOP, 0, SERDES_25G_TOP_CMD_ADDR, cmd); + + return 0; +} + +static int al_serdes_25g_mailbox_recv_rsp( + struct al_serdes_grp_obj *obj, + uint8_t *rsp_code, + uint8_t *data, + uint8_t *data_len) +{ + uint8_t val; + int i; + uint32_t timeout = SERDES_25G_MB_TIMEOUT; + + /* wait for RSP_FLAG to set */ + while(1) { + al_serdes_25g_reg_read(obj, AL_SRDS_REG_PAGE_TOP, 0, + SERDES_25G_TOP_RSP_FLAG_ADDR, &val); + if (val == 0x1) + break; + + if (timeout == 0) { + al_err("%s: timeout occurred waiting to RSP_FLAG\n", __func__); + *data_len = 0; + return -1; + } + + timeout--; + al_udelay(1); + } + + /* Grab the response code and data */ + al_serdes_25g_reg_read(obj, AL_SRDS_REG_PAGE_TOP, 0, + SERDES_25G_TOP_RSP_ADDR, rsp_code); + + for (i = 0; i < SERDES_25G_MB_RESP_BYTES; i++) { + al_serdes_25g_reg_read(obj, AL_SRDS_REG_PAGE_TOP, 0, + (SERDES_25G_TOP_RSP_DATA0_ADDR + i), &data[i]); + } + + /* clear the RSP_FLAG (write 1 to clear) */ + al_serdes_25g_reg_write(obj, AL_SRDS_REG_PAGE_TOP, 0, + SERDES_25G_TOP_RSP_FLAG_ADDR, 0x1); + + *data_len = SERDES_25G_MB_RESP_BYTES; + + return 0; +} + +/******************************************************************************/ +/******************************************************************************/ +static void al_serdes_25g_bist_rx_enable( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + al_bool enable) +{ + if (enable) { + switch (lane) { + case 0: + al_serdes_25g_reg_masked_write( + obj, + AL_SRDS_REG_PAGE_TOP, + SERDES_25G_TOP_CLOCK_LN0_CLK_RX_ADDR, + SERDES_25G_TOP_CLOCK_LN0_CLK_RX_CTRL_CG_EN_MASK, + SERDES_25G_TOP_CLOCK_LN0_CLK_RX_CTRL_CG_EN_SHIFT, + 0x1); + al_serdes_25g_reg_masked_write( + obj, + AL_SRDS_REG_PAGE_TOP, + SERDES_25G_TOP_CLOCK_LN0_CLK_RX_ADDR, + SERDES_25G_TOP_CLOCK_LN0_CLK_RX_CTRL_BIST_CG_EN_MASK, + SERDES_25G_TOP_CLOCK_LN0_CLK_RX_CTRL_BIST_CG_EN_SHIFT, + 0x1); + break; + case 1: + al_serdes_25g_reg_masked_write( + obj, + AL_SRDS_REG_PAGE_TOP, + SERDES_25G_TOP_CLOCK_LN1_CLK_RX_ADDR, + SERDES_25G_TOP_CLOCK_LN1_CLK_RX_CTRL_CG_EN_MASK, + SERDES_25G_TOP_CLOCK_LN1_CLK_RX_CTRL_CG_EN_SHIFT, + 0x1); + + al_serdes_25g_reg_masked_write( + obj, + AL_SRDS_REG_PAGE_TOP, + SERDES_25G_TOP_CLOCK_LN1_CLK_RX_ADDR, + SERDES_25G_TOP_CLOCK_LN1_CLK_RX_CTRL_BIST_CG_EN_MASK, + SERDES_25G_TOP_CLOCK_LN1_CLK_RX_CTRL_BIST_CG_EN_SHIFT, + 0x1); + break; + default: + al_err("%s: Wrong serdes lane %d\n", __func__, lane); + return; + } + + al_serdes_25g_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL4_ADDR, + SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL4_STOP_ON_LOSS_LOCK_MASK, + SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL4_STOP_ON_LOSS_LOCK_SHIFT, + 0); + al_serdes_25g_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_RX_BIST_CTRL_ADDR, + SERDES_25G_LANE_RX_BIST_CTRL_EN_MASK, + SERDES_25G_LANE_RX_BIST_CTRL_EN_SHIFT, + 1); + al_serdes_25g_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_RX_BIST_CTRL_ADDR, + SERDES_25G_LANE_RX_BIST_CTRL_PATTERN_SEL_MASK, + SERDES_25G_LANE_RX_BIST_CTRL_PATTERN_SEL_SHIFT, + 6); + } else { + /* clear counters */ + al_serdes_25g_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_RX_BIST_CTRL_ADDR, + SERDES_25G_LANE_RX_BIST_CTRL_CLEAR_BER_MASK, + SERDES_25G_LANE_RX_BIST_CTRL_CLEAR_BER_SHIFT, + 1); + + al_serdes_25g_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_RX_BIST_CTRL_ADDR, + SERDES_25G_LANE_RX_BIST_CTRL_CLEAR_BER_MASK, + SERDES_25G_LANE_RX_BIST_CTRL_CLEAR_BER_SHIFT, + 0); + + al_msleep(AL_SERDES_25G_WAIT_FOR_READY_TO); + + /* disable */ + al_serdes_25g_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_RX_BIST_CTRL_ADDR, + SERDES_25G_LANE_RX_BIST_CTRL_EN_MASK, + SERDES_25G_LANE_RX_BIST_CTRL_EN_SHIFT, + 0); + } +} + +// TODO: [Guy] change API to be per lane. +static void al_serdes_25g_bist_pattern_select( + struct al_serdes_grp_obj *obj, + enum al_serdes_bist_pattern pattern, + uint8_t *user_data) +{ + enum al_serdes_lane lane; + uint8_t val = 0; + + switch (pattern) { + case AL_SRDS_BIST_PATTERN_USER: + al_assert(user_data); + val = SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_PRBS_USER; + break; + case AL_SRDS_BIST_PATTERN_PRBS7: + val = SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_PRBS7; + break; + case AL_SRDS_BIST_PATTERN_PRBS23: + val = SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_PRBS23; + break; + case AL_SRDS_BIST_PATTERN_PRBS31: + val = SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_PRBS31; + break; + case AL_SRDS_BIST_PATTERN_CLK1010: + default: + al_err("%s: invalid pattern (%d)\n", __func__, pattern); + al_assert(0); + } + + for (lane = AL_SRDS_LANE_0; lane <= AL_SRDS_LANE_1; lane++) { + if (pattern == AL_SRDS_BIST_PATTERN_USER) { + int i; + + for (i = 0; i < SERDES_25G_LANE_TX_BIST_UDP_NUM_BYTES; i++) + al_serdes_25g_reg_write( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_LANE_TX_BIST_UDP_ADDR(i), + user_data[i]); + } + + al_serdes_25g_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_TX_BIST_CTRL_ADDR, + SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_SEL_MASK, + SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_SEL_SHIFT, + val); + } +} + +static void al_serdes_25g_bist_tx_enable( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + al_bool enable) +{ + if (enable) { + al_serdes_25g_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_TX_BIST_CTRL_ADDR, + SERDES_25G_LANE_TX_BIST_CTRL_EN_MASK, + SERDES_25G_LANE_TX_BIST_CTRL_EN_SHIFT, + 0x1); + al_serdes_25g_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_ADDR, + SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_DMUX_TXA_SEL_MASK, + SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_DMUX_TXA_SEL_SHIFT, + 0x2); + + switch (lane) { + case AL_SRDS_LANE_0: + al_serdes_25g_reg_masked_write( + obj, + AL_SRDS_REG_PAGE_TOP, + SERDES_25G_TOP_CLOCK_LN0_CLK_TX_ADDR, + SERDES_25G_TOP_CLOCK_LN0_CLK_TX_CTRL_BIST_CG_EN_MASK, + SERDES_25G_TOP_CLOCK_LN0_CLK_TX_CTRL_BIST_CG_EN_SHIFT, + 0x1); + break; + case AL_SRDS_LANE_1: + al_serdes_25g_reg_masked_write( + obj, + AL_SRDS_REG_PAGE_TOP, + SERDES_25G_TOP_CLOCK_LN1_CLK_TX_ADDR, + SERDES_25G_TOP_CLOCK_LN1_CLK_TX_CTRL_BIST_CG_EN_MASK, + SERDES_25G_TOP_CLOCK_LN1_CLK_TX_CTRL_BIST_CG_EN_SHIFT, + 0x1); + break; + default: + al_err("%s: Wrong serdes lane %d\n", __func__, lane); + return; + } + } else { + al_serdes_25g_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_TX_BIST_CTRL_ADDR, + SERDES_25G_LANE_TX_BIST_CTRL_EN_MASK, + SERDES_25G_LANE_TX_BIST_CTRL_EN_SHIFT, + 0); + } + +} + +static void al_serdes_25g_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; + uint8_t err1; + uint8_t err2; + uint8_t err3; + + al_serdes_25g_reg_masked_read( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_RX_BIST_STATUS_ADDR, + SERDES_25G_LANE_RX_BIST_STATUS_STATE_MASK, + SERDES_25G_LANE_RX_BIST_STATUS_STATE_SHIFT, + &status); + + if (status != 3) { + *is_locked = AL_FALSE; + return; + } + + *is_locked = AL_TRUE; + *err_cnt_overflow = AL_FALSE; + + al_serdes_25g_reg_masked_read( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_RX_BIST_BER_STATUS0_ADDR, + SERDES_25G_LANE_RX_BIST_BER_STATUS0_BIT_ERROR_COUNT_7_0_MASK, + SERDES_25G_LANE_RX_BIST_BER_STATUS0_BIT_ERROR_COUNT_7_0_SHIFT, + &err1); + + al_serdes_25g_reg_masked_read( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_RX_BIST_BER_STATUS1_ADDR, + SERDES_25G_LANE_RX_BIST_BER_STATUS1_BIT_ERROR_COUNT_15_8_MASK, + SERDES_25G_LANE_RX_BIST_BER_STATUS1_BIT_ERROR_COUNT_15_8_SHIFT, + &err2); + + al_serdes_25g_reg_masked_read( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_RX_BIST_BER_STATUS2_ADDR, + SERDES_25G_LANE_RX_BIST_BER_STATUS2_BIT_ERROR_COUNT_23_16_MASK, + SERDES_25G_LANE_RX_BIST_BER_STATUS2_BIT_ERROR_COUNT_23_16_SHIFT, + &err3); + + *err_cnt = (err1 + (err2 << 8) + (err3 << 16)); +} + +#define SERDES_MB_CMD_SWING_CFG 0x83 +#define SERDES_MB_CMD_SAMPLES_COUNT 0x84 +#define SERDES_MB_CMD_START_MEASURE 0x82 + +#define SERDES_MB_RSP_CODE_0 0 +#define SERDES_MB_RSP_CODE_1 1 +#define SERDES_MB_RSP_CODE_2 2 + +static int al_serdes_25g_eye_diag_run( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + int x_start, + int x_stop, + unsigned int x_step, + int y_start, + int y_stop, + unsigned int y_step, + uint64_t ber_target, + uint64_t *buf, + uint32_t buf_size) +{ + int rc; + uint8_t rsp_code; + uint8_t data[16]; + uint8_t data_len; + uint32_t total_bits; + uint8_t bits_left_curr_sample; + uint8_t bits_left_curr_byte; + uint32_t byte = 0; + uint32_t x = 0; + uint32_t x_samples = (((x_stop - x_start) / x_step) + 1); + uint32_t y = 0; + uint32_t y_samples = (((y_stop - y_start) / y_step) + 1); + uint8_t sample_width = (64 - __builtin_clzl(ber_target)); + uint8_t msb; + uint8_t lsb; + uint32_t samples_left = ((x_samples * y_samples)); + uint8_t sign = 0; + + al_assert(buf_size == (samples_left * sizeof(uint64_t))); + + al_memset(buf, 0, buf_size); + + if (y_start < 0) { + y_start *= -1; + sign |= 0x1; + } + + if (y_stop < 0) { + y_stop *= -1; + sign |= 0x2; + } + + data[0] = lane; + data[1] = x_start; + data[2] = x_stop; + data[3] = x_step; + data[4] = y_start; + data[5] = y_stop; + data[6] = sign; + data[7] = y_step; + + rc = al_serdes_25g_mailbox_send_cmd( + obj, + SERDES_MB_CMD_SWING_CFG, + data, + 8); + + if (rc) { + al_err("%s: Failed to send command %d to mailbox.\n", + __func__, SERDES_MB_CMD_SWING_CFG); + return rc; + } + + rc = al_serdes_25g_mailbox_recv_rsp( + obj, + &rsp_code, + data, + &data_len); + + if ((rc) || (rsp_code != SERDES_MB_RSP_CODE_0)) { + al_err("%s: Failed to send command %d to mailbox. rsp_code %d\n", + __func__, SERDES_MB_CMD_SWING_CFG, rsp_code); + + return (ETIMEDOUT); + } + + al_assert(sample_width <= 40); + + data[0] = lane; + data[1] = ((ber_target >> 32) & 0xFF); + data[2] = ((ber_target >> 24) & 0xFF); + data[3] = ((ber_target >> 16) & 0xFF); + data[4] = ((ber_target >> 8) & 0xFF); + data[5] = (ber_target & 0xFF); + + rc = al_serdes_25g_mailbox_send_cmd( + obj, + SERDES_MB_CMD_SAMPLES_COUNT, + data, + 6); + + if (rc) { + al_err("%s: Failed to send command %d to mailbox.\n", + __func__, SERDES_MB_CMD_SAMPLES_COUNT); + return rc; + } + + rc = al_serdes_25g_mailbox_recv_rsp( + obj, + &rsp_code, + data, + &data_len); + + if ((rc) || (rsp_code != SERDES_MB_RSP_CODE_0)) { + al_err("%s: Failed to send command %d to mailbox. rsp_code %d\n", + __func__, SERDES_MB_CMD_SAMPLES_COUNT, rsp_code); + + return (ETIMEDOUT); + } + + rc = al_serdes_25g_mailbox_send_cmd( + obj, + SERDES_MB_CMD_START_MEASURE, + data, + 0); + + bits_left_curr_sample = sample_width; + + while (rsp_code != SERDES_MB_RSP_CODE_1) { + uint8_t num_bits = 0; + + rc = al_serdes_25g_mailbox_recv_rsp( + obj, + &rsp_code, + data, + &data_len); + + if ((rc != 0) || (rsp_code > SERDES_MB_RSP_CODE_2)) { + al_err("%s: command %d return failure. rsp_code %d\n", + __func__, SERDES_MB_CMD_START_MEASURE, rsp_code); + + return (ETIMEDOUT); + } + byte = 0; + total_bits = data_len * 8; + bits_left_curr_byte = 8; + while (total_bits > 0) { + num_bits = al_min_t(uint8_t, bits_left_curr_sample, bits_left_curr_byte); + + buf[(y * x_samples) + x] <<= num_bits; + msb = bits_left_curr_byte - 1; + lsb = msb - num_bits + 1; + buf[(y * x_samples) + x] |= (data[byte] & AL_FIELD_MASK(msb, lsb) >> lsb); + + total_bits -= num_bits; + + bits_left_curr_byte -= num_bits; + if (!bits_left_curr_byte) { + bits_left_curr_byte = 8; + byte++; + } + + bits_left_curr_sample -= num_bits; + if (!bits_left_curr_sample) { + y++; + if (y == y_samples) { + y = 0; + x++; + } + + samples_left--; + bits_left_curr_sample = sample_width; + } + + if (samples_left == 0) + break; + } + + if ((samples_left == 0) && (rsp_code != SERDES_MB_RSP_CODE_1)) { + rc = al_serdes_25g_mailbox_recv_rsp( + obj, + &rsp_code, + data, + &data_len); + if ((rc) || (rsp_code == SERDES_MB_RSP_CODE_0)) { + al_err("%s: Parsed enough samples but f/w is still sending more\n", + __func__); + + return -EIO; + } + break; + } + } + + if (samples_left > 0) { + al_err("%s: Still need more samples but f/w has stopped sending them!?!?!?\n", + __func__); + + return -EIO; + } + + return 0; +} + +#define SERDES_25G_EYE_X_MIN 1 +#define SERDES_25G_EYE_X_MAX 127 +#define SERDES_25G_EYE_Y_MIN -200 +#define SERDES_25G_EYE_Y_MAX 200 +#define SERDES_25G_EYE_SIZE_MAX_SAMPLES 401 +#define SERDES_25G_EYE_SIZE_BER_TARGET 0xffff +#define SERDES_25G_EYE_SIZE_ERR_TH 10 + +static int al_serdes_25g_calc_eye_size( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + int *width, + int *height) +{ + uint64_t samples[SERDES_25G_EYE_SIZE_MAX_SAMPLES]; + int i; + int _width = 0; + int _height = 0; + int rc; + int mid_x = ((SERDES_25G_EYE_X_MIN + SERDES_25G_EYE_X_MAX) / 2); + int mid_y = ((SERDES_25G_EYE_Y_MIN + SERDES_25G_EYE_Y_MAX) / 2); + + *height = 0; + *width = 0; + + rc = al_serdes_25g_eye_diag_run(obj, + lane, + mid_x, + mid_x, + 1, + SERDES_25G_EYE_Y_MIN, + SERDES_25G_EYE_Y_MAX, + 1, + SERDES_25G_EYE_SIZE_BER_TARGET, + samples, + ((SERDES_25G_EYE_Y_MAX - SERDES_25G_EYE_Y_MIN + 1) * + sizeof(uint64_t))); + + if (rc) { + al_err("%s: failed to run eye_diag\n", __func__); + return rc; + } + + for (i = (mid_y - SERDES_25G_EYE_Y_MIN); + ((samples[i] < SERDES_25G_EYE_SIZE_ERR_TH) && + (i < (SERDES_25G_EYE_Y_MAX - SERDES_25G_EYE_Y_MIN + 1))); + i++, (_height)++) + ; + for (i = (mid_y - SERDES_25G_EYE_Y_MIN); + ((samples[i] < SERDES_25G_EYE_SIZE_ERR_TH) && (i >= 0)); + i--, (_height)++) + ; + + rc = al_serdes_25g_eye_diag_run(obj, + lane, + SERDES_25G_EYE_X_MIN, + SERDES_25G_EYE_X_MAX, + 1, + mid_y, + mid_y, + 1, + SERDES_25G_EYE_SIZE_BER_TARGET, + samples, + ((SERDES_25G_EYE_X_MAX - SERDES_25G_EYE_X_MIN + 1) * + sizeof(uint64_t))); + + if (rc) { + al_err("%s: failed to run eye_diag\n", __func__); + return rc; + } + + for (i = (mid_x - SERDES_25G_EYE_X_MIN); + ((samples[i] < SERDES_25G_EYE_SIZE_ERR_TH) && + (i < (SERDES_25G_EYE_X_MAX - SERDES_25G_EYE_X_MIN + 1))); + i++, (_width)++) + ; + for (i = (mid_x - SERDES_25G_EYE_X_MIN); + ((samples[i] < SERDES_25G_EYE_SIZE_ERR_TH) && (i >= 0)); + i--, (_width)++) + ; + + *height = _height; + *width = _width; + + return 0; +} + + +static void al_serdes_25g_tx_advanced_params_set(struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + void *tx_params) +{ + struct al_serdes_adv_tx_params *params = tx_params; + uint32_t timeout = 5000; + uint8_t val = 0; + + al_serdes_25g_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_DRV_TXEQ_CTRL3_ADDR, + SERDES_25G_LANE_DRV_TXEQ_CTRL3_TXEQ_CM1_MASK, + SERDES_25G_LANE_DRV_TXEQ_CTRL3_TXEQ_CM1_SHIFT, + params->c_minus_1); + + al_serdes_25g_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_DRV_TXEQ_CTRL1_ADDR, + SERDES_25G_LANE_DRV_TXEQ_CTRL1_TXEQ_C1_MASK, + SERDES_25G_LANE_DRV_TXEQ_CTRL1_TXEQ_C1_SHIFT, + params->c_plus_1); + + al_serdes_25g_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_DRV_TXEQ_CTRL5_ADDR, + SERDES_25G_LANE_DRV_TXEQ_CTRL5_DRV_SWING_MASK, + SERDES_25G_LANE_DRV_TXEQ_CTRL5_DRV_SWING_SHIFT, + params->total_driver_units); + + al_serdes_25g_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_DRV_TXEQ_CTRL0_ADDR, + SERDES_25G_LANE_DRV_TXEQ_CTRL0_REQ_MASK, + SERDES_25G_LANE_DRV_TXEQ_CTRL0_REQ_SHIFT, + 1); + + + /* wait for acknowledge */ + while (1) { + al_serdes_25g_reg_masked_read(obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_DRV_TXEQ_STATUS0_ADDR, + SERDES_25G_LANE_DRV_TXEQ_STATUS0_ACK_MASK, + SERDES_25G_LANE_DRV_TXEQ_STATUS0_ACK_SHIFT, + &val); + if (val == 1) + break; + + if (timeout == 0) { + al_err("%s: timeout occurred waiting to FW ack\n", __func__); + break; + } + + timeout--; + al_udelay(1); + } + + al_serdes_25g_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_DRV_TXEQ_CTRL0_ADDR, + SERDES_25G_LANE_DRV_TXEQ_CTRL0_REQ_MASK, + SERDES_25G_LANE_DRV_TXEQ_CTRL0_REQ_SHIFT, + 0); +} + +static void al_serdes_25g_tx_advanced_params_get(struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + void *tx_params) +{ + struct al_serdes_adv_tx_params *params = tx_params; + + al_serdes_25g_reg_masked_read(obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_DRV_TXEQ_CTRL3_ADDR, + SERDES_25G_LANE_DRV_TXEQ_CTRL3_TXEQ_CM1_MASK, + SERDES_25G_LANE_DRV_TXEQ_CTRL3_TXEQ_CM1_SHIFT, + ¶ms->c_minus_1); + + al_serdes_25g_reg_masked_read(obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_DRV_TXEQ_CTRL1_ADDR, + SERDES_25G_LANE_DRV_TXEQ_CTRL1_TXEQ_C1_MASK, + SERDES_25G_LANE_DRV_TXEQ_CTRL1_TXEQ_C1_SHIFT, + ¶ms->c_plus_1); + + al_serdes_25g_reg_masked_read(obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_DRV_TXEQ_CTRL5_ADDR, + SERDES_25G_LANE_DRV_TXEQ_CTRL5_DRV_SWING_MASK, + SERDES_25G_LANE_DRV_TXEQ_CTRL5_DRV_SWING_SHIFT, + ¶ms->total_driver_units); +} + +static al_bool al_serdes_25g_cdr_is_locked( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane) +{ + uint8_t reg; + + al_serdes_25g_reg_masked_read(obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS5_ADDR, + SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS5_LOCKED_MASK, + SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS5_LOCKED_SHIFT, + ®); + + return !!reg; + +} + +static al_bool al_serdes_25g_rx_valid( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane) +{ + uint8_t reg; + + al_serdes_25g_reg_masked_read(obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_TOP_LN_STAT_CTRL0_ADDR, + SERDES_25G_LANE_TOP_LN_STAT_CTRL0_RXVALID_MASK, + SERDES_25G_LANE_TOP_LN_STAT_CTRL0_RXVALID_SHIFT, + ®); + + return !!reg; + +} + +static al_bool al_serdes_25g_signal_is_detected( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane) +{ + struct al_serdes_c_regs __iomem *regs_base = obj->regs_base; + uint32_t reg; + al_bool signal_detect = AL_FALSE; + + reg = al_reg_read32(®s_base->lane[lane].stat); + + signal_detect = ((reg & (SERDES_C_LANE_STAT_LN_STAT_LOS | + SERDES_C_LANE_STAT_LN_STAT_LOS_DEGLITCH)) ? + AL_FALSE : AL_TRUE); + + return signal_detect; + +} + +static int al_serdes_25g_rx_equalization( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane) +{ + struct al_serdes_c_regs __iomem *regs_base = obj->regs_base; + uint32_t ready_mask = (SERDES_C_GEN_STATUS_CM0_RST_PD_READY | SERDES_C_GEN_STATUS_CM0_OK_O); + uint32_t reset_mask; + uint32_t timeout; + uint32_t reg_val; + uint32_t retries = AL_SERDES_25G_RESET_NUM_RETRIES; + int status = 0; + + if (lane == 0) { + ready_mask |= SERDES_C_GEN_STATUS_LN0_RST_PD_READY; + reset_mask = SERDES_C_GEN_RST_LN0_RST_N; + } else { + ready_mask |= SERDES_C_GEN_STATUS_LN1_RST_PD_READY; + reset_mask = SERDES_C_GEN_RST_LN1_RST_N; + } + + while (retries > 0) { + timeout = AL_SERDES_25G_WAIT_FOR_READY_TO; + status = 0; + + al_reg_write32_masked(®s_base->gen.rst, reset_mask, 0); + + al_msleep(AL_SERDES_25G_RESET_TO); + + al_serdes_25g_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_FEATURE_CTLE_ADAPT_MBS_CFG_ADDR, + SERDES_25G_LANE_FEATURE_CTLE_ADAPT_MBS_CFG_INIT0_EN_MASK, + SERDES_25G_LANE_FEATURE_CTLE_ADAPT_MBS_CFG_INIT0_EN_SHIFT, + 0); + + al_serdes_25g_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL1_ADDR, + SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL1_EQ_MBF_START_MASK, + SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL1_EQ_MBF_START_SHIFT, + 7); + + al_serdes_25g_reg_masked_write(obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL1_ADDR, + SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL1_EQ_MBG_START_MASK, + SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL1_EQ_MBG_START_SHIFT, + 15); + + al_msleep(AL_SERDES_25G_RESET_TO); + + al_reg_write32_masked(®s_base->gen.rst, reset_mask, reset_mask); + + while (1) { + reg_val = al_reg_read32(®s_base->gen.status); + if ((reg_val & ready_mask) == ready_mask) + break; + + al_udelay(1); + timeout--; + + if (timeout == 0) { + al_err("%s: Timeout waiting for serdes ready\n", __func__); + status = ETIMEDOUT; + retries--; + break; + } + } + + if (status) + continue; + + while (1) { + reg_val = al_reg_read32(®s_base->lane[lane].stat); + reg_val &= (SERDES_C_LANE_STAT_LNX_STAT_OK | + SERDES_C_LANE_STAT_LN_STAT_RXVALID); + if (reg_val == (SERDES_C_LANE_STAT_LNX_STAT_OK | + SERDES_C_LANE_STAT_LN_STAT_RXVALID)) + break; + + al_udelay(1); + timeout--; + + if (timeout == 0) { + al_err("%s: TO waiting for lane ready (%x)\n", __func__, reg_val); + status = ETIMEDOUT; + retries--; + break; + } + } + + if (status) + continue; + + break; + } + + if (retries == 0) { + al_err("%s: Failed to run equalization\n", __func__); + status = ETIMEDOUT; + } + + return status; + +} + +#define AL_SERDES_25G_GCFSM2_READ_TIMEOUT 2000000 /* uSec */ + +static int al_serdes_25g_gcfsm2_read( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + uint8_t offset, + uint16_t *data) +{ + int status = 0; + uint32_t timeout = AL_SERDES_25G_GCFSM2_READ_TIMEOUT; + uint8_t ack = 0; + uint8_t data_low, data_high; + + al_assert(data); + + /* Make sure GCFSM2 REQuest is off */ + al_serdes_25g_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_GCFSM2_CMD_CTRL0_ADDR, + SERDES_25G_LANE_GCFSM2_CMD_CTRL0_REQ_MASK, + SERDES_25G_LANE_GCFSM2_CMD_CTRL0_REQ_SHIFT, + 0); + /* Write GCFSM2 CMD; CMD=0 for Read Request */ + al_serdes_25g_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_GCFSM2_CMD_CTRL1_ADDR, + SERDES_25G_LANE_GCFSM2_CMD_CTRL1_CMD_MASK, + SERDES_25G_LANE_GCFSM2_CMD_CTRL1_CMD_SHIFT, + 0); + /* Write GCFSM2 the Address we wish to read */ + al_serdes_25g_reg_write( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_LANE_GCFSM2_CMD_CTRL2_ADDR, + offset); + /* Issue a command REQuest */ + al_serdes_25g_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_GCFSM2_CMD_CTRL0_ADDR, + SERDES_25G_LANE_GCFSM2_CMD_CTRL0_REQ_MASK, + SERDES_25G_LANE_GCFSM2_CMD_CTRL0_REQ_SHIFT, + 1); + /* Poll on GCFSM2 ACK */ + while (1) { + al_serdes_25g_reg_masked_read( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_GCFSM2_CMD_STATUS_ADDR, + SERDES_25G_LANE_GCFSM2_CMD_STATUS_ACK_MASK, + SERDES_25G_LANE_GCFSM2_CMD_STATUS_ACK_SHIFT, + &ack); + + if (ack || (timeout == 0)) + break; + + timeout--; + al_udelay(1); + } + + if (ack) { + /* Read 12bit of register value */ + al_serdes_25g_reg_read( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_LANE_GCFSM2_READ_SHADOW_DATA_STATUS0_ADDR, + &data_low); + al_serdes_25g_reg_masked_read( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_GCFSM2_READ_SHADOW_DATA_STATUS1_ADDR, + SERDES_25G_LANE_GCFSM2_READ_SHADOW_DATA_STATUS1_11_8_MASK, + SERDES_25G_LANE_GCFSM2_READ_SHADOW_DATA_STATUS1_11_8_SHIFT, + &data_high); + *data = (data_high << 8) | data_low; + } else { + al_err("%s: TO waiting for GCFSM2 req to complete (%x)\n", __func__, offset); + status = ETIMEDOUT; + } + + /* Deassert the GCFSM2 REQuest */ + al_serdes_25g_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_GCFSM2_CMD_CTRL0_ADDR, + SERDES_25G_LANE_GCFSM2_CMD_CTRL0_REQ_MASK, + SERDES_25G_LANE_GCFSM2_CMD_CTRL0_REQ_SHIFT, + 0); + + return status; +} + +enum al_serdes_25g_rx_leq_fsm_opcode { + AL_SERDES_25G_RX_LEQ_FSM_OPCODE_READ = 0x1, + AL_SERDES_25G_RX_LEQ_FSM_OPCODE_WRITE = 0x2, +}; + +enum al_serdes_25g_rx_leq_fsm_target { + AL_SERDES_25G_RX_LEQ_FSM_TARGET_AGC_SOURCE = 0x1, + AL_SERDES_25G_RX_LEQ_FSM_TARGET_PLE_ATT = 0x2, + AL_SERDES_25G_RX_LEQ_FSM_TARGET_EQ_LFG = 0x3, + AL_SERDES_25G_RX_LEQ_FSM_TARGET_GN_APG = 0x4, + AL_SERDES_25G_RX_LEQ_FSM_TARGET_GNEQ_CCL_LFG = 0x5, + AL_SERDES_25G_RX_LEQ_FSM_TARGET_HFG_SQL = 0x6, + AL_SERDES_25G_RX_LEQ_FSM_TARGET_EQ_MBF = 0x8, + AL_SERDES_25G_RX_LEQ_FSM_TARGET_EQ_MBG = 0x9, + AL_SERDES_25G_RX_LEQ_FSM_TARGET_VSCAN = 0xA, + AL_SERDES_25G_RX_LEQ_FSM_TARGET_HSCAN = 0xB, + AL_SERDES_25G_RX_LEQ_FSM_TARGET_EYE_INTF = 0xC, +}; + +#define AL_SERDES_25G_RX_LEQ_FSM_TIMEOUT 2000000 /* uSec */ + +static int al_serdes_25g_rx_leq_fsm_op( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + enum al_serdes_25g_rx_leq_fsm_opcode opcode, + enum al_serdes_25g_rx_leq_fsm_target target, + uint8_t val, + uint8_t *data, + uint8_t *err) +{ + uint32_t reg; + uint32_t timeout = AL_SERDES_25G_RX_LEQ_FSM_TIMEOUT; + uint8_t ack = 0; + int status = 0; + + al_assert(data); + al_assert(err); + + /* Write the OpCode & Target to LEQ FSM */ + reg = (target << 4) | opcode; + al_serdes_25g_reg_write( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CMD0_ADDR, + reg); + + /* Write 0 as MiscOption value to LEQ FSM */ + al_serdes_25g_reg_write( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CMD2_ADDR, + 0); + + /* Write the ArgumentValue to LEQ FSM if needed*/ + if (opcode == AL_SERDES_25G_RX_LEQ_FSM_OPCODE_WRITE) { + al_serdes_25g_reg_write( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CMD1_ADDR, + val); + } + + /* Issue an LEQ FSM Command Request */ + al_serdes_25g_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL0_ADDR, + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL0_LEQ_FSM_CMD_REQ_MASK, + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL0_LEQ_FSM_CMD_REQ_SHIFT, + 1); + + /* Poll on LEQ FSM Command acknowledge */ + while (1) { + al_serdes_25g_reg_masked_read( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS5_ADDR, + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS5_LEQ_FSM_CMD_ACK_MASK, + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS5_LEQ_FSM_CMD_ACK_SHIFT, + &ack); + + if (ack || (timeout == 0)) + break; + + timeout--; + al_udelay(1); + } + + if (ack) { + uint8_t err1, err2; + al_serdes_25g_reg_read( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_ADDR, + err); + + err1 = (*err & + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_LEQ_FSM_STATUS_ERROR1_MASK) >> + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_LEQ_FSM_STATUS_ERROR1_SHIFT; + err2 = (*err & + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_LEQ_FSM_STATUS_ERROR2_MASK) >> + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_LEQ_FSM_STATUS_ERROR2_SHIFT; + + if (err1 || err2) { + al_err("%s: error in RX LEQ FSM req, err status 1=0x%x, err status 2=0x%x", + __func__, err1, err2); + status = -EIO; + } + + /* Read LEQ FSM Command return Value */ + al_serdes_25g_reg_read( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS3_ADDR, + data); + + /* Clear an LEQ FSM Command Request */ + al_serdes_25g_reg_masked_write( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL0_ADDR, + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL0_LEQ_FSM_CMD_REQ_MASK, + SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL0_LEQ_FSM_CMD_REQ_SHIFT, + 0); + } else { + al_err("%s: TO waiting for RX LEQ FSM req to complete (opcode %x, target %x, val %x)\n", + __func__, opcode, target, val); + status = ETIMEDOUT; + } + + return status; +} + +/* enum values correspond to HW values, don't change! */ +enum al_serdes_25g_tbus_obj { + AL_SERDES_25G_TBUS_OBJ_TOP = 0, + AL_SERDES_25G_TBUS_OBJ_CMU = 1, + AL_SERDES_25G_TBUS_OBJ_LANE = 2, +}; + +#define AL_SERDES_25G_TBUS_DELAY 1000 /* uSec */ +#define AL_SERDES_25G_TBUS_ADDR_HIGH_SHIFT 5 + +static int al_serdes_25g_tbus_read( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + enum al_serdes_25g_tbus_obj tbus_obj, + uint8_t offset, + uint16_t *data) +{ + uint8_t addr_high, val_high, val_low; + + al_assert(lane < AL_SRDS_NUM_LANES); + + if (tbus_obj == AL_SERDES_25G_TBUS_OBJ_TOP) + addr_high = AL_SERDES_25G_TBUS_OBJ_TOP; + else if (tbus_obj == AL_SERDES_25G_TBUS_OBJ_CMU) + addr_high = AL_SERDES_25G_TBUS_OBJ_CMU; + else + addr_high = AL_SERDES_25G_TBUS_OBJ_LANE + lane; + + addr_high <<= AL_SERDES_25G_TBUS_ADDR_HIGH_SHIFT; + + al_serdes_25g_reg_write( + obj, + AL_SRDS_REG_PAGE_TOP, + 0, + SERDES_25G_TOP_TBUS_ADDR_7_0_ADDR, + offset); + + al_serdes_25g_reg_write( + obj, + AL_SRDS_REG_PAGE_TOP, + 0, + SERDES_25G_TOP_TBUS_ADDR_15_8_ADDR, + addr_high); + + al_udelay(AL_SERDES_25G_TBUS_DELAY); + + al_serdes_25g_reg_read( + obj, + AL_SRDS_REG_PAGE_TOP, + 0, + SERDES_25G_TOP_TBUS_DATA_7_0_ADDR, + &val_low); + + al_serdes_25g_reg_masked_read( + obj, + AL_SRDS_REG_PAGE_TOP, + SERDES_25G_TOP_TBUS_DATA_11_8_ADDR, + SERDES_25G_TOP_TBUS_DATA_11_8_MASK, + SERDES_25G_TOP_TBUS_DATA_11_8_SHIFT, + &val_high); + + *data = (val_high << 8) | val_low; + + return 0; +} + +#define AL_SERDES_25G_RX_ADV_PARAMS_ATT_MASK 0x07 +#define AL_SERDES_25G_RX_ADV_PARAMS_APG_MASK 0x03 +#define AL_SERDES_25G_RX_ADV_PARAMS_LFG_MASK 0x1F +#define AL_SERDES_25G_RX_ADV_PARAMS_HFG_MASK 0x1F +#define AL_SERDES_25G_RX_ADV_PARAMS_MBG_MASK 0x0F +#define AL_SERDES_25G_RX_ADV_PARAMS_MBF_MASK 0x0F +#define AL_SERDES_25G_RX_ADV_PARAMS_DFE_TAP_CNT 8 +#define AL_SERDES_25G_RX_ADV_PARAMS_DFE_TAP_MASK 0x1F +#define AL_SERDES_25G_RX_ADV_PARAMS_DFE_TAP_SIGN_SHIFT 7 + +static void al_serdes_25g_rx_advanced_params_get( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + void *rx_params) +{ + struct al_serdes_25g_adv_rx_params *params = rx_params; + uint8_t value, err; + int8_t tap_weight; + uint8_t tap_sign; + int8_t *tap_ptr_arr[AL_SERDES_25G_RX_ADV_PARAMS_DFE_TAP_CNT]; + int rc; + int i; + + rc = al_serdes_25g_rx_leq_fsm_op(obj, lane, AL_SERDES_25G_RX_LEQ_FSM_OPCODE_READ, + AL_SERDES_25G_RX_LEQ_FSM_TARGET_PLE_ATT, 0, &value, &err); + if (rc || err) { + al_err("%s: al_serdes_25g_rx_leq_fsm_op failed to read att, rc %d, err %d\n", + __func__, rc, err); + return; + } + params->att = value & AL_SERDES_25G_RX_ADV_PARAMS_ATT_MASK; + + rc = al_serdes_25g_rx_leq_fsm_op(obj, lane, AL_SERDES_25G_RX_LEQ_FSM_OPCODE_READ, + AL_SERDES_25G_RX_LEQ_FSM_TARGET_GN_APG, 0, &value, &err); + if (rc || err) { + al_err("%s: al_serdes_25g_rx_leq_fsm_op failed to read apg, rc %d, err %d\n", + __func__, rc, err); + return; + } + params->apg = value & AL_SERDES_25G_RX_ADV_PARAMS_APG_MASK; + + rc = al_serdes_25g_rx_leq_fsm_op(obj, lane, AL_SERDES_25G_RX_LEQ_FSM_OPCODE_READ, + AL_SERDES_25G_RX_LEQ_FSM_TARGET_EQ_LFG, 0, &value, &err); + if (rc || err) { + al_err("%s: al_serdes_25g_rx_leq_fsm_op failed to read lfg, rc %d, err %d\n", + __func__, rc, err); + return; + } + params->lfg = value & AL_SERDES_25G_RX_ADV_PARAMS_LFG_MASK; + + rc = al_serdes_25g_rx_leq_fsm_op(obj, lane, AL_SERDES_25G_RX_LEQ_FSM_OPCODE_READ, + AL_SERDES_25G_RX_LEQ_FSM_TARGET_HFG_SQL, 0, &value, &err); + if (rc || err) { + al_err("%s: al_serdes_25g_rx_leq_fsm_op failed to read hfg, rc %d, err %d\n", + __func__, rc, err); + return; + } + params->hfg = value & AL_SERDES_25G_RX_ADV_PARAMS_HFG_MASK; + + rc = al_serdes_25g_rx_leq_fsm_op(obj, lane, AL_SERDES_25G_RX_LEQ_FSM_OPCODE_READ, + AL_SERDES_25G_RX_LEQ_FSM_TARGET_EQ_MBG, 0, &value, &err); + if (rc || err) { + al_err("%s: al_serdes_25g_rx_leq_fsm_op failed to read mbg, rc %d, err %d\n", + __func__, rc, err); + return; + } + params->mbg = value & AL_SERDES_25G_RX_ADV_PARAMS_MBG_MASK; + + rc = al_serdes_25g_rx_leq_fsm_op(obj, lane, AL_SERDES_25G_RX_LEQ_FSM_OPCODE_READ, + AL_SERDES_25G_RX_LEQ_FSM_TARGET_EQ_MBF, 0, &value, &err); + if (rc || err) { + al_err("%s: al_serdes_25g_rx_leq_fsm_op failed to read mbf, rc %d, err %d\n", + __func__, rc, err); + return; + } + params->mbf = value & AL_SERDES_25G_RX_ADV_PARAMS_MBF_MASK; + + tap_ptr_arr[0] = ¶ms->dfe_first_tap_even0_ctrl; + tap_ptr_arr[1] = ¶ms->dfe_first_tap_even1_ctrl; + tap_ptr_arr[2] = ¶ms->dfe_first_tap_odd0_ctrl; + tap_ptr_arr[3] = ¶ms->dfe_first_tap_odd1_ctrl; + tap_ptr_arr[4] = ¶ms->dfe_second_tap_ctrl; + tap_ptr_arr[5] = ¶ms->dfe_third_tap_ctrl; + tap_ptr_arr[6] = ¶ms->dfe_fourth_tap_ctrl; + tap_ptr_arr[7] = ¶ms->dfe_fifth_tap_ctrl; + + for (i = 0; i < AL_SERDES_25G_RX_ADV_PARAMS_DFE_TAP_CNT; i++) { + al_serdes_25g_reg_read( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS0_ADDR + i, + &value); + + tap_weight = value & AL_SERDES_25G_RX_ADV_PARAMS_DFE_TAP_MASK; + tap_sign = (value & AL_BIT(AL_SERDES_25G_RX_ADV_PARAMS_DFE_TAP_SIGN_SHIFT)) >> + AL_SERDES_25G_RX_ADV_PARAMS_DFE_TAP_SIGN_SHIFT; + if (tap_sign == 0) + tap_weight = 0 - tap_weight; + + *tap_ptr_arr[i] = tap_weight; + } +} + +#define AL_SERDES_25G_TX_DIAG_GCFSM2_DCD_TRIM_ADDR 0x0B +#define AL_SERDES_25G_TX_DIAG_GCFSM2_DCD_TRIM_MASK 0x3F +#define AL_SERDES_25G_TX_DIAG_GCFSM2_DCD_TRIM_SIGN_SHIFT 7 +#define AL_SERDES_25G_TX_DIAG_GCFSM2_CLK_DELAY_ADDR 0x0C +#define AL_SERDES_25G_TX_DIAG_GCFSM2_CLK_DELAY_MASK 0xFFF + +static void al_serdes_25g_tx_diag_info_get( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + void *tx_info) +{ + struct al_serdes_25g_tx_diag_info *info = tx_info; + uint8_t cal_x1, cal_x1_fixed, cal_x2, cal_xp5_fixed; + uint16_t val16, sign; + uint8_t val8, abs; + int rc; + + al_serdes_25g_reg_read( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_ADDR, + &val8); + info->regulated_supply = val8 & SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_REG_TXCP_TRIM_MASK; + + rc = al_serdes_25g_gcfsm2_read( + obj, + lane, + AL_SERDES_25G_TX_DIAG_GCFSM2_DCD_TRIM_ADDR, + &val16); + if (rc) { + al_err("%s: al_serdes_25g_gcfsm2_read failed to read dcd_trim, rc %d\n", + __func__, rc); + return; + } + + abs = val16 & AL_SERDES_25G_TX_DIAG_GCFSM2_DCD_TRIM_MASK; + sign = (val16 & AL_BIT(AL_SERDES_25G_TX_DIAG_GCFSM2_DCD_TRIM_SIGN_SHIFT)) >> + AL_SERDES_25G_TX_DIAG_GCFSM2_DCD_TRIM_SIGN_SHIFT; + if (sign) + info->dcd_trim = abs; + else + info->dcd_trim = 0 - abs; + + rc = al_serdes_25g_gcfsm2_read( + obj, + lane, + AL_SERDES_25G_TX_DIAG_GCFSM2_CLK_DELAY_ADDR, + &val16); + if (rc) { + al_err("%s: al_serdes_25g_gcfsm2_read failed to read clk_delay, rc %d\n", + __func__, rc); + return; + } + info->clk_delay = val16 & AL_SERDES_25G_TX_DIAG_GCFSM2_CLK_DELAY_MASK; + + al_serdes_25g_reg_read( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_CM_TOP_AFE_TXTC_CTRL2_ADDR, + &val8); + cal_x1 = (val8 & SERDES_25G_CMU_TOP_AFE_TXTC_CTRL2_TXTC_CALP_X1_MASK) >> + SERDES_25G_CMU_TOP_AFE_TXTC_CTRL2_TXTC_CALP_X1_SHIFT; + cal_x1_fixed = (val8 & SERDES_25G_CMU_TOP_AFE_TXTC_CTRL2_TXTC_CALP_X1_FIXED_MASK) >> + SERDES_25G_CMU_TOP_AFE_TXTC_CTRL2_TXTC_CALP_X1_FIXED_SHIFT; + al_serdes_25g_reg_read( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_CM_TOP_AFE_TXTC_CTRL3_ADDR, + &val8); + cal_x2 = (val8 & SERDES_25G_CMU_TOP_AFE_TXTC_CTRL3_TXTC_CALP_X2_MASK) >> + SERDES_25G_CMU_TOP_AFE_TXTC_CTRL3_TXTC_CALP_X2_SHIFT; + cal_xp5_fixed = (val8 & + SERDES_25G_CMU_TOP_AFE_TXTC_CTRL3_TXTC_CALP_XP5_FIXED_MASK) >> + SERDES_25G_CMU_TOP_AFE_TXTC_CTRL3_TXTC_CALP_XP5_FIXED_SHIFT; + info->calp_multiplied_by_2 = 4 * cal_x2 + 2 * cal_x1 + 2 * cal_x1_fixed + cal_xp5_fixed; + + al_serdes_25g_reg_read( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_CM_TOP_AFE_TXTC_CTRL0_ADDR, + &val8); + cal_x1 = (val8 & SERDES_25G_CMU_TOP_AFE_TXTC_CTRL0_TXTC_CALN_X1_MASK) >> + SERDES_25G_CMU_TOP_AFE_TXTC_CTRL0_TXTC_CALN_X1_SHIFT; + cal_x1_fixed = (val8 & SERDES_25G_CMU_TOP_AFE_TXTC_CTRL0_TXTC_CALN_X1_FIXED_MASK) >> + SERDES_25G_CMU_TOP_AFE_TXTC_CTRL0_TXTC_CALN_X1_FIXED_SHIFT; + al_serdes_25g_reg_read( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_CM_TOP_AFE_TXTC_CTRL1_ADDR, + &val8); + cal_x2 = (val8 & SERDES_25G_CMU_TOP_AFE_TXTC_CTRL1_TXTC_CALN_X2_MASK) >> + SERDES_25G_CMU_TOP_AFE_TXTC_CTRL1_TXTC_CALN_X2_SHIFT; + cal_xp5_fixed = (val8 & + SERDES_25G_CMU_TOP_AFE_TXTC_CTRL1_TXTC_CALN_XP5_FIXED_MASK) >> + SERDES_25G_CMU_TOP_AFE_TXTC_CTRL1_TXTC_CALN_XP5_FIXED_SHIFT; + info->caln_multiplied_by_2 = 4 * cal_x2 + 2 * cal_x1 + 2 * cal_x1_fixed + cal_xp5_fixed; +} + +#define AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_ABS_MASK 0x1F +#define AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_MASK 0x3F +#define AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_SIGN_SHIFT 5 +#define AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_MASK 0xFC0 +#define AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_SHIFT 6 +#define AL_SERDES_25G_RX_DIAG_LEQ_EQ_COUNT 5 +#define AL_SERDES_25G_RX_DIAG_GCFSM2_LEQ_EQ_ADDR 0 +#define AL_SERDES_25G_RX_DIAG_GCFSM2_LEQ_GAINSTAGE_ADDR 0x5 +#define AL_SERDES_25G_RX_DIAG_GCFSM2_SUMMER_EVEN_ADDR 0x6 +#define AL_SERDES_25G_RX_DIAG_GCFSM2_SUMMER_ODD_ADDR 0x7 +#define AL_SERDES_25G_RX_DIAG_GCFSM2_VSCAN_EVEN_ADDR 0x8 +#define AL_SERDES_25G_RX_DIAG_GCFSM2_VSCAN_ODD_ADDR 0x9 +#define AL_SERDES_25G_RX_DIAG_GCFSM2_CDR_VCO_FR_ADDR 0xF +#define AL_SERDES_25G_RX_DIAG_GCFSM2_CDR_VCO_FR_MASK 0xFFF +#define AL_SERDES_25G_RX_DIAG_TBUS_DATA_SLICER_EVEN_ADDR 0x11 +#define AL_SERDES_25G_RX_DIAG_TBUS_DATA_SLICER_ODD_ADDR 0x12 +#define AL_SERDES_25G_RX_DIAG_TBUS_EDGE_SLICER_ADDR 0x13 +#define AL_SERDES_25G_RX_DIAG_TBUS_EYE_SLICER_ADDR 0x23 +#define AL_SERDES_25G_RX_DIAG_TBUS_CDR_CLK_Q_ADDR 0x2 +#define AL_SERDES_25G_RX_DIAG_TBUS_CDR_CLK_I_ADDR 0x1 +#define AL_SERDES_25G_RX_DIAG_CDR_RXCLK_DLPF_L_ADDR 0x26 +#define AL_SERDES_25G_RX_DIAG_CDR_RXCLK_DLPF_H_ADDR 0x27 + +static inline void al_serdes_25g_rx_diag_5bit_signed_set(uint8_t packed_val, int8_t *ptr) +{ + uint8_t abs, sign; + + abs = packed_val & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_ABS_MASK; + sign = (packed_val & AL_BIT(AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_SIGN_SHIFT)) >> + AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_SIGN_SHIFT; + if (sign) + *ptr = abs; + else + *ptr = 0 - abs; +} + +static void al_serdes_25g_rx_diag_info_get( + struct al_serdes_grp_obj *obj, + enum al_serdes_lane lane, + void *rx_info) +{ + struct al_serdes_25g_rx_diag_info *info = rx_info; + uint16_t val16; + uint8_t val8, val8_2; + int rc; + int i; + + al_serdes_25g_reg_read( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_STATUS0_ADDR, + &val8); + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->los_offset); + + al_serdes_25g_reg_read( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_STATUS1_ADDR, + &val8); + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->agc_offset); + + rc = al_serdes_25g_gcfsm2_read( + obj, + lane, + AL_SERDES_25G_RX_DIAG_GCFSM2_LEQ_GAINSTAGE_ADDR, + &val16); + if (rc) { + al_err("%s: al_serdes_25g_gcfsm2_read failed to read leq_gainstage, rc %d\n", + __func__, rc); + return; + } + val8 = (uint8_t)val16; + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->leq_gainstage_offset); + + for (i = 0; i < AL_SERDES_25G_RX_DIAG_LEQ_EQ_COUNT; i++) { + rc = al_serdes_25g_gcfsm2_read( + obj, + lane, + AL_SERDES_25G_RX_DIAG_GCFSM2_LEQ_EQ_ADDR + i, + &val16); + if (rc) { + al_err("%s: al_serdes_25g_gcfsm2_read failed to read leq_eq %d, rc %d\n", + __func__, i, rc); + return; + } + val8 = (uint8_t)val16; + + switch (i) { + case 0: + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->leq_eq1_offset); + break; + case 1: + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->leq_eq2_offset); + break; + case 2: + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->leq_eq3_offset); + break; + case 3: + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->leq_eq4_offset); + break; + case 4: + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->leq_eq5_offset); + break; + default: + break; + } + } + + rc = al_serdes_25g_gcfsm2_read( + obj, + lane, + AL_SERDES_25G_RX_DIAG_GCFSM2_SUMMER_EVEN_ADDR, + &val16); + if (rc) { + al_err("%s: al_serdes_25g_gcfsm2_read failed to read summer_even_offset, rc %d\n", + __func__, rc); + return; + } + val8 = (uint8_t)val16; + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->summer_even_offset); + + rc = al_serdes_25g_gcfsm2_read( + obj, + lane, + AL_SERDES_25G_RX_DIAG_GCFSM2_SUMMER_ODD_ADDR, + &val16); + if (rc) { + al_err("%s: al_serdes_25g_gcfsm2_read failed to read summer_odd_offset, rc %d\n", + __func__, rc); + return; + } + val8 = (uint8_t)val16; + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->summer_odd_offset); + + rc = al_serdes_25g_gcfsm2_read( + obj, + lane, + AL_SERDES_25G_RX_DIAG_GCFSM2_VSCAN_EVEN_ADDR, + &val16); + if (rc) { + al_err("%s: al_serdes_25g_gcfsm2_read failed to read vscan_even_offset, rc %d\n", + __func__, rc); + return; + } + val8 = (uint8_t)val16; + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->vscan_even_offset); + + rc = al_serdes_25g_gcfsm2_read( + obj, + lane, + AL_SERDES_25G_RX_DIAG_GCFSM2_VSCAN_ODD_ADDR, + &val16); + if (rc) { + al_err("%s: al_serdes_25g_gcfsm2_read failed to read vscan_odd_offset, rc %d\n", + __func__, rc); + return; + } + val8 = (uint8_t)val16; + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->vscan_odd_offset); + + al_serdes_25g_tbus_read( + obj, + lane, + AL_SERDES_25G_TBUS_OBJ_LANE, + AL_SERDES_25G_RX_DIAG_TBUS_DATA_SLICER_EVEN_ADDR, + &val16); + val8 = (uint8_t)(val16 & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_MASK); + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->data_slicer_even0_offset); + val8 = (uint8_t)((val16 & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_MASK) >> + AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_SHIFT); + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->data_slicer_even1_offset); + + al_serdes_25g_tbus_read( + obj, + lane, + AL_SERDES_25G_TBUS_OBJ_LANE, + AL_SERDES_25G_RX_DIAG_TBUS_DATA_SLICER_ODD_ADDR, + &val16); + val8 = (uint8_t)(val16 & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_MASK); + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->data_slicer_odd0_offset); + val8 = (uint8_t)((val16 & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_MASK) >> + AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_SHIFT); + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->data_slicer_odd1_offset); + + al_serdes_25g_tbus_read( + obj, + lane, + AL_SERDES_25G_TBUS_OBJ_LANE, + AL_SERDES_25G_RX_DIAG_TBUS_EDGE_SLICER_ADDR, + &val16); + val8 = (uint8_t)(val16 & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_MASK); + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->edge_slicer_even_offset); + val8 = (uint8_t)((val16 & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_MASK) >> + AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_SHIFT); + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->edge_slicer_odd_offset); + + al_serdes_25g_tbus_read( + obj, + lane, + AL_SERDES_25G_TBUS_OBJ_LANE, + AL_SERDES_25G_RX_DIAG_TBUS_EYE_SLICER_ADDR, + &val16); + val8 = (uint8_t)(val16 & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_MASK); + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->eye_slicer_even_offset); + val8 = (uint8_t)((val16 & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_MASK) >> + AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_SHIFT); + al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->eye_slicer_odd_offset); + + al_serdes_25g_reg_masked_read( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL0_ADDR, + SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL0_RXCDR_HSCAN_CLKQ_MASK, + SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL0_RXCDR_HSCAN_CLKQ_SHIFT, + &info->cdr_clk_q); + + al_serdes_25g_reg_masked_read( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL1_ADDR, + SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL1_RXCDR_HSCAN_CLKI_MASK, + SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL1_RXCDR_HSCAN_CLKI_SHIFT, + &info->cdr_clk_i); + + al_serdes_25g_reg_masked_read( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL2_ADDR, + SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL2_RXCDR_HSCAN_EYE_MASK, + SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL2_RXCDR_HSCAN_EYE_SHIFT, + &info->cdr_dll); + + al_serdes_25g_reg_masked_read( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL2_ADDR, + SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL2_RXCDR_DOSC_MASK, + SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL2_RXCDR_DOSC_SHIFT, + &info->cdr_vco_dosc); + + al_serdes_25g_reg_read( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL1_ADDR, + &val8_2); + al_serdes_25g_reg_read( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL0_ADDR, + &val8); + val8_2 &= SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL1_DLPF_VAL_8_MASK; + info->cdr_dlpf = (uint16_t)val8_2 << 8 | val8; + + rc = al_serdes_25g_gcfsm2_read( + obj, + lane, + AL_SERDES_25G_RX_DIAG_GCFSM2_CDR_VCO_FR_ADDR, + &val16); + if (rc) { + al_err("%s: al_serdes_25g_gcfsm2_read failed to read cdr_vco_fr, rc %d\n", + __func__, rc); + return; + } + info->cdr_vco_fr = val16 & AL_SERDES_25G_RX_DIAG_GCFSM2_CDR_VCO_FR_MASK; + + al_serdes_25g_reg_masked_read( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_LEQ_REFCLK_AFE_PLE_CTRL0_ADDR, + SERDES_25G_LANE_LEQ_REFCLK_AFE_PLE_CTRL0_RXLEQ_PLE_BLW_ZERO_MASK, + SERDES_25G_LANE_LEQ_REFCLK_AFE_PLE_CTRL0_RXLEQ_PLE_BLW_ZERO_SHIFT, + &info->ple_resistance); + + al_serdes_25g_reg_read( + obj, + (enum al_serdes_reg_page)lane, + 0, + SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_ADDR, + &val8); + + info->rx_term_mode = (val8 & SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_HIZ_MASK) >> + SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_HIZ_SHIFT; + + info->rx_coupling = (val8 & SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_VCM_GND_MASK) >> + SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_VCM_GND_SHIFT; + + al_serdes_25g_reg_masked_read( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL1_ADDR, + SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL1_RXTERM_VAL_MASK, + SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL1_RXTERM_VAL_SHIFT, + &info->rx_term_cal_code); + + al_serdes_25g_reg_masked_read( + obj, + (enum al_serdes_reg_page)lane, + SERDES_25G_LANE_LEQ_REFCLK_AFE_BIAS_CTRL1_ADDR, + SERDES_25G_LANE_LEQ_REFCLK_AFE_BIAS_CTRL1_RXLEQ_BIASI_TRIM_MASK, + SERDES_25G_LANE_LEQ_REFCLK_AFE_BIAS_CTRL1_RXLEQ_BIASI_TRIM_SHIFT, + &info->rx_sheet_res_cal_code); +} + +/******************************************************************************/ +/******************************************************************************/ +int al_serdes_25g_handle_init( + void __iomem *serdes_regs_base, + struct al_serdes_grp_obj *obj) +{ + al_dbg( + "%s(%p, %p)\n", + __func__, + serdes_regs_base, + obj); + + al_memset(obj, 0, sizeof(struct al_serdes_grp_obj)); + + obj->regs_base = (struct al_serdes_regs *)serdes_regs_base; + obj->type_get = al_serdes_25g_type_get; + obj->reg_read = al_serdes_25g_reg_read; + obj->reg_write = al_serdes_25g_reg_write; + obj->bist_overrides_enable = NULL; + obj->bist_overrides_disable = NULL; + obj->rx_rate_change = NULL; + obj->group_pm_set = NULL; + obj->lane_pm_set = NULL; + obj->pma_hard_reset_group = NULL; + obj->pma_hard_reset_lane = NULL; + obj->loopback_control = NULL; + obj->bist_pattern_select = AL_SRDS_ADV_SRVC(al_serdes_25g_bist_pattern_select); + obj->bist_tx_enable = AL_SRDS_ADV_SRVC(al_serdes_25g_bist_tx_enable); + obj->bist_tx_err_inject = NULL; + obj->bist_rx_enable = AL_SRDS_ADV_SRVC(al_serdes_25g_bist_rx_enable); + obj->bist_rx_status = AL_SRDS_ADV_SRVC(al_serdes_25g_bist_rx_status); + obj->tx_deemph_preset = NULL; + obj->tx_deemph_inc = NULL; + obj->tx_deemph_dec = NULL; + obj->eye_measure_run = NULL; + obj->eye_diag_sample = NULL; + obj->eye_diag_run = AL_SRDS_ADV_SRVC(al_serdes_25g_eye_diag_run); + obj->cdr_is_locked = AL_SRDS_ADV_SRVC(al_serdes_25g_cdr_is_locked); + obj->rx_valid = AL_SRDS_ADV_SRVC(al_serdes_25g_rx_valid); + obj->signal_is_detected = AL_SRDS_ADV_SRVC(al_serdes_25g_signal_is_detected); + obj->tx_advanced_params_set = AL_SRDS_ADV_SRVC(al_serdes_25g_tx_advanced_params_set); + obj->tx_advanced_params_get = AL_SRDS_ADV_SRVC(al_serdes_25g_tx_advanced_params_get); + obj->rx_advanced_params_set = NULL; + obj->rx_advanced_params_get = AL_SRDS_ADV_SRVC(al_serdes_25g_rx_advanced_params_get); + obj->tx_diag_info_get = AL_SRDS_ADV_SRVC(al_serdes_25g_tx_diag_info_get); + obj->rx_diag_info_get = AL_SRDS_ADV_SRVC(al_serdes_25g_rx_diag_info_get); + obj->mode_set_sgmii = NULL; + obj->mode_set_kr = NULL; + obj->rx_equalization = AL_SRDS_ADV_SRVC(al_serdes_25g_rx_equalization); + obj->calc_eye_size = AL_SRDS_ADV_SRVC(al_serdes_25g_calc_eye_size); + obj->sris_config = NULL; + + return 0; +} + diff --git a/al_hal_serdes_25g.h b/al_hal_serdes_25g.h new file mode 100644 index 00000000000..8865b7da94f --- /dev/null +++ b/al_hal_serdes_25g.h @@ -0,0 +1,74 @@ +/******************************************************************************* +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. + +*******************************************************************************/ + +/** + * @defgroup group_serdes_api API + * SerDes HAL driver API + * @ingroup group_serdes SerDes + * @{ + * + * @file al_hal_serdes_25g.h + * + * @brief Header file for the SerDes HAL driver + * + */ + +#ifndef __AL_HAL_SERDES_25G_H__ +#define __AL_HAL_SERDES_25G_H__ + +#include "al_hal_common.h" +#include "al_hal_serdes_interface.h" + +/* *INDENT-OFF* */ +#ifdef __cplusplus +extern "C" { +#endif +/* *INDENT-ON* */ + +int al_serdes_25g_handle_init( + void __iomem *serdes_regs_base, + struct al_serdes_grp_obj *obj); + + +/* *INDENT-OFF* */ +#ifdef __cplusplus +} +#endif + +/* *INDENT-ON* */ +#endif /* __AL_SRDS__ */ + +/** @} end of SERDES group */ + diff --git a/al_hal_serdes_25g_internal_regs.h b/al_hal_serdes_25g_internal_regs.h new file mode 100644 index 00000000000..ff48f98a940 --- /dev/null +++ b/al_hal_serdes_25g_internal_regs.h @@ -0,0 +1,4205 @@ +/******************************************************************************* +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. + +*******************************************************************************/ +#ifndef _AL_SERDES_25G_INTERNAL_REGS_H_ +#define _AL_SERDES_25G_INTERNAL_REGS_H_ + +#ifdef _cplusplus +extern "C" { +#endif + +/******************************************************************************* + * TOP Registers + ******************************************************************************/ +#define SERDES_25G_TOP_BASE 0x00 +#define SERDES_25G_TOP_SIZE 0x200 + +#define SERDES_25G_TOP_PHY_STAT0_ADDR 0x00 +#define SERDES_25G_TOP_PHY_CTRL0_ADDR 0x08 +#define SERDES_25G_TOP_PHY_CFG0_ADDR 0x09 +#define SERDES_25G_TOP_AFE_CALCOMP_CTRL0_ADDR 0x30 +#define SERDES_25G_TOP_AFE_CALCOMP_CTRL1_ADDR 0x31 +#define SERDES_25G_TOP_AFE_CALCOMP_CTRL2_ADDR 0x32 +#define SERDES_25G_TOP_AFE_CALCOMP_STATUS0_ADDR 0x33 +#define SERDES_25G_TOP_AFE_ATEST_CTRL0_ADDR 0x38 +#define SERDES_25G_TOP_AFE_ATEST_CTRL1_ADDR 0x39 +#define SERDES_25G_TOP_RESET_CTRL_CM0_ADDR 0x50 +#define SERDES_25G_TOP_RESET_CTRL_LN0_ADDR 0x54 +#define SERDES_25G_TOP_RESET_CTRL_LN1_ADDR 0x55 +#define SERDES_25G_TOP_RESET_CTRL_LN2_ADDR 0x56 +#define SERDES_25G_TOP_RESET_CTRL_LN3_ADDR 0x57 +#define SERDES_25G_TOP_CLOCK_AFE_CM0_CLK_REF_ADDR 0x100 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_REF_ADDR 0x101 +#define SERDES_25G_TOP_CLOCK_CM0_REFCLK_ADDR 0x102 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_SSC_GEN_ADDR 0x103 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_GCFSM_ADDR 0x104 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMPLL_VCO_ADDR 0x105 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMU_ADDR 0x106 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMU_CTRL1_ADDR 0x107 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMUDIV_ADDR 0x108 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMUDIV_CTRL1_ADDR 0x109 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_FRACN_FBK_ADDR 0x10A +#define SERDES_25G_TOP_CLOCK_LN0_CLK_TX_ADDR 0x110 +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RX_ADDR 0x111 +#define SERDES_25G_TOP_CLOCK_LN0_CLK_RX_ADDR 0x112 +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RXDIV_CORE_ADDR 0x113 +#define SERDES_25G_TOP_CLOCK_LN1_CLK_TX_ADDR 0x118 +#define SERDES_25G_TOP_CLOCK_AFE_LN1_CLK_RX_ADDR 0x119 +#define SERDES_25G_TOP_CLOCK_LN1_CLK_RX_ADDR 0x11A +#define SERDES_25G_TOP_CLOCK_AFE_LN1_CLK_RXDIV_CORE_ADDR 0x11B +#define SERDES_25G_TOP_CLOCK_LN2_CLK_TX_ADDR 0x120 +#define SERDES_25G_TOP_CLOCK_AFE_LN2_CLK_RX_ADDR 0x121 +#define SERDES_25G_TOP_CLOCK_LN2_CLK_RX_ADDR 0x122 +#define SERDES_25G_TOP_CLOCK_AFE_LN2_CLK_RXDIV_CORE_ADDR 0x123 +#define SERDES_25G_TOP_CLOCK_LN3_CLK_TX_ADDR 0x128 +#define SERDES_25G_TOP_CLOCK_AFE_LN3_CLK_RX_ADDR 0x129 +#define SERDES_25G_TOP_CLOCK_LN3_CLK_RX_ADDR 0x12A +#define SERDES_25G_TOP_CLOCK_AFE_LN3_CLK_RXDIV_CORE_ADDR 0x12B +#define SERDES_25G_TOP_LOS_INT_EN_CTRL_ADDR 0x130 +#define SERDES_25G_TOP_INT0_STATUS_ADDR 0x131 +#define SERDES_25G_TOP_REGBUS_TIMER_ADDR 0x170 +#define SERDES_25G_TOP_ERR_CTRL0_ADDR 0x180 +#define SERDES_25G_TOP_ERR_CTRL1_ADDR 0x181 +#define SERDES_25G_TOP_ERR_CTRL2_ADDR 0x182 +#define SERDES_25G_TOP_ERR_STATUS0_ADDR 0x185 +#define SERDES_25G_TOP_REGBUS_ERR_INFO_CTRL_ADDR 0x187 +#define SERDES_25G_TOP_REGBUS_ERR_INFO_STATUS0_ADDR 0x188 +#define SERDES_25G_TOP_REGBUS_ERR_INFO_STATUS1_ADDR 0x189 +#define SERDES_25G_TOP_REGBUS_ERR_INFO_STATUS2_ADDR 0x18A +#define SERDES_25G_TOP_REGBUS_ERR_INFO_STATUS3_ADDR 0x18B +#define SERDES_25G_TOP_REGBUS_ERR_INFO_STATUS4_ADDR 0x18C +#define SERDES_25G_TOP_TBUS_ADDR_7_0_ADDR 0x1A0 +#define SERDES_25G_TOP_TBUS_ADDR_15_8_ADDR 0x1A1 +#define SERDES_25G_TOP_TBUS_CTRL0_ADDR 0x1A2 +#define SERDES_25G_TOP_TBUS_CTRL1_ADDR 0x1A3 +#define SERDES_25G_TOP_TBUS_DATA_7_0_ADDR 0x1B0 +#define SERDES_25G_TOP_TBUS_DATA_11_8_ADDR 0x1B1 +#define SERDES_25G_TOP_SIM_CTRL_ADDR 0x1C0 + +/******************************************************************************* + * masks and shifts + ******************************************************************************/ +#define SERDES_25G_TOP_PHY_STAT0_PHY_CTRL_CFG_MASK 0x0F +#define SERDES_25G_TOP_PHY_STAT0_PHY_CTRL_CFG_SHIFT 0 + +#define SERDES_25G_TOP_PHY_CTRL0_PHY_CTRL_CFG_OVR_VAL_MASK 0x0F +#define SERDES_25G_TOP_PHY_CTRL0_PHY_CTRL_CFG_OVR_VAL_SHIFT 0 + +#define SERDES_25G_TOP_PHY_CTRL0_OVR_EN_MASK 0x80 +#define SERDES_25G_TOP_PHY_CTRL0_OVR_EN_SHIFT 7 + +#define SERDES_25G_TOP_PHY_CFG0_CPU_CLK_FREQ_MASK 0xFF +#define SERDES_25G_TOP_PHY_CFG0_CPU_CLK_FREQ_SHIFT 0 + +#define SERDES_25G_TOP_AFE_CALCOMP_CTRL0_ACAL_EN_MASK 0x0F +#define SERDES_25G_TOP_AFE_CALCOMP_CTRL0_ACAL_EN_SHIFT 0 + +#define SERDES_25G_TOP_AFE_CALCOMP_CTRL1_ACAL_SEL_MASK 0x1F +#define SERDES_25G_TOP_AFE_CALCOMP_CTRL1_ACAL_SEL_SHIFT 0 + +#define SERDES_25G_TOP_AFE_CALCOMP_CTRL2_CALCOMP_EN_MASK 0x01 +#define SERDES_25G_TOP_AFE_CALCOMP_CTRL2_CALCOMP_EN_SHIFT 0 + +#define SERDES_25G_TOP_AFE_CALCOMP_CTRL2_CALCOMP_MUTE_MASK 0x02 +#define SERDES_25G_TOP_AFE_CALCOMP_CTRL2_CALCOMP_MUTE_SHIFT 1 + +#define SERDES_25G_TOP_AFE_CALCOMP_CTRL2_CALCOMP_SEL_MASK 0x04 +#define SERDES_25G_TOP_AFE_CALCOMP_CTRL2_CALCOMP_SEL_SHIFT 2 + +#define SERDES_25G_TOP_AFE_CALCOMP_CTRL2_CALCOMP_SPARE_MASK 0xF0 +#define SERDES_25G_TOP_AFE_CALCOMP_CTRL2_CALCOMP_SPARE_SHIFT 4 + +#define SERDES_25G_TOP_AFE_CALCOMP_STATUS0_CALCOMP_OUT_MASK 0x01 +#define SERDES_25G_TOP_AFE_CALCOMP_STATUS0_CALCOMP_OUT_SHIFT 0 + +#define SERDES_25G_TOP_AFE_ATEST_CTRL0_ATEST_EN_MASK 0x0F +#define SERDES_25G_TOP_AFE_ATEST_CTRL0_ATEST_EN_SHIFT 0 + +#define SERDES_25G_TOP_AFE_ATEST_CTRL1_ATEST_SEL_MASK 0x3F +#define SERDES_25G_TOP_AFE_ATEST_CTRL1_ATEST_SEL_SHIFT 0 + +#define SERDES_25G_TOP_RESET_CTRL_CM0_CORE_SW_RESET_MASK 0x01 +#define SERDES_25G_TOP_RESET_CTRL_CM0_CORE_SW_RESET_SHIFT 0 + +#define SERDES_25G_TOP_RESET_CTRL_CM0_REG_SW_RESET_MASK 0x02 +#define SERDES_25G_TOP_RESET_CTRL_CM0_REG_SW_RESET_SHIFT 1 + +#define SERDES_25G_TOP_RESET_CTRL_CM0_SUBCORE_SW_RESET_MASK 0x04 +#define SERDES_25G_TOP_RESET_CTRL_CM0_SUBCORE_SW_RESET_SHIFT 2 + +#define SERDES_25G_TOP_RESET_CTRL_CM0_CAL_SW_RESET_MASK 0x40 +#define SERDES_25G_TOP_RESET_CTRL_CM0_CAL_SW_RESET_SHIFT 6 + +#define SERDES_25G_TOP_RESET_CTRL_LN0_CORE_SW_RESET_MASK 0x01 +#define SERDES_25G_TOP_RESET_CTRL_LN0_CORE_SW_RESET_SHIFT 0 + +#define SERDES_25G_TOP_RESET_CTRL_LN0_REG_SW_RESET_MASK 0x02 +#define SERDES_25G_TOP_RESET_CTRL_LN0_REG_SW_RESET_SHIFT 1 + +#define SERDES_25G_TOP_RESET_CTRL_LN0_SUBCORE_SW_RESET_MASK 0x04 +#define SERDES_25G_TOP_RESET_CTRL_LN0_SUBCORE_SW_RESET_SHIFT 2 + +#define SERDES_25G_TOP_RESET_CTRL_LN0_TXDP_SW_RESET_MASK 0x08 +#define SERDES_25G_TOP_RESET_CTRL_LN0_TXDP_SW_RESET_SHIFT 3 + +#define SERDES_25G_TOP_RESET_CTRL_LN0_RXDP_SW_RESET_MASK 0x10 +#define SERDES_25G_TOP_RESET_CTRL_LN0_RXDP_SW_RESET_SHIFT 4 + +#define SERDES_25G_TOP_RESET_CTRL_LN0_LOS_SW_RESET_MASK 0x20 +#define SERDES_25G_TOP_RESET_CTRL_LN0_LOS_SW_RESET_SHIFT 5 + +#define SERDES_25G_TOP_RESET_CTRL_LN0_CAL_SW_RESET_MASK 0x40 +#define SERDES_25G_TOP_RESET_CTRL_LN0_CAL_SW_RESET_SHIFT 6 + +#define SERDES_25G_TOP_RESET_CTRL_LN1_CORE_SW_RESET_MASK 0x01 +#define SERDES_25G_TOP_RESET_CTRL_LN1_CORE_SW_RESET_SHIFT 0 + +#define SERDES_25G_TOP_RESET_CTRL_LN1_REG_SW_RESET_MASK 0x02 +#define SERDES_25G_TOP_RESET_CTRL_LN1_REG_SW_RESET_SHIFT 1 + +#define SERDES_25G_TOP_RESET_CTRL_LN1_SUBCORE_SW_RESET_MASK 0x04 +#define SERDES_25G_TOP_RESET_CTRL_LN1_SUBCORE_SW_RESET_SHIFT 2 + +#define SERDES_25G_TOP_RESET_CTRL_LN1_TXDP_SW_RESET_MASK 0x08 +#define SERDES_25G_TOP_RESET_CTRL_LN1_TXDP_SW_RESET_SHIFT 3 + +#define SERDES_25G_TOP_RESET_CTRL_LN1_RXDP_SW_RESET_MASK 0x10 +#define SERDES_25G_TOP_RESET_CTRL_LN1_RXDP_SW_RESET_SHIFT 4 + +#define SERDES_25G_TOP_RESET_CTRL_LN1_LOS_SW_RESET_MASK 0x20 +#define SERDES_25G_TOP_RESET_CTRL_LN1_LOS_SW_RESET_SHIFT 5 + +#define SERDES_25G_TOP_RESET_CTRL_LN1_CAL_SW_RESET_MASK 0x40 +#define SERDES_25G_TOP_RESET_CTRL_LN1_CAL_SW_RESET_SHIFT 6 + +#define SERDES_25G_TOP_RESET_CTRL_LN2_CORE_SW_RESET_MASK 0x01 +#define SERDES_25G_TOP_RESET_CTRL_LN2_CORE_SW_RESET_SHIFT 0 + +#define SERDES_25G_TOP_RESET_CTRL_LN2_REG_SW_RESET_MASK 0x02 +#define SERDES_25G_TOP_RESET_CTRL_LN2_REG_SW_RESET_SHIFT 1 + +#define SERDES_25G_TOP_RESET_CTRL_LN2_SUBCORE_SW_RESET_MASK 0x04 +#define SERDES_25G_TOP_RESET_CTRL_LN2_SUBCORE_SW_RESET_SHIFT 2 + +#define SERDES_25G_TOP_RESET_CTRL_LN2_TXDP_SW_RESET_MASK 0x08 +#define SERDES_25G_TOP_RESET_CTRL_LN2_TXDP_SW_RESET_SHIFT 3 + +#define SERDES_25G_TOP_RESET_CTRL_LN2_RXDP_SW_RESET_MASK 0x10 +#define SERDES_25G_TOP_RESET_CTRL_LN2_RXDP_SW_RESET_SHIFT 4 + +#define SERDES_25G_TOP_RESET_CTRL_LN2_LOS_SW_RESET_MASK 0x20 +#define SERDES_25G_TOP_RESET_CTRL_LN2_LOS_SW_RESET_SHIFT 5 + +#define SERDES_25G_TOP_RESET_CTRL_LN2_CAL_SW_RESET_MASK 0x40 +#define SERDES_25G_TOP_RESET_CTRL_LN2_CAL_SW_RESET_SHIFT 6 + +#define SERDES_25G_TOP_RESET_CTRL_LN3_CORE_SW_RESET_MASK 0x01 +#define SERDES_25G_TOP_RESET_CTRL_LN3_CORE_SW_RESET_SHIFT 0 + +#define SERDES_25G_TOP_RESET_CTRL_LN3_REG_SW_RESET_MASK 0x02 +#define SERDES_25G_TOP_RESET_CTRL_LN3_REG_SW_RESET_SHIFT 1 + +#define SERDES_25G_TOP_RESET_CTRL_LN3_SUBCORE_SW_RESET_MASK 0x04 +#define SERDES_25G_TOP_RESET_CTRL_LN3_SUBCORE_SW_RESET_SHIFT 2 + +#define SERDES_25G_TOP_RESET_CTRL_LN3_TXDP_SW_RESET_MASK 0x08 +#define SERDES_25G_TOP_RESET_CTRL_LN3_TXDP_SW_RESET_SHIFT 3 + +#define SERDES_25G_TOP_RESET_CTRL_LN3_RXDP_SW_RESET_MASK 0x10 +#define SERDES_25G_TOP_RESET_CTRL_LN3_RXDP_SW_RESET_SHIFT 4 + +#define SERDES_25G_TOP_RESET_CTRL_LN3_LOS_SW_RESET_MASK 0x20 +#define SERDES_25G_TOP_RESET_CTRL_LN3_LOS_SW_RESET_SHIFT 5 + +#define SERDES_25G_TOP_RESET_CTRL_LN3_CAL_SW_RESET_MASK 0x40 +#define SERDES_25G_TOP_RESET_CTRL_LN3_CAL_SW_RESET_SHIFT 6 + +#define SERDES_25G_TOP_CLOCK_AFE_CM0_CLK_REF_CTRL_SRC_SEL_MASK 0x01 +#define SERDES_25G_TOP_CLOCK_AFE_CM0_CLK_REF_CTRL_SRC_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_AFE_CM0_CLK_REF_STAT_DEFAULT_CLK_EN_MASK 0x02 +#define SERDES_25G_TOP_CLOCK_AFE_CM0_CLK_REF_STAT_DEFAULT_CLK_EN_SHIFT 1 + +#define SERDES_25G_TOP_CLOCK_AFE_CM0_CLK_REF_STAT_REF_CLK_EN_MASK 0x04 +#define SERDES_25G_TOP_CLOCK_AFE_CM0_CLK_REF_STAT_REF_CLK_EN_SHIFT 2 + +#define SERDES_25G_TOP_CLOCK_AFE_CM0_CLK_REF_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_AFE_CM0_CLK_REF_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_REF_CTRL_DIV_SEL_MASK 0x01 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_REF_CTRL_DIV_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_REF_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_REF_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_CM0_REFCLK_CTRL_CG_EN_MASK 0x01 +#define SERDES_25G_TOP_CLOCK_CM0_REFCLK_CTRL_CG_EN_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_CM0_REFCLK_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_CM0_REFCLK_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_SSC_GEN_CTRL_DIV_SEL_MASK 0x07 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_SSC_GEN_CTRL_DIV_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_SSC_GEN_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_SSC_GEN_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_GCFSM_CTRL_DIV_SEL_MASK 0x07 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_GCFSM_CTRL_DIV_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_GCFSM_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_GCFSM_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMPLL_VCO_CTRL_DIV_SEL_MASK 0x01 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMPLL_VCO_CTRL_DIV_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMPLL_VCO_CTRL_CG_EN_MASK 0x02 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMPLL_VCO_CTRL_CG_EN_SHIFT 1 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMPLL_VCO_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMPLL_VCO_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMU_CTRL_SRC_SEL_MASK 0x01 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMU_CTRL_SRC_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMU_STAT_DEFAULT_CLK_EN_MASK 0x02 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMU_STAT_DEFAULT_CLK_EN_SHIFT 1 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMU_STAT_CMU_CLK_EN_MASK 0x04 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMU_STAT_CMU_CLK_EN_SHIFT 2 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMU_CTRL_DIV_SEL_MASK 0xF8 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMU_CTRL_DIV_SEL_SHIFT 3 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMU_CTRL1_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMU_CTRL1_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMUDIV_CTRL_SRC_SEL_MASK 0x01 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMUDIV_CTRL_SRC_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMUDIV_STAT_DEFAULT_CLK_EN_MASK 0x02 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMUDIV_STAT_DEFAULT_CLK_EN_SHIFT 1 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMUDIV_STAT_CMUDIV_CLK_EN_MASK 0x04 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMUDIV_STAT_CMUDIV_CLK_EN_SHIFT 2 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMUDIV_CTRL_DIV_SEL_MASK 0xF8 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMUDIV_CTRL_DIV_SEL_SHIFT 3 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMUDIV_CTRL1_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_CMUDIV_CTRL1_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_FRACN_FBK_CTRL_FRCDIV_MODE_EN_MASK 0x01 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_FRACN_FBK_CTRL_FRCDIV_MODE_EN_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_FRACN_FBK_CTRL_SRC_SEL_MASK 0x06 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_FRACN_FBK_CTRL_SRC_SEL_SHIFT 1 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_FRACN_FBK_CTRL_DIV_SEL_MASK 0x08 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_FRACN_FBK_CTRL_DIV_SEL_SHIFT 3 + +#define SERDES_25G_TOP_CLOCK_CM0_CLK_FRACN_FBK_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_CM0_CLK_FRACN_FBK_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_LN0_CLK_TX_CTRL_SRC_SEL_MASK 0x03 +#define SERDES_25G_TOP_CLOCK_LN0_CLK_TX_CTRL_SRC_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_LN0_CLK_TX_CTRL_DIV_SEL_MASK 0x04 +#define SERDES_25G_TOP_CLOCK_LN0_CLK_TX_CTRL_DIV_SEL_SHIFT 2 + +#define SERDES_25G_TOP_CLOCK_LN0_CLK_TX_CTRL_BIST_CG_EN_MASK 0x10 +#define SERDES_25G_TOP_CLOCK_LN0_CLK_TX_CTRL_BIST_CG_EN_SHIFT 4 + +#define SERDES_25G_TOP_CLOCK_LN0_CLK_TX_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_LN0_CLK_TX_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RX_CTRL_SRC_SEL_MASK 0x01 +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RX_CTRL_SRC_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RX_STAT_DEFAULT_CLK_EN_MASK 0x02 +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RX_STAT_DEFAULT_CLK_EN_SHIFT 1 + +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RX_STAT_RX_CLK_EN_MASK 0x04 +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RX_STAT_RX_CLK_EN_SHIFT 2 + +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RX_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RX_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_LN0_CLK_RX_CTRL_SRC_SEL_MASK 0x03 +#define SERDES_25G_TOP_CLOCK_LN0_CLK_RX_CTRL_SRC_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_LN0_CLK_RX_CTRL_CG_EN_MASK 0x10 +#define SERDES_25G_TOP_CLOCK_LN0_CLK_RX_CTRL_CG_EN_SHIFT 4 + +#define SERDES_25G_TOP_CLOCK_LN0_CLK_RX_CTRL_BIST_CG_EN_MASK 0x20 +#define SERDES_25G_TOP_CLOCK_LN0_CLK_RX_CTRL_BIST_CG_EN_SHIFT 5 + +#define SERDES_25G_TOP_CLOCK_LN0_CLK_RX_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_LN0_CLK_RX_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RXDIV_CORE_CTRL_SRC_SEL_MASK 0x01 +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RXDIV_CORE_CTRL_SRC_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RXDIV_CORE_STAT_DEFAULT_CLK_EN_MASK 0x02 +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RXDIV_CORE_STAT_DEFAULT_CLK_EN_SHIFT 1 + +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RXDIV_CORE_STAT_RX_CLKDIV_EN_MASK 0x04 +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RXDIV_CORE_STAT_RX_CLKDIV_EN_SHIFT 2 + +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RXDIV_CORE_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_AFE_LN0_CLK_RXDIV_CORE_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_LN1_CLK_TX_CTRL_SRC_SEL_MASK 0x03 +#define SERDES_25G_TOP_CLOCK_LN1_CLK_TX_CTRL_SRC_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_LN1_CLK_TX_CTRL_DIV_SEL_MASK 0x04 +#define SERDES_25G_TOP_CLOCK_LN1_CLK_TX_CTRL_DIV_SEL_SHIFT 2 + +#define SERDES_25G_TOP_CLOCK_LN1_CLK_TX_CTRL_BIST_CG_EN_MASK 0x10 +#define SERDES_25G_TOP_CLOCK_LN1_CLK_TX_CTRL_BIST_CG_EN_SHIFT 4 + +#define SERDES_25G_TOP_CLOCK_LN1_CLK_TX_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_LN1_CLK_TX_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_AFE_LN1_CLK_RX_CTRL_SRC_SEL_MASK 0x01 +#define SERDES_25G_TOP_CLOCK_AFE_LN1_CLK_RX_CTRL_SRC_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_AFE_LN1_CLK_RX_STAT_DEFAULT_CLK_EN_MASK 0x02 +#define SERDES_25G_TOP_CLOCK_AFE_LN1_CLK_RX_STAT_DEFAULT_CLK_EN_SHIFT 1 + +#define SERDES_25G_TOP_CLOCK_AFE_LN1_CLK_RX_STAT_RX_CLK_EN_MASK 0x04 +#define SERDES_25G_TOP_CLOCK_AFE_LN1_CLK_RX_STAT_RX_CLK_EN_SHIFT 2 + +#define SERDES_25G_TOP_CLOCK_AFE_LN1_CLK_RX_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_AFE_LN1_CLK_RX_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_LN1_CLK_RX_CTRL_SRC_SEL_MASK 0x03 +#define SERDES_25G_TOP_CLOCK_LN1_CLK_RX_CTRL_SRC_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_LN1_CLK_RX_CTRL_CG_EN_MASK 0x10 +#define SERDES_25G_TOP_CLOCK_LN1_CLK_RX_CTRL_CG_EN_SHIFT 4 + +#define SERDES_25G_TOP_CLOCK_LN1_CLK_RX_CTRL_BIST_CG_EN_MASK 0x20 +#define SERDES_25G_TOP_CLOCK_LN1_CLK_RX_CTRL_BIST_CG_EN_SHIFT 5 + +#define SERDES_25G_TOP_CLOCK_LN1_CLK_RX_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_LN1_CLK_RX_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_LN2_CLK_TX_CTRL_SRC_SEL_MASK 0x03 +#define SERDES_25G_TOP_CLOCK_LN2_CLK_TX_CTRL_SRC_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_LN2_CLK_TX_CTRL_DIV_SEL_MASK 0x04 +#define SERDES_25G_TOP_CLOCK_LN2_CLK_TX_CTRL_DIV_SEL_SHIFT 2 + +#define SERDES_25G_TOP_CLOCK_LN2_CLK_TX_CTRL_BIST_CG_EN_MASK 0x10 +#define SERDES_25G_TOP_CLOCK_LN2_CLK_TX_CTRL_BIST_CG_EN_SHIFT 4 + +#define SERDES_25G_TOP_CLOCK_LN2_CLK_TX_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_LN2_CLK_TX_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_AFE_LN2_CLK_RX_CTRL_SRC_SEL_MASK 0x01 +#define SERDES_25G_TOP_CLOCK_AFE_LN2_CLK_RX_CTRL_SRC_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_AFE_LN2_CLK_RX_STAT_DEFAULT_CLK_EN_MASK 0x02 +#define SERDES_25G_TOP_CLOCK_AFE_LN2_CLK_RX_STAT_DEFAULT_CLK_EN_SHIFT 1 + +#define SERDES_25G_TOP_CLOCK_AFE_LN2_CLK_RX_STAT_RX_CLK_EN_MASK 0x04 +#define SERDES_25G_TOP_CLOCK_AFE_LN2_CLK_RX_STAT_RX_CLK_EN_SHIFT 2 + +#define SERDES_25G_TOP_CLOCK_AFE_LN2_CLK_RX_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_AFE_LN2_CLK_RX_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_LN2_CLK_RX_CTRL_SRC_SEL_MASK 0x03 +#define SERDES_25G_TOP_CLOCK_LN2_CLK_RX_CTRL_SRC_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_LN2_CLK_RX_CTRL_CG_EN_MASK 0x10 +#define SERDES_25G_TOP_CLOCK_LN2_CLK_RX_CTRL_CG_EN_SHIFT 4 + +#define SERDES_25G_TOP_CLOCK_LN2_CLK_RX_CTRL_BIST_CG_EN_MASK 0x20 +#define SERDES_25G_TOP_CLOCK_LN2_CLK_RX_CTRL_BIST_CG_EN_SHIFT 5 + +#define SERDES_25G_TOP_CLOCK_LN2_CLK_RX_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_LN2_CLK_RX_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_LN3_CLK_TX_CTRL_SRC_SEL_MASK 0x03 +#define SERDES_25G_TOP_CLOCK_LN3_CLK_TX_CTRL_SRC_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_LN3_CLK_TX_CTRL_DIV_SEL_MASK 0x04 +#define SERDES_25G_TOP_CLOCK_LN3_CLK_TX_CTRL_DIV_SEL_SHIFT 2 + +#define SERDES_25G_TOP_CLOCK_LN3_CLK_TX_CTRL_BIST_CG_EN_MASK 0x10 +#define SERDES_25G_TOP_CLOCK_LN3_CLK_TX_CTRL_BIST_CG_EN_SHIFT 4 + +#define SERDES_25G_TOP_CLOCK_LN3_CLK_TX_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_LN3_CLK_TX_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_AFE_LN3_CLK_RX_CTRL_SRC_SEL_MASK 0x01 +#define SERDES_25G_TOP_CLOCK_AFE_LN3_CLK_RX_CTRL_SRC_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_AFE_LN3_CLK_RX_STAT_DEFAULT_CLK_EN_MASK 0x02 +#define SERDES_25G_TOP_CLOCK_AFE_LN3_CLK_RX_STAT_DEFAULT_CLK_EN_SHIFT 1 + +#define SERDES_25G_TOP_CLOCK_AFE_LN3_CLK_RX_STAT_RX_CLK_EN_MASK 0x04 +#define SERDES_25G_TOP_CLOCK_AFE_LN3_CLK_RX_STAT_RX_CLK_EN_SHIFT 2 + +#define SERDES_25G_TOP_CLOCK_AFE_LN3_CLK_RX_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_AFE_LN3_CLK_RX_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_CLOCK_LN3_CLK_RX_CTRL_SRC_SEL_MASK 0x03 +#define SERDES_25G_TOP_CLOCK_LN3_CLK_RX_CTRL_SRC_SEL_SHIFT 0 + +#define SERDES_25G_TOP_CLOCK_LN3_CLK_RX_CTRL_CG_EN_MASK 0x10 +#define SERDES_25G_TOP_CLOCK_LN3_CLK_RX_CTRL_CG_EN_SHIFT 4 + +#define SERDES_25G_TOP_CLOCK_LN3_CLK_RX_CTRL_BIST_CG_EN_MASK 0x20 +#define SERDES_25G_TOP_CLOCK_LN3_CLK_RX_CTRL_BIST_CG_EN_SHIFT 5 + +#define SERDES_25G_TOP_CLOCK_LN3_CLK_RX_CTRL_TBUS_OUT_CG_EN_MASK 0x80 +#define SERDES_25G_TOP_CLOCK_LN3_CLK_RX_CTRL_TBUS_OUT_CG_EN_SHIFT 7 + +#define SERDES_25G_TOP_LOS_INT_EN_CTRL_LN0_MASK 0x01 +#define SERDES_25G_TOP_LOS_INT_EN_CTRL_LN0_SHIFT 0 + +#define SERDES_25G_TOP_LOS_INT_EN_CTRL_LN1_MASK 0x02 +#define SERDES_25G_TOP_LOS_INT_EN_CTRL_LN1_SHIFT 1 + +#define SERDES_25G_TOP_LOS_INT_EN_CTRL_LN2_MASK 0x04 +#define SERDES_25G_TOP_LOS_INT_EN_CTRL_LN2_SHIFT 2 + +#define SERDES_25G_TOP_LOS_INT_EN_CTRL_LN3_MASK 0x08 +#define SERDES_25G_TOP_LOS_INT_EN_CTRL_LN3_SHIFT 3 + +#define SERDES_25G_TOP_REGBUS_TIMER_LOAD_VAL_MASK 0xFF +#define SERDES_25G_TOP_REGBUS_TIMER_LOAD_VAL_SHIFT 0 + +#define SERDES_25G_TOP_ERR_CTRL0_ERR_MASK 0x01 +#define SERDES_25G_TOP_ERR_CTRL0_ERR_SHIFT 0 + +#define SERDES_25G_TOP_ERR_CTRL1_ERR_CODE_7_0_MASK 0xFF +#define SERDES_25G_TOP_ERR_CTRL1_ERR_CODE_7_0_SHIFT 0 + +#define SERDES_25G_TOP_ERR_CTRL2_ERR_CODE_15_8_MASK 0xFF +#define SERDES_25G_TOP_ERR_CTRL2_ERR_CODE_15_8_SHIFT 0 + +#define SERDES_25G_TOP_ERR_STATUS0_REGBUS_ERR_MASK 0x01 +#define SERDES_25G_TOP_ERR_STATUS0_REGBUS_ERR_SHIFT 0 + +#define SERDES_25G_TOP_REGBUS_ERR_INFO_CTRL_CLR_MASK 0x01 +#define SERDES_25G_TOP_REGBUS_ERR_INFO_CTRL_CLR_SHIFT 0 + +#define SERDES_25G_TOP_REGBUS_ERR_INFO_STATUS0_ERR_TYPE_MASK 0x03 +#define SERDES_25G_TOP_REGBUS_ERR_INFO_STATUS0_ERR_TYPE_SHIFT 0 + +#define SERDES_25G_TOP_REGBUS_ERR_INFO_STATUS0_TRANSFER_RW_MASK 0x04 +#define SERDES_25G_TOP_REGBUS_ERR_INFO_STATUS0_TRANSFER_RW_SHIFT 2 + +#define SERDES_25G_TOP_REGBUS_ERR_INFO_STATUS1_TRANSFER_ADDR_LSB_MASK 0xFF +#define SERDES_25G_TOP_REGBUS_ERR_INFO_STATUS1_TRANSFER_ADDR_LSB_SHIFT 0 + +#define SERDES_25G_TOP_REGBUS_ERR_INFO_STATUS2_TRANSFER_ADDR_MSB_MASK 0x7F +#define SERDES_25G_TOP_REGBUS_ERR_INFO_STATUS2_TRANSFER_ADDR_MSB_SHIFT 0 + +#define SERDES_25G_TOP_REGBUS_ERR_INFO_STATUS3_TRANSFER_WD_MASK 0xFF +#define SERDES_25G_TOP_REGBUS_ERR_INFO_STATUS3_TRANSFER_WD_SHIFT 0 + +#define SERDES_25G_TOP_REGBUS_ERR_INFO_STATUS4_TRANSFER_WR_BIT_EN_MASK 0xFF +#define SERDES_25G_TOP_REGBUS_ERR_INFO_STATUS4_TRANSFER_WR_BIT_EN_SHIFT 0 + +#define SERDES_25G_TOP_TBUS_ADDR_7_0_MASK 0xFF +#define SERDES_25G_TOP_TBUS_ADDR_7_0_SHIFT 0 + +#define SERDES_25G_TOP_TBUS_ADDR_15_8_MASK 0xFF +#define SERDES_25G_TOP_TBUS_ADDR_15_8_SHIFT 0 + +#define SERDES_25G_TOP_TBUS_CTRL0_CLOCK_GATE0_MASK 0xFF +#define SERDES_25G_TOP_TBUS_CTRL0_CLOCK_GATE0_SHIFT 0 + +#define SERDES_25G_TOP_TBUS_CTRL1_CLOCK_GATE1_MASK 0xFF +#define SERDES_25G_TOP_TBUS_CTRL1_CLOCK_GATE1_SHIFT 0 + +#define SERDES_25G_TOP_TBUS_DATA_7_0_MASK 0xFF +#define SERDES_25G_TOP_TBUS_DATA_7_0_SHIFT 0 + +#define SERDES_25G_TOP_TBUS_DATA_11_8_MASK 0x0F +#define SERDES_25G_TOP_TBUS_DATA_11_8_SHIFT 0 + +/*********************************** Mailbox **********************************/ +#define SERDES_25G_TOP_MB_BASE 0x200 + +#define SERDES_25G_TOP_CMD_ADDR (SERDES_25G_TOP_MB_BASE + 0x00) +#define SERDES_25G_TOP_CMD_FLAG_ADDR (SERDES_25G_TOP_MB_BASE + 0x02) +#define SERDES_25G_TOP_CMD_DATA0_ADDR (SERDES_25G_TOP_MB_BASE + 0x03) +#define SERDES_25G_TOP_CMD_DATA1_ADDR (SERDES_25G_TOP_MB_BASE + 0x04) +#define SERDES_25G_TOP_CMD_DATA2_ADDR (SERDES_25G_TOP_MB_BASE + 0x05) +#define SERDES_25G_TOP_CMD_DATA3_ADDR (SERDES_25G_TOP_MB_BASE + 0x06) +#define SERDES_25G_TOP_CMD_DATA4_ADDR (SERDES_25G_TOP_MB_BASE + 0x07) +#define SERDES_25G_TOP_CMD_DATA5_ADDR (SERDES_25G_TOP_MB_BASE + 0x08) +#define SERDES_25G_TOP_CMD_DATA6_ADDR (SERDES_25G_TOP_MB_BASE + 0x09) +#define SERDES_25G_TOP_CMD_DATA7_ADDR (SERDES_25G_TOP_MB_BASE + 0x0A) +#define SERDES_25G_TOP_RSP_ADDR (SERDES_25G_TOP_MB_BASE + 0x10) +#define SERDES_25G_TOP_RSP_FLAG_ADDR (SERDES_25G_TOP_MB_BASE + 0x12) +#define SERDES_25G_TOP_RSP_DATA0_ADDR (SERDES_25G_TOP_MB_BASE + 0x13) +#define SERDES_25G_TOP_RSP_DATA1_ADDR (SERDES_25G_TOP_MB_BASE + 0x14) +#define SERDES_25G_TOP_RSP_DATA2_ADDR (SERDES_25G_TOP_MB_BASE + 0x15) +#define SERDES_25G_TOP_RSP_DATA3_ADDR (SERDES_25G_TOP_MB_BASE + 0x16) +#define SERDES_25G_TOP_RSP_DATA4_ADDR (SERDES_25G_TOP_MB_BASE + 0x17) +#define SERDES_25G_TOP_RSP_DATA5_ADDR (SERDES_25G_TOP_MB_BASE + 0x18) +#define SERDES_25G_TOP_RSP_DATA6_ADDR (SERDES_25G_TOP_MB_BASE + 0x19) +#define SERDES_25G_TOP_RSP_DATA7_ADDR (SERDES_25G_TOP_MB_BASE + 0x1A) +#define SERDES_25G_TOP_RSP_DATA8_ADDR (SERDES_25G_TOP_MB_BASE + 0x1B) +#define SERDES_25G_TOP_RSP_DATA9_ADDR (SERDES_25G_TOP_MB_BASE + 0x1C) +#define SERDES_25G_TOP_RSP_DATA10_ADDR (SERDES_25G_TOP_MB_BASE + 0x1D) +#define SERDES_25G_TOP_RSP_DATA11_ADDR (SERDES_25G_TOP_MB_BASE + 0x1E) +#define SERDES_25G_TOP_RSP_DATA12_ADDR (SERDES_25G_TOP_MB_BASE + 0x1F) +#define SERDES_25G_TOP_RSP_DATA13_ADDR (SERDES_25G_TOP_MB_BASE + 0x20) +#define SERDES_25G_TOP_RSP_DATA14_ADDR (SERDES_25G_TOP_MB_BASE + 0x21) +#define SERDES_25G_TOP_RSP_DATA15_ADDR (SERDES_25G_TOP_MB_BASE + 0x22) +/******************************************************************************* + * masks and shifts + ******************************************************************************/ +#define SERDES_25G_TOP_CMD_MASK 0xFF +#define SERDES_25G_TOP_CMD_SHIFT 0 + +#define SERDES_25G_TOP_CMD_FLAG_MASK 0x01 +#define SERDES_25G_TOP_CMD_FLAG_SHIFT 0 + +#define SERDES_25G_TOP_CMD_DATA0_MASK 0xFF +#define SERDES_25G_TOP_CMD_DATA0_SHIFT 0 + +#define SERDES_25G_TOP_CMD_DATA1_MASK 0xFF +#define SERDES_25G_TOP_CMD_DATA1_SHIFT 0 + +#define SERDES_25G_TOP_CMD_DATA2_MASK 0xFF +#define SERDES_25G_TOP_CMD_DATA2_SHIFT 0 + +#define SERDES_25G_TOP_CMD_DATA3_MASK 0xFF +#define SERDES_25G_TOP_CMD_DATA3_SHIFT 0 + +#define SERDES_25G_TOP_CMD_DATA4_MASK 0xFF +#define SERDES_25G_TOP_CMD_DATA4_SHIFT 0 + +#define SERDES_25G_TOP_CMD_DATA5_MASK 0xFF +#define SERDES_25G_TOP_CMD_DATA5_SHIFT 0 + +#define SERDES_25G_TOP_CMD_DATA6_MASK 0xFF +#define SERDES_25G_TOP_CMD_DATA6_SHIFT 0 + +#define SERDES_25G_TOP_CMD_DATA7_MASK 0xFF +#define SERDES_25G_TOP_CMD_DATA7_SHIFT 0 + +#define SERDES_25G_TOP_RSP_MASK 0xFF +#define SERDES_25G_TOP_RSP_SHIFT 0 + +#define SERDES_25G_TOP_RSP_FLAG_MASK 0x01 +#define SERDES_25G_TOP_RSP_FLAG_SHIFT 0 + +#define SERDES_25G_TOP_RSP_DATA0_MASK 0xFF +#define SERDES_25G_TOP_RSP_DATA0_SHIFT 0 + +#define SERDES_25G_TOP_RSP_DATA1_MASK 0xFF +#define SERDES_25G_TOP_RSP_DATA1_SHIFT 0 + +#define SERDES_25G_TOP_RSP_DATA2_MASK 0xFF +#define SERDES_25G_TOP_RSP_DATA2_SHIFT 0 + +#define SERDES_25G_TOP_RSP_DATA3_MASK 0xFF +#define SERDES_25G_TOP_RSP_DATA3_SHIFT 0 + +#define SERDES_25G_TOP_RSP_DATA4_MASK 0xFF +#define SERDES_25G_TOP_RSP_DATA4_SHIFT 0 + +#define SERDES_25G_TOP_RSP_DATA5_MASK 0xFF +#define SERDES_25G_TOP_RSP_DATA5_SHIFT 0 + +#define SERDES_25G_TOP_RSP_DATA6_MASK 0xFF +#define SERDES_25G_TOP_RSP_DATA6_SHIFT 0 + +#define SERDES_25G_TOP_RSP_DATA7_MASK 0xFF +#define SERDES_25G_TOP_RSP_DATA7_SHIFT 0 + +#define SERDES_25G_TOP_RSP_DATA8_MASK 0xFF +#define SERDES_25G_TOP_RSP_DATA8_SHIFT 0 + +#define SERDES_25G_TOP_RSP_DATA9_MASK 0xFF +#define SERDES_25G_TOP_RSP_DATA9_SHIFT 0 + +#define SERDES_25G_TOP_RSP_DATA10_MASK 0xFF +#define SERDES_25G_TOP_RSP_DATA10_SHIFT 0 + +#define SERDES_25G_TOP_RSP_DATA11_MASK 0xFF +#define SERDES_25G_TOP_RSP_DATA11_SHIFT 0 + +#define SERDES_25G_TOP_RSP_DATA12_MASK 0xFF +#define SERDES_25G_TOP_RSP_DATA12_SHIFT 0 + +#define SERDES_25G_TOP_RSP_DATA13_MASK 0xFF +#define SERDES_25G_TOP_RSP_DATA13_SHIFT 0 + +#define SERDES_25G_TOP_RSP_DATA14_MASK 0xFF +#define SERDES_25G_TOP_RSP_DATA14_SHIFT 0 + +#define SERDES_25G_TOP_RSP_DATA15_MASK 0xFF +#define SERDES_25G_TOP_RSP_DATA15_SHIFT 0 + +/******************************************************************************* + * Common Registers + ******************************************************************************/ +#define SERDES_25G_CM_BASE 0xC00 +#define SERDES_25G_CM_SIZE 0x400 + +#define SERDES_25G_CM_TOP_AFE_PD_CTRL0_ADDR 0x00 +#define SERDES_25G_CM_TOP_AFE_PD_CTRL1_ADDR 0x01 +#define SERDES_25G_CM_TOP_AFE_RST_CTRL0_ADDR 0x03 +#define SERDES_25G_CM_TOP_AFE_BIAS_CTRL0_ADDR 0x05 +#define SERDES_25G_CM_TOP_AFE_BIAS_CTRL1_ADDR 0x06 +#define SERDES_25G_CM_TOP_AFE_BIAS_CTRL2_ADDR 0x07 +#define SERDES_25G_CM_TOP_AFE_BIAS_CTRL3_ADDR 0x08 +#define SERDES_25G_CM_TOP_AFE_BIAS_CTRL4_ADDR 0x09 +#define SERDES_25G_CM_TOP_AFE_BIAS_CTRL5_ADDR 0x0A +#define SERDES_25G_CM_TOP_AFE_REG_CTRL0_ADDR 0x0C +#define SERDES_25G_CM_TOP_AFE_REFCLK_CTRL0_ADDR 0x1A +#define SERDES_25G_CM_TOP_AFE_REFCLK_CTRL1_ADDR 0x1B +#define SERDES_25G_CM_TOP_AFE_REFCLK_CTRL2_ADDR 0x1F +#define SERDES_25G_CM_TOP_AFE_CMCP_CTRL0_ADDR 0x20 +#define SERDES_25G_CM_TOP_AFE_CMCP_CTRL1_ADDR 0x21 +#define SERDES_25G_CM_TOP_AFE_CMCP_CTRL2_ADDR 0x22 +#define SERDES_25G_CM_TOP_AFE_MISC_CTRL0_ADDR 0x23 +#define SERDES_25G_CM_TOP_AFE_CMCP_STATUS_ADDR 0x24 +#define SERDES_25G_CM_TOP_AFE_TOGGLE_CTRL0_ADDR 0x25 +#define SERDES_25G_CM_TOP_AFE_TSTCLK_CTRL0_ADDR 0x28 +#define SERDES_25G_CM_TOP_AFE_TXTC_CTRL0_ADDR 0x30 +#define SERDES_25G_CM_TOP_AFE_TXTC_CTRL1_ADDR 0x31 +#define SERDES_25G_CM_TOP_AFE_TXTC_CTRL2_ADDR 0x32 +#define SERDES_25G_CM_TOP_AFE_TXTC_CTRL3_ADDR 0x33 +#define SERDES_25G_CM_TOP_AFE_TXTC_CTRL4_ADDR 0x34 +#define SERDES_25G_CM_TOP_PWR_STATE_REQ_STATUS_ADDR 0x50 +#define SERDES_25G_CM_TOP_PWR_STATE_ACK_CTRL_ADDR 0x51 +#define SERDES_25G_CM_TOP_PHY_IF_STATUS_ADDR 0x52 +#define SERDES_25G_CM_TOP_CMU_TOP_SPARE0_ADDR 0x58 +#define SERDES_25G_CM_TOP_CMU_TOP_SPARE1_ADDR 0x59 +#define SERDES_25G_CM_TOP_ERR_CTRL1_ADDR 0x80 +#define SERDES_25G_CM_TOP_ERR_CTRL2_ADDR 0x81 +#define SERDES_25G_CM_TOP_ERR_CTRL3_ADDR 0x82 +#define SERDES_25G_CM_TOP_CMU_IF_OVR_CTRL0_ADDR 0x8A +#define SERDES_25G_CM_TOP_CMU_IF_OVR_CTRL1_ADDR 0x8B +/******************************************************************************* + * masks and shifts + ******************************************************************************/ +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL0_PD_BIAS_MASK 0x01 +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL0_PD_BIAS_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL0_PD_BIAS_ICV_MASK 0x02 +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL0_PD_BIAS_ICV_SHIFT 1 + +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL0_PD_BIAS_ICC_MASK 0x04 +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL0_PD_BIAS_ICC_SHIFT 2 + +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL0_PD_BIAS_IPTAT_MASK 0x08 +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL0_PD_BIAS_IPTAT_SHIFT 3 + +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL0_PD_BIAS_SLAVE_MASK 0x10 +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL0_PD_BIAS_SLAVE_SHIFT 4 + +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL0_PD_REG_REF_MASK 0x20 +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL0_PD_REG_REF_SHIFT 5 + +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL0_PD_REFCLK_MASK 0x40 +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL0_PD_REFCLK_SHIFT 6 + +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL1_PD_CMCP_MASK 0x01 +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL1_PD_CMCP_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL1_PD_CMCP_TXCLK_LEFT_MASK 0x02 +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL1_PD_CMCP_TXCLK_LEFT_SHIFT 1 + +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL1_PD_CMCP_TXCLK_RIGHT_MASK 0x04 +#define SERDES_25G_CMU_TOP_AFE_PD_CTRL1_PD_CMCP_TXCLK_RIGHT_SHIFT 2 + +#define SERDES_25G_CMU_TOP_AFE_RST_CTRL0_RST_CMCP_CLK_CMU_N_MASK 0x01 +#define SERDES_25G_CMU_TOP_AFE_RST_CTRL0_RST_CMCP_CLK_CMU_N_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_RST_CTRL0_RST_CMCP_CLK_CMUDIV_N_MASK 0x02 +#define SERDES_25G_CMU_TOP_AFE_RST_CTRL0_RST_CMCP_CLK_CMUDIV_N_SHIFT 1 + +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL0_BIAS_ICV_TRIM_MASK 0x0F +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL0_BIAS_ICV_TRIM_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL0_BIAS_ICC_TRIM_MASK 0xF0 +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL0_BIAS_ICC_TRIM_SHIFT 4 + +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL1_BIAS_IPTAT_TRIM_MASK 0x0F +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL1_BIAS_IPTAT_TRIM_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL2_BIAS_BGSTART_BYP_MASK 0x01 +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL2_BIAS_BGSTART_BYP_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL2_BIAS_IPTATSTART_BYP_MASK 0x02 +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL2_BIAS_IPTATSTART_BYP_SHIFT 1 + +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL2_TERMCAL_EN_MASK 0x04 +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL2_TERMCAL_EN_SHIFT 2 + +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL3_TERMCAL_PTRIM_MASK 0x0F +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL3_TERMCAL_PTRIM_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL3_TERMCAL_NTRIM_MASK 0xF0 +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL3_TERMCAL_NTRIM_SHIFT 4 + +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL4_BIAS_SPARE_MASK 0x0F +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL4_BIAS_SPARE_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL5_BIAS_CALREF_TRIM_MASK 0x0F +#define SERDES_25G_CMU_TOP_AFE_BIAS_CTRL5_BIAS_CALREF_TRIM_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_REG_CTRL0_REG_REF_PASS_EN_MASK 0x01 +#define SERDES_25G_CMU_TOP_AFE_REG_CTRL0_REG_REF_PASS_EN_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_REG_CTRL0_REG_REF_TRIM_MASK 0x0E +#define SERDES_25G_CMU_TOP_AFE_REG_CTRL0_REG_REF_TRIM_SHIFT 1 + +#define SERDES_25G_CMU_TOP_AFE_REG_CTRL0_REG_REF_TRICKLE_MASK 0x30 +#define SERDES_25G_CMU_TOP_AFE_REG_CTRL0_REG_REF_TRICKLE_SHIFT 4 + +#define SERDES_25G_CMU_TOP_AFE_REFCLK_CTRL0_REFCLK_DIV_MASK 0x03 +#define SERDES_25G_CMU_TOP_AFE_REFCLK_CTRL0_REFCLK_DIV_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_REFCLK_CTRL0_REFCLK_DPL_DIV_MASK 0x0C +#define SERDES_25G_CMU_TOP_AFE_REFCLK_CTRL0_REFCLK_DPL_DIV_SHIFT 2 + +#define SERDES_25G_CMU_TOP_AFE_REFCLK_CTRL0_REFCLK_DEGLITCH_OVR_MASK 0x10 +#define SERDES_25G_CMU_TOP_AFE_REFCLK_CTRL0_REFCLK_DEGLITCH_OVR_SHIFT 4 + +#define SERDES_25G_CMU_TOP_AFE_REFCLK_CTRL1_REFCLK_TERM_MASK 0x1F +#define SERDES_25G_CMU_TOP_AFE_REFCLK_CTRL1_REFCLK_TERM_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_REFCLK_CTRL2_REFCLK_SPARE_MASK 0x0F +#define SERDES_25G_CMU_TOP_AFE_REFCLK_CTRL2_REFCLK_SPARE_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL0_CMCP_QSAMPLE_EN_MASK 0x01 +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL0_CMCP_QSAMPLE_EN_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL0_CMCP_DCD_RANGE_MASK 0x02 +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL0_CMCP_DCD_RANGE_SHIFT 1 + +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL0_CMCP_CMUCLK_DIV_MASK 0x1C +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL0_CMCP_CMUCLK_DIV_SHIFT 2 + +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL0_CMCP_CMUDIVCLK_DIV_MASK 0xE0 +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL0_CMCP_CMUDIVCLK_DIV_SHIFT 5 + +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL1_CMCP_CLKDIV_SWING_MASK 0x03 +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL1_CMCP_CLKDIV_SWING_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL1_CMCP_TXCLK_SWING_MASK 0x0C +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL1_CMCP_TXCLK_SWING_SHIFT 2 + +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL1_CMCP_CMUCLK_DIV2_BYPASS_MASK 0x10 +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL1_CMCP_CMUCLK_DIV2_BYPASS_SHIFT 4 + +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL2_CMCP_CLKDIV_OVR_MASK 0x03 +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL2_CMCP_CLKDIV_OVR_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL2_CMCP_TXCLK_BIASI_MASK 0x0C +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL2_CMCP_TXCLK_BIASI_SHIFT 2 + +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL2_CMCP_TXCLK_DIV_MASK 0x70 +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL2_CMCP_TXCLK_DIV_SHIFT 4 + +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL2_CMCP_DIV1P5_DUMMY_EN_MASK 0x80 +#define SERDES_25G_CMU_TOP_AFE_CMCP_CTRL2_CMCP_DIV1P5_DUMMY_EN_SHIFT 7 + +#define SERDES_25G_CMU_TOP_AFE_MISC_CTRL0_CMCP_SPARE_MASK 0xFF +#define SERDES_25G_CMU_TOP_AFE_MISC_CTRL0_CMCP_SPARE_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_CMCP_STATUS_CMCP_DIV1P5_QSAMPLE_MASK 0x0F +#define SERDES_25G_CMU_TOP_AFE_CMCP_STATUS_CMCP_DIV1P5_QSAMPLE_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_TOGGLE_CTRL0_CLK_TOGGLE_EN_MASK 0x01 +#define SERDES_25G_CMU_TOP_AFE_TOGGLE_CTRL0_CLK_TOGGLE_EN_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_TOGGLE_CTRL0_CMCP_TOGGLE_EN_MASK 0x02 +#define SERDES_25G_CMU_TOP_AFE_TOGGLE_CTRL0_CMCP_TOGGLE_EN_SHIFT 1 + +#define SERDES_25G_CMU_TOP_AFE_TSTCLK_CTRL0_CMCP_TSTCLK_MUX_MASK 0x03 +#define SERDES_25G_CMU_TOP_AFE_TSTCLK_CTRL0_CMCP_TSTCLK_MUX_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_TSTCLK_CTRL0_CMCP_TSTCLK_DIV_MASK 0x1C +#define SERDES_25G_CMU_TOP_AFE_TSTCLK_CTRL0_CMCP_TSTCLK_DIV_SHIFT 2 + +#define SERDES_25G_CMU_TOP_AFE_TSTCLK_CTRL0_CMCP_TSTCLK_SWING_MASK 0x60 +#define SERDES_25G_CMU_TOP_AFE_TSTCLK_CTRL0_CMCP_TSTCLK_SWING_SHIFT 5 + +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL0_TXTC_CALN_X1_MASK 0x07 +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL0_TXTC_CALN_X1_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL0_TXTC_CALN_X1_FIXED_MASK 0x18 +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL0_TXTC_CALN_X1_FIXED_SHIFT 3 + +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL1_TXTC_CALN_X2_MASK 0x1F +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL1_TXTC_CALN_X2_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL1_TXTC_CALN_XP5_FIXED_MASK 0x60 +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL1_TXTC_CALN_XP5_FIXED_SHIFT 5 + +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL2_TXTC_CALP_X1_MASK 0x07 +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL2_TXTC_CALP_X1_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL2_TXTC_CALP_X1_FIXED_MASK 0x18 +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL2_TXTC_CALP_X1_FIXED_SHIFT 3 + +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL3_TXTC_CALP_X2_MASK 0x1F +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL3_TXTC_CALP_X2_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL3_TXTC_CALP_XP5_FIXED_MASK 0x60 +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL3_TXTC_CALP_XP5_FIXED_SHIFT 5 + +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL4_TXTC_TERM_NEG_MASK 0x07 +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL4_TXTC_TERM_NEG_SHIFT 0 + +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL4_TXTC_TERM_POS_MASK 0x70 +#define SERDES_25G_CMU_TOP_AFE_TXTC_CTRL4_TXTC_TERM_POS_SHIFT 4 + +#define SERDES_25G_CMU_TOP_PWR_STATE_REQ_STATUS_STATE_MASK 0x07 +#define SERDES_25G_CMU_TOP_PWR_STATE_REQ_STATUS_STATE_SHIFT 0 + +#define SERDES_25G_CMU_TOP_PWR_STATE_REQ_STATUS_REQ_MASK 0x08 +#define SERDES_25G_CMU_TOP_PWR_STATE_REQ_STATUS_REQ_SHIFT 3 + +#define SERDES_25G_CMU_TOP_PWR_STATE_ACK_CTRL_STATE_MASK 0x07 +#define SERDES_25G_CMU_TOP_PWR_STATE_ACK_CTRL_STATE_SHIFT 0 + +#define SERDES_25G_CMU_TOP_PWR_STATE_ACK_CTRL_ACK_MASK 0x08 +#define SERDES_25G_CMU_TOP_PWR_STATE_ACK_CTRL_ACK_SHIFT 3 + +#define SERDES_25G_CMU_TOP_PWR_STATE_ACK_CTRL_DELAY_LEN_MASK 0x70 +#define SERDES_25G_CMU_TOP_PWR_STATE_ACK_CTRL_DELAY_LEN_SHIFT 4 + +#define SERDES_25G_CMU_TOP_PHY_IF_STATUS_CMU_OK_MASK 0x01 +#define SERDES_25G_CMU_TOP_PHY_IF_STATUS_CMU_OK_SHIFT 0 + +#define SERDES_25G_CMU_TOP_CMU_TOP_SPARE0_MASK 0xFF +#define SERDES_25G_CMU_TOP_CMU_TOP_SPARE0_SHIFT 0 + +#define SERDES_25G_CMU_TOP_CMU_TOP_SPARE1_MASK 0xFF +#define SERDES_25G_CMU_TOP_CMU_TOP_SPARE1_SHIFT 0 + +#define SERDES_25G_CMU_TOP_ERR_CTRL1_ERR_CODE_7_0_MASK 0xFF +#define SERDES_25G_CMU_TOP_ERR_CTRL1_ERR_CODE_7_0_SHIFT 0 + +#define SERDES_25G_CMU_TOP_ERR_CTRL2_ERR_CODE_15_8_MASK 0xFF +#define SERDES_25G_CMU_TOP_ERR_CTRL2_ERR_CODE_15_8_SHIFT 0 + +#define SERDES_25G_CMU_TOP_ERR_CTRL3_CMU_ERR__MASK 0x01 +#define SERDES_25G_CMU_TOP_ERR_CTRL3_CMU_ERR__SHIFT 0 + +#define SERDES_25G_CMU_TOP_CMU_IF_OVR_CTRL0_CMU_PD_OVR_EN_MASK 0x01 +#define SERDES_25G_CMU_TOP_CMU_IF_OVR_CTRL0_CMU_PD_OVR_EN_SHIFT 0 + +#define SERDES_25G_CMU_TOP_CMU_IF_OVR_CTRL0_CMU_PD_OVR_VAL_MASK 0x06 +#define SERDES_25G_CMU_TOP_CMU_IF_OVR_CTRL0_CMU_PD_OVR_VAL_SHIFT 1 + +#define SERDES_25G_CMU_TOP_CMU_IF_OVR_CTRL1_CMU_RST_N_OVR_EN_MASK 0x01 +#define SERDES_25G_CMU_TOP_CMU_IF_OVR_CTRL1_CMU_RST_N_OVR_EN_SHIFT 0 + +#define SERDES_25G_CMU_TOP_CMU_IF_OVR_CTRL1_CMU_RST_N_OVR_VAL_MASK 0x02 +#define SERDES_25G_CMU_TOP_CMU_IF_OVR_CTRL1_CMU_RST_N_OVR_VAL_SHIFT 1 + + +/******************************************************************************* + * Lane Registers + ******************************************************************************/ +#define SERDES_25G_LANE_BASE 0x1800 +#define SERDES_25G_LANE_SIZE 0x800 + +/********************************** LANE_TOP **********************************/ +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_ADDR 0x00 +#define SERDES_25G_LANE_TOP_AFE_RX_PD_CTRL_ADDR 0x01 +#define SERDES_25G_LANE_TOP_AFE_TX_PD_CTRL_ADDR 0x02 +#define SERDES_25G_LANE_TOP_AFE_BIAS_PD_CTRL_ADDR 0x03 +#define SERDES_25G_LANE_TOP_AFE_RX_RST_CTRL_ADDR 0x04 +#define SERDES_25G_LANE_TOP_AFE_TX_RST_CTRL_ADDR 0x05 +#define SERDES_25G_LANE_TOP_AFE_BIAS_CTRL_ADDR 0x06 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_ADDR 0x10 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL2_ADDR 0x12 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL3_ADDR 0x13 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL4_ADDR 0x14 +#define SERDES_25G_LANE_TOP_AFE_TXDP_CTRL0_ADDR 0x16 +#define SERDES_25G_LANE_TOP_AFE_RXDP_CTRL0_ADDR 0x19 +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_ADDR 0x1B +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL1_ADDR 0x1C +#define SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_ADDR 0x22 +#define SERDES_25G_LANE_TOP_DPL_RXDP_CTRL1_ADDR 0x24 +#define SERDES_25G_LANE_TOP_PWR_STATE_REQ_STATUS_ADDR 0x25 +#define SERDES_25G_LANE_TOP_PWR_STATE_ACK_CTRL_ADDR 0x26 +#define SERDES_25G_LANE_TOP_PHY_IF_STATUS_ADDR 0x27 +#define SERDES_25G_LANE_TOP_DELAY_CTRL0_ADDR 0x30 +#define SERDES_25G_LANE_TOP_DELAY_CTRL1_ADDR 0x31 +#define SERDES_25G_LANE_TOP_LN_STAT_CTRL0_ADDR 0x38 +#define SERDES_25G_LANE_TOP_LN_STAT_CTRL_OVR_ADDR 0x39 +#define SERDES_25G_LANE_TOP_LN_STAT_STATUS0_ADDR 0x3A +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_ADDR 0x3B +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR1_ADDR 0x3C +#define SERDES_25G_LANE_TOP_LN_CTRL_STATUS0_ADDR 0x3D +#define SERDES_25G_LANE_TOP_ERR_CTRL1_ADDR 0x40 +#define SERDES_25G_LANE_TOP_ERR_CTRL2_ADDR 0x41 +/******************************************************************************* + * masks and shifts + ******************************************************************************/ +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_LOOPBACK_RXCLK_EN_MASK 0x01 +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_LOOPBACK_RXCLK_EN_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_LOOPBACK_TXCLK_EN_MASK 0x02 +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_LOOPBACK_TXCLK_EN_SHIFT 1 + +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_LOOPBACK_FEA_EN_MASK 0x04 +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_LOOPBACK_FEA_EN_SHIFT 2 + +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_LOOPBACK_NEA_EN_MASK 0x08 +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_LOOPBACK_NEA_EN_SHIFT 3 + +#define SERDES_25G_LANE_TOP_AFE_RX_PD_CTRL_PD_RXTERM_MASK 0x01 +#define SERDES_25G_LANE_TOP_AFE_RX_PD_CTRL_PD_RXTERM_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_RX_PD_CTRL_PD_RXDP_MASK 0x02 +#define SERDES_25G_LANE_TOP_AFE_RX_PD_CTRL_PD_RXDP_SHIFT 1 + +#define SERDES_25G_LANE_TOP_AFE_TX_PD_CTRL_PD_REG_TXCP_MASK 0x01 +#define SERDES_25G_LANE_TOP_AFE_TX_PD_CTRL_PD_REG_TXCP_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_TX_PD_CTRL_PD_TXCP_MASK 0x02 +#define SERDES_25G_LANE_TOP_AFE_TX_PD_CTRL_PD_TXCP_SHIFT 1 + +#define SERDES_25G_LANE_TOP_AFE_BIAS_PD_CTRL_PD_BIAS_LANE_MASK 0x01 +#define SERDES_25G_LANE_TOP_AFE_BIAS_PD_CTRL_PD_BIAS_LANE_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_RX_RST_CTRL_RST_RXDP_N_MASK 0x01 +#define SERDES_25G_LANE_TOP_AFE_RX_RST_CTRL_RST_RXDP_N_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_TX_RST_CTRL_RST_TXDP_N_MASK 0x04 +#define SERDES_25G_LANE_TOP_AFE_TX_RST_CTRL_RST_TXDP_N_SHIFT 2 + +#define SERDES_25G_LANE_TOP_AFE_BIAS_CTRL_BIAS_SPARE_MASK 0x0F +#define SERDES_25G_LANE_TOP_AFE_BIAS_CTRL_BIAS_SPARE_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_REG_TXCP_TRIM_MASK 0x0F +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_REG_TXCP_TRIM_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_REG_TXCP_TRICKLE_MASK 0x30 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_REG_TXCP_TRICKLE_SHIFT 4 + +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_REG_TXCP_PASS_EN_MASK 0x40 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_REG_TXCP_PASS_EN_SHIFT 6 + +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL2_TXCP_TSTCLK_EN_MASK 0x01 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL2_TXCP_TSTCLK_EN_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL2_TXCP_CLKDIV_MASK 0x06 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL2_TXCP_CLKDIV_SHIFT 1 + +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL3_TXCP_SPARE_MASK 0x0F +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL3_TXCP_SPARE_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL4_TXCP_CLKDIV_SWING_MASK 0x03 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL4_TXCP_CLKDIV_SWING_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL4_TXCP_TOGGLE_EN_MASK 0x04 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL4_TXCP_TOGGLE_EN_SHIFT 2 + +#define SERDES_25G_LANE_TOP_AFE_TXDP_CTRL0_TXDP_SPARE_MASK 0xF0 +#define SERDES_25G_LANE_TOP_AFE_TXDP_CTRL0_TXDP_SPARE_SHIFT 4 + +#define SERDES_25G_LANE_TOP_AFE_RXDP_CTRL0_RXDP_CLKDLY_MASK 0x07 +#define SERDES_25G_LANE_TOP_AFE_RXDP_CTRL0_RXDP_CLKDLY_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_RXDP_CTRL0_RXDP_SPARE_MASK 0xF0 +#define SERDES_25G_LANE_TOP_AFE_RXDP_CTRL0_RXDP_SPARE_SHIFT 4 + +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_CMFILT_MASK 0x07 +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_CMFILT_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_HIZ_MASK 0x08 +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_HIZ_SHIFT 3 + +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_VCM_GND_MASK 0x10 +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_VCM_GND_SHIFT 4 + +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL1_RXTERM_VAL_MASK 0x1F +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL1_RXTERM_VAL_SHIFT 0 + +#define SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_DMUX_TXA_SEL_MASK 0x03 +#define SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_DMUX_TXA_SEL_SHIFT 0 + +#define SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_TXPOLARITY_MASK 0x04 +#define SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_TXPOLARITY_SHIFT 2 + +#define SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_DMUX_TXA_LB_FED_TX_EN_MASK 0x10 +#define SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_DMUX_TXA_LB_FED_TX_EN_SHIFT 4 + +#define SERDES_25G_LANE_TOP_DPL_RXDP_CTRL1_DMUX_RX_SEL_MASK 0x01 +#define SERDES_25G_LANE_TOP_DPL_RXDP_CTRL1_DMUX_RX_SEL_SHIFT 0 + +#define SERDES_25G_LANE_TOP_PWR_STATE_REQ_STATUS_STATE_MASK 0x07 +#define SERDES_25G_LANE_TOP_PWR_STATE_REQ_STATUS_STATE_SHIFT 0 + +#define SERDES_25G_LANE_TOP_PWR_STATE_REQ_STATUS_REQ_MASK 0x08 +#define SERDES_25G_LANE_TOP_PWR_STATE_REQ_STATUS_REQ_SHIFT 3 + +#define SERDES_25G_LANE_TOP_PWR_STATE_ACK_CTRL_STATE_MASK 0x07 +#define SERDES_25G_LANE_TOP_PWR_STATE_ACK_CTRL_STATE_SHIFT 0 + +#define SERDES_25G_LANE_TOP_PWR_STATE_ACK_CTRL_ACK_MASK 0x08 +#define SERDES_25G_LANE_TOP_PWR_STATE_ACK_CTRL_ACK_SHIFT 3 + +#define SERDES_25G_LANE_TOP_PWR_STATE_ACK_CTRL_DELAY_LEN_MASK 0x70 +#define SERDES_25G_LANE_TOP_PWR_STATE_ACK_CTRL_DELAY_LEN_SHIFT 4 + +#define SERDES_25G_LANE_TOP_PHY_IF_STATUS_LN_OK_MASK 0x01 +#define SERDES_25G_LANE_TOP_PHY_IF_STATUS_LN_OK_SHIFT 0 + +#define SERDES_25G_LANE_TOP_DELAY_CTRL0_RX_DATA_EDELAY_MASK 0x07 +#define SERDES_25G_LANE_TOP_DELAY_CTRL0_RX_DATA_EDELAY_SHIFT 0 + +#define SERDES_25G_LANE_TOP_DELAY_CTRL0_RX_EDGE_DELAY_MASK 0x38 +#define SERDES_25G_LANE_TOP_DELAY_CTRL0_RX_EDGE_DELAY_SHIFT 3 + +#define SERDES_25G_LANE_TOP_DELAY_CTRL1_RX_DATA_IDELAY_MASK 0x07 +#define SERDES_25G_LANE_TOP_DELAY_CTRL1_RX_DATA_IDELAY_SHIFT 0 + +#define SERDES_25G_LANE_TOP_DELAY_CTRL1_RX_EYE_DELAY_MASK 0x38 +#define SERDES_25G_LANE_TOP_DELAY_CTRL1_RX_EYE_DELAY_SHIFT 3 + +#define SERDES_25G_LANE_TOP_LN_STAT_CTRL0_RXVALID_MASK 0x01 +#define SERDES_25G_LANE_TOP_LN_STAT_CTRL0_RXVALID_SHIFT 0 + +#define SERDES_25G_LANE_TOP_LN_STAT_CTRL_OVR_OVR_EN_MASK 0x01 +#define SERDES_25G_LANE_TOP_LN_STAT_CTRL_OVR_OVR_EN_SHIFT 0 + +#define SERDES_25G_LANE_TOP_LN_STAT_CTRL_OVR_RST_PD_READY_MASK 0x02 +#define SERDES_25G_LANE_TOP_LN_STAT_CTRL_OVR_RST_PD_READY_SHIFT 1 + +#define SERDES_25G_LANE_TOP_LN_STAT_STATUS0_RST_PD_READY_MASK 0x01 +#define SERDES_25G_LANE_TOP_LN_STAT_STATUS0_RST_PD_READY_SHIFT 0 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_OVR_EN_MASK 0x01 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_OVR_EN_SHIFT 0 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_TX_DATA_WIDTH_MASK 0x02 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_TX_DATA_WIDTH_SHIFT 1 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_RX_DATA_WIDTH_MASK 0x04 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_RX_DATA_WIDTH_SHIFT 2 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_RXPOLARITY_MASK 0x08 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_RXPOLARITY_SHIFT 3 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_TX_EN_MASK 0x10 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_TX_EN_SHIFT 4 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_LOS_EII_EN_MASK 0x20 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_LOS_EII_EN_SHIFT 5 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_LOS_EII_VALUE_MASK 0x40 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_LOS_EII_VALUE_SHIFT 6 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR1_OVR_EN_MASK 0x01 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR1_OVR_EN_SHIFT 0 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR1_PD_MASK 0x06 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR1_PD_SHIFT 1 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR1_RST_N_MASK 0x08 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR1_RST_N_SHIFT 3 + +#define SERDES_25G_LANE_TOP_LN_CTRL_STATUS0_TX_DATA_WIDTH_MASK 0x01 +#define SERDES_25G_LANE_TOP_LN_CTRL_STATUS0_TX_DATA_WIDTH_SHIFT 0 + +#define SERDES_25G_LANE_TOP_LN_CTRL_STATUS0_RX_DATA_WIDTH_MASK 0x02 +#define SERDES_25G_LANE_TOP_LN_CTRL_STATUS0_RX_DATA_WIDTH_SHIFT 1 + +#define SERDES_25G_LANE_TOP_ERR_CTRL1_ERR_CODE_7_0_MASK 0xFF +#define SERDES_25G_LANE_TOP_ERR_CTRL1_ERR_CODE_7_0_SHIFT 0 + +#define SERDES_25G_LANE_TOP_ERR_CTRL2_ERR_CODE_15_8_MASK 0xFF +#define SERDES_25G_LANE_TOP_ERR_CTRL2_ERR_CODE_15_8_SHIFT 0 + +/********************************* Lane CDR RXCLK ***************************/ +#define SERDES_25G_LANE_CDR_RXCLK_BASE 0x80 + +#define SERDES_25G_LANE_CDR_RXCLK_CAL_CTRL0_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x10) +#define SERDES_25G_LANE_CDR_RXCLK_CAL_CTRL1_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x11) +#define SERDES_25G_LANE_CDR_RXCLK_INTEGRAL_CTRL0_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x21) +#define SERDES_25G_LANE_CDR_RXCLK_INTEGRAL_CTRL1_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x22) +#define SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL0_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x26) +#define SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL1_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x27) +#define SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL2_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x28) +#define SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL3_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x29) +#define SERDES_25G_LANE_CDR_RXCLK_FORCE_MODE_CTRL0_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x2A) +#define SERDES_25G_LANE_CDR_RXCLK_FORCE_MODE_CTRL1_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x2B) +#define SERDES_25G_LANE_CDR_RXCLK_FORCE_MODE_CTRL2_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x2D) +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL0_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x30) +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL1_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x31) +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL2_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x32) +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL3_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x34) +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL4_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x36) +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL5_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x37) +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL6_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x39) +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL7_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x3A) +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL8_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x3B) +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS0_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x3C) +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS1_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x3D) +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS2_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x3E) +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS3_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x3F) +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS4_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x40) +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS5_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x41) +#define SERDES_25G_LANE_CDR_RXCLK_INTEGRAL_STATUS0_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x44) +#define SERDES_25G_LANE_CDR_RXCLK_INTEGRAL_STATUS1_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x45) +#define SERDES_25G_LANE_CDR_RXCLK_INTEGRAL_STATUS2_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x46) +#define SERDES_25G_LANE_CDR_RXCLK_LOCKD_CTRL0_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x48) +#define SERDES_25G_LANE_CDR_RXCLK_LOCKD_CTRL1_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x49) +#define SERDES_25G_LANE_CDR_RXCLK_LOCKD_CTRL2_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x4A) +#define SERDES_25G_LANE_CDR_RXCLK_LOCKD_CTRL3_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x4B) +#define SERDES_25G_LANE_CDR_RXCLK_LOCKL_CTRL0_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x4C) +#define SERDES_25G_LANE_CDR_RXCLK_LOCKL_CTRL1_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x4D) +#define SERDES_25G_LANE_CDR_RXCLK_LOCKL_CTRL2_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x4E) +#define SERDES_25G_LANE_CDR_RXCLK_LOCKL_CTRL3_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x4F) +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_CTRL0_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x60) +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_CTRL1_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x61) +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_CTRL2_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x62) +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_CTRL3_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x63) +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_STATUS0_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x68) +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_FIRST_PEAK_STATUS0_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x69) +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_FIRST_PEAK_STATUS1_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x6A) +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_FIRST_PEAK_STATUS2_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x6B) +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_LAST_PEAK_STATUS0_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x6C) +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_LAST_PEAK_STATUS1_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x6D) +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_LAST_PEAK_STATUS2_ADDR (SERDES_25G_LANE_CDR_RXCLK_BASE + 0x6E) +/******************************************************************************* + * masks and shifts + ******************************************************************************/ +#define SERDES_25G_LANE_CDR_RXCLK_CAL_CTRL0_DLPF_SRC_SEL_MASK 0x01 +#define SERDES_25G_LANE_CDR_RXCLK_CAL_CTRL0_DLPF_SRC_SEL_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_CAL_CTRL1_CFG_DOSC_MIN_MASK 0x07 +#define SERDES_25G_LANE_CDR_RXCLK_CAL_CTRL1_CFG_DOSC_MIN_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_INTEGRAL_CTRL0_DECIMATION_MODE_MASK 0x0F +#define SERDES_25G_LANE_CDR_RXCLK_INTEGRAL_CTRL0_DECIMATION_MODE_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_INTEGRAL_CTRL0_DLPF_MODE_MASK 0x30 +#define SERDES_25G_LANE_CDR_RXCLK_INTEGRAL_CTRL0_DLPF_MODE_SHIFT 4 + +#define SERDES_25G_LANE_CDR_RXCLK_INTEGRAL_CTRL1_PD_OUT_MASK_MASK 0x03 +#define SERDES_25G_LANE_CDR_RXCLK_INTEGRAL_CTRL1_PD_OUT_MASK_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL0_DLPF_VAL_7_0_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL0_DLPF_VAL_7_0_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL1_DLPF_VAL_8_MASK 0x01 +#define SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL1_DLPF_VAL_8_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL2_DLPF_DITHER_VAL_7_0_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL2_DLPF_DITHER_VAL_7_0_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL3_DLPF_DITHER_VAL_10_8_MASK 0x07 +#define SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL3_DLPF_DITHER_VAL_10_8_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_FORCE_MODE_CTRL0_DLPF_VAL_7_0_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_FORCE_MODE_CTRL0_DLPF_VAL_7_0_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_FORCE_MODE_CTRL1_DLPF_VAL_8_MASK 0x01 +#define SERDES_25G_LANE_CDR_RXCLK_FORCE_MODE_CTRL1_DLPF_VAL_8_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_FORCE_MODE_CTRL2_EN_MASK 0x01 +#define SERDES_25G_LANE_CDR_RXCLK_FORCE_MODE_CTRL2_EN_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL0_NUM_DITHER_BITS_MASK 0x0F +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL0_NUM_DITHER_BITS_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL1_HIGH_THRESHOLD_7_0_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL1_HIGH_THRESHOLD_7_0_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL2_HIGH_THRESHOLD_8_MASK 0x01 +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL2_HIGH_THRESHOLD_8_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL3_HIGH_COUNT_MASK 0x0F +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL3_HIGH_COUNT_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL4_LOW_THRESHOLD_7_0_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL4_LOW_THRESHOLD_7_0_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL5_LOW_THRESHOLD_8_MASK 0x01 +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL5_LOW_THRESHOLD_8_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL6_LOW_COUNT_MASK 0x0F +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL6_LOW_COUNT_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL7_LOCK_EN_MASK 0x01 +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL7_LOCK_EN_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL7_LOCKL_EN_MASK 0x02 +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL7_LOCKL_EN_SHIFT 1 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL7_HIGH_EN_MASK 0x04 +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL7_HIGH_EN_SHIFT 2 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL7_LOW_EN_MASK 0x08 +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL7_LOW_EN_SHIFT 3 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL8_OUTPUT_SAMPLE_PERIOD_MASK 0x3F +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_CTRL8_OUTPUT_SAMPLE_PERIOD_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS0_GREY_VAL_7_0_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS0_GREY_VAL_7_0_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS1_GREY_VAL_8_MASK 0x01 +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS1_GREY_VAL_8_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS2_BINARY_VAL_7_0_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS2_BINARY_VAL_7_0_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS3_BINARY_VAL_8_MASK 0x01 +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS3_BINARY_VAL_8_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS4_DLPF_TOO_HIGH_MASK 0x01 +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS4_DLPF_TOO_HIGH_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS4_DLPF_TOO_LOW_MASK 0x02 +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS4_DLPF_TOO_LOW_SHIFT 1 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS4_LOCK_LOST_MASK 0x04 +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS4_LOCK_LOST_SHIFT 2 + +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS5_LOCKED_MASK 0x01 +#define SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS5_LOCKED_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_INTEGRAL_STATUS0_ACCUMULATOR_7_0_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_INTEGRAL_STATUS0_ACCUMULATOR_7_0_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_INTEGRAL_STATUS1_ACCUMULATOR_15_8_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_INTEGRAL_STATUS1_ACCUMULATOR_15_8_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_INTEGRAL_STATUS2_ACCUMULATOR_19_16_MASK 0x0F +#define SERDES_25G_LANE_CDR_RXCLK_INTEGRAL_STATUS2_ACCUMULATOR_19_16_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_LOCKD_CTRL0_DITHER_BITS_MASK 0x0F +#define SERDES_25G_LANE_CDR_RXCLK_LOCKD_CTRL0_DITHER_BITS_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_LOCKD_CTRL0_SAMPLE_PERIOD_MASK 0xF0 +#define SERDES_25G_LANE_CDR_RXCLK_LOCKD_CTRL0_SAMPLE_PERIOD_SHIFT 4 + +#define SERDES_25G_LANE_CDR_RXCLK_LOCKD_CTRL1_NUM_SAMPLES_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_LOCKD_CTRL1_NUM_SAMPLES_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_LOCKD_CTRL2_SLOPE_THRESHOLD_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_LOCKD_CTRL2_SLOPE_THRESHOLD_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_LOCKD_CTRL3_RANGE_THRESHOLD_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_LOCKD_CTRL3_RANGE_THRESHOLD_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_LOCKL_CTRL0_DITHER_BITS_MASK 0x0F +#define SERDES_25G_LANE_CDR_RXCLK_LOCKL_CTRL0_DITHER_BITS_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_LOCKL_CTRL0_SAMPLE_PERIOD_MASK 0xF0 +#define SERDES_25G_LANE_CDR_RXCLK_LOCKL_CTRL0_SAMPLE_PERIOD_SHIFT 4 + +#define SERDES_25G_LANE_CDR_RXCLK_LOCKL_CTRL1_NUM_SAMPLES_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_LOCKL_CTRL1_NUM_SAMPLES_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_LOCKL_CTRL2_SLOPE_THRESHOLD_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_LOCKL_CTRL2_SLOPE_THRESHOLD_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_LOCKL_CTRL3_RANGE_THRESHOLD_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_LOCKL_CTRL3_RANGE_THRESHOLD_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_CTRL0_EN_MASK 0x01 +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_CTRL0_EN_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_CTRL1_SAMPLE_DROP_BITS_MASK 0x07 +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_CTRL1_SAMPLE_DROP_BITS_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_CTRL1_NUM_PEAKS_MASK 0xF0 +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_CTRL1_NUM_PEAKS_SHIFT 4 + +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_CTRL2_PEAK2PEAK_PERIOD_MIN_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_CTRL2_PEAK2PEAK_PERIOD_MIN_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_CTRL3_PEAK2PEAK_PERIOD_MAX_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_CTRL3_PEAK2PEAK_PERIOD_MAX_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_STATUS0_DONE_MASK 0x01 +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_STATUS0_DONE_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_STATUS0_NOISY_MASK 0x02 +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_STATUS0_NOISY_SHIFT 1 + +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_STATUS0_SLOW_MASK 0x04 +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_PEAK_DETECT_STATUS0_SLOW_SHIFT 2 + +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_FIRST_PEAK_STATUS0_VAL_7_0_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_FIRST_PEAK_STATUS0_VAL_7_0_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_FIRST_PEAK_STATUS1_VAL_15_8_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_FIRST_PEAK_STATUS1_VAL_15_8_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_FIRST_PEAK_STATUS2_VAL_19_16_MASK 0x0F +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_FIRST_PEAK_STATUS2_VAL_19_16_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_LAST_PEAK_STATUS0_VAL_7_0_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_LAST_PEAK_STATUS0_VAL_7_0_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_LAST_PEAK_STATUS1_VAL_15_8_MASK 0xFF +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_LAST_PEAK_STATUS1_VAL_15_8_SHIFT 0 + +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_LAST_PEAK_STATUS2_VAL_19_16_MASK 0x0F +#define SERDES_25G_LANE_CDR_RXCLK_ACCUM_LAST_PEAK_STATUS2_VAL_19_16_SHIFT 0 + +/********************************* Lane CDR_REFCLK ***************************/ +#define SERDES_25G_LANE_CDR_REFCLK_BASE 0x180 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PD_CTRL0_ADDR (SERDES_25G_LANE_CDR_REFCLK_BASE + 0x00) +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PD_CTRL1_ADDR (SERDES_25G_LANE_CDR_REFCLK_BASE + 0x01) +#define SERDES_25G_LANE_CDR_REFCLK_AFE_RST_CTRL0_ADDR (SERDES_25G_LANE_CDR_REFCLK_BASE + 0x06) +#define SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL0_ADDR (SERDES_25G_LANE_CDR_REFCLK_BASE + 0x0A) +#define SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL1_ADDR (SERDES_25G_LANE_CDR_REFCLK_BASE + 0x0B) +#define SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL2_ADDR (SERDES_25G_LANE_CDR_REFCLK_BASE + 0x0C) +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CTRL0_ADDR (SERDES_25G_LANE_CDR_REFCLK_BASE + 0x10) +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CTRL1_ADDR (SERDES_25G_LANE_CDR_REFCLK_BASE + 0x11) +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL0_ADDR (SERDES_25G_LANE_CDR_REFCLK_BASE + 0x18) +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL1_ADDR (SERDES_25G_LANE_CDR_REFCLK_BASE + 0x19) +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL2_ADDR (SERDES_25G_LANE_CDR_REFCLK_BASE + 0x1A) +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL3_ADDR (SERDES_25G_LANE_CDR_REFCLK_BASE + 0x1B) +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CAL_CTRL0_ADDR (SERDES_25G_LANE_CDR_REFCLK_BASE + 0x20) +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CAL_CTRL1_ADDR (SERDES_25G_LANE_CDR_REFCLK_BASE + 0x21) +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CAL_CTRL2_ADDR (SERDES_25G_LANE_CDR_REFCLK_BASE + 0x22) +#define SERDES_25G_LANE_CDR_REFCLK_AFE_VCOCAL_STATUS0_ADDR (SERDES_25G_LANE_CDR_REFCLK_BASE + 0x24) +#define SERDES_25G_LANE_CDR_REFCLK_RXCDR_HSCAN_EYE_CFG_ADDR (SERDES_25G_LANE_CDR_REFCLK_BASE + 0x30) +/******************************************************************************* + * masks and shifts + ******************************************************************************/ +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PD_CTRL0_PD_RXCDR_MASK 0x01 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PD_CTRL0_PD_RXCDR_SHIFT 0 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PD_CTRL0_PD_RXCDR_EYE_MASK 0x02 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PD_CTRL0_PD_RXCDR_EYE_SHIFT 1 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PD_CTRL0_RXCDR_TOGGLE_EN_MASK 0x04 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PD_CTRL0_RXCDR_TOGGLE_EN_SHIFT 2 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PD_CTRL1_RXCDR_PHD_EN_MASK 0xFF +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PD_CTRL1_RXCDR_PHD_EN_SHIFT 0 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_RST_CTRL0_RST_RXCDR_PHD_N_MASK 0x01 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_RST_CTRL0_RST_RXCDR_PHD_N_SHIFT 0 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_RST_CTRL0_RST_RXCDR_CLKDIV_N_MASK 0x02 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_RST_CTRL0_RST_RXCDR_CLKDIV_N_SHIFT 1 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL0_RXCDR_VCO_KICK_MASK 0x01 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL0_RXCDR_VCO_KICK_SHIFT 0 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL1_RXCDR_REGDAC_BANDWIDTH_MASK 0x01 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL1_RXCDR_REGDAC_BANDWIDTH_SHIFT 0 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL1_RXCDR_SHORT_VOSC_PRP_MASK 0x02 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL1_RXCDR_SHORT_VOSC_PRP_SHIFT 1 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL1_RXCDR_REFDAC_GAIN_MASK 0x0C +#define SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL1_RXCDR_REFDAC_GAIN_SHIFT 2 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL2_RXCDR_DOSC_MASK 0x07 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL2_RXCDR_DOSC_SHIFT 0 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CTRL0_RXCDR_BBSTEP_MASK 0x1F +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CTRL0_RXCDR_BBSTEP_SHIFT 0 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CTRL0_RXCDR_CLKDIV_MASK 0x60 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CTRL0_RXCDR_CLKDIV_SHIFT 5 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CTRL1_RXCDR_CLKDIV_SWING_MASK 0x03 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CTRL1_RXCDR_CLKDIV_SWING_SHIFT 0 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CTRL1_RXCDR_SPARE_MASK 0x3C +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CTRL1_RXCDR_SPARE_SHIFT 2 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL0_RXCDR_HSCAN_CLKQ_MASK 0x7F +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL0_RXCDR_HSCAN_CLKQ_SHIFT 0 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL0_SRC_SEL_MASK 0x80 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL0_SRC_SEL_SHIFT 7 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL1_RXCDR_HSCAN_CLKI_MASK 0x7F +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL1_RXCDR_HSCAN_CLKI_SHIFT 0 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL1_SRC_SEL_MASK 0x80 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL1_SRC_SEL_SHIFT 7 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL2_RXCDR_HSCAN_EYE_MASK 0x7F +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL2_RXCDR_HSCAN_EYE_SHIFT 0 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL3_RXCDR_PI_CAP_MASK 0x07 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL3_RXCDR_PI_CAP_SHIFT 0 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL3_RXCDR_PI_SWING_MASK 0x18 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL3_RXCDR_PI_SWING_SHIFT 3 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CAL_CTRL0_RXCDR_CAL_EN_MASK 0x01 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CAL_CTRL0_RXCDR_CAL_EN_SHIFT 0 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CAL_CTRL0_RXCDR_VCOCAL_DIV4_MASK 0x02 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CAL_CTRL0_RXCDR_VCOCAL_DIV4_SHIFT 1 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CAL_CTRL1_RXCDR_VCOCAL_LOAD_VAL_11_8_MASK 0x0F +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CAL_CTRL1_RXCDR_VCOCAL_LOAD_VAL_11_8_SHIFT 0 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CAL_CTRL2_RXCDR_VCOCAL_LOAD_VAL_7_0_MASK 0xFF +#define SERDES_25G_LANE_CDR_REFCLK_AFE_CAL_CTRL2_RXCDR_VCOCAL_LOAD_VAL_7_0_SHIFT 0 + +#define SERDES_25G_LANE_CDR_REFCLK_AFE_VCOCAL_STATUS0_RXCDR_VCOCAL_UP_MASK 0x01 +#define SERDES_25G_LANE_CDR_REFCLK_AFE_VCOCAL_STATUS0_RXCDR_VCOCAL_UP_SHIFT 0 + +#define SERDES_25G_LANE_CDR_REFCLK_RXCDR_HSCAN_EYE_CFG_ZERO_PHASE_MASK 0x7F +#define SERDES_25G_LANE_CDR_REFCLK_RXCDR_HSCAN_EYE_CFG_ZERO_PHASE_SHIFT 0 + +/********************************* Lane BIST *********************************/ +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_ADDR 0x00 +#define SERDES_25G_LANE_TOP_AFE_RX_PD_CTRL_ADDR 0x01 +#define SERDES_25G_LANE_TOP_AFE_TX_PD_CTRL_ADDR 0x02 +#define SERDES_25G_LANE_TOP_AFE_BIAS_PD_CTRL_ADDR 0x03 +#define SERDES_25G_LANE_TOP_AFE_RX_RST_CTRL_ADDR 0x04 +#define SERDES_25G_LANE_TOP_AFE_TX_RST_CTRL_ADDR 0x05 +#define SERDES_25G_LANE_TOP_AFE_BIAS_CTRL_ADDR 0x06 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_ADDR 0x10 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL2_ADDR 0x12 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL3_ADDR 0x13 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL4_ADDR 0x14 +#define SERDES_25G_LANE_TOP_AFE_TXDP_CTRL0_ADDR 0x16 +#define SERDES_25G_LANE_TOP_AFE_RXDP_CTRL0_ADDR 0x19 +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_ADDR 0x1B +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL1_ADDR 0x1C +#define SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_ADDR 0x22 +#define SERDES_25G_LANE_TOP_DPL_RXDP_CTRL1_ADDR 0x24 +#define SERDES_25G_LANE_TOP_PWR_STATE_REQ_STATUS_ADDR 0x25 +#define SERDES_25G_LANE_TOP_PWR_STATE_ACK_CTRL_ADDR 0x26 +#define SERDES_25G_LANE_TOP_PHY_IF_STATUS_ADDR 0x27 +#define SERDES_25G_LANE_TOP_DELAY_CTRL0_ADDR 0x30 +#define SERDES_25G_LANE_TOP_DELAY_CTRL1_ADDR 0x31 +#define SERDES_25G_LANE_TOP_LN_STAT_CTRL0_ADDR 0x38 +#define SERDES_25G_LANE_TOP_LN_STAT_CTRL_OVR_ADDR 0x39 +#define SERDES_25G_LANE_TOP_LN_STAT_STATUS0_ADDR 0x3A +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_ADDR 0x3B +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR1_ADDR 0x3C +#define SERDES_25G_LANE_TOP_LN_CTRL_STATUS0_ADDR 0x3D +#define SERDES_25G_LANE_TOP_ERR_CTRL1_ADDR 0x40 +#define SERDES_25G_LANE_TOP_ERR_CTRL2_ADDR 0x41 +/******************************************************************************* + * masks and shifts + ******************************************************************************/ +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_LOOPBACK_RXCLK_EN_MASK 0x01 +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_LOOPBACK_RXCLK_EN_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_LOOPBACK_TXCLK_EN_MASK 0x02 +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_LOOPBACK_TXCLK_EN_SHIFT 1 + +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_LOOPBACK_FEA_EN_MASK 0x04 +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_LOOPBACK_FEA_EN_SHIFT 2 + +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_LOOPBACK_NEA_EN_MASK 0x08 +#define SERDES_25G_LANE_TOP_AFE_LOOPBACK_CTRL_LOOPBACK_NEA_EN_SHIFT 3 + +#define SERDES_25G_LANE_TOP_AFE_RX_PD_CTRL_PD_RXTERM_MASK 0x01 +#define SERDES_25G_LANE_TOP_AFE_RX_PD_CTRL_PD_RXTERM_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_RX_PD_CTRL_PD_RXDP_MASK 0x02 +#define SERDES_25G_LANE_TOP_AFE_RX_PD_CTRL_PD_RXDP_SHIFT 1 + +#define SERDES_25G_LANE_TOP_AFE_TX_PD_CTRL_PD_REG_TXCP_MASK 0x01 +#define SERDES_25G_LANE_TOP_AFE_TX_PD_CTRL_PD_REG_TXCP_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_TX_PD_CTRL_PD_TXCP_MASK 0x02 +#define SERDES_25G_LANE_TOP_AFE_TX_PD_CTRL_PD_TXCP_SHIFT 1 + +#define SERDES_25G_LANE_TOP_AFE_BIAS_PD_CTRL_PD_BIAS_LANE_MASK 0x01 +#define SERDES_25G_LANE_TOP_AFE_BIAS_PD_CTRL_PD_BIAS_LANE_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_RX_RST_CTRL_RST_RXDP_N_MASK 0x01 +#define SERDES_25G_LANE_TOP_AFE_RX_RST_CTRL_RST_RXDP_N_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_TX_RST_CTRL_RST_TXDP_N_MASK 0x04 +#define SERDES_25G_LANE_TOP_AFE_TX_RST_CTRL_RST_TXDP_N_SHIFT 2 + +#define SERDES_25G_LANE_TOP_AFE_BIAS_CTRL_BIAS_SPARE_MASK 0x0F +#define SERDES_25G_LANE_TOP_AFE_BIAS_CTRL_BIAS_SPARE_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_REG_TXCP_TRIM_MASK 0x0F +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_REG_TXCP_TRIM_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_REG_TXCP_TRICKLE_MASK 0x30 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_REG_TXCP_TRICKLE_SHIFT 4 + +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_REG_TXCP_PASS_EN_MASK 0x40 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_REG_TXCP_PASS_EN_SHIFT 6 + +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL2_TXCP_TSTCLK_EN_MASK 0x01 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL2_TXCP_TSTCLK_EN_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL2_TXCP_CLKDIV_MASK 0x06 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL2_TXCP_CLKDIV_SHIFT 1 + +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL3_TXCP_SPARE_MASK 0x0F +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL3_TXCP_SPARE_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL4_TXCP_CLKDIV_SWING_MASK 0x03 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL4_TXCP_CLKDIV_SWING_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL4_TXCP_TOGGLE_EN_MASK 0x04 +#define SERDES_25G_LANE_TOP_AFE_TXCP_CTRL4_TXCP_TOGGLE_EN_SHIFT 2 + +#define SERDES_25G_LANE_TOP_AFE_TXDP_CTRL0_TXDP_SPARE_MASK 0xF0 +#define SERDES_25G_LANE_TOP_AFE_TXDP_CTRL0_TXDP_SPARE_SHIFT 4 + +#define SERDES_25G_LANE_TOP_AFE_RXDP_CTRL0_RXDP_CLKDLY_MASK 0x07 +#define SERDES_25G_LANE_TOP_AFE_RXDP_CTRL0_RXDP_CLKDLY_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_RXDP_CTRL0_RXDP_SPARE_MASK 0xF0 +#define SERDES_25G_LANE_TOP_AFE_RXDP_CTRL0_RXDP_SPARE_SHIFT 4 + +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_CMFILT_MASK 0x07 +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_CMFILT_SHIFT 0 + +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_HIZ_MASK 0x08 +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_HIZ_SHIFT 3 + +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_VCM_GND_MASK 0x10 +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_VCM_GND_SHIFT 4 + +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL1_RXTERM_VAL_MASK 0x1F +#define SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL1_RXTERM_VAL_SHIFT 0 + +#define SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_DMUX_TXA_SEL_MASK 0x03 +#define SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_DMUX_TXA_SEL_SHIFT 0 + +#define SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_TXPOLARITY_MASK 0x04 +#define SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_TXPOLARITY_SHIFT 2 + +#define SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_DMUX_TXA_LB_FED_TX_EN_MASK 0x10 +#define SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_DMUX_TXA_LB_FED_TX_EN_SHIFT 4 + +#define SERDES_25G_LANE_TOP_DPL_RXDP_CTRL1_DMUX_RX_SEL_MASK 0x01 +#define SERDES_25G_LANE_TOP_DPL_RXDP_CTRL1_DMUX_RX_SEL_SHIFT 0 + +#define SERDES_25G_LANE_TOP_PWR_STATE_REQ_STATUS_STATE_MASK 0x07 +#define SERDES_25G_LANE_TOP_PWR_STATE_REQ_STATUS_STATE_SHIFT 0 + +#define SERDES_25G_LANE_TOP_PWR_STATE_REQ_STATUS_REQ_MASK 0x08 +#define SERDES_25G_LANE_TOP_PWR_STATE_REQ_STATUS_REQ_SHIFT 3 + +#define SERDES_25G_LANE_TOP_PWR_STATE_ACK_CTRL_STATE_MASK 0x07 +#define SERDES_25G_LANE_TOP_PWR_STATE_ACK_CTRL_STATE_SHIFT 0 + +#define SERDES_25G_LANE_TOP_PWR_STATE_ACK_CTRL_ACK_MASK 0x08 +#define SERDES_25G_LANE_TOP_PWR_STATE_ACK_CTRL_ACK_SHIFT 3 + +#define SERDES_25G_LANE_TOP_PWR_STATE_ACK_CTRL_DELAY_LEN_MASK 0x70 +#define SERDES_25G_LANE_TOP_PWR_STATE_ACK_CTRL_DELAY_LEN_SHIFT 4 + +#define SERDES_25G_LANE_TOP_PHY_IF_STATUS_LN_OK_MASK 0x01 +#define SERDES_25G_LANE_TOP_PHY_IF_STATUS_LN_OK_SHIFT 0 + +#define SERDES_25G_LANE_TOP_DELAY_CTRL0_RX_DATA_EDELAY_MASK 0x07 +#define SERDES_25G_LANE_TOP_DELAY_CTRL0_RX_DATA_EDELAY_SHIFT 0 + +#define SERDES_25G_LANE_TOP_DELAY_CTRL0_RX_EDGE_DELAY_MASK 0x38 +#define SERDES_25G_LANE_TOP_DELAY_CTRL0_RX_EDGE_DELAY_SHIFT 3 + +#define SERDES_25G_LANE_TOP_DELAY_CTRL1_RX_DATA_IDELAY_MASK 0x07 +#define SERDES_25G_LANE_TOP_DELAY_CTRL1_RX_DATA_IDELAY_SHIFT 0 + +#define SERDES_25G_LANE_TOP_DELAY_CTRL1_RX_EYE_DELAY_MASK 0x38 +#define SERDES_25G_LANE_TOP_DELAY_CTRL1_RX_EYE_DELAY_SHIFT 3 + +#define SERDES_25G_LANE_TOP_LN_STAT_CTRL0_RXVALID_MASK 0x01 +#define SERDES_25G_LANE_TOP_LN_STAT_CTRL0_RXVALID_SHIFT 0 + +#define SERDES_25G_LANE_TOP_LN_STAT_CTRL_OVR_OVR_EN_MASK 0x01 +#define SERDES_25G_LANE_TOP_LN_STAT_CTRL_OVR_OVR_EN_SHIFT 0 + +#define SERDES_25G_LANE_TOP_LN_STAT_CTRL_OVR_RST_PD_READY_MASK 0x02 +#define SERDES_25G_LANE_TOP_LN_STAT_CTRL_OVR_RST_PD_READY_SHIFT 1 + +#define SERDES_25G_LANE_TOP_LN_STAT_STATUS0_RST_PD_READY_MASK 0x01 +#define SERDES_25G_LANE_TOP_LN_STAT_STATUS0_RST_PD_READY_SHIFT 0 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_OVR_EN_MASK 0x01 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_OVR_EN_SHIFT 0 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_TX_DATA_WIDTH_MASK 0x02 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_TX_DATA_WIDTH_SHIFT 1 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_RX_DATA_WIDTH_MASK 0x04 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_RX_DATA_WIDTH_SHIFT 2 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_RXPOLARITY_MASK 0x08 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_RXPOLARITY_SHIFT 3 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_TX_EN_MASK 0x10 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_TX_EN_SHIFT 4 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_LOS_EII_EN_MASK 0x20 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_LOS_EII_EN_SHIFT 5 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_LOS_EII_VALUE_MASK 0x40 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR0_LOS_EII_VALUE_SHIFT 6 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR1_OVR_EN_MASK 0x01 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR1_OVR_EN_SHIFT 0 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR1_PD_MASK 0x06 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR1_PD_SHIFT 1 + +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR1_RST_N_MASK 0x08 +#define SERDES_25G_LANE_TOP_LN_CTRL_OVR1_RST_N_SHIFT 3 + +#define SERDES_25G_LANE_TOP_LN_CTRL_STATUS0_TX_DATA_WIDTH_MASK 0x01 +#define SERDES_25G_LANE_TOP_LN_CTRL_STATUS0_TX_DATA_WIDTH_SHIFT 0 + +#define SERDES_25G_LANE_TOP_LN_CTRL_STATUS0_RX_DATA_WIDTH_MASK 0x02 +#define SERDES_25G_LANE_TOP_LN_CTRL_STATUS0_RX_DATA_WIDTH_SHIFT 1 + +#define SERDES_25G_LANE_TOP_ERR_CTRL1_ERR_CODE_7_0_MASK 0xFF +#define SERDES_25G_LANE_TOP_ERR_CTRL1_ERR_CODE_7_0_SHIFT 0 + +#define SERDES_25G_LANE_TOP_ERR_CTRL2_ERR_CODE_15_8_MASK 0xFF +#define SERDES_25G_LANE_TOP_ERR_CTRL2_ERR_CODE_15_8_SHIFT 0 + +/********************************* LEQ_REFCLK *********************************/ +#define SERDES_25G_LANE_LEQ_REFCLK_BASE 0x200 + +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_PD_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x00) +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_BIAS_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x02) +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_BIAS_CTRL1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x03) +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_PLE_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x05) +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_EQ_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x07) +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_MISC_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x09) +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x0A) +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x0B) +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL2_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x0C) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x0E) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x0F) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL2_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x10) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL3_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x11) +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x20) +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CMD0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x21) +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CMD1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x22) +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CMD2_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x23) +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x24) +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x25) +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS2_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x26) +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS3_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x27) +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS4_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x28) +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x29) +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL2_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x2A) +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS5_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x2B) +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS6_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x2C) +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_OUTINTF_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x2E) +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x30) +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x31) +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL2_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x32) +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL3_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x33) +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL4_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x34) +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL5_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x35) +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL6_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x36) +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL7_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x37) +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL8_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x38) +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL9_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x39) +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL10_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x3A) +#define SERDES_25G_LANE_LEQ_REFCLK_PLE_LFG_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x3D) +#define SERDES_25G_LANE_LEQ_REFCLK_PLE_LFG_CTRL1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x3E) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x40) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x41) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL2_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x42) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL3_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x43) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL4_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x44) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL5_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x45) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL6_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x46) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x50) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x51) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL2_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x52) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL3_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x53) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL4_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x54) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL5_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x55) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL6_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x56) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL7_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x57) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL8_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x58) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL9_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x59) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL10_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x5A) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL11_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x5B) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL12_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x5C) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL13_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x5D) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL14_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x5E) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL15_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x5F) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL16_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x60) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL17_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x61) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL18_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x62) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL19_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x63) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL20_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x64) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL21_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x65) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL22_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x66) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL23_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x67) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL24_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x68) +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x70) +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x71) +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL2_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x72) +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL3_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x73) +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL4_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x74) +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL5_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x75) +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL6_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x76) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x80) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x81) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL2_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x82) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL3_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x83) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL4_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x84) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL5_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x85) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL6_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x86) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL7_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x87) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL8_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x88) +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x90) +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x91) +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL2_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x92) +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL3_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x93) +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL4_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x94) +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL5_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x95) +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL6_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x96) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x98) +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x99) +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x9A) +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x9B) +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL2_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x9C) +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL3_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0x9D) +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0xA0) +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0xA1) +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL2_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0xA2) +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL3_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0xA3) +#define SERDES_25G_LANE_LEQ_REFCLK_REF_THRESHOLD0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0xA6) +#define SERDES_25G_LANE_LEQ_REFCLK_REF_THRESHOLD1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0xA7) +#define SERDES_25G_LANE_LEQ_REFCLK_REF_THRESHOLD2_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0xA8) +#define SERDES_25G_LANE_LEQ_REFCLK_REF_THRESHOLD3_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0xA9) +#define SERDES_25G_LANE_LEQ_REFCLK_EYE_PHASE0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0xAB) +#define SERDES_25G_LANE_LEQ_REFCLK_EYE_PHASE1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0xAC) +#define SERDES_25G_LANE_LEQ_REFCLK_EYEMON_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0xAE) +#define SERDES_25G_LANE_LEQ_REFCLK_EYEINTF_CTRL0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0xAF) +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_REFCLK_SPARE0_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0xB8) +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_REFCLK_SPARE1_ADDR (SERDES_25G_LANE_LEQ_REFCLK_BASE + 0xB9) + +/******************************************************************************* + * masks and shifts + ******************************************************************************/ +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_PD_CTRL0_PD_RXLEQ_MASK 0x3F +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_PD_CTRL0_PD_RXLEQ_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_PD_CTRL0_PD_RXLEQ_BIASGEN_MASK 0x40 +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_PD_CTRL0_PD_RXLEQ_BIASGEN_SHIFT 6 + +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_BIAS_CTRL0_RXLEQ_BIAS_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_BIAS_CTRL0_RXLEQ_BIAS_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_BIAS_CTRL1_RXLEQ_VGSW_SEL_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_BIAS_CTRL1_RXLEQ_VGSW_SEL_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_BIAS_CTRL1_RXLEQ_BIASI_TRIM_MASK 0x18 +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_BIAS_CTRL1_RXLEQ_BIASI_TRIM_SHIFT 3 + +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_PLE_CTRL0_RXLEQ_PLE_MUTE_MASK 0x01 +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_PLE_CTRL0_RXLEQ_PLE_MUTE_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_PLE_CTRL0_RXLEQ_PLE_BLW_ZERO_MASK 0x06 +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_PLE_CTRL0_RXLEQ_PLE_BLW_ZERO_SHIFT 1 + +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_PLE_CTRL0_RXLEQ_PLE_PRECH_MASK 0x08 +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_PLE_CTRL0_RXLEQ_PLE_PRECH_SHIFT 3 + +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_EQ_CTRL0_RXLEQ_EQ_SQL_DIR_MASK 0x01 +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_EQ_CTRL0_RXLEQ_EQ_SQL_DIR_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_MISC_CTRL0_RXLEQ_SPARE_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_AFE_MISC_CTRL0_RXLEQ_SPARE_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL0_GN_LOADRES_START0_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL0_GN_LOADRES_START0_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL0_GN_LOADRES_START1_MASK 0x38 +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL0_GN_LOADRES_START1_SHIFT 3 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL1_GN_LOADRES_START2_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL1_GN_LOADRES_START2_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL1_GN_LOADRES_START3_MASK 0x38 +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL1_GN_LOADRES_START3_SHIFT 3 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL2_GN_BIASI_RATE0_MASK 0x03 +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL2_GN_BIASI_RATE0_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL2_GN_BIASI_RATE1_MASK 0x0C +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL2_GN_BIASI_RATE1_SHIFT 2 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL2_GN_BIASI_RATE2_MASK 0x30 +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL2_GN_BIASI_RATE2_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL2_GN_BIASI_RATE3_MASK 0xC0 +#define SERDES_25G_LANE_LEQ_REFCLK_GN_CTRL2_GN_BIASI_RATE3_SHIFT 6 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL0_EQ_LOADRES_START0_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL0_EQ_LOADRES_START0_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL0_EQ_LOADRES_START1_MASK 0x38 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL0_EQ_LOADRES_START1_SHIFT 3 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL1_EQ_LOADRES_START2_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL1_EQ_LOADRES_START2_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL1_EQ_LOADRES_START3_MASK 0x38 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL1_EQ_LOADRES_START3_SHIFT 3 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL2_EQ_BIASRES_START0_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL2_EQ_BIASRES_START0_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL2_EQ_BIASRES_START1_MASK 0x38 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL2_EQ_BIASRES_START1_SHIFT 3 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL3_EQ_BIASRES_START2_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL3_EQ_BIASRES_START2_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL3_EQ_BIASRES_START3_MASK 0x38 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_CTRL3_EQ_BIASRES_START3_SHIFT 3 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL0_LEQ_FSM_CMD_REQ_MASK 0x01 +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL0_LEQ_FSM_CMD_REQ_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL0_LEQ_FSM_STATE_RESET_MASK 0x04 +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL0_LEQ_FSM_STATE_RESET_SHIFT 2 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CMD0_LEQ_FSM_CMD_OPCODE_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CMD0_LEQ_FSM_CMD_OPCODE_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CMD0_LEQ_FSM_CMD_TARGET_MASK 0xF0 +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CMD0_LEQ_FSM_CMD_TARGET_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CMD1_LEQ_FSM_CMD_SCRATCHPAD_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CMD1_LEQ_FSM_CMD_SCRATCHPAD_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CMD2_LEQ_FSM_CMD_MISC_OPTION_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CMD2_LEQ_FSM_CMD_MISC_OPTION_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_LEQ_FSM_STATUS_ERROR1_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_LEQ_FSM_STATUS_ERROR1_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_LEQ_FSM_STATUS_ERROR2_MASK 0x38 +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_LEQ_FSM_STATUS_ERROR2_SHIFT 3 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_LEQ_FSM_MAX_CLAMP_MASK 0x40 +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_LEQ_FSM_MAX_CLAMP_SHIFT 6 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_LEQ_FSM_MIN_CLAMP_MASK 0x80 +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_LEQ_FSM_MIN_CLAMP_SHIFT 7 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS1_LEQ_FSM_STATE_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS1_LEQ_FSM_STATE_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS1_LEQ_FSM_LAST_RESULT_MASK 0xF0 +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS1_LEQ_FSM_LAST_RESULT_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS2_LEQ_FSM_LAST_STEP_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS2_LEQ_FSM_LAST_STEP_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS3_LEQ_FSM_LAST_VALUE_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS3_LEQ_FSM_LAST_VALUE_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS4_LEQ_FSM_LAST_OPCODE_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS4_LEQ_FSM_LAST_OPCODE_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS4_LEQ_FSM_LAST_TARGET_MASK 0xF0 +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS4_LEQ_FSM_LAST_TARGET_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL1_LEQ_FSM_TIMEOUT_LIMIT_7_0_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL1_LEQ_FSM_TIMEOUT_LIMIT_7_0_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL2_LEQ_FSM_TIMEOUT_LIMIT_15_8_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL2_LEQ_FSM_TIMEOUT_LIMIT_15_8_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS5_LEQ_FSM_CMD_ACK_MASK 0x02 +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS5_LEQ_FSM_CMD_ACK_SHIFT 1 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS6_LEQ_FSM_2LST_VALUE_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS6_LEQ_FSM_2LST_VALUE_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_OUTINTF_CTRL0_LEQ_OUTINTF_RDY_WAIT_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_OUTINTF_CTRL0_LEQ_OUTINTF_RDY_WAIT_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL0_AGCLOS_START_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL0_AGCLOS_START_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL1_AGCLOS_VALUE_MAX_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL1_AGCLOS_VALUE_MAX_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL2_AGCLOS_VALUE_MIN_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL2_AGCLOS_VALUE_MIN_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL3_AGCLOS_WRWAIT_TIME_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL3_AGCLOS_WRWAIT_TIME_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL3_AGCLOS_INIT_TIMEOUT_DISABLE_MASK 0x40 +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL3_AGCLOS_INIT_TIMEOUT_DISABLE_SHIFT 6 + +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL3_AGCLOS_MEASURE_TIMEOUT_DISABLE_MASK 0x80 +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL3_AGCLOS_MEASURE_TIMEOUT_DISABLE_SHIFT 7 + +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL4_AGCLOS_STEP_BY1_MASK 0x01 +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL4_AGCLOS_STEP_BY1_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL4_AGCLOS_ERROR_SIGN_MASK 0x02 +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL4_AGCLOS_ERROR_SIGN_SHIFT 1 + +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL4_AGCLOS_STEP_SIZE_MASK 0x1C +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL4_AGCLOS_STEP_SIZE_SHIFT 2 + +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL5_AGCLOS_BOUNCE_LIMIT_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL5_AGCLOS_BOUNCE_LIMIT_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL5_AGCLOS_LASTWR_AVG_MASK 0x30 +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL5_AGCLOS_LASTWR_AVG_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL5_AGCLOS_LASTWR_FLOOR_MASK 0x40 +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL5_AGCLOS_LASTWR_FLOOR_SHIFT 6 + +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL6_AGCLOS_LASTWR_ADJUST_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL6_AGCLOS_LASTWR_ADJUST_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL7_AGCLOS_PEAK_ACQ_TIME_7_0_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL7_AGCLOS_PEAK_ACQ_TIME_7_0_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL8_AGCLOS_PEAK_ACQ_TIME_15_8_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL8_AGCLOS_PEAK_ACQ_TIME_15_8_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL9_AGCLOS_PEAK_ACQ_TIME_23_16_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL9_AGCLOS_PEAK_ACQ_TIME_23_16_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL10_AGCLOS_PEAK_ACQ_TIME_25_24_MASK 0x03 +#define SERDES_25G_LANE_LEQ_REFCLK_AGCLOS_CTRL10_AGCLOS_PEAK_ACQ_TIME_25_24_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_PLE_LFG_CTRL0_PLE_LFG_WRWAIT_TIME_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_PLE_LFG_CTRL0_PLE_LFG_WRWAIT_TIME_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_PLE_LFG_CTRL0_PLE_LFG_STEP_BY1_MASK 0x10 +#define SERDES_25G_LANE_LEQ_REFCLK_PLE_LFG_CTRL0_PLE_LFG_STEP_BY1_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_PLE_LFG_CTRL1_PLE_LFG_START_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_PLE_LFG_CTRL1_PLE_LFG_START_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL0_EQ_HFG_SQL_START_MASK 0x1F +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL0_EQ_HFG_SQL_START_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL1_EQ_HFG_SQL_VALUE_MAX_MASK 0x1F +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL1_EQ_HFG_SQL_VALUE_MAX_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL2_EQ_HFG_SQL_VALUE_MIN_MASK 0x1F +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL2_EQ_HFG_SQL_VALUE_MIN_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL3_EQ_HFG_SQL_WRWAIT_TIME_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL3_EQ_HFG_SQL_WRWAIT_TIME_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL3_EQ_HFG_SQL_MEASURE_TIMEOUT_DISABLE_MASK 0x80 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL3_EQ_HFG_SQL_MEASURE_TIMEOUT_DISABLE_SHIFT 7 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL4_EQ_HFG_SQL_STEP_BY1_MASK 0x01 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL4_EQ_HFG_SQL_STEP_BY1_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL4_EQ_HFG_SQL_ERROR_SIGN_MASK 0x02 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL4_EQ_HFG_SQL_ERROR_SIGN_SHIFT 1 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL4_EQ_HFG_SQL_STEP_SIZE_MASK 0x1C +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL4_EQ_HFG_SQL_STEP_SIZE_SHIFT 2 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL5_EQ_HFG_SQL_BOUNCE_LIMIT_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL5_EQ_HFG_SQL_BOUNCE_LIMIT_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL5_EQ_HFG_SQL_LASTWR_AVG_MASK 0x30 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL5_EQ_HFG_SQL_LASTWR_AVG_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL5_EQ_HFG_SQL_LASTWR_FLOOR_MASK 0x40 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL5_EQ_HFG_SQL_LASTWR_FLOOR_SHIFT 6 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL6_EQ_HFG_SQL_LASTWR_ADJUST_MASK 0x1F +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_HFG_SQL_CTRL6_EQ_HFG_SQL_LASTWR_ADJUST_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL0_EQ_SQL_MAP_OPTION_RATE0_MASK 0x01 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL0_EQ_SQL_MAP_OPTION_RATE0_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL0_EQ_SQL_MAP_OPTION_RATE1_MASK 0x02 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL0_EQ_SQL_MAP_OPTION_RATE1_SHIFT 1 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL0_EQ_SQL_MAP_OPTION_RATE2_MASK 0x04 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL0_EQ_SQL_MAP_OPTION_RATE2_SHIFT 2 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL0_EQ_SQL_MAP_OPTION_RATE3_MASK 0x08 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL0_EQ_SQL_MAP_OPTION_RATE3_SHIFT 3 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL1_EQ_SQL_MAP0_RATE0_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL1_EQ_SQL_MAP0_RATE0_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL1_EQ_SQL_MAP1_RATE0_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL1_EQ_SQL_MAP1_RATE0_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL2_EQ_SQL_MAP2_RATE0_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL2_EQ_SQL_MAP2_RATE0_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL2_EQ_SQL_MAP3_RATE0_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL2_EQ_SQL_MAP3_RATE0_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL3_EQ_SQL_MAP4_RATE0_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL3_EQ_SQL_MAP4_RATE0_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL3_EQ_SQL_MAP5_RATE0_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL3_EQ_SQL_MAP5_RATE0_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL4_EQ_SQL_MAP6_RATE0_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL4_EQ_SQL_MAP6_RATE0_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL4_EQ_SQL_MAP7_RATE0_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL4_EQ_SQL_MAP7_RATE0_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL5_EQ_SQL_MAP8_RATE0_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL5_EQ_SQL_MAP8_RATE0_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL5_EQ_SQL_MAP9_RATE0_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL5_EQ_SQL_MAP9_RATE0_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL6_EQ_SQL_MAP10_RATE0_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL6_EQ_SQL_MAP10_RATE0_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL6_EQ_SQL_MAP11_RATE0_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL6_EQ_SQL_MAP11_RATE0_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL7_EQ_SQL_MAP0_RATE1_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL7_EQ_SQL_MAP0_RATE1_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL7_EQ_SQL_MAP1_RATE1_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL7_EQ_SQL_MAP1_RATE1_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL8_EQ_SQL_MAP2_RATE1_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL8_EQ_SQL_MAP2_RATE1_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL8_EQ_SQL_MAP3_RATE1_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL8_EQ_SQL_MAP3_RATE1_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL9_EQ_SQL_MAP4_RATE1_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL9_EQ_SQL_MAP4_RATE1_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL9_EQ_SQL_MAP5_RATE1_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL9_EQ_SQL_MAP5_RATE1_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL10_EQ_SQL_MAP6_RATE1_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL10_EQ_SQL_MAP6_RATE1_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL10_EQ_SQL_MAP7_RATE1_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL10_EQ_SQL_MAP7_RATE1_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL11_EQ_SQL_MAP8_RATE1_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL11_EQ_SQL_MAP8_RATE1_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL11_EQ_SQL_MAP9_RATE1_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL11_EQ_SQL_MAP9_RATE1_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL12_EQ_SQL_MAP10_RATE1_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL12_EQ_SQL_MAP10_RATE1_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL12_EQ_SQL_MAP11_RATE1_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL12_EQ_SQL_MAP11_RATE1_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL13_EQ_SQL_MAP0_RATE2_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL13_EQ_SQL_MAP0_RATE2_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL13_EQ_SQL_MAP1_RATE2_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL13_EQ_SQL_MAP1_RATE2_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL14_EQ_SQL_MAP2_RATE2_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL14_EQ_SQL_MAP2_RATE2_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL14_EQ_SQL_MAP3_RATE2_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL14_EQ_SQL_MAP3_RATE2_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL15_EQ_SQL_MAP4_RATE2_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL15_EQ_SQL_MAP4_RATE2_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL15_EQ_SQL_MAP5_RATE2_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL15_EQ_SQL_MAP5_RATE2_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL16_EQ_SQL_MAP6_RATE2_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL16_EQ_SQL_MAP6_RATE2_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL16_EQ_SQL_MAP7_RATE2_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL16_EQ_SQL_MAP7_RATE2_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL17_EQ_SQL_MAP8_RATE2_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL17_EQ_SQL_MAP8_RATE2_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL17_EQ_SQL_MAP9_RATE2_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL17_EQ_SQL_MAP9_RATE2_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL18_EQ_SQL_MAP10_RATE2_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL18_EQ_SQL_MAP10_RATE2_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL18_EQ_SQL_MAP11_RATE2_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL18_EQ_SQL_MAP11_RATE2_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL19_EQ_SQL_MAP0_RATE3_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL19_EQ_SQL_MAP0_RATE3_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL19_EQ_SQL_MAP1_RATE3_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL19_EQ_SQL_MAP1_RATE3_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL20_EQ_SQL_MAP2_RATE3_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL20_EQ_SQL_MAP2_RATE3_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL20_EQ_SQL_MAP3_RATE3_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL20_EQ_SQL_MAP3_RATE3_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL21_EQ_SQL_MAP4_RATE3_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL21_EQ_SQL_MAP4_RATE3_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL21_EQ_SQL_MAP5_RATE3_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL21_EQ_SQL_MAP5_RATE3_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL22_EQ_SQL_MAP6_RATE3_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL22_EQ_SQL_MAP6_RATE3_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL22_EQ_SQL_MAP7_RATE3_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL22_EQ_SQL_MAP7_RATE3_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL23_EQ_SQL_MAP8_RATE3_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL23_EQ_SQL_MAP8_RATE3_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL23_EQ_SQL_MAP9_RATE3_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL23_EQ_SQL_MAP9_RATE3_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL24_EQ_SQL_MAP10_RATE3_MASK 0x07 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL24_EQ_SQL_MAP10_RATE3_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL24_EQ_SQL_MAP11_RATE3_MASK 0x70 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_SQL_CTRL24_EQ_SQL_MAP11_RATE3_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL0_GN_APG_START_MASK 0x03 +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL0_GN_APG_START_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL1_GN_APG_VALUE_MAX_MASK 0x03 +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL1_GN_APG_VALUE_MAX_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL1_GN_APG_VALUE_MIN_MASK 0x0C +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL1_GN_APG_VALUE_MIN_SHIFT 2 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL2_GN_APG_WRWAIT_TIME_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL2_GN_APG_WRWAIT_TIME_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL2_GN_APG_MEASURE_TIMEOUT_DISABLE_MASK 0x80 +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL2_GN_APG_MEASURE_TIMEOUT_DISABLE_SHIFT 7 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL3_GN_APG_STEP_BY1_MASK 0x01 +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL3_GN_APG_STEP_BY1_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL3_GN_APG_ERROR_SIGN_MASK 0x02 +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL3_GN_APG_ERROR_SIGN_SHIFT 1 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL3_GN_APG_STEP_SIZE_MASK 0x0C +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL3_GN_APG_STEP_SIZE_SHIFT 2 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL4_GN_APG_BOUNCE_LIMIT_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL4_GN_APG_BOUNCE_LIMIT_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL4_GN_APG_LASTWR_AVG_MASK 0x30 +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL4_GN_APG_LASTWR_AVG_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL4_GN_APG_LASTWR_FLOOR_MASK 0x40 +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL4_GN_APG_LASTWR_FLOOR_SHIFT 6 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL5_GN_APG_LASTWR_ADJUST_MASK 0x03 +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL5_GN_APG_LASTWR_ADJUST_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL6_GN_APG_CCL_DELTA_MASK 0x03 +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL6_GN_APG_CCL_DELTA_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL6_GN_APG_CCL_MAX_MASK 0x0C +#define SERDES_25G_LANE_LEQ_REFCLK_GN_APG_CTRL6_GN_APG_CCL_MAX_SHIFT 2 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL0_EQ_LFG_START_MASK 0x1F +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL0_EQ_LFG_START_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL1_EQ_LFG_VALUE_MAX_MASK 0x1F +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL1_EQ_LFG_VALUE_MAX_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL2_EQ_LFG_VALUE_MIN_MASK 0x1F +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL2_EQ_LFG_VALUE_MIN_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL3_EQ_LFG_WRWAIT_TIME_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL3_EQ_LFG_WRWAIT_TIME_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL3_EQ_LFG_MEASURE_TIMEOUT_DISABLE_MASK 0x80 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL3_EQ_LFG_MEASURE_TIMEOUT_DISABLE_SHIFT 7 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL4_EQ_LFG_STEP_BY1_MASK 0x01 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL4_EQ_LFG_STEP_BY1_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL4_EQ_LFG_ERROR_SIGN_MASK 0x02 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL4_EQ_LFG_ERROR_SIGN_SHIFT 1 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL4_EQ_LFG_STEP_SIZE_MASK 0x1C +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL4_EQ_LFG_STEP_SIZE_SHIFT 2 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL5_EQ_LFG_BOUNCE_LIMIT_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL5_EQ_LFG_BOUNCE_LIMIT_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL5_EQ_LFG_LASTWR_AVG_MASK 0x30 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL5_EQ_LFG_LASTWR_AVG_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL5_EQ_LFG_LASTWR_FLOOR_MASK 0x40 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL5_EQ_LFG_LASTWR_FLOOR_SHIFT 6 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL6_EQ_LFG_LASTWR_ADJUST_MASK 0x1F +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL6_EQ_LFG_LASTWR_ADJUST_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL7_EQ_LFG_CCL_DELTA_MASK 0x1F +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL7_EQ_LFG_CCL_DELTA_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL8_EQ_LFG_CCL_MAX_MASK 0x1F +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_LFG_CTRL8_EQ_LFG_CCL_MAX_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL0_GNEQ_CCL_LFG_START_MASK 0x1F +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL0_GNEQ_CCL_LFG_START_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL1_GNEQ_CCL_LFG_VALUE_MAX_MASK 0x1F +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL1_GNEQ_CCL_LFG_VALUE_MAX_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL2_GNEQ_CCL_LFG_VALUE_MIN_MASK 0x1F +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL2_GNEQ_CCL_LFG_VALUE_MIN_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL3_GNEQ_CCL_LFG_WRWAIT_TIME_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL3_GNEQ_CCL_LFG_WRWAIT_TIME_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL3_GNEQ_CCL_LFG_MEASURE_TIMEOUT_DISABLE_MASK 0x80 +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL3_GNEQ_CCL_LFG_MEASURE_TIMEOUT_DISABLE_SHIFT 7 + +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL4_GNEQ_CCL_LFG_STEP_BY1_MASK 0x01 +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL4_GNEQ_CCL_LFG_STEP_BY1_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL4_GNEQ_CCL_LFG_ERROR_SIGN_MASK 0x02 +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL4_GNEQ_CCL_LFG_ERROR_SIGN_SHIFT 1 + +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL4_GNEQ_CCL_LFG_STEP_SIZE_MASK 0x1C +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL4_GNEQ_CCL_LFG_STEP_SIZE_SHIFT 2 + +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL5_GNEQ_CCL_LFG_BOUNCE_LIMIT_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL5_GNEQ_CCL_LFG_BOUNCE_LIMIT_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL5_GNEQ_CCL_LFG_LASTWR_AVG_MASK 0x30 +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL5_GNEQ_CCL_LFG_LASTWR_AVG_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL5_GNEQ_CCL_LFG_LASTWR_FLOOR_MASK 0x40 +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL5_GNEQ_CCL_LFG_LASTWR_FLOOR_SHIFT 6 + +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL6_GNEQ_CCL_LFG_LASTWR_ADJUST_MASK 0x1F +#define SERDES_25G_LANE_LEQ_REFCLK_GNEQ_CCL_LFG_CTRL6_GNEQ_CCL_LFG_LASTWR_ADJUST_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL0_EQ_MB_WRWAIT_TIME_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL0_EQ_MB_WRWAIT_TIME_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL0_EQ_MB_STEP_BY1_MASK 0x10 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL0_EQ_MB_STEP_BY1_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL1_EQ_MBF_START_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL1_EQ_MBF_START_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL1_EQ_MBG_START_MASK 0xF0 +#define SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL1_EQ_MBG_START_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL0_VSCAN_VALUE_MAX_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL0_VSCAN_VALUE_MAX_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL1_VSCAN_VALUE_MIN_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL1_VSCAN_VALUE_MIN_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL2_VSCAN_STEP_BY1_MASK 0x01 +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL2_VSCAN_STEP_BY1_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL2_VSCAN_ERROR_SIGN_MASK 0x02 +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL2_VSCAN_ERROR_SIGN_SHIFT 1 + +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL2_VSCAN_STEP_SIZE_MASK 0x3C +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL2_VSCAN_STEP_SIZE_SHIFT 2 + +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL3_VSCAN_BOUNCE_LIMIT_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL3_VSCAN_BOUNCE_LIMIT_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL3_VSCAN_LASTWR_AVG_MASK 0x30 +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL3_VSCAN_LASTWR_AVG_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL3_VSCAN_LASTWR_FLOOR_MASK 0x40 +#define SERDES_25G_LANE_LEQ_REFCLK_VSCAN_CTRL3_VSCAN_LASTWR_FLOOR_SHIFT 6 + +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL0_HSCAN_VALUE_MAX_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL0_HSCAN_VALUE_MAX_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL1_HSCAN_VALUE_MIN_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL1_HSCAN_VALUE_MIN_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL2_HSCAN_STEP_BY1_MASK 0x01 +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL2_HSCAN_STEP_BY1_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL2_HSCAN_ERROR_SIGN_MASK 0x02 +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL2_HSCAN_ERROR_SIGN_SHIFT 1 + +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL2_HSCAN_STEP_SIZE_MASK 0x3C +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL2_HSCAN_STEP_SIZE_SHIFT 2 + +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL3_HSCAN_BOUNCE_LIMIT_MASK 0x0F +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL3_HSCAN_BOUNCE_LIMIT_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL3_HSCAN_LASTWR_AVG_MASK 0x30 +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL3_HSCAN_LASTWR_AVG_SHIFT 4 + +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL3_HSCAN_LASTWR_FLOOR_MASK 0x40 +#define SERDES_25G_LANE_LEQ_REFCLK_HSCAN_CTRL3_HSCAN_LASTWR_FLOOR_SHIFT 6 + +#define SERDES_25G_LANE_LEQ_REFCLK_REF_THRESHOLD0_GN_APG_REF_N_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_REF_THRESHOLD0_GN_APG_REF_N_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_REF_THRESHOLD1_GN_APG_REF_P_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_REF_THRESHOLD1_GN_APG_REF_P_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_REF_THRESHOLD2_EQ_LFG_REF_N_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_REF_THRESHOLD2_EQ_LFG_REF_N_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_REF_THRESHOLD3_EQ_LFG_REF_P_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_REF_THRESHOLD3_EQ_LFG_REF_P_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EYE_PHASE0_EYE_PHASE_7_0_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_EYE_PHASE0_EYE_PHASE_7_0_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EYE_PHASE1_EYE_PHASE_8_MASK 0x01 +#define SERDES_25G_LANE_LEQ_REFCLK_EYE_PHASE1_EYE_PHASE_8_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EYE_PHASE1_EYE_PHASE_VALID_MASK 0x02 +#define SERDES_25G_LANE_LEQ_REFCLK_EYE_PHASE1_EYE_PHASE_VALID_SHIFT 1 + +#define SERDES_25G_LANE_LEQ_REFCLK_EYEMON_CTRL0_EYE_MONITOR_ODDEYE_MASK 0x01 +#define SERDES_25G_LANE_LEQ_REFCLK_EYEMON_CTRL0_EYE_MONITOR_ODDEYE_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_EYEMON_CTRL0_EYE_MONITOR_PATH1_MASK 0x02 +#define SERDES_25G_LANE_LEQ_REFCLK_EYEMON_CTRL0_EYE_MONITOR_PATH1_SHIFT 1 + +#define SERDES_25G_LANE_LEQ_REFCLK_EYEINTF_CTRL0_EYEINTF_INIT_TIMEOUT_DISABLE_MASK 0x40 +#define SERDES_25G_LANE_LEQ_REFCLK_EYEINTF_CTRL0_EYEINTF_INIT_TIMEOUT_DISABLE_SHIFT 6 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_REFCLK_SPARE0_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_REFCLK_SPARE0_SHIFT 0 + +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_REFCLK_SPARE1_MASK 0xFF +#define SERDES_25G_LANE_LEQ_REFCLK_LEQ_REFCLK_SPARE1_SHIFT 0 + +/********************************* DRV_REFCLK *********************************/ +#define SERDES_25G_LANE_DRV_REFCLK_BASE 0x380 + +#define SERDES_25G_LANE_DRV_AFE_PD_CTRL0_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x00) +#define SERDES_25G_LANE_DRV_AFE_RST_CTRL0_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x01) +#define SERDES_25G_LANE_DRV_AFE_CTRL1_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x03) +#define SERDES_25G_LANE_DRV_AFE_CTRL2_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x04) +#define SERDES_25G_LANE_DRV_AFE_CTRL3_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x05) +#define SERDES_25G_LANE_DRV_AFE_C1_CTRL0_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x06) +#define SERDES_25G_LANE_DRV_AFE_CM1_CTRL0_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x08) +#define SERDES_25G_LANE_DRV_AFE_ATT_CTRL0_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x09) +#define SERDES_25G_LANE_DRV_AFE_CALN_CTRL0_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x0A) +#define SERDES_25G_LANE_DRV_AFE_CALN_CTRL1_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x0B) +#define SERDES_25G_LANE_DRV_AFE_CALP_CTRL0_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x0C) +#define SERDES_25G_LANE_DRV_AFE_CALP_CTRL1_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x0D) +#define SERDES_25G_LANE_DRV_TXEQ_CTRL0_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x10) +#define SERDES_25G_LANE_DRV_TXEQ_STATUS0_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x11) +#define SERDES_25G_LANE_DRV_TXEQ_CTRL1_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x12) +#define SERDES_25G_LANE_DRV_TXEQ_CTRL2_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x13) +#define SERDES_25G_LANE_DRV_TXEQ_CTRL3_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x14) +#define SERDES_25G_LANE_DRV_TXEQ_CTRL4_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x15) +#define SERDES_25G_LANE_DRV_TXEQ_CTRL5_ADDR (SERDES_25G_LANE_DRV_REFCLK_BASE + 0x16) +/******************************************************************************* + * masks and shifts + ******************************************************************************/ +#define SERDES_25G_LANE_DRV_AFE_PD_CTRL0_PD_TXDRV_MASK 0x01 +#define SERDES_25G_LANE_DRV_AFE_PD_CTRL0_PD_TXDRV_SHIFT 0 + +#define SERDES_25G_LANE_DRV_AFE_PD_CTRL0_TXDRV_LP_IDLE_MASK 0x02 +#define SERDES_25G_LANE_DRV_AFE_PD_CTRL0_TXDRV_LP_IDLE_SHIFT 1 + +#define SERDES_25G_LANE_DRV_AFE_RST_CTRL0_RST_TXDRV_DIV2_N_MASK 0x01 +#define SERDES_25G_LANE_DRV_AFE_RST_CTRL0_RST_TXDRV_DIV2_N_SHIFT 0 + +#define SERDES_25G_LANE_DRV_AFE_CTRL1_TXDRV_SPARE_MASK 0xFF +#define SERDES_25G_LANE_DRV_AFE_CTRL1_TXDRV_SPARE_SHIFT 0 + +#define SERDES_25G_LANE_DRV_AFE_CTRL2_TXDRV_TOGGLE_EN_MASK 0x01 +#define SERDES_25G_LANE_DRV_AFE_CTRL2_TXDRV_TOGGLE_EN_SHIFT 0 + +#define SERDES_25G_LANE_DRV_AFE_CTRL2_TXDRV_CLK_DELAY_MASK 0x3E +#define SERDES_25G_LANE_DRV_AFE_CTRL2_TXDRV_CLK_DELAY_SHIFT 1 + +#define SERDES_25G_LANE_DRV_AFE_CTRL3_TXDRV_CO_POL_MASK 0x07 +#define SERDES_25G_LANE_DRV_AFE_CTRL3_TXDRV_CO_POL_SHIFT 0 + +#define SERDES_25G_LANE_DRV_AFE_C1_CTRL0_TXDRV_SEL_C1_P5_MASK 0x01 +#define SERDES_25G_LANE_DRV_AFE_C1_CTRL0_TXDRV_SEL_C1_P5_SHIFT 0 + +#define SERDES_25G_LANE_DRV_AFE_C1_CTRL0_TXDRV_SEL_C1_X1_MASK 0x02 +#define SERDES_25G_LANE_DRV_AFE_C1_CTRL0_TXDRV_SEL_C1_X1_SHIFT 1 + +#define SERDES_25G_LANE_DRV_AFE_C1_CTRL0_TXDRV_SEL_C1_X2_MASK 0x1C +#define SERDES_25G_LANE_DRV_AFE_C1_CTRL0_TXDRV_SEL_C1_X2_SHIFT 2 + +#define SERDES_25G_LANE_DRV_AFE_C1_CTRL0_TXDRV_SEL_CXC1_X1_MASK 0x20 +#define SERDES_25G_LANE_DRV_AFE_C1_CTRL0_TXDRV_SEL_CXC1_X1_SHIFT 5 + +#define SERDES_25G_LANE_DRV_AFE_C1_CTRL0_TXDRV_SEL_CXC1_X2_MASK 0xC0 +#define SERDES_25G_LANE_DRV_AFE_C1_CTRL0_TXDRV_SEL_CXC1_X2_SHIFT 6 + +#define SERDES_25G_LANE_DRV_AFE_CM1_CTRL0_TXDRV_SEL_CM1_P5_MASK 0x01 +#define SERDES_25G_LANE_DRV_AFE_CM1_CTRL0_TXDRV_SEL_CM1_P5_SHIFT 0 + +#define SERDES_25G_LANE_DRV_AFE_CM1_CTRL0_TXDRV_SEL_CM1_X1_MASK 0x02 +#define SERDES_25G_LANE_DRV_AFE_CM1_CTRL0_TXDRV_SEL_CM1_X1_SHIFT 1 + +#define SERDES_25G_LANE_DRV_AFE_CM1_CTRL0_TXDRV_SEL_CM1_X2_MASK 0x0C +#define SERDES_25G_LANE_DRV_AFE_CM1_CTRL0_TXDRV_SEL_CM1_X2_SHIFT 2 + +#define SERDES_25G_LANE_DRV_AFE_CM1_CTRL0_TXDRV_SEL_CXCM1_X2_MASK 0x10 +#define SERDES_25G_LANE_DRV_AFE_CM1_CTRL0_TXDRV_SEL_CXCM1_X2_SHIFT 4 + +#define SERDES_25G_LANE_DRV_AFE_ATT_CTRL0_TXDRV_SEL_ATT_X1_MASK 0x07 +#define SERDES_25G_LANE_DRV_AFE_ATT_CTRL0_TXDRV_SEL_ATT_X1_SHIFT 0 + +#define SERDES_25G_LANE_DRV_AFE_ATT_CTRL0_TXDRV_SEL_ATT_X2_MASK 0xF8 +#define SERDES_25G_LANE_DRV_AFE_ATT_CTRL0_TXDRV_SEL_ATT_X2_SHIFT 3 + +#define SERDES_25G_LANE_DRV_AFE_CALN_CTRL0_TXDRV_SEL_CXN_X1_MASK 0x07 +#define SERDES_25G_LANE_DRV_AFE_CALN_CTRL0_TXDRV_SEL_CXN_X1_SHIFT 0 + +#define SERDES_25G_LANE_DRV_AFE_CALN_CTRL0_TXDRV_SEL_FIXEDCXN_X1_MASK 0x18 +#define SERDES_25G_LANE_DRV_AFE_CALN_CTRL0_TXDRV_SEL_FIXEDCXN_X1_SHIFT 3 + +#define SERDES_25G_LANE_DRV_AFE_CALN_CTRL1_TXDRV_SEL_CXN_X2_MASK 0x1F +#define SERDES_25G_LANE_DRV_AFE_CALN_CTRL1_TXDRV_SEL_CXN_X2_SHIFT 0 + +#define SERDES_25G_LANE_DRV_AFE_CALN_CTRL1_TXDRV_SEL_FIXEDCXN_XP5_MASK 0x60 +#define SERDES_25G_LANE_DRV_AFE_CALN_CTRL1_TXDRV_SEL_FIXEDCXN_XP5_SHIFT 5 + +#define SERDES_25G_LANE_DRV_AFE_CALP_CTRL0_TXDRV_SEL_CXP_X1_MASK 0x07 +#define SERDES_25G_LANE_DRV_AFE_CALP_CTRL0_TXDRV_SEL_CXP_X1_SHIFT 0 + +#define SERDES_25G_LANE_DRV_AFE_CALP_CTRL0_TXDRV_SEL_FIXEDCXP_X1_MASK 0x18 +#define SERDES_25G_LANE_DRV_AFE_CALP_CTRL0_TXDRV_SEL_FIXEDCXP_X1_SHIFT 3 + +#define SERDES_25G_LANE_DRV_AFE_CALP_CTRL1_TXDRV_SEL_CXP_X2_MASK 0x1F +#define SERDES_25G_LANE_DRV_AFE_CALP_CTRL1_TXDRV_SEL_CXP_X2_SHIFT 0 + +#define SERDES_25G_LANE_DRV_AFE_CALP_CTRL1_TXDRV_SEL_FIXEDCXP_XP5_MASK 0x60 +#define SERDES_25G_LANE_DRV_AFE_CALP_CTRL1_TXDRV_SEL_FIXEDCXP_XP5_SHIFT 5 + +#define SERDES_25G_LANE_DRV_TXEQ_CTRL0_REQ_MASK 0x01 +#define SERDES_25G_LANE_DRV_TXEQ_CTRL0_REQ_SHIFT 0 + +#define SERDES_25G_LANE_DRV_TXEQ_STATUS0_ACK_MASK 0x01 +#define SERDES_25G_LANE_DRV_TXEQ_STATUS0_ACK_SHIFT 0 + +#define SERDES_25G_LANE_DRV_TXEQ_CTRL1_TXEQ_C1_MASK 0x1F +#define SERDES_25G_LANE_DRV_TXEQ_CTRL1_TXEQ_C1_SHIFT 0 + +#define SERDES_25G_LANE_DRV_TXEQ_CTRL2_TXEQ_C2_MASK 0x03 +#define SERDES_25G_LANE_DRV_TXEQ_CTRL2_TXEQ_C2_SHIFT 0 + +#define SERDES_25G_LANE_DRV_TXEQ_CTRL3_TXEQ_CM1_MASK 0x0F +#define SERDES_25G_LANE_DRV_TXEQ_CTRL3_TXEQ_CM1_SHIFT 0 + +#define SERDES_25G_LANE_DRV_TXEQ_CTRL4_TXEQ_1LSB_MODE_MASK 0x01 +#define SERDES_25G_LANE_DRV_TXEQ_CTRL4_TXEQ_1LSB_MODE_SHIFT 0 + +#define SERDES_25G_LANE_DRV_TXEQ_CTRL4_SWING_1LSB_MODE_MASK 0x02 +#define SERDES_25G_LANE_DRV_TXEQ_CTRL4_SWING_1LSB_MODE_SHIFT 1 + +#define SERDES_25G_LANE_DRV_TXEQ_CTRL5_DRV_SWING_MASK 0x0F +#define SERDES_25G_LANE_DRV_TXEQ_CTRL5_DRV_SWING_SHIFT 0 + +/********************************* DFE REFCLK *********************************/ +#define SERDES_25G_LANE_DFE_REFCLK_BASE 0x400 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_PD_CTRL0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x00) +#define SERDES_25G_LANE_DFE_REFCLK_AFE_PD_CTRL1_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x01) +#define SERDES_25G_LANE_DFE_REFCLK_AFE_PD_CTRL2_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x02) +#define SERDES_25G_LANE_DFE_REFCLK_AFE_RST_CTRL0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x04) +#define SERDES_25G_LANE_DFE_REFCLK_AFE_TOGGLE_CTRL0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x06) +#define SERDES_25G_LANE_DFE_REFCLK_AFE_MUTE_CTRL0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x0A) +#define SERDES_25G_LANE_DFE_REFCLK_AFE_CLK_CTRL0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x0C) +#define SERDES_25G_LANE_DFE_REFCLK_AFE_EYECLK_CTRL0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x0E) +#define SERDES_25G_LANE_DFE_REFCLK_AFE_CML_CTRL0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x10) +#define SERDES_25G_LANE_DFE_REFCLK_AFE_MISC_CTRL0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x12) +#define SERDES_25G_LANE_DFE_REFCLK_AFE_SPARE_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x14) +#define SERDES_25G_LANE_DFE_REFCLK_AFE_QSAMPLE_STATUS0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x16) +#define SERDES_25G_LANE_DFE_REFCLK_EYE_VSCAN_CTRL0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x18) +#define SERDES_25G_LANE_DFE_REFCLK_EYE_VSCAN_CTRL1_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x19) +#define SERDES_25G_LANE_DFE_REFCLK_EYE_TAP1_CTRL0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x1B) +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x20) +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL1_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x21) +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL2_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x22) +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL3_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x23) +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL4_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x24) +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL5_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x25) +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL6_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x26) +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL7_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x27) +#define SERDES_25G_LANE_DFE_REFCLK_FSM_STATUS0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x28) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_CTRL0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x2A) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x2B) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL1_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x2C) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL2_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x2D) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL3_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x2E) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL4_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x2F) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL5_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x30) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL6_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x31) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL7_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x32) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x33) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL1_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x34) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL2_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x35) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL3_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x36) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL4_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x37) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL5_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x38) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL6_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x39) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL7_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x3A) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x3B) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS1_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x3C) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS2_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x3D) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS3_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x3E) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS4_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x3F) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS5_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x40) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS6_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x41) +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS7_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x42) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x50) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL1_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x51) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL2_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x52) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x53) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL1_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x54) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL2_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x55) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL3_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x56) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL4_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x57) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL5_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x58) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL6_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x59) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL7_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x5A) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x5B) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS1_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x5C) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS2_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x5D) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS3_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x5E) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS4_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x5F) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS5_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x60) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS6_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x61) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS7_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x62) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_SOURCE_CTRL0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x63) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS0_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x64) +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS1_ADDR (SERDES_25G_LANE_DFE_REFCLK_BASE + 0x65) +/******************************************************************************* + * masks and shifts + ******************************************************************************/ +#define SERDES_25G_LANE_DFE_REFCLK_AFE_PD_CTRL0_PD_RXDFE_MASK 0x01 +#define SERDES_25G_LANE_DFE_REFCLK_AFE_PD_CTRL0_PD_RXDFE_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_PD_CTRL0_PD_RXDFE_TAP_MASK 0x3E +#define SERDES_25G_LANE_DFE_REFCLK_AFE_PD_CTRL0_PD_RXDFE_TAP_SHIFT 1 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_PD_CTRL1_PD_RXDFE_EVEN_PATH_MASK 0x03 +#define SERDES_25G_LANE_DFE_REFCLK_AFE_PD_CTRL1_PD_RXDFE_EVEN_PATH_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_PD_CTRL1_PD_RXDFE_ODD_PATH_MASK 0x0C +#define SERDES_25G_LANE_DFE_REFCLK_AFE_PD_CTRL1_PD_RXDFE_ODD_PATH_SHIFT 2 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_PD_CTRL2_PD_RXDFE_EYE_EVEN_MASK 0x07 +#define SERDES_25G_LANE_DFE_REFCLK_AFE_PD_CTRL2_PD_RXDFE_EYE_EVEN_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_PD_CTRL2_PD_RXDFE_EYE_ODD_MASK 0x38 +#define SERDES_25G_LANE_DFE_REFCLK_AFE_PD_CTRL2_PD_RXDFE_EYE_ODD_SHIFT 3 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_RST_CTRL0_RST_RXDFE_N_MASK 0x01 +#define SERDES_25G_LANE_DFE_REFCLK_AFE_RST_CTRL0_RST_RXDFE_N_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_TOGGLE_CTRL0_RXDFE_TOGGLE_EN_MASK 0x01 +#define SERDES_25G_LANE_DFE_REFCLK_AFE_TOGGLE_CTRL0_RXDFE_TOGGLE_EN_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_MUTE_CTRL0_RXDFE_MUTE_EYE_EVEN_MASK 0x01 +#define SERDES_25G_LANE_DFE_REFCLK_AFE_MUTE_CTRL0_RXDFE_MUTE_EYE_EVEN_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_MUTE_CTRL0_RXDFE_MUTE_EYE_ODD_MASK 0x02 +#define SERDES_25G_LANE_DFE_REFCLK_AFE_MUTE_CTRL0_RXDFE_MUTE_EYE_ODD_SHIFT 1 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_MUTE_CTRL0_RXDFE_EDGE_MUTE_MASK 0x0C +#define SERDES_25G_LANE_DFE_REFCLK_AFE_MUTE_CTRL0_RXDFE_EDGE_MUTE_SHIFT 2 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_CLK_CTRL0_RXDFE_CLK_DELAY_MASK 0x0F +#define SERDES_25G_LANE_DFE_REFCLK_AFE_CLK_CTRL0_RXDFE_CLK_DELAY_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_CLK_CTRL0_RXDFE_CLKDIV_OVR_MASK 0x30 +#define SERDES_25G_LANE_DFE_REFCLK_AFE_CLK_CTRL0_RXDFE_CLKDIV_OVR_SHIFT 4 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_EYECLK_CTRL0_RXDFE_EYECLK_DELAY_MASK 0x0F +#define SERDES_25G_LANE_DFE_REFCLK_AFE_EYECLK_CTRL0_RXDFE_EYECLK_DELAY_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_EYECLK_CTRL0_RXDFE_CLKDIVEYE_OVR_MASK 0x30 +#define SERDES_25G_LANE_DFE_REFCLK_AFE_EYECLK_CTRL0_RXDFE_CLKDIVEYE_OVR_SHIFT 4 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_EYECLK_CTRL0_RXDFE_EYERESAMP_ADJ_MASK 0xC0 +#define SERDES_25G_LANE_DFE_REFCLK_AFE_EYECLK_CTRL0_RXDFE_EYERESAMP_ADJ_SHIFT 6 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_CML_CTRL0_RXDFE_CMLI_MASK 0x0F +#define SERDES_25G_LANE_DFE_REFCLK_AFE_CML_CTRL0_RXDFE_CMLI_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_CML_CTRL0_RXDFE_CMLR_MASK 0x30 +#define SERDES_25G_LANE_DFE_REFCLK_AFE_CML_CTRL0_RXDFE_CMLR_SHIFT 4 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_CML_CTRL0_RXDFE_CMLR_LTCH_MASK 0x40 +#define SERDES_25G_LANE_DFE_REFCLK_AFE_CML_CTRL0_RXDFE_CMLR_LTCH_SHIFT 6 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_MISC_CTRL0_RXDFE_SUMGAIN_MASK 0x01 +#define SERDES_25G_LANE_DFE_REFCLK_AFE_MISC_CTRL0_RXDFE_SUMGAIN_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_MISC_CTRL0_RXDFE_LDR_MASK 0x06 +#define SERDES_25G_LANE_DFE_REFCLK_AFE_MISC_CTRL0_RXDFE_LDR_SHIFT 1 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_SPARE_RXDFE_SPARE_MASK 0xFF +#define SERDES_25G_LANE_DFE_REFCLK_AFE_SPARE_RXDFE_SPARE_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_QSAMPLE_STATUS0_RXDFE_CLKDIV_QSAMPLE_MASK 0x01 +#define SERDES_25G_LANE_DFE_REFCLK_AFE_QSAMPLE_STATUS0_RXDFE_CLKDIV_QSAMPLE_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_AFE_QSAMPLE_STATUS0_RXDFE_CLKDIVEYE_QSAMPLE_MASK 0x1E +#define SERDES_25G_LANE_DFE_REFCLK_AFE_QSAMPLE_STATUS0_RXDFE_CLKDIVEYE_QSAMPLE_SHIFT 1 + +#define SERDES_25G_LANE_DFE_REFCLK_EYE_VSCAN_CTRL0_MAG_MASK 0xFF +#define SERDES_25G_LANE_DFE_REFCLK_EYE_VSCAN_CTRL0_MAG_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_EYE_VSCAN_CTRL1_POL_MASK 0x01 +#define SERDES_25G_LANE_DFE_REFCLK_EYE_VSCAN_CTRL1_POL_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_EYE_TAP1_CTRL0_MAG_MASK 0x1F +#define SERDES_25G_LANE_DFE_REFCLK_EYE_TAP1_CTRL0_MAG_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_EYE_TAP1_CTRL0_POL_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_EYE_TAP1_CTRL0_POL_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL0_REQ_MASK 0x01 +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL0_REQ_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL0_CMD_MASK 0x3E +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL0_CMD_SHIFT 1 + +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL0_FINISH_MASK 0x40 +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL0_FINISH_SHIFT 6 + +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL0_DRIVE_BEFORE_EVAL_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL0_DRIVE_BEFORE_EVAL_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL1_NEXT_STATE_MASK 0x0F +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL1_NEXT_STATE_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL1_CTRL_EN_MASK 0x10 +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL1_CTRL_EN_SHIFT 4 + +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL2_WAIT_1_TIMER7_0_MASK 0xFF +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL2_WAIT_1_TIMER7_0_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL3_WAIT_1_TIMER9_8_MASK 0x03 +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL3_WAIT_1_TIMER9_8_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL4_WAIT_2_TIMER7_0_MASK 0xFF +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL4_WAIT_2_TIMER7_0_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL5_WAIT_2_TIMER9_8_MASK 0x03 +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL5_WAIT_2_TIMER9_8_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL6_TAP_DELAY_7_0_MASK 0xFF +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL6_TAP_DELAY_7_0_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL7_TAP_DELAY_9_8_MASK 0x03 +#define SERDES_25G_LANE_DFE_REFCLK_FSM_CTRL7_TAP_DELAY_9_8_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_FSM_STATUS0_ACK_MASK 0x01 +#define SERDES_25G_LANE_DFE_REFCLK_FSM_STATUS0_ACK_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_FSM_STATUS0_SLICER_OFST_ACK_MASK 0x02 +#define SERDES_25G_LANE_DFE_REFCLK_FSM_STATUS0_SLICER_OFST_ACK_SHIFT 1 + +#define SERDES_25G_LANE_DFE_REFCLK_FSM_STATUS0_ERR_FUNC_ACK_MASK 0x04 +#define SERDES_25G_LANE_DFE_REFCLK_FSM_STATUS0_ERR_FUNC_ACK_SHIFT 2 + +#define SERDES_25G_LANE_DFE_REFCLK_FSM_STATUS0_AFE_DRV_ACK_MASK 0x08 +#define SERDES_25G_LANE_DFE_REFCLK_FSM_STATUS0_AFE_DRV_ACK_SHIFT 3 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_CTRL0_TAP1_EVEN0_EN_MASK 0x01 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_CTRL0_TAP1_EVEN0_EN_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_CTRL0_TAP1_EVEN1_EN_MASK 0x02 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_CTRL0_TAP1_EVEN1_EN_SHIFT 1 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_CTRL0_TAP1_ODD0_EN_MASK 0x04 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_CTRL0_TAP1_ODD0_EN_SHIFT 2 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_CTRL0_TAP1_ODD1_EN_MASK 0x08 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_CTRL0_TAP1_ODD1_EN_SHIFT 3 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_CTRL0_TAP2_EN_MASK 0x10 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_CTRL0_TAP2_EN_SHIFT 4 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_CTRL0_TAP3_EN_MASK 0x20 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_CTRL0_TAP3_EN_SHIFT 5 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_CTRL0_TAP4_EN_MASK 0x40 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_CTRL0_TAP4_EN_SHIFT 6 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_CTRL0_TAP5_EN_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_CTRL0_TAP5_EN_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL0_TAP1_EVEN0_MASK 0x1F +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL0_TAP1_EVEN0_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL0_TAP1_EVEN0_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL0_TAP1_EVEN0_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL1_TAP1_EVEN1_MASK 0x1F +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL1_TAP1_EVEN1_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL1_TAP1_EVEN1_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL1_TAP1_EVEN1_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL2_TAP1_ODD0_MASK 0x1F +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL2_TAP1_ODD0_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL2_TAP1_ODD0_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL2_TAP1_ODD0_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL3_TAP1_ODD1_MASK 0x1F +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL3_TAP1_ODD1_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL3_TAP1_ODD1_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL3_TAP1_ODD1_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL4_TAP2_MASK 0x0F +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL4_TAP2_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL4_TAP2_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL4_TAP2_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL5_TAP3_MASK 0x07 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL5_TAP3_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL5_TAP3_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL5_TAP3_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL6_TAP4_MASK 0x07 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL6_TAP4_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL6_TAP4_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL6_TAP4_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL7_TAP5_MASK 0x07 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL7_TAP5_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL7_TAP5_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_START_VAL_CTRL7_TAP5_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL0_TAP1_EVEN0_MASK 0x1F +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL0_TAP1_EVEN0_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL0_TAP1_EVEN0_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL0_TAP1_EVEN0_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL1_TAP1_EVEN1_MASK 0x1F +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL1_TAP1_EVEN1_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL1_TAP1_EVEN1_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL1_TAP1_EVEN1_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL2_TAP1_ODD0_MASK 0x1F +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL2_TAP1_ODD0_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL2_TAP1_ODD0_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL2_TAP1_ODD0_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL3_TAP1_ODD1_MASK 0x1F +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL3_TAP1_ODD1_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL3_TAP1_ODD1_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL3_TAP1_ODD1_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL4_TAP2_MASK 0x0F +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL4_TAP2_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL4_TAP2_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL4_TAP2_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL5_TAP3_MASK 0x07 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL5_TAP3_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL5_TAP3_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL5_TAP3_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL6_TAP4_MASK 0x07 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL6_TAP4_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL6_TAP4_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL6_TAP4_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL7_TAP5_MASK 0x07 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL7_TAP5_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL7_TAP5_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_LOAD_VAL_CTRL7_TAP5_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS0_TAP1_EVEN0_MASK 0x1F +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS0_TAP1_EVEN0_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS0_TAP1_EVEN0_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS0_TAP1_EVEN0_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS1_TAP1_EVEN1_MASK 0x1F +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS1_TAP1_EVEN1_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS1_TAP1_EVEN1_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS1_TAP1_EVEN1_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS2_TAP1_ODD0_MASK 0x1F +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS2_TAP1_ODD0_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS2_TAP1_ODD0_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS2_TAP1_ODD0_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS3_TAP1_ODD1_MASK 0x1F +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS3_TAP1_ODD1_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS3_TAP1_ODD1_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS3_TAP1_ODD1_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS4_TAP2_MASK 0x0F +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS4_TAP2_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS4_TAP2_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS4_TAP2_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS5_TAP3_MASK 0x07 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS5_TAP3_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS5_TAP3_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS5_TAP3_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS6_TAP4_MASK 0x07 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS6_TAP4_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS6_TAP4_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS6_TAP4_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS7_TAP5_MASK 0x07 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS7_TAP5_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS7_TAP5_POLARITY_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS7_TAP5_POLARITY_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL0_EVEN0_DATA_EN_MASK 0x01 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL0_EVEN0_DATA_EN_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL0_EVEN1_DATA_EN_MASK 0x02 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL0_EVEN1_DATA_EN_SHIFT 1 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL0_ODD0_DATA_EN_MASK 0x04 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL0_ODD0_DATA_EN_SHIFT 2 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL0_ODD1_DATA_EN_MASK 0x08 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL0_ODD1_DATA_EN_SHIFT 3 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL0_EVEN_EDGE_EN_MASK 0x10 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL0_EVEN_EDGE_EN_SHIFT 4 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL0_ODD_EDGE_EN_MASK 0x20 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL0_ODD_EDGE_EN_SHIFT 5 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL0_EVEN_EYE_EN_MASK 0x40 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL0_EVEN_EYE_EN_SHIFT 6 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL0_ODD_EYE_EN_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL0_ODD_EYE_EN_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL1_LIMIT_MASK 0x1F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL1_LIMIT_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL2_MAX_BOUNCES_MASK 0x0F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_CTRL2_MAX_BOUNCES_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL0_EVEN0_DATA_MASK 0x3F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL0_EVEN0_DATA_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL1_EVEN1_DATA_MASK 0x3F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL1_EVEN1_DATA_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL2_ODD0_DATA_MASK 0x3F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL2_ODD0_DATA_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL3_ODD1_DATA_MASK 0x3F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL3_ODD1_DATA_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL4_EVEN_EDGE_MASK 0x3F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL4_EVEN_EDGE_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL5_ODD_EDGE_MASK 0x3F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL5_ODD_EDGE_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL6_EVEN_EYE_MASK 0x3F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL6_EVEN_EYE_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL7_ODD_EYE_MASK 0x3F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_VAL_CTRL7_ODD_EYE_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS0_EVEN0_DATA_MASK 0x3F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS0_EVEN0_DATA_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS1_EVEN1_DATA_MASK 0x3F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS1_EVEN1_DATA_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS2_ODD0_DATA_MASK 0x3F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS2_ODD0_DATA_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS3_ODD1_DATA_MASK 0x3F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS3_ODD1_DATA_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS4_EVEN_EDGE_MASK 0x3F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS4_EVEN_EDGE_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS5_ODD_EDGE_MASK 0x3F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS5_ODD_EDGE_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS6_EVEN_EYE_MASK 0x3F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS6_EVEN_EYE_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS7_ODD_EYE_MASK 0x3F +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_VAL_STATUS7_ODD_EYE_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_SOURCE_CTRL0_EVEN0_DATA_MASK 0x01 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_SOURCE_CTRL0_EVEN0_DATA_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_SOURCE_CTRL0_EVEN1_DATA_MASK 0x02 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_SOURCE_CTRL0_EVEN1_DATA_SHIFT 1 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_SOURCE_CTRL0_ODD0_DATA_MASK 0x04 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_SOURCE_CTRL0_ODD0_DATA_SHIFT 2 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_SOURCE_CTRL0_ODD1_DATA_MASK 0x08 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_SOURCE_CTRL0_ODD1_DATA_SHIFT 3 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_SOURCE_CTRL0_EVEN_EDGE_MASK 0x10 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_SOURCE_CTRL0_EVEN_EDGE_SHIFT 4 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_SOURCE_CTRL0_ODD_EDGE_MASK 0x20 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_SOURCE_CTRL0_ODD_EDGE_SHIFT 5 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_SOURCE_CTRL0_EVEN_EYE_MASK 0x40 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_SOURCE_CTRL0_EVEN_EYE_SHIFT 6 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_SOURCE_CTRL0_ODD_EYE_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_LOAD_SOURCE_CTRL0_ODD_EYE_SHIFT 7 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS0_ERR_MASK 0x01 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS0_ERR_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS0_INC_MASK 0x02 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS0_INC_SHIFT 1 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS0_DEC_MASK 0x04 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS0_DEC_SHIFT 2 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS1_EVEN0_DATA_MASK 0x01 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS1_EVEN0_DATA_SHIFT 0 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS1_EVEN1_DATA_MASK 0x02 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS1_EVEN1_DATA_SHIFT 1 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS1_ODD0_DATA_MASK 0x04 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS1_ODD0_DATA_SHIFT 2 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS1_ODD1_DATA_MASK 0x08 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS1_ODD1_DATA_SHIFT 3 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS1_EVEN_EDGE_MASK 0x10 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS1_EVEN_EDGE_SHIFT 4 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS1_ODD_EDGE_MASK 0x20 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS1_ODD_EDGE_SHIFT 5 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS1_EVEN_EYE_MASK 0x40 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS1_EVEN_EYE_SHIFT 6 + +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS1_ODD_EYE_MASK 0x80 +#define SERDES_25G_LANE_DFE_REFCLK_SLICER_OFST_STATUS1_ODD_EYE_SHIFT 7 + +/********************************** LOS REFCLK **********************************/ +#define SERDES_25G_LANE_LOS_REFCLK_BASE 0x500 + +#define SERDES_25G_LANE_LOS_REFCLK_RUN_LENGTH_CTRL0_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x00) +#define SERDES_25G_LANE_LOS_REFCLK_RUN_LENGTH_CTRL1_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x01) +#define SERDES_25G_LANE_LOS_REFCLK_RUN_LENGTH_STATUS0_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x02) +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL0_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x10) +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL1_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x11) +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL2_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x12) +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL3_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x13) +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL4_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x14) +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL5_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x15) +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL6_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x16) +#define SERDES_25G_LANE_LOS_REFCLK_TIMED_MODE_CTRL0_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x20) +#define SERDES_25G_LANE_LOS_REFCLK_TIMED_MODE_CTRL1_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x21) +#define SERDES_25G_LANE_LOS_REFCLK_TIMED_MODE_CTRL2_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x22) +#define SERDES_25G_LANE_LOS_REFCLK_TIMED_MODE_CTRL3_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x23) +#define SERDES_25G_LANE_LOS_REFCLK_TIMED_MODE_CTRL4_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x24) +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL0_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x30) +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL1_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x31) +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL2_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x32) +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL3_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x33) +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL0_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x40) +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL1_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x41) +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL2_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x42) +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL3_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x43) +#define SERDES_25G_LANE_LOS_REFCLK_EYE_CTRL_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x46) +#define SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_CTRL0_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x51) +#define SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_STATUS0_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x59) +#define SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_STATUS1_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x60) +#define SERDES_25G_LANE_LOS_REFCLK_CTRL0_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x70) +#define SERDES_25G_LANE_LOS_REFCLK_STATUS0_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x71) +#define SERDES_25G_LANE_LOS_REFCLK_AFE_SPARE_CTRL0_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x72) +#define SERDES_25G_LANE_LOS_REFCLK_AFE_PD_CTRL0_ADDR (SERDES_25G_LANE_LOS_REFCLK_BASE + 0x73) +/******************************************************************************* + * masks and shifts + ******************************************************************************/ + +#define SERDES_25G_LANE_LOS_REFCLK_RUN_LENGTH_CTRL0_EN_MASK 0x01 +#define SERDES_25G_LANE_LOS_REFCLK_RUN_LENGTH_CTRL0_EN_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_RUN_LENGTH_CTRL1_ASSERT_THRESHOLD_MASK 0xFF +#define SERDES_25G_LANE_LOS_REFCLK_RUN_LENGTH_CTRL1_ASSERT_THRESHOLD_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_RUN_LENGTH_STATUS0_EXCEED_MASK 0x01 +#define SERDES_25G_LANE_LOS_REFCLK_RUN_LENGTH_STATUS0_EXCEED_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_RUN_LENGTH_STATUS0_EXCEED_STICKY_MASK 0x02 +#define SERDES_25G_LANE_LOS_REFCLK_RUN_LENGTH_STATUS0_EXCEED_STICKY_SHIFT 1 + +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL0_ASSERT_THRESHOLD_7_0_MASK 0xFF +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL0_ASSERT_THRESHOLD_7_0_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL1_ASSERT_THRESHOLD_15_8_MASK 0xFF +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL1_ASSERT_THRESHOLD_15_8_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL2_DEASSERT_THRESHOLD_7_0_MASK 0xFF +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL2_DEASSERT_THRESHOLD_7_0_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL3_DEASSERT_THRESHOLD_15_8_MASK 0xFF +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL3_DEASSERT_THRESHOLD_15_8_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL4_DEASSERT_THRESHOLD_23_16_MASK 0xFF +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL4_DEASSERT_THRESHOLD_23_16_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL5_DEASSERT_THRESHOLD_25_24_MASK 0x03 +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL5_DEASSERT_THRESHOLD_25_24_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL6_EN_MASK 0x01 +#define SERDES_25G_LANE_LOS_REFCLK_FILTER_CTRL6_EN_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_TIMED_MODE_CTRL0_EN_MASK 0x01 +#define SERDES_25G_LANE_LOS_REFCLK_TIMED_MODE_CTRL0_EN_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_TIMED_MODE_CTRL1_PERIOD_7_0_MASK 0xFF +#define SERDES_25G_LANE_LOS_REFCLK_TIMED_MODE_CTRL1_PERIOD_7_0_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_TIMED_MODE_CTRL2_PERIOD_15_8_MASK 0xFF +#define SERDES_25G_LANE_LOS_REFCLK_TIMED_MODE_CTRL2_PERIOD_15_8_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_TIMED_MODE_CTRL3_PERIOD_23_16_MASK 0xFF +#define SERDES_25G_LANE_LOS_REFCLK_TIMED_MODE_CTRL3_PERIOD_23_16_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_TIMED_MODE_CTRL4_PERIOD_25_24_MASK 0x03 +#define SERDES_25G_LANE_LOS_REFCLK_TIMED_MODE_CTRL4_PERIOD_25_24_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL0_LOS_O_EN_MASK 0x01 +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL0_LOS_O_EN_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL0_LOS_O_VALUE_MASK 0x10 +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL0_LOS_O_VALUE_SHIFT 4 + +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL1_LOS_I_EN_MASK 0x01 +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL1_LOS_I_EN_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL1_LOS_I_VALUE_MASK 0x10 +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL1_LOS_I_VALUE_SHIFT 4 + +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL2_LOS_OFFSET_VALUE_MASK 0x3F +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL2_LOS_OFFSET_VALUE_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL2_LOS_OFFSET_EN_MASK 0x40 +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL2_LOS_OFFSET_EN_SHIFT 6 + +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL3_AGC_OFFSET_VALUE_MASK 0x3F +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL3_AGC_OFFSET_VALUE_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL3_AGC_OFFSET_EN_MASK 0x40 +#define SERDES_25G_LANE_LOS_REFCLK_OVERRIDE_CTRL3_AGC_OFFSET_EN_SHIFT 6 + +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL0_BANDWIDTH_MASK 0x01 +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL0_BANDWIDTH_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL0_HYSTERESIS_MASK 0x0E +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL0_HYSTERESIS_SHIFT 1 + +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL0_ENVDET_BYP_MASK 0x10 +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL0_ENVDET_BYP_SHIFT 4 + +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL1_GAIN_MASK 0x01 +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL1_GAIN_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL1_LOS_INVERT_MASK 0x02 +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL1_LOS_INVERT_SHIFT 1 + +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL1_AGC_INVERT_MASK 0x04 +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL1_AGC_INVERT_SHIFT 2 + +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL1_THRESHOLD_MASK 0x78 +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL1_THRESHOLD_SHIFT 3 + +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL2_MODE_SWITCH_WAIT_7_0_MASK 0xFF +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL2_MODE_SWITCH_WAIT_7_0_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL3_MODE_SWITCH_WAIT_15_8_MASK 0xFF +#define SERDES_25G_LANE_LOS_REFCLK_COMPARATOR_CTRL3_MODE_SWITCH_WAIT_15_8_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_EYE_CTRL_EYE_DATA_PARITY_MASK 0x01 +#define SERDES_25G_LANE_LOS_REFCLK_EYE_CTRL_EYE_DATA_PARITY_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_CTRL0_EN_MASK 0x01 +#define SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_CTRL0_EN_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_CTRL0_MODE_MASK 0x02 +#define SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_CTRL0_MODE_SHIFT 1 + +#define SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_STATUS0_LOS_OFFSET_MASK 0x3F +#define SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_STATUS0_LOS_OFFSET_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_STATUS1_AGC_CALIB_DONE_MASK 0x40 +#define SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_STATUS1_AGC_CALIB_DONE_SHIFT 6 + +#define SERDES_25G_LANE_LOS_REFCLK_CTRL0_EN_MASK 0x01 +#define SERDES_25G_LANE_LOS_REFCLK_CTRL0_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_CTRL0_SRC_SELECT_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_CTRL0_SRC_SELECT_SHIFT 1 + +#define SERDES_25G_LANE_LOS_REFCLK_STATUS0_LOS_READY_MASK 0x01 +#define SERDES_25G_LANE_LOS_REFCLK_STATUS0_LOS_READY_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_STATUS0_AGC_READY_MASK 0x02 +#define SERDES_25G_LANE_LOS_REFCLK_STATUS0_AGC_READY_SHIFT 1 + +#define SERDES_25G_LANE_LOS_REFCLK_STATUS0_LOS_MASK 0x04 +#define SERDES_25G_LANE_LOS_REFCLK_STATUS0_LOS_SHIFT 2 + +#define SERDES_25G_LANE_LOS_REFCLK_STATUS0_LOS_RAW_MASK 0x08 +#define SERDES_25G_LANE_LOS_REFCLK_STATUS0_LOS_RAW_SHIFT 3 + +#define SERDES_25G_LANE_LOS_REFCLK_STATUS0_AGC_MASK 0x10 +#define SERDES_25G_LANE_LOS_REFCLK_STATUS0_AGC_SHIFT 4 + +#define SERDES_25G_LANE_LOS_REFCLK_AFE_SPARE_CTRL0_RXLOS_SPARE_MASK 0x0F +#define SERDES_25G_LANE_LOS_REFCLK_AFE_SPARE_CTRL0_RXLOS_SPARE_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_AFE_PD_CTRL0_PD_RXLOS_MASK 0x01 +#define SERDES_25G_LANE_LOS_REFCLK_AFE_PD_CTRL0_PD_RXLOS_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_CTRL6_REQ_MASK 0x01 +#define SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_CTRL6_REQ_SHIFT 0 + +#define SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_STATUS2_ACK_MASK 0x01 +#define SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_STATUS2_ACK_SHIFT 0 + +/********************************** GCFSM2 **********************************/ +#define SERDES_25G_LANE_GCFSM2_BASE 0x580 + +#define SERDES_25G_LANE_GCFSM2_CMD_CTRL0_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x00) +#define SERDES_25G_LANE_GCFSM2_CMD_CTRL1_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x01) +#define SERDES_25G_LANE_GCFSM2_CMD_CTRL2_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x02) +#define SERDES_25G_LANE_GCFSM2_CMD_STATUS_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x03) +#define SERDES_25G_LANE_GCFSM2_READ_SHADOW_DATA_STATUS0_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x10) +#define SERDES_25G_LANE_GCFSM2_READ_SHADOW_DATA_STATUS1_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x11) +#define SERDES_25G_LANE_GCFSM2_AVG_UP_CNT_STATUS0_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x12) +#define SERDES_25G_LANE_GCFSM2_AVG_UP_CNT_STATUS1_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x13) +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL0_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x20) +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL1_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x21) +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL2_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x22) +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL3_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x23) +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL4_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x24) +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL5_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x25) +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL6_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x26) +#define SERDES_25G_LANE_GCFSM2_PARAMETER_CTRL0_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x30) +#define SERDES_25G_LANE_GCFSM2_PARAMETER_CTRL1_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x31) +#define SERDES_25G_LANE_GCFSM2_PARAMETER_CTRL2_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x32) +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL0_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x40) +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL1_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x41) +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL2_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x42) +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL3_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x43) +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL4_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x44) +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL5_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x45) +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL6_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x46) +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL7_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x47) +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL8_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x48) +#define SERDES_25G_LANE_GCFSM2_FEEDBACK_CTRL0_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x50) +#define SERDES_25G_LANE_GCFSM2_FEEDBACK_CTRL1_ADDR (SERDES_25G_LANE_GCFSM2_BASE + 0x51) +/******************************************************************************* + * masks and shifts + ******************************************************************************/ +#define SERDES_25G_LANE_GCFSM2_CMD_CTRL0_REQ_MASK 0x01 +#define SERDES_25G_LANE_GCFSM2_CMD_CTRL0_REQ_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_CMD_CTRL1_CMD_MASK 0x07 +#define SERDES_25G_LANE_GCFSM2_CMD_CTRL1_CMD_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_CMD_CTRL2_ADDR_MASK 0xFF +#define SERDES_25G_LANE_GCFSM2_CMD_CTRL2_ADDR_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_CMD_STATUS_ACK_MASK 0x01 +#define SERDES_25G_LANE_GCFSM2_CMD_STATUS_ACK_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_CMD_STATUS_CODE_MASK 0x1E +#define SERDES_25G_LANE_GCFSM2_CMD_STATUS_CODE_SHIFT 1 + +#define SERDES_25G_LANE_GCFSM2_READ_SHADOW_DATA_STATUS0_7_0_MASK 0xFF +#define SERDES_25G_LANE_GCFSM2_READ_SHADOW_DATA_STATUS0_7_0_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_READ_SHADOW_DATA_STATUS1_11_8_MASK 0x0F +#define SERDES_25G_LANE_GCFSM2_READ_SHADOW_DATA_STATUS1_11_8_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_AVG_UP_CNT_STATUS0_7_0_MASK 0xFF +#define SERDES_25G_LANE_GCFSM2_AVG_UP_CNT_STATUS0_7_0_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_AVG_UP_CNT_STATUS1_8_8_MASK 0x01 +#define SERDES_25G_LANE_GCFSM2_AVG_UP_CNT_STATUS1_8_8_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL0_TYPE_MASK 0x03 +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL0_TYPE_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL0_WIDTH_MASK 0x3C +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL0_WIDTH_SHIFT 2 + +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL1_START_7_0_MASK 0xFF +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL1_START_7_0_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL2_START_11_8_MASK 0x0F +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL2_START_11_8_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL3_MIN_7_0_MASK 0xFF +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL3_MIN_7_0_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL4_MIN_11_8_MASK 0x0F +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL4_MIN_11_8_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL5_MAX_7_0_MASK 0xFF +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL5_MAX_7_0_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL6_MAX_11_8_MASK 0x0F +#define SERDES_25G_LANE_GCFSM2_DATA_CTRL6_MAX_11_8_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_PARAMETER_CTRL0_STEP_SIZE_MASK 0x1F +#define SERDES_25G_LANE_GCFSM2_PARAMETER_CTRL0_STEP_SIZE_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_PARAMETER_CTRL1_BOUNCE_NUM_MASK 0x0F +#define SERDES_25G_LANE_GCFSM2_PARAMETER_CTRL1_BOUNCE_NUM_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_PARAMETER_CTRL1_COARSE_BOUNCE_NUM_MASK 0xF0 +#define SERDES_25G_LANE_GCFSM2_PARAMETER_CTRL1_COARSE_BOUNCE_NUM_SHIFT 4 + +#define SERDES_25G_LANE_GCFSM2_PARAMETER_CTRL2_SETTLE_ON_LOWEST_AVG_EN_MASK 0x01 +#define SERDES_25G_LANE_GCFSM2_PARAMETER_CTRL2_SETTLE_ON_LOWEST_AVG_EN_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL0_LEN_DELAY_AFE_EN_MASK 0x03 +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL0_LEN_DELAY_AFE_EN_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL1_LEN_AFE_1ST_LATCH_SETTLE_7_0_MASK 0xFF +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL1_LEN_AFE_1ST_LATCH_SETTLE_7_0_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL2_LEN_AFE_1ST_LATCH_SETTLE_15_8_MASK 0xFF +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL2_LEN_AFE_1ST_LATCH_SETTLE_15_8_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL3_LEN_AFE_LATCH_SETTLE_MASK 0xFF +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL3_LEN_AFE_LATCH_SETTLE_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL4_LEN_AFE_CMP_7_0_MASK 0xFF +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL4_LEN_AFE_CMP_7_0_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL5_LEN_AFE_CMP_15_8_MASK 0xFF +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL5_LEN_AFE_CMP_15_8_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL6_LEN_COARSE_BOUNCE_AFE_CMP_7_0_MASK 0xFF +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL6_LEN_COARSE_BOUNCE_AFE_CMP_7_0_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL7_LEN_COARSE_BOUNCE_AFE_CMP_15_8_MASK 0xFF +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL7_LEN_COARSE_BOUNCE_AFE_CMP_15_8_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL8_WAIT_MODE_MASK 0x01 +#define SERDES_25G_LANE_GCFSM2_WAIT_CTRL8_WAIT_MODE_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_FEEDBACK_CTRL0_INVERT_AFE_UP_MASK 0x01 +#define SERDES_25G_LANE_GCFSM2_FEEDBACK_CTRL0_INVERT_AFE_UP_SHIFT 0 + +#define SERDES_25G_LANE_GCFSM2_FEEDBACK_CTRL0_LEN_WAIT_AFE_UP_MASK 0x1E +#define SERDES_25G_LANE_GCFSM2_FEEDBACK_CTRL0_LEN_WAIT_AFE_UP_SHIFT 1 + +#define SERDES_25G_LANE_GCFSM2_FEEDBACK_CTRL1_LEN_AVG_AFE_UP_MASK 0xFF +#define SERDES_25G_LANE_GCFSM2_FEEDBACK_CTRL1_LEN_AVG_AFE_UP_SHIFT 0 + +/********************************** TX BIST **********************************/ +#define SERDES_25G_LANE_TX_BIST_BASE 0x600 + +#define SERDES_25G_LANE_TX_BIST_CTRL_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x00) +#define SERDES_25G_LANE_TX_BIST_BER_CTRL0_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x04) +#define SERDES_25G_LANE_TX_BIST_BER_CTRL1_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x05) +#define SERDES_25G_LANE_TX_BIST_BER_CTRL2_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x06) +#define SERDES_25G_LANE_TX_BIST_BER_CTRL3_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x07) +#define SERDES_25G_LANE_TX_BIST_BER_CTRL4_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x08) +#define SERDES_25G_LANE_TX_BIST_BER_CTRL5_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x09) +#define SERDES_25G_LANE_TX_BIST_BER_CTRL6_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x0A) +#define SERDES_25G_LANE_TX_BIST_BER_CTRL7_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x0B) +#define SERDES_25G_LANE_TX_BIST_UDP_SHIFT_AMOUNT_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x20) +#define SERDES_25G_LANE_TX_BIST_UDP_ADDR(byte_num) \ + ((SERDES_25G_LANE_TX_BIST_BASE + 0x24) + byte_num) +#define SERDES_25G_LANE_TX_BIST_UDP_NUM_BYTES 20 +#define SERDES_25G_LANE_TX_BIST_UDP_7_0_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x24) +#define SERDES_25G_LANE_TX_BIST_UDP_15_8_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x25) +#define SERDES_25G_LANE_TX_BIST_UDP_23_16_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x26) +#define SERDES_25G_LANE_TX_BIST_UDP_31_24_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x27) +#define SERDES_25G_LANE_TX_BIST_UDP_39_32_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x28) +#define SERDES_25G_LANE_TX_BIST_UDP_47_40_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x29) +#define SERDES_25G_LANE_TX_BIST_UDP_55_48_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x2A) +#define SERDES_25G_LANE_TX_BIST_UDP_63_56_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x2B) +#define SERDES_25G_LANE_TX_BIST_UDP_71_64_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x2C) +#define SERDES_25G_LANE_TX_BIST_UDP_79_72_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x2D) +#define SERDES_25G_LANE_TX_BIST_UDP_87_80_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x2E) +#define SERDES_25G_LANE_TX_BIST_UDP_95_88_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x2F) +#define SERDES_25G_LANE_TX_BIST_UDP_103_96_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x30) +#define SERDES_25G_LANE_TX_BIST_UDP_111_104_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x31) +#define SERDES_25G_LANE_TX_BIST_UDP_119_112_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x32) +#define SERDES_25G_LANE_TX_BIST_UDP_127_120_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x33) +#define SERDES_25G_LANE_TX_BIST_UDP_135_128_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x34) +#define SERDES_25G_LANE_TX_BIST_UDP_143_136_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x35) +#define SERDES_25G_LANE_TX_BIST_UDP_151_144_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x36) +#define SERDES_25G_LANE_TX_BIST_UDP_159_152_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x37) +#define SERDES_25G_LANE_TX_BIST_UDP_167_160_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x38) +#define SERDES_25G_LANE_TX_BIST_UDP_175_168_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x39) +#define SERDES_25G_LANE_TX_BIST_UDP_183_176_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x3A) +#define SERDES_25G_LANE_TX_BIST_UDP_191_184_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x3B) +#define SERDES_25G_LANE_TX_BIST_UDP_199_192_ADDR (SERDES_25G_LANE_TX_BIST_BASE + 0x3C) + +#define SERDES_25G_LANE_TX_BIST_CTRL_EN_MASK 0x01 +#define SERDES_25G_LANE_TX_BIST_CTRL_EN_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_SEL_MASK 0x1E +#define SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_SEL_SHIFT 1 + +#define SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_PRBS7 1 +#define SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_PRBS9 2 +#define SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_PRBS11 3 +#define SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_PRBS15 4 +#define SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_PRBS23 5 +#define SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_PRBS31 6 +#define SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_PRBS_USER 7 + +#define SERDES_25G_LANE_TX_BIST_BER_CTRL0_MODE_MASK 0x03 +#define SERDES_25G_LANE_TX_BIST_BER_CTRL0_MODE_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_BER_CTRL1_TIMER_7_0_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_BER_CTRL1_TIMER_7_0_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_BER_CTRL2_TIMER_15_8_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_BER_CTRL2_TIMER_15_8_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_BER_CTRL3_BIT_ERROR_FIELD_7_0_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_BER_CTRL3_BIT_ERROR_FIELD_7_0_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_BER_CTRL4_BIT_ERROR_FIELD_15_8_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_BER_CTRL4_BIT_ERROR_FIELD_15_8_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_BER_CTRL5_BIT_ERROR_FIELD_23_16_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_BER_CTRL5_BIT_ERROR_FIELD_23_16_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_BER_CTRL6_BIT_ERROR_FIELD_31_24_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_BER_CTRL6_BIT_ERROR_FIELD_31_24_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_BER_CTRL7_BIT_ERROR_FIELD_39_32_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_BER_CTRL7_BIT_ERROR_FIELD_39_32_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_SHIFT_AMOUNT_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_SHIFT_AMOUNT_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_7_0_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_7_0_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_15_8_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_15_8_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_23_16_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_23_16_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_31_24_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_31_24_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_39_32_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_39_32_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_47_40_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_47_40_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_55_48_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_55_48_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_63_56_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_63_56_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_71_64_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_71_64_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_79_72_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_79_72_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_87_80_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_87_80_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_95_88_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_95_88_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_103_96_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_103_96_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_111_104_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_111_104_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_119_112_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_119_112_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_127_120_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_127_120_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_135_128_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_135_128_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_143_136_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_143_136_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_151_144_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_151_144_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_159_152_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_159_152_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_167_160_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_167_160_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_175_168_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_175_168_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_183_176_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_183_176_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_191_184_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_191_184_SHIFT 0 + +#define SERDES_25G_LANE_TX_BIST_UDP_199_192_MASK 0xFF +#define SERDES_25G_LANE_TX_BIST_UDP_199_192_SHIFT 0 + +/********************************** RX BIST **********************************/ +#define SERDES_25G_LANE_RX_BIST_BASE 0x680 + +#define SERDES_25G_LANE_RX_BIST_CTRL_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x00) +#define SERDES_25G_LANE_RX_BIST_STATUS_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x04) +#define SERDES_25G_LANE_RX_BIST_BER_STATUS0_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x08) +#define SERDES_25G_LANE_RX_BIST_BER_STATUS1_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x09) +#define SERDES_25G_LANE_RX_BIST_BER_STATUS2_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x0A) +#define SERDES_25G_LANE_RX_BIST_BER_STATUS4_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x0C) +#define SERDES_25G_LANE_RX_BIST_BER_STATUS5_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x0D) +#define SERDES_25G_LANE_RX_BIST_BER_STATUS6_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x0E) +#define SERDES_25G_LANE_RX_BIST_LOCK_CTRL0_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x14) +#define SERDES_25G_LANE_RX_BIST_LOCK_CTRL1_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x15) +#define SERDES_25G_LANE_RX_BIST_LOCK_CTRL2_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x16) +#define SERDES_25G_LANE_RX_BIST_LOCK_CTRL3_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x17) +#define SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL0_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x20) +#define SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL1_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x21) +#define SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL2_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x22) +#define SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL3_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x23) +#define SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL4_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x24) +#define SERDES_25G_LANE_RX_BIST_SHIFT_AMOUNT_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x30) +#define SERDES_25G_LANE_RX_BIST_UDP_7_0_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x34) +#define SERDES_25G_LANE_RX_BIST_UDP_15_8_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x35) +#define SERDES_25G_LANE_RX_BIST_UDP_23_16_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x36) +#define SERDES_25G_LANE_RX_BIST_UDP_31_24_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x37) +#define SERDES_25G_LANE_RX_BIST_UDP_39_32_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x38) +#define SERDES_25G_LANE_RX_BIST_UDP_47_40_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x39) +#define SERDES_25G_LANE_RX_BIST_UDP_55_48_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x3A) +#define SERDES_25G_LANE_RX_BIST_UDP_63_56_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x3B) +#define SERDES_25G_LANE_RX_BIST_UDP_71_64_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x3C) +#define SERDES_25G_LANE_RX_BIST_UDP_79_72_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x3D) +#define SERDES_25G_LANE_RX_BIST_UDP_87_80_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x3E) +#define SERDES_25G_LANE_RX_BIST_UDP_95_88_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x3F) +#define SERDES_25G_LANE_RX_BIST_UDP_103_96_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x40) +#define SERDES_25G_LANE_RX_BIST_UDP_111_104_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x41) +#define SERDES_25G_LANE_RX_BIST_UDP_119_112_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x42) +#define SERDES_25G_LANE_RX_BIST_UDP_127_120_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x43) +#define SERDES_25G_LANE_RX_BIST_UDP_135_128_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x44) +#define SERDES_25G_LANE_RX_BIST_UDP_143_136_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x45) +#define SERDES_25G_LANE_RX_BIST_UDP_151_144_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x46) +#define SERDES_25G_LANE_RX_BIST_UDP_159_152_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x47) +#define SERDES_25G_LANE_RX_BIST_UDP_167_160_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x48) +#define SERDES_25G_LANE_RX_BIST_UDP_175_168_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x49) +#define SERDES_25G_LANE_RX_BIST_UDP_183_176_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x4A) +#define SERDES_25G_LANE_RX_BIST_UDP_191_184_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x4B) +#define SERDES_25G_LANE_RX_BIST_UDP_199_192_ADDR (SERDES_25G_LANE_RX_BIST_BASE + 0x4C) + +/******************************************************************************* + * masks and shifts + ******************************************************************************/ +#define SERDES_25G_LANE_RX_BIST_CTRL_EN_MASK 0x01 +#define SERDES_25G_LANE_RX_BIST_CTRL_EN_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_CTRL_PATTERN_SEL_MASK 0x1E +#define SERDES_25G_LANE_RX_BIST_CTRL_PATTERN_SEL_SHIFT 1 + +#define SERDES_25G_LANE_RX_BIST_CTRL_CLEAR_BER_MASK 0x20 +#define SERDES_25G_LANE_RX_BIST_CTRL_CLEAR_BER_SHIFT 5 + +#define SERDES_25G_LANE_RX_BIST_CTRL_STOP_ERROR_COUNT_MASK 0x40 +#define SERDES_25G_LANE_RX_BIST_CTRL_STOP_ERROR_COUNT_SHIFT 6 + +#define SERDES_25G_LANE_RX_BIST_CTRL_FORCE_LFSR_WITH_RXDATA_MASK 0x80 +#define SERDES_25G_LANE_RX_BIST_CTRL_FORCE_LFSR_WITH_RXDATA_SHIFT 7 + +#define SERDES_25G_LANE_RX_BIST_STATUS_STATE_MASK 0x07 +#define SERDES_25G_LANE_RX_BIST_STATUS_STATE_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_STATUS_PATTERN_DET_MASK 0x78 +#define SERDES_25G_LANE_RX_BIST_STATUS_PATTERN_DET_SHIFT 3 + +#define SERDES_25G_LANE_RX_BIST_BER_STATUS0_BIT_ERROR_COUNT_7_0_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_BER_STATUS0_BIT_ERROR_COUNT_7_0_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_BER_STATUS1_BIT_ERROR_COUNT_15_8_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_BER_STATUS1_BIT_ERROR_COUNT_15_8_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_BER_STATUS2_BIT_ERROR_COUNT_23_16_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_BER_STATUS2_BIT_ERROR_COUNT_23_16_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_BER_STATUS4_CYCLE_COUNT_7_0_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_BER_STATUS4_CYCLE_COUNT_7_0_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_BER_STATUS5_CYCLE_COUNT_15_8_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_BER_STATUS5_CYCLE_COUNT_15_8_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_BER_STATUS6_CYCLE_COUNT_23_16_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_BER_STATUS6_CYCLE_COUNT_23_16_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_LOCK_CTRL0_NUM_CYCLES_7_0_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_LOCK_CTRL0_NUM_CYCLES_7_0_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_LOCK_CTRL1_NUM_CYCLES_15_8_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_LOCK_CTRL1_NUM_CYCLES_15_8_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_LOCK_CTRL2_MAX_ERRORS_7_0_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_LOCK_CTRL2_MAX_ERRORS_7_0_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_LOCK_CTRL3_MAX_ERRORS_15_8_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_LOCK_CTRL3_MAX_ERRORS_15_8_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL0_NUM_CYCLES_7_0_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL0_NUM_CYCLES_7_0_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL1_NUM_CYCLES_15_8_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL1_NUM_CYCLES_15_8_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL2_MIN_ERRORS_7_0_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL2_MIN_ERRORS_7_0_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL3_MIN_ERRORS_15_8_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL3_MIN_ERRORS_15_8_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL4_STOP_ON_LOSS_LOCK_MASK 0x01 +#define SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL4_STOP_ON_LOSS_LOCK_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_SHIFT_AMOUNT_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_SHIFT_AMOUNT_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_7_0_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_7_0_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_15_8_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_15_8_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_23_16_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_23_16_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_31_24_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_31_24_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_39_32_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_39_32_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_47_40_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_47_40_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_55_48_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_55_48_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_63_56_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_63_56_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_71_64_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_71_64_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_79_72_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_79_72_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_87_80_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_87_80_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_95_88_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_95_88_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_103_96_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_103_96_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_111_104_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_111_104_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_119_112_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_119_112_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_127_120_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_127_120_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_135_128_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_135_128_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_143_136_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_143_136_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_151_144_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_151_144_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_159_152_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_159_152_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_167_160_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_167_160_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_175_168_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_175_168_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_183_176_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_183_176_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_191_184_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_191_184_SHIFT 0 + +#define SERDES_25G_LANE_RX_BIST_UDP_199_192_MASK 0xFF +#define SERDES_25G_LANE_RX_BIST_UDP_199_192_SHIFT 0 + +/*********************************** FEATURE **********************************/ +#define SERDES_25G_LANE_FEATURE_BASE 0x700 + +#define SERDES_25G_LANE_FEATURE_RXTERM_CFG0_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x00) +#define SERDES_25G_LANE_FEATURE_LOS_CAL_CFG0_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x04) +#define SERDES_25G_LANE_FEATURE_LEQ_OFFSET_CAL_CFG0_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x05) +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG0_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x06) +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG1_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x07) +#define SERDES_25G_LANE_FEATURE_CDR_CAL_CFG0_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x08) +#define SERDES_25G_LANE_FEATURE_TX_CAL_CFG0_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x09) +#define SERDES_25G_LANE_FEATURE_ADAPT_CFG_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x0C) +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CFG_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x10) +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CONT_CFG0_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x11) +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CONT_CFG1_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x12) +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CONT_CFG2_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x13) +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_AGC_CFG_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x14) +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_APG_MAP_CFG_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x15) +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_LFG_CFG_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x16) +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG0_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x17) +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG1_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x18) +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG2_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x19) +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_MBS_CFG_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x1A) +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_EIE0_CFG_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x1B) +#define SERDES_25G_LANE_FEATURE_DFE_CFG_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x1F) +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_CFG_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x20) +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_CONT_CFG0_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x21) +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_CONT_CFG1_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x22) +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_CONT_CFG2_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x23) +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP1_CFG_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x24) +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP2_CFG_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x25) +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP3_CFG_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x26) +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP4_CFG_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x27) +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP5_CFG_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x28) +#define SERDES_25G_LANE_FEATURE_RX_CTRL_CFG0_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x30) +#define SERDES_25G_LANE_FEATURE_RX_CTRL_CFG1_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x31) +#define SERDES_25G_LANE_FEATURE_RX_CTRL_CFG2_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x32) +#define SERDES_25G_LANE_FEATURE_RX_CTRL_CFG3_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x33) +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG0_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x40) +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG1_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x41) +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG2_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x42) +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG3_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x43) +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG4_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x44) +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG5_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x45) +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG6_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x46) +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG7_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x47) +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG8_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x48) +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG9_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x49) +#define SERDES_25G_LANE_FEATURE_TEST_CFG0_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x50) +#define SERDES_25G_LANE_FEATURE_SPARE_CFG0_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x58) +#define SERDES_25G_LANE_FEATURE_SPARE_CFG1_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x59) +#define SERDES_25G_LANE_FEATURE_SPARE_CFG2_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x5A) +#define SERDES_25G_LANE_FEATURE_SPARE_CFG3_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x5B) +#define SERDES_25G_LANE_FEATURE_SPARE_CFG4_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x5C) +#define SERDES_25G_LANE_FEATURE_SPARE_CFG5_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x5D) +#define SERDES_25G_LANE_FEATURE_SPARE_CFG6_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x5E) +#define SERDES_25G_LANE_FEATURE_SPARE_CFG7_ADDR (SERDES_25G_LANE_FEATURE_BASE + 0x5F) +/******************************************************************************* + * masks and shifts + ******************************************************************************/ +#define SERDES_25G_LANE_FEATURE_RXTERM_CFG0_AC_COUPLED_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_RXTERM_CFG0_AC_COUPLED_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_LOS_CAL_CFG0_LOS_COMP_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_LOS_CAL_CFG0_LOS_COMP_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_LOS_CAL_CFG0_AGC_COMP_EN_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_LOS_CAL_CFG0_AGC_COMP_EN_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_LEQ_OFFSET_CAL_CFG0_GN_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_LEQ_OFFSET_CAL_CFG0_GN_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_LEQ_OFFSET_CAL_CFG0_EQ1_EN_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_LEQ_OFFSET_CAL_CFG0_EQ1_EN_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_LEQ_OFFSET_CAL_CFG0_EQ2_EN_MASK 0x04 +#define SERDES_25G_LANE_FEATURE_LEQ_OFFSET_CAL_CFG0_EQ2_EN_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_LEQ_OFFSET_CAL_CFG0_EQ3_EN_MASK 0x08 +#define SERDES_25G_LANE_FEATURE_LEQ_OFFSET_CAL_CFG0_EQ3_EN_SHIFT 3 + +#define SERDES_25G_LANE_FEATURE_LEQ_OFFSET_CAL_CFG0_EQ4_EN_MASK 0x10 +#define SERDES_25G_LANE_FEATURE_LEQ_OFFSET_CAL_CFG0_EQ4_EN_SHIFT 4 + +#define SERDES_25G_LANE_FEATURE_LEQ_OFFSET_CAL_CFG0_EQ5_EN_MASK 0x20 +#define SERDES_25G_LANE_FEATURE_LEQ_OFFSET_CAL_CFG0_EQ5_EN_SHIFT 5 + +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG0_SUMMODD_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG0_SUMMODD_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG0_SUMMEVEN_EN_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG0_SUMMEVEN_EN_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG0_VSCANODD_EN_MASK 0x04 +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG0_VSCANODD_EN_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG0_VSCANEVEN_EN_MASK 0x08 +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG0_VSCANEVEN_EN_SHIFT 3 + +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG1_DATASLICEREVEN1_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG1_DATASLICEREVEN1_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG1_DATASLICEREVEN0_EN_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG1_DATASLICEREVEN0_EN_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG1_DATASLICERODD1_EN_MASK 0x04 +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG1_DATASLICERODD1_EN_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG1_DATASLICERODD0_EN_MASK 0x08 +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG1_DATASLICERODD0_EN_SHIFT 3 + +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG1_EDGESLICEREVEN_EN_MASK 0x10 +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG1_EDGESLICEREVEN_EN_SHIFT 4 + +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG1_EDGESLICERODD_EN_MASK 0x20 +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG1_EDGESLICERODD_EN_SHIFT 5 + +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG1_EYESLICEREVEN_EN_MASK 0x40 +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG1_EYESLICEREVEN_EN_SHIFT 6 + +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG1_EYESLICERODD_EN_MASK 0x80 +#define SERDES_25G_LANE_FEATURE_DFE_OFFSET_CAL_CFG1_EYESLICERODD_EN_SHIFT 7 + +#define SERDES_25G_LANE_FEATURE_CDR_CAL_CFG0_VCO_FREQ_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_CDR_CAL_CFG0_VCO_FREQ_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_CDR_CAL_CFG0_CDR_IQ_CAL1_EN_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_CDR_CAL_CFG0_CDR_IQ_CAL1_EN_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_CDR_CAL_CFG0_CDR_IQ_CAL2_EN_MASK 0x04 +#define SERDES_25G_LANE_FEATURE_CDR_CAL_CFG0_CDR_IQ_CAL2_EN_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_CDR_CAL_CFG0_CDR_IQ_CAL3_EN_MASK 0x08 +#define SERDES_25G_LANE_FEATURE_CDR_CAL_CFG0_CDR_IQ_CAL3_EN_SHIFT 3 + +#define SERDES_25G_LANE_FEATURE_CDR_CAL_CFG0_CDR_IQ_CAL_RESULT_SEL_MASK 0x30 +#define SERDES_25G_LANE_FEATURE_CDR_CAL_CFG0_CDR_IQ_CAL_RESULT_SEL_SHIFT 4 + +#define SERDES_25G_LANE_FEATURE_TX_CAL_CFG0_TX_REG_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_TX_CAL_CFG0_TX_REG_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_TX_CAL_CFG0_TX_DCD_EN_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_TX_CAL_CFG0_TX_DCD_EN_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_TX_CAL_CFG0_TXDP_CLOCK_PHASE_EN_MASK 0x04 +#define SERDES_25G_LANE_FEATURE_TX_CAL_CFG0_TXDP_CLOCK_PHASE_EN_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_ADAPT_CFG_EYE_MON_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_ADAPT_CFG_EYE_MON_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CFG_REPEAT_COUNT_INIT0_MASK 0x03 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CFG_REPEAT_COUNT_INIT0_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CFG_REPEAT_COUNT_INIT1_MASK 0x0C +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CFG_REPEAT_COUNT_INIT1_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CFG_REPEAT_COUNT_EIE0_MASK 0x30 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CFG_REPEAT_COUNT_EIE0_SHIFT 4 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CFG_REPEAT_COUNT_EIE1_MASK 0xC0 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CFG_REPEAT_COUNT_EIE1_SHIFT 6 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CONT_CFG0_INTERVAL_7_0_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CONT_CFG0_INTERVAL_7_0_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CONT_CFG1_INTERVAL_15_8_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CONT_CFG1_INTERVAL_15_8_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CONT_CFG2_INTERVAL_23_16_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_CONT_CFG2_INTERVAL_23_16_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_AGC_CFG_INIT0_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_AGC_CFG_INIT0_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_AGC_CFG_EIE0_EN_MASK 0x04 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_AGC_CFG_EIE0_EN_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_APG_MAP_CFG_INIT0_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_APG_MAP_CFG_INIT0_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_APG_MAP_CFG_EIE0_EN_MASK 0x04 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_APG_MAP_CFG_EIE0_EN_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_LFG_CFG_INIT0_SEL_MASK 0x03 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_LFG_CFG_INIT0_SEL_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_LFG_CFG_INIT1_SEL_MASK 0x0C +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_LFG_CFG_INIT1_SEL_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_LFG_CFG_EIE0_SEL_MASK 0x30 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_LFG_CFG_EIE0_SEL_SHIFT 4 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_LFG_CFG_EIE1_SEL_MASK 0xC0 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_LFG_CFG_EIE1_SEL_SHIFT 6 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG0_INIT0_EDGE_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG0_INIT0_EDGE_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG0_INIT0_DATA_EN_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG0_INIT0_DATA_EN_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG0_INIT1_EDGE_EN_MASK 0x04 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG0_INIT1_EDGE_EN_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG0_INIT1_DATA_EN_MASK 0x08 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG0_INIT1_DATA_EN_SHIFT 3 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG0_EIE0_EDGE_EN_MASK 0x10 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG0_EIE0_EDGE_EN_SHIFT 4 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG0_EIE0_DATA_EN_MASK 0x20 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG0_EIE0_DATA_EN_SHIFT 5 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG0_EIE1_EDGE_EN_MASK 0x40 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG0_EIE1_EDGE_EN_SHIFT 6 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG0_EIE1_DATA_EN_MASK 0x80 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG0_EIE1_DATA_EN_SHIFT 7 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG1_INIT0_RESULT_SEL_MASK 0x03 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG1_INIT0_RESULT_SEL_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG1_INIT1_RESULT_SEL_MASK 0x0C +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG1_INIT1_RESULT_SEL_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG1_EIE0_RESULT_SEL_MASK 0x30 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG1_EIE0_RESULT_SEL_SHIFT 4 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG1_EIE1_RESULT_SEL_MASK 0xC0 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG1_EIE1_RESULT_SEL_SHIFT 6 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG2_CONT_EDGE_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG2_CONT_EDGE_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG2_CONT_DATA_EN_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG2_CONT_DATA_EN_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG2_CONT_RESULT_SEL_MASK 0x0C +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_HFG_CFG2_CONT_RESULT_SEL_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_MBS_CFG_INIT0_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_MBS_CFG_INIT0_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_MBS_CFG_INIT1_EN_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_MBS_CFG_INIT1_EN_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_MBS_CFG_EIE0_EN_MASK 0x04 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_MBS_CFG_EIE0_EN_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_MBS_CFG_EIE1_EN_MASK 0x08 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_MBS_CFG_EIE1_EN_SHIFT 3 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_MBS_CFG_CONT_EN_MASK 0x10 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_MBS_CFG_CONT_EN_SHIFT 4 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_EIE0_CFG_AGCLOS_START_VAL_SEL_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_EIE0_CFG_AGCLOS_START_VAL_SEL_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_EIE0_CFG_PLE_ATT_START_VAL_SEL_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_EIE0_CFG_PLE_ATT_START_VAL_SEL_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_EIE0_CFG_GN_APG_START_VAL_SEL_MASK 0x04 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_EIE0_CFG_GN_APG_START_VAL_SEL_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_EIE0_CFG_EQ_LFG_START_VAL_SEL_MASK 0x08 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_EIE0_CFG_EQ_LFG_START_VAL_SEL_SHIFT 3 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_EIE0_CFG_GNEQ_CCL_LFG_START_VAL_SEL_MASK 0x10 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_EIE0_CFG_GNEQ_CCL_LFG_START_VAL_SEL_SHIFT 4 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_EIE0_CFG_EQ_HFG_SQL_START_VAL_SEL_MASK 0x20 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_EIE0_CFG_EQ_HFG_SQL_START_VAL_SEL_SHIFT 5 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_EIE0_CFG_EQ_MBF_START_VAL_SEL_MASK 0x40 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_EIE0_CFG_EQ_MBF_START_VAL_SEL_SHIFT 6 + +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_EIE0_CFG_EQ_MBG_START_VAL_SEL_MASK 0x80 +#define SERDES_25G_LANE_FEATURE_CTLE_ADAPT_EIE0_CFG_EQ_MBG_START_VAL_SEL_SHIFT 7 + +#define SERDES_25G_LANE_FEATURE_DFE_CFG_TAP1_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_DFE_CFG_TAP1_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_DFE_CFG_TAP2_EN_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_DFE_CFG_TAP2_EN_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_DFE_CFG_TAP3_EN_MASK 0x04 +#define SERDES_25G_LANE_FEATURE_DFE_CFG_TAP3_EN_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_DFE_CFG_TAP4_EN_MASK 0x08 +#define SERDES_25G_LANE_FEATURE_DFE_CFG_TAP4_EN_SHIFT 3 + +#define SERDES_25G_LANE_FEATURE_DFE_CFG_TAP5_EN_MASK 0x10 +#define SERDES_25G_LANE_FEATURE_DFE_CFG_TAP5_EN_SHIFT 4 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_CFG_METHOD_SEL_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_CFG_METHOD_SEL_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_CONT_CFG0_INTERVAL_7_0_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_CONT_CFG0_INTERVAL_7_0_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_CONT_CFG1_INTERVAL_15_8_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_CONT_CFG1_INTERVAL_15_8_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_CONT_CFG2_INTERVAL_23_16_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_CONT_CFG2_INTERVAL_23_16_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP1_CFG_TAP1_INIT_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP1_CFG_TAP1_INIT_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP1_CFG_TAP1_EIE_EN_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP1_CFG_TAP1_EIE_EN_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP1_CFG_TAP1_CONT_EN_MASK 0x04 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP1_CFG_TAP1_CONT_EN_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP1_CFG_TAP1_START_VAL_SEL_MASK 0x08 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP1_CFG_TAP1_START_VAL_SEL_SHIFT 3 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP2_CFG_TAP2_INIT_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP2_CFG_TAP2_INIT_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP2_CFG_TAP2_EIE_EN_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP2_CFG_TAP2_EIE_EN_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP2_CFG_TAP2_CONT_EN_MASK 0x04 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP2_CFG_TAP2_CONT_EN_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP2_CFG_TAP2_START_VAL_SEL_MASK 0x08 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP2_CFG_TAP2_START_VAL_SEL_SHIFT 3 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP3_CFG_TAP3_INIT_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP3_CFG_TAP3_INIT_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP3_CFG_TAP3_EIE_EN_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP3_CFG_TAP3_EIE_EN_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP3_CFG_TAP3_CONT_EN_MASK 0x04 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP3_CFG_TAP3_CONT_EN_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP3_CFG_TAP3_START_VAL_SEL_MASK 0x08 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP3_CFG_TAP3_START_VAL_SEL_SHIFT 3 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP4_CFG_TAP4_INIT_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP4_CFG_TAP4_INIT_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP4_CFG_TAP4_EIE_EN_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP4_CFG_TAP4_EIE_EN_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP4_CFG_TAP4_CONT_EN_MASK 0x04 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP4_CFG_TAP4_CONT_EN_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP4_CFG_TAP4_START_VAL_SEL_MASK 0x08 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP4_CFG_TAP4_START_VAL_SEL_SHIFT 3 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP5_CFG_TAP5_INIT_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP5_CFG_TAP5_INIT_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP5_CFG_TAP5_EIE_EN_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP5_CFG_TAP5_EIE_EN_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP5_CFG_TAP5_CONT_EN_MASK 0x04 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP5_CFG_TAP5_CONT_EN_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP5_CFG_TAP5_START_VAL_SEL_MASK 0x08 +#define SERDES_25G_LANE_FEATURE_DFE_ADAPT_TAP5_CFG_TAP5_START_VAL_SEL_SHIFT 3 + +#define SERDES_25G_LANE_FEATURE_RX_CTRL_CFG0_CDR_LOCKD_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_RX_CTRL_CFG0_CDR_LOCKD_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_RX_CTRL_CFG0_CDR_LOCKD_TIMEOUT_US_MASK 0xFE +#define SERDES_25G_LANE_FEATURE_RX_CTRL_CFG0_CDR_LOCKD_TIMEOUT_US_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_RX_CTRL_CFG1_CDR_LOCK_WAIT_TIME_US_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_RX_CTRL_CFG1_CDR_LOCK_WAIT_TIME_US_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_RX_CTRL_CFG2_CDR_FREQ_MEASURE_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_RX_CTRL_CFG2_CDR_FREQ_MEASURE_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_RX_CTRL_CFG3_RXCLKDIV_EN_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_RX_CTRL_CFG3_RXCLKDIV_EN_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_RX_CTRL_CFG3_BIST_HANDSHAKE_EN_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_RX_CTRL_CFG3_BIST_HANDSHAKE_EN_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG0_SIG_DET_MODE_MASK 0x03 +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG0_SIG_DET_MODE_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG0_LOS_DET_MODE_MASK 0x0C +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG0_LOS_DET_MODE_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG1_SIG_DET_THRESHOLD_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG1_SIG_DET_THRESHOLD_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG2_LOS_DET_THRESHOLD_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG2_LOS_DET_THRESHOLD_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG3_INTERVAL_7_0_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG3_INTERVAL_7_0_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG4_INTERVAL_15_8_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG4_INTERVAL_15_8_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG5_SAMPLE_LEN_7_0_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG5_SAMPLE_LEN_7_0_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG6_SAMPLE_LEN_11_8_MASK 0x0F +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG6_SAMPLE_LEN_11_8_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG7_PLE_ATT_MASK 0x07 +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG7_PLE_ATT_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG7_EQ_LFG_MASK 0xF8 +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG7_EQ_LFG_SHIFT 3 + +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG8_GN_APG_MASK 0x03 +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG8_GN_APG_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG8_HFG_SQL_MASK 0x7C +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG8_HFG_SQL_SHIFT 2 + +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG9_MBF_MASK 0x0F +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG9_MBF_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG9_MBG_MASK 0xF0 +#define SERDES_25G_LANE_FEATURE_EYE_LOS_CFG9_MBG_SHIFT 4 + +#define SERDES_25G_LANE_FEATURE_TEST_CFG0_LANE_MSM_DIS_MASK 0x01 +#define SERDES_25G_LANE_FEATURE_TEST_CFG0_LANE_MSM_DIS_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_TEST_CFG0_RX_CTRL_DIS_MASK 0x02 +#define SERDES_25G_LANE_FEATURE_TEST_CFG0_RX_CTRL_DIS_SHIFT 1 + +#define SERDES_25G_LANE_FEATURE_SPARE_CFG0_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_SPARE_CFG0_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_SPARE_CFG1_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_SPARE_CFG1_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_SPARE_CFG2_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_SPARE_CFG2_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_SPARE_CFG3_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_SPARE_CFG3_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_SPARE_CFG4_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_SPARE_CFG4_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_SPARE_CFG5_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_SPARE_CFG5_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_SPARE_CFG6_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_SPARE_CFG6_SHIFT 0 + +#define SERDES_25G_LANE_FEATURE_SPARE_CFG7_MASK 0xFF +#define SERDES_25G_LANE_FEATURE_SPARE_CFG7_SHIFT 0 + +#ifdef _cplusplus +} +#endif + +#endif diff --git a/al_hal_serdes_25g_regs.h b/al_hal_serdes_25g_regs.h new file mode 100644 index 00000000000..64422f7e931 --- /dev/null +++ b/al_hal_serdes_25g_regs.h @@ -0,0 +1,434 @@ +/******************************************************************************* +Copyright (C) 2013 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 or V3 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_serdes_c_regs.h + * + * @brief ... registers + * + */ + +#ifndef __AL_HAL_serdes_c_REGS_H__ +#define __AL_HAL_serdes_c_REGS_H__ + +#include "al_hal_plat_types.h" + +#ifdef __cplusplus +extern "C" { +#endif +/* +* Unit Registers +*/ + +struct al_serdes_c_gen { + /* [0x0] SERDES registers Version */ + uint32_t version; + uint32_t rsrvd_0[3]; + /* [0x10] SERDES register file address */ + uint32_t reg_addr; + /* [0x14] SERDES register file data */ + uint32_t reg_data; + /* [0x18] SERDES control */ + uint32_t ctrl; + /* [0x1c] SERDES cpu mem address */ + uint32_t cpu_prog_addr; + /* [0x20] SERDES cpu mem data */ + uint32_t cpu_prog_data; + /* [0x24] SERDES data mem address */ + uint32_t cpu_data_mem_addr; + /* [0x28] SERDES data mem data */ + uint32_t cpu_data_mem_data; + /* [0x2c] SERDES control */ + uint32_t rst; + /* [0x30] SERDES control */ + uint32_t status; + uint32_t rsrvd[51]; +}; +struct al_serdes_c_lane { + uint32_t rsrvd_0[4]; + /* [0x10] Data configuration */ + uint32_t cfg; + /* [0x14] Lane status */ + uint32_t stat; + /* [0x18] SERDES control */ + uint32_t reserved; + uint32_t rsrvd[25]; +}; + +struct al_serdes_c_regs { + uint32_t rsrvd_0[64]; + struct al_serdes_c_gen gen; /* [0x100] */ + struct al_serdes_c_lane lane[2]; /* [0x200] */ +}; + + +/* +* Registers Fields +*/ + + +/**** version register ****/ +/* Revision number (Minor) */ +#define SERDES_C_GEN_VERSION_RELEASE_NUM_MINOR_MASK 0x000000FF +#define SERDES_C_GEN_VERSION_RELEASE_NUM_MINOR_SHIFT 0 +/* Revision number (Major) */ +#define SERDES_C_GEN_VERSION_RELEASE_NUM_MAJOR_MASK 0x0000FF00 +#define SERDES_C_GEN_VERSION_RELEASE_NUM_MAJOR_SHIFT 8 +/* date of release */ +#define SERDES_C_GEN_VERSION_DATE_DAY_MASK 0x001F0000 +#define SERDES_C_GEN_VERSION_DATE_DAY_SHIFT 16 +/* month of release */ +#define SERDES_C_GEN_VERSION_DATA_MONTH_MASK 0x01E00000 +#define SERDES_C_GEN_VERSION_DATA_MONTH_SHIFT 21 +/* year of release (starting from 2000) */ +#define SERDES_C_GEN_VERSION_DATE_YEAR_MASK 0x3E000000 +#define SERDES_C_GEN_VERSION_DATE_YEAR_SHIFT 25 +/* Reserved */ +#define SERDES_C_GEN_VERSION_RESERVED_MASK 0xC0000000 +#define SERDES_C_GEN_VERSION_RESERVED_SHIFT 30 + +/**** reg_addr register ****/ +/* address value */ +#define SERDES_C_GEN_REG_ADDR_VAL_MASK 0x00007FFF +#define SERDES_C_GEN_REG_ADDR_VAL_SHIFT 0 + +/**** reg_data register ****/ +/* data value */ +#define SERDES_C_GEN_REG_DATA_VAL_MASK 0x000000FF +#define SERDES_C_GEN_REG_DATA_VAL_SHIFT 0 +/* Bit-wise write enable */ +#define SERDES_C_GEN_REG_DATA_STRB_MASK 0x0000FF00 +#define SERDES_C_GEN_REG_DATA_STRB_SHIFT 8 + +/**** ctrl register ****/ +/* + * 0x0 – Select reference clock from Bump + * 0x1 – Select inter-macro reference clock from the left side + * 0x2 – Same as 0x0 + * 0x3 – Select inter-macro reference clock from the right side + */ +#define SERDES_C_GEN_CTRL_REFCLK_INPUT_SEL_MASK 0x00000003 +#define SERDES_C_GEN_CTRL_REFCLK_INPUT_SEL_SHIFT 0 + +#define SERDES_C_GEN_CTRL_REFCLK_INPUT_SEL_REF \ + (0 << (SERDES_C_GEN_CTRL_REFCLK_INPUT_SEL_SHIFT)) +#define SERDES_C_GEN_CTRL_REFCLK_INPUT_SEL_L2R \ + (1 << (SERDES_C_GEN_CTRL_REFCLK_INPUT_SEL_SHIFT)) +#define SERDES_C_GEN_CTRL_REFCLK_INPUT_SEL_R2L \ + (3 << (SERDES_C_GEN_CTRL_REFCLK_INPUT_SEL_SHIFT)) + +/* + * 0x0 – Tied to 0 to save power + * 0x1 – Select reference clock from Bump + * 0x2 – Select inter-macro reference clock input from right side + * 0x3 – Same as 0x2 + */ +#define SERDES_C_GEN_CTRL_REFCLK_LEFT_SEL_MASK 0x00000030 +#define SERDES_C_GEN_CTRL_REFCLK_LEFT_SEL_SHIFT 4 + +#define SERDES_C_GEN_CTRL_REFCLK_LEFT_SEL_0 \ + (0 << (SERDES_C_GEN_CTRL_REFCLK_LEFT_SEL_SHIFT)) +#define SERDES_C_GEN_CTRL_REFCLK_LEFT_SEL_REF \ + (1 << (SERDES_C_GEN_CTRL_REFCLK_LEFT_SEL_SHIFT)) +#define SERDES_C_GEN_CTRL_REFCLK_LEFT_SEL_R2L \ + (2 << (SERDES_C_GEN_CTRL_REFCLK_LEFT_SEL_SHIFT)) + +/* + * 0x0 – Tied to 0 to save power + * 0x1 – Select reference clock from Bump + * 0x2 – Select inter-macro reference clock input from left side + * 0x3 – Same as 0x2 + */ +#define SERDES_C_GEN_CTRL_REFCLK_RIGHT_SEL_MASK 0x000000C0 +#define SERDES_C_GEN_CTRL_REFCLK_RIGHT_SEL_SHIFT 6 + +#define SERDES_C_GEN_CTRL_REFCLK_RIGHT_SEL_0 \ + (0 << (SERDES_C_GEN_CTRL_REFCLK_RIGHT_SEL_SHIFT)) +#define SERDES_C_GEN_CTRL_REFCLK_RIGHT_SEL_REF \ + (1 << (SERDES_C_GEN_CTRL_REFCLK_RIGHT_SEL_SHIFT)) +#define SERDES_C_GEN_CTRL_REFCLK_RIGHT_SEL_L2R \ + (2 << (SERDES_C_GEN_CTRL_REFCLK_RIGHT_SEL_SHIFT)) + +/* + * Program memory acknowledge - Only when the access + * to the program memory is not + * ready for the microcontroller, it + * is driven to 0 + */ +#define SERDES_C_GEN_CTRL_CPU_MEMPSACK (1 << 8) +/* + * Data memory acknowledge - Only when the access + * to the program memory is not + * ready for the microcontroller, it + * is driven to 0 + */ +#define SERDES_C_GEN_CTRL_CPU_MEMACK (1 << 12) +/* + * 0 - keep cpu clk as sb clk + * 1 – cpu_clk is sb_clk divided by 2 + */ +#define SERDES_C_GEN_CTRL_CPU_CLK_DIV (1 << 16) +/* + * 0x0 – OIF CEI-28G-SR + * 0x1 – OIF CIE-25G-LR + * 0x8 – XFI + * Others – Reserved + * + * Note that phy_ctrl_cfg_i[3] is used to signify high-speed/low-speed + */ +#define SERDES_C_GEN_CTRL_PHY_CTRL_CFG_MASK 0x00F00000 +#define SERDES_C_GEN_CTRL_PHY_CTRL_CFG_SHIFT 20 +/* + * 0 - Internal 8051 micro- controller is allowed to access the internal APB + * CSR. Internal APB runs at cpu_clk_i, and the accesses from the external APB + * in apb_clk_i domain to APB CSR are resynchronized to cpu_clk_i. 1 – Bypass + * CPU. Internal 8051 micro-controller is blocked from accessing the internal + * APB CSR. Internal APB runs at apb_clk_i. + */ +#define SERDES_C_GEN_CTRL_CPU_BYPASS (1 << 24) + +/**** cpu_prog_addr register ****/ +/* + * address value 32 bit, + * The firmware data will be 1 byte with 64K rows + */ +#define SERDES_C_GEN_CPU_PROG_ADDR_VAL_MASK 0x00007FFF +#define SERDES_C_GEN_CPU_PROG_ADDR_VAL_SHIFT 0 + +/**** cpu_data_mem_addr register ****/ +/* address value – 8K byte memory */ +#define SERDES_C_GEN_CPU_DATA_MEM_ADDR_VAL_MASK 0x00001FFF +#define SERDES_C_GEN_CPU_DATA_MEM_ADDR_VAL_SHIFT 0 + +/**** cpu_data_mem_data register ****/ +/* data value */ +#define SERDES_C_GEN_CPU_DATA_MEM_DATA_VAL_MASK 0x000000FF +#define SERDES_C_GEN_CPU_DATA_MEM_DATA_VAL_SHIFT 0 + +/**** rst register ****/ +/* Power on reset Signal – active low */ +#define SERDES_C_GEN_RST_POR_N (1 << 0) +/* CMU reset Active low */ +#define SERDES_C_GEN_RST_CM0_RST_N (1 << 1) +/* + * 0x0 – Normal / Active + * 0x1 – Partial power down + * 0x2 – Near complete power down (only + * refclk buffers and portions of analog bias + * active) + * 0x3 – complete power down (IDDQ mode) + * Can be asserted when CMU is in normal + * mode. These modes provide an increased + * power savings compared to reset mode. + * Signal is overridden by por_n_i so has no + * effect in power on reset state. + */ +#define SERDES_C_GEN_RST_CM0_PD_MASK 0x00000030 +#define SERDES_C_GEN_RST_CM0_PD_SHIFT 4 +/* Lane0 reset signal active low */ +#define SERDES_C_GEN_RST_LN0_RST_N (1 << 6) +/* Lane1 reset signal active low */ +#define SERDES_C_GEN_RST_LN1_RST_N (1 << 7) +/* + * 0x0 – Normal / Active + * 0x1 – Partial power down + * 0x2 – Most blocks powered down (only LOS + * active) + * 0x3 – complete power down (IDDQ mode) + * Can be asserted when Lane is in normal + * mode. These modes provide an increased + * power savings compared to reset mode. + * Signal is overridden by por_n_i so has no + * affect in power on reset state + */ +#define SERDES_C_GEN_RST_LN0_PD_MASK 0x00000300 +#define SERDES_C_GEN_RST_LN0_PD_SHIFT 8 +/* + * 0x0 – Normal / Active + * 0x1 – Partial power down + * 0x2 – Most blocks powered down (only LOS + * active) + * 0x3 – complete power down (IDDQ mode) + * Can be asserted when Lane is in normal + * mode. These modes provide an increased + * power savings compared to reset mode. + * Signal is overridden by por_n_i so has no + * affect in power on reset state + */ +#define SERDES_C_GEN_RST_LN1_PD_MASK 0x00000C00 +#define SERDES_C_GEN_RST_LN1_PD_SHIFT 10 + +#define SERDES_C_GEN_RST_CPU_MEM_RESET (1 << 12) + +#define SERDES_C_GEN_RST_CPU_MEM_SHUTDOWN (1 << 13) + +#define SERDES_C_GEN_RST_CAPRI_APB_RESET (1 << 14) + +/**** status register ****/ +/* + * 0x0 – No error + * 0x1 – PHY has an internal error + */ +#define SERDES_C_GEN_STATUS_ERR_O (1 << 0) +/* + * 0x0 – PHY is not ready to respond to + * cm0_rst_n_i and cm0_pd_i[1:0]. The + * signals should not be changed. + * 0x1 - PHY is ready to respond to + * cm0_rst_n_i and cm0_pd_i[1:0] + */ +#define SERDES_C_GEN_STATUS_CM0_RST_PD_READY (1 << 1) +/* + * Indicates CMU PLL has locked to the + * reference clock and all output clocks are at + * the correct frequency + */ +#define SERDES_C_GEN_STATUS_CM0_OK_O (1 << 2) +/* + * 0x0 – PHY is not ready to respond to + * ln0_rst_n and ln0_pd[1:0]. The signals + * should not be changed. + * 0x1 - PHY is ready to respond to lnX_rst_n_i + * and lnX_pd_i[1:0] + */ +#define SERDES_C_GEN_STATUS_LN0_RST_PD_READY (1 << 3) +/* + * 0x0 – PHY is not ready to respond to + * ln1_rst_n_i and ln1_pd[1:0]. The signals + * should not be changed. + * 0x1 - PHY is ready to respond to lnX_rst_n_i + * and lnX_pd_i[1:0] + */ +#define SERDES_C_GEN_STATUS_LN1_RST_PD_READY (1 << 4) +/* + * Active low when the CPU performs a wait cycle (internally or externally + * generated) + */ +#define SERDES_C_GEN_STATUS_CPU_WAITSTATE (1 << 5) + +#define SERDES_C_GEN_STATUS_TBUS_MASK 0x000FFF00 +#define SERDES_C_GEN_STATUS_TBUS_SHIFT 8 + +/**** cfg register ****/ +/* 1- Swap 32 bit data on RX side */ +#define SERDES_C_LANE_CFG_RX_LANE_SWAP (1 << 0) +/* 1- Swap 32 bit data on TX side */ +#define SERDES_C_LANE_CFG_TX_LANE_SWAP (1 << 1) +/* 1 – invert rx data polarity */ +#define SERDES_C_LANE_CFG_LN_CTRL_RXPOLARITY (1 << 2) +/* 1 – invert tx data polarity */ +#define SERDES_C_LANE_CFG_TX_LANE_POLARITY (1 << 3) +/* + * 0x0 –Data on lnX_txdata_o will not be + * transmitted. Transmitter will be placed into + * electrical idle. + * 0x1 – Data on the active bits of + * lnX_txdata_o will be transmitted + */ +#define SERDES_C_LANE_CFG_LN_CTRL_TX_EN (1 << 4) +/* + * Informs the PHY to bypass the output of the + * analog LOS detector and instead rely upon + * a protocol LOS mechanism in the SoC/ASIC + * 0x0 – LOS operates as normal + * 0x1 – Bypass analog LOS output and + * instead rely upon protocol-level LOS + * detection via input lnX_ctrl_los_eii_value + */ +#define SERDES_C_LANE_CFG_LN_CTRL_LOS_EII_EN (1 << 5) +/* + * If lnX_ctrl_los_eii_en_i = 1 then Informs + * the PHY that the received signal was lost + */ +#define SERDES_C_LANE_CFG_LN_CTRL_LOS_EII_VALUE (1 << 6) +/* One hot mux */ +#define SERDES_C_LANE_CFG_TX_DATA_SRC_SELECT_MASK 0x00000F00 +#define SERDES_C_LANE_CFG_TX_DATA_SRC_SELECT_SHIFT 8 +/* 0x0 - 20-bit 0x1 – 40-bit */ +#define SERDES_C_LANE_CFG_LN_CTRL_DATA_WIDTH (1 << 12) + +/**** stat register ****/ +/* + * x0 – lane is not ready to send and receive data + * 0x1 – lane is ready to send and receive data + */ +#define SERDES_C_LANE_STAT_LNX_STAT_OK (1 << 0) +/* + * 0x0 – received data run length has not + * exceed the programmable run length + * detector threshold + * 0x1 – received data run length has + * exceeded the programmable run length + * detector threshold + */ +#define SERDES_C_LANE_STAT_LN_STAT_RUNLEN_ERR (1 << 1) +/* + * 0x0 – data on lnX_rxdata_o are invalid + * 0x1 – data on the active bits of + * lnX_rxdata_o are valid + */ +#define SERDES_C_LANE_STAT_LN_STAT_RXVALID (1 << 2) +/* + * Loss of Signal (LOS) indicator that includes + * the combined functions of the digitally + * assisted analog LOS, digital LOS, and + * protocol LOS override features + * 0x0 – Signal detected on lnX_rxp_i / + * lnX_rxm_i pins + * 0x1 – No signal detected on lnX_rxp_i / + * lnX_rxm_i pins + */ +#define SERDES_C_LANE_STAT_LN_STAT_LOS (1 << 3) + +#define SERDES_C_LANE_STAT_LN_STAT_LOS_DEGLITCH (1 << 4) + +/**** reserved register ****/ + +#define SERDES_C_LANE_RESERVED_DEF_0_MASK 0x0000FFFF +#define SERDES_C_LANE_RESERVED_DEF_0_SHIFT 0 + +#define SERDES_C_LANE_RESERVED_DEF_1_MASK 0xFFFF0000 +#define SERDES_C_LANE_RESERVED_DEF_1_SHIFT 16 + +#ifdef __cplusplus +} +#endif + +#endif /* __AL_HAL_serdes_c_REGS_H__ */ + +/** @} end of ... group */ + + diff --git a/al_hal_serdes_hssp.h b/al_hal_serdes_hssp.h new file mode 100644 index 00000000000..fe530f6a31b --- /dev/null +++ b/al_hal_serdes_hssp.h @@ -0,0 +1,87 @@ +/******************************************************************************* +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. + +*******************************************************************************/ + +/** + * @defgroup group_serdes_api API + * SerDes HAL driver API + * @ingroup group_serdes SerDes + * @{ + * + * @file al_hal_serdes.h + * + * @brief Header file for the SerDes HAL driver + * + */ + +#ifndef __AL_HAL_SERDES_H__ +#define __AL_HAL_SERDES_H__ + +#include "al_hal_common.h" +#include "al_hal_serdes_interface.h" +#include "al_hal_serdes_hssp_regs.h" + +/* *INDENT-OFF* */ +#ifdef __cplusplus +extern "C" { +#endif +/* *INDENT-ON* */ + +/** + * Initializes a SERDES group object + * + * @param serdes_regs_base + * The SERDES register file base pointer + * + * @param obj + * An allocated, non initialized object context + * + * @return 0 if no error found. + * + */ +int al_serdes_hssp_handle_init( + void __iomem *serdes_regs_base, + struct al_serdes_grp_obj *obj); + + +/* *INDENT-OFF* */ +#ifdef __cplusplus +} +#endif + +/* *INDENT-ON* */ +#endif /* __AL_SRDS__ */ + +/** @} end of SERDES group */ + diff --git a/al_hal_serdes_hssp_internal_regs.h b/al_hal_serdes_hssp_internal_regs.h new file mode 100644 index 00000000000..d5b02151994 --- /dev/null +++ b/al_hal_serdes_hssp_internal_regs.h @@ -0,0 +1,749 @@ +/******************************************************************************* +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. + +*******************************************************************************/ +#ifndef __AL_SERDES_INTERNAL_REGS_H__ +#define __AL_SERDES_INTERNAL_REGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * Per lane register fields + ******************************************************************************/ +/* + * RX and TX lane hard reset + * 0 - Hard reset is asserted + * 1 - Hard reset is de-asserted + */ +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_REG_NUM 2 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_MASK 0x01 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_VAL_ASSERT 0x00 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_VAL_DEASSERT 0x01 + +/* + * RX and TX lane hard reset control + * 0 - Hard reset is taken from the interface pins + * 1 - Hard reset is taken from registers + */ +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_REG_NUM 2 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_MASK 0x02 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_VAL_IFACE 0x00 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_VAL_REGS 0x02 + +/* RX lane power state control */ +#define SERDES_IREG_FLD_LANEPCSPSTATE_RX_REG_NUM 3 +#define SERDES_IREG_FLD_LANEPCSPSTATE_RX_MASK 0x1f +#define SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_PD 0x01 +#define SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_P2 0x02 +#define SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_P1 0x04 +#define SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_P0S 0x08 +#define SERDES_IREG_FLD_LANEPCSPSTATE_RX_VAL_P0 0x10 + +/* TX lane power state control */ +#define SERDES_IREG_FLD_LANEPCSPSTATE_TX_REG_NUM 4 +#define SERDES_IREG_FLD_LANEPCSPSTATE_TX_MASK 0x1f +#define SERDES_IREG_FLD_LANEPCSPSTATE_TX_VAL_PD 0x01 +#define SERDES_IREG_FLD_LANEPCSPSTATE_TX_VAL_P2 0x02 +#define SERDES_IREG_FLD_LANEPCSPSTATE_TX_VAL_P1 0x04 +#define SERDES_IREG_FLD_LANEPCSPSTATE_TX_VAL_P0S 0x08 +#define SERDES_IREG_FLD_LANEPCSPSTATE_TX_VAL_P0 0x10 + +/* RX lane word width */ +#define SERDES_IREG_FLD_PCSRX_DATAWIDTH_REG_NUM 5 +#define SERDES_IREG_FLD_PCSRX_DATAWIDTH_MASK 0x07 +#define SERDES_IREG_FLD_PCSRX_DATAWIDTH_VAL_8 0x00 +#define SERDES_IREG_FLD_PCSRX_DATAWIDTH_VAL_10 0x01 +#define SERDES_IREG_FLD_PCSRX_DATAWIDTH_VAL_16 0x02 +#define SERDES_IREG_FLD_PCSRX_DATAWIDTH_VAL_20 0x03 +#define SERDES_IREG_FLD_PCSRX_DATAWIDTH_VAL_32 0x04 +#define SERDES_IREG_FLD_PCSRX_DATAWIDTH_VAL_40 0x05 + +/* TX lane word width */ +#define SERDES_IREG_FLD_PCSTX_DATAWIDTH_REG_NUM 5 +#define SERDES_IREG_FLD_PCSTX_DATAWIDTH_MASK 0x70 +#define SERDES_IREG_FLD_PCSTX_DATAWIDTH_VAL_8 0x00 +#define SERDES_IREG_FLD_PCSTX_DATAWIDTH_VAL_10 0x10 +#define SERDES_IREG_FLD_PCSTX_DATAWIDTH_VAL_16 0x20 +#define SERDES_IREG_FLD_PCSTX_DATAWIDTH_VAL_20 0x30 +#define SERDES_IREG_FLD_PCSTX_DATAWIDTH_VAL_32 0x40 +#define SERDES_IREG_FLD_PCSTX_DATAWIDTH_VAL_40 0x50 + +/* RX lane rate select */ +#define SERDES_IREG_FLD_PCSRX_DIVRATE_REG_NUM 6 +#define SERDES_IREG_FLD_PCSRX_DIVRATE_MASK 0x07 +#define SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_8 0x00 +#define SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_4 0x01 +#define SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_2 0x02 +#define SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_1 0x03 + +/* TX lane rate select */ +#define SERDES_IREG_FLD_PCSTX_DIVRATE_REG_NUM 6 +#define SERDES_IREG_FLD_PCSTX_DIVRATE_MASK 0x70 +#define SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_8 0x00 +#define SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_4 0x10 +#define SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_2 0x20 +#define SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_1 0x30 + +/* + * PMA serial RX-to-TX loop-back enable (from AGC to IO Driver). Serial receive + * to transmit loopback: 0 - Disables loopback 1 - Transmits the untimed, + * partial equalized RX signal out the transmit IO pins + */ +#define SERDES_IREG_FLD_LB_RX2TXUNTIMEDEN_REG_NUM 7 +#define SERDES_IREG_FLD_LB_RX2TXUNTIMEDEN 0x10 + +/* + * PMA TX-to-RX buffered serial loop-back enable (bypasses IO Driver). Serial + * transmit to receive buffered loopback: 0 - Disables loopback 1 - Loops back + * the TX serializer output into the CDR + */ +#define SERDES_IREG_FLD_LB_TX2RXBUFTIMEDEN_REG_NUM 7 +#define SERDES_IREG_FLD_LB_TX2RXBUFTIMEDEN 0x20 + +/* + * PMA TX-to-RX I/O serial loop-back enable (loop back done directly from TX to + * RX pads). Serial IO loopback from the transmit lane IO pins to the receive + * lane IO pins: 0 - Disables loopback 1 - Loops back the driver IO signal to + * the RX IO pins + */ +#define SERDES_IREG_FLD_LB_TX2RXIOTIMEDEN_REG_NUM 7 +#define SERDES_IREG_FLD_LB_TX2RXIOTIMEDEN 0x40 + +/* + * PMA Parallel RX-to-TX loop-back enable. Parallel loopback from the PMA + * receive lane 20-bit data ports, to the transmit lane 20-bit data ports 0 - + * Disables loopback 1 - Loops back the 20-bit receive data port to the + * transmitter + */ +#define SERDES_IREG_FLD_LB_PARRX2TXTIMEDEN_REG_NUM 7 +#define SERDES_IREG_FLD_LB_PARRX2TXTIMEDEN 0x80 + +/* + * PMA CDR recovered-clock loopback enable; asserted when PARRX2TXTIMEDEN is 1. + * Transmit bit clock select: 0 - Selects synthesizer bit clock for transmit 1 + * - Selects CDR clock for transmit + */ +#define SERDES_IREG_FLD_LB_CDRCLK2TXEN_REG_NUM 7 +#define SERDES_IREG_FLD_LB_CDRCLK2TXEN 0x01 + +/* Receive lane BIST enable. Active High */ +#define SERDES_IREG_FLD_PCSRXBIST_EN_REG_NUM 8 +#define SERDES_IREG_FLD_PCSRXBIST_EN 0x01 + +/* TX lane BIST enable. Active High */ +#define SERDES_IREG_FLD_PCSTXBIST_EN_REG_NUM 8 +#define SERDES_IREG_FLD_PCSTXBIST_EN 0x02 + +/* + * RX BIST completion signal 0 - Indicates test is not completed 1 - Indicates + * the test has completed, and will remain high until a new test is initiated + */ +#define SERDES_IREG_FLD_RXBIST_DONE_REG_NUM 8 +#define SERDES_IREG_FLD_RXBIST_DONE 0x04 + +/* + * RX BIST error count overflow indicator. Indicates an overflow in the number + * of byte errors identified during the course of the test. This word is stable + * to sample when *_DONE_* signal has asserted + */ +#define SERDES_IREG_FLD_RXBIST_ERRCOUNT_OVERFLOW_REG_NUM 8 +#define SERDES_IREG_FLD_RXBIST_ERRCOUNT_OVERFLOW 0x08 + +/* + * RX BIST locked indicator 0 - Indicates BIST is not word locked and error + * comparisons have not begun yet 1 - Indicates BIST is word locked and error + * comparisons have begun + */ +#define SERDES_IREG_FLD_RXBIST_RXLOCKED_REG_NUM 8 +#define SERDES_IREG_FLD_RXBIST_RXLOCKED 0x10 + +/* + * RX BIST error count word. Indicates the number of byte errors identified + * during the course of the test. This word is stable to sample when *_DONE_* + * signal has asserted + */ +#define SERDES_IREG_FLD_RXBIST_ERRCOUNT_MSB_REG_NUM 9 +#define SERDES_IREG_FLD_RXBIST_ERRCOUNT_LSB_REG_NUM 10 + +/* Tx params */ +#define SERDES_IREG_TX_DRV_1_REG_NUM 21 +#define SERDES_IREG_TX_DRV_1_HLEV_MASK 0x7 +#define SERDES_IREG_TX_DRV_1_HLEV_SHIFT 0 +#define SERDES_IREG_TX_DRV_1_LEVN_MASK 0xf8 +#define SERDES_IREG_TX_DRV_1_LEVN_SHIFT 3 + +#define SERDES_IREG_TX_DRV_2_REG_NUM 22 +#define SERDES_IREG_TX_DRV_2_LEVNM1_MASK 0xf +#define SERDES_IREG_TX_DRV_2_LEVNM1_SHIFT 0 +#define SERDES_IREG_TX_DRV_2_LEVNM2_MASK 0x30 +#define SERDES_IREG_TX_DRV_2_LEVNM2_SHIFT 4 + +#define SERDES_IREG_TX_DRV_3_REG_NUM 23 +#define SERDES_IREG_TX_DRV_3_LEVNP1_MASK 0x7 +#define SERDES_IREG_TX_DRV_3_LEVNP1_SHIFT 0 +#define SERDES_IREG_TX_DRV_3_SLEW_MASK 0x18 +#define SERDES_IREG_TX_DRV_3_SLEW_SHIFT 3 + +/* Rx params */ +#define SERDES_IREG_RX_CALEQ_1_REG_NUM 24 +#define SERDES_IREG_RX_CALEQ_1_DCGAIN_MASK 0x7 +#define SERDES_IREG_RX_CALEQ_1_DCGAIN_SHIFT 0 +/* DFE post-shaping tap 3dB frequency */ +#define SERDES_IREG_RX_CALEQ_1_DFEPSTAP3DB_MASK 0x38 +#define SERDES_IREG_RX_CALEQ_1_DFEPSTAP3DB_SHIFT 3 + +#define SERDES_IREG_RX_CALEQ_2_REG_NUM 25 +/* DFE post-shaping tap gain */ +#define SERDES_IREG_RX_CALEQ_2_DFEPSTAPGAIN_MASK 0x7 +#define SERDES_IREG_RX_CALEQ_2_DFEPSTAPGAIN_SHIFT 0 +/* DFE first tap gain control */ +#define SERDES_IREG_RX_CALEQ_2_DFETAP1GAIN_MASK 0x78 +#define SERDES_IREG_RX_CALEQ_2_DFETAP1GAIN_SHIFT 3 + +#define SERDES_IREG_RX_CALEQ_3_REG_NUM 26 +#define SERDES_IREG_RX_CALEQ_3_DFETAP2GAIN_MASK 0xf +#define SERDES_IREG_RX_CALEQ_3_DFETAP2GAIN_SHIFT 0 +#define SERDES_IREG_RX_CALEQ_3_DFETAP3GAIN_MASK 0xf0 +#define SERDES_IREG_RX_CALEQ_3_DFETAP3GAIN_SHIFT 4 + +#define SERDES_IREG_RX_CALEQ_4_REG_NUM 27 +#define SERDES_IREG_RX_CALEQ_4_DFETAP4GAIN_MASK 0xf +#define SERDES_IREG_RX_CALEQ_4_DFETAP4GAIN_SHIFT 0 +#define SERDES_IREG_RX_CALEQ_4_LOFREQAGCGAIN_MASK 0x70 +#define SERDES_IREG_RX_CALEQ_4_LOFREQAGCGAIN_SHIFT 4 + +#define SERDES_IREG_RX_CALEQ_5_REG_NUM 28 +#define SERDES_IREG_RX_CALEQ_5_PRECAL_CODE_SEL_MASK 0x7 +#define SERDES_IREG_RX_CALEQ_5_PRECAL_CODE_SEL_SHIFT 0 +#define SERDES_IREG_RX_CALEQ_5_HIFREQAGCCAP_MASK 0xf8 +#define SERDES_IREG_RX_CALEQ_5_HIFREQAGCCAP_SHIFT 3 + +/* RX lane best eye point measurement result */ +#define SERDES_IREG_RXEQ_BEST_EYE_MSB_VAL_REG_NUM 29 +#define SERDES_IREG_RXEQ_BEST_EYE_LSB_VAL_REG_NUM 30 +#define SERDES_IREG_RXEQ_BEST_EYE_LSB_VAL_MASK 0x3F + +/* + * Adaptive RX Equalization enable + * 0 - Disables adaptive RX equalization. + * 1 - Enables adaptive RX equalization. + */ +#define SERDES_IREG_FLD_PCSRXEQ_START_REG_NUM 31 +#define SERDES_IREG_FLD_PCSRXEQ_START (1 << 0) + +/* + * Enables an eye diagram measurement + * within the PHY. + * 0 - Disables eye diagram measurement + * 1 - Enables eye diagram measurement + */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START_REG_NUM 31 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_START (1 << 1) + + +/* + * RX lane single roam eye point measurement start signal. + * If asserted, single measurement at fix XADJUST and YADJUST is started. + */ +#define SERDES_IREG_FLD_RXCALROAMEYEMEASIN_CYCLEEN_REG_NUM 31 +#define SERDES_IREG_FLD_RXCALROAMEYEMEASIN_CYCLEEN_START (1 << 2) + + +/* + * PHY Eye diagram measurement status + * signal + * 0 - Indicates eye diagram results are not + * valid for sampling + * 1 - Indicates eye diagram is complete and + * results are valid for sampling + */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_DONE_REG_NUM 32 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_DONE (1 << 0) + +/* + * Eye diagram error signal. Indicates if the + * measurement was invalid because the eye + * diagram was interrupted by the link entering + * electrical idle. + * 0 - Indicates eye diagram is valid + * 1- Indicates an error occurred, and the eye + * diagram measurement should be re-run + */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_ERR_REG_NUM 32 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_ERR (1 << 1) + +/* + * PHY Adaptive Equalization status + * 0 - Indicates Adaptive Equalization results are not valid for sampling + * 1 - Indicates Adaptive Equalization is complete and results are valid for + * sampling + */ +#define SERDES_IREG_FLD_RXCALROAMEYEMEASDONE_REG_NUM 32 +#define SERDES_IREG_FLD_RXCALROAMEYEMEASDONE (1 << 2) + +/* + * + * PHY Adaptive Equalization Status Signal + * 0 – Indicates adaptive equalization results + * are not valid for sampling + * 1 – Indicates adaptive equalization is + * complete and results are valid for sampling. + */ +#define SERDES_IREG_FLD_RXEQ_DONE_REG_NUM 32 +#define SERDES_IREG_FLD_RXEQ_DONE (1 << 3) + + +/* + * 7-bit eye diagram time adjust control + * - 6-bits per UI + * - spans 2 UI + */ +#define SERDES_IREG_FLD_RXCALROAMXADJUST_REG_NUM 33 + +/* 6-bit eye diagram voltage adjust control - spans +/-300mVdiff */ +#define SERDES_IREG_FLD_RXCALROAMYADJUST_REG_NUM 34 + +/* + * Eye diagram status signal. Safe for + * sampling when *DONE* signal has + * asserted + * 14'h0000 - Completely Closed Eye + * 14'hFFFF - Completely Open Eye + */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_MSB_REG_NUM 35 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_MSB_MAKE 0xFF +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_MSB_SHIFT 0 + +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB_REG_NUM 36 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB_MAKE 0x3F +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_EYESUM_LSB_SHIFT 0 + +/* + * RX lane single roam eye point measurement result. + * If 0, eye is open at current XADJUST and YADJUST settings. + */ +#define SERDES_IREG_FLD_RXCALROAMEYEMEAS_ACC_MSB_REG_NUM 37 +#define SERDES_IREG_FLD_RXCALROAMEYEMEAS_ACC_LSB_REG_NUM 38 + +/* + * Override enable for CDR lock to reference clock + * 0 - CDR is always locked to reference + * 1 - CDR operation mode (Lock2Reference or Lock2data are controlled internally + * depending on the incoming signal and ppm status) + */ +#define SERDES_IREG_FLD_RXLOCK2REF_OVREN_REG_NUM 39 +#define SERDES_IREG_FLD_RXLOCK2REF_OVREN (1 << 1) + +/* + * Selects Eye to capture based on edge + * 0 - Capture 1st Eye in Eye Diagram + * 1 - Capture 2nd Eye in Eye Diagram measurement + */ +#define SERDES_IREG_FLD_RXROAM_XORBITSEL_REG_NUM 39 +#define SERDES_IREG_FLD_RXROAM_XORBITSEL (1 << 2) +#define SERDES_IREG_FLD_RXROAM_XORBITSEL_1ST 0 +#define SERDES_IREG_FLD_RXROAM_XORBITSEL_2ND (1 << 2) + +/* + * RX Signal detect. 0 indicates no signal, 1 indicates signal detected. + */ +#define SERDES_IREG_FLD_RXRANDET_REG_NUM 41 +#define SERDES_IREG_FLD_RXRANDET_STAT 0x20 + +/* + * RX data polarity inversion control: + * 1'b0: no inversion + * 1'b1: invert polarity + */ +#define SERDES_IREG_FLD_POLARITY_RX_REG_NUM 46 +#define SERDES_IREG_FLD_POLARITY_RX_INV (1 << 0) + +/* + * TX data polarity inversion control: + * 1'b0: no inversion + * 1'b1: invert polarity + */ +#define SERDES_IREG_FLD_POLARITY_TX_REG_NUM 46 +#define SERDES_IREG_FLD_POLARITY_TX_INV (1 << 1) + +/* LANEPCSPSTATE* override enable (Active low) */ +#define SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM 85 +#define SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN (1 << 0) + +/* LB* override enable (Active low) */ +#define SERDES_IREG_FLD_LB_LOCWREN_REG_NUM 85 +#define SERDES_IREG_FLD_LB_LOCWREN (1 << 1) + +/* PCSRX* override enable (Active low) */ +#define SERDES_IREG_FLD_PCSRX_LOCWREN_REG_NUM 85 +#define SERDES_IREG_FLD_PCSRX_LOCWREN (1 << 4) + +/* PCSRXBIST* override enable (Active low) */ +#define SERDES_IREG_FLD_PCSRXBIST_LOCWREN_REG_NUM 85 +#define SERDES_IREG_FLD_PCSRXBIST_LOCWREN (1 << 5) + +/* PCSRXEQ* override enable (Active low) */ +#define SERDES_IREG_FLD_PCSRXEQ_LOCWREN_REG_NUM 85 +#define SERDES_IREG_FLD_PCSRXEQ_LOCWREN (1 << 6) + +/* PCSTX* override enable (Active low) */ +#define SERDES_IREG_FLD_PCSTX_LOCWREN_REG_NUM 85 +#define SERDES_IREG_FLD_PCSTX_LOCWREN (1 << 7) + +/* + * group registers: + * SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN, + * SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN + * SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN + */ +#define SERDES_IREG_FLD_RXCAL_LOCWREN_REG_NUM 86 + +/* PCSTXBIST* override enable (Active low) */ +#define SERDES_IREG_FLD_PCSTXBIST_LOCWREN_REG_NUM 86 +#define SERDES_IREG_FLD_PCSTXBIST_LOCWREN (1 << 0) + +/* Override RX_CALCEQ through the internal registers (Active low) */ +#define SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN_REG_NUM 86 +#define SERDES_IREG_FLD_RX_DRV_OVERRIDE_EN (1 << 3) + +#define SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN_REG_NUM 86 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSMIN_LOCWREN (1 << 4) + + +/* RXCALROAMEYEMEASIN* override enable - Active Low */ +#define SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN_REG_NUM 86 +#define SERDES_IREG_FLD_RXCALROAMEYEMEASIN_LOCWREN (1 << 6) + +/* RXCALROAMXADJUST* override enable - Active Low */ +#define SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN_REG_NUM 86 +#define SERDES_IREG_FLD_RXCALROAMXADJUST_LOCWREN (1 << 7) + +/* RXCALROAMYADJUST* override enable - Active Low */ +#define SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN_REG_NUM 87 +#define SERDES_IREG_FLD_RXCALROAMYADJUST_LOCWREN (1 << 0) + +/* RXCDRCALFOSC* override enable. Active Low */ +#define SERDES_IREG_FLD_RXCDRCALFOSC_LOCWREN_REG_NUM 87 +#define SERDES_IREG_FLD_RXCDRCALFOSC_LOCWREN (1 << 1) + +/* Over-write enable for RXEYEDIAGFSM_INITXVAL */ +#define SERDES_IREG_FLD_RXEYEDIAGFSM_LOCWREN_REG_NUM 87 +#define SERDES_IREG_FLD_RXEYEDIAGFSM_LOCWREN (1 << 2) + +/* Over-write enable for CMNCLKGENMUXSEL_TXINTERNAL */ +#define SERDES_IREG_FLD_RXTERMHIZ_LOCWREN_REG_NUM 87 +#define SERDES_IREG_FLD_RXTERMHIZ_LOCWREN (1 << 3) + +/* TXCALTCLKDUTY* override enable. Active Low */ +#define SERDES_IREG_FLD_TXCALTCLKDUTY_LOCWREN_REG_NUM 87 +#define SERDES_IREG_FLD_TXCALTCLKDUTY_LOCWREN (1 << 4) + +/* Override TX_DRV through the internal registers (Active low) */ +#define SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN_REG_NUM 87 +#define SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN (1 << 5) + +/******************************************************************************* + * Common lane register fields - PMA + ******************************************************************************/ +/* + * Common lane hard reset control + * 0 - Hard reset is taken from the interface pins + * 1 - Hard reset is taken from registers + */ +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_SYNTH_REG_NUM 2 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_SYNTH_MASK 0x01 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_SYNTH_VAL_IFACE 0x00 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASSEN_SYNTH_VAL_REGS 0x01 + +/* + * Common lane hard reset + * 0 - Hard reset is asserted + * 1 - Hard reset is de-asserted + */ +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_SYNTH_REG_NUM 2 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_SYNTH_MASK 0x02 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_SYNTH_VAL_ASSERT 0x00 +#define SERDES_IREG_FLD_CMNCTLPOR_HARDRSTBYPASS_SYNTH_VAL_DEASSERT 0x02 + +/* Synth power state control */ +#define SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_REG_NUM 3 +#define SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_MASK 0x1f +#define SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_PD 0x01 +#define SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P2 0x02 +#define SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P1 0x04 +#define SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P0S 0x08 +#define SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P0 0x10 + +/* Transmit datapath FIFO enable (Active High) */ +#define SERDES_IREG_FLD_CMNPCS_TXENABLE_REG_NUM 8 +#define SERDES_IREG_FLD_CMNPCS_TXENABLE (1 << 2) + +/* + * RX lost of signal detector enable + * - 0 - disable + * - 1 - enable + */ +#define SERDES_IREG_FLD_RXLOSDET_ENABLE_REG_NUM 13 +#define SERDES_IREG_FLD_RXLOSDET_ENABLE AL_BIT(4) + +/* Signal Detect Threshold Level */ +#define SERDES_IREG_FLD_RXELECIDLE_SIGDETTHRESH_REG_NUM 15 +#define SERDES_IREG_FLD_RXELECIDLE_SIGDETTHRESH_MASK AL_FIELD_MASK(2, 0) + +/* LOS Detect Threshold Level */ +#define SERDES_IREG_FLD_RXLOSDET_THRESH_REG_NUM 15 +#define SERDES_IREG_FLD_RXLOSDET_THRESH_MASK AL_FIELD_MASK(4, 3) +#define SERDES_IREG_FLD_RXLOSDET_THRESH_SHIFT 3 + +#define SERDES_IREG_FLD_RXEQ_COARSE_ITER_NUM_REG_NUM 30 +#define SERDES_IREG_FLD_RXEQ_COARSE_ITER_NUM_MASK 0x7f +#define SERDES_IREG_FLD_RXEQ_COARSE_ITER_NUM_SHIFT 0 + +#define SERDES_IREG_FLD_RXEQ_FINE_ITER_NUM_REG_NUM 31 +#define SERDES_IREG_FLD_RXEQ_FINE_ITER_NUM_MASK 0x7f +#define SERDES_IREG_FLD_RXEQ_FINE_ITER_NUM_SHIFT 0 + +#define SERDES_IREG_FLD_RXEQ_COARSE_RUN1_MASK_REG_NUM 32 +#define SERDES_IREG_FLD_RXEQ_COARSE_RUN1_MASK_MASK 0xff +#define SERDES_IREG_FLD_RXEQ_COARSE_RUN1_MASK_SHIFT 0 + +#define SERDES_IREG_FLD_RXEQ_COARSE_RUN2_MASK_REG_NUM 33 +#define SERDES_IREG_FLD_RXEQ_COARSE_RUN2_MASK_MASK 0x1 +#define SERDES_IREG_FLD_RXEQ_COARSE_RUN2_MASK_SHIFT 0 + +#define SERDES_IREG_FLD_RXEQ_COARSE_STEP_REG_NUM 33 +#define SERDES_IREG_FLD_RXEQ_COARSE_STEP_MASK 0x3e +#define SERDES_IREG_FLD_RXEQ_COARSE_STEP_SHIFT 1 + +#define SERDES_IREG_FLD_RXEQ_FINE_RUN1_MASK_REG_NUM 34 +#define SERDES_IREG_FLD_RXEQ_FINE_RUN1_MASK_MASK 0xff +#define SERDES_IREG_FLD_RXEQ_FINE_RUN1_MASK_SHIFT 0 + +#define SERDES_IREG_FLD_RXEQ_FINE_RUN2_MASK_REG_NUM 35 +#define SERDES_IREG_FLD_RXEQ_FINE_RUN2_MASK_MASK 0x1 +#define SERDES_IREG_FLD_RXEQ_FINE_RUN2_MASK_SHIFT 0 + +#define SERDES_IREG_FLD_RXEQ_FINE_STEP_REG_NUM 35 +#define SERDES_IREG_FLD_RXEQ_FINE_STEP_MASK 0x3e +#define SERDES_IREG_FLD_RXEQ_FINE_STEP_SHIFT 1 + +#define SERDES_IREG_FLD_RXEQ_LOOKUP_CODE_EN_REG_NUM 36 +#define SERDES_IREG_FLD_RXEQ_LOOKUP_CODE_EN_MASK 0xff +#define SERDES_IREG_FLD_RXEQ_LOOKUP_CODE_EN_SHIFT 0 + +#define SERDES_IREG_FLD_RXEQ_LOOKUP_LASTCODE_REG_NUM 37 +#define SERDES_IREG_FLD_RXEQ_LOOKUP_LASTCODE_MASK 0x7 +#define SERDES_IREG_FLD_RXEQ_LOOKUP_LASTCODE_SHIFT 0 + +#define SERDES_IREG_FLD_RXEQ_DCGAIN_LUP0_REG_NUM 43 +#define SERDES_IREG_FLD_RXEQ_DCGAIN_LUP0_MASK 0x7 +#define SERDES_IREG_FLD_RXEQ_DCGAIN_LUP0_SHIFT 0 + +#define SERDES_IREG_FLD_TX_BIST_PAT_REG_NUM(byte_num) (56 + (byte_num)) +#define SERDES_IREG_FLD_TX_BIST_PAT_NUM_BYTES 10 + +/* + * Selects the transmit BIST mode: + * 0 - Uses the 80-bit internal memory pattern (w/ OOB) + * 1 - Uses a 27 PRBS pattern + * 2 - Uses a 223 PRBS pattern + * 3 - Uses a 231 PRBS pattern + * 4 - Uses a 1010 clock pattern + * 5 and above - Reserved + */ +#define SERDES_IREG_FLD_CMNPCSBIST_MODESEL_REG_NUM 80 +#define SERDES_IREG_FLD_CMNPCSBIST_MODESEL_MASK 0x07 +#define SERDES_IREG_FLD_CMNPCSBIST_MODESEL_VAL_USER 0x00 +#define SERDES_IREG_FLD_CMNPCSBIST_MODESEL_VAL_PRBS7 0x01 +#define SERDES_IREG_FLD_CMNPCSBIST_MODESEL_VAL_PRBS23 0x02 +#define SERDES_IREG_FLD_CMNPCSBIST_MODESEL_VAL_PRBS31 0x03 +#define SERDES_IREG_FLD_CMNPCSBIST_MODESEL_VAL_CLK1010 0x04 + +/* Single-Bit error injection enable (on posedge) */ +#define SERDES_IREG_FLD_TXBIST_BITERROR_EN_REG_NUM 80 +#define SERDES_IREG_FLD_TXBIST_BITERROR_EN 0x20 + +/* CMNPCIEGEN3* override enable (Active Low) */ +#define SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN_REG_NUM 95 +#define SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN (1 << 2) + +/* CMNPCS* override enable (Active Low) */ +#define SERDES_IREG_FLD_CMNPCS_LOCWREN_REG_NUM 95 +#define SERDES_IREG_FLD_CMNPCS_LOCWREN (1 << 3) + +/* CMNPCSBIST* override enable (Active Low) */ +#define SERDES_IREG_FLD_CMNPCSBIST_LOCWREN_REG_NUM 95 +#define SERDES_IREG_FLD_CMNPCSBIST_LOCWREN (1 << 4) + +/* CMNPCSPSTATE* override enable (Active Low) */ +#define SERDES_IREG_FLD_CMNPCSPSTATE_LOCWREN_REG_NUM 95 +#define SERDES_IREG_FLD_CMNPCSPSTATE_LOCWREN (1 << 5) + +/* PCS_EN* override enable (Active Low) */ +#define SERDES_IREG_FLD_PCS_LOCWREN_REG_NUM 96 +#define SERDES_IREG_FLD_PCS_LOCWREN (1 << 3) + +/* Eye diagram sample count */ +#define SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_MSB_REG_NUM 150 +#define SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_MSB_MASK 0xff +#define SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_MSB_SHIFT 0 + +#define SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_LSB_REG_NUM 151 +#define SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_LSB_MASK 0xff +#define SERDES_IREG_FLD_EYE_DIAG_SAMPLE_CNT_LSB_SHIFT 0 + +/* override control */ +#define SERDES_IREG_FLD_RXLOCK2REF_LOCWREN_REG_NUM 230 +#define SERDES_IREG_FLD_RXLOCK2REF_LOCWREN 1 << 0 + +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD1_REG_NUM 623 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD1_MASK 0xff +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD1_SHIFT 0 + +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD2_REG_NUM 624 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD2_MASK 0xff +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_BERTHRESHOLD2_SHIFT 0 + +/* X and Y coefficient return value */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_X_Y_VALWEIGHT_REG_NUM 626 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALWEIGHT_MASK 0x0F +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALWEIGHT_SHIFT 0 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALWEIGHT_MASK 0xF0 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALWEIGHT_SHIFT 4 + +/* X coarse scan step */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_REG_NUM 627 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_MASK 0x7F +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALCOARSE_SHIFT 0 + +/* X fine scan step */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_REG_NUM 628 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_MASK 0x7F +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_XVALFINE_SHIFT 0 + +/* Y coarse scan step */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_REG_NUM 629 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_MASK 0x0F +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALCOARSE_SHIFT 0 + +/* Y fine scan step */ +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_REG_NUM 630 +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_MASK 0x0F +#define SERDES_IREG_FLD_RXCALEYEDIAGFSM_YVALFINE_SHIFT 0 + +#define SERDES_IREG_FLD_PPMDRIFTCOUNT1_REG_NUM 157 + +#define SERDES_IREG_FLD_PPMDRIFTCOUNT2_REG_NUM 158 + +#define SERDES_IREG_FLD_PPMDRIFTMAX1_REG_NUM 159 + +#define SERDES_IREG_FLD_PPMDRIFTMAX2_REG_NUM 160 + +#define SERDES_IREG_FLD_SYNTHPPMDRIFTMAX1_REG_NUM 163 + +#define SERDES_IREG_FLD_SYNTHPPMDRIFTMAX2_REG_NUM 164 + +/******************************************************************************* + * Common lane register fields - PCS + ******************************************************************************/ +#define SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_REG_NUM 3 +#define SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_MASK AL_FIELD_MASK(5, 4) +#define SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_SHIFT 4 + +#define SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_ENA_REG_NUM 6 +#define SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_ENA AL_BIT(2) + +#define SERDES_IREG_FLD_PCS_EBUF_FULL_D2R1_REG_NUM 18 +#define SERDES_IREG_FLD_PCS_EBUF_FULL_D2R1_REG_MASK 0x1F +#define SERDES_IREG_FLD_PCS_EBUF_FULL_D2R1_REG_SHIFT 0 + +#define SERDES_IREG_FLD_PCS_EBUF_FULL_PCIE_G3_REG_NUM 19 +#define SERDES_IREG_FLD_PCS_EBUF_FULL_PCIE_G3_REG_MASK 0x7C +#define SERDES_IREG_FLD_PCS_EBUF_FULL_PCIE_G3_REG_SHIFT 2 + +#define SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_D2R1_REG_NUM 20 +#define SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_D2R1_REG_MASK 0x1F +#define SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_D2R1_REG_SHIFT 0 + +#define SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_PCIE_G3_REG_NUM 21 +#define SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_PCIE_G3_REG_MASK 0x7C +#define SERDES_IREG_FLD_PCS_EBUF_RD_THRESHOLD_PCIE_G3_REG_SHIFT 2 + +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_ITER_NUM_REG_NUM 22 +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_ITER_NUM_MASK 0x7f +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_ITER_NUM_SHIFT 0 + +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_ITER_NUM_REG_NUM 34 +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_ITER_NUM_MASK 0x7f +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_ITER_NUM_SHIFT 0 + +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_RUN1_MASK_REG_NUM 23 +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_RUN1_MASK_MASK 0xff +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_RUN1_MASK_SHIFT 0 + +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_RUN2_MASK_REG_NUM 22 +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_RUN2_MASK_MASK 0x80 +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_RUN2_MASK_SHIFT 7 + +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_STEP_REG_NUM 24 +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_STEP_MASK 0x3e +#define SERDES_IREG_FLD_PCS_RXEQ_COARSE_STEP_SHIFT 1 + +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_RUN1_MASK_REG_NUM 35 +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_RUN1_MASK_MASK 0xff +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_RUN1_MASK_SHIFT 0 + +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_RUN2_MASK_REG_NUM 34 +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_RUN2_MASK_MASK 0x80 +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_RUN2_MASK_SHIFT 7 + +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_STEP_REG_NUM 36 +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_STEP_MASK 0x1f +#define SERDES_IREG_FLD_PCS_RXEQ_FINE_STEP_SHIFT 0 + +#define SERDES_IREG_FLD_PCS_RXEQ_LOOKUP_CODE_EN_REG_NUM 37 +#define SERDES_IREG_FLD_PCS_RXEQ_LOOKUP_CODE_EN_MASK 0xff +#define SERDES_IREG_FLD_PCS_RXEQ_LOOKUP_CODE_EN_SHIFT 0 + +#define SERDES_IREG_FLD_PCS_RXEQ_LOOKUP_LASTCODE_REG_NUM 36 +#define SERDES_IREG_FLD_PCS_RXEQ_LOOKUP_LASTCODE_MASK 0xe0 +#define SERDES_IREG_FLD_PCS_RXEQ_LOOKUP_LASTCODE_SHIFT 5 + +#ifdef __cplusplus +} +#endif + +#endif /* __AL_serdes_REG_H */ + diff --git a/al_hal_serdes_hssp_regs.h b/al_hal_serdes_hssp_regs.h new file mode 100644 index 00000000000..20f6cbfa020 --- /dev/null +++ b/al_hal_serdes_hssp_regs.h @@ -0,0 +1,494 @@ +/******************************************************************************* +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_serdes_regs.h + * + * @brief ... registers + * + */ + +#ifndef __AL_HAL_SERDES_REGS_H__ +#define __AL_HAL_SERDES_REGS_H__ + +#include "al_hal_plat_types.h" + +#ifdef __cplusplus +extern "C" { +#endif +/* +* Unit Registers +*/ + +struct serdes_gen { + /* [0x0] SerDes Registers Version */ + uint32_t version; + uint32_t rsrvd_0[3]; + /* [0x10] SerDes register file address */ + uint32_t reg_addr; + /* [0x14] SerDes register file data */ + uint32_t reg_data; + uint32_t rsrvd_1[2]; + /* [0x20] SerDes control */ + uint32_t ictl_multi_bist; + /* [0x24] SerDes control */ + uint32_t ictl_pcs; + /* [0x28] SerDes control */ + uint32_t ictl_pma; + uint32_t rsrvd_2; + /* [0x30] SerDes control */ + uint32_t ipd_multi_synth; + /* [0x34] SerDes control */ + uint32_t irst; + /* [0x38] SerDes control */ + uint32_t octl_multi_synthready; + /* [0x3c] SerDes control */ + uint32_t octl_multi_synthstatus; + /* [0x40] SerDes control */ + uint32_t clk_out; + uint32_t rsrvd[47]; +}; +struct serdes_lane { + uint32_t rsrvd1[4]; + /* [0x10] SerDes status */ + uint32_t octl_pma; + /* [0x14] SerDes control */ + uint32_t ictl_multi_andme; + /* [0x18] SerDes control */ + uint32_t ictl_multi_lb; + /* [0x1c] SerDes control */ + uint32_t ictl_multi_rxbist; + /* [0x20] SerDes control */ + uint32_t ictl_multi_txbist; + /* [0x24] SerDes control */ + uint32_t ictl_multi; + /* [0x28] SerDes control */ + uint32_t ictl_multi_rxeq; + /* [0x2c] SerDes control */ + uint32_t ictl_multi_rxeq_l_low; + /* [0x30] SerDes control */ + uint32_t ictl_multi_rxeq_l_high; + /* [0x34] SerDes control */ + uint32_t ictl_multi_rxeyediag; + /* [0x38] SerDes control */ + uint32_t ictl_multi_txdeemph; + /* [0x3c] SerDes control */ + uint32_t ictl_multi_txmargin; + /* [0x40] SerDes control */ + uint32_t ictl_multi_txswing; + /* [0x44] SerDes control */ + uint32_t idat_multi; + /* [0x48] SerDes control */ + uint32_t ipd_multi; + /* [0x4c] SerDes control */ + uint32_t octl_multi_rxbist; + /* [0x50] SerDes control */ + uint32_t octl_multi; + /* [0x54] SerDes control */ + uint32_t octl_multi_rxeyediag; + /* [0x58] SerDes control */ + uint32_t odat_multi_rxbist; + /* [0x5c] SerDes control */ + uint32_t odat_multi_rxeq; + /* [0x60] SerDes control */ + uint32_t multi_rx_dvalid; + /* [0x64] SerDes control */ + uint32_t reserved; + uint32_t rsrvd[6]; +}; + +struct al_serdes_regs { + uint32_t rsrvd_0[64]; + struct serdes_gen gen; /* [0x100] */ + struct serdes_lane lane[4]; /* [0x200] */ +}; + + +/* +* Registers Fields +*/ + + +/**** version register ****/ +/* Revision number (Minor) */ +#define SERDES_GEN_VERSION_RELEASE_NUM_MINOR_MASK 0x000000FF +#define SERDES_GEN_VERSION_RELEASE_NUM_MINOR_SHIFT 0 +/* Revision number (Major) */ +#define SERDES_GEN_VERSION_RELEASE_NUM_MAJOR_MASK 0x0000FF00 +#define SERDES_GEN_VERSION_RELEASE_NUM_MAJOR_SHIFT 8 +/* Date of release */ +#define SERDES_GEN_VERSION_DATE_DAY_MASK 0x001F0000 +#define SERDES_GEN_VERSION_DATE_DAY_SHIFT 16 +/* Month of release */ +#define SERDES_GEN_VERSION_DATA_MONTH_MASK 0x01E00000 +#define SERDES_GEN_VERSION_DATA_MONTH_SHIFT 21 +/* Year of release (starting from 2000) */ +#define SERDES_GEN_VERSION_DATE_YEAR_MASK 0x3E000000 +#define SERDES_GEN_VERSION_DATE_YEAR_SHIFT 25 +/* Reserved */ +#define SERDES_GEN_VERSION_RESERVED_MASK 0xC0000000 +#define SERDES_GEN_VERSION_RESERVED_SHIFT 30 + +/**** reg_addr register ****/ +/* Address value */ +#define SERDES_GEN_REG_ADDR_VAL_MASK 0x0000FFFF +#define SERDES_GEN_REG_ADDR_VAL_SHIFT 0 + +/**** reg_data register ****/ +/* Data value */ +#define SERDES_GEN_REG_DATA_VAL_MASK 0x000000FF +#define SERDES_GEN_REG_DATA_VAL_SHIFT 0 + +/**** ICTL_MULTI_BIST register ****/ + +#define SERDES_GEN_ICTL_MULTI_BIST_MODESEL_NT_MASK 0x00000007 +#define SERDES_GEN_ICTL_MULTI_BIST_MODESEL_NT_SHIFT 0 + +/**** ICTL_PCS register ****/ + +#define SERDES_GEN_ICTL_PCS_EN_NT (1 << 0) + +/**** ICTL_PMA register ****/ + +#define SERDES_GEN_ICTL_PMA_REF_SEL_NT_MASK 0x00000007 +#define SERDES_GEN_ICTL_PMA_REF_SEL_NT_SHIFT 0 + +#define SERDES_GEN_ICTL_PMA_REF_SEL_NT_REF \ + (0 << (SERDES_GEN_ICTL_PMA_REF_SEL_NT_SHIFT)) +#define SERDES_GEN_ICTL_PMA_REF_SEL_NT_R2L \ + (3 << (SERDES_GEN_ICTL_PMA_REF_SEL_NT_SHIFT)) +#define SERDES_GEN_ICTL_PMA_REF_SEL_NT_L2R \ + (4 << (SERDES_GEN_ICTL_PMA_REF_SEL_NT_SHIFT)) + +#define SERDES_GEN_ICTL_PMA_REFBUSRIGHT2LEFT_MODE_NT_MASK 0x00000070 +#define SERDES_GEN_ICTL_PMA_REFBUSRIGHT2LEFT_MODE_NT_SHIFT 4 + +#define SERDES_GEN_ICTL_PMA_REFBUSRIGHT2LEFT_MODE_NT_0 \ + (0 << (SERDES_GEN_ICTL_PMA_REFBUSRIGHT2LEFT_MODE_NT_SHIFT)) +#define SERDES_GEN_ICTL_PMA_REFBUSRIGHT2LEFT_MODE_NT_REF \ + (2 << (SERDES_GEN_ICTL_PMA_REFBUSRIGHT2LEFT_MODE_NT_SHIFT)) +#define SERDES_GEN_ICTL_PMA_REFBUSRIGHT2LEFT_MODE_NT_R2L \ + (3 << (SERDES_GEN_ICTL_PMA_REFBUSRIGHT2LEFT_MODE_NT_SHIFT)) + +#define SERDES_GEN_ICTL_PMA_REFBUSLEFT2RIGHT_MODE_NT_MASK 0x00000700 +#define SERDES_GEN_ICTL_PMA_REFBUSLEFT2RIGHT_MODE_NT_SHIFT 8 + +#define SERDES_GEN_ICTL_PMA_REFBUSLEFT2RIGHT_MODE_NT_0 \ + (0 << (SERDES_GEN_ICTL_PMA_REFBUSLEFT2RIGHT_MODE_NT_SHIFT)) +#define SERDES_GEN_ICTL_PMA_REFBUSLEFT2RIGHT_MODE_NT_REF \ + (2 << (SERDES_GEN_ICTL_PMA_REFBUSLEFT2RIGHT_MODE_NT_SHIFT)) +#define SERDES_GEN_ICTL_PMA_REFBUSLEFT2RIGHT_MODE_NT_L2R \ + (3 << (SERDES_GEN_ICTL_PMA_REFBUSLEFT2RIGHT_MODE_NT_SHIFT)) + +#define SERDES_GEN_ICTL_PMA_TXENABLE_A_SRC (1 << 11) +#define SERDES_GEN_ICTL_PMA_TXENABLE_A_SRC_THIS (0 << 11) +#define SERDES_GEN_ICTL_PMA_TXENABLE_A_SRC_MASTER (1 << 11) + +#define SERDES_GEN_ICTL_PMA_TXENABLE_A (1 << 12) + +#define SERDES_GEN_ICTL_PMA_SYNTHCKBYPASSEN_NT (1 << 13) + +/**** IPD_MULTI_SYNTH register ****/ + +#define SERDES_GEN_IPD_MULTI_SYNTH_B (1 << 0) + +/**** IRST register ****/ + +#define SERDES_GEN_IRST_PIPE_RST_L3_B_A (1 << 0) + +#define SERDES_GEN_IRST_PIPE_RST_L2_B_A (1 << 1) + +#define SERDES_GEN_IRST_PIPE_RST_L1_B_A (1 << 2) + +#define SERDES_GEN_IRST_PIPE_RST_L0_B_A (1 << 3) + +#define SERDES_GEN_IRST_MULTI_HARD_TXRX_L3_B_A (1 << 4) + +#define SERDES_GEN_IRST_MULTI_HARD_TXRX_L2_B_A (1 << 5) + +#define SERDES_GEN_IRST_MULTI_HARD_TXRX_L1_B_A (1 << 6) + +#define SERDES_GEN_IRST_MULTI_HARD_TXRX_L0_B_A (1 << 7) + +#define SERDES_GEN_IRST_MULTI_HARD_SYNTH_B_A (1 << 8) + +#define SERDES_GEN_IRST_POR_B_A (1 << 12) + +#define SERDES_GEN_IRST_PIPE_RST_L3_B_A_SEL (1 << 16) + +#define SERDES_GEN_IRST_PIPE_RST_L2_B_A_SEL (1 << 17) + +#define SERDES_GEN_IRST_PIPE_RST_L1_B_A_SEL (1 << 18) + +#define SERDES_GEN_IRST_PIPE_RST_L0_B_A_SEL (1 << 19) + +#define SERDES_GEN_IRST_MULTI_HARD_TXRX_L3_B_A_SEL (1 << 20) + +#define SERDES_GEN_IRST_MULTI_HARD_TXRX_L2_B_A_SEL (1 << 21) + +#define SERDES_GEN_IRST_MULTI_HARD_TXRX_L1_B_A_SEL (1 << 22) + +#define SERDES_GEN_IRST_MULTI_HARD_TXRX_L0_B_A_SEL (1 << 23) + +/**** OCTL_MULTI_SYNTHREADY register ****/ + +#define SERDES_GEN_OCTL_MULTI_SYNTHREADY_A (1 << 0) + +/**** OCTL_MULTI_SYNTHSTATUS register ****/ + +#define SERDES_GEN_OCTL_MULTI_SYNTHSTATUS_A (1 << 0) + +/**** clk_out register ****/ + +#define SERDES_GEN_CLK_OUT_SEL_MASK 0x0000003F +#define SERDES_GEN_CLK_OUT_SEL_SHIFT 0 + +/**** OCTL_PMA register ****/ + +#define SERDES_LANE_OCTL_PMA_TXSTATUS_L_A (1 << 0) + +/**** ICTL_MULTI_ANDME register ****/ + +#define SERDES_LANE_ICTL_MULTI_ANDME_EN_L_A (1 << 0) + +#define SERDES_LANE_ICTL_MULTI_ANDME_EN_L_A_SEL (1 << 1) + +/**** ICTL_MULTI_LB register ****/ + +#define SERDES_LANE_ICTL_MULTI_LB_TX2RXIOTIMEDEN_L_NT (1 << 0) + +#define SERDES_LANE_ICTL_MULTI_LB_TX2RXBUFTIMEDEN_L_NT (1 << 1) + +#define SERDES_LANE_ICTL_MULTI_LB_RX2TXUNTIMEDEN_L_NT (1 << 2) + +#define SERDES_LANE_ICTL_MULTI_LB_PARRX2TXTIMEDEN_L_NT (1 << 3) + +#define SERDES_LANE_ICTL_MULTI_LB_CDRCLK2TXEN_L_NT (1 << 4) + +#define SERDES_LANE_ICTL_MULTI_LB_TX2RXBUFTIMEDEN_L_NT_SEL (1 << 8) + +#define SERDES_LANE_ICTL_MULTI_LB_RX2TXUNTIMEDEN_L_NT_SEL (1 << 9) + +/**** ICTL_MULTI_RXBIST register ****/ + +#define SERDES_LANE_ICTL_MULTI_RXBIST_EN_L_A (1 << 0) + +/**** ICTL_MULTI_TXBIST register ****/ + +#define SERDES_LANE_ICTL_MULTI_TXBIST_EN_L_A (1 << 0) + +/**** ICTL_MULTI register ****/ + +#define SERDES_LANE_ICTL_MULTI_PSTATE_L_MASK 0x00000003 +#define SERDES_LANE_ICTL_MULTI_PSTATE_L_SHIFT 0 + +#define SERDES_LANE_ICTL_MULTI_PSTATE_L_SEL (1 << 2) + +#define SERDES_LANE_ICTL_MULTI_RXDATAWIDTH_L_MASK 0x00000070 +#define SERDES_LANE_ICTL_MULTI_RXDATAWIDTH_L_SHIFT 4 + +#define SERDES_LANE_ICTL_MULTI_RXOVRCDRLOCK2DATAEN_L_A (1 << 8) + +#define SERDES_LANE_ICTL_MULTI_RXOVRCDRLOCK2DATA_L_A (1 << 9) + +#define SERDES_LANE_ICTL_MULTI_TXBEACON_L_A (1 << 12) + +#define SERDES_LANE_ICTL_MULTI_TXDETECTRXREQ_L_A (1 << 13) + +#define SERDES_LANE_ICTL_MULTI_RXRATE_L_MASK 0x00070000 +#define SERDES_LANE_ICTL_MULTI_RXRATE_L_SHIFT 16 + +#define SERDES_LANE_ICTL_MULTI_RXRATE_L_SEL (1 << 19) + +#define SERDES_LANE_ICTL_MULTI_TXRATE_L_MASK 0x00700000 +#define SERDES_LANE_ICTL_MULTI_TXRATE_L_SHIFT 20 + +#define SERDES_LANE_ICTL_MULTI_TXRATE_L_SEL (1 << 23) + +#define SERDES_LANE_ICTL_MULTI_TXAMP_L_MASK 0x07000000 +#define SERDES_LANE_ICTL_MULTI_TXAMP_L_SHIFT 24 + +#define SERDES_LANE_ICTL_MULTI_TXAMP_EN_L (1 << 27) + +#define SERDES_LANE_ICTL_MULTI_TXDATAWIDTH_L_MASK 0x70000000 +#define SERDES_LANE_ICTL_MULTI_TXDATAWIDTH_L_SHIFT 28 + +/**** ICTL_MULTI_RXEQ register ****/ + +#define SERDES_LANE_ICTL_MULTI_RXEQ_EN_L (1 << 0) + +#define SERDES_LANE_ICTL_MULTI_RXEQ_START_L_A (1 << 1) + +#define SERDES_LANE_ICTL_MULTI_RXEQ_PRECAL_CODE_SEL_MASK 0x00000070 +#define SERDES_LANE_ICTL_MULTI_RXEQ_PRECAL_CODE_SEL_SHIFT 4 + +/**** ICTL_MULTI_RXEQ_L_high register ****/ + +#define SERDES_LANE_ICTL_MULTI_RXEQ_L_HIGH_VAL (1 << 0) + +/**** ICTL_MULTI_RXEYEDIAG register ****/ + +#define SERDES_LANE_ICTL_MULTI_RXEYEDIAG_START_L_A (1 << 0) + +/**** ICTL_MULTI_TXDEEMPH register ****/ + +#define SERDES_LANE_ICTL_MULTI_TXDEEMPH_L_MASK 0x0003FFFF +#define SERDES_LANE_ICTL_MULTI_TXDEEMPH_L_SHIFT 0 + +#define SERDES_LANE_ICTL_MULTI_TXDEEMPH_C_ZERO_MASK 0x7c0 +#define SERDES_LANE_ICTL_MULTI_TXDEEMPH_C_ZERO_SHIFT 6 +#define SERDES_LANE_ICTL_MULTI_TXDEEMPH_C_PLUS_MASK 0xf000 +#define SERDES_LANE_ICTL_MULTI_TXDEEMPH_C_PLUS_SHIFT 12 +#define SERDES_LANE_ICTL_MULTI_TXDEEMPH_C_MINUS_MASK 0x7 +#define SERDES_LANE_ICTL_MULTI_TXDEEMPH_C_MINUS_SHIFT 0 + +/**** ICTL_MULTI_TXMARGIN register ****/ + +#define SERDES_LANE_ICTL_MULTI_TXMARGIN_L_MASK 0x00000007 +#define SERDES_LANE_ICTL_MULTI_TXMARGIN_L_SHIFT 0 + +/**** ICTL_MULTI_TXSWING register ****/ + +#define SERDES_LANE_ICTL_MULTI_TXSWING_L (1 << 0) + +/**** IDAT_MULTI register ****/ + +#define SERDES_LANE_IDAT_MULTI_TXELECIDLE_L_MASK 0x0000000F +#define SERDES_LANE_IDAT_MULTI_TXELECIDLE_L_SHIFT 0 + +#define SERDES_LANE_IDAT_MULTI_TXELECIDLE_L_SEL (1 << 4) + +/**** IPD_MULTI register ****/ + +#define SERDES_LANE_IPD_MULTI_TX_L_B (1 << 0) + +#define SERDES_LANE_IPD_MULTI_RX_L_B (1 << 1) + +/**** OCTL_MULTI_RXBIST register ****/ + +#define SERDES_LANE_OCTL_MULTI_RXBIST_DONE_L_A (1 << 0) + +#define SERDES_LANE_OCTL_MULTI_RXBIST_RXLOCKED_L_A (1 << 1) + +/**** OCTL_MULTI register ****/ + +#define SERDES_LANE_OCTL_MULTI_RXCDRLOCK2DATA_L_A (1 << 0) + +#define SERDES_LANE_OCTL_MULTI_RXEQ_DONE_L_A (1 << 1) + +#define SERDES_LANE_OCTL_MULTI_RXREADY_L_A (1 << 2) + +#define SERDES_LANE_OCTL_MULTI_RXSTATUS_L_A (1 << 3) + +#define SERDES_LANE_OCTL_MULTI_TXREADY_L_A (1 << 4) + +#define SERDES_LANE_OCTL_MULTI_TXDETECTRXSTAT_L_A (1 << 5) + +#define SERDES_LANE_OCTL_MULTI_TXDETECTRXACK_L_A (1 << 6) + +#define SERDES_LANE_OCTL_MULTI_RXSIGNALDETECT_L_A (1 << 7) + +/**** OCTL_MULTI_RXEYEDIAG register ****/ + +#define SERDES_LANE_OCTL_MULTI_RXEYEDIAG_STAT_L_A_MASK 0x00003FFF +#define SERDES_LANE_OCTL_MULTI_RXEYEDIAG_STAT_L_A_SHIFT 0 + +#define SERDES_LANE_OCTL_MULTI_RXEYEDIAG_DONE_L_A (1 << 16) + +#define SERDES_LANE_OCTL_MULTI_RXEYEDIAG_ERR_L_A (1 << 17) + +/**** ODAT_MULTI_RXBIST register ****/ + +#define SERDES_LANE_ODAT_MULTI_RXBIST_ERRCOUNT_L_A_MASK 0x0000FFFF +#define SERDES_LANE_ODAT_MULTI_RXBIST_ERRCOUNT_L_A_SHIFT 0 + +#define SERDES_LANE_ODAT_MULTI_RXBIST_ERRCOUNT_OVERFLOW_L_A (1 << 16) + +/**** ODAT_MULTI_RXEQ register ****/ + +#define SERDES_LANE_ODAT_MULTI_RXEQ_BEST_EYE_VAL_L_A_MASK 0x00003FFF +#define SERDES_LANE_ODAT_MULTI_RXEQ_BEST_EYE_VAL_L_A_SHIFT 0 + +/**** MULTI_RX_DVALID register ****/ + +#define SERDES_LANE_MULTI_RX_DVALID_MASK_CDR_LOCK (1 << 0) + +#define SERDES_LANE_MULTI_RX_DVALID_MASK_SIGNALDETECT (1 << 1) + +#define SERDES_LANE_MULTI_RX_DVALID_MASK_TX_READY (1 << 2) + +#define SERDES_LANE_MULTI_RX_DVALID_MASK_RX_READY (1 << 3) + +#define SERDES_LANE_MULTI_RX_DVALID_MASK_SYNT_READY (1 << 4) + +#define SERDES_LANE_MULTI_RX_DVALID_MASK_RX_ELECIDLE (1 << 5) + +#define SERDES_LANE_MULTI_RX_DVALID_MUX_SEL_MASK 0x00FF0000 +#define SERDES_LANE_MULTI_RX_DVALID_MUX_SEL_SHIFT 16 + +#define SERDES_LANE_MULTI_RX_DVALID_PS_00_SEL (1 << 24) + +#define SERDES_LANE_MULTI_RX_DVALID_PS_00_VAL (1 << 25) + +#define SERDES_LANE_MULTI_RX_DVALID_PS_01_SEL (1 << 26) + +#define SERDES_LANE_MULTI_RX_DVALID_PS_01_VAL (1 << 27) + +#define SERDES_LANE_MULTI_RX_DVALID_PS_10_SEL (1 << 28) + +#define SERDES_LANE_MULTI_RX_DVALID_PS_10_VAL (1 << 29) + +#define SERDES_LANE_MULTI_RX_DVALID_PS_11_SEL (1 << 30) + +#define SERDES_LANE_MULTI_RX_DVALID_PS_11_VAL (1 << 31) + +/**** reserved register ****/ + +#define SERDES_LANE_RESERVED_OUT_MASK 0x000000FF +#define SERDES_LANE_RESERVED_OUT_SHIFT 0 + +#define SERDES_LANE_RESERVED_IN_MASK 0x00FF0000 +#define SERDES_LANE_RESERVED_IN_SHIFT 16 + +#ifdef __cplusplus +} +#endif + +#endif /* __AL_HAL_serdes_REGS_H__ */ + +/** @} end of ... group */ + + diff --git a/al_hal_serdes_interface.h b/al_hal_serdes_interface.h new file mode 100644 index 00000000000..c41e6c30b69 --- /dev/null +++ b/al_hal_serdes_interface.h @@ -0,0 +1,875 @@ +/******************************************************************************* +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. + +*******************************************************************************/ + +/** + * @defgroup group_serdes_api API + * SerDes HAL driver API + * @ingroup group_serdes SerDes + * @{ + * + * @file al_hal_serdes_interface.h + * + * @brief Header file for the SerDes HAL driver + * + */ + +#ifndef __AL_HAL_SERDES_INTERFACE_H__ +#define __AL_HAL_SERDES_INTERFACE_H__ + +#include "al_hal_common.h" + +/* *INDENT-OFF* */ +#ifdef __cplusplus +extern "C" { +#endif +/* *INDENT-ON* */ + +enum al_serdes_type { + AL_SRDS_TYPE_HSSP, + AL_SRDS_TYPE_25G, +}; + +enum al_serdes_reg_page { + /* Relevant to Serdes hssp and 25g */ + AL_SRDS_REG_PAGE_0_LANE_0 = 0, + AL_SRDS_REG_PAGE_1_LANE_1, + /* Relevant to Serdes hssp only */ + AL_SRDS_REG_PAGE_2_LANE_2, + AL_SRDS_REG_PAGE_3_LANE_3, + /* Relevant to Serdes hssp and 25g */ + AL_SRDS_REG_PAGE_4_COMMON, + /* Relevant to Serdes hssp only */ + AL_SRDS_REG_PAGE_0123_LANES_0123 = 7, + /* Relevant to Serdes 25g only */ + AL_SRDS_REG_PAGE_TOP, +}; + +/* Relevant to Serdes hssp only */ +enum al_serdes_reg_type { + AL_SRDS_REG_TYPE_PMA = 0, + AL_SRDS_REG_TYPE_PCS, +}; + +enum al_serdes_lane { + AL_SRDS_LANE_0 = AL_SRDS_REG_PAGE_0_LANE_0, + AL_SRDS_LANE_1 = AL_SRDS_REG_PAGE_1_LANE_1, + AL_SRDS_LANE_2 = AL_SRDS_REG_PAGE_2_LANE_2, + AL_SRDS_LANE_3 = AL_SRDS_REG_PAGE_3_LANE_3, + + AL_SRDS_NUM_LANES, + AL_SRDS_LANES_0123 = AL_SRDS_REG_PAGE_0123_LANES_0123, +}; + +/** Serdes loopback mode */ +enum al_serdes_lb_mode { + /** No loopback */ + AL_SRDS_LB_MODE_OFF, + + /** + * Transmits the untimed, partial equalized RX signal out the transmit + * IO pins. + * No clock used (untimed) + */ + AL_SRDS_LB_MODE_PMA_IO_UN_TIMED_RX_TO_TX, + + /** + * Loops back the TX serializer output into the CDR. + * CDR recovered bit clock used (without attenuation) + */ + AL_SRDS_LB_MODE_PMA_INTERNALLY_BUFFERED_SERIAL_TX_TO_RX, + + /** + * Loops back the TX driver IO signal to the RX IO pins + * CDR recovered bit clock used (only through IO) + */ + AL_SRDS_LB_MODE_PMA_SERIAL_TX_IO_TO_RX_IO, + + /** + * Parallel loopback from the PMA receive lane data ports, to the + * transmit lane data ports + * CDR recovered bit clock used + */ + AL_SRDS_LB_MODE_PMA_PARALLEL_RX_TO_TX, + + /** Loops received data after elastic buffer to transmit path */ + AL_SRDS_LB_MODE_PCS_PIPE, + + /** Loops TX data (to PMA) to RX path (instead of PMA data) */ + AL_SRDS_LB_MODE_PCS_NEAR_END, + + /** Loops receive data prior to interface block to transmit path */ + AL_SRDS_LB_MODE_PCS_FAR_END, +}; + +enum al_serdes_clk_freq { + AL_SRDS_CLK_FREQ_NA, + AL_SRDS_CLK_FREQ_100_MHZ, + AL_SRDS_CLK_FREQ_125_MHZ, + AL_SRDS_CLK_FREQ_156_MHZ, +}; + +enum al_serdes_clk_src { + AL_SRDS_CLK_SRC_LOGIC_0, + AL_SRDS_CLK_SRC_REF_PINS, + AL_SRDS_CLK_SRC_R2L, + AL_SRDS_CLK_SRC_R2L_PLL, + AL_SRDS_CLK_SRC_L2R, +}; + +/** Serdes BIST pattern */ +enum al_serdes_bist_pattern { + AL_SRDS_BIST_PATTERN_USER, + AL_SRDS_BIST_PATTERN_PRBS7, + AL_SRDS_BIST_PATTERN_PRBS23, + AL_SRDS_BIST_PATTERN_PRBS31, + AL_SRDS_BIST_PATTERN_CLK1010, +}; + +/** SerDes group rate */ +enum al_serdes_rate { + AL_SRDS_RATE_1_8, + AL_SRDS_RATE_1_4, + AL_SRDS_RATE_1_2, + AL_SRDS_RATE_FULL, +}; + +/** SerDes power mode */ +enum al_serdes_pm { + AL_SRDS_PM_PD, + AL_SRDS_PM_P2, + AL_SRDS_PM_P1, + AL_SRDS_PM_P0S, + AL_SRDS_PM_P0, +}; + +/** + * Tx de-emphasis parameters + */ +enum al_serdes_tx_deemph_param { + AL_SERDES_TX_DEEMP_C_ZERO, /*< c(0) */ + AL_SERDES_TX_DEEMP_C_PLUS, /*< c(1) */ + AL_SERDES_TX_DEEMP_C_MINUS, /*< c(-1) */ +}; + +struct al_serdes_adv_tx_params { + /* + * select the input values location. + * When set to true the values will be taken from the internal registers + * that will be override with the next following parameters. + * When set to false the values will be taken from external pins (the + * other parameters in this case is not needed) + */ + al_bool override; + /* + * Transmit Amplitude control signal. Used to define the full-scale + * maximum swing of the driver. + * 000 - Not Supported + * 001 - 952mVdiff-pkpk + * 010 - 1024mVdiff-pkpk + * 011 - 1094mVdiff-pkpk + * 100 - 1163mVdiff-pkpk + * 101 - 1227mVdiff-pkpk + * 110 - 1283mVdiff-pkpk + * 111 - 1331mVdiff-pkpk + */ + uint8_t amp; + /* Defines the total number of driver units allocated in the driver */ + uint8_t total_driver_units; + /* Defines the total number of driver units allocated to the + * first post-cursor (C+1) tap. */ + uint8_t c_plus_1; + /* Defines the total number of driver units allocated to the + * second post-cursor (C+2) tap. */ + uint8_t c_plus_2; + /* Defines the total number of driver units allocated to the + * first pre-cursor (C-1) tap. */ + uint8_t c_minus_1; + /* TX driver Slew Rate control: + * 00 - 31ps + * 01 - 33ps + * 10 - 68ps + * 11 - 170ps + */ + uint8_t slew_rate; +}; + +struct al_serdes_adv_rx_params { + /* + * select the input values location. + * When set to true the values will be taken from the internal registers + * that will be override with the next following parameters. + * When set to false the values will be taken based in the equalization + * results (the other parameters in this case is not needed) + */ + al_bool override; + /* RX agc high frequency dc gain: + * -3'b000: -3dB + * -3'b001: -2.5dB + * -3'b010: -2dB + * -3'b011: -1.5dB + * -3'b100: -1dB + * -3'b101: -0.5dB + * -3'b110: -0dB + * -3'b111: 0.5dB + */ + uint8_t dcgain; + /* DFE post-shaping tap 3dB frequency + * -3'b000: 684MHz + * -3'b001: 576MHz + * -3'b010: 514MHz + * -3'b011: 435MHz + * -3'b100: 354MHz + * -3'b101: 281MHz + * -3'b110: 199MHz + * -3'b111: 125MHz + */ + uint8_t dfe_3db_freq; + /* DFE post-shaping tap gain + * 0: no pulse shaping tap + * 1: -24mVpeak + * 2: -45mVpeak + * 3: -64mVpeak + * 4: -80mVpeak + * 5: -93mVpeak + * 6: -101mVpeak + * 7: -105mVpeak + */ + uint8_t dfe_gain; + /* DFE first tap gain control + * -4'b0000: +1mVpeak + * -4'b0001: +10mVpeak + * .... + * -4'b0110: +55mVpeak + * -4'b0111: +64mVpeak + * -4'b1000: -1mVpeak + * -4'b1001: -10mVpeak + * .... + * -4'b1110: -55mVpeak + * -4'b1111: -64mVpeak + */ + uint8_t dfe_first_tap_ctrl; + /* DFE second tap gain control + * -4'b0000: +0mVpeak + * -4'b0001: +9mVpeak + * .... + * -4'b0110: +46mVpeak + * -4'b0111: +53mVpeak + * -4'b1000: -0mVpeak + * -4'b1001: -9mVpeak + * .... + * -4'b1110: -46mVpeak + * -4'b1111: -53mVpeak + */ + uint8_t dfe_secound_tap_ctrl; + /* DFE third tap gain control + * -4'b0000: +0mVpeak + * -4'b0001: +7mVpeak + * .... + * -4'b0110: +38mVpeak + * -4'b0111: +44mVpeak + * -4'b1000: -0mVpeak + * -4'b1001: -7mVpeak + * .... + * -4'b1110: -38mVpeak + * -4'b1111: -44mVpeak + */ + uint8_t dfe_third_tap_ctrl; + /* DFE fourth tap gain control + * -4'b0000: +0mVpeak + * -4'b0001: +6mVpeak + * .... + * -4'b0110: +29mVpeak + * -4'b0111: +33mVpeak + * -4'b1000: -0mVpeak + * -4'b1001: -6mVpeak + * .... + * -4'b1110: -29mVpeak + * -4'b1111: -33mVpeak + */ + uint8_t dfe_fourth_tap_ctrl; + /* Low frequency agc gain (att) select + * -3'b000: Disconnected + * -3'b001: -18.5dB + * -3'b010: -12.5dB + * -3'b011: -9dB + * -3'b100: -6.5dB + * -3'b101: -4.5dB + * -3'b110: -2.9dB + * -3'b111: -1.6dB + */ + uint8_t low_freq_agc_gain; + /* Provides a RX Equalizer pre-hint, prior to beginning + * adaptive equalization */ + uint8_t precal_code_sel; + /* High frequency agc boost control + * Min d0: Boost ~4dB + * Max d31: Boost ~20dB + */ + uint8_t high_freq_agc_boost; +}; + +struct al_serdes_25g_adv_rx_params { + /* ATT (PLE Flat-Band Gain) */ + uint8_t att; + /* APG (CTLE's Flat-Band Gain) */ + uint8_t apg; + /* LFG (Low-Freq Gain) */ + uint8_t lfg; + /* HFG (High-Freq Gain) */ + uint8_t hfg; + /* MBG (MidBand-Freq-knob Gain) */ + uint8_t mbg; + /* MBF (MidBand-Freq-knob Frequency position Gain) */ + uint8_t mbf; + /* DFE Tap1 even#0 Value */ + int8_t dfe_first_tap_even0_ctrl; + /* DFE Tap1 even#1 Value */ + int8_t dfe_first_tap_even1_ctrl; + /* DFE Tap1 odd#0 Value */ + int8_t dfe_first_tap_odd0_ctrl; + /* DFE Tap1 odd#1 Value */ + int8_t dfe_first_tap_odd1_ctrl; + /* DFE Tap2 Value */ + int8_t dfe_second_tap_ctrl; + /* DFE Tap3 Value */ + int8_t dfe_third_tap_ctrl; + /* DFE Tap4 Value */ + int8_t dfe_fourth_tap_ctrl; + /* DFE Tap5 Value */ + int8_t dfe_fifth_tap_ctrl; +}; + +struct al_serdes_25g_tx_diag_info { + uint8_t regulated_supply; + int8_t dcd_trim; + uint8_t clk_delay; + uint8_t calp_multiplied_by_2; + uint8_t caln_multiplied_by_2; +}; + +struct al_serdes_25g_rx_diag_info { + int8_t los_offset; + int8_t agc_offset; + int8_t leq_gainstage_offset; + int8_t leq_eq1_offset; + int8_t leq_eq2_offset; + int8_t leq_eq3_offset; + int8_t leq_eq4_offset; + int8_t leq_eq5_offset; + int8_t summer_even_offset; + int8_t summer_odd_offset; + int8_t vscan_even_offset; + int8_t vscan_odd_offset; + int8_t data_slicer_even0_offset; + int8_t data_slicer_even1_offset; + int8_t data_slicer_odd0_offset; + int8_t data_slicer_odd1_offset; + int8_t edge_slicer_even_offset; + int8_t edge_slicer_odd_offset; + int8_t eye_slicer_even_offset; + int8_t eye_slicer_odd_offset; + uint8_t cdr_clk_i; + uint8_t cdr_clk_q; + uint8_t cdr_dll; + uint8_t cdr_vco_dosc; + uint8_t cdr_vco_fr; + uint16_t cdr_dlpf; + uint8_t ple_resistance; + uint8_t rx_term_mode; + uint8_t rx_coupling; + uint8_t rx_term_cal_code; + uint8_t rx_sheet_res_cal_code; +}; + +/** + * SRIS parameters + */ +struct al_serdes_sris_params { + /* Controls the frequency accuracy threshold (ppm) for lock detection CDR */ + uint16_t ppm_drift_count; + /* Controls the frequency accuracy threshold (ppm) for lock detection in the CDR */ + uint16_t ppm_drift_max; + /* Controls the frequency accuracy threshold (ppm) for lock detection in PLL */ + uint16_t synth_ppm_drift_max; + /* Elastic buffer full threshold for PCIE modes: GEN1/GEN2 */ + uint8_t full_d2r1; + /* Elastic buffer full threshold for PCIE modes: GEN3 */ + uint8_t full_pcie_g3; + /* Elastic buffer midpoint threshold. + * Sets the depth of the buffer while in PCIE mode, GEN1/GEN2 + */ + uint8_t rd_threshold_d2r1; + /* Elastic buffer midpoint threshold. + * Sets the depth of the buffer while in PCIE mode, GEN3 + */ + uint8_t rd_threshold_pcie_g3; +}; + +/** SerDes PCIe Rate - values are important for proper behavior */ +enum al_serdes_pcie_rate { + AL_SRDS_PCIE_RATE_GEN1 = 0, + AL_SRDS_PCIE_RATE_GEN2, + AL_SRDS_PCIE_RATE_GEN3, +}; + +struct al_serdes_grp_obj { + void __iomem *regs_base; + + /** + * get the type of the serdes. + * Must be implemented for all SerDes unit. + * + * @return the serdes type. + */ + enum al_serdes_type (*type_get)(void); + + /** + * Reads a SERDES internal register + * + * @param obj The object context + * @param page The SERDES register page within the group + * @param type The SERDES register type (PMA /PCS) + * @param offset The SERDES register offset (0 - 4095) + * @param data The read data + * + * @return 0 if no error found. + */ + int (*reg_read)(struct al_serdes_grp_obj *, enum al_serdes_reg_page, + enum al_serdes_reg_type, uint16_t, uint8_t *); + + /** + * Writes a SERDES internal register + * + * @param obj The object context + * @param page The SERDES register page within the group + * @param type The SERDES register type (PMA /PCS) + * @param offset The SERDES register offset (0 - 4095) + * @param data The data to write + * + * @return 0 if no error found. + */ + int (*reg_write)(struct al_serdes_grp_obj *, enum al_serdes_reg_page, + enum al_serdes_reg_type, uint16_t, uint8_t); + + /** + * Enable BIST required overrides + * + * @param obj The object context + * @param grp The SERDES group + * @param rate The required speed rate + */ + void (*bist_overrides_enable)(struct al_serdes_grp_obj *, enum al_serdes_rate); + /** + * Disable BIST required overrides + * + * @param obj The object context + * @param grp The SERDES group + * @param rate The required speed rate + */ + void (*bist_overrides_disable)(struct al_serdes_grp_obj *); + /** + * Rx rate change + * + * @param obj The object context + * @param grp The SERDES group + * @param rate The Rx required rate + */ + void (*rx_rate_change)(struct al_serdes_grp_obj *, enum al_serdes_rate); + /** + * SERDES lane Rx rate change software flow enable + * + * @param obj The object context + * @param lane The SERDES lane within the group + */ + void (*rx_rate_change_sw_flow_en)(struct al_serdes_grp_obj *, enum al_serdes_lane); + /** + * SERDES lane Rx rate change software flow disable + * + * @param obj The object context + * @param lane The SERDES lane within the group + */ + void (*rx_rate_change_sw_flow_dis)(struct al_serdes_grp_obj *, enum al_serdes_lane); + /** + * PCIe lane rate override check + * + * @param obj The object context + * @param grp The SERDES group + * @param lane The SERDES lane within the group + * + * @returns AL_TRUE if the override is enabled + */ + al_bool (*pcie_rate_override_is_enabled)(struct al_serdes_grp_obj *, enum al_serdes_lane); + /** + * PCIe lane rate override control + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param en Enable/disable + */ + void (*pcie_rate_override_enable_set)(struct al_serdes_grp_obj *, enum al_serdes_lane, + al_bool en); + /** + * PCIe lane rate get + * + * @param obj The object context + * @param lane The SERDES lane within the group + */ + enum al_serdes_pcie_rate (*pcie_rate_get)(struct al_serdes_grp_obj *, enum al_serdes_lane); + /** + * PCIe lane rate set + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param rate The required rate + */ + void (*pcie_rate_set)(struct al_serdes_grp_obj *, enum al_serdes_lane, + enum al_serdes_pcie_rate rate); + /** + * SERDES group power mode control + * + * @param obj The object context + * @param grp The SERDES group + * @param pm The required power mode + */ + void (*group_pm_set)(struct al_serdes_grp_obj *, enum al_serdes_pm); + /** + * SERDES lane power mode control + * + * @param obj The object context + * @param grp The SERDES group + * @param lane The SERDES lane within the group + * @param rx_pm The required RX power mode + * @param tx_pm The required TX power mode + */ + void (*lane_pm_set)(struct al_serdes_grp_obj *, enum al_serdes_lane, + enum al_serdes_pm, enum al_serdes_pm); + + /** + * SERDES group PMA hard reset + * Controls Serdes group PMA hard reset + * + * @param obj The object context + * @param grp The SERDES group + * @param enable Enable/disable hard reset + */ + void (*pma_hard_reset_group)(struct al_serdes_grp_obj *, al_bool); + /** + * SERDES lane PMA hard reset + * Controls Serdes lane PMA hard reset + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param enable Enable/disable hard reset + */ + void (*pma_hard_reset_lane)(struct al_serdes_grp_obj *, enum al_serdes_lane, al_bool); + /** + * Configure SERDES loopback + * Controls the loopback + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param mode The requested loopback mode + */ + void (*loopback_control)(struct al_serdes_grp_obj *, enum al_serdes_lane, + enum al_serdes_lb_mode); + /** + * SERDES BIST pattern selection + * Selects the BIST pattern to be used + * + * @param obj The object context + * @param pattern The pattern to set + * @param user_data The pattern user data (when pattern == AL_SRDS_BIST_PATTERN_USER) + * 80 bits (8 bytes array) + */ + void (*bist_pattern_select)(struct al_serdes_grp_obj *, + enum al_serdes_bist_pattern, uint8_t *); + /** + * SERDES BIST TX Enable + * Enables/disables TX BIST per lane + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param enable Enable or disable TX BIST + */ + void (*bist_tx_enable)(struct al_serdes_grp_obj *, enum al_serdes_lane, al_bool); + /** + * SERDES BIST TX single bit error injection + * Injects single bit error during a TX BIST + * + * @param obj The object context + */ + void (*bist_tx_err_inject)(struct al_serdes_grp_obj *); + /** + * SERDES BIST RX Enable + * Enables/disables RX BIST per lane + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param enable Enable or disable TX BIST + */ + void (*bist_rx_enable)(struct al_serdes_grp_obj *, enum al_serdes_lane, al_bool); + /** + * SERDES BIST RX status + * Checks the RX BIST status for a specific SERDES lane + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param is_locked An indication whether RX BIST is locked + * @param err_cnt_overflow An indication whether error count overflow occured + * @param err_cnt Current bit error count + */ + void (*bist_rx_status)(struct al_serdes_grp_obj *, enum al_serdes_lane, al_bool *, + al_bool *, uint32_t *); + + /** + * Set the tx de-emphasis to preset values + * + * @param obj The object context + * @param lane The SERDES lane within the group + * + */ + void (*tx_deemph_preset)(struct al_serdes_grp_obj *, enum al_serdes_lane); + /** + * Increase tx de-emphasis param. + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param param which tx de-emphasis to change + * + * @return false in case max is reached. true otherwise. + */ + al_bool (*tx_deemph_inc)(struct al_serdes_grp_obj *, enum al_serdes_lane, + enum al_serdes_tx_deemph_param); + /** + * Decrease tx de-emphasis param. + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param param which tx de-emphasis to change + * + * @return false in case min is reached. true otherwise. + */ + al_bool (*tx_deemph_dec)(struct al_serdes_grp_obj *, enum al_serdes_lane, + enum al_serdes_tx_deemph_param); + /** + * run Rx eye measurement. + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param timeout timeout in uSec + * @param value Rx eye measurement value + * (0 - completely closed eye, 0xffff - completely open eye). + * + * @return 0 if no error found. + */ + int (*eye_measure_run)(struct al_serdes_grp_obj *, enum al_serdes_lane, + uint32_t, unsigned int *); + /** + * Eye diagram single sampling + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param x Sampling X position (0 - 63 --> -1.00 UI ... 1.00 UI) + * @param y Sampling Y position (0 - 62 --> 500mV ... -500mV) + * @param timeout timeout in uSec + * @param value Eye diagram sample value (BER - 0x0000 - 0xffff) + * + * @return 0 if no error found. + */ + int (*eye_diag_sample)(struct al_serdes_grp_obj *, enum al_serdes_lane, + unsigned int, int, unsigned int, unsigned int *); + + /** + * Eye diagram full run + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param x_start Sampling from X position + * @param x_stop Sampling to X position + * @param x_step jump in x_step + * @param y_start Sampling from Y position + * @param y_stop Sampling to Y position + * @param y_step jump in y_step + * @param num_bits_per_sample How many bits to check + * @param buf array of results + * @param buf_size array size - must be equal to + * (((y_stop - y_start) / y_step) + 1) * + * (((x_stop - x_start) / x_step) + 1) + * + * @return 0 if no error found. + */ + int (*eye_diag_run)(struct al_serdes_grp_obj *, enum al_serdes_lane, + int, int, unsigned int, int, int, unsigned int, uint64_t, uint64_t *, + uint32_t); + /** + * Check if signal is detected + * + * @param obj The object context + * @param lane The SERDES lane within the group + * + * @return true if signal is detected. false otherwise. + */ + al_bool (*signal_is_detected)(struct al_serdes_grp_obj *, enum al_serdes_lane); + + /** + * Check if CDR is locked + * + * @param obj The object context + * @param lane The SERDES lane within the group + * + * @return true if cdr is locked. false otherwise. + */ + al_bool (*cdr_is_locked)(struct al_serdes_grp_obj *, enum al_serdes_lane); + + /** + * Check if rx is valid for this lane + * + * @param obj The object context + * @param lane The SERDES lane within the group + * + * @return true if rx is valid. false otherwise. + */ + al_bool (*rx_valid)(struct al_serdes_grp_obj *, enum al_serdes_lane); + + /** + * configure tx advanced parameters + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param params pointer to the tx parameters + */ + void (*tx_advanced_params_set)(struct al_serdes_grp_obj *, enum al_serdes_lane, void *); + /** + * read tx advanced parameters + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param params pointer to the tx parameters + */ + void (*tx_advanced_params_get)(struct al_serdes_grp_obj *, enum al_serdes_lane, void *); + /** + * configure rx advanced parameters + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param params pointer to the rx parameters + */ + void (*rx_advanced_params_set)(struct al_serdes_grp_obj *, enum al_serdes_lane, void *); + /** + * read rx advanced parameters + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param params pointer to the rx parameters + */ + void (*rx_advanced_params_get)(struct al_serdes_grp_obj *, enum al_serdes_lane, void *); + /** + * Switch entire SerDes group to SGMII mode based on 156.25 Mhz reference clock + * + * @param obj The object context + * + */ + void (*mode_set_sgmii)(struct al_serdes_grp_obj *); + /** + * Switch entire SerDes group to KR mode based on 156.25 Mhz reference clock + * + * @param obj The object context + * + */ + void (*mode_set_kr)(struct al_serdes_grp_obj *); + /** + * performs SerDes HW equalization test and update equalization parameters + * + * @param obj the object context + * @param lane The SERDES lane within the group + */ + int (*rx_equalization)(struct al_serdes_grp_obj *, enum al_serdes_lane); + /** + * performs Rx equalization and compute the width and height of the eye + * + * @param obj the object context + * @param lane The SERDES lane within the group + * @param width the output width of the eye + * @param height the output height of the eye + */ + int (*calc_eye_size)(struct al_serdes_grp_obj *, enum al_serdes_lane, int *, int *); + /** + * SRIS: Separate Refclk Independent SSC (Spread Spectrum Clocking) + * Currently available only for PCIe interfaces. + * When working with local Refclk, same SRIS configuration in both serdes sides + * (EP and RC in PCIe interface) is required. + * + * performs SRIS configuration according to params + * + * @param obj the object context + * @param params the SRIS parameters + */ + void (*sris_config)(struct al_serdes_grp_obj *, void *); + /** + * set SERDES dcgain parameter + * + * @param obj the object context + * @param dcgain dcgain value to set + */ + void (*dcgain_set)(struct al_serdes_grp_obj *, uint8_t); + /** + * read tx diagnostics info + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param params pointer to the tx diagnostics info structure + */ + void (*tx_diag_info_get)(struct al_serdes_grp_obj *, enum al_serdes_lane, void*); + /** + * read rx diagnostics info + * + * @param obj The object context + * @param lane The SERDES lane within the group + * @param params pointer to the rx diagnostics info structure + */ + void (*rx_diag_info_get)(struct al_serdes_grp_obj *, enum al_serdes_lane, void*); +}; + + +/* *INDENT-OFF* */ +#ifdef __cplusplus +} +#endif + +/* *INDENT-ON* */ +#endif /* __AL_HAL_SERDES_INTERFACE_H__ */ + +/** @} end of SERDES group */ + diff --git a/al_hal_udma.h b/al_hal_udma.h index a1bdb4fe8db..6d94379869b 100644 --- a/al_hal_udma.h +++ b/al_hal_udma.h @@ -70,7 +70,6 @@ extern "C" { /* Default Max number of descriptors supported per action */ #define AL_UDMA_DEFAULT_MAX_ACTN_DESCS 16 -#define AL_UDMA_REV_ID_0 0 #define AL_UDMA_REV_ID_1 1 #define AL_UDMA_REV_ID_2 2 @@ -130,8 +129,8 @@ union al_udma_desc { #define AL_S2M_DESC_LEN2_MASK (0x3fff << AL_S2M_DESC_LEN2_SHIFT) #define AL_S2M_DESC_LEN2_GRANULARITY_SHIFT 6 -/* TX/RX descriptor VMID field (in the buffer address 64 bit field) */ -#define AL_UDMA_DESC_VMID_SHIFT 48 +/* TX/RX descriptor Target-ID field (in the buffer address 64 bit field) */ +#define AL_UDMA_DESC_TGTID_SHIFT 48 /** UDMA completion descriptor */ union al_udma_cdesc { @@ -168,11 +167,11 @@ struct al_block { uint32_t num; /**< Number of buffers of the block */ /**< - * VMID to be assigned to the block descriptors - * Requires VMID in descriptor to be enabled for the specific UDMA + * Target-ID to be assigned to the block descriptors + * Requires Target-ID in descriptor to be enabled for the specific UDMA * queue. */ - uint16_t vmid; + uint16_t tgtid; }; /** UDMA type */ diff --git a/al_hal_udma_config.c b/al_hal_udma_config.c index a06f7898308..5ef01f356e0 100644 --- a/al_hal_udma_config.c +++ b/al_hal_udma_config.c @@ -565,7 +565,7 @@ int al_udma_s2m_pref_set(struct al_udma *udma, reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_MASK; reg |=(conf->min_burst_above_thr << UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_SHIFT) & - UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_MASK; + UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_MASK; al_reg_write32(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_3, reg); @@ -1114,260 +1114,105 @@ int al_udma_s2m_q_comp_set(struct al_udma_q *udma_q, return 0; } -/* UDMA VMID control configuration */ -void al_udma_gen_vmid_conf_set( +/* UDMA Target-ID control configuration per queue */ +void al_udma_gen_tgtid_conf_queue_set( struct unit_regs *unit_regs, - struct al_udma_gen_vmid_conf *conf) + struct al_udma_gen_tgtid_conf *conf, + uint32_t qid) { + uint32_t *tx_tgtid_reg, *rx_tgtid_reg, *tx_tgtaddr_reg, *rx_tgtaddr_reg; unsigned int rev_id; - al_reg_write32_masked( - &unit_regs->gen.vmid.cfg_vmid_0, - UDMA_GEN_VMID_CFG_VMID_0_TX_Q_VMID_DESC_EN_MASK | - UDMA_GEN_VMID_CFG_VMID_0_TX_Q_VMID_QUEUE_EN_MASK | - UDMA_GEN_VMID_CFG_VMID_0_RX_Q_VMID_DESC_EN_MASK | - UDMA_GEN_VMID_CFG_VMID_0_RX_Q_VMID_QUEUE_EN_MASK, - (((conf->tx_q_conf[0].desc_en << 0) | - (conf->tx_q_conf[1].desc_en << 1) | - (conf->tx_q_conf[2].desc_en << 2) | - (conf->tx_q_conf[3].desc_en << 3)) << - UDMA_GEN_VMID_CFG_VMID_0_TX_Q_VMID_DESC_EN_SHIFT) | - (((conf->tx_q_conf[0].queue_en << 0) | - (conf->tx_q_conf[1].queue_en << 1) | - (conf->tx_q_conf[2].queue_en << 2) | - (conf->tx_q_conf[3].queue_en << 3)) << - UDMA_GEN_VMID_CFG_VMID_0_TX_Q_VMID_QUEUE_EN_SHIFT) | - (((conf->rx_q_conf[0].desc_en << 0) | - (conf->rx_q_conf[1].desc_en << 1) | - (conf->rx_q_conf[2].desc_en << 2) | - (conf->rx_q_conf[3].desc_en << 3)) << - UDMA_GEN_VMID_CFG_VMID_0_RX_Q_VMID_DESC_EN_SHIFT) | - (((conf->rx_q_conf[0].queue_en << 0) | - (conf->rx_q_conf[1].queue_en << 1) | - (conf->rx_q_conf[2].queue_en << 2) | - (conf->rx_q_conf[3].queue_en << 3)) << - UDMA_GEN_VMID_CFG_VMID_0_RX_Q_VMID_QUEUE_EN_SHIFT)); - - /* VMID per queue */ - al_reg_write32( - &unit_regs->gen.vmid.cfg_vmid_1, - (conf->tx_q_conf[0].vmid << - UDMA_GEN_VMID_CFG_VMID_1_TX_Q_0_VMID_SHIFT) | - (conf->tx_q_conf[1].vmid << - UDMA_GEN_VMID_CFG_VMID_1_TX_Q_1_VMID_SHIFT)); - - al_reg_write32( - &unit_regs->gen.vmid.cfg_vmid_2, - (conf->tx_q_conf[2].vmid << - UDMA_GEN_VMID_CFG_VMID_2_TX_Q_2_VMID_SHIFT) | - (conf->tx_q_conf[3].vmid << - UDMA_GEN_VMID_CFG_VMID_2_TX_Q_3_VMID_SHIFT)); - - al_reg_write32( - &unit_regs->gen.vmid.cfg_vmid_3, - (conf->rx_q_conf[0].vmid << - UDMA_GEN_VMID_CFG_VMID_3_RX_Q_0_VMID_SHIFT) | - (conf->rx_q_conf[1].vmid << - UDMA_GEN_VMID_CFG_VMID_3_RX_Q_1_VMID_SHIFT)); - - al_reg_write32( - &unit_regs->gen.vmid.cfg_vmid_4, - (conf->rx_q_conf[2].vmid << - UDMA_GEN_VMID_CFG_VMID_4_RX_Q_2_VMID_SHIFT) | - (conf->rx_q_conf[3].vmid << - UDMA_GEN_VMID_CFG_VMID_4_RX_Q_3_VMID_SHIFT)); - - /* VMADDR per queue */ + al_assert(qid < DMA_MAX_Q); rev_id = al_udma_get_revision(unit_regs); + + /* Target-ID TX DESC EN */ + al_reg_write32_masked(&unit_regs->gen.tgtid.cfg_tgtid_0, + (conf->tx_q_conf[qid].desc_en << qid) << + UDMA_GEN_TGTID_CFG_TGTID_0_TX_Q_TGTID_DESC_EN_SHIFT, + (conf->tx_q_conf[qid].desc_en << qid) << + UDMA_GEN_TGTID_CFG_TGTID_0_TX_Q_TGTID_DESC_EN_SHIFT); + + /* Target-ID TX QUEUE EN */ + al_reg_write32_masked(&unit_regs->gen.tgtid.cfg_tgtid_0, + (conf->tx_q_conf[qid].queue_en << qid) << + UDMA_GEN_TGTID_CFG_TGTID_0_TX_Q_TGTID_QUEUE_EN_SHIFT, + (conf->tx_q_conf[qid].queue_en << qid) << + UDMA_GEN_TGTID_CFG_TGTID_0_TX_Q_TGTID_QUEUE_EN_SHIFT); + + /* Target-ID RX DESC EN */ + al_reg_write32_masked(&unit_regs->gen.tgtid.cfg_tgtid_0, + (conf->rx_q_conf[qid].desc_en << qid) << + UDMA_GEN_TGTID_CFG_TGTID_0_RX_Q_TGTID_DESC_EN_SHIFT, + (conf->rx_q_conf[qid].desc_en << qid) << + UDMA_GEN_TGTID_CFG_TGTID_0_RX_Q_TGTID_DESC_EN_SHIFT); + + /* Target-ID RX QUEUE EN */ + al_reg_write32_masked(&unit_regs->gen.tgtid.cfg_tgtid_0, + (conf->rx_q_conf[qid].queue_en << qid) << + UDMA_GEN_TGTID_CFG_TGTID_0_RX_Q_TGTID_QUEUE_EN_SHIFT, + (conf->rx_q_conf[qid].queue_en << qid) << + UDMA_GEN_TGTID_CFG_TGTID_0_RX_Q_TGTID_QUEUE_EN_SHIFT); + + switch (qid) { + case 0: + case 1: + tx_tgtid_reg = &unit_regs->gen.tgtid.cfg_tgtid_1; + rx_tgtid_reg = &unit_regs->gen.tgtid.cfg_tgtid_3; + tx_tgtaddr_reg = &unit_regs->gen.tgtaddr.cfg_tgtaddr_0; + rx_tgtaddr_reg = &unit_regs->gen.tgtaddr.cfg_tgtaddr_2; + break; + case 2: + case 3: + tx_tgtid_reg = &unit_regs->gen.tgtid.cfg_tgtid_2; + rx_tgtid_reg = &unit_regs->gen.tgtid.cfg_tgtid_4; + tx_tgtaddr_reg = &unit_regs->gen.tgtaddr.cfg_tgtaddr_1; + rx_tgtaddr_reg = &unit_regs->gen.tgtaddr.cfg_tgtaddr_3; + break; + default: + al_assert(AL_FALSE); + return; + } + + al_reg_write32_masked(tx_tgtid_reg, + UDMA_GEN_TGTID_CFG_TGTID_MASK(qid), + conf->tx_q_conf[qid].tgtid << UDMA_GEN_TGTID_CFG_TGTID_SHIFT(qid)); + + al_reg_write32_masked(rx_tgtid_reg, + UDMA_GEN_TGTID_CFG_TGTID_MASK(qid), + conf->rx_q_conf[qid].tgtid << UDMA_GEN_TGTID_CFG_TGTID_SHIFT(qid)); + if (rev_id >= AL_UDMA_REV_ID_REV2) { - al_reg_write32( - &unit_regs->gen.vmaddr.cfg_vmaddr_0, - (conf->tx_q_conf[0].vmaddr << - UDMA_GEN_VMADDR_CFG_VMADDR_0_TX_Q_0_VMADDR_SHIFT) | - (conf->tx_q_conf[1].vmaddr << - UDMA_GEN_VMADDR_CFG_VMADDR_0_TX_Q_1_VMADDR_SHIFT)); + al_reg_write32_masked(tx_tgtaddr_reg, + UDMA_GEN_TGTADDR_CFG_MASK(qid), + conf->tx_q_conf[qid].tgtaddr << UDMA_GEN_TGTADDR_CFG_SHIFT(qid)); - al_reg_write32( - &unit_regs->gen.vmaddr.cfg_vmaddr_1, - (conf->tx_q_conf[2].vmaddr << - UDMA_GEN_VMADDR_CFG_VMADDR_1_TX_Q_2_VMADDR_SHIFT) | - (conf->tx_q_conf[3].vmaddr << - UDMA_GEN_VMADDR_CFG_VMADDR_1_TX_Q_3_VMADDR_SHIFT)); - - al_reg_write32( - &unit_regs->gen.vmaddr.cfg_vmaddr_2, - (conf->rx_q_conf[0].vmaddr << - UDMA_GEN_VMADDR_CFG_VMADDR_2_RX_Q_0_VMADDR_SHIFT) | - (conf->rx_q_conf[1].vmaddr << - UDMA_GEN_VMADDR_CFG_VMADDR_2_RX_Q_1_VMADDR_SHIFT)); - - al_reg_write32( - &unit_regs->gen.vmaddr.cfg_vmaddr_3, - (conf->rx_q_conf[2].vmaddr << - UDMA_GEN_VMADDR_CFG_VMADDR_3_RX_Q_2_VMADDR_SHIFT) | - (conf->rx_q_conf[3].vmaddr << - UDMA_GEN_VMADDR_CFG_VMADDR_3_RX_Q_3_VMADDR_SHIFT)); + al_reg_write32_masked(rx_tgtaddr_reg, + UDMA_GEN_TGTADDR_CFG_MASK(qid), + conf->rx_q_conf[qid].tgtaddr << UDMA_GEN_TGTADDR_CFG_SHIFT(qid)); } } -/* UDMA VMID MSIX control configuration */ -void al_udma_gen_vmid_msix_conf_set( +/* UDMA Target-ID control configuration */ +void al_udma_gen_tgtid_conf_set( + struct unit_regs *unit_regs, + struct al_udma_gen_tgtid_conf *conf) +{ + int i; + + for (i = 0; i < DMA_MAX_Q; i++) + al_udma_gen_tgtid_conf_queue_set(unit_regs, conf, i); +} + +/* UDMA Target-ID MSIX control configuration */ +void al_udma_gen_tgtid_msix_conf_set( struct unit_regs *unit_regs, - struct al_udma_gen_vmid_msix_conf *conf) + struct al_udma_gen_tgtid_msix_conf *conf) { al_reg_write32_masked( - &unit_regs->gen.vmid.cfg_vmid_0, - UDMA_GEN_VMID_CFG_VMID_0_MSIX_VMID_ACCESS_EN | - UDMA_GEN_VMID_CFG_VMID_0_MSIX_VMID_SEL, - (conf->access_en ? UDMA_GEN_VMID_CFG_VMID_0_MSIX_VMID_ACCESS_EN : 0) | - (conf->sel ? UDMA_GEN_VMID_CFG_VMID_0_MSIX_VMID_SEL : 0)); + &unit_regs->gen.tgtid.cfg_tgtid_0, + UDMA_GEN_TGTID_CFG_TGTID_0_MSIX_TGTID_ACCESS_EN | + UDMA_GEN_TGTID_CFG_TGTID_0_MSIX_TGTID_SEL, + (conf->access_en ? UDMA_GEN_TGTID_CFG_TGTID_0_MSIX_TGTID_ACCESS_EN : 0) | + (conf->sel ? UDMA_GEN_TGTID_CFG_TGTID_0_MSIX_TGTID_SEL : 0)); } - -/* UDMA VMID control advanced Tx queue configuration */ -void al_udma_gen_vmid_advanced_tx_q_conf( - struct al_udma_q *q, - struct al_udma_gen_vmid_advanced_tx_q_conf *conf) -{ - struct udma_gen_regs *gen_regs = q->udma->gen_regs; - struct udma_gen_vmpr *vmpr = &gen_regs->vmpr[q->qid]; - - al_reg_write32_masked( - &vmpr->cfg_vmpr_0, - UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_HISEL_MASK | - UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_DATA_VMID_EN | - UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_PREF_VMID_EN | - UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_CMPL_VMID_EN, - conf->tx_q_addr_hi_sel | - ((conf->tx_q_data_vmid_en == AL_TRUE) ? - UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_DATA_VMID_EN : 0) | - ((conf->tx_q_prefetch_vmid_en == AL_TRUE) ? - UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_PREF_VMID_EN : 0) | - ((conf->tx_q_compl_vmid_en == AL_TRUE) ? - UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_CMPL_VMID_EN : 0)); - - al_reg_write32( - &vmpr->cfg_vmpr_1, - conf->tx_q_addr_hi); - - al_reg_write32_masked( - &vmpr->cfg_vmpr_2, - UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_PREF_VMID_MASK | - UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_CMPL_VMID_MASK, - (conf->tx_q_prefetch_vmid << - UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_PREF_VMID_SHIFT) | - (conf->tx_q_compl_vmid << - UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_CMPL_VMID_SHIFT)); - - al_reg_write32_masked( - &vmpr->cfg_vmpr_3, - UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_VMID_MASK | - UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_VMID_SEL_MASK, - (conf->tx_q_data_vmid << - UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_VMID_SHIFT) | - (conf->tx_q_data_vmid_mask << - UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_VMID_SEL_SHIFT)); -} - -/** UDMA VMID control advanced Rx queue configuration */ -void al_udma_gen_vmid_advanced_rx_q_conf( - struct al_udma_q *q, - struct al_udma_gen_vmid_advanced_rx_q_conf *conf) -{ - struct udma_gen_regs *gen_regs = q->udma->gen_regs; - struct udma_gen_vmpr *vmpr = &gen_regs->vmpr[q->qid]; - - al_reg_write32_masked( - &vmpr->cfg_vmpr_4, - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF1_HISEL_MASK | - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF1_VMID_EN | - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_HISEL_MASK | - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_VMID_EN | - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_DDP_HISEL_MASK | - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_DDP_VMID_EN | - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_PREF_VMID_EN | - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_CMPL_VMID_EN, - (conf->rx_q_addr_hi_sel << - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF1_HISEL_SHIFT) | - ((conf->rx_q_data_vmid_en == AL_TRUE) ? - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF1_VMID_EN : 0) | - (conf->rx_q_data_buff2_addr_hi_sel << - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_HISEL_SHIFT) | - ((conf->rx_q_data_buff2_vmid_en == AL_TRUE) ? - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_VMID_EN : 0) | - (conf->rx_q_ddp_addr_hi_sel << - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_DDP_HISEL_SHIFT) | - ((conf->rx_q_ddp_vmid_en == AL_TRUE) ? - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_DDP_VMID_EN : 0) | - ((conf->rx_q_prefetch_vmid_en == AL_TRUE) ? - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_PREF_VMID_EN : 0) | - ((conf->rx_q_compl_vmid_en == AL_TRUE) ? - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_CMPL_VMID_EN : 0)); - - al_reg_write32_masked( - &vmpr->cfg_vmpr_6, - UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_PREF_VMID_MASK | - UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_CMPL_VMID_MASK, - (conf->rx_q_prefetch_vmid << - UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_PREF_VMID_SHIFT) | - (conf->rx_q_compl_vmid << - UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_CMPL_VMID_SHIFT)); - - al_reg_write32_masked( - &vmpr->cfg_vmpr_7, - UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_VMID_MASK | - UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_VMID_SEL_MASK, - (conf->rx_q_data_vmid << - UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_VMID_SHIFT) | - (conf->rx_q_data_vmid_mask << - UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_VMID_SEL_SHIFT)); - - al_reg_write32_masked( - &vmpr->cfg_vmpr_8, - UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_VMID_MASK | - UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_VMID_SEL_MASK, - (conf->rx_q_data_buff2_vmid << - UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_VMID_SHIFT) | - (conf->rx_q_data_buff2_mask << - UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_VMID_SEL_SHIFT)); - - al_reg_write32_masked( - &vmpr->cfg_vmpr_9, - UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_VMID_MASK | - UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_VMID_SEL_MASK, - (conf->rx_q_ddp_vmid << - UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_VMID_SHIFT) | - (conf->rx_q_ddp_mask << - UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_VMID_SEL_SHIFT)); - - al_reg_write32( - &vmpr->cfg_vmpr_10, - conf->rx_q_addr_hi); - - al_reg_write32( - &vmpr->cfg_vmpr_11, - conf->rx_q_data_buff2_addr_hi); - - al_reg_write32( - &vmpr->cfg_vmpr_12, - conf->rx_q_ddp_addr_hi); -} - -/* UDMA header split buffer 2 Rx queue configuration */ -void al_udma_gen_hdr_split_buff2_rx_q_conf( - struct al_udma_q *q, - struct al_udma_gen_hdr_split_buff2_q_conf *conf) -{ - struct udma_gen_regs *gen_regs = q->udma->gen_regs; - struct udma_gen_vmpr *vmpr = &gen_regs->vmpr[q->qid]; - - al_reg_write32_masked( - &vmpr->cfg_vmpr_4, - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_MSB_ADDR_SEL_MASK, - conf->add_msb_sel << - UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_MSB_ADDR_SEL_SHIFT); - - al_reg_write32( - &vmpr->cfg_vmpr_5, - conf->addr_msb); -} - diff --git a/al_hal_udma_config.h b/al_hal_udma_config.h index b742e1824c9..8e689a630c2 100644 --- a/al_hal_udma_config.h +++ b/al_hal_udma_config.h @@ -1,5 +1,4 @@ -/*- -******************************************************************************* +/******************************************************************************* Copyright (C) 2015 Annapurna Labs Ltd. This file may be licensed under the terms of the Annapurna Labs Commercial @@ -313,237 +312,40 @@ struct al_udma_s2m_q_comp_conf { uint8_t q_qos; /* queue QoS */ }; -/** UDMA per queue VMID control configuration */ -struct al_udma_gen_vmid_q_conf { - /* Enable usage of the VMID per queue according to 'vmid' */ +/** UDMA per queue Target-ID control configuration */ +struct al_udma_gen_tgtid_q_conf { + /* Enable usage of the Target-ID per queue according to 'tgtid' */ al_bool queue_en; - /* Enable usage of the VMID from the descriptor buffer address 63:48 */ + /* Enable usage of the Target-ID from the descriptor buffer address 63:48 */ al_bool desc_en; - /* VMID to be applied when 'queue_en' is asserted */ - uint16_t vmid; + /* Target-ID to be applied when 'queue_en' is asserted */ + uint16_t tgtid; - /* VMADDR to be applied to msbs when 'desc_en' is asserted. + /* TGTADDR to be applied to msbs when 'desc_en' is asserted. * Relevant for revisions >= AL_UDMA_REV_ID_REV2 */ - uint16_t vmaddr; + uint16_t tgtaddr; }; -/** UDMA VMID control configuration */ -struct al_udma_gen_vmid_conf { +/** UDMA Target-ID control configuration */ +struct al_udma_gen_tgtid_conf { /* TX queue configuration */ - struct al_udma_gen_vmid_q_conf tx_q_conf[DMA_MAX_Q]; + struct al_udma_gen_tgtid_q_conf tx_q_conf[DMA_MAX_Q]; /* RX queue configuration */ - struct al_udma_gen_vmid_q_conf rx_q_conf[DMA_MAX_Q]; + struct al_udma_gen_tgtid_q_conf rx_q_conf[DMA_MAX_Q]; }; -/** UDMA VMID MSIX control configuration */ -struct al_udma_gen_vmid_msix_conf { - /* Enable write to all VMID_n registers in the MSI-X Controller */ +/** UDMA Target-ID MSIX control configuration */ +struct al_udma_gen_tgtid_msix_conf { + /* Enable write to all TGTID_n registers in the MSI-X Controller */ al_bool access_en; - /* use VMID_n [7:0] from MSI-X Controller for MSI-X message */ + /* use TGTID_n [7:0] from MSI-X Controller for MSI-X message */ al_bool sel; }; -/** UDMA per Tx queue advanced VMID control configuration */ -struct al_udma_gen_vmid_advanced_tx_q_conf { - /********************************************************************** - * Tx Data VMID - **********************************************************************/ - /* Tx data VMID enable */ - al_bool tx_q_data_vmid_en; - - /* - * For Tx data reads, replacement bits for the original address. - * The number of bits replaced is determined according to - * 'tx_q_addr_hi_sel' - */ - unsigned int tx_q_addr_hi; - - /* - * For Tx data reads, 6 bits serving the number of bits taken from the - * extra register on account of bits coming from the original address - * field. - * When 'tx_q_addr_hi_sel'=32 all of 'tx_q_addr_hi' will be taken. - * When 'tx_q_addr_hi_sel'=0 none of it will be taken, and when any - * value in between, it will start from the MSB bit and sweep down as - * many bits as needed. For example if 'tx_q_addr_hi_sel'=8, the final - * address [63:56] will carry 'tx_q_addr_hi'[31:24] while [55:32] will - * carry the original buffer address[55:32]. - */ - unsigned int tx_q_addr_hi_sel; - - /* - * Tx data read VMID - * Masked per bit with 'tx_q_data_vmid_mask' - */ - unsigned int tx_q_data_vmid; - - /* - * Tx data read VMID mask - * Each '1' selects from the buffer address, each '0' selects from - * 'tx_q_data_vmid' - */ - unsigned int tx_q_data_vmid_mask; - - /********************************************************************** - * Tx prefetch VMID - **********************************************************************/ - /* Tx prefetch VMID enable */ - al_bool tx_q_prefetch_vmid_en; - - /* Tx prefetch VMID */ - unsigned int tx_q_prefetch_vmid; - - /********************************************************************** - * Tx completion VMID - **********************************************************************/ - /* Tx completion VMID enable */ - al_bool tx_q_compl_vmid_en; - - /* Tx completion VMID */ - unsigned int tx_q_compl_vmid; -}; - -/** UDMA per Rx queue advanced VMID control configuration */ -struct al_udma_gen_vmid_advanced_rx_q_conf { - /********************************************************************** - * Rx Data VMID - **********************************************************************/ - /* Rx data VMID enable */ - al_bool rx_q_data_vmid_en; - - /* - * For Rx data writes, replacement bits for the original address. - * The number of bits replaced is determined according to - * 'rx_q_addr_hi_sel' - */ - unsigned int rx_q_addr_hi; - - /* - * For Rx data writes, 6 bits serving the number of bits taken from the - * extra register on account of bits coming from the original address - * field. - */ - unsigned int rx_q_addr_hi_sel; - - /* - * Rx data write VMID - * Masked per bit with 'rx_q_data_vmid_mask' - */ - unsigned int rx_q_data_vmid; - - /* Rx data write VMID mask */ - unsigned int rx_q_data_vmid_mask; - - /********************************************************************** - * Rx Data Buffer 2 VMID - **********************************************************************/ - /* Rx data buff2 VMID enable */ - al_bool rx_q_data_buff2_vmid_en; - - /* - * For Rx data buff2 writes, replacement bits for the original address. - * The number of bits replaced is determined according to - * 'rx_q_data_buff2_addr_hi_sel' - */ - unsigned int rx_q_data_buff2_addr_hi; - - /* - * For Rx data buff2 writes, 6 bits serving the number of bits taken - * from the extra register on account of bits coming from the original - * address field. - */ - unsigned int rx_q_data_buff2_addr_hi_sel; - - /* - * Rx data buff2 write VMID - * Masked per bit with 'rx_q_data_buff2_mask' - */ - unsigned int rx_q_data_buff2_vmid; - - /* Rx data buff2 write VMID mask */ - unsigned int rx_q_data_buff2_mask; - - /********************************************************************** - * Rx DDP VMID - **********************************************************************/ - /* Rx DDP write VMID enable */ - al_bool rx_q_ddp_vmid_en; - - /* - * For Rx DDP writes, replacement bits for the original address. - * The number of bits replaced is determined according to - * 'rx_q_ddp_addr_hi_sel' - */ - unsigned int rx_q_ddp_addr_hi; - - /* - * For Rx DDP writes, 6 bits serving the number of bits taken from the - * extra register on account of bits coming from the original address - * field. - */ - unsigned int rx_q_ddp_addr_hi_sel; - - /* - * Rx DDP write VMID - * Masked per bit with 'rx_q_ddp_mask' - */ - unsigned int rx_q_ddp_vmid; - - /* Rx DDP write VMID mask */ - unsigned int rx_q_ddp_mask; - - /********************************************************************** - * Rx prefetch VMID - **********************************************************************/ - /* Rx prefetch VMID enable */ - al_bool rx_q_prefetch_vmid_en; - - /* Rx prefetch VMID */ - unsigned int rx_q_prefetch_vmid; - - /********************************************************************** - * Rx completion VMID - **********************************************************************/ - /* Rx completion VMID enable */ - al_bool rx_q_compl_vmid_en; - - /* Rx completion VMID */ - unsigned int rx_q_compl_vmid; -}; - -/** - * Header split, buffer 2 per queue configuration - * When header split is enabled, Buffer_2 is used as an address for the header - * data. Buffer_2 is defined as 32-bits in the RX descriptor and it is defined - * that the MSB ([63:32]) of Buffer_1 is used as address [63:32] for the header - * address. - */ -struct al_udma_gen_hdr_split_buff2_q_conf { - /* - * MSB of the 64-bit address (bits [63:32]) that can be used for header - * split for this queue - */ - unsigned int addr_msb; - - /* - * Determine how to select the MSB (bits [63:32]) of the address when - * header split is enabled (4 bits, one per byte) - * - Bits [3:0]: - * [0] – selector for bits [39:32] - * [1] – selector for bits [47:40] - * [2] – selector for bits [55:48] - * [3] – selector for bits [63:55] - * - Bit value: - * 0 – Use Buffer_1 (legacy operation) - * 1 – Use the queue configuration 'addr_msb' - */ - unsigned int add_msb_sel; -}; - /* Report Error - to be used for abort */ void al_udma_err_report(struct al_udma *udma); @@ -721,30 +523,21 @@ int al_udma_s2m_q_compl_hdr_split_config(struct al_udma_q *udma_q, int al_udma_s2m_q_comp_set(struct al_udma_q *udma_q, struct al_udma_s2m_q_comp_conf *conf); -/** UDMA VMID control configuration */ -void al_udma_gen_vmid_conf_set( +/** UDMA Target-ID control configuration per queue */ +void al_udma_gen_tgtid_conf_queue_set( + struct unit_regs *unit_regs, + struct al_udma_gen_tgtid_conf *conf, + uint32_t qid); + +/** UDMA Target-ID control configuration */ +void al_udma_gen_tgtid_conf_set( struct unit_regs __iomem *unit_regs, - struct al_udma_gen_vmid_conf *conf); + struct al_udma_gen_tgtid_conf *conf); -/** UDMA VMID MSIX control configuration */ -void al_udma_gen_vmid_msix_conf_set( +/** UDMA Target-ID MSIX control configuration */ +void al_udma_gen_tgtid_msix_conf_set( struct unit_regs __iomem *unit_regs, - struct al_udma_gen_vmid_msix_conf *conf); - -/** UDMA VMID control advanced Tx queue configuration */ -void al_udma_gen_vmid_advanced_tx_q_conf( - struct al_udma_q *q, - struct al_udma_gen_vmid_advanced_tx_q_conf *conf); - -/** UDMA VMID control advanced Rx queue configuration */ -void al_udma_gen_vmid_advanced_rx_q_conf( - struct al_udma_q *q, - struct al_udma_gen_vmid_advanced_rx_q_conf *conf); - -/** UDMA header split buffer 2 Rx queue configuration */ -void al_udma_gen_hdr_split_buff2_rx_q_conf( - struct al_udma_q *q, - struct al_udma_gen_hdr_split_buff2_q_conf *conf); + struct al_udma_gen_tgtid_msix_conf *conf); /* *INDENT-OFF* */ #ifdef __cplusplus diff --git a/al_hal_udma_debug.c b/al_hal_udma_debug.c index c6b9bf4b9bf..189e6767e89 100644 --- a/al_hal_udma_debug.c +++ b/al_hal_udma_debug.c @@ -425,9 +425,9 @@ void al_udma_q_struct_print(struct al_udma *udma, uint32_t qid) al_dbg(" comp_head_ptr = %p\n", queue->comp_head_ptr); al_dbg(" pkt_crnt_descs = %d\n", (uint32_t)queue->pkt_crnt_descs); al_dbg(" comp_ring_id = %d\n", (uint32_t)queue->comp_ring_id); - al_dbg(" desc_phy_base = 0x%016llx\n", (uint64_t)queue->desc_phy_base); - al_dbg(" cdesc_phy_base = 0x%016llx\n", - (uint64_t)queue->cdesc_phy_base); + al_dbg(" desc_phy_base = 0x%016jx\n", (uintmax_t)queue->desc_phy_base); + al_dbg(" cdesc_phy_base = 0x%016jx\n", + (uintmax_t)queue->cdesc_phy_base); al_dbg(" flags = 0x%08x\n", (uint32_t)queue->flags); al_dbg(" size = %d\n", (uint32_t)queue->size); al_dbg(" status = %d\n", (uint32_t)queue->status); @@ -471,7 +471,7 @@ void al_udma_ring_print(struct al_udma *udma, uint32_t qid, } for (i = 0; i < queue->size; i++) { - uint32_t *curr_addr = (void*)((uint32_t)base_ptr + i * desc_size); + uint32_t *curr_addr = (void*)((uintptr_t)base_ptr + i * desc_size); if (desc_size == 16) al_dbg("[%04d](%p): %08x %08x %08x %08x\n", i, diff --git a/al_hal_udma_iofic.h b/al_hal_udma_iofic.h index 9e795004837..65871c80f17 100644 --- a/al_hal_udma_iofic.h +++ b/al_hal_udma_iofic.h @@ -610,5 +610,23 @@ static INLINE uint32_t al_udma_iofic_read_cause( return al_iofic_read_cause(al_udma_iofic_reg_base_get(regs, level), group); } +/** + * clear bits in the interrupt cause register for a given group + * + * @param regs pointer to udma unit registers + * @param level the interrupt controller level (primary / secondary) + * @param group the interrupt group ('AL_INT_GROUP_*') + * @param mask bitwise of bits to be cleared, set bits will be cleared. + */ +static INLINE void al_udma_iofic_clear_cause( + struct unit_regs __iomem *regs, + enum al_udma_iofic_level level, + int group, + uint32_t mask) +{ + al_assert(al_udma_iofic_level_and_group_valid(level, group)); + al_iofic_clear_cause(al_udma_iofic_reg_base_get(regs, level), group, mask); +} + #endif /** @} end of UDMA group */ diff --git a/al_hal_udma_main.c b/al_hal_udma_main.c index 6e9919b3596..6dac88c1b7c 100644 --- a/al_hal_udma_main.c +++ b/al_hal_udma_main.c @@ -70,7 +70,6 @@ const char *const al_udma_states_name[] = { static void al_udma_set_defaults(struct al_udma *udma) { - uint32_t tmp; uint8_t rev_id = udma->rev_id; if (udma->type == UDMA_TX) { @@ -85,25 +84,11 @@ static void al_udma_set_defaults(struct al_udma *udma) 256 << UDMA_M2S_RD_DATA_CFG_DATA_FIFO_DEPTH_SHIFT); } - if (rev_id == AL_UDMA_REV_ID_0) - /* disable AXI timeout for M0*/ - al_reg_write32(&tmp_unit_regs->gen.axi.cfg_1, 0); - else - /* set AXI timeout to 1M (~2.6 ms) */ - al_reg_write32(&tmp_unit_regs->gen.axi.cfg_1, 1000000); + /* set AXI timeout to 1M (~2.6 ms) */ + al_reg_write32(&tmp_unit_regs->gen.axi.cfg_1, 1000000); al_reg_write32(&tmp_unit_regs->m2s.m2s_comp.cfg_application_ack , 0); /* Ack time out */ - - - if (rev_id == AL_UDMA_REV_ID_0) { - tmp = al_reg_read32(&udma->udma_regs->m2s.axi_m2s.desc_wr_cfg_1); - tmp &= ~UDMA_AXI_M2S_DESC_WR_CFG_1_MAX_AXI_BEATS_MASK; - tmp |= 4 << UDMA_AXI_M2S_DESC_WR_CFG_1_MAX_AXI_BEATS_SHIFT; - al_reg_write32(&udma->udma_regs->m2s.axi_m2s.desc_wr_cfg_1 - , tmp); - } - } if (udma->type == UDMA_RX) { al_reg_write32( @@ -365,14 +350,13 @@ int al_udma_q_init(struct al_udma *udma, uint32_t qid, al_udma_q_enable(udma_q, 1); al_dbg("udma [%s %d]: %s q init. size 0x%x\n" - " desc ring info: phys base 0x%llx virt base %p\n" - " cdesc ring info: phys base 0x%llx virt base %p " - "entry size 0x%x", + " desc ring info: phys base 0x%llx virt base %p)", udma_q->udma->name, udma_q->qid, udma->type == UDMA_TX ? "Tx" : "Rx", q_params->size, (unsigned long long)q_params->desc_phy_base, - q_params->desc_base, + q_params->desc_base); + al_dbg(" cdesc ring info: phys base 0x%llx virt base %p entry size 0x%x", (unsigned long long)q_params->cdesc_phy_base, q_params->cdesc_base, q_params->cdesc_size); diff --git a/al_hal_udma_regs_gen.h b/al_hal_udma_regs_gen.h index 89f94b85a56..5c60fc9506e 100644 --- a/al_hal_udma_regs_gen.h +++ b/al_hal_udma_regs_gen.h @@ -1,5 +1,4 @@ -/*- -******************************************************************************* +/******************************************************************************* Copyright (C) 2015 Annapurna Labs Ltd. This file may be licensed under the terms of the Annapurna Labs Commercial @@ -97,48 +96,48 @@ struct udma_gen_sram_ctrl { /* [0x0] Timing configuration */ uint32_t timing; }; -struct udma_gen_vmid { - /* [0x0] VMID control */ - uint32_t cfg_vmid_0; - /* [0x4] TX queue 0/1 VMID */ - uint32_t cfg_vmid_1; - /* [0x8] TX queue 2/3 VMID */ - uint32_t cfg_vmid_2; - /* [0xc] RX queue 0/1 VMID */ - uint32_t cfg_vmid_3; - /* [0x10] RX queue 2/3 VMID */ - uint32_t cfg_vmid_4; +struct udma_gen_tgtid { + /* [0x0] Target-ID control */ + uint32_t cfg_tgtid_0; + /* [0x4] TX queue 0/1 Target-ID */ + uint32_t cfg_tgtid_1; + /* [0x8] TX queue 2/3 Target-ID */ + uint32_t cfg_tgtid_2; + /* [0xc] RX queue 0/1 Target-ID */ + uint32_t cfg_tgtid_3; + /* [0x10] RX queue 2/3 Target-ID */ + uint32_t cfg_tgtid_4; }; -struct udma_gen_vmaddr { - /* [0x0] TX queue 0/1 VMADDR */ - uint32_t cfg_vmaddr_0; - /* [0x4] TX queue 2/3 VMADDR */ - uint32_t cfg_vmaddr_1; - /* [0x8] RX queue 0/1 VMADDR */ - uint32_t cfg_vmaddr_2; - /* [0xc] RX queue 2/3 VMADDR */ - uint32_t cfg_vmaddr_3; +struct udma_gen_tgtaddr { + /* [0x0] TX queue 0/1 Target-Address */ + uint32_t cfg_tgtaddr_0; + /* [0x4] TX queue 2/3 Target-Address */ + uint32_t cfg_tgtaddr_1; + /* [0x8] RX queue 0/1 Target-Address */ + uint32_t cfg_tgtaddr_2; + /* [0xc] RX queue 2/3 Target-Address */ + uint32_t cfg_tgtaddr_3; }; struct udma_gen_vmpr { /* [0x0] TX VMPR control */ uint32_t cfg_vmpr_0; /* [0x4] TX VMPR Address High Regsiter */ uint32_t cfg_vmpr_1; - /* [0x8] TX queue VMID values */ + /* [0x8] TX queue Target-ID values */ uint32_t cfg_vmpr_2; - /* [0xc] TX queue VMID values */ + /* [0xc] TX queue Target-ID values */ uint32_t cfg_vmpr_3; /* [0x10] RX VMPR control */ uint32_t cfg_vmpr_4; /* [0x14] RX VMPR Buffer2 MSB address */ uint32_t cfg_vmpr_5; - /* [0x18] RX queue VMID values */ + /* [0x18] RX queue Target-ID values */ uint32_t cfg_vmpr_6; - /* [0x1c] RX queue BUF1 VMID values */ + /* [0x1c] RX queue BUF1 Target-ID values */ uint32_t cfg_vmpr_7; - /* [0x20] RX queue BUF2 VMID values */ + /* [0x20] RX queue BUF2 Target-ID values */ uint32_t cfg_vmpr_8; - /* [0x24] RX queue Direct Data Placement VMID values */ + /* [0x24] RX queue Direct Data Placement Target-ID values */ uint32_t cfg_vmpr_9; /* [0x28] RX VMPR BUF1 Address High Regsiter */ uint32_t cfg_vmpr_10; @@ -156,8 +155,8 @@ struct udma_gen_regs { struct udma_gen_axi axi; /* [0x2280] */ struct udma_gen_sram_ctrl sram_ctrl[25]; /* [0x2380] */ uint32_t rsrvd_1[2]; - struct udma_gen_vmid vmid; /* [0x23ec] */ - struct udma_gen_vmaddr vmaddr; /* [0x2400] */ + struct udma_gen_tgtid tgtid; /* [0x23ec] */ + struct udma_gen_tgtaddr tgtaddr; /* [0x2400] */ uint32_t rsrvd_2[252]; struct udma_gen_vmpr vmpr[4]; /* [0x2800] */ }; @@ -236,176 +235,182 @@ struct udma_gen_regs { /* Read margin enable */ #define UDMA_GEN_SRAM_CTRL_TIMING_RMEB (1 << 24) -/**** cfg_vmid_0 register ****/ -/* For M2S queues 3:0, enable usage of the VMID from the buffer address 63:56 */ -#define UDMA_GEN_VMID_CFG_VMID_0_TX_Q_VMID_DESC_EN_MASK 0x0000000F -#define UDMA_GEN_VMID_CFG_VMID_0_TX_Q_VMID_DESC_EN_SHIFT 0 +/**** cfg_tgtid_0 register ****/ +/* For M2S queues 3:0, enable usage of the Target-ID from the buffer address 63:56 */ +#define UDMA_GEN_TGTID_CFG_TGTID_0_TX_Q_TGTID_DESC_EN_MASK 0x0000000F +#define UDMA_GEN_TGTID_CFG_TGTID_0_TX_Q_TGTID_DESC_EN_SHIFT 0 /* - * For M2S queues 3:0, enable usage of the VMID from the configuration register - * (cfg_vmid_1/2 used for M2S queue_x) + * For M2S queues 3:0, enable usage of the Target-ID from the configuration register + * (cfg_tgtid_1/2 used for M2S queue_x) */ -#define UDMA_GEN_VMID_CFG_VMID_0_TX_Q_VMID_QUEUE_EN_MASK 0x000000F0 -#define UDMA_GEN_VMID_CFG_VMID_0_TX_Q_VMID_QUEUE_EN_SHIFT 4 -/* use VMID_n [7:0] from MSI-X Controller for MSI-X message */ -#define UDMA_GEN_VMID_CFG_VMID_0_MSIX_VMID_SEL (1 << 8) -/* Enable write to all VMID_n registers in the MSI-X Controller */ -#define UDMA_GEN_VMID_CFG_VMID_0_MSIX_VMID_ACCESS_EN (1 << 9) -/* For S2M queues 3:0, enable usage of the VMID from the buffer address 63:56 */ -#define UDMA_GEN_VMID_CFG_VMID_0_RX_Q_VMID_DESC_EN_MASK 0x000F0000 -#define UDMA_GEN_VMID_CFG_VMID_0_RX_Q_VMID_DESC_EN_SHIFT 16 +#define UDMA_GEN_TGTID_CFG_TGTID_0_TX_Q_TGTID_QUEUE_EN_MASK 0x000000F0 +#define UDMA_GEN_TGTID_CFG_TGTID_0_TX_Q_TGTID_QUEUE_EN_SHIFT 4 +/* use Target-ID_n [7:0] from MSI-X Controller for MSI-X message */ +#define UDMA_GEN_TGTID_CFG_TGTID_0_MSIX_TGTID_SEL (1 << 8) +/* Enable write to all Target-ID_n registers in the MSI-X Controller */ +#define UDMA_GEN_TGTID_CFG_TGTID_0_MSIX_TGTID_ACCESS_EN (1 << 9) +/* For S2M queues 3:0, enable usage of the Target-ID from the buffer address 63:56 */ +#define UDMA_GEN_TGTID_CFG_TGTID_0_RX_Q_TGTID_DESC_EN_MASK 0x000F0000 +#define UDMA_GEN_TGTID_CFG_TGTID_0_RX_Q_TGTID_DESC_EN_SHIFT 16 /* - * For S2M queues 3:0, enable usage of the VMID from the configuration register - * (cfg_vmid_3/4 used for M2S queue_x) + * For S2M queues 3:0, enable usage of the Target-ID from the configuration register + * (cfg_tgtid_3/4 used for M2S queue_x) */ -#define UDMA_GEN_VMID_CFG_VMID_0_RX_Q_VMID_QUEUE_EN_MASK 0x00F00000 -#define UDMA_GEN_VMID_CFG_VMID_0_RX_Q_VMID_QUEUE_EN_SHIFT 20 +#define UDMA_GEN_TGTID_CFG_TGTID_0_RX_Q_TGTID_QUEUE_EN_MASK 0x00F00000 +#define UDMA_GEN_TGTID_CFG_TGTID_0_RX_Q_TGTID_QUEUE_EN_SHIFT 20 -/**** cfg_vmid_1 register ****/ -/* TX queue 0 VMID value */ -#define UDMA_GEN_VMID_CFG_VMID_1_TX_Q_0_VMID_MASK 0x0000FFFF -#define UDMA_GEN_VMID_CFG_VMID_1_TX_Q_0_VMID_SHIFT 0 -/* TX queue 1 VMID value */ -#define UDMA_GEN_VMID_CFG_VMID_1_TX_Q_1_VMID_MASK 0xFFFF0000 -#define UDMA_GEN_VMID_CFG_VMID_1_TX_Q_1_VMID_SHIFT 16 +#define UDMA_GEN_TGTID_CFG_TGTID_SHIFT(qid) (((qid) & 0x1) ? 16 : 0) +#define UDMA_GEN_TGTID_CFG_TGTID_MASK(qid) (((qid) & 0x1) ? 0xFFFF0000 : 0x0000FFFF) -/**** cfg_vmid_2 register ****/ -/* TX queue 2 VMID value */ -#define UDMA_GEN_VMID_CFG_VMID_2_TX_Q_2_VMID_MASK 0x0000FFFF -#define UDMA_GEN_VMID_CFG_VMID_2_TX_Q_2_VMID_SHIFT 0 -/* TX queue 3 VMID value */ -#define UDMA_GEN_VMID_CFG_VMID_2_TX_Q_3_VMID_MASK 0xFFFF0000 -#define UDMA_GEN_VMID_CFG_VMID_2_TX_Q_3_VMID_SHIFT 16 +/**** cfg_tgtid_1 register ****/ +/* TX queue 0 Target-ID value */ +#define UDMA_GEN_TGTID_CFG_TGTID_1_TX_Q_0_TGTID_MASK 0x0000FFFF +#define UDMA_GEN_TGTID_CFG_TGTID_1_TX_Q_0_TGTID_SHIFT 0 +/* TX queue 1 Target-ID value */ +#define UDMA_GEN_TGTID_CFG_TGTID_1_TX_Q_1_TGTID_MASK 0xFFFF0000 +#define UDMA_GEN_TGTID_CFG_TGTID_1_TX_Q_1_TGTID_SHIFT 16 -/**** cfg_vmid_3 register ****/ -/* RX queue 0 VMID value */ -#define UDMA_GEN_VMID_CFG_VMID_3_RX_Q_0_VMID_MASK 0x0000FFFF -#define UDMA_GEN_VMID_CFG_VMID_3_RX_Q_0_VMID_SHIFT 0 -/* RX queue 1 VMID value */ -#define UDMA_GEN_VMID_CFG_VMID_3_RX_Q_1_VMID_MASK 0xFFFF0000 -#define UDMA_GEN_VMID_CFG_VMID_3_RX_Q_1_VMID_SHIFT 16 +/**** cfg_tgtid_2 register ****/ +/* TX queue 2 Target-ID value */ +#define UDMA_GEN_TGTID_CFG_TGTID_2_TX_Q_2_TGTID_MASK 0x0000FFFF +#define UDMA_GEN_TGTID_CFG_TGTID_2_TX_Q_2_TGTID_SHIFT 0 +/* TX queue 3 Target-ID value */ +#define UDMA_GEN_TGTID_CFG_TGTID_2_TX_Q_3_TGTID_MASK 0xFFFF0000 +#define UDMA_GEN_TGTID_CFG_TGTID_2_TX_Q_3_TGTID_SHIFT 16 -/**** cfg_vmid_4 register ****/ -/* RX queue 2 VMID value */ -#define UDMA_GEN_VMID_CFG_VMID_4_RX_Q_2_VMID_MASK 0x0000FFFF -#define UDMA_GEN_VMID_CFG_VMID_4_RX_Q_2_VMID_SHIFT 0 -/* RX queue 3 VMID value */ -#define UDMA_GEN_VMID_CFG_VMID_4_RX_Q_3_VMID_MASK 0xFFFF0000 -#define UDMA_GEN_VMID_CFG_VMID_4_RX_Q_3_VMID_SHIFT 16 +/**** cfg_tgtid_3 register ****/ +/* RX queue 0 Target-ID value */ +#define UDMA_GEN_TGTID_CFG_TGTID_3_RX_Q_0_TGTID_MASK 0x0000FFFF +#define UDMA_GEN_TGTID_CFG_TGTID_3_RX_Q_0_TGTID_SHIFT 0 +/* RX queue 1 Target-ID value */ +#define UDMA_GEN_TGTID_CFG_TGTID_3_RX_Q_1_TGTID_MASK 0xFFFF0000 +#define UDMA_GEN_TGTID_CFG_TGTID_3_RX_Q_1_TGTID_SHIFT 16 -/**** cfg_vmaddr_0 register ****/ -/* TX queue 0 VMADDR value */ -#define UDMA_GEN_VMADDR_CFG_VMADDR_0_TX_Q_0_VMADDR_MASK 0x0000FFFF -#define UDMA_GEN_VMADDR_CFG_VMADDR_0_TX_Q_0_VMADDR_SHIFT 0 -/* TX queue 1 VMADDR value */ -#define UDMA_GEN_VMADDR_CFG_VMADDR_0_TX_Q_1_VMADDR_MASK 0xFFFF0000 -#define UDMA_GEN_VMADDR_CFG_VMADDR_0_TX_Q_1_VMADDR_SHIFT 16 +/**** cfg_tgtid_4 register ****/ +/* RX queue 2 Target-ID value */ +#define UDMA_GEN_TGTID_CFG_TGTID_4_RX_Q_2_TGTID_MASK 0x0000FFFF +#define UDMA_GEN_TGTID_CFG_TGTID_4_RX_Q_2_TGTID_SHIFT 0 +/* RX queue 3 Target-ID value */ +#define UDMA_GEN_TGTID_CFG_TGTID_4_RX_Q_3_TGTID_MASK 0xFFFF0000 +#define UDMA_GEN_TGTID_CFG_TGTID_4_RX_Q_3_TGTID_SHIFT 16 -/**** cfg_vmaddr_1 register ****/ -/* TX queue 2 VMADDR value */ -#define UDMA_GEN_VMADDR_CFG_VMADDR_1_TX_Q_2_VMADDR_MASK 0x0000FFFF -#define UDMA_GEN_VMADDR_CFG_VMADDR_1_TX_Q_2_VMADDR_SHIFT 0 -/* TX queue 3 VMADDR value */ -#define UDMA_GEN_VMADDR_CFG_VMADDR_1_TX_Q_3_VMADDR_MASK 0xFFFF0000 -#define UDMA_GEN_VMADDR_CFG_VMADDR_1_TX_Q_3_VMADDR_SHIFT 16 +#define UDMA_GEN_TGTADDR_CFG_SHIFT(qid) (((qid) & 0x1) ? 16 : 0) +#define UDMA_GEN_TGTADDR_CFG_MASK(qid) (((qid) & 0x1) ? 0xFFFF0000 : 0x0000FFFF) -/**** cfg_vmaddr_2 register ****/ -/* RX queue 0 VMADDR value */ -#define UDMA_GEN_VMADDR_CFG_VMADDR_2_RX_Q_0_VMADDR_MASK 0x0000FFFF -#define UDMA_GEN_VMADDR_CFG_VMADDR_2_RX_Q_0_VMADDR_SHIFT 0 -/* RX queue 1 VMADDR value */ -#define UDMA_GEN_VMADDR_CFG_VMADDR_2_RX_Q_1_VMADDR_MASK 0xFFFF0000 -#define UDMA_GEN_VMADDR_CFG_VMADDR_2_RX_Q_1_VMADDR_SHIFT 16 +/**** cfg_tgtaddr_0 register ****/ +/* TX queue 0 Target-Address value */ +#define UDMA_GEN_TGTADDR_CFG_TGTADDR_0_TX_Q_0_TGTADDR_MASK 0x0000FFFF +#define UDMA_GEN_TGTADDR_CFG_TGTADDR_0_TX_Q_0_TGTADDR_SHIFT 0 +/* TX queue 1 Target-Address value */ +#define UDMA_GEN_TGTADDR_CFG_TGTADDR_0_TX_Q_1_TGTADDR_MASK 0xFFFF0000 +#define UDMA_GEN_TGTADDR_CFG_TGTADDR_0_TX_Q_1_TGTADDR_SHIFT 16 -/**** cfg_vmaddr_3 register ****/ -/* RX queue 2 VMADDR value */ -#define UDMA_GEN_VMADDR_CFG_VMADDR_3_RX_Q_2_VMADDR_MASK 0x0000FFFF -#define UDMA_GEN_VMADDR_CFG_VMADDR_3_RX_Q_2_VMADDR_SHIFT 0 -/* RX queue 3 VMADDR value */ -#define UDMA_GEN_VMADDR_CFG_VMADDR_3_RX_Q_3_VMADDR_MASK 0xFFFF0000 -#define UDMA_GEN_VMADDR_CFG_VMADDR_3_RX_Q_3_VMADDR_SHIFT 16 +/**** cfg_tgtaddr_1 register ****/ +/* TX queue 2 Target-Address value */ +#define UDMA_GEN_TGTADDR_CFG_TGTADDR_1_TX_Q_2_TGTADDR_MASK 0x0000FFFF +#define UDMA_GEN_TGTADDR_CFG_TGTADDR_1_TX_Q_2_TGTADDR_SHIFT 0 +/* TX queue 3 Target-Address value */ +#define UDMA_GEN_TGTADDR_CFG_TGTADDR_1_TX_Q_3_TGTADDR_MASK 0xFFFF0000 +#define UDMA_GEN_TGTADDR_CFG_TGTADDR_1_TX_Q_3_TGTADDR_SHIFT 16 + +/**** cfg_tgtaddr_2 register ****/ +/* RX queue 0 Target-Address value */ +#define UDMA_GEN_TGTADDR_CFG_TGTADDR_2_RX_Q_0_TGTADDR_MASK 0x0000FFFF +#define UDMA_GEN_TGTADDR_CFG_TGTADDR_2_RX_Q_0_TGTADDR_SHIFT 0 +/* RX queue 1 Target-Address value */ +#define UDMA_GEN_TGTADDR_CFG_TGTADDR_2_RX_Q_1_TGTADDR_MASK 0xFFFF0000 +#define UDMA_GEN_TGTADDR_CFG_TGTADDR_2_RX_Q_1_TGTADDR_SHIFT 16 + +/**** cfg_tgtaddr_3 register ****/ +/* RX queue 2 Target-Address value */ +#define UDMA_GEN_TGTADDR_CFG_TGTADDR_3_RX_Q_2_TGTADDR_MASK 0x0000FFFF +#define UDMA_GEN_TGTADDR_CFG_TGTADDR_3_RX_Q_2_TGTADDR_SHIFT 0 +/* RX queue 3 Target-Address value */ +#define UDMA_GEN_TGTADDR_CFG_TGTADDR_3_RX_Q_3_TGTADDR_MASK 0xFFFF0000 +#define UDMA_GEN_TGTADDR_CFG_TGTADDR_3_RX_Q_3_TGTADDR_SHIFT 16 /**** cfg_vmpr_0 register ****/ /* TX High Address Select Per Q */ #define UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_HISEL_MASK 0x0000003F #define UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_HISEL_SHIFT 0 -/* TX Data VMID Enable Per Q */ -#define UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_DATA_VMID_EN (1 << 7) -/* TX Prefetch VMID Enable Per Q */ -#define UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_PREF_VMID_EN (1 << 28) -/* TX Completions VMID Enable Per Q */ -#define UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_CMPL_VMID_EN (1 << 29) +/* TX Data Target-ID Enable Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_DATA_TGTID_EN (1 << 7) +/* TX Prefetch Target-ID Enable Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_PREF_TGTID_EN (1 << 28) +/* TX Completions Target-ID Enable Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_0_TX_Q_CMPL_TGTID_EN (1 << 29) /**** cfg_vmpr_2 register ****/ -/* TX queue Prefetch VMID */ -#define UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_PREF_VMID_MASK 0x0000FFFF -#define UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_PREF_VMID_SHIFT 0 -/* TX queue Completion VMID */ -#define UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_CMPL_VMID_MASK 0xFFFF0000 -#define UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_CMPL_VMID_SHIFT 16 +/* TX queue Prefetch Target-ID */ +#define UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_PREF_TGTID_MASK 0x0000FFFF +#define UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_PREF_TGTID_SHIFT 0 +/* TX queue Completion Target-ID */ +#define UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_CMPL_TGTID_MASK 0xFFFF0000 +#define UDMA_GEN_VMPR_CFG_VMPR_2_TX_Q_CMPL_TGTID_SHIFT 16 /**** cfg_vmpr_3 register ****/ -/* TX queue Data VMID */ -#define UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_VMID_MASK 0x0000FFFF -#define UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_VMID_SHIFT 0 -/* TX queue Data VMID select */ -#define UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_VMID_SEL_MASK 0xFFFF0000 -#define UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_VMID_SEL_SHIFT 16 +/* TX queue Data Target-ID */ +#define UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_TGTID_MASK 0x0000FFFF +#define UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_TGTID_SHIFT 0 +/* TX queue Data Target-ID select */ +#define UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_TGTID_SEL_MASK 0xFFFF0000 +#define UDMA_GEN_VMPR_CFG_VMPR_3_TX_Q_DATA_TGTID_SEL_SHIFT 16 /**** cfg_vmpr_4 register ****/ /* RX Data Buffer1 - High Address Select Per Q */ #define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF1_HISEL_MASK 0x0000003F #define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF1_HISEL_SHIFT 0 -/* RX Data Buffer1 VMID Enable Per Q */ -#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF1_VMID_EN (1 << 7) +/* RX Data Buffer1 Target-ID Enable Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF1_TGTID_EN (1 << 7) /* RX Data Buffer2 - High Address Select Per Q */ #define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_HISEL_MASK 0x00003F00 #define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_HISEL_SHIFT 8 -/* RX Data Buffer2 VMID Enable Per Q */ -#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_VMID_EN (1 << 15) +/* RX Data Buffer2 Target-ID Enable Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_TGTID_EN (1 << 15) /* RX Direct Data Placement - High Address Select Per Q */ #define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_DDP_HISEL_MASK 0x003F0000 #define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_DDP_HISEL_SHIFT 16 -/* RX Direct Data Placement VMID Enable Per Q */ -#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_DDP_VMID_EN (1 << 23) +/* RX Direct Data Placement Target-ID Enable Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_DDP_TGTID_EN (1 << 23) /* RX Buffer 2 MSB address word selects per bytes, per queue */ #define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_MSB_ADDR_SEL_MASK 0x0F000000 #define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_BUF2_MSB_ADDR_SEL_SHIFT 24 -/* RX Prefetch VMID Enable Per Q */ -#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_PREF_VMID_EN (1 << 28) -/* RX Completions VMID Enable Per Q */ -#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_CMPL_VMID_EN (1 << 29) +/* RX Prefetch Target-ID Enable Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_PREF_TGTID_EN (1 << 28) +/* RX Completions Target-ID Enable Per Q */ +#define UDMA_GEN_VMPR_CFG_VMPR_4_RX_Q_CMPL_TGTID_EN (1 << 29) /**** cfg_vmpr_6 register ****/ -/* RX queue Prefetch VMID */ -#define UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_PREF_VMID_MASK 0x0000FFFF -#define UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_PREF_VMID_SHIFT 0 -/* RX queue Completion VMID */ -#define UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_CMPL_VMID_MASK 0xFFFF0000 -#define UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_CMPL_VMID_SHIFT 16 +/* RX queue Prefetch Target-ID */ +#define UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_PREF_TGTID_MASK 0x0000FFFF +#define UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_PREF_TGTID_SHIFT 0 +/* RX queue Completion Target-ID */ +#define UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_CMPL_TGTID_MASK 0xFFFF0000 +#define UDMA_GEN_VMPR_CFG_VMPR_6_RX_Q_CMPL_TGTID_SHIFT 16 /**** cfg_vmpr_7 register ****/ -/* RX queue Data Buffer 1 VMID */ -#define UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_VMID_MASK 0x0000FFFF -#define UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_VMID_SHIFT 0 -/* RX queue Data Buffer 1 VMID select */ -#define UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_VMID_SEL_MASK 0xFFFF0000 -#define UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_VMID_SEL_SHIFT 16 +/* RX queue Data Buffer 1 Target-ID */ +#define UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_TGTID_MASK 0x0000FFFF +#define UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_TGTID_SHIFT 0 +/* RX queue Data Buffer 1 Target-ID select */ +#define UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_TGTID_SEL_MASK 0xFFFF0000 +#define UDMA_GEN_VMPR_CFG_VMPR_7_RX_Q_BUF1_TGTID_SEL_SHIFT 16 /**** cfg_vmpr_8 register ****/ -/* RX queue Data Buffer 2 VMID */ -#define UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_VMID_MASK 0x0000FFFF -#define UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_VMID_SHIFT 0 -/* RX queue Data Buffer 2 VMID select */ -#define UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_VMID_SEL_MASK 0xFFFF0000 -#define UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_VMID_SEL_SHIFT 16 +/* RX queue Data Buffer 2 Target-ID */ +#define UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_TGTID_MASK 0x0000FFFF +#define UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_TGTID_SHIFT 0 +/* RX queue Data Buffer 2 Target-ID select */ +#define UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_TGTID_SEL_MASK 0xFFFF0000 +#define UDMA_GEN_VMPR_CFG_VMPR_8_RX_Q_BUF2_TGTID_SEL_SHIFT 16 /**** cfg_vmpr_9 register ****/ -/* RX queue DDP VMID */ -#define UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_VMID_MASK 0x0000FFFF -#define UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_VMID_SHIFT 0 -/* RX queue DDP VMID select */ -#define UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_VMID_SEL_MASK 0xFFFF0000 -#define UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_VMID_SEL_SHIFT 16 +/* RX queue DDP Target-ID */ +#define UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_TGTID_MASK 0x0000FFFF +#define UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_TGTID_SHIFT 0 +/* RX queue DDP Target-ID select */ +#define UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_TGTID_SEL_MASK 0xFFFF0000 +#define UDMA_GEN_VMPR_CFG_VMPR_9_RX_Q_DDP_TGTID_SEL_SHIFT 16 #ifdef __cplusplus } diff --git a/al_hal_unit_adapter_regs.h b/al_hal_unit_adapter_regs.h index 740b959ab43..7a832cde94c 100644 --- a/al_hal_unit_adapter_regs.h +++ b/al_hal_unit_adapter_regs.h @@ -274,11 +274,11 @@ extern "C" { #define AL_ADPTR_GEN_CTL_13_SATA_ARUSER_VAL_SHIFT 0 #define AL_ADPTR_GEN_CTL_13_SATA_ARUSER_SEL_MASK AL_FIELD_MASK(31, 16) #define AL_ADPTR_GEN_CTL_13_SATA_ARUSER_SEL_SHIFT 16 -/* Central VMID enabler. If set, then each entry will be used as programmed */ -#define AL_ADPTR_GEN_CTL_14_SATA_MSIX_VMID_SEL AL_BIT(0) -/* Allow access to store VMID values per entry */ -#define AL_ADPTR_GEN_CTL_14_SATA_MSIX_VMID_ACCESS_EN AL_BIT(1) -/* VMID Address select */ +/* Central Target-ID enabler. If set, then each entry will be used as programmed */ +#define AL_ADPTR_GEN_CTL_14_SATA_MSIX_TGTID_SEL AL_BIT(0) +/* Allow access to store Target-ID values per entry */ +#define AL_ADPTR_GEN_CTL_14_SATA_MSIX_TGTID_ACCESS_EN AL_BIT(1) +/* Target-ID Address select */ /* Tx */ #define AL_ADPTR_GEN_CTL_14_SATA_VM_ARADDR_SEL_MASK AL_FIELD_MASK(13, 8) #define AL_ADPTR_GEN_CTL_14_SATA_VM_ARADDR_SEL_SHIFT 8 @@ -294,13 +294,13 @@ extern "C" { /* * ROB registers */ -/* Read ROB_Enable, when disabled the read ROB is bypassed */ +/* Read ROB Enable, when disabled the read ROB is bypassed */ #define AL_ADPTR_GEN_CTL_19_READ_ROB_EN AL_BIT(0) /* Read force in-order of every read transaction */ #define AL_ADPTR_GEN_CTL_19_READ_ROB_FORCE_INORDER AL_BIT(1) /* Read software reset */ #define AL_ADPTR_GEN_CTL_19_READ_ROB_SW_RESET AL_BIT(15) -/* Write ROB_Enable, when disabled_the_Write ROB is bypassed */ +/* Write ROB Enable, when disabled the Write ROB is bypassed */ #define AL_ADPTR_GEN_CTL_19_WRITE_ROB_EN AL_BIT(16) /* Write force in-order of every write transaction */ #define AL_ADPTR_GEN_CTL_19_WRITE_ROB_FORCE_INORDER AL_BIT(17) diff --git a/al_serdes.c b/al_serdes.c new file mode 100644 index 00000000000..6f978232756 --- /dev/null +++ b/al_serdes.c @@ -0,0 +1,59 @@ +/******************************************************************************* +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_serdes.h" +#include "al_hal_serdes_hssp.h" +#include "al_hal_serdes_25g.h" + +static int(*handle_init[AL_SRDS_NUM_GROUPS])(void __iomem *, struct al_serdes_grp_obj *) = { + al_serdes_hssp_handle_init, + al_serdes_hssp_handle_init, + al_serdes_hssp_handle_init, + al_serdes_hssp_handle_init, +#if CHECK_ALPINE_V2 + al_serdes_25g_handle_init, +#endif +}; + +int al_serdes_handle_grp_init( + void __iomem *serdes_regs_base, + enum al_serdes_group grp, + struct al_serdes_grp_obj *obj) +{ + handle_init[grp](serdes_regs_base, obj); + + return 0; +} + diff --git a/al_serdes.h b/al_serdes.h new file mode 100644 index 00000000000..44e217e7887 --- /dev/null +++ b/al_serdes.h @@ -0,0 +1,78 @@ +/******************************************************************************* +Copyright (C) 2013 Annapurna Labs Ltd. + +This file is licensed under the terms of the Annapurna Labs' Commercial License +Agreement distributed with the file or available on the software download site. +Recipient shall use the content of this file only on semiconductor devices or +systems developed by or for Annapurna Labs. + + 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. + +*******************************************************************************/ + +/** + * @defgroup group_serdes_init SerDes Initialization + * @ingroup group_serdes SerDes + * @{ + * + * @file al_serdes.h + * + */ + +#ifndef __AL_SERDES_H__ +#define __AL_SERDES_H__ + +#include "al_hal_serdes_interface.h" + +/* *INDENT-OFF* */ +#ifdef __cplusplus +extern "C" { +#endif +/* *INDENT-ON* */ + +#ifdef AL_DEV_ID +#define CHECK_ALPINE_V1 (AL_DEV_ID == AL_DEV_ID_ALPINE_V1) +#define CHECK_ALPINE_V2 (AL_DEV_ID == AL_DEV_ID_ALPINE_V2) +#else +#define CHECK_ALPINE_V1 1 +#define CHECK_ALPINE_V2 1 +#endif + +enum al_serdes_group { + AL_SRDS_GRP_A = 0, + AL_SRDS_GRP_B, + AL_SRDS_GRP_C, + AL_SRDS_GRP_D, + AL_SRDS_NUM_HSSP_GROUPS, +#if CHECK_ALPINE_V2 + AL_SRDS_GRP_E = AL_SRDS_NUM_HSSP_GROUPS, + AL_SRDS_NUM_GROUPS, +#else + AL_SRDS_NUM_GROUPS = AL_SRDS_NUM_HSSP_GROUPS, +#endif +}; + +int al_serdes_handle_grp_init( + void __iomem *serdes_regs_base, + enum al_serdes_group grp, + struct al_serdes_grp_obj *obj); + +/* *INDENT-OFF* */ +#ifdef __cplusplus +} +#endif + +/* *INDENT-ON* */ +#endif + +/** @} end of SERDES group */ + diff --git a/eth/al_hal_eth.h b/eth/al_hal_eth.h index 86108b0df4c..12944d30772 100644 --- a/eth/al_hal_eth.h +++ b/eth/al_hal_eth.h @@ -68,7 +68,7 @@ extern "C" { #ifndef AL_ETH_EX #define AL_ETH_PKT_MAX_BUFS 19 #else -#define AL_ETH_PKT_MAX_BUFS 29 +#define AL_ETH_PKT_MAX_BUFS 30 #endif #endif @@ -136,7 +136,8 @@ enum al_eth_mac_mode { AL_ETH_MAC_MODE_10G_SGMII, /**< SGMII using the 10G MAC, don't use*/ AL_ETH_MAC_MODE_XLG_LL_40G, /**< applies to 40G mode using the 40G low latency (LL) MAC */ AL_ETH_MAC_MODE_KR_LL_25G, /**< applies to 25G mode using the 10/25G low latency (LL) MAC */ - AL_ETH_MAC_MODE_XLG_LL_50G /**< applies to 50G mode using the 40/50G low latency (LL) MAC */ + AL_ETH_MAC_MODE_XLG_LL_50G, /**< applies to 50G mode using the 40/50G low latency (LL) MAC */ + AL_ETH_MAC_MODE_XLG_LL_25G /**< applies to 25G mode using the 40/50G low latency (LL) MAC */ }; struct al_eth_capabilities { @@ -338,11 +339,11 @@ struct al_eth_meta_data{ /* Packet Rx flags when adding buffer to receive queue */ /**< - * VMID to be assigned to the packet descriptors - * Requires VMID in descriptor to be enabled for the specific UDMA + * Target-ID to be assigned to the packet descriptors + * Requires Target-ID in descriptor to be enabled for the specific UDMA * queue. */ -#define AL_ETH_RX_FLAGS_VMID_MASK AL_FIELD_MASK(15, 0) +#define AL_ETH_RX_FLAGS_TGTID_MASK AL_FIELD_MASK(15, 0) #define AL_ETH_RX_FLAGS_NO_SNOOP AL_M2S_DESC_NO_SNOOP_H #define AL_ETH_RX_FLAGS_INT AL_M2S_DESC_INT_EN #define AL_ETH_RX_FLAGS_DUAL_BUF AL_BIT(31) @@ -382,11 +383,11 @@ struct al_eth_pkt{ enum AL_ETH_PROTO_ID outer_l3_proto_idx; /**< for tunneling mode */ /**< - * VMID to be assigned to the packet descriptors - * Requires VMID in descriptor to be enabled for the specific UDMA + * Target-ID to be assigned to the packet descriptors + * Requires Target-ID in descriptor to be enabled for the specific UDMA * queue. */ - uint16_t vmid; + uint16_t tgtid; uint32_t rx_header_len; /**< header buffer length of rx packet, not used */ struct al_eth_meta_data *meta; /**< if null, then no meta added */ @@ -434,6 +435,7 @@ struct al_hal_eth_adapter{ enum al_eth_mdio_type mdio_type; /**< mdio protocol type */ al_bool shared_mdio_if; /**< when AL_TRUE, the mdio interface is shared with other controllers.*/ uint8_t curr_lt_unit; + uint8_t serdes_lane; #ifdef AL_ETH_EX struct al_eth_ex_state ex_state; #endif @@ -452,6 +454,8 @@ struct al_eth_adapter_params{ * can be null if the function is virtual */ char *name; /**< the upper layer must keep the string area */ + + uint8_t serdes_lane; /**< serdes lane (relevant to 25G macs only) */ }; /* adapter management */ @@ -563,6 +567,39 @@ int al_eth_mac_stop(struct al_hal_eth_adapter *adapter); */ int al_eth_mac_start(struct al_hal_eth_adapter *adapter); +/** + * Perform gearbox reset for tx lanes And/Or Rx lanes. + * applicable only when the controller is connected to srds25G. + * This reset should be performed after each operation that changes the clocks + * (such as serdes reset, mac stop, etc.) + * + * @param adapter pointer to the private structure. + * @param tx_reset assert and de-assert reset for tx lanes + * @param rx_reset assert and de-assert reset for rx lanes + */ +void al_eth_gearbox_reset(struct al_hal_eth_adapter *adapter, al_bool tx_reset, al_bool rx_reset); + +/** + * Enable / Disable forward error correction (FEC) + * + * @param adapter pointer to the private structure. + * @param enable true to enable FEC. false to disable FEC. + * + * @return 0 on success. negative error on failure. + */ +int al_eth_fec_enable(struct al_hal_eth_adapter *adapter, al_bool enable); + +/** + * Get forward error correction (FEC) statistics + * + * @param adapter pointer to the private structure. + * @param corrected number of bits been corrected by the FEC + * @param uncorrectable number of bits that FEC couldn't correct. + * + * @return 0 on success. negative error on failure. + */ +int al_eth_fec_stats_get(struct al_hal_eth_adapter *adapter, + uint32_t *corrected, uint32_t *uncorrectable); /** * get the adapter capabilities (speed, duplex,..) @@ -1333,6 +1370,7 @@ struct al_eth_eee_params{ uint32_t tx_eee_timer; /**< time in cycles the interface delays prior to entering eee state */ uint32_t min_interval; /**< minimum interval in cycles between two eee states */ uint32_t stop_cnt; /**< time in cycles to stop Tx mac i/f after getting out of eee state */ + al_bool fast_wake; /**< fast_wake is only applicable to 40/50G, otherwise the mode is deep_sleep */ }; /** @@ -1609,6 +1647,8 @@ int al_eth_pth_pulse_out_config(struct al_hal_eth_adapter *adapter, /* link */ struct al_eth_link_status { al_bool link_up; + al_bool local_fault; + al_bool remote_fault; }; /** @@ -1622,7 +1662,19 @@ struct al_eth_link_status { * * @return return 0 on success. otherwise on failure. */ -int al_eth_link_status_get(struct al_hal_eth_adapter *adapter, struct al_eth_link_status *status); +int al_eth_link_status_get(struct al_hal_eth_adapter *adapter, + struct al_eth_link_status *status); + +/** + * clear link status + * + * this function clear latched status of the link. + * + * @param adapter pointer to the private structure. + * + * @return return 0 if supported. + */ +int al_eth_link_status_clear(struct al_hal_eth_adapter *adapter); /** * Set LEDs to represent link status. @@ -1929,6 +1981,7 @@ enum al_eth_board_media_type { AL_ETH_BOARD_MEDIA_TYPE_AUTO_DETECT_AUTO_SPEED = 5, AL_ETH_BOARD_MEDIA_TYPE_SGMII_2_5G = 6, AL_ETH_BOARD_MEDIA_TYPE_NBASE_T = 7, + AL_ETH_BOARD_MEDIA_TYPE_25G = 8, }; enum al_eth_board_mdio_freq { @@ -1961,13 +2014,18 @@ enum al_eth_retimer_channel { AL_ETH_RETIMER_CHANNEL_B = 1, AL_ETH_RETIMER_CHANNEL_C = 2, AL_ETH_RETIMER_CHANNEL_D = 3, - AL_ETH_RETIMER_CHANNEL_MAX = 4 + AL_ETH_RETIMER_CHANNEL_E = 4, + AL_ETH_RETIMER_CHANNEL_F = 5, + AL_ETH_RETIMER_CHANNEL_G = 6, + AL_ETH_RETIMER_CHANNEL_H = 7, + AL_ETH_RETIMER_CHANNEL_MAX = 8 }; /* list of supported retimers */ enum al_eth_retimer_type { AL_ETH_RETIMER_BR_210 = 0, AL_ETH_RETIMER_BR_410 = 1, + AL_ETH_RETIMER_DS_25 = 2, AL_ETH_RETIMER_TYPE_MAX = 4, }; @@ -1999,10 +2057,12 @@ struct al_eth_board_params { al_bool retimer_exist; /**< retimer is exist on the board */ uint8_t retimer_bus_id; /**< in what i2c bus the retimer is on */ uint8_t retimer_i2c_addr; /**< i2c address of the retimer */ - enum al_eth_retimer_channel retimer_channel; /**< what channel connected to this port */ + enum al_eth_retimer_channel retimer_channel; /**< what channel connected to this port (Rx) */ al_bool dac; /**< assume direct attached cable is connected if auto detect is off or failed */ uint8_t dac_len; /**< assume this cable length if auto detect is off or failed */ enum al_eth_retimer_type retimer_type; /**< the type of the specific retimer */ + enum al_eth_retimer_channel retimer_tx_channel; /**< what channel connected to this port (Tx) */ + uint8_t gpio_sfp_present; /**< gpio number of sfp present for this port. 0 if not exist */ }; /** diff --git a/eth/al_hal_eth_mac_regs.h b/eth/al_hal_eth_mac_regs.h index a2dc745ffde..3218e5c4cac 100644 --- a/eth/al_hal_eth_mac_regs.h +++ b/eth/al_hal_eth_mac_regs.h @@ -54,6 +54,42 @@ extern "C" { * Unit Registers */ +struct al_eth_mac_1g_stats { + uint32_t reserved1[2]; + uint32_t aFramesTransmittedOK; /* 0x68 */ + uint32_t aFramesReceivedOK; /* 0x6c */ + uint32_t aFrameCheckSequenceErrors; /* 0x70 */ + uint32_t aAlignmentErrors; /* 0x74 */ + uint32_t aOctetsTransmittedOK; /* 0x78 */ + uint32_t aOctetsReceivedOK; /* 0x7c */ + uint32_t aPAUSEMACCtrlFramesTransmitted; /* 0x80 */ + uint32_t aPAUSEMACCtrlFramesReceived; /* 0x84 */ + uint32_t ifInErrors ; /* 0x88 */ + uint32_t ifOutErrors; /* 0x8c */ + uint32_t ifInUcastPkts; /* 0x90 */ + uint32_t ifInMulticastPkts; /* 0x94 */ + uint32_t ifInBroadcastPkts; /* 0x98 */ + uint32_t reserved2; + uint32_t ifOutUcastPkts; /* 0xa0 */ + uint32_t ifOutMulticastPkts; /* 0xa4 */ + uint32_t ifOutBroadcastPkts; /* 0xa8 */ + uint32_t etherStatsDropEvents; /* 0xac */ + uint32_t etherStatsOctets; /* 0xb0 */ + uint32_t etherStatsPkts; /* 0xb4 */ + uint32_t etherStatsUndersizePkts; /* 0xb8 */ + uint32_t etherStatsOversizePkts; /* 0xbc */ + uint32_t etherStatsPkts64Octets; /* 0xc0 */ + uint32_t etherStatsPkts65to127Octets; /* 0xc4 */ + uint32_t etherStatsPkts128to255Octets; /* 0xc8 */ + uint32_t etherStatsPkts256to511Octets; /* 0xcc */ + uint32_t etherStatsPkts512to1023Octets; /* 0xd0 */ + uint32_t etherStatsPkts1024to1518Octets; /* 0xd4 */ + uint32_t etherStatsPkts1519toX; /* 0xd8 */ + uint32_t etherStatsJabbers; /* 0xdc */ + uint32_t etherStatsFragments; /* 0xe0 */ + uint32_t reserved3[71]; +}; + struct al_eth_mac_1g { /* [0x0] */ uint32_t rev; @@ -82,12 +118,202 @@ struct al_eth_mac_1g { uint32_t reg_stat; uint32_t tx_ipg_len; /* [0x60] */ - uint32_t Reserved1[104]; + struct al_eth_mac_1g_stats stats; /* [0x200] */ uint32_t phy_regs_base; uint32_t Reserved2[127]; }; +struct al_eth_mac_10g_stats_v2 { + uint32_t aFramesTransmittedOK; /* 0x80 */ + uint32_t reserved1; + uint32_t aFramesReceivedOK; /* 0x88 */ + uint32_t reserved2; + uint32_t aFrameCheckSequenceErrors; /* 0x90 */ + uint32_t reserved3; + uint32_t aAlignmentErrors; /* 0x98 */ + uint32_t reserved4; + uint32_t aPAUSEMACCtrlFramesTransmitted; /* 0xa0 */ + uint32_t reserved5; + uint32_t aPAUSEMACCtrlFramesReceived; /* 0xa8 */ + uint32_t reserved6; + uint32_t aFrameTooLongErrors; /* 0xb0 */ + uint32_t reserved7; + uint32_t aInRangeLengthErrors; /* 0xb8 */ + uint32_t reserved8; + uint32_t VLANTransmittedOK; /* 0xc0 */ + uint32_t reserved9; + uint32_t VLANReceivedOK; /* 0xc8 */ + uint32_t reserved10; + uint32_t ifOutOctetsL; /* 0xd0 */ + uint32_t ifOutOctetsH; /* 0xd4 */ + uint32_t ifInOctetsL; /* 0xd8 */ + uint32_t ifInOctetsH; /* 0xdc */ + uint32_t ifInUcastPkts; /* 0xe0 */ + uint32_t reserved11; + uint32_t ifInMulticastPkts; /* 0xe8 */ + uint32_t reserved12; + uint32_t ifInBroadcastPkts; /* 0xf0 */ + uint32_t reserved13; + uint32_t ifOutErrors; /* 0xf8 */ + uint32_t reserved14[3]; + uint32_t ifOutUcastPkts; /* 0x108 */ + uint32_t reserved15; + uint32_t ifOutMulticastPkts; /* 0x110 */ + uint32_t reserved16; + uint32_t ifOutBroadcastPkts; /* 0x118 */ + uint32_t reserved17; + uint32_t etherStatsDropEvents; /* 0x120 */ + uint32_t reserved18; + uint32_t etherStatsOctets; /* 0x128 */ + uint32_t reserved19; + uint32_t etherStatsPkts; /* 0x130 */ + uint32_t reserved20; + uint32_t etherStatsUndersizePkts; /* 0x138 */ + uint32_t reserved21; + uint32_t etherStatsPkts64Octets; /* 0x140 */ + uint32_t reserved22; + uint32_t etherStatsPkts65to127Octets; /* 0x148 */ + uint32_t reserved23; + uint32_t etherStatsPkts128to255Octets; /* 0x150 */ + uint32_t reserved24; + uint32_t etherStatsPkts256to511Octets; /* 0x158 */ + uint32_t reserved25; + uint32_t etherStatsPkts512to1023Octets; /* 0x160 */ + uint32_t reserved26; + uint32_t etherStatsPkts1024to1518Octets; /* 0x168 */ + uint32_t reserved27; + uint32_t etherStatsPkts1519toX; /* 0x170 */ + uint32_t reserved28; + uint32_t etherStatsOversizePkts; /* 0x178 */ + uint32_t reserved29; + uint32_t etherStatsJabbers; /* 0x180 */ + uint32_t reserved30; + uint32_t etherStatsFragments; /* 0x188 */ + uint32_t reserved31; + uint32_t ifInErrors; /* 0x190 */ + uint32_t reserved32[91]; +}; + +struct al_eth_mac_10g_stats_v3_rx { + uint32_t etherStatsOctets; /* 0x00 */ + uint32_t reserved2; + uint32_t ifOctetsL; /* 0x08 */ + uint32_t ifOctetsH; /* 0x0c */ + uint32_t aAlignmentErrors; /* 0x10 */ + uint32_t reserved4; + uint32_t aPAUSEMACCtrlFrames; /* 0x18 */ + uint32_t reserved5; + uint32_t FramesOK; /* 0x20 */ + uint32_t reserved6; + uint32_t CRCErrors; /* 0x28 */ + uint32_t reserved7; + uint32_t VLANOK; /* 0x30 */ + uint32_t reserved8; + uint32_t ifInErrors; /* 0x38 */ + uint32_t reserved9; + uint32_t ifInUcastPkts; /* 0x40 */ + uint32_t reserved10; + uint32_t ifInMulticastPkts; /* 0x48 */ + uint32_t reserved11; + uint32_t ifInBroadcastPkts; /* 0x50 */ + uint32_t reserved12; + uint32_t etherStatsDropEvents; /* 0x58 */ + uint32_t reserved13; + uint32_t etherStatsPkts; /* 0x60 */ + uint32_t reserved14; + uint32_t etherStatsUndersizePkts; /* 0x68 */ + uint32_t reserved15; + uint32_t etherStatsPkts64Octets; /* 0x70 */ + uint32_t reserved16; + uint32_t etherStatsPkts65to127Octets; /* 0x78 */ + uint32_t reserved17; + uint32_t etherStatsPkts128to255Octets; /* 0x80 */ + uint32_t reserved18; + uint32_t etherStatsPkts256to511Octets; /* 0x88 */ + uint32_t reserved19; + uint32_t etherStatsPkts512to1023Octets; /* 0x90 */ + uint32_t reserved20; + uint32_t etherStatsPkts1024to1518Octets; /* 0x98 */ + uint32_t reserved21; + uint32_t etherStatsPkts1519toMax; /* 0xa0 */ + uint32_t reserved22; + uint32_t etherStatsOversizePkts; /* 0xa8 */ + uint32_t reserved23; + uint32_t etherStatsJabbers; /* 0xb0 */ + uint32_t reserved24; + uint32_t etherStatsFragments; /* 0xb8 */ + uint32_t reserved25; + uint32_t aMACControlFramesReceived; /* 0xc0 */ + uint32_t reserved26; + uint32_t aFrameTooLong; /* 0xc8 */ + uint32_t reserved27; + uint32_t aInRangeLengthErrors; /* 0xd0 */ + uint32_t reserved28; + uint32_t reserved29[10]; +}; + +struct al_eth_mac_10g_stats_v3_tx { + uint32_t etherStatsOctets; /* 0x00 */ + uint32_t reserved30; + uint32_t ifOctetsL; /* 0x08 */ + uint32_t ifOctetsH; /* 0x0c */ + uint32_t aAlignmentErrors; /* 0x10 */ + uint32_t reserved32; + uint32_t aPAUSEMACCtrlFrames; /* 0x18 */ + uint32_t reserved33; + uint32_t FramesOK; /* 0x20 */ + uint32_t reserved34; + uint32_t CRCErrors; /* 0x28 */ + uint32_t reserved35; + uint32_t VLANOK; /* 0x30 */ + uint32_t reserved36; + uint32_t ifOutErrors; /* 0x38 */ + uint32_t reserved37; + uint32_t ifUcastPkts; /* 0x40 */ + uint32_t reserved38; + uint32_t ifMulticastPkts; /* 0x48 */ + uint32_t reserved39; + uint32_t ifBroadcastPkts; /* 0x50 */ + uint32_t reserved40; + uint32_t etherStatsDropEvents; /* 0x58 */ + uint32_t reserved41; + uint32_t etherStatsPkts; /* 0x60 */ + uint32_t reserved42; + uint32_t etherStatsUndersizePkts; /* 0x68 */ + uint32_t reserved43; + uint32_t etherStatsPkts64Octets; /* 0x70 */ + uint32_t reserved44; + uint32_t etherStatsPkts65to127Octets; /* 0x78 */ + uint32_t reserved45; + uint32_t etherStatsPkts128to255Octets; /* 0x80 */ + uint32_t reserved46; + uint32_t etherStatsPkts256to511Octets; /* 0x88 */ + uint32_t reserved47; + uint32_t etherStatsPkts512to1023Octets; /* 0x90 */ + uint32_t reserved48; + uint32_t etherStatsPkts1024to1518Octets; /* 0x98 */ + uint32_t reserved49; + uint32_t etherStatsPkts1519toTX_MTU; /* 0xa0 */ + uint32_t reserved50; + uint32_t reserved51[4]; + uint32_t aMACControlFrames; /* 0xc0 */ + uint32_t reserved52[15]; +}; + +struct al_eth_mac_10g_stats_v3 { + uint32_t reserved1[32]; + /* 0x100 */ + struct al_eth_mac_10g_stats_v3_rx rx; + /* 0x200 */ + struct al_eth_mac_10g_stats_v3_tx tx; +}; + +union al_eth_mac_10g_stats { + struct al_eth_mac_10g_stats_v2 v2; + struct al_eth_mac_10g_stats_v3 v3; +}; + struct al_eth_mac_10g { /* [0x0] */ uint32_t rev; @@ -131,8 +357,7 @@ struct al_eth_mac_10g { uint32_t Reserved2; uint32_t ts_timestamp; /* [0x80] */ - - uint32_t Reserved3[160]; + union al_eth_mac_10g_stats stats; /* [0x300] */ uint32_t control; @@ -442,16 +667,45 @@ struct al_eth_mac_regs { * Registers Fields */ -/**** control register (1G mac) ****/ +/**** 1G MAC registers ****/ +/* cmd_cfg */ +#define ETH_1G_MAC_CMD_CFG_TX_ENA (1 << 0) +#define ETH_1G_MAC_CMD_CFG_RX_ENA (1 << 1) /* enable Half Duplex */ -#define AL_ETH_1G_MAC_CTRL_HD_EN (1 << 10) +#define ETH_1G_MAC_CMD_CFG_HD_EN (1 << 10) /* enable 1G speed */ -#define AL_ETH_1G_MAC_CTRL_1G_SPD (1 << 3) +#define ETH_1G_MAC_CMD_CFG_1G_SPD (1 << 3) /* enable 10M speed */ -#define AL_ETH_1G_MAC_CTRL_10M_SPD (1 << 25) +#define ETH_1G_MAC_CMD_CFG_10M_SPD (1 << 25) +/**** 10G MAC registers ****/ +/* cmd_cfg */ +#define ETH_10G_MAC_CMD_CFG_TX_ENA (1 << 0) +#define ETH_10G_MAC_CMD_CFG_RX_ENA (1 << 1) +#define ETH_10G_MAC_CMD_CFG_WAN_MODE (1 << 3) +#define ETH_10G_MAC_CMD_CFG_PROMIS_EN (1 << 4) +#define ETH_10G_MAC_CMD_CFG_PAD_EN (1 << 5) +#define ETH_10G_MAC_CMD_CFG_CRC_FWD (1 << 6) +#define ETH_10G_MAC_CMD_CFG_PAUSE_FWD (1 << 7) +#define ETH_10G_MAC_CMD_CFG_PAUSE_IGNORE (1 << 8) +#define ETH_10G_MAC_CMD_CFG_TX_ADDR_INS (1 << 9) +#define ETH_10G_MAC_CMD_CFG_LOOP_ENA (1 << 10) +#define ETH_10G_MAC_CMD_CFG_TX_PAD_EN (1 << 11) +#define ETH_10G_MAC_CMD_CFG_SW_RESET (1 << 12) +#define ETH_10G_MAC_CMD_CFG_CNTL_FRM_ENA (1 << 13) +#define ETH_10G_MAC_CMD_CFG_RX_ERR_DISC (1 << 14) +#define ETH_10G_MAC_CMD_CFG_PHY_TXENA (1 << 15) +#define ETH_10G_MAC_CMD_CFG_FORCE_SEND_IDLE (1 << 16) +#define ETH_10G_MAC_CMD_CFG_NO_LGTH_CHECK (1 << 17) +#define ETH_10G_MAC_CMD_CFG_COL_CNT_EXT (1 << 18) +#define ETH_10G_MAC_CMD_CFG_PFC_MODE (1 << 19) +#define ETH_10G_MAC_CMD_CFG_PAUSE_PFC_COMP (1 << 20) +#define ETH_10G_MAC_CMD_CFG_SFD_ANY (1 << 21) +#define ETH_10G_MAC_CMD_CFG_TX_FLUSH (1 << 22) +#define ETH_10G_MAC_CMD_CFG_TX_LOWP_ENA (1 << 23) +#define ETH_10G_MAC_CMD_CFG_REG_LOWP_RXEMPTY (1 << 24) +#define ETH_10G_MAC_CMD_CFG_SHORT_DISCARD (1 << 25) -/**** 10G MAC register ****/ /* mdio_cfg_status */ #define ETH_10G_MAC_MDIO_CFG_HOLD_TIME_MASK 0x0000001c #define ETH_10G_MAC_MDIO_CFG_HOLD_TIME_SHIFT 2 @@ -465,6 +719,27 @@ struct al_eth_mac_regs { #define ETH_10G_MAC_MDIO_CFG_HOLD_TIME_13_CLK 6 #define ETH_10G_MAC_MDIO_CFG_HOLD_TIME_15_CLK 7 +/* control */ +#define ETH_10G_MAC_CONTROL_AN_EN_MASK 0x00001000 +#define ETH_10G_MAC_CONTROL_AN_EN_SHIFT 12 + +/* if_mode */ +#define ETH_10G_MAC_IF_MODE_SGMII_EN_MASK 0x00000001 +#define ETH_10G_MAC_IF_MODE_SGMII_EN_SHIFT 0 +#define ETH_10G_MAC_IF_MODE_SGMII_AN_MASK 0x00000002 +#define ETH_10G_MAC_IF_MODE_SGMII_AN_SHIFT 1 +#define ETH_10G_MAC_IF_MODE_SGMII_SPEED_MASK 0x0000000c +#define ETH_10G_MAC_IF_MODE_SGMII_SPEED_SHIFT 2 +#define ETH_10G_MAC_IF_MODE_SGMII_DUPLEX_MASK 0x00000010 +#define ETH_10G_MAC_IF_MODE_SGMII_DUPLEX_SHIFT 4 + +#define ETH_10G_MAC_IF_MODE_SGMII_SPEED_10M 0 +#define ETH_10G_MAC_IF_MODE_SGMII_SPEED_100M 1 +#define ETH_10G_MAC_IF_MODE_SGMII_SPEED_1G 2 + +#define ETH_10G_MAC_IF_MODE_SGMII_DUPLEX_FULL 0 +#define ETH_10G_MAC_IF_MODE_SGMII_DUPLEX_HALF 1 + /**** version register ****/ /* Revision number (Minor) */ #define ETH_MAC_GEN_VERSION_RELEASE_NUM_MINOR_MASK 0x000000FF @@ -1794,9 +2069,13 @@ struct al_eth_mac_regs { /*** PCS Core registers addresses ***/ /* 40g control/status */ #define ETH_MAC_GEN_V3_PCS_40G_CONTROL_STATUS_ADDR 0x00000000 +/* 40g EEE control and capability */ +#define ETH_MAC_GEN_V3_PCS_40G_EEE_CONTROL_ADDR 0x00000028 /* 10g control_1 */ #define ETH_MAC_KR_PCS_CONTROL_1_ADDR 0x00000000 +#define ETH_MAC_KR_PCS_BASE_R_STATUS2 0x00000021 + #define ETH_MAC_KR_AN_MILLISECONDS_COUNTER_ADDR 0x00008000 #define ETH_MAC_AN_LT_MILLISECONDS_COUNTER_ADDR 0x00000020 diff --git a/eth/al_hal_eth_main.c b/eth/al_hal_eth_main.c index b3a5c70b1f0..d7913af2c93 100644 --- a/eth/al_hal_eth_main.c +++ b/eth/al_hal_eth_main.c @@ -43,18 +43,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "al_hal_eth.h" -#include -#include -#include +#include "al_hal_udma_iofic.h" +#include "al_hal_udma_config.h" #include "al_hal_eth_ec_regs.h" #include "al_hal_eth_mac_regs.h" -#include +#include "al_hal_unit_adapter_regs.h" #ifdef AL_ETH_EX #include "al_hal_eth_ex_internal.h" #endif /* Number of xfi_txclk cycles that accumulate into 100ns */ -#define ETH_MAC_KR_PCS_CFG_EEE_TIMER_VAL 52 +#define ETH_MAC_KR_10_PCS_CFG_EEE_TIMER_VAL 52 +#define ETH_MAC_KR_25_PCS_CFG_EEE_TIMER_VAL 80 +#define ETH_MAC_XLG_40_PCS_CFG_EEE_TIMER_VAL 63 +#define ETH_MAC_XLG_50_PCS_CFG_EEE_TIMER_VAL 85 #define AL_ETH_TX_PKT_UDMA_FLAGS (AL_ETH_TX_FLAGS_NO_SNOOP | \ AL_ETH_TX_FLAGS_INT) @@ -335,6 +337,8 @@ static const char *al_eth_mac_mode_str(enum al_eth_mac_mode mode) return "40G_LL"; case AL_ETH_MAC_MODE_XLG_LL_50G: return "50G_LL"; + case AL_ETH_MAC_MODE_XLG_LL_25G: + return "25G_LL"; default: return "N/A"; } @@ -572,8 +576,10 @@ int al_eth_adapter_init(struct al_hal_eth_adapter *adapter, struct al_eth_adapte adapter->mac_regs_base = (struct al_eth_mac_regs __iomem*)params->mac_regs_base; adapter->unit_regs = (struct unit_regs __iomem *)params->udma_regs_base; adapter->enable_rx_parser = params->enable_rx_parser; - adapter->ec_ints_base = (void __iomem *)((uint32_t)adapter->ec_regs_base + 0x1c00); - adapter->mac_ints_base = (void __iomem *)((uint32_t)adapter->mac_regs_base + 0x800); + adapter->serdes_lane = params->serdes_lane; + adapter->ec_ints_base = (uint8_t __iomem *)adapter->ec_regs_base + 0x1c00; + adapter->mac_ints_base = (struct interrupt_controller_ctrl __iomem *) + ((uint8_t __iomem *)adapter->mac_regs_base + 0x800); /* initialize Tx udma */ udma_params.udma_regs_base = adapter->unit_regs; @@ -963,7 +969,7 @@ int al_eth_mac_config(struct al_hal_eth_adapter *adapter, enum al_eth_mac_mode m if (adapter->rev_id > AL_ETH_REV_ID_2) { /* configure and enable the ASYNC FIFO between the MACs and the EC */ /* TX min packet size */ - al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037); + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000010); /* TX max packet size */ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800); /* TX input bus configuration */ @@ -1060,7 +1066,7 @@ int al_eth_mac_config(struct al_hal_eth_adapter *adapter, enum al_eth_mac_mode m if (adapter->rev_id > AL_ETH_REV_ID_2) { /* configure and enable the ASYNC FIFO between the MACs and the EC */ /* TX min packet size */ - al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037); + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000010); /* TX max packet size */ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800); /* TX input bus configuration */ @@ -1110,7 +1116,7 @@ int al_eth_mac_config(struct al_hal_eth_adapter *adapter, enum al_eth_mac_mode m if (adapter->rev_id > AL_ETH_REV_ID_2) { /* configure and enable the ASYNC FIFO between the MACs and the EC */ /* TX min packet size */ - al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037); + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000010); /* TX max packet size */ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800); /* TX input bus configuration */ @@ -1162,11 +1168,12 @@ int al_eth_mac_config(struct al_hal_eth_adapter *adapter, enum al_eth_mac_mode m case AL_ETH_MAC_MODE_KR_LL_25G: /* select 25G SERDES lane 0 and lane 1 */ - al_reg_write32(&adapter->mac_regs_base->gen_v3.ext_serdes_ctrl, 0x03821101); + al_reg_write32(&adapter->mac_regs_base->gen_v3.ext_serdes_ctrl, 0x0002110f); + if (adapter->rev_id > AL_ETH_REV_ID_2) { /* configure and enable the ASYNC FIFO between the MACs and the EC */ /* TX min packet size */ - al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037); + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000010); /* TX max packet size */ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800); /* TX input bus configuration */ @@ -1205,15 +1212,29 @@ int al_eth_mac_config(struct al_hal_eth_adapter *adapter, enum al_eth_mac_mode m /* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_out, 0x00000401); */ al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_64_32, 0x00000401); /* al_reg_write32(&adapter->mac_regs_base->gen.mac_res_1_in, 0x00000401); */ - al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, + + if (adapter->serdes_lane == 0) + al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x00073910); - al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x10003210); + else + al_reg_write32(&adapter->mac_regs_base->gen.mux_sel, 0x00077910); + + if (adapter->serdes_lane == 0) + al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x10003210); + else + al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x10000101); + al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x000004f0); al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x00000401); al_reg_write32_masked(&adapter->mac_regs_base->gen.led_cfg, ETH_MAC_GEN_LED_CFG_SEL_MASK, ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG); + + if (adapter->serdes_lane == 1) + al_reg_write32(&adapter->mac_regs_base->gen.los_sel, 0x101); + + break; case AL_ETH_MAC_MODE_10G_SGMII: @@ -1250,7 +1271,7 @@ int al_eth_mac_config(struct al_hal_eth_adapter *adapter, enum al_eth_mac_mode m case AL_ETH_MAC_MODE_XLG_LL_40G: /* configure and enable the ASYNC FIFO between the MACs and the EC */ /* TX min packet size */ - al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037); + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000010); /* TX max packet size */ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800); /* TX input bus configuration */ @@ -1318,11 +1339,102 @@ int al_eth_mac_config(struct al_hal_eth_adapter *adapter, enum al_eth_mac_mode m ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG); break; + case AL_ETH_MAC_MODE_XLG_LL_25G: + /* xgmii_mode: 0=xlgmii, 1=xgmii */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_addr, 0x0080); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_data, 0x00000001); + + /* configure and enable the ASYNC FIFO between the MACs and the EC */ + /* TX min packet size */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000010); + /* TX max packet size */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800); + /* TX input bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_3, 0x00000080); + /* TX output bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_4, 0x00010040); + /* TX Valid/ready configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_5, 0x00000023); + /* RX min packet size */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_1, 0x00000040); */ + /* RX max packet size */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_2, 0x00002800); */ + /* RX input bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_3, 0x00010040); + /* RX output bus configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_4, 0x00000080); + /* RX Valid/ready configuration */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.rx_afifo_cfg_5, 0x00000112); + /* V3 additional MAC selection */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_sel, 0x00000010); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_cfg, 0x00000000); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_10g_ll_ctrl, 0x00000000); + al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_10g_ll_cfg, 0x00000000); + /* ASYNC FIFO ENABLE */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.afifo_ctrl, 0x00003333); + + /* cmd_cfg */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_addr, 0x00000008); + al_reg_write32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_data, 0x01022810); + /* speed_ability //Read-Only */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_addr, 0x00000008); */ + /* 40G capable */ + /* al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_data, 0x00000002); */ + + /* select the 25G serdes for lanes 0/1 */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.ext_serdes_ctrl, 0x0002110f); + /* configure the PCS to work with 2 lanes */ + /* configure which two of the 4 PCS Lanes (VL) are combined to one RXLAUI lane */ + /* use VL 0-2 for RXLAUI lane 0, use VL 1-3 for RXLAUI lane 1 */ + al_eth_40g_pcs_reg_write(adapter, 0x00010008, 0x0d80); + /* configure the PCS to work 32 bit interface */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_cfg, 0x00440000); + + /* disable MLD and move to clause 49 PCS: */ + al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_addr, 0xE); + al_reg_write32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_data, 0); + +#ifdef AL_HAL_ETH_FAST_AN + al_eth_40g_pcs_reg_write(adapter, 0x00010004, 1023); + al_eth_40g_pcs_reg_write(adapter, 0x00000000, 0xA04c); + al_eth_40g_pcs_reg_write(adapter, 0x00000000, 0x204c); +#endif + + /* XAUI MAC control register */ + if (adapter->serdes_lane == 0) + al_reg_write32_masked(&adapter->mac_regs_base->gen.mux_sel, + ~ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, 0x06883910); + else + al_reg_write32(&adapter->mac_regs_base->gen.mux_sel, 0x06803950); + + al_reg_write32(&adapter->mac_regs_base->gen.sd_fifo_ctrl, 0x0000040f); + + /* XAUI MAC control register */ + al_reg_write32(&adapter->mac_regs_base->gen.cfg, 0x00000005); + /* RXAUI MAC control register */ + al_reg_write32(&adapter->mac_regs_base->gen.rxaui_cfg, 0x00000007); + al_reg_write32(&adapter->mac_regs_base->gen.sd_cfg, 0x000001F1); + al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_32_64, 0x00000401); + al_reg_write32(&adapter->mac_regs_base->gen.xgmii_dfifo_64_32, 0x00000401); + if (adapter->serdes_lane == 0) + al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x10003210); + else + al_reg_write32(&adapter->mac_regs_base->gen.clk_cfg, 0x10000101); + + al_reg_write32_masked(&adapter->mac_regs_base->gen.led_cfg, + ETH_MAC_GEN_LED_CFG_SEL_MASK, + ETH_MAC_GEN_LED_CFG_SEL_DEFAULT_REG); + + if (adapter->serdes_lane == 1) + al_reg_write32(&adapter->mac_regs_base->gen.los_sel, 0x101); + + break; + case AL_ETH_MAC_MODE_XLG_LL_50G: /* configure and enable the ASYNC FIFO between the MACs and the EC */ /* TX min packet size */ - al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000037); + al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_1, 0x00000010); /* TX max packet size */ al_reg_write32(&adapter->mac_regs_base->gen_v3.tx_afifo_cfg_2, 0x00002800); /* TX input bus configuration */ @@ -1414,19 +1526,26 @@ int al_eth_mac_start(struct al_hal_eth_adapter *adapter) { if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) { /* 1G MAC control register */ - al_reg_write32_masked(&adapter->mac_regs_base->mac_1g.cmd_cfg, 0x3, 0x3); + al_reg_write32_masked(&adapter->mac_regs_base->mac_1g.cmd_cfg, + ETH_1G_MAC_CMD_CFG_TX_ENA | ETH_1G_MAC_CMD_CFG_RX_ENA, + ETH_1G_MAC_CMD_CFG_TX_ENA | ETH_1G_MAC_CMD_CFG_RX_ENA); } else if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) { /* 10G MAC control register */ - al_reg_write32_masked(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x3, 0x3); + al_reg_write32_masked(&adapter->mac_regs_base->mac_10g.cmd_cfg, + ETH_10G_MAC_CMD_CFG_TX_ENA | ETH_10G_MAC_CMD_CFG_RX_ENA, + ETH_10G_MAC_CMD_CFG_TX_ENA | ETH_10G_MAC_CMD_CFG_RX_ENA); } else { uint32_t cmd_cfg; - cmd_cfg = al_eth_40g_mac_reg_read(adapter, ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR); + cmd_cfg = al_eth_40g_mac_reg_read(adapter, + ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR); cmd_cfg |= (ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_TX_ENA | ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_RX_ENA); - al_eth_40g_mac_reg_write(adapter, ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR, cmd_cfg); + al_eth_40g_mac_reg_write(adapter, + ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR, + cmd_cfg); } return 0; @@ -1437,16 +1556,91 @@ int al_eth_mac_stop(struct al_hal_eth_adapter *adapter) { if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) /* 1G MAC control register */ - al_reg_write32(&adapter->mac_regs_base->mac_1g.cmd_cfg, 0x0); + al_reg_write32_masked(&adapter->mac_regs_base->mac_1g.cmd_cfg, + ETH_1G_MAC_CMD_CFG_TX_ENA | ETH_1G_MAC_CMD_CFG_RX_ENA, + 0); else if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) /* 10G MAC control register */ - al_reg_write32(&adapter->mac_regs_base->mac_10g.cmd_cfg, 0x0); - else - al_eth_40g_mac_reg_write(adapter, ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR, 0); + al_reg_write32_masked(&adapter->mac_regs_base->mac_10g.cmd_cfg, + ETH_10G_MAC_CMD_CFG_TX_ENA | ETH_10G_MAC_CMD_CFG_RX_ENA, + 0); + else { + uint32_t cmd_cfg; + + cmd_cfg = al_eth_40g_mac_reg_read(adapter, + ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR); + + cmd_cfg &= ~(ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_TX_ENA | + ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_RX_ENA); + + al_eth_40g_mac_reg_write(adapter, + ETH_MAC_GEN_V3_MAC_40G_COMMAND_CONFIG_ADDR, + cmd_cfg); + } return 0; } +void al_eth_gearbox_reset(struct al_hal_eth_adapter *adapter, al_bool tx_reset, al_bool rx_reset) +{ + uint32_t reg, orig_val; + + /* Gearbox is exist only from revision 3 */ + al_assert(adapter->rev_id > AL_ETH_REV_ID_2); + + orig_val = al_reg_read32(&adapter->mac_regs_base->gen_v3.ext_serdes_ctrl); + reg = orig_val; + + if (tx_reset) { + reg |= (ETH_MAC_GEN_V3_EXT_SERDES_CTRL_LANE_0_TX_25_GS_SW_RESET | + ETH_MAC_GEN_V3_EXT_SERDES_CTRL_LANE_1_TX_25_GS_SW_RESET); + } + + if (rx_reset) { + reg |= (ETH_MAC_GEN_V3_EXT_SERDES_CTRL_LANE_0_RX_25_GS_SW_RESET | + ETH_MAC_GEN_V3_EXT_SERDES_CTRL_LANE_1_RX_25_GS_SW_RESET); + } + + al_dbg("%s: perform gearbox reset (Tx %d, Rx %d) \n", __func__, tx_reset, rx_reset); + al_reg_write32(&adapter->mac_regs_base->gen_v3.ext_serdes_ctrl, reg); + + al_udelay(10); + + al_reg_write32(&adapter->mac_regs_base->gen_v3.ext_serdes_ctrl, orig_val); +} + +int al_eth_fec_enable(struct al_hal_eth_adapter *adapter, al_bool enable) +{ + if (adapter->rev_id <= AL_ETH_REV_ID_2) + return -1; + + if (enable) + al_reg_write32_masked(&adapter->mac_regs_base->gen_v3.pcs_10g_ll_cfg, + (ETH_MAC_GEN_V3_PCS_10G_LL_CFG_FEC_EN_RX | + ETH_MAC_GEN_V3_PCS_10G_LL_CFG_FEC_EN_TX), + (ETH_MAC_GEN_V3_PCS_10G_LL_CFG_FEC_EN_RX | + ETH_MAC_GEN_V3_PCS_10G_LL_CFG_FEC_EN_TX)); + else + al_reg_write32_masked(&adapter->mac_regs_base->gen_v3.pcs_10g_ll_cfg, + (ETH_MAC_GEN_V3_PCS_10G_LL_CFG_FEC_EN_RX | + ETH_MAC_GEN_V3_PCS_10G_LL_CFG_FEC_EN_TX), + 0); + return 0; +} + +int al_eth_fec_stats_get(struct al_hal_eth_adapter *adapter, + uint32_t *corrected, uint32_t *uncorrectable) +{ + if (adapter->rev_id <= AL_ETH_REV_ID_2) + return -1; + + *corrected = al_reg_read32(&adapter->mac_regs_base->stat.v3_pcs_10g_ll_cerr); + *uncorrectable = al_reg_read32(&adapter->mac_regs_base->stat.v3_pcs_10g_ll_ncerr); + + return 0; +} + + int al_eth_capabilities_get(struct al_hal_eth_adapter *adapter, struct al_eth_capabilities *caps) { al_assert(caps); @@ -1483,46 +1677,18 @@ int al_eth_capabilities_get(struct al_hal_eth_adapter *adapter, struct al_eth_ca return 0; } -/* update link speed and duplex mode */ -int al_eth_mac_link_config(struct al_hal_eth_adapter *adapter, - al_bool force_1000_base_x, - al_bool an_enable, - uint32_t speed, - al_bool full_duplex) +static void al_eth_mac_link_config_1g_mac( + struct al_hal_eth_adapter *adapter, + al_bool force_1000_base_x, + al_bool an_enable, + uint32_t speed, + al_bool full_duplex) { uint32_t mac_ctrl; uint32_t sgmii_ctrl = 0; uint32_t sgmii_if_mode = 0; uint32_t rgmii_ctrl = 0; - if (!AL_ETH_IS_1G_MAC(adapter->mac_mode)) { - al_err("eth [%s]: this function not supported in this mac mode.\n", - adapter->name); - return -EINVAL; - } - - if ((adapter->mac_mode != AL_ETH_MAC_MODE_RGMII) && (an_enable)) { - /* - * an_enable is not relevant to RGMII mode. - * in AN mode speed and duplex aren't relevant. - */ - al_info("eth [%s]: set auto negotiation to enable\n", adapter->name); - } else { - al_info("eth [%s]: set link speed to %dMbps. %s duplex.\n", adapter->name, - speed, full_duplex == AL_TRUE ? "full" : "half"); - - if ((speed != 10) && (speed != 100) && (speed != 1000)) { - al_err("eth [%s]: bad speed parameter (%d).\n", - adapter->name, speed); - return -EINVAL; - } - if ((speed == 1000) && (full_duplex == AL_FALSE)) { - al_err("eth [%s]: half duplex in 1Gbps is not supported.\n", - adapter->name); - return -EINVAL; - } - } - mac_ctrl = al_reg_read32(&adapter->mac_regs_base->mac_1g.cmd_cfg); if (adapter->mac_mode == AL_ETH_MAC_MODE_SGMII) { @@ -1558,22 +1724,22 @@ int al_eth_mac_link_config(struct al_hal_eth_adapter *adapter, } if (full_duplex == AL_TRUE) { - AL_REG_MASK_CLEAR(mac_ctrl, AL_ETH_1G_MAC_CTRL_HD_EN); + AL_REG_MASK_CLEAR(mac_ctrl, ETH_1G_MAC_CMD_CFG_HD_EN); } else { - AL_REG_MASK_SET(mac_ctrl, AL_ETH_1G_MAC_CTRL_HD_EN); + AL_REG_MASK_SET(mac_ctrl, ETH_1G_MAC_CMD_CFG_HD_EN); sgmii_if_mode |= ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_DUPLEX; } if (speed == 1000) { - AL_REG_MASK_SET(mac_ctrl, AL_ETH_1G_MAC_CTRL_1G_SPD); + AL_REG_MASK_SET(mac_ctrl, ETH_1G_MAC_CMD_CFG_1G_SPD); sgmii_if_mode |= ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_SPEED_1000; } else { - AL_REG_MASK_CLEAR(mac_ctrl, AL_ETH_1G_MAC_CTRL_1G_SPD); + AL_REG_MASK_CLEAR(mac_ctrl, ETH_1G_MAC_CMD_CFG_1G_SPD); if (speed == 10) { - AL_REG_MASK_SET(mac_ctrl, AL_ETH_1G_MAC_CTRL_10M_SPD); + AL_REG_MASK_SET(mac_ctrl, ETH_1G_MAC_CMD_CFG_10M_SPD); } else { sgmii_if_mode |= ETH_MAC_SGMII_REG_DATA_IF_MODE_SGMII_SPEED_100; - AL_REG_MASK_CLEAR(mac_ctrl, AL_ETH_1G_MAC_CTRL_10M_SPD); + AL_REG_MASK_CLEAR(mac_ctrl, ETH_1G_MAC_CMD_CFG_10M_SPD); } } @@ -1590,6 +1756,113 @@ int al_eth_mac_link_config(struct al_hal_eth_adapter *adapter, } al_reg_write32(&adapter->mac_regs_base->mac_1g.cmd_cfg, mac_ctrl); +} + +static void al_eth_mac_link_config_10g_mac( + struct al_hal_eth_adapter *adapter, + al_bool force_1000_base_x, + al_bool an_enable, + uint32_t speed, + al_bool full_duplex) +{ + uint32_t if_mode; + uint32_t val; + + if_mode = al_reg_read32(&adapter->mac_regs_base->mac_10g.if_mode); + + if (force_1000_base_x) { + uint32_t control; + + AL_REG_MASK_CLEAR(if_mode, ETH_10G_MAC_IF_MODE_SGMII_EN_MASK); + + control = al_reg_read32(&adapter->mac_regs_base->mac_10g.control); + + if (an_enable) + AL_REG_MASK_SET(control, ETH_10G_MAC_CONTROL_AN_EN_MASK); + else + AL_REG_MASK_CLEAR(control, ETH_10G_MAC_CONTROL_AN_EN_MASK); + + al_reg_write32(&adapter->mac_regs_base->mac_10g.control, control); + + } else { + AL_REG_MASK_SET(if_mode, ETH_10G_MAC_IF_MODE_SGMII_EN_MASK); + if (an_enable) { + AL_REG_MASK_SET(if_mode, ETH_10G_MAC_IF_MODE_SGMII_AN_MASK); + } else { + AL_REG_MASK_CLEAR(if_mode, ETH_10G_MAC_IF_MODE_SGMII_AN_MASK); + + if (speed == 1000) + val = ETH_10G_MAC_IF_MODE_SGMII_SPEED_1G; + else if (speed == 100) + val = ETH_10G_MAC_IF_MODE_SGMII_SPEED_100M; + else + val = ETH_10G_MAC_IF_MODE_SGMII_SPEED_10M; + + AL_REG_FIELD_SET(if_mode, + ETH_10G_MAC_IF_MODE_SGMII_SPEED_MASK, + ETH_10G_MAC_IF_MODE_SGMII_SPEED_SHIFT, + val); + + AL_REG_FIELD_SET(if_mode, + ETH_10G_MAC_IF_MODE_SGMII_DUPLEX_MASK, + ETH_10G_MAC_IF_MODE_SGMII_DUPLEX_SHIFT, + ((full_duplex) ? + ETH_10G_MAC_IF_MODE_SGMII_DUPLEX_FULL : + ETH_10G_MAC_IF_MODE_SGMII_DUPLEX_HALF)); + } + } + + al_reg_write32(&adapter->mac_regs_base->mac_10g.if_mode, if_mode); +} + +/* update link speed and duplex mode */ +int al_eth_mac_link_config(struct al_hal_eth_adapter *adapter, + al_bool force_1000_base_x, + al_bool an_enable, + uint32_t speed, + al_bool full_duplex) +{ + if ((!AL_ETH_IS_1G_MAC(adapter->mac_mode)) && + (adapter->mac_mode != AL_ETH_MAC_MODE_SGMII_2_5G)) { + al_err("eth [%s]: this function not supported in this mac mode.\n", + adapter->name); + return -EINVAL; + } + + if ((adapter->mac_mode != AL_ETH_MAC_MODE_RGMII) && (an_enable)) { + /* + * an_enable is not relevant to RGMII mode. + * in AN mode speed and duplex aren't relevant. + */ + al_info("eth [%s]: set auto negotiation to enable\n", adapter->name); + } else { + al_info("eth [%s]: set link speed to %dMbps. %s duplex.\n", adapter->name, + speed, full_duplex == AL_TRUE ? "full" : "half"); + + if ((speed != 10) && (speed != 100) && (speed != 1000)) { + al_err("eth [%s]: bad speed parameter (%d).\n", + adapter->name, speed); + return -EINVAL; + } + if ((speed == 1000) && (full_duplex == AL_FALSE)) { + al_err("eth [%s]: half duplex in 1Gbps is not supported.\n", + adapter->name); + return -EINVAL; + } + } + + if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) + al_eth_mac_link_config_1g_mac(adapter, + force_1000_base_x, + an_enable, + speed, + full_duplex); + else + al_eth_mac_link_config_10g_mac(adapter, + force_1000_base_x, + an_enable, + speed, + full_duplex); return 0; } @@ -2014,12 +2287,12 @@ al_dump_tx_pkt(struct al_udma_q *tx_dma_q, struct al_eth_pkt *pkt) const char *l3_proto_name = "unknown"; const char *l4_proto_name = "unknown"; const char *outer_l3_proto_name = "N/A"; - const char *tunnel_mode = ((pkt->tunnel_mode & AL_ETH_TUNNEL_WITH_UDP) == - AL_ETH_TUNNEL_WITH_UDP) ? - "TUNNEL_WITH_UDP" : - ((pkt->tunnel_mode & AL_ETH_TUNNEL_NO_UDP) == - AL_ETH_TUNNEL_NO_UDP) ? - "TUNNEL_NO_UDP" : ""; + const char *tunnel_mode = (((pkt->tunnel_mode & + AL_ETH_TUNNEL_WITH_UDP) == AL_ETH_TUNNEL_WITH_UDP) ? + "TUNNEL_WITH_UDP" : + (((pkt->tunnel_mode & + AL_ETH_TUNNEL_NO_UDP) == AL_ETH_TUNNEL_NO_UDP) ? + "TUNNEL_NO_UDP" : "")); uint32_t total_len = 0; int i; @@ -2071,26 +2344,19 @@ al_dump_tx_pkt(struct al_udma_q *tx_dma_q, struct al_eth_pkt *pkt) if (pkt->meta) { const char * store = pkt->meta->store ? "Yes" : "No"; + const char *ptp_val = (pkt->flags & AL_ETH_TX_FLAGS_TS) ? "Yes" : "No"; al_dbg("[%s %d]: tx pkt with meta data. words valid %x\n", tx_dma_q->udma->name, tx_dma_q->qid, pkt->meta->words_valid); - if (tx_dma_q->adapter_rev_id == AL_ETH_REV_ID_0) - al_dbg("[%s %d]: meta: store to cache %s. l3 hdr len %d. l3 hdr offset %d. l4 hdr len %d. mss sel %d\n" - , tx_dma_q->udma->name, tx_dma_q->qid, store, - pkt->meta->l3_header_len, pkt->meta->l3_header_offset, - pkt->meta->l4_header_len, - pkt->meta->mss_idx_sel); - else { - const char *ptp_val = (pkt->flags & AL_ETH_TX_FLAGS_TS) ? "Yes" : "No"; - al_dbg("[%s %d]: meta: store to cache %s. l3 hdr len %d. l3 hdr offset %d. l4 hdr len %d. mss val %d ts_index %d ts_val:%s\n" - , tx_dma_q->udma->name, tx_dma_q->qid, store, - pkt->meta->l3_header_len, pkt->meta->l3_header_offset, - pkt->meta->l4_header_len, pkt->meta->mss_val, - pkt->meta->ts_index, ptp_val); - al_dbg("outer_l3_hdr_offset %d. outer_l3_len %d.\n", - pkt->meta->outer_l3_offset, pkt->meta->outer_l3_len); - } + al_dbg("[%s %d]: meta: store to cache %s. l3 hdr len %d. l3 hdr offset %d. " + "l4 hdr len %d. mss val %d ts_index %d ts_val:%s\n" + , tx_dma_q->udma->name, tx_dma_q->qid, store, + pkt->meta->l3_header_len, pkt->meta->l3_header_offset, + pkt->meta->l4_header_len, pkt->meta->mss_val, + pkt->meta->ts_index, ptp_val); + al_dbg("outer_l3_hdr_offset %d. outer_l3_len %d.\n", + pkt->meta->outer_l3_offset, pkt->meta->outer_l3_len); } al_dbg("[%s %d]: num of bufs: %d\n", tx_dma_q->udma->name, tx_dma_q->qid, @@ -2115,7 +2381,7 @@ int al_eth_tx_pkt_prepare(struct al_udma_q *tx_dma_q, struct al_eth_pkt *pkt) uint32_t flags = AL_M2S_DESC_FIRST | AL_M2S_DESC_CONCAT | (pkt->flags & AL_ETH_TX_FLAGS_INT); - uint64_t vmid = ((uint64_t)pkt->vmid) << AL_UDMA_DESC_VMID_SHIFT; + uint64_t tgtid = ((uint64_t)pkt->tgtid) << AL_UDMA_DESC_TGTID_SHIFT; uint32_t meta_ctrl; uint32_t ring_id; int buf_idx; @@ -2190,49 +2456,46 @@ int al_eth_tx_pkt_prepare(struct al_udma_q *tx_dma_q, struct al_eth_pkt *pkt) } if (pkt->meta->words_valid & 4) { + uint32_t l3_offset; + meta_word_2 = pkt->meta->l3_header_len & AL_ETH_TX_META_L3_LEN_MASK; meta_word_2 |= (pkt->meta->l3_header_offset & AL_ETH_TX_META_L3_OFF_MASK) << AL_ETH_TX_META_L3_OFF_SHIFT; meta_word_2 |= (pkt->meta->l4_header_len & 0x3f) << 16; - if (tx_dma_q->adapter_rev_id == AL_ETH_REV_ID_0) { - meta_word_2 |= (pkt->meta->mss_idx_sel & 7) << 24; - } else { - uint32_t l3_offset; + if (unlikely(pkt->flags & AL_ETH_TX_FLAGS_TS)) + meta_word_0 |= pkt->meta->ts_index << + AL_ETH_TX_META_MSS_MSB_TS_VAL_SHIFT; + else + meta_word_0 |= (((pkt->meta->mss_val & 0x3c00) >> 10) + << AL_ETH_TX_META_MSS_MSB_TS_VAL_SHIFT); + meta_word_2 |= ((pkt->meta->mss_val & 0x03ff) + << AL_ETH_TX_META_MSS_LSB_VAL_SHIFT); - if (unlikely(pkt->flags & AL_ETH_TX_FLAGS_TS)) - meta_word_0 |= pkt->meta->ts_index << AL_ETH_TX_META_MSS_MSB_TS_VAL_SHIFT; - else - meta_word_0 |= (((pkt->meta->mss_val & 0x3c00) >> 10) - << AL_ETH_TX_META_MSS_MSB_TS_VAL_SHIFT); - meta_word_2 |= ((pkt->meta->mss_val & 0x03ff) - << AL_ETH_TX_META_MSS_LSB_VAL_SHIFT); + /* + * move from bytes to multiplication of 2 as the HW + * expect to get it + */ + l3_offset = (pkt->meta->outer_l3_offset >> 1); - /* - * move from bytes to multiplication of 2 as the HW - * expect to get it - */ - l3_offset = (pkt->meta->outer_l3_offset >> 1); + meta_word_0 |= + (((l3_offset & + AL_ETH_TX_META_OUTER_L3_OFF_HIGH_MASK) >> 3) + << AL_ETH_TX_META_OUTER_L3_OFF_HIGH_SHIFT); - meta_word_0 |= - (((l3_offset & - AL_ETH_TX_META_OUTER_L3_OFF_HIGH_MASK) >> 3) - << AL_ETH_TX_META_OUTER_L3_OFF_HIGH_SHIFT); + meta_word_3 |= + ((l3_offset & + AL_ETH_TX_META_OUTER_L3_OFF_LOW_MASK) + << AL_ETH_TX_META_OUTER_L3_OFF_LOW_SHIFT); - meta_word_3 |= - ((l3_offset & - AL_ETH_TX_META_OUTER_L3_OFF_LOW_MASK) - << AL_ETH_TX_META_OUTER_L3_OFF_LOW_SHIFT); - - /* - * shift right 2 bits to work in multiplication of 4 - * as the HW expect to get it - */ - meta_word_3 |= - (((pkt->meta->outer_l3_len >> 2) & - AL_ETH_TX_META_OUTER_L3_LEN_MASK) - << AL_ETH_TX_META_OUTER_L3_LEN_SHIFT); - } + /* + * shift right 2 bits to work in multiplication of 4 + * as the HW expect to get it + */ + meta_word_3 |= + (((pkt->meta->outer_l3_len >> 2) & + AL_ETH_TX_META_OUTER_L3_LEN_MASK) + << AL_ETH_TX_META_OUTER_L3_LEN_SHIFT); } tx_desc->tx_meta.len_ctrl = swap32_to_le(meta_word_0); @@ -2266,11 +2529,9 @@ int al_eth_tx_pkt_prepare(struct al_udma_q *tx_dma_q, struct al_eth_pkt *pkt) meta_ctrl |= AL_ETH_TX_FLAGS_ENCRYPT; #endif - if (tx_dma_q->adapter_rev_id > AL_ETH_REV_ID_0) { - meta_ctrl |= pkt->tunnel_mode << AL_ETH_TX_TUNNEL_MODE_SHIFT; - if (pkt->outer_l3_proto_idx == AL_ETH_PROTO_ID_IPv4) - meta_ctrl |= 1 << AL_ETH_TX_OUTER_L3_PROTO_SHIFT; - } + meta_ctrl |= pkt->tunnel_mode << AL_ETH_TX_TUNNEL_MODE_SHIFT; + if (pkt->outer_l3_proto_idx == AL_ETH_PROTO_ID_IPv4) + meta_ctrl |= 1 << AL_ETH_TX_OUTER_L3_PROTO_SHIFT; flags |= pkt->flags & AL_ETH_TX_PKT_UDMA_FLAGS; for(buf_idx = 0; buf_idx < pkt->num_of_bufs; buf_idx++ ) { @@ -2295,7 +2556,7 @@ int al_eth_tx_pkt_prepare(struct al_udma_q *tx_dma_q, struct al_eth_pkt *pkt) if (buf_idx == 0) tx_desc->tx.meta_ctrl = swap32_to_le(meta_ctrl); tx_desc->tx.buf_ptr = swap64_to_le( - pkt->bufs[buf_idx].addr | vmid); + pkt->bufs[buf_idx].addr | tgtid); al_dump_tx_desc(tx_desc); } @@ -2408,10 +2669,6 @@ int al_eth_rx_header_split_config(struct al_hal_eth_adapter *adapter, al_bool en { uint32_t reg; - if (adapter->rev_id < AL_ETH_REV_ID_1) { - al_err("[%s]: header split feature not supported by this revision\n", adapter->name); - return -EINVAL; - } reg = al_reg_read32(&adapter->ec_regs_base->rfw.hdr_split); if (enable == AL_TRUE) reg |= EC_RFW_HDR_SPLIT_EN; @@ -2447,9 +2704,9 @@ int al_eth_rx_buffer_add(struct al_udma_q *rx_dma_q, struct al_buf *buf, uint32_t flags, struct al_buf *header_buf) { - uint64_t vmid = ((uint64_t)flags & AL_ETH_RX_FLAGS_VMID_MASK) << - AL_UDMA_DESC_VMID_SHIFT; - uint32_t flags_len = flags & ~AL_ETH_RX_FLAGS_VMID_MASK; + uint64_t tgtid = ((uint64_t)flags & AL_ETH_RX_FLAGS_TGTID_MASK) << + AL_UDMA_DESC_TGTID_SHIFT; + uint32_t flags_len = flags & ~AL_ETH_RX_FLAGS_TGTID_MASK; union al_udma_desc *rx_desc; al_dbg("[%s %d]: add rx buffer.\n", rx_dma_q->udma->name, rx_dma_q->qid); @@ -2476,7 +2733,7 @@ int al_eth_rx_buffer_add(struct al_udma_q *rx_dma_q, rx_desc->rx.buf2_ptr_lo = swap32_to_le(AL_ADDR_LOW(header_buf->addr)); } rx_desc->rx.len_ctrl = swap32_to_le(flags_len); - rx_desc->rx.buf1_ptr = swap64_to_le(buf->addr | vmid); + rx_desc->rx.buf1_ptr = swap64_to_le(buf->addr | tgtid); return 0; } @@ -2943,7 +3200,8 @@ int al_eth_switching_config_set(struct al_hal_eth_adapter *adapter, uint8_t udma AL_ETH_RFW_FILTER_VLAN_VID | \ AL_ETH_RFW_FILTER_CTRL_TABLE | \ AL_ETH_RFW_FILTER_PROT_INDEX | \ - ((rev_id > AL_ETH_REV_ID_0) ? ((AL_ETH_RFW_FILTER_WOL) | (AL_ETH_RFW_FILTER_PARSE)) : 0)) + AL_ETH_RFW_FILTER_WOL | \ + AL_ETH_RFW_FILTER_PARSE) /* Configure the receive filters */ int al_eth_filter_config(struct al_hal_eth_adapter *adapter, struct al_eth_filter_params *params) @@ -3236,11 +3494,27 @@ int al_eth_eee_config(struct al_hal_eth_adapter *adapter, struct al_eth_eee_para al_reg_write32(&adapter->ec_regs_base->eee.cfg_e, 0); return 0; } - if (AL_ETH_IS_10G_MAC(adapter->mac_mode)) { - reg = ETH_MAC_KR_PCS_CFG_EEE_TIMER_VAL << ETH_MAC_KR_PCS_CFG_EEE_TIMER_VAL_SHIFT; + if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) { al_reg_write32_masked( &adapter->mac_regs_base->kr.pcs_cfg, - ETH_MAC_KR_PCS_CFG_EEE_TIMER_VAL_MASK, reg); + ETH_MAC_KR_PCS_CFG_EEE_TIMER_VAL_MASK, + ((AL_ETH_IS_10G_MAC(adapter->mac_mode)) ? + ETH_MAC_KR_10_PCS_CFG_EEE_TIMER_VAL : + ETH_MAC_KR_25_PCS_CFG_EEE_TIMER_VAL) << + ETH_MAC_KR_PCS_CFG_EEE_TIMER_VAL_SHIFT); + } + if ((adapter->mac_mode == AL_ETH_MAC_MODE_XLG_LL_40G) || + (adapter->mac_mode == AL_ETH_MAC_MODE_XLG_LL_50G)) { + al_reg_write32_masked( + &adapter->mac_regs_base->gen_v3.pcs_40g_ll_eee_cfg, + ETH_MAC_GEN_V3_PCS_40G_LL_EEE_CFG_TIMER_VAL_MASK, + ((adapter->mac_mode == AL_ETH_MAC_MODE_XLG_LL_40G) ? + ETH_MAC_XLG_40_PCS_CFG_EEE_TIMER_VAL : + ETH_MAC_XLG_50_PCS_CFG_EEE_TIMER_VAL) << + ETH_MAC_GEN_V3_PCS_40G_LL_EEE_CFG_TIMER_VAL_SHIFT); + /* set Deep sleep mode as the LPI function (instead of Fast wake mode) */ + al_eth_40g_pcs_reg_write(adapter, ETH_MAC_GEN_V3_PCS_40G_EEE_CONTROL_ADDR, + params->fast_wake ? 1 : 0); } al_reg_write32(&adapter->ec_regs_base->eee.pre_cnt, params->tx_eee_timer); @@ -3551,13 +3825,24 @@ int al_eth_link_status_get(struct al_hal_eth_adapter *adapter, uint32_t reg; if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) { - reg = al_reg_read32(&adapter->mac_regs_base->gen.mac_10g_stat); + status->link_up = AL_FALSE; + status->local_fault = AL_TRUE; + status->remote_fault = AL_TRUE; - status->link_up = AL_TRUE; + al_reg_write32(&adapter->mac_regs_base->kr.pcs_addr, ETH_MAC_KR_PCS_BASE_R_STATUS2); + reg = al_reg_read32(&adapter->mac_regs_base->kr.pcs_data); - if (reg & (ETH_MAC_GEN_MAC_10G_STAT_LOC_FAULT | - ETH_MAC_GEN_MAC_10G_STAT_REM_FAULT)) - status->link_up = AL_FALSE; + if (reg & AL_BIT(15)) { + reg = al_reg_read32(&adapter->mac_regs_base->mac_10g.status); + + status->remote_fault = ((reg & ETH_MAC_GEN_MAC_10G_STAT_REM_FAULT) ? + AL_TRUE : AL_FALSE); + status->local_fault = ((reg & ETH_MAC_GEN_MAC_10G_STAT_LOC_FAULT) ? + AL_TRUE : AL_FALSE); + + status->link_up = ((status->remote_fault == AL_FALSE) && + (status->local_fault == AL_FALSE)); + } } else if (adapter->mac_mode == AL_ETH_MAC_MODE_SGMII) { al_reg_write32(&adapter->mac_regs_base->sgmii.reg_addr, 1); @@ -3586,6 +3871,27 @@ int al_eth_link_status_get(struct al_hal_eth_adapter *adapter, if (reg & AL_BIT(4)) status->link_up = AL_TRUE; + } else if (adapter->mac_mode == AL_ETH_MAC_MODE_XLG_LL_25G) { + status->link_up = AL_FALSE; + status->local_fault = AL_TRUE; + status->remote_fault = AL_TRUE; + + reg = al_reg_read32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_status); + + status->link_up = AL_FALSE; + + if ((reg & 0xF) == 0xF) { + reg = al_reg_read32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_status); + + status->remote_fault = ((reg & ETH_MAC_GEN_V3_MAC_40G_LL_STATUS_REM_FAULT) ? + AL_TRUE : AL_FALSE); + status->local_fault = ((reg & ETH_MAC_GEN_V3_MAC_40G_LL_STATUS_LOC_FAULT) ? + AL_TRUE : AL_FALSE); + + status->link_up = ((status->remote_fault == AL_FALSE) && + (status->local_fault == AL_FALSE)); + } + } else if ((adapter->mac_mode == AL_ETH_MAC_MODE_XLG_LL_40G) || (adapter->mac_mode == AL_ETH_MAC_MODE_XLG_LL_50G)) { reg = al_reg_read32(&adapter->mac_regs_base->gen_v3.pcs_40g_ll_status); @@ -3595,7 +3901,7 @@ int al_eth_link_status_get(struct al_hal_eth_adapter *adapter, if ((reg & 0x1F) == 0x1F) { reg = al_reg_read32(&adapter->mac_regs_base->gen_v3.mac_40g_ll_status); if ((reg & (ETH_MAC_GEN_V3_MAC_40G_LL_STATUS_REM_FAULT | -ETH_MAC_GEN_V3_MAC_40G_LL_STATUS_LOC_FAULT)) == 0) + ETH_MAC_GEN_V3_MAC_40G_LL_STATUS_LOC_FAULT)) == 0) status->link_up = AL_TRUE; } @@ -3611,6 +3917,22 @@ ETH_MAC_GEN_V3_MAC_40G_LL_STATUS_LOC_FAULT)) == 0) return 0; } +int al_eth_link_status_clear(struct al_hal_eth_adapter *adapter) +{ + int status = 0; + + if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) { + al_reg_write32(&adapter->mac_regs_base->kr.pcs_addr, ETH_MAC_KR_PCS_BASE_R_STATUS2); + al_reg_read32(&adapter->mac_regs_base->kr.pcs_data); + + al_reg_read32(&adapter->mac_regs_base->mac_10g.status); + } else { + status = -1; + } + + return status; +} + /** set LED mode and value */ int al_eth_led_set(struct al_hal_eth_adapter *adapter, al_bool link_is_up) { @@ -3641,179 +3963,220 @@ int al_eth_mac_stats_get(struct al_hal_eth_adapter *adapter, struct al_eth_mac_s { al_assert(stats); + al_memset(stats, 0, sizeof(struct al_eth_mac_stats)); + if (AL_ETH_IS_1G_MAC(adapter->mac_mode)) { - void __iomem *mac_1g_regs_base = &adapter->mac_regs_base->mac_1g; + struct al_eth_mac_1g_stats __iomem *reg_stats = + &adapter->mac_regs_base->mac_1g.stats; - stats->ifInUcastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x90)); - stats->ifInMulticastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x94)); - stats->ifInBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x98)); - stats->etherStatsPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xb4)); - stats->ifOutUcastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xa0)); - stats->ifOutMulticastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xa4)); - stats->ifOutBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xa8)); - stats->ifInErrors = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x88)); - stats->ifOutErrors = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x8c)); - - stats->aFramesReceivedOK = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x6c)); - stats->aFramesTransmittedOK = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x68)); - - stats->aOctetsReceivedOK = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x7c)); - stats->aOctetsTransmittedOK = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x78)); - - stats->etherStatsUndersizePkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xB8)); - stats->etherStatsFragments = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xE0)); - stats->etherStatsJabbers = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xDC)); - stats->etherStatsOversizePkts = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xBC)); - - stats->aFrameCheckSequenceErrors = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x70)); - stats->aAlignmentErrors = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x74)); - stats->etherStatsDropEvents = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xAC)); - - stats->aPAUSEMACCtrlFramesTransmitted = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x80)); - stats->aPAUSEMACCtrlFramesReceived = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0x84)); + stats->ifInUcastPkts = al_reg_read32(®_stats->ifInUcastPkts); + stats->ifInMulticastPkts = al_reg_read32(®_stats->ifInMulticastPkts); + stats->ifInBroadcastPkts = al_reg_read32(®_stats->ifInBroadcastPkts); + stats->etherStatsPkts = al_reg_read32(®_stats->etherStatsPkts); + stats->ifOutUcastPkts = al_reg_read32(®_stats->ifOutUcastPkts); + stats->ifOutMulticastPkts = al_reg_read32(®_stats->ifOutMulticastPkts); + stats->ifOutBroadcastPkts = al_reg_read32(®_stats->ifOutBroadcastPkts); + stats->ifInErrors = al_reg_read32(®_stats->ifInErrors); + stats->ifOutErrors = al_reg_read32(®_stats->ifOutErrors); + stats->aFramesReceivedOK = al_reg_read32(®_stats->aFramesReceivedOK); + stats->aFramesTransmittedOK = al_reg_read32(®_stats->aFramesTransmittedOK); + stats->aOctetsReceivedOK = al_reg_read32(®_stats->aOctetsReceivedOK); + stats->aOctetsTransmittedOK = al_reg_read32(®_stats->aOctetsTransmittedOK); + stats->etherStatsUndersizePkts = al_reg_read32(®_stats->etherStatsUndersizePkts); + stats->etherStatsFragments = al_reg_read32(®_stats->etherStatsFragments); + stats->etherStatsJabbers = al_reg_read32(®_stats->etherStatsJabbers); + stats->etherStatsOversizePkts = al_reg_read32(®_stats->etherStatsOversizePkts); + stats->aFrameCheckSequenceErrors = + al_reg_read32(®_stats->aFrameCheckSequenceErrors); + stats->aAlignmentErrors = al_reg_read32(®_stats->aAlignmentErrors); + stats->etherStatsDropEvents = al_reg_read32(®_stats->etherStatsDropEvents); + stats->aPAUSEMACCtrlFramesTransmitted = + al_reg_read32(®_stats->aPAUSEMACCtrlFramesTransmitted); + stats->aPAUSEMACCtrlFramesReceived = + al_reg_read32(®_stats->aPAUSEMACCtrlFramesReceived); stats->aFrameTooLongErrors = 0; /* N/A */ stats->aInRangeLengthErrors = 0; /* N/A */ stats->VLANTransmittedOK = 0; /* N/A */ stats->VLANReceivedOK = 0; /* N/A */ - stats->etherStatsOctets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xB0)); - - stats->etherStatsPkts64Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xC0)); - stats->etherStatsPkts65to127Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xC4)); - stats->etherStatsPkts128to255Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xC8)); - stats->etherStatsPkts256to511Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xCC)); - stats->etherStatsPkts512to1023Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xD0)); - stats->etherStatsPkts1024to1518Octets = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xD4)); - stats->etherStatsPkts1519toX = al_reg_read32((void *)((uint32_t)mac_1g_regs_base + 0xD8)); + stats->etherStatsOctets = al_reg_read32(®_stats->etherStatsOctets); + stats->etherStatsPkts64Octets = al_reg_read32(®_stats->etherStatsPkts64Octets); + stats->etherStatsPkts65to127Octets = + al_reg_read32(®_stats->etherStatsPkts65to127Octets); + stats->etherStatsPkts128to255Octets = + al_reg_read32(®_stats->etherStatsPkts128to255Octets); + stats->etherStatsPkts256to511Octets = + al_reg_read32(®_stats->etherStatsPkts256to511Octets); + stats->etherStatsPkts512to1023Octets = + al_reg_read32(®_stats->etherStatsPkts512to1023Octets); + stats->etherStatsPkts1024to1518Octets = + al_reg_read32(®_stats->etherStatsPkts1024to1518Octets); + stats->etherStatsPkts1519toX = al_reg_read32(®_stats->etherStatsPkts1519toX); } else if (AL_ETH_IS_10G_MAC(adapter->mac_mode) || AL_ETH_IS_25G_MAC(adapter->mac_mode)) { if (adapter->rev_id < AL_ETH_REV_ID_3) { - void __iomem *mac_10g_regs_base = &adapter->mac_regs_base->mac_10g; + struct al_eth_mac_10g_stats_v2 __iomem *reg_stats = + &adapter->mac_regs_base->mac_10g.stats.v2; uint64_t octets; - stats->ifInUcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xE0)); - stats->ifInMulticastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xE8)); - stats->ifInBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xF0)); - stats->etherStatsPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x130)); - stats->ifOutUcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x108)); - stats->ifOutMulticastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x110)); - stats->ifOutBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x118)); - stats->ifInErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x190)); - stats->ifOutErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xf8)); + stats->ifInUcastPkts = al_reg_read32(®_stats->ifInUcastPkts); + stats->ifInMulticastPkts = al_reg_read32(®_stats->ifInMulticastPkts); + stats->ifInBroadcastPkts = al_reg_read32(®_stats->ifInBroadcastPkts); + stats->etherStatsPkts = al_reg_read32(®_stats->etherStatsPkts); + stats->ifOutUcastPkts = al_reg_read32(®_stats->ifOutUcastPkts); + stats->ifOutMulticastPkts = al_reg_read32(®_stats->ifOutMulticastPkts); + stats->ifOutBroadcastPkts = al_reg_read32(®_stats->ifOutBroadcastPkts); + stats->ifInErrors = al_reg_read32(®_stats->ifInErrors); + stats->ifOutErrors = al_reg_read32(®_stats->ifOutErrors); + stats->aFramesReceivedOK = al_reg_read32(®_stats->aFramesReceivedOK); + stats->aFramesTransmittedOK = al_reg_read32(®_stats->aFramesTransmittedOK); - stats->aFramesReceivedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x88)); - stats->aFramesTransmittedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x80)); /* aOctetsReceivedOK = ifInOctets - 18 * aFramesReceivedOK - 4 * VLANReceivedOK */ - octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xD8)); - octets |= (uint64_t)(al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xDC))) << 32; + octets = al_reg_read32(®_stats->ifInOctetsL); + octets |= (uint64_t)(al_reg_read32(®_stats->ifInOctetsH)) << 32; octets -= 18 * stats->aFramesReceivedOK; - octets -= 4 * al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xC8)); + octets -= 4 * al_reg_read32(®_stats->VLANReceivedOK); stats->aOctetsReceivedOK = octets; /* aOctetsTransmittedOK = ifOutOctets - 18 * aFramesTransmittedOK - 4 * VLANTransmittedOK */ - octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xD0)); - octets |= (uint64_t)(al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xD4))) << 32; + octets = al_reg_read32(®_stats->ifOutOctetsL); + octets |= (uint64_t)(al_reg_read32(®_stats->ifOutOctetsH)) << 32; octets -= 18 * stats->aFramesTransmittedOK; - octets -= 4 * al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xC0)); + octets -= 4 * al_reg_read32(®_stats->VLANTransmittedOK); stats->aOctetsTransmittedOK = octets; - stats->etherStatsUndersizePkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x138)); - stats->etherStatsFragments = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x188)); - stats->etherStatsJabbers = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x180)); - stats->etherStatsOversizePkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x178)); - - stats->aFrameCheckSequenceErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x90)); - stats->aAlignmentErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x98)); - stats->etherStatsDropEvents = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x120)); - - stats->aPAUSEMACCtrlFramesTransmitted = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xA0)); - stats->aPAUSEMACCtrlFramesReceived = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xA8)); - stats->aFrameTooLongErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xB0)); - stats->aInRangeLengthErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xB8)); - stats->VLANTransmittedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xC0)); - stats->VLANReceivedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0xC8)); - stats->etherStatsOctets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x128)); - - stats->etherStatsPkts64Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x140)); - stats->etherStatsPkts65to127Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x148)); - stats->etherStatsPkts128to255Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x150)); - stats->etherStatsPkts256to511Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x158)); - stats->etherStatsPkts512to1023Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x160)); - stats->etherStatsPkts1024to1518Octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x168)); - stats->etherStatsPkts1519toX = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x170)); + stats->etherStatsUndersizePkts = al_reg_read32(®_stats->etherStatsUndersizePkts); + stats->etherStatsFragments = al_reg_read32(®_stats->etherStatsFragments); + stats->etherStatsJabbers = al_reg_read32(®_stats->etherStatsJabbers); + stats->etherStatsOversizePkts = al_reg_read32(®_stats->etherStatsOversizePkts); + stats->aFrameCheckSequenceErrors = al_reg_read32(®_stats->aFrameCheckSequenceErrors); + stats->aAlignmentErrors = al_reg_read32(®_stats->aAlignmentErrors); + stats->etherStatsDropEvents = al_reg_read32(®_stats->etherStatsDropEvents); + stats->aPAUSEMACCtrlFramesTransmitted = al_reg_read32(®_stats->aPAUSEMACCtrlFramesTransmitted); + stats->aPAUSEMACCtrlFramesReceived = al_reg_read32(®_stats->aPAUSEMACCtrlFramesReceived); + stats->aFrameTooLongErrors = al_reg_read32(®_stats->aFrameTooLongErrors); + stats->aInRangeLengthErrors = al_reg_read32(®_stats->aInRangeLengthErrors); + stats->VLANTransmittedOK = al_reg_read32(®_stats->VLANTransmittedOK); + stats->VLANReceivedOK = al_reg_read32(®_stats->VLANReceivedOK); + stats->etherStatsOctets = al_reg_read32(®_stats->etherStatsOctets); + stats->etherStatsPkts64Octets = al_reg_read32(®_stats->etherStatsPkts64Octets); + stats->etherStatsPkts65to127Octets = al_reg_read32(®_stats->etherStatsPkts65to127Octets); + stats->etherStatsPkts128to255Octets = al_reg_read32(®_stats->etherStatsPkts128to255Octets); + stats->etherStatsPkts256to511Octets = al_reg_read32(®_stats->etherStatsPkts256to511Octets); + stats->etherStatsPkts512to1023Octets = al_reg_read32(®_stats->etherStatsPkts512to1023Octets); + stats->etherStatsPkts1024to1518Octets = al_reg_read32(®_stats->etherStatsPkts1024to1518Octets); + stats->etherStatsPkts1519toX = al_reg_read32(®_stats->etherStatsPkts1519toX); } else { - void __iomem *mac_10g_regs_base = &adapter->mac_regs_base->mac_10g; + struct al_eth_mac_10g_stats_v3_rx __iomem *reg_rx_stats = + &adapter->mac_regs_base->mac_10g.stats.v3.rx; + struct al_eth_mac_10g_stats_v3_tx __iomem *reg_tx_stats = + &adapter->mac_regs_base->mac_10g.stats.v3.tx; uint64_t octets; - /* TODO - change to 64 bit */ - stats->ifInUcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x140)); - stats->ifInMulticastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x148)); - stats->ifInBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x150)); - stats->etherStatsPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x160)); - stats->ifOutUcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x240)); - stats->ifOutMulticastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x248)); - stats->ifOutBroadcastPkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x250)); - stats->ifInErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x138)); - stats->ifOutErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x238)); - stats->aFramesReceivedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x120)); /*frames_ok*/ - stats->aFramesTransmittedOK = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x220)); /*frames_ok*/ + stats->ifInUcastPkts = al_reg_read32(®_rx_stats->ifInUcastPkts); + stats->ifInMulticastPkts = al_reg_read32(®_rx_stats->ifInMulticastPkts); + stats->ifInBroadcastPkts = al_reg_read32(®_rx_stats->ifInBroadcastPkts); + stats->etherStatsPkts = al_reg_read32(®_rx_stats->etherStatsPkts); + stats->ifOutUcastPkts = al_reg_read32(®_tx_stats->ifUcastPkts); + stats->ifOutMulticastPkts = al_reg_read32(®_tx_stats->ifMulticastPkts); + stats->ifOutBroadcastPkts = al_reg_read32(®_tx_stats->ifBroadcastPkts); + stats->ifInErrors = al_reg_read32(®_rx_stats->ifInErrors); + stats->ifOutErrors = al_reg_read32(®_tx_stats->ifOutErrors); + stats->aFramesReceivedOK = al_reg_read32(®_rx_stats->FramesOK); + stats->aFramesTransmittedOK = al_reg_read32(®_tx_stats->FramesOK); + /* aOctetsReceivedOK = ifInOctets - 18 * aFramesReceivedOK - 4 * VLANReceivedOK */ - octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x108)); /*OctetsOK*/ - octets |= (uint64_t)(al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x10C))) << 32; + octets = al_reg_read32(®_rx_stats->ifOctetsL); + octets |= (uint64_t)(al_reg_read32(®_rx_stats->ifOctetsH)) << 32; octets -= 18 * stats->aFramesReceivedOK; - octets -= 4 * al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x130)); /*VLANOK*/ + octets -= 4 * al_reg_read32(®_rx_stats->VLANOK); stats->aOctetsReceivedOK = octets; /* aOctetsTransmittedOK = ifOutOctets - 18 * aFramesTransmittedOK - 4 * VLANTransmittedOK */ - octets = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x208)); /*OctetsOK*/ - octets |= (uint64_t)(al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x20c))) << 32; + octets = al_reg_read32(®_tx_stats->ifOctetsL); + octets |= (uint64_t)(al_reg_read32(®_tx_stats->ifOctetsH)) << 32; octets -= 18 * stats->aFramesTransmittedOK; - octets -= 4 * al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x230)); /*VLANOK*/ + octets -= 4 * al_reg_read32(®_tx_stats->VLANOK); stats->aOctetsTransmittedOK = octets; - stats->etherStatsUndersizePkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x168)); - stats->etherStatsFragments = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x1b8)); - stats->etherStatsJabbers = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x1b0)); - stats->etherStatsOversizePkts = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x1a8)); - - stats->aFrameCheckSequenceErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x128)); /* CRCErrors */ - /* stats->aAlignmentErrors = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x98)); */ /* not implemented */ - stats->etherStatsDropEvents = al_reg_read32((void *)((uint32_t)mac_10g_regs_base + 0x158)); + stats->etherStatsUndersizePkts = al_reg_read32(®_rx_stats->etherStatsUndersizePkts); + stats->etherStatsFragments = al_reg_read32(®_rx_stats->etherStatsFragments); + stats->etherStatsJabbers = al_reg_read32(®_rx_stats->etherStatsJabbers); + stats->etherStatsOversizePkts = al_reg_read32(®_rx_stats->etherStatsOversizePkts); + stats->aFrameCheckSequenceErrors = al_reg_read32(®_rx_stats->CRCErrors); + stats->aAlignmentErrors = al_reg_read32(®_rx_stats->aAlignmentErrors); + stats->etherStatsDropEvents = al_reg_read32(®_rx_stats->etherStatsDropEvents); + stats->aPAUSEMACCtrlFramesTransmitted = al_reg_read32(®_tx_stats->aPAUSEMACCtrlFrames); + stats->aPAUSEMACCtrlFramesReceived = al_reg_read32(®_rx_stats->aPAUSEMACCtrlFrames); + stats->aFrameTooLongErrors = al_reg_read32(®_rx_stats->aFrameTooLong); + stats->aInRangeLengthErrors = al_reg_read32(®_rx_stats->aInRangeLengthErrors); + stats->VLANTransmittedOK = al_reg_read32(®_tx_stats->VLANOK); + stats->VLANReceivedOK = al_reg_read32(®_rx_stats->VLANOK); + stats->etherStatsOctets = al_reg_read32(®_rx_stats->etherStatsOctets); + stats->etherStatsPkts64Octets = al_reg_read32(®_rx_stats->etherStatsPkts64Octets); + stats->etherStatsPkts65to127Octets = al_reg_read32(®_rx_stats->etherStatsPkts65to127Octets); + stats->etherStatsPkts128to255Octets = al_reg_read32(®_rx_stats->etherStatsPkts128to255Octets); + stats->etherStatsPkts256to511Octets = al_reg_read32(®_rx_stats->etherStatsPkts256to511Octets); + stats->etherStatsPkts512to1023Octets = al_reg_read32(®_rx_stats->etherStatsPkts512to1023Octets); + stats->etherStatsPkts1024to1518Octets = al_reg_read32(®_rx_stats->etherStatsPkts1024to1518Octets); + stats->etherStatsPkts1519toX = al_reg_read32(®_rx_stats->etherStatsPkts1519toMax); } } else { + struct al_eth_mac_10g_stats_v3_rx __iomem *reg_rx_stats = + &adapter->mac_regs_base->mac_10g.stats.v3.rx; + struct al_eth_mac_10g_stats_v3_tx __iomem *reg_tx_stats = + &adapter->mac_regs_base->mac_10g.stats.v3.tx; uint64_t octets; - /* TODO - change to 64 bit */ - stats->ifInUcastPkts = al_eth_40g_mac_reg_read(adapter, 0x140); - stats->ifInMulticastPkts = al_eth_40g_mac_reg_read(adapter, 0x148); - stats->ifInBroadcastPkts = al_eth_40g_mac_reg_read(adapter, 0x150); - stats->etherStatsPkts = al_eth_40g_mac_reg_read(adapter, 0x160); - stats->ifOutUcastPkts = al_eth_40g_mac_reg_read(adapter, 0x240); - stats->ifOutMulticastPkts = al_eth_40g_mac_reg_read(adapter, 0x248); - stats->ifOutBroadcastPkts = al_eth_40g_mac_reg_read(adapter, 0x250); - stats->ifInErrors = al_eth_40g_mac_reg_read(adapter, 0x138); - stats->ifOutErrors = al_eth_40g_mac_reg_read(adapter, 0x238); - stats->aFramesReceivedOK = al_eth_40g_mac_reg_read(adapter, 0x120); - stats->aFramesTransmittedOK = al_eth_40g_mac_reg_read(adapter, 0x220); + + /* 40G MAC statistics registers are the same, only read indirectly */ + #define _40g_mac_reg_read32(field) al_eth_40g_mac_reg_read(adapter, \ + ((uint8_t *)(field)) - ((uint8_t *)&adapter->mac_regs_base->mac_10g)) + + stats->ifInUcastPkts = _40g_mac_reg_read32(®_rx_stats->ifInUcastPkts); + stats->ifInMulticastPkts = _40g_mac_reg_read32(®_rx_stats->ifInMulticastPkts); + stats->ifInBroadcastPkts = _40g_mac_reg_read32(®_rx_stats->ifInBroadcastPkts); + stats->etherStatsPkts = _40g_mac_reg_read32(®_rx_stats->etherStatsPkts); + stats->ifOutUcastPkts = _40g_mac_reg_read32(®_tx_stats->ifUcastPkts); + stats->ifOutMulticastPkts = _40g_mac_reg_read32(®_tx_stats->ifMulticastPkts); + stats->ifOutBroadcastPkts = _40g_mac_reg_read32(®_tx_stats->ifBroadcastPkts); + stats->ifInErrors = _40g_mac_reg_read32(®_rx_stats->ifInErrors); + stats->ifOutErrors = _40g_mac_reg_read32(®_tx_stats->ifOutErrors); + stats->aFramesReceivedOK = _40g_mac_reg_read32(®_rx_stats->FramesOK); + stats->aFramesTransmittedOK = _40g_mac_reg_read32(®_tx_stats->FramesOK); /* aOctetsReceivedOK = ifInOctets - 18 * aFramesReceivedOK - 4 * VLANReceivedOK */ - octets = al_eth_40g_mac_reg_read(adapter, 0x100); - octets |= (uint64_t)(al_eth_40g_mac_reg_read(adapter, 0x104)) << 32; + octets = _40g_mac_reg_read32(®_rx_stats->ifOctetsL); + octets |= (uint64_t)(_40g_mac_reg_read32(®_rx_stats->ifOctetsH)) << 32; octets -= 18 * stats->aFramesReceivedOK; - octets -= 4 * al_eth_40g_mac_reg_read(adapter, 0x130); /*VLANOK*/ - stats->aOctetsTransmittedOK = octets; - - /* aOctetsTransmittedOK = ifOutOctets - 18 * aFramesTransmittedOK - 4 * VLANTransmittedOK */ - octets = al_eth_40g_mac_reg_read(adapter, 0x200); - octets |= (uint64_t)(al_eth_40g_mac_reg_read(adapter, 0x204)) << 32; - octets -= 18 * stats->aFramesReceivedOK; - octets -= 4 * al_eth_40g_mac_reg_read(adapter, 0x230); /*VLANOK*/ + octets -= 4 * _40g_mac_reg_read32(®_rx_stats->VLANOK); stats->aOctetsReceivedOK = octets; - stats->etherStatsUndersizePkts = al_eth_40g_mac_reg_read(adapter, 0x168); - stats->etherStatsFragments = al_eth_40g_mac_reg_read(adapter, 0x1b8); - stats->etherStatsJabbers = al_eth_40g_mac_reg_read(adapter, 0x1b0); - stats->etherStatsOversizePkts = al_eth_40g_mac_reg_read(adapter, 0x1a8); - stats->aFrameCheckSequenceErrors = al_eth_40g_mac_reg_read(adapter, 0x128); - stats->aAlignmentErrors = al_eth_40g_mac_reg_read(adapter, 0x110); - stats->etherStatsDropEvents = al_eth_40g_mac_reg_read(adapter, 0x158); + /* aOctetsTransmittedOK = ifOutOctets - 18 * aFramesTransmittedOK - 4 * VLANTransmittedOK */ + octets = _40g_mac_reg_read32(®_tx_stats->ifOctetsL); + octets |= (uint64_t)(_40g_mac_reg_read32(®_tx_stats->ifOctetsH)) << 32; + octets -= 18 * stats->aFramesTransmittedOK; + octets -= 4 * _40g_mac_reg_read32(®_tx_stats->VLANOK); + stats->aOctetsTransmittedOK = octets; + + stats->etherStatsUndersizePkts = _40g_mac_reg_read32(®_rx_stats->etherStatsUndersizePkts); + stats->etherStatsFragments = _40g_mac_reg_read32(®_rx_stats->etherStatsFragments); + stats->etherStatsJabbers = _40g_mac_reg_read32(®_rx_stats->etherStatsJabbers); + stats->etherStatsOversizePkts = _40g_mac_reg_read32(®_rx_stats->etherStatsOversizePkts); + stats->aFrameCheckSequenceErrors = _40g_mac_reg_read32(®_rx_stats->CRCErrors); + stats->aAlignmentErrors = _40g_mac_reg_read32(®_rx_stats->aAlignmentErrors); + stats->etherStatsDropEvents = _40g_mac_reg_read32(®_rx_stats->etherStatsDropEvents); + stats->aPAUSEMACCtrlFramesTransmitted = _40g_mac_reg_read32(®_tx_stats->aPAUSEMACCtrlFrames); + stats->aPAUSEMACCtrlFramesReceived = _40g_mac_reg_read32(®_rx_stats->aPAUSEMACCtrlFrames); + stats->aFrameTooLongErrors = _40g_mac_reg_read32(®_rx_stats->aFrameTooLong); + stats->aInRangeLengthErrors = _40g_mac_reg_read32(®_rx_stats->aInRangeLengthErrors); + stats->VLANTransmittedOK = _40g_mac_reg_read32(®_tx_stats->VLANOK); + stats->VLANReceivedOK = _40g_mac_reg_read32(®_rx_stats->VLANOK); + stats->etherStatsOctets = _40g_mac_reg_read32(®_rx_stats->etherStatsOctets); + stats->etherStatsPkts64Octets = _40g_mac_reg_read32(®_rx_stats->etherStatsPkts64Octets); + stats->etherStatsPkts65to127Octets = _40g_mac_reg_read32(®_rx_stats->etherStatsPkts65to127Octets); + stats->etherStatsPkts128to255Octets = _40g_mac_reg_read32(®_rx_stats->etherStatsPkts128to255Octets); + stats->etherStatsPkts256to511Octets = _40g_mac_reg_read32(®_rx_stats->etherStatsPkts256to511Octets); + stats->etherStatsPkts512to1023Octets = _40g_mac_reg_read32(®_rx_stats->etherStatsPkts512to1023Octets); + stats->etherStatsPkts1024to1518Octets = _40g_mac_reg_read32(®_rx_stats->etherStatsPkts1024to1518Octets); + stats->etherStatsPkts1519toX = _40g_mac_reg_read32(®_rx_stats->etherStatsPkts1519toMax); } stats->eee_in = al_reg_read32(&adapter->mac_regs_base->stat.eee_in); @@ -3958,7 +4321,7 @@ int al_eth_flr_rmn(int (* pci_read_config_u32)(void *handle, int where, uint32_t al_reg_write32_masked(&mac_regs_base->gen.mux_sel, ETH_MAC_GEN_MUX_SEL_KR_IN_MASK, mux_sel); /* set SGMII clock to 125MHz */ - al_reg_write32(mac_base + 0xB08, 0x03320501); + al_reg_write32(&mac_regs_base->sgmii.clk_div, 0x03320501); /* reset 1G mac */ AL_REG_MASK_SET(reg, AL_ADAPTER_GENERIC_CONTROL_0_ETH_RESET_1GMAC); @@ -3971,15 +4334,15 @@ int al_eth_flr_rmn(int (* pci_read_config_u32)(void *handle, int where, uint32_t (*pci_write_config_u32)(handle, AL_ADAPTER_GENERIC_CONTROL_0, reg); /* reset SGMII mac clock to default */ - al_reg_write32(mac_base + 0xB08, 0x00320501); + al_reg_write32(&mac_regs_base->sgmii.clk_div, 0x00320501); al_udelay(1000); /* reset async fifo */ - reg = al_reg_read32((void*)((uint32_t)mac_base + 0x95c)); + reg = al_reg_read32(&mac_regs_base->gen.sd_fifo_ctrl); AL_REG_MASK_SET(reg, 0xF0); - al_reg_write32((void*)((uint32_t)mac_base + 0x95c), reg); - reg = al_reg_read32((void*)((uint32_t)mac_base + 0x95c)); + al_reg_write32(&mac_regs_base->gen.sd_fifo_ctrl, reg); + reg = al_reg_read32(&mac_regs_base->gen.sd_fifo_ctrl); AL_REG_MASK_CLEAR(reg, 0xF0); - al_reg_write32((void*)((uint32_t)mac_base + 0x95c), reg); + al_reg_write32(&mac_regs_base->gen.sd_fifo_ctrl, reg); return 0; } @@ -4028,6 +4391,7 @@ int al_eth_flr_rmn_restore_params(int (* pci_read_config_u32)(void *handle, int #define AL_HAL_ETH_EXT_PHY_IF_MASK (AL_FIELD_MASK(21, 20)) #define AL_HAL_ETH_EXT_PHY_IF_SHIFT 20 #define AL_HAL_ETH_AUTO_NEG_MODE_SHIFT 22 +#define AL_HAL_ETH_SERDES_GRP_2_SHIFT 23 #define AL_HAL_ETH_SERDES_GRP_MASK (AL_FIELD_MASK(26, 25)) #define AL_HAL_ETH_SERDES_GRP_SHIFT 25 #define AL_HAL_ETH_SERDES_LANE_MASK (AL_FIELD_MASK(28, 27)) @@ -4054,9 +4418,19 @@ int al_eth_flr_rmn_restore_params(int (* pci_read_config_u32)(void *handle, int #define AL_HAL_ETH_DAC_SHIFT 24 #define AL_HAL_ETH_RETIMER_TYPE_MASK (AL_FIELD_MASK(26, 25)) #define AL_HAL_ETH_RETIMER_TYPE_SHIFT 25 +#define AL_HAL_ETH_RETIMER_CHANNEL_2_MASK (AL_FIELD_MASK(28, 27)) #define AL_HAL_ETH_RETIMER_CHANNEL_2_SHIFT 27 +#define AL_HAL_ETH_RETIMER_TX_CHANNEL_MASK (AL_FIELD_MASK(31, 29)) +#define AL_HAL_ETH_RETIMER_TX_CHANNEL_SHIFT 29 -int al_eth_board_params_set(void * __iomem mac_base, struct al_eth_board_params *params){ +/* board params register 3 */ +#define AL_HAL_ETH_GPIO_SFP_PRESENT_MASK (AL_FIELD_MASK(5, 0)) +#define AL_HAL_ETH_GPIO_SFP_PRESENT_SHIFT 0 + +int al_eth_board_params_set(void * __iomem mac_base, struct al_eth_board_params *params) +{ + struct al_eth_mac_regs __iomem *mac_regs_base = + (struct al_eth_mac_regs __iomem *)mac_base; uint32_t reg = 0; /* ************* Setting Board params register 1 **************** */ @@ -4083,6 +4457,10 @@ int al_eth_board_params_set(void * __iomem mac_base, struct al_eth_board_params AL_REG_FIELD_SET(reg, AL_HAL_ETH_SERDES_GRP_MASK, AL_HAL_ETH_SERDES_GRP_SHIFT, params->serdes_grp); + + AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_SERDES_GRP_2_SHIFT, + (params->serdes_grp & AL_BIT(2)) ? 1 : 0); + AL_REG_FIELD_SET(reg, AL_HAL_ETH_SERDES_LANE_MASK, AL_HAL_ETH_SERDES_LANE_SHIFT, params->serdes_lane); @@ -4091,7 +4469,7 @@ int al_eth_board_params_set(void * __iomem mac_base, struct al_eth_board_params al_assert(reg != 0); - al_reg_write32(mac_base + 0x4, reg); + al_reg_write32(&mac_regs_base->mac_1g.scratch, reg); /* ************* Setting Board params register 2 **************** */ reg = 0; @@ -4120,12 +4498,11 @@ int al_eth_board_params_set(void * __iomem mac_base, struct al_eth_board_params AL_HAL_ETH_RETIMER_I2C_ADDR_SHIFT, params->retimer_i2c_addr); AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_RETIMER_CHANNEL_SHIFT, - ((params->retimer_channel == AL_ETH_RETIMER_CHANNEL_B) || - (params->retimer_channel == AL_ETH_RETIMER_CHANNEL_D))); + (params->retimer_channel & AL_BIT(0))); - AL_REG_BIT_VAL_SET(reg, AL_HAL_ETH_RETIMER_CHANNEL_2_SHIFT, - ((params->retimer_channel == AL_ETH_RETIMER_CHANNEL_C) || - (params->retimer_channel == AL_ETH_RETIMER_CHANNEL_D))); + AL_REG_FIELD_SET(reg, AL_HAL_ETH_RETIMER_CHANNEL_2_MASK, + AL_HAL_ETH_RETIMER_CHANNEL_2_SHIFT, + (AL_REG_FIELD_GET(params->retimer_channel, 0x6, 1))); AL_REG_FIELD_SET(reg, AL_HAL_ETH_DAC_LENGTH_MASK, AL_HAL_ETH_DAC_LENGTH_SHIFT, params->dac_len); @@ -4134,12 +4511,29 @@ int al_eth_board_params_set(void * __iomem mac_base, struct al_eth_board_params AL_REG_FIELD_SET(reg, AL_HAL_ETH_RETIMER_TYPE_MASK, AL_HAL_ETH_RETIMER_TYPE_SHIFT, params->retimer_type); - al_reg_write32(mac_base + 0x404, reg); + AL_REG_FIELD_SET(reg, AL_HAL_ETH_RETIMER_TX_CHANNEL_MASK, + AL_HAL_ETH_RETIMER_TX_CHANNEL_SHIFT, + params->retimer_tx_channel); + + al_reg_write32(&mac_regs_base->mac_10g.scratch, reg); + + /* ************* Setting Board params register 3 **************** */ + reg = 0; + + AL_REG_FIELD_SET(reg, AL_HAL_ETH_GPIO_SFP_PRESENT_MASK, + AL_HAL_ETH_GPIO_SFP_PRESENT_SHIFT, + params->gpio_sfp_present); + + al_reg_write32(&mac_regs_base->mac_1g.mac_0, reg); + return 0; } -int al_eth_board_params_get(void * __iomem mac_base, struct al_eth_board_params *params){ - uint32_t reg = al_reg_read32((void*)((uint32_t)mac_base + 0x4)); +int al_eth_board_params_get(void * __iomem mac_base, struct al_eth_board_params *params) +{ + struct al_eth_mac_regs __iomem *mac_regs_base = + (struct al_eth_mac_regs __iomem *)mac_base; + uint32_t reg = al_reg_read32(&mac_regs_base->mac_1g.scratch); /* check if the register was initialized, 0 is not a valid value */ if (reg == 0) @@ -4197,6 +4591,8 @@ int al_eth_board_params_get(void * __iomem mac_base, struct al_eth_board_params AL_HAL_ETH_SERDES_GRP_MASK, AL_HAL_ETH_SERDES_GRP_SHIFT); + params->serdes_grp |= (AL_REG_BIT_GET(reg, AL_HAL_ETH_SERDES_GRP_2_SHIFT) ? AL_BIT(2) : 0); + params->serdes_lane = AL_REG_FIELD_GET(reg, AL_HAL_ETH_SERDES_LANE_MASK, AL_HAL_ETH_SERDES_LANE_SHIFT); @@ -4206,7 +4602,7 @@ int al_eth_board_params_get(void * __iomem mac_base, struct al_eth_board_params AL_HAL_ETH_REF_CLK_FREQ_SHIFT); /* ************* Getting Board params register 2 **************** */ - reg = al_reg_read32((void*)((uint32_t)mac_base + 0x404)); + reg = al_reg_read32(&mac_regs_base->mac_10g.scratch); if (AL_REG_BIT_GET(reg, AL_HAL_ETH_DONT_OVERRIDE_SERDES_SHIFT)) params->dont_override_serdes = AL_TRUE; else @@ -4250,7 +4646,8 @@ int al_eth_board_params_get(void * __iomem mac_base, struct al_eth_board_params params->retimer_channel = ((AL_REG_BIT_GET(reg, AL_HAL_ETH_RETIMER_CHANNEL_SHIFT)) | - (AL_REG_BIT_GET(reg, AL_HAL_ETH_RETIMER_CHANNEL_2_SHIFT) << 1)); + (AL_REG_FIELD_GET(reg, AL_HAL_ETH_RETIMER_CHANNEL_2_MASK, + AL_HAL_ETH_RETIMER_CHANNEL_2_SHIFT) << 1)); params->dac_len = AL_REG_FIELD_GET(reg, AL_HAL_ETH_DAC_LENGTH_MASK, @@ -4265,6 +4662,17 @@ int al_eth_board_params_get(void * __iomem mac_base, struct al_eth_board_params AL_HAL_ETH_RETIMER_TYPE_MASK, AL_HAL_ETH_RETIMER_TYPE_SHIFT); + params->retimer_tx_channel = AL_REG_FIELD_GET(reg, + AL_HAL_ETH_RETIMER_TX_CHANNEL_MASK, + AL_HAL_ETH_RETIMER_TX_CHANNEL_SHIFT); + + /* ************* Getting Board params register 3 **************** */ + reg = al_reg_read32(&mac_regs_base->mac_1g.mac_0); + + params->gpio_sfp_present = AL_REG_FIELD_GET(reg, + AL_HAL_ETH_GPIO_SFP_PRESENT_MASK, + AL_HAL_ETH_GPIO_SFP_PRESENT_SHIFT); + return 0; } From d8f1c69cc20a9cc56b2c77a054ea2fccd1abace2 Mon Sep 17 00:00:00 2001 From: Wojciech Macek Date: Tue, 6 Sep 2016 15:06:08 +0000 Subject: [PATCH 025/109] Remove check for 64-bit FDT ranges in pci-host-generic This allows 32-bit platforms to use pci-host-generic. Obtained from: Semihalf Submitted by: Michal Stanek Sponsored by: Annapurna Labs Reviewed by: wma Differential Revision: https://reviews.freebsd.org/D7560 --- sys/dev/pci/pci_host_generic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/pci/pci_host_generic.c b/sys/dev/pci/pci_host_generic.c index e95543dc4fd..ed26b08ed8e 100644 --- a/sys/dev/pci/pci_host_generic.c +++ b/sys/dev/pci/pci_host_generic.c @@ -281,7 +281,7 @@ parse_pci_mem_ranges(struct generic_pcie_softc *sc) OF_getencprop(OF_parent(node), "#address-cells", &parent_addr_cells, sizeof(parent_addr_cells)); - if (parent_addr_cells != 2 || pci_addr_cells != 3 || size_cells != 2) { + if (parent_addr_cells > 2 || pci_addr_cells != 3 || size_cells > 2) { device_printf(sc->dev, "Unexpected number of address or size cells in FDT\n"); return (ENXIO); From aab9fdaf6ffbdeb0335883596fc7aedae1412794 Mon Sep 17 00:00:00 2001 From: Wojciech Macek Date: Tue, 6 Sep 2016 15:11:37 +0000 Subject: [PATCH 026/109] Import missing enum declaration in pci_host_generic header file Other files including pci_host_generic.h failed to compile due to missing declaration of enum pci_id_type. Obtained from: Semihalf Submitted by: Michal Stanek Sponsored by: Annapurna Labs Reviewed by: wma Differential Revision: https://reviews.freebsd.org/D7561 --- sys/dev/pci/pci_host_generic.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/dev/pci/pci_host_generic.h b/sys/dev/pci/pci_host_generic.h index 3b307b48a5e..adb5934c9cc 100644 --- a/sys/dev/pci/pci_host_generic.h +++ b/sys/dev/pci/pci_host_generic.h @@ -34,6 +34,8 @@ #ifndef __PCI_HOST_GENERIC_H_ #define __PCI_HOST_GENERIC_H_ +#include "pci_if.h" + #define MAX_RANGES_TUPLES 16 #define MIN_RANGES_TUPLES 2 From 949b56ba6637de7aca061d12795740d6245dda21 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Tue, 6 Sep 2016 15:17:35 +0000 Subject: [PATCH 027/109] Renumber the advertising clause. --- lib/libstand/ufs.c | 2 +- sys/ufs/ffs/fs.h | 2 +- sys/ufs/ufs/dir.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/libstand/ufs.c b/lib/libstand/ufs.c index 21e341f1494..ed06dcae60a 100644 --- a/lib/libstand/ufs.c +++ b/lib/libstand/ufs.c @@ -24,7 +24,7 @@ * 2. 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. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/sys/ufs/ffs/fs.h b/sys/ufs/ffs/fs.h index 620fee95d56..c2f77a58556 100644 --- a/sys/ufs/ffs/fs.h +++ b/sys/ufs/ffs/fs.h @@ -10,7 +10,7 @@ * 2. 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. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/sys/ufs/ufs/dir.h b/sys/ufs/ufs/dir.h index 574a32f9e7f..b94d64a784b 100644 --- a/sys/ufs/ufs/dir.h +++ b/sys/ufs/ufs/dir.h @@ -15,7 +15,7 @@ * 2. 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. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * From 5b7d9ae2fd435be7eb653ac3eb5d66e9f3d55a52 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Tue, 6 Sep 2016 17:16:59 +0000 Subject: [PATCH 028/109] cv: do a lockless check for no waiters in cv_signal and cv_broadcastpri In case of some consumers like zfs there are no waiters vast majority of the time Reviewed by: jhb MFC after: 1 week --- sys/kern/kern_condvar.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/kern/kern_condvar.c b/sys/kern/kern_condvar.c index d4b477f3d59..5b10914fe03 100644 --- a/sys/kern/kern_condvar.c +++ b/sys/kern/kern_condvar.c @@ -397,6 +397,8 @@ cv_signal(struct cv *cvp) { int wakeup_swapper; + if (cvp->cv_waiters == 0) + return; wakeup_swapper = 0; sleepq_lock(cvp); if (cvp->cv_waiters > 0) { @@ -424,6 +426,8 @@ cv_broadcastpri(struct cv *cvp, int pri) { int wakeup_swapper; + if (cvp->cv_waiters == 0) + return; /* * XXX sleepq_broadcast pri argument changed from -1 meaning * no pri to 0 meaning no pri. From 3d1eb084e9da73ed9339674bb1c2f8e570f7fe0a Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Tue, 6 Sep 2016 17:22:25 +0000 Subject: [PATCH 029/109] Fix tests/sys/kqueue NetBSD tests on 32-bit platforms by using proper format specifier for pointers when printing them out with printf(3) MFC after: 57 days Pointyhat to: ngie Reported by: bz, cy, Jenkins (i386 job) Submitted by: cy Sponsored by: EMC / Isilon Storage Division --- contrib/netbsd-tests/kernel/kqueue/read/t_fifo.c | 4 ++++ contrib/netbsd-tests/kernel/kqueue/read/t_file.c | 4 ++++ contrib/netbsd-tests/kernel/kqueue/read/t_pipe.c | 4 ++++ contrib/netbsd-tests/kernel/kqueue/read/t_ttypty.c | 4 ++++ contrib/netbsd-tests/kernel/kqueue/t_proc1.c | 4 ++++ contrib/netbsd-tests/kernel/kqueue/t_sig.c | 4 ++++ 6 files changed, 24 insertions(+) diff --git a/contrib/netbsd-tests/kernel/kqueue/read/t_fifo.c b/contrib/netbsd-tests/kernel/kqueue/read/t_fifo.c index 5908547693c..19c7b02ea32 100644 --- a/contrib/netbsd-tests/kernel/kqueue/read/t_fifo.c +++ b/contrib/netbsd-tests/kernel/kqueue/read/t_fifo.c @@ -78,7 +78,11 @@ ATF_TC_BODY(fifo, tc) RL(n = kevent(kq, NULL, 0, event, 1, NULL)); (void)printf("kevent num %d filt %d flags: %#x, fflags: %#x, " +#ifdef __FreeBSD__ + "data: %" PRIdPTR "\n", n, event[0].filter, event[0].flags, +#else "data: %" PRId64 "\n", n, event[0].filter, event[0].flags, +#endif event[0].fflags, event[0].data); ATF_REQUIRE_EQ(event[0].filter, EVFILT_READ); diff --git a/contrib/netbsd-tests/kernel/kqueue/read/t_file.c b/contrib/netbsd-tests/kernel/kqueue/read/t_file.c index 23351729796..80479afc7f7 100644 --- a/contrib/netbsd-tests/kernel/kqueue/read/t_file.c +++ b/contrib/netbsd-tests/kernel/kqueue/read/t_file.c @@ -111,7 +111,11 @@ ATF_TC_BODY(file, tc) num += n; (void)printf("kevent num %d flags: %#x, fflags: %#x, data: " +#ifdef __FreeBSD__ + "%" PRIdPTR "\n", n, event[0].flags, event[0].fflags, +#else "%" PRId64 "\n", n, event[0].flags, event[0].fflags, +#endif event[0].data); if (event[0].data < 0) diff --git a/contrib/netbsd-tests/kernel/kqueue/read/t_pipe.c b/contrib/netbsd-tests/kernel/kqueue/read/t_pipe.c index d8e05f262e3..2cdd0159341 100644 --- a/contrib/netbsd-tests/kernel/kqueue/read/t_pipe.c +++ b/contrib/netbsd-tests/kernel/kqueue/read/t_pipe.c @@ -67,7 +67,11 @@ ATF_TC_BODY(pipe, tc) RL(n = kevent(kq, NULL, 0, event, 1, NULL)); (void)printf("kevent num %d flags: %#x, fflags: %#x, data: " +#ifdef __FreeBSD__ + "%" PRIdPTR "\n", n, event[0].flags, event[0].fflags, event[0].data); +#else "%" PRId64 "\n", n, event[0].flags, event[0].fflags, event[0].data); +#endif RL(n = read(fds[0], buffer, event[0].data)); buffer[n] = '\0'; diff --git a/contrib/netbsd-tests/kernel/kqueue/read/t_ttypty.c b/contrib/netbsd-tests/kernel/kqueue/read/t_ttypty.c index 3a42fd3927f..57ccf925625 100644 --- a/contrib/netbsd-tests/kernel/kqueue/read/t_ttypty.c +++ b/contrib/netbsd-tests/kernel/kqueue/read/t_ttypty.c @@ -103,7 +103,11 @@ h_check(bool check_master) RL(n = kevent(kq, NULL, 0, event, 1, NULL)); (void)printf("kevent num %d filt %d flags: %#x, fflags: %#x, " +#ifdef __FreeBSD__ + "data: %" PRIdPTR "\n", n, event[0].filter, event[0].flags, +#else "data: %" PRId64 "\n", n, event[0].filter, event[0].flags, +#endif event[0].fflags, event[0].data); ATF_REQUIRE_EQ(event[0].filter, EVFILT_READ); diff --git a/contrib/netbsd-tests/kernel/kqueue/t_proc1.c b/contrib/netbsd-tests/kernel/kqueue/t_proc1.c index 07d5a3c0279..aa806ba1a8f 100644 --- a/contrib/netbsd-tests/kernel/kqueue/t_proc1.c +++ b/contrib/netbsd-tests/kernel/kqueue/t_proc1.c @@ -139,7 +139,11 @@ ATF_TC_BODY(proc1, tc) printf(" NOTE_FORK"); } if (event[0].fflags & NOTE_CHILD) +#ifdef __FreeBSD__ + printf(" NOTE_CHILD, parent = %" PRIdPTR, event[0].data); +#else printf(" NOTE_CHILD, parent = %" PRId64, event[0].data); +#endif printf("\n"); } diff --git a/contrib/netbsd-tests/kernel/kqueue/t_sig.c b/contrib/netbsd-tests/kernel/kqueue/t_sig.c index 8726fe98bb7..ebbd76ec887 100644 --- a/contrib/netbsd-tests/kernel/kqueue/t_sig.c +++ b/contrib/netbsd-tests/kernel/kqueue/t_sig.c @@ -130,7 +130,11 @@ ATF_TC_BODY(sig, tc) if (n == 0) continue; +#ifdef __FreeBSD__ + (void)printf("sig: kevent flags: 0x%x, data: %" PRIdPTR " (# " +#else (void)printf("sig: kevent flags: 0x%x, data: %" PRId64 " (# " +#endif "times signal posted)\n", event[0].flags, event[0].data); } From d945328992cdfced70ff3cf4ceb3c4c5445b837c Mon Sep 17 00:00:00 2001 From: Will Andrews Date: Tue, 6 Sep 2016 17:58:58 +0000 Subject: [PATCH 030/109] loader.efi: Bump the staging size to 64M. This is required on my system, which loads nvidia, vmm, and zfs, and 48M is no longer enough for that. nvidia-driver's recent update increased its size by several megabytes. Reviewed by: jhb MFC after: 1 week --- sys/boot/efi/loader/copy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/boot/efi/loader/copy.c b/sys/boot/efi/loader/copy.c index 128196e2696..8d026b3a230 100644 --- a/sys/boot/efi/loader/copy.c +++ b/sys/boot/efi/loader/copy.c @@ -40,7 +40,7 @@ __FBSDID("$FreeBSD$"); #include "loader_efi.h" #ifndef EFI_STAGING_SIZE -#define EFI_STAGING_SIZE 48 +#define EFI_STAGING_SIZE 64 #endif #define STAGE_PAGES EFI_SIZE_TO_PAGES((EFI_STAGING_SIZE) * 1024 * 1024) From 5fb03c3780809f666f89a9e6bbca2f7b8fb513f3 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 6 Sep 2016 18:53:17 +0000 Subject: [PATCH 031/109] Leave ppt devices in the host domain when they are not attached to a VM. This allows a pass through device to be reset to a normal device driver on the host and reused on the host. ppt devices are now always active in some I/O MMU domain when the I/O MMU is active, either the host domain or the domain of a VM they are attached to. Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D7666 --- sys/amd64/vmm/io/iommu.c | 8 +------- sys/amd64/vmm/io/ppt.c | 2 ++ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/sys/amd64/vmm/io/iommu.c b/sys/amd64/vmm/io/iommu.c index 524b150ed91..b17953549e9 100644 --- a/sys/amd64/vmm/io/iommu.c +++ b/sys/amd64/vmm/io/iommu.c @@ -158,7 +158,6 @@ iommu_init(void) { int error, bus, slot, func; vm_paddr_t maxaddr; - const char *name; device_t dev; if (!iommu_enable) @@ -203,12 +202,7 @@ iommu_init(void) if (dev == NULL) continue; - /* skip passthrough devices */ - name = device_get_name(dev); - if (name != NULL && strcmp(name, "ppt") == 0) - continue; - - /* everything else belongs to the host domain */ + /* Everything belongs to the host domain. */ iommu_add_device(host_domain, pci_get_rid(dev)); } diff --git a/sys/amd64/vmm/io/ppt.c b/sys/amd64/vmm/io/ppt.c index 692190a5c2b..6541d7d2994 100644 --- a/sys/amd64/vmm/io/ppt.c +++ b/sys/amd64/vmm/io/ppt.c @@ -363,6 +363,7 @@ ppt_assign_device(struct vm *vm, int bus, int slot, int func) return (EBUSY); ppt->vm = vm; + iommu_remove_device(iommu_host_domain(), pci_get_rid(ppt->dev)); iommu_add_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev)); return (0); } @@ -385,6 +386,7 @@ ppt_unassign_device(struct vm *vm, int bus, int slot, int func) ppt_teardown_msi(ppt); ppt_teardown_msix(ppt); iommu_remove_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev)); + iommu_add_device(iommu_host_domain(), pci_get_rid(ppt->dev)); ppt->vm = NULL; return (0); } From e3d9ae4c56e15404846e4cb3360394a0a36cec23 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Tue, 6 Sep 2016 19:00:37 +0000 Subject: [PATCH 032/109] bspatch: add sanity checks on sizes to avoid integer overflow Note that this introduces an explicit 2GB limit, but this was already implicit in variable and function argument types. This is based on the "non-cryptanalytic attacks against freebsd update components" anonymous gist. Further refinement is planned. Reviewed by: allanjude, cem, kib Obtained from: anonymous gist MFC after: 3 days Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D7619 --- usr.bin/bsdiff/bspatch/bspatch.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/usr.bin/bsdiff/bspatch/bspatch.c b/usr.bin/bsdiff/bspatch/bspatch.c index 5f6679c58f8..4e65dcdb784 100644 --- a/usr.bin/bsdiff/bspatch/bspatch.c +++ b/usr.bin/bsdiff/bspatch/bspatch.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -98,8 +99,8 @@ int main(int argc, char *argv[]) char *directory, *namebuf; int cbz2err, dbz2err, ebz2err; int newfd, oldfd; - ssize_t oldsize, newsize; - ssize_t bzctrllen, bzdatalen; + off_t oldsize, newsize; + off_t bzctrllen, bzdatalen; u_char header[32], buf[8]; u_char *old, *new; off_t oldpos, newpos; @@ -194,7 +195,9 @@ int main(int argc, char *argv[]) bzctrllen = offtin(header + 8); bzdatalen = offtin(header + 16); newsize = offtin(header + 24); - if ((bzctrllen < 0) || (bzdatalen < 0) || (newsize < 0)) + if (bzctrllen < 0 || bzctrllen > OFF_MAX - 32 || + bzdatalen < 0 || bzctrllen + 32 > OFF_MAX - bzdatalen || + newsize < 0 || newsize > SSIZE_MAX) errx(1, "Corrupt patch\n"); /* Close patch file and re-open it via libbzip2 at the right places */ @@ -217,12 +220,13 @@ int main(int argc, char *argv[]) errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err); if ((oldsize = lseek(oldfd, 0, SEEK_END)) == -1 || - (old = malloc(oldsize+1)) == NULL || + oldsize > SSIZE_MAX || + (old = malloc(oldsize)) == NULL || lseek(oldfd, 0, SEEK_SET) != 0 || read(oldfd, old, oldsize) != oldsize || close(oldfd) == -1) err(1, "%s", argv[1]); - if ((new = malloc(newsize + 1)) == NULL) + if ((new = malloc(newsize)) == NULL) err(1, NULL); oldpos = 0; @@ -238,7 +242,8 @@ int main(int argc, char *argv[]) } /* Sanity-check */ - if ((ctrl[0] < 0) || (ctrl[1] < 0)) + if (ctrl[0] < 0 || ctrl[0] > INT_MAX || + ctrl[1] < 0 || ctrl[1] > INT_MAX) errx(1, "Corrupt patch\n"); /* Sanity-check */ From db4b3cdad83dcc43b13407b1c02c9ed785bccc4b Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 6 Sep 2016 19:25:32 +0000 Subject: [PATCH 033/109] Remove remnants of PERFMON and I586_PMC_GUPROF from amd64. These options were never fully ported over from i386. --- sys/amd64/amd64/machdep.c | 7 --- sys/amd64/amd64/prof_machdep.c | 96 ++-------------------------------- sys/amd64/conf/NOTES | 6 --- sys/conf/options.amd64 | 1 - sys/x86/x86/cpu_machdep.c | 4 -- 5 files changed, 3 insertions(+), 111 deletions(-) diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 26c6e0fcc3e..19691f3dcf9 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$"); #include "opt_kstack_pages.h" #include "opt_maxmem.h" #include "opt_mp_watchdog.h" -#include "opt_perfmon.h" #include "opt_platform.h" #include "opt_sched.h" @@ -125,9 +124,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#ifdef PERFMON -#include -#endif #include #ifdef SMP #include @@ -274,9 +270,6 @@ cpu_startup(dummy) startrtclock(); printcpuinfo(); panicifcpuunsupported(); -#ifdef PERFMON - perfmon_init(); -#endif /* * Display physical memory if SMBIOS reports reasonable amount. diff --git a/sys/amd64/amd64/prof_machdep.c b/sys/amd64/amd64/prof_machdep.c index 273c8336fca..d111d455a42 100644 --- a/sys/amd64/amd64/prof_machdep.c +++ b/sys/amd64/amd64/prof_machdep.c @@ -28,10 +28,6 @@ __FBSDID("$FreeBSD$"); #ifdef GUPROF -#if 0 -#include "opt_i586_guprof.h" -#include "opt_perfmon.h" -#endif #include #include @@ -44,25 +40,16 @@ __FBSDID("$FreeBSD$"); #include #include -#if 0 -#include -#endif #include #define CPUTIME_CLOCK_UNINITIALIZED 0 #define CPUTIME_CLOCK_I8254 1 #define CPUTIME_CLOCK_TSC 2 -#define CPUTIME_CLOCK_I586_PMC 3 #define CPUTIME_CLOCK_I8254_SHIFT 7 int cputime_bias = 1; /* initialize for locality of reference */ static int cputime_clock = CPUTIME_CLOCK_UNINITIALIZED; -#if defined(PERFMON) && defined(I586_PMC_GUPROF) -static u_int cputime_clock_pmc_conf = I586_PMC_GUPROF; -static int cputime_clock_pmc_init; -static struct gmonparam saved_gmp; -#endif static int cputime_prof_active; #endif /* GUPROF */ @@ -198,9 +185,6 @@ cputime() { u_int count; int delta; -#if defined(PERFMON) && defined(I586_PMC_GUPROF) && !defined(SMP) - u_quad_t event_count; -#endif u_char high, low; static u_int prev_count; @@ -217,21 +201,6 @@ cputime() prev_count = count; return (delta); } -#if defined(PERFMON) && defined(I586_PMC_GUPROF) && !defined(SMP) - if (cputime_clock == CPUTIME_CLOCK_I586_PMC) { - /* - * XXX permon_read() should be inlined so that the - * perfmon module doesn't need to be compiled with - * profiling disabled and so that it is fast. - */ - perfmon_read(0, &event_count); - - count = (u_int)event_count; - delta = (int)(count - prev_count); - prev_count = count; - return (delta); - } -#endif /* PERFMON && I586_PMC_GUPROF && !SMP */ /* * Read the current value of the 8254 timer counter 0. @@ -262,39 +231,13 @@ sysctl_machdep_cputime_clock(SYSCTL_HANDLER_ARGS) { int clock; int error; -#if defined(PERFMON) && defined(I586_PMC_GUPROF) - int event; - struct pmc pmc; -#endif clock = cputime_clock; -#if defined(PERFMON) && defined(I586_PMC_GUPROF) - if (clock == CPUTIME_CLOCK_I586_PMC) { - pmc.pmc_val = cputime_clock_pmc_conf; - clock += pmc.pmc_event; - } -#endif error = sysctl_handle_opaque(oidp, &clock, sizeof clock, req); if (error == 0 && req->newptr != NULL) { -#if defined(PERFMON) && defined(I586_PMC_GUPROF) - if (clock >= CPUTIME_CLOCK_I586_PMC) { - event = clock - CPUTIME_CLOCK_I586_PMC; - if (event >= 256) - return (EINVAL); - pmc.pmc_num = 0; - pmc.pmc_event = event; - pmc.pmc_unit = 0; - pmc.pmc_flags = PMCF_E | PMCF_OS | PMCF_USR; - pmc.pmc_mask = 0; - cputime_clock_pmc_conf = pmc.pmc_val; - cputime_clock = CPUTIME_CLOCK_I586_PMC; - } else -#endif - { - if (clock < 0 || clock >= CPUTIME_CLOCK_I586_PMC) - return (EINVAL); - cputime_clock = clock; - } + if (clock < 0 || clock > CPUTIME_CLOCK_TSC) + return (EINVAL); + cputime_clock = clock; } return (error); } @@ -325,32 +268,6 @@ startguprof(gp) cputime_prof_active = 1; } else gp->profrate = i8254_freq << CPUTIME_CLOCK_I8254_SHIFT; -#if defined(PERFMON) && defined(I586_PMC_GUPROF) - if (cputime_clock == CPUTIME_CLOCK_I586_PMC) { - if (perfmon_avail() && - perfmon_setup(0, cputime_clock_pmc_conf) == 0) { - if (perfmon_start(0) != 0) - perfmon_fini(0); - else { - /* XXX 1 event == 1 us. */ - gp->profrate = 1000000; - - saved_gmp = *gp; - - /* Zap overheads. They are invalid. */ - gp->cputime_overhead = 0; - gp->mcount_overhead = 0; - gp->mcount_post_overhead = 0; - gp->mcount_pre_overhead = 0; - gp->mexitcount_overhead = 0; - gp->mexitcount_post_overhead = 0; - gp->mexitcount_pre_overhead = 0; - - cputime_clock_pmc_init = TRUE; - } - } - } -#endif /* PERFMON && I586_PMC_GUPROF */ cputime_bias = 0; cputime(); } @@ -359,13 +276,6 @@ void stopguprof(gp) struct gmonparam *gp; { -#if defined(PERFMON) && defined(I586_PMC_GUPROF) - if (cputime_clock_pmc_init) { - *gp = saved_gmp; - perfmon_fini(0); - cputime_clock_pmc_init = FALSE; - } -#endif if (cputime_clock == CPUTIME_CLOCK_TSC) cputime_prof_active = 0; } diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES index 61a5953cb3d..2c3ca3e78d0 100644 --- a/sys/amd64/conf/NOTES +++ b/sys/amd64/conf/NOTES @@ -73,12 +73,6 @@ cpu HAMMER # aka K8, aka Opteron & Athlon64 # Options for CPU features. # -# -# PERFMON causes the driver for Pentium/Pentium Pro performance counters -# to be compiled. See perfmon(4) for more information. -# -#XXX#options PERFMON - ##################################################################### # NETWORKING OPTIONS diff --git a/sys/conf/options.amd64 b/sys/conf/options.amd64 index f1d4b4a57e4..532df6fb92f 100644 --- a/sys/conf/options.amd64 +++ b/sys/conf/options.amd64 @@ -6,7 +6,6 @@ AUTO_EOI_2 opt_auto_eoi.h COUNT_XINVLTLB_HITS opt_smp.h COUNT_IPIS opt_smp.h MAXMEM -PERFMON MPTABLE_FORCE_HTT MP_WATCHDOG NKPT opt_pmap.h diff --git a/sys/x86/x86/cpu_machdep.c b/sys/x86/x86/cpu_machdep.c index f07b97e7901..551a514e1f4 100644 --- a/sys/x86/x86/cpu_machdep.c +++ b/sys/x86/x86/cpu_machdep.c @@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$"); #include "opt_kstack_pages.h" #include "opt_maxmem.h" #include "opt_mp_watchdog.h" -#include "opt_perfmon.h" #include "opt_platform.h" #ifdef __i386__ #include "opt_npx.h" @@ -83,9 +82,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#ifdef PERFMON -#include -#endif #include #ifdef SMP #include From a4554c37367746c53e28ab065fb6ed43e6ebe234 Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Tue, 6 Sep 2016 19:36:28 +0000 Subject: [PATCH 034/109] Let knlist_add do the locking part Remove explicit mtx_lock/mtx_unlock around knlist_add and pass 0 as locked parameter so knlist_add does the locking itself Suggested by: kib@ --- sys/arm/ti/ti_pruss.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sys/arm/ti/ti_pruss.c b/sys/arm/ti/ti_pruss.c index c82d23f4ed0..cbf8050a57b 100644 --- a/sys/arm/ti/ti_pruss.c +++ b/sys/arm/ti/ti_pruss.c @@ -310,9 +310,7 @@ ti_pruss_kqfilter(struct cdev *cdev, struct knote *kn) case EVFILT_READ: kn->kn_hook = sc; kn->kn_fop = &ti_pruss_kq_read; - mtx_lock(&sc->sc_mtx); - knlist_add(&sc->sc_selinfo.si_note, kn, 1); - mtx_unlock(&sc->sc_mtx); + knlist_add(&sc->sc_selinfo.si_note, kn, 0); break; default: return (EINVAL); From 64414cc00fb76d5ae12d483c3d4ae46d3009c46f Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 6 Sep 2016 20:17:54 +0000 Subject: [PATCH 035/109] Update the I/O MMU in bhyve when PCI devices are added and removed. When the I/O MMU is active in bhyve, all PCI devices need valid entries in the DMAR context tables. The I/O MMU code does a single enumeration of the available PCI devices during initialization to add all existing devices to a domain representing the host. The ppt(4) driver then moves pass through devices in and out of domains for virtual machines as needed. However, when new PCI devices were added at runtime either via SR-IOV or HotPlug, the I/O MMU tables were not updated. This change adds a new set of EVENTHANDLERS that are invoked when PCI devices are added and deleted. The I/O MMU driver in bhyve installs handlers for these events which it uses to add and remove devices to the "host" domain. Reviewed by: imp Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D7667 --- share/man/man9/pci.9 | 25 ++++++++++++++++++++++++- sys/amd64/vmm/io/iommu.c | 28 ++++++++++++++++++++++++++++ sys/dev/pci/pci.c | 3 +++ sys/dev/pci/pcivar.h | 9 +++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/share/man/man9/pci.9 b/share/man/man9/pci.9 index 1a4c5deb8a9..209986b1b1a 100644 --- a/share/man/man9/pci.9 +++ b/share/man/man9/pci.9 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 1, 2016 +.Dd September 6, 2016 .Dt PCI 9 .Os .Sh NAME @@ -149,6 +149,10 @@ .Fn pcie_read_config "device_t dev" "int reg" "int width" .Ft void .Fn pcie_write_config "device_t dev" "int reg" "uint32_t val" "int width" +.Ft void +.Fn pci_event_fn "void *arg" "device_t dev" +.Fn EVENTHANDLER_REGISTER "pci_add_device" "pci_event_fn" +.Fn EVENTHANDLER_DEREGISTER "pci_delete_resource" "pci_event_fn" .In dev/pci/pci_iov.h .Ft int .Fn pci_iov_attach "device_t dev" "nvlist_t *pf_schema" "nvlist_t *vf_schema" @@ -910,6 +914,24 @@ with one in the new distribution. The .Fn pci_remap_msix function will fail if this condition is not met. +.Ss Device Events +The +.Va pci_add_device +event handler is invoked every time a new PCI device is added to the system. +This includes the creation of Virtual Functions via SR-IOV. +.Pp +The +.Va pci_delete_device +event handler is invoked every time a PCI device is removed from the system. +.Pp +Both event handlers pass the +.Vt device_t +object of the relevant PCI device as +.Fa dev +to each callback function. +Both event handlers are invoked while +.Fa dev +is unattached but with valid instance variables. .Sh SEE ALSO .Xr pci 4 , .Xr pciconf 8 , @@ -921,6 +943,7 @@ function will fail if this condition is not met. .Xr devclass 9 , .Xr device 9 , .Xr driver 9 , +.Xr eventhandler 9 , .Xr rman 9 .Rs .%B FreeBSD Developers' Handbook diff --git a/sys/amd64/vmm/io/iommu.c b/sys/amd64/vmm/io/iommu.c index b17953549e9..75cf1ecceec 100644 --- a/sys/amd64/vmm/io/iommu.c +++ b/sys/amd64/vmm/io/iommu.c @@ -58,6 +58,7 @@ SYSCTL_INT(_hw_vmm_iommu, OID_AUTO, enable, CTLFLAG_RDTUN, &iommu_enable, 0, static struct iommu_ops *ops; static void *host_domain; +static eventhandler_tag add_tag, delete_tag; static __inline int IOMMU_INIT(void) @@ -153,6 +154,21 @@ IOMMU_DISABLE(void) (*ops->disable)(); } +static void +iommu_pci_add(void *arg, device_t dev) +{ + + /* Add new devices to the host domain. */ + iommu_add_device(host_domain, pci_get_rid(dev)); +} + +static void +iommu_pci_delete(void *arg, device_t dev) +{ + + iommu_remove_device(host_domain, pci_get_rid(dev)); +} + static void iommu_init(void) { @@ -195,6 +211,9 @@ iommu_init(void) */ iommu_create_mapping(host_domain, 0, 0, maxaddr); + add_tag = EVENTHANDLER_REGISTER(pci_add_device, iommu_pci_add, NULL, 0); + delete_tag = EVENTHANDLER_REGISTER(pci_delete_device, iommu_pci_delete, + NULL, 0); for (bus = 0; bus <= PCI_BUSMAX; bus++) { for (slot = 0; slot <= PCI_SLOTMAX; slot++) { for (func = 0; func <= PCI_FUNCMAX; func++) { @@ -215,6 +234,15 @@ iommu_init(void) void iommu_cleanup(void) { + + if (add_tag != NULL) { + EVENTHANDLER_DEREGISTER(pci_add_device, add_tag); + add_tag = NULL; + } + if (delete_tag != NULL) { + EVENTHANDLER_DEREGISTER(pci_delete_device, delete_tag); + delete_tag = NULL; + } IOMMU_DISABLE(); IOMMU_DESTROY_DOMAIN(host_domain); IOMMU_CLEANUP(); diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 3a3461c649c..5281892ee91 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -4071,6 +4071,7 @@ pci_add_child(device_t bus, struct pci_devinfo *dinfo) pci_print_verbose(dinfo); pci_add_resources(bus, dinfo->cfg.dev, 0, 0); pci_child_added(dinfo->cfg.dev); + EVENTHANDLER_INVOKE(pci_add_device, dinfo->cfg.dev); } void @@ -5312,6 +5313,8 @@ pci_child_deleted(device_t dev, device_t child) dinfo = device_get_ivars(child); rl = &dinfo->resources; + EVENTHANDLER_INVOKE(pci_delete_device, child); + /* Turn off access to resources we're about to free */ if (bus_child_present(child) != 0) { pci_write_config(child, PCIR_COMMAND, pci_read_config(child, diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h index 2e50af66c1c..91fc71d6a81 100644 --- a/sys/dev/pci/pcivar.h +++ b/sys/dev/pci/pcivar.h @@ -31,6 +31,7 @@ #define _PCIVAR_H_ #include +#include /* some PCI bus constants */ #define PCI_MAXMAPS_0 6 /* max. no. of memory/port maps */ @@ -631,4 +632,12 @@ void * vga_pci_map_bios(device_t dev, size_t *size); void vga_pci_unmap_bios(device_t dev, void *bios); int vga_pci_repost(device_t dev); +/** + * Global eventhandlers invoked when PCI devices are added or removed + * from the system. + */ +typedef void (*pci_event_fn)(void *arg, device_t dev); +EVENTHANDLER_DECLARE(pci_add_device, pci_event_fn); +EVENTHANDLER_DECLARE(pci_delete_device, pci_event_fn); + #endif /* _PCIVAR_H_ */ From 319336a943a5da19130b59cbaac73be19bf8a673 Mon Sep 17 00:00:00 2001 From: Jared McNeill Date: Tue, 6 Sep 2016 20:43:26 +0000 Subject: [PATCH 036/109] Add generic device-tree cpufreq driver. This driver supports two bindings: - cpufreq-dt: systems which share clock and voltage across all CPUs - arm_big_little_dt: systems which share clock and voltage across all CPUs in a single cluster Reviewed by: andrew, imp Relnotes: yes Differential Revision: https://reviews.freebsd.org/D7741 --- sys/dev/cpufreq/cpufreq_dt.c | 360 +++++++++++++++++++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 sys/dev/cpufreq/cpufreq_dt.c diff --git a/sys/dev/cpufreq/cpufreq_dt.c b/sys/dev/cpufreq/cpufreq_dt.c new file mode 100644 index 00000000000..23a69361ab1 --- /dev/null +++ b/sys/dev/cpufreq/cpufreq_dt.c @@ -0,0 +1,360 @@ +/*- + * Copyright (c) 2016 Jared McNeill + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 AUTHOR ``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 AUTHOR 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. + * + * $FreeBSD$ + */ + +/* + * Generic DT based cpufreq driver + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "cpufreq_if.h" + +struct cpufreq_dt_opp { + uint32_t freq_khz; + uint32_t voltage_uv; +}; + +struct cpufreq_dt_softc { + clk_t clk; + regulator_t reg; + + struct cpufreq_dt_opp *opp; + ssize_t nopp; + int clk_latency; + + cpuset_t cpus; +}; + +static void +cpufreq_dt_notify(device_t dev, uint64_t freq) +{ +#ifdef __aarch64__ + struct cpufreq_dt_softc *sc; + struct pcpu *pc; + int cpu; + + sc = device_get_softc(dev); + + CPU_FOREACH(cpu) { + if (CPU_ISSET(cpu, &sc->cpus)) { + pc = pcpu_find(cpu); + pc->pc_clock = freq; + } + } +#endif +} + +static const struct cpufreq_dt_opp * +cpufreq_dt_find_opp(device_t dev, uint32_t freq_mhz) +{ + struct cpufreq_dt_softc *sc; + ssize_t n; + + sc = device_get_softc(dev); + + for (n = 0; n < sc->nopp; n++) + if (CPUFREQ_CMP(sc->opp[n].freq_khz / 1000, freq_mhz)) + return (&sc->opp[n]); + + return (NULL); +} + +static void +cpufreq_dt_opp_to_setting(device_t dev, const struct cpufreq_dt_opp *opp, + struct cf_setting *set) +{ + struct cpufreq_dt_softc *sc; + + sc = device_get_softc(dev); + + memset(set, 0, sizeof(*set)); + set->freq = opp->freq_khz / 1000; + set->volts = opp->voltage_uv / 1000; + set->power = CPUFREQ_VAL_UNKNOWN; + set->lat = sc->clk_latency; + set->dev = dev; +} + +static int +cpufreq_dt_get(device_t dev, struct cf_setting *set) +{ + struct cpufreq_dt_softc *sc; + const struct cpufreq_dt_opp *opp; + uint64_t freq; + + sc = device_get_softc(dev); + + if (clk_get_freq(sc->clk, &freq) != 0) + return (ENXIO); + + opp = cpufreq_dt_find_opp(dev, freq / 1000000); + if (opp == NULL) + return (ENOENT); + + cpufreq_dt_opp_to_setting(dev, opp, set); + + return (0); +} + +static int +cpufreq_dt_set(device_t dev, const struct cf_setting *set) +{ + struct cpufreq_dt_softc *sc; + const struct cpufreq_dt_opp *opp, *copp; + uint64_t freq; + int error; + + sc = device_get_softc(dev); + + if (clk_get_freq(sc->clk, &freq) != 0) + return (ENXIO); + + copp = cpufreq_dt_find_opp(dev, freq / 1000000); + if (copp == NULL) + return (ENOENT); + opp = cpufreq_dt_find_opp(dev, set->freq); + if (opp == NULL) + return (EINVAL); + + if (copp->voltage_uv < opp->voltage_uv) { + error = regulator_set_voltage(sc->reg, opp->voltage_uv, + opp->voltage_uv); + if (error != 0) + return (ENXIO); + } + + error = clk_set_freq(sc->clk, (uint64_t)opp->freq_khz * 1000, 0); + if (error != 0) { + /* Restore previous voltage (best effort) */ + (void)regulator_set_voltage(sc->reg, copp->voltage_uv, + copp->voltage_uv); + return (ENXIO); + } + + if (copp->voltage_uv > opp->voltage_uv) { + error = regulator_set_voltage(sc->reg, opp->voltage_uv, + opp->voltage_uv); + if (error != 0) { + /* Restore previous CPU frequency (best effort) */ + (void)clk_set_freq(sc->clk, + (uint64_t)copp->freq_khz * 1000, 0); + return (ENXIO); + } + } + + if (clk_get_freq(sc->clk, &freq) == 0) + cpufreq_dt_notify(dev, freq); + + return (0); +} + + +static int +cpufreq_dt_type(device_t dev, int *type) +{ + if (type == NULL) + return (EINVAL); + + *type = CPUFREQ_TYPE_ABSOLUTE; + return (0); +} + +static int +cpufreq_dt_settings(device_t dev, struct cf_setting *sets, int *count) +{ + struct cpufreq_dt_softc *sc; + ssize_t n; + + if (sets == NULL || count == NULL) + return (EINVAL); + + sc = device_get_softc(dev); + + if (*count < sc->nopp) { + *count = (int)sc->nopp; + return (E2BIG); + } + + for (n = 0; n < sc->nopp; n++) + cpufreq_dt_opp_to_setting(dev, &sc->opp[n], &sets[n]); + + *count = (int)sc->nopp; + + return (0); +} + +static void +cpufreq_dt_identify(driver_t *driver, device_t parent) +{ + phandle_t node; + + /* Properties must be listed under node /cpus/cpu@0 */ + node = ofw_bus_get_node(parent); + + /* The cpu@0 node must have the following properties */ + if (!OF_hasprop(node, "operating-points") || + !OF_hasprop(node, "clocks") || + !OF_hasprop(node, "cpu-supply")) + return; + + if (device_find_child(parent, "cpufreq_dt", -1) != NULL) + return; + + if (BUS_ADD_CHILD(parent, 0, "cpufreq_dt", -1) == NULL) + device_printf(parent, "add cpufreq_dt child failed\n"); +} + +static int +cpufreq_dt_probe(device_t dev) +{ + phandle_t node; + + node = ofw_bus_get_node(device_get_parent(dev)); + + if (!OF_hasprop(node, "operating-points") || + !OF_hasprop(node, "clocks") || + !OF_hasprop(node, "cpu-supply")) + return (ENXIO); + + device_set_desc(dev, "Generic cpufreq driver"); + return (BUS_PROBE_GENERIC); +} + +static int +cpufreq_dt_attach(device_t dev) +{ + struct cpufreq_dt_softc *sc; + uint32_t *opp, lat; + phandle_t node, cnode; + uint64_t freq; + ssize_t n; + int cpu; + + sc = device_get_softc(dev); + node = ofw_bus_get_node(device_get_parent(dev)); + + if (regulator_get_by_ofw_property(dev, node, + "cpu-supply", &sc->reg) != 0) { + device_printf(dev, "no regulator for %s\n", + ofw_bus_get_name(device_get_parent(dev))); + return (ENXIO); + } + + if (clk_get_by_ofw_index(dev, node, 0, &sc->clk) != 0) { + device_printf(dev, "no clock for %s\n", + ofw_bus_get_name(device_get_parent(dev))); + regulator_release(sc->reg); + return (ENXIO); + } + + sc->nopp = OF_getencprop_alloc(node, "operating-points", + sizeof(*sc->opp), (void **)&opp); + if (sc->nopp == -1) + return (ENXIO); + sc->opp = malloc(sizeof(*sc->opp) * sc->nopp, M_DEVBUF, M_WAITOK); + for (n = 0; n < sc->nopp; n++) { + sc->opp[n].freq_khz = opp[n * 2 + 0]; + sc->opp[n].voltage_uv = opp[n * 2 + 1]; + + if (bootverbose) + device_printf(dev, "%u.%03u MHz, %u uV\n", + sc->opp[n].freq_khz / 1000, + sc->opp[n].freq_khz % 1000, + sc->opp[n].voltage_uv); + } + free(opp, M_OFWPROP); + + if (OF_getencprop(node, "clock-latency", &lat, sizeof(lat)) == -1) + sc->clk_latency = CPUFREQ_VAL_UNKNOWN; + else + sc->clk_latency = (int)lat; + + /* + * Find all CPUs that share the same voltage and CPU frequency + * controls. Start with the current node and move forward until + * the end is reached or a peer has an "operating-points" property. + */ + CPU_ZERO(&sc->cpus); + cpu = device_get_unit(device_get_parent(dev)); + for (cnode = node; cnode > 0; cnode = OF_peer(cnode), cpu++) { + if (cnode != node && OF_hasprop(cnode, "operating-points")) + break; + CPU_SET(cpu, &sc->cpus); + } + + if (clk_get_freq(sc->clk, &freq) == 0) + cpufreq_dt_notify(dev, freq); + + cpufreq_register(dev); + + return (0); +} + + +static device_method_t cpufreq_dt_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, cpufreq_dt_identify), + DEVMETHOD(device_probe, cpufreq_dt_probe), + DEVMETHOD(device_attach, cpufreq_dt_attach), + + /* cpufreq interface */ + DEVMETHOD(cpufreq_drv_get, cpufreq_dt_get), + DEVMETHOD(cpufreq_drv_set, cpufreq_dt_set), + DEVMETHOD(cpufreq_drv_type, cpufreq_dt_type), + DEVMETHOD(cpufreq_drv_settings, cpufreq_dt_settings), + + DEVMETHOD_END +}; + +static driver_t cpufreq_dt_driver = { + "cpufreq_dt", + cpufreq_dt_methods, + sizeof(struct cpufreq_dt_softc), +}; + +static devclass_t cpufreq_dt_devclass; + +DRIVER_MODULE(cpufreq_dt, cpu, cpufreq_dt_driver, cpufreq_dt_devclass, 0, 0); +MODULE_VERSION(cpufreq_dt, 1); From b90d9a37521db7d68c466441b17b0914e4324027 Mon Sep 17 00:00:00 2001 From: Jared McNeill Date: Tue, 6 Sep 2016 21:01:38 +0000 Subject: [PATCH 037/109] Add "pci" as a dependency to ichss. Reviewed by: jhibbits --- sys/conf/files | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/conf/files b/sys/conf/files index c501e9cfa1c..886b77e2c7b 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1236,7 +1236,7 @@ dev/ciss/ciss.c optional ciss dev/cm/smc90cx6.c optional cm dev/cmx/cmx.c optional cmx dev/cmx/cmx_pccard.c optional cmx pccard -dev/cpufreq/ichss.c optional cpufreq +dev/cpufreq/ichss.c optional cpufreq pci dev/cs/if_cs.c optional cs dev/cs/if_cs_isa.c optional cs isa dev/cs/if_cs_pccard.c optional cs pccard From da0fc9250c31dfb380b868492644e0f1bf64275d Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 6 Sep 2016 21:15:35 +0000 Subject: [PATCH 038/109] Reset PCI pass through devices via PCI-e FLR during VM start and end. Add routines to trigger a function level reset (FLR) of a PCI-express device via the PCI-express device control register. This also includes support routines to wait for pending transactions to complete as well as calculating the maximum completion timeout permitted by a device. Change the ppt(4) driver to reset pass through devices before attaching to a VM during startup and before detaching from a VM during shutdown. Reviewed by: imp, wblock (earlier version) MFC after: 1 month Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D7751 --- share/man/man9/Makefile | 3 + share/man/man9/pci.9 | 99 ++++++++++++++++++++++++ sys/amd64/vmm/io/ppt.c | 11 +++ sys/dev/pci/pci.c | 162 ++++++++++++++++++++++++++++++++++++++++ sys/dev/pci/pcireg.h | 21 +++++- sys/dev/pci/pcivar.h | 4 +- 6 files changed, 296 insertions(+), 4 deletions(-) diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index e54328fa649..a9dfc68ef9b 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -1354,7 +1354,10 @@ MLINKS+=pci.9 pci_alloc_msi.9 \ pci.9 pci_set_max_read_req.9 \ pci.9 pci_write_config.9 \ pci.9 pcie_adjust_config.9 \ + pci.9 pcie_flr.9 \ + pci.9 pcie_max_completion_timeout.9 \ pci.9 pcie_read_config.9 \ + pci.9 pcie_wait_for_pending_transactions.9 \ pci.9 pcie_write_config.9 MLINKS+=pci_iov_schema.9 pci_iov_schema_alloc_node.9 \ pci_iov_schema.9 pci_iov_schema_add_bool.9 \ diff --git a/share/man/man9/pci.9 b/share/man/man9/pci.9 index 209986b1b1a..d8b4b91c406 100644 --- a/share/man/man9/pci.9 +++ b/share/man/man9/pci.9 @@ -66,7 +66,10 @@ .Nm pci_set_powerstate , .Nm pci_write_config , .Nm pcie_adjust_config , +.Nm pcie_flr , +.Nm pcie_get_max_completion_timeout , .Nm pcie_read_config , +.Nm pcie_wait_for_pending_transactions , .Nm pcie_write_config .Nd PCI bus interface .Sh SYNOPSIS @@ -145,8 +148,14 @@ .Fa "uint32_t val" .Fa "int width" .Fc +.Ft bool +.Fn pcie_flr "device_t dev" "u_int max_delay" "bool force" +.Ft int +.Fn pcie_get_max_completion_timeout "device_t dev" .Ft uint32_t .Fn pcie_read_config "device_t dev" "int reg" "int width" +.Ft bool +.Fn pcie_wait_for_pending_transactions "device_t dev" "u_int max_delay" .Ft void .Fn pcie_write_config "device_t dev" "int reg" "uint32_t val" "int width" .Ft void @@ -431,6 +440,51 @@ keyword, then .Fn pci_get_vpd_readonly returns an error. +.Pp +The +.Fn pcie_get_max_completion_timeout +function returns the maximum completion timeout configured for the device +.Fa dev +in microseconds. +If the +.Fa dev +device is not a PCI-express device, +.Fn pcie_get_max_completion_timeout +returns zero. +When completion timeouts are disabled for +.Fa dev , +this function returns the maxmimum timeout that would be used if timeouts +were enabled. +.Pp +The +.Fn pcie_wait_for_pending_transactions +function waits for any pending transactions initiated by the +.Fa dev +device to complete. +The function checks for pending transactions by polling the transactions +pending flag in the PCI-express device status register. +It returns +.Dv true +once the transaction pending flag is clear. +If transactions are still pending after +.Fa max_delay +milliseconds, +.Fn pcie_wait_for_pending_transactions +returns +.Dv false . +If +.Fa max_delay +is set to zero, +.Fn pcie_wait_for_pending_transactions +performs a single check; +otherwise, +this function may sleep while polling the transactions pending flag. +.Nm pcie_wait_for_pending_transactions +returns +.Dv true +if +.Fa dev +is not a PCI-express device. .Ss Device Configuration The .Fn pci_enable_busmaster @@ -662,6 +716,51 @@ is invoked, then the device will be transitioned to .Dv PCI_POWERSTATE_D0 before any config registers are restored. +.Pp +The +.Fn pcie_flr +function requests a Function Level Reset +.Pq FLR +of +.Fa dev . +If +.Fa dev +is not a PCI-express device or does not support Function Level Resets via +the PCI-express device control register, +.Dv false +is returned. +Pending transactions are drained by disabling busmastering and calling +.Fn pcie_wait_for_pending_transactions +before resetting the device. +The +.Fa max_delay +argument specifies the maximum timeout to wait for pending transactions as +described for +.Fn pcie_wait_for_pending_transactions . +If +.Fn pcie_wait_for_pending_transactions +fails with a timeout and +.Fa force +is +.Dv false , +busmastering is re-enabled and +.Dv false +is returned. +If +.Fn pcie_wait_for_pending_transactions +fails with a timeout and +.Fa force +is +.Dv true , +the device is reset despite the timeout. +After the reset has been requested, +.Nm pcie_flr +sleeps for at least 100 milliseconds before returning +.Dv true . +Note that +.Nm pcie_flr +does not save and restore any state around the reset. +The caller should save and restore state as needed. .Ss Message Signaled Interrupts Message Signaled Interrupts .Pq MSI diff --git a/sys/amd64/vmm/io/ppt.c b/sys/amd64/vmm/io/ppt.c index 6541d7d2994..4c9ff474580 100644 --- a/sys/amd64/vmm/io/ppt.c +++ b/sys/amd64/vmm/io/ppt.c @@ -362,6 +362,11 @@ ppt_assign_device(struct vm *vm, int bus, int slot, int func) if (ppt->vm != NULL && ppt->vm != vm) return (EBUSY); + pci_save_state(ppt->dev); + pcie_flr(ppt->dev, + max(pcie_get_max_completion_timeout(ppt->dev) / 1000, 10), + true); + pci_restore_state(ppt->dev); ppt->vm = vm; iommu_remove_device(iommu_host_domain(), pci_get_rid(ppt->dev)); iommu_add_device(vm_iommu_domain(vm), pci_get_rid(ppt->dev)); @@ -382,6 +387,12 @@ ppt_unassign_device(struct vm *vm, int bus, int slot, int func) */ if (ppt->vm != vm) return (EBUSY); + + pci_save_state(ppt->dev); + pcie_flr(ppt->dev, + max(pcie_get_max_completion_timeout(ppt->dev) / 1000, 10), + true); + pci_restore_state(ppt->dev); ppt_unmap_mmio(vm, ppt); ppt_teardown_msi(ppt); ppt_teardown_msix(ppt); diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 5281892ee91..c92fb4a0902 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -5892,3 +5892,165 @@ pci_find_pcie_root_port(device_t dev) dev = pcib; } } + +/* + * Wait for pending transactions to complete on a PCI-express function. + * + * The maximum delay is specified in milliseconds in max_delay. Note + * that this function may sleep. + * + * Returns true if the function is idle and false if the timeout is + * exceeded. If dev is not a PCI-express function, this returns true. + */ +bool +pcie_wait_for_pending_transactions(device_t dev, u_int max_delay) +{ + struct pci_devinfo *dinfo = device_get_ivars(dev); + uint16_t sta; + int cap; + + cap = dinfo->cfg.pcie.pcie_location; + if (cap == 0) + return (true); + + sta = pci_read_config(dev, cap + PCIER_DEVICE_STA, 2); + while (sta & PCIEM_STA_TRANSACTION_PND) { + if (max_delay == 0) + return (false); + + /* Poll once every 100 milliseconds up to the timeout. */ + if (max_delay > 100) { + pause_sbt("pcietp", 100 * SBT_1MS, 0, C_HARDCLOCK); + max_delay -= 100; + } else { + pause_sbt("pcietp", max_delay * SBT_1MS, 0, + C_HARDCLOCK); + max_delay = 0; + } + sta = pci_read_config(dev, cap + PCIER_DEVICE_STA, 2); + } + + return (true); +} + +/* + * Determine the maximum Completion Timeout in microseconds. + * + * For non-PCI-express functions this returns 0. + */ +int +pcie_get_max_completion_timeout(device_t dev) +{ + struct pci_devinfo *dinfo = device_get_ivars(dev); + int cap; + + cap = dinfo->cfg.pcie.pcie_location; + if (cap == 0) + return (0); + + /* + * Functions using the 1.x spec use the default timeout range of + * 50 microseconds to 50 milliseconds. Functions that do not + * support programmable timeouts also use this range. + */ + if ((dinfo->cfg.pcie.pcie_flags & PCIEM_FLAGS_VERSION) < 2 || + (pci_read_config(dev, cap + PCIER_DEVICE_CAP2, 4) & + PCIEM_CAP2_COMP_TIMO_RANGES) == 0) + return (50 * 1000); + + switch (pci_read_config(dev, cap + PCIER_DEVICE_CTL2, 2) & + PCIEM_CTL2_COMP_TIMO_VAL) { + case PCIEM_CTL2_COMP_TIMO_100US: + return (100); + case PCIEM_CTL2_COMP_TIMO_10MS: + return (10 * 1000); + case PCIEM_CTL2_COMP_TIMO_55MS: + return (55 * 1000); + case PCIEM_CTL2_COMP_TIMO_210MS: + return (210 * 1000); + case PCIEM_CTL2_COMP_TIMO_900MS: + return (900 * 1000); + case PCIEM_CTL2_COMP_TIMO_3500MS: + return (3500 * 1000); + case PCIEM_CTL2_COMP_TIMO_13S: + return (13 * 1000 * 1000); + case PCIEM_CTL2_COMP_TIMO_64S: + return (64 * 1000 * 1000); + default: + return (50 * 1000); + } +} + +/* + * Perform a Function Level Reset (FLR) on a device. + * + * This function first waits for any pending transactions to complete + * within the timeout specified by max_delay. If transactions are + * still pending, the function will return false without attempting a + * reset. + * + * If dev is not a PCI-express function or does not support FLR, this + * function returns false. + * + * Note that no registers are saved or restored. The caller is + * responsible for saving and restoring any registers including + * PCI-standard registers via pci_save_state() and + * pci_restore_state(). + */ +bool +pcie_flr(device_t dev, u_int max_delay, bool force) +{ + struct pci_devinfo *dinfo = device_get_ivars(dev); + uint16_t cmd, ctl; + int compl_delay; + int cap; + + cap = dinfo->cfg.pcie.pcie_location; + if (cap == 0) + return (false); + + if (!(pci_read_config(dev, cap + PCIER_DEVICE_CAP, 4) & PCIEM_CAP_FLR)) + return (false); + + /* + * Disable busmastering to prevent generation of new + * transactions while waiting for the device to go idle. If + * the idle timeout fails, the command register is restored + * which will re-enable busmastering. + */ + cmd = pci_read_config(dev, PCIR_COMMAND, 2); + pci_write_config(dev, PCIR_COMMAND, cmd & ~(PCIM_CMD_BUSMASTEREN), 2); + if (!pcie_wait_for_pending_transactions(dev, max_delay)) { + if (!force) { + pci_write_config(dev, PCIR_COMMAND, cmd, 2); + return (false); + } + pci_printf(&dinfo->cfg, + "Resetting with transactions pending after %d ms\n", + max_delay); + + /* + * Extend the post-FLR delay to cover the maximum + * Completion Timeout delay of anything in flight + * during the FLR delay. Enforce a minimum delay of + * at least 10ms. + */ + compl_delay = pcie_get_max_completion_timeout(dev) / 1000; + if (compl_delay < 10) + compl_delay = 10; + } else + compl_delay = 0; + + /* Initiate the reset. */ + ctl = pci_read_config(dev, cap + PCIER_DEVICE_CTL, 2); + pci_write_config(dev, cap + PCIER_DEVICE_CTL, ctl | + PCIEM_CTL_INITIATE_FLR, 2); + + /* Wait for 100ms. */ + pause_sbt("pcieflr", (100 + compl_delay) * SBT_1MS, 0, C_HARDCLOCK); + + if (pci_read_config(dev, cap + PCIER_DEVICE_STA, 2) & + PCIEM_STA_TRANSACTION_PND) + pci_printf(&dinfo->cfg, "Transactions pending after FLR!\n"); + return (true); +} diff --git a/sys/dev/pci/pcireg.h b/sys/dev/pci/pcireg.h index d463b7a5669..291bb2ea809 100644 --- a/sys/dev/pci/pcireg.h +++ b/sys/dev/pci/pcireg.h @@ -885,10 +885,25 @@ #define PCIEM_ROOT_STA_PME_STATUS 0x00010000 #define PCIEM_ROOT_STA_PME_PEND 0x00020000 #define PCIER_DEVICE_CAP2 0x24 -#define PCIEM_CAP2_ARI 0x20 +#define PCIEM_CAP2_COMP_TIMO_RANGES 0x0000000f +#define PCIEM_CAP2_COMP_TIMO_RANGE_A 0x00000001 +#define PCIEM_CAP2_COMP_TIMO_RANGE_B 0x00000002 +#define PCIEM_CAP2_COMP_TIMO_RANGE_C 0x00000004 +#define PCIEM_CAP2_COMP_TIMO_RANGE_D 0x00000008 +#define PCIEM_CAP2_COMP_TIMO_DISABLE 0x00000010 +#define PCIEM_CAP2_ARI 0x00000020 #define PCIER_DEVICE_CTL2 0x28 -#define PCIEM_CTL2_COMP_TIMEOUT_VAL 0x000f -#define PCIEM_CTL2_COMP_TIMEOUT_DIS 0x0010 +#define PCIEM_CTL2_COMP_TIMO_VAL 0x000f +#define PCIEM_CTL2_COMP_TIMO_50MS 0x0000 +#define PCIEM_CTL2_COMP_TIMO_100US 0x0001 +#define PCIEM_CTL2_COMP_TIMO_10MS 0x0002 +#define PCIEM_CTL2_COMP_TIMO_55MS 0x0005 +#define PCIEM_CTL2_COMP_TIMO_210MS 0x0006 +#define PCIEM_CTL2_COMP_TIMO_900MS 0x0009 +#define PCIEM_CTL2_COMP_TIMO_3500MS 0x000a +#define PCIEM_CTL2_COMP_TIMO_13S 0x000d +#define PCIEM_CTL2_COMP_TIMO_64S 0x000e +#define PCIEM_CTL2_COMP_TIMO_DISABLE 0x0010 #define PCIEM_CTL2_ARI 0x0020 #define PCIEM_CTL2_ATOMIC_REQ_ENABLE 0x0040 #define PCIEM_CTL2_ATOMIC_EGR_BLOCK 0x0080 diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h index 91fc71d6a81..d6e773c0a4c 100644 --- a/sys/dev/pci/pcivar.h +++ b/sys/dev/pci/pcivar.h @@ -595,7 +595,9 @@ uint32_t pcie_read_config(device_t dev, int reg, int width); void pcie_write_config(device_t dev, int reg, uint32_t value, int width); uint32_t pcie_adjust_config(device_t dev, int reg, uint32_t mask, uint32_t value, int width); - +bool pcie_flr(device_t dev, u_int max_delay, bool force); +int pcie_get_max_completion_timeout(device_t dev); +bool pcie_wait_for_pending_transactions(device_t dev, u_int max_delay); #ifdef BUS_SPACE_MAXADDR #if (BUS_SPACE_MAXADDR > 0xFFFFFFFF) From 0fbb017195f5a680a90f252bf77de570907b0cfd Mon Sep 17 00:00:00 2001 From: Jared McNeill Date: Tue, 6 Sep 2016 21:18:14 +0000 Subject: [PATCH 039/109] Add generic device-tree cpufreq driver. --- sys/arm64/conf/GENERIC | 3 +++ sys/conf/files.arm64 | 1 + 2 files changed, 4 insertions(+) diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC index 9357fc8d1a0..40c3fc65e50 100644 --- a/sys/arm64/conf/GENERIC +++ b/sys/arm64/conf/GENERIC @@ -96,6 +96,9 @@ device virtio_mmio device virtio_blk device vtnet +# CPU frequency control +device cpufreq + # Bus drivers device pci options PCI_HP # PCI-Express native HotPlug diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index 9804cb78a64..46b28909e50 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -97,6 +97,7 @@ crypto/blowfish/bf_enc.c optional crypto | ipsec crypto/des/des_enc.c optional crypto | ipsec | netsmb dev/acpica/acpi_if.m optional acpi dev/ahci/ahci_generic.c optional ahci fdt +dev/cpufreq/cpufreq_dt.c optional cpufreq fdt dev/hwpmc/hwpmc_arm64.c optional hwpmc dev/hwpmc/hwpmc_arm64_md.c optional hwpmc dev/mmc/host/dwmmc.c optional dwmmc fdt From 27405515454f61eb82c417c948fced42cd2cd087 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Tue, 6 Sep 2016 21:22:03 +0000 Subject: [PATCH 040/109] nullfs: stop special-casing directories in null_vptocnp The previous code was forcing an expensive walk in vop_stdvptocnp, which was causing performance issues on highly contended zfs. No objections: kib MFC after: 2 weeks --- sys/fs/nullfs/null_vnops.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c index d3a7906f750..d544e053066 100644 --- a/sys/fs/nullfs/null_vnops.c +++ b/sys/fs/nullfs/null_vnops.c @@ -870,9 +870,6 @@ null_vptocnp(struct vop_vptocnp_args *ap) struct ucred *cred = ap->a_cred; int error, locked; - if (vp->v_type == VDIR) - return (vop_stdvptocnp(ap)); - locked = VOP_ISLOCKED(vp); lvp = NULLVPTOLOWERVP(vp); vhold(lvp); From fa1cbf00d7a8bae7a992a6b6393ed8247b011b8d Mon Sep 17 00:00:00 2001 From: Jared McNeill Date: Tue, 6 Sep 2016 21:36:20 +0000 Subject: [PATCH 041/109] Add generic device-tree cpufreq driver. --- sys/arm/conf/ALLWINNER | 3 +++ sys/conf/files.arm | 1 + 2 files changed, 4 insertions(+) diff --git a/sys/arm/conf/ALLWINNER b/sys/arm/conf/ALLWINNER index a725c11cabb..11cb3b516f2 100644 --- a/sys/arm/conf/ALLWINNER +++ b/sys/arm/conf/ALLWINNER @@ -52,6 +52,9 @@ device phy device hwreset device regulator +# CPU frequency control +device cpufreq + # Interrupt controller device gic diff --git a/sys/conf/files.arm b/sys/conf/files.arm index 559c9419f94..c2eaf4af609 100644 --- a/sys/conf/files.arm +++ b/sys/conf/files.arm @@ -94,6 +94,7 @@ cddl/dev/dtrace/arm/dtrace_subr.c optional dtrace compile-with "${DTRACE_C}" cddl/dev/fbt/arm/fbt_isa.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}" crypto/blowfish/bf_enc.c optional crypto | ipsec crypto/des/des_enc.c optional crypto | ipsec | netsmb +dev/cpufreq/cpufreq_dt.c optional cpufreq fdt dev/dwc/if_dwc.c optional dwc dev/dwc/if_dwc_if.m optional dwc dev/fb/fb.c optional sc From ed6d876b19c0922d43890eb31c5b7a24b0c8bc89 Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Tue, 6 Sep 2016 22:03:53 +0000 Subject: [PATCH 042/109] Modernize the initalization of sigproptbl. Use C99 designators to set the value of each slot and the nitems macro to check for valid entries. In the process, switch to indexing by signal number rather than signal-1 for improved clarity. Obtained from: CheriBSD (a6053c5abf03a5f53bbfcdd3a26429383f67e09f) Sponsored by: DARPA, AFRL Reviewed by: kib --- sys/kern/kern_sig.c | 66 ++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index fc73f08fe51..2259c43bbc2 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -198,37 +198,37 @@ SYSCTL_INT(_kern, OID_AUTO, coredump_devctl, CTLFLAG_RW, &coredump_devctl, #define SIGPROP_CANTMASK 0x40 /* non-maskable, catchable */ static int sigproptbl[NSIG] = { - SIGPROP_KILL, /* SIGHUP */ - SIGPROP_KILL, /* SIGINT */ - SIGPROP_KILL | SIGPROP_CORE, /* SIGQUIT */ - SIGPROP_KILL | SIGPROP_CORE, /* SIGILL */ - SIGPROP_KILL | SIGPROP_CORE, /* SIGTRAP */ - SIGPROP_KILL | SIGPROP_CORE, /* SIGABRT */ - SIGPROP_KILL | SIGPROP_CORE, /* SIGEMT */ - SIGPROP_KILL | SIGPROP_CORE, /* SIGFPE */ - SIGPROP_KILL, /* SIGKILL */ - SIGPROP_KILL | SIGPROP_CORE, /* SIGBUS */ - SIGPROP_KILL | SIGPROP_CORE, /* SIGSEGV */ - SIGPROP_KILL | SIGPROP_CORE, /* SIGSYS */ - SIGPROP_KILL, /* SIGPIPE */ - SIGPROP_KILL, /* SIGALRM */ - SIGPROP_KILL, /* SIGTERM */ - SIGPROP_IGNORE, /* SIGURG */ - SIGPROP_STOP, /* SIGSTOP */ - SIGPROP_STOP | SIGPROP_TTYSTOP, /* SIGTSTP */ - SIGPROP_IGNORE | SIGPROP_CONT, /* SIGCONT */ - SIGPROP_IGNORE, /* SIGCHLD */ - SIGPROP_STOP | SIGPROP_TTYSTOP, /* SIGTTIN */ - SIGPROP_STOP | SIGPROP_TTYSTOP, /* SIGTTOU */ - SIGPROP_IGNORE, /* SIGIO */ - SIGPROP_KILL, /* SIGXCPU */ - SIGPROP_KILL, /* SIGXFSZ */ - SIGPROP_KILL, /* SIGVTALRM */ - SIGPROP_KILL, /* SIGPROF */ - SIGPROP_IGNORE, /* SIGWINCH */ - SIGPROP_IGNORE, /* SIGINFO */ - SIGPROP_KILL, /* SIGUSR1 */ - SIGPROP_KILL, /* SIGUSR2 */ + [SIGHUP] = SIGPROP_KILL, + [SIGINT] = SIGPROP_KILL, + [SIGQUIT] = SIGPROP_KILL | SIGPROP_CORE, + [SIGILL] = SIGPROP_KILL | SIGPROP_CORE, + [SIGTRAP] = SIGPROP_KILL | SIGPROP_CORE, + [SIGABRT] = SIGPROP_KILL | SIGPROP_CORE, + [SIGEMT] = SIGPROP_KILL | SIGPROP_CORE, + [SIGFPE] = SIGPROP_KILL | SIGPROP_CORE, + [SIGKILL] = SIGPROP_KILL, + [SIGBUS] = SIGPROP_KILL | SIGPROP_CORE, + [SIGSEGV] = SIGPROP_KILL | SIGPROP_CORE, + [SIGSYS] = SIGPROP_KILL | SIGPROP_CORE, + [SIGPIPE] = SIGPROP_KILL, + [SIGALRM] = SIGPROP_KILL, + [SIGTERM] = SIGPROP_KILL, + [SIGURG] = SIGPROP_IGNORE, + [SIGSTOP] = SIGPROP_STOP, + [SIGTSTP] = SIGPROP_STOP | SIGPROP_TTYSTOP, + [SIGCONT] = SIGPROP_IGNORE | SIGPROP_CONT, + [SIGCHLD] = SIGPROP_IGNORE, + [SIGTTIN] = SIGPROP_STOP | SIGPROP_TTYSTOP, + [SIGTTOU] = SIGPROP_STOP | SIGPROP_TTYSTOP, + [SIGIO] = SIGPROP_IGNORE, + [SIGXCPU] = SIGPROP_KILL, + [SIGXFSZ] = SIGPROP_KILL, + [SIGVTALRM] = SIGPROP_KILL, + [SIGPROF] = SIGPROP_KILL, + [SIGWINCH] = SIGPROP_IGNORE, + [SIGINFO] = SIGPROP_IGNORE, + [SIGUSR1] = SIGPROP_KILL, + [SIGUSR2] = SIGPROP_KILL, }; static void reschedule_signals(struct proc *p, sigset_t block, int flags); @@ -611,8 +611,8 @@ static __inline int sigprop(int sig) { - if (sig > 0 && sig < NSIG) - return (sigproptbl[_SIG_IDX(sig)]); + if (sig > 0 && sig < nitems(sigproptbl)) + return (sigproptbl[sig]); return (0); } From b2fd098e58a21229a3b7b6b4b40cc99e44937fa3 Mon Sep 17 00:00:00 2001 From: Marius Strobl Date: Tue, 6 Sep 2016 22:18:08 +0000 Subject: [PATCH 043/109] Disable vt(4) by default on sparc64 as creator_vt(4) and vt_ofwfb(4) have the serious problem of not actually attaching the hardware they are driving at the bus level. This causes creator(4) and machfb(4) to attach and drive the very same hardware in parallel when both syscons(4) and vt(4) as well as their associated hardware drivers are built into a kernel, i. e. GENERIC, at the same time. Also, syscons(4) and its drivers still are way superior to vt(4) and its equivalents; unlike the syscons(4) counterparts the vt(4) drivers don't provide hardware acceleration resulting in considerably slower screen drawing, creator_vt(4) doesn't provide a /dev/fb node as required by the Xorg sunffb(4) etc. In theory, vt_ofwfb(4) should be able to handle more devices than machfb(4). However, testing shows that it hardly works with any hardware machfb(4) isn't also able to drive, making vt(4) and vt_ofwfb(4) not favorable for the time being from that perspective either. MFC after: 3 days --- sys/sparc64/conf/GENERIC | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/sparc64/conf/GENERIC b/sys/sparc64/conf/GENERIC index 27fea645bc2..a03f6367f35 100644 --- a/sys/sparc64/conf/GENERIC +++ b/sys/sparc64/conf/GENERIC @@ -147,7 +147,7 @@ device splash # Splash screen and screen saver support options KBD_INSTALL_CDEV # install a CDEV entry in /dev # vt is the new video console driver -device vt +#device vt # Builtin hardware device auxio # auxiliary I/O device From 40c5032d32033f34a5bd1bfe42cff9f1ef16e29b Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Tue, 6 Sep 2016 23:35:48 +0000 Subject: [PATCH 044/109] Add some fail points to gmirror. These are useful for testing changes to I/O error handling, and for reproducing existing bugs in a controlled manner. The fail points are g_mirror_regular_request_read g_mirror_regular_request_write g_mirror_sync_request_read g_mirror_sync_request_write g_mirror_metadata_write They all effectively allow one to inject an error value into the bio_error field of a corresponding BIO request as it is being completed. MFC after: 2 weeks Sponsored by: EMC / Isilon Storage Division --- sys/geom/mirror/g_mirror.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index b8924b0ab3d..a8ad857e237 100644 --- a/sys/geom/mirror/g_mirror.c +++ b/sys/geom/mirror/g_mirror.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -646,6 +647,7 @@ g_mirror_write_metadata(struct g_mirror_disk *disk, else mirror_metadata_encode(md, sector); } + KFAIL_POINT_ERROR(DEBUG_FP, g_mirror_metadata_write, error); if (error == 0) error = g_write_data(cp, offset, sector, length); free(sector, M_MIRROR); @@ -914,6 +916,13 @@ g_mirror_regular_request(struct bio *bp) g_topology_unlock(); } + if (bp->bio_cmd == BIO_READ) + KFAIL_POINT_ERROR(DEBUG_FP, g_mirror_regular_request_read, + bp->bio_error); + else if (bp->bio_cmd == BIO_WRITE) + KFAIL_POINT_ERROR(DEBUG_FP, g_mirror_regular_request_write, + bp->bio_error); + pbp->bio_inbed++; KASSERT(pbp->bio_inbed <= pbp->bio_children, ("bio_inbed (%u) is bigger than bio_children (%u).", pbp->bio_inbed, @@ -1308,6 +1317,9 @@ g_mirror_sync_request(struct bio *bp) { struct g_consumer *cp; + KFAIL_POINT_ERROR(DEBUG_FP, g_mirror_sync_request_read, + bp->bio_error); + if (bp->bio_error != 0) { G_MIRROR_LOGREQ(0, bp, "Synchronization request failed (error=%d).", @@ -1334,6 +1346,9 @@ g_mirror_sync_request(struct bio *bp) void *data; int i; + KFAIL_POINT_ERROR(DEBUG_FP, g_mirror_sync_request_write, + bp->bio_error); + if (bp->bio_error != 0) { G_MIRROR_LOGREQ(0, bp, "Synchronization request failed (error=%d).", From 4bfb58535169a2020192913ab8e839300c442051 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Tue, 6 Sep 2016 23:42:59 +0000 Subject: [PATCH 045/109] Don't treat an error from g_mirror_clear_metadata() as fatal. Such errors can occur as the result of a write error or because the disk backing the mirror element was removed. They result in a generation ID bump on all active elements of the mirror, so we can safely disconnect the mirror component rather than destroy it. MFC after: 2 weeks Sponsored by: EMC / Isilon Storage Division Differential Revision: https://reviews.freebsd.org/D7750 --- sys/geom/mirror/g_mirror.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c index a8ad857e237..75433d15b6d 100644 --- a/sys/geom/mirror/g_mirror.c +++ b/sys/geom/mirror/g_mirror.c @@ -2678,8 +2678,12 @@ again: int error; error = g_mirror_clear_metadata(disk); - if (error != 0) - return (error); + if (error != 0) { + G_MIRROR_DEBUG(0, + "Device %s: failed to clear metadata on %s: %d.", + sc->sc_name, g_mirror_get_diskname(disk), error); + break; + } DISK_STATE_CHANGED(); G_MIRROR_DEBUG(0, "Device %s: provider %s destroyed.", sc->sc_name, g_mirror_get_diskname(disk)); From b3868b9f16df5cafdc8eb77c6940cc049627f671 Mon Sep 17 00:00:00 2001 From: Jared McNeill Date: Wed, 7 Sep 2016 01:09:25 +0000 Subject: [PATCH 046/109] Attach later so axp81x attaches after aw_nmi. --- sys/arm/allwinner/axp81x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/arm/allwinner/axp81x.c b/sys/arm/allwinner/axp81x.c index 9849517769c..9693b1007ce 100644 --- a/sys/arm/allwinner/axp81x.c +++ b/sys/arm/allwinner/axp81x.c @@ -777,9 +777,9 @@ extern devclass_t ofwgpiobus_devclass, gpioc_devclass; extern driver_t ofw_gpiobus_driver, gpioc_driver; EARLY_DRIVER_MODULE(axp81x, iicbus, axp81x_driver, axp81x_devclass, 0, 0, - BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); + BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST); EARLY_DRIVER_MODULE(ofw_gpiobus, axp81x_pmu, ofw_gpiobus_driver, - ofwgpiobus_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); + ofwgpiobus_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST); DRIVER_MODULE(gpioc, axp81x_pmu, gpioc_driver, gpioc_devclass, 0, 0); MODULE_VERSION(axp81x, 1); MODULE_DEPEND(axp81x, iicbus, 1, 1, 1); From b78c83e321291c729dfb5a0a02e84a2835a83538 Mon Sep 17 00:00:00 2001 From: Jared McNeill Date: Wed, 7 Sep 2016 01:10:16 +0000 Subject: [PATCH 047/109] Add support for Allwinner A83T CPU frequency scaling. --- sys/arm/allwinner/clk/aw_cpuclk.c | 46 +++++++++++++++++--- sys/arm/allwinner/clk/aw_pll.c | 54 ++++++++++++++++++++++++ sys/boot/fdt/dts/arm/a83t.dtsi | 44 +++++++++++++++++++ sys/boot/fdt/dts/arm/sinovoip-bpi-m3.dts | 36 ++++++++++++++++ 4 files changed, 175 insertions(+), 5 deletions(-) diff --git a/sys/arm/allwinner/clk/aw_cpuclk.c b/sys/arm/allwinner/clk/aw_cpuclk.c index d6ae4584039..86d071efeba 100644 --- a/sys/arm/allwinner/clk/aw_cpuclk.c +++ b/sys/arm/allwinner/clk/aw_cpuclk.c @@ -47,8 +47,42 @@ __FBSDID("$FreeBSD$"); #include -#define CPU_CLK_SRC_SEL_WIDTH 2 -#define CPU_CLK_SRC_SEL_SHIFT 16 +#define A10_CPU_CLK_SRC_SEL_WIDTH 2 +#define A10_CPU_CLK_SRC_SEL_SHIFT 16 + +#define A83T_Cx_CLK_SRC_SEL_WIDTH 1 +#define A83T_C0_CLK_SRC_SEL_SHIFT 12 +#define A83T_C1_CLK_SRC_SEL_SHIFT 28 + +struct aw_cpuclk_config { + u_int width; + u_int shift; +}; + +static struct aw_cpuclk_config a10_config = { + .width = A10_CPU_CLK_SRC_SEL_WIDTH, + .shift = A10_CPU_CLK_SRC_SEL_SHIFT, +}; + +static struct aw_cpuclk_config a83t_c0_config = { + .width = A83T_Cx_CLK_SRC_SEL_WIDTH, + .shift = A83T_C0_CLK_SRC_SEL_SHIFT, +}; + +static struct aw_cpuclk_config a83t_c1_config = { + .width = A83T_Cx_CLK_SRC_SEL_WIDTH, + .shift = A83T_C1_CLK_SRC_SEL_SHIFT, +}; + +static struct ofw_compat_data compat_data[] = { + { "allwinner,sun4i-a10-cpu-clk", (uintptr_t)&a10_config }, + { "allwinner,sun8i-a83t-c0cpu-clk", (uintptr_t)&a83t_c0_config }, + { "allwinner,sun8i-a83t-c1cpu-clk", (uintptr_t)&a83t_c1_config }, + { NULL, (uintptr_t)NULL } +}; + +#define CPUCLK_CONF(d) \ + (void *)ofw_bus_search_compatible((d), compat_data)->ocd_data static int aw_cpuclk_probe(device_t dev) @@ -56,7 +90,7 @@ aw_cpuclk_probe(device_t dev) if (!ofw_bus_status_okay(dev)) return (ENXIO); - if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-a10-cpu-clk")) + if (CPUCLK_CONF(dev) == NULL) return (ENXIO); device_set_desc(dev, "Allwinner CPU Clock"); @@ -68,6 +102,7 @@ aw_cpuclk_attach(device_t dev) { struct clk_mux_def def; struct clkdom *clkdom; + struct aw_cpuclk_config *conf; bus_addr_t paddr; bus_size_t psize; phandle_t node; @@ -75,6 +110,7 @@ aw_cpuclk_attach(device_t dev) clk_t clk; node = ofw_bus_get_node(dev); + conf = CPUCLK_CONF(dev); if (ofw_reg_to_paddr(node, 0, &paddr, &psize, NULL) != 0) { device_printf(dev, "cannot parse 'reg' property\n"); @@ -105,8 +141,8 @@ aw_cpuclk_attach(device_t dev) } def.clkdef.parent_cnt = ncells; def.offset = paddr; - def.shift = CPU_CLK_SRC_SEL_SHIFT; - def.width = CPU_CLK_SRC_SEL_WIDTH; + def.shift = conf->shift; + def.width = conf->width; error = clk_parse_ofw_clk_name(dev, node, &def.clkdef.name); if (error != 0) { diff --git a/sys/arm/allwinner/clk/aw_pll.c b/sys/arm/allwinner/clk/aw_pll.c index 8936c913f37..7a17f0f1cea 100644 --- a/sys/arm/allwinner/clk/aw_pll.c +++ b/sys/arm/allwinner/clk/aw_pll.c @@ -157,6 +157,17 @@ __FBSDID("$FreeBSD$"); #define A80_PLL4_FACTOR_N (0xff << 8) #define A80_PLL4_FACTOR_N_SHIFT 8 +#define A83T_PLLCPUX_LOCK_TIME (0x7 << 24) +#define A83T_PLLCPUX_LOCK_TIME_SHIFT 24 +#define A83T_PLLCPUX_CLOCK_OUTPUT_DIS (1 << 20) +#define A83T_PLLCPUX_OUT_EXT_DIVP (1 << 16) +#define A83T_PLLCPUX_FACTOR_N (0xff << 8) +#define A83T_PLLCPUX_FACTOR_N_SHIFT 8 +#define A83T_PLLCPUX_FACTOR_N_MIN 12 +#define A83T_PLLCPUX_FACTOR_N_MAX 125 +#define A83T_PLLCPUX_POSTDIV_M (0x3 << 0) +#define A83T_PLLCPUX_POSTDIV_M_SHIFT 0 + #define CLKID_A10_PLL3_1X 0 #define CLKID_A10_PLL3_2X 1 @@ -202,6 +213,7 @@ enum aw_pll_type { AWPLL_A31_PLL6, AWPLL_A64_PLLHSIC, AWPLL_A80_PLL4, + AWPLL_A83T_PLLCPUX, AWPLL_H3_PLL1, }; @@ -824,6 +836,46 @@ a64_pllhsic_init(device_t dev, bus_addr_t reg, struct clknode_init_def *def) return (0); } +static int +a83t_pllcpux_recalc(struct aw_pll_sc *sc, uint64_t *freq) +{ + uint32_t val, n, p; + + DEVICE_LOCK(sc); + PLL_READ(sc, &val); + DEVICE_UNLOCK(sc); + + n = (val & A83T_PLLCPUX_FACTOR_N) >> A83T_PLLCPUX_FACTOR_N_SHIFT; + p = (val & A83T_PLLCPUX_OUT_EXT_DIVP) ? 4 : 1; + + *freq = (*freq * n) / p; + + return (0); +} + +static int +a83t_pllcpux_set_freq(struct aw_pll_sc *sc, uint64_t fin, uint64_t *fout, + int flags) +{ + uint32_t val; + u_int n; + + n = *fout / fin; + + if (n < A83T_PLLCPUX_FACTOR_N_MIN || n > A83T_PLLCPUX_FACTOR_N_MAX) + return (EINVAL); + + DEVICE_LOCK(sc); + PLL_READ(sc, &val); + val &= ~A83T_PLLCPUX_FACTOR_N; + val |= (n << A83T_PLLCPUX_FACTOR_N_SHIFT); + val &= ~A83T_PLLCPUX_CLOCK_OUTPUT_DIS; + PLL_WRITE(sc, val); + DEVICE_UNLOCK(sc); + + return (0); +} + #define PLL(_type, _recalc, _set_freq, _init) \ [(_type)] = { \ .recalc = (_recalc), \ @@ -842,6 +894,7 @@ static struct aw_pll_funcs aw_pll_func[] = { PLL(AWPLL_A31_PLL1, a31_pll1_recalc, NULL, NULL), PLL(AWPLL_A31_PLL6, a31_pll6_recalc, NULL, a31_pll6_init), PLL(AWPLL_A80_PLL4, a80_pll4_recalc, NULL, NULL), + PLL(AWPLL_A83T_PLLCPUX, a83t_pllcpux_recalc, a83t_pllcpux_set_freq, NULL), PLL(AWPLL_A64_PLLHSIC, a64_pllhsic_recalc, NULL, a64_pllhsic_init), PLL(AWPLL_H3_PLL1, a23_pll1_recalc, h3_pll1_set_freq, NULL), }; @@ -856,6 +909,7 @@ static struct ofw_compat_data compat_data[] = { { "allwinner,sun6i-a31-pll1-clk", AWPLL_A31_PLL1 }, { "allwinner,sun6i-a31-pll6-clk", AWPLL_A31_PLL6 }, { "allwinner,sun8i-a23-pll1-clk", AWPLL_A23_PLL1 }, + { "allwinner,sun8i-a83t-pllcpux-clk", AWPLL_A83T_PLLCPUX }, { "allwinner,sun8i-h3-pll1-clk", AWPLL_H3_PLL1 }, { "allwinner,sun9i-a80-pll4-clk", AWPLL_A80_PLL4 }, { "allwinner,sun50i-a64-pllhsic-clk", AWPLL_A64_PLLHSIC }, diff --git a/sys/boot/fdt/dts/arm/a83t.dtsi b/sys/boot/fdt/dts/arm/a83t.dtsi index 1ff4d182c75..52a3b3fc641 100644 --- a/sys/boot/fdt/dts/arm/a83t.dtsi +++ b/sys/boot/fdt/dts/arm/a83t.dtsi @@ -27,6 +27,18 @@ */ / { + cpus { + cpu@0 { + clocks = <&c0_cpux_clk>; + clock-latency = <2000000>; + }; + + cpu@100 { + clocks = <&c1_cpux_clk>; + clock-latency = <2000000>; + }; + }; + pmu { compatible = "arm,cortex-a7-pmu", "arm,cortex-a15-pmu"; @@ -38,6 +50,38 @@ }; clocks { + pll_c0cpux: clk@01c20000 { + #clock-cells = <0>; + compatible = "allwinner,sun8i-a83t-pllcpux-clk"; + reg = <0x01c20000 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll_c0cpux"; + }; + + pll_c1cpux: clk@01c20004 { + #clock-cells = <0>; + compatible = "allwinner,sun8i-a83t-pllcpux-clk"; + reg = <0x01c20004 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll_c1cpux"; + }; + + c0_cpux_clk: c0clk@01c20050 { + #clock-cells = <0>; + compatible = "allwinner,sun8i-a83t-c0cpu-clk"; + reg = <0x01c20050 0x4>; + clocks = <&osc24M>, <&pll_c0cpux>; + clock-output-names = "c0_cpux"; + }; + + c1_cpux_clk: c1clk@01c20050 { + #clock-cells = <0>; + compatible = "allwinner,sun8i-a83t-c1cpu-clk"; + reg = <0x01c20050 0x4>; + clocks = <&osc24M>, <&pll_c1cpux>; + clock-output-names = "c1_cpux"; + }; + /* cpus_clk compatible in gnu dt is incorrect */ cpus_clk: clk@01f01400 { compatible = "allwinner,sun8i-a83t-cpus-clk"; diff --git a/sys/boot/fdt/dts/arm/sinovoip-bpi-m3.dts b/sys/boot/fdt/dts/arm/sinovoip-bpi-m3.dts index 5d4d0666b57..b88ef52ff22 100644 --- a/sys/boot/fdt/dts/arm/sinovoip-bpi-m3.dts +++ b/sys/boot/fdt/dts/arm/sinovoip-bpi-m3.dts @@ -29,6 +29,32 @@ #include "sun8i-a83t-sinovoip-bpi-m3.dts" #include "a83t.dtsi" +/ { + cpus { + cpu@0 { + cpu-supply = <®_dcdc2>; + operating-points = < + /* kHz uV */ + 1200000 840000 + 1008000 840000 + 648000 840000 + 408000 840000 + >; + }; + + cpu@100 { + cpu-supply = <®_dcdc3>; + operating-points = < + /* kHz uV */ + 1200000 840000 + 1008000 840000 + 648000 840000 + 408000 840000 + >; + }; + }; +}; + &ehci0 { status = "okay"; }; @@ -115,6 +141,16 @@ interrupts = <0 IRQ_TYPE_LEVEL_LOW>; gpio-controller; #gpio-cells = <1>; + + regulators { + reg_dcdc2: dcdc2 { + regulator-name = "dcdc2"; + }; + + reg_dcdc3: dcdc3 { + regulator-name = "dcdc3"; + }; + }; }; }; From fcb926a7196409b518e31bf5d333420a78143d71 Mon Sep 17 00:00:00 2001 From: Kevin Lo Date: Wed, 7 Sep 2016 02:45:09 +0000 Subject: [PATCH 048/109] Remove extra period from kern.vt.kbd_reboot --- share/man/man4/vt.4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/man/man4/vt.4 b/share/man/man4/vt.4 index 400d5d188cc..56e38019906 100644 --- a/share/man/man4/vt.4 +++ b/share/man/man4/vt.4 @@ -250,7 +250,7 @@ command. Enable halt keyboard combination. .It Va kern.vt.kbd_poweroff Enable power off key combination. -.It Va kern.vt.kbd_reboot. +.It Va kern.vt.kbd_reboot Enable reboot key combination, usually Ctrl+Alt+Del. .It Va kern.vt.kbd_debug Enable debug request key combination, usually Ctrl+Alt+Esc. From bdee3435fa936d779c96f38c412c30c1cf7b205f Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Wed, 7 Sep 2016 03:26:55 +0000 Subject: [PATCH 049/109] Allow pmap_early_io_unmap() to reclaim memory pmap_early_io_map()/pmap_early_io_unmap(), if used in pairs, should be used in the form: pmap_early_io_map() ..do stuff.. pmap_early_io_unmap() Without other allocations in the middle. Without reclaiming memory this can leave large holes in the device space. While here, make a simple change to the unmap loop which now permits it to unmap multiple TLB entries in the range. --- sys/powerpc/booke/pmap.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c index 7aa2845e120..bf8c79a83a1 100644 --- a/sys/powerpc/booke/pmap.c +++ b/sys/powerpc/booke/pmap.c @@ -3391,27 +3391,37 @@ tlb1_init() set_mas4_defaults(); } +/* + * pmap_early_io_unmap() should be used in short conjunction with + * pmap_early_io_map(), as in the following snippet: + * + * x = pmap_early_io_map(...); + * + * pmap_early_io_unmap(x, size); + * + * And avoiding more allocations between. + */ void pmap_early_io_unmap(vm_offset_t va, vm_size_t size) { int i; tlb_entry_t e; + vm_size_t isize; - for (i = 0; i < TLB1_ENTRIES && size > 0; i ++) { + size = roundup(size, PAGE_SIZE); + isize = size; + for (i = 0; i < TLB1_ENTRIES && size > 0; i++) { tlb1_read_entry(&e, i); if (!(e.mas1 & MAS1_VALID)) continue; - /* - * FIXME: this code does not work if VA region - * spans multiple TLB entries. This does not cause - * problems right now but shall be fixed in the future - */ - if (va >= e.virt && (va + size) <= (e.virt + e.size)) { + if (va <= e.virt && (va + isize) >= (e.virt + e.size)) { size -= e.size; e.mas1 &= ~MAS1_VALID; tlb1_write_entry(&e, i); } } + if (tlb1_map_base == va + isize) + tlb1_map_base -= isize; } vm_offset_t From a2fe9079a8b7f30dd6607bd51a53f9df859020cb Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Wed, 7 Sep 2016 04:13:28 +0000 Subject: [PATCH 050/109] Disable the qoriq errata fix for now It hangs more often than it actually works it seems. Further debugging is needed to determine why, but for now the system needs to be able to boot. --- sys/powerpc/mpc85xx/platform_mpc85xx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/powerpc/mpc85xx/platform_mpc85xx.c b/sys/powerpc/mpc85xx/platform_mpc85xx.c index 972c3b16636..b965b5ca87e 100644 --- a/sys/powerpc/mpc85xx/platform_mpc85xx.c +++ b/sys/powerpc/mpc85xx/platform_mpc85xx.c @@ -195,7 +195,9 @@ mpc85xx_attach(platform_t plat) } ccsrbar_va = pmap_early_io_map(ccsrbar, ccsrsize); +#if 0 mpc85xx_fix_errata(ccsrbar_va); +#endif mpc85xx_enable_l3_cache(); return (0); From 5761f5dfdd4694b962dee4abeb6c8025bf6da1bf Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Wed, 7 Sep 2016 05:27:43 +0000 Subject: [PATCH 051/109] hyperv/hn: Avoid bit fields for TXCSUM setup. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7792 --- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 14 ++++++-------- sys/dev/hyperv/netvsc/ndis.h | 10 ++++++++++ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index c923d23b1f0..78409a3e170 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -972,16 +972,14 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) csum_info = (rndis_tcp_ip_csum_info *)((uint8_t *)rppi + rppi->per_packet_info_offset); - csum_info->xmit.is_ipv4 = 1; + csum_info->value = NDIS_TXCSUM_INFO_IPV4; if (m_head->m_pkthdr.csum_flags & CSUM_IP) - csum_info->xmit.ip_header_csum = 1; + csum_info->value |= NDIS_TXCSUM_INFO_IPCS; - if (m_head->m_pkthdr.csum_flags & CSUM_TCP) { - csum_info->xmit.tcp_csum = 1; - csum_info->xmit.tcp_header_offset = 0; - } else if (m_head->m_pkthdr.csum_flags & CSUM_UDP) { - csum_info->xmit.udp_csum = 1; - } + if (m_head->m_pkthdr.csum_flags & CSUM_TCP) + csum_info->value |= NDIS_TXCSUM_INFO_TCPCS; + else if (m_head->m_pkthdr.csum_flags & CSUM_UDP) + csum_info->value |= NDIS_TXCSUM_INFO_UDPCS; } rndis_mesg->msg_len = tot_data_buf_len + rndis_msg_size; diff --git a/sys/dev/hyperv/netvsc/ndis.h b/sys/dev/hyperv/netvsc/ndis.h index 327402803ff..895f756db16 100644 --- a/sys/dev/hyperv/netvsc/ndis.h +++ b/sys/dev/hyperv/netvsc/ndis.h @@ -232,6 +232,7 @@ struct ndis_rssprm_toeplitz { #define NDIS_RXCSUM_INFO_IPCS_INVAL 0x0100 /* LSOv2 */ +#define NDIS_LSO2_INFO_SIZE sizeof(uint32_t) #define NDIS_LSO2_INFO_MSS_MASK 0x000fffff #define NDIS_LSO2_INFO_THOFF_MASK 0x3ff00000 #define NDIS_LSO2_INFO_ISLSO2 0x40000000 @@ -248,4 +249,13 @@ struct ndis_rssprm_toeplitz { #define NDIS_LSO2_INFO_MAKEIPV6(thoff, mss) \ (NDIS_LSO2_INFO_MAKE((thoff), (mss)) | NDIS_LSO2_INFO_ISIPV6) +/* Transmission checksum */ +#define NDIS_TXCSUM_INFO_SIZE sizeof(uint32_t) +#define NDIS_TXCSUM_INFO_IPV4 0x00000001 +#define NDIS_TXCSUM_INFO_IPV6 0x00000002 +#define NDIS_TXCSUM_INFO_TCPCS 0x00000004 +#define NDIS_TXCSUM_INFO_UDPCS 0x00000008 +#define NDIS_TXCSUM_INFO_IPCS 0x00000010 +#define NDIS_TXCSUM_INFO_THOFF 0x03ff0000 + #endif /* !_NET_NDIS_H_ */ From 9d6cd3d858a142730ebc056a022f248ec603e154 Mon Sep 17 00:00:00 2001 From: Wojciech Macek Date: Wed, 7 Sep 2016 05:34:41 +0000 Subject: [PATCH 052/109] Introduce support for Annapurna Alpine CCU and NB devices This commit adds drivers for Alpine Cache Coherency Unit and North Bridge Service whose task is to configure the system fabric and enable cache coherency. Obtained from: Semihalf Submitted by: Michal Stanek Sponsored by: Annapurna Labs Reviewed by: wma Differential Revision: https://reviews.freebsd.org/D7565 --- sys/arm/annapurna/alpine/alpine_ccu.c | 131 +++++++++++++++++++ sys/arm/annapurna/alpine/alpine_nb_service.c | 129 ++++++++++++++++++ sys/arm64/conf/GENERIC | 4 + sys/boot/fdt/dts/arm/annapurna-alpine.dts | 6 + sys/conf/files.arm | 2 + sys/conf/files.arm64 | 2 + 6 files changed, 274 insertions(+) create mode 100644 sys/arm/annapurna/alpine/alpine_ccu.c create mode 100644 sys/arm/annapurna/alpine/alpine_nb_service.c diff --git a/sys/arm/annapurna/alpine/alpine_ccu.c b/sys/arm/annapurna/alpine/alpine_ccu.c new file mode 100644 index 00000000000..19dc57a6dc5 --- /dev/null +++ b/sys/arm/annapurna/alpine/alpine_ccu.c @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 2015,2016 Annapurna Labs Ltd. and affiliates + * All rights reserved. + * + * Developed by Semihalf. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 AUTHOR 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 AUTHOR 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define AL_CCU_SNOOP_CONTROL_IOFAB_0_OFFSET 0x4000 +#define AL_CCU_SNOOP_CONTROL_IOFAB_1_OFFSET 0x5000 +#define AL_CCU_SPECULATION_CONTROL_OFFSET 0x4 + +static struct resource_spec al_ccu_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +struct al_ccu_softc { + struct resource *res; +}; + +static int al_ccu_probe(device_t dev); +static int al_ccu_attach(device_t dev); +static int al_ccu_detach(device_t dev); + +static device_method_t al_ccu_methods[] = { + DEVMETHOD(device_probe, al_ccu_probe), + DEVMETHOD(device_attach, al_ccu_attach), + DEVMETHOD(device_detach, al_ccu_detach), + + { 0, 0 } +}; + +static driver_t al_ccu_driver = { + "ccu", + al_ccu_methods, + sizeof(struct al_ccu_softc) +}; + +static devclass_t al_ccu_devclass; + +EARLY_DRIVER_MODULE(al_ccu, simplebus, al_ccu_driver, + al_ccu_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_MIDDLE); +EARLY_DRIVER_MODULE(al_ccu, ofwbus, al_ccu_driver, + al_ccu_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_MIDDLE); + +static int +al_ccu_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_is_compatible(dev, "annapurna-labs,al-ccu")) + return (ENXIO); + + device_set_desc(dev, "Alpine CCU"); + + return (BUS_PROBE_DEFAULT); +} + +static int +al_ccu_attach(device_t dev) +{ + struct al_ccu_softc *sc; + int err; + + sc = device_get_softc(dev); + + err = bus_alloc_resources(dev, al_ccu_spec, &sc->res); + if (err != 0) { + device_printf(dev, "could not allocate resources\n"); + return (err); + } + + /* Enable cache snoop */ + bus_write_4(sc->res, AL_CCU_SNOOP_CONTROL_IOFAB_0_OFFSET, 1); + bus_write_4(sc->res, AL_CCU_SNOOP_CONTROL_IOFAB_1_OFFSET, 1); + + /* Disable speculative fetches from masters */ + bus_write_4(sc->res, AL_CCU_SPECULATION_CONTROL_OFFSET, 7); + + return (0); +} + +static int +al_ccu_detach(device_t dev) +{ + struct al_ccu_softc *sc; + + sc = device_get_softc(dev); + + bus_release_resources(dev, al_ccu_spec, &sc->res); + + return (0); +} diff --git a/sys/arm/annapurna/alpine/alpine_nb_service.c b/sys/arm/annapurna/alpine/alpine_nb_service.c new file mode 100644 index 00000000000..3725cd340f3 --- /dev/null +++ b/sys/arm/annapurna/alpine/alpine_nb_service.c @@ -0,0 +1,129 @@ +/*- + * Copyright (c) 2015,2016 Annapurna Labs Ltd. and affiliates + * All rights reserved. + * + * Developed by Semihalf. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 AUTHOR 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 AUTHOR 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define AL_NB_ACF_MISC_OFFSET 0xD0 +#define AL_NB_ACF_MISC_READ_BYPASS (1 << 30) + +static struct resource_spec nb_service_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +struct nb_service_softc { + struct resource *res; +}; + +static int nb_service_probe(device_t dev); +static int nb_service_attach(device_t dev); +static int nb_service_detach(device_t dev); + +static device_method_t nb_service_methods[] = { + DEVMETHOD(device_probe, nb_service_probe), + DEVMETHOD(device_attach, nb_service_attach), + DEVMETHOD(device_detach, nb_service_detach), + + { 0, 0 } +}; + +static driver_t nb_service_driver = { + "nb_service", + nb_service_methods, + sizeof(struct nb_service_softc) +}; + +static devclass_t nb_service_devclass; + +EARLY_DRIVER_MODULE(nb_service, simplebus, nb_service_driver, + nb_service_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_MIDDLE); +EARLY_DRIVER_MODULE(nb_service, ofwbus, nb_service_driver, + nb_service_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_MIDDLE); + +static int +nb_service_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_is_compatible(dev, "annapurna-labs,al-nb-service")) + return (ENXIO); + + device_set_desc(dev, "Alpine North Bridge Service"); + + return (BUS_PROBE_DEFAULT); +} + +static int +nb_service_attach(device_t dev) +{ + struct nb_service_softc *sc; + uint32_t val; + int err; + + sc = device_get_softc(dev); + + err = bus_alloc_resources(dev, nb_service_spec, &sc->res); + if (err != 0) { + device_printf(dev, "could not allocate resources\n"); + return (err); + } + + /* Do not allow reads to bypass writes to different addresses */ + val = bus_read_4(sc->res, AL_NB_ACF_MISC_OFFSET); + val &= ~AL_NB_ACF_MISC_READ_BYPASS; + bus_write_4(sc->res, AL_NB_ACF_MISC_OFFSET, val); + + return (0); +} + +static int +nb_service_detach(device_t dev) +{ + struct nb_service_softc *sc; + + sc = device_get_softc(dev); + + bus_release_resources(dev, nb_service_spec, &sc->res); + + return (0); +} diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC index 40c3fc65e50..35633ec5c05 100644 --- a/sys/arm64/conf/GENERIC +++ b/sys/arm64/conf/GENERIC @@ -90,6 +90,10 @@ options SOC_ALLWINNER_A64 options SOC_CAVM_THUNDERX options SOC_HISI_HI6220 +# Annapurna Alpine drivers +device al_ccu # Alpine Cache Coherency Unit +device al_nb_service # Alpine North Bridge Service + # VirtIO support device virtio device virtio_mmio diff --git a/sys/boot/fdt/dts/arm/annapurna-alpine.dts b/sys/boot/fdt/dts/arm/annapurna-alpine.dts index 100d2d046fe..f6768db7882 100644 --- a/sys/boot/fdt/dts/arm/annapurna-alpine.dts +++ b/sys/boot/fdt/dts/arm/annapurna-alpine.dts @@ -137,6 +137,12 @@ reg = <0x00ff5ec0 0x30>; }; + ccu { + compatible = "annapurna-labs,al-ccu"; + reg = <0x00090000 0x10000>; + io_coherency = <1>; + }; + nb_service { compatible = "annapurna-labs,al-nb-service"; reg = <0x00070000 0x10000>; diff --git a/sys/conf/files.arm b/sys/conf/files.arm index c2eaf4af609..86ae79e96dd 100644 --- a/sys/conf/files.arm +++ b/sys/conf/files.arm @@ -1,4 +1,6 @@ # $FreeBSD$ +arm/annapurna/alpine/alpine_ccu.c optional al_ccu fdt +arm/annapurna/alpine/alpine_nb_service.c optional al_nb_service fdt arm/arm/autoconf.c standard arm/arm/bcopy_page.S standard arm/arm/bcopyinout.S standard diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index 46b28909e50..c3d795734f1 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -38,6 +38,8 @@ arm/allwinner/clk/aw_pll.c optional aw_ccu \ arm/allwinner/clk/aw_thsclk.c optional aw_ccu arm/allwinner/clk/aw_usbclk.c optional aw_ccu arm/allwinner/if_awg.c optional awg +arm/annapurna/alpine/alpine_ccu.c optional al_ccu fdt +arm/annapurna/alpine/alpine_nb_service.c optional al_nb_service fdt arm/arm/generic_timer.c standard arm/arm/gic.c standard arm/arm/gic_fdt.c optional fdt From 4192788cb261013be8d923dc659be1cec580454f Mon Sep 17 00:00:00 2001 From: Wojciech Macek Date: Wed, 7 Sep 2016 05:36:55 +0000 Subject: [PATCH 053/109] Remove messy machdep code for Alpine V1 and use proper drivers instead Let drivers for Alpine CCU, NB and Serdes take care of internal SoC configuration. Obtained from: Semihalf Submitted by: Michal Stanek Sponsored by: Annapurna Labs Reviewed by: imp,wma Differential Revision: https://reviews.freebsd.org/D7566 --- sys/arm/annapurna/alpine/alpine_machdep.c | 39 ------------ sys/arm/annapurna/alpine/alpine_machdep_mp.c | 65 -------------------- sys/arm/conf/ALPINE | 4 ++ 3 files changed, 4 insertions(+), 104 deletions(-) diff --git a/sys/arm/annapurna/alpine/alpine_machdep.c b/sys/arm/annapurna/alpine/alpine_machdep.c index acb9ba25d45..8c00303b531 100644 --- a/sys/arm/annapurna/alpine/alpine_machdep.c +++ b/sys/arm/annapurna/alpine/alpine_machdep.c @@ -51,21 +51,10 @@ __FBSDID("$FreeBSD$"); #include "opt_ddb.h" #include "opt_platform.h" -struct mtx al_dbg_lock; - #define DEVMAP_MAX_VA_ADDRESS 0xF0000000 bus_addr_t al_devmap_pa; bus_addr_t al_devmap_size; -#define AL_NB_SERVICE_OFFSET 0x70000 -#define AL_NB_CCU_OFFSET 0x90000 -#define AL_CCU_SNOOP_CONTROL_IOFAB_0_OFFSET 0x4000 -#define AL_CCU_SNOOP_CONTROL_IOFAB_1_OFFSET 0x5000 -#define AL_CCU_SPECULATION_CONTROL_OFFSET 0x4 - -#define AL_NB_ACF_MISC_OFFSET 0xD0 -#define AL_NB_ACF_MISC_READ_BYPASS (1 << 30) - int alpine_get_devmap_base(bus_addr_t *pa, bus_addr_t *size); vm_offset_t @@ -90,35 +79,7 @@ platform_gpio_init(void) void platform_late_init(void) { - bus_addr_t reg_baddr; - uint32_t val; - if (!mtx_initialized(&al_dbg_lock)) - mtx_init(&al_dbg_lock, "ALDBG", "ALDBG", MTX_SPIN); - - /* configure system fabric */ - if (bus_space_map(fdtbus_bs_tag, al_devmap_pa, al_devmap_size, 0, - ®_baddr)) - panic("Couldn't map Register Space area"); - - /* do not allow reads to bypass writes to different addresses */ - val = bus_space_read_4(fdtbus_bs_tag, reg_baddr, - AL_NB_SERVICE_OFFSET + AL_NB_ACF_MISC_OFFSET); - val &= ~AL_NB_ACF_MISC_READ_BYPASS; - bus_space_write_4(fdtbus_bs_tag, reg_baddr, - AL_NB_SERVICE_OFFSET + AL_NB_ACF_MISC_OFFSET, val); - - /* enable cache snoop */ - bus_space_write_4(fdtbus_bs_tag, reg_baddr, - AL_NB_CCU_OFFSET + AL_CCU_SNOOP_CONTROL_IOFAB_0_OFFSET, 1); - bus_space_write_4(fdtbus_bs_tag, reg_baddr, - AL_NB_CCU_OFFSET + AL_CCU_SNOOP_CONTROL_IOFAB_1_OFFSET, 1); - - /* disable speculative fetches from masters */ - bus_space_write_4(fdtbus_bs_tag, reg_baddr, - AL_NB_CCU_OFFSET + AL_CCU_SPECULATION_CONTROL_OFFSET, 7); - - bus_space_unmap(fdtbus_bs_tag, reg_baddr, al_devmap_size); } /* diff --git a/sys/arm/annapurna/alpine/alpine_machdep_mp.c b/sys/arm/annapurna/alpine/alpine_machdep_mp.c index ada7b024387..e48a1a3c577 100644 --- a/sys/arm/annapurna/alpine/alpine_machdep_mp.c +++ b/sys/arm/annapurna/alpine/alpine_machdep_mp.c @@ -68,22 +68,14 @@ __FBSDID("$FreeBSD$"); #define AL_NB_INIT_CONTROL (0x8) #define AL_NB_CONFIG_STATUS_PWR_CTRL(cpu) (0x2020 + (cpu)*0x100) -#define SERDES_NUM_GROUPS 4 -#define SERDES_GROUP_SIZE 0x400 - extern bus_addr_t al_devmap_pa; extern bus_addr_t al_devmap_size; extern void mpentry(void); -int alpine_serdes_resource_get(uint32_t group, bus_space_tag_t *tag, - bus_addr_t *baddr); static int platform_mp_get_core_cnt(void); static int alpine_get_cpu_resume_base(u_long *pbase, u_long *psize); static int alpine_get_nb_base(u_long *pbase, u_long *psize); -static int alpine_get_serdes_base(u_long *pbase, u_long *psize); -int alpine_serdes_resource_get(uint32_t group, bus_space_tag_t *tag, - bus_addr_t *baddr); static boolean_t alpine_validate_cpu(u_int, phandle_t, u_int, pcell_t *); static boolean_t @@ -254,60 +246,3 @@ platform_mp_start_ap(void) bus_space_unmap(fdtbus_bs_tag, nb_baddr, nb_size); bus_space_unmap(fdtbus_bs_tag, cpu_resume_baddr, cpu_resume_size); } - -static int -alpine_get_serdes_base(u_long *pbase, u_long *psize) -{ - phandle_t node; - u_long base = 0; - u_long size = 0; - - if (pbase == NULL || psize == NULL) - return (EINVAL); - - if ((node = OF_finddevice("/")) == -1) - return (EFAULT); - - if ((node = - ofw_bus_find_compatible(node, "annapurna-labs,al-serdes")) == 0) - return (EFAULT); - - if (fdt_regsize(node, &base, &size)) - return (EFAULT); - - *pbase = base; - *psize = size; - - return (0); -} - -int -alpine_serdes_resource_get(uint32_t group, bus_space_tag_t *tag, bus_addr_t *baddr) -{ - u_long serdes_base, serdes_size; - int ret; - static bus_addr_t baddr_mapped[SERDES_NUM_GROUPS]; - - if (group >= SERDES_NUM_GROUPS) - return (EINVAL); - - if (baddr_mapped[group]) { - *tag = fdtbus_bs_tag; - *baddr = baddr_mapped[group]; - return (0); - } - - ret = alpine_get_serdes_base(&serdes_base, &serdes_size); - if (ret) - return (ret); - - ret = bus_space_map(fdtbus_bs_tag, - al_devmap_pa + serdes_base + group * SERDES_GROUP_SIZE, - (SERDES_NUM_GROUPS - group) * SERDES_GROUP_SIZE, 0, baddr); - if (ret) - return (ret); - - baddr_mapped[group] = *baddr; - - return (0); -} diff --git a/sys/arm/conf/ALPINE b/sys/arm/conf/ALPINE index 64a9f6a70b1..c1f4eca3efc 100644 --- a/sys/arm/conf/ALPINE +++ b/sys/arm/conf/ALPINE @@ -32,6 +32,10 @@ options SMP # Enable multiple cores device gic options INTRNG +# Annapurna Alpine drivers +device al_ccu # Alpine Cache Coherency Unit +device al_nb_service # Alpine North Bridge Service + # Pseudo devices device loop device random From 61ac564fd0886c40403f97501e2b9f35510c53de Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Wed, 7 Sep 2016 05:41:01 +0000 Subject: [PATCH 054/109] hyperv/hn: Cleanup RNDIS packet message encapsulation. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7793 --- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 122 +++++++++--------- sys/dev/hyperv/netvsc/hv_rndis.h | 3 +- sys/dev/hyperv/netvsc/hv_rndis_filter.c | 25 ++-- 3 files changed, 78 insertions(+), 72 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index 78409a3e170..b8a434b314d 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -142,14 +142,14 @@ __FBSDID("$FreeBSD$"); #define HN_RING_CNT_DEF_MAX 8 -#define HN_RNDIS_MSG_LEN \ - (sizeof(rndis_msg) + \ +#define HN_RNDIS_PKT_LEN \ + (sizeof(struct rndis_packet_msg) + \ RNDIS_HASHVAL_PPI_SIZE + \ RNDIS_VLAN_PPI_SIZE + \ RNDIS_TSO_PPI_SIZE + \ RNDIS_CSUM_PPI_SIZE) -#define HN_RNDIS_MSG_BOUNDARY PAGE_SIZE -#define HN_RNDIS_MSG_ALIGN CACHE_LINE_SIZE +#define HN_RNDIS_PKT_BOUNDARY PAGE_SIZE +#define HN_RNDIS_PKT_ALIGN CACHE_LINE_SIZE #define HN_TX_DATA_BOUNDARY PAGE_SIZE #define HN_TX_DATA_MAXSIZE IP_MAXPACKET @@ -173,9 +173,9 @@ struct hn_txdesc { bus_dmamap_t data_dmap; - bus_addr_t rndis_msg_paddr; - rndis_msg *rndis_msg; - bus_dmamap_t rndis_msg_dmap; + bus_addr_t rndis_pkt_paddr; + struct rndis_packet_msg *rndis_pkt; + bus_dmamap_t rndis_pkt_dmap; }; #define HN_TXD_FLAG_ONLIST 0x1 @@ -845,6 +845,15 @@ netvsc_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr) hn_txeof(txr); } +static __inline uint32_t +hn_rndis_pktmsg_offset(uint32_t ofs) +{ + + KASSERT(ofs >= sizeof(struct rndis_packet_msg), + ("invalid RNDIS packet msg offset %u", ofs)); + return (ofs - __offsetof(struct rndis_packet_msg, rm_dataoffset)); +} + /* * NOTE: * If this function fails, then both txd and m_head0 will be freed. @@ -855,14 +864,11 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) bus_dma_segment_t segs[HN_TX_DATA_SEGCNT_MAX]; int error, nsegs, i; struct mbuf *m_head = *m_head0; - rndis_msg *rndis_mesg; - rndis_packet *rndis_pkt; + struct rndis_packet_msg *pkt; rndis_per_packet_info *rppi; struct rndis_hash_value *hash_value; - uint32_t rndis_msg_size, tot_data_buf_len, send_buf_section_idx; - int send_buf_section_size; - - tot_data_buf_len = m_head->m_pkthdr.len; + uint32_t send_buf_section_idx; + int send_buf_section_size, pktlen; /* * extension points to the area reserved for the @@ -870,25 +876,20 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) * the netvsc_packet (and rppi struct, if present; * length is updated later). */ - rndis_mesg = txd->rndis_msg; - /* XXX not necessary */ - memset(rndis_mesg, 0, HN_RNDIS_MSG_LEN); - rndis_mesg->ndis_msg_type = REMOTE_NDIS_PACKET_MSG; - - rndis_pkt = &rndis_mesg->msg.packet; - rndis_pkt->data_offset = sizeof(rndis_packet); - rndis_pkt->data_length = tot_data_buf_len; - rndis_pkt->per_pkt_info_offset = sizeof(rndis_packet); - - rndis_msg_size = RNDIS_MESSAGE_SIZE(rndis_packet); + pkt = txd->rndis_pkt; + pkt->rm_type = REMOTE_NDIS_PACKET_MSG; + pkt->rm_len = sizeof(*pkt) + m_head->m_pkthdr.len; + pkt->rm_dataoffset = sizeof(*pkt); + pkt->rm_datalen = m_head->m_pkthdr.len; + pkt->rm_pktinfooffset = sizeof(*pkt); + pkt->rm_pktinfolen = 0; /* * Set the hash value for this packet, so that the host could * dispatch the TX done event for this packet back to this TX * ring's channel. */ - rndis_msg_size += RNDIS_HASHVAL_PPI_SIZE; - rppi = hv_set_rppi_data(rndis_mesg, RNDIS_HASHVAL_PPI_SIZE, + rppi = hv_set_rppi_data(pkt, RNDIS_HASHVAL_PPI_SIZE, nbl_hash_value); hash_value = (struct rndis_hash_value *)((uint8_t *)rppi + rppi->per_packet_info_offset); @@ -897,8 +898,7 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) if (m_head->m_flags & M_VLANTAG) { ndis_8021q_info *rppi_vlan_info; - rndis_msg_size += RNDIS_VLAN_PPI_SIZE; - rppi = hv_set_rppi_data(rndis_mesg, RNDIS_VLAN_PPI_SIZE, + rppi = hv_set_rppi_data(pkt, RNDIS_VLAN_PPI_SIZE, ieee_8021q_info); rppi_vlan_info = (ndis_8021q_info *)((uint8_t *)rppi + @@ -924,8 +924,7 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) else ether_len = ETHER_HDR_LEN; - rndis_msg_size += RNDIS_TSO_PPI_SIZE; - rppi = hv_set_rppi_data(rndis_mesg, RNDIS_TSO_PPI_SIZE, + rppi = hv_set_rppi_data(pkt, RNDIS_TSO_PPI_SIZE, tcp_large_send_info); tso_info = (rndis_tcp_tso_info *)((uint8_t *)rppi + @@ -966,8 +965,7 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) } else if (m_head->m_pkthdr.csum_flags & txr->hn_csum_assist) { rndis_tcp_ip_csum_info *csum_info; - rndis_msg_size += RNDIS_CSUM_PPI_SIZE; - rppi = hv_set_rppi_data(rndis_mesg, RNDIS_CSUM_PPI_SIZE, + rppi = hv_set_rppi_data(pkt, RNDIS_CSUM_PPI_SIZE, tcpip_chksum_info); csum_info = (rndis_tcp_ip_csum_info *)((uint8_t *)rppi + rppi->per_packet_info_offset); @@ -982,24 +980,26 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) csum_info->value |= NDIS_TXCSUM_INFO_UDPCS; } - rndis_mesg->msg_len = tot_data_buf_len + rndis_msg_size; - tot_data_buf_len = rndis_mesg->msg_len; + pktlen = pkt->rm_pktinfooffset + pkt->rm_pktinfolen; + /* Convert RNDIS packet message offsets */ + pkt->rm_dataoffset = hn_rndis_pktmsg_offset(pkt->rm_dataoffset); + pkt->rm_pktinfooffset = hn_rndis_pktmsg_offset(pkt->rm_pktinfooffset); /* * Chimney send, if the packet could fit into one chimney buffer. */ - if (tot_data_buf_len < txr->hn_chim_size) { + if (pkt->rm_len < txr->hn_chim_size) { txr->hn_tx_chimney_tried++; send_buf_section_idx = hn_chim_alloc(txr->hn_sc); if (send_buf_section_idx != HN_NVS_CHIM_IDX_INVALID) { uint8_t *dest = txr->hn_sc->hn_chim + (send_buf_section_idx * txr->hn_sc->hn_chim_szmax); - memcpy(dest, rndis_mesg, rndis_msg_size); - dest += rndis_msg_size; + memcpy(dest, pkt, pktlen); + dest += pktlen; m_copydata(m_head, 0, m_head->m_pkthdr.len, dest); - send_buf_section_size = tot_data_buf_len; + send_buf_section_size = pkt->rm_len; txr->hn_gpa_cnt = 0; txr->hn_tx_chimney++; goto done; @@ -1030,9 +1030,9 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) txr->hn_gpa_cnt = nsegs + 1; /* send packet with page buffer */ - txr->hn_gpa[0].gpa_page = atop(txd->rndis_msg_paddr); - txr->hn_gpa[0].gpa_ofs = txd->rndis_msg_paddr & PAGE_MASK; - txr->hn_gpa[0].gpa_len = rndis_msg_size; + txr->hn_gpa[0].gpa_page = atop(txd->rndis_pkt_paddr); + txr->hn_gpa[0].gpa_ofs = txd->rndis_pkt_paddr & PAGE_MASK; + txr->hn_gpa[0].gpa_len = pktlen; /* * Fill the page buffers with mbuf info after the page @@ -2457,16 +2457,16 @@ hn_create_tx_ring(struct hn_softc *sc, int id) parent_dtag = bus_get_dma_tag(dev); - /* DMA tag for RNDIS messages. */ + /* DMA tag for RNDIS packet messages. */ error = bus_dma_tag_create(parent_dtag, /* parent */ - HN_RNDIS_MSG_ALIGN, /* alignment */ - HN_RNDIS_MSG_BOUNDARY, /* boundary */ + HN_RNDIS_PKT_ALIGN, /* alignment */ + HN_RNDIS_PKT_BOUNDARY, /* boundary */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ - HN_RNDIS_MSG_LEN, /* maxsize */ + HN_RNDIS_PKT_LEN, /* maxsize */ 1, /* nsegments */ - HN_RNDIS_MSG_LEN, /* maxsegsize */ + HN_RNDIS_PKT_LEN, /* maxsegsize */ 0, /* flags */ NULL, /* lockfunc */ NULL, /* lockfuncarg */ @@ -2501,28 +2501,28 @@ hn_create_tx_ring(struct hn_softc *sc, int id) txd->txr = txr; /* - * Allocate and load RNDIS messages. + * Allocate and load RNDIS packet message. */ error = bus_dmamem_alloc(txr->hn_tx_rndis_dtag, - (void **)&txd->rndis_msg, - BUS_DMA_WAITOK | BUS_DMA_COHERENT, - &txd->rndis_msg_dmap); + (void **)&txd->rndis_pkt, + BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, + &txd->rndis_pkt_dmap); if (error) { device_printf(dev, - "failed to allocate rndis_msg, %d\n", i); + "failed to allocate rndis_packet_msg, %d\n", i); return error; } error = bus_dmamap_load(txr->hn_tx_rndis_dtag, - txd->rndis_msg_dmap, - txd->rndis_msg, HN_RNDIS_MSG_LEN, - hyperv_dma_map_paddr, &txd->rndis_msg_paddr, + txd->rndis_pkt_dmap, + txd->rndis_pkt, HN_RNDIS_PKT_LEN, + hyperv_dma_map_paddr, &txd->rndis_pkt_paddr, BUS_DMA_NOWAIT); if (error) { device_printf(dev, - "failed to load rndis_msg, %d\n", i); + "failed to load rndis_packet_msg, %d\n", i); bus_dmamem_free(txr->hn_tx_rndis_dtag, - txd->rndis_msg, txd->rndis_msg_dmap); + txd->rndis_pkt, txd->rndis_pkt_dmap); return error; } @@ -2533,9 +2533,9 @@ hn_create_tx_ring(struct hn_softc *sc, int id) device_printf(dev, "failed to allocate tx data dmamap\n"); bus_dmamap_unload(txr->hn_tx_rndis_dtag, - txd->rndis_msg_dmap); + txd->rndis_pkt_dmap); bus_dmamem_free(txr->hn_tx_rndis_dtag, - txd->rndis_msg, txd->rndis_msg_dmap); + txd->rndis_pkt, txd->rndis_pkt_dmap); return error; } @@ -2593,9 +2593,9 @@ hn_txdesc_dmamap_destroy(struct hn_txdesc *txd) KASSERT(txd->m == NULL, ("still has mbuf installed")); KASSERT((txd->flags & HN_TXD_FLAG_DMAMAP) == 0, ("still dma mapped")); - bus_dmamap_unload(txr->hn_tx_rndis_dtag, txd->rndis_msg_dmap); - bus_dmamem_free(txr->hn_tx_rndis_dtag, txd->rndis_msg, - txd->rndis_msg_dmap); + bus_dmamap_unload(txr->hn_tx_rndis_dtag, txd->rndis_pkt_dmap); + bus_dmamem_free(txr->hn_tx_rndis_dtag, txd->rndis_pkt, + txd->rndis_pkt_dmap); bus_dmamap_destroy(txr->hn_tx_data_dtag, txd->data_dmap); } diff --git a/sys/dev/hyperv/netvsc/hv_rndis.h b/sys/dev/hyperv/netvsc/hv_rndis.h index f765745321f..9ba719241e4 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis.h +++ b/sys/dev/hyperv/netvsc/hv_rndis.h @@ -900,8 +900,7 @@ int netvsc_recv(struct hn_rx_ring *rxr, const void *data, int dlen, const struct hn_recvinfo *info); void netvsc_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr); -void* hv_set_rppi_data(rndis_msg *rndis_mesg, - uint32_t rppi_size, +void* hv_set_rppi_data(struct rndis_packet_msg *pkt, uint32_t rppi_size, int pkt_type); #endif /* __HV_RNDIS_H__ */ diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.c b/sys/dev/hyperv/netvsc/hv_rndis_filter.c index efa8638457b..c56de8c3513 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.c +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.c @@ -106,24 +106,31 @@ again: * Set the Per-Packet-Info with the specified type */ void * -hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size, - int pkt_type) +hv_set_rppi_data(struct rndis_packet_msg *pkt, uint32_t rppi_size, int pkt_type) { - rndis_packet *rndis_pkt; rndis_per_packet_info *rppi; - rndis_pkt = &rndis_mesg->msg.packet; - rndis_pkt->data_offset += rppi_size; + /* Data immediately follow per-packet-info. */ + pkt->rm_dataoffset += rppi_size; - rppi = (rndis_per_packet_info *)((char *)rndis_pkt + - rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_length); + /* Update RNDIS packet msg length */ + pkt->rm_len += rppi_size; + + /* + * Per-packet-info does not move; it only grows. + * + * NOTE: + * rm_pktinfooffset in this phase counts from the beginning + * of rndis_packet_msg. + */ + rppi = (rndis_per_packet_info *)((uint8_t *)pkt + + pkt->rm_pktinfooffset + pkt->rm_pktinfolen); + pkt->rm_pktinfolen += rppi_size; rppi->size = rppi_size; rppi->type = pkt_type; rppi->per_packet_info_offset = sizeof(rndis_per_packet_info); - rndis_pkt->per_pkt_info_length += rppi_size; - return (rppi); } From b44fb279e8b4d44da46216e552981d19878a7a5f Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Wed, 7 Sep 2016 06:02:29 +0000 Subject: [PATCH 055/109] hyperv/hn: Simplify per-packet-info construction. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7794 --- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 63 +++++++------------ sys/dev/hyperv/netvsc/hv_rndis.h | 15 ----- sys/dev/hyperv/netvsc/hv_rndis_filter.c | 38 ++++++----- sys/dev/hyperv/netvsc/if_hnreg.h | 4 ++ sys/dev/hyperv/netvsc/if_hnvar.h | 3 + 5 files changed, 51 insertions(+), 72 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index b8a434b314d..1d2b140d707 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -142,12 +142,12 @@ __FBSDID("$FreeBSD$"); #define HN_RING_CNT_DEF_MAX 8 -#define HN_RNDIS_PKT_LEN \ - (sizeof(struct rndis_packet_msg) + \ - RNDIS_HASHVAL_PPI_SIZE + \ - RNDIS_VLAN_PPI_SIZE + \ - RNDIS_TSO_PPI_SIZE + \ - RNDIS_CSUM_PPI_SIZE) +#define HN_RNDIS_PKT_LEN \ + (sizeof(struct rndis_packet_msg) + \ + HN_RNDIS_PKTINFO_SIZE(HN_NDIS_HASH_VALUE_SIZE) + \ + HN_RNDIS_PKTINFO_SIZE(NDIS_VLAN_INFO_SIZE) + \ + HN_RNDIS_PKTINFO_SIZE(NDIS_LSO2_INFO_SIZE) + \ + HN_RNDIS_PKTINFO_SIZE(NDIS_TXCSUM_INFO_SIZE)) #define HN_RNDIS_PKT_BOUNDARY PAGE_SIZE #define HN_RNDIS_PKT_ALIGN CACHE_LINE_SIZE @@ -865,10 +865,9 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) int error, nsegs, i; struct mbuf *m_head = *m_head0; struct rndis_packet_msg *pkt; - rndis_per_packet_info *rppi; - struct rndis_hash_value *hash_value; uint32_t send_buf_section_idx; int send_buf_section_size, pktlen; + uint32_t *pi_data; /* * extension points to the area reserved for the @@ -889,21 +888,14 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) * dispatch the TX done event for this packet back to this TX * ring's channel. */ - rppi = hv_set_rppi_data(pkt, RNDIS_HASHVAL_PPI_SIZE, - nbl_hash_value); - hash_value = (struct rndis_hash_value *)((uint8_t *)rppi + - rppi->per_packet_info_offset); - hash_value->hash_value = txr->hn_tx_idx; + pi_data = hn_rndis_pktinfo_append(pkt, HN_RNDIS_PKT_LEN, + HN_NDIS_HASH_VALUE_SIZE, HN_NDIS_PKTINFO_TYPE_HASHVAL); + *pi_data = txr->hn_tx_idx; if (m_head->m_flags & M_VLANTAG) { - ndis_8021q_info *rppi_vlan_info; - - rppi = hv_set_rppi_data(pkt, RNDIS_VLAN_PPI_SIZE, - ieee_8021q_info); - - rppi_vlan_info = (ndis_8021q_info *)((uint8_t *)rppi + - rppi->per_packet_info_offset); - rppi_vlan_info->u1.value = NDIS_VLAN_INFO_MAKE( + pi_data = hn_rndis_pktinfo_append(pkt, HN_RNDIS_PKT_LEN, + NDIS_VLAN_INFO_SIZE, NDIS_PKTINFO_TYPE_VLAN); + *pi_data = NDIS_VLAN_INFO_MAKE( EVL_VLANOFTAG(m_head->m_pkthdr.ether_vtag), EVL_PRIOFTAG(m_head->m_pkthdr.ether_vtag), EVL_CFIOFTAG(m_head->m_pkthdr.ether_vtag)); @@ -911,7 +903,6 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) if (m_head->m_pkthdr.csum_flags & CSUM_TSO) { #if defined(INET6) || defined(INET) - rndis_tcp_tso_info *tso_info; struct ether_vlan_header *eh; int ether_len; @@ -924,12 +915,8 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) else ether_len = ETHER_HDR_LEN; - rppi = hv_set_rppi_data(pkt, RNDIS_TSO_PPI_SIZE, - tcp_large_send_info); - - tso_info = (rndis_tcp_tso_info *)((uint8_t *)rppi + - rppi->per_packet_info_offset); - + pi_data = hn_rndis_pktinfo_append(pkt, HN_RNDIS_PKT_LEN, + NDIS_LSO2_INFO_SIZE, NDIS_PKTINFO_TYPE_LSO); #ifdef INET if (m_head->m_pkthdr.csum_flags & CSUM_IP_TSO) { struct ip *ip = @@ -942,7 +929,7 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) ip->ip_sum = 0; th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, htons(IPPROTO_TCP)); - tso_info->value = NDIS_LSO2_INFO_MAKEIPV4(0, + *pi_data = NDIS_LSO2_INFO_MAKEIPV4(0, m_head->m_pkthdr.tso_segsz); } #endif @@ -957,27 +944,23 @@ hn_encap(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head0) ip6->ip6_plen = 0; th->th_sum = in6_cksum_pseudo(ip6, 0, IPPROTO_TCP, 0); - tso_info->value = NDIS_LSO2_INFO_MAKEIPV6(0, + *pi_data = NDIS_LSO2_INFO_MAKEIPV6(0, m_head->m_pkthdr.tso_segsz); } #endif #endif /* INET6 || INET */ } else if (m_head->m_pkthdr.csum_flags & txr->hn_csum_assist) { - rndis_tcp_ip_csum_info *csum_info; + pi_data = hn_rndis_pktinfo_append(pkt, HN_RNDIS_PKT_LEN, + NDIS_TXCSUM_INFO_SIZE, NDIS_PKTINFO_TYPE_CSUM); + *pi_data = NDIS_TXCSUM_INFO_IPV4; - rppi = hv_set_rppi_data(pkt, RNDIS_CSUM_PPI_SIZE, - tcpip_chksum_info); - csum_info = (rndis_tcp_ip_csum_info *)((uint8_t *)rppi + - rppi->per_packet_info_offset); - - csum_info->value = NDIS_TXCSUM_INFO_IPV4; if (m_head->m_pkthdr.csum_flags & CSUM_IP) - csum_info->value |= NDIS_TXCSUM_INFO_IPCS; + *pi_data |= NDIS_TXCSUM_INFO_IPCS; if (m_head->m_pkthdr.csum_flags & CSUM_TCP) - csum_info->value |= NDIS_TXCSUM_INFO_TCPCS; + *pi_data |= NDIS_TXCSUM_INFO_TCPCS; else if (m_head->m_pkthdr.csum_flags & CSUM_UDP) - csum_info->value |= NDIS_TXCSUM_INFO_UDPCS; + *pi_data |= NDIS_TXCSUM_INFO_UDPCS; } pktlen = pkt->rm_pktinfooffset + pkt->rm_pktinfolen; diff --git a/sys/dev/hyperv/netvsc/hv_rndis.h b/sys/dev/hyperv/netvsc/hv_rndis.h index 9ba719241e4..896c7f97e0b 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis.h +++ b/sys/dev/hyperv/netvsc/hv_rndis.h @@ -569,18 +569,6 @@ typedef struct rndis_tcp_tso_info_ { }; } rndis_tcp_tso_info; -#define RNDIS_HASHVAL_PPI_SIZE (sizeof(rndis_per_packet_info) + \ - sizeof(struct rndis_hash_value)) - -#define RNDIS_VLAN_PPI_SIZE (sizeof(rndis_per_packet_info) + \ - sizeof(ndis_8021q_info)) - -#define RNDIS_CSUM_PPI_SIZE (sizeof(rndis_per_packet_info) + \ - sizeof(rndis_tcp_ip_csum_info)) - -#define RNDIS_TSO_PPI_SIZE (sizeof(rndis_per_packet_info) + \ - sizeof(rndis_tcp_tso_info)) - /* * Format of Information buffer passed in a SetRequest for the OID * OID_GEN_RNDIS_CONFIG_PARAMETER. @@ -900,8 +888,5 @@ int netvsc_recv(struct hn_rx_ring *rxr, const void *data, int dlen, const struct hn_recvinfo *info); void netvsc_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr); -void* hv_set_rppi_data(struct rndis_packet_msg *pkt, uint32_t rppi_size, - int pkt_type); - #endif /* __HV_RNDIS_H__ */ diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.c b/sys/dev/hyperv/netvsc/hv_rndis_filter.c index c56de8c3513..a4d796eb171 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.c +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.c @@ -102,19 +102,15 @@ again: return ((rid & 0xffff) << 16); } -/* - * Set the Per-Packet-Info with the specified type - */ void * -hv_set_rppi_data(struct rndis_packet_msg *pkt, uint32_t rppi_size, int pkt_type) +hn_rndis_pktinfo_append(struct rndis_packet_msg *pkt, size_t pktsize, + size_t pi_dlen, uint32_t pi_type) { - rndis_per_packet_info *rppi; + const size_t pi_size = HN_RNDIS_PKTINFO_SIZE(pi_dlen); + struct rndis_pktinfo *pi; - /* Data immediately follow per-packet-info. */ - pkt->rm_dataoffset += rppi_size; - - /* Update RNDIS packet msg length */ - pkt->rm_len += rppi_size; + KASSERT((pi_size & RNDIS_PACKET_MSG_OFFSET_ALIGNMASK) == 0, + ("unaligned pktinfo size %zu, pktinfo dlen %zu", pi_size, pi_dlen)); /* * Per-packet-info does not move; it only grows. @@ -123,15 +119,23 @@ hv_set_rppi_data(struct rndis_packet_msg *pkt, uint32_t rppi_size, int pkt_type) * rm_pktinfooffset in this phase counts from the beginning * of rndis_packet_msg. */ - rppi = (rndis_per_packet_info *)((uint8_t *)pkt + - pkt->rm_pktinfooffset + pkt->rm_pktinfolen); - pkt->rm_pktinfolen += rppi_size; + KASSERT(pkt->rm_pktinfooffset + pkt->rm_pktinfolen + pi_size <= pktsize, + ("%u pktinfo overflows RNDIS packet msg", pi_type)); + pi = (struct rndis_pktinfo *)((uint8_t *)pkt + pkt->rm_pktinfooffset + + pkt->rm_pktinfolen); + pkt->rm_pktinfolen += pi_size; - rppi->size = rppi_size; - rppi->type = pkt_type; - rppi->per_packet_info_offset = sizeof(rndis_per_packet_info); + pi->rm_size = pi_size; + pi->rm_type = pi_type; + pi->rm_pktinfooffset = RNDIS_PKTINFO_OFFSET; - return (rppi); + /* Data immediately follow per-packet-info. */ + pkt->rm_dataoffset += pi_size; + + /* Update RNDIS packet msg length */ + pkt->rm_len += pi_size; + + return (pi->rm_data); } /* diff --git a/sys/dev/hyperv/netvsc/if_hnreg.h b/sys/dev/hyperv/netvsc/if_hnreg.h index 5dfadbf5535..a2ddf9c998b 100644 --- a/sys/dev/hyperv/netvsc/if_hnreg.h +++ b/sys/dev/hyperv/netvsc/if_hnreg.h @@ -221,4 +221,8 @@ CTASSERT(sizeof(struct hn_nvs_rndis_ack) >= HN_NVS_REQSIZE_MIN); #define HN_NDIS_HASH_VALUE_SIZE sizeof(uint32_t) #define HN_NDIS_PKTINFO_TYPE_HASHVAL NDIS_PKTINFO_TYPE_PKT_CANCELID +/* Per-packet-info size */ +#define HN_RNDIS_PKTINFO_SIZE(dlen) \ + __offsetof(struct rndis_pktinfo, rm_data[dlen]) + #endif /* !_IF_HNREG_H_ */ diff --git a/sys/dev/hyperv/netvsc/if_hnvar.h b/sys/dev/hyperv/netvsc/if_hnvar.h index 00ef144273c..697b6358b97 100644 --- a/sys/dev/hyperv/netvsc/if_hnvar.h +++ b/sys/dev/hyperv/netvsc/if_hnvar.h @@ -121,6 +121,9 @@ void hn_nvs_sent_xact(struct hn_send_ctx *sndc, struct hn_softc *sc, uint32_t hn_chim_alloc(struct hn_softc *sc); void hn_chim_free(struct hn_softc *sc, uint32_t chim_idx); +void *hn_rndis_pktinfo_append(struct rndis_packet_msg *, + size_t pktsize, size_t pi_dlen, uint32_t pi_type); + extern struct hn_send_ctx hn_send_ctx_none; #endif /* !_IF_HNVAR_H_ */ From b67f3d2873d7ccc39a9de6049fa428009bd96f37 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Wed, 7 Sep 2016 09:20:58 +0000 Subject: [PATCH 056/109] hyperv/hn: Nuke unused bits MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7795 --- sys/dev/hyperv/netvsc/hv_net_vsc.c | 16 +- sys/dev/hyperv/netvsc/hv_net_vsc.h | 130 --- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 11 +- sys/dev/hyperv/netvsc/hv_rndis.h | 892 ------------------ sys/dev/hyperv/netvsc/hv_rndis_filter.c | 16 +- sys/dev/hyperv/netvsc/if_hnreg.h | 8 + sys/dev/hyperv/netvsc/if_hnvar.h | 5 + 7 files changed, 34 insertions(+), 1044 deletions(-) delete mode 100644 sys/dev/hyperv/netvsc/hv_rndis.h diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index 870c0634998..5163be58f51 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -48,9 +48,9 @@ #include #include #include -#include #include #include +#include MALLOC_DEFINE(M_NETVSC, "netvsc", "Hyper-V netvsc driver"); @@ -513,15 +513,15 @@ hv_nv_connect_to_vsp(struct hn_softc *sc) for (i = protocol_number - 1; i >= 0; i--) { if (hv_nv_negotiate_nvsp_protocol(sc, protocol_list[i]) == 0) { sc->hn_nvs_ver = protocol_list[i]; - sc->hn_ndis_ver = NDIS_VERSION_6_30; + sc->hn_ndis_ver = HN_NDIS_VERSION_6_30; if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_4) - sc->hn_ndis_ver = NDIS_VERSION_6_1; + sc->hn_ndis_ver = HN_NDIS_VERSION_6_1; if (bootverbose) { if_printf(sc->hn_ifp, "NVS version 0x%x, " "NDIS version %u.%u\n", sc->hn_nvs_ver, - NDIS_VERSION_MAJOR(sc->hn_ndis_ver), - NDIS_VERSION_MINOR(sc->hn_ndis_ver)); + HN_NDIS_VERSION_MAJOR(sc->hn_ndis_ver), + HN_NDIS_VERSION_MINOR(sc->hn_ndis_ver)); } break; } @@ -547,8 +547,8 @@ hv_nv_connect_to_vsp(struct hn_softc *sc) memset(&ndis, 0, sizeof(ndis)); ndis.nvs_type = HN_NVS_TYPE_NDIS_INIT; - ndis.nvs_ndis_major = NDIS_VERSION_MAJOR(sc->hn_ndis_ver); - ndis.nvs_ndis_minor = NDIS_VERSION_MINOR(sc->hn_ndis_ver); + ndis.nvs_ndis_major = HN_NDIS_VERSION_MAJOR(sc->hn_ndis_ver); + ndis.nvs_ndis_minor = HN_NDIS_VERSION_MINOR(sc->hn_ndis_ver); /* NOTE: No response. */ ret = hn_nvs_req_send(sc, &ndis, sizeof(ndis)); @@ -764,7 +764,7 @@ hv_nv_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr, } pkt = (const struct vmbus_chanpkt_rxbuf *)pkthdr; - if (__predict_false(pkt->cp_rxbuf_id != NETVSC_RECEIVE_BUFFER_ID)) { + if (__predict_false(pkt->cp_rxbuf_id != HN_NVS_RXBUF_SIG)) { if_printf(rxr->hn_ifp, "invalid rxbuf_id 0x%08x\n", pkt->cp_rxbuf_id); return; diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h index b4688ce3828..359fb73567f 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.h +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h @@ -74,110 +74,6 @@ MALLOC_DECLARE(M_NETVSC); #define NVSP_PROTOCOL_VERSION_2 0x30002 #define NVSP_PROTOCOL_VERSION_4 0x40000 #define NVSP_PROTOCOL_VERSION_5 0x50000 -#define NVSP_MIN_PROTOCOL_VERSION (NVSP_PROTOCOL_VERSION_1) -#define NVSP_MAX_PROTOCOL_VERSION (NVSP_PROTOCOL_VERSION_2) - -#define NVSP_PROTOCOL_VERSION_CURRENT NVSP_PROTOCOL_VERSION_2 - -#define VERSION_4_OFFLOAD_SIZE 22 - -#define NVSP_OPERATIONAL_STATUS_OK (0x00000000) -#define NVSP_OPERATIONAL_STATUS_DEGRADED (0x00000001) -#define NVSP_OPERATIONAL_STATUS_NONRECOVERABLE (0x00000002) -#define NVSP_OPERATIONAL_STATUS_NO_CONTACT (0x00000003) -#define NVSP_OPERATIONAL_STATUS_LOST_COMMUNICATION (0x00000004) - -/* - * Maximun number of transfer pages (packets) the VSP will use on a receive - */ -#define NVSP_MAX_PACKETS_PER_RECEIVE 375 - -/* vRSS stuff */ -#define RNDIS_OBJECT_TYPE_RSS_CAPABILITIES 0x88 -#define RNDIS_OBJECT_TYPE_RSS_PARAMETERS 0x89 - -#define RNDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2 2 -#define RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2 2 - -struct rndis_obj_header { - uint8_t type; - uint8_t rev; - uint16_t size; -} __packed; - -/* rndis_recv_scale_cap/cap_flag */ -#define RNDIS_RSS_CAPS_MESSAGE_SIGNALED_INTERRUPTS 0x01000000 -#define RNDIS_RSS_CAPS_CLASSIFICATION_AT_ISR 0x02000000 -#define RNDIS_RSS_CAPS_CLASSIFICATION_AT_DPC 0x04000000 -#define RNDIS_RSS_CAPS_USING_MSI_X 0x08000000 -#define RNDIS_RSS_CAPS_RSS_AVAILABLE_ON_PORTS 0x10000000 -#define RNDIS_RSS_CAPS_SUPPORTS_MSI_X 0x20000000 -#define RNDIS_RSS_CAPS_HASH_TYPE_TCP_IPV4 0x00000100 -#define RNDIS_RSS_CAPS_HASH_TYPE_TCP_IPV6 0x00000200 -#define RNDIS_RSS_CAPS_HASH_TYPE_TCP_IPV6_EX 0x00000400 - -/* RNDIS_RECEIVE_SCALE_CAPABILITIES */ -struct rndis_recv_scale_cap { - struct rndis_obj_header hdr; - uint32_t cap_flag; - uint32_t num_int_msg; - uint32_t num_recv_que; - uint16_t num_indirect_tabent; -} __packed; - -/* rndis_recv_scale_param flags */ -#define RNDIS_RSS_PARAM_FLAG_BASE_CPU_UNCHANGED 0x0001 -#define RNDIS_RSS_PARAM_FLAG_HASH_INFO_UNCHANGED 0x0002 -#define RNDIS_RSS_PARAM_FLAG_ITABLE_UNCHANGED 0x0004 -#define RNDIS_RSS_PARAM_FLAG_HASH_KEY_UNCHANGED 0x0008 -#define RNDIS_RSS_PARAM_FLAG_DISABLE_RSS 0x0010 - -/* Hash info bits */ -#define RNDIS_HASH_FUNC_TOEPLITZ 0x00000001 -#define RNDIS_HASH_IPV4 0x00000100 -#define RNDIS_HASH_TCP_IPV4 0x00000200 -#define RNDIS_HASH_IPV6 0x00000400 -#define RNDIS_HASH_IPV6_EX 0x00000800 -#define RNDIS_HASH_TCP_IPV6 0x00001000 -#define RNDIS_HASH_TCP_IPV6_EX 0x00002000 - -#define RNDIS_RSS_INDIRECTION_TABLE_MAX_SIZE_REVISION_2 (128 * 4) -#define RNDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_2 40 - -#define ITAB_NUM 128 -#define HASH_KEYLEN RNDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_2 - -/* RNDIS_RECEIVE_SCALE_PARAMETERS */ -typedef struct rndis_recv_scale_param_ { - struct rndis_obj_header hdr; - - /* Qualifies the rest of the information */ - uint16_t flag; - - /* The base CPU number to do receive processing. not used */ - uint16_t base_cpu_number; - - /* This describes the hash function and type being enabled */ - uint32_t hashinfo; - - /* The size of indirection table array */ - uint16_t indirect_tabsize; - - /* The offset of the indirection table from the beginning of this - * structure - */ - uint32_t indirect_taboffset; - - /* The size of the hash secret key */ - uint16_t hashkey_size; - - /* The offset of the secret key from the beginning of this structure */ - uint32_t hashkey_offset; - - uint32_t processor_masks_offset; - uint32_t num_processor_masks; - uint32_t processor_masks_entry_size; -} rndis_recv_scale_param; /* * The following arguably belongs in a separate header file @@ -188,18 +84,10 @@ typedef struct rndis_recv_scale_param_ { */ #define NETVSC_SEND_BUFFER_SIZE (1024*1024*15) /* 15M */ -#define NETVSC_SEND_BUFFER_ID 0xface #define NETVSC_RECEIVE_BUFFER_SIZE_LEGACY (1024*1024*15) /* 15MB */ #define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024*16) /* 16MB */ -#define NETVSC_RECEIVE_BUFFER_ID 0xcafe - -#define NETVSC_RECEIVE_SG_COUNT 1 - -/* Preallocated receive packets */ -#define NETVSC_RECEIVE_PACKETLIST_COUNT 256 - /* * Maximum MTU we permit to be configured for a netvsc interface. * When the code was developed, a max MTU of 12232 was tested and @@ -208,7 +96,6 @@ typedef struct rndis_recv_scale_param_ { #define NETVSC_MAX_CONFIGURABLE_MTU (9 * 1024) #define NETVSC_PACKET_SIZE PAGE_SIZE -#define VRSS_SEND_TABLE_SIZE 16 /* * Data types @@ -216,26 +103,9 @@ typedef struct rndis_recv_scale_param_ { struct vmbus_channel; -typedef void (*pfn_on_send_rx_completion)(struct vmbus_channel *, void *); - #define NETVSC_DEVICE_RING_BUFFER_SIZE (128 * PAGE_SIZE) #define NETVSC_PACKET_MAXPAGE 32 -#define NETVSC_VLAN_PRIO_MASK 0xe000 -#define NETVSC_VLAN_PRIO_SHIFT 13 -#define NETVSC_VLAN_VID_MASK 0x0fff - -#define TYPE_IPV4 2 -#define TYPE_IPV6 4 -#define TYPE_TCP 2 -#define TYPE_UDP 4 - -#define TRANSPORT_TYPE_NOT_IP 0 -#define TRANSPORT_TYPE_IPV4_TCP ((TYPE_IPV4 << 16) | TYPE_TCP) -#define TRANSPORT_TYPE_IPV4_UDP ((TYPE_IPV4 << 16) | TYPE_UDP) -#define TRANSPORT_TYPE_IPV6_TCP ((TYPE_IPV6 << 16) | TYPE_TCP) -#define TRANSPORT_TYPE_IPV6_UDP ((TYPE_IPV6 << 16) | TYPE_UDP) - typedef struct { uint8_t mac_addr[ETHER_ADDR_LEN]; uint32_t link_state; diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index 1d2b140d707..b443c2e72bf 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -78,7 +78,7 @@ __FBSDID("$FreeBSD$"); #include #include #include - +#include #include #include @@ -118,7 +118,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -827,7 +826,7 @@ hn_tx_done(struct hn_send_ctx *sndc, struct hn_softc *sc, } void -netvsc_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr) +hn_chan_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr) { #if defined(INET) || defined(INET6) tcp_lro_flush_all(&rxr->hn_lro); @@ -1263,7 +1262,7 @@ hn_lro_rx(struct lro_ctrl *lc, struct mbuf *m) * Note: This is no longer used as a callback */ int -netvsc_recv(struct hn_rx_ring *rxr, const void *data, int dlen, +hn_rxpkt(struct hn_rx_ring *rxr, const void *data, int dlen, const struct hn_recvinfo *info) { struct ifnet *ifp = rxr->hn_ifp; @@ -2089,8 +2088,8 @@ hn_ndis_version_sysctl(SYSCTL_HANDLER_ARGS) char verstr[16]; snprintf(verstr, sizeof(verstr), "%u.%u", - NDIS_VERSION_MAJOR(sc->hn_ndis_ver), - NDIS_VERSION_MINOR(sc->hn_ndis_ver)); + HN_NDIS_VERSION_MAJOR(sc->hn_ndis_ver), + HN_NDIS_VERSION_MINOR(sc->hn_ndis_ver)); return sysctl_handle_string(oidp, verstr, sizeof(verstr), req); } diff --git a/sys/dev/hyperv/netvsc/hv_rndis.h b/sys/dev/hyperv/netvsc/hv_rndis.h deleted file mode 100644 index 896c7f97e0b..00000000000 --- a/sys/dev/hyperv/netvsc/hv_rndis.h +++ /dev/null @@ -1,892 +0,0 @@ -/*- - * Copyright (c) 2009-2012,2016 Microsoft Corp. - * Copyright (c) 2010-2012 Citrix Inc. - * Copyright (c) 2012 NetApp Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. 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 AUTHOR ``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 AUTHOR 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. - * - * $FreeBSD$ - */ - -#ifndef __HV_RNDIS_H__ -#define __HV_RNDIS_H__ - -#include - -/* - * NDIS protocol version numbers - */ -#define NDIS_VERSION_5_0 0x00050000 -#define NDIS_VERSION_5_1 0x00050001 -#define NDIS_VERSION_6_0 0x00060000 -#define NDIS_VERSION_6_1 0x00060001 -#define NDIS_VERSION_6_30 0x0006001e - -#define NDIS_VERSION_MAJOR(ver) (((ver) & 0xffff0000) >> 16) -#define NDIS_VERSION_MINOR(ver) ((ver) & 0xffff) - -/* - * Object Identifiers used by NdisRequest Query/Set Information - */ - -/* - * General Objects - */ - -#define RNDIS_OID_GEN_SUPPORTED_LIST 0x00010101 -#define RNDIS_OID_GEN_HARDWARE_STATUS 0x00010102 -#define RNDIS_OID_GEN_MEDIA_SUPPORTED 0x00010103 -#define RNDIS_OID_GEN_MEDIA_IN_USE 0x00010104 -#define RNDIS_OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 -#define RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 -#define RNDIS_OID_GEN_LINK_SPEED 0x00010107 -#define RNDIS_OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 -#define RNDIS_OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 -#define RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A -#define RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B -#define RNDIS_OID_GEN_VENDOR_ID 0x0001010C -#define RNDIS_OID_GEN_VENDOR_DESCRIPTION 0x0001010D -#define RNDIS_OID_GEN_CURRENT_PACKET_FILTER 0x0001010E -#define RNDIS_OID_GEN_CURRENT_LOOKAHEAD 0x0001010F -#define RNDIS_OID_GEN_DRIVER_VERSION 0x00010110 -#define RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 -#define RNDIS_OID_GEN_PROTOCOL_OPTIONS 0x00010112 -#define RNDIS_OID_GEN_MAC_OPTIONS 0x00010113 -#define RNDIS_OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 -#define RNDIS_OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 -#define RNDIS_OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 -#define RNDIS_OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 -#define RNDIS_OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 -#define RNDIS_OID_GEN_MACHINE_NAME 0x0001021A -#define RNDIS_OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B - -/* - * For receive side scale - */ -/* Query only */ -#define RNDIS_OID_GEN_RSS_CAPABILITIES 0x00010203 -/* Query and set */ -#define RNDIS_OID_GEN_RSS_PARAMETERS 0x00010204 - -#define RNDIS_OID_GEN_XMIT_OK 0x00020101 -#define RNDIS_OID_GEN_RCV_OK 0x00020102 -#define RNDIS_OID_GEN_XMIT_ERROR 0x00020103 -#define RNDIS_OID_GEN_RCV_ERROR 0x00020104 -#define RNDIS_OID_GEN_RCV_NO_BUFFER 0x00020105 - -#define RNDIS_OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 -#define RNDIS_OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 -#define RNDIS_OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 -#define RNDIS_OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 -#define RNDIS_OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 -#define RNDIS_OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 -#define RNDIS_OID_GEN_DIRECTED_BYTES_RCV 0x00020207 -#define RNDIS_OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 -#define RNDIS_OID_GEN_MULTICAST_BYTES_RCV 0x00020209 -#define RNDIS_OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A -#define RNDIS_OID_GEN_BROADCAST_BYTES_RCV 0x0002020B -#define RNDIS_OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C - -#define RNDIS_OID_GEN_RCV_CRC_ERROR 0x0002020D -#define RNDIS_OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E - -#define RNDIS_OID_GEN_GET_TIME_CAPS 0x0002020F -#define RNDIS_OID_GEN_GET_NETCARD_TIME 0x00020210 - -/* - * These are connection-oriented general OIDs. - * These replace the above OIDs for connection-oriented media. - */ -#define RNDIS_OID_GEN_CO_SUPPORTED_LIST 0x00010101 -#define RNDIS_OID_GEN_CO_HARDWARE_STATUS 0x00010102 -#define RNDIS_OID_GEN_CO_MEDIA_SUPPORTED 0x00010103 -#define RNDIS_OID_GEN_CO_MEDIA_IN_USE 0x00010104 -#define RNDIS_OID_GEN_CO_LINK_SPEED 0x00010105 -#define RNDIS_OID_GEN_CO_VENDOR_ID 0x00010106 -#define RNDIS_OID_GEN_CO_VENDOR_DESCRIPTION 0x00010107 -#define RNDIS_OID_GEN_CO_DRIVER_VERSION 0x00010108 -#define RNDIS_OID_GEN_CO_PROTOCOL_OPTIONS 0x00010109 -#define RNDIS_OID_GEN_CO_MAC_OPTIONS 0x0001010A -#define RNDIS_OID_GEN_CO_MEDIA_CONNECT_STATUS 0x0001010B -#define RNDIS_OID_GEN_CO_VENDOR_DRIVER_VERSION 0x0001010C -#define RNDIS_OID_GEN_CO_MINIMUM_LINK_SPEED 0x0001010D - -#define RNDIS_OID_GEN_CO_GET_TIME_CAPS 0x00010201 -#define RNDIS_OID_GEN_CO_GET_NETCARD_TIME 0x00010202 - -/* - * These are connection-oriented statistics OIDs. - */ -#define RNDIS_OID_GEN_CO_XMIT_PDUS_OK 0x00020101 -#define RNDIS_OID_GEN_CO_RCV_PDUS_OK 0x00020102 -#define RNDIS_OID_GEN_CO_XMIT_PDUS_ERROR 0x00020103 -#define RNDIS_OID_GEN_CO_RCV_PDUS_ERROR 0x00020104 -#define RNDIS_OID_GEN_CO_RCV_PDUS_NO_BUFFER 0x00020105 - - -#define RNDIS_OID_GEN_CO_RCV_CRC_ERROR 0x00020201 -#define RNDIS_OID_GEN_CO_TRANSMIT_QUEUE_LENGTH 0x00020202 -#define RNDIS_OID_GEN_CO_BYTES_XMIT 0x00020203 -#define RNDIS_OID_GEN_CO_BYTES_RCV 0x00020204 -#define RNDIS_OID_GEN_CO_BYTES_XMIT_OUTSTANDING 0x00020205 -#define RNDIS_OID_GEN_CO_NETCARD_LOAD 0x00020206 - -/* - * These are objects for Connection-oriented media call-managers. - */ -#define RNDIS_OID_CO_ADD_PVC 0xFF000001 -#define RNDIS_OID_CO_DELETE_PVC 0xFF000002 -#define RNDIS_OID_CO_GET_CALL_INFORMATION 0xFF000003 -#define RNDIS_OID_CO_ADD_ADDRESS 0xFF000004 -#define RNDIS_OID_CO_DELETE_ADDRESS 0xFF000005 -#define RNDIS_OID_CO_GET_ADDRESSES 0xFF000006 -#define RNDIS_OID_CO_ADDRESS_CHANGE 0xFF000007 -#define RNDIS_OID_CO_SIGNALING_ENABLED 0xFF000008 -#define RNDIS_OID_CO_SIGNALING_DISABLED 0xFF000009 - - -/* - * 802.3 Objects (Ethernet) - */ - -#define RNDIS_OID_802_3_PERMANENT_ADDRESS 0x01010101 -#define RNDIS_OID_802_3_CURRENT_ADDRESS 0x01010102 -#define RNDIS_OID_802_3_MULTICAST_LIST 0x01010103 -#define RNDIS_OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 -#define RNDIS_OID_802_3_MAC_OPTIONS 0x01010105 - -/* - * - */ -#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 - -#define RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 -#define RNDIS_OID_802_3_XMIT_ONE_COLLISION 0x01020102 -#define RNDIS_OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 - -#define RNDIS_OID_802_3_XMIT_DEFERRED 0x01020201 -#define RNDIS_OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 -#define RNDIS_OID_802_3_RCV_OVERRUN 0x01020203 -#define RNDIS_OID_802_3_XMIT_UNDERRUN 0x01020204 -#define RNDIS_OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 -#define RNDIS_OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 -#define RNDIS_OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 - - -/* - * RNDIS MP custom OID for test - */ -#define OID_RNDISMP_GET_RECEIVE_BUFFERS 0xFFA0C90D // Query only - -/* - * Remote NDIS offload parameters - */ -#define RNDIS_OBJECT_TYPE_DEFAULT 0x80 - -#define RNDIS_OFFLOAD_PARAMETERS_REVISION_3 3 -#define RNDIS_OFFLOAD_PARAMETERS_NO_CHANGE 0 -#define RNDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED 1 -#define RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED 2 -#define RNDIS_OFFLOAD_PARAMETERS_LSOV1_ENABLED 2 -#define RNDIS_OFFLOAD_PARAMETERS_RSC_DISABLED 1 -#define RNDIS_OFFLOAD_PARAMETERS_RSC_ENABLED 2 -#define RNDIS_OFFLOAD_PARAMETERS_TX_RX_DISABLED 1 -#define RNDIS_OFFLOAD_PARAMETERS_TX_ENABLED_RX_DISABLED 2 -#define RNDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED 3 -#define RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED 4 - -#define RNDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE 1 -#define RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV4 0 -#define RNDIS_TCP_LARGE_SEND_OFFLOAD_IPV6 1 - - -#define RNDIS_OID_TCP_OFFLOAD_CURRENT_CONFIG 0xFC01020B /* query only */ -#define RNDIS_OID_TCP_OFFLOAD_PARAMETERS 0xFC01020C /* set only */ -#define RNDIS_OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020D/* query only */ -#define RNDIS_OID_TCP_CONNECTION_OFFLOAD_CURRENT_CONFIG 0xFC01020E /* query only */ -#define RNDIS_OID_TCP_CONNECTION_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020F /* query */ -#define RNDIS_OID_OFFLOAD_ENCAPSULATION 0x0101010A /* set/query */ - -/* - * NdisInitialize message - */ -typedef struct rndis_initialize_request_ { - /* RNDIS request ID */ - uint32_t request_id; - uint32_t major_version; - uint32_t minor_version; - uint32_t max_xfer_size; -} rndis_initialize_request; - -/* - * Response to NdisInitialize - */ -typedef struct rndis_initialize_complete_ { - /* RNDIS request ID */ - uint32_t request_id; - /* RNDIS status */ - uint32_t status; - uint32_t major_version; - uint32_t minor_version; - uint32_t device_flags; - /* RNDIS medium */ - uint32_t medium; - uint32_t max_pkts_per_msg; - uint32_t max_xfer_size; - uint32_t pkt_align_factor; - uint32_t af_list_offset; - uint32_t af_list_size; -} rndis_initialize_complete; - -/* - * Call manager devices only: Information about an address family - * supported by the device is appended to the response to NdisInitialize. - */ -typedef struct rndis_co_address_family_ { - /* RNDIS AF */ - uint32_t address_family; - uint32_t major_version; - uint32_t minor_version; -} rndis_co_address_family; - -/* - * NdisHalt message - */ -typedef struct rndis_halt_request_ { - /* RNDIS request ID */ - uint32_t request_id; -} rndis_halt_request; - -/* - * NdisQueryRequest message - */ -typedef struct rndis_query_request_ { - /* RNDIS request ID */ - uint32_t request_id; - /* RNDIS OID */ - uint32_t oid; - uint32_t info_buffer_length; - uint32_t info_buffer_offset; - /* RNDIS handle */ - uint32_t device_vc_handle; -} rndis_query_request; - -/* - * Response to NdisQueryRequest - */ -typedef struct rndis_query_complete_ { - /* RNDIS request ID */ - uint32_t request_id; - /* RNDIS status */ - uint32_t status; - uint32_t info_buffer_length; - uint32_t info_buffer_offset; -} rndis_query_complete; - -/* - * NdisSetRequest message - */ -typedef struct rndis_set_request_ { - /* RNDIS request ID */ - uint32_t request_id; - /* RNDIS OID */ - uint32_t oid; - uint32_t info_buffer_length; - uint32_t info_buffer_offset; - /* RNDIS handle */ - uint32_t device_vc_handle; -} rndis_set_request; - -/* - * Response to NdisSetRequest - */ -typedef struct rndis_set_complete_ { - /* RNDIS request ID */ - uint32_t request_id; - /* RNDIS status */ - uint32_t status; -} rndis_set_complete; - -/* - * NdisReset message - */ -typedef struct rndis_reset_request_ { - uint32_t reserved; -} rndis_reset_request; - -/* - * Response to NdisReset - */ -typedef struct rndis_reset_complete_ { - /* RNDIS status */ - uint32_t status; - uint32_t addressing_reset; -} rndis_reset_complete; - -/* - * NdisMIndicateStatus message - */ -typedef struct rndis_indicate_status_ { - /* RNDIS status */ - uint32_t status; - uint32_t status_buf_length; - uint32_t status_buf_offset; -} rndis_indicate_status; - -/* - * Diagnostic information passed as the status buffer in - * rndis_indicate_status messages signifying error conditions. - */ -typedef struct rndis_diagnostic_info_ { - /* RNDIS status */ - uint32_t diag_status; - uint32_t error_offset; -} rndis_diagnostic_info; - -/* - * NdisKeepAlive message - */ -typedef struct rndis_keepalive_request_ { - /* RNDIS request ID */ - uint32_t request_id; -} rndis_keepalive_request; - -/* - * Response to NdisKeepAlive - */ -typedef struct rndis_keepalive_complete_ { - /* RNDIS request ID */ - uint32_t request_id; - /* RNDIS status */ - uint32_t status; -} rndis_keepalive_complete; - -/* - * Data message. All offset fields contain byte offsets from the beginning - * of the rndis_packet structure. All length fields are in bytes. - * VcHandle is set to 0 for connectionless data, otherwise it - * contains the VC handle. - */ -typedef struct rndis_packet_ { - uint32_t data_offset; - uint32_t data_length; - uint32_t oob_data_offset; - uint32_t oob_data_length; - uint32_t num_oob_data_elements; - uint32_t per_pkt_info_offset; - uint32_t per_pkt_info_length; - /* RNDIS handle */ - uint32_t vc_handle; - uint32_t reserved; -} rndis_packet; - -typedef struct rndis_packet_ex_ { - uint32_t data_offset; - uint32_t data_length; - uint32_t oob_data_offset; - uint32_t oob_data_length; - uint32_t num_oob_data_elements; - uint32_t per_pkt_info_offset; - uint32_t per_pkt_info_length; - /* RNDIS handle */ - uint32_t vc_handle; - uint32_t reserved; - uint64_t data_buf_id; - uint32_t data_buf_offset; - uint64_t next_header_buf_id; - uint32_t next_header_byte_offset; - uint32_t next_header_byte_count; -} rndis_packet_ex; - -/* - * Optional Out of Band data associated with a Data message. - */ -typedef struct rndis_oobd_ { - uint32_t size; - /* RNDIS class ID */ - uint32_t type; - uint32_t class_info_offset; -} rndis_oobd; - -/* - * Packet extension field contents associated with a Data message. - */ -typedef struct rndis_per_packet_info_ { - uint32_t size; - uint32_t type; - uint32_t per_packet_info_offset; -} rndis_per_packet_info; - -typedef enum ndis_per_pkt_infotype_ { - tcpip_chksum_info, - ipsec_info, - tcp_large_send_info, - classification_handle_info, - ndis_reserved, - sgl_info, - ieee_8021q_info, - original_pkt_info, - pkt_cancel_id, - original_netbuf_list, - cached_netbuf_list, - short_pkt_padding_info, - max_perpkt_info -} ndis_per_pkt_infotype; - -#define nbl_hash_value pkt_cancel_id -#define nbl_hash_info original_netbuf_list - -typedef struct ndis_8021q_info_ { - union { - struct { - uint32_t user_pri : 3; /* User Priority */ - uint32_t cfi : 1; /* Canonical Format ID */ - uint32_t vlan_id : 12; - uint32_t reserved : 16; - } s1; - uint32_t value; - } u1; -} ndis_8021q_info; - -struct rndis_object_header { - uint8_t type; - uint8_t revision; - uint16_t size; -}; - -typedef struct rndis_offload_params_ { - struct rndis_object_header header; - uint8_t ipv4_csum; - uint8_t tcp_ipv4_csum; - uint8_t udp_ipv4_csum; - uint8_t tcp_ipv6_csum; - uint8_t udp_ipv6_csum; - uint8_t lso_v1; - uint8_t ip_sec_v1; - uint8_t lso_v2_ipv4; - uint8_t lso_v2_ipv6; - uint8_t tcp_connection_ipv4; - uint8_t tcp_connection_ipv6; - uint32_t flags; - uint8_t ip_sec_v2; - uint8_t ip_sec_v2_ipv4; - struct { - uint8_t rsc_ipv4; - uint8_t rsc_ipv6; - }; - struct { - uint8_t encapsulated_packet_task_offload; - uint8_t encapsulation_types; - }; - -} rndis_offload_params; - - -typedef struct rndis_tcp_ip_csum_info_ { - union { - struct { - uint32_t is_ipv4:1; - uint32_t is_ipv6:1; - uint32_t tcp_csum:1; - uint32_t udp_csum:1; - uint32_t ip_header_csum:1; - uint32_t reserved:11; - uint32_t tcp_header_offset:10; - } xmit; - struct { - uint32_t tcp_csum_failed:1; - uint32_t udp_csum_failed:1; - uint32_t ip_csum_failed:1; - uint32_t tcp_csum_succeeded:1; - uint32_t udp_csum_succeeded:1; - uint32_t ip_csum_succeeded:1; - uint32_t loopback:1; - uint32_t tcp_csum_value_invalid:1; - uint32_t ip_csum_value_invalid:1; - } receive; - uint32_t value; - }; -} rndis_tcp_ip_csum_info; - -struct rndis_hash_value { - uint32_t hash_value; -} __packed; - -struct rndis_hash_info { - uint32_t hash_info; -} __packed; - -typedef struct rndis_tcp_tso_info_ { - union { - struct { - uint32_t unused:30; - uint32_t type:1; - uint32_t reserved2:1; - } xmit; - struct { - uint32_t mss:20; - uint32_t tcp_header_offset:10; - uint32_t type:1; - uint32_t reserved2:1; - } lso_v1_xmit; - struct { - uint32_t tcp_payload:30; - uint32_t type:1; - uint32_t reserved2:1; - } lso_v1_xmit_complete; - struct { - uint32_t mss:20; - uint32_t tcp_header_offset:10; - uint32_t type:1; - uint32_t ip_version:1; - } lso_v2_xmit; - struct { - uint32_t reserved:30; - uint32_t type:1; - uint32_t reserved2:1; - } lso_v2_xmit_complete; - uint32_t value; - }; -} rndis_tcp_tso_info; - -/* - * Format of Information buffer passed in a SetRequest for the OID - * OID_GEN_RNDIS_CONFIG_PARAMETER. - */ -typedef struct rndis_config_parameter_info_ { - uint32_t parameter_name_offset; - uint32_t parameter_name_length; - uint32_t parameter_type; - uint32_t parameter_value_offset; - uint32_t parameter_value_length; -} rndis_config_parameter_info; - -/* - * Values for ParameterType in rndis_config_parameter_info - */ -#define RNDIS_CONFIG_PARAM_TYPE_INTEGER 0 -#define RNDIS_CONFIG_PARAM_TYPE_STRING 2 - - -/* - * CONDIS Miniport messages for connection oriented devices - * that do not implement a call manager. - */ - -/* - * CoNdisMiniportCreateVc message - */ -typedef struct rcondis_mp_create_vc_ { - /* RNDIS request ID */ - uint32_t request_id; - /* RNDIS handle */ - uint32_t ndis_vc_handle; -} rcondis_mp_create_vc; - -/* - * Response to CoNdisMiniportCreateVc - */ -typedef struct rcondis_mp_create_vc_complete_ { - /* RNDIS request ID */ - uint32_t request_id; - /* RNDIS handle */ - uint32_t device_vc_handle; - /* RNDIS status */ - uint32_t status; -} rcondis_mp_create_vc_complete; - -/* - * CoNdisMiniportDeleteVc message - */ -typedef struct rcondis_mp_delete_vc_ { - /* RNDIS request ID */ - uint32_t request_id; - /* RNDIS handle */ - uint32_t device_vc_handle; -} rcondis_mp_delete_vc; - -/* - * Response to CoNdisMiniportDeleteVc - */ -typedef struct rcondis_mp_delete_vc_complete_ { - /* RNDIS request ID */ - uint32_t request_id; - /* RNDIS status */ - uint32_t status; -} rcondis_mp_delete_vc_complete; - -/* - * CoNdisMiniportQueryRequest message - */ -typedef struct rcondis_mp_query_request_ { - /* RNDIS request ID */ - uint32_t request_id; - /* RNDIS request type */ - uint32_t request_type; - /* RNDIS OID */ - uint32_t oid; - /* RNDIS handle */ - uint32_t device_vc_handle; - uint32_t info_buf_length; - uint32_t info_buf_offset; -} rcondis_mp_query_request; - -/* - * CoNdisMiniportSetRequest message - */ -typedef struct rcondis_mp_set_request_ { - /* RNDIS request ID */ - uint32_t request_id; - /* RNDIS request type */ - uint32_t request_type; - /* RNDIS OID */ - uint32_t oid; - /* RNDIS handle */ - uint32_t device_vc_handle; - uint32_t info_buf_length; - uint32_t info_buf_offset; -} rcondis_mp_set_request; - -/* - * CoNdisIndicateStatus message - */ -typedef struct rcondis_indicate_status_ { - /* RNDIS handle */ - uint32_t ndis_vc_handle; - /* RNDIS status */ - uint32_t status; - uint32_t status_buf_length; - uint32_t status_buf_offset; -} rcondis_indicate_status; - -/* - * CONDIS Call/VC parameters - */ - -typedef struct rcondis_specific_parameters_ { - uint32_t parameter_type; - uint32_t parameter_length; - uint32_t parameter_offset; -} rcondis_specific_parameters; - -typedef struct rcondis_media_parameters_ { - uint32_t flags; - uint32_t reserved1; - uint32_t reserved2; - rcondis_specific_parameters media_specific; -} rcondis_media_parameters; - -typedef struct rndis_flowspec_ { - uint32_t token_rate; - uint32_t token_bucket_size; - uint32_t peak_bandwidth; - uint32_t latency; - uint32_t delay_variation; - uint32_t service_type; - uint32_t max_sdu_size; - uint32_t minimum_policed_size; -} rndis_flowspec; - -typedef struct rcondis_call_manager_parameters_ { - rndis_flowspec transmit; - rndis_flowspec receive; - rcondis_specific_parameters call_mgr_specific; -} rcondis_call_manager_parameters; - -/* - * CoNdisMiniportActivateVc message - */ -typedef struct rcondis_mp_activate_vc_request_ { - /* RNDIS request ID */ - uint32_t request_id; - uint32_t flags; - /* RNDIS handle */ - uint32_t device_vc_handle; - uint32_t media_params_offset; - uint32_t media_params_length; - uint32_t call_mgr_params_offset; - uint32_t call_mgr_params_length; -} rcondis_mp_activate_vc_request; - -/* - * Response to CoNdisMiniportActivateVc - */ -typedef struct rcondis_mp_activate_vc_complete_ { - /* RNDIS request ID */ - uint32_t request_id; - /* RNDIS status */ - uint32_t status; -} rcondis_mp_activate_vc_complete; - -/* - * CoNdisMiniportDeactivateVc message - */ -typedef struct rcondis_mp_deactivate_vc_request_ { - /* RNDIS request ID */ - uint32_t request_id; - uint32_t flags; - /* RNDIS handle */ - uint32_t device_vc_handle; -} rcondis_mp_deactivate_vc_request; - -/* - * Response to CoNdisMiniportDeactivateVc - */ -typedef struct rcondis_mp_deactivate_vc_complete_ { - /* RNDIS request ID */ - uint32_t request_id; - /* RNDIS status */ - uint32_t status; -} rcondis_mp_deactivate_vc_complete; - -/* - * union with all of the RNDIS messages - */ -typedef union rndis_msg_container_ { - rndis_packet packet; - rndis_initialize_request init_request; - rndis_halt_request halt_request; - rndis_query_request query_request; - rndis_set_request set_request; - rndis_reset_request reset_request; - rndis_keepalive_request keepalive_request; - rndis_indicate_status indicate_status; - rndis_initialize_complete init_complete; - rndis_query_complete query_complete; - rndis_set_complete set_complete; - rndis_reset_complete reset_complete; - rndis_keepalive_complete keepalive_complete; - rcondis_mp_create_vc co_miniport_create_vc; - rcondis_mp_delete_vc co_miniport_delete_vc; - rcondis_indicate_status co_miniport_status; - rcondis_mp_activate_vc_request co_miniport_activate_vc; - rcondis_mp_deactivate_vc_request co_miniport_deactivate_vc; - rcondis_mp_create_vc_complete co_miniport_create_vc_complete; - rcondis_mp_delete_vc_complete co_miniport_delete_vc_complete; - rcondis_mp_activate_vc_complete co_miniport_activate_vc_complete; - rcondis_mp_deactivate_vc_complete co_miniport_deactivate_vc_complete; - rndis_packet_ex packet_ex; -} rndis_msg_container; - -/* - * Remote NDIS message format - */ -typedef struct rndis_msg_ { - uint32_t ndis_msg_type; - - /* - * Total length of this message, from the beginning - * of the rndis_msg struct, in bytes. - */ - uint32_t msg_len; - - /* Actual message */ - rndis_msg_container msg; -} rndis_msg; - - -/* - * Handy macros - */ - -/* - * get the size of an RNDIS message. Pass in the message type, - * rndis_set_request, rndis_packet for example - */ -#define RNDIS_MESSAGE_SIZE(message) \ - (sizeof(message) + (sizeof(rndis_msg) - sizeof(rndis_msg_container))) - -/* - * get pointer to info buffer with message pointer - */ -#define MESSAGE_TO_INFO_BUFFER(message) \ - (((PUCHAR)(message)) + message->InformationBufferOffset) - -/* - * get pointer to status buffer with message pointer - */ -#define MESSAGE_TO_STATUS_BUFFER(message) \ - (((PUCHAR)(message)) + message->StatusBufferOffset) - -/* - * get pointer to OOBD buffer with message pointer - */ -#define MESSAGE_TO_OOBD_BUFFER(message) \ - (((PUCHAR)(message)) + message->OOBDataOffset) - -/* - * get pointer to data buffer with message pointer - */ -#define MESSAGE_TO_DATA_BUFFER(message) \ - (((PUCHAR)(message)) + message->PerPacketInfoOffset) - -/* - * get pointer to contained message from NDIS_MESSAGE pointer - */ -#define RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(rndis_message) \ - ((void *) &rndis_message->Message) - -/* - * get pointer to contained message from NDIS_MESSAGE pointer - */ -#define RNDIS_MESSAGE_RAW_PTR_TO_MESSAGE_PTR(rndis_message) \ - ((void *) rndis_message) - - - -/* - * Structures used in OID_RNDISMP_GET_RECEIVE_BUFFERS - */ - -#define RNDISMP_RECEIVE_BUFFER_ELEM_FLAG_VMQ_RECEIVE_BUFFER 0x00000001 - -typedef struct rndismp_rx_buf_elem_ { - uint32_t flags; - uint32_t length; - uint64_t rx_buf_id; - uint32_t gpadl_handle; - void *rx_buf; -} rndismp_rx_buf_elem; - -typedef struct rndismp_rx_bufs_info_ { - uint32_t num_rx_bufs; - rndismp_rx_buf_elem rx_buf_elems[1]; -} rndismp_rx_bufs_info; - - - -#define RNDIS_HEADER_SIZE (sizeof(rndis_msg) - sizeof(rndis_msg_container)) - -/* - * Externs - */ -struct hn_rx_ring; -struct hn_tx_ring; -struct hn_recvinfo; - -int netvsc_recv(struct hn_rx_ring *rxr, const void *data, int dlen, - const struct hn_recvinfo *info); -void netvsc_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr); - -#endif /* __HV_RNDIS_H__ */ - diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.c b/sys/dev/hyperv/netvsc/hv_rndis_filter.c index a4d796eb171..2cbf5bc8273 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.c +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -48,7 +49,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include @@ -419,7 +419,7 @@ hv_rf_receive_data(struct hn_rx_ring *rxr, const void *data, int dlen) pkt->rm_len, data_off, data_len); return; } - netvsc_recv(rxr, ((const uint8_t *)pkt) + data_off, data_len, &info); + hn_rxpkt(rxr, ((const uint8_t *)pkt) + data_off, data_len, &info); } /* @@ -731,7 +731,7 @@ hn_rndis_get_rsscaps(struct hn_softc *sc, int *rxr_cnt) /* * Only NDIS 6.30+ is supported. */ - KASSERT(sc->hn_ndis_ver >= NDIS_VERSION_6_30, + KASSERT(sc->hn_ndis_ver >= HN_NDIS_VERSION_6_30, ("NDIS 6.30+ is required, NDIS version 0x%08x", sc->hn_ndis_ver)); *rxr_cnt = 0; @@ -827,7 +827,7 @@ hn_rndis_conf_offload(struct hn_softc *sc) memset(¶ms, 0, sizeof(params)); params.ndis_hdr.ndis_type = NDIS_OBJTYPE_DEFAULT; - if (sc->hn_ndis_ver < NDIS_VERSION_6_30) { + if (sc->hn_ndis_ver < HN_NDIS_VERSION_6_30) { params.ndis_hdr.ndis_rev = NDIS_OFFLOAD_PARAMS_REV_2; paramsz = NDIS_OFFLOAD_PARAMS_SIZE_6_1; } else { @@ -839,7 +839,7 @@ hn_rndis_conf_offload(struct hn_softc *sc) params.ndis_ip4csum = NDIS_OFFLOAD_PARAM_TXRX; params.ndis_tcp4csum = NDIS_OFFLOAD_PARAM_TXRX; params.ndis_tcp6csum = NDIS_OFFLOAD_PARAM_TXRX; - if (sc->hn_ndis_ver >= NDIS_VERSION_6_30) { + if (sc->hn_ndis_ver >= HN_NDIS_VERSION_6_30) { params.ndis_udp4csum = NDIS_OFFLOAD_PARAM_TXRX; params.ndis_udp6csum = NDIS_OFFLOAD_PARAM_TXRX; } @@ -866,7 +866,7 @@ hn_rndis_conf_rss(struct hn_softc *sc, int nchan) /* * Only NDIS 6.30+ is supported. */ - KASSERT(sc->hn_ndis_ver >= NDIS_VERSION_6_30, + KASSERT(sc->hn_ndis_ver >= HN_NDIS_VERSION_6_30, ("NDIS 6.30+ is required, NDIS version 0x%08x", sc->hn_ndis_ver)); memset(rss, 0, sizeof(*rss)); @@ -1059,7 +1059,7 @@ hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, hv_rf_query_device_link_status(sc, &dev_info->link_state); - if (sc->hn_ndis_ver < NDIS_VERSION_6_30 || nchan == 1) { + if (sc->hn_ndis_ver < HN_NDIS_VERSION_6_30 || nchan == 1) { /* * Either RSS is not supported, or multiple RX/TX rings * are not requested. @@ -1189,5 +1189,5 @@ void hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr) { - netvsc_channel_rollup(rxr, txr); + hn_chan_rollup(rxr, txr); } diff --git a/sys/dev/hyperv/netvsc/if_hnreg.h b/sys/dev/hyperv/netvsc/if_hnreg.h index a2ddf9c998b..4d5441263a9 100644 --- a/sys/dev/hyperv/netvsc/if_hnreg.h +++ b/sys/dev/hyperv/netvsc/if_hnreg.h @@ -32,6 +32,14 @@ #include #include +/* + * NDIS protocol version numbers + */ +#define HN_NDIS_VERSION_6_1 0x00060001 +#define HN_NDIS_VERSION_6_30 0x0006001e +#define HN_NDIS_VERSION_MAJOR(ver) (((ver) & 0xffff0000) >> 16) +#define HN_NDIS_VERSION_MINOR(ver) ((ver) & 0xffff) + #define HN_NVS_RXBUF_SIG 0xcafe #define HN_NVS_CHIM_SIG 0xface diff --git a/sys/dev/hyperv/netvsc/if_hnvar.h b/sys/dev/hyperv/netvsc/if_hnvar.h index 697b6358b97..8be1aa326a8 100644 --- a/sys/dev/hyperv/netvsc/if_hnvar.h +++ b/sys/dev/hyperv/netvsc/if_hnvar.h @@ -112,6 +112,7 @@ hn_nvs_send_sglist(struct vmbus_channel *chan, struct vmbus_gpa sg[], int sglen, } struct vmbus_xact; +struct rndis_packet_msg; const void *hn_nvs_xact_execute(struct hn_softc *sc, struct vmbus_xact *xact, void *req, int reqlen, @@ -124,6 +125,10 @@ void hn_chim_free(struct hn_softc *sc, uint32_t chim_idx); void *hn_rndis_pktinfo_append(struct rndis_packet_msg *, size_t pktsize, size_t pi_dlen, uint32_t pi_type); +int hn_rxpkt(struct hn_rx_ring *rxr, const void *data, int dlen, + const struct hn_recvinfo *info); +void hn_chan_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr); + extern struct hn_send_ctx hn_send_ctx_none; #endif /* !_IF_HNVAR_H_ */ From 2b99b9f3d2f12661ad063359f3c3f210b8311a78 Mon Sep 17 00:00:00 2001 From: Stanislav Galabov Date: Wed, 7 Sep 2016 09:31:10 +0000 Subject: [PATCH 057/109] Fix MIPS INTRNG (both FDT and non-FDT) behaviour broken by r304459 More changes to MIPS may be required, as commented in D7692, but this revision aims to restore MIPS INTRNG functionality so we can move on with working interrupts. Reported by: yamori813@yahoo.co.jp Tested by: mizhka (on BCM), sgalabov (on Mediatek) Reviewed by: adrian, nwhitehorn (older version) Sponsored by: Smartcom - Bulgaria AD Differential Revision: https://reviews.freebsd.org/D7692 --- sys/mips/include/intr.h | 2 + sys/mips/mips/mips_pic.c | 89 ++++++++++++++++++++++++++++++++++------ sys/mips/mips/nexus.c | 17 +++++++- 3 files changed, 94 insertions(+), 14 deletions(-) diff --git a/sys/mips/include/intr.h b/sys/mips/include/intr.h index 6e00643f431..ee8d09336fd 100644 --- a/sys/mips/include/intr.h +++ b/sys/mips/include/intr.h @@ -63,6 +63,8 @@ void cpu_establish_hardintr(const char *, driver_filter_t *, driver_intr_t *, void *, int, int, void **); void cpu_establish_softintr(const char *, driver_filter_t *, void (*)(void*), void *, int, int, void **); +int cpu_create_intr_map(int); +struct resource *cpu_get_irq_resource(int); /* MIPS interrupt C entry point */ void cpu_intr(struct trapframe *); diff --git a/sys/mips/mips/mips_pic.c b/sys/mips/mips/mips_pic.c index c2e8db7d2af..18ecb5c15da 100644 --- a/sys/mips/mips/mips_pic.c +++ b/sys/mips/mips/mips_pic.c @@ -71,6 +71,11 @@ __FBSDID("$FreeBSD$"); static int mips_pic_intr(void *); +struct intr_map_data_mips_pic { + struct intr_map_data hdr; + u_int irq; +}; + struct mips_pic_irqsrc { struct intr_irqsrc isrc; struct resource *res; @@ -304,24 +309,37 @@ static int mips_pic_map_intr(device_t dev, struct intr_map_data *data, struct intr_irqsrc **isrcp) { -#ifdef FDT - struct intr_map_data_fdt *daf; struct mips_pic_softc *sc; - - if (data->type != INTR_MAP_DATA_FDT) - return (ENOTSUP); + int res; sc = device_get_softc(dev); - daf = (struct intr_map_data_fdt *)data; + res = 0; +#ifdef FDT + if (data->type == INTR_MAP_DATA_FDT) { + struct intr_map_data_fdt *daf; - if (daf->ncells != 1 || daf->cells[0] >= sc->nirqs) - return (EINVAL); + daf = (struct intr_map_data_fdt *)data; - *isrcp = PIC_INTR_ISRC(sc, daf->cells[0]); - return (0); -#else - return (ENOTSUP); + if (daf->ncells != 1 || daf->cells[0] >= sc->nirqs) + return (EINVAL); + + *isrcp = PIC_INTR_ISRC(sc, daf->cells[0]); + } else #endif + if (data->type == INTR_MAP_DATA_PLAT_1) { + struct intr_map_data_mips_pic *mpd; + + mpd = (struct intr_map_data_mips_pic *)data; + + if (mpd->irq < 0 || mpd->irq >= sc->nirqs) + return (EINVAL); + + *isrcp = PIC_INTR_ISRC(sc, mpd->irq); + } else { + res = ENOTSUP; + } + + return (res); } static void @@ -383,6 +401,46 @@ cpu_init_interrupts(void) { } +int +cpu_create_intr_map(int irq) +{ + struct intr_map_data_mips_pic *mips_pic_data; + intptr_t iparent; + size_t len; + u_int new_irq; + + len = sizeof(*mips_pic_data); + iparent = pic_xref(pic_sc->pic_dev); + + /* Allocate mips_pic data and fill it in */ + mips_pic_data = (struct intr_map_data_mips_pic *)intr_alloc_map_data( + INTR_MAP_DATA_PLAT_1, len, M_WAITOK | M_ZERO); + mips_pic_data->irq = irq; + + /* Get the new irq number */ + new_irq = intr_map_irq(pic_sc->pic_dev, iparent, + (struct intr_map_data *)mips_pic_data); + + /* Adjust the resource accordingly */ + rman_set_start(pic_sc->pic_irqs[irq].res, new_irq); + rman_set_end(pic_sc->pic_irqs[irq].res, new_irq); + + /* Activate the new irq */ + return (intr_activate_irq(pic_sc->pic_dev, pic_sc->pic_irqs[irq].res)); +} + +struct resource * +cpu_get_irq_resource(int irq) +{ + + KASSERT(pic_sc != NULL, ("%s: no pic", __func__)); + + if (irq < 0 || irq >= pic_sc->nirqs) + panic("%s called for unknown irq %d", __func__, irq); + + return pic_sc->pic_irqs[irq].res; +} + void cpu_establish_hardintr(const char *name, driver_filter_t *filt, void (*handler)(void*), void *arg, int irq, int flags, void **cookiep) @@ -398,6 +456,10 @@ cpu_establish_hardintr(const char *name, driver_filter_t *filt, KASSERT(pic_sc != NULL, ("%s: no pic", __func__)); irq += NSOFT_IRQS; + + res = cpu_create_intr_map(irq); + if (res != 0) panic("Unable to create map for hard IRQ %d", irq); + res = intr_setup_irq(pic_sc->pic_dev, pic_sc->pic_irqs[irq].res, filt, handler, arg, flags, cookiep); if (res != 0) panic("Unable to add hard IRQ %d handler", irq); @@ -415,6 +477,9 @@ cpu_establish_softintr(const char *name, driver_filter_t *filt, KASSERT(pic_sc != NULL, ("%s: no pic", __func__)); + res = cpu_create_intr_map(irq); + if (res != 0) panic("Unable to create map for soft IRQ %d", irq); + res = intr_setup_irq(pic_sc->pic_dev, pic_sc->pic_irqs[irq].res, filt, handler, arg, flags, cookiep); if (res != 0) panic("Unable to add soft IRQ %d handler", irq); diff --git a/sys/mips/mips/nexus.c b/sys/mips/mips/nexus.c index c1bcedd01c8..c0a25a28f1b 100644 --- a/sys/mips/mips/nexus.c +++ b/sys/mips/mips/nexus.c @@ -432,7 +432,16 @@ nexus_activate_resource(device_t bus, device_t child, int type, int rid, rman_set_bushandle(r, (bus_space_handle_t)(uintptr_t)vaddr); } else if (type == SYS_RES_IRQ) { #ifdef INTRNG +#ifdef FDT intr_activate_irq(child, r); +#else + /* + * INTRNG without FDT needs to have the interrupt properly + * mapped first. cpu_create_intr_map() will do that and + * call intr_activate_irq() at the end. + */ + cpu_create_intr_map(rman_get_start(r)); +#endif #endif } @@ -466,9 +475,13 @@ static int nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { - #ifdef INTRNG - return (intr_setup_irq(child, res, filt, intr, arg, flags, cookiep)); + struct resource *r = res; + +#ifndef FDT + r = cpu_get_irq_resource(rman_get_start(r)); +#endif + return (intr_setup_irq(child, r, filt, intr, arg, flags, cookiep)); #else int irq; register_t s; From 4c90f11b3caa1f49d91300bce10b1efbfe064864 Mon Sep 17 00:00:00 2001 From: Andriy Voskoboinyk Date: Wed, 7 Sep 2016 12:07:02 +0000 Subject: [PATCH 058/109] rum: use mgmt frame rate for EAPOL frames. --- sys/dev/usb/wlan/if_rum.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c index 924458159ab..9cdfd099ef3 100644 --- a/sys/dev/usb/wlan/if_rum.c +++ b/sys/dev/usb/wlan/if_rum.c @@ -1631,6 +1631,8 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) rate = tp->mcastrate; else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) rate = tp->ucastrate; + else if (m0->m_flags & M_EAPOL) + rate = tp->mgmtrate; else rate = ni->ni_txrate; From 9626ccde7f6b26428ba9fe2be701dd493da3e851 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Wed, 7 Sep 2016 13:45:35 +0000 Subject: [PATCH 059/109] amdsbwd: add support for FCH in family 16h models 30h-3Fh processors Requested by: Mike Tancsa Tested by: Mike Tancsa MFC after: 1 week --- sys/dev/amdsbwd/amdsbwd.c | 87 +++++++++++++++++++++++++++++++++------ 1 file changed, 75 insertions(+), 12 deletions(-) diff --git a/sys/dev/amdsbwd/amdsbwd.c b/sys/dev/amdsbwd/amdsbwd.c index 207d0b94643..bc6e256bdc7 100644 --- a/sys/dev/amdsbwd/amdsbwd.c +++ b/sys/dev/amdsbwd/amdsbwd.c @@ -108,6 +108,21 @@ __FBSDID("$FreeBSD$"); #define AMDSB8_SMBUS_REVID 0x40 #define AMDHUDSON_SMBUS_DEVID 0x780b1022 #define AMDKERNCZ_SMBUS_DEVID 0x790b1022 +/* BKDG Family 16h Models 30h - 3Fh */ +#define AMDFCH16H3XH_PM_WDT_EN 0x00 +#define AMDFCH_WDT_DEC_EN 0x80 +#define AMDFCH16H3XH_PM_WDT_CTRL 0x03 +#define AMDFCH_WDT_RES_MASK 0x03 +#define AMDFCH_WDT_RES_32US 0x00 +#define AMDFCH_WDT_RES_10MS 0x01 +#define AMDFCH_WDT_RES_100MS 0x02 +#define AMDFCH_WDT_RES_1S 0x03 +#define AMDFCH_WDT_ENABLE_MASK 0x0c +#define AMDFCH_WDT_ENABLE 0x00 +#define AMDFCH16H3XH_PM_MMIO_CTRL 0x04 +#define AMDFCH_WDT_MMIO_EN 0x02 +#define AMDFCH16H3XH_WDT_ADDR1 0xfed80b00u +#define AMDFCH16H3XH_WDT_ADDR2 0xfeb00000u #define amdsbwd_verbose_printf(dev, ...) \ do { \ @@ -295,8 +310,8 @@ amdsbwd_identify(driver_t *driver, device_t parent) static void amdsbwd_probe_sb7xx(device_t dev, struct resource *pmres, uint32_t *addr) { - uint32_t val; - int i; + uint8_t val; + int i; /* Report cause of previous reset for user's convenience. */ val = pmio_read(pmres, AMDSB_PM_RESET_STATUS0); @@ -336,8 +351,8 @@ amdsbwd_probe_sb7xx(device_t dev, struct resource *pmres, uint32_t *addr) static void amdsbwd_probe_sb8xx(device_t dev, struct resource *pmres, uint32_t *addr) { - uint32_t val; - int i; + uint8_t val; + int i; /* Report cause of previous reset for user's convenience. */ val = pmio_read(pmres, AMDSB8_PM_RESET_STATUS0); @@ -363,7 +378,7 @@ amdsbwd_probe_sb8xx(device_t dev, struct resource *pmres, uint32_t *addr) pmio_write(pmres, AMDSB8_PM_WDT_CTRL, val); #ifdef AMDSBWD_DEBUG val = pmio_read(pmres, AMDSB8_PM_WDT_CTRL); - amdsbwd_verbose_printf(dev, "AMDSB8_PM_WDT_CTRL value = %#02x\n", val); + amdsbwd_verbose_printf(dev, "AMDSB8_PM_WDT_CTRL value = %#04x\n", val); #endif /* @@ -376,11 +391,56 @@ amdsbwd_probe_sb8xx(device_t dev, struct resource *pmres, uint32_t *addr) pmio_write(pmres, AMDSB8_PM_WDT_EN, val); #ifdef AMDSBWD_DEBUG val = pmio_read(pmres, AMDSB8_PM_WDT_EN); - device_printf(dev, "AMDSB8_PM_WDT_EN value = %#02x\n", val); + device_printf(dev, "AMDSB8_PM_WDT_EN value = %#04x\n", val); #endif device_set_desc(dev, "AMD SB8xx/SB9xx/Axx Watchdog Timer"); } +static void +amdsbwd_probe_fch_16h_3xh(device_t dev, struct resource *pmres, uint32_t *addr) +{ + uint8_t val; + + val = pmio_read(pmres, AMDFCH16H3XH_PM_MMIO_CTRL); + if ((val & AMDFCH_WDT_MMIO_EN) != 0) { + /* Fixed offset for the watchdog within ACPI MMIO range. */ + amdsbwd_verbose_printf(dev, "ACPI MMIO range is enabled\n"); + *addr = AMDFCH16H3XH_WDT_ADDR1; + } else { + /* + * Enable decoding of watchdog MMIO address. + */ + val = pmio_read(pmres, AMDFCH16H3XH_PM_WDT_EN); + val |= AMDFCH_WDT_DEC_EN; + pmio_write(pmres, AMDFCH16H3XH_PM_WDT_EN, val); +#ifdef AMDSBWD_DEBUG + val = pmio_read(pmres, AMDFCH16H3XH_PM_WDT_EN); + device_printf(dev, "AMDFCH16H3XH_PM_WDT_EN value = %#04x\n", + val); +#endif + + /* Special fixed MMIO range for the watchdog. */ + *addr = AMDFCH16H3XH_WDT_ADDR2; + } + + /* + * Set watchdog timer tick to 1s and + * enable the watchdog device (in stopped state). + */ + val = pmio_read(pmres, AMDFCH16H3XH_PM_WDT_CTRL); + val &= ~AMDFCH_WDT_RES_MASK; + val |= AMDFCH_WDT_RES_1S; + val &= ~AMDFCH_WDT_ENABLE_MASK; + val |= AMDFCH_WDT_ENABLE; + pmio_write(pmres, AMDFCH16H3XH_PM_WDT_CTRL, val); +#ifdef AMDSBWD_DEBUG + val = pmio_read(pmres, AMDFCH16H3XH_PM_WDT_CTRL); + amdsbwd_verbose_printf(dev, "AMDFCH16H3XH_PM_WDT_CTRL value = %#04x\n", + val); +#endif + device_set_desc(dev, "AMD FCH Rev 42h+ Watchdog Timer"); +} + static int amdsbwd_probe(device_t dev) { @@ -389,6 +449,8 @@ amdsbwd_probe(device_t dev) uint32_t addr; int rid; int rc; + uint32_t devid; + uint8_t revid; /* Do not claim some ISA PnP device by accident. */ if (isa_get_logicalid(dev) != 0) @@ -410,11 +472,15 @@ amdsbwd_probe(device_t dev) smb_dev = pci_find_bsf(0, 20, 0); KASSERT(smb_dev != NULL, ("can't find SMBus PCI device\n")); - if (pci_get_devid(smb_dev) == AMDSB_SMBUS_DEVID && - pci_get_revid(smb_dev) < AMDSB8_SMBUS_REVID) + devid = pci_get_devid(smb_dev); + revid = pci_get_revid(smb_dev); + if (devid == AMDSB_SMBUS_DEVID && revid < AMDSB8_SMBUS_REVID) amdsbwd_probe_sb7xx(dev, res, &addr); - else + else if (devid == AMDSB_SMBUS_DEVID || devid == AMDKERNCZ_SMBUS_DEVID || + (devid == AMDHUDSON_SMBUS_DEVID && revid < 0x42)) amdsbwd_probe_sb8xx(dev, res, &addr); + else + amdsbwd_probe_fch_16h_3xh(dev, res, &addr); bus_release_resource(dev, SYS_RES_IOPORT, rid, res); bus_delete_resource(dev, SYS_RES_IOPORT, rid); @@ -439,14 +505,11 @@ amdsbwd_probe(device_t dev) static int amdsbwd_attach_sb(device_t dev, struct amdsbwd_softc *sc) { - device_t smb_dev; sc->max_ticks = UINT16_MAX; sc->rid_ctrl = 0; sc->rid_count = 1; - smb_dev = pci_find_bsf(0, 20, 0); - KASSERT(smb_dev != NULL, ("can't find SMBus PCI device\n")); sc->ms_per_tick = 1000; sc->res_ctrl = bus_alloc_resource_any(dev, SYS_RES_MEMORY, From 07c35043043fd2ac90c893c5bad94f525ba77423 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Wed, 7 Sep 2016 13:51:34 +0000 Subject: [PATCH 060/109] Fix channel initialization in FBS mode. Due to reading initialized variable, FIS receive area was always allocated as 256 bytes, suitable for command-based switching, instead of 4096 bytes, required for FIS-based switching. This caused memory corruption in case of port multipliers used on FBS-capable HBAs (Marvell). MFC after: 1 week --- sys/dev/ahci/ahci.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c index ee0e95795a9..cf1d48ac929 100644 --- a/sys/dev/ahci/ahci.c +++ b/sys/dev/ahci/ahci.c @@ -715,6 +715,21 @@ ahci_ch_attach(device_t dev) if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE))) return (ENXIO); + ch->chcaps = ATA_INL(ch->r_mem, AHCI_P_CMD); + version = ATA_INL(ctlr->r_mem, AHCI_VS); + if (version < 0x00010200 && (ctlr->caps & AHCI_CAP_FBSS)) + ch->chcaps |= AHCI_P_CMD_FBSCP; + if (ch->caps2 & AHCI_CAP2_SDS) + ch->chscaps = ATA_INL(ch->r_mem, AHCI_P_DEVSLP); + if (bootverbose) { + device_printf(dev, "Caps:%s%s%s%s%s%s\n", + (ch->chcaps & AHCI_P_CMD_HPCP) ? " HPCP":"", + (ch->chcaps & AHCI_P_CMD_MPSP) ? " MPSP":"", + (ch->chcaps & AHCI_P_CMD_CPD) ? " CPD":"", + (ch->chcaps & AHCI_P_CMD_ESP) ? " ESP":"", + (ch->chcaps & AHCI_P_CMD_FBSCP) ? " FBSCP":"", + (ch->chscaps & AHCI_P_DEVSLP_DSP) ? " DSP":""); + } ahci_dmainit(dev); ahci_slotsalloc(dev); mtx_lock(&ch->mtx); @@ -733,21 +748,6 @@ ahci_ch_attach(device_t dev) error = ENXIO; goto err1; } - ch->chcaps = ATA_INL(ch->r_mem, AHCI_P_CMD); - version = ATA_INL(ctlr->r_mem, AHCI_VS); - if (version < 0x00010200 && (ctlr->caps & AHCI_CAP_FBSS)) - ch->chcaps |= AHCI_P_CMD_FBSCP; - if (ch->caps2 & AHCI_CAP2_SDS) - ch->chscaps = ATA_INL(ch->r_mem, AHCI_P_DEVSLP); - if (bootverbose) { - device_printf(dev, "Caps:%s%s%s%s%s%s\n", - (ch->chcaps & AHCI_P_CMD_HPCP) ? " HPCP":"", - (ch->chcaps & AHCI_P_CMD_MPSP) ? " MPSP":"", - (ch->chcaps & AHCI_P_CMD_CPD) ? " CPD":"", - (ch->chcaps & AHCI_P_CMD_ESP) ? " ESP":"", - (ch->chcaps & AHCI_P_CMD_FBSCP) ? " FBSCP":"", - (ch->chscaps & AHCI_P_DEVSLP_DSP) ? " DSP":""); - } /* Create the device queue for our SIM. */ devq = cam_simq_alloc(ch->numslots); if (devq == NULL) { From f13826052b7fd102c8fdebeb7887a86826b2c5f6 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Wed, 7 Sep 2016 14:24:29 +0000 Subject: [PATCH 061/109] work around AMD erratum 793 for family 16h, models 00h-0Fh --- sys/amd64/amd64/initcpu.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sys/amd64/amd64/initcpu.c b/sys/amd64/amd64/initcpu.c index 305d0bfbf0a..63c0f20f492 100644 --- a/sys/amd64/amd64/initcpu.c +++ b/sys/amd64/amd64/initcpu.c @@ -108,6 +108,20 @@ init_amd(void) wrmsr(0xc001102a, msr); } } + + /* + * Work around Erratum 793: Specific Combination of Writes to Write + * Combined Memory Types and Locked Instructions May Cause Core Hang. + * See Revision Guide for AMD Family 16h Models 00h-0Fh Processors, + * revision 3.04 or later, publication 51810. + */ + if (CPUID_TO_FAMILY(cpu_id) == 0x16 && CPUID_TO_MODEL(cpu_id) <= 0xf) { + if ((cpu_feature2 & CPUID2_HV) == 0) { + msr = rdmsr(0xc0011020); + msr |= (uint64_t)1 << 15; + wrmsr(0xc0011020, msr); + } + } } /* From 9a6eb971a1eb36af2e64032091619040bc370297 Mon Sep 17 00:00:00 2001 From: Ruslan Bukin Date: Wed, 7 Sep 2016 15:48:44 +0000 Subject: [PATCH 062/109] o Update QEMU device tree. QEMU was updated to privileged architecture v1.9 and we now fully support it. Sponsored by: DARPA, AFRL Sponsored by: HEIF5 --- sys/boot/fdt/dts/riscv/qemu.dts | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/sys/boot/fdt/dts/riscv/qemu.dts b/sys/boot/fdt/dts/riscv/qemu.dts index 8da1ae5b663..df6fe0086ae 100644 --- a/sys/boot/fdt/dts/riscv/qemu.dts +++ b/sys/boot/fdt/dts/riscv/qemu.dts @@ -37,24 +37,39 @@ /dts-v1/; / { - model = "QEMU RV64I"; - compatible = "riscv,rv64i"; + model = "QEMU RV64"; + compatible = "riscv,rv64"; #address-cells = <1>; #size-cells = <1>; #interrupt-cells = <1>; + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "riscv,rv64"; + reg = <0x0>; + }; + }; + aliases { console0 = &console0; }; memory { + /* + * This is not used currently. + * We take information from sbi_query_memory. + */ device_type = "memory"; - reg = <0x0 0x40000000>; /* 1GB at 0x0 */ + reg = <0x80000000 0x40000000>; /* 1GB at 0x80000000 */ }; soc { - #address-cells = <2>; - #size-cells = <2>; + #address-cells = <1>; + #size-cells = <1>; #interrupt-cells = <1>; compatible = "simple-bus"; @@ -67,7 +82,9 @@ timer0: timer@0 { compatible = "riscv,timer"; - interrupts = < 1 >; + reg = < 0x40000000 0x0008 >, /* rtc */ + < 0x40000008 0x1000 >; /* timecmp */ + interrupts = < 5 >; interrupt-parent = < &pic0 >; clock-frequency = < 400000000 >; }; From d204cea9f8a9eb39eb49cda3924aca7de1d16ca3 Mon Sep 17 00:00:00 2001 From: Andriy Voskoboinyk Date: Wed, 7 Sep 2016 16:19:20 +0000 Subject: [PATCH 063/109] rum: fix possible panic on device detach (similar to r302034). Tested with WUSB54GC, STA/AP modes. --- sys/dev/usb/wlan/if_rum.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c index 9cdfd099ef3..932f2a57de9 100644 --- a/sys/dev/usb/wlan/if_rum.c +++ b/sys/dev/usb/wlan/if_rum.c @@ -165,6 +165,8 @@ static int rum_cmd_sleepable(struct rum_softc *, const void *, size_t, uint8_t, CMD_FUNC_PROTO); static void rum_tx_free(struct rum_tx_data *, int); static void rum_setup_tx_list(struct rum_softc *); +static void rum_reset_tx_list(struct rum_softc *, + struct ieee80211vap *); static void rum_unsetup_tx_list(struct rum_softc *); static void rum_beacon_miss(struct ieee80211vap *); static void rum_sta_recv_mgmt(struct ieee80211_node *, @@ -723,12 +725,22 @@ rum_vap_delete(struct ieee80211vap *vap) { struct rum_vap *rvp = RUM_VAP(vap); struct ieee80211com *ic = vap->iv_ic; + struct rum_softc *sc = ic->ic_softc; + + /* Put vap into INIT state. */ + ieee80211_new_state(vap, IEEE80211_S_INIT, -1); + ieee80211_draintask(ic, &vap->iv_nstate_task); + + RUM_LOCK(sc); + /* Cancel any unfinished Tx. */ + rum_reset_tx_list(sc, vap); + RUM_UNLOCK(sc); - m_freem(rvp->bcn_mbuf); usb_callout_drain(&rvp->ratectl_ch); ieee80211_draintask(ic, &rvp->ratectl_task); ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); + m_freem(rvp->bcn_mbuf); free(rvp, M_80211_VAP); } @@ -815,6 +827,30 @@ rum_setup_tx_list(struct rum_softc *sc) } } +static void +rum_reset_tx_list(struct rum_softc *sc, struct ieee80211vap *vap) +{ + struct rum_tx_data *data, *tmp; + + KASSERT(vap != NULL, ("%s: vap is NULL\n", __func__)); + + STAILQ_FOREACH_SAFE(data, &sc->tx_q, next, tmp) { + if (data->ni != NULL && data->ni->ni_vap == vap) { + ieee80211_free_node(data->ni); + data->ni = NULL; + + KASSERT(data->m != NULL, ("%s: m is NULL\n", + __func__)); + m_freem(data->m); + data->m = NULL; + + STAILQ_REMOVE(&sc->tx_q, data, rum_tx_data, next); + STAILQ_INSERT_TAIL(&sc->tx_free, data, next); + sc->tx_nfree++; + } + } +} + static void rum_unsetup_tx_list(struct rum_softc *sc) { From 3b343644508bf4b0c2233d7bb3a49374d9437418 Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Wed, 7 Sep 2016 16:22:05 +0000 Subject: [PATCH 064/109] Only call cpu_icache_sync_range when inserting an executable page. If the page is non-executable the contents of the i-cache are unimportant so this call is just adding unneeded overhead when inserting pages. While doing research using gem5 with an O3 pipeline and 1k/32k/1M iTLB/L1 iCache/L2 Bjoern Zeeb (bz@) observed a fairly high rate of calls into arm64_icache_sync_range() from pmap_enter() along with a high number of instruction fetches and iTLB/iCache hits. Limiting the calls to arm64_icache_sync_range() to only executable pages, we observe the iTLB and iCache Hit going down by about 43%. These numbers are quite misleading when looked at alone as at the same time instructions retired were reduced by 19.2% and instruction fetches were reduced by 38.8%. Overall this reduced the runtime of the test program by 22.4%. On Juno hardware, in steady-state, running the same test, using the cycle count to determine runtime, we do see a reduction of up to 28.9% in runtime. While these numbers certainly depend on the program executed, we expect an overall performance improvement. Reported by: bz Obtained from: ABT Systems Ltd MFC after: 1 week Sponsored by: The FreeBSD Foundation --- sys/arm64/arm64/pmap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c index 09189115aec..7e76056b9ee 100644 --- a/sys/arm64/arm64/pmap.c +++ b/sys/arm64/arm64/pmap.c @@ -2939,8 +2939,9 @@ validate: pmap_invalidate_page(pmap, va); if (pmap != pmap_kernel()) { - if (pmap == &curproc->p_vmspace->vm_pmap) - cpu_icache_sync_range(va, PAGE_SIZE); + if (pmap == &curproc->p_vmspace->vm_pmap && + (prot & VM_PROT_EXECUTE) != 0) + cpu_icache_sync_range(va, PAGE_SIZE); if ((mpte == NULL || mpte->wire_count == NL3PG) && pmap_superpages_enabled() && From 77c02eccb859c8fa8b98e1fe635d779e979b784f Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Wed, 7 Sep 2016 16:46:54 +0000 Subject: [PATCH 065/109] When synchronising the instruction and data caches we only need to clean the data cache to the point of unification. This is the point where the two caches are unified to a single unified cache so cleaning past here is just extra unneeded work. This was noticed when investigating r305545. Reported by: bz Obtained from: ABT Systems Ltd MFC after: 1 week Sponsored by: The FreeBSD Foundation --- sys/arm64/arm64/cpufunc_asm.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/arm64/arm64/cpufunc_asm.S b/sys/arm64/arm64/cpufunc_asm.S index 49cd6f16837..06fc5125a58 100644 --- a/sys/arm64/arm64/cpufunc_asm.S +++ b/sys/arm64/arm64/cpufunc_asm.S @@ -151,5 +151,5 @@ END(arm64_idcache_wbinv_range) * void arm64_icache_sync_range(vm_offset_t, vm_size_t) */ ENTRY(arm64_icache_sync_range) - cache_handle_range dcop = cvac, ic = 1, icop = ivau + cache_handle_range dcop = cvau, ic = 1, icop = ivau END(arm64_icache_sync_range) From e06ab612d25d068327949db8f1e24c4f824d9ef6 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Wed, 7 Sep 2016 18:08:43 +0000 Subject: [PATCH 066/109] Don't break out of the m_advance() loop if len drops to zero. If a packet contains the Ethernet header (14 bytes) in the first mbuf and the payload (IP + UDP + data) in the second mbuf, then the attempt to fetch the l3hdr will return a NULL pointer. The first loop iteration will drop len to zero and exit the loop without setting 'p'. However, the desired data is at the start of the second mbuf, so the correct behavior is to loop around and let the conditional set 'p' to m_data of the next mbuf (and leave offset as 0). Reviewed by: np Sponsored by: Chelsio Communications --- sys/dev/cxgbe/t4_sge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c index 923f1c16de9..8bee75d9838 100644 --- a/sys/dev/cxgbe/t4_sge.c +++ b/sys/dev/cxgbe/t4_sge.c @@ -2082,7 +2082,7 @@ m_advance(struct mbuf **pm, int *poffset, int len) MPASS(len > 0); - while (len) { + for (;;) { if (offset + len < m->m_len) { offset += len; p = mtod(m, uintptr_t) + offset; From 6af45170c16bdebc1825165e3d6eb5b222e010d8 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Wed, 7 Sep 2016 18:13:57 +0000 Subject: [PATCH 067/109] Chelsio T4/T5 VF driver. The cxgbev/cxlv driver supports Virtual Function devices for Chelsio T4 and T4 adapters. The VF devices share most of their code with the existing PF4 driver (cxgbe/cxl) and as such the VF device driver currently depends on the PF4 driver. Similar to the cxgbe/cxl drivers, the VF driver includes a t4vf/t5vf PCI device driver that attaches to the VF device. It then creates child cxgbev/cxlv devices representing ports assigned to the VF. By default, the PF driver assigns a single port to each VF. t4vf_hw.c contains VF-specific routines from the shared code used to fetch VF-specific parameters from the firmware. t4_vf.c contains the VF-specific PCI device driver and includes its own attach routine. VF devices are required to use a different firmware request when transmitting packets (which in turn requires a different CPL message to encapsulate messages). This alternate firmware request does not permit chaining multiple packets in a single message, so each packet results in a firmware request. In addition, the different CPL message requires more detailed information when enabling hardware checksums, so parse_pkt() on VF devices must examine L2 and L3 headers for all packets (not just TSO packets) for VF devices. Finally, L2 checksums on non-UDP/non-TCP packets do not work reliably (the firmware trashes the IPv4 fragment field), so IPv4 checksums for such packets are calculated in software. Most of the other changes in the non-VF-specific code are to expose various variables and functions private to the PF driver so that they can be used by the VF driver. Note that a limited subset of cxgbetool functions are supported on VF devices including register dumps, scheduler classes, and clearing of statistics. In addition, TOE is not supported on VF devices, only for the PF interfaces. Reviewed by: np MFC after: 2 months Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D7599 --- share/man/man4/Makefile | 4 + share/man/man4/cxgbe.4 | 4 +- share/man/man4/cxgbev.4 | 290 ++++++++ sys/arm/conf/NOTES | 1 + sys/conf/NOTES | 2 + sys/conf/files | 4 + sys/dev/cxgbe/adapter.h | 26 +- sys/dev/cxgbe/common/common.h | 29 + sys/dev/cxgbe/common/t4_hw.c | 4 +- sys/dev/cxgbe/common/t4vf_hw.c | 376 +++++++++++ sys/dev/cxgbe/if_cxlv.c | 44 ++ sys/dev/cxgbe/t4_main.c | 184 +++--- sys/dev/cxgbe/t4_sge.c | 257 +++++++- sys/dev/cxgbe/t4_vf.c | 950 +++++++++++++++++++++++++++ sys/modules/cxgbe/Makefile | 2 + sys/modules/cxgbe/if_cxgbev/Makefile | 21 + sys/modules/cxgbe/if_cxlv/Makefile | 11 + sys/powerpc/conf/NOTES | 1 + 18 files changed, 2113 insertions(+), 97 deletions(-) create mode 100644 share/man/man4/cxgbev.4 create mode 100644 sys/dev/cxgbe/common/t4vf_hw.c create mode 100644 sys/dev/cxgbe/if_cxlv.c create mode 100644 sys/dev/cxgbe/t4_vf.c create mode 100644 sys/modules/cxgbe/if_cxgbev/Makefile create mode 100644 sys/modules/cxgbe/if_cxlv/Makefile diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 0f64f72c431..b31e016c7c8 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -113,6 +113,7 @@ MAN= aac.4 \ cue.4 \ cxgb.4 \ cxgbe.4 \ + cxgbev.4 \ cy.4 \ cyapa.4 \ da.4 \ @@ -602,6 +603,9 @@ MLINKS+=cxgb.4 if_cxgb.4 MLINKS+=cxgbe.4 if_cxgbe.4 \ cxgbe.4 cxl.4 \ cxgbe.4 if_cxl.4 +MLINKS+=cxgbev.4 if_cxgbev.4 \ + cxgbev.4 cxlv.4 \ + cxgbev.4 if_cxlv.4 MLINKS+=dc.4 if_dc.4 MLINKS+=de.4 if_de.4 MLINKS+=disc.4 if_disc.4 diff --git a/share/man/man4/cxgbe.4 b/share/man/man4/cxgbe.4 index 72a9483aca1..afa7e38b812 100644 --- a/share/man/man4/cxgbe.4 +++ b/share/man/man4/cxgbe.4 @@ -77,8 +77,7 @@ For more information on configuring this device, see .Sh HARDWARE The .Nm -driver supports 40Gb, 10Gb and 1Gb Ethernet adapters based on the T5 ASIC -(ports will be named cxl): +driver supports 40Gb, 10Gb and 1Gb Ethernet adapters based on the T5 ASIC: .Pp .Bl -bullet -compact .It @@ -320,6 +319,7 @@ email all the specific information related to the issue to .Xr altq 4 , .Xr arp 4 , .Xr cxgb 4 , +.Xr cxgbev 4 , .Xr netintro 4 , .Xr ng_ether 4 , .Xr ifconfig 8 diff --git a/share/man/man4/cxgbev.4 b/share/man/man4/cxgbev.4 new file mode 100644 index 00000000000..f4e3dc5b430 --- /dev/null +++ b/share/man/man4/cxgbev.4 @@ -0,0 +1,290 @@ +.\" Copyright (c) 2011-2016, Chelsio Inc +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright notice, +.\" this list of conditions and the following disclaimer. +.\" +.\" 2. 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. +.\" +.\" 3. Neither the name of the Chelsio Inc nor the names of its +.\" contributors may be used to endorse or promote products derived from +.\" this software without specific prior written permission. +.\" +.\" 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. +.\" +.\" * Other names and brands may be claimed as the property of others. +.\" +.\" $FreeBSD$ +.\" +.Dd August 22, 2016 +.Dt CXGBEV 4 +.Os +.Sh NAME +.Nm cxgbev +.Nd "Chelsio T4 and T5 based 40Gb, 10Gb, and 1Gb Ethernet VF driver" +.Sh SYNOPSIS +To compile this driver into the kernel, +place the following lines in your +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device cxgbe" +.Cd "device cxgbev" +.Ed +.Pp +To load the driver as a +module at boot time, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +if_cxgbev_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +driver provides support for Virtual Functions on PCI Express Ethernet adapters +based on the Chelsio Terminator 4 and Terminator 5 ASICs (T4 and T5). +The driver supports Jumbo Frames, Transmit/Receive checksum offload, +TCP segmentation offload (TSO), Large Receive Offload (LRO), VLAN +tag insertion/extraction, VLAN checksum offload, VLAN TSO, and +Receive Side Steering (RSS). +For further hardware information and questions related to hardware +requirements, see +.Pa http://www.chelsio.com/ . +.Pp +Note that ports of T5 VFs are named cxlv and attach to a t5vf parent device +(in contrast to ports named cxgbev that attach to a t4vf parent for a T4 VF). +Loader tunables with the hw.cxgbe prefix apply to both T4 and T5 VFs. +The Physical Function driver for T4 and T5 adapters shares these tunables. +The sysctl MIBs are at dev.t5vf and dev.cxlv for T5 cards and at dev.t4vf and +dev.cxgbev for T4 cards. +.Pp +For more information on configuring this device, see +.Xr ifconfig 8 . +.Sh HARDWARE +The +.Nm +driver supports Virtual Functions on 40Gb, 10Gb and 1Gb Ethernet adapters +based on the T5 ASIC: +.Pp +.Bl -bullet -compact +.It +Chelsio T580-CR +.It +Chelsio T580-LP-CR +.It +Chelsio T580-LP-SO-CR +.It +Chelsio T560-CR +.It +Chelsio T540-CR +.It +Chelsio T540-LP-CR +.It +Chelsio T522-CR +.It +Chelsio T520-LL-CR +.It +Chelsio T520-CR +.It +Chelsio T520-SO +.It +Chelsio T520-BT +.It +Chelsio T504-BT +.El +.Pp +The +.Nm +driver supports Virtual Functions on 10Gb and 1Gb Ethernet adapters based +on the T4 ASIC: +.Pp +.Bl -bullet -compact +.It +Chelsio T420-CR +.It +Chelsio T422-CR +.It +Chelsio T440-CR +.It +Chelsio T420-BCH +.It +Chelsio T440-BCH +.It +Chelsio T440-CH +.It +Chelsio T420-SO +.It +Chelsio T420-CX +.It +Chelsio T420-BT +.It +Chelsio T404-BT +.El +.Sh LOADER TUNABLES +Tunables can be set at the +.Xr loader 8 +prompt before booting the kernel or stored in +.Xr loader.conf 5 . +.Bl -tag -width indent +.It Va hw.cxgbe.ntxq10g +The number of tx queues to use for a 10Gb or 40Gb port. +The default is 16 or the number +of CPU cores in the system, whichever is less. +.It Va hw.cxgbe.nrxq10g +The number of rx queues to use for a 10Gb or 40Gb port. +The default is 8 or the number +of CPU cores in the system, whichever is less. +.It Va hw.cxgbe.ntxq1g +The number of tx queues to use for a 1Gb port. +The default is 4 or the number +of CPU cores in the system, whichever is less. +.It Va hw.cxgbe.nrxq1g +The number of rx queues to use for a 1Gb port. +The default is 2 or the number +of CPU cores in the system, whichever is less. +.It Va hw.cxgbe.holdoff_timer_idx_10G +.It Va hw.cxgbe.holdoff_timer_idx_1G +The timer index value to use to delay interrupts. +The holdoff timer list has the values 1, 5, 10, 50, 100, and 200 +by default (all values are in microseconds) and the index selects a +value from this list. +The default value is 1 which means the timer value is 5us. +Different interfaces can be assigned different values at any time via the +dev.cxgbev.X.holdoff_tmr_idx or dev.cxlv.X.holdoff_tmr_idx sysctl. +.It Va hw.cxgbe.holdoff_pktc_idx_10G +.It Va hw.cxgbe.holdoff_pktc_idx_1G +The packet-count index value to use to delay interrupts. +The packet-count list has the values 1, 8, 16, and 32 by default +and the index selects a value from this list. +The default value is -1 which means packet counting is disabled and interrupts +are generated based solely on the holdoff timer value. +Different interfaces can be assigned different values via the +dev.cxgbev.X.holdoff_pktc_idx or dev.cxlv.X.holdoff_pktc_idx sysctl. +This sysctl works only when the interface has never been marked up (as done by +ifconfig up). +.It Va hw.cxgbe.qsize_txq +The size, in number of entries, of the descriptor ring used for a tx +queue. +A buf_ring of the same size is also allocated for additional +software queuing. +See +.Xr ifnet 9 . +The default value is 1024. +Different interfaces can be assigned different values via the +dev.cxgbev.X.qsize_txq sysctl or dev.cxlv.X.qsize_txq sysctl. +This sysctl works only when the interface has never been marked up (as done by +ifconfig up). +.It Va hw.cxgbe.qsize_rxq +The size, in number of entries, of the descriptor ring used for an +rx queue. +The default value is 1024. +Different interfaces can be assigned different values via the +dev.cxgbev.X.qsize_rxq or dev.cxlv.X.qsize_rxq sysctl. +This sysctl works only when the interface has never been marked up (as done by +ifconfig up). +.It Va hw.cxgbe.interrupt_types +The interrupt types that the driver is allowed to use. +Bit 0 represents INTx (line interrupts), bit 1 MSI, bit 2 MSI-X. +The default is 7 (all allowed). +The driver will select the best possible type out of the allowed types by +itself. +.It Va hw.cxgbe.fl_pktshift +The number of bytes of padding inserted before the beginning of an Ethernet +frame in the receive buffer. +The default value of 2 ensures that the Ethernet payload (usually the IP header) +is at a 4 byte aligned address. +0-7 are all valid values. +.It Va hw.cxgbe.fl_pad +A non-zero value ensures that writes from the hardware to a receive buffer are +padded up to the specified boundary. +The default is -1 which lets the driver pick a pad boundary. +0 disables trailer padding completely. +.It Va hw.cxgbe.buffer_packing +Allow the hardware to deliver multiple frames in the same receive buffer +opportunistically. +The default is -1 which lets the driver decide. +0 or 1 explicitly disable or enable this feature. +.It Va hw.cxgbe.allow_mbufs_in_cluster +1 allows the driver to lay down one or more mbufs within the receive buffer +opportunistically. +This is the default. +0 prohibits the driver from doing so. +.It Va hw.cxgbe.largest_rx_cluster +.It Va hw.cxgbe.safest_rx_cluster +Sizes of rx clusters. +Each of these must be set to one of the sizes available +(usually 2048, 4096, 9216, and 16384) and largest_rx_cluster must be greater +than or equal to safest_rx_cluster. +The defaults are 16384 and 4096 respectively. +The driver will never attempt to allocate a receive buffer larger than +largest_rx_cluster and will fall back to allocating buffers of +safest_rx_cluster size if an allocation larger than safest_rx_cluster fails. +Note that largest_rx_cluster merely establishes a ceiling -- the driver is +allowed to allocate buffers of smaller sizes. +.El +.Pp +Certain settings and resources for Virtual Functions are dictated +by the parent Physical Function driver. +For example, the Physical Function driver limits the number of queues a +Virtual Function is permitted to use. +Some of these limits can be adjusted in the firmware configuration file +used with the Physical Function driver. +.Pp +The PAUSE settings on the port of a Virtual Function are inherited from +the settings of the same port on the Physical Function. +Virtual Functions cannot modify the setting and track changes made to +the associated port's setting by the Physical Function driver. +.Pp +Receive queues on a Virtual Function always drop packets in response to +congestion +.Po +equivalent to setting +.Va hw.cxgbe.cong_drop +to 1 +.Pc . +.Pp +The VF driver currently depends on the PF driver. +As a result, loading the VF driver will also load the PF driver as a +dependency. +.Sh SUPPORT +For general information and support, +go to the Chelsio support website at: +.Pa http://www.chelsio.com/ . +.Pp +If an issue is identified with this driver with a supported adapter, +email all the specific information related to the issue to +.Aq Mt support@chelsio.com . +.Sh SEE ALSO +.Xr altq 4 , +.Xr arp 4 , +.Xr cxgbe 4 , +.Xr netintro 4 , +.Xr ng_ether 4 , +.Xr ifconfig 8 +.Sh HISTORY +The +.Nm +device driver first appeared in +.Fx 12.0 . +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Navdeep Parhar Aq Mt np@FreeBSD.org +and +.An John Baldwin Aq Mt jhb@FreeBSD.org . diff --git a/sys/arm/conf/NOTES b/sys/arm/conf/NOTES index ebb5d041017..b7859271493 100644 --- a/sys/arm/conf/NOTES +++ b/sys/arm/conf/NOTES @@ -80,6 +80,7 @@ nodevice star_saver nodevice warp_saver nodevice cxgbe +nodevice cxgbev nodevice snd_cmi # diff --git a/sys/conf/NOTES b/sys/conf/NOTES index ddaed9c1cf0..ee9f178236f 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -1949,6 +1949,7 @@ device xmphy # XaQti XMAC II # (and SMC COM90c66 in '56 compatibility mode) adapters. # cxgb: Chelsio T3 based 1GbE/10GbE PCIe Ethernet adapters. # cxgbe:Chelsio T4 and T5 based 1GbE/10GbE/40GbE PCIe Ethernet adapters. +# cxgbev: Chelsio T4 and T5 based PCIe Virtual Functions. # dc: Support for PCI fast ethernet adapters based on the DEC/Intel 21143 # and various workalikes including: # the ADMtek AL981 Comet and AN985 Centaur, the ASIX Electronics @@ -2132,6 +2133,7 @@ device xl # 3Com 3c90x (``Boomerang'', ``Cyclone'') device cxgb # Chelsio T3 10 Gigabit Ethernet device cxgb_t3fw # Chelsio T3 10 Gigabit Ethernet firmware device cxgbe # Chelsio T4 and T5 1GbE/10GbE/40GbE +device cxgbev # Chelsio T4 and T5 1GbE/10GbE/40GbE VF device de # DEC/Intel DC21x4x (``Tulip'') device em # Intel Pro/1000 Gigabit Ethernet device igb # Intel Pro/1000 PCIE Gigabit Ethernet diff --git a/sys/conf/files b/sys/conf/files index 886b77e2c7b..ce1d00ea17d 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1281,8 +1281,12 @@ dev/cxgbe/t4_l2t.c optional cxgbe pci \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" dev/cxgbe/t4_tracer.c optional cxgbe pci \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" +dev/cxgbe/t4_vf.c optional cxgbev pci \ + compile-with "${NORMAL_C} -I$S/dev/cxgbe" dev/cxgbe/common/t4_hw.c optional cxgbe pci \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" +dev/cxgbe/common/t4vf_hw.c optional cxgbev pci \ + compile-with "${NORMAL_C} -I$S/dev/cxgbe" t4fw_cfg.c optional cxgbe \ compile-with "${AWK} -f $S/tools/fw_stub.awk t4fw_cfg.fw:t4fw_cfg t4fw_cfg_uwire.fw:t4fw_cfg_uwire t4fw.fw:t4fw -mt4fw_cfg -c${.TARGET}" \ no-implicit-rule before-depend local \ diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h index 174ce12c904..0660090b328 100644 --- a/sys/dev/cxgbe/adapter.h +++ b/sys/dev/cxgbe/adapter.h @@ -945,6 +945,9 @@ struct adapter { /* One for errors, one for firmware events */ #define T4_EXTRA_INTR 2 +/* One for firmware events */ +#define T4VF_EXTRA_INTR 1 + static inline uint32_t t4_read_reg(struct adapter *sc, uint32_t reg) { @@ -1079,13 +1082,34 @@ t4_use_ldst(struct adapter *sc) } /* t4_main.c */ +extern int t4_ntxq10g; +extern int t4_nrxq10g; +extern int t4_ntxq1g; +extern int t4_nrxq1g; +extern int t4_intr_types; +extern int t4_tmr_idx_10g; +extern int t4_pktc_idx_10g; +extern int t4_tmr_idx_1g; +extern int t4_pktc_idx_1g; +extern unsigned int t4_qsize_rxq; +extern unsigned int t4_qsize_txq; +extern device_method_t cxgbe_methods[]; + int t4_os_find_pci_capability(struct adapter *, int); int t4_os_pci_save_state(struct adapter *); int t4_os_pci_restore_state(struct adapter *); void t4_os_portmod_changed(const struct adapter *, int); void t4_os_link_changed(struct adapter *, int, int, int); void t4_iterate(void (*)(struct adapter *, void *), void *); +void t4_add_adapter(struct adapter *); +int t4_detach_common(device_t); int t4_filter_rpl(struct sge_iq *, const struct rss_header *, struct mbuf *); +int t4_map_bars_0_and_4(struct adapter *); +int t4_map_bar_2(struct adapter *); +int t4_set_sched_class(struct adapter *, struct t4_sched_params *); +int t4_set_sched_queue(struct adapter *, struct t4_sched_queue *); +int t4_setup_intr_handlers(struct adapter *); +void t4_sysctls(struct adapter *); int begin_synchronized_op(struct adapter *, struct vi_info *, int, char *); void doom_vi(struct adapter *, struct vi_info *); void end_synchronized_op(struct adapter *, int); @@ -1126,7 +1150,7 @@ void t4_intr_err(void *); void t4_intr_evt(void *); void t4_wrq_tx_locked(struct adapter *, struct sge_wrq *, struct wrqe *); void t4_update_fl_bufsize(struct ifnet *); -int parse_pkt(struct mbuf **); +int parse_pkt(struct adapter *, struct mbuf **); void *start_wrq_wr(struct sge_wrq *, int, struct wrq_cookie *); void commit_wrq_wr(struct sge_wrq *, void *, struct wrq_cookie *); int tnl_cong(struct port_info *, int); diff --git a/sys/dev/cxgbe/common/common.h b/sys/dev/cxgbe/common/common.h index 75f63e5d240..954501e1e27 100644 --- a/sys/dev/cxgbe/common/common.h +++ b/sys/dev/cxgbe/common/common.h @@ -558,6 +558,7 @@ int t4_get_scfg_version(struct adapter *adapter, u32 *vers); int t4_get_vpd_version(struct adapter *adapter, u32 *vers); int t4_get_version_info(struct adapter *adapter); int t4_init_hw(struct adapter *adapter, u32 fw_params); +const struct chip_params *t4_get_chip_params(int chipid); int t4_prep_adapter(struct adapter *adapter, u8 *buf); int t4_shutdown_adapter(struct adapter *adapter); int t4_init_devlog_params(struct adapter *adapter, int fw_attach); @@ -765,4 +766,32 @@ int t4_config_watchdog(struct adapter *adapter, unsigned int mbox, int t4_get_devlog_level(struct adapter *adapter, unsigned int *level); int t4_set_devlog_level(struct adapter *adapter, unsigned int level); void t4_sge_decode_idma_state(struct adapter *adapter, int state); + +static inline int t4vf_query_params(struct adapter *adapter, + unsigned int nparams, const u32 *params, + u32 *vals) +{ + return t4_query_params(adapter, 0, 0, 0, nparams, params, vals); +} + +static inline int t4vf_set_params(struct adapter *adapter, + unsigned int nparams, const u32 *params, + const u32 *vals) +{ + return t4_set_params(adapter, 0, 0, 0, nparams, params, vals); +} + +static inline int t4vf_wr_mbox(struct adapter *adap, const void *cmd, + int size, void *rpl) +{ + return t4_wr_mbox(adap, adap->mbox, cmd, size, rpl); +} + +int t4vf_wait_dev_ready(struct adapter *adapter); +int t4vf_fw_reset(struct adapter *adapter); +int t4vf_get_sge_params(struct adapter *adapter); +int t4vf_get_rss_glb_config(struct adapter *adapter); +int t4vf_get_vfres(struct adapter *adapter); +int t4vf_prep_adapter(struct adapter *adapter); + #endif /* __CHELSIO_COMMON_H */ diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c index 674dc4a92c0..77381b9014e 100644 --- a/sys/dev/cxgbe/common/t4_hw.c +++ b/sys/dev/cxgbe/common/t4_hw.c @@ -7616,7 +7616,7 @@ static void set_pcie_completion_timeout(struct adapter *adapter, } } -static const struct chip_params *get_chip_params(int chipid) +const struct chip_params *t4_get_chip_params(int chipid) { static const struct chip_params chip_params[] = { { @@ -7695,7 +7695,7 @@ int t4_prep_adapter(struct adapter *adapter, u8 *buf) } } - adapter->chip_params = get_chip_params(chip_id(adapter)); + adapter->chip_params = t4_get_chip_params(chip_id(adapter)); if (adapter->chip_params == NULL) return -EINVAL; diff --git a/sys/dev/cxgbe/common/t4vf_hw.c b/sys/dev/cxgbe/common/t4vf_hw.c new file mode 100644 index 00000000000..adbeb0e4caf --- /dev/null +++ b/sys/dev/cxgbe/common/t4vf_hw.c @@ -0,0 +1,376 @@ +/*- + * Copyright (c) 2016 Chelsio Communications, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 AUTHOR 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 AUTHOR 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 +__FBSDID("$FreeBSD$"); + +#include "common.h" +#include "t4_regs.h" + +#undef msleep +#define msleep(x) do { \ + if (cold) \ + DELAY((x) * 1000); \ + else \ + pause("t4hw", (x) * hz / 1000); \ +} while (0) + +/* + * Wait for the device to become ready (signified by our "who am I" register + * returning a value other than all 1's). Return an error if it doesn't + * become ready ... + */ +int t4vf_wait_dev_ready(struct adapter *adapter) +{ + const u32 whoami = VF_PL_REG(A_PL_VF_WHOAMI); + const u32 notready1 = 0xffffffff; + const u32 notready2 = 0xeeeeeeee; + u32 val; + + val = t4_read_reg(adapter, whoami); + if (val != notready1 && val != notready2) + return 0; + msleep(500); + val = t4_read_reg(adapter, whoami); + if (val != notready1 && val != notready2) + return 0; + else + return -EIO; +} + + +/** + * t4vf_fw_reset - issue a reset to FW + * @adapter: the adapter + * + * Issues a reset command to FW. For a Physical Function this would + * result in the Firmware reseting all of its state. For a Virtual + * Function this just resets the state associated with the VF. + */ +int t4vf_fw_reset(struct adapter *adapter) +{ + struct fw_reset_cmd cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_RESET_CMD) | + F_FW_CMD_WRITE); + cmd.retval_len16 = cpu_to_be32(V_FW_CMD_LEN16(FW_LEN16(cmd))); + return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL); +} + +/** + * t4vf_get_sge_params - retrieve adapter Scatter gather Engine parameters + * @adapter: the adapter + * + * Retrieves various core SGE parameters in the form of hardware SGE + * register values. The caller is responsible for decoding these as + * needed. The SGE parameters are stored in @adapter->params.sge. + */ +int t4vf_get_sge_params(struct adapter *adapter) +{ + struct sge_params *sp = &adapter->params.sge; + u32 params[7], vals[7]; + u32 whoami; + unsigned int pf, s_hps; + int i, v; + + params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | + V_FW_PARAMS_PARAM_XYZ(A_SGE_CONTROL)); + params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | + V_FW_PARAMS_PARAM_XYZ(A_SGE_HOST_PAGE_SIZE)); + params[2] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | + V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_0_AND_1)); + params[3] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | + V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_2_AND_3)); + params[4] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | + V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_4_AND_5)); + params[5] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | + V_FW_PARAMS_PARAM_XYZ(A_SGE_CONM_CTRL)); + params[6] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | + V_FW_PARAMS_PARAM_XYZ(A_SGE_INGRESS_RX_THRESHOLD)); + v = t4vf_query_params(adapter, 7, params, vals); + if (v != FW_SUCCESS) + return v; + + sp->sge_control = vals[0]; + sp->counter_val[0] = G_THRESHOLD_0(vals[6]); + sp->counter_val[1] = G_THRESHOLD_1(vals[6]); + sp->counter_val[2] = G_THRESHOLD_2(vals[6]); + sp->counter_val[3] = G_THRESHOLD_3(vals[6]); + sp->timer_val[0] = core_ticks_to_us(adapter, G_TIMERVALUE0(vals[2])); + sp->timer_val[1] = core_ticks_to_us(adapter, G_TIMERVALUE1(vals[2])); + sp->timer_val[2] = core_ticks_to_us(adapter, G_TIMERVALUE2(vals[3])); + sp->timer_val[3] = core_ticks_to_us(adapter, G_TIMERVALUE3(vals[3])); + sp->timer_val[4] = core_ticks_to_us(adapter, G_TIMERVALUE4(vals[4])); + sp->timer_val[5] = core_ticks_to_us(adapter, G_TIMERVALUE5(vals[4])); + + sp->fl_starve_threshold = G_EGRTHRESHOLD(vals[5]) * 2 + 1; + if (is_t4(adapter)) + sp->fl_starve_threshold2 = sp->fl_starve_threshold; + else + sp->fl_starve_threshold2 = G_EGRTHRESHOLDPACKING(vals[5]) * 2 + + 1; + + /* + * We need the Queues/Page and Host Page Size for our VF. + * This is based on the PF from which we're instantiated. + */ + whoami = t4_read_reg(adapter, VF_PL_REG(A_PL_VF_WHOAMI)); + pf = G_SOURCEPF(whoami); + + s_hps = (S_HOSTPAGESIZEPF0 + + (S_HOSTPAGESIZEPF1 - S_HOSTPAGESIZEPF0) * pf); + sp->page_shift = ((vals[1] >> s_hps) & M_HOSTPAGESIZEPF0) + 10; + + for (i = 0; i < SGE_FLBUF_SIZES; i++) { + params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | + V_FW_PARAMS_PARAM_XYZ(A_SGE_FL_BUFFER_SIZE0 + (4 * i))); + v = t4vf_query_params(adapter, 1, params, vals); + if (v != FW_SUCCESS) + return v; + + sp->sge_fl_buffer_size[i] = vals[0]; + } + + /* + * T4 uses a single control field to specify both the PCIe Padding and + * Packing Boundary. T5 introduced the ability to specify these + * separately with the Padding Boundary in SGE_CONTROL and and Packing + * Boundary in SGE_CONTROL2. So for T5 and later we need to grab + * SGE_CONTROL in order to determine how ingress packet data will be + * laid out in Packed Buffer Mode. Unfortunately, older versions of + * the firmware won't let us retrieve SGE_CONTROL2 so if we get a + * failure grabbing it we throw an error since we can't figure out the + * right value. + */ + sp->spg_len = sp->sge_control & F_EGRSTATUSPAGESIZE ? 128 : 64; + sp->fl_pktshift = G_PKTSHIFT(sp->sge_control); + sp->pad_boundary = 1 << (G_INGPADBOUNDARY(sp->sge_control) + 5); + if (is_t4(adapter)) + sp->pack_boundary = sp->pad_boundary; + else { + params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | + V_FW_PARAMS_PARAM_XYZ(A_SGE_CONTROL2)); + v = t4vf_query_params(adapter, 1, params, vals); + if (v != FW_SUCCESS) { + CH_ERR(adapter, "Unable to get SGE Control2; " + "probably old firmware.\n"); + return v; + } + if (G_INGPACKBOUNDARY(vals[0]) == 0) + sp->pack_boundary = 16; + else + sp->pack_boundary = 1 << (G_INGPACKBOUNDARY(vals[0]) + + 5); + } + + /* + * For T5 and later we want to use the new BAR2 Doorbells. + * Unfortunately, older firmware didn't allow the this register to be + * read. + */ + if (!is_t4(adapter)) { + unsigned int s_qpp; + + params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | + V_FW_PARAMS_PARAM_XYZ(A_SGE_EGRESS_QUEUES_PER_PAGE_VF)); + params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) | + V_FW_PARAMS_PARAM_XYZ(A_SGE_INGRESS_QUEUES_PER_PAGE_VF)); + v = t4vf_query_params(adapter, 2, params, vals); + if (v != FW_SUCCESS) { + CH_WARN(adapter, "Unable to get VF SGE Queues/Page; " + "probably old firmware.\n"); + return v; + } + + s_qpp = (S_QUEUESPERPAGEPF0 + + (S_QUEUESPERPAGEPF1 - S_QUEUESPERPAGEPF0) * pf); + sp->eq_s_qpp = ((vals[0] >> s_qpp) & M_QUEUESPERPAGEPF0); + sp->iq_s_qpp = ((vals[1] >> s_qpp) & M_QUEUESPERPAGEPF0); + } + + return 0; +} + +/** + * t4vf_get_rss_glb_config - retrieve adapter RSS Global Configuration + * @adapter: the adapter + * + * Retrieves global RSS mode and parameters with which we have to live + * and stores them in the @adapter's RSS parameters. + */ +int t4vf_get_rss_glb_config(struct adapter *adapter) +{ + struct rss_params *rss = &adapter->params.rss; + struct fw_rss_glb_config_cmd cmd, rpl; + int v; + + /* + * Execute an RSS Global Configuration read command to retrieve + * our RSS configuration. + */ + memset(&cmd, 0, sizeof(cmd)); + cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) | + F_FW_CMD_REQUEST | + F_FW_CMD_READ); + cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); + v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl); + if (v != FW_SUCCESS) + return v; + + /* + * Transate the big-endian RSS Global Configuration into our + * cpu-endian format based on the RSS mode. We also do first level + * filtering at this point to weed out modes which don't support + * VF Drivers ... + */ + rss->mode = G_FW_RSS_GLB_CONFIG_CMD_MODE( + be32_to_cpu(rpl.u.manual.mode_pkd)); + switch (rss->mode) { + case FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL: { + u32 word = be32_to_cpu( + rpl.u.basicvirtual.synmapen_to_hashtoeplitz); + + rss->u.basicvirtual.synmapen = + ((word & F_FW_RSS_GLB_CONFIG_CMD_SYNMAPEN) != 0); + rss->u.basicvirtual.syn4tupenipv6 = + ((word & F_FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV6) != 0); + rss->u.basicvirtual.syn2tupenipv6 = + ((word & F_FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV6) != 0); + rss->u.basicvirtual.syn4tupenipv4 = + ((word & F_FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV4) != 0); + rss->u.basicvirtual.syn2tupenipv4 = + ((word & F_FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV4) != 0); + + rss->u.basicvirtual.ofdmapen = + ((word & F_FW_RSS_GLB_CONFIG_CMD_OFDMAPEN) != 0); + + rss->u.basicvirtual.tnlmapen = + ((word & F_FW_RSS_GLB_CONFIG_CMD_TNLMAPEN) != 0); + rss->u.basicvirtual.tnlalllookup = + ((word & F_FW_RSS_GLB_CONFIG_CMD_TNLALLLKP) != 0); + + rss->u.basicvirtual.hashtoeplitz = + ((word & F_FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ) != 0); + + /* we need at least Tunnel Map Enable to be set */ + if (!rss->u.basicvirtual.tnlmapen) + return -EINVAL; + break; + } + + default: + /* all unknown/unsupported RSS modes result in an error */ + return -EINVAL; + } + + return 0; +} + +/** + * t4vf_get_vfres - retrieve VF resource limits + * @adapter: the adapter + * + * Retrieves configured resource limits and capabilities for a virtual + * function. The results are stored in @adapter->vfres. + */ +int t4vf_get_vfres(struct adapter *adapter) +{ + struct vf_resources *vfres = &adapter->params.vfres; + struct fw_pfvf_cmd cmd, rpl; + int v; + u32 word; + + /* + * Execute PFVF Read command to get VF resource limits; bail out early + * with error on command failure. + */ + memset(&cmd, 0, sizeof(cmd)); + cmd.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_PFVF_CMD) | + F_FW_CMD_REQUEST | + F_FW_CMD_READ); + cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); + v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl); + if (v != FW_SUCCESS) + return v; + + /* + * Extract VF resource limits and return success. + */ + word = be32_to_cpu(rpl.niqflint_niq); + vfres->niqflint = G_FW_PFVF_CMD_NIQFLINT(word); + vfres->niq = G_FW_PFVF_CMD_NIQ(word); + + word = be32_to_cpu(rpl.type_to_neq); + vfres->neq = G_FW_PFVF_CMD_NEQ(word); + vfres->pmask = G_FW_PFVF_CMD_PMASK(word); + + word = be32_to_cpu(rpl.tc_to_nexactf); + vfres->tc = G_FW_PFVF_CMD_TC(word); + vfres->nvi = G_FW_PFVF_CMD_NVI(word); + vfres->nexactf = G_FW_PFVF_CMD_NEXACTF(word); + + word = be32_to_cpu(rpl.r_caps_to_nethctrl); + vfres->r_caps = G_FW_PFVF_CMD_R_CAPS(word); + vfres->wx_caps = G_FW_PFVF_CMD_WX_CAPS(word); + vfres->nethctrl = G_FW_PFVF_CMD_NETHCTRL(word); + + return 0; +} + +/** + */ +int t4vf_prep_adapter(struct adapter *adapter) +{ + int err; + + /* + * Wait for the device to become ready before proceeding ... + */ + err = t4vf_wait_dev_ready(adapter); + if (err) + return err; + + adapter->params.chipid = pci_get_device(adapter->dev) >> 12; + if (adapter->params.chipid >= 0xa) { + adapter->params.chipid -= (0xa - 0x4); + adapter->params.fpga = 1; + } + + /* + * Default port and clock for debugging in case we can't reach + * firmware. + */ + adapter->params.nports = 1; + adapter->params.vfres.pmask = 1; + adapter->params.vpd.cclk = 50000; + + adapter->chip_params = t4_get_chip_params(chip_id(adapter)); + if (adapter->chip_params == NULL) + return -EINVAL; + + return 0; +} diff --git a/sys/dev/cxgbe/if_cxlv.c b/sys/dev/cxgbe/if_cxlv.c new file mode 100644 index 00000000000..5a169d0d33b --- /dev/null +++ b/sys/dev/cxgbe/if_cxlv.c @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 2015 Chelsio Communications, Inc. + * All rights reserved. + * Written by: Navdeep Parhar + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 AUTHOR 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 AUTHOR 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +static int +mod_event(module_t mod, int cmd, void *arg) +{ + + return (0); +} +static moduledata_t if_cxlv_mod = {"if_cxlv", mod_event}; +DECLARE_MODULE(if_cxlv, if_cxlv_mod, SI_SUB_EXEC, SI_ORDER_ANY); +MODULE_VERSION(if_cxlv, 1); +MODULE_DEPEND(if_cxlv, cxlv, 1, 1, 1); diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index b416603f7ef..2513a7591c6 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -105,7 +105,7 @@ static driver_t t4_driver = { static int cxgbe_probe(device_t); static int cxgbe_attach(device_t); static int cxgbe_detach(device_t); -static device_method_t cxgbe_methods[] = { +device_method_t cxgbe_methods[] = { DEVMETHOD(device_probe, cxgbe_probe), DEVMETHOD(device_attach, cxgbe_attach), DEVMETHOD(device_detach, cxgbe_detach), @@ -210,19 +210,19 @@ SLIST_HEAD(, uld_info) t4_uld_list; * Number of queues for tx and rx, 10G and 1G, NIC and offload. */ #define NTXQ_10G 16 -static int t4_ntxq10g = -1; +int t4_ntxq10g = -1; TUNABLE_INT("hw.cxgbe.ntxq10g", &t4_ntxq10g); #define NRXQ_10G 8 -static int t4_nrxq10g = -1; +int t4_nrxq10g = -1; TUNABLE_INT("hw.cxgbe.nrxq10g", &t4_nrxq10g); #define NTXQ_1G 4 -static int t4_ntxq1g = -1; +int t4_ntxq1g = -1; TUNABLE_INT("hw.cxgbe.ntxq1g", &t4_ntxq1g); #define NRXQ_1G 2 -static int t4_nrxq1g = -1; +int t4_nrxq1g = -1; TUNABLE_INT("hw.cxgbe.nrxq1g", &t4_nrxq1g); #define NTXQ_VI 1 @@ -276,34 +276,34 @@ TUNABLE_INT("hw.cxgbe.nnmrxq_vi", &t4_nnmrxq_vi); * Holdoff parameters for 10G and 1G ports. */ #define TMR_IDX_10G 1 -static int t4_tmr_idx_10g = TMR_IDX_10G; +int t4_tmr_idx_10g = TMR_IDX_10G; TUNABLE_INT("hw.cxgbe.holdoff_timer_idx_10G", &t4_tmr_idx_10g); #define PKTC_IDX_10G (-1) -static int t4_pktc_idx_10g = PKTC_IDX_10G; +int t4_pktc_idx_10g = PKTC_IDX_10G; TUNABLE_INT("hw.cxgbe.holdoff_pktc_idx_10G", &t4_pktc_idx_10g); #define TMR_IDX_1G 1 -static int t4_tmr_idx_1g = TMR_IDX_1G; +int t4_tmr_idx_1g = TMR_IDX_1G; TUNABLE_INT("hw.cxgbe.holdoff_timer_idx_1G", &t4_tmr_idx_1g); #define PKTC_IDX_1G (-1) -static int t4_pktc_idx_1g = PKTC_IDX_1G; +int t4_pktc_idx_1g = PKTC_IDX_1G; TUNABLE_INT("hw.cxgbe.holdoff_pktc_idx_1G", &t4_pktc_idx_1g); /* * Size (# of entries) of each tx and rx queue. */ -static unsigned int t4_qsize_txq = TX_EQ_QSIZE; +unsigned int t4_qsize_txq = TX_EQ_QSIZE; TUNABLE_INT("hw.cxgbe.qsize_txq", &t4_qsize_txq); -static unsigned int t4_qsize_rxq = RX_IQ_QSIZE; +unsigned int t4_qsize_rxq = RX_IQ_QSIZE; TUNABLE_INT("hw.cxgbe.qsize_rxq", &t4_qsize_rxq); /* * Interrupt types allowed (bits 0, 1, 2 = INTx, MSI, MSI-X respectively). */ -static int t4_intr_types = INTR_MSIX | INTR_MSI | INTR_INTX; +int t4_intr_types = INTR_MSIX | INTR_MSI | INTR_INTX; TUNABLE_INT("hw.cxgbe.interrupt_types", &t4_intr_types); /* @@ -414,8 +414,6 @@ struct filter_entry { struct t4_filter_specification fs; }; -static int map_bars_0_and_4(struct adapter *); -static int map_bar_2(struct adapter *); static void setup_memwin(struct adapter *); static void position_memwin(struct adapter *, int, uint32_t); static int rw_via_memwin(struct adapter *, int, uint32_t, uint32_t *, int, int); @@ -440,7 +438,6 @@ static void t4_set_desc(struct adapter *); static void build_medialist(struct port_info *, struct ifmedia *); static int cxgbe_init_synchronized(struct vi_info *); static int cxgbe_uninit_synchronized(struct vi_info *); -static int setup_intr_handlers(struct adapter *); static void quiesce_txq(struct adapter *, struct sge_txq *); static void quiesce_wrq(struct adapter *, struct sge_wrq *); static void quiesce_iq(struct adapter *, struct sge_iq *); @@ -453,7 +450,6 @@ static void vi_refresh_stats(struct adapter *, struct vi_info *); static void cxgbe_refresh_stats(struct adapter *, struct port_info *); static void cxgbe_tick(void *); static void cxgbe_vlan_config(void *, struct ifnet *, uint16_t); -static void t4_sysctls(struct adapter *); static void cxgbe_sysctls(struct port_info *); static int sysctl_int_array(SYSCTL_HANDLER_ARGS); static int sysctl_bitfield(SYSCTL_HANDLER_ARGS); @@ -522,8 +518,6 @@ static int get_sge_context(struct adapter *, struct t4_sge_context *); static int load_fw(struct adapter *, struct t4_data *); static int read_card_mem(struct adapter *, int, struct t4_mem_range *); static int read_i2c(struct adapter *, struct t4_i2c_data *); -static int set_sched_class(struct adapter *, struct t4_sched_params *); -static int set_sched_queue(struct adapter *, struct t4_sched_queue *); #ifdef TCP_OFFLOAD static int toe_capability(struct vi_info *, int); #endif @@ -707,9 +701,7 @@ t4_attach(device_t dev) snprintf(sc->lockname, sizeof(sc->lockname), "%s", device_get_nameunit(dev)); mtx_init(&sc->sc_lock, sc->lockname, 0, MTX_DEF); - sx_xlock(&t4_list_lock); - SLIST_INSERT_HEAD(&t4_list, sc, link); - sx_xunlock(&t4_list_lock); + t4_add_adapter(sc); mtx_init(&sc->sfl_lock, "starving freelists", 0, MTX_DEF); TAILQ_INIT(&sc->sfl); @@ -717,7 +709,7 @@ t4_attach(device_t dev) mtx_init(&sc->reg_lock, "indirect register access", 0, MTX_DEF); - rc = map_bars_0_and_4(sc); + rc = t4_map_bars_0_and_4(sc); if (rc != 0) goto done; /* error message displayed already */ @@ -787,7 +779,7 @@ t4_attach(device_t dev) if (rc != 0) goto done; /* error message displayed already */ - rc = map_bar_2(sc); + rc = t4_map_bar_2(sc); if (rc != 0) goto done; /* error message displayed already */ @@ -1041,7 +1033,7 @@ t4_attach(device_t dev) } } - rc = setup_intr_handlers(sc); + rc = t4_setup_intr_handlers(sc); if (rc != 0) { device_printf(dev, "failed to setup interrupt handlers: %d\n", rc); @@ -1075,7 +1067,7 @@ done: } if (rc != 0) - t4_detach(dev); + t4_detach_common(dev); else t4_sysctls(sc); @@ -1140,8 +1132,7 @@ static int t4_detach(device_t dev) { struct adapter *sc; - struct port_info *pi; - int i, rc; + int rc; sc = device_get_softc(dev); @@ -1152,19 +1143,35 @@ t4_detach(device_t dev) return (rc); } - if (sc->flags & FULL_INIT_DONE) - t4_intr_disable(sc); + return (t4_detach_common(dev)); +} + +int +t4_detach_common(device_t dev) +{ + struct adapter *sc; + struct port_info *pi; + int i, rc; + + sc = device_get_softc(dev); + + if (sc->flags & FULL_INIT_DONE) { + if (!(sc->flags & IS_VF)) + t4_intr_disable(sc); + } if (sc->cdev) { destroy_dev(sc->cdev); sc->cdev = NULL; } - rc = bus_generic_detach(dev); - if (rc) { - device_printf(dev, - "failed to detach child devices: %d\n", rc); - return (rc); + if (device_is_attached(dev)) { + rc = bus_generic_detach(dev); + if (rc) { + device_printf(dev, + "failed to detach child devices: %d\n", rc); + return (rc); + } } for (i = 0; i < sc->intr_count; i++) @@ -1187,7 +1194,7 @@ t4_detach(device_t dev) if (sc->flags & FULL_INIT_DONE) adapter_full_uninit(sc); - if (sc->flags & FW_OK) + if ((sc->flags & (IS_VF | FW_OK)) == FW_OK) t4_fw_bye(sc, sc->mbox); if (sc->intr_type == INTR_MSI || sc->intr_type == INTR_MSIX) @@ -1677,7 +1684,7 @@ cxgbe_transmit(struct ifnet *ifp, struct mbuf *m) return (ENETDOWN); } - rc = parse_pkt(&m); + rc = parse_pkt(sc, &m); if (__predict_false(rc != 0)) { MPASS(m == NULL); /* was freed already */ atomic_add_int(&pi->tx_parse_error, 1); /* rare, atomic is ok */ @@ -1778,7 +1785,7 @@ cxgbe_get_counter(struct ifnet *ifp, ift_counter c) struct adapter *sc = pi->adapter; struct port_stats *s = &pi->stats; - if (pi->nvi > 1) + if (pi->nvi > 1 || sc->flags & IS_VF) return (vi_get_counter(ifp, c)); cxgbe_refresh_stats(sc, pi); @@ -1966,8 +1973,16 @@ t4_fatal_err(struct adapter *sc) device_get_nameunit(sc->dev)); } -static int -map_bars_0_and_4(struct adapter *sc) +void +t4_add_adapter(struct adapter *sc) +{ + sx_xlock(&t4_list_lock); + SLIST_INSERT_HEAD(&t4_list, sc, link); + sx_xunlock(&t4_list_lock); +} + +int +t4_map_bars_0_and_4(struct adapter *sc) { sc->regs_rid = PCIR_BAR(0); sc->regs_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, @@ -1992,8 +2007,8 @@ map_bars_0_and_4(struct adapter *sc) return (0); } -static int -map_bar_2(struct adapter *sc) +int +t4_map_bar_2(struct adapter *sc) { /* @@ -3773,7 +3788,7 @@ cxgbe_init_synchronized(struct vi_info *vi) ifp->if_drv_flags |= IFF_DRV_RUNNING; pi->up_vis++; - if (pi->nvi > 1) + if (pi->nvi > 1 || sc->flags & IS_VF) callout_reset(&vi->tick, hz, vi_tick, vi); else callout_reset(&pi->tick, hz, cxgbe_tick, pi); @@ -3825,10 +3840,10 @@ cxgbe_uninit_synchronized(struct vi_info *vi) } PORT_LOCK(pi); - if (pi->nvi == 1) - callout_stop(&pi->tick); - else + if (pi->nvi > 1 || sc->flags & IS_VF) callout_stop(&vi->tick); + else + callout_stop(&pi->tick); if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { PORT_UNLOCK(pi); return (0); @@ -3853,8 +3868,8 @@ cxgbe_uninit_synchronized(struct vi_info *vi) * It is ok for this function to fail midway and return right away. t4_detach * will walk the entire sc->irq list and clean up whatever is valid. */ -static int -setup_intr_handlers(struct adapter *sc) +int +t4_setup_intr_handlers(struct adapter *sc) { int rc, rid, p, q, v; char s[8]; @@ -3882,17 +3897,23 @@ setup_intr_handlers(struct adapter *sc) return (t4_alloc_irq(sc, irq, rid, t4_intr_all, sc, "all")); /* Multiple interrupts. */ - KASSERT(sc->intr_count >= T4_EXTRA_INTR + sc->params.nports, - ("%s: too few intr.", __func__)); + if (sc->flags & IS_VF) + KASSERT(sc->intr_count >= T4VF_EXTRA_INTR + sc->params.nports, + ("%s: too few intr.", __func__)); + else + KASSERT(sc->intr_count >= T4_EXTRA_INTR + sc->params.nports, + ("%s: too few intr.", __func__)); - /* The first one is always error intr */ - rc = t4_alloc_irq(sc, irq, rid, t4_intr_err, sc, "err"); - if (rc != 0) - return (rc); - irq++; - rid++; + /* The first one is always error intr on PFs */ + if (!(sc->flags & IS_VF)) { + rc = t4_alloc_irq(sc, irq, rid, t4_intr_err, sc, "err"); + if (rc != 0) + return (rc); + irq++; + rid++; + } - /* The second one is always the firmware event queue */ + /* The second one is always the firmware event queue (first on VFs) */ rc = t4_alloc_irq(sc, irq, rid, t4_intr_evt, &sge->fwq, "evt"); if (rc != 0) return (rc); @@ -3999,7 +4020,8 @@ adapter_full_init(struct adapter *sc) device_get_nameunit(sc->dev), i); } - t4_intr_enable(sc); + if (!(sc->flags & IS_VF)) + t4_intr_enable(sc); sc->flags |= FULL_INIT_DONE; done: if (rc != 0) @@ -4248,7 +4270,7 @@ vi_full_uninit(struct vi_info *vi) /* Need to quiesce queues. */ /* XXX: Only for the first VI? */ - if (IS_MAIN_VI(vi)) + if (IS_MAIN_VI(vi) && !(sc->flags & IS_VF)) quiesce_wrq(sc, &sc->sge.ctrlq[pi->port_id]); for_each_txq(vi, i, txq) { @@ -4415,10 +4437,16 @@ read_vf_stat(struct adapter *sc, unsigned int viid, int reg) u32 stats[2]; mtx_assert(&sc->reg_lock, MA_OWNED); - t4_write_reg(sc, A_PL_INDIR_CMD, V_PL_AUTOINC(1) | - V_PL_VFID(G_FW_VIID_VIN(viid)) | V_PL_ADDR(VF_MPS_REG(reg))); - stats[0] = t4_read_reg(sc, A_PL_INDIR_DATA); - stats[1] = t4_read_reg(sc, A_PL_INDIR_DATA); + if (sc->flags & IS_VF) { + stats[0] = t4_read_reg(sc, VF_MPS_REG(reg)); + stats[1] = t4_read_reg(sc, VF_MPS_REG(reg + 4)); + } else { + t4_write_reg(sc, A_PL_INDIR_CMD, V_PL_AUTOINC(1) | + V_PL_VFID(G_FW_VIID_VIN(viid)) | + V_PL_ADDR(VF_MPS_REG(reg))); + stats[0] = t4_read_reg(sc, A_PL_INDIR_DATA); + stats[1] = t4_read_reg(sc, A_PL_INDIR_DATA); + } return (((uint64_t)stats[1]) << 32 | stats[0]); } @@ -4567,7 +4595,7 @@ static char *caps_decoder[] = { "\004PO_INITIATOR\005PO_TARGET", }; -static void +void t4_sysctls(struct adapter *sc) { struct sysctl_ctx_list *ctx; @@ -4616,6 +4644,15 @@ t4_sysctls(struct adapter *sc) SYSCTL_ADD_INT(ctx, children, OID_AUTO, "debug_flags", CTLFLAG_RW, &sc->debug_flags, 0, "flags to enable runtime debugging"); + SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "tp_version", + CTLFLAG_RD, sc->tp_version, 0, "TP microcode version"); + + SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "firmware_version", + CTLFLAG_RD, sc->fw_version, 0, "firmware version"); + + if (sc->flags & IS_VF) + return; + SYSCTL_ADD_INT(ctx, children, OID_AUTO, "hw_revision", CTLFLAG_RD, NULL, chip_rev(sc), "chip hardware revision"); @@ -4631,15 +4668,9 @@ t4_sysctls(struct adapter *sc) SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "na", CTLFLAG_RD, sc->params.vpd.na, 0, "network address"); - SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "tp_version", - CTLFLAG_RD, sc->tp_version, 0, "TP microcode version"); - SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "er_version", CTLFLAG_RD, sc->er_version, 0, "expansion ROM version"); - SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "firmware_version", - CTLFLAG_RD, sc->fw_version, 0, "firmware version"); - SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "bs_version", CTLFLAG_RD, sc->bs_version, 0, "bootstrap firmware version"); @@ -5047,6 +5078,9 @@ cxgbe_sysctls(struct port_info *pi) SYSCTL_ADD_INT(ctx, children, OID_AUTO, "max_speed", CTLFLAG_RD, NULL, port_top_speed(pi), "max speed (in Gbps)"); + if (sc->flags & IS_VF) + return; + /* * dev.(cxgbe|cxl).X.tc. */ @@ -8541,8 +8575,8 @@ set_sched_class_params(struct adapter *sc, struct t4_sched_class_params *p, return (rc); } -static int -set_sched_class(struct adapter *sc, struct t4_sched_params *p) +int +t4_set_sched_class(struct adapter *sc, struct t4_sched_params *p) { if (p->type != SCHED_CLASS_TYPE_PACKET) @@ -8557,8 +8591,8 @@ set_sched_class(struct adapter *sc, struct t4_sched_params *p) return (EINVAL); } -static int -set_sched_queue(struct adapter *sc, struct t4_sched_queue *p) +int +t4_set_sched_queue(struct adapter *sc, struct t4_sched_queue *p) { struct port_info *pi = NULL; struct vi_info *vi; @@ -8896,10 +8930,10 @@ t4_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data, int fflag, break; } case CHELSIO_T4_SCHED_CLASS: - rc = set_sched_class(sc, (struct t4_sched_params *)data); + rc = t4_set_sched_class(sc, (struct t4_sched_params *)data); break; case CHELSIO_T4_SCHED_QUEUE: - rc = set_sched_queue(sc, (struct t4_sched_queue *)data); + rc = t4_set_sched_queue(sc, (struct t4_sched_queue *)data); break; case CHELSIO_T4_GET_TRACER: rc = t4_get_tracer(sc, (struct t4_tracer *)data); diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c index 8bee75d9838..b98bfe3640e 100644 --- a/sys/dev/cxgbe/t4_sge.c +++ b/sys/dev/cxgbe/t4_sge.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -223,10 +224,13 @@ static void add_fl_to_sfl(struct adapter *, struct sge_fl *); static inline void get_pkt_gl(struct mbuf *, struct sglist *); static inline u_int txpkt_len16(u_int, u_int); +static inline u_int txpkt_vm_len16(u_int, u_int); static inline u_int txpkts0_len16(u_int); static inline u_int txpkts1_len16(void); static u_int write_txpkt_wr(struct sge_txq *, struct fw_eth_tx_pkt_wr *, struct mbuf *, u_int); +static u_int write_txpkt_vm_wr(struct sge_txq *, struct fw_eth_tx_pkt_vm_wr *, + struct mbuf *, u_int); static int try_txpkts(struct mbuf *, struct mbuf *, struct txpkts *, u_int); static int add_to_txpkts(struct mbuf *, struct txpkts *, u_int); static u_int write_txpkts_wr(struct sge_txq *, struct fw_eth_tx_pkts_wr *, @@ -759,6 +763,9 @@ t4_read_chip_settings(struct adapter *sc) } } + if (sc->flags & IS_VF) + return (0); + v = V_HPZ0(0) | V_HPZ1(2) | V_HPZ2(4) | V_HPZ3(6); r = t4_read_reg(sc, A_ULP_RX_TDDP_PSZ); if (r != v) { @@ -869,7 +876,8 @@ t4_setup_adapter_queues(struct adapter *sc) * Management queue. This is just a control queue that uses the fwq as * its associated iq. */ - rc = alloc_mgmtq(sc); + if (!(sc->flags & IS_VF)) + rc = alloc_mgmtq(sc); return (rc); } @@ -1175,7 +1183,7 @@ t4_setup_vi_queues(struct vi_info *vi) /* * Finally, the control queue. */ - if (!IS_MAIN_VI(vi)) + if (!IS_MAIN_VI(vi) || sc->flags & IS_VF) goto done; oid = SYSCTL_ADD_NODE(&vi->ctx, children, OID_AUTO, "ctrlq", CTLFLAG_RD, NULL, "ctrl queue"); @@ -1236,7 +1244,7 @@ t4_teardown_vi_queues(struct vi_info *vi) * (for egress updates, etc.). */ - if (IS_MAIN_VI(vi)) + if (IS_MAIN_VI(vi) && !(sc->flags & IS_VF)) free_wrq(sc, &sc->sge.ctrlq[pi->port_id]); for_each_txq(vi, i, txq) { @@ -2153,7 +2161,7 @@ count_mbuf_nsegs(struct mbuf *m) * b) it may get defragged up if the gather list is too long for the hardware. */ int -parse_pkt(struct mbuf **mp) +parse_pkt(struct adapter *sc, struct mbuf **mp) { struct mbuf *m0 = *mp, *m; int rc, nsegs, defragged = 0, offset; @@ -2200,9 +2208,13 @@ restart: goto restart; } set_mbuf_nsegs(m0, nsegs); - set_mbuf_len16(m0, txpkt_len16(nsegs, needs_tso(m0))); + if (sc->flags & IS_VF) + set_mbuf_len16(m0, txpkt_vm_len16(nsegs, needs_tso(m0))); + else + set_mbuf_len16(m0, txpkt_len16(nsegs, needs_tso(m0))); - if (!needs_tso(m0)) + if (!needs_tso(m0) && + !(sc->flags & IS_VF && (needs_l3_csum(m0) || needs_l4_csum(m0)))) return (0); m = m0; @@ -2225,7 +2237,7 @@ restart: { struct ip6_hdr *ip6 = l3hdr; - MPASS(ip6->ip6_nxt == IPPROTO_TCP); + MPASS(!needs_tso(m0) || ip6->ip6_nxt == IPPROTO_TCP); m0->m_pkthdr.l3hlen = sizeof(*ip6); break; @@ -2247,8 +2259,10 @@ restart: } #if defined(INET) || defined(INET6) - tcp = m_advance(&m, &offset, m0->m_pkthdr.l3hlen); - m0->m_pkthdr.l4hlen = tcp->th_off * 4; + if (needs_tso(m0)) { + tcp = m_advance(&m, &offset, m0->m_pkthdr.l3hlen); + m0->m_pkthdr.l4hlen = tcp->th_off * 4; + } #endif MPASS(m0 == *mp); return (0); @@ -2443,7 +2457,12 @@ eth_tx(struct mp_ring *r, u_int cidx, u_int pidx) next_cidx = 0; wr = (void *)&eq->desc[eq->pidx]; - if (remaining > 1 && + if (sc->flags & IS_VF) { + total++; + remaining--; + ETHER_BPF_MTAP(ifp, m0); + n = write_txpkt_vm_wr(txq, (void *)wr, m0, available); + } else if (remaining > 1 && try_txpkts(m0, r->items[next_cidx], &txp, available) == 0) { /* pkts at cidx, next_cidx should both be in txp. */ @@ -2774,7 +2793,7 @@ alloc_iq_fl(struct vi_info *vi, struct sge_iq *iq, struct sge_fl *fl, FL_UNLOCK(fl); } - if (is_t5(sc) && cong >= 0) { + if (is_t5(sc) && !(sc->flags & IS_VF) && cong >= 0) { uint32_t param, val; param = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) | @@ -2898,9 +2917,13 @@ alloc_fwq(struct adapter *sc) init_iq(fwq, sc, 0, 0, FW_IQ_QSIZE); fwq->flags |= IQ_INTR; /* always */ - intr_idx = sc->intr_count > 1 ? 1 : 0; - fwq->set_tcb_rpl = t4_filter_rpl; - fwq->l2t_write_rpl = do_l2t_write_rpl; + if (sc->flags & IS_VF) + intr_idx = 0; + else { + intr_idx = sc->intr_count > 1 ? 1 : 0; + fwq->set_tcb_rpl = t4_filter_rpl; + fwq->l2t_write_rpl = do_l2t_write_rpl; + } rc = alloc_iq_fl(&sc->port[0]->vi[0], fwq, NULL, intr_idx, -1); if (rc != 0) { device_printf(sc->dev, @@ -3586,9 +3609,13 @@ alloc_txq(struct vi_info *vi, struct sge_txq *txq, int idx, TASK_INIT(&txq->tx_reclaim_task, 0, tx_reclaim, eq); txq->ifp = vi->ifp; txq->gl = sglist_alloc(TX_SGL_SEGS, M_WAITOK); - txq->cpl_ctrl0 = htobe32(V_TXPKT_OPCODE(CPL_TX_PKT) | - V_TXPKT_INTF(pi->tx_chan) | V_TXPKT_VF_VLD(1) | - V_TXPKT_VF(vi->viid)); + if (sc->flags & IS_VF) + txq->cpl_ctrl0 = htobe32(V_TXPKT_OPCODE(CPL_TX_PKT_XT) | + V_TXPKT_INTF(pi->tx_chan)); + else + txq->cpl_ctrl0 = htobe32(V_TXPKT_OPCODE(CPL_TX_PKT) | + V_TXPKT_INTF(pi->tx_chan) | V_TXPKT_VF_VLD(1) | + V_TXPKT_VF(vi->viid)); txq->tc_idx = -1; txq->sdesc = malloc(eq->sidx * sizeof(struct tx_sdesc), M_CXGBE, M_ZERO | M_WAITOK); @@ -3940,6 +3967,27 @@ txpkt_len16(u_int nsegs, u_int tso) return (howmany(n, 16)); } +/* + * len16 for a txpkt_vm WR with a GL. Includes the firmware work + * request header. + */ +static inline u_int +txpkt_vm_len16(u_int nsegs, u_int tso) +{ + u_int n; + + MPASS(nsegs > 0); + + nsegs--; /* first segment is part of ulptx_sgl */ + n = sizeof(struct fw_eth_tx_pkt_vm_wr) + + sizeof(struct cpl_tx_pkt_core) + + sizeof(struct ulptx_sgl) + 8 * ((3 * nsegs) / 2 + (nsegs & 1)); + if (tso) + n += sizeof(struct cpl_tx_pkt_lso_core); + + return (howmany(n, 16)); +} + /* * len16 for a txpkts type 0 WR with a GL. Does not include the firmware work * request header. @@ -3984,6 +4032,181 @@ imm_payload(u_int ndesc) return (n); } +/* + * Write a VM txpkt WR for this packet to the hardware descriptors, update the + * software descriptor, and advance the pidx. It is guaranteed that enough + * descriptors are available. + * + * The return value is the # of hardware descriptors used. + */ +static u_int +write_txpkt_vm_wr(struct sge_txq *txq, struct fw_eth_tx_pkt_vm_wr *wr, + struct mbuf *m0, u_int available) +{ + struct sge_eq *eq = &txq->eq; + struct tx_sdesc *txsd; + struct cpl_tx_pkt_core *cpl; + uint32_t ctrl; /* used in many unrelated places */ + uint64_t ctrl1; + int csum_type, len16, ndesc, pktlen, nsegs; + caddr_t dst; + + TXQ_LOCK_ASSERT_OWNED(txq); + M_ASSERTPKTHDR(m0); + MPASS(available > 0 && available < eq->sidx); + + len16 = mbuf_len16(m0); + nsegs = mbuf_nsegs(m0); + pktlen = m0->m_pkthdr.len; + ctrl = sizeof(struct cpl_tx_pkt_core); + if (needs_tso(m0)) + ctrl += sizeof(struct cpl_tx_pkt_lso_core); + ndesc = howmany(len16, EQ_ESIZE / 16); + MPASS(ndesc <= available); + + /* Firmware work request header */ + MPASS(wr == (void *)&eq->desc[eq->pidx]); + wr->op_immdlen = htobe32(V_FW_WR_OP(FW_ETH_TX_PKT_VM_WR) | + V_FW_ETH_TX_PKT_WR_IMMDLEN(ctrl)); + + ctrl = V_FW_WR_LEN16(len16); + wr->equiq_to_len16 = htobe32(ctrl); + wr->r3[0] = 0; + wr->r3[1] = 0; + + /* + * Copy over ethmacdst, ethmacsrc, ethtype, and vlantci. + * vlantci is ignored unless the ethtype is 0x8100, so it's + * simpler to always copy it rather than making it + * conditional. Also, it seems that we do not have to set + * vlantci or fake the ethtype when doing VLAN tag insertion. + */ + m_copydata(m0, 0, sizeof(struct ether_header) + 2, wr->ethmacdst); + + csum_type = -1; + if (needs_tso(m0)) { + struct cpl_tx_pkt_lso_core *lso = (void *)(wr + 1); + + KASSERT(m0->m_pkthdr.l2hlen > 0 && m0->m_pkthdr.l3hlen > 0 && + m0->m_pkthdr.l4hlen > 0, + ("%s: mbuf %p needs TSO but missing header lengths", + __func__, m0)); + + ctrl = V_LSO_OPCODE(CPL_TX_PKT_LSO) | F_LSO_FIRST_SLICE | + F_LSO_LAST_SLICE | V_LSO_IPHDR_LEN(m0->m_pkthdr.l3hlen >> 2) + | V_LSO_TCPHDR_LEN(m0->m_pkthdr.l4hlen >> 2); + if (m0->m_pkthdr.l2hlen == sizeof(struct ether_vlan_header)) + ctrl |= V_LSO_ETHHDR_LEN(1); + if (m0->m_pkthdr.l3hlen == sizeof(struct ip6_hdr)) + ctrl |= F_LSO_IPV6; + + lso->lso_ctrl = htobe32(ctrl); + lso->ipid_ofst = htobe16(0); + lso->mss = htobe16(m0->m_pkthdr.tso_segsz); + lso->seqno_offset = htobe32(0); + lso->len = htobe32(pktlen); + + if (m0->m_pkthdr.l3hlen == sizeof(struct ip6_hdr)) + csum_type = TX_CSUM_TCPIP6; + else + csum_type = TX_CSUM_TCPIP; + + cpl = (void *)(lso + 1); + + txq->tso_wrs++; + } else { + if (m0->m_pkthdr.csum_flags & CSUM_IP_TCP) + csum_type = TX_CSUM_TCPIP; + else if (m0->m_pkthdr.csum_flags & CSUM_IP_UDP) + csum_type = TX_CSUM_UDPIP; + else if (m0->m_pkthdr.csum_flags & CSUM_IP6_TCP) + csum_type = TX_CSUM_TCPIP6; + else if (m0->m_pkthdr.csum_flags & CSUM_IP6_UDP) + csum_type = TX_CSUM_UDPIP6; +#if defined(INET) + else if (m0->m_pkthdr.csum_flags & CSUM_IP) { + /* + * XXX: The firmware appears to stomp on the + * fragment/flags field of the IP header when + * using TX_CSUM_IP. Fall back to doing + * software checksums. + */ + u_short *sump; + struct mbuf *m; + int offset; + + m = m0; + offset = 0; + sump = m_advance(&m, &offset, m0->m_pkthdr.l2hlen + + offsetof(struct ip, ip_sum)); + *sump = in_cksum_skip(m0, m0->m_pkthdr.l2hlen + + m0->m_pkthdr.l3hlen, m0->m_pkthdr.l2hlen); + m0->m_pkthdr.csum_flags &= ~CSUM_IP; + } +#endif + + cpl = (void *)(wr + 1); + } + + /* Checksum offload */ + ctrl1 = 0; + if (needs_l3_csum(m0) == 0) + ctrl1 |= F_TXPKT_IPCSUM_DIS; + if (csum_type >= 0) { + KASSERT(m0->m_pkthdr.l2hlen > 0 && m0->m_pkthdr.l3hlen > 0, + ("%s: mbuf %p needs checksum offload but missing header lengths", + __func__, m0)); + + /* XXX: T6 */ + ctrl1 |= V_TXPKT_ETHHDR_LEN(m0->m_pkthdr.l2hlen - + ETHER_HDR_LEN); + ctrl1 |= V_TXPKT_IPHDR_LEN(m0->m_pkthdr.l3hlen); + ctrl1 |= V_TXPKT_CSUM_TYPE(csum_type); + } else + ctrl1 |= F_TXPKT_L4CSUM_DIS; + if (m0->m_pkthdr.csum_flags & (CSUM_IP | CSUM_TCP | CSUM_UDP | + CSUM_UDP_IPV6 | CSUM_TCP_IPV6 | CSUM_TSO)) + txq->txcsum++; /* some hardware assistance provided */ + + /* VLAN tag insertion */ + if (needs_vlan_insertion(m0)) { + ctrl1 |= F_TXPKT_VLAN_VLD | + V_TXPKT_VLAN(m0->m_pkthdr.ether_vtag); + txq->vlan_insertion++; + } + + /* CPL header */ + cpl->ctrl0 = txq->cpl_ctrl0; + cpl->pack = 0; + cpl->len = htobe16(pktlen); + cpl->ctrl1 = htobe64(ctrl1); + + /* SGL */ + dst = (void *)(cpl + 1); + + /* + * A packet using TSO will use up an entire descriptor for the + * firmware work request header, LSO CPL, and TX_PKT_XT CPL. + * If this descriptor is the last descriptor in the ring, wrap + * around to the front of the ring explicitly for the start of + * the sgl. + */ + if (dst == (void *)&eq->desc[eq->sidx]) { + dst = (void *)&eq->desc[0]; + write_gl_to_txd(txq, m0, &dst, 0); + } else + write_gl_to_txd(txq, m0, &dst, eq->sidx - ndesc < eq->pidx); + txq->sgl_wrs++; + + txq->txpkt_wrs++; + + txsd = &txq->sdesc[eq->pidx]; + txsd->m = m0; + txsd->desc_used = ndesc; + + return (ndesc); +} + /* * Write a txpkt WR for this packet to the hardware descriptors, update the * software descriptor, and advance the pidx. It is guaranteed that enough diff --git a/sys/dev/cxgbe/t4_vf.c b/sys/dev/cxgbe/t4_vf.c new file mode 100644 index 00000000000..dc02e30c5c1 --- /dev/null +++ b/sys/dev/cxgbe/t4_vf.c @@ -0,0 +1,950 @@ +/*- + * Copyright (c) 2016 Chelsio Communications, Inc. + * All rights reserved. + * Written by: John Baldwin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 AUTHOR 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 AUTHOR 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 +__FBSDID("$FreeBSD$"); + +#include "opt_inet.h" +#include "opt_inet6.h" + +#include +#include +#include +#include +#include +#include +#include +#if defined(__i386__) || defined(__amd64__) +#include +#include +#endif + +#include "common/common.h" +#include "common/t4_regs.h" +#include "t4_ioctl.h" +#include "t4_mp_ring.h" + +/* + * Some notes: + * + * The Virtual Interfaces are connected to an internal switch on the chip + * which allows VIs attached to the same port to talk to each other even when + * the port link is down. As a result, we might want to always report a + * VF's link as being "up". + * + * XXX: Add a TUNABLE and possible per-device sysctl for this? + */ + +struct intrs_and_queues { + uint16_t intr_type; /* MSI, or MSI-X */ + uint16_t nirq; /* Total # of vectors */ + uint16_t intr_flags_10g;/* Interrupt flags for each 10G port */ + uint16_t intr_flags_1g; /* Interrupt flags for each 1G port */ + uint16_t ntxq10g; /* # of NIC txq's for each 10G port */ + uint16_t nrxq10g; /* # of NIC rxq's for each 10G port */ + uint16_t ntxq1g; /* # of NIC txq's for each 1G port */ + uint16_t nrxq1g; /* # of NIC rxq's for each 1G port */ +}; + +struct { + uint16_t device; + char *desc; +} t4vf_pciids[] = { + {0x4800, "Chelsio T440-dbg VF"}, + {0x4801, "Chelsio T420-CR VF"}, + {0x4802, "Chelsio T422-CR VF"}, + {0x4803, "Chelsio T440-CR VF"}, + {0x4804, "Chelsio T420-BCH VF"}, + {0x4805, "Chelsio T440-BCH VF"}, + {0x4806, "Chelsio T440-CH VF"}, + {0x4807, "Chelsio T420-SO VF"}, + {0x4808, "Chelsio T420-CX VF"}, + {0x4809, "Chelsio T420-BT VF"}, + {0x480a, "Chelsio T404-BT VF"}, + {0x480e, "Chelsio T440-LP-CR VF"}, +}, t5vf_pciids[] = { + {0x5800, "Chelsio T580-dbg VF"}, + {0x5801, "Chelsio T520-CR VF"}, /* 2 x 10G */ + {0x5802, "Chelsio T522-CR VF"}, /* 2 x 10G, 2 X 1G */ + {0x5803, "Chelsio T540-CR VF"}, /* 4 x 10G */ + {0x5807, "Chelsio T520-SO VF"}, /* 2 x 10G, nomem */ + {0x5809, "Chelsio T520-BT VF"}, /* 2 x 10GBaseT */ + {0x580a, "Chelsio T504-BT VF"}, /* 4 x 1G */ + {0x580d, "Chelsio T580-CR VF"}, /* 2 x 40G */ + {0x580e, "Chelsio T540-LP-CR VF"}, /* 4 x 10G */ + {0x5810, "Chelsio T580-LP-CR VF"}, /* 2 x 40G */ + {0x5811, "Chelsio T520-LL-CR VF"}, /* 2 x 10G */ + {0x5812, "Chelsio T560-CR VF"}, /* 1 x 40G, 2 x 10G */ + {0x5814, "Chelsio T580-LP-SO-CR VF"}, /* 2 x 40G, nomem */ + {0x5815, "Chelsio T502-BT VF"}, /* 2 x 1G */ +#ifdef notyet + {0x5804, "Chelsio T520-BCH VF"}, + {0x5805, "Chelsio T540-BCH VF"}, + {0x5806, "Chelsio T540-CH VF"}, + {0x5808, "Chelsio T520-CX VF"}, + {0x580b, "Chelsio B520-SR VF"}, + {0x580c, "Chelsio B504-BT VF"}, + {0x580f, "Chelsio Amsterdam VF"}, + {0x5813, "Chelsio T580-CHR VF"}, +#endif +}; + +static d_ioctl_t t4vf_ioctl; + +static struct cdevsw t4vf_cdevsw = { + .d_version = D_VERSION, + .d_ioctl = t4vf_ioctl, + .d_name = "t4vf", +}; + +static int +t4vf_probe(device_t dev) +{ + uint16_t d; + size_t i; + + d = pci_get_device(dev); + for (i = 0; i < nitems(t4vf_pciids); i++) { + if (d == t4vf_pciids[i].device) { + device_set_desc(dev, t4vf_pciids[i].desc); + return (BUS_PROBE_DEFAULT); + } + } + return (ENXIO); +} + +static int +t5vf_probe(device_t dev) +{ + uint16_t d; + size_t i; + + d = pci_get_device(dev); + for (i = 0; i < nitems(t5vf_pciids); i++) { + if (d == t5vf_pciids[i].device) { + device_set_desc(dev, t5vf_pciids[i].desc); + return (BUS_PROBE_DEFAULT); + } + } + return (ENXIO); +} + +#define FW_PARAM_DEV(param) \ + (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \ + V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param)) +#define FW_PARAM_PFVF(param) \ + (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \ + V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param)) + +static int +get_params__pre_init(struct adapter *sc) +{ + int rc; + uint32_t param[3], val[3]; + + param[0] = FW_PARAM_DEV(FWREV); + param[1] = FW_PARAM_DEV(TPREV); + param[2] = FW_PARAM_DEV(CCLK); + rc = -t4vf_query_params(sc, nitems(param), param, val); + if (rc != 0) { + device_printf(sc->dev, + "failed to query parameters (pre_init): %d.\n", rc); + return (rc); + } + + sc->params.fw_vers = val[0]; + sc->params.tp_vers = val[1]; + sc->params.vpd.cclk = val[2]; + + snprintf(sc->fw_version, sizeof(sc->fw_version), "%u.%u.%u.%u", + G_FW_HDR_FW_VER_MAJOR(sc->params.fw_vers), + G_FW_HDR_FW_VER_MINOR(sc->params.fw_vers), + G_FW_HDR_FW_VER_MICRO(sc->params.fw_vers), + G_FW_HDR_FW_VER_BUILD(sc->params.fw_vers)); + + snprintf(sc->tp_version, sizeof(sc->tp_version), "%u.%u.%u.%u", + G_FW_HDR_FW_VER_MAJOR(sc->params.tp_vers), + G_FW_HDR_FW_VER_MINOR(sc->params.tp_vers), + G_FW_HDR_FW_VER_MICRO(sc->params.tp_vers), + G_FW_HDR_FW_VER_BUILD(sc->params.tp_vers)); + + return (0); +} + +static int +get_params__post_init(struct adapter *sc) +{ + int rc; + + rc = -t4vf_get_sge_params(sc); + if (rc != 0) { + device_printf(sc->dev, + "unable to retrieve adapter SGE parameters: %d\n", rc); + return (rc); + } + + rc = -t4vf_get_rss_glb_config(sc); + if (rc != 0) { + device_printf(sc->dev, + "unable to retrieve adapter RSS parameters: %d\n", rc); + return (rc); + } + if (sc->params.rss.mode != FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL) { + device_printf(sc->dev, + "unable to operate with global RSS mode %d\n", + sc->params.rss.mode); + return (EINVAL); + } + + rc = t4_read_chip_settings(sc); + if (rc != 0) + return (rc); + + /* + * Grab our Virtual Interface resource allocation, extract the + * features that we're interested in and do a bit of sanity testing on + * what we discover. + */ + rc = -t4vf_get_vfres(sc); + if (rc != 0) { + device_printf(sc->dev, + "unable to get virtual interface resources: %d\n", rc); + return (rc); + } + + /* + * Check for various parameter sanity issues. + */ + if (sc->params.vfres.pmask == 0) { + device_printf(sc->dev, "no port access configured/usable!\n"); + return (EINVAL); + } + if (sc->params.vfres.nvi == 0) { + device_printf(sc->dev, + "no virtual interfaces configured/usable!\n"); + return (EINVAL); + } + sc->params.portvec = sc->params.vfres.pmask; + + return (0); +} + +static int +set_params__post_init(struct adapter *sc) +{ + uint32_t param, val; + + /* ask for encapsulated CPLs */ + param = FW_PARAM_PFVF(CPLFW4MSG_ENCAP); + val = 1; + (void)t4vf_set_params(sc, 1, ¶m, &val); + + return (0); +} + +#undef FW_PARAM_PFVF +#undef FW_PARAM_DEV + +static int +cfg_itype_and_nqueues(struct adapter *sc, int n10g, int n1g, + struct intrs_and_queues *iaq) +{ + struct vf_resources *vfres; + int nrxq10g, nrxq1g, nrxq; + int ntxq10g, ntxq1g, ntxq; + int itype, iq_avail, navail, rc; + + /* + * Figure out the layout of queues across our VIs and ensure + * we can allocate enough interrupts for our layout. + */ + vfres = &sc->params.vfres; + bzero(iaq, sizeof(*iaq)); + + for (itype = INTR_MSIX; itype != 0; itype >>= 1) { + if (itype == INTR_INTX) + continue; + + if (itype == INTR_MSIX) + navail = pci_msix_count(sc->dev); + else + navail = pci_msi_count(sc->dev); + + if (navail == 0) + continue; + + iaq->intr_type = itype; + iaq->intr_flags_10g = 0; + iaq->intr_flags_1g = 0; + + /* + * XXX: The Linux driver reserves an Ingress Queue for + * forwarded interrupts when using MSI (but not MSI-X). + * It seems it just always asks for 2 interrupts and + * forwards all rxqs to the forwarded interrupt. + * + * We must reserve one IRQ for the for the firmware + * event queue. + * + * Every rxq requires an ingress queue with a free + * list and interrupts and an egress queue. Every txq + * requires an ETH egress queue. + */ + iaq->nirq = T4VF_EXTRA_INTR; + + /* + * First, determine how many queues we can allocate. + * Start by finding the upper bound on rxqs from the + * limit on ingress queues. + */ + iq_avail = vfres->niqflint - iaq->nirq; + if (iq_avail < n10g + n1g) { + device_printf(sc->dev, + "Not enough ingress queues (%d) for %d ports\n", + vfres->niqflint, n10g + n1g); + return (ENXIO); + } + + /* + * Try to honor the cap on interrupts. If there aren't + * enough interrupts for at least one interrupt per + * port, then don't bother, we will just forward all + * interrupts to one interrupt in that case. + */ + if (iaq->nirq + n10g + n1g <= navail) { + if (iq_avail > navail - iaq->nirq) + iq_avail = navail - iaq->nirq; + } + + nrxq10g = t4_nrxq10g; + nrxq1g = t4_nrxq1g; + nrxq = n10g * nrxq10g + n1g * nrxq1g; + if (nrxq > iq_avail && nrxq1g > 1) { + /* Too many ingress queues. Try just 1 for 1G. */ + nrxq1g = 1; + nrxq = n10g * nrxq10g + n1g * nrxq1g; + } + if (nrxq > iq_avail) { + /* + * Still too many ingress queues. Use what we + * can for each 10G port. + */ + nrxq10g = (iq_avail - n1g) / n10g; + nrxq = n10g * nrxq10g + n1g * nrxq1g; + } + KASSERT(nrxq <= iq_avail, ("too many ingress queues")); + + /* + * Next, determine the upper bound on txqs from the limit + * on ETH queues. + */ + if (vfres->nethctrl < n10g + n1g) { + device_printf(sc->dev, + "Not enough ETH queues (%d) for %d ports\n", + vfres->nethctrl, n10g + n1g); + return (ENXIO); + } + + ntxq10g = t4_ntxq10g; + ntxq1g = t4_ntxq1g; + ntxq = n10g * ntxq10g + n1g * ntxq1g; + if (ntxq > vfres->nethctrl) { + /* Too many ETH queues. Try just 1 for 1G. */ + ntxq1g = 1; + ntxq = n10g * ntxq10g + n1g * ntxq1g; + } + if (ntxq > vfres->nethctrl) { + /* + * Still too many ETH queues. Use what we + * can for each 10G port. + */ + ntxq10g = (vfres->nethctrl - n1g) / n10g; + ntxq = n10g * ntxq10g + n1g * ntxq1g; + } + KASSERT(ntxq <= vfres->nethctrl, ("too many ETH queues")); + + /* + * Finally, ensure we have enough egress queues. + */ + if (vfres->neq < (n10g + n1g) * 2) { + device_printf(sc->dev, + "Not enough egress queues (%d) for %d ports\n", + vfres->neq, n10g + n1g); + return (ENXIO); + } + if (nrxq + ntxq > vfres->neq) { + /* Just punt and use 1 for everything. */ + nrxq1g = ntxq1g = nrxq10g = ntxq10g = 1; + nrxq = n10g * nrxq10g + n1g * nrxq1g; + ntxq = n10g * ntxq10g + n1g * ntxq1g; + } + KASSERT(nrxq <= iq_avail, ("too many ingress queues")); + KASSERT(ntxq <= vfres->nethctrl, ("too many ETH queues")); + KASSERT(nrxq + ntxq <= vfres->neq, ("too many egress queues")); + + /* + * Do we have enough interrupts? For MSI the interrupts + * have to be a power of 2 as well. + */ + iaq->nirq += nrxq; + iaq->ntxq10g = ntxq10g; + iaq->ntxq1g = ntxq1g; + iaq->nrxq10g = nrxq10g; + iaq->nrxq1g = nrxq1g; + if (iaq->nirq <= navail && + (itype != INTR_MSI || powerof2(iaq->nirq))) { + navail = iaq->nirq; + if (itype == INTR_MSIX) + rc = pci_alloc_msix(sc->dev, &navail); + else + rc = pci_alloc_msi(sc->dev, &navail); + if (rc != 0) { + device_printf(sc->dev, + "failed to allocate vectors:%d, type=%d, req=%d, rcvd=%d\n", + itype, rc, iaq->nirq, navail); + return (rc); + } + if (navail == iaq->nirq) { + iaq->intr_flags_10g = INTR_RXQ; + iaq->intr_flags_1g = INTR_RXQ; + return (0); + } + pci_release_msi(sc->dev); + } + + /* Fall back to a single interrupt. */ + iaq->nirq = 1; + navail = iaq->nirq; + if (itype == INTR_MSIX) + rc = pci_alloc_msix(sc->dev, &navail); + else + rc = pci_alloc_msi(sc->dev, &navail); + if (rc != 0) + device_printf(sc->dev, + "failed to allocate vectors:%d, type=%d, req=%d, rcvd=%d\n", + itype, rc, iaq->nirq, navail); + iaq->intr_flags_10g = 0; + iaq->intr_flags_1g = 0; + return (rc); + } + + device_printf(sc->dev, + "failed to find a usable interrupt type. " + "allowed=%d, msi-x=%d, msi=%d, intx=1", t4_intr_types, + pci_msix_count(sc->dev), pci_msi_count(sc->dev)); + + return (ENXIO); +} + +static int +t4vf_attach(device_t dev) +{ + struct adapter *sc; + int rc = 0, i, j, n10g, n1g, rqidx, tqidx; + struct make_dev_args mda; + struct intrs_and_queues iaq; + struct sge *s; + + sc = device_get_softc(dev); + sc->dev = dev; + pci_enable_busmaster(dev); + pci_set_max_read_req(dev, 4096); + sc->params.pci.mps = pci_get_max_payload(dev); + + sc->flags |= IS_VF; + + sc->sge_gts_reg = VF_SGE_REG(A_SGE_VF_GTS); + sc->sge_kdoorbell_reg = VF_SGE_REG(A_SGE_VF_KDOORBELL); + snprintf(sc->lockname, sizeof(sc->lockname), "%s", + device_get_nameunit(dev)); + mtx_init(&sc->sc_lock, sc->lockname, 0, MTX_DEF); + t4_add_adapter(sc); + + mtx_init(&sc->sfl_lock, "starving freelists", 0, MTX_DEF); + TAILQ_INIT(&sc->sfl); + callout_init_mtx(&sc->sfl_callout, &sc->sfl_lock, 0); + + mtx_init(&sc->reg_lock, "indirect register access", 0, MTX_DEF); + + rc = t4_map_bars_0_and_4(sc); + if (rc != 0) + goto done; /* error message displayed already */ + + rc = -t4vf_prep_adapter(sc); + if (rc != 0) + goto done; + + /* + * Leave the 'pf' and 'mbox' values as zero. This ensures + * that various firmware messages do not set the fields which + * is the correct thing to do for a VF. + */ + + memset(sc->chan_map, 0xff, sizeof(sc->chan_map)); + + make_dev_args_init(&mda); + mda.mda_devsw = &t4vf_cdevsw; + mda.mda_uid = UID_ROOT; + mda.mda_gid = GID_WHEEL; + mda.mda_mode = 0600; + mda.mda_si_drv1 = sc; + rc = make_dev_s(&mda, &sc->cdev, "%s", device_get_nameunit(dev)); + if (rc != 0) + device_printf(dev, "failed to create nexus char device: %d.\n", + rc); + +#if defined(__i386__) + if ((cpu_feature & CPUID_CX8) == 0) { + device_printf(dev, "64 bit atomics not available.\n"); + rc = ENOTSUP; + goto done; + } +#endif + + /* + * Some environments do not properly handle PCIE FLRs -- e.g. in Linux + * 2.6.31 and later we can't call pci_reset_function() in order to + * issue an FLR because of a self- deadlock on the device semaphore. + * Meanwhile, the OS infrastructure doesn't issue FLRs in all the + * cases where they're needed -- for instance, some versions of KVM + * fail to reset "Assigned Devices" when the VM reboots. Therefore we + * use the firmware based reset in order to reset any per function + * state. + */ + rc = -t4vf_fw_reset(sc); + if (rc != 0) { + device_printf(dev, "FW reset failed: %d\n", rc); + goto done; + } + sc->flags |= FW_OK; + + /* + * Grab basic operational parameters. These will predominantly have + * been set up by the Physical Function Driver or will be hard coded + * into the adapter. We just have to live with them ... Note that + * we _must_ get our VPD parameters before our SGE parameters because + * we need to know the adapter's core clock from the VPD in order to + * properly decode the SGE Timer Values. + */ + rc = get_params__pre_init(sc); + if (rc != 0) + goto done; /* error message displayed already */ + rc = get_params__post_init(sc); + if (rc != 0) + goto done; /* error message displayed already */ + + rc = set_params__post_init(sc); + if (rc != 0) + goto done; /* error message displayed already */ + + rc = t4_map_bar_2(sc); + if (rc != 0) + goto done; /* error message displayed already */ + + rc = t4_create_dma_tag(sc); + if (rc != 0) + goto done; /* error message displayed already */ + + /* + * The number of "ports" which we support is equal to the number of + * Virtual Interfaces with which we've been provisioned. + */ + sc->params.nports = imin(sc->params.vfres.nvi, MAX_NPORTS); + + /* + * We may have been provisioned with more VIs than the number of + * ports we're allowed to access (our Port Access Rights Mask). + * Just use a single VI for each port. + */ + sc->params.nports = imin(sc->params.nports, + bitcount32(sc->params.vfres.pmask)); + +#ifdef notyet + /* + * XXX: The Linux VF driver will lower nports if it thinks there + * are too few resources in vfres (niqflint, nethctrl, neq). + */ +#endif + + /* + * First pass over all the ports - allocate VIs and initialize some + * basic parameters like mac address, port type, etc. We also figure + * out whether a port is 10G or 1G and use that information when + * calculating how many interrupts to attempt to allocate. + */ + n10g = n1g = 0; + for_each_port(sc, i) { + struct port_info *pi; + + pi = malloc(sizeof(*pi), M_CXGBE, M_ZERO | M_WAITOK); + sc->port[i] = pi; + + /* These must be set before t4_port_init */ + pi->adapter = sc; + pi->port_id = i; + pi->nvi = 1; + pi->vi = malloc(sizeof(struct vi_info) * pi->nvi, M_CXGBE, + M_ZERO | M_WAITOK); + + /* + * Allocate the "main" VI and initialize parameters + * like mac addr. + */ + rc = -t4_port_init(sc, sc->mbox, sc->pf, 0, i); + if (rc != 0) { + device_printf(dev, "unable to initialize port %d: %d\n", + i, rc); + free(pi->vi, M_CXGBE); + free(pi, M_CXGBE); + sc->port[i] = NULL; + goto done; + } + + /* No t4_link_start. */ + + snprintf(pi->lockname, sizeof(pi->lockname), "%sp%d", + device_get_nameunit(dev), i); + mtx_init(&pi->pi_lock, pi->lockname, 0, MTX_DEF); + sc->chan_map[pi->tx_chan] = i; + + pi->tc = malloc(sizeof(struct tx_sched_class) * + sc->chip_params->nsched_cls, M_CXGBE, M_ZERO | M_WAITOK); + + if (is_10G_port(pi) || is_40G_port(pi)) { + n10g++; + } else { + n1g++; + } + + pi->linkdnrc = -1; + + pi->dev = device_add_child(dev, is_t4(sc) ? "cxgbev" : "cxlv", + -1); + if (pi->dev == NULL) { + device_printf(dev, + "failed to add device for port %d.\n", i); + rc = ENXIO; + goto done; + } + pi->vi[0].dev = pi->dev; + device_set_softc(pi->dev, pi); + } + + /* + * Interrupt type, # of interrupts, # of rx/tx queues, etc. + */ + rc = cfg_itype_and_nqueues(sc, n10g, n1g, &iaq); + if (rc != 0) + goto done; /* error message displayed already */ + + sc->intr_type = iaq.intr_type; + sc->intr_count = iaq.nirq; + + s = &sc->sge; + s->nrxq = n10g * iaq.nrxq10g + n1g * iaq.nrxq1g; + s->ntxq = n10g * iaq.ntxq10g + n1g * iaq.ntxq1g; + s->neq = s->ntxq + s->nrxq; /* the free list in an rxq is an eq */ + s->neq += sc->params.nports + 1;/* ctrl queues: 1 per port + 1 mgmt */ + s->niq = s->nrxq + 1; /* 1 extra for firmware event queue */ + + s->rxq = malloc(s->nrxq * sizeof(struct sge_rxq), M_CXGBE, + M_ZERO | M_WAITOK); + s->txq = malloc(s->ntxq * sizeof(struct sge_txq), M_CXGBE, + M_ZERO | M_WAITOK); + s->iqmap = malloc(s->niq * sizeof(struct sge_iq *), M_CXGBE, + M_ZERO | M_WAITOK); + s->eqmap = malloc(s->neq * sizeof(struct sge_eq *), M_CXGBE, + M_ZERO | M_WAITOK); + + sc->irq = malloc(sc->intr_count * sizeof(struct irq), M_CXGBE, + M_ZERO | M_WAITOK); + + /* + * Second pass over the ports. This time we know the number of rx and + * tx queues that each port should get. + */ + rqidx = tqidx = 0; + for_each_port(sc, i) { + struct port_info *pi = sc->port[i]; + struct vi_info *vi; + + if (pi == NULL) + continue; + + for_each_vi(pi, j, vi) { + vi->pi = pi; + vi->qsize_rxq = t4_qsize_rxq; + vi->qsize_txq = t4_qsize_txq; + + vi->first_rxq = rqidx; + vi->first_txq = tqidx; + if (is_10G_port(pi) || is_40G_port(pi)) { + vi->tmr_idx = t4_tmr_idx_10g; + vi->pktc_idx = t4_pktc_idx_10g; + vi->flags |= iaq.intr_flags_10g & INTR_RXQ; + vi->nrxq = j == 0 ? iaq.nrxq10g : 1; + vi->ntxq = j == 0 ? iaq.ntxq10g : 1; + } else { + vi->tmr_idx = t4_tmr_idx_1g; + vi->pktc_idx = t4_pktc_idx_1g; + vi->flags |= iaq.intr_flags_1g & INTR_RXQ; + vi->nrxq = j == 0 ? iaq.nrxq1g : 1; + vi->ntxq = j == 0 ? iaq.ntxq1g : 1; + } + rqidx += vi->nrxq; + tqidx += vi->ntxq; + + vi->rsrv_noflowq = 0; + } + } + + rc = t4_setup_intr_handlers(sc); + if (rc != 0) { + device_printf(dev, + "failed to setup interrupt handlers: %d\n", rc); + goto done; + } + + rc = bus_generic_attach(dev); + if (rc != 0) { + device_printf(dev, + "failed to attach all child ports: %d\n", rc); + goto done; + } + + device_printf(dev, + "%d ports, %d %s interrupt%s, %d eq, %d iq\n", + sc->params.nports, sc->intr_count, sc->intr_type == INTR_MSIX ? + "MSI-X" : "MSI", sc->intr_count > 1 ? "s" : "", sc->sge.neq, + sc->sge.niq); + +done: + if (rc != 0) + t4_detach_common(dev); + else + t4_sysctls(sc); + + return (rc); +} + +static void +get_regs(struct adapter *sc, struct t4_regdump *regs, uint8_t *buf) +{ + + /* 0x3f is used as the revision for VFs. */ + regs->version = chip_id(sc) | (0x3f << 10); + t4_get_regs(sc, buf, regs->len); +} + +static void +t4_clr_vi_stats(struct adapter *sc) +{ + int reg; + + for (reg = A_MPS_VF_STAT_TX_VF_BCAST_BYTES_L; + reg <= A_MPS_VF_STAT_RX_VF_ERR_FRAMES_H; reg += 4) + t4_write_reg(sc, VF_MPS_REG(reg), 0); +} + +static int +t4vf_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data, int fflag, + struct thread *td) +{ + int rc; + struct adapter *sc = dev->si_drv1; + + rc = priv_check(td, PRIV_DRIVER); + if (rc != 0) + return (rc); + + switch (cmd) { + case CHELSIO_T4_GETREG: { + struct t4_reg *edata = (struct t4_reg *)data; + + if ((edata->addr & 0x3) != 0 || edata->addr >= sc->mmio_len) + return (EFAULT); + + if (edata->size == 4) + edata->val = t4_read_reg(sc, edata->addr); + else if (edata->size == 8) + edata->val = t4_read_reg64(sc, edata->addr); + else + return (EINVAL); + + break; + } + case CHELSIO_T4_SETREG: { + struct t4_reg *edata = (struct t4_reg *)data; + + if ((edata->addr & 0x3) != 0 || edata->addr >= sc->mmio_len) + return (EFAULT); + + if (edata->size == 4) { + if (edata->val & 0xffffffff00000000) + return (EINVAL); + t4_write_reg(sc, edata->addr, (uint32_t) edata->val); + } else if (edata->size == 8) + t4_write_reg64(sc, edata->addr, edata->val); + else + return (EINVAL); + break; + } + case CHELSIO_T4_REGDUMP: { + struct t4_regdump *regs = (struct t4_regdump *)data; + int reglen = t4_get_regs_len(sc); + uint8_t *buf; + + if (regs->len < reglen) { + regs->len = reglen; /* hint to the caller */ + return (ENOBUFS); + } + + regs->len = reglen; + buf = malloc(reglen, M_CXGBE, M_WAITOK | M_ZERO); + get_regs(sc, regs, buf); + rc = copyout(buf, regs->data, reglen); + free(buf, M_CXGBE); + break; + } + case CHELSIO_T4_CLEAR_STATS: { + int i, v; + u_int port_id = *(uint32_t *)data; + struct port_info *pi; + struct vi_info *vi; + + if (port_id >= sc->params.nports) + return (EINVAL); + pi = sc->port[port_id]; + + /* MAC stats */ + pi->tx_parse_error = 0; + t4_clr_vi_stats(sc); + + /* + * Since this command accepts a port, clear stats for + * all VIs on this port. + */ + for_each_vi(pi, v, vi) { + if (vi->flags & VI_INIT_DONE) { + struct sge_rxq *rxq; + struct sge_txq *txq; + + for_each_rxq(vi, i, rxq) { +#if defined(INET) || defined(INET6) + rxq->lro.lro_queued = 0; + rxq->lro.lro_flushed = 0; +#endif + rxq->rxcsum = 0; + rxq->vlan_extraction = 0; + } + + for_each_txq(vi, i, txq) { + txq->txcsum = 0; + txq->tso_wrs = 0; + txq->vlan_insertion = 0; + txq->imm_wrs = 0; + txq->sgl_wrs = 0; + txq->txpkt_wrs = 0; + txq->txpkts0_wrs = 0; + txq->txpkts1_wrs = 0; + txq->txpkts0_pkts = 0; + txq->txpkts1_pkts = 0; + mp_ring_reset_stats(txq->r); + } + } + } + break; + } + case CHELSIO_T4_SCHED_CLASS: + rc = t4_set_sched_class(sc, (struct t4_sched_params *)data); + break; + case CHELSIO_T4_SCHED_QUEUE: + rc = t4_set_sched_queue(sc, (struct t4_sched_queue *)data); + break; + default: + rc = ENOTTY; + } + + return (rc); +} + +static device_method_t t4vf_methods[] = { + DEVMETHOD(device_probe, t4vf_probe), + DEVMETHOD(device_attach, t4vf_attach), + DEVMETHOD(device_detach, t4_detach_common), + + DEVMETHOD_END +}; + +static driver_t t4vf_driver = { + "t4vf", + t4vf_methods, + sizeof(struct adapter) +}; + +static device_method_t t5vf_methods[] = { + DEVMETHOD(device_probe, t5vf_probe), + DEVMETHOD(device_attach, t4vf_attach), + DEVMETHOD(device_detach, t4_detach_common), + + DEVMETHOD_END +}; + +static driver_t t5vf_driver = { + "t5vf", + t5vf_methods, + sizeof(struct adapter) +}; + +static driver_t cxgbev_driver = { + "cxgbev", + cxgbe_methods, + sizeof(struct port_info) +}; + +static driver_t cxlv_driver = { + "cxlv", + cxgbe_methods, + sizeof(struct port_info) +}; + +static devclass_t t4vf_devclass, t5vf_devclass; +static devclass_t cxgbev_devclass, cxlv_devclass; + +DRIVER_MODULE(t4vf, pci, t4vf_driver, t4vf_devclass, 0, 0); +MODULE_VERSION(t4vf, 1); +MODULE_DEPEND(t4vf, t4nex, 1, 1, 1); + +DRIVER_MODULE(t5vf, pci, t5vf_driver, t5vf_devclass, 0, 0); +MODULE_VERSION(t5vf, 1); +MODULE_DEPEND(t5vf, t5nex, 1, 1, 1); + +DRIVER_MODULE(cxgbev, t4vf, cxgbev_driver, cxgbev_devclass, 0, 0); +MODULE_VERSION(cxgbev, 1); + +DRIVER_MODULE(cxlv, t5vf, cxlv_driver, cxlv_devclass, 0, 0); +MODULE_VERSION(cxlv, 1); diff --git a/sys/modules/cxgbe/Makefile b/sys/modules/cxgbe/Makefile index 23a823fb19e..57409db4f07 100644 --- a/sys/modules/cxgbe/Makefile +++ b/sys/modules/cxgbe/Makefile @@ -7,6 +7,8 @@ SYSDIR?=${.CURDIR}/../.. SUBDIR= if_cxgbe SUBDIR+= if_cxl +SUBDIR+= if_cxgbev +SUBDIR+= if_cxlv SUBDIR+= t4_firmware SUBDIR+= t5_firmware SUBDIR+= ${_tom} diff --git a/sys/modules/cxgbe/if_cxgbev/Makefile b/sys/modules/cxgbe/if_cxgbev/Makefile new file mode 100644 index 00000000000..9c72a7aad40 --- /dev/null +++ b/sys/modules/cxgbe/if_cxgbev/Makefile @@ -0,0 +1,21 @@ +# +# $FreeBSD$ +# + +CXGBE= ${.CURDIR}/../../../dev/cxgbe +.PATH: ${CXGBE} ${CXGBE}/common + +KMOD= if_cxgbev +SRCS= bus_if.h +SRCS+= device_if.h +SRCS+= opt_inet.h +SRCS+= opt_inet6.h +SRCS+= opt_ofed.h +SRCS+= opt_rss.h +SRCS+= pci_if.h pci_iov_if.h +SRCS+= t4_vf.c +SRCS+= t4vf_hw.c + +CFLAGS+= -I${CXGBE} + +.include diff --git a/sys/modules/cxgbe/if_cxlv/Makefile b/sys/modules/cxgbe/if_cxlv/Makefile new file mode 100644 index 00000000000..943ea58bc2a --- /dev/null +++ b/sys/modules/cxgbe/if_cxlv/Makefile @@ -0,0 +1,11 @@ +# +# $FreeBSD$ +# + +CXGBE= ${.CURDIR}/../../../dev/cxgbe +.PATH: ${CXGBE} + +KMOD= if_cxlv +SRCS= if_cxlv.c + +.include diff --git a/sys/powerpc/conf/NOTES b/sys/powerpc/conf/NOTES index fbceea7cb2c..553dee5a6da 100644 --- a/sys/powerpc/conf/NOTES +++ b/sys/powerpc/conf/NOTES @@ -77,6 +77,7 @@ device adm1030 # Apple G4 MDD fan controller nodevice bktr nodevice cxgbe # XXX: builds on powerpc64 only. +nodevice cxgbev nodevice fdc nodevice ppc nodevice splash From 03d951aef363eebea2225fbdc70cc03fb577b0d7 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Wed, 7 Sep 2016 20:00:22 +0000 Subject: [PATCH 068/109] 7278 tuning zfs_arc_max does not impact arc_c_min When changing zfs_arc_max (e.g. as zdb does), it may be set to less than the default arc_c_min. arc_c_min should decrease to not be more than arc_c_max, but it doesn't; therefore tuning of arc_c_max is ineffective. Reviewed by: Dan Kimmel Reviewed by: Paul Dagnelie Reviewed by: Prakash Surya Reviewed by: Igor Kozhukhov Author: Matthew Ahrens openzfs/openzfs@608764beadaf4bb71c5d8fe1818e8392ac66a61b --- uts/common/fs/zfs/arc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/uts/common/fs/zfs/arc.c b/uts/common/fs/zfs/arc.c index db935415bf1..ef8482bacf8 100644 --- a/uts/common/fs/zfs/arc.c +++ b/uts/common/fs/zfs/arc.c @@ -5618,8 +5618,10 @@ arc_init(void) * Allow the tunables to override our calculations if they are * reasonable (ie. over 64MB) */ - if (zfs_arc_max > 64 << 20 && zfs_arc_max < allmem) + if (zfs_arc_max > 64 << 20 && zfs_arc_max < allmem) { arc_c_max = zfs_arc_max; + arc_c_min = MIN(arc_c_min, arc_c_max); + } if (zfs_arc_min > 64 << 20 && zfs_arc_min <= arc_c_max) arc_c_min = zfs_arc_min; From ccb5d7b8e8363d5f4b84f8e393d6fe9af64c50cc Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Wed, 7 Sep 2016 20:07:39 +0000 Subject: [PATCH 069/109] 7259 DS_FIELD_LARGE_BLOCKS is unused The DS_FIELD_LARGE_BLOCKS macro has been unused since the integration of this patch: commit ca0cc3918a1789fa839194af2a9245f801a06b1a Author: Matthew Ahrens Date: Fri Jul 24 09:53:55 2015 -0700 5959 clean up per-dataset feature count code Reviewed by: Toomas Soome Reviewed by: George Wilson Reviewed by: Alex Reece Approved by: Richard Lowe This patch simply removes this macro from dsl_dataset.h. Reviewed by: Dan Kimmel Reviewed by: Prakash Surya Reviewed by: Dan McDonald Reviewed by: Igor Kozhukhov Author: Matthew Ahrens --- uts/common/fs/zfs/sys/dsl_dataset.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/uts/common/fs/zfs/sys/dsl_dataset.h b/uts/common/fs/zfs/sys/dsl_dataset.h index f8c53c41964..54c63b92368 100644 --- a/uts/common/fs/zfs/sys/dsl_dataset.h +++ b/uts/common/fs/zfs/sys/dsl_dataset.h @@ -85,13 +85,6 @@ struct dsl_pool; */ #define DS_FIELD_BOOKMARK_NAMES "com.delphix:bookmarks" -/* - * This field is present (with value=0) if this dataset may contain large - * blocks (>128KB). If it is present, then this dataset - * is counted in the refcount of the SPA_FEATURE_LARGE_BLOCKS feature. - */ -#define DS_FIELD_LARGE_BLOCKS "org.open-zfs:large_blocks" - /* * These fields are set on datasets that are in the middle of a resumable * receive, and allow the sender to resume the send if it is interrupted. From fd593533020e7f10c506f4cbece09540e74f9412 Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Wed, 7 Sep 2016 23:35:38 +0000 Subject: [PATCH 070/109] =?UTF-8?q?Suffix=20short=20month=20names=20with?= =?UTF-8?q?=20"=EC=9B=94"=20and=20replace=20%b=20with=20%=5Fm=20for=20date?= =?UTF-8?q?=20formats.=20This=20change=20is=20analogous=20to=20r199179,=20?= =?UTF-8?q?r199271,=20and=20r289041=20for=20japanese=20and=20chinese=20loc?= =?UTF-8?q?ales.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- share/timedef/ko_KR.UTF-8.src | 26 +++++++++++++------------- share/timedef/ko_KR.eucKR.src | 26 +++++++++++++------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/share/timedef/ko_KR.UTF-8.src b/share/timedef/ko_KR.UTF-8.src index 98e512a7761..84f17a6acf5 100644 --- a/share/timedef/ko_KR.UTF-8.src +++ b/share/timedef/ko_KR.UTF-8.src @@ -4,18 +4,18 @@ # ----------------------------------------------------------------------------- # # Short month names - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 + 1ì›” + 2ì›” + 3ì›” + 4ì›” + 5ì›” + 6ì›” + 7ì›” + 8ì›” + 9ì›” +10ì›” +11ì›” +12ì›” # # Long month names (as in a date) 1ì›” @@ -53,7 +53,7 @@ %H시 %Më¶„ %Sì´ˆ # # x_fmt -%Yë…„ %bì›” %eì¼ +%Yë…„ %_mì›” %eì¼ # # c_fmt %x %A %X diff --git a/share/timedef/ko_KR.eucKR.src b/share/timedef/ko_KR.eucKR.src index b85195371a9..920f710d225 100644 --- a/share/timedef/ko_KR.eucKR.src +++ b/share/timedef/ko_KR.eucKR.src @@ -4,18 +4,18 @@ # ----------------------------------------------------------------------------- # # Short month names - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -10 -11 -12 + 1¿ù + 2¿ù + 3¿ù + 4¿ù + 5¿ù + 6¿ù + 7¿ù + 8¿ù + 9¿ù +10¿ù +11¿ù +12¿ù # # Long month names (as in a date) 1¿ù @@ -53,7 +53,7 @@ %H½Ã %MºÐ %SÃÊ # # x_fmt -%Y³â %b¿ù %eÀÏ +%Y³â %_m¿ù %eÀÏ # # c_fmt %x %A %X From 00f3ae2678a3d98d3e6080d35ba1e425af05b4d3 Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Wed, 7 Sep 2016 23:37:10 +0000 Subject: [PATCH 071/109] Fix an obvious typo. --- tools/tools/locale/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/tools/locale/Makefile b/tools/tools/locale/Makefile index 55434bb2970..0776b601af6 100644 --- a/tools/tools/locale/Makefile +++ b/tools/tools/locale/Makefile @@ -178,4 +178,4 @@ POSIX: .endif clean-POSIX: - rm -f {CLDRDIR}/posix/* + rm -f ${CLDRDIR}/posix/* From ef136816313fc0b751b146bba237ce86560485b2 Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Thu, 8 Sep 2016 00:38:50 +0000 Subject: [PATCH 072/109] Remove a pointless translation of struct ioc_toc_header. struct ioc_toc_header will be the same size (and thus IOREADTOCHEADER will have the same value on all supported platforms). Sponsored by: DARPA, AFRL --- sys/compat/freebsd32/freebsd32_ioctl.c | 24 ------------------------ sys/compat/freebsd32/freebsd32_ioctl.h | 7 ------- 2 files changed, 31 deletions(-) diff --git a/sys/compat/freebsd32/freebsd32_ioctl.c b/sys/compat/freebsd32/freebsd32_ioctl.c index b634b30960b..05d7e73fe0b 100644 --- a/sys/compat/freebsd32/freebsd32_ioctl.c +++ b/sys/compat/freebsd32/freebsd32_ioctl.c @@ -58,7 +58,6 @@ __FBSDID("$FreeBSD$"); /* Cannot get exact size in 64-bit due to alignment issue of entire struct. */ CTASSERT((sizeof(struct md_ioctl32)+4) == 436); CTASSERT(sizeof(struct ioc_read_toc_entry32) == 8); -CTASSERT(sizeof(struct ioc_toc_header32) == 4); CTASSERT(sizeof(struct mem_range_op32) == 12); CTASSERT(sizeof(struct pci_conf_io32) == 36); CTASSERT(sizeof(struct pci_match_conf32) == 44); @@ -138,25 +137,6 @@ freebsd32_ioctl_md(struct thread *td, struct freebsd32_ioctl_args *uap, } -static int -freebsd32_ioctl_ioc_toc_header(struct thread *td, - struct freebsd32_ioctl_args *uap, struct file *fp) -{ - struct ioc_toc_header toch; - struct ioc_toc_header32 toch32; - int error; - - if ((error = copyin(uap->data, &toch32, sizeof(toch32)))) - return (error); - CP(toch32, toch, len); - CP(toch32, toch, starting_track); - CP(toch32, toch, ending_track); - error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&toch, - td->td_ucred, td); - return (error); -} - - static int freebsd32_ioctl_ioc_read_toc(struct thread *td, struct freebsd32_ioctl_args *uap, struct file *fp) @@ -441,10 +421,6 @@ freebsd32_ioctl(struct thread *td, struct freebsd32_ioctl_args *uap) error = freebsd32_ioctl_ioc_read_toc(td, uap, fp); break; - case CDIOREADTOCHEADER_32: - error = freebsd32_ioctl_ioc_toc_header(td, uap, fp); - break; - case FIODGNAME_32: error = freebsd32_ioctl_fiodgname(td, uap, fp); break; diff --git a/sys/compat/freebsd32/freebsd32_ioctl.h b/sys/compat/freebsd32/freebsd32_ioctl.h index 18cfc95c569..2b79f72ea23 100644 --- a/sys/compat/freebsd32/freebsd32_ioctl.h +++ b/sys/compat/freebsd32/freebsd32_ioctl.h @@ -36,12 +36,6 @@ typedef __uint32_t caddr_t32; -struct ioc_toc_header32 { - u_short len; - u_char starting_track; - u_char ending_track; -}; - struct ioc_read_toc_entry32 { u_char address_format; u_char starting_track; @@ -115,7 +109,6 @@ struct pci_conf_io32 { }; #define CDIOREADTOCENTRYS_32 _IOWR('c', 5, struct ioc_read_toc_entry32) -#define CDIOREADTOCHEADER_32 _IOR('c', 4, struct ioc_toc_header32) #define MDIOCATTACH_32 _IOC(IOC_INOUT, 'm', 0, sizeof(struct md_ioctl32) + 4) #define MDIOCDETACH_32 _IOC(IOC_INOUT, 'm', 1, sizeof(struct md_ioctl32) + 4) #define MDIOCQUERY_32 _IOC(IOC_INOUT, 'm', 2, sizeof(struct md_ioctl32) + 4) From cee4a056691e41b8143412681fa4b2c4f357a63d Mon Sep 17 00:00:00 2001 From: Kevin Lo Date: Thu, 8 Sep 2016 01:02:53 +0000 Subject: [PATCH 073/109] In m_devget(), if the data fits in a packet header mbuf, check the amount of data is less than or equal to MHLEN instead of MLEN when placing initial small packet header at end of mbuf. Reviewed by: glebius MFC after: 3 days --- sys/kern/uipc_mbuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index 84354f3454b..8c5ee7818e6 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -984,7 +984,7 @@ m_devget(char *buf, int totlen, int off, struct ifnet *ifp, len = MHLEN; /* Place initial small packet/header at end of mbuf */ - if (m && totlen + off + max_linkhdr <= MLEN) { + if (m && totlen + off + max_linkhdr <= MHLEN) { m->m_data += max_linkhdr; len -= max_linkhdr; } From 2b53c517676d09970200c9bf9130631d43ce71a1 Mon Sep 17 00:00:00 2001 From: Allan Jude Date: Thu, 8 Sep 2016 02:38:55 +0000 Subject: [PATCH 074/109] Fix typo in skein amd64 assembly Sponsored by: ScaleEngine Inc. --- sys/crypto/skein/amd64/skein_block_asm.s | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/crypto/skein/amd64/skein_block_asm.s b/sys/crypto/skein/amd64/skein_block_asm.s index b2d0a83acbe..84cb47005e4 100644 --- a/sys/crypto/skein/amd64/skein_block_asm.s +++ b/sys/crypto/skein/amd64/skein_block_asm.s @@ -6,6 +6,7 @@ # # This code is released to the public domain. #---------------------------------------------------------------- +# $FreeBSD$ # .text .altmacro @@ -869,7 +870,7 @@ _UNROLL_CNT = ROUNDS_512/8 .else _UNROLL_CNT = SKEIN_UNROLL_512 .if ((ROUNDS_512/8) % _UNROLL_CNT) - .err "Invalid SKEIN_UNROLL_512" + .error "Invalid SKEIN_UNROLL_512" .endif xorq %rdi,%rdi #rdi = round counter Skein_512_round_loop: From c8fca9324a9a799451b22ad7ad69d298b5c8b865 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Thu, 8 Sep 2016 05:27:43 +0000 Subject: [PATCH 075/109] hyperv/hn: Pull vmbus channel open up. While I'm here, pull up the channel callback related code too. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7805 --- sys/dev/hyperv/netvsc/hv_net_vsc.c | 254 +-------------- sys/dev/hyperv/netvsc/hv_net_vsc.h | 4 +- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 296 +++++++++++++++--- sys/dev/hyperv/netvsc/hv_rndis_filter.c | 4 +- sys/dev/hyperv/netvsc/hv_rndis_filter.h | 3 +- 5 files changed, 264 insertions(+), 297 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index 5163be58f51..94e4cdf5255 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -57,20 +57,11 @@ MALLOC_DEFINE(M_NETVSC, "netvsc", "Hyper-V netvsc driver"); /* * Forward declarations */ -static void hv_nv_on_channel_callback(struct vmbus_channel *chan, - void *xrxr); static int hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc); static int hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *, int); static int hv_nv_destroy_send_buffer(struct hn_softc *sc); static int hv_nv_destroy_rx_buffer(struct hn_softc *sc); static int hv_nv_connect_to_vsp(struct hn_softc *sc); -static void hv_nv_on_send_completion(struct hn_softc *sc, - struct vmbus_channel *, const struct vmbus_chanpkt_hdr *pkt); -static void hv_nv_on_receive_completion(struct vmbus_channel *chan, - uint64_t tid); -static void hv_nv_on_receive(struct hn_softc *sc, - struct hn_rx_ring *rxr, struct vmbus_channel *chan, - const struct vmbus_chanpkt_hdr *pkt); static void hn_nvs_sent_none(struct hn_send_ctx *sndc, struct hn_softc *, struct vmbus_channel *chan, const void *, int); @@ -581,54 +572,19 @@ hv_nv_disconnect_from_vsp(struct hn_softc *sc) hv_nv_destroy_send_buffer(sc); } -void -hv_nv_subchan_attach(struct vmbus_channel *chan, struct hn_rx_ring *rxr) -{ - KASSERT(rxr->hn_rx_idx == vmbus_chan_subidx(chan), - ("chan%u subidx %u, rxr%d mismatch", - vmbus_chan_id(chan), vmbus_chan_subidx(chan), rxr->hn_rx_idx)); - vmbus_chan_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE, - NETVSC_DEVICE_RING_BUFFER_SIZE, NULL, 0, - hv_nv_on_channel_callback, rxr); -} - /* * Net VSC on device add * * Callback when the device belonging to this driver is added */ int -hv_nv_on_device_add(struct hn_softc *sc, struct hn_rx_ring *rxr) +hv_nv_on_device_add(struct hn_softc *sc) { - struct vmbus_channel *chan = sc->hn_prichan; - int ret = 0; - - /* - * Open the channel - */ - KASSERT(rxr->hn_rx_idx == vmbus_chan_subidx(chan), - ("chan%u subidx %u, rxr%d mismatch", - vmbus_chan_id(chan), vmbus_chan_subidx(chan), rxr->hn_rx_idx)); - ret = vmbus_chan_open(chan, - NETVSC_DEVICE_RING_BUFFER_SIZE, NETVSC_DEVICE_RING_BUFFER_SIZE, - NULL, 0, hv_nv_on_channel_callback, rxr); - if (ret != 0) - goto cleanup; /* * Connect with the NetVsp */ - ret = hv_nv_connect_to_vsp(sc); - if (ret != 0) - goto close; - - return (0); - -close: - /* Now, we can close the channel safely */ - vmbus_chan_close(chan); -cleanup: - return (ret); + return (hv_nv_connect_to_vsp(sc)); } /* @@ -683,25 +639,6 @@ hn_chim_free(struct hn_softc *sc, uint32_t chim_idx) atomic_clear_long(&sc->hn_chim_bmap[idx], mask); } -/* - * Net VSC on send completion - */ -static void -hv_nv_on_send_completion(struct hn_softc *sc, struct vmbus_channel *chan, - const struct vmbus_chanpkt_hdr *pkt) -{ - struct hn_send_ctx *sndc; - - sndc = (struct hn_send_ctx *)(uintptr_t)pkt->cph_xactid; - sndc->hn_cb(sndc, sc, chan, VMBUS_CHANPKT_CONST_DATA(pkt), - VMBUS_CHANPKT_DATALEN(pkt)); - /* - * NOTE: - * 'sndc' CAN NOT be accessed anymore, since it can be freed by - * its callback. - */ -} - /* * Net VSC on send * Sends a packet on the specified Hyper-V device. @@ -729,190 +666,3 @@ hv_nv_on_send(struct vmbus_channel *chan, uint32_t rndis_mtype, return (ret); } - -/* - * Net VSC on receive - * - * In the FreeBSD Hyper-V virtual world, this function deals exclusively - * with virtual addresses. - */ -static void -hv_nv_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr, - struct vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkthdr) -{ - const struct vmbus_chanpkt_rxbuf *pkt; - const struct hn_nvs_hdr *nvs_hdr; - int count, i, hlen; - - if (__predict_false(VMBUS_CHANPKT_DATALEN(pkthdr) < sizeof(*nvs_hdr))) { - if_printf(rxr->hn_ifp, "invalid nvs RNDIS\n"); - return; - } - nvs_hdr = VMBUS_CHANPKT_CONST_DATA(pkthdr); - - /* Make sure that this is a RNDIS message. */ - if (__predict_false(nvs_hdr->nvs_type != HN_NVS_TYPE_RNDIS)) { - if_printf(rxr->hn_ifp, "nvs type %u, not RNDIS\n", - nvs_hdr->nvs_type); - return; - } - - hlen = VMBUS_CHANPKT_GETLEN(pkthdr->cph_hlen); - if (__predict_false(hlen < sizeof(*pkt))) { - if_printf(rxr->hn_ifp, "invalid rxbuf chanpkt\n"); - return; - } - pkt = (const struct vmbus_chanpkt_rxbuf *)pkthdr; - - if (__predict_false(pkt->cp_rxbuf_id != HN_NVS_RXBUF_SIG)) { - if_printf(rxr->hn_ifp, "invalid rxbuf_id 0x%08x\n", - pkt->cp_rxbuf_id); - return; - } - - count = pkt->cp_rxbuf_cnt; - if (__predict_false(hlen < - __offsetof(struct vmbus_chanpkt_rxbuf, cp_rxbuf[count]))) { - if_printf(rxr->hn_ifp, "invalid rxbuf_cnt %d\n", count); - return; - } - - /* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */ - for (i = 0; i < count; ++i) { - int ofs, len; - - ofs = pkt->cp_rxbuf[i].rb_ofs; - len = pkt->cp_rxbuf[i].rb_len; - if (__predict_false(ofs + len > NETVSC_RECEIVE_BUFFER_SIZE)) { - if_printf(rxr->hn_ifp, "%dth RNDIS msg overflow rxbuf, " - "ofs %d, len %d\n", i, ofs, len); - continue; - } - hv_rf_on_receive(sc, rxr, rxr->hn_rxbuf + ofs, len); - } - - /* - * Moved completion call back here so that all received - * messages (not just data messages) will trigger a response - * message back to the host. - */ - hv_nv_on_receive_completion(chan, pkt->cp_hdr.cph_xactid); -} - -/* - * Net VSC on receive completion - * - * Send a receive completion packet to RNDIS device (ie NetVsp) - */ -static void -hv_nv_on_receive_completion(struct vmbus_channel *chan, uint64_t tid) -{ - struct hn_nvs_rndis_ack ack; - int retries = 0; - int ret = 0; - - ack.nvs_type = HN_NVS_TYPE_RNDIS_ACK; - ack.nvs_status = HN_NVS_STATUS_OK; - -retry_send_cmplt: - /* Send the completion */ - ret = vmbus_chan_send(chan, VMBUS_CHANPKT_TYPE_COMP, - VMBUS_CHANPKT_FLAG_NONE, &ack, sizeof(ack), tid); - if (ret == 0) { - /* success */ - /* no-op */ - } else if (ret == EAGAIN) { - /* no more room... wait a bit and attempt to retry 3 times */ - retries++; - - if (retries < 4) { - DELAY(100); - goto retry_send_cmplt; - } - } -} - -static void -hn_proc_notify(struct hn_softc *sc, const struct vmbus_chanpkt_hdr *pkt) -{ - const struct hn_nvs_hdr *hdr; - - if (VMBUS_CHANPKT_DATALEN(pkt) < sizeof(*hdr)) { - if_printf(sc->hn_ifp, "invalid nvs notify\n"); - return; - } - hdr = VMBUS_CHANPKT_CONST_DATA(pkt); - - if (hdr->nvs_type == HN_NVS_TYPE_TXTBL_NOTE) { - /* Useless; ignore */ - return; - } - if_printf(sc->hn_ifp, "got notify, nvs type %u\n", hdr->nvs_type); -} - -/* - * Net VSC on channel callback - */ -static void -hv_nv_on_channel_callback(struct vmbus_channel *chan, void *xrxr) -{ - struct hn_rx_ring *rxr = xrxr; - struct hn_softc *sc = rxr->hn_ifp->if_softc; - void *buffer; - int bufferlen = NETVSC_PACKET_SIZE; - - buffer = rxr->hn_rdbuf; - do { - struct vmbus_chanpkt_hdr *pkt = buffer; - uint32_t bytes_rxed; - int ret; - - bytes_rxed = bufferlen; - ret = vmbus_chan_recv_pkt(chan, pkt, &bytes_rxed); - if (ret == 0) { - if (bytes_rxed > 0) { - switch (pkt->cph_type) { - case VMBUS_CHANPKT_TYPE_COMP: - hv_nv_on_send_completion(sc, chan, pkt); - break; - case VMBUS_CHANPKT_TYPE_RXBUF: - hv_nv_on_receive(sc, rxr, chan, pkt); - break; - case VMBUS_CHANPKT_TYPE_INBAND: - hn_proc_notify(sc, pkt); - break; - default: - if_printf(rxr->hn_ifp, - "unknown chan pkt %u\n", - pkt->cph_type); - break; - } - } - } else if (ret == ENOBUFS) { - /* Handle large packet */ - if (bufferlen > NETVSC_PACKET_SIZE) { - free(buffer, M_NETVSC); - buffer = NULL; - } - - /* alloc new buffer */ - buffer = malloc(bytes_rxed, M_NETVSC, M_NOWAIT); - if (buffer == NULL) { - if_printf(rxr->hn_ifp, - "hv_cb malloc buffer failed, len=%u\n", - bytes_rxed); - bufferlen = 0; - break; - } - bufferlen = bytes_rxed; - } else { - /* No more packets */ - break; - } - } while (1); - - if (bufferlen > NETVSC_PACKET_SIZE) - free(buffer, M_NETVSC); - - hv_rf_channel_rollup(rxr, rxr->hn_txr); -} diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h index 359fb73567f..7bf5d8dade9 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.h +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h @@ -268,12 +268,10 @@ extern int hv_promisc_mode; struct hn_send_ctx; void netvsc_linkstatus_callback(struct hn_softc *sc, uint32_t status); -int hv_nv_on_device_add(struct hn_softc *sc, struct hn_rx_ring *rxr); +int hv_nv_on_device_add(struct hn_softc *sc); int hv_nv_on_device_remove(struct hn_softc *sc); int hv_nv_on_send(struct vmbus_channel *chan, uint32_t rndis_mtype, struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt); -void hv_nv_subchan_attach(struct vmbus_channel *chan, - struct hn_rx_ring *rxr); #endif /* __HV_NET_VSC_H__ */ diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index b443c2e72bf..b0f25d21cb7 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -344,9 +344,18 @@ static int hn_encap(struct hn_tx_ring *, struct hn_txdesc *, struct mbuf **); static int hn_create_rx_data(struct hn_softc *sc, int); static void hn_destroy_rx_data(struct hn_softc *sc); static void hn_set_chim_size(struct hn_softc *, int); -static void hn_channel_attach(struct hn_softc *, struct vmbus_channel *); -static void hn_subchan_attach(struct hn_softc *, struct vmbus_channel *); -static void hn_subchan_setup(struct hn_softc *); +static int hn_chan_attach(struct hn_softc *, struct vmbus_channel *); +static int hn_attach_subchans(struct hn_softc *); +static void hn_chan_callback(struct vmbus_channel *chan, void *xrxr); + +static void hn_nvs_handle_notify(struct hn_softc *sc, + const struct vmbus_chanpkt_hdr *pkt); +static void hn_nvs_handle_comp(struct hn_softc *sc, struct vmbus_channel *chan, + const struct vmbus_chanpkt_hdr *pkt); +static void hn_nvs_handle_rxbuf(struct hn_softc *sc, struct hn_rx_ring *rxr, + struct vmbus_channel *chan, + const struct vmbus_chanpkt_hdr *pkthdr); +static void hn_nvs_ack_rxbuf(struct vmbus_channel *chan, uint64_t tid); static int hn_transmit(struct ifnet *, struct mbuf *); static void hn_xmit_qflush(struct ifnet *); @@ -512,7 +521,9 @@ netvsc_attach(device_t dev) /* * Associate the first TX/RX ring w/ the primary channel. */ - hn_channel_attach(sc, sc->hn_prichan); + error = hn_chan_attach(sc, sc->hn_prichan); + if (error) + goto failed; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = hn_ioctl; @@ -554,8 +565,7 @@ netvsc_attach(device_t dev) if (sc->hn_xact == NULL) goto failed; - error = hv_rf_on_device_add(sc, &device_info, &ring_cnt, - &sc->hn_rx_ring[0]); + error = hv_rf_on_device_add(sc, &device_info, &ring_cnt); if (error) goto failed; KASSERT(ring_cnt > 0 && ring_cnt <= sc->hn_rx_ring_inuse, @@ -572,8 +582,11 @@ netvsc_attach(device_t dev) device_printf(dev, "%d TX ring, %d RX ring\n", sc->hn_tx_ring_inuse, sc->hn_rx_ring_inuse); - if (sc->hn_rx_ring_inuse > 1) - hn_subchan_setup(sc); + if (sc->hn_rx_ring_inuse > 1) { + error = hn_attach_subchans(sc); + if (error) + goto failed; + } #if __FreeBSD_version >= 1100099 if (sc->hn_rx_ring_inuse > 1) { @@ -1566,9 +1579,12 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) /* Wait for subchannels to be destroyed */ vmbus_subchan_drain(sc->hn_prichan); + sc->hn_rx_ring[0].hn_rx_flags &= ~HN_RX_FLAG_ATTACHED; + sc->hn_tx_ring[0].hn_tx_flags &= ~HN_TX_FLAG_ATTACHED; + hn_chan_attach(sc, sc->hn_prichan); /* XXX check error */ + ring_cnt = sc->hn_rx_ring_inuse; - error = hv_rf_on_device_add(sc, &device_info, &ring_cnt, - &sc->hn_rx_ring[0]); + error = hv_rf_on_device_add(sc, &device_info, &ring_cnt); if (error) { NV_LOCK(sc); sc->temp_unusable = FALSE; @@ -1594,7 +1610,7 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) sc->hn_tx_ring[r].hn_tx_flags &= ~HN_TX_FLAG_ATTACHED; } - hn_subchan_setup(sc); + hn_attach_subchans(sc); /* XXX check error */ } if (sc->hn_tx_ring[0].hn_chim_size > sc->hn_chim_szmax) @@ -2948,14 +2964,18 @@ hn_xmit_txeof_taskfunc(void *xtxr, int pending __unused) mtx_unlock(&txr->hn_tx_lock); } -static void -hn_channel_attach(struct hn_softc *sc, struct vmbus_channel *chan) +static int +hn_chan_attach(struct hn_softc *sc, struct vmbus_channel *chan) { struct hn_rx_ring *rxr; - int idx; + struct hn_tx_ring *txr = NULL; + int idx, error; idx = vmbus_chan_subidx(chan); + /* + * Link this channel to RX/TX ring. + */ KASSERT(idx >= 0 && idx < sc->hn_rx_ring_inuse, ("invalid channel index %d, should > 0 && < %d", idx, sc->hn_rx_ring_inuse)); @@ -2965,60 +2985,260 @@ hn_channel_attach(struct hn_softc *sc, struct vmbus_channel *chan) rxr->hn_rx_flags |= HN_RX_FLAG_ATTACHED; if (bootverbose) { - if_printf(sc->hn_ifp, "link RX ring %d to channel%u\n", + if_printf(sc->hn_ifp, "link RX ring %d to chan%u\n", idx, vmbus_chan_id(chan)); } if (idx < sc->hn_tx_ring_inuse) { - struct hn_tx_ring *txr = &sc->hn_tx_ring[idx]; - + txr = &sc->hn_tx_ring[idx]; KASSERT((txr->hn_tx_flags & HN_TX_FLAG_ATTACHED) == 0, ("TX ring %d already attached", idx)); txr->hn_tx_flags |= HN_TX_FLAG_ATTACHED; txr->hn_chan = chan; if (bootverbose) { - if_printf(sc->hn_ifp, "link TX ring %d to channel%u\n", + if_printf(sc->hn_ifp, "link TX ring %d to chan%u\n", idx, vmbus_chan_id(chan)); } } - /* Bind channel to a proper CPU */ + /* Bind this channel to a proper CPU. */ vmbus_chan_cpu_set(chan, (sc->hn_cpu + idx) % mp_ncpus); + + /* Open this channel */ + error = vmbus_chan_open(chan, NETVSC_DEVICE_RING_BUFFER_SIZE, + NETVSC_DEVICE_RING_BUFFER_SIZE, NULL, 0, hn_chan_callback, rxr); + if (error) { + if_printf(sc->hn_ifp, "open chan%u failed: %d\n", + vmbus_chan_id(chan), error); + rxr->hn_rx_flags &= ~HN_RX_FLAG_ATTACHED; + if (txr != NULL) + txr->hn_tx_flags &= ~HN_TX_FLAG_ATTACHED; + } + return (error); } -static void -hn_subchan_attach(struct hn_softc *sc, struct vmbus_channel *chan) -{ - - KASSERT(!vmbus_chan_is_primary(chan), - ("subchannel callback on primary channel")); - hn_channel_attach(sc, chan); -} - -static void -hn_subchan_setup(struct hn_softc *sc) +static int +hn_attach_subchans(struct hn_softc *sc) { struct vmbus_channel **subchans; int subchan_cnt = sc->hn_rx_ring_inuse - 1; - int i; + int i, error = 0; /* Wait for sub-channels setup to complete. */ subchans = vmbus_subchan_get(sc->hn_prichan, subchan_cnt); /* Attach the sub-channels. */ for (i = 0; i < subchan_cnt; ++i) { - struct vmbus_channel *subchan = subchans[i]; - - /* NOTE: Calling order is critical. */ - hn_subchan_attach(sc, subchan); - hv_nv_subchan_attach(subchan, - &sc->hn_rx_ring[vmbus_chan_subidx(subchan)]); + error = hn_chan_attach(sc, subchans[i]); + if (error) + break; } /* Release the sub-channels */ vmbus_subchan_rel(subchans, subchan_cnt); - if_printf(sc->hn_ifp, "%d sub-channels setup done\n", subchan_cnt); + + if (error) { + if_printf(sc->hn_ifp, "sub-channels attach failed: %d\n", error); + } else { + if (bootverbose) { + if_printf(sc->hn_ifp, "%d sub-channels attached\n", + subchan_cnt); + } + } + return (error); +} + +static void +hn_nvs_handle_notify(struct hn_softc *sc, const struct vmbus_chanpkt_hdr *pkt) +{ + const struct hn_nvs_hdr *hdr; + + if (VMBUS_CHANPKT_DATALEN(pkt) < sizeof(*hdr)) { + if_printf(sc->hn_ifp, "invalid nvs notify\n"); + return; + } + hdr = VMBUS_CHANPKT_CONST_DATA(pkt); + + if (hdr->nvs_type == HN_NVS_TYPE_TXTBL_NOTE) { + /* Useless; ignore */ + return; + } + if_printf(sc->hn_ifp, "got notify, nvs type %u\n", hdr->nvs_type); +} + +static void +hn_nvs_handle_comp(struct hn_softc *sc, struct vmbus_channel *chan, + const struct vmbus_chanpkt_hdr *pkt) +{ + struct hn_send_ctx *sndc; + + sndc = (struct hn_send_ctx *)(uintptr_t)pkt->cph_xactid; + sndc->hn_cb(sndc, sc, chan, VMBUS_CHANPKT_CONST_DATA(pkt), + VMBUS_CHANPKT_DATALEN(pkt)); + /* + * NOTE: + * 'sndc' CAN NOT be accessed anymore, since it can be freed by + * its callback. + */ +} + +static void +hn_nvs_handle_rxbuf(struct hn_softc *sc, struct hn_rx_ring *rxr, + struct vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkthdr) +{ + const struct vmbus_chanpkt_rxbuf *pkt; + const struct hn_nvs_hdr *nvs_hdr; + int count, i, hlen; + + if (__predict_false(VMBUS_CHANPKT_DATALEN(pkthdr) < sizeof(*nvs_hdr))) { + if_printf(rxr->hn_ifp, "invalid nvs RNDIS\n"); + return; + } + nvs_hdr = VMBUS_CHANPKT_CONST_DATA(pkthdr); + + /* Make sure that this is a RNDIS message. */ + if (__predict_false(nvs_hdr->nvs_type != HN_NVS_TYPE_RNDIS)) { + if_printf(rxr->hn_ifp, "nvs type %u, not RNDIS\n", + nvs_hdr->nvs_type); + return; + } + + hlen = VMBUS_CHANPKT_GETLEN(pkthdr->cph_hlen); + if (__predict_false(hlen < sizeof(*pkt))) { + if_printf(rxr->hn_ifp, "invalid rxbuf chanpkt\n"); + return; + } + pkt = (const struct vmbus_chanpkt_rxbuf *)pkthdr; + + if (__predict_false(pkt->cp_rxbuf_id != HN_NVS_RXBUF_SIG)) { + if_printf(rxr->hn_ifp, "invalid rxbuf_id 0x%08x\n", + pkt->cp_rxbuf_id); + return; + } + + count = pkt->cp_rxbuf_cnt; + if (__predict_false(hlen < + __offsetof(struct vmbus_chanpkt_rxbuf, cp_rxbuf[count]))) { + if_printf(rxr->hn_ifp, "invalid rxbuf_cnt %d\n", count); + return; + } + + /* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */ + for (i = 0; i < count; ++i) { + int ofs, len; + + ofs = pkt->cp_rxbuf[i].rb_ofs; + len = pkt->cp_rxbuf[i].rb_len; + if (__predict_false(ofs + len > NETVSC_RECEIVE_BUFFER_SIZE)) { + if_printf(rxr->hn_ifp, "%dth RNDIS msg overflow rxbuf, " + "ofs %d, len %d\n", i, ofs, len); + continue; + } + hv_rf_on_receive(sc, rxr, rxr->hn_rxbuf + ofs, len); + } + + /* + * Moved completion call back here so that all received + * messages (not just data messages) will trigger a response + * message back to the host. + */ + hn_nvs_ack_rxbuf(chan, pkt->cp_hdr.cph_xactid); +} + +/* + * Net VSC on receive completion + * + * Send a receive completion packet to RNDIS device (ie NetVsp) + */ +static void +hn_nvs_ack_rxbuf(struct vmbus_channel *chan, uint64_t tid) +{ + struct hn_nvs_rndis_ack ack; + int retries = 0; + int ret = 0; + + ack.nvs_type = HN_NVS_TYPE_RNDIS_ACK; + ack.nvs_status = HN_NVS_STATUS_OK; + +retry_send_cmplt: + /* Send the completion */ + ret = vmbus_chan_send(chan, VMBUS_CHANPKT_TYPE_COMP, + VMBUS_CHANPKT_FLAG_NONE, &ack, sizeof(ack), tid); + if (ret == 0) { + /* success */ + /* no-op */ + } else if (ret == EAGAIN) { + /* no more room... wait a bit and attempt to retry 3 times */ + retries++; + + if (retries < 4) { + DELAY(100); + goto retry_send_cmplt; + } + } +} + +static void +hn_chan_callback(struct vmbus_channel *chan, void *xrxr) +{ + struct hn_rx_ring *rxr = xrxr; + struct hn_softc *sc = rxr->hn_ifp->if_softc; + void *buffer; + int bufferlen = NETVSC_PACKET_SIZE; + + buffer = rxr->hn_rdbuf; + do { + struct vmbus_chanpkt_hdr *pkt = buffer; + uint32_t bytes_rxed; + int ret; + + bytes_rxed = bufferlen; + ret = vmbus_chan_recv_pkt(chan, pkt, &bytes_rxed); + if (ret == 0) { + switch (pkt->cph_type) { + case VMBUS_CHANPKT_TYPE_COMP: + hn_nvs_handle_comp(sc, chan, pkt); + break; + case VMBUS_CHANPKT_TYPE_RXBUF: + hn_nvs_handle_rxbuf(sc, rxr, chan, pkt); + break; + case VMBUS_CHANPKT_TYPE_INBAND: + hn_nvs_handle_notify(sc, pkt); + break; + default: + if_printf(rxr->hn_ifp, + "unknown chan pkt %u\n", + pkt->cph_type); + break; + } + } else if (ret == ENOBUFS) { + /* Handle large packet */ + if (bufferlen > NETVSC_PACKET_SIZE) { + free(buffer, M_NETVSC); + buffer = NULL; + } + + /* alloc new buffer */ + buffer = malloc(bytes_rxed, M_NETVSC, M_NOWAIT); + if (buffer == NULL) { + if_printf(rxr->hn_ifp, + "hv_cb malloc buffer failed, len=%u\n", + bytes_rxed); + bufferlen = 0; + break; + } + bufferlen = bytes_rxed; + } else { + /* No more packets */ + break; + } + } while (1); + + if (bufferlen > NETVSC_PACKET_SIZE) + free(buffer, M_NETVSC); + + hv_rf_channel_rollup(rxr, rxr->hn_txr); } static void diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.c b/sys/dev/hyperv/netvsc/hv_rndis_filter.c index 2cbf5bc8273..56df29ca9d6 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.c +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.c @@ -1012,7 +1012,7 @@ hv_rf_halt_device(struct hn_softc *sc) */ int hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, - int *nchan0, struct hn_rx_ring *rxr) + int *nchan0) { int ret; netvsc_device_info *dev_info = (netvsc_device_info *)additl_info; @@ -1031,7 +1031,7 @@ hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, * (hv_rf_on_receive()) before this call is completed. * Note: Earlier code used a function pointer here. */ - ret = hv_nv_on_device_add(sc, rxr); + ret = hv_nv_on_device_add(sc); if (ret != 0) return (ret); diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.h b/sys/dev/hyperv/netvsc/hv_rndis_filter.h index ad29e8b0f7a..31ba9b1dac0 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.h +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.h @@ -43,8 +43,7 @@ struct hn_rx_ring; void hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr, const void *data, int dlen); void hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr); -int hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, int *nchan, - struct hn_rx_ring *rxr); +int hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, int *nchan); int hv_rf_on_device_remove(struct hn_softc *sc); int hv_rf_on_open(struct hn_softc *sc); int hv_rf_on_close(struct hn_softc *sc); From f7a9af2829c0c11e8ffcdf5af6509ea078d03e50 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Thu, 8 Sep 2016 06:06:54 +0000 Subject: [PATCH 076/109] hyperv/hn: Push RXBUF size adjustment down. It is not used in other places. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7806 --- sys/dev/hyperv/netvsc/hv_net_vsc.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index 94e4cdf5255..57ca6a82d6a 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -58,7 +58,7 @@ MALLOC_DEFINE(M_NETVSC, "netvsc", "Hyper-V netvsc driver"); * Forward declarations */ static int hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc); -static int hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *, int); +static int hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *); static int hv_nv_destroy_send_buffer(struct hn_softc *sc); static int hv_nv_destroy_rx_buffer(struct hn_softc *sc); static int hv_nv_connect_to_vsp(struct hn_softc *sc); @@ -154,17 +154,22 @@ hn_nvs_req_send(struct hn_softc *sc, void *req, int reqlen) * Hyper-V extensible switch and the synthetic data path. */ static int -hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc, int rxbuf_size) +hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc) { struct vmbus_xact *xact = NULL; struct hn_nvs_rxbuf_conn *conn; const struct hn_nvs_rxbuf_connresp *resp; size_t resp_len; uint32_t status; - int error; + int error, rxbuf_size; - KASSERT(rxbuf_size <= NETVSC_RECEIVE_BUFFER_SIZE, - ("invalid rxbuf size %d", rxbuf_size)); + /* + * Limit RXBUF size for old NVS. + */ + if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_2) + rxbuf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY; + else + rxbuf_size = NETVSC_RECEIVE_BUFFER_SIZE; /* * Connect the RXBUF GPADL to the primary channel. @@ -496,7 +501,6 @@ hv_nv_connect_to_vsp(struct hn_softc *sc) device_t dev = sc->hn_dev; struct ifnet *ifp = sc->hn_ifp; struct hn_nvs_ndis_init ndis; - int rxbuf_size; /* * Negotiate the NVSP version. Try the latest NVSP first. @@ -548,13 +552,7 @@ hv_nv_connect_to_vsp(struct hn_softc *sc) goto cleanup; } - /* Post the big receive buffer to NetVSP */ - if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_2) - rxbuf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY; - else - rxbuf_size = NETVSC_RECEIVE_BUFFER_SIZE; - - ret = hv_nv_init_rx_buffer_with_net_vsp(sc, rxbuf_size); + ret = hv_nv_init_rx_buffer_with_net_vsp(sc); if (ret == 0) ret = hv_nv_init_send_buffer_with_net_vsp(sc); From 021deece8f5019ca831b75f6e47b43d021859035 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Thu, 8 Sep 2016 06:23:08 +0000 Subject: [PATCH 077/109] hyperv/hn: Factor out function to do NVS initialization. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7807 --- sys/dev/hyperv/netvsc/hv_net_vsc.c | 79 ++++++++++++++++-------------- sys/dev/hyperv/netvsc/hv_net_vsc.h | 7 --- sys/dev/hyperv/netvsc/if_hnreg.h | 8 +++ 3 files changed, 51 insertions(+), 43 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index 57ca6a82d6a..142741bc754 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -69,6 +69,13 @@ static void hn_nvs_sent_none(struct hn_send_ctx *sndc, struct hn_send_ctx hn_send_ctx_none = HN_SEND_CTX_INITIALIZER(hn_nvs_sent_none, NULL); +static const uint32_t hn_nvs_version[] = { + HN_NVS_VERSION_5, + HN_NVS_VERSION_4, + HN_NVS_VERSION_2, + HN_NVS_VERSION_1 +}; + uint32_t hn_chim_alloc(struct hn_softc *sc) { @@ -166,7 +173,7 @@ hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc) /* * Limit RXBUF size for old NVS. */ - if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_2) + if (sc->hn_nvs_ver <= HN_NVS_VERSION_2) rxbuf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY; else rxbuf_size = NETVSC_RECEIVE_BUFFER_SIZE; @@ -424,7 +431,7 @@ hv_nv_destroy_send_buffer(struct hn_softc *sc) } static int -hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, uint32_t nvs_ver) +hn_nvs_doinit(struct hn_softc *sc, uint32_t nvs_ver) { struct vmbus_xact *xact; struct hn_nvs_init *init; @@ -485,55 +492,55 @@ hv_nv_send_ndis_config(struct hn_softc *sc, uint32_t mtu) return (error); } +static int +hn_nvs_init(struct hn_softc *sc) +{ + int i; + + for (i = 0; i < nitems(hn_nvs_version); ++i) { + int error; + + error = hn_nvs_doinit(sc, hn_nvs_version[i]); + if (!error) { + sc->hn_nvs_ver = hn_nvs_version[i]; + + /* Set NDIS version according to NVS version. */ + sc->hn_ndis_ver = HN_NDIS_VERSION_6_30; + if (sc->hn_nvs_ver <= HN_NVS_VERSION_4) + sc->hn_ndis_ver = HN_NDIS_VERSION_6_1; + + if (bootverbose) { + if_printf(sc->hn_ifp, "NVS version 0x%x, " + "NDIS version %u.%u\n", sc->hn_nvs_ver, + HN_NDIS_VERSION_MAJOR(sc->hn_ndis_ver), + HN_NDIS_VERSION_MINOR(sc->hn_ndis_ver)); + } + return (0); + } + } + if_printf(sc->hn_ifp, "no NVS available\n"); + return (ENXIO); +} + /* * Net VSC connect to VSP */ static int hv_nv_connect_to_vsp(struct hn_softc *sc) { - uint32_t protocol_list[] = { NVSP_PROTOCOL_VERSION_1, - NVSP_PROTOCOL_VERSION_2, - NVSP_PROTOCOL_VERSION_4, - NVSP_PROTOCOL_VERSION_5 }; - int i; - int protocol_number = nitems(protocol_list); int ret = 0; - device_t dev = sc->hn_dev; struct ifnet *ifp = sc->hn_ifp; struct hn_nvs_ndis_init ndis; - /* - * Negotiate the NVSP version. Try the latest NVSP first. - */ - for (i = protocol_number - 1; i >= 0; i--) { - if (hv_nv_negotiate_nvsp_protocol(sc, protocol_list[i]) == 0) { - sc->hn_nvs_ver = protocol_list[i]; - sc->hn_ndis_ver = HN_NDIS_VERSION_6_30; - if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_4) - sc->hn_ndis_ver = HN_NDIS_VERSION_6_1; - if (bootverbose) { - if_printf(sc->hn_ifp, "NVS version 0x%x, " - "NDIS version %u.%u\n", - sc->hn_nvs_ver, - HN_NDIS_VERSION_MAJOR(sc->hn_ndis_ver), - HN_NDIS_VERSION_MINOR(sc->hn_ndis_ver)); - } - break; - } - } - - if (i < 0) { - if (bootverbose) - device_printf(dev, "failed to negotiate a valid " - "protocol.\n"); - return (EPROTO); - } + ret = hn_nvs_init(sc); + if (ret != 0) + return (ret); /* * Set the MTU if supported by this NVSP protocol version * This needs to be right after the NVSP init message per Haiyang */ - if (sc->hn_nvs_ver >= NVSP_PROTOCOL_VERSION_2) + if (sc->hn_nvs_ver >= HN_NVS_VERSION_2) ret = hv_nv_send_ndis_config(sc, ifp->if_mtu); /* diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h index 7bf5d8dade9..90627cd9872 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.h +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h @@ -68,13 +68,6 @@ MALLOC_DECLARE(M_NETVSC); -#define NVSP_INVALID_PROTOCOL_VERSION (0xFFFFFFFF) - -#define NVSP_PROTOCOL_VERSION_1 2 -#define NVSP_PROTOCOL_VERSION_2 0x30002 -#define NVSP_PROTOCOL_VERSION_4 0x40000 -#define NVSP_PROTOCOL_VERSION_5 0x50000 - /* * The following arguably belongs in a separate header file */ diff --git a/sys/dev/hyperv/netvsc/if_hnreg.h b/sys/dev/hyperv/netvsc/if_hnreg.h index 4d5441263a9..53f59ec61fa 100644 --- a/sys/dev/hyperv/netvsc/if_hnreg.h +++ b/sys/dev/hyperv/netvsc/if_hnreg.h @@ -40,6 +40,14 @@ #define HN_NDIS_VERSION_MAJOR(ver) (((ver) & 0xffff0000) >> 16) #define HN_NDIS_VERSION_MINOR(ver) ((ver) & 0xffff) +/* + * NVS versions. + */ +#define HN_NVS_VERSION_1 0x00002 +#define HN_NVS_VERSION_2 0x30002 +#define HN_NVS_VERSION_4 0x40000 +#define HN_NVS_VERSION_5 0x50000 + #define HN_NVS_RXBUF_SIG 0xcafe #define HN_NVS_CHIM_SIG 0xface From a74e025394de14ee8f3d1d7245ab1844d1e4404d Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Thu, 8 Sep 2016 06:42:30 +0000 Subject: [PATCH 078/109] hyperv/hn: Pass MTU around. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7808 --- sys/dev/hyperv/netvsc/hv_net_vsc.c | 11 +++++------ sys/dev/hyperv/netvsc/hv_net_vsc.h | 2 +- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c | 6 +++--- sys/dev/hyperv/netvsc/hv_rndis_filter.c | 4 ++-- sys/dev/hyperv/netvsc/hv_rndis_filter.h | 3 ++- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index 142741bc754..dd3a95b52d2 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -61,7 +61,7 @@ static int hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc); static int hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *); static int hv_nv_destroy_send_buffer(struct hn_softc *sc); static int hv_nv_destroy_rx_buffer(struct hn_softc *sc); -static int hv_nv_connect_to_vsp(struct hn_softc *sc); +static int hv_nv_connect_to_vsp(struct hn_softc *sc, int mtu); static void hn_nvs_sent_none(struct hn_send_ctx *sndc, struct hn_softc *, struct vmbus_channel *chan, const void *, int); @@ -526,10 +526,9 @@ hn_nvs_init(struct hn_softc *sc) * Net VSC connect to VSP */ static int -hv_nv_connect_to_vsp(struct hn_softc *sc) +hv_nv_connect_to_vsp(struct hn_softc *sc, int mtu) { int ret = 0; - struct ifnet *ifp = sc->hn_ifp; struct hn_nvs_ndis_init ndis; ret = hn_nvs_init(sc); @@ -541,7 +540,7 @@ hv_nv_connect_to_vsp(struct hn_softc *sc) * This needs to be right after the NVSP init message per Haiyang */ if (sc->hn_nvs_ver >= HN_NVS_VERSION_2) - ret = hv_nv_send_ndis_config(sc, ifp->if_mtu); + ret = hv_nv_send_ndis_config(sc, mtu); /* * Initialize NDIS. @@ -583,13 +582,13 @@ hv_nv_disconnect_from_vsp(struct hn_softc *sc) * Callback when the device belonging to this driver is added */ int -hv_nv_on_device_add(struct hn_softc *sc) +hv_nv_on_device_add(struct hn_softc *sc, int mtu) { /* * Connect with the NetVsp */ - return (hv_nv_connect_to_vsp(sc)); + return (hv_nv_connect_to_vsp(sc, mtu)); } /* diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h index 90627cd9872..077cd105257 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.h +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h @@ -261,7 +261,7 @@ extern int hv_promisc_mode; struct hn_send_ctx; void netvsc_linkstatus_callback(struct hn_softc *sc, uint32_t status); -int hv_nv_on_device_add(struct hn_softc *sc); +int hv_nv_on_device_add(struct hn_softc *sc, int mtu); int hv_nv_on_device_remove(struct hn_softc *sc); int hv_nv_on_send(struct vmbus_channel *chan, uint32_t rndis_mtype, struct hn_send_ctx *sndc, struct vmbus_gpa *gpa, int gpa_cnt); diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c index b0f25d21cb7..d2afa0fd337 100644 --- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -528,7 +528,6 @@ netvsc_attach(device_t dev) ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = hn_ioctl; ifp->if_init = hn_ifinit; - /* needed by hv_rf_on_device_add() code */ ifp->if_mtu = ETHERMTU; if (hn_use_if_start) { int qdepth = hn_get_txswq_depth(&sc->hn_tx_ring[0]); @@ -565,7 +564,7 @@ netvsc_attach(device_t dev) if (sc->hn_xact == NULL) goto failed; - error = hv_rf_on_device_add(sc, &device_info, &ring_cnt); + error = hv_rf_on_device_add(sc, &device_info, &ring_cnt, ETHERMTU); if (error) goto failed; KASSERT(ring_cnt > 0 && ring_cnt <= sc->hn_rx_ring_inuse, @@ -1584,7 +1583,8 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) hn_chan_attach(sc, sc->hn_prichan); /* XXX check error */ ring_cnt = sc->hn_rx_ring_inuse; - error = hv_rf_on_device_add(sc, &device_info, &ring_cnt); + error = hv_rf_on_device_add(sc, &device_info, &ring_cnt, + ifr->ifr_mtu); if (error) { NV_LOCK(sc); sc->temp_unusable = FALSE; diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.c b/sys/dev/hyperv/netvsc/hv_rndis_filter.c index 56df29ca9d6..1279e9f4cdb 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.c +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.c @@ -1012,7 +1012,7 @@ hv_rf_halt_device(struct hn_softc *sc) */ int hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, - int *nchan0) + int *nchan0, int mtu) { int ret; netvsc_device_info *dev_info = (netvsc_device_info *)additl_info; @@ -1031,7 +1031,7 @@ hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, * (hv_rf_on_receive()) before this call is completed. * Note: Earlier code used a function pointer here. */ - ret = hv_nv_on_device_add(sc); + ret = hv_nv_on_device_add(sc, mtu); if (ret != 0) return (ret); diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.h b/sys/dev/hyperv/netvsc/hv_rndis_filter.h index 31ba9b1dac0..18dd460d638 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.h +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.h @@ -43,7 +43,8 @@ struct hn_rx_ring; void hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr, const void *data, int dlen); void hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr); -int hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, int *nchan); +int hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, int *nchan, + int mtu); int hv_rf_on_device_remove(struct hn_softc *sc); int hv_rf_on_open(struct hn_softc *sc); int hv_rf_on_close(struct hn_softc *sc); From 74decee899ad014435a533f44ca96439311ab4a1 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Thu, 8 Sep 2016 07:16:56 +0000 Subject: [PATCH 079/109] hyperv/kvp: Fix IPv4/IPv6 address injection support. The GUID string provided by hypervisor has leading and trailing braces, while our GUID string does not have braces at all. Both braces should be ignored, when the GUID strings are compared. Submitted by: Hongjiang Zhang Modified by: sephe MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7809 --- sys/dev/hyperv/utilities/hv_kvp.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/sys/dev/hyperv/utilities/hv_kvp.c b/sys/dev/hyperv/utilities/hv_kvp.c index 222383a4432..9d1abb4c42b 100644 --- a/sys/dev/hyperv/utilities/hv_kvp.c +++ b/sys/dev/hyperv/utilities/hv_kvp.c @@ -332,20 +332,23 @@ hv_kvp_convert_utf16_ipinfo_to_utf8(struct hv_kvp_ip_msg *host_ip_msg, if (devclass_get_devices(devclass_find("hn"), &devs, &devcnt) == 0) { for (devcnt = devcnt - 1; devcnt >= 0; devcnt--) { - /* XXX access other driver's softc? are you kidding? */ device_t dev = devs[devcnt]; struct vmbus_channel *chan; char buf[HYPERV_GUID_STRLEN]; + int n; + + chan = vmbus_get_channel(dev); + n = hyperv_guid2str(vmbus_chan_guid_inst(chan), buf, + sizeof(buf)); /* - * Trying to find GUID of Network Device + * The string in the 'kvp_ip_val.adapter_id' has + * braces around the GUID; skip the leading brace + * in 'kvp_ip_val.adapter_id'. */ - chan = vmbus_get_channel(dev); - hyperv_guid2str(vmbus_chan_guid_inst(chan), - buf, sizeof(buf)); - - if (strncmp(buf, (char *)umsg->body.kvp_ip_val.adapter_id, - HYPERV_GUID_STRLEN - 1) == 0) { + if (strncmp(buf, + ((char *)&umsg->body.kvp_ip_val.adapter_id) + 1, + n) == 0) { strlcpy((char *)umsg->body.kvp_ip_val.adapter_id, device_get_nameunit(dev), MAX_ADAPTER_ID_SIZE); break; From 5152795ab971a1e2b20da2128912b50676c4d7d4 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Thu, 8 Sep 2016 07:34:31 +0000 Subject: [PATCH 080/109] hyperv/hn: Function renaming. While I'm here, remove obvious comment. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7810 --- sys/dev/hyperv/netvsc/hv_net_vsc.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index dd3a95b52d2..9cc077ab7e9 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -470,12 +470,10 @@ hn_nvs_doinit(struct hn_softc *sc, uint32_t nvs_ver) } /* - * Send NDIS version 2 config packet containing MTU. - * - * Not valid for NDIS version 1. + * Configure MTU and enable VLAN. */ static int -hv_nv_send_ndis_config(struct hn_softc *sc, uint32_t mtu) +hn_nvs_conf_ndis(struct hn_softc *sc, int mtu) { struct hn_nvs_ndis_conf conf; int error; @@ -522,25 +520,27 @@ hn_nvs_init(struct hn_softc *sc) return (ENXIO); } -/* - * Net VSC connect to VSP - */ static int hv_nv_connect_to_vsp(struct hn_softc *sc, int mtu) { int ret = 0; struct hn_nvs_ndis_init ndis; + /* + * Initialize NVS. + */ ret = hn_nvs_init(sc); if (ret != 0) return (ret); - /* - * Set the MTU if supported by this NVSP protocol version - * This needs to be right after the NVSP init message per Haiyang - */ - if (sc->hn_nvs_ver >= HN_NVS_VERSION_2) - ret = hv_nv_send_ndis_config(sc, mtu); + if (sc->hn_nvs_ver >= HN_NVS_VERSION_2) { + /* + * Configure NDIS before initializing it. + */ + ret = hn_nvs_conf_ndis(sc, mtu); + if (ret != 0) + return (ret); + } /* * Initialize NDIS. From b33720da593e26e7535edd303efc2f55c8b9f5b0 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Thu, 8 Sep 2016 07:45:20 +0000 Subject: [PATCH 081/109] hyperv/hn: Factor out NVS NDIS initialization MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7811 --- sys/dev/hyperv/netvsc/hv_net_vsc.c | 38 +++++++++++++++++------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index 9cc077ab7e9..b66fe418d68 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -490,6 +490,24 @@ hn_nvs_conf_ndis(struct hn_softc *sc, int mtu) return (error); } +static int +hn_nvs_init_ndis(struct hn_softc *sc) +{ + struct hn_nvs_ndis_init ndis; + int error; + + memset(&ndis, 0, sizeof(ndis)); + ndis.nvs_type = HN_NVS_TYPE_NDIS_INIT; + ndis.nvs_ndis_major = HN_NDIS_VERSION_MAJOR(sc->hn_ndis_ver); + ndis.nvs_ndis_minor = HN_NDIS_VERSION_MINOR(sc->hn_ndis_ver); + + /* NOTE: No response. */ + error = hn_nvs_req_send(sc, &ndis, sizeof(ndis)); + if (error) + if_printf(sc->hn_ifp, "send nvs ndis init failed: %d\n", error); + return (error); +} + static int hn_nvs_init(struct hn_softc *sc) { @@ -523,8 +541,7 @@ hn_nvs_init(struct hn_softc *sc) static int hv_nv_connect_to_vsp(struct hn_softc *sc, int mtu) { - int ret = 0; - struct hn_nvs_ndis_init ndis; + int ret; /* * Initialize NVS. @@ -545,24 +562,13 @@ hv_nv_connect_to_vsp(struct hn_softc *sc, int mtu) /* * Initialize NDIS. */ - - memset(&ndis, 0, sizeof(ndis)); - ndis.nvs_type = HN_NVS_TYPE_NDIS_INIT; - ndis.nvs_ndis_major = HN_NDIS_VERSION_MAJOR(sc->hn_ndis_ver); - ndis.nvs_ndis_minor = HN_NDIS_VERSION_MINOR(sc->hn_ndis_ver); - - /* NOTE: No response. */ - ret = hn_nvs_req_send(sc, &ndis, sizeof(ndis)); - if (ret != 0) { - if_printf(sc->hn_ifp, "send nvs ndis init failed: %d\n", ret); - goto cleanup; - } + ret = hn_nvs_init_ndis(sc); + if (ret != 0) + return (ret); ret = hv_nv_init_rx_buffer_with_net_vsp(sc); if (ret == 0) ret = hv_nv_init_send_buffer_with_net_vsp(sc); - -cleanup: return (ret); } From ff9eac2e6d7a306b16618020d6d9811a3728e1ad Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Thu, 8 Sep 2016 09:11:13 +0000 Subject: [PATCH 082/109] pxeboot: Add nfs.read_size tunable. Increase this tunable improves kernel loading speed. Submitted by: Jun Su Reviewed by: rpokala, wblock (previous version) Obtained from: DragonFlyBSD MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7756 --- lib/libstand/nfs.c | 33 ++++++++++++++++++++++++--------- sys/boot/i386/pxeldr/pxeboot.8 | 8 ++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/lib/libstand/nfs.c b/lib/libstand/nfs.c index 29f8ecf514b..19bc73c77a8 100644 --- a/lib/libstand/nfs.c +++ b/lib/libstand/nfs.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -50,7 +51,8 @@ __FBSDID("$FreeBSD$"); #define NFS_DEBUGxx -#define NFSREAD_SIZE 1024 +#define NFSREAD_MIN_SIZE 1024 +#define NFSREAD_MAX_SIZE 4096 /* Define our own NFS attributes without NQNFS stuff. */ #ifdef OLD_NFSV2 @@ -83,7 +85,7 @@ struct nfs_read_repl { n_long errno; struct nfsv2_fattrs fa; n_long count; - u_char data[NFSREAD_SIZE]; + u_char data[NFSREAD_MAX_SIZE]; }; #ifndef NFS_NOSYMLINK @@ -210,6 +212,8 @@ struct fs_ops nfs_fsops = { nfs_readdir }; +static int nfs_read_size = NFSREAD_MIN_SIZE; + #ifdef OLD_NFSV2 /* * Fetch the root file handle (call mount daemon) @@ -264,6 +268,17 @@ nfs_getrootfh(struct iodesc *d, char *path, u_char *fhp) if (repl->errno) return (ntohl(repl->errno)); bcopy(repl->fh, fhp, sizeof(repl->fh)); + + /* + * Improve boot performance over NFS + */ + if (getenv("nfs.read_size") != NULL) + nfs_read_size = strtol(getenv("nfs.read_size"), NULL, 0); + if (nfs_read_size < NFSREAD_MIN_SIZE) + nfs_read_size = NFSREAD_MIN_SIZE; + if (nfs_read_size > NFSREAD_MAX_SIZE) + nfs_read_size = NFSREAD_MAX_SIZE; + return (0); } @@ -401,11 +416,11 @@ nfs_readdata(struct nfs_iodesc *d, off_t off, void *addr, size_t len) bcopy(d->fh, args->fh, NFS_FHSIZE); args->off = htonl((n_long)off); - if (len > NFSREAD_SIZE) - len = NFSREAD_SIZE; + if (len > nfs_read_size) + len = nfs_read_size; args->len = htonl((n_long)len); args->xxx = htonl((n_long)0); - hlen = sizeof(*repl) - NFSREAD_SIZE; + hlen = offsetof(struct nfs_read_rpl, data[0]); cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READ, args, sizeof(*args), @@ -1025,7 +1040,7 @@ nfs_readdata(struct nfs_iodesc *d, off_t off, void *addr, size_t len) uint32_t count; uint32_t eof; uint32_t len; - u_char data[NFSREAD_SIZE]; + u_char data[NFSREAD_MAX_SIZE]; } *repl; struct { uint32_t h[RPC_HEADER_WORDS]; @@ -1048,10 +1063,10 @@ nfs_readdata(struct nfs_iodesc *d, off_t off, void *addr, size_t len) pos = roundup(d->fhsize, sizeof(uint32_t)) / sizeof(uint32_t); args->fhoffcnt[pos++] = 0; args->fhoffcnt[pos++] = htonl((uint32_t)off); - if (len > NFSREAD_SIZE) - len = NFSREAD_SIZE; + if (len > nfs_read_size) + len = nfs_read_size; args->fhoffcnt[pos] = htonl((uint32_t)len); - hlen = sizeof(*repl) - NFSREAD_SIZE; + hlen = offsetof(struct repl, data[0]); cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER3, NFSPROCV3_READ, args, 4 * sizeof(uint32_t) + roundup(d->fhsize, sizeof(uint32_t)), diff --git a/sys/boot/i386/pxeldr/pxeboot.8 b/sys/boot/i386/pxeldr/pxeboot.8 index d2ca7038c50..7f57d5a087b 100644 --- a/sys/boot/i386/pxeldr/pxeboot.8 +++ b/sys/boot/i386/pxeldr/pxeboot.8 @@ -85,6 +85,14 @@ expects to fetch .Pa /boot/loader.rc from the specified server before loading any other files. .Pp +.Nm +defaults to a conservative 1024 byte NFS data packet size. +This may be changed by setting the +.Va nfs.read_size +variable in +.Pa /boot/loader.conf . +Valid values range from 1024 to 4096 bytes. +.Pp In all other respects, .Nm acts just like From 2b5b3a0923a09cf28fd3bfdee067cfe0fb96beb8 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Thu, 8 Sep 2016 10:10:05 +0000 Subject: [PATCH 083/109] Correctly map the USB mouse tilt delta values into buttons 5 and 6 instead of 3 and 4 which is used for the scroll wheel, according to X.org. PR: 170358 MFC after: 1 week --- sys/dev/usb/input/ums.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/dev/usb/input/ums.c b/sys/dev/usb/input/ums.c index 4c85e6e638d..a26db87cc8b 100644 --- a/sys/dev/usb/input/ums.c +++ b/sys/dev/usb/input/ums.c @@ -288,9 +288,9 @@ ums_intr_callback(struct usb_xfer *xfer, usb_error_t error) /* translate T-axis into button presses until further */ if (dt > 0) - buttons |= 1UL << 3; + buttons |= 1UL << 5; else if (dt < 0) - buttons |= 1UL << 4; + buttons |= 1UL << 6; sc->sc_status.button = buttons; sc->sc_status.dx += dx; From d4a08767bafe578fcb258c30efda972a0001e4b0 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Thu, 8 Sep 2016 12:00:02 +0000 Subject: [PATCH 084/109] Decode ATA Status Return descriptor. MFC after: 2 weeks --- sys/cam/scsi/scsi_all.c | 48 +++++++++++++++++++++++++++++++++++++++++ sys/cam/scsi/scsi_all.h | 4 ++++ 2 files changed, 52 insertions(+) diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c index 6559217ec66..28c5c038d6b 100644 --- a/sys/cam/scsi/scsi_all.c +++ b/sys/cam/scsi/scsi_all.c @@ -4652,6 +4652,53 @@ scsi_sense_progress_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, scsi_progress_sbuf(sb, progress_val); } +void +scsi_sense_ata_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, + u_int sense_len, uint8_t *cdb, int cdb_len, + struct scsi_inquiry_data *inq_data, + struct scsi_sense_desc_header *header) +{ + struct scsi_sense_ata_ret_desc *res; + + res = (struct scsi_sense_ata_ret_desc *)header; + + sbuf_printf(sb, "ATA status: %02x (%s%s%s%s%s%s%s%s), ", + res->status, + (res->status & 0x80) ? "BSY " : "", + (res->status & 0x40) ? "DRDY " : "", + (res->status & 0x20) ? "DF " : "", + (res->status & 0x10) ? "SERV " : "", + (res->status & 0x08) ? "DRQ " : "", + (res->status & 0x04) ? "CORR " : "", + (res->status & 0x02) ? "IDX " : "", + (res->status & 0x01) ? "ERR" : ""); + if (res->status & 1) { + sbuf_printf(sb, "error: %02x (%s%s%s%s%s%s%s%s), ", + res->error, + (res->error & 0x80) ? "ICRC " : "", + (res->error & 0x40) ? "UNC " : "", + (res->error & 0x20) ? "MC " : "", + (res->error & 0x10) ? "IDNF " : "", + (res->error & 0x08) ? "MCR " : "", + (res->error & 0x04) ? "ABRT " : "", + (res->error & 0x02) ? "NM " : "", + (res->error & 0x01) ? "ILI" : ""); + } + + if (res->flags & SSD_DESC_ATA_FLAG_EXTEND) { + sbuf_printf(sb, "count: %02x%02x, ", + res->count_15_8, res->count_7_0); + sbuf_printf(sb, "LBA: %02x%02x%02x%02x%02x%02x, ", + res->lba_47_40, res->lba_39_32, res->lba_31_24, + res->lba_23_16, res->lba_15_8, res->lba_7_0); + } else { + sbuf_printf(sb, "count: %02x, ", res->count_7_0); + sbuf_printf(sb, "LBA: %02x%02x%02x, ", + res->lba_23_16, res->lba_15_8, res->lba_7_0); + } + sbuf_printf(sb, "device: %02x, ", res->device); +} + /* * Generic sense descriptor printing routine. This is used when we have * not yet implemented a specific printing routine for this descriptor. @@ -4698,6 +4745,7 @@ struct scsi_sense_desc_printer { {SSD_DESC_FRU, scsi_sense_fru_sbuf}, {SSD_DESC_STREAM, scsi_sense_stream_sbuf}, {SSD_DESC_BLOCK, scsi_sense_block_sbuf}, + {SSD_DESC_ATA, scsi_sense_ata_sbuf}, {SSD_DESC_PROGRESS, scsi_sense_progress_sbuf} }; diff --git a/sys/cam/scsi/scsi_all.h b/sys/cam/scsi/scsi_all.h index 1fd45405560..a23554b6c35 100644 --- a/sys/cam/scsi/scsi_all.h +++ b/sys/cam/scsi/scsi_all.h @@ -3682,6 +3682,10 @@ void scsi_sense_progress_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, u_int sense_len, uint8_t *cdb, int cdb_len, struct scsi_inquiry_data *inq_data, struct scsi_sense_desc_header *header); +void scsi_sense_ata_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, + u_int sense_len, uint8_t *cdb, int cdb_len, + struct scsi_inquiry_data *inq_data, + struct scsi_sense_desc_header *header); void scsi_sense_generic_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, u_int sense_len, uint8_t *cdb, int cdb_len, struct scsi_inquiry_data *inq_data, From df4265774e5ffc29e37a95952eb269e9fe3abead Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 8 Sep 2016 12:01:28 +0000 Subject: [PATCH 085/109] Partially lift suspension when ffs_reload() finished with cgs and going to re-read inodes. Secondary write initiators, e.g. ufs_inactive(), might need to start a write while owning the vnode lock. Since the suspended state established by /dev/ufssuspend prevents them from entering vn_start_secondary_write(), we get deadlock otherwise. Note that it is arguably not very useful to re-read inodes after /dev/ufssuspend suspension, because the suspension does not block readers, and other threads might read existing files in parallel with suspension owner (for now, only growfs(8)) operations. This effectively means that suspension owner cannot safely modify existing inodes, and then there is no sense in re-reading. But keep the code enabled for now. Reported and tested by: pho Reviewed by: mckusick Sponsored by: The FreeBSD Foundation MFC after: 2 weeks --- sys/ufs/ffs/ffs_extern.h | 3 +++ sys/ufs/ffs/ffs_suspend.c | 2 +- sys/ufs/ffs/ffs_vfsops.c | 16 ++++++++++++---- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h index 203bc6684d0..56f5cd8e3ef 100644 --- a/sys/ufs/ffs/ffs_extern.h +++ b/sys/ufs/ffs/ffs_extern.h @@ -106,6 +106,9 @@ void ffs_susp_uninitialize(void); #define FFSV_FORCEINSMQ 0x0001 +#define FFSR_FORCE 0x0001 +#define FFSR_UNSUSPEND 0x0002 + extern struct vop_vector ffs_vnodeops1; extern struct vop_vector ffs_fifoops1; extern struct vop_vector ffs_vnodeops2; diff --git a/sys/ufs/ffs/ffs_suspend.c b/sys/ufs/ffs/ffs_suspend.c index 450282ceb17..926dba3148e 100644 --- a/sys/ufs/ffs/ffs_suspend.c +++ b/sys/ufs/ffs/ffs_suspend.c @@ -235,7 +235,7 @@ ffs_susp_dtor(void *data) KASSERT((mp->mnt_kern_flag & MNTK_SUSPEND) != 0, ("MNTK_SUSPEND not set")); - error = ffs_reload(mp, curthread, 1); + error = ffs_reload(mp, curthread, FFSR_FORCE | FFSR_UNSUSPEND); if (error != 0) panic("failed to unsuspend writes on %s", fs->fs_fsmnt); diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index d644b73f4fb..b28b742934b 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -573,11 +573,13 @@ ffs_cmount(struct mntarg *ma, void *data, uint64_t flags) * 2) re-read superblock from disk. * 3) re-read summary information from disk. * 4) invalidate all inactive vnodes. - * 5) invalidate all cached file data. - * 6) re-read inode data for all active vnodes. + * 5) clear MNTK_SUSPEND2 and MNTK_SUSPENDED flags, allowing secondary + * writers, if requested. + * 6) invalidate all cached file data. + * 7) re-read inode data for all active vnodes. */ int -ffs_reload(struct mount *mp, struct thread *td, int force) +ffs_reload(struct mount *mp, struct thread *td, int flags) { struct vnode *vp, *mvp, *devvp; struct inode *ip; @@ -592,7 +594,7 @@ ffs_reload(struct mount *mp, struct thread *td, int force) ump = VFSTOUFS(mp); MNT_ILOCK(mp); - if ((mp->mnt_flag & MNT_RDONLY) == 0 && force == 0) { + if ((mp->mnt_flag & MNT_RDONLY) == 0 && (flags & FFSR_FORCE) == 0) { MNT_IUNLOCK(mp); return (EINVAL); } @@ -682,6 +684,12 @@ ffs_reload(struct mount *mp, struct thread *td, int force) size = fs->fs_ncg * sizeof(u_int8_t); fs->fs_contigdirs = (u_int8_t *)space; bzero(fs->fs_contigdirs, size); + if ((flags & FFSR_UNSUSPEND) != 0) { + MNT_ILOCK(mp); + mp->mnt_kern_flag &= ~(MNTK_SUSPENDED | MNTK_SUSPEND2); + wakeup(&mp->mnt_flag); + MNT_IUNLOCK(mp); + } loop: MNT_VNODE_FOREACH_ALL(vp, mp, mvp) { From ccb19123e540582f4ebcd39fa63daeb637be6467 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 8 Sep 2016 12:04:45 +0000 Subject: [PATCH 086/109] There is no need to upgrade the last dvp lock on lookups for modifying operations. Instead of upgrading, assert that the lock is exclusive. Explain the cause in comments. This effectively reverts r209367. Tested by: pho Reviewed by: mckusick Sponsored by: The FreeBSD Foundation MFC after: 2 weeks --- sys/ufs/ufs/ufs_lookup.c | 51 +++++++++++++++------------------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c index dcff4fbe3d7..a86f70d4226 100644 --- a/sys/ufs/ufs/ufs_lookup.c +++ b/sys/ufs/ufs/ufs_lookup.c @@ -76,32 +76,6 @@ SYSCTL_INT(_debug, OID_AUTO, dircheck, CTLFLAG_RW, &dirchk, 0, ""); /* true if old FS format...*/ #define OFSFMT(vp) ((vp)->v_mount->mnt_maxsymlinklen <= 0) -#ifdef QUOTA -static int -ufs_lookup_upgrade_lock(struct vnode *vp) -{ - int error; - - ASSERT_VOP_LOCKED(vp, __FUNCTION__); - if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE) - return (0); - - error = 0; - - /* - * Upgrade vnode lock, since getinoquota() - * requires exclusive lock to modify inode. - */ - vhold(vp); - vn_lock(vp, LK_UPGRADE | LK_RETRY); - VI_LOCK(vp); - if (vp->v_iflag & VI_DOOMED) - error = ENOENT; - vdropl(vp); - return (error); -} -#endif - static int ufs_delete_denied(struct vnode *vdp, struct vnode *tdp, struct ucred *cred, struct thread *td) @@ -259,12 +233,25 @@ ufs_lookup_ino(struct vnode *vdp, struct vnode **vpp, struct componentname *cnp, vnode_create_vobject(vdp, DIP(dp, i_size), cnp->cn_thread); bmask = VFSTOUFS(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1; -#ifdef QUOTA - if ((nameiop == DELETE || nameiop == RENAME) && (flags & ISLASTCN)) { - error = ufs_lookup_upgrade_lock(vdp); - if (error != 0) - return (error); - } + +#ifdef DEBUG_VFS_LOCKS + /* + * Assert that the directory vnode is locked, and locked + * exclusively for the last component lookup for modifying + * operations. + * + * The directory-modifying operations need to save + * intermediate state in the inode between namei() call and + * actual directory manipulations. See fields in the struct + * inode marked as 'used during directory lookup'. We must + * ensure that upgrade in namei() does not happen, since + * upgrade might need to unlock vdp. If quotas are enabled, + * getinoquota() also requires exclusive lock to modify inode. + */ + ASSERT_VOP_LOCKED(vdp, "ufs_lookup1"); + if ((nameiop == CREATE || nameiop == DELETE || nameiop == RENAME) && + (flags & (LOCKPARENT | ISLASTCN)) == (LOCKPARENT | ISLASTCN)) + ASSERT_VOP_ELOCKED(vdp, "ufs_lookup2"); #endif restart: From 60f1c000f30d01ea8311d1cfb184106eb1542ba5 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 8 Sep 2016 12:05:13 +0000 Subject: [PATCH 087/109] In softdep_prealloc(), return early not only for snapshots, but for the quota files as well. Reported and tested by: pho Reviewed by: mckusick Sponsored by: The FreeBSD Foundation MFC after: 2 weeks --- sys/ufs/ffs/ffs_softdep.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index d06f5dee434..122848dced7 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -2997,10 +2997,13 @@ softdep_prealloc(vp, waitok) ("softdep_prealloc called on non-softdep filesystem")); /* * Nothing to do if we are not running journaled soft updates. - * If we currently hold the snapshot lock, we must avoid handling - * other resources that could cause deadlock. + * If we currently hold the snapshot lock, we must avoid + * handling other resources that could cause deadlock. Do not + * touch quotas vnode since it is typically recursed with + * other vnode locks held. */ - if (DOINGSUJ(vp) == 0 || IS_SNAPSHOT(VTOI(vp))) + if (DOINGSUJ(vp) == 0 || IS_SNAPSHOT(VTOI(vp)) || + (vp->v_vflag & VV_SYSTEM) != 0) return (0); ump = VFSTOUFS(vp->v_mount); ACQUIRE_LOCK(ump); From e599d951e3e256b7de7c0e85e65c87e21b873d1e Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 8 Sep 2016 12:06:43 +0000 Subject: [PATCH 088/109] In dqsync(), when called from quotactl(), um_quotas entry might appear cleared since nothing prevents completion of the parallel quotaoff. There is nothing to sync in this case, and no reason to panic. Reported and tested by: pho Reviewed by: mckusick Sponsored by: The FreeBSD Foundation MFC after: 2 weeks --- sys/ufs/ufs/ufs_quota.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c index c236706f334..ccc496203ac 100644 --- a/sys/ufs/ufs/ufs_quota.c +++ b/sys/ufs/ufs/ufs_quota.c @@ -1538,8 +1538,13 @@ dqsync(struct vnode *vp, struct dquot *dq) if ((ump = dq->dq_ump) == NULL) return (0); UFS_LOCK(ump); - if ((dqvp = ump->um_quotas[dq->dq_type]) == NULLVP) - panic("dqsync: file"); + if ((dqvp = ump->um_quotas[dq->dq_type]) == NULLVP) { + if (vp == NULL) { + UFS_UNLOCK(ump); + return (0); + } else + panic("dqsync: file"); + } vref(dqvp); UFS_UNLOCK(ump); From 6cb0fae25efef3f01adcef0ecebc0d687e220f87 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Thu, 8 Sep 2016 12:07:25 +0000 Subject: [PATCH 089/109] intpm.4 update supported hardware list MFC after: 1 week --- share/man/man4/intpm.4 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/share/man/man4/intpm.4 b/share/man/man4/intpm.4 index 9e0b30d8fdf..92ad89b681a 100644 --- a/share/man/man4/intpm.4 +++ b/share/man/man4/intpm.4 @@ -55,7 +55,11 @@ Intel 82371AB/82443MX .It ATI IXP400 .It -AMD SB600/700/710/750 +AMD SB600/7x0/8x0/9x0 southbridges +.It +AMD Axx/Hudson/Bolton FCHs +.It +AMD FCH integrated into Family 16h Models 00h-0Fh Processors .El .Sh SEE ALSO .Xr amdpm 4 , From ea16af59a11ad2bf957819f145d6a8747f233f17 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 8 Sep 2016 12:07:25 +0000 Subject: [PATCH 090/109] When externding directory inode in ufs_direnter(), adjust i_endoff. This change is formally not needed, since i_endoff not used in all code paths after the call to ufs_direnter(), and i_endoff is recalculated by the next lookup. But having the value correct makes the reasoning about code simpler. Reported and tested by: pho Reviewed by: mckusick Sponsored by: The FreeBSD Foundation MFC after: 2 weeks --- sys/ufs/ufs/ufs_lookup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c index a86f70d4226..5597def194d 100644 --- a/sys/ufs/ufs/ufs_lookup.c +++ b/sys/ufs/ufs/ufs_lookup.c @@ -908,6 +908,7 @@ ufs_direnter(dvp, tvp, dirp, cnp, newdirbp, isrename) } dp->i_size = dp->i_offset + DIRBLKSIZ; DIP_SET(dp, i_size, dp->i_size); + dp->i_endoff = dp->i_size; dp->i_flag |= IN_CHANGE | IN_UPDATE; dirp->d_reclen = DIRBLKSIZ; blkoff = dp->i_offset & From 76db05eb14d958b40e8bd3a7c48cbd4490077843 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 8 Sep 2016 12:08:08 +0000 Subject: [PATCH 091/109] When logging unlikely UFS_TRUNCATE() failure in ufs_direnter(), include error code. Reported and tested by: pho Reviewed by: mckusick Sponsored by: The FreeBSD Foundation MFC after: 2 weeks --- sys/ufs/ufs/ufs_lookup.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c index 5597def194d..c3e3de9e878 100644 --- a/sys/ufs/ufs/ufs_lookup.c +++ b/sys/ufs/ufs/ufs_lookup.c @@ -1124,7 +1124,8 @@ ufs_direnter(dvp, tvp, dirp, cnp, newdirbp, isrename) error = UFS_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_NORMAL | (DOINGASYNC(dvp) ? 0 : IO_SYNC), cr); if (error != 0) - vn_printf(dvp, "ufs_direnter: failed to truncate "); + vn_printf(dvp, "ufs_direnter: failed to truncate " + "err %d", error); #ifdef UFS_DIRHASH if (error == 0 && dp->i_dirhash != NULL) ufsdirhash_dirtrunc(dp, dp->i_endoff); From 7b05b8a29cf9c50d5d6210b802dd39f16dfa0627 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 8 Sep 2016 12:08:54 +0000 Subject: [PATCH 092/109] Do not leak transient ENOLCK error from flush_newblk_dep() loop. The buffer lock is retried on failed LK_SLEEPFAIL attempt, and error from the failed attempt is irrelevant. But since there is path after retry which does not clear error, it is possible to return spurious error from the function. The issue resulted in a spurious failure of softdep_sync_buf(), causing further spurious failure of ffs_sync(). In collaboration with: pho Reviewed by: mckusick Sponsored by: The FreeBSD Foundation MFC after: 2 weeks --- sys/ufs/ffs/ffs_softdep.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 122848dced7..7434974ce9c 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -12954,6 +12954,7 @@ flush_newblk_dep(vp, mp, lbn) LK_INTERLOCK, BO_LOCKPTR(bo)); if (error == ENOLCK) { ACQUIRE_LOCK(ump); + error = 0; continue; /* Slept, retry */ } if (error != 0) From f0c4119c9adf5e4553cd50b7ae1097c9f0c19552 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Thu, 8 Sep 2016 12:09:13 +0000 Subject: [PATCH 093/109] amdsbwd.4: update supported hardware list And place it into its own section. MFC after: 1 week --- share/man/man4/amdsbwd.4 | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/share/man/man4/amdsbwd.4 b/share/man/man4/amdsbwd.4 index 656921a8113..5535f7c7b50 100644 --- a/share/man/man4/amdsbwd.4 +++ b/share/man/man4/amdsbwd.4 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 29, 2016 +.Dd September 8, 2016 .Dt AMDSBWD 4 .Os .Sh NAME @@ -51,7 +51,22 @@ The driver provides .Xr watchdog 4 support for the watchdog timers present on -AMD SB600, SB7xx, SB8xx and SB9xx southbridges and Axx FCHs. +the supported chipsets. +.Sh HARDWARE +The +.Nm +driver supports the following chipsets: +.Pp +.Bl -bullet -compact +.It +AMD SB600/7x0/8x0/9x0 southbridges +.It +AMD Axx/Hudson/Bolton FCHs +.It +AMD FCHs integrated into Family 15h Models 60h-6Fh, 70h-7Fh Processors +.It +AMD FCHs integrated into Family 16h Models 00h-0Fh, 30h-3Fh Processors +.El .Sh SEE ALSO .Xr watchdog 4 , .Xr watchdog 8 , From 63876b3ba2a64bf6e0d96b6aefeeb25ccb9b5f78 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 8 Sep 2016 12:09:34 +0000 Subject: [PATCH 094/109] On rename, do not perform truncation of dirhash if the vnode truncation failed. Doing so resulted in inconsistent state of the ufs dirhash with regard to the actual directory inode state, and could lead to spurious ENOENT errors for lookups of existing files in production kernels, or assertion failures in the debugging kernels. Change the logic of calling ufsdirhash_dirtrunc() to be same as in ufs_direnter(). Execute UFS_TRUNCATE() first, log error, and only do dirtrunc() if UFS_TRUNCATE() succeeded. Note that the problem was exacerbated by the bug in the flush_newblk_dep() function (see r305599), which caused in the spurios errors from ffs_sync() and then ffs_truncate(). In collaboration with: pho Reviewed by: mckusick Sponsored by: The FreeBSD Foundation MFC after: 2 weeks --- sys/ufs/ufs/ufs_vnops.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 217ca9062d5..07e59aa1ce1 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -1529,11 +1529,21 @@ unlockout: * are no longer needed. */ if (error == 0 && endoff != 0) { + error = UFS_TRUNCATE(tdvp, endoff, IO_NORMAL | IO_SYNC, + tcnp->cn_cred); + if (error != 0) + vn_printf(tdvp, "ufs_rename: failed to truncate " + "err %d", error); #ifdef UFS_DIRHASH - if (tdp->i_dirhash != NULL) + else if (tdp->i_dirhash != NULL) ufsdirhash_dirtrunc(tdp, endoff); #endif - UFS_TRUNCATE(tdvp, endoff, IO_NORMAL | IO_SYNC, tcnp->cn_cred); + /* + * Even if the directory compaction failed, rename was + * succesful. Do not propagate a UFS_TRUNCATE() error + * to the caller. + */ + error = 0; } if (error == 0 && tdp->i_flag & IN_NEEDSYNC) error = VOP_FSYNC(tdvp, MNT_WAIT, td); From 6c29523e00a9f8cd441f5105edd4869f33fce288 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Thu, 8 Sep 2016 12:12:39 +0000 Subject: [PATCH 095/109] intpm: fix attachment to supported AMD FCHs --- sys/dev/intpm/intpm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sys/dev/intpm/intpm.c b/sys/dev/intpm/intpm.c index 3e844cb486a..aaeb3d0f864 100644 --- a/sys/dev/intpm/intpm.c +++ b/sys/dev/intpm/intpm.c @@ -218,10 +218,12 @@ intsmb_attach(device_t dev) break; #endif case 0x43851002: - case 0x780b1022: if (pci_get_revid(dev) >= 0x40) sc->sb8xx = 1; break; + case 0x780b1022: + sc->sb8xx = 1; + break; } if (sc->sb8xx) { From c47117f43ae0a97c0e7fb01b488b1f25d59e99ef Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Thu, 8 Sep 2016 12:24:46 +0000 Subject: [PATCH 096/109] intpm: do not try attaching to unsupported controller revisions While there set a different device description for the controllers found in various FCHs (Hudson, Bolton, CPU integrated). MFC after: 1 week --- sys/dev/intpm/intpm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sys/dev/intpm/intpm.c b/sys/dev/intpm/intpm.c index aaeb3d0f864..c520d8927fb 100644 --- a/sys/dev/intpm/intpm.c +++ b/sys/dev/intpm/intpm.c @@ -104,9 +104,12 @@ intsmb_probe(device_t dev) device_set_desc(dev, "ATI IXP400 SMBus Controller"); break; case 0x43851002: - case 0x780b1022: /* AMD Hudson */ - device_set_desc(dev, "AMD SB600/7xx/8xx SMBus Controller"); - /* XXX Maybe force polling right here? */ + device_set_desc(dev, "AMD SB600/7xx/8xx/9xx SMBus Controller"); + break; + case 0x780b1022: /* AMD FCH */ + if (pci_get_revid(dev) < 0x40) + return (ENXIO); + device_set_desc(dev, "AMD FCH SMBus Controller"); break; default: return (ENXIO); From a2f51f57d195d45982aebd43255c063c65cf151c Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Thu, 8 Sep 2016 12:27:34 +0000 Subject: [PATCH 097/109] intpm: better clean up resources after a failed attachment bus_generic_detach() fails when called from attach method thus preventing further clean up actions. MFC after: 1 week --- sys/dev/intpm/intpm.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/sys/dev/intpm/intpm.c b/sys/dev/intpm/intpm.c index c520d8927fb..3a5054ff1a6 100644 --- a/sys/dev/intpm/intpm.c +++ b/sys/dev/intpm/intpm.c @@ -199,6 +199,23 @@ sb8xx_attach(device_t dev) return (0); } +static void +intsmb_release_resources(device_t dev) +{ + struct intsmb_softc *sc = device_get_softc(dev); + + if (sc->smbus) + device_delete_child(dev, sc->smbus); + if (sc->irq_hand) + bus_teardown_intr(dev, sc->irq_res, sc->irq_hand); + if (sc->irq_res) + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); + if (sc->io_res) + bus_release_resource(dev, SYS_RES_IOPORT, sc->io_rid, + sc->io_res); + mtx_destroy(&sc->lock); +} + static int intsmb_attach(device_t dev) { @@ -311,12 +328,15 @@ no_intr: sc->isbusy = 0; sc->smbus = device_add_child(dev, "smbus", -1); if (sc->smbus == NULL) { + device_printf(dev, "failed to add smbus child\n"); error = ENXIO; goto fail; } error = device_probe_and_attach(sc->smbus); - if (error) + if (error) { + device_printf(dev, "failed to probe+attach smbus child\n"); goto fail; + } #ifdef ENABLE_ALART /* Enable Arart */ @@ -325,30 +345,22 @@ no_intr: return (0); fail: - intsmb_detach(dev); + intsmb_release_resources(dev); return (error); } static int intsmb_detach(device_t dev) { - struct intsmb_softc *sc = device_get_softc(dev); int error; error = bus_generic_detach(dev); - if (error) + if (error) { + device_printf(dev, "bus detach failed\n"); return (error); + } - if (sc->smbus) - device_delete_child(dev, sc->smbus); - if (sc->irq_hand) - bus_teardown_intr(dev, sc->irq_res, sc->irq_hand); - if (sc->irq_res) - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); - if (sc->io_res) - bus_release_resource(dev, SYS_RES_IOPORT, sc->io_rid, - sc->io_res); - mtx_destroy(&sc->lock); + intsmb_release_resources(dev); return (0); } From e0c6c1d1fd53ee7757c7e3ea1f88add7356e7e92 Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Thu, 8 Sep 2016 12:39:03 +0000 Subject: [PATCH 098/109] Don't panic when we don't handle a userland exception, not all we may see are currently handled. Obtained from: ABT Systems Ltd MFC after: 3 days Sponsored by: The FreeBSD Foundation --- sys/arm64/arm64/trap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c index b2ca455ea74..bc191056f13 100644 --- a/sys/arm64/arm64/trap.c +++ b/sys/arm64/arm64/trap.c @@ -401,9 +401,9 @@ do_el0_sync(struct trapframe *frame) userret(td, frame); break; default: - print_registers(frame); - panic("Unknown userland exception %x esr_el1 %lx\n", exception, - esr); + call_trapsignal(td, SIGBUS, BUS_OBJERR, (void *)frame->tf_elr); + userret(td, frame); + break; } } From 19afdc91b9e06b4ffcd107b01724abab728d5a53 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Thu, 8 Sep 2016 12:43:24 +0000 Subject: [PATCH 099/109] intpm: make sure to register smbus driver before intpm driver Otherwise we can fail to create an smbus child of intpm. MFC after: 1 week --- sys/dev/intpm/intpm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/dev/intpm/intpm.c b/sys/dev/intpm/intpm.c index 3a5054ff1a6..76076ab80ef 100644 --- a/sys/dev/intpm/intpm.c +++ b/sys/dev/intpm/intpm.c @@ -924,7 +924,8 @@ static driver_t intsmb_driver = { sizeof(struct intsmb_softc), }; -DRIVER_MODULE(intsmb, pci, intsmb_driver, intsmb_devclass, 0, 0); +DRIVER_MODULE_ORDERED(intsmb, pci, intsmb_driver, intsmb_devclass, 0, 0, + SI_ORDER_ANY); DRIVER_MODULE(smbus, intsmb, smbus_driver, smbus_devclass, 0, 0); MODULE_DEPEND(intsmb, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); MODULE_VERSION(intsmb, 1); From 13db69623b6ea8ff8e89911050d1a4d3fef81485 Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Thu, 8 Sep 2016 12:53:01 +0000 Subject: [PATCH 100/109] Trap msr/mrs instructions. These are privileged arm64 instructions and shouldn't normally be used. Obtained from: ABT Systems Ltd MFC after: 1 week Sponsored by: The FreeBSD Foundation --- sys/arm64/arm64/trap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c index bc191056f13..1748ece4831 100644 --- a/sys/arm64/arm64/trap.c +++ b/sys/arm64/arm64/trap.c @@ -391,6 +391,10 @@ do_el0_sync(struct trapframe *frame) call_trapsignal(td, SIGTRAP, TRAP_BRKPT, (void *)frame->tf_elr); userret(td, frame); break; + case EXCP_MSR: + call_trapsignal(td, SIGILL, ILL_PRVOPC, (void *)frame->tf_elr); + userret(td, frame); + break; case EXCP_SOFTSTP_EL0: td->td_frame->tf_spsr &= ~PSR_SS; td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP; From 6867747328f70594f19772eb122f3c65bbe7b765 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Thu, 8 Sep 2016 12:58:33 +0000 Subject: [PATCH 101/109] "ATA pass through information available" is not an error. MFC after: 2 weeks --- sys/cam/scsi/scsi_all.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c index 28c5c038d6b..0c44f8b4878 100644 --- a/sys/cam/scsi/scsi_all.c +++ b/sys/cam/scsi/scsi_all.c @@ -1056,7 +1056,7 @@ static struct asc_table_entry asc_table[] = { { SST(0x00, 0x1C, SS_RDEF, /* XXX TBD */ "Verify operation in progress") }, /* DT B */ - { SST(0x00, 0x1D, SS_RDEF, /* XXX TBD */ + { SST(0x00, 0x1D, SS_NOP, "ATA pass through information available") }, /* DT R MAEBKV */ { SST(0x00, 0x1E, SS_RDEF, /* XXX TBD */ From 5d18110a7fab1e9e66f99d9cbb5651b048b46c4c Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Thu, 8 Sep 2016 13:03:49 +0000 Subject: [PATCH 102/109] "Extended copy information available" is not an error either. MFC after: 2 weeks --- sys/cam/scsi/scsi_all.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c index 0c44f8b4878..c6a4533aa84 100644 --- a/sys/cam/scsi/scsi_all.c +++ b/sys/cam/scsi/scsi_all.c @@ -1065,7 +1065,7 @@ static struct asc_table_entry asc_table[] = { { SST(0x00, 0x1F, SS_RDEF, /* XXX TBD */ "Logical unit transitioning to another power condition") }, /* DT P B */ - { SST(0x00, 0x20, SS_RDEF, /* XXX TBD */ + { SST(0x00, 0x20, SS_NOP, "Extended copy information available") }, /* D */ { SST(0x00, 0x21, SS_RDEF, /* XXX TBD */ From cd3752643cd87c20c30aada1215ec292e3cebcac Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Thu, 8 Sep 2016 13:33:33 +0000 Subject: [PATCH 103/109] Don't report to devd statuses that CAM doesn't consider errors. Some statuses, such as "ATA pass through information available", are part part of absolutely normal operation and do not worth reporting. MFC after: 2 weeks --- sys/cam/cam_periph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c index 0415643814a..091b96f2488 100644 --- a/sys/cam/cam_periph.c +++ b/sys/cam/cam_periph.c @@ -1772,7 +1772,7 @@ cam_periph_error(union ccb *ccb, cam_flags camflags, xpt_print(ccb->ccb_h.path, "Retrying command\n"); } - if (devctl_err) + if (devctl_err && (error != 0 || (action & SSQ_PRINT_SENSE) != 0)) cam_periph_devctl_notify(orig_ccb); if ((action & SSQ_LOST) != 0) { From e62264e2dd8b01d4678891783606408bc37f3c22 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Thu, 8 Sep 2016 14:04:04 +0000 Subject: [PATCH 104/109] Update capabilities.conf comment getdtablesize is per-process state, not global state --- sys/kern/capabilities.conf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/kern/capabilities.conf b/sys/kern/capabilities.conf index 37a03f620de..97fb88144b8 100644 --- a/sys/kern/capabilities.conf +++ b/sys/kern/capabilities.conf @@ -248,6 +248,10 @@ getdirentries ## Allow querying certain trivial global state. ## getdomainname + +## +## Allow querying certain per-process resource limit state. +## getdtablesize ## From 8b530941f4eb4e48ad6ee127a0767ac7eafe4cb1 Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Thu, 8 Sep 2016 14:43:39 +0000 Subject: [PATCH 105/109] Fix single-stepping of instructions emulated by vm86. In vm86.c, fix 2 (rarely used) cases where the return code lost the single-step indicator. While here, fix 2 misspellings of PSL_T as PSL_TF (TF is the CPU manufacturer's spelling, but we use T). In trap.c, turn T_PROTFLT and T_STKFLT into T_TRCTRAP if vm86_emulate() asked for this (it does this when the instruction is being traced and was successully emulated). In the kernel case, we used to deliver the trap as SIGTRAP to the process, where it always terminated the process; now we deliver the trap as T_TRCTRAP to kdb, where it normally gives single-stepping. In the user case, the only difference is that we now clear PSL_T and initialize ucode properly. Reviewed by: kib --- sys/i386/i386/trap.c | 10 ++++++++++ sys/i386/i386/vm86.c | 8 ++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index c540a49a00e..e04368efee5 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -335,6 +335,7 @@ trap(struct trapframe *frame) goto out; } #endif +user_trctrap_out: frame->tf_eflags &= ~PSL_T; i = SIGTRAP; ucode = (type == T_TRCTRAP ? TRAP_TRACE : TRAP_BRKPT); @@ -360,6 +361,10 @@ trap(struct trapframe *frame) case T_STKFLT: /* stack fault */ if (frame->tf_eflags & PSL_VM) { i = vm86_emulate((struct vm86frame *)frame); + if (i == SIGTRAP) { + type = T_TRCTRAP; + goto user_trctrap_out; + } if (i == 0) goto user; break; @@ -566,6 +571,10 @@ trap(struct trapframe *frame) case T_STKFLT: /* stack fault */ if (frame->tf_eflags & PSL_VM) { i = vm86_emulate((struct vm86frame *)frame); + if (i == SIGTRAP) { + type = T_TRCTRAP; + goto kernel_trctrap; + } if (i != 0) /* * returns to original process @@ -654,6 +663,7 @@ trap(struct trapframe *frame) break; case T_TRCTRAP: /* trace trap */ +kernel_trctrap: if (frame->tf_eip == (int)IDTVEC(lcall_syscall)) { /* * We've just entered system mode via the diff --git a/sys/i386/i386/vm86.c b/sys/i386/i386/vm86.c index 93ff855750b..baa1912d44f 100644 --- a/sys/i386/i386/vm86.c +++ b/sys/i386/i386/vm86.c @@ -171,7 +171,7 @@ vm86_emulate(vmf) PUSHL((vmf->vmf_eflags & PUSH_MASK) | PSL_IOPL, vmf); vmf->vmf_ip += inc_ip; - return (0); + return (retcode); case POPF: temp_flags = POPL(vmf) & POP_MASK; @@ -185,7 +185,7 @@ vm86_emulate(vmf) } else { vmf->vmf_eflags &= ~PSL_VIF; } - return (0); + return (retcode); } break; @@ -203,7 +203,7 @@ vm86_emulate(vmf) case INTn: break; - /* VME if trying to set PSL_TF, or PSL_I when VIP is set */ + /* VME if trying to set PSL_T, or PSL_I when VIP is set */ case POPF: temp_flags = POP(vmf) & POP_MASK; vmf->vmf_flags = (vmf->vmf_flags & ~POP_MASK) @@ -218,7 +218,7 @@ vm86_emulate(vmf) } return (retcode); - /* VME if trying to set PSL_TF, or PSL_I when VIP is set */ + /* VME if trying to set PSL_T, or PSL_I when VIP is set */ case IRET: vmf->vmf_ip = POP(vmf); vmf->vmf_cs = POP(vmf); From a6be46901402c0f21a65aa523c8ffcd94d88007a Mon Sep 17 00:00:00 2001 From: Gabor Kovesdan Date: Thu, 8 Sep 2016 14:50:23 +0000 Subject: [PATCH 106/109] - Fix typo PR: 211245 Submitted by: Christoph Schonweiler MFC after: 5 days --- usr.bin/sort/sort.1.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.bin/sort/sort.1.in b/usr.bin/sort/sort.1.in index e3266c131e8..daec043c7a1 100644 --- a/usr.bin/sort/sort.1.in +++ b/usr.bin/sort/sort.1.in @@ -133,7 +133,7 @@ also checks that there are no lines with duplicate keys. .It Fl s Stable sort. This option maintains the original record order of records that have -and equal key. +an equal key. This is a non-standard feature, but it is widely accepted and used. .It Fl Fl version Print the version and silently exits. From 1a04446f088c79cc2cf85fd86e60ebcc228d3075 Mon Sep 17 00:00:00 2001 From: Eric van Gyzen Date: Thu, 8 Sep 2016 15:53:49 +0000 Subject: [PATCH 107/109] etcupdate: preserve the metadata of the destination file When using diff3 to perform a three-way merge, etcupdate lost the destination file's metadata. The metadata from the temporary file were used instead. This was unpleasant for rc.d scripts, which require execute permission. Use "cat >" to overwrite the destination file's contents while preserving its metadata. Reviewed by: bapt Sponsored by: Dell Technologies Differential Revision: https://reviews.freebsd.org/D7817 --- usr.sbin/etcupdate/etcupdate.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/usr.sbin/etcupdate/etcupdate.sh b/usr.sbin/etcupdate/etcupdate.sh index 6330c60da85..2b4c145fa3f 100755 --- a/usr.sbin/etcupdate/etcupdate.sh +++ b/usr.sbin/etcupdate/etcupdate.sh @@ -824,7 +824,9 @@ merge_file() if [ -z "$dryrun" ]; then temp=$(mktemp -t etcupdate) diff3 -E -m ${DESTDIR}$1 ${OLDTREE}$1 ${NEWTREE}$1 > ${temp} - mv -f ${temp} ${DESTDIR}$1 + # Use "cat >" to preserve metadata. + cat ${temp} > ${DESTDIR}$1 + rm -f ${temp} fi post_install_file $1 echo " M $1" From 84aec472fc5193360cc0f3f921f631dc9a1acb78 Mon Sep 17 00:00:00 2001 From: Ruslan Bukin Date: Thu, 8 Sep 2016 17:37:13 +0000 Subject: [PATCH 108/109] Allow the use of soft-interrupts for sending IPIs. This will be required for SMP support on MIPS Malta platform. Reviewed by: adrian Sponsored by: DARPA, AFRL Sponsored by: HEIF5 Differential Revision: https://reviews.freebsd.org/D7835 --- sys/mips/cavium/octeon_mp.c | 12 ++++++++++-- sys/mips/gxemul/gxemul_machdep.c | 12 ++++++++++-- sys/mips/include/hwfunc.h | 3 ++- sys/mips/mips/mp_machdep.c | 12 +++++++++--- sys/mips/nlm/xlp_machdep.c | 11 +++++++++-- sys/mips/rmi/xlr_machdep.c | 11 +++++++++-- sys/mips/sibyte/sb_machdep.c | 13 ++++++++++--- sys/mips/sibyte/sb_scd.c | 2 +- 8 files changed, 60 insertions(+), 16 deletions(-) diff --git a/sys/mips/cavium/octeon_mp.c b/sys/mips/cavium/octeon_mp.c index 783a45f81bc..51d2167b9a9 100644 --- a/sys/mips/cavium/octeon_mp.c +++ b/sys/mips/cavium/octeon_mp.c @@ -63,11 +63,19 @@ platform_ipi_clear(void) } int -platform_ipi_intrnum(void) +platform_ipi_hardintr_num(void) { + return (1); } +int +platform_ipi_softintr_num(void) +{ + + return (-1); +} + void platform_init_ap(int cpuid) { @@ -93,7 +101,7 @@ platform_init_ap(int cpuid) */ ciu_int_mask = hard_int_mask(0); clock_int_mask = hard_int_mask(5); - ipi_int_mask = hard_int_mask(platform_ipi_intrnum()); + ipi_int_mask = hard_int_mask(platform_ipi_hardintr_num()); set_intr_mask(ciu_int_mask | clock_int_mask | ipi_int_mask); mips_wbflush(); diff --git a/sys/mips/gxemul/gxemul_machdep.c b/sys/mips/gxemul/gxemul_machdep.c index a068efc7b4e..065bbde896c 100644 --- a/sys/mips/gxemul/gxemul_machdep.c +++ b/sys/mips/gxemul/gxemul_machdep.c @@ -186,11 +186,19 @@ platform_ipi_clear(void) } int -platform_ipi_intrnum(void) +platform_ipi_hardintr_num(void) { + return (GXEMUL_MP_DEV_IPI_INTERRUPT - 2); } +int +platform_ipi_softintr_num(void) +{ + + return (-1); +} + struct cpu_group * platform_smp_topo(void) { @@ -206,7 +214,7 @@ platform_init_ap(int cpuid) * Unmask the clock and ipi interrupts. */ clock_int_mask = hard_int_mask(5); - ipi_int_mask = hard_int_mask(platform_ipi_intrnum()); + ipi_int_mask = hard_int_mask(platform_ipi_hardintr_num()); set_intr_mask(ipi_int_mask | clock_int_mask); } diff --git a/sys/mips/include/hwfunc.h b/sys/mips/include/hwfunc.h index 5c797fc4ec4..efbe4253dae 100644 --- a/sys/mips/include/hwfunc.h +++ b/sys/mips/include/hwfunc.h @@ -67,7 +67,8 @@ void platform_init_ap(int processor_id); * This hardware interrupt is used to deliver IPIs exclusively and must * not be used for any other interrupt source. */ -int platform_ipi_intrnum(void); +int platform_ipi_hardintr_num(void); +int platform_ipi_softintr_num(void); /* * Trigger a IPI interrupt on 'cpuid'. diff --git a/sys/mips/mips/mp_machdep.c b/sys/mips/mips/mp_machdep.c index 9f989091e07..88c7bf290c6 100644 --- a/sys/mips/mips/mp_machdep.c +++ b/sys/mips/mips/mp_machdep.c @@ -345,9 +345,15 @@ release_aps(void *dummy __unused) /* * IPI handler */ - ipi_irq = platform_ipi_intrnum(); - cpu_establish_hardintr("ipi", mips_ipi_handler, NULL, NULL, ipi_irq, - INTR_TYPE_MISC | INTR_EXCL, NULL); + ipi_irq = platform_ipi_hardintr_num(); + if (ipi_irq != -1) { + cpu_establish_hardintr("ipi", mips_ipi_handler, NULL, NULL, + ipi_irq, INTR_TYPE_MISC | INTR_EXCL, NULL); + } else { + ipi_irq = platform_ipi_softintr_num(); + cpu_establish_softintr("ipi", mips_ipi_handler, NULL, NULL, + ipi_irq, INTR_TYPE_MISC | INTR_EXCL, NULL); + } atomic_store_rel_int(&aps_ready, 1); diff --git a/sys/mips/nlm/xlp_machdep.c b/sys/mips/nlm/xlp_machdep.c index 5f93d6c232e..df94530ff4d 100644 --- a/sys/mips/nlm/xlp_machdep.c +++ b/sys/mips/nlm/xlp_machdep.c @@ -687,18 +687,25 @@ platform_init_ap(int cpuid) } int -platform_ipi_intrnum(void) +platform_ipi_hardintr_num(void) { return (IRQ_IPI); } +int +platform_ipi_softintr_num(void) +{ + + return (-1); +} + void platform_ipi_send(int cpuid) { nlm_pic_send_ipi(xlp_pic_base, xlp_cpuid_to_hwtid[cpuid], - platform_ipi_intrnum(), 0); + platform_ipi_hardintr_num(), 0); } void diff --git a/sys/mips/rmi/xlr_machdep.c b/sys/mips/rmi/xlr_machdep.c index ad3d07355fd..645d226e6e5 100644 --- a/sys/mips/rmi/xlr_machdep.c +++ b/sys/mips/rmi/xlr_machdep.c @@ -571,17 +571,24 @@ platform_init_ap(int cpuid) } int -platform_ipi_intrnum(void) +platform_ipi_hardintr_num(void) { return (IRQ_IPI); } +int +platform_ipi_softintr_num(void) +{ + + return (-1); +} + void platform_ipi_send(int cpuid) { - pic_send_ipi(xlr_cpuid_to_hwtid[cpuid], platform_ipi_intrnum()); + pic_send_ipi(xlr_cpuid_to_hwtid[cpuid], platform_ipi_hardintr_num()); } void diff --git a/sys/mips/sibyte/sb_machdep.c b/sys/mips/sibyte/sb_machdep.c index 5e7c2fded87..db70fcc4f7c 100644 --- a/sys/mips/sibyte/sb_machdep.c +++ b/sys/mips/sibyte/sb_machdep.c @@ -124,7 +124,7 @@ sb_intr_init(int cpuid) * with any other interrupt source. */ if (intsrc == INTSRC_MAILBOX3) { - intrnum = platform_ipi_intrnum(); + intrnum = platform_ipi_hardintr_num(); sb_write_intmap(cpuid, INTSRC_MAILBOX3, intrnum); sb_enable_intsrc(cpuid, INTSRC_MAILBOX3); } @@ -313,12 +313,19 @@ platform_ipi_clear(void) } int -platform_ipi_intrnum(void) +platform_ipi_hardintr_num(void) { return (4); } +int +platform_ipi_softintr_num(void) +{ + + return (-1); +} + struct cpu_group * platform_smp_topo(void) { @@ -344,7 +351,7 @@ platform_init_ap(int cpuid) * Unmask the clock and ipi interrupts. */ clock_int_mask = hard_int_mask(5); - ipi_int_mask = hard_int_mask(platform_ipi_intrnum()); + ipi_int_mask = hard_int_mask(platform_ipi_hardintr_num()); set_intr_mask(ipi_int_mask | clock_int_mask); } diff --git a/sys/mips/sibyte/sb_scd.c b/sys/mips/sibyte/sb_scd.c index 50b99876aca..c841065e2ef 100644 --- a/sys/mips/sibyte/sb_scd.c +++ b/sys/mips/sibyte/sb_scd.c @@ -207,7 +207,7 @@ sb_route_intsrc(int intsrc) * Use a deterministic mapping for the remaining sources. */ #ifdef SMP - KASSERT(platform_ipi_intrnum() == 4, + KASSERT(platform_ipi_hardintr_num() == 4, ("Unexpected interrupt number used for IPI")); intrnum = intsrc % 4; #else From 0c01bcb9ffd9168f8fe5cb786c85d47437f0606a Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Thu, 8 Sep 2016 17:40:40 +0000 Subject: [PATCH 109/109] Sprinkle DOINGASYNC() checks so as to do delayed writes for async mounts in almost all cases instead of in most cases. Don't override DOINGASYNC() by any condition except IO_SYNC. Fix previous sprinking of DOINGASYNC() checks. Don't override IO_SYNC by DOINGASYNC(). In ffs_write() and ffs_extwrite(), there were intentional overrides that just broke O_SYNC of data. In ffs_truncate(), there are 5 calls to ffs_update(), 4 with apparently-unintentional overrides and 1 without; this had no effect due to the main async mount hack descibed below. Fix 1 place in ffs_truncate() where the caller's IO_ASYNC was overridden for the soft updates case too (to do a delayed write instead of a sync write). This is supposed to be the only change that affects anything except async mounts. In ffs_update(), remove the 19 year old efficiency hack of ignoring the waitfor flag for async mounts, so that fsync() almost works for async mounts. All callers are supposed to be fixed to not ask for a sync update unless they are for fsync() or [I]O_SYNC operations. fsync() now almost works for async mounts. It used to sync the data but not the most important metdata (the inode). It still doesn't sync associated directories. This gave 10-20% fewer writes for my makeworld benchmark with async mounted tmp and obj directories from an already small number. Style fixes: - in ffs_balloc.c, remove rotted quadruplicated comments about the simplest part of the DOING*() decisions and rearrange the nearly- quadruplicated code to be more nearly so. - in ufs_vnops.c, use a consistent style with less negative logic and no manual "optimization" of || to | in DOING*() expressions. Reviewed by: kib (previous version) --- sys/ufs/ffs/ffs_balloc.c | 42 +++++++++++++++++++--------------------- sys/ufs/ffs/ffs_inode.c | 21 ++++++++++---------- sys/ufs/ffs/ffs_vnops.c | 4 ++-- sys/ufs/ufs/ufs_lookup.c | 2 +- sys/ufs/ufs/ufs_vnops.c | 20 +++++++++---------- 5 files changed, 44 insertions(+), 45 deletions(-) diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c index 04e0ae93b23..676dcb4e4d4 100644 --- a/sys/ufs/ffs/ffs_balloc.c +++ b/sys/ufs/ffs/ffs_balloc.c @@ -154,6 +154,8 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, ip->i_flag |= IN_CHANGE | IN_UPDATE; if (flags & IO_SYNC) bwrite(bp); + else if (DOINGASYNC(vp)) + bdwrite(bp); else bawrite(bp); } @@ -266,14 +268,12 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, softdep_setup_allocdirect(ip, NDADDR + indirs[0].in_off, newb, 0, fs->fs_bsize, 0, bp); bdwrite(bp); + } else if ((flags & IO_SYNC) == 0 && DOINGASYNC(vp)) { + if (bp->b_bufsize == fs->fs_bsize) + bp->b_flags |= B_CLUSTEROK; + bdwrite(bp); } else { - /* - * Write synchronously so that indirect blocks - * never point at garbage. - */ - if (DOINGASYNC(vp)) - bdwrite(bp); - else if ((error = bwrite(bp)) != 0) + if ((error = bwrite(bp)) != 0) goto fail; } allocib = &dp->di_ib[indirs[0].in_off]; @@ -338,11 +338,11 @@ retry: softdep_setup_allocindir_meta(nbp, ip, bp, indirs[i - 1].in_off, nb); bdwrite(nbp); + } else if ((flags & IO_SYNC) == 0 && DOINGASYNC(vp)) { + if (nbp->b_bufsize == fs->fs_bsize) + nbp->b_flags |= B_CLUSTEROK; + bdwrite(nbp); } else { - /* - * Write synchronously so that indirect blocks - * never point at garbage. - */ if ((error = bwrite(nbp)) != 0) { brelse(bp); goto fail; @@ -854,14 +854,12 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, softdep_setup_allocdirect(ip, NDADDR + indirs[0].in_off, newb, 0, fs->fs_bsize, 0, bp); bdwrite(bp); + } else if ((flags & IO_SYNC) == 0 && DOINGASYNC(vp)) { + if (bp->b_bufsize == fs->fs_bsize) + bp->b_flags |= B_CLUSTEROK; + bdwrite(bp); } else { - /* - * Write synchronously so that indirect blocks - * never point at garbage. - */ - if (DOINGASYNC(vp)) - bdwrite(bp); - else if ((error = bwrite(bp)) != 0) + if ((error = bwrite(bp)) != 0) goto fail; } allocib = &dp->di_ib[indirs[0].in_off]; @@ -927,11 +925,11 @@ retry: softdep_setup_allocindir_meta(nbp, ip, bp, indirs[i - 1].in_off, nb); bdwrite(nbp); + } else if ((flags & IO_SYNC) == 0 && DOINGASYNC(vp)) { + if (nbp->b_bufsize == fs->fs_bsize) + nbp->b_flags |= B_CLUSTEROK; + bdwrite(nbp); } else { - /* - * Write synchronously so that indirect blocks - * never point at garbage. - */ if ((error = bwrite(nbp)) != 0) { brelse(bp); goto fail; diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c index 50b456bd787..4bd38d58692 100644 --- a/sys/ufs/ffs/ffs_inode.c +++ b/sys/ufs/ffs/ffs_inode.c @@ -154,7 +154,7 @@ loop: /* XXX: FIX? The entropy here is desirable, but the harvesting may be expensive */ random_harvest_queue(&(ip->i_din2), sizeof(ip->i_din2), 1, RANDOM_FS_ATIME); } - if (waitfor && !DOINGASYNC(vp)) + if (waitfor) error = bwrite(bp); else if (vm_page_count_severe() || buf_dirty_count_severe()) { bawrite(bp); @@ -193,7 +193,7 @@ ffs_truncate(vp, length, flags, cred) int softdeptrunc, journaltrunc; int needextclean, extblocks; int offset, size, level, nblocks; - int i, error, allerror, indiroff; + int i, error, allerror, indiroff, waitforupdate; off_t osize; ip = VTOI(vp); @@ -221,6 +221,7 @@ ffs_truncate(vp, length, flags, cred) flags |= IO_NORMAL; if (!DOINGSOFTDEP(vp) && !DOINGASYNC(vp)) flags |= IO_SYNC; + waitforupdate = (flags & IO_SYNC) != 0 || !DOINGASYNC(vp); /* * If we are truncating the extended-attributes, and cannot * do it with soft updates, then do it slowly here. If we are @@ -264,7 +265,7 @@ ffs_truncate(vp, length, flags, cred) ip->i_din2->di_extb[i] = 0; } ip->i_flag |= IN_CHANGE; - if ((error = ffs_update(vp, !DOINGASYNC(vp)))) + if ((error = ffs_update(vp, waitforupdate))) return (error); for (i = 0; i < NXADDR; i++) { if (oldblks[i] == 0) @@ -290,7 +291,7 @@ ffs_truncate(vp, length, flags, cred) ip->i_flag |= IN_CHANGE | IN_UPDATE; if (needextclean) goto extclean; - return (ffs_update(vp, !DOINGASYNC(vp))); + return (ffs_update(vp, waitforupdate)); } if (ip->i_size == length) { ip->i_flag |= IN_CHANGE | IN_UPDATE; @@ -328,7 +329,7 @@ ffs_truncate(vp, length, flags, cred) else bawrite(bp); ip->i_flag |= IN_CHANGE | IN_UPDATE; - return (ffs_update(vp, !DOINGASYNC(vp))); + return (ffs_update(vp, waitforupdate)); } /* * Lookup block number for a given offset. Zero length files @@ -357,10 +358,10 @@ ffs_truncate(vp, length, flags, cred) */ if (blkno != 0) brelse(bp); - else if (DOINGSOFTDEP(vp) || DOINGASYNC(vp)) - bdwrite(bp); - else + else if (flags & IO_SYNC) bwrite(bp); + else + bdwrite(bp); } /* * If the block number at the new end of the file is zero, @@ -478,7 +479,7 @@ ffs_truncate(vp, length, flags, cred) DIP_SET(ip, i_db[i], 0); } ip->i_flag |= IN_CHANGE | IN_UPDATE; - allerror = ffs_update(vp, !DOINGASYNC(vp)); + allerror = ffs_update(vp, waitforupdate); /* * Having written the new inode to disk, save its new configuration @@ -610,7 +611,7 @@ extclean: softdep_journal_freeblocks(ip, cred, length, IO_EXT); else softdep_setup_freeblocks(ip, length, IO_EXT); - return (ffs_update(vp, (flags & IO_SYNC) != 0 || !DOINGASYNC(vp))); + return (ffs_update(vp, waitforupdate)); } /* diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 27654804046..0ed7c592398 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -757,7 +757,7 @@ ffs_write(ap) flags = BA_SEQMAX << BA_SEQSHIFT; else flags = seqcount << BA_SEQSHIFT; - if ((ioflag & IO_SYNC) && !DOINGASYNC(vp)) + if (ioflag & IO_SYNC) flags |= IO_SYNC; flags |= BA_UNMAPPED; @@ -1077,7 +1077,7 @@ ffs_extwrite(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *ucred) resid = uio->uio_resid; osize = dp->di_extsize; flags = IO_EXT; - if ((ioflag & IO_SYNC) && !DOINGASYNC(vp)) + if (ioflag & IO_SYNC) flags |= IO_SYNC; for (error = 0; uio->uio_resid > 0;) { diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c index c3e3de9e878..343162434eb 100644 --- a/sys/ufs/ufs/ufs_lookup.c +++ b/sys/ufs/ufs/ufs_lookup.c @@ -1237,7 +1237,7 @@ out: } else { if (flags & DOWHITEOUT) error = bwrite(bp); - else if (DOINGASYNC(dvp) && dp->i_count != 0) + else if (DOINGASYNC(dvp)) bdwrite(bp); else error = bwrite(bp); diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 07e59aa1ce1..46e5b24a36f 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -991,7 +991,7 @@ ufs_link(ap) ip->i_flag |= IN_CHANGE; if (DOINGSOFTDEP(vp)) softdep_setup_link(VTOI(tdvp), ip); - error = UFS_UPDATE(vp, !(DOINGSOFTDEP(vp) | DOINGASYNC(vp))); + error = UFS_UPDATE(vp, !DOINGSOFTDEP(vp) && !DOINGASYNC(vp)); if (!error) { ufs_makedirentry(ip, cnp, &newdir); error = ufs_direnter(tdvp, vp, &newdir, cnp, NULL, 0); @@ -1335,7 +1335,7 @@ relock: fip->i_flag |= IN_CHANGE; if (DOINGSOFTDEP(fvp)) softdep_setup_link(tdp, fip); - error = UFS_UPDATE(fvp, !(DOINGSOFTDEP(fvp) | DOINGASYNC(fvp))); + error = UFS_UPDATE(fvp, !DOINGSOFTDEP(fvp) && !DOINGASYNC(fvp)); if (error) goto bad; @@ -1488,8 +1488,8 @@ relock: tdp->i_flag |= IN_CHANGE; if (DOINGSOFTDEP(tdvp)) softdep_setup_dotdot_link(tdp, fip); - error = UFS_UPDATE(tdvp, !(DOINGSOFTDEP(tdvp) | - DOINGASYNC(tdvp))); + error = UFS_UPDATE(tdvp, !DOINGSOFTDEP(tdvp) && + !DOINGASYNC(tdvp)); /* Don't go to bad here as the new link exists. */ if (error) goto unlockout; @@ -1529,8 +1529,8 @@ unlockout: * are no longer needed. */ if (error == 0 && endoff != 0) { - error = UFS_TRUNCATE(tdvp, endoff, IO_NORMAL | IO_SYNC, - tcnp->cn_cred); + error = UFS_TRUNCATE(tdvp, endoff, IO_NORMAL | + (DOINGASYNC(tdvp) ? 0 : IO_SYNC), tcnp->cn_cred); if (error != 0) vn_printf(tdvp, "ufs_rename: failed to truncate " "err %d", error); @@ -1888,7 +1888,7 @@ ufs_mkdir(ap) dp->i_flag |= IN_CHANGE; if (DOINGSOFTDEP(dvp)) softdep_setup_mkdir(dp, ip); - error = UFS_UPDATE(dvp, !(DOINGSOFTDEP(dvp) | DOINGASYNC(dvp))); + error = UFS_UPDATE(dvp, !DOINGSOFTDEP(dvp) && !DOINGASYNC(dvp)); if (error) goto bad; #ifdef MAC @@ -1945,8 +1945,8 @@ ufs_mkdir(ap) blkoff += DIRBLKSIZ; } } - if ((error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(tvp) | - DOINGASYNC(tvp)))) != 0) { + if ((error = UFS_UPDATE(tvp, !DOINGSOFTDEP(tvp) && + !DOINGASYNC(tvp))) != 0) { (void)bwrite(bp); goto bad; } @@ -2680,7 +2680,7 @@ ufs_makeinode(mode, dvp, vpp, cnp) /* * Make sure inode goes to disk before directory entry. */ - error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(tvp) | DOINGASYNC(tvp))); + error = UFS_UPDATE(tvp, !DOINGSOFTDEP(tvp) && !DOINGASYNC(tvp)); if (error) goto bad; #ifdef MAC