X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=arch%2Farm%2Fcpu%2Farmv8%2Ffsl-layerscape%2Ffsl_lsch3_serdes.c;h=3f1da436142a1639a8ee63f66592f9f6f1113750;hb=c05ed00afb95fa5237f16962fccf5810437317bf;hp=2bef841194b2e51a820256bbcf129b0cf3c22c8a;hpb=e8f80a5a58c9b506453cc0780687e8ed457d30a6;p=oweals%2Fu-boot.git diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c index 2bef841194..3f1da43614 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c @@ -1,10 +1,14 @@ // SPDX-License-Identifier: GPL-2.0+ /* + * Copyright 2016-2018 NXP * Copyright 2014-2015 Freescale Semiconductor, Inc. */ #include +#include +#include #include +#include #include #include #include @@ -16,11 +20,23 @@ static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT]; #ifdef CONFIG_SYS_FSL_SRDS_2 static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT]; #endif +#ifdef CONFIG_SYS_NXP_SRDS_3 +static u8 serdes3_prtcl_map[SERDES_PRCTL_COUNT]; +#endif #if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD) +#ifdef CONFIG_ARCH_LX2160A +int xfi_dpmac[XFI14 + 1]; +int sgmii_dpmac[SGMII18 + 1]; +int a25gaui_dpmac[_25GE10 + 1]; +int xlaui_dpmac[_40GE2 + 1]; +int caui2_dpmac[_50GE2 + 1]; +int caui4_dpmac[_100GE2 + 1]; +#else int xfi_dpmac[XFI8 + 1]; int sgmii_dpmac[SGMII16 + 1]; #endif +#endif __weak void wriop_init_dpmac_qsgmii(int sd, int lane_prtcl) { @@ -57,6 +73,12 @@ int is_serdes_configured(enum srds_prtcl device) ret |= serdes2_prtcl_map[device]; #endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + if (!serdes3_prtcl_map[NONE]) + fsl_serdes_init(); + + ret |= serdes3_prtcl_map[device]; +#endif return !!ret; } @@ -81,6 +103,13 @@ int serdes_get_first_lane(u32 sd, enum srds_prtcl device) cfg &= FSL_CHASSIS3_SRDS2_PRTCL_MASK; cfg >>= FSL_CHASSIS3_SRDS2_PRTCL_SHIFT; break; +#endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + case NXP_SRDS_3: + cfg = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS3_REGSR - 1]); + cfg &= FSL_CHASSIS3_SRDS3_PRTCL_MASK; + cfg >>= FSL_CHASSIS3_SRDS3_PRTCL_SHIFT; + break; #endif default: printf("invalid SerDes%d\n", sd); @@ -129,6 +158,32 @@ void serdes_init(u32 sd, u32 sd_addr, u32 rcwsr, u32 sd_prctl_mask, else { serdes_prtcl_map[lane_prtcl] = 1; #if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD) +#ifdef CONFIG_ARCH_LX2160A + if (lane_prtcl >= XFI1 && lane_prtcl <= XFI14) + wriop_init_dpmac(sd, xfi_dpmac[lane_prtcl], + (int)lane_prtcl); + + if (lane_prtcl >= SGMII1 && lane_prtcl <= SGMII18) + wriop_init_dpmac(sd, sgmii_dpmac[lane_prtcl], + (int)lane_prtcl); + + if (lane_prtcl >= _25GE1 && lane_prtcl <= _25GE10) + wriop_init_dpmac(sd, a25gaui_dpmac[lane_prtcl], + (int)lane_prtcl); + + if (lane_prtcl >= _40GE1 && lane_prtcl <= _40GE2) + wriop_init_dpmac(sd, xlaui_dpmac[lane_prtcl], + (int)lane_prtcl); + + if (lane_prtcl >= _50GE1 && lane_prtcl <= _50GE2) + wriop_init_dpmac(sd, caui2_dpmac[lane_prtcl], + (int)lane_prtcl); + + if (lane_prtcl >= _100GE1 && lane_prtcl <= _100GE2) + wriop_init_dpmac(sd, caui4_dpmac[lane_prtcl], + (int)lane_prtcl); + +#else switch (lane_prtcl) { case QSGMII_A: case QSGMII_B: @@ -149,6 +204,7 @@ void serdes_init(u32 sd, u32 sd_addr, u32 rcwsr, u32 sd_prctl_mask, (int)lane_prtcl); break; } +#endif #endif } } @@ -200,6 +256,12 @@ struct serdes_prctl_info srds_prctl_info[] = { .mask = FSL_CHASSIS3_SRDS2_PRTCL_MASK, .shift = FSL_CHASSIS3_SRDS2_PRTCL_SHIFT }, +#endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + {.id = 3, + .mask = FSL_CHASSIS3_SRDS3_PRTCL_MASK, + .shift = FSL_CHASSIS3_SRDS3_PRTCL_SHIFT + }, #endif {} /* NULL ENTRY */ }; @@ -340,6 +402,11 @@ int setup_serdes_volt(u32 svdd) struct ccsr_serdes __iomem *serdes2_base = (void *)(CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + 0x10000); u32 cfg_rcwsrds2 = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS2_REGSR - 1]); +#endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + struct ccsr_serdes __iomem *serdes3_base = + (void *)(CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + 0x20000); + u32 cfg_rcwsrds3 = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS3_REGSR - 1]); #endif u32 cfg_tmp; int svdd_cur, svdd_tar; @@ -370,6 +437,9 @@ int setup_serdes_volt(u32 svdd) #ifdef CONFIG_SYS_FSL_SRDS_2 do_enabled_lanes_reset(2, cfg_rcwsrds2, serdes2_base, false); #endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + do_enabled_lanes_reset(3, cfg_rcwsrds3, serdes3_base, false); +#endif /* Put the all enabled PLL in reset */ #ifdef CONFIG_SYS_FSL_SRDS_1 @@ -383,6 +453,12 @@ int setup_serdes_volt(u32 svdd) do_pll_reset(cfg_tmp, serdes2_base); #endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + cfg_tmp = cfg_rcwsrds3 & 0x30; + cfg_tmp >>= 4; + do_pll_reset(cfg_tmp, serdes3_base); +#endif + /* Put the Rx/Tx calibration into reset */ #ifdef CONFIG_SYS_FSL_SRDS_1 do_rx_tx_cal_reset(serdes1_base); @@ -392,6 +468,10 @@ int setup_serdes_volt(u32 svdd) do_rx_tx_cal_reset(serdes2_base); #endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + do_rx_tx_cal_reset(serdes3_base); +#endif + ret = set_serdes_volt(svdd); if (ret < 0) { printf("could not change SVDD\n"); @@ -408,6 +488,11 @@ int setup_serdes_volt(u32 svdd) cfg_tmp >>= 2; do_serdes_enable(cfg_tmp, serdes2_base); #endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + cfg_tmp = cfg_rcwsrds3 & 0x30; + cfg_tmp >>= 4; + do_serdes_enable(cfg_tmp, serdes3_base); +#endif /* Wait for at at least 625us, ensure the PLLs being reset are locked */ udelay(800); @@ -422,6 +507,13 @@ int setup_serdes_volt(u32 svdd) cfg_tmp >>= 2; do_pll_lock(cfg_tmp, serdes2_base); #endif + +#ifdef CONFIG_SYS_NXP_SRDS_3 + cfg_tmp = cfg_rcwsrds3 & 0x30; + cfg_tmp >>= 4; + do_pll_lock(cfg_tmp, serdes3_base); +#endif + /* Take the all enabled lanes out of reset */ #ifdef CONFIG_SYS_FSL_SRDS_1 do_enabled_lanes_reset(1, cfg_rcwsrds1, serdes1_base, true); @@ -430,6 +522,10 @@ int setup_serdes_volt(u32 svdd) do_enabled_lanes_reset(2, cfg_rcwsrds2, serdes2_base, true); #endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + do_enabled_lanes_reset(3, cfg_rcwsrds3, serdes3_base, true); +#endif + /* For each PLL being reset, and achieved PLL lock set RST_DONE */ #ifdef CONFIG_SYS_FSL_SRDS_1 cfg_tmp = cfg_rcwsrds1 & 0x3; @@ -441,6 +537,12 @@ int setup_serdes_volt(u32 svdd) do_pll_reset_done(cfg_tmp, serdes2_base); #endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + cfg_tmp = cfg_rcwsrds3 & 0x30; + cfg_tmp >>= 4; + do_pll_reset_done(cfg_tmp, serdes3_base); +#endif + return ret; } @@ -449,12 +551,32 @@ void fsl_serdes_init(void) #if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD) int i , j; +#ifdef CONFIG_ARCH_LX2160A + for (i = XFI1, j = 1; i <= XFI14; i++, j++) + xfi_dpmac[i] = j; + + for (i = SGMII1, j = 1; i <= SGMII18; i++, j++) + sgmii_dpmac[i] = j; + + for (i = _25GE1, j = 1; i <= _25GE10; i++, j++) + a25gaui_dpmac[i] = j; + + for (i = _40GE1, j = 1; i <= _40GE2; i++, j++) + xlaui_dpmac[i] = j; + + for (i = _50GE1, j = 1; i <= _50GE2; i++, j++) + caui2_dpmac[i] = j; + + for (i = _100GE1, j = 1; i <= _100GE2; i++, j++) + caui4_dpmac[i] = j; +#else for (i = XFI1, j = 1; i <= XFI8; i++, j++) xfi_dpmac[i] = j; for (i = SGMII1, j = 1; i <= SGMII16; i++, j++) sgmii_dpmac[i] = j; #endif +#endif #ifdef CONFIG_SYS_FSL_SRDS_1 serdes_init(FSL_SRDS_1, @@ -472,4 +594,71 @@ void fsl_serdes_init(void) FSL_CHASSIS3_SRDS2_PRTCL_SHIFT, serdes2_prtcl_map); #endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + serdes_init(NXP_SRDS_3, + CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + NXP_SRDS_3 * 0x10000, + FSL_CHASSIS3_SRDS3_REGSR, + FSL_CHASSIS3_SRDS3_PRTCL_MASK, + FSL_CHASSIS3_SRDS3_PRTCL_SHIFT, + serdes3_prtcl_map); +#endif +} + +int serdes_set_env(int sd, int rcwsr, int sd_prctl_mask, int sd_prctl_shift) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + char scfg[16], snum[16]; + int cfgr = 0; + u32 cfg; + + cfg = gur_in32(&gur->rcwsr[rcwsr - 1]) & sd_prctl_mask; + cfg >>= sd_prctl_shift; + cfg = serdes_get_number(sd, cfg); + +#if defined(SRDS_BITS_PER_LANE) + /* + * reverse lanes, lane 0 should be printed first so it must be moved to + * high order bits. + * For example bb58 should read 85bb, lane 0 being protocol 8. + * This only applies to SoCs that define SRDS_BITS_PER_LANE and have + * independent per-lane protocol configuration, at this time LS1028A and + * LS1088A. LS2 and LX2 SoCs encode the full protocol mix across all + * lanes as a single value. + */ + for (int i = 0; i < SRDS_MAX_LANES; i++) { + int tmp; + + tmp = cfg >> (i * SRDS_BITS_PER_LANE); + tmp &= GENMASK(SRDS_BITS_PER_LANE - 1, 0); + tmp <<= (SRDS_MAX_LANES - i - 1) * SRDS_BITS_PER_LANE; + cfgr |= tmp; + } +#endif /* SRDS_BITS_PER_LANE */ + + snprintf(snum, 16, "serdes%d", sd); + snprintf(scfg, 16, "%x", cfgr); + env_set(snum, scfg); + + return 0; +} + +int serdes_misc_init(void) +{ +#ifdef CONFIG_SYS_FSL_SRDS_1 + serdes_set_env(FSL_SRDS_1, FSL_CHASSIS3_SRDS1_REGSR, + FSL_CHASSIS3_SRDS1_PRTCL_MASK, + FSL_CHASSIS3_SRDS1_PRTCL_SHIFT); +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + serdes_set_env(FSL_SRDS_2, FSL_CHASSIS3_SRDS2_REGSR, + FSL_CHASSIS3_SRDS2_PRTCL_MASK, + FSL_CHASSIS3_SRDS2_PRTCL_SHIFT); +#endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + serdes_set_env(NXP_SRDS_3, FSL_CHASSIS3_SRDS3_REGSR, + FSL_CHASSIS3_SRDS3_PRTCL_MASK, + FSL_CHASSIS3_SRDS3_PRTCL_SHIFT); +#endif + + return 0; }