diff options
author | Priyanka Jain <priyanka.jain@nxp.com> | 2018-10-29 09:17:09 +0000 |
---|---|---|
committer | York Sun <york.sun@nxp.com> | 2018-12-06 14:37:19 -0800 |
commit | 4909b89ec763f0c7030fa8474f9b6c5df866b01f (patch) | |
tree | 4e2258c0a30e5576116e258d5597aa7168a1facb /arch/arm/cpu/armv8 | |
parent | d6fdec211f7913c97917ba262fa257fdcb6b000e (diff) |
armv8: lx2160a: Add LX2160A SoC Support
LX2160A Soc is based on Layerscape Chassis Generation 3.2
architecture with features:
16 ARM v8 Cortex-A72 cores in 8 cluster, CCN508, SEC,
2 64-bit DDR4 memory controller, RGMII, 8 I2C controllers,
3 serdes modules, USB 3.0, SATA, 4 PL011 SBSA UARTs,
4 TZASC instances, etc.
SoC personalites:
LX2120A is SoC with Twelve 64-bit ARM v8 Cortex-A72 CPUs
LX2080A is SoC with Eight 64-bit ARM v8 Cortex-A72 CPUs
Signed-off-by: Bao Xiaowei <xiaowei.bao@nxp.com>
Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
Signed-off-by: Vabhav Sharma <vabhav.sharma@nxp.com>
Signed-off-by: Sriram Dash <sriram.dash@nxp.com>
Signed-off-by: Priyanka Jain <priyanka.jain@nxp.com>
Reviewed-by: York Sun <york.sun@nxp.com>
Diffstat (limited to 'arch/arm/cpu/armv8')
-rw-r--r-- | arch/arm/cpu/armv8/fsl-layerscape/Kconfig | 52 | ||||
-rw-r--r-- | arch/arm/cpu/armv8/fsl-layerscape/Makefile | 6 | ||||
-rw-r--r-- | arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 15 | ||||
-rw-r--r-- | arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc | 57 | ||||
-rw-r--r-- | arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c | 36 | ||||
-rw-r--r-- | arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S | 2 | ||||
-rw-r--r-- | arch/arm/cpu/armv8/fsl-layerscape/lx2160a_serdes.c | 132 |
7 files changed, 293 insertions, 7 deletions
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig index 650ac94165..2b086da79b 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig +++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig @@ -170,6 +170,42 @@ config ARCH_LS2080A imply DISTRO_DEFAULTS imply PANIC_HANG +config ARCH_LX2160A + bool + select ARMV8_SET_SMPEN + select FSL_LSCH3 + select NXP_LSCH3_2 + select SYS_HAS_SERDES + select SYS_FSL_SRDS_1 + select SYS_FSL_SRDS_2 + select SYS_NXP_SRDS_3 + select SYS_FSL_DDR + select SYS_FSL_DDR_LE + select SYS_FSL_DDR_VER_50 + select SYS_FSL_EC1 + select SYS_FSL_EC2 + select SYS_FSL_HAS_RGMII + select SYS_FSL_HAS_SEC + select SYS_FSL_HAS_CCN508 + select SYS_FSL_HAS_DDR4 + select SYS_FSL_SEC_COMPAT_5 + select SYS_FSL_SEC_LE + select ARCH_EARLY_INIT_R + select BOARD_EARLY_INIT_F + select SYS_I2C_MXC + select SYS_I2C_MXC_I2C1 + select SYS_I2C_MXC_I2C2 + select SYS_I2C_MXC_I2C3 + select SYS_I2C_MXC_I2C4 + select SYS_I2C_MXC_I2C5 + select SYS_I2C_MXC_I2C6 + select SYS_I2C_MXC_I2C7 + select SYS_I2C_MXC_I2C8 + imply DISTRO_DEFAULTS + imply PANIC_HANG + imply SCSI + imply SCSI_AHCI + config FSL_LSCH2 bool select SYS_FSL_HAS_CCI400 @@ -185,7 +221,7 @@ config NXP_LSCH3_2 config FSL_MC_ENET bool "Management Complex network" - depends on ARCH_LS2080A || ARCH_LS1088A + depends on ARCH_LS2080A || ARCH_LS1088A || ARCH_LX2160A default y select RESV_RAM help @@ -202,6 +238,7 @@ config FSL_PCIE_COMPAT default "fsl,ls1046a-pcie" if ARCH_LS1046A default "fsl,ls2080a-pcie" if ARCH_LS2080A default "fsl,ls1088a-pcie" if ARCH_LS1088A + default "fsl,lx2160a-pcie" if ARCH_LX2160A help This compatible is used to find pci controller node in Kernel DT to complete fixup. @@ -300,6 +337,7 @@ config MAX_CPUS default 4 if ARCH_LS1046A default 16 if ARCH_LS2080A default 8 if ARCH_LS1088A + default 16 if ARCH_LX2160A default 1 help Set this number to the maximum number of possible CPUs in the SoC. @@ -342,6 +380,9 @@ config SYS_FSL_HAS_CCI400 config SYS_FSL_HAS_CCN504 bool +config SYS_FSL_HAS_CCN508 + bool + config SYS_FSL_HAS_DP_DDR bool @@ -404,6 +445,7 @@ config SYS_FSL_DSPI_CLK_DIV config SYS_FSL_DUART_CLK_DIV int "DUART clock divider" default 1 if ARCH_LS1043A + default 4 if ARCH_LX2160A default 2 help This is the divider that is used to derive DUART clock from Platform @@ -464,13 +506,15 @@ config RESV_RAM config SYS_FSL_EC1 bool help - Ethernet controller 1, this is connected to MAC3. + Ethernet controller 1, this is connected to + MAC17 for LX2160A or to MAC3 for other SoCs Provides DPAA2 capabilities config SYS_FSL_EC2 bool help - Ethernet controller 2, this is connected to MAC4. + Ethernet controller 2, this is connected to + MAC18 for LX2160A or to MAC4 for other SoCs Provides DPAA2 capabilities config SYS_FSL_ERRATUM_A008336 @@ -506,7 +550,7 @@ config SYS_FSL_HAS_RGMII config SYS_MC_RSV_MEM_ALIGN hex "Management Complex reserved memory alignment" depends on RESV_RAM - default 0x20000000 if ARCH_LS2080A || ARCH_LS1088A + default 0x20000000 if ARCH_LS2080A || ARCH_LS1088A || ARCH_LX2160A help Reserved memory needs to be aligned for MC to use. Default value is 512MB. diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Makefile b/arch/arm/cpu/armv8/fsl-layerscape/Makefile index 91fdbad8be..e9bc987a9c 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/Makefile +++ b/arch/arm/cpu/armv8/fsl-layerscape/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0+ -# +# Copyright 2016-2018 NXP # Copyright 2014-2015, Freescale Semiconductor obj-y += cpu.o @@ -22,6 +22,10 @@ obj-$(CONFIG_SYS_HAS_SERDES) += fsl_lsch2_serdes.o endif endif +ifneq ($(CONFIG_ARCH_LX2160A),) +obj-$(CONFIG_SYS_HAS_SERDES) += lx2160a_serdes.o +endif + ifneq ($(CONFIG_ARCH_LS2080A),) obj-$(CONFIG_SYS_HAS_SERDES) += ls2080a_serdes.o endif diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c index 5c62bcc2e9..1fc025b581 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c @@ -60,6 +60,9 @@ static struct cpu_type cpu_type_list[] = { CPU_TYPE_ENTRY(LS1084A, LS1084A, 8), CPU_TYPE_ENTRY(LS1048A, LS1048A, 4), CPU_TYPE_ENTRY(LS1044A, LS1044A, 4), + CPU_TYPE_ENTRY(LX2160A, LX2160A, 16), + CPU_TYPE_ENTRY(LX2120A, LX2120A, 12), + CPU_TYPE_ENTRY(LX2080A, LX2080A, 8), }; #define EARLY_PGTABLE_SIZE 0x5000 @@ -246,7 +249,7 @@ static struct mm_region final_map[] = { PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN }, -#ifdef CONFIG_ARCH_LS2080A +#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LX2160A) { CONFIG_SYS_PCIE4_PHYS_ADDR, CONFIG_SYS_PCIE4_PHYS_ADDR, CONFIG_SYS_PCIE4_PHYS_SIZE, PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | @@ -366,6 +369,10 @@ void cpu_name(char *name) for (i = 0; i < ARRAY_SIZE(cpu_type_list); i++) if ((cpu_type_list[i].soc_ver & SVR_WO_E) == ver) { strcpy(name, cpu_type_list[i].name); +#ifdef CONFIG_ARCH_LX2160A + if (IS_C_PROCESSOR(svr)) + strcat(name, "C"); +#endif if (IS_E_PROCESSOR(svr)) strcat(name, "E"); @@ -1164,10 +1171,16 @@ void __efi_runtime reset_cpu(ulong addr) { u32 val; +#ifdef CONFIG_ARCH_LX2160A + val = in_le32(rstcr); + val |= 0x01; + out_le32(rstcr, val); +#else /* Raise RESET_REQ_B */ val = scfg_in32(rstcr); val |= 0x02; scfg_out32(rstcr, val); +#endif } #ifdef CONFIG_EFI_LOADER diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc index 276ab9052d..a0e262169e 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc +++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc @@ -7,6 +7,7 @@ SoC overview 5. LS1046A 6. LS2088A 7. LS2081A + 8. LX2160A LS1043A --------- @@ -271,3 +272,59 @@ Refer to LS2084A(LS2088A) section above for details. It has one more similar SoC personality 1)LS2041A, few difference w.r.t. LS2081A: a) Four 64-bit ARM v8 Cortex-A72 CPUs + +LX2160A +-------- +The QorIQ LX2160A processor is built in the 16FFC process on +the Layerscape architecture combining sixteen ARM A72 processor +cores with advanced, high-performance datapath acceleration and +network, peripheral interfaces required for networking, wireless +infrastructure, storage, and general-purpose embedded applications. + +LX2160A is compliant with the Layerscape Chassis Generation 3.2. + +The LX2160A SoC includes the following function and features: + Sixteen 32-bit / 64-bit ARM v8 A72 CPUs + Cache Coherent Interconnect Fabric (CCN508 aka “Eliot”) + Two 64-bit 3.2GT/s DDR4 SDRAM memory controllers with ECC. + Data path acceleration architecture (DPAA2) + 24 Serdes lanes at up to 25 GHz + Ethernet interfaces + Single WRIOP tile supporting 130Gbps using 18 MACs + Support for 10G-SXGMII (aka USXGMII). + Support for SGMII (and 1000Base-KX) + Support for XFI (and 10GBase-KR) + Support for CAUI4 (100G); CAUI2 (50G) and 25G-AUI(25G). + Support for XLAUI (and 40GBase-KR4) for 40G. + Support for two RGMII parallel interfaces. + Energy efficient Ethernet support (802.3az) + IEEE 1588 support. + High-speed peripheral interfaces + Two PCIe Gen 4.0 8-lane controllers supporting SR-IOV, + Four PCIe Gen 4.0 4-lane controllers. + Four serial ATA (SATA 3.0) controllers. + Two USB 3.0 controllers with integrated PHY + Two Enhanced secure digital host controllers + Two Controller Area Network (CAN) modules + Flexible Serial peripheral interface (FlexSPI) controller. + Three Serial peripheral interface (SPI) controllers. + Eight I2C Controllers. + Four PL011 UARTs supporting two 4-pin UART ports or four 2-pin UART ports. + General Purpose IO (GPIO) + Support for hardware virtualization and partitioning (ARM MMU-500) + Support for GIC (ARM GIC-500) + QorIQ platform Trust Architecture 3.0 + One Secure WatchDog timer and one Non-Secure Watchdog timer. + ARM Generic Timer + Two Flextimers + Debug supporting run control, data acquisition, high-speed trace, + performance/event monitoring + Thermal Monitor Unit (TMU) with +/- 2C accuracy + Support for Voltage ID (VID) for yield improvement + +LX2160A SoC has 2 more similar SoC personalities +1)LX2120A, few difference w.r.t. LX2160A: + a) Twelve 64-bit ARM v8 Cortex-A72 CPUs + +2)LX2080A, few difference w.r.t. LX2160A: + a) Eight 64-bit ARM v8 Cortex-A72 CPUs 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 bb50e3d5a7..ab1be3fa54 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c @@ -22,9 +22,18 @@ 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) { @@ -146,6 +155,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: @@ -167,6 +202,7 @@ void serdes_init(u32 sd, u32 sd_addr, u32 rcwsr, u32 sd_prctl_mask, break; } #endif +#endif } } diff --git a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S index cbc9112eb1..6721a579ea 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S +++ b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S @@ -354,7 +354,7 @@ get_svr: ret #endif -#ifdef CONFIG_SYS_FSL_HAS_CCN504 +#if defined(CONFIG_SYS_FSL_HAS_CCN504) || defined(CONFIG_SYS_FSL_HAS_CCN508) hnf_pstate_poll: /* x0 has the desired status, return 0 for success, 1 for timeout * clobber x1, x2, x3, x4, x6, x7 diff --git a/arch/arm/cpu/armv8/fsl-layerscape/lx2160a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/lx2160a_serdes.c new file mode 100644 index 0000000000..a04a370268 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/lx2160a_serdes.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018 NXP + */ + +#include <common.h> +#include <asm/arch/fsl_serdes.h> + +struct serdes_config { + u8 protocol; + u8 lanes[SRDS_MAX_LANES]; +}; + +static struct serdes_config serdes1_cfg_tbl[] = { + /* SerDes 1 */ + {0x01, {PCIE2, PCIE2, PCIE2, PCIE2, PCIE1, PCIE1, PCIE1, PCIE1 } }, + {0x02, {PCIE2, PCIE2, PCIE2, PCIE2, SGMII6, SGMII5, SGMII4, SGMII3 } }, + {0x03, {PCIE2, PCIE2, PCIE2, PCIE2, XFI6, XFI5, XFI4, + XFI3 } }, + {0x04, {SGMII10, SGMII9, SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, + SGMII3 } }, + {0x05, {XFI10, XFI9, XFI8, XFI7, PCIE1, PCIE1, PCIE1, + PCIE1 } }, + {0x06, {SGMII10, SGMII9, SGMII8, SGMII7, SGMII6, SGMII5, XFI4, + XFI3 } }, + {0x07, {SGMII10, SGMII9, SGMII8, SGMII7, XFI6, XFI5, XFI4, + XFI3 } }, + {0x08, {XFI10, XFI9, XFI8, XFI7, XFI6, XFI5, XFI4, XFI3 } }, + {0x09, {SGMII10, SGMII9, SGMII8, PCIE2, SGMII6, SGMII5, SGMII4, + PCIE1 } }, + {0x0A, {XFI10, XFI9, XFI8, PCIE2, XFI6, XFI5, XFI4, PCIE1 } }, + {0x0B, {SGMII10, SGMII9, PCIE2, PCIE2, SGMII6, SGMII5, PCIE1, PCIE1 } }, + {0x0C, {SGMII10, SGMII9, PCIE2, PCIE2, PCIE1, PCIE1, PCIE1, PCIE1 } }, + {0x0D, {_100GE2, _100GE2, _100GE2, _100GE2, _100GE1, _100GE1, _100GE1, + _100GE1 } }, + {0x0E, {PCIE2, PCIE2, PCIE2, PCIE2, _100GE1, _100GE1, _100GE1, + _100GE1 } }, + {0x0F, {PCIE2, PCIE2, PCIE2, PCIE2, _50GE2, _50GE2, _50GE1, _50GE1 } }, + {0x10, {PCIE2, PCIE2, PCIE2, PCIE2, _25GE6, _25GE5, _50GE1, _50GE1 } }, + {0x11, {PCIE2, PCIE2, PCIE2, PCIE2, _25GE6, _25GE5, _25GE4, _25GE3 } }, + {0x12, {XFI10, XFI9, XFI8, XFI7, _25GE6, _25GE5, XFI4, + XFI3 } }, + {0x13, {_40GE2, _40GE2, _40GE2, _40GE2, _25GE6, _25GE5, XFI4, XFI3 } }, + {0x14, {_40GE2, _40GE2, _40GE2, _40GE2, _40GE1, _40GE1, _40GE1, + _40GE1 } }, + {0x15, {_25GE10, _25GE9, PCIE2, PCIE2, _25GE6, _25GE5, _25GE4, + _25GE3 } }, + {0x16, {XFI10, XFI9, PCIE2, PCIE2, XFI6, XFI5, XFI4, XFI3 } }, + {} +}; + +static struct serdes_config serdes2_cfg_tbl[] = { + /* SerDes 2 */ + {0x01, {PCIE3, PCIE3, SATA1, SATA2, PCIE4, PCIE4, PCIE4, PCIE4 } }, + {0x02, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3 } }, + {0x03, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4 } }, + {0x04, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SATA1, SATA2 } }, + {0x05, {PCIE3, PCIE3, PCIE3, PCIE3, SATA3, SATA4, SATA1, SATA2 } }, + {0x06, {PCIE3, PCIE3, PCIE3, PCIE3, SGMII15, SGMII16, XFI13, + XFI14 } }, + {0x07, {PCIE3, SGMII12, SGMII17, SGMII18, PCIE4, SGMII16, XFI13, + XFI14 } }, + {0x08, {NONE, NONE, SATA1, SATA2, SATA3, SATA4, XFI13, XFI14 } }, + {0x09, {SGMII11, SGMII12, SGMII17, SGMII18, SGMII15, SGMII16, SGMII13, + SGMII14} }, + {0x0A, {SGMII11, SGMII12, SGMII17, SGMII18, PCIE4, PCIE4, PCIE4, + PCIE4 } }, + {0x0B, {PCIE3, SGMII12, SGMII17, SGMII18, PCIE4, SGMII16, SGMII13, + SGMII14 } }, + {0x0C, {SGMII11, SGMII12, SGMII17, SGMII18, PCIE4, PCIE4, SATA1, + SATA2 } }, + {0x0D, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SGMII13, SGMII14 } }, + {0x0E, {PCIE3, PCIE3, SGMII17, SGMII18, PCIE4, PCIE4, SGMII13, + SGMII14 } }, + {} +}; + +static struct serdes_config serdes3_cfg_tbl[] = { + /* SerDes 3 */ + {0x02, {PCIE5, PCIE5, PCIE5, PCIE5, PCIE5, PCIE5, PCIE5, PCIE5 } }, + {0x03, {PCIE5, PCIE5, PCIE5, PCIE5, PCIE6, PCIE6, PCIE6, PCIE6 } }, + {} +}; + +static struct serdes_config *serdes_cfg_tbl[] = { + serdes1_cfg_tbl, + serdes2_cfg_tbl, + serdes3_cfg_tbl, +}; + +enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane) +{ + struct serdes_config *ptr; + + if (serdes >= ARRAY_SIZE(serdes_cfg_tbl)) + return 0; + + ptr = serdes_cfg_tbl[serdes]; + while (ptr->protocol) { + if (ptr->protocol == cfg) + return ptr->lanes[lane]; + ptr++; + } + + return 0; +} + +int is_serdes_prtcl_valid(int serdes, u32 prtcl) +{ + int i; + struct serdes_config *ptr; + + if (serdes >= ARRAY_SIZE(serdes_cfg_tbl)) + return 0; + + ptr = serdes_cfg_tbl[serdes]; + while (ptr->protocol) { + if (ptr->protocol == prtcl) + break; + ptr++; + } + + if (!ptr->protocol) + return 0; + + for (i = 0; i < SRDS_MAX_LANES; i++) { + if (ptr->lanes[i] != NONE) + return 1; + } + + return 0; +} |