diff options
164 files changed, 11694 insertions, 713 deletions
@@ -690,6 +690,14 @@ The following options need to be configured: exists, unlike the similar options in the Linux kernel. Do not set these options unless they apply! + COUNTER_FREQUENCY + Generic timer clock source frequency. + + COUNTER_FREQUENCY_REAL + Generic timer clock source frequency if the real clock is + different from COUNTER_FREQUENCY, and can only be determined + at run time. + NOTE: The following can be machine specific errata. These do have ability to provide rudimentary version and machine specific checks, but expect no product checks. @@ -2395,6 +2403,8 @@ CBFS (Coreboot Filesystem) support - define slave for bus 3 with CONFIG_SYS_MXC_I2C3_SLAVE If those defines are not set, default value is 100000 for speed, and 0 for slave. + - enable bus 3 with CONFIG_SYS_I2C_MXC_I2C3 + - enable bus 4 with CONFIG_SYS_I2C_MXC_I2C4 - drivers/i2c/rcar_i2c.c: - activate this driver with CONFIG_SYS_I2C_RCAR @@ -4882,6 +4892,9 @@ Low Level (hardware related) configuration options: - CONFIG_FSL_DDR_SYNC_REFRESH Enable sync of refresh for multiple controllers. +- CONFIG_FSL_DDR_BIST + Enable built-in memory test for Freescale DDR controllers. + - CONFIG_SYS_83XX_DDR_USES_CS0 Only for 83xx systems. If specified, then DDR should be configured using CS0 and CS1 instead of CS2 and CS3. diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index b39bb4f..5f21b59 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -690,6 +690,28 @@ config TARGET_LS2085A_SIMU select ARM64 select ARMV8_MULTIENTRY +config TARGET_LS2085AQDS + bool "Support ls2085aqds" + select ARM64 + select ARMV8_MULTIENTRY + select SUPPORT_SPL + help + Support for Freescale LS2085AQDS platform + The LS2085A Development System (QDS) is a high-performance + development platform that supports the QorIQ LS2085A + Layerscape Architecture processor. + +config TARGET_LS2085ARDB + bool "Support ls2085ardb" + select ARM64 + select ARMV8_MULTIENTRY + select SUPPORT_SPL + help + Support for Freescale LS2085ARDB platform. + The LS2085A Reference design board (RDB) is a high-performance + development platform that supports the QorIQ LS2085A + Layerscape Architecture processor. + config TARGET_LS1021AQDS bool "Support ls1021aqds" select CPU_V7 @@ -849,6 +871,8 @@ source "board/denx/m53evk/Kconfig" source "board/embest/mx6boards/Kconfig" source "board/esg/ima3-mx53/Kconfig" source "board/freescale/ls2085a/Kconfig" +source "board/freescale/ls2085aqds/Kconfig" +source "board/freescale/ls2085ardb/Kconfig" source "board/freescale/ls1021aqds/Kconfig" source "board/freescale/ls1021atwr/Kconfig" source "board/freescale/mx23evk/Kconfig" diff --git a/arch/arm/cpu/armv7/ls102xa/clock.c b/arch/arm/cpu/armv7/ls102xa/clock.c index 8f80c61..7a337e1 100644 --- a/arch/arm/cpu/armv7/ls102xa/clock.c +++ b/arch/arm/cpu/armv7/ls102xa/clock.c @@ -20,7 +20,7 @@ void get_sys_info(struct sys_info *sys_info) { struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); #ifdef CONFIG_FSL_IFC - struct fsl_ifc *ifc_regs = (void *)CONFIG_SYS_IFC_ADDR; + struct fsl_ifc ifc_regs = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL}; u32 ccr; #endif struct ccsr_clk *clk = (void *)(CONFIG_SYS_FSL_LS1_CLK_ADDR); @@ -74,7 +74,7 @@ void get_sys_info(struct sys_info *sys_info) } #if defined(CONFIG_FSL_IFC) - ccr = in_be32(&ifc_regs->ifc_ccr); + ccr = in_be32(&ifc_regs.gregs->ifc_ccr); ccr = ((ccr & IFC_CCR_CLK_DIV_MASK) >> IFC_CCR_CLK_DIV_SHIFT) + 1; sys_info->freq_localbus = sys_info->freq_systembus / ccr; diff --git a/arch/arm/cpu/armv8/fsl-lsch3/Makefile b/arch/arm/cpu/armv8/fsl-lsch3/Makefile index f920eeb..9f7815b 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/Makefile +++ b/arch/arm/cpu/armv8/fsl-lsch3/Makefile @@ -6,6 +6,8 @@ obj-y += cpu.o obj-y += lowlevel.o +obj-y += soc.o obj-y += speed.o +obj-$(CONFIG_SYS_HAS_SERDES) += fsl_lsch3_serdes.o ls2085a_serdes.o obj-$(CONFIG_MP) += mp.o obj-$(CONFIG_OF_LIBFDT) += fdt.o diff --git a/arch/arm/cpu/armv8/fsl-lsch3/README b/arch/arm/cpu/armv8/fsl-lsch3/README index cc47466..37f07fb 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/README +++ b/arch/arm/cpu/armv8/fsl-lsch3/README @@ -8,3 +8,141 @@ Freescale LayerScape with Chassis Generation 3 This architecture supports Freescale ARMv8 SoCs with Chassis generation 3, for example LS2085A. + +Flash Layout +============ + +(1) A typical layout of various images (including Linux and other firmware images) + is shown below considering a 32MB NOR flash device present on most + pre-silicon platforms (simulator and emulator): + + ------------------------- + | FIT Image | + | (linux + DTB + RFS) | + ------------------------- ----> 0x0120_0000 + | Debug Server FW | + ------------------------- ----> 0x00C0_0000 + | AIOP FW | + ------------------------- ----> 0x0070_0000 + | MC FW | + ------------------------- ----> 0x006C_0000 + | MC DPL Blob | + ------------------------- ----> 0x0020_0000 + | BootLoader + Env| + ------------------------- ----> 0x0000_1000 + | PBI | + ------------------------- ----> 0x0000_0080 + | RCW | + ------------------------- ----> 0x0000_0000 + + 32-MB NOR flash layout for pre-silicon platforms (simulator and emulator) + +(2) A typical layout of various images (including Linux and other firmware images) + is shown below considering a 128MB NOR flash device present on QDS and RDB + boards: + ----------------------------------------- ----> 0x5_8800_0000 --- + | .. Unused .. (7M) | | + ----------------------------------------- ----> 0x5_8790_0000 | + | FIT Image (linux + DTB + RFS) (40M) | | + ----------------------------------------- ----> 0x5_8510_0000 | + | PHY firmware (2M) | | + ----------------------------------------- ----> 0x5_84F0_0000 | 64K + | Debug Server FW (2M) | | Alt + ----------------------------------------- ----> 0x5_84D0_0000 | Bank + | AIOP FW (4M) | | + ----------------------------------------- ----> 0x5_8490_0000 (vbank4) + | MC DPC Blob (1M) | | + ----------------------------------------- ----> 0x5_8480_0000 | + | MC DPL Blob (1M) | | + ----------------------------------------- ----> 0x5_8470_0000 | + | MC FW (4M) | | + ----------------------------------------- ----> 0x5_8430_0000 | + | BootLoader Environment (1M) | | + ----------------------------------------- ----> 0x5_8420_0000 | + | BootLoader (1M) | | + ----------------------------------------- ----> 0x5_8410_0000 | + | RCW and PBI (1M) | | + ----------------------------------------- ----> 0x5_8400_0000 --- + | .. Unused .. (7M) | | + ----------------------------------------- ----> 0x5_8390_0000 | + | FIT Image (linux + DTB + RFS) (40M) | | + ----------------------------------------- ----> 0x5_8110_0000 | + | PHY firmware (2M) | | + ----------------------------------------- ----> 0x5_80F0_0000 | 64K + | Debug Server FW (2M) | | Bank + ----------------------------------------- ----> 0x5_80D0_0000 | + | AIOP FW (4M) | | + ----------------------------------------- ----> 0x5_8090_0000 (vbank0) + | MC DPC Blob (1M) | | + ----------------------------------------- ----> 0x5_8080_0000 | + | MC DPL Blob (1M) | | + ----------------------------------------- ----> 0x5_8070_0000 | + | MC FW (4M) | | + ----------------------------------------- ----> 0x5_8030_0000 | + | BootLoader Environment (1M) | | + ----------------------------------------- ----> 0x5_8020_0000 | + | BootLoader (1M) | | + ----------------------------------------- ----> 0x5_8010_0000 | + | RCW and PBI (1M) | | + ----------------------------------------- ----> 0x5_8000_0000 --- + + 128-MB NOR flash layout for QDS and RDB boards + +Environment Variables +===================== +mcboottimeout: MC boot timeout in milliseconds. If this variable is not defined + the value CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS will be assumed. + +mcmemsize: MC DRAM block size. If this variable is not defined, the value + CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE will be assumed. + +Booting from NAND +------------------- +Booting from NAND requires two images, RCW and u-boot-with-spl.bin. +The difference between NAND boot RCW image and NOR boot image is the PBI +command sequence. Below is one example for PBI commands for QDS which uses +NAND device with 2KB/page, block size 128KB. + +1) CCSR 4-byte write to 0x00e00404, data=0x00000000 +2) CCSR 4-byte write to 0x00e00400, data=0x1800a000 +The above two commands set bootloc register to 0x00000000_1800a000 where +the u-boot code will be running in OCRAM. + +3) Block Copy: SRC=0x0107, SRC_ADDR=0x00020000, DEST_ADDR=0x1800a000, +BLOCK_SIZE=0x00014000 +This command copies u-boot image from NAND device into OCRAM. The values need +to adjust accordingly. + +SRC should match the cfg_rcw_src, the reset config pins. It depends + on the NAND device. See reference manual for cfg_rcw_src. +SRC_ADDR is the offset of u-boot-with-spl.bin image in NAND device. In + the example above, 128KB. For easy maintenance, we put it at + the beginning of next block from RCW. +DEST_ADDR is fixed at 0x1800a000, matching bootloc set above. +BLOCK_SIZE is the size to be copied by PBI. + +RCW image should be written to the beginning of NAND device. Example of using +u-boot command + +nand write <rcw image in memory> 0 <size of rcw image> + +To form the NAND image, build u-boot with NAND config, for example, +ls2085aqds_nand_defconfig. The image needed is u-boot-with-spl.bin. +The u-boot image should be written to match SRC_ADDR, in above example 0x20000. + +nand write <u-boot image in memory> 200000 <size of u-boot image> + +With these two images in NAND device, the board can boot from NAND. + +Another example for RDB boards, + +1) CCSR 4-byte write to 0x00e00404, data=0x00000000 +2) CCSR 4-byte write to 0x00e00400, data=0x1800a000 +3) Block Copy: SRC=0x0119, SRC_ADDR=0x00080000, DEST_ADDR=0x1800a000, +BLOCK_SIZE=0x00014000 + +nand write <rcw image in memory> 0 <size of rcw image> +nand write <u-boot image in memory> 80000 <size of u-boot image> + +Notice the difference from QDS is SRC, SRC_ADDR and the offset of u-boot image +to match board NAND device with 4KB/page, block size 512KB. diff --git a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c index 4997487..6714577 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c +++ b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c @@ -10,7 +10,12 @@ #include <asm/armv8/mmu.h> #include <asm/io.h> #include <asm/arch-fsl-lsch3/immap_lsch3.h> +#include <fsl_debug_server.h> #include <fsl-mc/fsl_mc.h> +#include <asm/arch/fsl_serdes.h> +#ifdef CONFIG_FSL_ESDHC +#include <fsl_esdhc.h> +#endif #include "cpu.h" #include "mp.h" #include "speed.h" @@ -24,8 +29,9 @@ DECLARE_GLOBAL_DATA_PTR; * levels of translation tables here to cover 40-bit address space. * We use 4KB granule size, with 40 bits physical address, T0SZ=24 * Level 0 IA[39], table address @0 - * Level 1 IA[31:30], table address @01000, 0x2000 - * Level 2 IA[29:21], table address @0x3000 + * Level 1 IA[31:30], table address @0x1000, 0x2000 + * Level 2 IA[29:21], table address @0x3000, 0x4000 + * Address above 0x5000 is free for other purpose. */ #define SECTION_SHIFT_L0 39UL @@ -60,12 +66,12 @@ static inline void early_mmu_setup(void) { int el; u64 i; - u64 section_l1t0, section_l1t1, section_l2; + u64 section_l1t0, section_l1t1, section_l2t0, section_l2t1; u64 *level0_table = (u64 *)CONFIG_SYS_FSL_OCRAM_BASE; u64 *level1_table_0 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x1000); u64 *level1_table_1 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x2000); - u64 *level2_table = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x3000); - + u64 *level2_table_0 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x3000); + u64 *level2_table_1 = (u64 *)(CONFIG_SYS_FSL_OCRAM_BASE + 0x4000); level0_table[0] = (u64)level1_table_0 | PMD_TYPE_TABLE; @@ -79,21 +85,25 @@ static inline void early_mmu_setup(void) */ section_l1t0 = 0; section_l1t1 = BLOCK_SIZE_L0; - section_l2 = 0; + section_l2t0 = 0; + section_l2t1 = CONFIG_SYS_FLASH_BASE; for (i = 0; i < 512; i++) { set_pgtable_section(level1_table_0, i, section_l1t0, MT_DEVICE_NGNRNE); set_pgtable_section(level1_table_1, i, section_l1t1, MT_NORMAL); - set_pgtable_section(level2_table, i, section_l2, + set_pgtable_section(level2_table_0, i, section_l2t0, + MT_DEVICE_NGNRNE); + set_pgtable_section(level2_table_1, i, section_l2t1, MT_DEVICE_NGNRNE); section_l1t0 += BLOCK_SIZE_L1; section_l1t1 += BLOCK_SIZE_L1; - section_l2 += BLOCK_SIZE_L2; + section_l2t0 += BLOCK_SIZE_L2; + section_l2t1 += BLOCK_SIZE_L2; } level1_table_0[0] = - (u64)level2_table | PMD_TYPE_TABLE; + (u64)level2_table_0 | PMD_TYPE_TABLE; level1_table_0[1] = 0x40000000 | PMD_SECT_AF | PMD_TYPE_SECT | PMD_ATTRINDX(MT_DEVICE_NGNRNE); @@ -104,17 +114,34 @@ static inline void early_mmu_setup(void) 0xc0000000 | PMD_SECT_AF | PMD_TYPE_SECT | PMD_ATTRINDX(MT_NORMAL); - /* Rewrite table to enable cache */ - set_pgtable_section(level2_table, + /* Rewerite table to enable cache for OCRAM */ + set_pgtable_section(level2_table_0, CONFIG_SYS_FSL_OCRAM_BASE >> SECTION_SHIFT_L2, CONFIG_SYS_FSL_OCRAM_BASE, MT_NORMAL); - for (i = CONFIG_SYS_IFC_BASE >> SECTION_SHIFT_L2; - i < (CONFIG_SYS_IFC_BASE + CONFIG_SYS_IFC_SIZE) - >> SECTION_SHIFT_L2; i++) { - section_l2 = i << SECTION_SHIFT_L2; - set_pgtable_section(level2_table, i, - section_l2, MT_NORMAL); + +#if defined(CONFIG_SYS_NOR0_CSPR_EARLY) && defined(CONFIG_SYS_NOR_AMASK_EARLY) + /* Rewrite table to enable cache for two entries (4MB) */ + section_l2t1 = CONFIG_SYS_IFC_BASE; + set_pgtable_section(level2_table_0, + section_l2t1 >> SECTION_SHIFT_L2, + section_l2t1, + MT_NORMAL); + section_l2t1 += BLOCK_SIZE_L2; + set_pgtable_section(level2_table_0, + section_l2t1 >> SECTION_SHIFT_L2, + section_l2t1, + MT_NORMAL); +#endif + + /* Create a mapping for 256MB IFC region to final flash location */ + level1_table_0[CONFIG_SYS_FLASH_BASE >> SECTION_SHIFT_L1] = + (u64)level2_table_1 | PMD_TYPE_TABLE; + section_l2t1 = CONFIG_SYS_IFC_BASE; + for (i = 0; i < 0x10000000 >> SECTION_SHIFT_L2; i++) { + set_pgtable_section(level2_table_1, i, + section_l2t1, MT_DEVICE_NGNRNE); + section_l2t1 += BLOCK_SIZE_L2; } el = current_el(); @@ -347,6 +374,7 @@ u32 fsl_qoriq_core_to_type(unsigned int core) #ifdef CONFIG_DISPLAY_CPUINFO int print_cpuinfo(void) { + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); struct sys_info sysinfo; char buf[32]; unsigned int i, core; @@ -370,21 +398,40 @@ int print_cpuinfo(void) printf(" DP-DDR: %-4s MHz", strmhz(buf, sysinfo.freq_ddrbus2)); puts("\n"); + /* Display the RCW, so that no one gets confused as to what RCW + * we're actually using for this boot. + */ + puts("Reset Configuration Word (RCW):"); + for (i = 0; i < ARRAY_SIZE(gur->rcwsr); i++) { + u32 rcw = in_le32(&gur->rcwsr[i]); + + if ((i % 4) == 0) + printf("\n %02x:", i * 4); + printf(" %08x", rcw); + } + puts("\n"); + return 0; } #endif +#ifdef CONFIG_FSL_ESDHC +int cpu_mmc_init(bd_t *bis) +{ + return fsl_esdhc_mmc_init(bis); +} +#endif + int cpu_eth_init(bd_t *bis) { int error = 0; #ifdef CONFIG_FSL_MC_ENET - error = mc_init(bis); + error = fsl_mc_ldpaa_init(bis); #endif return error; } - int arch_early_init_r(void) { int rv; @@ -393,5 +440,43 @@ int arch_early_init_r(void) if (rv) printf("Did not wake secondary cores\n"); +#ifdef CONFIG_SYS_HAS_SERDES + fsl_serdes_init(); +#endif + return 0; +} + +int timer_init(void) +{ + u32 __iomem *cntcr = (u32 *)CONFIG_SYS_FSL_TIMER_ADDR; + u32 __iomem *cltbenr = (u32 *)CONFIG_SYS_FSL_PMU_CLTBENR; +#ifdef COUNTER_FREQUENCY_REAL + unsigned long cntfrq = COUNTER_FREQUENCY_REAL; + + /* Update with accurate clock frequency */ + asm volatile("msr cntfrq_el0, %0" : : "r" (cntfrq) : "memory"); +#endif + + /* Enable timebase for all clusters. + * It is safe to do so even some clusters are not enabled. + */ + out_le32(cltbenr, 0xf); + + /* Enable clock for timer + * This is a global setting. + */ + out_le32(cntcr, 0x1); + return 0; } + +void reset_cpu(ulong addr) +{ + u32 __iomem *rstcr = (u32 *)CONFIG_SYS_FSL_RST_ADDR; + u32 val; + + /* Raise RESET_REQ_B */ + val = in_le32(rstcr); + val |= 0x02; + out_le32(rstcr, val); +} diff --git a/arch/arm/cpu/armv8/fsl-lsch3/fdt.c b/arch/arm/cpu/armv8/fsl-lsch3/fdt.c index 7eb9b6a..d370023 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/fdt.c +++ b/arch/arm/cpu/armv8/fsl-lsch3/fdt.c @@ -7,6 +7,9 @@ #include <common.h> #include <libfdt.h> #include <fdt_support.h> +#ifdef CONFIG_FSL_ESDHC +#include <fsl_esdhc.h> +#endif #include "mp.h" #ifdef CONFIG_MP @@ -62,7 +65,11 @@ void ft_cpu_setup(void *blob, bd_t *bd) #endif #ifdef CONFIG_SYS_NS16550 - do_fixup_by_compat_u32(blob, "ns16550", + do_fixup_by_compat_u32(blob, "fsl,ns16550", "clock-frequency", CONFIG_SYS_NS16550_CLK, 1); #endif + +#if defined(CONFIG_FSL_ESDHC) + fdt_fixup_esdhc(blob, bd); +#endif } diff --git a/arch/arm/cpu/armv8/fsl-lsch3/fsl_lsch3_serdes.c b/arch/arm/cpu/armv8/fsl-lsch3/fsl_lsch3_serdes.c new file mode 100644 index 0000000..02ca126 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-lsch3/fsl_lsch3_serdes.c @@ -0,0 +1,115 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/arch/fsl_serdes.h> +#include <asm/arch-fsl-lsch3/immap_lsch3.h> +#include <fsl-mc/ldpaa_wriop.h> + +#ifdef CONFIG_SYS_FSL_SRDS_1 +static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT]; +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 +static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT]; +#endif + +int is_serdes_configured(enum srds_prtcl device) +{ + int ret = 0; + +#ifdef CONFIG_SYS_FSL_SRDS_1 + ret |= serdes1_prtcl_map[device]; +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + ret |= serdes2_prtcl_map[device]; +#endif + + return !!ret; +} + +int serdes_get_first_lane(u32 sd, enum srds_prtcl device) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + u32 cfg = in_le32(&gur->rcwsr[28]); + int i; + + switch (sd) { +#ifdef CONFIG_SYS_FSL_SRDS_1 + case FSL_SRDS_1: + cfg &= FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK; + cfg >>= FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT; + break; +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + case FSL_SRDS_2: + cfg &= FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK; + cfg >>= FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT; + break; +#endif + default: + printf("invalid SerDes%d\n", sd); + break; + } + /* Is serdes enabled at all? */ + if (cfg == 0) + return -ENODEV; + + for (i = 0; i < SRDS_MAX_LANES; i++) { + if (serdes_get_prtcl(sd, cfg, i) == device) + return i; + } + + return -ENODEV; +} + +void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift, + u8 serdes_prtcl_map[SERDES_PRCTL_COUNT]) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + u32 cfg; + int lane; + + memset(serdes_prtcl_map, 0, sizeof(serdes_prtcl_map)); + + cfg = in_le32(&gur->rcwsr[28]) & sd_prctl_mask; + cfg >>= sd_prctl_shift; + printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg); + + if (!is_serdes_prtcl_valid(sd, cfg)) + printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg); + + for (lane = 0; lane < SRDS_MAX_LANES; lane++) { + enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane); + if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT)) + debug("Unknown SerDes lane protocol %d\n", lane_prtcl); + else { + serdes_prtcl_map[lane_prtcl] = 1; +#ifdef CONFIG_FSL_MC_ENET + wriop_init_dpmac(sd, lane + 1, (int)lane_prtcl); +#endif + } + } +} + +void fsl_serdes_init(void) +{ +#ifdef CONFIG_SYS_FSL_SRDS_1 + serdes_init(FSL_SRDS_1, + CONFIG_SYS_FSL_LSCH3_SERDES_ADDR, + FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK, + FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT, + serdes1_prtcl_map); +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + serdes_init(FSL_SRDS_2, + CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + FSL_SRDS_2 * 0x10000, + FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK, + FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT, + serdes2_prtcl_map); +#endif +} diff --git a/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S b/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S index 886576e..018c617 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S +++ b/arch/arm/cpu/armv8/fsl-lsch3/lowlevel.S @@ -15,6 +15,15 @@ ENTRY(lowlevel_init) mov x29, lr /* Save LR */ + /* Add fully-coherent masters to DVM domain */ + ldr x1, =CCI_MN_BASE + ldr x2, [x1, #CCI_MN_RNF_NODEID_LIST] + str x2, [x1, #CCI_MN_DVM_DOMAIN_CTL_SET] +1: ldr x3, [x1, #CCI_MN_DVM_DOMAIN_CTL_SET] + mvn x0, x3 + tst x0, x3 /* Wait for domain addition to complete */ + b.ne 1b + /* Set the SMMU page size in the sACR register */ ldr x1, =SMMU_BASE ldr w0, [x1, #0x10] @@ -224,6 +233,9 @@ ENTRY(secondary_boot_func) /* physical address of this cpus spin table element */ add x11, x1, x0 + ldr x0, =__real_cntfrq + ldr x0, [x0] + msr cntfrq_el0, x0 /* set with real frequency */ str x9, [x11, #16] /* LPID */ mov x4, #1 str x4, [x11, #8] /* STATUS */ @@ -275,6 +287,9 @@ ENDPROC(secondary_switch_to_el1) /* 64 bit alignment for elements accessed as data */ .align 4 + .global __real_cntfrq +__real_cntfrq: + .quad COUNTER_FREQUENCY .globl __secondary_boot_code_size .type __secondary_boot_code_size, %object /* Secondary Boot Code ends here */ diff --git a/arch/arm/cpu/armv8/fsl-lsch3/ls2085a_serdes.c b/arch/arm/cpu/armv8/fsl-lsch3/ls2085a_serdes.c new file mode 100644 index 0000000..098745b --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-lsch3/ls2085a_serdes.c @@ -0,0 +1,117 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/fsl_serdes.h> +#include <asm/arch-fsl-lsch3/immap_lsch3.h> + +struct serdes_config { + u8 protocol; + u8 lanes[SRDS_MAX_LANES]; +}; + +static struct serdes_config serdes1_cfg_tbl[] = { + /* SerDes 1 */ + {0x03, {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2 } }, + {0x05, {PCIE2, PCIE2, PCIE2, PCIE2, SGMII4, SGMII3, SGMII2, SGMII1 } }, + {0x07, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2, + SGMII1 } }, + {0x09, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2, + SGMII1 } }, + {0x0A, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2, + SGMII1 } }, + {0x0C, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2, + SGMII1 } }, + {0x0E, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2, + SGMII1 } }, + {0x26, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, XFI2, XFI1 } }, + {0x28, {SGMII8, SGMII7, SGMII6, SGMII5, XFI4, XFI3, XFI2, XFI1 } }, + {0x2A, {XFI8, XFI7, XFI6, XFI5, XFI4, XFI3, XFI2, XFI1 } }, + {0x2B, {SGMII8, SGMII7, SGMII6, SGMII5, XAUI1, XAUI1, XAUI1, XAUI1 } }, + {0x32, {XAUI2, XAUI2, XAUI2, XAUI2, XAUI1, XAUI1, XAUI1, XAUI1 } }, + {0x33, {PCIE2, PCIE2, PCIE2, PCIE2, QSGMII_D, QSGMII_C, QSGMII_B, + QSGMII_A} }, + {0x35, {QSGMII_D, QSGMII_C, QSGMII_B, PCIE2, XFI4, XFI3, XFI2, XFI1 } }, + {} +}; +static struct serdes_config serdes2_cfg_tbl[] = { + /* SerDes 2 */ + {0x07, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15, + SGMII16 } }, + {0x09, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15, + SGMII16 } }, + {0x0A, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15, + SGMII16 } }, + {0x0C, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15, + SGMII16 } }, + {0x0E, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15, + SGMII16 } }, + {0x3D, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3 } }, + {0x3E, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3 } }, + {0x3F, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4 } }, + {0x40, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4 } }, + {0x41, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SATA1, SATA2 } }, + {0x42, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SATA1, SATA2 } }, + {0x43, {PCIE3, PCIE3, PCIE3, PCIE3, NONE, NONE, SATA1, SATA2 } }, + {0x44, {PCIE3, PCIE3, PCIE3, PCIE3, NONE, NONE, SATA1, SATA2 } }, + {0x45, {PCIE3, SGMII10, SGMII11, SGMII12, PCIE4, SGMII14, SGMII15, + SGMII16 } }, + {0x47, {SGMII9, SGMII10, SGMII11, SGMII12, PCIE4, PCIE4, PCIE4, + PCIE4 } }, + {0x49, {SGMII9, SGMII10, SGMII11, SGMII12, PCIE4, PCIE4, SATA1, + SATA2 } }, + {0x4A, {SGMII9, SGMII10, SGMII11, SGMII12, PCIE4, PCIE4, SATA1, + SATA2 } }, + {} +}; + +static struct serdes_config *serdes_cfg_tbl[] = { + serdes1_cfg_tbl, + serdes2_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; +} diff --git a/arch/arm/cpu/armv8/fsl-lsch3/mp.c b/arch/arm/cpu/armv8/fsl-lsch3/mp.c index ce9c0c1..da7853a 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/mp.c +++ b/arch/arm/cpu/armv8/fsl-lsch3/mp.c @@ -31,6 +31,13 @@ int fsl_lsch3_wake_seconday_cores(void) int i, timeout = 10; u64 *table = get_spin_tbl_addr(); +#ifdef COUNTER_FREQUENCY_REAL + /* update for secondary cores */ + __real_cntfrq = COUNTER_FREQUENCY_REAL; + flush_dcache_range((unsigned long)&__real_cntfrq, + (unsigned long)&__real_cntfrq + 8); +#endif + cores = cpu_mask(); /* Clear spin table so that secondary processors * observe the correct value after waking up from wfe. diff --git a/arch/arm/cpu/armv8/fsl-lsch3/mp.h b/arch/arm/cpu/armv8/fsl-lsch3/mp.h index 66144d6..c985d6a 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/mp.h +++ b/arch/arm/cpu/armv8/fsl-lsch3/mp.h @@ -26,6 +26,7 @@ #define id_to_core(x) ((x & 3) | (x >> 6)) #ifndef __ASSEMBLY__ extern u64 __spin_table[]; +extern u64 __real_cntfrq; extern u64 *secondary_boot_code; extern size_t __secondary_boot_code_size; int fsl_lsch3_wake_seconday_cores(void); diff --git a/arch/arm/cpu/armv8/fsl-lsch3/soc.c b/arch/arm/cpu/armv8/fsl-lsch3/soc.c new file mode 100644 index 0000000..2538001 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-lsch3/soc.c @@ -0,0 +1,107 @@ +/* + * Copyright 2015 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <fsl_ifc.h> +#include <nand.h> +#include <spl.h> +#include <asm/arch-fsl-lsch3/soc.h> +#include <asm/io.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; + +static void erratum_a008751(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A008751 + u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE; + + writel(0x27672b2a, scfg + SCFG_USB3PRM1CR / 4); +#endif +} + +static void erratum_rcw_src(void) +{ +#if defined(CONFIG_SPL) + u32 __iomem *dcfg_ccsr = (u32 __iomem *)DCFG_BASE; + u32 __iomem *dcfg_dcsr = (u32 __iomem *)DCFG_DCSR_BASE; + u32 val; + + val = in_le32(dcfg_ccsr + DCFG_PORSR1 / 4); + val &= ~DCFG_PORSR1_RCW_SRC; + val |= DCFG_PORSR1_RCW_SRC_NOR; + out_le32(dcfg_dcsr + DCFG_DCSR_PORCR1 / 4, val); +#endif +} + +#define I2C_DEBUG_REG 0x6 +#define I2C_GLITCH_EN 0x8 +/* + * This erratum requires setting glitch_en bit to enable + * digital glitch filter to improve clock stability. + */ +static void erratum_a009203(void) +{ + u8 __iomem *ptr; +#ifdef CONFIG_SYS_I2C +#ifdef I2C1_BASE_ADDR + ptr = (u8 __iomem *)(I2C1_BASE_ADDR + I2C_DEBUG_REG); + + writeb(I2C_GLITCH_EN, ptr); +#endif +#ifdef I2C2_BASE_ADDR + ptr = (u8 __iomem *)(I2C2_BASE_ADDR + I2C_DEBUG_REG); + + writeb(I2C_GLITCH_EN, ptr); +#endif +#ifdef I2C3_BASE_ADDR + ptr = (u8 __iomem *)(I2C3_BASE_ADDR + I2C_DEBUG_REG); + + writeb(I2C_GLITCH_EN, ptr); +#endif +#ifdef I2C4_BASE_ADDR + ptr = (u8 __iomem *)(I2C4_BASE_ADDR + I2C_DEBUG_REG); + + writeb(I2C_GLITCH_EN, ptr); +#endif +#endif +} + +void fsl_lsch3_early_init_f(void) +{ + erratum_a008751(); + erratum_rcw_src(); + init_early_memctl_regs(); /* tighten IFC timing */ + erratum_a009203(); +} + +#ifdef CONFIG_SPL_BUILD +void board_init_f(ulong dummy) +{ + /* Clear global data */ + memset((void *)gd, 0, sizeof(gd_t)); + + arch_cpu_init(); + board_early_init_f(); + timer_init(); + env_init(); + gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE); + + serial_init(); + console_init_f(); + dram_init(); + + /* Clear the BSS. */ + memset(__bss_start, 0, __bss_end - __bss_start); + + board_init_r(NULL, 0); +} + +u32 spl_boot_device(void) +{ + return BOOT_DEVICE_NAND; +} +#endif diff --git a/arch/arm/cpu/armv8/fsl-lsch3/speed.c b/arch/arm/cpu/armv8/fsl-lsch3/speed.c index 72cd999..cac4f92 100644 --- a/arch/arm/cpu/armv8/fsl-lsch3/speed.c +++ b/arch/arm/cpu/armv8/fsl-lsch3/speed.c @@ -26,7 +26,7 @@ void get_sys_info(struct sys_info *sys_info) { struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); #ifdef CONFIG_FSL_IFC - struct fsl_ifc *ifc_regs = (void *)CONFIG_SYS_IFC_ADDR; + struct fsl_ifc ifc_regs = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL}; u32 ccr; #endif struct ccsr_clk_cluster_group __iomem *clk_grp[2] = { @@ -86,6 +86,8 @@ void get_sys_info(struct sys_info *sys_info) sys_info->freq_systembus *= (in_le32(&gur->rcwsr[0]) >> FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_SHIFT) & FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_MASK; + /* Platform clock is half of platform PLL */ + sys_info->freq_systembus /= 2; sys_info->freq_ddrbus *= (in_le32(&gur->rcwsr[0]) >> FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_SHIFT) & FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_MASK; @@ -102,10 +104,7 @@ void get_sys_info(struct sys_info *sys_info) offsetof(struct ccsr_clk_cluster_group, pllngsr[i%3].gsr)); ratio[i] = (in_le32(offset) >> 1) & 0x3f; - if (ratio[i] > 4) - freq_c_pll[i] = sysclk * ratio[i]; - else - freq_c_pll[i] = sys_info->freq_systembus * ratio[i]; + freq_c_pll[i] = sysclk * ratio[i]; } for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) { @@ -119,7 +118,7 @@ void get_sys_info(struct sys_info *sys_info) } #if defined(CONFIG_FSL_IFC) - ccr = in_le32(&ifc_regs->ifc_ccr); + ccr = in_le32(&ifc_regs.gregs->ifc_ccr); ccr = ((ccr & IFC_CCR_CLK_DIV_MASK) >> IFC_CCR_CLK_DIV_SHIFT) + 1; sys_info->freq_localbus = sys_info->freq_systembus / ccr; diff --git a/arch/arm/cpu/armv8/generic_timer.c b/arch/arm/cpu/armv8/generic_timer.c index 223b95e..8e60bae 100644 --- a/arch/arm/cpu/armv8/generic_timer.c +++ b/arch/arm/cpu/armv8/generic_timer.c @@ -25,7 +25,18 @@ unsigned long get_tbclk(void) unsigned long timer_read_counter(void) { unsigned long cntpct; +#ifdef CONFIG_SYS_FSL_ERRATUM_A008585 + /* This erratum number needs to be confirmed to match ARM document */ + unsigned long temp; +#endif isb(); asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct)); +#ifdef CONFIG_SYS_FSL_ERRATUM_A008585 + asm volatile("mrs %0, cntpct_el0" : "=r" (temp)); + while (temp != cntpct) { + asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct)); + asm volatile("mrs %0, cntpct_el0" : "=r" (temp)); + } +#endif return cntpct; } diff --git a/arch/arm/cpu/armv8/u-boot-spl.lds b/arch/arm/cpu/armv8/u-boot-spl.lds new file mode 100644 index 0000000..4df339c --- /dev/null +++ b/arch/arm/cpu/armv8/u-boot-spl.lds @@ -0,0 +1,77 @@ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * Aneesh V <aneesh@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE, + LENGTH = CONFIG_SPL_MAX_SIZE } +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(_start) +SECTIONS +{ + .text : { + . = ALIGN(8); + *(.__image_copy_start) + CPUDIR/start.o (.text*) + *(.text*) + } >.sram + + .rodata : { + . = ALIGN(8); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) + } >.sram + + .data : { + . = ALIGN(8); + *(.data*) + } >.sram + + .u_boot_list : { + . = ALIGN(8); + KEEP(*(SORT(.u_boot_list*))); + } >.sram + + .image_copy_end : { + . = ALIGN(8); + *(.__image_copy_end) + } >.sram + + .end : { + . = ALIGN(8); + *(.__end) + } >.sram + + .bss_start : { + . = ALIGN(8); + KEEP(*(.__bss_start)); + } >.sdram + + .bss : { + *(.bss*) + . = ALIGN(8); + } >.sdram + + .bss_end : { + KEEP(*(.__bss_end)); + } >.sdram + + /DISCARD/ : { *(.dynsym) } + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } +} diff --git a/arch/arm/include/asm/arch-fsl-lsch3/config.h b/arch/arm/include/asm/arch-fsl-lsch3/config.h index b140c1f..ca8d38c 100644 --- a/arch/arm/include/asm/arch-fsl-lsch3/config.h +++ b/arch/arm/include/asm/arch-fsl-lsch3/config.h @@ -8,6 +8,14 @@ #define _ASM_ARMV8_FSL_LSCH3_CONFIG_ #include <fsl_ddrc_version.h> + +#define CONFIG_SYS_PAGE_SIZE 0x10000 + +#ifndef L1_CACHE_BYTES +#define L1_CACHE_SHIFT 6 +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) +#endif + #define CONFIG_MP #define CONFIG_SYS_FSL_OCRAM_BASE 0x18000000 /* initial RAM */ /* Link Definitions */ @@ -23,6 +31,7 @@ #define CONFIG_SYS_FSL_CH3_CLK_GRPA_ADDR (CONFIG_SYS_IMMR + 0x00300000) #define CONFIG_SYS_FSL_CH3_CLK_GRPB_ADDR (CONFIG_SYS_IMMR + 0x00310000) #define CONFIG_SYS_FSL_CH3_CLK_CTRL_ADDR (CONFIG_SYS_IMMR + 0x00370000) +#define CONFIG_SYS_FSL_ESDHC_ADDR (CONFIG_SYS_IMMR + 0x01140000) #define CONFIG_SYS_IFC_ADDR (CONFIG_SYS_IMMR + 0x01240000) #define CONFIG_SYS_NS16550_COM1 (CONFIG_SYS_IMMR + 0x011C0500) #define CONFIG_SYS_NS16550_COM2 (CONFIG_SYS_IMMR + 0x011C0600) @@ -30,6 +39,20 @@ #define CONFIG_SYS_FSL_PMU_CLTBENR (CONFIG_SYS_FSL_PMU_ADDR + \ 0x18A0) +#define CONFIG_SYS_FSL_WRIOP1_ADDR (CONFIG_SYS_IMMR + 0x7B80000) +#define CONFIG_SYS_FSL_WRIOP1_MDIO1 (CONFIG_SYS_FSL_WRIOP1_ADDR + 0x16000) +#define CONFIG_SYS_FSL_WRIOP1_MDIO2 (CONFIG_SYS_FSL_WRIOP1_ADDR + 0x17000) +#define CONFIG_SYS_FSL_LSCH3_SERDES_ADDR (CONFIG_SYS_IMMR + 0xEA0000) + +/* SP (Cortex-A5) related */ +#define CONFIG_SYS_FSL_SP_ADDR (CONFIG_SYS_IMMR + 0x00F00000) +#define CONFIG_SYS_FSL_SP_VSG_GIC_ADDR (CONFIG_SYS_FSL_SP_ADDR) +#define CONFIG_SYS_FSL_SP_VSG_GIC_VIGR1 (CONFIG_SYS_FSL_SP_ADDR) +#define CONFIG_SYS_FSL_SP_VSG_GIC_VIGR2 \ + (CONFIG_SYS_FSL_SP_ADDR + 0x0008) +#define CONFIG_SYS_FSL_SP_LOOPBACK_DUART \ + (CONFIG_SYS_FSL_SP_ADDR + 0x1000) + #define CONFIG_SYS_FSL_DCSR_DDR_ADDR 0x70012c000ULL #define CONFIG_SYS_FSL_DCSR_DDR2_ADDR 0x70012d000ULL #define CONFIG_SYS_FSL_DCSR_DDR3_ADDR 0x700132000ULL @@ -88,22 +111,57 @@ #define CONFIG_MAX_MEM_MAPPED CONFIG_SYS_LS2_DDR_BLOCK1_SIZE #define CONFIG_SYS_FSL_DDR_VER FSL_DDR_VER_5_0 - +#define CONFIG_SYS_FSL_ESDHC_LE /* IFC */ #define CONFIG_SYS_FSL_IFC_LE +#define CONFIG_SYS_MEMAC_LITTLE_ENDIAN + +/* PCIe */ +#define CONFIG_SYS_PCIE1_ADDR (CONFIG_SYS_IMMR + 0x2400000) +#define CONFIG_SYS_PCIE2_ADDR (CONFIG_SYS_IMMR + 0x2500000) +#define CONFIG_SYS_PCIE3_ADDR (CONFIG_SYS_IMMR + 0x2600000) +#define CONFIG_SYS_PCIE4_ADDR (CONFIG_SYS_IMMR + 0x2700000) +#define CONFIG_SYS_PCIE1_PHYS_ADDR 0x1000000000ULL +#define CONFIG_SYS_PCIE2_PHYS_ADDR 0x1200000000ULL +#define CONFIG_SYS_PCIE3_PHYS_ADDR 0x1400000000ULL +#define CONFIG_SYS_PCIE4_PHYS_ADDR 0x1600000000ULL + +/* Cache Coherent Interconnect */ +#define CCI_MN_BASE 0x04000000 +#define CCI_MN_RNF_NODEID_LIST 0x180 +#define CCI_MN_DVM_DOMAIN_CTL 0x200 +#define CCI_MN_DVM_DOMAIN_CTL_SET 0x210 + +/* Device Configuration */ +#define DCFG_BASE 0x01e00000 +#define DCFG_PORSR1 0x000 +#define DCFG_PORSR1_RCW_SRC 0xff800000 +#define DCFG_PORSR1_RCW_SRC_NOR 0x12f00000 + +#define DCFG_DCSR_BASE 0X700100000ULL +#define DCFG_DCSR_PORCR1 0x000 + +/* Supplemental Configuration */ +#define SCFG_BASE 0x01fc0000 +#define SCFG_USB3PRM1CR 0x000 #ifdef CONFIG_LS2085A #define CONFIG_MAX_CPUS 16 #define CONFIG_SYS_FSL_IFC_BANK_COUNT 8 #define CONFIG_NUM_DDR_CONTROLLERS 3 #define CONFIG_SYS_FSL_CLUSTER_CLOCKS { 1, 1, 4, 4 } +#define CONFIG_SYS_FSL_SRDS_1 +#define CONFIG_SYS_FSL_SRDS_2 #else #error SoC not defined #endif #ifdef CONFIG_LS2085A #define CONFIG_SYS_FSL_ERRATUM_A008336 +#define CONFIG_SYS_FSL_ERRATUM_A008511 #define CONFIG_SYS_FSL_ERRATUM_A008514 +#define CONFIG_SYS_FSL_ERRATUM_A008585 +#define CONFIG_SYS_FSL_ERRATUM_A008751 #endif #endif /* _ASM_ARMV8_FSL_LSCH3_CONFIG_ */ diff --git a/arch/arm/include/asm/arch-fsl-lsch3/fsl_serdes.h b/arch/arm/include/asm/arch-fsl-lsch3/fsl_serdes.h new file mode 100644 index 0000000..2810f3f --- /dev/null +++ b/arch/arm/include/asm/arch-fsl-lsch3/fsl_serdes.h @@ -0,0 +1,67 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __FSL_SERDES_H +#define __FSL_SERDES_H + +#include <config.h> + +#define SRDS_MAX_LANES 8 + +enum srds_prtcl { + NONE = 0, + PCIE1, + PCIE2, + PCIE3, + PCIE4, + SATA1, + SATA2, + XAUI1, + XAUI2, + XFI1, + XFI2, + XFI3, + XFI4, + XFI5, + XFI6, + XFI7, + XFI8, + SGMII1, + SGMII2, + SGMII3, + SGMII4, + SGMII5, + SGMII6, + SGMII7, + SGMII8, + SGMII9, + SGMII10, + SGMII11, + SGMII12, + SGMII13, + SGMII14, + SGMII15, + SGMII16, + QSGMII_A, /* A indicates MACs 1-4 */ + QSGMII_B, /* B indicates MACs 5-8 */ + QSGMII_C, /* C indicates MACs 9-12 */ + QSGMII_D, /* D indicates MACs 12-16 */ + SERDES_PRCTL_COUNT +}; + +enum srds { + FSL_SRDS_1 = 0, + FSL_SRDS_2 = 1, +}; + +int is_serdes_configured(enum srds_prtcl device); +void fsl_serdes_init(void); + +int serdes_get_first_lane(u32 sd, enum srds_prtcl device); +enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane); +int is_serdes_prtcl_valid(int serdes, u32 prtcl); + +#endif /* __FSL_SERDES_H */ diff --git a/arch/arm/include/asm/arch-fsl-lsch3/immap_lsch3.h b/arch/arm/include/asm/arch-fsl-lsch3/immap_lsch3.h index dd11ef7..d6bee60 100644 --- a/arch/arm/include/asm/arch-fsl-lsch3/immap_lsch3.h +++ b/arch/arm/include/asm/arch-fsl-lsch3/immap_lsch3.h @@ -47,6 +47,30 @@ struct ccsr_gur { u32 devdisr5; /* Device disable control 5 */ u32 devdisr6; /* Device disable control 6 */ u32 devdisr7; /* Device disable control 7 */ +#define FSL_CHASSIS3_DEVDISR2_DPMAC1 0x00000001 +#define FSL_CHASSIS3_DEVDISR2_DPMAC2 0x00000002 +#define FSL_CHASSIS3_DEVDISR2_DPMAC3 0x00000004 +#define FSL_CHASSIS3_DEVDISR2_DPMAC4 0x00000008 +#define FSL_CHASSIS3_DEVDISR2_DPMAC5 0x00000010 +#define FSL_CHASSIS3_DEVDISR2_DPMAC6 0x00000020 +#define FSL_CHASSIS3_DEVDISR2_DPMAC7 0x00000040 +#define FSL_CHASSIS3_DEVDISR2_DPMAC8 0x00000080 +#define FSL_CHASSIS3_DEVDISR2_DPMAC9 0x00000100 +#define FSL_CHASSIS3_DEVDISR2_DPMAC10 0x00000200 +#define FSL_CHASSIS3_DEVDISR2_DPMAC11 0x00000400 +#define FSL_CHASSIS3_DEVDISR2_DPMAC12 0x00000800 +#define FSL_CHASSIS3_DEVDISR2_DPMAC13 0x00001000 +#define FSL_CHASSIS3_DEVDISR2_DPMAC14 0x00002000 +#define FSL_CHASSIS3_DEVDISR2_DPMAC15 0x00004000 +#define FSL_CHASSIS3_DEVDISR2_DPMAC16 0x00008000 +#define FSL_CHASSIS3_DEVDISR2_DPMAC17 0x00010000 +#define FSL_CHASSIS3_DEVDISR2_DPMAC18 0x00020000 +#define FSL_CHASSIS3_DEVDISR2_DPMAC19 0x00040000 +#define FSL_CHASSIS3_DEVDISR2_DPMAC20 0x00080000 +#define FSL_CHASSIS3_DEVDISR2_DPMAC21 0x00100000 +#define FSL_CHASSIS3_DEVDISR2_DPMAC22 0x00200000 +#define FSL_CHASSIS3_DEVDISR2_DPMAC23 0x00400000 +#define FSL_CHASSIS3_DEVDISR2_DPMAC24 0x00800000 u8 res_08c[0x90-0x8c]; u32 coredisru; /* uppper portion for support of 64 cores */ u32 coredisrl; /* lower portion for support of 64 cores */ @@ -63,6 +87,11 @@ struct ccsr_gur { #define FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_MASK 0x3f #define FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_SHIFT 18 #define FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_MASK 0x3f +#define FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK 0x00FF0000 +#define FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT 16 +#define FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK 0xFF000000 +#define FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT 24 + u8 res_180[0x200-0x180]; u32 scratchrw[32]; /* Scratch Read/Write */ u8 res_280[0x300-0x280]; diff --git a/arch/arm/include/asm/arch-fsl-lsch3/soc.h b/arch/arm/include/asm/arch-fsl-lsch3/soc.h new file mode 100644 index 0000000..16b723d --- /dev/null +++ b/arch/arm/include/asm/arch-fsl-lsch3/soc.h @@ -0,0 +1,8 @@ +/* + * Copyright 2015 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +void fsl_lsch3_early_init_f(void); + diff --git a/arch/arm/include/asm/arch-ls102xa/config.h b/arch/arm/include/asm/arch-ls102xa/config.h index 6561ce6..4dc528b 100644 --- a/arch/arm/include/asm/arch-ls102xa/config.h +++ b/arch/arm/include/asm/arch-ls102xa/config.h @@ -119,10 +119,6 @@ #define DCU_LAYER_MAX_NUM 16 -#define QE_MURAM_SIZE 0x6000UL -#define MAX_QE_RISC 1 -#define QE_NUM_OF_SNUM 28 - #define CONFIG_SYS_FSL_SRDS_1 #ifdef CONFIG_LS102XA diff --git a/arch/arm/include/asm/arch-ls102xa/immap_ls102xa.h b/arch/arm/include/asm/arch-ls102xa/immap_ls102xa.h index 3a64afc..a8122c1 100644 --- a/arch/arm/include/asm/arch-ls102xa/immap_ls102xa.h +++ b/arch/arm/include/asm/arch-ls102xa/immap_ls102xa.h @@ -17,6 +17,9 @@ #define SOC_VER_LS1021 0x11 #define SOC_VER_LS1022 0x12 +#define SOC_MAJOR_VER_1_0 0x1 +#define SOC_MAJOR_VER_2_0 0x2 + #define CCSR_BRR_OFFSET 0xe4 #define CCSR_SCRATCHRW1_OFFSET 0x200 diff --git a/arch/arm/include/asm/fsl_secure_boot.h b/arch/arm/include/asm/fsl_secure_boot.h new file mode 100644 index 0000000..f097c81 --- /dev/null +++ b/arch/arm/include/asm/fsl_secure_boot.h @@ -0,0 +1,25 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __FSL_SECURE_BOOT_H +#define __FSL_SECURE_BOOT_H + +#ifdef CONFIG_SECURE_BOOT +#ifndef CONFIG_FIT_SIGNATURE + +#define CONFIG_EXTRA_ENV \ + "setenv fdt_high 0xcfffffff;" \ + "setenv initrd_high 0xcfffffff;" \ + "setenv hwconfig \'fsl_ddr:ctlr_intlv=null,bank_intlv=null\';" + +/* The address needs to be modified according to NOR memory map */ +#define CONFIG_BOOTSCRIPT_HDR_ADDR 0x600a0000 + +#include <config_fsl_secboot.h> +#endif +#endif + +#endif diff --git a/arch/arm/include/asm/pcie_layerscape.h b/arch/arm/include/asm/pcie_layerscape.h deleted file mode 100644 index fb08578..0000000 --- a/arch/arm/include/asm/pcie_layerscape.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright 2014 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __PCIE_LAYERSCAPE_H_ -#define __PCIE_LAYERSCAPE_H_ - -void pci_init_board(void); -void ft_pcie_setup(void *blob, bd_t *bd); - -#endif diff --git a/arch/arm/lib/crt0_64.S b/arch/arm/lib/crt0_64.S index 1654011..bc9c53c 100644 --- a/arch/arm/lib/crt0_64.S +++ b/arch/arm/lib/crt0_64.S @@ -61,7 +61,11 @@ ENTRY(_main) /* * Set up initial C runtime environment and call board_init_f(0). */ +#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) + ldr x0, =(CONFIG_SPL_STACK) +#else ldr x0, =(CONFIG_SYS_INIT_SP_ADDR) +#endif sub x18, x0, #GD_SIZE /* allocate one GD above SP */ bic x18, x18, #0x7 /* 8-byte alignment for GD */ zero_gd: @@ -77,6 +81,7 @@ zero_gd: mov x0, #0 bl board_init_f +#if !defined(CONFIG_SPL_BUILD) /* * Set up intermediate environment (new sp and gd) and call * relocate_code(addr_moni). Trick here is that we'll return @@ -119,4 +124,6 @@ clear_loop: /* NOTREACHED - board_init_r() does not return */ +#endif /* !CONFIG_SPL_BUILD */ + ENDPROC(_main) diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init_early.c b/arch/powerpc/cpu/mpc85xx/cpu_init_early.c index 5ca9bf5..235a635 100644 --- a/arch/powerpc/cpu/mpc85xx/cpu_init_early.c +++ b/arch/powerpc/cpu/mpc85xx/cpu_init_early.c @@ -15,7 +15,7 @@ DECLARE_GLOBAL_DATA_PTR; #ifdef CONFIG_A003399_NOR_WORKAROUND void setup_ifc(void) { - struct fsl_ifc *ifc_regs = (void *)CONFIG_SYS_IFC_ADDR; + struct fsl_ifc ifc_regs = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL}; u32 _mas0, _mas1, _mas2, _mas3, _mas7; phys_addr_t flash_phys = CONFIG_SYS_FLASH_BASE_PHYS; @@ -70,9 +70,9 @@ void setup_ifc(void) #endif /* Change flash's physical address */ - ifc_out32(&(ifc_regs->cspr_cs[0].cspr), CONFIG_SYS_CSPR0); - ifc_out32(&(ifc_regs->csor_cs[0].csor), CONFIG_SYS_CSOR0); - ifc_out32(&(ifc_regs->amask_cs[0].amask), CONFIG_SYS_AMASK0); + ifc_out32(&(ifc_regs.gregs->cspr_cs[0].cspr), CONFIG_SYS_CSPR0); + ifc_out32(&(ifc_regs.gregs->csor_cs[0].csor), CONFIG_SYS_CSOR0); + ifc_out32(&(ifc_regs.gregs->amask_cs[0].amask), CONFIG_SYS_AMASK0); return ; } diff --git a/arch/powerpc/cpu/mpc85xx/speed.c b/arch/powerpc/cpu/mpc85xx/speed.c index e24b857..321ade2 100644 --- a/arch/powerpc/cpu/mpc85xx/speed.c +++ b/arch/powerpc/cpu/mpc85xx/speed.c @@ -28,7 +28,7 @@ void get_sys_info(sys_info_t *sys_info) { volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); #ifdef CONFIG_FSL_IFC - struct fsl_ifc *ifc_regs = (void *)CONFIG_SYS_IFC_ADDR; + struct fsl_ifc ifc_regs = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL}; u32 ccr; #endif #ifdef CONFIG_FSL_CORENET @@ -597,7 +597,7 @@ void get_sys_info(sys_info_t *sys_info) #endif #if defined(CONFIG_FSL_IFC) - ccr = ifc_in32(&ifc_regs->ifc_ccr); + ccr = ifc_in32(&ifc_regs.gregs->ifc_ccr); ccr = ((ccr & IFC_CCR_CLK_DIV_MASK) >> IFC_CCR_CLK_DIV_SHIFT) + 1; sys_info->freq_localbus = sys_info->freq_systembus / ccr; diff --git a/arch/powerpc/include/asm/fsl_secure_boot.h b/arch/powerpc/include/asm/fsl_secure_boot.h index 49f6814..8f794ef 100644 --- a/arch/powerpc/include/asm/fsl_secure_boot.h +++ b/arch/powerpc/include/asm/fsl_secure_boot.h @@ -67,5 +67,24 @@ #define CONFIG_FSL_ISBC_KEY_EXT #endif +#ifndef CONFIG_FIT_SIGNATURE +/* The bootscript header address is different for B4860 because the NOR + * mapping is different on B4 due to reduced NOR size. + */ +#if defined(CONFIG_B4860QDS) +#define CONFIG_BOOTSCRIPT_HDR_ADDR 0xecc00000 +#elif defined(CONFIG_FSL_CORENET) +#define CONFIG_BOOTSCRIPT_HDR_ADDR 0xe8e00000 +#elif defined(CONFIG_BSC9132QDS) +#define CONFIG_BOOTSCRIPT_HDR_ADDR 0x88020000 +#elif defined(CONFIG_C29XPCIE) +#define CONFIG_BOOTSCRIPT_HDR_ADDR 0xec020000 +#else +#define CONFIG_BOOTSCRIPT_HDR_ADDR 0xee020000 +#endif + +#include <config_fsl_secboot.h> +#endif + #endif #endif diff --git a/board/freescale/bsc9132qds/bsc9132qds.c b/board/freescale/bsc9132qds/bsc9132qds.c index 36a68db..586dacc 100644 --- a/board/freescale/bsc9132qds/bsc9132qds.c +++ b/board/freescale/bsc9132qds/bsc9132qds.c @@ -36,9 +36,9 @@ DECLARE_GLOBAL_DATA_PTR; int board_early_init_f(void) { - struct fsl_ifc *ifc = (void *)CONFIG_SYS_IFC_ADDR; + struct fsl_ifc ifc = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL}; - setbits_be32(&ifc->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT); + setbits_be32(&ifc.gregs->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT); return 0; } diff --git a/board/freescale/c29xpcie/c29xpcie.c b/board/freescale/c29xpcie/c29xpcie.c index d7577096..f42d373 100644 --- a/board/freescale/c29xpcie/c29xpcie.c +++ b/board/freescale/c29xpcie/c29xpcie.c @@ -38,10 +38,10 @@ int checkboard(void) int board_early_init_f(void) { - struct fsl_ifc *ifc = (void *)CONFIG_SYS_IFC_ADDR; + struct fsl_ifc ifc = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL}; /* Clock configuration to access CPLD using IFC(GPCM) */ - setbits_be32(&ifc->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT); + setbits_be32(&ifc.gregs->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT); return 0; } diff --git a/board/freescale/common/arm_sleep.c b/board/freescale/common/arm_sleep.c index 8edf878..c06b862 100644 --- a/board/freescale/common/arm_sleep.c +++ b/board/freescale/common/arm_sleep.c @@ -19,6 +19,9 @@ #endif #include "sleep.h" +#ifdef CONFIG_U_QE +#include "../../../drivers/qe/qe.h" +#endif DECLARE_GLOBAL_DATA_PTR; @@ -72,6 +75,9 @@ static void dp_resume_prepare(void) board_sleep_prepare(); armv7_init_nonsec(); cleanup_before_linux(); +#ifdef CONFIG_U_QE + u_qe_resume(); +#endif } int fsl_dp_resume(void) diff --git a/board/freescale/common/cmd_esbc_validate.c b/board/freescale/common/cmd_esbc_validate.c index 8500ba5..8bbe85b 100644 --- a/board/freescale/common/cmd_esbc_validate.c +++ b/board/freescale/common/cmd_esbc_validate.c @@ -8,6 +8,16 @@ #include <command.h> #include <fsl_validate.h> +static int do_esbc_halt(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + printf("Core is entering spin loop.\n"); +loop: + goto loop; + + return 0; +} + static int do_esbc_validate(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { @@ -32,3 +42,9 @@ U_BOOT_CMD( "Validates signature on a given image using RSA verification", esbc_validate_help_text ); + +U_BOOT_CMD( + esbc_halt, 1, 0, do_esbc_halt, + "Put the core in spin loop ", + "" +); diff --git a/board/freescale/common/mpc85xx_sleep.c b/board/freescale/common/mpc85xx_sleep.c index f924e7f..9e4132c 100644 --- a/board/freescale/common/mpc85xx_sleep.c +++ b/board/freescale/common/mpc85xx_sleep.c @@ -7,6 +7,9 @@ #include <common.h> #include <asm/immap_85xx.h> #include "sleep.h" +#ifdef CONFIG_U_QE +#include "../../../drivers/qe/qe.h" +#endif DECLARE_GLOBAL_DATA_PTR; @@ -65,6 +68,11 @@ static void dp_resume_prepare(void) disable_cpc_sram(); #endif enable_cpc(); + +#ifdef CONFIG_U_QE + u_qe_resume(); +#endif + } int fsl_dp_resume(void) diff --git a/board/freescale/common/qixis.c b/board/freescale/common/qixis.c index a49e300..9f6b0e7 100644 --- a/board/freescale/common/qixis.c +++ b/board/freescale/common/qixis.c @@ -138,24 +138,23 @@ void qixis_bank_reset(void) QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START); } -/* Set the boot bank to the power-on default bank */ -void clear_altbank(void) +static void __maybe_unused set_lbmap(int lbmap) { u8 reg; reg = QIXIS_READ(brdcfg[0]); - reg = (reg & ~QIXIS_LBMAP_MASK) | QIXIS_LBMAP_DFLTBANK; + reg = (reg & ~QIXIS_LBMAP_MASK) | lbmap; QIXIS_WRITE(brdcfg[0], reg); } -/* Set the boot bank to the alternate bank */ -void set_altbank(void) +static void __maybe_unused set_rcw_src(int rcw_src) { u8 reg; - reg = QIXIS_READ(brdcfg[0]); - reg = (reg & ~QIXIS_LBMAP_MASK) | QIXIS_LBMAP_ALTBANK; - QIXIS_WRITE(brdcfg[0], reg); + reg = QIXIS_READ(dutcfg[1]); + reg = (reg & ~1) | (rcw_src & 1); + QIXIS_WRITE(dutcfg[1], reg); + QIXIS_WRITE(dutcfg[0], (rcw_src >> 1) & 0xff); } static void qixis_dump_regs(void) @@ -201,11 +200,22 @@ int qixis_reset_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) int i; if (argc <= 1) { - clear_altbank(); + set_lbmap(QIXIS_LBMAP_DFLTBANK); qixis_reset(); } else if (strcmp(argv[1], "altbank") == 0) { - set_altbank(); + set_lbmap(QIXIS_LBMAP_ALTBANK); qixis_bank_reset(); + } else if (strcmp(argv[1], "nand") == 0) { +#ifdef QIXIS_LBMAP_NAND + QIXIS_WRITE(rst_ctl, 0x30); + QIXIS_WRITE(rcfg_ctl, 0); + set_lbmap(QIXIS_LBMAP_NAND); + set_rcw_src(QIXIS_RCW_SRC_NAND); + QIXIS_WRITE(rcfg_ctl, 0x20); + QIXIS_WRITE(rcfg_ctl, 0x21); +#else + printf("Not implemented\n"); +#endif } else if (strcmp(argv[1], "watchdog") == 0) { static char *period[9] = {"2s", "4s", "8s", "16s", "32s", "1min", "2min", "4min", "8min"}; @@ -244,6 +254,7 @@ U_BOOT_CMD( "Reset the board using the FPGA sequencer", "- hard reset to default bank\n" "qixis_reset altbank - reset to alternate bank\n" + "qixis_reset nand - reset to nand\n" "qixis watchdog <watchdog_period> - set the watchdog period\n" " period: 1s 2s 4s 8s 16s 32s 1min 2min 4min 8min\n" "qixis_reset dump - display the QIXIS registers\n" diff --git a/board/freescale/ls1021aqds/MAINTAINERS b/board/freescale/ls1021aqds/MAINTAINERS index 661526b..820d322 100644 --- a/board/freescale/ls1021aqds/MAINTAINERS +++ b/board/freescale/ls1021aqds/MAINTAINERS @@ -5,6 +5,7 @@ F: board/freescale/ls1021aqds/ F: include/configs/ls1021aqds.h F: configs/ls1021aqds_nor_defconfig F: configs/ls1021aqds_ddr4_nor_defconfig +F: configs/ls1021aqds_ddr4_nor_lpuart_defconfig F: configs/ls1021aqds_nor_SECURE_BOOT_defconfig F: configs/ls1021aqds_nor_lpuart_defconfig F: configs/ls1021aqds_sdcard_defconfig diff --git a/board/freescale/ls1021aqds/ls1021aqds.c b/board/freescale/ls1021aqds/ls1021aqds.c index 722b88f..92f613a 100644 --- a/board/freescale/ls1021aqds/ls1021aqds.c +++ b/board/freescale/ls1021aqds/ls1021aqds.c @@ -12,7 +12,6 @@ #include <asm/arch/clock.h> #include <asm/arch/fsl_serdes.h> #include <asm/arch/ls102xa_stream_id.h> -#include <asm/pcie_layerscape.h> #include <hwconfig.h> #include <mmc.h> #include <fsl_esdhc.h> @@ -138,6 +137,17 @@ unsigned long get_board_ddr_clk(void) return 66666666; } +unsigned int get_soc_major_rev(void) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + unsigned int svr, major; + + svr = in_be32(&gur->svr); + major = SVR_MAJ(svr); + + return major; +} + int select_i2c_ch_pca9547(u8 ch) { int ret; @@ -181,6 +191,7 @@ int board_early_init_f(void) { struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR; struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR; + unsigned int major; #ifdef CONFIG_TSEC_ENET out_be32(&scfg->etsecdmamcr, SCFG_ETSECDMAMCR_LE_BD_FR); @@ -205,19 +216,22 @@ int board_early_init_f(void) out_le32(&cci->slave[4].snoop_ctrl, CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN); - /* - * Set CCI-400 Slave interface S1, S2 Shareable Override Register - * All transactions are treated as non-shareable - */ - out_le32(&cci->slave[1].sha_ord, CCI400_SHAORD_NON_SHAREABLE); - out_le32(&cci->slave[2].sha_ord, CCI400_SHAORD_NON_SHAREABLE); - - /* Workaround for the issue that DDR could not respond to - * barrier transaction which is generated by executing DSB/ISB - * instruction. Set CCI-400 control override register to - * terminate the barrier transaction. After DDR is initialized, - * allow barrier transaction to DDR again */ - out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER); + major = get_soc_major_rev(); + if (major == SOC_MAJOR_VER_1_0) { + /* + * Set CCI-400 Slave interface S1, S2 Shareable Override + * Register All transactions are treated as non-shareable + */ + out_le32(&cci->slave[1].sha_ord, CCI400_SHAORD_NON_SHAREABLE); + out_le32(&cci->slave[2].sha_ord, CCI400_SHAORD_NON_SHAREABLE); + + /* Workaround for the issue that DDR could not respond to + * barrier transaction which is generated by executing DSB/ISB + * instruction. Set CCI-400 control override register to + * terminate the barrier transaction. After DDR is initialized, + * allow barrier transaction to DDR again */ + out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER); + } #if defined(CONFIG_DEEP_SLEEP) if (is_warm_boot()) @@ -231,6 +245,7 @@ int board_early_init_f(void) void board_init_f(ulong dummy) { struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR; + unsigned int major; #ifdef CONFIG_NAND_BOOT struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; @@ -267,7 +282,10 @@ void board_init_f(ulong dummy) #ifdef CONFIG_SPL_I2C_SUPPORT i2c_init_all(); #endif - out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER); + + major = get_soc_major_rev(); + if (major == SOC_MAJOR_VER_1_0) + out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER); dram_init(); @@ -548,10 +566,14 @@ struct smmu_stream_id dev_stream_id[] = { int board_init(void) { struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR; + unsigned int major; - /* Set CCI-400 control override register to - * enable barrier transaction */ - out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER); + major = get_soc_major_rev(); + if (major == SOC_MAJOR_VER_1_0) { + /* Set CCI-400 control override register to + * enable barrier transaction */ + out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER); + } select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT); @@ -580,10 +602,15 @@ int board_init(void) void board_sleep_prepare(void) { struct ccsr_cci400 __iomem *cci = (void *)CONFIG_SYS_CCI400_ADDR; + unsigned int major; + + major = get_soc_major_rev(); + if (major == SOC_MAJOR_VER_1_0) { + /* Set CCI-400 control override register to + * enable barrier transaction */ + out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER); + } - /* Set CCI-400 control override register to - * enable barrier transaction */ - out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER); #ifdef CONFIG_LS102XA_NS_ACCESS enable_devices_ns_access(ns_dev, ARRAY_SIZE(ns_dev)); @@ -595,8 +622,8 @@ int ft_board_setup(void *blob, bd_t *bd) { ft_cpu_setup(blob, bd); -#ifdef CONFIG_PCIE_LAYERSCAPE - ft_pcie_setup(blob, bd); +#ifdef CONFIG_PCI + ft_pci_setup(blob, bd); #endif return 0; diff --git a/board/freescale/ls1021atwr/ls1021atwr.c b/board/freescale/ls1021atwr/ls1021atwr.c index fb8525f..ed5bd27 100644 --- a/board/freescale/ls1021atwr/ls1021atwr.c +++ b/board/freescale/ls1021atwr/ls1021atwr.c @@ -12,7 +12,7 @@ #include <asm/arch/clock.h> #include <asm/arch/fsl_serdes.h> #include <asm/arch/ls102xa_stream_id.h> -#include <asm/pcie_layerscape.h> +#include <hwconfig.h> #include <mmc.h> #include <fsl_esdhc.h> #include <fsl_ifc.h> @@ -54,6 +54,17 @@ DECLARE_GLOBAL_DATA_PTR; #define KEEP_STATUS 0x0 #define NEED_RESET 0x1 +#define SOFT_MUX_ON_I2C3_IFC 0x2 +#define SOFT_MUX_ON_CAN3_USB2 0x8 +#define SOFT_MUX_ON_QE_LCD 0x10 + +#define PIN_I2C3_IFC_MUX_I2C3 0x0 +#define PIN_I2C3_IFC_MUX_IFC 0x1 +#define PIN_CAN3_USB2_MUX_USB2 0x0 +#define PIN_CAN3_USB2_MUX_CAN3 0x1 +#define PIN_QE_LCD_MUX_LCD 0x0 +#define PIN_QE_LCD_MUX_QE 0x1 + struct cpld_data { u8 cpld_ver; /* cpld revision */ u8 cpld_ver_sub; /* cpld sub revision */ @@ -122,6 +133,17 @@ int checkboard(void) return 0; } +unsigned int get_soc_major_rev(void) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + unsigned int svr, major; + + svr = in_be32(&gur->svr); + major = SVR_MAJ(svr); + + return major; +} + void ddrmc_init(void) { struct ccsr_ddr *ddr = (struct ccsr_ddr *)CONFIG_SYS_FSL_DDR_ADDR; @@ -260,10 +282,73 @@ int config_serdes_mux(void) } #endif +#ifndef CONFIG_QSPI_BOOT +int config_board_mux(void) +{ + struct cpld_data *cpld_data = (void *)(CONFIG_SYS_CPLD_BASE); + int conflict_flag; + + conflict_flag = 0; + if (hwconfig("i2c3")) { + conflict_flag++; + cpld_data->soft_mux_on |= SOFT_MUX_ON_I2C3_IFC; + cpld_data->i2c3_ifc_mux = PIN_I2C3_IFC_MUX_I2C3; + } + + if (hwconfig("ifc")) { + conflict_flag++; + /* some signals can not enable simultaneous*/ + if (conflict_flag > 1) + goto conflict; + cpld_data->soft_mux_on |= SOFT_MUX_ON_I2C3_IFC; + cpld_data->i2c3_ifc_mux = PIN_I2C3_IFC_MUX_IFC; + } + + conflict_flag = 0; + if (hwconfig("usb2")) { + conflict_flag++; + cpld_data->soft_mux_on |= SOFT_MUX_ON_CAN3_USB2; + cpld_data->can3_usb2_mux = PIN_CAN3_USB2_MUX_USB2; + } + + if (hwconfig("can3")) { + conflict_flag++; + /* some signals can not enable simultaneous*/ + if (conflict_flag > 1) + goto conflict; + cpld_data->soft_mux_on |= SOFT_MUX_ON_CAN3_USB2; + cpld_data->can3_usb2_mux = PIN_CAN3_USB2_MUX_CAN3; + } + + conflict_flag = 0; + if (hwconfig("lcd")) { + conflict_flag++; + cpld_data->soft_mux_on |= SOFT_MUX_ON_QE_LCD; + cpld_data->qe_lcd_mux = PIN_QE_LCD_MUX_LCD; + } + + if (hwconfig("qe")) { + conflict_flag++; + /* some signals can not enable simultaneous*/ + if (conflict_flag > 1) + goto conflict; + cpld_data->soft_mux_on |= SOFT_MUX_ON_QE_LCD; + cpld_data->qe_lcd_mux = PIN_QE_LCD_MUX_QE; + } + + return 0; + +conflict: + printf("WARNING: pin conflict! MUX setting may failed!\n"); + return 0; +} +#endif + int board_early_init_f(void) { struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR; struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR; + unsigned int major; #ifdef CONFIG_TSEC_ENET out_be32(&scfg->etsecdmamcr, SCFG_ETSECDMAMCR_LE_BD_FR); @@ -289,12 +374,15 @@ int board_early_init_f(void) out_le32(&cci->slave[4].snoop_ctrl, CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN); - /* - * Set CCI-400 Slave interface S1, S2 Shareable Override Register - * All transactions are treated as non-shareable - */ - out_le32(&cci->slave[1].sha_ord, CCI400_SHAORD_NON_SHAREABLE); - out_le32(&cci->slave[2].sha_ord, CCI400_SHAORD_NON_SHAREABLE); + major = get_soc_major_rev(); + if (major == SOC_MAJOR_VER_1_0) { + /* + * Set CCI-400 Slave interface S1, S2 Shareable Override + * Register All transactions are treated as non-shareable + */ + out_le32(&cci->slave[1].sha_ord, CCI400_SHAORD_NON_SHAREABLE); + out_le32(&cci->slave[2].sha_ord, CCI400_SHAORD_NON_SHAREABLE); + } return 0; } @@ -465,6 +553,10 @@ int board_init(void) #if defined(CONFIG_MISC_INIT_R) int misc_init_r(void) { +#ifndef CONFIG_QSPI_BOOT + config_board_mux(); +#endif + #ifdef CONFIG_FSL_CAAM return sec_init(); #endif @@ -475,8 +567,8 @@ int ft_board_setup(void *blob, bd_t *bd) { ft_cpu_setup(blob, bd); -#ifdef CONFIG_PCIE_LAYERSCAPE - ft_pcie_setup(blob, bd); +#ifdef CONFIG_PCI + ft_pci_setup(blob, bd); #endif return 0; diff --git a/board/freescale/ls2085a/ls2085a.c b/board/freescale/ls2085a/ls2085a.c index 519d61c..dd0acf2 100644 --- a/board/freescale/ls2085a/ls2085a.c +++ b/board/freescale/ls2085a/ls2085a.c @@ -12,8 +12,10 @@ #include <asm/io.h> #include <fdt_support.h> #include <libfdt.h> +#include <fsl_debug_server.h> #include <fsl-mc/fsl_mc.h> #include <environment.h> +#include <asm/arch-fsl-lsch3/soc.h> DECLARE_GLOBAL_DATA_PTR; @@ -30,8 +32,7 @@ int board_init(void) int board_early_init_f(void) { - init_early_memctl_regs(); /* tighten IFC timing */ - + fsl_lsch3_early_init_f(); return 0; } @@ -54,29 +55,32 @@ int dram_init(void) return 0; } -int timer_init(void) +#if defined(CONFIG_ARCH_MISC_INIT) +int arch_misc_init(void) { - u32 __iomem *cntcr = (u32 *)CONFIG_SYS_FSL_TIMER_ADDR; - u32 __iomem *cltbenr = (u32 *)CONFIG_SYS_FSL_PMU_CLTBENR; - - /* Enable timebase for all clusters. - * It is safe to do so even some clusters are not enabled. - */ - out_le32(cltbenr, 0xf); - - /* Enable clock for timer - * This is a global setting. - */ - out_le32(cntcr, 0x1); +#ifdef CONFIG_FSL_DEBUG_SERVER + debug_server_init(); +#endif return 0; } +#endif -/* - * Board specific reset that is system reset. - */ -void reset_cpu(ulong addr) +unsigned long get_dram_size_to_hide(void) { + unsigned long dram_to_hide = 0; + +/* Carve the Debug Server private DRAM block from the end of DRAM */ +#ifdef CONFIG_FSL_DEBUG_SERVER + dram_to_hide += debug_server_get_dram_block_size(); +#endif + +/* Carve the MC private DRAM block from the end of DRAM */ +#ifdef CONFIG_FSL_MC_ENET + dram_to_hide += mc_get_dram_block_size(); +#endif + + return dram_to_hide; } int board_eth_init(bd_t *bis) @@ -135,6 +139,7 @@ int ft_board_setup(void *blob, bd_t *bd) #ifdef CONFIG_FSL_MC_ENET fdt_fixup_board_enet(blob); + fsl_mc_ldpaa_exit(bd); #endif return 0; diff --git a/board/freescale/ls2085aqds/Kconfig b/board/freescale/ls2085aqds/Kconfig new file mode 100644 index 0000000..deb640d --- /dev/null +++ b/board/freescale/ls2085aqds/Kconfig @@ -0,0 +1,16 @@ + +if TARGET_LS2085AQDS + +config SYS_BOARD + default "ls2085aqds" + +config SYS_VENDOR + default "freescale" + +config SYS_SOC + default "fsl-lsch3" + +config SYS_CONFIG_NAME + default "ls2085aqds" + +endif diff --git a/board/freescale/ls2085aqds/MAINTAINERS b/board/freescale/ls2085aqds/MAINTAINERS new file mode 100644 index 0000000..fbed672 --- /dev/null +++ b/board/freescale/ls2085aqds/MAINTAINERS @@ -0,0 +1,8 @@ +LS2085A BOARD +M: Prabhakar Kushwaha <prabhakar@freescale.com> +S: Maintained +F: board/freescale/ls2085aqds/ +F: board/freescale/ls2085a/ls2085aqds.c +F: include/configs/ls2085aqds.h +F: configs/ls2085aqds_defconfig +F: configs/ls2085aqds_nand_defconfig diff --git a/board/freescale/ls2085aqds/Makefile b/board/freescale/ls2085aqds/Makefile new file mode 100644 index 0000000..da69a7d --- /dev/null +++ b/board/freescale/ls2085aqds/Makefile @@ -0,0 +1,9 @@ +# +# Copyright 2015 Freescale Semiconductor +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += ls2085aqds.o +obj-y += ddr.o +obj-y += eth.o diff --git a/board/freescale/ls2085aqds/README b/board/freescale/ls2085aqds/README new file mode 100644 index 0000000..fb3938e --- /dev/null +++ b/board/freescale/ls2085aqds/README @@ -0,0 +1,129 @@ +Overview +-------- +The LS2085A Development System (QDS) is a high-performance computing, +evaluation, and development platform that supports the QorIQ LS2085A +Layerscape Architecture processor. The LS2085AQDS provides validation and +SW development platform for the Freescale LS2085A processor series, with +a complete debugging environment. + +LS2085A SoC Overview +------------------ +The LS2085A integrated multicore processor combines eight ARM Cortex-A57 +processor cores with high-performance data path acceleration logic and network +and peripheral bus interfaces required for networking, telecom/datacom, +wireless infrastructure, and mil/aerospace applications. + +The LS2085A SoC includes the following function and features: + + - Eight 64-bit ARM Cortex-A57 CPUs + - 1 MB platform cache with ECC + - Two 64-bit DDR4 SDRAM memory controllers with ECC and interleaving support + - One secondary 32-bit DDR4 SDRAM memory controller, intended for use by + the AIOP + - Data path acceleration architecture (DPAA2) incorporating acceleration for + the following functions: + - Packet parsing, classification, and distribution (WRIOP) + - Queue and Hardware buffer management for scheduling, packet sequencing, and + congestion management, buffer allocation and de-allocation (QBMan) + - Cryptography acceleration (SEC) at up to 10 Gbps + - RegEx pattern matching acceleration (PME) at up to 10 Gbps + - Decompression/compression acceleration (DCE) at up to 20 Gbps + - Accelerated I/O processing (AIOP) at up to 20 Gbps + - QDMA engine + - 16 SerDes lanes at up to 10.3125 GHz + - Ethernet interfaces + - Up to eight 10 Gbps Ethernet MACs + - Up to eight 1 / 2.5 Gbps Ethernet MACs + - High-speed peripheral interfaces + - Four PCIe 3.0 controllers, one supporting SR-IOV + - Additional peripheral interfaces + - Two serial ATA (SATA 3.0) controllers + - Two high-speed USB 3.0 controllers with integrated PHY + - Enhanced secure digital host controller (eSDXC/eMMC) + - Serial peripheral interface (SPI) controller + - Quad Serial Peripheral Interface (QSPI) Controller + - Four I2C controllers + - Two DUARTs + - Integrated flash controller (IFC 2.0) supporting NAND and NOR flash + - Support for hardware virtualization and partitioning enforcement + - QorIQ platform's trust architecture 3.0 + - Service processor (SP) provides pre-boot initialization and secure-boot + capabilities + + LS2085AQDS board Overview + ----------------------- + - SERDES Connections, 16 lanes supporting: + - PCI Express - 3.0 + - SGMII, SGMII 2.5 + - QSGMII + - SATA 3.0 + - XAUI + - XFI + - DDR Controller + - Two ports of 72-bits (8-bits ECC) DDR4. Each port supports four + chip-selects and two DIMM connectors. Support is up to 2133MT/s. + - One port of 40-bits (8-bits ECC) DDR4 which supports four chip-selects + and two DIMM connectors. Support is up to 1600MT/s. + -IFC/Local Bus + - IFC rev. 2.0 implementation supporting Little Endian connection scheme. + - One in-socket 128 MB NOR flash 16-bit data bus + - One 512 MB NAND flash with ECC support + - IFC Test Port + - PromJet Port + - FPGA connection + - USB 3.0 + - Two high speed USB 3.0 ports + - First USB 3.0 port configured as Host with Type-A connector + - Second USB 3.0 port configured as OTG with micro-AB connector + - SDHC: PCIe x1 Right Angle connector for supporting following cards + - 1/4-/8-bit SD/MMC Legacy CARD supporting 3.3V devices only + - 1-/4-/8-bit SD/MMC Card supporting 1.8V devices only + - 4-bit eMMC Card Rev 4.4 (1.8V only) + - 8-bit eMMC Card Rev 4.5 (1.8V only) + - SD Card Rev 2.0 and Rev 3.0 + - DSPI: 3 high-speed flash Memory for storage + - 16 MB high-speed flash Memory for boot code and storage (up to 108MHz) + - 8 MB high-speed flash Memory (up to 104 MHz) + - 512 MB low-speed flash Memory (up to 40 MHz) + - QSPI: via NAND/QSPI Card + - 4 I2C controllers + - Two SATA onboard connectors + - UART + - Two 4-pin (HW control) or four 2-pin (SW control) serial ports at up to 115.2 Kbit/s + - Two DB9 D-Type connectors supporting one Serial port each + - ARM JTAG support + +Memory map from core's view +---------------------------- +0x00_0000_0000 .. 0x00_000F_FFFF Boot Rom +0x00_0100_0000 .. 0x00_0FFF_FFFF CCSR +0x00_1800_0000 .. 0x00_181F_FFFF OCRAM +0x00_3000_0000 .. 0x00_3FFF_FFFF IFC region #1 +0x00_8000_0000 .. 0x00_FFFF_FFFF DDR region #1 +0x05_1000_0000 .. 0x05_FFFF_FFFF IFC region #2 +0x80_8000_0000 .. 0xFF_FFFF_FFFF DDR region #2 + +Other addresses are either reserved, or not used directly by u-boot. +This list should be updated when more addresses are used. + +IFC region map from core's view +------------------------------- +During boot i.e. IFC Region #1:- + 0x30000000 - 0x37ffffff : 128MB : NOR flash + 0x38000000 - 0x3BFFFFFF : 64MB : Promjet + 0x3C000000 - 0x40000000 : 64MB : FPGA etc + +After relocate to DDR i.e. IFC Region #2:- + 0x5_1000_0000..0x5_1fff_ffff Memory Hole + 0x5_2000_0000..0x5_3fff_ffff IFC CSx (FPGA, NAND and others 512MB) + 0x5_4000_0000..0x5_7fff_ffff ASIC or others 1GB + 0x5_8000_0000..0x5_bfff_ffff IFC CS0 1GB (NOR/Promjet) + 0x5_C000_0000..0x5_ffff_ffff IFC CS1 1GB (NOR/Promjet) + +Booting Options +--------------- +a) Promjet Boot +b) NOR boot +c) NAND boot +d) SD boot +e) QSPI boot diff --git a/board/freescale/ls2085aqds/ddr.c b/board/freescale/ls2085aqds/ddr.c new file mode 100644 index 0000000..8d71ae1 --- /dev/null +++ b/board/freescale/ls2085aqds/ddr.c @@ -0,0 +1,196 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <fsl_ddr_sdram.h> +#include <fsl_ddr_dimm_params.h> +#include "ddr.h" + +DECLARE_GLOBAL_DATA_PTR; + +void fsl_ddr_board_options(memctl_options_t *popts, + dimm_params_t *pdimm, + unsigned int ctrl_num) +{ + u8 dq_mapping_0, dq_mapping_2, dq_mapping_3; + const struct board_specific_parameters *pbsp, *pbsp_highest = NULL; + ulong ddr_freq; + int slot; + + if (ctrl_num > 2) { + printf("Not supported controller number %d\n", ctrl_num); + return; + } + + for (slot = 0; slot < CONFIG_DIMM_SLOTS_PER_CTLR; slot++) { + if (pdimm[slot].n_ranks) + break; + } + + if (slot >= CONFIG_DIMM_SLOTS_PER_CTLR) + return; + + /* + * we use identical timing for all slots. If needed, change the code + * to pbsp = rdimms[ctrl_num] or pbsp = udimms[ctrl_num]; + */ + if (popts->registered_dimm_en) + pbsp = rdimms[ctrl_num]; + else + pbsp = udimms[ctrl_num]; + + + /* Get clk_adjust, wrlvl_start, wrlvl_ctl, according to the board ddr + * freqency and n_banks specified in board_specific_parameters table. + */ + ddr_freq = get_ddr_freq(ctrl_num) / 1000000; + while (pbsp->datarate_mhz_high) { + if (pbsp->n_ranks == pdimm[slot].n_ranks && + (pdimm[slot].rank_density >> 30) >= pbsp->rank_gb) { + if (ddr_freq <= pbsp->datarate_mhz_high) { + popts->clk_adjust = pbsp->clk_adjust; + popts->wrlvl_start = pbsp->wrlvl_start; + popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2; + popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3; + goto found; + } + pbsp_highest = pbsp; + } + pbsp++; + } + + if (pbsp_highest) { + printf("Error: board specific timing not found for data rate %lu MT/s\n" + "Trying to use the highest speed (%u) parameters\n", + ddr_freq, pbsp_highest->datarate_mhz_high); + popts->clk_adjust = pbsp_highest->clk_adjust; + popts->wrlvl_start = pbsp_highest->wrlvl_start; + popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2; + popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3; + } else { + panic("DIMM is not supported by this board"); + } +found: + debug("Found timing match: n_ranks %d, data rate %d, rank_gb %d\n" + "\tclk_adjust %d, wrlvl_start %d, wrlvl_ctrl_2 0x%x, wrlvl_ctrl_3 0x%x\n", + pbsp->n_ranks, pbsp->datarate_mhz_high, pbsp->rank_gb, + pbsp->clk_adjust, pbsp->wrlvl_start, pbsp->wrlvl_ctl_2, + pbsp->wrlvl_ctl_3); + + if (ctrl_num == CONFIG_DP_DDR_CTRL) { + /* force DDR bus width to 32 bits */ + popts->data_bus_width = 1; + popts->otf_burst_chop_en = 0; + popts->burst_length = DDR_BL8; + popts->bstopre = 0; /* enable auto precharge */ + /* + * Layout optimization results byte mapping + * Byte 0 -> Byte ECC + * Byte 1 -> Byte 3 + * Byte 2 -> Byte 2 + * Byte 3 -> Byte 1 + * Byte ECC -> Byte 0 + */ + dq_mapping_0 = pdimm[slot].dq_mapping[0]; + dq_mapping_2 = pdimm[slot].dq_mapping[2]; + dq_mapping_3 = pdimm[slot].dq_mapping[3]; + pdimm[slot].dq_mapping[0] = pdimm[slot].dq_mapping[8]; + pdimm[slot].dq_mapping[1] = pdimm[slot].dq_mapping[9]; + pdimm[slot].dq_mapping[2] = pdimm[slot].dq_mapping[6]; + pdimm[slot].dq_mapping[3] = pdimm[slot].dq_mapping[7]; + pdimm[slot].dq_mapping[6] = dq_mapping_2; + pdimm[slot].dq_mapping[7] = dq_mapping_3; + pdimm[slot].dq_mapping[8] = dq_mapping_0; + pdimm[slot].dq_mapping[9] = 0; + pdimm[slot].dq_mapping[10] = 0; + pdimm[slot].dq_mapping[11] = 0; + pdimm[slot].dq_mapping[12] = 0; + pdimm[slot].dq_mapping[13] = 0; + pdimm[slot].dq_mapping[14] = 0; + pdimm[slot].dq_mapping[15] = 0; + pdimm[slot].dq_mapping[16] = 0; + pdimm[slot].dq_mapping[17] = 0; + } + /* To work at higher than 1333MT/s */ + popts->half_strength_driver_enable = 0; + /* + * Write leveling override + */ + popts->wrlvl_override = 1; + popts->wrlvl_sample = 0x0; /* 32 clocks */ + + /* + * Rtt and Rtt_WR override + */ + popts->rtt_override = 0; + + /* Enable ZQ calibration */ + popts->zq_en = 1; + + if (ddr_freq < 2350) { + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | + DDR_CDR1_ODT(DDR_CDR_ODT_60ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_60ohm) | + DDR_CDR2_VREF_RANGE_2; + } else { + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | + DDR_CDR1_ODT(DDR_CDR_ODT_100ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_100ohm) | + DDR_CDR2_VREF_RANGE_2; + } +} + +phys_size_t initdram(int board_type) +{ + phys_size_t dram_size; + +#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD) + return fsl_ddr_sdram_size(); +#else + puts("Initializing DDR....using SPD\n"); + + dram_size = fsl_ddr_sdram(); +#endif + + return dram_size; +} + +void dram_init_banksize(void) +{ +#ifdef CONFIG_SYS_DP_DDR_BASE_PHY + phys_size_t dp_ddr_size; +#endif + + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; + if (gd->ram_size > CONFIG_SYS_LS2_DDR_BLOCK1_SIZE) { + gd->bd->bi_dram[0].size = CONFIG_SYS_LS2_DDR_BLOCK1_SIZE; + gd->bd->bi_dram[1].start = CONFIG_SYS_DDR_BLOCK2_BASE; + gd->bd->bi_dram[1].size = gd->ram_size - + CONFIG_SYS_LS2_DDR_BLOCK1_SIZE; + } else { + gd->bd->bi_dram[0].size = gd->ram_size; + } + +#ifdef CONFIG_SYS_DP_DDR_BASE_PHY + /* initialize DP-DDR here */ + puts("DP-DDR: "); + /* + * DDR controller use 0 as the base address for binding. + * It is mapped to CONFIG_SYS_DP_DDR_BASE for core to access. + */ + dp_ddr_size = fsl_other_ddr_sdram(CONFIG_SYS_DP_DDR_BASE_PHY, + CONFIG_DP_DDR_CTRL, + CONFIG_DP_DDR_NUM_CTRLS, + CONFIG_DP_DDR_DIMM_SLOTS_PER_CTLR, + NULL, NULL, NULL); + if (dp_ddr_size) { + gd->bd->bi_dram[2].start = CONFIG_SYS_DP_DDR_BASE; + gd->bd->bi_dram[2].size = dp_ddr_size; + } else { + puts("Not detected"); + } +#endif +} diff --git a/board/freescale/ls2085aqds/ddr.h b/board/freescale/ls2085aqds/ddr.h new file mode 100644 index 0000000..b76ea61 --- /dev/null +++ b/board/freescale/ls2085aqds/ddr.h @@ -0,0 +1,92 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __DDR_H__ +#define __DDR_H__ +struct board_specific_parameters { + u32 n_ranks; + u32 datarate_mhz_high; + u32 rank_gb; + u32 clk_adjust; + u32 wrlvl_start; + u32 wrlvl_ctl_2; + u32 wrlvl_ctl_3; +}; + +/* + * These tables contain all valid speeds we want to override with board + * specific parameters. datarate_mhz_high values need to be in ascending order + * for each n_ranks group. + */ + +static const struct board_specific_parameters udimm0[] = { + /* + * memory controller 0 + * num| hi| rank| clk| wrlvl | wrlvl | wrlvl + * ranks| mhz| GB |adjst| start | ctl2 | ctl3 + */ + {2, 1350, 0, 4, 6, 0x0708090B, 0x0C0D0E09,}, + {2, 1666, 0, 4, 7, 0x08090A0C, 0x0D0F100B,}, + {2, 1900, 0, 4, 7, 0x09090B0D, 0x0E10120B,}, + {2, 2300, 0, 4, 8, 0x090A0C0F, 0x1012130C,}, + {} +}; + +/* DP-DDR DIMM */ +static const struct board_specific_parameters udimm2[] = { + /* + * memory controller 2 + * num| hi| rank| clk| wrlvl | wrlvl | wrlvl + * ranks| mhz| GB |adjst| start | ctl2 | ctl3 + */ + {2, 1350, 0, 4, 0xd, 0x0C0A0A00, 0x00000009,}, + {2, 1666, 0, 4, 0xd, 0x0C0A0A00, 0x00000009,}, + {2, 1900, 0, 4, 0xe, 0x0D0C0B00, 0x0000000A,}, + {2, 2200, 0, 4, 0xe, 0x0D0C0B00, 0x0000000A,}, + {} +}; + +static const struct board_specific_parameters rdimm0[] = { + /* + * memory controller 0 + * num| hi| rank| clk| wrlvl | wrlvl | wrlvl + * ranks| mhz| GB |adjst| start | ctl2 | ctl3 + */ + {2, 1350, 0, 4, 6, 0x0708090B, 0x0C0D0E09,}, + {2, 1666, 0, 4, 7, 0x08090A0C, 0x0D0F100B,}, + {2, 1900, 0, 4, 7, 0x09090B0D, 0x0E10120B,}, + {2, 2200, 0, 4, 8, 0x090A0C0F, 0x1012130C,}, + {} +}; + +/* DP-DDR DIMM */ +static const struct board_specific_parameters rdimm2[] = { + /* + * memory controller 2 + * num| hi| rank| clk| wrlvl | wrlvl | wrlvl + * ranks| mhz| GB |adjst| start | ctl2 | ctl3 + */ + {2, 1350, 0, 4, 6, 0x0708090B, 0x0C0D0E09,}, + {2, 1666, 0, 4, 7, 0x0B0A090C, 0x0D0F100B,}, + {2, 1900, 0, 4, 7, 0x09090B0D, 0x0E10120B,}, + {2, 2200, 0, 4, 8, 0x090A0C0F, 0x1012130C,}, + {} +}; + +static const struct board_specific_parameters *udimms[] = { + udimm0, + udimm0, + udimm2, +}; + +static const struct board_specific_parameters *rdimms[] = { + rdimm0, + rdimm0, + rdimm2, +}; + + +#endif diff --git a/board/freescale/ls2085aqds/eth.c b/board/freescale/ls2085aqds/eth.c new file mode 100644 index 0000000..5ba4770 --- /dev/null +++ b/board/freescale/ls2085aqds/eth.c @@ -0,0 +1,380 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <netdev.h> +#include <asm/io.h> +#include <asm/arch/fsl_serdes.h> +#include <asm/arch-fsl-lsch3/immap_lsch3.h> +#include <fsl_mdio.h> +#include <malloc.h> +#include <fm_eth.h> +#include <fsl-mc/ldpaa_wriop.h> + +#include "../common/qixis.h" + +#include "ls2085aqds_qixis.h" + + +#ifdef CONFIG_FSL_MC_ENET + /* - In LS2085A there are only 16 SERDES lanes, spread across 2 SERDES banks. + * Bank 1 -> Lanes A, B, C, D, E, F, G, H + * Bank 2 -> Lanes A,B, C, D, E, F, G, H + */ + + /* Mapping of 16 SERDES lanes to LS2085A QDS board slots. A value of '0' here + * means that the mapping must be determined dynamically, or that the lane + * maps to something other than a board slot. + */ + +static u8 lane_to_slot_fsm2[] = { + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* On the Vitesse VSC8234XHG SGMII riser card there are 4 SGMII PHYs + * housed. + */ +static int riser_phy_addr[] = { + SGMII_CARD_PORT1_PHY_ADDR, + SGMII_CARD_PORT2_PHY_ADDR, + SGMII_CARD_PORT3_PHY_ADDR, + SGMII_CARD_PORT4_PHY_ADDR, +}; + +/* Slot2 does not have EMI connections */ +#define EMI_NONE 0xFFFFFFFF +#define EMI1_SLOT1 0 +#define EMI1_SLOT2 1 +#define EMI1_SLOT3 2 +#define EMI1_SLOT4 3 +#define EMI1_SLOT5 4 +#define EMI1_SLOT6 5 +#define EMI2 6 +#define SFP_TX 1 + +static const char * const mdio_names[] = { + "LS2085A_QDS_MDIO0", + "LS2085A_QDS_MDIO1", + "LS2085A_QDS_MDIO2", + "LS2085A_QDS_MDIO3", + "LS2085A_QDS_MDIO4", + "LS2085A_QDS_MDIO5", + DEFAULT_WRIOP_MDIO2_NAME, +}; + +struct ls2085a_qds_mdio { + u8 muxval; + struct mii_dev *realbus; +}; + +static const char *ls2085a_qds_mdio_name_for_muxval(u8 muxval) +{ + return mdio_names[muxval]; +} + +struct mii_dev *mii_dev_for_muxval(u8 muxval) +{ + struct mii_dev *bus; + const char *name = ls2085a_qds_mdio_name_for_muxval(muxval); + + if (!name) { + printf("No bus for muxval %x\n", muxval); + return NULL; + } + + bus = miiphy_get_dev_by_name(name); + + if (!bus) { + printf("No bus by name %s\n", name); + return NULL; + } + + return bus; +} + +static void ls2085a_qds_enable_SFP_TX(u8 muxval) +{ + u8 brdcfg9; + + brdcfg9 = QIXIS_READ(brdcfg[9]); + brdcfg9 &= ~BRDCFG9_SFPTX_MASK; + brdcfg9 |= (muxval << BRDCFG9_SFPTX_SHIFT); + QIXIS_WRITE(brdcfg[9], brdcfg9); +} + +static void ls2085a_qds_mux_mdio(u8 muxval) +{ + u8 brdcfg4; + + if (muxval <= 5) { + brdcfg4 = QIXIS_READ(brdcfg[4]); + brdcfg4 &= ~BRDCFG4_EMISEL_MASK; + brdcfg4 |= (muxval << BRDCFG4_EMISEL_SHIFT); + QIXIS_WRITE(brdcfg[4], brdcfg4); + } +} + +static int ls2085a_qds_mdio_read(struct mii_dev *bus, int addr, + int devad, int regnum) +{ + struct ls2085a_qds_mdio *priv = bus->priv; + + ls2085a_qds_mux_mdio(priv->muxval); + + return priv->realbus->read(priv->realbus, addr, devad, regnum); +} + +static int ls2085a_qds_mdio_write(struct mii_dev *bus, int addr, int devad, + int regnum, u16 value) +{ + struct ls2085a_qds_mdio *priv = bus->priv; + + ls2085a_qds_mux_mdio(priv->muxval); + + return priv->realbus->write(priv->realbus, addr, devad, regnum, value); +} + +static int ls2085a_qds_mdio_reset(struct mii_dev *bus) +{ + struct ls2085a_qds_mdio *priv = bus->priv; + + return priv->realbus->reset(priv->realbus); +} + +static int ls2085a_qds_mdio_init(char *realbusname, u8 muxval) +{ + struct ls2085a_qds_mdio *pmdio; + struct mii_dev *bus = mdio_alloc(); + + if (!bus) { + printf("Failed to allocate ls2085a_qds MDIO bus\n"); + return -1; + } + + pmdio = malloc(sizeof(*pmdio)); + if (!pmdio) { + printf("Failed to allocate ls2085a_qds private data\n"); + free(bus); + return -1; + } + + bus->read = ls2085a_qds_mdio_read; + bus->write = ls2085a_qds_mdio_write; + bus->reset = ls2085a_qds_mdio_reset; + sprintf(bus->name, ls2085a_qds_mdio_name_for_muxval(muxval)); + + pmdio->realbus = miiphy_get_dev_by_name(realbusname); + + if (!pmdio->realbus) { + printf("No bus with name %s\n", realbusname); + free(bus); + free(pmdio); + return -1; + } + + pmdio->muxval = muxval; + bus->priv = pmdio; + + return mdio_register(bus); +} + +/* + * Initialize the dpmac_info array. + * + */ +static void initialize_dpmac_to_slot(void) +{ + struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; + int serdes1_prtcl = (in_le32(&gur->rcwsr[28]) & + FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK) + >> FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT; + int serdes2_prtcl = (in_le32(&gur->rcwsr[28]) & + FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK) + >> FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT; + + + switch (serdes1_prtcl) { + case 0x2A: + printf("qds: WRIOP: Supported SerDes Protocol 0x%02x\n", + serdes1_prtcl); + break; + default: + printf("qds: WRIOP: Unsupported SerDes Protocol 0x%02x\n", + serdes1_prtcl); + break; + } + + switch (serdes2_prtcl) { + case 0x07: + case 0x08: + printf("qds: WRIOP: Supported SerDes Protocol 0x%02x\n", + serdes2_prtcl); + lane_to_slot_fsm2[0] = EMI1_SLOT4; + lane_to_slot_fsm2[1] = EMI1_SLOT4; + lane_to_slot_fsm2[2] = EMI1_SLOT4; + lane_to_slot_fsm2[3] = EMI1_SLOT4; + /* No MDIO physical connection */ + lane_to_slot_fsm2[4] = EMI1_SLOT6; + lane_to_slot_fsm2[5] = EMI1_SLOT6; + lane_to_slot_fsm2[6] = EMI1_SLOT6; + lane_to_slot_fsm2[7] = EMI1_SLOT6; + break; + default: + printf("qds: WRIOP: Unsupported SerDes Protocol 0x%02x\n", + serdes2_prtcl); + break; + } +} + +void ls2085a_handle_phy_interface_sgmii(int dpmac_id) +{ + int lane, slot; + struct mii_dev *bus; + struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; + int serdes1_prtcl = (in_le32(&gur->rcwsr[28]) & + FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK) + >> FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT; + int serdes2_prtcl = (in_le32(&gur->rcwsr[28]) & + FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK) + >> FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT; + + switch (serdes1_prtcl) { + } + + switch (serdes2_prtcl) { + case 0x07: + case 0x08: + lane = serdes_get_first_lane(FSL_SRDS_2, SGMII9 + + (dpmac_id - 9)); + slot = lane_to_slot_fsm2[lane]; + + switch (++slot) { + case 1: + break; + case 3: + break; + case 4: + /* Slot housing a SGMII riser card? */ + wriop_set_phy_address(dpmac_id, + riser_phy_addr[dpmac_id - 9]); + dpmac_info[dpmac_id].board_mux = EMI1_SLOT4; + bus = mii_dev_for_muxval(EMI1_SLOT4); + wriop_set_mdio(dpmac_id, bus); + dpmac_info[dpmac_id].phydev = phy_connect( + dpmac_info[dpmac_id].bus, + dpmac_info[dpmac_id].phy_addr, + NULL, + dpmac_info[dpmac_id].enet_if); + phy_config(dpmac_info[dpmac_id].phydev); + break; + case 5: + break; + case 6: + /* Slot housing a SGMII riser card? */ + wriop_set_phy_address(dpmac_id, + riser_phy_addr[dpmac_id - 13]); + dpmac_info[dpmac_id].board_mux = EMI1_SLOT6; + bus = mii_dev_for_muxval(EMI1_SLOT6); + wriop_set_mdio(dpmac_id, bus); + break; + } + break; + default: + printf("qds: WRIOP: Unsupported SerDes Protocol 0x%02x\n", + serdes2_prtcl); + break; + } +} +void ls2085a_handle_phy_interface_xsgmii(int i) +{ + struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; + int serdes1_prtcl = (in_le32(&gur->rcwsr[28]) & + FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK) + >> FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT; + + switch (serdes1_prtcl) { + case 0x2A: + /* + * XFI does not need a PHY to work, but to avoid U-boot use + * default PHY address which is zero to a MAC when it found + * a MAC has no PHY address, we give a PHY address to XFI + * MAC, and should not use a real XAUI PHY address, since + * MDIO can access it successfully, and then MDIO thinks + * the XAUI card is used for the XFI MAC, which will cause + * error. + */ + wriop_set_phy_address(i, i + 4); + ls2085a_qds_enable_SFP_TX(SFP_TX); + + break; + default: + printf("qds: WRIOP: Unsupported SerDes Protocol 0x%02x\n", + serdes1_prtcl); + break; + } +} +#endif + +int board_eth_init(bd_t *bis) +{ + int error; +#ifdef CONFIG_FSL_MC_ENET + struct memac_mdio_info *memac_mdio0_info; + struct memac_mdio_info *memac_mdio1_info; + unsigned int i; + + initialize_dpmac_to_slot(); + + memac_mdio0_info = (struct memac_mdio_info *)malloc( + sizeof(struct memac_mdio_info)); + memac_mdio0_info->regs = + (struct memac_mdio_controller *) + CONFIG_SYS_FSL_WRIOP1_MDIO1; + memac_mdio0_info->name = DEFAULT_WRIOP_MDIO1_NAME; + + /* Register the real MDIO1 bus */ + fm_memac_mdio_init(bis, memac_mdio0_info); + + memac_mdio1_info = (struct memac_mdio_info *)malloc( + sizeof(struct memac_mdio_info)); + memac_mdio1_info->regs = + (struct memac_mdio_controller *) + CONFIG_SYS_FSL_WRIOP1_MDIO2; + memac_mdio1_info->name = DEFAULT_WRIOP_MDIO2_NAME; + + /* Register the real MDIO2 bus */ + fm_memac_mdio_init(bis, memac_mdio1_info); + + /* Register the muxing front-ends to the MDIO buses */ + ls2085a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT1); + ls2085a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT2); + ls2085a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT3); + ls2085a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT4); + ls2085a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT5); + ls2085a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT6); + + ls2085a_qds_mdio_init(DEFAULT_WRIOP_MDIO2_NAME, EMI2); + + for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) { + switch (wriop_get_enet_if(i)) { + case PHY_INTERFACE_MODE_QSGMII: + break; + case PHY_INTERFACE_MODE_SGMII: + ls2085a_handle_phy_interface_sgmii(i); + break; + case PHY_INTERFACE_MODE_XGMII: + ls2085a_handle_phy_interface_xsgmii(i); + break; + default: + break; + } + } + + error = cpu_eth_init(bis); +#endif + error = pci_eth_init(bis); + return error; +} diff --git a/board/freescale/ls2085aqds/ls2085aqds.c b/board/freescale/ls2085aqds/ls2085aqds.c new file mode 100644 index 0000000..6a22122 --- /dev/null +++ b/board/freescale/ls2085aqds/ls2085aqds.c @@ -0,0 +1,274 @@ +/* + * Copyright 2015 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <malloc.h> +#include <errno.h> +#include <netdev.h> +#include <fsl_ifc.h> +#include <fsl_ddr.h> +#include <asm/io.h> +#include <fdt_support.h> +#include <libfdt.h> +#include <fsl_debug_server.h> +#include <fsl-mc/fsl_mc.h> +#include <environment.h> +#include <i2c.h> +#include <asm/arch-fsl-lsch3/soc.h> + +#include "../common/qixis.h" +#include "ls2085aqds_qixis.h" + +DECLARE_GLOBAL_DATA_PTR; + +unsigned long long get_qixis_addr(void) +{ + unsigned long long addr; + + if (gd->flags & GD_FLG_RELOC) + addr = QIXIS_BASE_PHYS; + else + addr = QIXIS_BASE_PHYS_EARLY; + + /* + * IFC address under 256MB is mapped to 0x30000000, any address above + * is mapped to 0x5_10000000 up to 4GB. + */ + addr = addr > 0x10000000 ? addr + 0x500000000ULL : addr + 0x30000000; + + return addr; +} + +int checkboard(void) +{ + char buf[64]; + u8 sw; + static const char *const freq[] = {"100", "125", "156.25", + "100 separate SSCG"}; + int clock; + + sw = QIXIS_READ(arch); + printf("Board: %s, ", CONFIG_IDENT_STRING); + printf("Board Arch: V%d, ", sw >> 4); + printf("Board version: %c, boot from ", (sw & 0xf) + 'A' - 1); + + sw = QIXIS_READ(brdcfg[0]); + sw = (sw & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT; + + if (sw < 0x8) + printf("vBank: %d\n", sw); + else if (sw == 0x8) + puts("PromJet\n"); + else if (sw == 0x9) + puts("NAND\n"); + else if (sw == 0x15) + printf("IFCCard\n"); + else + printf("invalid setting of SW%u\n", QIXIS_LBMAP_SWITCH); + + printf("FPGA: v%d (%s), build %d", + (int)QIXIS_READ(scver), qixis_read_tag(buf), + (int)qixis_read_minor()); + /* the timestamp string contains "\n" at the end */ + printf(" on %s", qixis_read_time(buf)); + + /* + * Display the actual SERDES reference clocks as configured by the + * dip switches on the board. Note that the SWx registers could + * technically be set to force the reference clocks to match the + * values that the SERDES expects (or vice versa). For now, however, + * we just display both values and hope the user notices when they + * don't match. + */ + puts("SERDES1 Reference : "); + sw = QIXIS_READ(brdcfg[2]); + clock = (sw >> 6) & 3; + printf("Clock1 = %sMHz ", freq[clock]); + clock = (sw >> 4) & 3; + printf("Clock2 = %sMHz", freq[clock]); + + puts("\nSERDES2 Reference : "); + clock = (sw >> 2) & 3; + printf("Clock1 = %sMHz ", freq[clock]); + clock = (sw >> 0) & 3; + printf("Clock2 = %sMHz\n", freq[clock]); + + return 0; +} + +unsigned long get_board_sys_clk(void) +{ + u8 sysclk_conf = QIXIS_READ(brdcfg[1]); + + switch (sysclk_conf & 0x0F) { + case QIXIS_SYSCLK_83: + return 83333333; + case QIXIS_SYSCLK_100: + return 100000000; + case QIXIS_SYSCLK_125: + return 125000000; + case QIXIS_SYSCLK_133: + return 133333333; + case QIXIS_SYSCLK_150: + return 150000000; + case QIXIS_SYSCLK_160: + return 160000000; + case QIXIS_SYSCLK_166: + return 166666666; + } + return 66666666; +} + +unsigned long get_board_ddr_clk(void) +{ + u8 ddrclk_conf = QIXIS_READ(brdcfg[1]); + + switch ((ddrclk_conf & 0x30) >> 4) { + case QIXIS_DDRCLK_100: + return 100000000; + case QIXIS_DDRCLK_125: + return 125000000; + case QIXIS_DDRCLK_133: + return 133333333; + } + return 66666666; +} + +int select_i2c_ch_pca9547(u8 ch) +{ + int ret; + + ret = i2c_write(I2C_MUX_PCA_ADDR_PRI, 0, 1, &ch, 1); + if (ret) { + puts("PCA: failed to select proper channel\n"); + return ret; + } + + return 0; +} + +int board_init(void) +{ + init_final_memctl_regs(); + +#ifdef CONFIG_ENV_IS_NOWHERE + gd->env_addr = (ulong)&default_environment[0]; +#endif + select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT); + + return 0; +} + +int board_early_init_f(void) +{ + fsl_lsch3_early_init_f(); + return 0; +} + +void detail_board_ddr_info(void) +{ + puts("\nDDR "); + print_size(gd->bd->bi_dram[0].size + gd->bd->bi_dram[1].size, ""); + print_ddr_info(0); + if (gd->bd->bi_dram[2].size) { + puts("\nDP-DDR "); + print_size(gd->bd->bi_dram[2].size, ""); + print_ddr_info(CONFIG_DP_DDR_CTRL); + } +} + +int dram_init(void) +{ + gd->ram_size = initdram(0); + + return 0; +} + +#if defined(CONFIG_ARCH_MISC_INIT) +int arch_misc_init(void) +{ +#ifdef CONFIG_FSL_DEBUG_SERVER + debug_server_init(); +#endif + + return 0; +} +#endif + +unsigned long get_dram_size_to_hide(void) +{ + unsigned long dram_to_hide = 0; + +/* Carve the Debug Server private DRAM block from the end of DRAM */ +#ifdef CONFIG_FSL_DEBUG_SERVER + dram_to_hide += debug_server_get_dram_block_size(); +#endif + +/* Carve the MC private DRAM block from the end of DRAM */ +#ifdef CONFIG_FSL_MC_ENET + dram_to_hide += mc_get_dram_block_size(); +#endif + + return dram_to_hide; +} + +#ifdef CONFIG_FSL_MC_ENET +void fdt_fixup_board_enet(void *fdt) +{ + int offset; + + offset = fdt_path_offset(fdt, "/fsl-mc"); + + if (offset < 0) + offset = fdt_path_offset(fdt, "/fsl,dprc@0"); + + if (offset < 0) { + printf("%s: ERROR: fsl-mc node not found in device tree (error %d)\n", + __func__, offset); + return; + } + + if (get_mc_boot_status() == 0) + fdt_status_okay(fdt, offset); + else + fdt_status_fail(fdt, offset); +} +#endif + +#ifdef CONFIG_OF_BOARD_SETUP +int ft_board_setup(void *blob, bd_t *bd) +{ + phys_addr_t base; + phys_size_t size; + + ft_cpu_setup(blob, bd); + + /* limit the memory size to bank 1 until Linux can handle 40-bit PA */ + base = getenv_bootm_low(); + size = getenv_bootm_size(); + fdt_fixup_memory(blob, (u64)base, (u64)size); + +#ifdef CONFIG_FSL_MC_ENET + fdt_fixup_board_enet(blob); + fsl_mc_ldpaa_exit(bd); +#endif + + return 0; +} +#endif + +void qixis_dump_switch(void) +{ + int i, nr_of_cfgsw; + + QIXIS_WRITE(cms[0], 0x00); + nr_of_cfgsw = QIXIS_READ(cms[1]); + + puts("DIP switch settings dump:\n"); + for (i = 1; i <= nr_of_cfgsw; i++) { + QIXIS_WRITE(cms[0], i); + printf("SW%d = (0x%02x)\n", i, QIXIS_READ(cms[1])); + } +} diff --git a/board/freescale/ls2085aqds/ls2085aqds_qixis.h b/board/freescale/ls2085aqds/ls2085aqds_qixis.h new file mode 100644 index 0000000..e281e5f --- /dev/null +++ b/board/freescale/ls2085aqds/ls2085aqds_qixis.h @@ -0,0 +1,30 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __LS2_QDS_QIXIS_H__ +#define __LS2_QDS_QIXIS_H__ + +/* SYSCLK */ +#define QIXIS_SYSCLK_66 0x0 +#define QIXIS_SYSCLK_83 0x1 +#define QIXIS_SYSCLK_100 0x2 +#define QIXIS_SYSCLK_125 0x3 +#define QIXIS_SYSCLK_133 0x4 +#define QIXIS_SYSCLK_150 0x5 +#define QIXIS_SYSCLK_160 0x6 +#define QIXIS_SYSCLK_166 0x7 + +/* DDRCLK */ +#define QIXIS_DDRCLK_66 0x0 +#define QIXIS_DDRCLK_100 0x1 +#define QIXIS_DDRCLK_125 0x2 +#define QIXIS_DDRCLK_133 0x3 + +#define BRDCFG4_EMISEL_MASK 0xE0 +#define BRDCFG4_EMISEL_SHIFT 5 +#define BRDCFG9_SFPTX_MASK 0x10 +#define BRDCFG9_SFPTX_SHIFT 4 +#endif /*__LS2_QDS_QIXIS_H__*/ diff --git a/board/freescale/ls2085ardb/Kconfig b/board/freescale/ls2085ardb/Kconfig new file mode 100644 index 0000000..85a3dcd --- /dev/null +++ b/board/freescale/ls2085ardb/Kconfig @@ -0,0 +1,16 @@ + +if TARGET_LS2085ARDB + +config SYS_BOARD + default "ls2085ardb" + +config SYS_VENDOR + default "freescale" + +config SYS_SOC + default "fsl-lsch3" + +config SYS_CONFIG_NAME + default "ls2085ardb" + +endif diff --git a/board/freescale/ls2085ardb/MAINTAINERS b/board/freescale/ls2085ardb/MAINTAINERS new file mode 100644 index 0000000..d5cce40 --- /dev/null +++ b/board/freescale/ls2085ardb/MAINTAINERS @@ -0,0 +1,8 @@ +LS2085A BOARD +M: Prabhakar Kushwaha <prabhakar@freescale.com> +S: Maintained +F: board/freescale/ls2085ardb/ +F: board/freescale/ls2085a/ls2085ardb.c +F: include/configs/ls2085ardb.h +F: configs/ls2085ardb_defconfig +F: configs/ls2085ardb_nand_defconfig diff --git a/board/freescale/ls2085ardb/Makefile b/board/freescale/ls2085ardb/Makefile new file mode 100644 index 0000000..0bfe21c --- /dev/null +++ b/board/freescale/ls2085ardb/Makefile @@ -0,0 +1,8 @@ +# +# Copyright 2015 Freescale Semiconductor +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += ls2085ardb.o +obj-y += ddr.o diff --git a/board/freescale/ls2085ardb/README b/board/freescale/ls2085ardb/README new file mode 100644 index 0000000..cfd5185 --- /dev/null +++ b/board/freescale/ls2085ardb/README @@ -0,0 +1,109 @@ +Overview +-------- +The LS2085A Reference Design (RDB) is a high-performance computing, +evaluation, and development platform that supports the QorIQ LS2085A +Layerscape Architecture processor. + +LS2085A SoC Overview +------------------ +The LS2085A integrated multicore processor combines eight ARM Cortex-A57 +processor cores with high-performance data path acceleration logic and network +and peripheral bus interfaces required for networking, telecom/datacom, +wireless infrastructure, and mil/aerospace applications. + +The LS2085A SoC includes the following function and features: + + - Eight 64-bit ARM Cortex-A57 CPUs + - 1 MB platform cache with ECC + - Two 64-bit DDR4 SDRAM memory controllers with ECC and interleaving support + - One secondary 32-bit DDR4 SDRAM memory controller, intended for use by + the AIOP + - Data path acceleration architecture (DPAA2) incorporating acceleration for + the following functions: + - Packet parsing, classification, and distribution (WRIOP) + - Queue and Hardware buffer management for scheduling, packet sequencing, and + congestion management, buffer allocation and de-allocation (QBMan) + - Cryptography acceleration (SEC) at up to 10 Gbps + - RegEx pattern matching acceleration (PME) at up to 10 Gbps + - Decompression/compression acceleration (DCE) at up to 20 Gbps + - Accelerated I/O processing (AIOP) at up to 20 Gbps + - QDMA engine + - 16 SerDes lanes at up to 10.3125 GHz + - Ethernet interfaces + - Up to eight 10 Gbps Ethernet MACs + - Up to eight 1 / 2.5 Gbps Ethernet MACs + - High-speed peripheral interfaces + - Four PCIe 3.0 controllers, one supporting SR-IOV + - Additional peripheral interfaces + - Two serial ATA (SATA 3.0) controllers + - Two high-speed USB 3.0 controllers with integrated PHY + - Enhanced secure digital host controller (eSDXC/eMMC) + - Serial peripheral interface (SPI) controller + - Quad Serial Peripheral Interface (QSPI) Controller + - Four I2C controllers + - Two DUARTs + - Integrated flash controller (IFC 2.0) supporting NAND and NOR flash + - Support for hardware virtualization and partitioning enforcement + - QorIQ platform's trust architecture 3.0 + - Service processor (SP) provides pre-boot initialization and secure-boot + capabilities + + LS2085ARDB board Overview + ----------------------- + - SERDES Connections, 16 lanes supporting: + - PCI Express - 3.0 + - SATA 3.0 + - XFI + - DDR Controller + - Two ports of 72-bits (8-bits ECC) DDR4. Each port supports four + chip-selects and two DIMM connectors. Support is up to 2133MT/s. + - One port of 40-bits (8-bits ECC) DDR4 which supports four chip-selects + and two DIMM connectors. Support is up to 1600MT/s. + -IFC/Local Bus + - IFC rev. 2.0 implementation supporting Little Endian connection scheme. + - 128 MB NOR flash 16-bit data bus + - One 2 GB NAND flash with ECC support + - CPLD connection + - USB 3.0 + - Two high speed USB 3.0 ports + - First USB 3.0 port configured as Host with Type-A connector + - Second USB 3.0 port configured as OTG with micro-AB connector + - SDHC adapter + - SD Card Rev 2.0 and Rev 3.0 + - DSPI + - 128 MB high-speed flash Memory for boot code and storage (up to 108MHz) + - 4 I2C controllers + - Two SATA onboard connectors + - UART + - ARM JTAG support + +Memory map from core's view +---------------------------- +0x00_0000_0000 .. 0x00_000F_FFFF Boot Rom +0x00_0100_0000 .. 0x00_0FFF_FFFF CCSR +0x00_1800_0000 .. 0x00_181F_FFFF OCRAM +0x00_3000_0000 .. 0x00_3FFF_FFFF IFC region #1 +0x00_8000_0000 .. 0x00_FFFF_FFFF DDR region #1 +0x05_1000_0000 .. 0x05_FFFF_FFFF IFC region #2 +0x80_8000_0000 .. 0xFF_FFFF_FFFF DDR region #2 + +Other addresses are either reserved, or not used directly by u-boot. +This list should be updated when more addresses are used. + +IFC region map from core's view +------------------------------- +During boot i.e. IFC Region #1:- + 0x30000000 - 0x37ffffff : 128MB : NOR flash + 0x3C000000 - 0x40000000 : 64MB : CPLD + +After relocate to DDR i.e. IFC Region #2:- + 0x5_1000_0000..0x5_1fff_ffff Memory Hole + 0x5_2000_0000..0x5_3fff_ffff IFC CSx (CPLD, NAND and others 512MB) + 0x5_4000_0000..0x5_7fff_ffff ASIC or others 1GB + 0x5_8000_0000..0x5_bfff_ffff IFC CS0 1GB (NOR/Promjet) + 0x5_C000_0000..0x5_ffff_ffff IFC CS1 1GB (NOR/Promjet) + +Booting Options +--------------- +a) NOR boot +b) NAND boot diff --git a/board/freescale/ls2085ardb/ddr.c b/board/freescale/ls2085ardb/ddr.c new file mode 100644 index 0000000..8d71ae1 --- /dev/null +++ b/board/freescale/ls2085ardb/ddr.c @@ -0,0 +1,196 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <fsl_ddr_sdram.h> +#include <fsl_ddr_dimm_params.h> +#include "ddr.h" + +DECLARE_GLOBAL_DATA_PTR; + +void fsl_ddr_board_options(memctl_options_t *popts, + dimm_params_t *pdimm, + unsigned int ctrl_num) +{ + u8 dq_mapping_0, dq_mapping_2, dq_mapping_3; + const struct board_specific_parameters *pbsp, *pbsp_highest = NULL; + ulong ddr_freq; + int slot; + + if (ctrl_num > 2) { + printf("Not supported controller number %d\n", ctrl_num); + return; + } + + for (slot = 0; slot < CONFIG_DIMM_SLOTS_PER_CTLR; slot++) { + if (pdimm[slot].n_ranks) + break; + } + + if (slot >= CONFIG_DIMM_SLOTS_PER_CTLR) + return; + + /* + * we use identical timing for all slots. If needed, change the code + * to pbsp = rdimms[ctrl_num] or pbsp = udimms[ctrl_num]; + */ + if (popts->registered_dimm_en) + pbsp = rdimms[ctrl_num]; + else + pbsp = udimms[ctrl_num]; + + + /* Get clk_adjust, wrlvl_start, wrlvl_ctl, according to the board ddr + * freqency and n_banks specified in board_specific_parameters table. + */ + ddr_freq = get_ddr_freq(ctrl_num) / 1000000; + while (pbsp->datarate_mhz_high) { + if (pbsp->n_ranks == pdimm[slot].n_ranks && + (pdimm[slot].rank_density >> 30) >= pbsp->rank_gb) { + if (ddr_freq <= pbsp->datarate_mhz_high) { + popts->clk_adjust = pbsp->clk_adjust; + popts->wrlvl_start = pbsp->wrlvl_start; + popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2; + popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3; + goto found; + } + pbsp_highest = pbsp; + } + pbsp++; + } + + if (pbsp_highest) { + printf("Error: board specific timing not found for data rate %lu MT/s\n" + "Trying to use the highest speed (%u) parameters\n", + ddr_freq, pbsp_highest->datarate_mhz_high); + popts->clk_adjust = pbsp_highest->clk_adjust; + popts->wrlvl_start = pbsp_highest->wrlvl_start; + popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2; + popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3; + } else { + panic("DIMM is not supported by this board"); + } +found: + debug("Found timing match: n_ranks %d, data rate %d, rank_gb %d\n" + "\tclk_adjust %d, wrlvl_start %d, wrlvl_ctrl_2 0x%x, wrlvl_ctrl_3 0x%x\n", + pbsp->n_ranks, pbsp->datarate_mhz_high, pbsp->rank_gb, + pbsp->clk_adjust, pbsp->wrlvl_start, pbsp->wrlvl_ctl_2, + pbsp->wrlvl_ctl_3); + + if (ctrl_num == CONFIG_DP_DDR_CTRL) { + /* force DDR bus width to 32 bits */ + popts->data_bus_width = 1; + popts->otf_burst_chop_en = 0; + popts->burst_length = DDR_BL8; + popts->bstopre = 0; /* enable auto precharge */ + /* + * Layout optimization results byte mapping + * Byte 0 -> Byte ECC + * Byte 1 -> Byte 3 + * Byte 2 -> Byte 2 + * Byte 3 -> Byte 1 + * Byte ECC -> Byte 0 + */ + dq_mapping_0 = pdimm[slot].dq_mapping[0]; + dq_mapping_2 = pdimm[slot].dq_mapping[2]; + dq_mapping_3 = pdimm[slot].dq_mapping[3]; + pdimm[slot].dq_mapping[0] = pdimm[slot].dq_mapping[8]; + pdimm[slot].dq_mapping[1] = pdimm[slot].dq_mapping[9]; + pdimm[slot].dq_mapping[2] = pdimm[slot].dq_mapping[6]; + pdimm[slot].dq_mapping[3] = pdimm[slot].dq_mapping[7]; + pdimm[slot].dq_mapping[6] = dq_mapping_2; + pdimm[slot].dq_mapping[7] = dq_mapping_3; + pdimm[slot].dq_mapping[8] = dq_mapping_0; + pdimm[slot].dq_mapping[9] = 0; + pdimm[slot].dq_mapping[10] = 0; + pdimm[slot].dq_mapping[11] = 0; + pdimm[slot].dq_mapping[12] = 0; + pdimm[slot].dq_mapping[13] = 0; + pdimm[slot].dq_mapping[14] = 0; + pdimm[slot].dq_mapping[15] = 0; + pdimm[slot].dq_mapping[16] = 0; + pdimm[slot].dq_mapping[17] = 0; + } + /* To work at higher than 1333MT/s */ + popts->half_strength_driver_enable = 0; + /* + * Write leveling override + */ + popts->wrlvl_override = 1; + popts->wrlvl_sample = 0x0; /* 32 clocks */ + + /* + * Rtt and Rtt_WR override + */ + popts->rtt_override = 0; + + /* Enable ZQ calibration */ + popts->zq_en = 1; + + if (ddr_freq < 2350) { + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | + DDR_CDR1_ODT(DDR_CDR_ODT_60ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_60ohm) | + DDR_CDR2_VREF_RANGE_2; + } else { + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | + DDR_CDR1_ODT(DDR_CDR_ODT_100ohm); + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_100ohm) | + DDR_CDR2_VREF_RANGE_2; + } +} + +phys_size_t initdram(int board_type) +{ + phys_size_t dram_size; + +#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD) + return fsl_ddr_sdram_size(); +#else + puts("Initializing DDR....using SPD\n"); + + dram_size = fsl_ddr_sdram(); +#endif + + return dram_size; +} + +void dram_init_banksize(void) +{ +#ifdef CONFIG_SYS_DP_DDR_BASE_PHY + phys_size_t dp_ddr_size; +#endif + + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; + if (gd->ram_size > CONFIG_SYS_LS2_DDR_BLOCK1_SIZE) { + gd->bd->bi_dram[0].size = CONFIG_SYS_LS2_DDR_BLOCK1_SIZE; + gd->bd->bi_dram[1].start = CONFIG_SYS_DDR_BLOCK2_BASE; + gd->bd->bi_dram[1].size = gd->ram_size - + CONFIG_SYS_LS2_DDR_BLOCK1_SIZE; + } else { + gd->bd->bi_dram[0].size = gd->ram_size; + } + +#ifdef CONFIG_SYS_DP_DDR_BASE_PHY + /* initialize DP-DDR here */ + puts("DP-DDR: "); + /* + * DDR controller use 0 as the base address for binding. + * It is mapped to CONFIG_SYS_DP_DDR_BASE for core to access. + */ + dp_ddr_size = fsl_other_ddr_sdram(CONFIG_SYS_DP_DDR_BASE_PHY, + CONFIG_DP_DDR_CTRL, + CONFIG_DP_DDR_NUM_CTRLS, + CONFIG_DP_DDR_DIMM_SLOTS_PER_CTLR, + NULL, NULL, NULL); + if (dp_ddr_size) { + gd->bd->bi_dram[2].start = CONFIG_SYS_DP_DDR_BASE; + gd->bd->bi_dram[2].size = dp_ddr_size; + } else { + puts("Not detected"); + } +#endif +} diff --git a/board/freescale/ls2085ardb/ddr.h b/board/freescale/ls2085ardb/ddr.h new file mode 100644 index 0000000..bda9d4a --- /dev/null +++ b/board/freescale/ls2085ardb/ddr.h @@ -0,0 +1,92 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __DDR_H__ +#define __DDR_H__ +struct board_specific_parameters { + u32 n_ranks; + u32 datarate_mhz_high; + u32 rank_gb; + u32 clk_adjust; + u32 wrlvl_start; + u32 wrlvl_ctl_2; + u32 wrlvl_ctl_3; +}; + +/* + * These tables contain all valid speeds we want to override with board + * specific parameters. datarate_mhz_high values need to be in ascending order + * for each n_ranks group. + */ + +static const struct board_specific_parameters udimm0[] = { + /* + * memory controller 0 + * num| hi| rank| clk| wrlvl | wrlvl | wrlvl + * ranks| mhz| GB |adjst| start | ctl2 | ctl3 + */ + {2, 1350, 0, 4, 6, 0x0708090B, 0x0C0D0E09,}, + {2, 1666, 0, 4, 8, 0x08090B0D, 0x0E10100C,}, + {2, 1900, 0, 4, 8, 0x090A0C0E, 0x1012120D,}, + {2, 2300, 0, 4, 9, 0x0A0B0C10, 0x1114140E,}, + {} +}; + +/* DP-DDR DIMM */ +static const struct board_specific_parameters udimm2[] = { + /* + * memory controller 2 + * num| hi| rank| clk| wrlvl | wrlvl | wrlvl + * ranks| mhz| GB |adjst| start | ctl2 | ctl3 + */ + {2, 1350, 0, 4, 0xd, 0x0C0A0A00, 0x00000009,}, + {2, 1666, 0, 4, 0xd, 0x0C0A0A00, 0x00000009,}, + {2, 1900, 0, 4, 0xe, 0x0D0C0B00, 0x0000000A,}, + {2, 2200, 0, 4, 0xe, 0x0D0C0B00, 0x0000000A,}, + {} +}; + +static const struct board_specific_parameters rdimm0[] = { + /* + * memory controller 0 + * num| hi| rank| clk| wrlvl | wrlvl | wrlvl + * ranks| mhz| GB |adjst| start | ctl2 | ctl3 + */ + {2, 1350, 0, 4, 6, 0x0708090B, 0x0C0D0E09,}, + {2, 1666, 0, 4, 7, 0x08090A0C, 0x0D0F100B,}, + {2, 1900, 0, 4, 7, 0x09090B0D, 0x0E10120B,}, + {2, 2200, 0, 4, 8, 0x090A0C0F, 0x1012130C,}, + {} +}; + +/* DP-DDR DIMM */ +static const struct board_specific_parameters rdimm2[] = { + /* + * memory controller 2 + * num| hi| rank| clk| wrlvl | wrlvl | wrlvl + * ranks| mhz| GB |adjst| start | ctl2 | ctl3 + */ + {2, 1350, 0, 4, 6, 0x0708090B, 0x0C0D0E09,}, + {2, 1666, 0, 4, 7, 0x0B0A090C, 0x0D0F100B,}, + {2, 1900, 0, 4, 7, 0x09090B0D, 0x0E10120B,}, + {2, 2200, 0, 4, 8, 0x090A0C0F, 0x1012130C,}, + {} +}; + +static const struct board_specific_parameters *udimms[] = { + udimm0, + udimm0, + udimm2, +}; + +static const struct board_specific_parameters *rdimms[] = { + rdimm0, + rdimm0, + rdimm2, +}; + + +#endif diff --git a/board/freescale/ls2085ardb/ls2085ardb.c b/board/freescale/ls2085ardb/ls2085ardb.c new file mode 100644 index 0000000..d05f2bc --- /dev/null +++ b/board/freescale/ls2085ardb/ls2085ardb.c @@ -0,0 +1,249 @@ +/* + * Copyright 2015 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <malloc.h> +#include <errno.h> +#include <netdev.h> +#include <fsl_ifc.h> +#include <fsl_ddr.h> +#include <asm/io.h> +#include <fdt_support.h> +#include <libfdt.h> +#include <fsl_debug_server.h> +#include <fsl-mc/fsl_mc.h> +#include <environment.h> +#include <i2c.h> +#include <asm/arch-fsl-lsch3/soc.h> + +#include "../common/qixis.h" +#include "ls2085ardb_qixis.h" + +DECLARE_GLOBAL_DATA_PTR; + +unsigned long long get_qixis_addr(void) +{ + unsigned long long addr; + + if (gd->flags & GD_FLG_RELOC) + addr = QIXIS_BASE_PHYS; + else + addr = QIXIS_BASE_PHYS_EARLY; + + /* + * IFC address under 256MB is mapped to 0x30000000, any address above + * is mapped to 0x5_10000000 up to 4GB. + */ + addr = addr > 0x10000000 ? addr + 0x500000000ULL : addr + 0x30000000; + + return addr; +} + +int checkboard(void) +{ + u8 sw; + + sw = QIXIS_READ(arch); + printf("Board: %s, ", CONFIG_IDENT_STRING); + printf("Board Arch: V%d, ", sw >> 4); + printf("Board version: %c, boot from ", (sw & 0xf) + 'A' - 1); + + sw = QIXIS_READ(brdcfg[0]); + sw = (sw & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT; + + if (sw < 0x8) + printf("vBank: %d\n", sw); + else if (sw == 0x9) + puts("NAND\n"); + else + printf("invalid setting of SW%u\n", QIXIS_LBMAP_SWITCH); + + printf("FPGA: v%d.%d\n", QIXIS_READ(scver), QIXIS_READ(tagdata)); + + puts("SERDES1 Reference : "); + printf("Clock1 = 156.25MHz "); + printf("Clock2 = 156.25MHz"); + + puts("\nSERDES2 Reference : "); + printf("Clock1 = 100MHz "); + printf("Clock2 = 100MHz\n"); + + return 0; +} + +unsigned long get_board_sys_clk(void) +{ + u8 sysclk_conf = QIXIS_READ(brdcfg[1]); + + switch (sysclk_conf & 0x0F) { + case QIXIS_SYSCLK_83: + return 83333333; + case QIXIS_SYSCLK_100: + return 100000000; + case QIXIS_SYSCLK_125: + return 125000000; + case QIXIS_SYSCLK_133: + return 133333333; + case QIXIS_SYSCLK_150: + return 150000000; + case QIXIS_SYSCLK_160: + return 160000000; + case QIXIS_SYSCLK_166: + return 166666666; + } + return 66666666; +} + +int select_i2c_ch_pca9547(u8 ch) +{ + int ret; + + ret = i2c_write(I2C_MUX_PCA_ADDR_PRI, 0, 1, &ch, 1); + if (ret) { + puts("PCA: failed to select proper channel\n"); + return ret; + } + + return 0; +} + +int board_init(void) +{ + init_final_memctl_regs(); + +#ifdef CONFIG_ENV_IS_NOWHERE + gd->env_addr = (ulong)&default_environment[0]; +#endif + select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT); + + QIXIS_WRITE(rst_ctl, QIXIS_RST_CTL_RESET_EN); + + return 0; +} + +int board_early_init_f(void) +{ + fsl_lsch3_early_init_f(); + return 0; +} + +void detail_board_ddr_info(void) +{ + puts("\nDDR "); + print_size(gd->bd->bi_dram[0].size + gd->bd->bi_dram[1].size, ""); + print_ddr_info(0); + if (gd->bd->bi_dram[2].size) { + puts("\nDP-DDR "); + print_size(gd->bd->bi_dram[2].size, ""); + print_ddr_info(CONFIG_DP_DDR_CTRL); + } +} + +int dram_init(void) +{ + gd->ram_size = initdram(0); + + return 0; +} + +#if defined(CONFIG_ARCH_MISC_INIT) +int arch_misc_init(void) +{ +#ifdef CONFIG_FSL_DEBUG_SERVER + debug_server_init(); +#endif + + return 0; +} +#endif + +unsigned long get_dram_size_to_hide(void) +{ + unsigned long dram_to_hide = 0; + +/* Carve the Debug Server private DRAM block from the end of DRAM */ +#ifdef CONFIG_FSL_DEBUG_SERVER + dram_to_hide += debug_server_get_dram_block_size(); +#endif + +/* Carve the MC private DRAM block from the end of DRAM */ +#ifdef CONFIG_FSL_MC_ENET + dram_to_hide += mc_get_dram_block_size(); +#endif + + return dram_to_hide; +} + +int board_eth_init(bd_t *bis) +{ + int error = 0; + +#ifdef CONFIG_FSL_MC_ENET + error = cpu_eth_init(bis); +#endif + + error = pci_eth_init(bis); + + return error; +} + +#ifdef CONFIG_FSL_MC_ENET +void fdt_fixup_board_enet(void *fdt) +{ + int offset; + + offset = fdt_path_offset(fdt, "/fsl-mc"); + + if (offset < 0) + offset = fdt_path_offset(fdt, "/fsl,dprc@0"); + + if (offset < 0) { + printf("%s: ERROR: fsl-mc node not found in device tree (error %d)\n", + __func__, offset); + return; + } + + if (get_mc_boot_status() == 0) + fdt_status_okay(fdt, offset); + else + fdt_status_fail(fdt, offset); +} +#endif + +#ifdef CONFIG_OF_BOARD_SETUP +int ft_board_setup(void *blob, bd_t *bd) +{ + phys_addr_t base; + phys_size_t size; + + ft_cpu_setup(blob, bd); + + /* limit the memory size to bank 1 until Linux can handle 40-bit PA */ + base = getenv_bootm_low(); + size = getenv_bootm_size(); + fdt_fixup_memory(blob, (u64)base, (u64)size); + +#ifdef CONFIG_FSL_MC_ENET + fdt_fixup_board_enet(blob); + fsl_mc_ldpaa_exit(bd); +#endif + + return 0; +} +#endif + +void qixis_dump_switch(void) +{ + int i, nr_of_cfgsw; + + QIXIS_WRITE(cms[0], 0x00); + nr_of_cfgsw = QIXIS_READ(cms[1]); + + puts("DIP switch settings dump:\n"); + for (i = 1; i <= nr_of_cfgsw; i++) { + QIXIS_WRITE(cms[0], i); + printf("SW%d = (0x%02x)\n", i, QIXIS_READ(cms[1])); + } +} diff --git a/board/freescale/ls2085ardb/ls2085ardb_qixis.h b/board/freescale/ls2085ardb/ls2085ardb_qixis.h new file mode 100644 index 0000000..cb60c00 --- /dev/null +++ b/board/freescale/ls2085ardb/ls2085ardb_qixis.h @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __LS2_RDB_QIXIS_H__ +#define __LS2_RDB_QIXIS_H__ + +/* SYSCLK */ +#define QIXIS_SYSCLK_66 0x0 +#define QIXIS_SYSCLK_83 0x1 +#define QIXIS_SYSCLK_100 0x2 +#define QIXIS_SYSCLK_125 0x3 +#define QIXIS_SYSCLK_133 0x4 +#define QIXIS_SYSCLK_150 0x5 +#define QIXIS_SYSCLK_160 0x6 +#define QIXIS_SYSCLK_166 0x7 + +#endif /*__LS2_RDB_QIXIS_H__*/ diff --git a/board/freescale/p1010rdb/p1010rdb.c b/board/freescale/p1010rdb/p1010rdb.c index 1cf0ab7..ebffe9a 100644 --- a/board/freescale/p1010rdb/p1010rdb.c +++ b/board/freescale/p1010rdb/p1010rdb.c @@ -77,10 +77,9 @@ struct cpld_data { int board_early_init_f(void) { ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO_ADDR); - struct fsl_ifc *ifc = (void *)CONFIG_SYS_IFC_ADDR; - + struct fsl_ifc ifc = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL}; /* Clock configuration to access CPLD using IFC(GPCM) */ - setbits_be32(&ifc->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT); + setbits_be32(&ifc.gregs->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT); /* * Reset PCIe slots via GPIO4 */ diff --git a/board/freescale/p1010rdb/spl.c b/board/freescale/p1010rdb/spl.c index 11bd9cf..ee873b0 100644 --- a/board/freescale/p1010rdb/spl.c +++ b/board/freescale/p1010rdb/spl.c @@ -23,12 +23,12 @@ void board_init_f(ulong bootflag) { u32 plat_ratio; ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR; - struct fsl_ifc *ifc = (void *)CONFIG_SYS_IFC_ADDR; + struct fsl_ifc ifc = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL}; console_init_f(); /* Clock configuration to access CPLD using IFC(GPCM) */ - setbits_be32(&ifc->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT); + setbits_be32(&ifc.gregs->ifc_gcr, 1 << IFC_GCR_TBCTL_TRN_TIME_SHIFT); #ifdef CONFIG_P1010RDB_PB setbits_be32(&gur->pmuxcr2, MPC85xx_PMUXCR2_GPIO01_DRVVBUS); diff --git a/common/board_r.c b/common/board_r.c index 42ff18c..307124e 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -702,6 +702,12 @@ init_fnc_t init_sequence_r[] = { /* TODO: could x86/PPC have this also perhaps? */ #ifdef CONFIG_ARM initr_caches, + /* Note: For Freescale LS2 SoCs, new MMU table is created in DDR. + * A temporary mapping of IFC high region is since removed, + * so environmental variables in NOR flash is not availble + * until board_init() is called below to remap IFC to high + * region. + */ #endif initr_reloc_global_data, #if defined(CONFIG_SYS_INIT_RAM_LOCK) && defined(CONFIG_E500) diff --git a/common/cmd_mem.c b/common/cmd_mem.c index 45e471c..5d8c9e6 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -36,9 +36,9 @@ static int mod_mem(cmd_tbl_t *, int, int, int, char * const []); /* Display values from last command. * Memory modify remembered values are different from display memory. */ -static uint dp_last_addr, dp_last_size; -static uint dp_last_length = 0x40; -static uint mm_last_addr, mm_last_size; +static ulong dp_last_addr, dp_last_size; +static ulong dp_last_length = 0x40; +static ulong mm_last_addr, mm_last_size; static ulong base_address = 0; diff --git a/common/spl/spl.c b/common/spl/spl.c index 6a02c9e..690c9b0 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -125,7 +125,7 @@ __weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) typedef void __noreturn (*image_entry_noargs_t)(void); image_entry_noargs_t image_entry = - (image_entry_noargs_t) spl_image->entry_point; + (image_entry_noargs_t)(unsigned long)spl_image->entry_point; debug("image entry point: 0x%X\n", spl_image->entry_point); image_entry(); diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index b7801cb..b8c369d 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -91,7 +91,7 @@ void spl_nand_load_image(void) sizeof(*header), (void *)header); spl_parse_image_header(header); nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS, - spl_image.size, (void *)spl_image.load_addr); + spl_image.size, (void *)(unsigned long)spl_image.load_addr); nand_deselect(); } #endif diff --git a/configs/ls1021aqds_ddr4_nor_lpuart_defconfig b/configs/ls1021aqds_ddr4_nor_lpuart_defconfig new file mode 100644 index 0000000..4d2714b --- /dev/null +++ b/configs/ls1021aqds_ddr4_nor_lpuart_defconfig @@ -0,0 +1,3 @@ +CONFIG_SYS_EXTRA_OPTIONS="SYS_FSL_DDR4,LPUART" +CONFIG_ARM=y +CONFIG_TARGET_LS1021AQDS=y diff --git a/configs/ls2085aqds_defconfig b/configs/ls2085aqds_defconfig new file mode 100644 index 0000000..e3a17a3 --- /dev/null +++ b/configs/ls2085aqds_defconfig @@ -0,0 +1,3 @@ +CONFIG_SYS_EXTRA_OPTIONS="SYS_FSL_DDR4" +CONFIG_ARM=y +CONFIG_TARGET_LS2085AQDS=y diff --git a/configs/ls2085aqds_nand_defconfig b/configs/ls2085aqds_nand_defconfig new file mode 100644 index 0000000..f84a426 --- /dev/null +++ b/configs/ls2085aqds_nand_defconfig @@ -0,0 +1,4 @@ +CONFIG_SYS_EXTRA_OPTIONS="SYS_FSL_DDR4,NAND" +CONFIG_SPL=y +CONFIG_ARM=y +CONFIG_TARGET_LS2085AQDS=y diff --git a/configs/ls2085ardb_defconfig b/configs/ls2085ardb_defconfig new file mode 100644 index 0000000..6b64f71 --- /dev/null +++ b/configs/ls2085ardb_defconfig @@ -0,0 +1,3 @@ +CONFIG_SYS_EXTRA_OPTIONS="SYS_FSL_DDR4" +CONFIG_ARM=y +CONFIG_TARGET_LS2085ARDB=y diff --git a/configs/ls2085ardb_nand_defconfig b/configs/ls2085ardb_nand_defconfig new file mode 100644 index 0000000..74812f7 --- /dev/null +++ b/configs/ls2085ardb_nand_defconfig @@ -0,0 +1,4 @@ +CONFIG_SYS_EXTRA_OPTIONS="SYS_FSL_DDR4,NAND" +CONFIG_SPL=y +CONFIG_ARM=y +CONFIG_TARGET_LS2085ARDB=y diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c index 3919257..8367c95 100644 --- a/drivers/ddr/fsl/ctrl_regs.c +++ b/drivers/ddr/fsl/ctrl_regs.c @@ -313,7 +313,10 @@ static void set_timing_cfg_0(const unsigned int ctrl_num, #ifdef CONFIG_SYS_FSL_DDR4 /* tXP=max(4nCK, 6ns) */ int txp = max((int)mclk_ps * 4, 6000); /* unit=ps */ - trwt_mclk = 2; + unsigned int data_rate = get_ddr_freq(ctrl_num); + + /* for faster clock, need more time for data setup */ + trwt_mclk = (data_rate/1000000 > 1900) ? 3 : 2; twrt_mclk = 1; act_pd_exit_mclk = picos_to_mclk(ctrl_num, txp); pre_pd_exit_mclk = act_pd_exit_mclk; @@ -338,7 +341,7 @@ static void set_timing_cfg_0(const unsigned int ctrl_num, */ txp = max((int)mclk_ps * 3, (mclk_ps > 1540 ? 7500 : 6000)); - ip_rev = fsl_ddr_get_version(); + ip_rev = fsl_ddr_get_version(ctrl_num); if (ip_rev >= 0x40700) { /* * MRS_CYC = max(tMRD, tMOD) @@ -544,7 +547,7 @@ static void set_timing_cfg_1(const unsigned int ctrl_num, * we need set extend bit for it at * TIMING_CFG_3[EXT_CASLAT] */ - if (fsl_ddr_get_version() <= 0x40400) + if (fsl_ddr_get_version(ctrl_num) <= 0x40400) caslat_ctrl = 2 * cas_latency - 1; else caslat_ctrl = (cas_latency - 1) << 1; @@ -1113,16 +1116,32 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr, int i; unsigned short esdmode4 = 0; /* Extended SDRAM mode 4 */ unsigned short esdmode5; /* Extended SDRAM mode 5 */ + int rtt_park = 0; - esdmode5 = 0x00000400; /* Data mask enabled */ + if (ddr->cs[0].config & SDRAM_CS_CONFIG_EN) { + esdmode5 = 0x00000500; /* Data mask enable, RTT_PARK CS0 */ + rtt_park = 1; + } else { + esdmode5 = 0x00000400; /* Data mask enabled */ + } ddr->ddr_sdram_mode_9 = (0 | ((esdmode4 & 0xffff) << 16) | ((esdmode5 & 0xffff) << 0) ); + + /* only mode_9 use 0x500, others use 0x400 */ + debug("FSLDDR: ddr_sdram_mode_9) = 0x%08x\n", ddr->ddr_sdram_mode_9); if (unq_mrs_en) { /* unique mode registers are supported */ for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { + if (!rtt_park && + (ddr->cs[i].config & SDRAM_CS_CONFIG_EN)) { + esdmode5 |= 0x00000500; /* RTT_PARK */ + rtt_park = 1; + } else { + esdmode5 = 0x00000400; + } switch (i) { case 1: ddr->ddr_sdram_mode_11 = (0 @@ -1970,31 +1989,41 @@ static void set_ddr_dq_mapping(fsl_ddr_cfg_regs_t *ddr, const dimm_params_t *dimm_params) { unsigned int acc_ecc_en = (ddr->ddr_sdram_cfg >> 2) & 0x1; + int i; + + for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) { + if (dimm_params[i].n_ranks) + break; + } + if (i >= CONFIG_DIMM_SLOTS_PER_CTLR) { + puts("DDR error: no DIMM found!\n"); + return; + } - ddr->dq_map_0 = ((dimm_params->dq_mapping[0] & 0x3F) << 26) | - ((dimm_params->dq_mapping[1] & 0x3F) << 20) | - ((dimm_params->dq_mapping[2] & 0x3F) << 14) | - ((dimm_params->dq_mapping[3] & 0x3F) << 8) | - ((dimm_params->dq_mapping[4] & 0x3F) << 2); + ddr->dq_map_0 = ((dimm_params[i].dq_mapping[0] & 0x3F) << 26) | + ((dimm_params[i].dq_mapping[1] & 0x3F) << 20) | + ((dimm_params[i].dq_mapping[2] & 0x3F) << 14) | + ((dimm_params[i].dq_mapping[3] & 0x3F) << 8) | + ((dimm_params[i].dq_mapping[4] & 0x3F) << 2); - ddr->dq_map_1 = ((dimm_params->dq_mapping[5] & 0x3F) << 26) | - ((dimm_params->dq_mapping[6] & 0x3F) << 20) | - ((dimm_params->dq_mapping[7] & 0x3F) << 14) | - ((dimm_params->dq_mapping[10] & 0x3F) << 8) | - ((dimm_params->dq_mapping[11] & 0x3F) << 2); + ddr->dq_map_1 = ((dimm_params[i].dq_mapping[5] & 0x3F) << 26) | + ((dimm_params[i].dq_mapping[6] & 0x3F) << 20) | + ((dimm_params[i].dq_mapping[7] & 0x3F) << 14) | + ((dimm_params[i].dq_mapping[10] & 0x3F) << 8) | + ((dimm_params[i].dq_mapping[11] & 0x3F) << 2); - ddr->dq_map_2 = ((dimm_params->dq_mapping[12] & 0x3F) << 26) | - ((dimm_params->dq_mapping[13] & 0x3F) << 20) | - ((dimm_params->dq_mapping[14] & 0x3F) << 14) | - ((dimm_params->dq_mapping[15] & 0x3F) << 8) | - ((dimm_params->dq_mapping[16] & 0x3F) << 2); + ddr->dq_map_2 = ((dimm_params[i].dq_mapping[12] & 0x3F) << 26) | + ((dimm_params[i].dq_mapping[13] & 0x3F) << 20) | + ((dimm_params[i].dq_mapping[14] & 0x3F) << 14) | + ((dimm_params[i].dq_mapping[15] & 0x3F) << 8) | + ((dimm_params[i].dq_mapping[16] & 0x3F) << 2); /* dq_map for ECC[4:7] is set to 0 if accumulated ECC is enabled */ - ddr->dq_map_3 = ((dimm_params->dq_mapping[17] & 0x3F) << 26) | - ((dimm_params->dq_mapping[8] & 0x3F) << 20) | + ddr->dq_map_3 = ((dimm_params[i].dq_mapping[17] & 0x3F) << 26) | + ((dimm_params[i].dq_mapping[8] & 0x3F) << 20) | (acc_ecc_en ? 0 : - (dimm_params->dq_mapping[9] & 0x3F) << 14) | - dimm_params->dq_mapping_ors; + (dimm_params[i].dq_mapping[9] & 0x3F) << 14) | + dimm_params[i].dq_mapping_ors; debug("FSLDDR: dq_map_0 = 0x%08x\n", ddr->dq_map_0); debug("FSLDDR: dq_map_1 = 0x%08x\n", ddr->dq_map_1); @@ -2357,7 +2386,7 @@ compute_fsl_memctl_config_regs(const unsigned int ctrl_num, set_ddr_cdr1(ddr, popts); set_ddr_cdr2(ddr, popts); set_ddr_sdram_cfg(ddr, popts, common_dimm); - ip_rev = fsl_ddr_get_version(); + ip_rev = fsl_ddr_get_version(ctrl_num); if (ip_rev > 0x40400) unq_mrs_en = 1; diff --git a/drivers/ddr/fsl/ddr4_dimm_params.c b/drivers/ddr/fsl/ddr4_dimm_params.c index bbfb4ee..42834ca 100644 --- a/drivers/ddr/fsl/ddr4_dimm_params.c +++ b/drivers/ddr/fsl/ddr4_dimm_params.c @@ -135,7 +135,8 @@ unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num, if (spd->mem_type) { if (spd->mem_type != SPD_MEMTYPE_DDR4) { - printf("DIMM %u: is not a DDR4 SPD.\n", dimm_number); + printf("Ctrl %u DIMM %u: is not a DDR4 SPD.\n", + ctrl_num, dimm_number); return 1; } } else { diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c index d9fce7d..49e4688 100644 --- a/drivers/ddr/fsl/fsl_ddr_gen4.c +++ b/drivers/ddr/fsl/fsl_ddr_gen4.c @@ -1,5 +1,5 @@ /* - * Copyright 2014 Freescale Semiconductor, Inc. + * Copyright 2014-2015 Freescale Semiconductor, Inc. * * SPDX-License-Identifier: GPL-2.0+ */ @@ -11,6 +11,22 @@ #include <fsl_immap.h> #include <fsl_ddr.h> +#ifdef CONFIG_SYS_FSL_ERRATUM_A008511 +static void set_wait_for_bits_clear(void *ptr, u32 value, u32 bits) +{ + int timeout = 1000; + + ddr_out32(ptr, value); + + while (ddr_in32(ptr) & bits) { + udelay(100); + timeout--; + } + if (timeout <= 0) + puts("Error: A007865 wait for clear timeout.\n"); +} +#endif /* CONFIG_SYS_FSL_ERRATUM_A008511 */ + #if (CONFIG_CHIP_SELECTS_PER_CTRL > 4) #error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL #endif @@ -36,6 +52,16 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, defined(CONFIG_SYS_FSL_ERRATUM_A008514) u32 *eddrtqcr1; #endif +#ifdef CONFIG_SYS_FSL_ERRATUM_A008511 + u32 temp32, mr6; +#endif +#ifdef CONFIG_FSL_DDR_BIST + u32 mtcr, err_detect, err_sbe; + u32 cs0_bnds, cs1_bnds, cs2_bnds, cs3_bnds, cs0_config; +#endif +#ifdef CONFIG_FSL_DDR_BIST + char buffer[CONFIG_SYS_CBSIZE]; +#endif switch (ctrl_num) { case 0: @@ -214,6 +240,21 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, ddr_setbits32(ddr->debug[28], 0x9 << 20); #endif +#ifdef CONFIG_SYS_FSL_ERRATUM_A008511 + /* Part 1 of 2 */ + /* This erraum only applies to verion 5.2.0 */ + if (fsl_ddr_get_version(ctrl_num) == 0x50200) { + /* Disable DRAM VRef training */ + ddr_out32(&ddr->ddr_cdr2, + regs->ddr_cdr2 & ~DDR_CDR2_VREF_TRAIN_EN); + /* Disable deskew */ + ddr_out32(&ddr->debug[28], 0x400); + /* Disable D_INIT */ + ddr_out32(&ddr->sdram_cfg_2, + regs->ddr_sdram_cfg_2 & ~SDRAM_CFG2_D_INIT); + ddr_out32(&ddr->debug[25], 0x9000); + } +#endif /* * For RDIMMs, JEDEC spec requires clocks to be stable before reset is * deasserted. Clocks start when any chip select is enabled and clock @@ -261,6 +302,66 @@ step2: mb(); isb(); +#ifdef CONFIG_SYS_FSL_ERRATUM_A008511 + /* Part 2 of 2 */ + /* This erraum only applies to verion 5.2.0 */ + if (fsl_ddr_get_version(ctrl_num) == 0x50200) { + /* Wait for idle */ + timeout = 200; + while (!(ddr_in32(&ddr->debug[1]) & 0x2) && + (timeout > 0)) { + udelay(100); + timeout--; + } + if (timeout <= 0) { + printf("Controler %d timeout, debug_2 = %x\n", + ctrl_num, ddr_in32(&ddr->debug[1])); + } + /* Set VREF */ + for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { + if (!(regs->cs[i].config & SDRAM_CS_CONFIG_EN)) + continue; + + mr6 = (regs->ddr_sdram_mode_10 >> 16) | + MD_CNTL_MD_EN | + MD_CNTL_CS_SEL(i) | + MD_CNTL_MD_SEL(6) | + 0x00200000; + temp32 = mr6 | 0xc0; + set_wait_for_bits_clear(&ddr->sdram_md_cntl, + temp32, MD_CNTL_MD_EN); + udelay(1); + debug("MR6 = 0x%08x\n", temp32); + temp32 = mr6 | 0xf0; + set_wait_for_bits_clear(&ddr->sdram_md_cntl, + temp32, MD_CNTL_MD_EN); + udelay(1); + debug("MR6 = 0x%08x\n", temp32); + temp32 = mr6 | 0x70; + set_wait_for_bits_clear(&ddr->sdram_md_cntl, + temp32, MD_CNTL_MD_EN); + udelay(1); + debug("MR6 = 0x%08x\n", temp32); + } + ddr_out32(&ddr->sdram_md_cntl, 0); + ddr_out32(&ddr->debug[28], 0); /* Enable deskew */ + ddr_out32(&ddr->debug[1], 0x400); /* restart deskew */ + /* wait for idle */ + timeout = 200; + while (!(ddr_in32(&ddr->debug[1]) & 0x2) && + (timeout > 0)) { + udelay(100); + timeout--; + } + if (timeout <= 0) { + printf("Controler %d timeout, debug_2 = %x\n", + ctrl_num, ddr_in32(&ddr->debug[1])); + } + /* Restore D_INIT */ + ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2); + } +#endif /* CONFIG_SYS_FSL_ERRATUM_A008511 */ + total_gb_size_per_controller = 0; for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { if (!(regs->cs[i].config & 0x80000000)) @@ -309,4 +410,70 @@ step2: ddr_out32(&ddr->sdram_cfg_2, temp_sdram_cfg); } #endif + +#ifdef CONFIG_FSL_DDR_BIST +#define BIST_PATTERN1 0xFFFFFFFF +#define BIST_PATTERN2 0x0 +#define BIST_CR 0x80010000 +#define BIST_CR_EN 0x80000000 +#define BIST_CR_STAT 0x00000001 +#define CTLR_INTLV_MASK 0x20000000 + /* Perform build-in test on memory. Three-way interleaving is not yet + * supported by this code. */ + if (getenv_f("ddr_bist", buffer, CONFIG_SYS_CBSIZE) >= 0) { + puts("Running BIST test. This will take a while..."); + cs0_config = ddr_in32(&ddr->cs0_config); + if (cs0_config & CTLR_INTLV_MASK) { + cs0_bnds = ddr_in32(&cs0_bnds); + cs1_bnds = ddr_in32(&cs1_bnds); + cs2_bnds = ddr_in32(&cs2_bnds); + cs3_bnds = ddr_in32(&cs3_bnds); + /* set bnds to non-interleaving */ + ddr_out32(&cs0_bnds, (cs0_bnds & 0xfffefffe) >> 1); + ddr_out32(&cs1_bnds, (cs1_bnds & 0xfffefffe) >> 1); + ddr_out32(&cs2_bnds, (cs2_bnds & 0xfffefffe) >> 1); + ddr_out32(&cs3_bnds, (cs3_bnds & 0xfffefffe) >> 1); + } + ddr_out32(&ddr->mtp1, BIST_PATTERN1); + ddr_out32(&ddr->mtp2, BIST_PATTERN1); + ddr_out32(&ddr->mtp3, BIST_PATTERN2); + ddr_out32(&ddr->mtp4, BIST_PATTERN2); + ddr_out32(&ddr->mtp5, BIST_PATTERN1); + ddr_out32(&ddr->mtp6, BIST_PATTERN1); + ddr_out32(&ddr->mtp7, BIST_PATTERN2); + ddr_out32(&ddr->mtp8, BIST_PATTERN2); + ddr_out32(&ddr->mtp9, BIST_PATTERN1); + ddr_out32(&ddr->mtp10, BIST_PATTERN2); + mtcr = BIST_CR; + ddr_out32(&ddr->mtcr, mtcr); + timeout = 100; + while (timeout > 0 && (mtcr & BIST_CR_EN)) { + mdelay(1000); + timeout--; + mtcr = ddr_in32(&ddr->mtcr); + } + if (timeout <= 0) + puts("Timeout\n"); + else + puts("Done\n"); + err_detect = ddr_in32(&ddr->err_detect); + err_sbe = ddr_in32(&ddr->err_sbe); + if (mtcr & BIST_CR_STAT) { + printf("BIST test failed on controller %d.\n", + ctrl_num); + } + if (err_detect || (err_sbe & 0xffff)) { + printf("ECC error detected on controller %d.\n", + ctrl_num); + } + + if (cs0_config & CTLR_INTLV_MASK) { + /* restore bnds registers */ + ddr_out32(&cs0_bnds, cs0_bnds); + ddr_out32(&cs1_bnds, cs1_bnds); + ddr_out32(&cs2_bnds, cs2_bnds); + ddr_out32(&cs3_bnds, cs3_bnds); + } + } +#endif } diff --git a/drivers/ddr/fsl/interactive.c b/drivers/ddr/fsl/interactive.c index 32ba6d8..d23e6e5 100644 --- a/drivers/ddr/fsl/interactive.c +++ b/drivers/ddr/fsl/interactive.c @@ -205,6 +205,8 @@ static void lowest_common_dimm_parameters_edit(fsl_ddr_info_t *pinfo, #define DIMM_PARM(x) {#x, offsetof(dimm_params_t, x), \ sizeof((dimm_params_t *)0)->x, 0} +#define DIMM_PARM_HEX(x) {#x, offsetof(dimm_params_t, x), \ + sizeof((dimm_params_t *)0)->x, 1} static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo, unsigned int ctrl_num, @@ -220,6 +222,7 @@ static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo, DIMM_PARM(primary_sdram_width), DIMM_PARM(ec_sdram_width), DIMM_PARM(registered_dimm), + DIMM_PARM(mirrored_dimm), DIMM_PARM(device_width), DIMM_PARM(n_row_addr), @@ -274,7 +277,27 @@ static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo, DIMM_PARM(tdqsq_max_ps), DIMM_PARM(tqhs_ps), #endif - +#ifdef CONFIG_SYS_FSL_DDR4 + DIMM_PARM_HEX(dq_mapping[0]), + DIMM_PARM_HEX(dq_mapping[1]), + DIMM_PARM_HEX(dq_mapping[2]), + DIMM_PARM_HEX(dq_mapping[3]), + DIMM_PARM_HEX(dq_mapping[4]), + DIMM_PARM_HEX(dq_mapping[5]), + DIMM_PARM_HEX(dq_mapping[6]), + DIMM_PARM_HEX(dq_mapping[7]), + DIMM_PARM_HEX(dq_mapping[8]), + DIMM_PARM_HEX(dq_mapping[9]), + DIMM_PARM_HEX(dq_mapping[10]), + DIMM_PARM_HEX(dq_mapping[11]), + DIMM_PARM_HEX(dq_mapping[12]), + DIMM_PARM_HEX(dq_mapping[13]), + DIMM_PARM_HEX(dq_mapping[14]), + DIMM_PARM_HEX(dq_mapping[15]), + DIMM_PARM_HEX(dq_mapping[16]), + DIMM_PARM_HEX(dq_mapping[17]), + DIMM_PARM(dq_mapping_ors), +#endif DIMM_PARM(rank_density), DIMM_PARM(capacity), DIMM_PARM(base_address), @@ -296,6 +319,7 @@ static void print_dimm_parameters(const dimm_params_t *pdimm) DIMM_PARM(primary_sdram_width), DIMM_PARM(ec_sdram_width), DIMM_PARM(registered_dimm), + DIMM_PARM(mirrored_dimm), DIMM_PARM(device_width), DIMM_PARM(n_row_addr), @@ -314,6 +338,7 @@ static void print_dimm_parameters(const dimm_params_t *pdimm) DIMM_PARM(tckmax_ps), DIMM_PARM(caslat_x), + DIMM_PARM_HEX(caslat_x), DIMM_PARM(taa_ps), DIMM_PARM(caslat_x_minus_1), DIMM_PARM(caslat_x_minus_2), @@ -322,6 +347,9 @@ static void print_dimm_parameters(const dimm_params_t *pdimm) DIMM_PARM(trcd_ps), DIMM_PARM(trp_ps), DIMM_PARM(tras_ps), +#if defined(CONFIG_SYS_FSL_DDR4) || defined(CONFIG_SYS_FSL_DDR3) + DIMM_PARM(tfaw_ps), +#endif #ifdef CONFIG_SYS_FSL_DDR4 DIMM_PARM(trfc1_ps), DIMM_PARM(trfc2_ps), @@ -347,6 +375,27 @@ static void print_dimm_parameters(const dimm_params_t *pdimm) DIMM_PARM(tdqsq_max_ps), DIMM_PARM(tqhs_ps), #endif +#ifdef CONFIG_SYS_FSL_DDR4 + DIMM_PARM_HEX(dq_mapping[0]), + DIMM_PARM_HEX(dq_mapping[1]), + DIMM_PARM_HEX(dq_mapping[2]), + DIMM_PARM_HEX(dq_mapping[3]), + DIMM_PARM_HEX(dq_mapping[4]), + DIMM_PARM_HEX(dq_mapping[5]), + DIMM_PARM_HEX(dq_mapping[6]), + DIMM_PARM_HEX(dq_mapping[7]), + DIMM_PARM_HEX(dq_mapping[8]), + DIMM_PARM_HEX(dq_mapping[9]), + DIMM_PARM_HEX(dq_mapping[10]), + DIMM_PARM_HEX(dq_mapping[11]), + DIMM_PARM_HEX(dq_mapping[12]), + DIMM_PARM_HEX(dq_mapping[13]), + DIMM_PARM_HEX(dq_mapping[14]), + DIMM_PARM_HEX(dq_mapping[15]), + DIMM_PARM_HEX(dq_mapping[16]), + DIMM_PARM_HEX(dq_mapping[17]), + DIMM_PARM(dq_mapping_ors), +#endif }; static const unsigned int n_opts = ARRAY_SIZE(options); @@ -463,7 +512,7 @@ static void fsl_ddr_options_edit(fsl_ddr_info_t *pinfo, CTRL_OPTIONS_CS(3, odt_rd_cfg), CTRL_OPTIONS_CS(3, odt_wr_cfg), #endif -#if defined(CONFIG_SYS_FSL_DDR3) +#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4) CTRL_OPTIONS_CS(0, odt_rtt_norm), CTRL_OPTIONS_CS(0, odt_rtt_wr), #if (CONFIG_CHIP_SELECTS_PER_CTRL > 1) @@ -753,7 +802,7 @@ static void print_memctl_options(const memctl_options_t *popts) CTRL_OPTIONS_CS(3, odt_rd_cfg), CTRL_OPTIONS_CS(3, odt_wr_cfg), #endif -#if defined(CONFIG_SYS_FSL_DDR3) +#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4) CTRL_OPTIONS_CS(0, odt_rtt_norm), CTRL_OPTIONS_CS(0, odt_rtt_wr), #if (CONFIG_CHIP_SELECTS_PER_CTRL > 1) @@ -795,6 +844,7 @@ static void print_memctl_options(const memctl_options_t *popts) CTRL_OPTIONS(twot_en), CTRL_OPTIONS(threet_en), CTRL_OPTIONS(registered_dimm_en), + CTRL_OPTIONS(mirrored_dimm), CTRL_OPTIONS(ap_en), CTRL_OPTIONS(x4_en), CTRL_OPTIONS(bstopre), diff --git a/drivers/ddr/fsl/lc_common_dimm_params.c b/drivers/ddr/fsl/lc_common_dimm_params.c index b295344..b12eeb9 100644 --- a/drivers/ddr/fsl/lc_common_dimm_params.c +++ b/drivers/ddr/fsl/lc_common_dimm_params.c @@ -22,7 +22,7 @@ compute_cas_latency(const unsigned int ctrl_num, unsigned int common_caslat; unsigned int caslat_actual; unsigned int retry = 16; - unsigned int tmp; + unsigned int tmp = ~0; const unsigned int mclk_ps = get_memory_clk_period_ps(ctrl_num); #ifdef CONFIG_SYS_FSL_DDR3 const unsigned int taamax = 20000; @@ -31,8 +31,7 @@ compute_cas_latency(const unsigned int ctrl_num, #endif /* compute the common CAS latency supported between slots */ - tmp = dimm_params[0].caslat_x; - for (i = 1; i < number_of_dimms; i++) { + for (i = 0; i < number_of_dimms; i++) { if (dimm_params[i].n_ranks) tmp &= dimm_params[i].caslat_x; } diff --git a/drivers/ddr/fsl/main.c b/drivers/ddr/fsl/main.c index b72b242..fa22383 100644 --- a/drivers/ddr/fsl/main.c +++ b/drivers/ddr/fsl/main.c @@ -453,7 +453,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, retval = compute_dimm_parameters( i, spd, pdimm, j); #ifdef CONFIG_SYS_DDR_RAW_TIMING - if (!i && !j && retval) { + if (!j && retval) { printf("SPD error on controller %d! " "Trying fallback to raw timing " "calculation\n", i); diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c index 5beb11b..3b30fa2 100644 --- a/drivers/ddr/fsl/options.c +++ b/drivers/ddr/fsl/options.c @@ -728,7 +728,12 @@ unsigned int populate_memctl_options(int all_dimms_registered, /* Choose ddr controller address mirror mode */ #if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4) - popts->mirrored_dimm = pdimm[0].mirrored_dimm; + for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) { + if (pdimm[i].n_ranks) { + popts->mirrored_dimm = pdimm[i].mirrored_dimm; + break; + } + } #endif /* Global Timing Parameters. */ diff --git a/drivers/ddr/fsl/util.c b/drivers/ddr/fsl/util.c index 664081b..ce55aea 100644 --- a/drivers/ddr/fsl/util.c +++ b/drivers/ddr/fsl/util.c @@ -23,12 +23,34 @@ #define ULL_8FS 0xFFFFFFFFULL -u32 fsl_ddr_get_version(void) +u32 fsl_ddr_get_version(unsigned int ctrl_num) { struct ccsr_ddr __iomem *ddr; u32 ver_major_minor_errata; - ddr = (void *)_DDR_ADDR; + switch (ctrl_num) { + case 0: + ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; + break; +#if defined(CONFIG_SYS_FSL_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1) + case 1: + ddr = (void *)CONFIG_SYS_FSL_DDR2_ADDR; + break; +#endif +#if defined(CONFIG_SYS_FSL_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2) + case 2: + ddr = (void *)CONFIG_SYS_FSL_DDR3_ADDR; + break; +#endif +#if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3) + case 3: + ddr = (void *)CONFIG_SYS_FSL_DDR4_ADDR; + break; +#endif + default: + printf("%s unexpected ctrl_num = %u\n", __func__, ctrl_num); + return 0; + } ver_major_minor_errata = (ddr_in32(&ddr->ip_rev1) & 0xFFFF) << 8; ver_major_minor_errata |= (ddr_in32(&ddr->ip_rev2) & 0xFF00) >> 8; @@ -212,7 +234,7 @@ void print_ddr_info(unsigned int start_ctrl) /* Calculate CAS latency based on timing cfg values */ cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf); - if (fsl_ddr_get_version() <= 0x40400) + if (fsl_ddr_get_version(0) <= 0x40400) cas_lat += 1; else cas_lat += 2; diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c index fc5ee35..42782cb 100644 --- a/drivers/i2c/mxc_i2c.c +++ b/drivers/i2c/mxc_i2c.c @@ -114,6 +114,9 @@ static u16 i2c_clk_div[50][2] = { #ifndef CONFIG_SYS_MXC_I2C3_SPEED #define CONFIG_SYS_MXC_I2C3_SPEED 100000 #endif +#ifndef CONFIG_SYS_MXC_I2C4_SPEED +#define CONFIG_SYS_MXC_I2C4_SPEED 100000 +#endif #ifndef CONFIG_SYS_MXC_I2C1_SLAVE #define CONFIG_SYS_MXC_I2C1_SLAVE 0 @@ -124,6 +127,9 @@ static u16 i2c_clk_div[50][2] = { #ifndef CONFIG_SYS_MXC_I2C3_SLAVE #define CONFIG_SYS_MXC_I2C3_SLAVE 0 #endif +#ifndef CONFIG_SYS_MXC_I2C4_SLAVE +#define CONFIG_SYS_MXC_I2C4_SLAVE 0 +#endif /* @@ -543,12 +549,17 @@ U_BOOT_I2C_ADAP_COMPLETE(mxc1, mxc_i2c_init, mxc_i2c_probe, mxc_i2c_set_bus_speed, CONFIG_SYS_MXC_I2C2_SPEED, CONFIG_SYS_MXC_I2C2_SLAVE, 1) -#if defined(CONFIG_MX31) || defined(CONFIG_MX35) ||\ - defined(CONFIG_MX51) || defined(CONFIG_MX53) ||\ - defined(CONFIG_MX6) || defined(CONFIG_LS102XA) +#ifdef CONFIG_SYS_I2C_MXC_I2C3 U_BOOT_I2C_ADAP_COMPLETE(mxc2, mxc_i2c_init, mxc_i2c_probe, mxc_i2c_read, mxc_i2c_write, mxc_i2c_set_bus_speed, CONFIG_SYS_MXC_I2C3_SPEED, CONFIG_SYS_MXC_I2C3_SLAVE, 2) #endif +#ifdef CONFIG_SYS_I2C_MXC_I2C4 +U_BOOT_I2C_ADAP_COMPLETE(mxc3, mxc_i2c_init, mxc_i2c_probe, + mxc_i2c_read, mxc_i2c_write, + mxc_i2c_set_bus_speed, + CONFIG_SYS_MXC_I2C4_SPEED, + CONFIG_SYS_MXC_I2C4_SLAVE, 3) +#endif diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 842209a..25630c3 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpc.o obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o obj-$(CONFIG_CROS_EC_SANDBOX) += cros_ec_sandbox.o obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o +obj-$(CONFIG_FSL_DEBUG_SERVER) += fsl_debug_server.o obj-$(CONFIG_FSL_IIM) += fsl_iim.o obj-$(CONFIG_GPIO_LED) += gpio_led.o obj-$(CONFIG_I2C_EEPROM) += i2c_eeprom.o diff --git a/drivers/misc/fsl_debug_server.c b/drivers/misc/fsl_debug_server.c new file mode 100644 index 0000000..e080fe6 --- /dev/null +++ b/drivers/misc/fsl_debug_server.c @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <errno.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/arch-fsl-lsch3/immap_lsch3.h> + +#include <fsl_debug_server.h> + +DECLARE_GLOBAL_DATA_PTR; +static int debug_server_ver_info_maj, debug_server_ver_info_min; + +/** + * Copying Debug Server firmware to DDR + */ +static int debug_server_copy_image(const char *title, u64 image_addr, + u32 image_size, u64 debug_server_ram_addr) +{ + debug("%s copied to address %p\n", title, + (void *)debug_server_ram_addr); + memcpy((void *)debug_server_ram_addr, (void *)image_addr, image_size); + + return 0; +} + +/** + * Debug Server FIT image parser checks if the image is in FIT + * format, verifies integrity of the image and calculates + * raw image address and size values. + * + * Returns 0 if success and -1 if any of the above mentioned + * task fail. + **/ +int debug_server_parse_firmware_fit_image(const void **raw_image_addr, + size_t *raw_image_size) +{ + int format; + void *fit_hdr; + int node_offset; + const void *data; + size_t size; + const char *uname = "firmware"; + char *desc; + char *debug_server_ver_info; + char *debug_server_ver_info_major, *debug_server_ver_info_minor; + + /* Check if the image is in NOR flash */ +#ifdef CONFIG_SYS_DEBUG_SERVER_FW_IN_NOR + fit_hdr = (void *)CONFIG_SYS_DEBUG_SERVER_FW_ADDR; +#else +#error "CONFIG_SYS_DEBUG_SERVER_FW_IN_NOR not defined" +#endif + + /* Check if Image is in FIT format */ + format = genimg_get_format(fit_hdr); + if (format != IMAGE_FORMAT_FIT) { + printf("Error! Not a FIT image\n"); + goto out_error; + } + + if (!fit_check_format(fit_hdr)) { + printf("Error! Bad FIT image format\n"); + goto out_error; + } + + node_offset = fit_image_get_node(fit_hdr, uname); + if (node_offset < 0) { + printf("Error! Can not find %s subimage\n", uname); + goto out_error; + } + + /* Verify Debug Server firmware image */ + if (!fit_image_verify(fit_hdr, node_offset)) { + printf("Error! Bad Debug Server firmware hash"); + goto out_error; + } + + if (fit_get_desc(fit_hdr, node_offset, &desc) < 0) { + printf("Error! Failed to get Debug Server fw description"); + goto out_error; + } + + debug_server_ver_info = strstr(desc, "Version"); + debug_server_ver_info_major = strtok(debug_server_ver_info, "."); + debug_server_ver_info_minor = strtok(NULL, "."); + + debug_server_ver_info_maj = + simple_strtoul(debug_server_ver_info_major, NULL, 10); + debug_server_ver_info_min = + simple_strtoul(debug_server_ver_info_minor, NULL, 10); + + /* Debug server version checking */ + if ((debug_server_ver_info_maj < DEBUG_SERVER_VER_MAJOR) || + (debug_server_ver_info_min < DEBUG_SERVER_VER_MINOR)) { + printf("Debug server FW mismatches the min version required\n"); + printf("Expected:%d.%d, Got %d.%d\n", + DEBUG_SERVER_VER_MAJOR, DEBUG_SERVER_VER_MINOR, + debug_server_ver_info_maj, + debug_server_ver_info_min); + goto out_error; + } + + /* Get address and size of raw image */ + fit_image_get_data(fit_hdr, node_offset, &data, &size); + + *raw_image_addr = data; + *raw_image_size = size; + + return 0; + +out_error: + return -1; +} + +/** + * Return the actual size of the Debug Server private DRAM block. + * + * NOTE: For now this function always returns the minimum required size, + * However, in the future, the actual size may be obtained from an environment + * variable. + */ +unsigned long debug_server_get_dram_block_size(void) +{ + return CONFIG_SYS_DEBUG_SERVER_DRAM_BLOCK_MIN_SIZE; +} + +int debug_server_init(void) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + int error, timeout = CONFIG_SYS_DEBUG_SERVER_TIMEOUT; + int debug_server_boot_status; + u64 debug_server_ram_addr, debug_server_ram_size; + const void *raw_image_addr; + size_t raw_image_size = 0; + + debug("debug_server_init called\n"); + /* + * The Debug Server private DRAM block was already carved at the end of + * DRAM by board_init_f() using CONFIG_SYS_MEM_TOP_HIDE: + */ + debug_server_ram_size = debug_server_get_dram_block_size(); + if (gd->bd->bi_dram[1].start) + debug_server_ram_addr = + gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size; + else + debug_server_ram_addr = + gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size; + + error = debug_server_parse_firmware_fit_image(&raw_image_addr, + &raw_image_size); + if (error != 0) + goto out; + + debug("debug server (ram addr = 0x%llx, ram size = 0x%llx)\n", + debug_server_ram_addr, debug_server_ram_size); + /* + * Load the Debug Server FW at the beginning of the Debug Server + * private DRAM block: + */ + debug_server_copy_image("Debug Server Firmware", + (u64)raw_image_addr, raw_image_size, + debug_server_ram_addr); + + /* flush dcache */ + flush_dcache_range((unsigned long)debug_server_ram_addr, + (unsigned long)debug_server_ram_addr + + (unsigned long)debug_server_ram_size); + + /* + * Tell SP that the Debug Server FW is about to be launched. Before that + * populate the following: + * 1. Write the size allocated to SP Memory region into Bits {31:16} of + * SCRATCHRW5. + * 2. Write the start address of the SP memory regions into + * SCRATCHRW5 (Bits {15:0}, contain most significant bits, Bits + * {47:32} of the SP Memory Region physical start address + * (SoC address)) and SCRATCHRW6 (Bits {31:0}). + * 3. To know the Debug Server FW boot status, set bit 0 of SCRATCHRW11 + * to 1. The Debug Server sets this to 0 to indicate a + * successul boot. + * 4. Wakeup SP by writing 0x1F to VSG GIC reg VIGR2. + */ + + /* 512 MB */ + out_le32(&gur->scratchrw[5 - 1], + (u32)((u64)debug_server_ram_addr >> 32) | (0x000D << 16)); + out_le32(&gur->scratchrw[6 - 1], + ((u32)debug_server_ram_addr) & 0xFFFFFFFF); + + out_le32(&gur->scratchrw[11 - 1], DEBUG_SERVER_INIT_STATUS); + /* Allow the changes to reflect in GUR block */ + mb(); + + /* + * Program VGIC to raise an interrupt to SP + */ + out_le32(CONFIG_SYS_FSL_SP_VSG_GIC_VIGR2, 0x1F); + /* Allow the changes to reflect in VIGR2 */ + mb(); + + dmb(); + debug("Polling for Debug server to launch ...\n"); + + while (1) { + debug_server_boot_status = in_le32(&gur->scratchrw[11 - 1]); + if (!(debug_server_boot_status & DEBUG_SERVER_INIT_STATUS_MASK)) + break; + + udelay(1); /* throttle polling */ + if (timeout-- <= 0) + break; + } + + if (timeout <= 0) { + printf("Debug Server FW timed out (boot status: 0x%x)\n", + debug_server_boot_status); + error = -ETIMEDOUT; + goto out; + } + + if (debug_server_boot_status & DEBUG_SERVER_INIT_STATUS_MASK) { + printf("Debug server FW error'ed out (boot status: 0x%x)\n", + debug_server_boot_status); + error = -ENODEV; + goto out; + } + + printf("Debug server booted\n"); + printf("Detected firmware %d.%d, (boot status: 0x0%x)\n", + debug_server_ver_info_maj, debug_server_ver_info_min, + debug_server_boot_status); + +out: + if (error != 0) + debug_server_boot_status = -error; + else + debug_server_boot_status = 0; + + return debug_server_boot_status; +} + diff --git a/drivers/misc/fsl_ifc.c b/drivers/misc/fsl_ifc.c index 3902e9f..a33efdb 100644 --- a/drivers/misc/fsl_ifc.c +++ b/drivers/misc/fsl_ifc.c @@ -168,4 +168,25 @@ void init_final_memctl_regs(void) #ifdef CONFIG_SYS_CSPR0_FINAL set_ifc_cspr(IFC_CS0, CONFIG_SYS_CSPR0_FINAL); #endif +#ifdef CONFIG_SYS_AMASK0_FINAL + set_ifc_amask(IFC_CS0, CONFIG_SYS_AMASK0); +#endif +#ifdef CONFIG_SYS_CSPR1_FINAL + set_ifc_cspr(IFC_CS1, CONFIG_SYS_CSPR1_FINAL); +#endif +#ifdef CONFIG_SYS_AMASK1_FINAL + set_ifc_amask(IFC_CS1, CONFIG_SYS_AMASK1_FINAL); +#endif +#ifdef CONFIG_SYS_CSPR2_FINAL + set_ifc_cspr(IFC_CS2, CONFIG_SYS_CSPR2_FINAL); +#endif +#ifdef CONFIG_SYS_AMASK2_FINAL + set_ifc_amask(IFC_CS2, CONFIG_SYS_AMASK2); +#endif +#ifdef CONFIG_SYS_CSPR3_FINAL + set_ifc_cspr(IFC_CS3, CONFIG_SYS_CSPR3_FINAL); +#endif +#ifdef CONFIG_SYS_AMASK3_FINAL + set_ifc_amask(IFC_CS3, CONFIG_SYS_AMASK3); +#endif } diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index db4d251..10ec216 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -105,7 +105,8 @@ static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data) else if (cmd->resp_type & MMC_RSP_PRESENT) xfertyp |= XFERTYP_RSPTYP_48; -#if defined(CONFIG_MX53) || defined(CONFIG_PPC_T4240) || defined(CONFIG_LS102XA) +#if defined(CONFIG_MX53) || defined(CONFIG_PPC_T4240) || \ + defined(CONFIG_LS102XA) || defined(CONFIG_LS2085A) if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) xfertyp |= XFERTYP_CMDTYP_ABORT; #endif @@ -183,7 +184,9 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) int timeout; struct fsl_esdhc_cfg *cfg = mmc->priv; struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; - +#ifdef CONFIG_LS2085A + dma_addr_t addr; +#endif uint wml_value; wml_value = data->blocksize/4; @@ -194,8 +197,16 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) esdhc_clrsetbits32(®s->wml, WML_RD_WML_MASK, wml_value); #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO +#ifdef CONFIG_LS2085A + addr = virt_to_phys((void *)(data->dest)); + if (upper_32_bits(addr)) + printf("Error found for upper 32 bits\n"); + else + esdhc_write32(®s->dsaddr, lower_32_bits(addr)); +#else esdhc_write32(®s->dsaddr, (u32)data->dest); #endif +#endif } else { #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO flush_dcache_range((ulong)data->src, @@ -212,8 +223,16 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) esdhc_clrsetbits32(®s->wml, WML_WR_WML_MASK, wml_value << 16); #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO +#ifdef CONFIG_LS2085A + addr = virt_to_phys((void *)(data->src)); + if (upper_32_bits(addr)) + printf("Error found for upper 32 bits\n"); + else + esdhc_write32(®s->dsaddr, lower_32_bits(addr)); +#else esdhc_write32(®s->dsaddr, (u32)data->src); #endif +#endif } esdhc_write32(®s->blkattr, data->blocks << 16 | data->blocksize); @@ -259,10 +278,23 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) static void check_and_invalidate_dcache_range (struct mmc_cmd *cmd, struct mmc_data *data) { +#ifdef CONFIG_LS2085A + unsigned start = 0; +#else unsigned start = (unsigned)data->dest ; +#endif unsigned size = roundup(ARCH_DMA_MINALIGN, data->blocks*data->blocksize); unsigned end = start+size ; +#ifdef CONFIG_LS2085A + dma_addr_t addr; + + addr = virt_to_phys((void *)(data->dest)); + if (upper_32_bits(addr)) + printf("Error found for upper 32 bits\n"); + else + start = lower_32_bits(addr); +#endif invalidate_dcache_range(start, end); } #endif diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index 7903eeb..79fa88b 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -46,7 +46,7 @@ struct fsl_ifc_ctrl { struct fsl_ifc_mtd *chips[MAX_BANKS]; /* device info */ - struct fsl_ifc *regs; + struct fsl_ifc regs; uint8_t __iomem *addr; /* Address of assigned IFC buffer */ unsigned int cs_nand; /* On which chipsel NAND is connected */ unsigned int page; /* Last page written to / read from */ @@ -225,7 +225,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) struct nand_chip *chip = mtd->priv; struct fsl_ifc_mtd *priv = chip->priv; struct fsl_ifc_ctrl *ctrl = priv->ctrl; - struct fsl_ifc *ifc = ctrl->regs; + struct fsl_ifc_runtime *ifc = ctrl->regs.rregs; int buf_num; ctrl->page = page_addr; @@ -289,10 +289,10 @@ static int fsl_ifc_run_command(struct mtd_info *mtd) struct nand_chip *chip = mtd->priv; struct fsl_ifc_mtd *priv = chip->priv; struct fsl_ifc_ctrl *ctrl = priv->ctrl; - struct fsl_ifc *ifc = ctrl->regs; + struct fsl_ifc_runtime *ifc = ctrl->regs.rregs; u32 timeo = (CONFIG_SYS_HZ * 10) / 1000; u32 time_start; - u32 eccstat[4] = {0}; + u32 eccstat[8] = {0}; int i; /* set the chip select for NAND Transaction */ @@ -325,8 +325,15 @@ static int fsl_ifc_run_command(struct mtd_info *mtd) int sector = bufnum * chip->ecc.steps; int sector_end = sector + chip->ecc.steps - 1; - for (i = sector / 4; i <= sector_end / 4; i++) + for (i = sector / 4; i <= sector_end / 4; i++) { + if (i >= ARRAY_SIZE(eccstat)) { + printf("%s: eccstat too small for %d\n", + __func__, i); + return -EIO; + } + eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]); + } for (i = sector; i <= sector_end; i++) { errors = check_read_ecc(mtd, ctrl, eccstat, i); @@ -362,7 +369,7 @@ static void fsl_ifc_do_read(struct nand_chip *chip, { struct fsl_ifc_mtd *priv = chip->priv; struct fsl_ifc_ctrl *ctrl = priv->ctrl; - struct fsl_ifc *ifc = ctrl->regs; + struct fsl_ifc_runtime *ifc = ctrl->regs.rregs; /* Program FIR/IFC_NAND_FCR0 for Small/Large page */ if (mtd->writesize > 512) { @@ -400,7 +407,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, struct nand_chip *chip = mtd->priv; struct fsl_ifc_mtd *priv = chip->priv; struct fsl_ifc_ctrl *ctrl = priv->ctrl; - struct fsl_ifc *ifc = ctrl->regs; + struct fsl_ifc_runtime *ifc = ctrl->regs.rregs; /* clear the read buffer */ ctrl->read_bytes = 0; @@ -690,7 +697,7 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) { struct fsl_ifc_mtd *priv = chip->priv; struct fsl_ifc_ctrl *ctrl = priv->ctrl; - struct fsl_ifc *ifc = ctrl->regs; + struct fsl_ifc_runtime *ifc = ctrl->regs.rregs; u32 nand_fsr; if (ctrl->status != IFC_NAND_EVTER_STAT_OPC) @@ -747,24 +754,33 @@ static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip, static void fsl_ifc_ctrl_init(void) { + uint32_t ver = 0; ifc_ctrl = kzalloc(sizeof(*ifc_ctrl), GFP_KERNEL); if (!ifc_ctrl) return; - ifc_ctrl->regs = IFC_BASE_ADDR; + ifc_ctrl->regs.gregs = IFC_FCM_BASE_ADDR; + + ver = ifc_in32(&ifc_ctrl->regs.gregs->ifc_rev); + if (ver >= FSL_IFC_V2_0_0) + ifc_ctrl->regs.rregs = + (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_64KOFFSET; + else + ifc_ctrl->regs.rregs = + (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_4KOFFSET; /* clear event registers */ - ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_stat, ~0U); - ifc_out32(&ifc_ctrl->regs->ifc_nand.pgrdcmpl_evt_stat, ~0U); + ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_stat, ~0U); + ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.pgrdcmpl_evt_stat, ~0U); /* Enable error and event for any detected errors */ - ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_en, + ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.nand_evter_en, IFC_NAND_EVTER_EN_OPC_EN | IFC_NAND_EVTER_EN_PGRDCMPL_EN | IFC_NAND_EVTER_EN_FTOER_EN | IFC_NAND_EVTER_EN_WPER_EN); - ifc_out32(&ifc_ctrl->regs->ifc_nand.ncfgr, 0x0); + ifc_out32(&ifc_ctrl->regs.rregs->ifc_nand.ncfgr, 0x0); } static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip) @@ -773,7 +789,7 @@ static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip) static int fsl_ifc_sram_init(uint32_t ver) { - struct fsl_ifc *ifc = ifc_ctrl->regs; + struct fsl_ifc_runtime *ifc = ifc_ctrl->regs.rregs; uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0; uint32_t ncfgr = 0; u32 timeo = (CONFIG_SYS_HZ * 10) / 1000; @@ -799,13 +815,13 @@ static int fsl_ifc_sram_init(uint32_t ver) cs = ifc_ctrl->cs_nand >> IFC_NAND_CSEL_SHIFT; /* Save CSOR and CSOR_ext */ - csor = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor); - csor_ext = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor_ext); + csor = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor); + csor_ext = ifc_in32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext); /* chage PageSize 8K and SpareSize 1K*/ csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000; - ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor_8k); - ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, 0x0000400); + ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor_8k); + ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, 0x0000400); /* READID */ ifc_out32(&ifc->ifc_nand.nand_fir0, @@ -845,8 +861,8 @@ static int fsl_ifc_sram_init(uint32_t ver) ifc_out32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status); /* Restore CSOR and CSOR_ext */ - ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor); - ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, csor_ext); + ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor, csor); + ifc_out32(&ifc_ctrl->regs.gregs->csor_cs[cs].csor_ext, csor_ext); return 0; } @@ -857,6 +873,7 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr) struct nand_chip *nand; struct fsl_ifc_mtd *priv; struct nand_ecclayout *layout; + struct fsl_ifc_fcm *gregs = NULL; uint32_t cspr = 0, csor = 0, ver = 0; int ret = 0; @@ -872,14 +889,15 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr) priv->ctrl = ifc_ctrl; priv->vbase = addr; + gregs = ifc_ctrl->regs.gregs; /* Find which chip select it is connected to. */ for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) { phys_addr_t phys_addr = virt_to_phys(addr); - cspr = ifc_in32(&ifc_ctrl->regs->cspr_cs[priv->bank].cspr); - csor = ifc_in32(&ifc_ctrl->regs->csor_cs[priv->bank].csor); + cspr = ifc_in32(&gregs->cspr_cs[priv->bank].cspr); + csor = ifc_in32(&gregs->csor_cs[priv->bank].csor); if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND && (cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr)) { @@ -998,7 +1016,7 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr) nand->ecc.mode = NAND_ECC_SOFT; } - ver = ifc_in32(&ifc_ctrl->regs->ifc_rev); + ver = ifc_in32(&gregs->ifc_rev); if (ver >= FSL_IFC_V1_1_0) ret = fsl_ifc_sram_init(ver); if (ret) diff --git a/drivers/mtd/nand/fsl_ifc_spl.c b/drivers/mtd/nand/fsl_ifc_spl.c index fb827c5..fccbfb5 100644 --- a/drivers/mtd/nand/fsl_ifc_spl.c +++ b/drivers/mtd/nand/fsl_ifc_spl.c @@ -48,11 +48,25 @@ static inline int check_read_ecc(uchar *buf, u32 *eccstat, return 0; } +static inline struct fsl_ifc_runtime *runtime_regs_address(void) +{ + struct fsl_ifc regs = {(void *)CONFIG_SYS_IFC_ADDR, NULL}; + int ver = 0; + + ver = ifc_in32(®s.gregs->ifc_rev); + if (ver >= FSL_IFC_V2_0_0) + regs.rregs = (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_64KOFFSET; + else + regs.rregs = (void *)CONFIG_SYS_IFC_ADDR + IFC_RREGS_4KOFFSET; + + return regs.rregs; +} + static inline void nand_wait(uchar *buf, int bufnum, int page_size) { - struct fsl_ifc *ifc = IFC_BASE_ADDR; + struct fsl_ifc_runtime *ifc = runtime_regs_address(); u32 status; - u32 eccstat[4]; + u32 eccstat[8]; int bufperpage = page_size / 512; int bufnum_end, i; @@ -90,7 +104,8 @@ static inline int bad_block(uchar *marker, int port_size) int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst) { - struct fsl_ifc *ifc = IFC_BASE_ADDR; + struct fsl_ifc_fcm *gregs = (void *)CONFIG_SYS_IFC_ADDR; + struct fsl_ifc_runtime *ifc = NULL; uchar *buf = (uchar *)CONFIG_SYS_NAND_BASE; int page_size; int port_size; @@ -107,6 +122,8 @@ int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst) int pg_no; uchar *dst = vdst; + ifc = runtime_regs_address(); + /* Get NAND Flash configuration */ csor = CONFIG_SYS_NAND_CSOR; cspr = CONFIG_SYS_NAND_CSPR; @@ -130,7 +147,7 @@ int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst) bad_marker = 5; } - ver = ifc_in32(&ifc->ifc_rev); + ver = ifc_in32(&gregs->ifc_rev); if (ver >= FSL_IFC_V2_0_0) bufnum_mask = (bufnum_mask * 2) + 1; diff --git a/drivers/net/Makefile b/drivers/net/Makefile index f24443d..150470c 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -69,4 +69,6 @@ obj-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o xilinx_ll_temac_mdio.o \ xilinx_ll_temac_fifo.o xilinx_ll_temac_sdma.o obj-$(CONFIG_ZYNQ_GEM) += zynq_gem.o obj-$(CONFIG_FSL_MC_ENET) += fsl-mc/ +obj-$(CONFIG_FSL_MC_ENET) += ldpaa_eth/ +obj-$(CONFIG_FSL_MEMAC) += fm/memac_phy.o obj-$(CONFIG_VSC9953) += vsc9953.o diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 2d66690..96e6bb0 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -2174,7 +2174,7 @@ e1000_copper_link_preconfig(struct e1000_hw *hw) DEBUGOUT("Error, did not detect valid phy.\n"); return ret_val; } - DEBUGOUT("Phy ID = %x \n", hw->phy_id); + DEBUGOUT("Phy ID = %x\n", hw->phy_id); /* Set PHY to class A mode (if necessary) */ ret_val = e1000_set_phy_mode(hw); @@ -3485,11 +3485,11 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw) * some "sticky" (latched) bits. */ if (e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error \n"); + DEBUGOUT("PHY Read Error\n"); return -E1000_ERR_PHY; } if (e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error \n"); + DEBUGOUT("PHY Read Error\n"); return -E1000_ERR_PHY; } @@ -5152,7 +5152,7 @@ e1000_poll(struct eth_device *nic) if (!(le32_to_cpu(rd->status)) & E1000_RXD_STAT_DD) return 0; - /*DEBUGOUT("recv: packet len=%d \n", rd->length); */ + /* DEBUGOUT("recv: packet len=%d\n", rd->length); */ /* Packet received, make sure the data are re-loaded from RAM. */ len = le32_to_cpu(rd->length); invalidate_dcache_range((unsigned long)packet, diff --git a/drivers/net/fm/eth.c b/drivers/net/fm/eth.c index 55e76a7..d7a37f3 100644 --- a/drivers/net/fm/eth.c +++ b/drivers/net/fm/eth.c @@ -15,7 +15,7 @@ #include <phy.h> #include <asm/fsl_dtsec.h> #include <asm/fsl_tgec.h> -#include <asm/fsl_memac.h> +#include <fsl_memac.h> #include "fm.h" diff --git a/drivers/net/fm/memac.c b/drivers/net/fm/memac.c index 60e898c..81a64bf 100644 --- a/drivers/net/fm/memac.c +++ b/drivers/net/fm/memac.c @@ -12,7 +12,7 @@ #include <phy.h> #include <asm/types.h> #include <asm/io.h> -#include <asm/fsl_memac.h> +#include <fsl_memac.h> #include "fm.h" diff --git a/drivers/net/fm/memac_phy.c b/drivers/net/fm/memac_phy.c index a155d89..4ab78e6 100644 --- a/drivers/net/fm/memac_phy.c +++ b/drivers/net/fm/memac_phy.c @@ -10,9 +10,28 @@ #include <miiphy.h> #include <phy.h> #include <asm/io.h> -#include <asm/fsl_memac.h> +#include <fsl_memac.h> #include <fm_eth.h> +#ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN +#define memac_out_32(a, v) out_le32(a, v) +#define memac_clrbits_32(a, v) clrbits_le32(a, v) +#define memac_setbits_32(a, v) setbits_le32(a, v) +#else +#define memac_out_32(a, v) out_be32(a, v) +#define memac_clrbits_32(a, v) clrbits_be32(a, v) +#define memac_setbits_32(a, v) setbits_be32(a, v) +#endif + +static u32 memac_in_32(u32 *reg) +{ +#ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN + return in_le32(reg); +#else + return in_be32(reg); +#endif +} + /* * Write value to the PHY for this device to the register at regnum, waiting * until the write is done before it returns. All PHY configuration has to be @@ -28,31 +47,31 @@ int memac_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr, if (dev_addr == MDIO_DEVAD_NONE) { c45 = 0; /* clause 22 */ dev_addr = regnum & 0x1f; - clrbits_be32(®s->mdio_stat, MDIO_STAT_ENC); + memac_clrbits_32(®s->mdio_stat, MDIO_STAT_ENC); } else - setbits_be32(®s->mdio_stat, MDIO_STAT_ENC); + memac_setbits_32(®s->mdio_stat, MDIO_STAT_ENC); /* Wait till the bus is free */ - while ((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY) + while ((memac_in_32(®s->mdio_stat)) & MDIO_STAT_BSY) ; /* Set the port and dev addr */ mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr); - out_be32(®s->mdio_ctl, mdio_ctl); + memac_out_32(®s->mdio_ctl, mdio_ctl); /* Set the register address */ if (c45) - out_be32(®s->mdio_addr, regnum & 0xffff); + memac_out_32(®s->mdio_addr, regnum & 0xffff); /* Wait till the bus is free */ - while ((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY) + while ((memac_in_32(®s->mdio_stat)) & MDIO_STAT_BSY) ; /* Write the value to the register */ - out_be32(®s->mdio_data, MDIO_DATA(value)); + memac_out_32(®s->mdio_data, MDIO_DATA(value)); /* Wait till the MDIO write is complete */ - while ((in_be32(®s->mdio_data)) & MDIO_DATA_BSY) + while ((memac_in_32(®s->mdio_data)) & MDIO_DATA_BSY) ; return 0; @@ -75,39 +94,39 @@ int memac_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr, return 0xffff; c45 = 0; /* clause 22 */ dev_addr = regnum & 0x1f; - clrbits_be32(®s->mdio_stat, MDIO_STAT_ENC); + memac_clrbits_32(®s->mdio_stat, MDIO_STAT_ENC); } else - setbits_be32(®s->mdio_stat, MDIO_STAT_ENC); + memac_setbits_32(®s->mdio_stat, MDIO_STAT_ENC); /* Wait till the bus is free */ - while ((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY) + while ((memac_in_32(®s->mdio_stat)) & MDIO_STAT_BSY) ; /* Set the Port and Device Addrs */ mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr); - out_be32(®s->mdio_ctl, mdio_ctl); + memac_out_32(®s->mdio_ctl, mdio_ctl); /* Set the register address */ if (c45) - out_be32(®s->mdio_addr, regnum & 0xffff); + memac_out_32(®s->mdio_addr, regnum & 0xffff); /* Wait till the bus is free */ - while ((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY) + while ((memac_in_32(®s->mdio_stat)) & MDIO_STAT_BSY) ; /* Initiate the read */ mdio_ctl |= MDIO_CTL_READ; - out_be32(®s->mdio_ctl, mdio_ctl); + memac_out_32(®s->mdio_ctl, mdio_ctl); /* Wait till the MDIO write is complete */ - while ((in_be32(®s->mdio_data)) & MDIO_DATA_BSY) + while ((memac_in_32(®s->mdio_data)) & MDIO_DATA_BSY) ; /* Return all Fs if nothing was there */ - if (in_be32(®s->mdio_stat) & MDIO_STAT_RD_ER) + if (memac_in_32(®s->mdio_stat) & MDIO_STAT_RD_ER) return 0xffff; - return in_be32(®s->mdio_data) & 0xffff; + return memac_in_32(®s->mdio_data) & 0xffff; } int memac_mdio_reset(struct mii_dev *bus) @@ -143,8 +162,9 @@ int fm_memac_mdio_init(bd_t *bis, struct memac_mdio_info *info) * like T2080QDS, this bit default is '0', which leads to MDIO failure * on XAUI PHY, so set this bit definitely. */ - setbits_be32(&((struct memac_mdio_controller *)info->regs)->mdio_stat, - MDIO_STAT_CLKDIV(258) | MDIO_STAT_NEG); + memac_setbits_32( + &((struct memac_mdio_controller *)info->regs)->mdio_stat, + MDIO_STAT_CLKDIV(258) | MDIO_STAT_NEG); return mdio_register(bus); } diff --git a/drivers/net/fsl-mc/Makefile b/drivers/net/fsl-mc/Makefile index 206ac6b..7563a5f 100644 --- a/drivers/net/fsl-mc/Makefile +++ b/drivers/net/fsl-mc/Makefile @@ -7,4 +7,8 @@ # Layerscape MC driver obj-y += mc.o \ mc_sys.o \ - dpmng.o + dpmng.o \ + dprc.o \ + dpbp.o \ + dpni.o +obj-y += dpio/ diff --git a/drivers/net/fsl-mc/dpbp.c b/drivers/net/fsl-mc/dpbp.c new file mode 100644 index 0000000..3853e58 --- /dev/null +++ b/drivers/net/fsl-mc/dpbp.c @@ -0,0 +1,102 @@ +/* + * Freescale Layerscape MC I/O wrapper + * + * Copyright (C) 2013-2015 Freescale Semiconductor, Inc. + * Author: German Rivera <German.Rivera@freescale.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <fsl-mc/fsl_mc_sys.h> +#include <fsl-mc/fsl_mc_cmd.h> +#include <fsl-mc/fsl_dpbp.h> + +int dpbp_open(struct fsl_mc_io *mc_io, int dpbp_id, uint16_t *token) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN, + MC_CMD_PRI_LOW, 0); + DPBP_CMD_OPEN(cmd, dpbp_id); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + *token = MC_CMD_HDR_READ_TOKEN(cmd.header); + + return err; +} + +int dpbp_close(struct fsl_mc_io *mc_io, uint16_t token) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, MC_CMD_PRI_HIGH, + token); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpbp_enable(struct fsl_mc_io *mc_io, uint16_t token) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, MC_CMD_PRI_LOW, + token); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpbp_disable(struct fsl_mc_io *mc_io, uint16_t token) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE, + MC_CMD_PRI_LOW, token); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpbp_reset(struct fsl_mc_io *mc_io, uint16_t token) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET, + MC_CMD_PRI_LOW, token); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpbp_get_attributes(struct fsl_mc_io *mc_io, + uint16_t token, + struct dpbp_attr *attr) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR, + MC_CMD_PRI_LOW, token); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPBP_RSP_GET_ATTRIBUTES(cmd, attr); + + return 0; +} diff --git a/drivers/net/fsl-mc/dpio/Makefile b/drivers/net/fsl-mc/dpio/Makefile new file mode 100644 index 0000000..1ccefc0 --- /dev/null +++ b/drivers/net/fsl-mc/dpio/Makefile @@ -0,0 +1,9 @@ +# +# Copyright 2014 Freescale Semiconductor, Inc. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +# Layerscape MC DPIO driver +obj-y += dpio.o \ + qbman_portal.o diff --git a/drivers/net/fsl-mc/dpio/dpio.c b/drivers/net/fsl-mc/dpio/dpio.c new file mode 100644 index 0000000..b07eff7 --- /dev/null +++ b/drivers/net/fsl-mc/dpio/dpio.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2013-2015 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <fsl-mc/fsl_mc_sys.h> +#include <fsl-mc/fsl_mc_cmd.h> +#include <fsl-mc/fsl_dpio.h> + +int dpio_open(struct fsl_mc_io *mc_io, int dpio_id, uint16_t *token) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPIO_CMDID_OPEN, + MC_CMD_PRI_LOW, 0); + DPIO_CMD_OPEN(cmd, dpio_id); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + *token = MC_CMD_HDR_READ_TOKEN(cmd.header); + + return 0; +} + +int dpio_close(struct fsl_mc_io *mc_io, uint16_t token) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPIO_CMDID_CLOSE, + MC_CMD_PRI_HIGH, token); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpio_enable(struct fsl_mc_io *mc_io, uint16_t token) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPIO_CMDID_ENABLE, + MC_CMD_PRI_LOW, token); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpio_disable(struct fsl_mc_io *mc_io, uint16_t token) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPIO_CMDID_DISABLE, + MC_CMD_PRI_LOW, + token); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpio_reset(struct fsl_mc_io *mc_io, uint16_t token) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPIO_CMDID_RESET, + MC_CMD_PRI_LOW, token); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpio_get_attributes(struct fsl_mc_io *mc_io, + uint16_t token, + struct dpio_attr *attr) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_ATTR, + MC_CMD_PRI_LOW, + token); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPIO_RSP_GET_ATTR(cmd, attr); + + return 0; +} diff --git a/drivers/net/fsl-mc/dpio/qbman_portal.c b/drivers/net/fsl-mc/dpio/qbman_portal.c new file mode 100644 index 0000000..dd2a7de --- /dev/null +++ b/drivers/net/fsl-mc/dpio/qbman_portal.c @@ -0,0 +1,593 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "qbman_portal.h" + +/* QBMan portal management command codes */ +#define QBMAN_MC_ACQUIRE 0x30 +#define QBMAN_WQCHAN_CONFIGURE 0x46 + +/* CINH register offsets */ +#define QBMAN_CINH_SWP_EQAR 0x8c0 +#define QBMAN_CINH_SWP_DCAP 0xac0 +#define QBMAN_CINH_SWP_SDQCR 0xb00 +#define QBMAN_CINH_SWP_RAR 0xcc0 + +/* CENA register offsets */ +#define QBMAN_CENA_SWP_EQCR(n) (0x000 + ((uint32_t)(n) << 6)) +#define QBMAN_CENA_SWP_DQRR(n) (0x200 + ((uint32_t)(n) << 6)) +#define QBMAN_CENA_SWP_RCR(n) (0x400 + ((uint32_t)(n) << 6)) +#define QBMAN_CENA_SWP_CR 0x600 +#define QBMAN_CENA_SWP_RR(vb) (0x700 + ((uint32_t)(vb) >> 1)) +#define QBMAN_CENA_SWP_VDQCR 0x780 + +/* Reverse mapping of QBMAN_CENA_SWP_DQRR() */ +#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)p & 0xff) >> 6) + +/*******************************/ +/* Pre-defined attribute codes */ +/*******************************/ + +struct qb_attr_code code_generic_verb = QB_CODE(0, 0, 7); +struct qb_attr_code code_generic_rslt = QB_CODE(0, 8, 8); + +/*************************/ +/* SDQCR attribute codes */ +/*************************/ + +/* we put these here because at least some of them are required by + * qbman_swp_init() */ +struct qb_attr_code code_sdqcr_dct = QB_CODE(0, 24, 2); +struct qb_attr_code code_sdqcr_fc = QB_CODE(0, 29, 1); +struct qb_attr_code code_sdqcr_tok = QB_CODE(0, 16, 8); +#define CODE_SDQCR_DQSRC(n) QB_CODE(0, n, 1) +enum qbman_sdqcr_dct { + qbman_sdqcr_dct_null = 0, + qbman_sdqcr_dct_prio_ics, + qbman_sdqcr_dct_active_ics, + qbman_sdqcr_dct_active +}; +enum qbman_sdqcr_fc { + qbman_sdqcr_fc_one = 0, + qbman_sdqcr_fc_up_to_3 = 1 +}; + +/*********************************/ +/* Portal constructor/destructor */ +/*********************************/ + +/* Software portals should always be in the power-on state when we initialise, + * due to the CCSR-based portal reset functionality that MC has. */ +struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) +{ + int ret; + struct qbman_swp *p = kmalloc(sizeof(*p), GFP_KERNEL); + + if (!p) + return NULL; + p->desc = d; +#ifdef QBMAN_CHECKING + p->mc.check = swp_mc_can_start; +#endif + p->mc.valid_bit = QB_VALID_BIT; + p->sdq = 0; + qb_attr_code_encode(&code_sdqcr_dct, &p->sdq, qbman_sdqcr_dct_prio_ics); + qb_attr_code_encode(&code_sdqcr_fc, &p->sdq, qbman_sdqcr_fc_up_to_3); + qb_attr_code_encode(&code_sdqcr_tok, &p->sdq, 0xbb); + p->vdq.busy = 0; /* TODO: convert to atomic_t */ + p->vdq.valid_bit = QB_VALID_BIT; + p->dqrr.next_idx = 0; + p->dqrr.valid_bit = QB_VALID_BIT; + ret = qbman_swp_sys_init(&p->sys, d); + if (ret) { + free(p); + printf("qbman_swp_sys_init() failed %d\n", ret); + return NULL; + } + qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_SDQCR, p->sdq); + return p; +} + +/***********************/ +/* Management commands */ +/***********************/ + +/* + * Internal code common to all types of management commands. + */ + +void *qbman_swp_mc_start(struct qbman_swp *p) +{ + void *ret; +#ifdef QBMAN_CHECKING + BUG_ON(p->mc.check != swp_mc_can_start); +#endif + ret = qbman_cena_write_start(&p->sys, QBMAN_CENA_SWP_CR); +#ifdef QBMAN_CHECKING + if (!ret) + p->mc.check = swp_mc_can_submit; +#endif + return ret; +} + +void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, uint32_t cmd_verb) +{ + uint32_t *v = cmd; +#ifdef QBMAN_CHECKING + BUG_ON(!p->mc.check != swp_mc_can_submit); +#endif + lwsync(); + /* TBD: "|=" is going to hurt performance. Need to move as many fields + * out of word zero, and for those that remain, the "OR" needs to occur + * at the caller side. This debug check helps to catch cases where the + * caller wants to OR but has forgotten to do so. */ + BUG_ON((*v & cmd_verb) != *v); + *v = cmd_verb | p->mc.valid_bit; + qbman_cena_write_complete(&p->sys, QBMAN_CENA_SWP_CR, cmd); + /* TODO: add prefetch support for GPP */ +#ifdef QBMAN_CHECKING + p->mc.check = swp_mc_can_poll; +#endif +} + +void *qbman_swp_mc_result(struct qbman_swp *p) +{ + uint32_t *ret, verb; +#ifdef QBMAN_CHECKING + BUG_ON(p->mc.check != swp_mc_can_poll); +#endif + ret = qbman_cena_read(&p->sys, QBMAN_CENA_SWP_RR(p->mc.valid_bit)); + /* Remove the valid-bit - command completed iff the rest is non-zero */ + verb = ret[0] & ~QB_VALID_BIT; + if (!verb) + return NULL; +#ifdef QBMAN_CHECKING + p->mc.check = swp_mc_can_start; +#endif + p->mc.valid_bit ^= QB_VALID_BIT; + return ret; +} + +/***********/ +/* Enqueue */ +/***********/ + +/* These should be const, eventually */ +static struct qb_attr_code code_eq_cmd = QB_CODE(0, 0, 2); +static struct qb_attr_code code_eq_orp_en = QB_CODE(0, 2, 1); +static struct qb_attr_code code_eq_tgt_id = QB_CODE(2, 0, 24); +/* static struct qb_attr_code code_eq_tag = QB_CODE(3, 0, 32); */ +static struct qb_attr_code code_eq_qd_en = QB_CODE(0, 4, 1); +static struct qb_attr_code code_eq_qd_bin = QB_CODE(4, 0, 16); +static struct qb_attr_code code_eq_qd_pri = QB_CODE(4, 16, 4); +static struct qb_attr_code code_eq_rsp_stash = QB_CODE(5, 16, 1); +static struct qb_attr_code code_eq_rsp_lo = QB_CODE(6, 0, 32); +static struct qb_attr_code code_eq_rsp_hi = QB_CODE(7, 0, 32); + +enum qbman_eq_cmd_e { + /* No enqueue, primarily for plugging ORP gaps for dropped frames */ + qbman_eq_cmd_empty, + /* DMA an enqueue response once complete */ + qbman_eq_cmd_respond, + /* DMA an enqueue response only if the enqueue fails */ + qbman_eq_cmd_respond_reject +}; + +void qbman_eq_desc_clear(struct qbman_eq_desc *d) +{ + memset(d, 0, sizeof(*d)); +} + +void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success) +{ + uint32_t *cl = qb_cl(d); + + qb_attr_code_encode(&code_eq_orp_en, cl, 0); + qb_attr_code_encode(&code_eq_cmd, cl, + respond_success ? qbman_eq_cmd_respond : + qbman_eq_cmd_respond_reject); +} + +void qbman_eq_desc_set_response(struct qbman_eq_desc *d, + dma_addr_t storage_phys, + int stash) +{ + uint32_t *cl = qb_cl(d); + + qb_attr_code_encode(&code_eq_rsp_lo, cl, lower32(storage_phys)); + qb_attr_code_encode(&code_eq_rsp_hi, cl, upper32(storage_phys)); + qb_attr_code_encode(&code_eq_rsp_stash, cl, !!stash); +} + + +void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, uint32_t qdid, + uint32_t qd_bin, uint32_t qd_prio) +{ + uint32_t *cl = qb_cl(d); + + qb_attr_code_encode(&code_eq_qd_en, cl, 1); + qb_attr_code_encode(&code_eq_tgt_id, cl, qdid); + qb_attr_code_encode(&code_eq_qd_bin, cl, qd_bin); + qb_attr_code_encode(&code_eq_qd_pri, cl, qd_prio); +} + +#define EQAR_IDX(eqar) ((eqar) & 0x7) +#define EQAR_VB(eqar) ((eqar) & 0x80) +#define EQAR_SUCCESS(eqar) ((eqar) & 0x100) + +int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d, + const struct qbman_fd *fd) +{ + uint32_t *p; + const uint32_t *cl = qb_cl(d); + uint32_t eqar = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_EQAR); + debug("EQAR=%08x\n", eqar); + if (!EQAR_SUCCESS(eqar)) + return -EBUSY; + p = qbman_cena_write_start(&s->sys, + QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar))); + word_copy(&p[1], &cl[1], 7); + word_copy(&p[8], fd, sizeof(*fd) >> 2); + lwsync(); + /* Set the verb byte, have to substitute in the valid-bit */ + p[0] = cl[0] | EQAR_VB(eqar); + qbman_cena_write_complete(&s->sys, + QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar)), + p); + return 0; +} + +/***************************/ +/* Volatile (pull) dequeue */ +/***************************/ + +/* These should be const, eventually */ +static struct qb_attr_code code_pull_dct = QB_CODE(0, 0, 2); +static struct qb_attr_code code_pull_dt = QB_CODE(0, 2, 2); +static struct qb_attr_code code_pull_rls = QB_CODE(0, 4, 1); +static struct qb_attr_code code_pull_stash = QB_CODE(0, 5, 1); +static struct qb_attr_code code_pull_numframes = QB_CODE(0, 8, 4); +static struct qb_attr_code code_pull_token = QB_CODE(0, 16, 8); +static struct qb_attr_code code_pull_dqsource = QB_CODE(1, 0, 24); +static struct qb_attr_code code_pull_rsp_lo = QB_CODE(2, 0, 32); +static struct qb_attr_code code_pull_rsp_hi = QB_CODE(3, 0, 32); + +enum qb_pull_dt_e { + qb_pull_dt_channel, + qb_pull_dt_workqueue, + qb_pull_dt_framequeue +}; + +void qbman_pull_desc_clear(struct qbman_pull_desc *d) +{ + memset(d, 0, sizeof(*d)); +} + +void qbman_pull_desc_set_storage(struct qbman_pull_desc *d, + struct ldpaa_dq *storage, + dma_addr_t storage_phys, + int stash) +{ + uint32_t *cl = qb_cl(d); + + /* Squiggle the pointer 'storage' into the extra 2 words of the + * descriptor (which aren't copied to the hw command) */ + *(void **)&cl[4] = storage; + if (!storage) { + qb_attr_code_encode(&code_pull_rls, cl, 0); + return; + } + qb_attr_code_encode(&code_pull_rls, cl, 1); + qb_attr_code_encode(&code_pull_stash, cl, !!stash); + qb_attr_code_encode(&code_pull_rsp_lo, cl, lower32(storage_phys)); + qb_attr_code_encode(&code_pull_rsp_hi, cl, upper32(storage_phys)); +} + +void qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, uint8_t numframes) +{ + uint32_t *cl = qb_cl(d); + + BUG_ON(!numframes || (numframes > 16)); + qb_attr_code_encode(&code_pull_numframes, cl, + (uint32_t)(numframes - 1)); +} + +void qbman_pull_desc_set_token(struct qbman_pull_desc *d, uint8_t token) +{ + uint32_t *cl = qb_cl(d); + + qb_attr_code_encode(&code_pull_token, cl, token); +} + +void qbman_pull_desc_set_fq(struct qbman_pull_desc *d, uint32_t fqid) +{ + uint32_t *cl = qb_cl(d); + + qb_attr_code_encode(&code_pull_dct, cl, 1); + qb_attr_code_encode(&code_pull_dt, cl, qb_pull_dt_framequeue); + qb_attr_code_encode(&code_pull_dqsource, cl, fqid); +} + +int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d) +{ + uint32_t *p; + uint32_t *cl = qb_cl(d); + + /* TODO: convert to atomic_t */ + if (s->vdq.busy) + return -EBUSY; + s->vdq.busy = 1; + s->vdq.storage = *(void **)&cl[4]; + s->vdq.token = qb_attr_code_decode(&code_pull_token, cl); + p = qbman_cena_write_start(&s->sys, QBMAN_CENA_SWP_VDQCR); + word_copy(&p[1], &cl[1], 3); + lwsync(); + /* Set the verb byte, have to substitute in the valid-bit */ + p[0] = cl[0] | s->vdq.valid_bit; + s->vdq.valid_bit ^= QB_VALID_BIT; + qbman_cena_write_complete(&s->sys, QBMAN_CENA_SWP_VDQCR, p); + return 0; +} + +/****************/ +/* Polling DQRR */ +/****************/ + +static struct qb_attr_code code_dqrr_verb = QB_CODE(0, 0, 8); +static struct qb_attr_code code_dqrr_response = QB_CODE(0, 0, 7); +static struct qb_attr_code code_dqrr_stat = QB_CODE(0, 8, 8); + +#define QBMAN_DQRR_RESPONSE_DQ 0x60 +#define QBMAN_DQRR_RESPONSE_FQRN 0x21 +#define QBMAN_DQRR_RESPONSE_FQRNI 0x22 +#define QBMAN_DQRR_RESPONSE_FQPN 0x24 +#define QBMAN_DQRR_RESPONSE_FQDAN 0x25 +#define QBMAN_DQRR_RESPONSE_CDAN 0x26 +#define QBMAN_DQRR_RESPONSE_CSCN_MEM 0x27 +#define QBMAN_DQRR_RESPONSE_CGCU 0x28 +#define QBMAN_DQRR_RESPONSE_BPSCN 0x29 +#define QBMAN_DQRR_RESPONSE_CSCN_WQ 0x2a + + +/* NULL return if there are no unconsumed DQRR entries. Returns a DQRR entry + * only once, so repeated calls can return a sequence of DQRR entries, without + * requiring they be consumed immediately or in any particular order. */ +const struct ldpaa_dq *qbman_swp_dqrr_next(struct qbman_swp *s) +{ + uint32_t verb; + uint32_t response_verb; + const struct ldpaa_dq *dq = qbman_cena_read(&s->sys, + QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); + const uint32_t *p = qb_cl(dq); + + verb = qb_attr_code_decode(&code_dqrr_verb, p); + /* If the valid-bit isn't of the expected polarity, nothing there */ + if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) { + qbman_cena_invalidate_prefetch(&s->sys, + QBMAN_CENA_SWP_DQRR( + s->dqrr.next_idx)); + return NULL; + } + /* There's something there. Move "next_idx" attention to the next ring + * entry (and prefetch it) before returning what we found. */ + s->dqrr.next_idx++; + s->dqrr.next_idx &= 3; /* Wrap around at 4 */ + /* TODO: it's possible to do all this without conditionals, optimise it + * later. */ + if (!s->dqrr.next_idx) + s->dqrr.valid_bit ^= QB_VALID_BIT; + /* VDQCR "no longer busy" hook - if VDQCR shows "busy" and this is a + * VDQCR result, mark it as non-busy. */ + if (s->vdq.busy) { + uint32_t flags = ldpaa_dq_flags(dq); + + response_verb = qb_attr_code_decode(&code_dqrr_response, &verb); + if ((response_verb == QBMAN_DQRR_RESPONSE_DQ) && + (flags & LDPAA_DQ_STAT_VOLATILE)) + s->vdq.busy = 0; + } + qbman_cena_invalidate_prefetch(&s->sys, + QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); + return dq; +} + +/* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). */ +void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct ldpaa_dq *dq) +{ + qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq)); +} + +/*********************************/ +/* Polling user-provided storage */ +/*********************************/ + +void qbman_dq_entry_set_oldtoken(struct ldpaa_dq *dq, + unsigned int num_entries, + uint8_t oldtoken) +{ + memset(dq, oldtoken, num_entries * sizeof(*dq)); +} + +int qbman_dq_entry_has_newtoken(struct qbman_swp *s, + const struct ldpaa_dq *dq, + uint8_t newtoken) +{ + /* To avoid converting the little-endian DQ entry to host-endian prior + * to us knowing whether there is a valid entry or not (and run the + * risk of corrupting the incoming hardware LE write), we detect in + * hardware endianness rather than host. This means we need a different + * "code" depending on whether we are BE or LE in software, which is + * where DQRR_TOK_OFFSET comes in... */ + static struct qb_attr_code code_dqrr_tok_detect = + QB_CODE(0, DQRR_TOK_OFFSET, 8); + /* The user trying to poll for a result treats "dq" as const. It is + * however the same address that was provided to us non-const in the + * first place, for directing hardware DMA to. So we can cast away the + * const because it is mutable from our perspective. */ + uint32_t *p = qb_cl((struct ldpaa_dq *)dq); + uint32_t token; + + token = qb_attr_code_decode(&code_dqrr_tok_detect, &p[1]); + if (token != newtoken) + return 0; + + /* Only now do we convert from hardware to host endianness. Also, as we + * are returning success, the user has promised not to call us again, so + * there's no risk of us converting the endianness twice... */ + make_le32_n(p, 16); + + /* VDQCR "no longer busy" hook - not quite the same as DQRR, because the + * fact "VDQCR" shows busy doesn't mean that the result we're looking at + * is from the same command. Eg. we may be looking at our 10th dequeue + * result from our first VDQCR command, yet the second dequeue command + * could have been kicked off already, after seeing the 1st result. Ie. + * the result we're looking at is not necessarily proof that we can + * reset "busy". We instead base the decision on whether the current + * result is sitting at the first 'storage' location of the busy + * command. */ + if (s->vdq.busy && (s->vdq.storage == dq)) + s->vdq.busy = 0; + return 1; +} + +/********************************/ +/* Categorising dequeue entries */ +/********************************/ + +static inline int __qbman_dq_entry_is_x(const struct ldpaa_dq *dq, uint32_t x) +{ + const uint32_t *p = qb_cl(dq); + uint32_t response_verb = qb_attr_code_decode(&code_dqrr_response, p); + + return response_verb == x; +} + +int qbman_dq_entry_is_DQ(const struct ldpaa_dq *dq) +{ + return __qbman_dq_entry_is_x(dq, QBMAN_DQRR_RESPONSE_DQ); +} + +/*********************************/ +/* Parsing frame dequeue results */ +/*********************************/ + +/* These APIs assume qbman_dq_entry_is_DQ() is TRUE */ + +uint32_t ldpaa_dq_flags(const struct ldpaa_dq *dq) +{ + const uint32_t *p = qb_cl(dq); + + return qb_attr_code_decode(&code_dqrr_stat, p); +} + +const struct dpaa_fd *ldpaa_dq_fd(const struct ldpaa_dq *dq) +{ + const uint32_t *p = qb_cl(dq); + + return (const struct dpaa_fd *)&p[8]; +} + +/******************/ +/* Buffer release */ +/******************/ + +/* These should be const, eventually */ +/* static struct qb_attr_code code_release_num = QB_CODE(0, 0, 3); */ +static struct qb_attr_code code_release_set_me = QB_CODE(0, 5, 1); +static struct qb_attr_code code_release_bpid = QB_CODE(0, 16, 16); + +void qbman_release_desc_clear(struct qbman_release_desc *d) +{ + uint32_t *cl; + + memset(d, 0, sizeof(*d)); + cl = qb_cl(d); + qb_attr_code_encode(&code_release_set_me, cl, 1); +} + +void qbman_release_desc_set_bpid(struct qbman_release_desc *d, uint32_t bpid) +{ + uint32_t *cl = qb_cl(d); + + qb_attr_code_encode(&code_release_bpid, cl, bpid); +} + +#define RAR_IDX(rar) ((rar) & 0x7) +#define RAR_VB(rar) ((rar) & 0x80) +#define RAR_SUCCESS(rar) ((rar) & 0x100) + +int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d, + const uint64_t *buffers, unsigned int num_buffers) +{ + uint32_t *p; + const uint32_t *cl = qb_cl(d); + uint32_t rar = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_RAR); + debug("RAR=%08x\n", rar); + if (!RAR_SUCCESS(rar)) + return -EBUSY; + BUG_ON(!num_buffers || (num_buffers > 7)); + /* Start the release command */ + p = qbman_cena_write_start(&s->sys, + QBMAN_CENA_SWP_RCR(RAR_IDX(rar))); + /* Copy the caller's buffer pointers to the command */ + u64_to_le32_copy(&p[2], buffers, num_buffers); + lwsync(); + /* Set the verb byte, have to substitute in the valid-bit and the number + * of buffers. */ + p[0] = cl[0] | RAR_VB(rar) | num_buffers; + qbman_cena_write_complete(&s->sys, + QBMAN_CENA_SWP_RCR(RAR_IDX(rar)), + p); + return 0; +} + +/*******************/ +/* Buffer acquires */ +/*******************/ + +/* These should be const, eventually */ +static struct qb_attr_code code_acquire_bpid = QB_CODE(0, 16, 16); +static struct qb_attr_code code_acquire_num = QB_CODE(1, 0, 3); +static struct qb_attr_code code_acquire_r_num = QB_CODE(1, 0, 3); + +int qbman_swp_acquire(struct qbman_swp *s, uint32_t bpid, uint64_t *buffers, + unsigned int num_buffers) +{ + uint32_t *p; + uint32_t verb, rslt, num; + + BUG_ON(!num_buffers || (num_buffers > 7)); + + /* Start the management command */ + p = qbman_swp_mc_start(s); + + if (!p) + return -EBUSY; + + /* Encode the caller-provided attributes */ + qb_attr_code_encode(&code_acquire_bpid, p, bpid); + qb_attr_code_encode(&code_acquire_num, p, num_buffers); + + /* Complete the management command */ + p = qbman_swp_mc_complete(s, p, p[0] | QBMAN_MC_ACQUIRE); + + /* Decode the outcome */ + verb = qb_attr_code_decode(&code_generic_verb, p); + rslt = qb_attr_code_decode(&code_generic_rslt, p); + num = qb_attr_code_decode(&code_acquire_r_num, p); + BUG_ON(verb != QBMAN_MC_ACQUIRE); + + /* Determine success or failure */ + if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { + printf("Acquire buffers from BPID 0x%x failed, code=0x%02x\n", + bpid, rslt); + return -EIO; + } + BUG_ON(num > num_buffers); + /* Copy the acquired buffers to the caller's array */ + u64_from_le32_copy(buffers, &p[2], num); + return (int)num; +} diff --git a/drivers/net/fsl-mc/dpio/qbman_portal.h b/drivers/net/fsl-mc/dpio/qbman_portal.h new file mode 100644 index 0000000..bb67c3b --- /dev/null +++ b/drivers/net/fsl-mc/dpio/qbman_portal.h @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "qbman_private.h" +#include <fsl-mc/fsl_qbman_portal.h> +#include <fsl-mc/fsl_dpaa_fd.h> + +/* All QBMan command and result structures use this "valid bit" encoding */ +#define QB_VALID_BIT ((uint32_t)0x80) + +/* Management command result codes */ +#define QBMAN_MC_RSLT_OK 0xf0 + +/* --------------------- */ +/* portal data structure */ +/* --------------------- */ + +struct qbman_swp { + const struct qbman_swp_desc *desc; + /* The qbman_sys (ie. arch/OS-specific) support code can put anything it + * needs in here. */ + struct qbman_swp_sys sys; + /* Management commands */ + struct { +#ifdef QBMAN_CHECKING + enum swp_mc_check { + swp_mc_can_start, /* call __qbman_swp_mc_start() */ + swp_mc_can_submit, /* call __qbman_swp_mc_submit() */ + swp_mc_can_poll, /* call __qbman_swp_mc_result() */ + } check; +#endif + uint32_t valid_bit; /* 0x00 or 0x80 */ + } mc; + /* Push dequeues */ + uint32_t sdq; + /* Volatile dequeues */ + struct { + /* VDQCR supports a "1 deep pipeline", meaning that if you know + * the last-submitted command is already executing in the + * hardware (as evidenced by at least 1 valid dequeue result), + * you can write another dequeue command to the register, the + * hardware will start executing it as soon as the + * already-executing command terminates. (This minimises latency + * and stalls.) With that in mind, this "busy" variable refers + * to whether or not a command can be submitted, not whether or + * not a previously-submitted command is still executing. In + * other words, once proof is seen that the previously-submitted + * command is executing, "vdq" is no longer "busy". TODO: + * convert this to "atomic_t" so that it is thread-safe (without + * locking). */ + int busy; + uint32_t valid_bit; /* 0x00 or 0x80 */ + /* We need to determine when vdq is no longer busy. This depends + * on whether the "busy" (last-submitted) dequeue command is + * targetting DQRR or main-memory, and detected is based on the + * presence of the dequeue command's "token" showing up in + * dequeue entries in DQRR or main-memory (respectively). Debug + * builds will, when submitting vdq commands, verify that the + * dequeue result location is not already equal to the command's + * token value. */ + struct ldpaa_dq *storage; /* NULL if DQRR */ + uint32_t token; + } vdq; + /* DQRR */ + struct { + uint32_t next_idx; + uint32_t valid_bit; + } dqrr; +}; + +/* -------------------------- */ +/* portal management commands */ +/* -------------------------- */ + +/* Different management commands all use this common base layer of code to issue + * commands and poll for results. The first function returns a pointer to where + * the caller should fill in their MC command (though they should ignore the + * verb byte), the second function commits merges in the caller-supplied command + * verb (which should not include the valid-bit) and submits the command to + * hardware, and the third function checks for a completed response (returns + * non-NULL if only if the response is complete). */ +void *qbman_swp_mc_start(struct qbman_swp *p); +void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, uint32_t cmd_verb); +void *qbman_swp_mc_result(struct qbman_swp *p); + +/* Wraps up submit + poll-for-result */ +static inline void *qbman_swp_mc_complete(struct qbman_swp *swp, void *cmd, + uint32_t cmd_verb) +{ + int loopvar; + + qbman_swp_mc_submit(swp, cmd, cmd_verb); + DBG_POLL_START(loopvar); + do { + DBG_POLL_CHECK(loopvar); + cmd = qbman_swp_mc_result(swp); + } while (!cmd); + return cmd; +} + +/* ------------ */ +/* qb_attr_code */ +/* ------------ */ + +/* This struct locates a sub-field within a QBMan portal (CENA) cacheline which + * is either serving as a configuration command or a query result. The + * representation is inherently little-endian, as the indexing of the words is + * itself little-endian in nature and layerscape is little endian for anything + * that crosses a word boundary too (64-bit fields are the obvious examples). + */ +struct qb_attr_code { + unsigned int word; /* which uint32_t[] array member encodes the field */ + unsigned int lsoffset; /* encoding offset from ls-bit */ + unsigned int width; /* encoding width. (bool must be 1.) */ +}; + +/* Macros to define codes */ +#define QB_CODE(a, b, c) { a, b, c} + +/* decode a field from a cacheline */ +static inline uint32_t qb_attr_code_decode(const struct qb_attr_code *code, + const uint32_t *cacheline) +{ + return d32_uint32_t(code->lsoffset, code->width, cacheline[code->word]); +} + +/* encode a field to a cacheline */ +static inline void qb_attr_code_encode(const struct qb_attr_code *code, + uint32_t *cacheline, uint32_t val) +{ + cacheline[code->word] = + r32_uint32_t(code->lsoffset, code->width, cacheline[code->word]) + | e32_uint32_t(code->lsoffset, code->width, val); +} + +/* ---------------------- */ +/* Descriptors/cachelines */ +/* ---------------------- */ + +/* To avoid needless dynamic allocation, the driver API often gives the caller + * a "descriptor" type that the caller can instantiate however they like. + * Ultimately though, it is just a cacheline of binary storage (or something + * smaller when it is known that the descriptor doesn't need all 64 bytes) for + * holding pre-formatted pieces of harware commands. The performance-critical + * code can then copy these descriptors directly into hardware command + * registers more efficiently than trying to construct/format commands + * on-the-fly. The API user sees the descriptor as an array of 32-bit words in + * order for the compiler to know its size, but the internal details are not + * exposed. The following macro is used within the driver for converting *any* + * descriptor pointer to a usable array pointer. The use of a macro (instead of + * an inline) is necessary to work with different descriptor types and to work + * correctly with const and non-const inputs (and similarly-qualified outputs). + */ +#define qb_cl(d) (&(d)->dont_manipulate_directly[0]) diff --git a/drivers/net/fsl-mc/dpio/qbman_private.h b/drivers/net/fsl-mc/dpio/qbman_private.h new file mode 100644 index 0000000..2d2556b --- /dev/null +++ b/drivers/net/fsl-mc/dpio/qbman_private.h @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* Perform extra checking */ +#include <common.h> +#include <errno.h> +#include <asm/io.h> +#include <linux/types.h> +#include <linux/compat.h> +#include <malloc.h> +#include <fsl-mc/fsl_qbman_base.h> + +#define QBMAN_CHECKING + +/* Any time there is a register interface which we poll on, this provides a + * "break after x iterations" scheme for it. It's handy for debugging, eg. + * where you don't want millions of lines of log output from a polling loop + * that won't, because such things tend to drown out the earlier log output + * that might explain what caused the problem. (NB: put ";" after each macro!) + * TODO: we should probably remove this once we're done sanitising the + * simulator... + */ +#define DBG_POLL_START(loopvar) (loopvar = 10) +#define DBG_POLL_CHECK(loopvar) \ + do {if (!(loopvar--)) BUG_ON(NULL == "DBG_POLL_CHECK"); } while (0) + +/* For CCSR or portal-CINH registers that contain fields at arbitrary offsets + * and widths, these macro-generated encode/decode/isolate/remove inlines can + * be used. + * + * Eg. to "d"ecode a 14-bit field out of a register (into a "uint16_t" type), + * where the field is located 3 bits "up" from the least-significant bit of the + * register (ie. the field location within the 32-bit register corresponds to a + * mask of 0x0001fff8), you would do; + * uint16_t field = d32_uint16_t(3, 14, reg_value); + * + * Or to "e"ncode a 1-bit boolean value (input type is "int", zero is FALSE, + * non-zero is TRUE, so must convert all non-zero inputs to 1, hence the "!!" + * operator) into a register at bit location 0x00080000 (19 bits "in" from the + * LS bit), do; + * reg_value |= e32_int(19, 1, !!field); + * + * If you wish to read-modify-write a register, such that you leave the 14-bit + * field as-is but have all other fields set to zero, then "i"solate the 14-bit + * value using; + * reg_value = i32_uint16_t(3, 14, reg_value); + * + * Alternatively, you could "r"emove the 1-bit boolean field (setting it to + * zero) but leaving all other fields as-is; + * reg_val = r32_int(19, 1, reg_value); + * + */ +#define MAKE_MASK32(width) (width == 32 ? 0xffffffff : \ + (uint32_t)((1 << width) - 1)) +#define DECLARE_CODEC32(t) \ +static inline uint32_t e32_##t(uint32_t lsoffset, uint32_t width, t val) \ +{ \ + BUG_ON(width > (sizeof(t) * 8)); \ + return ((uint32_t)val & MAKE_MASK32(width)) << lsoffset; \ +} \ +static inline t d32_##t(uint32_t lsoffset, uint32_t width, uint32_t val) \ +{ \ + BUG_ON(width > (sizeof(t) * 8)); \ + return (t)((val >> lsoffset) & MAKE_MASK32(width)); \ +} \ +static inline uint32_t i32_##t(uint32_t lsoffset, uint32_t width, \ + uint32_t val) \ +{ \ + BUG_ON(width > (sizeof(t) * 8)); \ + return e32_##t(lsoffset, width, d32_##t(lsoffset, width, val)); \ +} \ +static inline uint32_t r32_##t(uint32_t lsoffset, uint32_t width, \ + uint32_t val) \ +{ \ + BUG_ON(width > (sizeof(t) * 8)); \ + return ~(MAKE_MASK32(width) << lsoffset) & val; \ +} +DECLARE_CODEC32(uint32_t) +DECLARE_CODEC32(uint16_t) +DECLARE_CODEC32(uint8_t) +DECLARE_CODEC32(int) + + /*********************/ + /* Debugging assists */ + /*********************/ + +static inline void __hexdump(unsigned long start, unsigned long end, + unsigned long p, size_t sz, const unsigned char *c) +{ + while (start < end) { + unsigned int pos = 0; + char buf[64]; + int nl = 0; + + pos += sprintf(buf + pos, "%08lx: ", start); + do { + if ((start < p) || (start >= (p + sz))) + pos += sprintf(buf + pos, ".."); + else + pos += sprintf(buf + pos, "%02x", *(c++)); + if (!(++start & 15)) { + buf[pos++] = '\n'; + nl = 1; + } else { + nl = 0; + if (!(start & 1)) + buf[pos++] = ' '; + if (!(start & 3)) + buf[pos++] = ' '; + } + } while (start & 15); + if (!nl) + buf[pos++] = '\n'; + buf[pos] = '\0'; + debug("%s", buf); + } +} +static inline void hexdump(const void *ptr, size_t sz) +{ + unsigned long p = (unsigned long)ptr; + unsigned long start = p & ~(unsigned long)15; + unsigned long end = (p + sz + 15) & ~(unsigned long)15; + const unsigned char *c = ptr; + + __hexdump(start, end, p, sz, c); +} + +#if defined(__BIG_ENDIAN) +#define DQRR_TOK_OFFSET 0 +#else +#define DQRR_TOK_OFFSET 24 +#endif + +/* Similarly-named functions */ +#define upper32(a) upper_32_bits(a) +#define lower32(a) lower_32_bits(a) + + /****************/ + /* arch assists */ + /****************/ + +static inline void dcbz(void *ptr) +{ + uint32_t *p = ptr; + BUG_ON((unsigned long)ptr & 63); + p[0] = 0; + p[1] = 0; + p[2] = 0; + p[3] = 0; + p[4] = 0; + p[5] = 0; + p[6] = 0; + p[7] = 0; + p[8] = 0; + p[9] = 0; + p[10] = 0; + p[11] = 0; + p[12] = 0; + p[13] = 0; + p[14] = 0; + p[15] = 0; +} + +#define lwsync() + +#include "qbman_sys.h" diff --git a/drivers/net/fsl-mc/dpio/qbman_sys.h b/drivers/net/fsl-mc/dpio/qbman_sys.h new file mode 100644 index 0000000..235d641 --- /dev/null +++ b/drivers/net/fsl-mc/dpio/qbman_sys.h @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* qbman_sys_decl.h and qbman_sys.h are the two platform-specific files in the + * driver. They are only included via qbman_private.h, which is itself a + * platform-independent file and is included by all the other driver source. + * + * qbman_sys_decl.h is included prior to all other declarations and logic, and + * it exists to provide compatibility with any linux interfaces our + * single-source driver code is dependent on (eg. kmalloc). Ie. this file + * provides linux compatibility. + * + * This qbman_sys.h header, on the other hand, is included *after* any common + * and platform-neutral declarations and logic in qbman_private.h, and exists to + * implement any platform-specific logic of the qbman driver itself. Ie. it is + * *not* to provide linux compatibility. + */ + +/* Trace the 3 different classes of read/write access to QBMan. #undef as + * required. */ +#undef QBMAN_CCSR_TRACE +#undef QBMAN_CINH_TRACE +#undef QBMAN_CENA_TRACE + +/* Temporarily define this to get around the fact that cache enabled mapping is + * not working right now. Will remove this after uboot could map the cache + * enabled portal memory. + */ +#define QBMAN_CINH_ONLY + +static inline void word_copy(void *d, const void *s, unsigned int cnt) +{ + uint32_t *dd = d; + const uint32_t *ss = s; + + while (cnt--) + *(dd++) = *(ss++); +} + +/* Currently, the CENA support code expects each 32-bit word to be written in + * host order, and these are converted to hardware (little-endian) order on + * command submission. However, 64-bit quantities are must be written (and read) + * as two 32-bit words with the least-significant word first, irrespective of + * host endianness. */ +static inline void u64_to_le32_copy(void *d, const uint64_t *s, + unsigned int cnt) +{ + uint32_t *dd = d; + const uint32_t *ss = (const uint32_t *)s; + + while (cnt--) { + /* TBD: the toolchain was choking on the use of 64-bit types up + * until recently so this works entirely with 32-bit variables. + * When 64-bit types become usable again, investigate better + * ways of doing this. */ +#if defined(__BIG_ENDIAN) + *(dd++) = ss[1]; + *(dd++) = ss[0]; + ss += 2; +#else + *(dd++) = *(ss++); + *(dd++) = *(ss++); +#endif + } +} +static inline void u64_from_le32_copy(uint64_t *d, const void *s, + unsigned int cnt) +{ + const uint32_t *ss = s; + uint32_t *dd = (uint32_t *)d; + + while (cnt--) { +#if defined(__BIG_ENDIAN) + dd[1] = *(ss++); + dd[0] = *(ss++); + dd += 2; +#else + *(dd++) = *(ss++); + *(dd++) = *(ss++); +#endif + } +} + +/* Convert a host-native 32bit value into little endian */ +#if defined(__BIG_ENDIAN) +static inline uint32_t make_le32(uint32_t val) +{ + return ((val & 0xff) << 24) | ((val & 0xff00) << 8) | + ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24); +} +#else +#define make_le32(val) (val) +#endif +static inline void make_le32_n(uint32_t *val, unsigned int num) +{ + while (num--) { + *val = make_le32(*val); + val++; + } +} + + /******************/ + /* Portal access */ + /******************/ +struct qbman_swp_sys { + /* On GPP, the sys support for qbman_swp is here. The CENA region isi + * not an mmap() of the real portal registers, but an allocated + * place-holder, because the actual writes/reads to/from the portal are + * marshalled from these allocated areas using QBMan's "MC access + * registers". CINH accesses are atomic so there's no need for a + * place-holder. */ + void *cena; + void __iomem *addr_cena; + void __iomem *addr_cinh; +}; + +/* P_OFFSET is (ACCESS_CMD,0,12) - offset within the portal + * C is (ACCESS_CMD,12,1) - is inhibited? (0==CENA, 1==CINH) + * SWP_IDX is (ACCESS_CMD,16,10) - Software portal index + * P is (ACCESS_CMD,28,1) - (0==special portal, 1==any portal) + * T is (ACCESS_CMD,29,1) - Command type (0==READ, 1==WRITE) + * E is (ACCESS_CMD,31,1) - Command execute (1 to issue, poll for 0==complete) + */ + +static inline void qbman_cinh_write(struct qbman_swp_sys *s, uint32_t offset, + uint32_t val) +{ + __raw_writel(val, s->addr_cinh + offset); +#ifdef QBMAN_CINH_TRACE + pr_info("qbman_cinh_write(%p:0x%03x) 0x%08x\n", + s->addr_cinh, offset, val); +#endif +} + +static inline uint32_t qbman_cinh_read(struct qbman_swp_sys *s, uint32_t offset) +{ + uint32_t reg = __raw_readl(s->addr_cinh + offset); + +#ifdef QBMAN_CINH_TRACE + pr_info("qbman_cinh_read(%p:0x%03x) 0x%08x\n", + s->addr_cinh, offset, reg); +#endif + return reg; +} + +static inline void *qbman_cena_write_start(struct qbman_swp_sys *s, + uint32_t offset) +{ + void *shadow = s->cena + offset; + +#ifdef QBMAN_CENA_TRACE + pr_info("qbman_cena_write_start(%p:0x%03x) %p\n", + s->addr_cena, offset, shadow); +#endif + BUG_ON(offset & 63); + dcbz(shadow); + return shadow; +} + +static inline void qbman_cena_write_complete(struct qbman_swp_sys *s, + uint32_t offset, void *cmd) +{ + const uint32_t *shadow = cmd; + int loop; + +#ifdef QBMAN_CENA_TRACE + pr_info("qbman_cena_write_complete(%p:0x%03x) %p\n", + s->addr_cena, offset, shadow); + hexdump(cmd, 64); +#endif + for (loop = 15; loop >= 0; loop--) +#ifdef QBMAN_CINH_ONLY + __raw_writel(shadow[loop], s->addr_cinh + + offset + loop * 4); +#else + __raw_writel(shadow[loop], s->addr_cena + + offset + loop * 4); +#endif +} + +static inline void *qbman_cena_read(struct qbman_swp_sys *s, uint32_t offset) +{ + uint32_t *shadow = s->cena + offset; + unsigned int loop; + +#ifdef QBMAN_CENA_TRACE + pr_info("qbman_cena_read(%p:0x%03x) %p\n", + s->addr_cena, offset, shadow); +#endif + + for (loop = 0; loop < 16; loop++) +#ifdef QBMAN_CINH_ONLY + shadow[loop] = __raw_readl(s->addr_cinh + offset + + loop * 4); +#else + shadow[loop] = __raw_readl(s->addr_cena + offset + + loop * 4); +#endif +#ifdef QBMAN_CENA_TRACE + hexdump(shadow, 64); +#endif + return shadow; +} + +static inline void qbman_cena_invalidate_prefetch(struct qbman_swp_sys *s, + uint32_t offset) +{ +} + + /******************/ + /* Portal support */ + /******************/ + +/* The SWP_CFG portal register is special, in that it is used by the + * platform-specific code rather than the platform-independent code in + * qbman_portal.c. So use of it is declared locally here. */ +#define QBMAN_CINH_SWP_CFG 0xd00 + +/* For MC portal use, we always configure with + * DQRR_MF is (SWP_CFG,20,3) - DQRR max fill (<- 0x4) + * EST is (SWP_CFG,16,3) - EQCR_CI stashing threshold (<- 0x0) + * RPM is (SWP_CFG,12,2) - RCR production notification mode (<- 0x3) + * DCM is (SWP_CFG,10,2) - DQRR consumption notification mode (<- 0x2) + * EPM is (SWP_CFG,8,2) - EQCR production notification mode (<- 0x3) + * SD is (SWP_CFG,5,1) - memory stashing drop enable (<- FALSE) + * SP is (SWP_CFG,4,1) - memory stashing priority (<- TRUE) + * SE is (SWP_CFG,3,1) - memory stashing enable (<- 0x0) + * DP is (SWP_CFG,2,1) - dequeue stashing priority (<- TRUE) + * DE is (SWP_CFG,1,1) - dequeue stashing enable (<- 0x0) + * EP is (SWP_CFG,0,1) - EQCR_CI stashing priority (<- FALSE) + */ +static inline uint32_t qbman_set_swp_cfg(uint8_t max_fill, uint8_t wn, + uint8_t est, uint8_t rpm, uint8_t dcm, + uint8_t epm, int sd, int sp, int se, + int dp, int de, int ep) +{ + uint32_t reg; + + reg = e32_uint8_t(20, 3, max_fill) | e32_uint8_t(16, 3, est) | + e32_uint8_t(12, 2, rpm) | e32_uint8_t(10, 2, dcm) | + e32_uint8_t(8, 2, epm) | e32_int(5, 1, sd) | + e32_int(4, 1, sp) | e32_int(3, 1, se) | e32_int(2, 1, dp) | + e32_int(1, 1, de) | e32_int(0, 1, ep) | e32_uint8_t(14, 1, wn); + return reg; +} + +static inline int qbman_swp_sys_init(struct qbman_swp_sys *s, + const struct qbman_swp_desc *d) +{ + uint32_t reg; + + s->addr_cena = d->cena_bar; + s->addr_cinh = d->cinh_bar; + s->cena = (void *)valloc(CONFIG_SYS_PAGE_SIZE); + memset((void *)s->cena, 0x00, CONFIG_SYS_PAGE_SIZE); + if (!s->cena) { + printf("Could not allocate page for cena shadow\n"); + return -1; + } + +#ifdef QBMAN_CHECKING + /* We should never be asked to initialise for a portal that isn't in + * the power-on state. (Ie. don't forget to reset portals when they are + * decommissioned!) + */ + reg = qbman_cinh_read(s, QBMAN_CINH_SWP_CFG); + BUG_ON(reg); +#endif +#ifdef QBMAN_CINH_ONLY + reg = qbman_set_swp_cfg(4, 1, 0, 3, 2, 3, 0, 1, 0, 1, 0, 0); +#else + reg = qbman_set_swp_cfg(4, 0, 0, 3, 2, 3, 0, 1, 0, 1, 0, 0); +#endif + qbman_cinh_write(s, QBMAN_CINH_SWP_CFG, reg); + reg = qbman_cinh_read(s, QBMAN_CINH_SWP_CFG); + if (!reg) { + printf("The portal is not enabled!\n"); + free(s->cena); + return -1; + } + return 0; +} + +static inline void qbman_swp_sys_finish(struct qbman_swp_sys *s) +{ + free((void *)s->cena); +} diff --git a/drivers/net/fsl-mc/dpmng.c b/drivers/net/fsl-mc/dpmng.c index cc14c7b..01ee112 100644 --- a/drivers/net/fsl-mc/dpmng.c +++ b/drivers/net/fsl-mc/dpmng.c @@ -1,4 +1,4 @@ -/* Copyright 2014 Freescale Semiconductor Inc. +/* Copyright 2013-2015 Freescale Semiconductor Inc. * * SPDX-License-Identifier: GPL-2.0+ */ @@ -26,66 +26,3 @@ int mc_get_version(struct fsl_mc_io *mc_io, struct mc_version *mc_ver_info) return 0; } - -int dpmng_reset_aiop(struct fsl_mc_io *mc_io, int container_id, - int aiop_tile_id) -{ - struct mc_command cmd = { 0 }; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPMNG_CMDID_RESET_AIOP, - MC_CMD_PRI_LOW, 0); - DPMNG_CMD_RESET_AIOP(cmd, container_id, aiop_tile_id); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -int dpmng_load_aiop(struct fsl_mc_io *mc_io, - int container_id, - int aiop_tile_id, - uint64_t img_iova, - uint32_t img_size) -{ - struct mc_command cmd = { 0 }; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPMNG_CMDID_LOAD_AIOP, - MC_CMD_PRI_LOW, - 0); - DPMNG_CMD_LOAD_AIOP(cmd, container_id, aiop_tile_id, img_size, - img_iova); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -int dpmng_run_aiop(struct fsl_mc_io *mc_io, - int container_id, - int aiop_tile_id, - const struct dpmng_aiop_run_cfg *cfg) -{ - struct mc_command cmd = { 0 }; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPMNG_CMDID_RUN_AIOP, - MC_CMD_PRI_LOW, - 0); - DPMNG_CMD_RUN_AIOP(cmd, container_id, aiop_tile_id, cfg); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} - -int dpmng_reset_mc_portal(struct fsl_mc_io *mc_io) -{ - struct mc_command cmd = { 0 }; - - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPMNG_CMDID_RESET_MC_PORTAL, - MC_CMD_PRI_LOW, - 0); - - /* send command to mc*/ - return mc_send_command(mc_io, &cmd); -} diff --git a/drivers/net/fsl-mc/dpni.c b/drivers/net/fsl-mc/dpni.c new file mode 100644 index 0000000..b384401 --- /dev/null +++ b/drivers/net/fsl-mc/dpni.c @@ -0,0 +1,506 @@ +/* + * Copyright (C) 2013-2015 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <fsl-mc/fsl_mc_sys.h> +#include <fsl-mc/fsl_mc_cmd.h> +#include <fsl-mc/fsl_dpni.h> + +int dpni_open(struct fsl_mc_io *mc_io, int dpni_id, uint16_t *token) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_OPEN, + MC_CMD_PRI_LOW, 0); + DPNI_CMD_OPEN(cmd, dpni_id); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + *token = MC_CMD_HDR_READ_TOKEN(cmd.header); + + return 0; +} + +int dpni_close(struct fsl_mc_io *mc_io, uint16_t token) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLOSE, + MC_CMD_PRI_HIGH, token); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_set_pools(struct fsl_mc_io *mc_io, + uint16_t token, + const struct dpni_pools_cfg *cfg) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_POOLS, + MC_CMD_PRI_LOW, + token); + DPNI_CMD_SET_POOLS(cmd, cfg); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_enable(struct fsl_mc_io *mc_io, uint16_t token) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_ENABLE, + MC_CMD_PRI_LOW, token); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_disable(struct fsl_mc_io *mc_io, uint16_t token) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_DISABLE, + MC_CMD_PRI_LOW, + token); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_reset(struct fsl_mc_io *mc_io, uint16_t token) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_RESET, + MC_CMD_PRI_LOW, token); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_get_attributes(struct fsl_mc_io *mc_io, + uint16_t token, + struct dpni_attr *attr) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_ATTR, + MC_CMD_PRI_LOW, + token); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPNI_RSP_GET_ATTR(cmd, attr); + + return 0; +} + +int dpni_get_rx_buffer_layout(struct fsl_mc_io *mc_io, + uint16_t token, + struct dpni_buffer_layout *layout) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_BUFFER_LAYOUT, + MC_CMD_PRI_LOW, token); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPNI_RSP_GET_RX_BUFFER_LAYOUT(cmd, layout); + + return 0; +} + +int dpni_set_rx_buffer_layout(struct fsl_mc_io *mc_io, + uint16_t token, + const struct dpni_buffer_layout *layout) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_BUFFER_LAYOUT, + MC_CMD_PRI_LOW, token); + DPNI_CMD_SET_RX_BUFFER_LAYOUT(cmd, layout); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_get_tx_buffer_layout(struct fsl_mc_io *mc_io, + uint16_t token, + struct dpni_buffer_layout *layout) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_BUFFER_LAYOUT, + MC_CMD_PRI_LOW, token); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPNI_RSP_GET_TX_BUFFER_LAYOUT(cmd, layout); + + return 0; +} + +int dpni_set_tx_buffer_layout(struct fsl_mc_io *mc_io, + uint16_t token, + const struct dpni_buffer_layout *layout) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_BUFFER_LAYOUT, + MC_CMD_PRI_LOW, token); + DPNI_CMD_SET_TX_BUFFER_LAYOUT(cmd, layout); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_get_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, + uint16_t token, + struct dpni_buffer_layout *layout) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_CONF_BUFFER_LAYOUT, + MC_CMD_PRI_LOW, token); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPNI_RSP_GET_TX_CONF_BUFFER_LAYOUT(cmd, layout); + + return 0; +} + +int dpni_set_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, + uint16_t token, + const struct dpni_buffer_layout *layout) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONF_BUFFER_LAYOUT, + MC_CMD_PRI_LOW, token); + DPNI_CMD_SET_TX_CONF_BUFFER_LAYOUT(cmd, layout); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_get_qdid(struct fsl_mc_io *mc_io, uint16_t token, uint16_t *qdid) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_QDID, + MC_CMD_PRI_LOW, + token); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPNI_RSP_GET_QDID(cmd, *qdid); + + return 0; +} + +int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io, + uint16_t token, + uint16_t *data_offset) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_DATA_OFFSET, + MC_CMD_PRI_LOW, token); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPNI_RSP_GET_TX_DATA_OFFSET(cmd, *data_offset); + + return 0; +} + +int dpni_get_counter(struct fsl_mc_io *mc_io, + uint16_t token, + enum dpni_counter counter, + uint64_t *value) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_COUNTER, + MC_CMD_PRI_LOW, token); + DPNI_CMD_GET_COUNTER(cmd, counter); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPNI_RSP_GET_COUNTER(cmd, *value); + + return 0; +} + +int dpni_set_counter(struct fsl_mc_io *mc_io, + uint16_t token, + enum dpni_counter counter, + uint64_t value) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_COUNTER, + MC_CMD_PRI_LOW, token); + DPNI_CMD_SET_COUNTER(cmd, counter, value); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_set_link_cfg(struct fsl_mc_io *mc_io, + uint16_t token, + struct dpni_link_cfg *cfg) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_LINK_CFG, + MC_CMD_PRI_LOW, token); + DPNI_CMD_SET_LINK_CFG(cmd, cfg); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_get_link_state(struct fsl_mc_io *mc_io, + uint16_t token, + struct dpni_link_state *state) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_LINK_STATE, + MC_CMD_PRI_LOW, token); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPNI_RSP_GET_LINK_STATE(cmd, state); + + return 0; +} + + +int dpni_set_primary_mac_addr(struct fsl_mc_io *mc_io, + uint16_t token, + const uint8_t mac_addr[6]) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_PRIM_MAC, + MC_CMD_PRI_LOW, token); + DPNI_CMD_SET_PRIMARY_MAC_ADDR(cmd, mac_addr); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_get_primary_mac_addr(struct fsl_mc_io *mc_io, + uint16_t token, + uint8_t mac_addr[6]) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_PRIM_MAC, + MC_CMD_PRI_LOW, token); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPNI_RSP_GET_PRIMARY_MAC_ADDR(cmd, mac_addr); + + return 0; +} + +int dpni_add_mac_addr(struct fsl_mc_io *mc_io, + uint16_t token, + const uint8_t mac_addr[6]) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_MAC_ADDR, + MC_CMD_PRI_LOW, token); + DPNI_CMD_ADD_MAC_ADDR(cmd, mac_addr); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_remove_mac_addr(struct fsl_mc_io *mc_io, + uint16_t token, + const uint8_t mac_addr[6]) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_MAC_ADDR, + MC_CMD_PRI_LOW, token); + DPNI_CMD_REMOVE_MAC_ADDR(cmd, mac_addr); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_set_tx_flow(struct fsl_mc_io *mc_io, + uint16_t token, + uint16_t *flow_id, + const struct dpni_tx_flow_cfg *cfg) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_FLOW, + MC_CMD_PRI_LOW, token); + DPNI_CMD_SET_TX_FLOW(cmd, *flow_id, cfg); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPNI_RSP_SET_TX_FLOW(cmd, *flow_id); + + return 0; +} + +int dpni_get_tx_flow(struct fsl_mc_io *mc_io, + uint16_t token, + uint16_t flow_id, + struct dpni_tx_flow_attr *attr) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_FLOW, + MC_CMD_PRI_LOW, token); + DPNI_CMD_GET_TX_FLOW(cmd, flow_id); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPNI_RSP_GET_TX_FLOW(cmd, attr); + + return 0; +} + +int dpni_set_rx_flow(struct fsl_mc_io *mc_io, + uint16_t token, + uint8_t tc_id, + uint16_t flow_id, + const struct dpni_queue_cfg *cfg) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_FLOW, + MC_CMD_PRI_LOW, token); + DPNI_CMD_SET_RX_FLOW(cmd, tc_id, flow_id, cfg); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_get_rx_flow(struct fsl_mc_io *mc_io, + uint16_t token, + uint8_t tc_id, + uint16_t flow_id, + struct dpni_queue_attr *attr) +{ + struct mc_command cmd = { 0 }; + int err; + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_FLOW, + MC_CMD_PRI_LOW, token); + DPNI_CMD_GET_RX_FLOW(cmd, tc_id, flow_id); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPNI_RSP_GET_RX_FLOW(cmd, attr); + + return 0; +} diff --git a/drivers/net/fsl-mc/dprc.c b/drivers/net/fsl-mc/dprc.c new file mode 100644 index 0000000..d481200 --- /dev/null +++ b/drivers/net/fsl-mc/dprc.c @@ -0,0 +1,283 @@ +/* + * Freescale Layerscape MC I/O wrapper + * + * Copyright (C) 2013-2015 Freescale Semiconductor, Inc. + * Author: German Rivera <German.Rivera@freescale.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <fsl-mc/fsl_mc_sys.h> +#include <fsl-mc/fsl_mc_cmd.h> +#include <fsl-mc/fsl_dprc.h> + +int dprc_get_container_id(struct fsl_mc_io *mc_io, int *container_id) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID, + MC_CMD_PRI_LOW, 0); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPRC_RSP_GET_CONTAINER_ID(cmd, *container_id); + + return 0; +} + +int dprc_open(struct fsl_mc_io *mc_io, int container_id, uint16_t *token) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, MC_CMD_PRI_LOW, + 0); + DPRC_CMD_OPEN(cmd, container_id); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + *token = MC_CMD_HDR_READ_TOKEN(cmd.header); + + return 0; +} + +int dprc_close(struct fsl_mc_io *mc_io, uint16_t token) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, MC_CMD_PRI_HIGH, + token); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dprc_reset_container(struct fsl_mc_io *mc_io, + uint16_t token, + int child_container_id) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT, + MC_CMD_PRI_LOW, token); + DPRC_CMD_RESET_CONTAINER(cmd, child_container_id); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dprc_get_attributes(struct fsl_mc_io *mc_io, + uint16_t token, + struct dprc_attributes *attr) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR, + MC_CMD_PRI_LOW, + token); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPRC_RSP_GET_ATTRIBUTES(cmd, attr); + + return 0; +} + +int dprc_get_obj_count(struct fsl_mc_io *mc_io, uint16_t token, int *obj_count) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT, + MC_CMD_PRI_LOW, token); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPRC_RSP_GET_OBJ_COUNT(cmd, *obj_count); + + return 0; +} + +int dprc_get_obj(struct fsl_mc_io *mc_io, + uint16_t token, + int obj_index, + struct dprc_obj_desc *obj_desc) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ, + MC_CMD_PRI_LOW, + token); + DPRC_CMD_GET_OBJ(cmd, obj_index); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPRC_RSP_GET_OBJ(cmd, obj_desc); + + return 0; +} + +int dprc_get_res_count(struct fsl_mc_io *mc_io, + uint16_t token, + char *type, + int *res_count) +{ + struct mc_command cmd = { 0 }; + int err; + + *res_count = 0; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_COUNT, + MC_CMD_PRI_LOW, token); + DPRC_CMD_GET_RES_COUNT(cmd, type); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPRC_RSP_GET_RES_COUNT(cmd, *res_count); + + return 0; +} + +int dprc_get_res_ids(struct fsl_mc_io *mc_io, + uint16_t token, + char *type, + struct dprc_res_ids_range_desc *range_desc) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_IDS, + MC_CMD_PRI_LOW, token); + DPRC_CMD_GET_RES_IDS(cmd, range_desc, type); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPRC_RSP_GET_RES_IDS(cmd, range_desc); + + return 0; +} + +int dprc_get_obj_region(struct fsl_mc_io *mc_io, + uint16_t token, + char *obj_type, + int obj_id, + uint8_t region_index, + struct dprc_region_desc *region_desc) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG, + MC_CMD_PRI_LOW, token); + DPRC_CMD_GET_OBJ_REGION(cmd, obj_type, obj_id, region_index); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPRC_RSP_GET_OBJ_REGION(cmd, region_desc); + + return 0; +} + +int dprc_connect(struct fsl_mc_io *mc_io, + uint16_t token, + const struct dprc_endpoint *endpoint1, + const struct dprc_endpoint *endpoint2) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_CONNECT, + MC_CMD_PRI_LOW, + token); + DPRC_CMD_CONNECT(cmd, endpoint1, endpoint2); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dprc_disconnect(struct fsl_mc_io *mc_io, + uint16_t token, + const struct dprc_endpoint *endpoint) +{ + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_DISCONNECT, + MC_CMD_PRI_LOW, + token); + DPRC_CMD_DISCONNECT(cmd, endpoint); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dprc_get_connection(struct fsl_mc_io *mc_io, + uint16_t token, + const struct dprc_endpoint *endpoint1, + struct dprc_endpoint *endpoint2, + int *state) +{ + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONNECTION, + MC_CMD_PRI_LOW, + token); + DPRC_CMD_GET_CONNECTION(cmd, endpoint1); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + DPRC_RSP_GET_CONNECTION(cmd, endpoint2, *state); + + return 0; +} diff --git a/drivers/net/fsl-mc/fsl_dpmng_cmd.h b/drivers/net/fsl-mc/fsl_dpmng_cmd.h index c9fe021..33f84f3 100644 --- a/drivers/net/fsl-mc/fsl_dpmng_cmd.h +++ b/drivers/net/fsl-mc/fsl_dpmng_cmd.h @@ -1,4 +1,4 @@ -/* Copyright 2014 Freescale Semiconductor Inc. +/* Copyright 2013-2015 Freescale Semiconductor Inc. * * SPDX-License-Identifier: GPL-2.0+ */ @@ -7,10 +7,6 @@ /* Command IDs */ #define DPMNG_CMDID_GET_VERSION 0x831 -#define DPMNG_CMDID_RESET_AIOP 0x832 -#define DPMNG_CMDID_LOAD_AIOP 0x833 -#define DPMNG_CMDID_RUN_AIOP 0x834 -#define DPMNG_CMDID_RESET_MC_PORTAL 0x835 /* cmd, param, offset, width, type, arg_name */ #define DPMNG_RSP_GET_VERSION(cmd, mc_ver_info) \ @@ -20,30 +16,4 @@ do { \ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, mc_ver_info->minor); \ } while (0) -/* cmd, param, offset, width, type, arg_name */ -#define DPMNG_CMD_RESET_AIOP(cmd, container_id, aiop_tile_id) \ -do { \ - MC_CMD_OP(cmd, 0, 0, 32, int, aiop_tile_id); \ - MC_CMD_OP(cmd, 0, 32, 32, int, container_id); \ -} while (0) - -/* cmd, param, offset, width, type, arg_name */ -#define DPMNG_CMD_LOAD_AIOP(cmd, container_id, aiop_tile_id, img_size, \ - img_iova) \ -do { \ - MC_CMD_OP(cmd, 0, 0, 32, int, aiop_tile_id); \ - MC_CMD_OP(cmd, 0, 32, 32, int, container_id); \ - MC_CMD_OP(cmd, 1, 0, 32, uint32_t, img_size); \ - MC_CMD_OP(cmd, 2, 0, 64, uint64_t, img_iova); \ -} while (0) - -/* cmd, param, offset, width, type, arg_name */ -#define DPMNG_CMD_RUN_AIOP(cmd, container_id, aiop_tile_id, cfg) \ -do { \ - MC_CMD_OP(cmd, 0, 0, 32, int, aiop_tile_id); \ - MC_CMD_OP(cmd, 0, 32, 32, int, container_id); \ - MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->cores_mask); \ - MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options); \ -} while (0) - #endif /* __FSL_DPMNG_CMD_H */ diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c index 74b0085..c5c44bc 100644 --- a/drivers/net/fsl-mc/mc.c +++ b/drivers/net/fsl-mc/mc.c @@ -3,16 +3,75 @@ * * SPDX-License-Identifier: GPL-2.0+ */ - #include <errno.h> #include <asm/io.h> #include <fsl-mc/fsl_mc.h> #include <fsl-mc/fsl_mc_sys.h> +#include <fsl-mc/fsl_mc_private.h> #include <fsl-mc/fsl_dpmng.h> +#include <fsl_debug_server.h> +#include <fsl-mc/fsl_dprc.h> +#include <fsl-mc/fsl_dpio.h> +#include <fsl-mc/fsl_qbman_portal.h> + +#define MC_RAM_BASE_ADDR_ALIGNMENT (512UL * 1024 * 1024) +#define MC_RAM_BASE_ADDR_ALIGNMENT_MASK (~(MC_RAM_BASE_ADDR_ALIGNMENT - 1)) +#define MC_RAM_SIZE_ALIGNMENT (256UL * 1024 * 1024) + +#define MC_MEM_SIZE_ENV_VAR "mcmemsize" +#define MC_BOOT_TIMEOUT_ENV_VAR "mcboottimeout" DECLARE_GLOBAL_DATA_PTR; static int mc_boot_status; +struct fsl_mc_io *dflt_mc_io = NULL; +uint16_t dflt_dprc_handle = 0; +struct fsl_dpbp_obj *dflt_dpbp = NULL; +struct fsl_dpio_obj *dflt_dpio = NULL; +uint16_t dflt_dpio_handle = 0; + +#ifdef DEBUG +void dump_ram_words(const char *title, void *addr) +{ + int i; + uint32_t *words = addr; + + printf("Dumping beginning of %s (%p):\n", title, addr); + for (i = 0; i < 16; i++) + printf("%#x ", words[i]); + printf("\n"); +} + +void dump_mc_ccsr_regs(struct mc_ccsr_registers __iomem *mc_ccsr_regs) +{ + printf("MC CCSR registers:\n" + "reg_gcr1 %#x\n" + "reg_gsr %#x\n" + "reg_sicbalr %#x\n" + "reg_sicbahr %#x\n" + "reg_sicapr %#x\n" + "reg_mcfbalr %#x\n" + "reg_mcfbahr %#x\n" + "reg_mcfapr %#x\n" + "reg_psr %#x\n", + mc_ccsr_regs->reg_gcr1, + mc_ccsr_regs->reg_gsr, + mc_ccsr_regs->reg_sicbalr, + mc_ccsr_regs->reg_sicbahr, + mc_ccsr_regs->reg_sicapr, + mc_ccsr_regs->reg_mcfbalr, + mc_ccsr_regs->reg_mcfbahr, + mc_ccsr_regs->reg_mcfapr, + mc_ccsr_regs->reg_psr); +} +#else + +#define dump_ram_words(title, addr) +#define dump_mc_ccsr_regs(mc_ccsr_regs) + +#endif /* DEBUG */ + +#ifndef CONFIG_SYS_LS_MC_FW_IN_DDR /** * Copying MC firmware or DPL image to DDR */ @@ -21,6 +80,7 @@ static int mc_copy_image(const char *title, { debug("%s copied to address %p\n", title, (void *)mc_ram_addr); memcpy((void *)mc_ram_addr, (void *)image_addr, image_size); + flush_dcache_range(mc_ram_addr, mc_ram_addr + image_size); return 0; } @@ -82,23 +142,254 @@ int parse_mc_firmware_fit_image(const void **raw_image_addr, return 0; } +#endif + +/* + * Calculates the values to be used to specify the address range + * for the MC private DRAM block, in the MCFBALR/MCFBAHR registers. + * It returns the highest 512MB-aligned address within the given + * address range, in '*aligned_base_addr', and the number of 256 MiB + * blocks in it, in 'num_256mb_blocks'. + */ +static int calculate_mc_private_ram_params(u64 mc_private_ram_start_addr, + size_t mc_ram_size, + u64 *aligned_base_addr, + u8 *num_256mb_blocks) +{ + u64 addr; + u16 num_blocks; + + if (mc_ram_size % MC_RAM_SIZE_ALIGNMENT != 0) { + printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n", + mc_ram_size); + return -EINVAL; + } + + num_blocks = mc_ram_size / MC_RAM_SIZE_ALIGNMENT; + if (num_blocks < 1 || num_blocks > 0xff) { + printf("fsl-mc: ERROR: invalid MC private RAM size (%lu)\n", + mc_ram_size); + return -EINVAL; + } + + addr = (mc_private_ram_start_addr + mc_ram_size - 1) & + MC_RAM_BASE_ADDR_ALIGNMENT_MASK; + + if (addr < mc_private_ram_start_addr) { + printf("fsl-mc: ERROR: bad start address %#llx\n", + mc_private_ram_start_addr); + return -EFAULT; + } + + *aligned_base_addr = addr; + *num_256mb_blocks = num_blocks; + return 0; +} + +static int load_mc_dpc(u64 mc_ram_addr, size_t mc_ram_size) +{ + u64 mc_dpc_offset; +#ifndef CONFIG_SYS_LS_MC_DPC_IN_DDR + int error; + void *dpc_fdt_hdr; + int dpc_size; +#endif + +#ifdef CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET + BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET & 0x3) != 0 || + CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET > 0xffffffff); + + mc_dpc_offset = CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET; +#else +#error "CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET not defined" +#endif + + /* + * Load the MC DPC blob in the MC private DRAM block: + */ +#ifdef CONFIG_SYS_LS_MC_DPC_IN_DDR + printf("MC DPC is preloaded to %#llx\n", mc_ram_addr + mc_dpc_offset); +#else + /* + * Get address and size of the DPC blob stored in flash: + */ +#ifdef CONFIG_SYS_LS_MC_DPC_IN_NOR + dpc_fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPC_ADDR; +#else +#error "No CONFIG_SYS_LS_MC_DPC_IN_xxx defined" +#endif + + error = fdt_check_header(dpc_fdt_hdr); + if (error != 0) { + /* + * Don't return with error here, since the MC firmware can + * still boot without a DPC + */ + printf("fsl-mc: WARNING: No DPC image found\n"); + return 0; + } + + dpc_size = fdt_totalsize(dpc_fdt_hdr); + if (dpc_size > CONFIG_SYS_LS_MC_DPC_MAX_LENGTH) { + printf("fsl-mc: ERROR: Bad DPC image (too large: %d)\n", + dpc_size); + return -EINVAL; + } + + mc_copy_image("MC DPC blob", + (u64)dpc_fdt_hdr, dpc_size, mc_ram_addr + mc_dpc_offset); +#endif /* not defined CONFIG_SYS_LS_MC_DPC_IN_DDR */ + + dump_ram_words("DPC", (void *)(mc_ram_addr + mc_dpc_offset)); + return 0; +} -int mc_init(bd_t *bis) +static int load_mc_dpl(u64 mc_ram_addr, size_t mc_ram_size) +{ + u64 mc_dpl_offset; +#ifndef CONFIG_SYS_LS_MC_DPL_IN_DDR + int error; + void *dpl_fdt_hdr; + int dpl_size; +#endif + +#ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET + BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 || + CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff); + + mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET; +#else +#error "CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET not defined" +#endif + + /* + * Load the MC DPL blob in the MC private DRAM block: + */ +#ifdef CONFIG_SYS_LS_MC_DPL_IN_DDR + printf("MC DPL is preloaded to %#llx\n", mc_ram_addr + mc_dpl_offset); +#else + /* + * Get address and size of the DPL blob stored in flash: + */ +#ifdef CONFIG_SYS_LS_MC_DPL_IN_NOR + dpl_fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPL_ADDR; +#else +#error "No CONFIG_SYS_LS_MC_DPL_IN_xxx defined" +#endif + + error = fdt_check_header(dpl_fdt_hdr); + if (error != 0) { + printf("fsl-mc: ERROR: Bad DPL image (bad header)\n"); + return error; + } + + dpl_size = fdt_totalsize(dpl_fdt_hdr); + if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) { + printf("fsl-mc: ERROR: Bad DPL image (too large: %d)\n", + dpl_size); + return -EINVAL; + } + + mc_copy_image("MC DPL blob", + (u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset); +#endif /* not defined CONFIG_SYS_LS_MC_DPL_IN_DDR */ + + dump_ram_words("DPL", (void *)(mc_ram_addr + mc_dpl_offset)); + return 0; +} + +/** + * Return the MC boot timeout value in milliseconds + */ +static unsigned long get_mc_boot_timeout_ms(void) +{ + unsigned long timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS; + + char *timeout_ms_env_var = getenv(MC_BOOT_TIMEOUT_ENV_VAR); + + if (timeout_ms_env_var) { + timeout_ms = simple_strtoul(timeout_ms_env_var, NULL, 10); + if (timeout_ms == 0) { + printf("fsl-mc: WARNING: Invalid value for \'" + MC_BOOT_TIMEOUT_ENV_VAR + "\' environment variable: %lu\n", + timeout_ms); + + timeout_ms = CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS; + } + } + + return timeout_ms; +} + +static int wait_for_mc(bool booting_mc, u32 *final_reg_gsr) +{ + u32 reg_gsr; + u32 mc_fw_boot_status; + unsigned long timeout_ms = get_mc_boot_timeout_ms(); + struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR; + + dmb(); + debug("Polling mc_ccsr_regs->reg_gsr ...\n"); + assert(timeout_ms > 0); + for (;;) { + udelay(1000); /* throttle polling */ + reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr); + mc_fw_boot_status = (reg_gsr & GSR_FS_MASK); + if (mc_fw_boot_status & 0x1) + break; + + timeout_ms--; + if (timeout_ms == 0) + break; + } + + if (timeout_ms == 0) { + if (booting_mc) + printf("fsl-mc: timeout booting management complex firmware\n"); + else + printf("fsl-mc: timeout deploying data path layout\n"); + + /* TODO: Get an error status from an MC CCSR register */ + return -ETIMEDOUT; + } + + if (mc_fw_boot_status != 0x1) { + /* + * TODO: Identify critical errors from the GSR register's FS + * field and for those errors, set error to -ENODEV or other + * appropriate errno, so that the status property is set to + * failure in the fsl,dprc device tree node. + */ + if (booting_mc) { + printf("fsl-mc: WARNING: Firmware booted with error (GSR: %#x)\n", + reg_gsr); + } else { + printf("fsl-mc: WARNING: Data path layout deployed with error (GSR: %#x)\n", + reg_gsr); + } + } + + *final_reg_gsr = reg_gsr; + return 0; +} + +int mc_init(void) { int error = 0; - int timeout = 200000; + int portal_id = 0; struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR; u64 mc_ram_addr; - u64 mc_dpl_offset; u32 reg_gsr; - u32 mc_fw_boot_status; - void *dpl_fdt_hdr; - int dpl_size; + u32 reg_mcfbalr; +#ifndef CONFIG_SYS_LS_MC_FW_IN_DDR const void *raw_image_addr; size_t raw_image_size = 0; - struct fsl_mc_io mc_io; - int portal_id; +#endif struct mc_version mc_ver_info; + u64 mc_ram_aligned_base_addr; + u8 mc_ram_num_256mb_blocks; + size_t mc_ram_size = mc_get_dram_block_size(); /* * The MC private DRAM block was already carved at the end of DRAM @@ -112,6 +403,20 @@ int mc_init(bd_t *bis) gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size; } +#ifdef CONFIG_FSL_DEBUG_SERVER + /* + * FIXME: I don't think this is right. See get_dram_size_to_hide() + */ + mc_ram_addr -= debug_server_get_dram_block_size(); +#endif + + error = calculate_mc_private_ram_params(mc_ram_addr, + mc_ram_size, + &mc_ram_aligned_base_addr, + &mc_ram_num_256mb_blocks); + if (error != 0) + goto out; + /* * Management Complex cores should be held at reset out of POR. * U-boot should be the first software to touch MC. To be safe, @@ -127,6 +432,9 @@ int mc_init(bd_t *bis) out_le32(&mc_ccsr_regs->reg_gcr1, 0); dmb(); +#ifdef CONFIG_SYS_LS_MC_FW_IN_DDR + printf("MC firmware is preloaded to %#llx\n", mc_ram_addr); +#else error = parse_mc_firmware_fit_image(&raw_image_addr, &raw_image_size); if (error != 0) goto out; @@ -135,83 +443,34 @@ int mc_init(bd_t *bis) */ mc_copy_image("MC Firmware", (u64)raw_image_addr, raw_image_size, mc_ram_addr); - - /* - * Get address and size of the DPL blob stored in flash: - */ -#ifdef CONFIG_SYS_LS_MC_DPL_IN_NOR - dpl_fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPL_ADDR; -#else -#error "No CONFIG_SYS_LS_MC_DPL_IN_xxx defined" #endif + dump_ram_words("firmware", (void *)mc_ram_addr); - error = fdt_check_header(dpl_fdt_hdr); - if (error != 0) { - printf("fsl-mc: ERROR: Bad DPL image (bad header)\n"); - goto out; - } - - dpl_size = fdt_totalsize(dpl_fdt_hdr); - if (dpl_size > CONFIG_SYS_LS_MC_DPL_MAX_LENGTH) { - printf("fsl-mc: ERROR: Bad DPL image (too large: %d)\n", - dpl_size); - error = -EINVAL; + error = load_mc_dpc(mc_ram_addr, mc_ram_size); + if (error != 0) goto out; - } - /* - * Calculate offset in the MC private DRAM block at which the MC DPL - * blob is to be placed: - */ -#ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET - BUILD_BUG_ON((CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 || - CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff); - - mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET; -#else - mc_dpl_offset = mc_get_dram_block_size() - - roundup(CONFIG_SYS_LS_MC_DPL_MAX_LENGTH, 4096); - - if ((mc_dpl_offset & 0x3) != 0 || mc_dpl_offset > 0xffffffff) { - printf("%s: Invalid MC DPL offset: %llu\n", - __func__, mc_dpl_offset); - error = -EINVAL; + error = load_mc_dpl(mc_ram_addr, mc_ram_size); + if (error != 0) goto out; - } -#endif - - /* - * Load the MC DPL blob at the far end of the MC private DRAM block: - * - * TODO: Should we place the DPL at a different location to match - * assumptions of MC firmware about its memory layout? - */ - mc_copy_image("MC DPL blob", - (u64)dpl_fdt_hdr, dpl_size, mc_ram_addr + mc_dpl_offset); debug("mc_ccsr_regs %p\n", mc_ccsr_regs); + dump_mc_ccsr_regs(mc_ccsr_regs); /* - * Tell MC where the MC Firmware image was loaded in DDR: + * Tell MC what is the address range of the DRAM block assigned to it: */ - out_le32(&mc_ccsr_regs->reg_mcfbalr, (u32)mc_ram_addr); - out_le32(&mc_ccsr_regs->reg_mcfbahr, (u32)((u64)mc_ram_addr >> 32)); + reg_mcfbalr = (u32)mc_ram_aligned_base_addr | + (mc_ram_num_256mb_blocks - 1); + out_le32(&mc_ccsr_regs->reg_mcfbalr, reg_mcfbalr); + out_le32(&mc_ccsr_regs->reg_mcfbahr, + (u32)(mc_ram_aligned_base_addr >> 32)); out_le32(&mc_ccsr_regs->reg_mcfapr, MCFAPR_BYPASS_ICID_MASK); /* - * Tell MC where the DPL blob was loaded in DDR, by indicating - * its offset relative to the beginning of the DDR block - * allocated to the MC firmware. The MC firmware is responsible - * for checking that there is no overlap between the DPL blob - * and the runtime heap and stack of the MC firmware itself. - * - * NOTE: bits [31:2] of this offset need to be stored in bits [29:0] of - * the GSR MC CCSR register. So, this offset is assumed to be 4-byte - * aligned. - * Care must be taken not to write 1s into bits 31 and 30 of the GSR in - * this case as the SoC COP or PIC will be signaled. + * Tell the MC that we want delayed DPL deployment. */ - out_le32(&mc_ccsr_regs->reg_gsr, (u32)(mc_dpl_offset >> 2)); + out_le32(&mc_ccsr_regs->reg_gsr, 0xDD00); printf("\nfsl-mc: Booting Management Complex ...\n"); @@ -219,38 +478,9 @@ int mc_init(bd_t *bis) * Deassert reset and release MC core 0 to run */ out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST); - dmb(); - debug("Polling mc_ccsr_regs->reg_gsr ...\n"); - - for (;;) { - reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr); - mc_fw_boot_status = (reg_gsr & GSR_FS_MASK); - if (mc_fw_boot_status & 0x1) - break; - - udelay(1000); /* throttle polling */ - if (timeout-- <= 0) - break; - } - - if (timeout <= 0) { - printf("fsl-mc: timeout booting management complex firmware\n"); - - /* TODO: Get an error status from an MC CCSR register */ - error = -ETIMEDOUT; + error = wait_for_mc(true, ®_gsr); + if (error != 0) goto out; - } - - if (mc_fw_boot_status != 0x1) { - /* - * TODO: Identify critical errors from the GSR register's FS - * field and for those errors, set error to -ENODEV or other - * appropriate errno, so that the status property is set to - * failure in the fsl,dprc device tree node. - */ - printf("fsl-mc: WARNING: Firmware booted with error (GSR: %#x)\n", - reg_gsr); - } /* * TODO: need to obtain the portal_id for the root container from the @@ -259,13 +489,20 @@ int mc_init(bd_t *bis) portal_id = 0; /* - * Check that the MC firmware is responding portal commands: + * Initialize the global default MC portal + * And check that the MC firmware is responding portal commands: */ - mc_io.mmio_regs = SOC_MC_PORTAL_ADDR(portal_id); + dflt_mc_io = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io)); + if (!dflt_mc_io) { + printf(" No memory: malloc() failed\n"); + return -ENOMEM; + } + + dflt_mc_io->mmio_regs = SOC_MC_PORTAL_ADDR(portal_id); debug("Checking access to MC portal of root DPRC container (portal_id %d, portal physical addr %p)\n", - portal_id, mc_io.mmio_regs); + portal_id, dflt_mc_io->mmio_regs); - error = mc_get_version(&mc_io, &mc_ver_info); + error = mc_get_version(dflt_mc_io, &mc_ver_info); if (error != 0) { printf("fsl-mc: ERROR: Firmware version check failed (error: %d)\n", error); @@ -282,7 +519,16 @@ int mc_init(bd_t *bis) printf("fsl-mc: Management Complex booted (version: %d.%d.%d, boot status: %#x)\n", mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision, - mc_fw_boot_status); + reg_gsr & GSR_FS_MASK); + + /* + * Tell the MC to deploy the DPL: + */ + out_le32(&mc_ccsr_regs->reg_gsr, 0x0); + printf("\nfsl-mc: Deploying data path layout ...\n"); + error = wait_for_mc(false, ®_gsr); + if (error != 0) + goto out; out: if (error != 0) mc_boot_status = -error; @@ -299,12 +545,242 @@ int get_mc_boot_status(void) /** * Return the actual size of the MC private DRAM block. - * - * NOTE: For now this function always returns the minimum required size, - * However, in the future, the actual size may be obtained from an environment - * variable. */ unsigned long mc_get_dram_block_size(void) { - return CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE; + unsigned long dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE; + + char *dram_block_size_env_var = getenv(MC_MEM_SIZE_ENV_VAR); + + if (dram_block_size_env_var) { + dram_block_size = simple_strtoul(dram_block_size_env_var, NULL, + 10); + + if (dram_block_size < CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE) { + printf("fsl-mc: WARNING: Invalid value for \'" + MC_MEM_SIZE_ENV_VAR + "\' environment variable: %lu\n", + dram_block_size); + + dram_block_size = CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE; + } + } + + return dram_block_size; +} + +int dpio_init(struct dprc_obj_desc obj_desc) +{ + struct qbman_swp_desc p_des; + struct dpio_attr attr; + int err = 0; + + dflt_dpio = (struct fsl_dpio_obj *)malloc(sizeof(struct fsl_dpio_obj)); + if (!dflt_dpio) { + printf(" No memory: malloc() failed\n"); + return -ENOMEM; + } + + dflt_dpio->dpio_id = obj_desc.id; + + err = dpio_open(dflt_mc_io, obj_desc.id, &dflt_dpio_handle); + if (err) { + printf("dpio_open() failed\n"); + goto err_open; + } + + err = dpio_get_attributes(dflt_mc_io, dflt_dpio_handle, &attr); + if (err) { + printf("dpio_get_attributes() failed %d\n", err); + goto err_get_attr; + } + + err = dpio_enable(dflt_mc_io, dflt_dpio_handle); + if (err) { + printf("dpio_enable() failed %d\n", err); + goto err_get_enable; + } + debug("ce_paddr=0x%llx, ci_paddr=0x%llx, portalid=%d, prios=%d\n", + attr.qbman_portal_ce_paddr, + attr.qbman_portal_ci_paddr, + attr.qbman_portal_id, + attr.num_priorities); + + p_des.cena_bar = (void *)attr.qbman_portal_ce_paddr; + p_des.cinh_bar = (void *)attr.qbman_portal_ci_paddr; + + dflt_dpio->sw_portal = qbman_swp_init(&p_des); + if (dflt_dpio->sw_portal == NULL) { + printf("qbman_swp_init() failed\n"); + goto err_get_swp_init; + } + return 0; + +err_get_swp_init: +err_get_enable: + dpio_disable(dflt_mc_io, dflt_dpio_handle); +err_get_attr: + dpio_close(dflt_mc_io, dflt_dpio_handle); +err_open: + free(dflt_dpio); + return err; +} + +int dpbp_init(struct dprc_obj_desc obj_desc) +{ + dflt_dpbp = (struct fsl_dpbp_obj *)malloc(sizeof(struct fsl_dpbp_obj)); + if (!dflt_dpbp) { + printf(" No memory: malloc() failed\n"); + return -ENOMEM; + } + dflt_dpbp->dpbp_attr.id = obj_desc.id; + + return 0; +} + +int dprc_init_container_obj(struct dprc_obj_desc obj_desc, uint16_t dprc_handle) +{ + int error = 0, state = 0; + struct dprc_endpoint dpni_endpoint, dpmac_endpoint; + if (!strcmp(obj_desc.type, "dpbp")) { + if (!dflt_dpbp) { + error = dpbp_init(obj_desc); + if (error < 0) + printf("dpbp_init failed\n"); + } + } else if (!strcmp(obj_desc.type, "dpio")) { + if (!dflt_dpio) { + error = dpio_init(obj_desc); + if (error < 0) + printf("dpio_init failed\n"); + } + } else if (!strcmp(obj_desc.type, "dpni")) { + strcpy(dpni_endpoint.type, obj_desc.type); + dpni_endpoint.id = obj_desc.id; + error = dprc_get_connection(dflt_mc_io, dprc_handle, + &dpni_endpoint, &dpmac_endpoint, &state); + if (!strcmp(dpmac_endpoint.type, "dpmac")) + error = ldpaa_eth_init(obj_desc); + if (error < 0) + printf("ldpaa_eth_init failed\n"); + } + + return error; +} + +int dprc_scan_container_obj(uint16_t dprc_handle, char *obj_type, int i) +{ + int error = 0; + struct dprc_obj_desc obj_desc; + + memset((void *)&obj_desc, 0x00, sizeof(struct dprc_obj_desc)); + + error = dprc_get_obj(dflt_mc_io, dprc_handle, + i, &obj_desc); + if (error < 0) { + printf("dprc_get_obj(i=%d) failed: %d\n", + i, error); + return error; + } + + if (!strcmp(obj_desc.type, obj_type)) { + debug("Discovered object: type %s, id %d, req %s\n", + obj_desc.type, obj_desc.id, obj_type); + + error = dprc_init_container_obj(obj_desc, dprc_handle); + if (error < 0) { + printf("dprc_init_container_obj(i=%d) failed: %d\n", + i, error); + return error; + } + } + + return error; +} + +int fsl_mc_ldpaa_init(bd_t *bis) +{ + int i, error = 0; + int dprc_opened = 0, container_id; + int num_child_objects = 0; + + error = mc_init(); + if (error < 0) + goto error; + + error = dprc_get_container_id(dflt_mc_io, &container_id); + if (error < 0) { + printf("dprc_get_container_id() failed: %d\n", error); + goto error; + } + + debug("fsl-mc: Container id=0x%x\n", container_id); + + error = dprc_open(dflt_mc_io, container_id, &dflt_dprc_handle); + if (error < 0) { + printf("dprc_open() failed: %d\n", error); + goto error; + } + dprc_opened = true; + + error = dprc_get_obj_count(dflt_mc_io, + dflt_dprc_handle, + &num_child_objects); + if (error < 0) { + printf("dprc_get_obj_count() failed: %d\n", error); + goto error; + } + debug("Total child in container %d = %d\n", container_id, + num_child_objects); + + if (num_child_objects != 0) { + /* + * Discover objects currently in the DPRC container in the MC: + */ + for (i = 0; i < num_child_objects; i++) + error = dprc_scan_container_obj(dflt_dprc_handle, + "dpbp", i); + + for (i = 0; i < num_child_objects; i++) + error = dprc_scan_container_obj(dflt_dprc_handle, + "dpio", i); + + for (i = 0; i < num_child_objects; i++) + error = dprc_scan_container_obj(dflt_dprc_handle, + "dpni", i); + } +error: + if (dprc_opened) + dprc_close(dflt_mc_io, dflt_dprc_handle); + + return error; +} + +void fsl_mc_ldpaa_exit(bd_t *bis) +{ + int err; + + if (get_mc_boot_status() == 0) { + err = dpio_disable(dflt_mc_io, dflt_dpio_handle); + if (err < 0) { + printf("dpio_disable() failed: %d\n", err); + return; + } + err = dpio_reset(dflt_mc_io, dflt_dpio_handle); + if (err < 0) { + printf("dpio_reset() failed: %d\n", err); + return; + } + err = dpio_close(dflt_mc_io, dflt_dpio_handle); + if (err < 0) { + printf("dpio_close() failed: %d\n", err); + return; + } + + free(dflt_dpio); + free(dflt_dpbp); + } + + if (dflt_mc_io) + free(dflt_mc_io); } diff --git a/drivers/net/fsl-mc/mc_sys.c b/drivers/net/fsl-mc/mc_sys.c index 7c8e003..3fc1f98 100644 --- a/drivers/net/fsl-mc/mc_sys.c +++ b/drivers/net/fsl-mc/mc_sys.c @@ -1,7 +1,7 @@ /* * Freescale Layerscape MC I/O wrapper * - * Copyright (C) 2014 Freescale Semiconductor, Inc. + * Copyright (C) 2013-2015 Freescale Semiconductor, Inc. * Author: German Rivera <German.Rivera@freescale.com> * * SPDX-License-Identifier: GPL-2.0+ @@ -32,7 +32,7 @@ int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) { enum mc_cmd_status status; - int timeout = 2000; + int timeout = 6000; mc_write_command(mc_io->mmio_regs, cmd); @@ -52,7 +52,7 @@ int mc_send_command(struct fsl_mc_io *mc_io, if (status != MC_CMD_STATUS_OK) { printf("Error: MC command failed (portal: %p, obj handle: %#x, command: %#x, status: %#x)\n", mc_io->mmio_regs, - (unsigned int)MC_CMD_HDR_READ_AUTHID(cmd->header), + (unsigned int)MC_CMD_HDR_READ_TOKEN(cmd->header), (unsigned int)MC_CMD_HDR_READ_CMDID(cmd->header), (unsigned int)status); diff --git a/drivers/net/ldpaa_eth/Makefile b/drivers/net/ldpaa_eth/Makefile new file mode 100644 index 0000000..c37633f --- /dev/null +++ b/drivers/net/ldpaa_eth/Makefile @@ -0,0 +1,9 @@ +# +# Copyright 2014 Freescale Semiconductor, Inc. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += ldpaa_wriop.o +obj-y += ldpaa_eth.o +obj-$(CONFIG_LS2085A) += ls2085a.o diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c new file mode 100644 index 0000000..d4be1ba --- /dev/null +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -0,0 +1,710 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/types.h> +#include <malloc.h> +#include <net.h> +#include <hwconfig.h> +#include <phy.h> +#include <linux/compat.h> + +#include "ldpaa_eth.h" + +#undef CONFIG_PHYLIB +static int init_phy(struct eth_device *dev) +{ + /*TODO for external PHY */ + + return 0; +} + +static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv, + const struct dpaa_fd *fd) +{ + u64 fd_addr; + uint16_t fd_offset; + uint32_t fd_length; + struct ldpaa_fas *fas; + uint32_t status, err; + struct qbman_release_desc releasedesc; + struct qbman_swp *swp = dflt_dpio->sw_portal; + + fd_addr = ldpaa_fd_get_addr(fd); + fd_offset = ldpaa_fd_get_offset(fd); + fd_length = ldpaa_fd_get_len(fd); + + debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length); + + if (fd->simple.frc & LDPAA_FD_FRC_FASV) { + /* Read the frame annotation status word and check for errors */ + fas = (struct ldpaa_fas *) + ((uint8_t *)(fd_addr) + + priv->buf_layout.private_data_size); + status = le32_to_cpu(fas->status); + if (status & LDPAA_ETH_RX_ERR_MASK) { + printf("Rx frame error(s): 0x%08x\n", + status & LDPAA_ETH_RX_ERR_MASK); + goto error; + } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) { + printf("Unsupported feature in bitmask: 0x%08x\n", + status & LDPAA_ETH_RX_UNSUPP_MASK); + goto error; + } + } + + debug("Rx frame: To Upper layer\n"); + net_process_received_packet((uint8_t *)(fd_addr) + fd_offset, + fd_length); + +error: + flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE); + qbman_release_desc_clear(&releasedesc); + qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid); + do { + /* Release buffer into the QBMAN */ + err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1); + } while (err == -EBUSY); + return; +} + +static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev) +{ + struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv; + const struct ldpaa_dq *dq; + const struct dpaa_fd *fd; + int i = 5, err = 0, status, loop = 20; + static struct qbman_pull_desc pulldesc; + struct qbman_swp *swp = dflt_dpio->sw_portal; + + while (--i) { + qbman_pull_desc_clear(&pulldesc); + qbman_pull_desc_set_numframes(&pulldesc, 1); + qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid); + + err = qbman_swp_pull(swp, &pulldesc); + if (err < 0) { + printf("Dequeue frames error:0x%08x\n", err); + continue; + } + + do { + loop--; + dq = qbman_swp_dqrr_next(swp); + + if (!loop) + break; + } while (!dq); + + if (dq) { + /* Check for valid frame. If not sent a consume + * confirmation to QBMAN otherwise give it to NADK + * application and then send consume confirmation to + * QBMAN. + */ + status = (uint8_t)ldpaa_dq_flags(dq); + if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) { + debug("Dequeue RX frames:"); + debug("No frame delivered\n"); + + qbman_swp_dqrr_consume(swp, dq); + break; + } + + fd = ldpaa_dq_fd(dq); + + /* Obtain FD and process it */ + ldpaa_eth_rx(priv, fd); + qbman_swp_dqrr_consume(swp, dq); + break; + } + } + + return err; +} + +static void ldpaa_eth_tx_conf(struct ldpaa_eth_priv *priv, + const struct dpaa_fd *fd) +{ + uint64_t fd_addr; + struct ldpaa_fas *fas; + uint32_t status, err; + struct qbman_release_desc releasedesc; + struct qbman_swp *swp = dflt_dpio->sw_portal; + + fd_addr = ldpaa_fd_get_addr(fd); + + + debug("TX Conf frame:data addr=0x%p\n", (u64 *)fd_addr); + + /* Check the status from the Frame Annotation */ + if (fd->simple.frc & LDPAA_FD_FRC_FASV) { + fas = (struct ldpaa_fas *) + ((uint8_t *)(fd_addr) + + priv->buf_layout.private_data_size); + status = le32_to_cpu(fas->status); + if (status & LDPAA_ETH_TXCONF_ERR_MASK) { + printf("TxConf frame error(s): 0x%08x\n", + status & LDPAA_ETH_TXCONF_ERR_MASK); + } + } + + qbman_release_desc_clear(&releasedesc); + qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid); + do { + /* Release buffer into the QBMAN */ + err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1); + } while (err == -EBUSY); +} + +static int ldpaa_eth_pull_dequeue_tx_conf(struct ldpaa_eth_priv *priv) +{ + const struct ldpaa_dq *dq; + const struct dpaa_fd *fd; + int err = 0; + int i = 5, status, loop = 20; + static struct qbman_pull_desc pulldesc; + struct qbman_swp *swp = dflt_dpio->sw_portal; + + while (--i) { + qbman_pull_desc_clear(&pulldesc); + qbman_pull_desc_set_numframes(&pulldesc, 1); + qbman_pull_desc_set_fq(&pulldesc, priv->tx_conf_fqid); + + err = qbman_swp_pull(swp, &pulldesc); + if (err < 0) { + printf("Dequeue TX conf frames error:0x%08x\n", err); + continue; + } + + do { + loop--; + dq = qbman_swp_dqrr_next(swp); + + if (!loop) + break; + } while (!dq); + + if (dq) { + /* Check for valid frame. If not sent a consume + * confirmation to QBMAN otherwise give it to NADK + * application and then send consume confirmation to + * QBMAN. + */ + status = (uint8_t)ldpaa_dq_flags(dq); + if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) { + debug("Dequeue TX conf frames:"); + debug("No frame is delivered\n"); + + qbman_swp_dqrr_consume(swp, dq); + break; + } + fd = ldpaa_dq_fd(dq); + + ldpaa_eth_tx_conf(priv, fd); + qbman_swp_dqrr_consume(swp, dq); + break; + } + } + + return err; +} + +static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len) +{ + struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; + struct dpaa_fd fd; + u64 buffer_start; + int data_offset, err; + struct qbman_swp *swp = dflt_dpio->sw_portal; + struct qbman_eq_desc ed; + + /* Setup the FD fields */ + memset(&fd, 0, sizeof(fd)); + + data_offset = priv->tx_data_offset; + + do { + err = qbman_swp_acquire(dflt_dpio->sw_portal, + dflt_dpbp->dpbp_attr.bpid, + &buffer_start, 1); + } while (err == -EBUSY); + + if (err < 0) { + printf("qbman_swp_acquire() failed\n"); + return -ENOMEM; + } + + debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start); + + memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len); + + flush_dcache_range(buffer_start, buffer_start + + LDPAA_ETH_RX_BUFFER_SIZE); + + ldpaa_fd_set_addr(&fd, (u64)buffer_start); + ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset)); + ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid); + ldpaa_fd_set_len(&fd, len); + + fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA | + LDPAA_FD_CTRL_PTV1; + + qbman_eq_desc_clear(&ed); + qbman_eq_desc_set_no_orp(&ed, 0); + qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0); + err = qbman_swp_enqueue(swp, &ed, (const struct qbman_fd *)(&fd)); + if (err < 0) + printf("error enqueueing Tx frame\n"); + + mdelay(1); + + err = ldpaa_eth_pull_dequeue_tx_conf(priv); + if (err < 0) + printf("error Tx Conf frame\n"); + + return err; +} + +static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) +{ + struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; + struct dpni_queue_attr rx_queue_attr; + struct dpni_tx_flow_attr tx_flow_attr; + uint8_t mac_addr[6]; + int err; + + if (net_dev->state == ETH_STATE_ACTIVE) + return 0; + + /* DPNI initialization */ + err = ldpaa_dpni_setup(priv); + if (err < 0) + goto err_dpni_setup; + + err = ldpaa_dpbp_setup(); + if (err < 0) + goto err_dpbp_setup; + + /* DPNI binding DPBP */ + err = ldpaa_dpni_bind(priv); + if (err) + goto err_bind; + + err = dpni_get_primary_mac_addr(dflt_mc_io, priv->dpni_handle, + mac_addr); + if (err) { + printf("dpni_get_primary_mac_addr() failed\n"); + return err; + } + + memcpy(net_dev->enetaddr, mac_addr, 0x6); + + /* setup the MAC address */ + if (net_dev->enetaddr[0] & 0x01) { + printf("%s: MacAddress is multcast address\n", __func__); + return 1; + } + +#ifdef CONFIG_PHYLIB + /* TODO Check this path */ + err = phy_startup(priv->phydev); + if (err) { + printf("%s: Could not initialize\n", priv->phydev->dev->name); + return err; + } +#else + priv->phydev->speed = SPEED_1000; + priv->phydev->link = 1; + priv->phydev->duplex = DUPLEX_FULL; +#endif + + err = dpni_enable(dflt_mc_io, priv->dpni_handle); + if (err < 0) { + printf("dpni_enable() failed\n"); + return err; + } + + /* TODO: support multiple Rx flows */ + err = dpni_get_rx_flow(dflt_mc_io, priv->dpni_handle, 0, 0, + &rx_queue_attr); + if (err) { + printf("dpni_get_rx_flow() failed\n"); + goto err_rx_flow; + } + + priv->rx_dflt_fqid = rx_queue_attr.fqid; + + err = dpni_get_qdid(dflt_mc_io, priv->dpni_handle, &priv->tx_qdid); + if (err) { + printf("dpni_get_qdid() failed\n"); + goto err_qdid; + } + + err = dpni_get_tx_flow(dflt_mc_io, priv->dpni_handle, priv->tx_flow_id, + &tx_flow_attr); + if (err) { + printf("dpni_get_tx_flow() failed\n"); + goto err_tx_flow; + } + + priv->tx_conf_fqid = tx_flow_attr.conf_err_attr.queue_attr.fqid; + + if (!priv->phydev->link) + printf("%s: No link.\n", priv->phydev->dev->name); + + return priv->phydev->link ? 0 : -1; + +err_tx_flow: +err_qdid: +err_rx_flow: + dpni_disable(dflt_mc_io, priv->dpni_handle); +err_bind: + ldpaa_dpbp_free(); +err_dpbp_setup: + dpni_close(dflt_mc_io, priv->dpni_handle); +err_dpni_setup: + return err; +} + +static void ldpaa_eth_stop(struct eth_device *net_dev) +{ + struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; + int err = 0; + + if ((net_dev->state == ETH_STATE_PASSIVE) || + (net_dev->state == ETH_STATE_INIT)) + return; + /* Stop Tx and Rx traffic */ + err = dpni_disable(dflt_mc_io, priv->dpni_handle); + if (err < 0) + printf("dpni_disable() failed\n"); + +#ifdef CONFIG_PHYLIB + phy_shutdown(priv->phydev); +#endif + + ldpaa_dpbp_free(); + dpni_reset(dflt_mc_io, priv->dpni_handle); + dpni_close(dflt_mc_io, priv->dpni_handle); +} + +static void ldpaa_dpbp_drain_cnt(int count) +{ + uint64_t buf_array[7]; + void *addr; + int ret, i; + + BUG_ON(count > 7); + + do { + ret = qbman_swp_acquire(dflt_dpio->sw_portal, + dflt_dpbp->dpbp_attr.bpid, + buf_array, count); + if (ret < 0) { + printf("qbman_swp_acquire() failed\n"); + return; + } + for (i = 0; i < ret; i++) { + addr = (void *)buf_array[i]; + debug("Free: buffer addr =0x%p\n", addr); + free(addr); + } + } while (ret); +} + +static void ldpaa_dpbp_drain(void) +{ + int i; + for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) + ldpaa_dpbp_drain_cnt(7); +} + +static int ldpaa_bp_add_7(uint16_t bpid) +{ + uint64_t buf_array[7]; + u8 *addr; + int i; + struct qbman_release_desc rd; + + for (i = 0; i < 7; i++) { + addr = memalign(L1_CACHE_BYTES, LDPAA_ETH_RX_BUFFER_SIZE); + if (!addr) { + printf("addr allocation failed\n"); + goto err_alloc; + } + memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE); + flush_dcache_range((u64)addr, + (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE)); + + buf_array[i] = (uint64_t)addr; + debug("Release: buffer addr =0x%p\n", addr); + } + +release_bufs: + /* In case the portal is busy, retry until successful. + * This function is guaranteed to succeed in a reasonable amount + * of time. + */ + + do { + mdelay(1); + qbman_release_desc_clear(&rd); + qbman_release_desc_set_bpid(&rd, bpid); + } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i)); + + return i; + +err_alloc: + if (i) + goto release_bufs; + + return 0; +} + +static int ldpaa_dpbp_seed(uint16_t bpid) +{ + int i; + int count; + + for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) { + count = ldpaa_bp_add_7(bpid); + if (count < 7) + printf("Buffer Seed= %d\n", count); + } + + return 0; +} + +static int ldpaa_dpbp_setup(void) +{ + int err; + + err = dpbp_open(dflt_mc_io, dflt_dpbp->dpbp_attr.id, + &dflt_dpbp->dpbp_handle); + if (err) { + printf("dpbp_open() failed\n"); + goto err_open; + } + + err = dpbp_enable(dflt_mc_io, dflt_dpbp->dpbp_handle); + if (err) { + printf("dpbp_enable() failed\n"); + goto err_enable; + } + + err = dpbp_get_attributes(dflt_mc_io, dflt_dpbp->dpbp_handle, + &dflt_dpbp->dpbp_attr); + if (err) { + printf("dpbp_get_attributes() failed\n"); + goto err_get_attr; + } + + err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid); + if (err) { + printf("Buffer seeding failed for DPBP %d (bpid=%d)\n", + dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid); + goto err_seed; + } + + return 0; + +err_seed: +err_get_attr: + dpbp_disable(dflt_mc_io, dflt_dpbp->dpbp_handle); +err_enable: + dpbp_close(dflt_mc_io, dflt_dpbp->dpbp_handle); +err_open: + return err; +} + +static void ldpaa_dpbp_free(void) +{ + ldpaa_dpbp_drain(); + dpbp_disable(dflt_mc_io, dflt_dpbp->dpbp_handle); + dpbp_reset(dflt_mc_io, dflt_dpbp->dpbp_handle); + dpbp_close(dflt_mc_io, dflt_dpbp->dpbp_handle); +} + +static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv) +{ + int err; + + /* and get a handle for the DPNI this interface is associate with */ + err = dpni_open(dflt_mc_io, priv->dpni_id, &priv->dpni_handle); + if (err) { + printf("dpni_open() failed\n"); + goto err_open; + } + + err = dpni_get_attributes(dflt_mc_io, priv->dpni_handle, + &priv->dpni_attrs); + if (err) { + printf("dpni_get_attributes() failed (err=%d)\n", err); + goto err_get_attr; + } + + /* Configure our buffers' layout */ + priv->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT | + DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | + DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; + priv->buf_layout.pass_parser_result = true; + priv->buf_layout.pass_frame_status = true; + priv->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE; + /* ...rx, ... */ + err = dpni_set_rx_buffer_layout(dflt_mc_io, priv->dpni_handle, + &priv->buf_layout); + if (err) { + printf("dpni_set_rx_buffer_layout() failed"); + goto err_buf_layout; + } + + /* ... tx, ... */ + priv->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PARSER_RESULT; + err = dpni_set_tx_buffer_layout(dflt_mc_io, priv->dpni_handle, + &priv->buf_layout); + if (err) { + printf("dpni_set_tx_buffer_layout() failed"); + goto err_buf_layout; + } + + /* ... tx-confirm. */ + priv->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; + err = dpni_set_tx_conf_buffer_layout(dflt_mc_io, priv->dpni_handle, + &priv->buf_layout); + if (err) { + printf("dpni_set_tx_conf_buffer_layout() failed"); + goto err_buf_layout; + } + + /* Now that we've set our tx buffer layout, retrieve the minimum + * required tx data offset. + */ + err = dpni_get_tx_data_offset(dflt_mc_io, priv->dpni_handle, + &priv->tx_data_offset); + if (err) { + printf("dpni_get_tx_data_offset() failed\n"); + goto err_data_offset; + } + + /* Warn in case TX data offset is not multiple of 64 bytes. */ + WARN_ON(priv->tx_data_offset % 64); + + /* Accomodate SWA space. */ + priv->tx_data_offset += LDPAA_ETH_SWA_SIZE; + debug("priv->tx_data_offset=%d\n", priv->tx_data_offset); + + return 0; + +err_data_offset: +err_buf_layout: +err_get_attr: + dpni_close(dflt_mc_io, priv->dpni_handle); +err_open: + return err; +} + +static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv) +{ + struct dpni_pools_cfg pools_params; + struct dpni_tx_flow_cfg dflt_tx_flow; + int err = 0; + + pools_params.num_dpbp = 1; + pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id; + pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE; + err = dpni_set_pools(dflt_mc_io, priv->dpni_handle, &pools_params); + if (err) { + printf("dpni_set_pools() failed\n"); + return err; + } + + priv->tx_flow_id = DPNI_NEW_FLOW_ID; + memset(&dflt_tx_flow, 0, sizeof(dflt_tx_flow)); + + err = dpni_set_tx_flow(dflt_mc_io, priv->dpni_handle, + &priv->tx_flow_id, &dflt_tx_flow); + if (err) { + printf("dpni_set_tx_flow() failed\n"); + return err; + } + + return 0; +} + +static int ldpaa_eth_netdev_init(struct eth_device *net_dev) +{ + int err; + struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; + + sprintf(net_dev->name, "DPNI%d", priv->dpni_id); + + net_dev->iobase = 0; + net_dev->init = ldpaa_eth_open; + net_dev->halt = ldpaa_eth_stop; + net_dev->send = ldpaa_eth_tx; + net_dev->recv = ldpaa_eth_pull_dequeue_rx; +/* + TODO: PHY MDIO information + priv->bus = info->bus; + priv->phyaddr = info->phy_addr; + priv->enet_if = info->enet_if; +*/ + + if (init_phy(net_dev)) + return 0; + + err = eth_register(net_dev); + if (err < 0) { + printf("eth_register() = %d\n", err); + return err; + } + + return 0; +} + +int ldpaa_eth_init(struct dprc_obj_desc obj_desc) +{ + struct eth_device *net_dev = NULL; + struct ldpaa_eth_priv *priv = NULL; + int err = 0; + + + /* Net device */ + net_dev = (struct eth_device *)malloc(sizeof(struct eth_device)); + if (!net_dev) { + printf("eth_device malloc() failed\n"); + return -ENOMEM; + } + memset(net_dev, 0, sizeof(struct eth_device)); + + /* alloc the ldpaa ethernet private struct */ + priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv)); + if (!priv) { + printf("ldpaa_eth_priv malloc() failed\n"); + return -ENOMEM; + } + memset(priv, 0, sizeof(struct ldpaa_eth_priv)); + + net_dev->priv = (void *)priv; + priv->net_dev = (struct eth_device *)net_dev; + priv->dpni_id = obj_desc.id; + + err = ldpaa_eth_netdev_init(net_dev); + if (err) + goto err_netdev_init; + + debug("ldpaa ethernet: Probed interface %s\n", net_dev->name); + return 0; + +err_netdev_init: + free(priv); + net_dev->priv = NULL; + free(net_dev); + + return err; +} diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.h b/drivers/net/ldpaa_eth/ldpaa_eth.h new file mode 100644 index 0000000..3107ab6 --- /dev/null +++ b/drivers/net/ldpaa_eth/ldpaa_eth.h @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __LDPAA_ETH_H +#define __LDPAA_ETH_H + +#include <linux/netdevice.h> +#include <fsl-mc/fsl_mc.h> +#include <fsl-mc/fsl_dpaa_fd.h> +#include <fsl-mc/fsl_dprc.h> +#include <fsl-mc/fsl_dpni.h> +#include <fsl-mc/fsl_dpbp.h> +#include <fsl-mc/fsl_dpio.h> +#include <fsl-mc/fsl_qbman_portal.h> +#include <fsl-mc/fsl_mc_private.h> + + +enum ldpaa_eth_type { + LDPAA_ETH_1G_E, + LDPAA_ETH_10G_E, +}; + +/* Arbitrary values for now, but we'll need to tune */ +#define LDPAA_ETH_NUM_BUFS (2 * 7) +#define LDPAA_ETH_REFILL_THRESH (LDPAA_ETH_NUM_BUFS/2) +#define LDPAA_ETH_RX_BUFFER_SIZE 2048 + +/* Hardware requires alignment for ingress/egress buffer addresses + * and ingress buffer lengths. + */ +#define LDPAA_ETH_BUF_ALIGN 64 + +/* So far we're only accomodating a skb backpointer in the frame's + * software annotation, but the hardware options are either 0 or 64. + */ +#define LDPAA_ETH_SWA_SIZE 64 + +/* Annotation valid bits in FD FRC */ +#define LDPAA_FD_FRC_FASV 0x8000 +#define LDPAA_FD_FRC_FAEADV 0x4000 +#define LDPAA_FD_FRC_FAPRV 0x2000 +#define LDPAA_FD_FRC_FAIADV 0x1000 +#define LDPAA_FD_FRC_FASWOV 0x0800 +#define LDPAA_FD_FRC_FAICFDV 0x0400 + +/* Annotation bits in FD CTRL */ +#define LDPAA_FD_CTRL_ASAL 0x00020000 /* ASAL = 128 */ +#define LDPAA_FD_CTRL_PTA 0x00800000 +#define LDPAA_FD_CTRL_PTV1 0x00400000 + +/* TODO: we may want to move this and other WRIOP related defines + * to a separate header + */ +/* Frame annotation status */ +struct ldpaa_fas { + u8 reserved; + u8 ppid; + __le16 ifpid; + __le32 status; +} __packed; + +/* Debug frame, otherwise supposed to be discarded */ +#define LDPAA_ETH_FAS_DISC 0x80000000 +/* MACSEC frame */ +#define LDPAA_ETH_FAS_MS 0x40000000 +#define LDPAA_ETH_FAS_PTP 0x08000000 +/* Ethernet multicast frame */ +#define LDPAA_ETH_FAS_MC 0x04000000 +/* Ethernet broadcast frame */ +#define LDPAA_ETH_FAS_BC 0x02000000 +#define LDPAA_ETH_FAS_KSE 0x00040000 +#define LDPAA_ETH_FAS_EOFHE 0x00020000 +#define LDPAA_ETH_FAS_MNLE 0x00010000 +#define LDPAA_ETH_FAS_TIDE 0x00008000 +#define LDPAA_ETH_FAS_PIEE 0x00004000 +/* Frame length error */ +#define LDPAA_ETH_FAS_FLE 0x00002000 +/* Frame physical error; our favourite pastime */ +#define LDPAA_ETH_FAS_FPE 0x00001000 +#define LDPAA_ETH_FAS_PTE 0x00000080 +#define LDPAA_ETH_FAS_ISP 0x00000040 +#define LDPAA_ETH_FAS_PHE 0x00000020 +#define LDPAA_ETH_FAS_BLE 0x00000010 +/* L3 csum validation performed */ +#define LDPAA_ETH_FAS_L3CV 0x00000008 +/* L3 csum error */ +#define LDPAA_ETH_FAS_L3CE 0x00000004 +/* L4 csum validation performed */ +#define LDPAA_ETH_FAS_L4CV 0x00000002 +/* L4 csum error */ +#define LDPAA_ETH_FAS_L4CE 0x00000001 +/* These bits always signal errors */ +#define LDPAA_ETH_RX_ERR_MASK (LDPAA_ETH_FAS_DISC | \ + LDPAA_ETH_FAS_KSE | \ + LDPAA_ETH_FAS_EOFHE | \ + LDPAA_ETH_FAS_MNLE | \ + LDPAA_ETH_FAS_TIDE | \ + LDPAA_ETH_FAS_PIEE | \ + LDPAA_ETH_FAS_FLE | \ + LDPAA_ETH_FAS_FPE | \ + LDPAA_ETH_FAS_PTE | \ + LDPAA_ETH_FAS_ISP | \ + LDPAA_ETH_FAS_PHE | \ + LDPAA_ETH_FAS_BLE | \ + LDPAA_ETH_FAS_L3CE | \ + LDPAA_ETH_FAS_L4CE) +/* Unsupported features in the ingress */ +#define LDPAA_ETH_RX_UNSUPP_MASK LDPAA_ETH_FAS_MS +/* TODO trim down the bitmask; not all of them apply to Tx-confirm */ +#define LDPAA_ETH_TXCONF_ERR_MASK (LDPAA_ETH_FAS_KSE | \ + LDPAA_ETH_FAS_EOFHE | \ + LDPAA_ETH_FAS_MNLE | \ + LDPAA_ETH_FAS_TIDE) + +struct ldpaa_eth_priv { + struct eth_device *net_dev; + int dpni_id; + uint16_t dpni_handle; + struct dpni_attr dpni_attrs; + /* Insofar as the MC is concerned, we're using one layout on all 3 types + * of buffers (Rx, Tx, Tx-Conf). + */ + struct dpni_buffer_layout buf_layout; + uint16_t tx_data_offset; + + uint32_t rx_dflt_fqid; + uint16_t tx_qdid; + uint32_t tx_conf_fqid; + uint16_t tx_flow_id; + + enum ldpaa_eth_type type; /* 1G or 10G ethernet */ + struct phy_device *phydev; +}; + +extern struct fsl_mc_io *dflt_mc_io; +extern struct fsl_dpbp_obj *dflt_dpbp; +extern struct fsl_dpio_obj *dflt_dpio; + +static void ldpaa_dpbp_drain_cnt(int count); +static void ldpaa_dpbp_drain(void); +static int ldpaa_dpbp_seed(uint16_t bpid); +static void ldpaa_dpbp_free(void); +static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv); +static int ldpaa_dpbp_setup(void); +static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv); +#endif /* __LDPAA_H */ diff --git a/drivers/net/ldpaa_eth/ldpaa_wriop.c b/drivers/net/ldpaa_eth/ldpaa_wriop.c new file mode 100644 index 0000000..926057a --- /dev/null +++ b/drivers/net/ldpaa_eth/ldpaa_wriop.c @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2015 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/types.h> +#include <malloc.h> +#include <net.h> +#include <linux/compat.h> +#include <asm/arch/fsl_serdes.h> +#include <fsl-mc/ldpaa_wriop.h> + +struct wriop_dpmac_info dpmac_info[NUM_WRIOP_PORTS]; + +__weak phy_interface_t wriop_dpmac_enet_if(int dpmac_id, int lane_prtc) +{ + return PHY_INTERFACE_MODE_NONE; +} + +void wriop_init_dpmac(int sd, int dpmac_id, int lane_prtcl) +{ + phy_interface_t enet_if; + int index = dpmac_id + sd * 8; + + dpmac_info[index].enabled = 0; + dpmac_info[index].id = 0; + dpmac_info[index].enet_if = PHY_INTERFACE_MODE_NONE; + + enet_if = wriop_dpmac_enet_if(index, lane_prtcl); + if (enet_if != PHY_INTERFACE_MODE_NONE) { + dpmac_info[index].enabled = 1; + dpmac_info[index].id = index; + dpmac_info[index].enet_if = enet_if; + } +} + +/*TODO what it do */ +static int wriop_dpmac_to_index(int dpmac_id) +{ + int i; + + for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) { + if (dpmac_info[i].id == dpmac_id) + return i; + } + + return -1; +} + +void wriop_disable_dpmac(int dpmac_id) +{ + int i = wriop_dpmac_to_index(dpmac_id); + + if (i == -1) + return; + + dpmac_info[i].enabled = 0; + wriop_dpmac_disable(dpmac_id); +} + +void wriop_enable_dpmac(int dpmac_id) +{ + int i = wriop_dpmac_to_index(dpmac_id); + + if (i == -1) + return; + + dpmac_info[i].enabled = 1; + wriop_dpmac_enable(dpmac_id); +} + +void wriop_set_mdio(int dpmac_id, struct mii_dev *bus) +{ + int i = wriop_dpmac_to_index(dpmac_id); + + if (i == -1) + return; + + dpmac_info[i].bus = bus; +} + +struct mii_dev *wriop_get_mdio(int dpmac_id) +{ + int i = wriop_dpmac_to_index(dpmac_id); + + if (i == -1) + return NULL; + + return dpmac_info[i].bus; +} + +void wriop_set_phy_address(int dpmac_id, int address) +{ + int i = wriop_dpmac_to_index(dpmac_id); + + if (i == -1) + return; + + dpmac_info[i].phy_addr = address; +} + +int wriop_get_phy_address(int dpmac_id) +{ + int i = wriop_dpmac_to_index(dpmac_id); + + if (i == -1) + return -1; + + return dpmac_info[i].phy_addr; +} + +void wriop_set_phy_dev(int dpmac_id, struct phy_device *phydev) +{ + int i = wriop_dpmac_to_index(dpmac_id); + + if (i == -1) + return; + + dpmac_info[i].phydev = phydev; +} + +struct phy_device *wriop_get_phy_dev(int dpmac_id) +{ + int i = wriop_dpmac_to_index(dpmac_id); + + if (i == -1) + return NULL; + + return dpmac_info[i].phydev; +} + +phy_interface_t wriop_get_enet_if(int dpmac_id) +{ + int i = wriop_dpmac_to_index(dpmac_id); + + if (i == -1) + return PHY_INTERFACE_MODE_NONE; + + if (dpmac_info[i].enabled) + return dpmac_info[i].enet_if; + + return PHY_INTERFACE_MODE_NONE; +} diff --git a/drivers/net/ldpaa_eth/ls2085a.c b/drivers/net/ldpaa_eth/ls2085a.c new file mode 100644 index 0000000..6b7960a --- /dev/null +++ b/drivers/net/ldpaa_eth/ls2085a.c @@ -0,0 +1,83 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <phy.h> +#include <fsl-mc/ldpaa_wriop.h> +#include <asm/io.h> +#include <asm/arch-fsl-lsch3/immap_lsch3.h> +#include <asm/arch/fsl_serdes.h> +#include <fsl-mc/ldpaa_wriop.h> + +u32 dpmac_to_devdisr[] = { + [WRIOP1_DPMAC1] = FSL_CHASSIS3_DEVDISR2_DPMAC1, + [WRIOP1_DPMAC2] = FSL_CHASSIS3_DEVDISR2_DPMAC2, + [WRIOP1_DPMAC3] = FSL_CHASSIS3_DEVDISR2_DPMAC3, + [WRIOP1_DPMAC4] = FSL_CHASSIS3_DEVDISR2_DPMAC4, + [WRIOP1_DPMAC5] = FSL_CHASSIS3_DEVDISR2_DPMAC5, + [WRIOP1_DPMAC6] = FSL_CHASSIS3_DEVDISR2_DPMAC6, + [WRIOP1_DPMAC7] = FSL_CHASSIS3_DEVDISR2_DPMAC7, + [WRIOP1_DPMAC8] = FSL_CHASSIS3_DEVDISR2_DPMAC8, + [WRIOP1_DPMAC9] = FSL_CHASSIS3_DEVDISR2_DPMAC9, + [WRIOP1_DPMAC10] = FSL_CHASSIS3_DEVDISR2_DPMAC10, + [WRIOP1_DPMAC11] = FSL_CHASSIS3_DEVDISR2_DPMAC11, + [WRIOP1_DPMAC12] = FSL_CHASSIS3_DEVDISR2_DPMAC12, + [WRIOP1_DPMAC13] = FSL_CHASSIS3_DEVDISR2_DPMAC13, + [WRIOP1_DPMAC14] = FSL_CHASSIS3_DEVDISR2_DPMAC14, + [WRIOP1_DPMAC15] = FSL_CHASSIS3_DEVDISR2_DPMAC15, + [WRIOP1_DPMAC16] = FSL_CHASSIS3_DEVDISR2_DPMAC16, + [WRIOP1_DPMAC17] = FSL_CHASSIS3_DEVDISR2_DPMAC17, + [WRIOP1_DPMAC18] = FSL_CHASSIS3_DEVDISR2_DPMAC18, + [WRIOP1_DPMAC19] = FSL_CHASSIS3_DEVDISR2_DPMAC19, + [WRIOP1_DPMAC20] = FSL_CHASSIS3_DEVDISR2_DPMAC20, + [WRIOP1_DPMAC21] = FSL_CHASSIS3_DEVDISR2_DPMAC21, + [WRIOP1_DPMAC22] = FSL_CHASSIS3_DEVDISR2_DPMAC22, + [WRIOP1_DPMAC23] = FSL_CHASSIS3_DEVDISR2_DPMAC23, + [WRIOP1_DPMAC24] = FSL_CHASSIS3_DEVDISR2_DPMAC24, +}; + +static int is_device_disabled(int dpmac_id) +{ + struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; + u32 devdisr2 = in_le32(&gur->devdisr2); + + return dpmac_to_devdisr[dpmac_id] & devdisr2; +} + +void wriop_dpmac_disable(int dpmac_id) +{ + struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; + + setbits_le32(&gur->devdisr2, dpmac_to_devdisr[dpmac_id]); +} + +void wriop_dpmac_enable(int dpmac_id) +{ + struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; + + clrbits_le32(&gur->devdisr2, dpmac_to_devdisr[dpmac_id]); +} + +phy_interface_t wriop_dpmac_enet_if(int dpmac_id, int lane_prtcl) +{ + enum srds_prtcl; + + if (is_device_disabled(dpmac_id + 1)) + return PHY_INTERFACE_MODE_NONE; + + if (lane_prtcl >= SGMII1 && lane_prtcl <= SGMII16) + return PHY_INTERFACE_MODE_SGMII; + + if (lane_prtcl >= XFI1 && lane_prtcl <= XFI8) + return PHY_INTERFACE_MODE_XGMII; + + if (lane_prtcl >= XAUI1 && lane_prtcl <= XAUI2) + return PHY_INTERFACE_MODE_XGMII; + + if (lane_prtcl >= QSGMII_A && lane_prtcl <= QSGMII_D) + return PHY_INTERFACE_MODE_QSGMII; + + return PHY_INTERFACE_MODE_NONE; +} diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c index 254f056..3a2b3bb 100644 --- a/drivers/net/phy/cortina.c +++ b/drivers/net/phy/cortina.c @@ -186,8 +186,8 @@ void cs4340_upload_firmware(struct phy_device *phydev) while (*addr != 0x0a) { line_temp[i++] = *addr++; if (0x50 < i) { - printf("Not found Cortina PHY ucode at 0x%x\n", - CONFIG_CORTINA_FW_ADDR); + printf("Not found Cortina PHY ucode at 0x%p\n", + (char *)CONFIG_CORTINA_FW_ADDR); return; } } diff --git a/drivers/net/vsc9953.c b/drivers/net/vsc9953.c index 9fc3c18..fed7358 100644 --- a/drivers/net/vsc9953.c +++ b/drivers/net/vsc9953.c @@ -9,7 +9,7 @@ #include <asm/io.h> #include <asm/fsl_serdes.h> #include <fm_eth.h> -#include <asm/fsl_memac.h> +#include <fsl_memac.h> #include <vsc9953.h> static struct vsc9953_info vsc9953_l2sw = { diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c index bcad8f2..402c519 100644 --- a/drivers/pci/pcie_layerscape.c +++ b/drivers/pci/pcie_layerscape.c @@ -11,7 +11,6 @@ #include <asm/io.h> #include <errno.h> #include <malloc.h> -#include <asm/pcie_layerscape.h> #ifndef CONFIG_SYS_PCI_MEMORY_BUS #define CONFIG_SYS_PCI_MEMORY_BUS CONFIG_SYS_SDRAM_BASE @@ -50,11 +49,20 @@ #define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) #define PCIE_ATU_UPPER_TARGET 0x91C +/* LUT registers */ +#define PCIE_LUT_BASE 0x80000 +#define PCIE_LUT_DBG 0x7FC + +#define PCIE_DBI_RO_WR_EN 0x8bc + #define PCIE_LINK_CAP 0x7c #define PCIE_LINK_SPEED_MASK 0xf #define PCIE_LINK_STA 0x82 -#define PCIE_DBI_SIZE (4 * 1024) /* 4K */ +#define LTSSM_STATE_MASK 0x3f +#define LTSSM_PCIE_L0 0x11 /* L0 state */ + +#define PCIE_DBI_SIZE 0x100000 /* 1M */ struct ls_pcie { int idx; @@ -104,8 +112,6 @@ struct ls_pcie_info { /* PEX1/2 Misc Ports Status Register */ #define LTSSM_STATE_SHIFT 20 -#define LTSSM_STATE_MASK 0x3f -#define LTSSM_PCIE_L0 0x11 /* L0 state */ static int ls_pcie_link_state(struct ls_pcie *pcie) { @@ -122,18 +128,18 @@ static int ls_pcie_link_state(struct ls_pcie *pcie) return 1; } #else -#define PCIE_LDBG 0x7FC - static int ls_pcie_link_state(struct ls_pcie *pcie) { u32 state; - state = readl(pcie->dbi + PCIE_LDBG); - if (state) - return 1; + state = readl(pcie->dbi + PCIE_LUT_BASE + PCIE_LUT_DBG) & + LTSSM_STATE_MASK; + if (state < LTSSM_PCIE_L0) { + debug("....PCIe link error. LTSSM=0x%02x.\n", state); + return 0; + } - debug("....PCIe link error.\n"); - return 0; + return 1; } #endif @@ -149,7 +155,11 @@ static int ls_pcie_link_up(struct ls_pcie *pcie) /* Try to download speed to gen1 */ cap = readl(pcie->dbi + PCIE_LINK_CAP); writel((cap & (~PCIE_LINK_SPEED_MASK)) | 1, pcie->dbi + PCIE_LINK_CAP); - udelay(2000); + /* + * Notice: the following delay has critical impact on link training + * if too short (<30ms) the link doesn't get up. + */ + mdelay(100); state = ls_pcie_link_state(pcie); if (state) return state; @@ -251,6 +261,10 @@ static int ls_pcie_addr_valid(struct pci_controller *hose, pci_dev_t d) if (PCI_DEV(d) > 0) return -EINVAL; + /* Controller does not support multi-function in RC mode */ + if ((PCI_BUS(d) == hose->first_busno) && (PCI_FUNC(d) > 0)) + return -EINVAL; + return 0; } @@ -327,8 +341,12 @@ static void ls_pcie_setup_ctrl(struct ls_pcie *pcie, pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_0, 0); /* program correct class for RC */ + writel(1, pcie->dbi + PCIE_DBI_RO_WR_EN); pci_hose_write_config_word(hose, dev, PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_PCI); +#ifndef CONFIG_LS102XA + writel(0, pcie->dbi + PCIE_DBI_RO_WR_EN); +#endif } int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info) @@ -417,9 +435,9 @@ int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info) } /* Print the negotiated PCIe link width */ - pci_hose_read_config_word(hose, dev, PCIE_LINK_STA, &temp16); - printf("x%d gen%d, regs @ 0x%lx\n", (temp16 & 0x3f0) >> 4, - (temp16 & 0xf), info->regs); + pci_hose_read_config_word(hose, pdev, PCIE_LINK_STA, &temp16); + printf("x%d gen%d, regs @ 0x%lx\n", (temp16 & 0x3f0) >> 4, + (temp16 & 0xf), info->regs); if (ep_mode) return busno; @@ -486,7 +504,7 @@ static void ft_pcie_ls_setup(void *blob, const char *pci_compat, fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); } -void ft_pcie_setup(void *blob, bd_t *bd) +void ft_pci_setup(void *blob, bd_t *bd) { #ifdef CONFIG_PCIE1 ft_pcie_ls_setup(blob, FSL_PCIE_COMPAT, CONFIG_SYS_PCIE1_ADDR, PCIE1); @@ -506,7 +524,7 @@ void ft_pcie_setup(void *blob, bd_t *bd) } #else -void ft_pcie_setup(void *blob, bd_t *bd) +void ft_pci_setup(void *blob, bd_t *bd) { } #endif diff --git a/drivers/qe/qe.c b/drivers/qe/qe.c index d24651b..84e1433 100644 --- a/drivers/qe/qe.c +++ b/drivers/qe/qe.c @@ -196,6 +196,18 @@ void u_qe_init(void) } #endif +#ifdef CONFIG_U_QE +void u_qe_resume(void) +{ + qe_map_t *qe_immrr; + uint qe_base = CONFIG_SYS_IMMR + QE_IMMR_OFFSET; /* QE immr base */ + qe_immrr = (qe_map_t *)qe_base; + + u_qe_firmware_resume((const void *)CONFIG_SYS_QE_FW_ADDR, qe_immrr); + out_be32(&qe_immrr->iram.iready, QE_IRAM_READY); +} +#endif + void qe_reset(void) { qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID, @@ -580,6 +592,76 @@ int u_qe_upload_firmware(const struct qe_firmware *firmware) } #endif +#ifdef CONFIG_U_QE +int u_qe_firmware_resume(const struct qe_firmware *firmware, qe_map_t *qe_immrr) +{ + unsigned int i; + unsigned int j; + const struct qe_header *hdr; + const u32 *code; +#ifdef CONFIG_DEEP_SLEEP +#ifdef CONFIG_PPC + ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); +#else + struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; +#endif +#endif + + if (!firmware) + return -EINVAL; + + hdr = &firmware->header; + + /* Check the magic */ + if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') || + (hdr->magic[2] != 'F')) { +#ifdef CONFIG_DEEP_SLEEP + setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE); +#endif + return -EPERM; + } + + /* + * If the microcode calls for it, split the I-RAM. + */ + if (!firmware->split) { + out_be16(&qe_immrr->cp.cercr, + in_be16(&qe_immrr->cp.cercr) | QE_CP_CERCR_CIR); + } + + /* Loop through each microcode. */ + for (i = 0; i < firmware->count; i++) { + const struct qe_microcode *ucode = &firmware->microcode[i]; + + /* Upload a microcode if it's present */ + if (!ucode->code_offset) + return 0; + + code = (const void *)firmware + be32_to_cpu(ucode->code_offset); + + /* Use auto-increment */ + out_be32(&qe_immrr->iram.iadd, be32_to_cpu(ucode->iram_offset) | + QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR); + + for (i = 0; i < be32_to_cpu(ucode->count); i++) + out_be32(&qe_immrr->iram.idata, be32_to_cpu(code[i])); + + /* Program the traps for this processor */ + for (j = 0; j < 16; j++) { + u32 trap = be32_to_cpu(ucode->traps[j]); + + if (trap) + out_be32(&qe_immrr->rsp[i].tibcr[j], trap); + } + + /* Enable traps */ + out_be32(&qe_immrr->rsp[i].eccr, be32_to_cpu(ucode->eccr)); + } + + return 0; +} +#endif + struct qe_firmware_info *qe_get_firmware_info(void) { return qe_firmware_uploaded ? &qe_firmware_info : NULL; diff --git a/drivers/qe/qe.h b/drivers/qe/qe.h index 33878f8..77b18e9 100644 --- a/drivers/qe/qe.h +++ b/drivers/qe/qe.h @@ -11,6 +11,9 @@ #define __QE_H__ #include "common.h" +#ifdef CONFIG_U_QE +#include <linux/immap_qe.h> +#endif #define QE_NUM_OF_BRGS 16 #define UCC_MAX_NUM 8 @@ -288,6 +291,9 @@ void qe_reset(void); #ifdef CONFIG_U_QE void u_qe_init(void); int u_qe_upload_firmware(const struct qe_firmware *firmware); +void u_qe_resume(void); +int u_qe_firmware_resume(const struct qe_firmware *firmware, + qe_map_t *qe_immrr); #endif #endif /* __QE_H__ */ diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 5d4288d..2dca524 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -259,10 +259,11 @@ static int fdt_fixup_usb_erratum(void *blob, const char *prop_erratum, void fdt_fixup_dr_usb(void *blob, bd_t *bd) { static const char * const modes[] = { "host", "peripheral", "otg" }; - static const char * const phys[] = { "ulpi", "utmi" }; + static const char * const phys[] = { "ulpi", "utmi", "utmi_dual" }; int usb_erratum_a006261_off = -1; int usb_erratum_a007075_off = -1; int usb_erratum_a007792_off = -1; + int usb_erratum_a005697_off = -1; int usb_mode_off = -1; int usb_phy_off = -1; char str[5]; @@ -303,6 +304,9 @@ void fdt_fixup_dr_usb(void *blob, bd_t *bd) dr_phy_type = phys[phy_idx]; } + if (has_dual_phy()) + dr_phy_type = phys[2]; + usb_mode_off = fdt_fixup_usb_mode_phy_type(blob, dr_mode_type, NULL, usb_mode_off); @@ -325,6 +329,7 @@ void fdt_fixup_dr_usb(void *blob, bd_t *bd) if (usb_erratum_a006261_off < 0) return; } + if (has_erratum_a007075()) { usb_erratum_a007075_off = fdt_fixup_usb_erratum (blob, @@ -333,6 +338,7 @@ void fdt_fixup_dr_usb(void *blob, bd_t *bd) if (usb_erratum_a007075_off < 0) return; } + if (has_erratum_a007792()) { usb_erratum_a007792_off = fdt_fixup_usb_erratum (blob, @@ -341,6 +347,14 @@ void fdt_fixup_dr_usb(void *blob, bd_t *bd) if (usb_erratum_a007792_off < 0) return; } + if (has_erratum_a005697()) { + usb_erratum_a005697_off = fdt_fixup_usb_erratum + (blob, + "fsl,usb-erratum-a005697", + usb_erratum_a005697_off); + if (usb_erratum_a005697_off < 0) + return; + } } } #endif diff --git a/include/config_fsl_secboot.h b/include/config_fsl_secboot.h new file mode 100644 index 0000000..050b157 --- /dev/null +++ b/include/config_fsl_secboot.h @@ -0,0 +1,89 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_FSL_SECBOOT_H +#define __CONFIG_FSL_SECBOOT_H + +#ifdef CONFIG_SECURE_BOOT + +#ifndef CONFIG_CMD_ESBC_VALIDATE +#define CONFIG_CMD_ESBC_VALIDATE +#endif + +#ifndef CONFIG_EXTRA_ENV +#define CONFIG_EXTRA_ENV "" +#endif + +/* + * Control should not reach back to uboot after validation of images + * for secure boot flow and therefore bootscript should have + * the bootm command. If control reaches back to uboot anyhow + * after validating images, core should just spin. + */ + +/* + * Define the key hash for boot script here if public/private key pair used to + * sign bootscript are different from the SRK hash put in the fuse + * Example of defining KEY_HASH is + * #define CONFIG_BOOTSCRIPT_KEY_HASH \ + * "41066b564c6ffcef40ccbc1e0a5d0d519604000c785d97bbefd25e4d288d1c8b" + */ + +#ifdef CONFIG_BOOTSCRIPT_KEY_HASH +#define CONFIG_SECBOOT \ + "setenv bs_hdraddr " __stringify(CONFIG_BOOTSCRIPT_HDR_ADDR)";" \ + "setenv bootargs \'root=/dev/ram rw console=ttyS0,115200 " \ + "ramdisk_size=600000\';" \ + CONFIG_EXTRA_ENV \ + "esbc_validate $bs_hdraddr " \ + __stringify(CONFIG_BOOTSCRIPT_KEY_HASH)";" \ + "source $img_addr;" \ + "esbc_halt\0" +#else +#define CONFIG_SECBOOT \ + "setenv bs_hdraddr " __stringify(CONFIG_BOOTSCRIPT_HDR_ADDR)";" \ + "setenv bootargs \'root=/dev/ram rw console=ttyS0,115200 " \ + "ramdisk_size=600000\';" \ + CONFIG_EXTRA_ENV \ + "esbc_validate $bs_hdraddr;" \ + "source $img_addr;" \ + "esbc_halt\0" +#endif + +/* For secure boot flow, default environment used will be used */ +#if defined(CONFIG_SYS_RAMBOOT) +#if defined(CONFIG_RAMBOOT_SPIFLASH) +#undef CONFIG_ENV_IS_IN_SPI_FLASH +#elif defined(CONFIG_RAMBOOT_NAND) +#undef CONFIG_ENV_IS_IN_NAND +#elif defined(CONFIG_RAMBOOT_SDCARD) +#undef CONFIG_ENV_IS_IN_MMC +#endif +#else /*CONFIG_SYS_RAMBOOT*/ +#undef CONFIG_ENV_IS_IN_FLASH +#endif + +#define CONFIG_ENV_IS_NOWHERE + +/* + * We don't want boot delay for secure boot flow + * before autoboot starts + */ +#undef CONFIG_BOOTDELAY +#define CONFIG_BOOTDELAY 0 +#undef CONFIG_BOOTCOMMAND +#define CONFIG_BOOTCOMMAND CONFIG_SECBOOT + +/* + * CONFIG_ZERO_BOOTDELAY_CHECK should not be defined for + * secure boot flow as defining this would enable a user to + * reach uboot prompt by pressing some key before start of + * autoboot + */ +#undef CONFIG_ZERO_BOOTDELAY_CHECK + +#endif +#endif diff --git a/include/configs/aristainetos.h b/include/configs/aristainetos.h index 3066fd0..cc26790 100644 --- a/include/configs/aristainetos.h +++ b/include/configs/aristainetos.h @@ -262,6 +262,7 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_SYS_I2C_SLAVE 0x7f #define CONFIG_SYS_I2C_NOPROBES { {0, 0x00} } diff --git a/include/configs/cm_fx6.h b/include/configs/cm_fx6.h index 4207504..d6e5a2b 100644 --- a/include/configs/cm_fx6.h +++ b/include/configs/cm_fx6.h @@ -245,6 +245,7 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_SYS_MXC_I2C3_SPEED 400000 diff --git a/include/configs/embestmx6boards.h b/include/configs/embestmx6boards.h index b4b3ae8..e9f5bed 100644 --- a/include/configs/embestmx6boards.h +++ b/include/configs/embestmx6boards.h @@ -55,6 +55,7 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_I2C_SPEED 100000 /* USB Configs */ diff --git a/include/configs/flea3.h b/include/configs/flea3.h index 854ae90..5f7cad8 100644 --- a/include/configs/flea3.h +++ b/include/configs/flea3.h @@ -52,6 +52,7 @@ */ #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_SPD_BUS_NUM 2 /* I2C3 */ #define CONFIG_SYS_MXC_I2C3_SLAVE 0xfe #define CONFIG_MXC_SPI diff --git a/include/configs/gw_ventana.h b/include/configs/gw_ventana.h index 620f950..9bc3250 100644 --- a/include/configs/gw_ventana.h +++ b/include/configs/gw_ventana.h @@ -95,6 +95,7 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_I2C_GSC 0 #define CONFIG_I2C_PMIC 1 diff --git a/include/configs/imx31_phycore.h b/include/configs/imx31_phycore.h index 49039d6..db197f3 100644 --- a/include/configs/imx31_phycore.h +++ b/include/configs/imx31_phycore.h @@ -38,6 +38,7 @@ #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_I2C_CLK_OFFSET I2C2_CLK_OFFSET #define CONFIG_MXC_UART diff --git a/include/configs/ls1021aqds.h b/include/configs/ls1021aqds.h index 5de416d..9a8fd50 100644 --- a/include/configs/ls1021aqds.h +++ b/include/configs/ls1021aqds.h @@ -389,6 +389,7 @@ unsigned long get_board_ddr_clk(void); #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ /* * I2C bus multiplexer @@ -655,6 +656,7 @@ unsigned long get_board_ddr_clk(void); #ifdef CONFIG_SECURE_BOOT #define CONFIG_CMD_BLOB +#include <asm/fsl_secure_boot.h> #endif #endif diff --git a/include/configs/ls1021atwr.h b/include/configs/ls1021atwr.h index a13876b..729205f 100644 --- a/include/configs/ls1021atwr.h +++ b/include/configs/ls1021atwr.h @@ -205,6 +205,7 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ /* EEPROM */ #ifndef CONFIG_SD_BOOT diff --git a/include/configs/ls2085a_common.h b/include/configs/ls2085a_common.h index e0435cc..e270fc8 100644 --- a/include/configs/ls2085a_common.h +++ b/include/configs/ls2085a_common.h @@ -19,8 +19,20 @@ #define CONFIG_ARM_ERRATA_828024 #define CONFIG_ARM_ERRATA_826974 +#include <asm/arch-fsl-lsch3/config.h> +#if (defined(CONFIG_SYS_FSL_SRDS_1) || defined(CONFIG_SYS_FSL_SRDS_2)) +#define CONFIG_SYS_HAS_SERDES +#endif + +/* We need architecture specific misc initializations */ +#define CONFIG_ARCH_MISC_INIT + /* Link Definitions */ -#define CONFIG_SYS_TEXT_BASE 0x30001000 +#ifdef CONFIG_SPL +#define CONFIG_SYS_TEXT_BASE 0x80400000 +#else +#define CONFIG_SYS_TEXT_BASE 0x30100000 +#endif #ifdef CONFIG_EMU #define CONFIG_SYS_NO_FLASH @@ -39,13 +51,13 @@ #define CONFIG_FIT #define CONFIG_FIT_VERBOSE /* enable fit_format_{error,warning}() */ +#ifndef CONFIG_SPL #define CONFIG_FSL_DDR_INTERACTIVE /* Interactive debugging */ +#endif #ifndef CONFIG_SYS_FSL_DDR4 #define CONFIG_SYS_FSL_DDR3 /* Use DDR3 memory */ #define CONFIG_SYS_DDR_RAW_TIMING #endif -#define CONFIG_DIMM_SLOTS_PER_CTLR 1 -#define CONFIG_CHIP_SELECTS_PER_CTRL 4 #define CONFIG_SYS_FSL_DDR_INTLV_256B /* force 256 byte interleaving */ @@ -69,23 +81,26 @@ #define CONFIG_SYS_DP_DDR_BASE_PHY 0 #define CONFIG_DP_DDR_CTRL 2 #define CONFIG_DP_DDR_NUM_CTRLS 1 -#define CONFIG_DP_DDR_DIMM_SLOTS_PER_CTLR 1 /* Generic Timer Definitions */ -#define COUNTER_FREQUENCY 12000000 /* 12MHz */ +/* + * This is not an accurate number. It is used in start.S. The frequency + * will be udpated later when get_bus_freq(0) is available. + */ +#define COUNTER_FREQUENCY 25000000 /* 25MHz */ /* Size of malloc() pool */ -#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 128 * 1024) +#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 2048 * 1024) /* I2C */ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC -#define CONFIG_SYS_MXC_I2C1_SPEED 40000000 -#define CONFIG_SYS_MXC_I2C2_SPEED 40000000 +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ +#define CONFIG_SYS_I2C_MXC_I2C4 /* enable I2C bus 4 */ /* Serial Port */ -#define CONFIG_CONS_INDEX 2 +#define CONFIG_CONS_INDEX 1 #define CONFIG_SYS_NS16550 #define CONFIG_SYS_NS16550_SERIAL #define CONFIG_SYS_NS16550_REG_SIZE 1 @@ -96,131 +111,98 @@ /* IFC */ #define CONFIG_FSL_IFC -#define CONFIG_SYS_NOR0_CSPR_EXT (0x0) -#define CONFIG_SYS_NOR_AMASK IFC_AMASK(128*1024*1024) + /* - * During booting, CS0 needs to be at the region of 0x30000000, i.e. the IFC - * address 0. But this region is limited to 256MB. To accommodate bigger NOR - * flash and other devices, we will map CS0 to 0x580000000 after relocation. + * During booting, IFC is mapped at the region of 0x30000000. + * But this region is limited to 256MB. To accommodate NOR, promjet + * and FPGA. This region is divided as below: + * 0x30000000 - 0x37ffffff : 128MB : NOR flash + * 0x38000000 - 0x3BFFFFFF : 64MB : Promjet + * 0x3C000000 - 0x40000000 : 64MB : FPGA etc + * + * To accommodate bigger NOR flash and other devices, we will map IFC + * chip selects to as below: + * 0x5_1000_0000..0x5_1fff_ffff Memory Hole + * 0x5_2000_0000..0x5_3fff_ffff IFC CSx (FPGA, NAND and others 512MB) + * 0x5_4000_0000..0x5_7fff_ffff ASIC or others 1GB + * 0x5_8000_0000..0x5_bfff_ffff IFC CS0 1GB (NOR/Promjet) + * 0x5_C000_0000..0x5_ffff_ffff IFC CS1 1GB (NOR/Promjet) + * + * For e.g. NOR flash at CS0 will be mapped to 0x580000000 after relocation. * CONFIG_SYS_FLASH_BASE has the final address (core view) * CONFIG_SYS_FLASH_BASE_PHYS has the final address (IFC view) * CONFIG_SYS_FLASH_BASE_PHYS_EARLY has the temporary IFC address * CONFIG_SYS_TEXT_BASE is linked to 0x30000000 for booting */ + #define CONFIG_SYS_FLASH_BASE 0x580000000ULL #define CONFIG_SYS_FLASH_BASE_PHYS 0x80000000 #define CONFIG_SYS_FLASH_BASE_PHYS_EARLY 0x00000000 -/* - * NOR Flash Timing Params - */ -#define CONFIG_SYS_NOR0_CSPR \ - (CSPR_PHYS_ADDR(CONFIG_SYS_FLASH_BASE_PHYS) | \ - CSPR_PORT_SIZE_16 | \ - CSPR_MSEL_NOR | \ - CSPR_V) -#define CONFIG_SYS_NOR0_CSPR_EARLY \ - (CSPR_PHYS_ADDR(CONFIG_SYS_FLASH_BASE_PHYS_EARLY) | \ - CSPR_PORT_SIZE_16 | \ - CSPR_MSEL_NOR | \ - CSPR_V) -#define CONFIG_SYS_NOR_CSOR CSOR_NOR_ADM_SHIFT(12) -#define CONFIG_SYS_NOR_FTIM0 (FTIM0_NOR_TACSE(0x1) | \ - FTIM0_NOR_TEADC(0x1) | \ - FTIM0_NOR_TEAHC(0x1)) -#define CONFIG_SYS_NOR_FTIM1 (FTIM1_NOR_TACO(0x1) | \ - FTIM1_NOR_TRAD_NOR(0x1)) -#define CONFIG_SYS_NOR_FTIM2 (FTIM2_NOR_TCS(0x0) | \ - FTIM2_NOR_TCH(0x0) | \ - FTIM2_NOR_TWP(0x1)) -#define CONFIG_SYS_NOR_FTIM3 0x04000000 -#define CONFIG_SYS_IFC_CCR 0x01000000 +#define CONFIG_SYS_FLASH1_BASE_PHYS 0xC0000000 +#define CONFIG_SYS_FLASH1_BASE_PHYS_EARLY 0x8000000 #ifndef CONFIG_SYS_NO_FLASH #define CONFIG_FLASH_CFI_DRIVER #define CONFIG_SYS_FLASH_CFI #define CONFIG_SYS_FLASH_USE_BUFFER_WRITE #define CONFIG_SYS_FLASH_QUIET_TEST -#define CONFIG_FLASH_SHOW_PROGRESS 45 /* count down from 45/5: 9..1 */ - -#define CONFIG_SYS_MAX_FLASH_BANKS 1 /* number of banks */ -#define CONFIG_SYS_MAX_FLASH_SECT 1024 /* sectors per device */ -#define CONFIG_SYS_FLASH_ERASE_TOUT 60000 /* Flash Erase Timeout (ms) */ -#define CONFIG_SYS_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (ms) */ +#endif -#define CONFIG_SYS_FLASH_EMPTY_INFO -#define CONFIG_SYS_FLASH_BANKS_LIST { CONFIG_SYS_FLASH_BASE } +#ifndef __ASSEMBLY__ +unsigned long long get_qixis_addr(void); #endif +#define QIXIS_BASE get_qixis_addr() +#define QIXIS_BASE_PHYS 0x20000000 +#define QIXIS_BASE_PHYS_EARLY 0xC000000 +#define QIXIS_STAT_PRES1 0xb +#define QIXIS_SDID_MASK 0x07 +#define QIXIS_ESDHC_NO_ADAPTER 0x7 + +#define CONFIG_SYS_NAND_BASE 0x530000000ULL +#define CONFIG_SYS_NAND_BASE_PHYS 0x30000000 -#define CONFIG_NAND_FSL_IFC -#define CONFIG_SYS_NAND_MAX_ECCPOS 256 -#define CONFIG_SYS_NAND_MAX_OOBFREE 2 -#define CONFIG_SYS_NAND_BASE 0x520000000 -#define CONFIG_SYS_NAND_BASE_PHYS 0x20000000 - -#define CONFIG_SYS_NAND_CSPR_EXT (0x0) -#define CONFIG_SYS_NAND_CSPR (CSPR_PHYS_ADDR(CONFIG_SYS_NAND_BASE_PHYS) \ - | CSPR_PORT_SIZE_8 /* Port Size = 8 bit */ \ - | CSPR_MSEL_NAND /* MSEL = NAND */ \ - | CSPR_V) -#define CONFIG_SYS_NAND_AMASK IFC_AMASK(64 * 1024) - -#define CONFIG_SYS_NAND_CSOR (CSOR_NAND_ECC_ENC_EN /* ECC on encode */ \ - | CSOR_NAND_ECC_DEC_EN /* ECC on decode */ \ - | CSOR_NAND_ECC_MODE_4 /* 4-bit ECC */ \ - | CSOR_NAND_RAL_3 /* RAL = 2Byes */ \ - | CSOR_NAND_PGS_2K /* Page Size = 2K */ \ - | CSOR_NAND_SPRZ_64/* Spare size = 64 */ \ - | CSOR_NAND_PB(64)) /*Pages Per Block = 64*/ - -#define CONFIG_SYS_NAND_ONFI_DETECTION - -/* ONFI NAND Flash mode0 Timing Params */ -#define CONFIG_SYS_NAND_FTIM0 (FTIM0_NAND_TCCST(0x07) | \ - FTIM0_NAND_TWP(0x18) | \ - FTIM0_NAND_TWCHT(0x07) | \ - FTIM0_NAND_TWH(0x0a)) -#define CONFIG_SYS_NAND_FTIM1 (FTIM1_NAND_TADLE(0x32) | \ - FTIM1_NAND_TWBE(0x39) | \ - FTIM1_NAND_TRR(0x0e) | \ - FTIM1_NAND_TRP(0x18)) -#define CONFIG_SYS_NAND_FTIM2 (FTIM2_NAND_TRAD(0x0f) | \ - FTIM2_NAND_TREH(0x0a) | \ - FTIM2_NAND_TWHRE(0x1e)) -#define CONFIG_SYS_NAND_FTIM3 0x0 - -#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE } -#define CONFIG_SYS_MAX_NAND_DEVICE 1 -#define CONFIG_CMD_NAND - -#define CONFIG_SYS_NAND_BLOCK_SIZE (128 * 1024) - -#define CONFIG_SYS_CSPR0_EXT CONFIG_SYS_NOR0_CSPR_EXT -#define CONFIG_SYS_CSPR0 CONFIG_SYS_NOR0_CSPR_EARLY -#define CONFIG_SYS_CSPR0_FINAL CONFIG_SYS_NOR0_CSPR -#define CONFIG_SYS_AMASK0 CONFIG_SYS_NOR_AMASK -#define CONFIG_SYS_CSOR0 CONFIG_SYS_NOR_CSOR -#define CONFIG_SYS_CS0_FTIM0 CONFIG_SYS_NOR_FTIM0 -#define CONFIG_SYS_CS0_FTIM1 CONFIG_SYS_NOR_FTIM1 -#define CONFIG_SYS_CS0_FTIM2 CONFIG_SYS_NOR_FTIM2 -#define CONFIG_SYS_CS0_FTIM3 CONFIG_SYS_NOR_FTIM3 +/* Debug Server firmware */ +#define CONFIG_SYS_DEBUG_SERVER_DRAM_BLOCK_MIN_SIZE (512UL * 1024 * 1024) +/* 2 sec timeout */ +#define CONFIG_SYS_DEBUG_SERVER_TIMEOUT (2 * 1000 * 1000) /* MC firmware */ #define CONFIG_FSL_MC_ENET #define CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE (512UL * 1024 * 1024) -#define CONFIG_SYS_LS_MC_FW_IN_NOR -#define CONFIG_SYS_LS_MC_FW_ADDR 0x580200000ULL -#define CONFIG_SYS_LS_MC_DPL_IN_NOR -#define CONFIG_SYS_LS_MC_DPL_ADDR 0x5806C0000ULL /* TODO Actual DPL max length needs to be confirmed with the MC FW team */ -#define CONFIG_SYS_LS_MC_DPL_MAX_LENGTH (256 * 1024) -#define CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET 0xe00000 - -/* Carve the MC private DRAM block from the end of DRAM */ -#ifdef CONFIG_FSL_MC_ENET -#define CONFIG_SYS_MEM_TOP_HIDE mc_get_dram_block_size() +#define CONFIG_SYS_LS_MC_DPC_MAX_LENGTH 0x20000 +#define CONFIG_SYS_LS_MC_DRAM_DPC_OFFSET 0x00F00000 +#define CONFIG_SYS_LS_MC_DPL_MAX_LENGTH 0x20000 +#define CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET 0x00F20000 + +/* Carve out a DDR region which will not be used by u-boot/Linux */ +#if defined(CONFIG_FSL_MC_ENET) || defined(CONFIG_FSL_DEBUG_SERVER) +#define CONFIG_SYS_MEM_TOP_HIDE get_dram_size_to_hide() #endif +/* PCIe */ +#define CONFIG_PCIE1 /* PCIE controler 1 */ +#define CONFIG_PCIE2 /* PCIE controler 2 */ +#define CONFIG_PCIE3 /* PCIE controler 3 */ +#define CONFIG_PCIE4 /* PCIE controler 4 */ +#define FSL_PCIE_COMPAT "fsl,20851a-pcie" + +#define CONFIG_SYS_PCI_64BIT + +#define CONFIG_SYS_PCIE_CFG0_PHYS_OFF 0x00000000 +#define CONFIG_SYS_PCIE_CFG0_SIZE 0x00001000 /* 4k */ +#define CONFIG_SYS_PCIE_CFG1_PHYS_OFF 0x00001000 +#define CONFIG_SYS_PCIE_CFG1_SIZE 0x00001000 /* 4k */ + +#define CONFIG_SYS_PCIE_IO_BUS 0x00000000 +#define CONFIG_SYS_PCIE_IO_PHYS_OFF 0x00010000 +#define CONFIG_SYS_PCIE_IO_SIZE 0x00010000 /* 64k */ + +#define CONFIG_SYS_PCIE_MEM_BUS 0x40000000 +#define CONFIG_SYS_PCIE_MEM_PHYS_OFF 0x40000000 +#define CONFIG_SYS_PCIE_MEM_SIZE 0x40000000 /* 1G */ + /* Command line configuration */ #define CONFIG_CMD_CACHE #define CONFIG_CMD_BDI @@ -228,6 +210,7 @@ #define CONFIG_CMD_ENV #define CONFIG_CMD_FLASH #define CONFIG_CMD_IMI +#define CONFIG_CMD_LOADB #define CONFIG_CMD_MEMORY #define CONFIG_CMD_MII #define CONFIG_CMD_NET @@ -237,8 +220,6 @@ #define CONFIG_CMD_BOOTD #define CONFIG_CMD_ECHO #define CONFIG_CMD_SOURCE -#define CONFIG_CMD_FAT -#define CONFIG_DOS_PARTITION /* Miscellaneous configurable options */ #define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_DDR_SDRAM_BASE + 0x10000000) @@ -247,9 +228,6 @@ /* Physical Memory Map */ /* fixme: these need to be checked against the board */ #define CONFIG_CHIP_SELECTS_PER_CTRL 4 -#define CONFIG_SYS_CLK_FREQ 100000000 -#define CONFIG_DDR_CLK_FREQ 133333333 - #define CONFIG_NR_DRAM_BANKS 3 @@ -265,7 +243,7 @@ "kernel_addr=0x100000\0" \ "ramdisk_addr=0x800000\0" \ "ramdisk_size=0x2000000\0" \ - "fdt_high=0xffffffffffffffff\0" \ + "fdt_high=0xa0000000\0" \ "initrd_high=0xffffffffffffffff\0" \ "kernel_start=0x581200000\0" \ "kernel_load=0xa0000000\0" \ @@ -278,15 +256,11 @@ "hugepages=16" #define CONFIG_BOOTCOMMAND "cp.b $kernel_start $kernel_load " \ "$kernel_size && bootm $kernel_load" -#define CONFIG_BOOTDELAY 1 - -/* Store environment at top of flash */ -#define CONFIG_ENV_IS_NOWHERE 1 -#define CONFIG_ENV_SIZE 0x1000 +#define CONFIG_BOOTDELAY 10 /* Monitor Command Prompt */ #define CONFIG_SYS_CBSIZE 512 /* Console I/O Buffer Size */ -#define CONFIG_SYS_PROMPT "> " +#define CONFIG_SYS_PROMPT "=> " #define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \ sizeof(CONFIG_SYS_PROMPT) + 16) #define CONFIG_SYS_HUSH_PARSER @@ -294,10 +268,36 @@ #define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot args buffer */ #define CONFIG_SYS_LONGHELP #define CONFIG_CMDLINE_EDITING 1 +#define CONFIG_AUTO_COMPLETE #define CONFIG_SYS_MAXARGS 64 /* max command args */ #ifndef __ASSEMBLY__ -unsigned long mc_get_dram_block_size(void); +unsigned long get_dram_size_to_hide(void); #endif +#define CONFIG_PANIC_HANG /* do not reset board on panic */ + +#define CONFIG_SPL_BSS_START_ADDR 0x80100000 +#define CONFIG_SPL_BSS_MAX_SIZE 0x00100000 +#define CONFIG_SPL_DRIVERS_MISC_SUPPORT +#define CONFIG_SPL_ENV_SUPPORT +#define CONFIG_SPL_FRAMEWORK +#define CONFIG_SPL_I2C_SUPPORT +#define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/armv8/u-boot-spl.lds" +#define CONFIG_SPL_LIBCOMMON_SUPPORT +#define CONFIG_SPL_LIBGENERIC_SUPPORT +#define CONFIG_SPL_MAX_SIZE 0x16000 +#define CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT +#define CONFIG_SPL_NAND_SUPPORT +#define CONFIG_SPL_SERIAL_SUPPORT +#define CONFIG_SPL_STACK (CONFIG_SYS_FSL_OCRAM_BASE + 0x9ff0) +#define CONFIG_SPL_TARGET "u-boot-with-spl.bin" +#define CONFIG_SPL_TEXT_BASE 0x1800a000 + +#define CONFIG_SYS_NAND_U_BOOT_DST 0x80400000 +#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_NAND_U_BOOT_DST +#define CONFIG_SYS_SPL_MALLOC_SIZE 0x00100000 +#define CONFIG_SYS_SPL_MALLOC_START 0x80200000 +#define CONFIG_SYS_MONITOR_LEN (512 * 1024) + #endif /* __LS2_COMMON_H */ diff --git a/include/configs/ls2085a_emu.h b/include/configs/ls2085a_emu.h index a02d694..2d68e1b 100644 --- a/include/configs/ls2085a_emu.h +++ b/include/configs/ls2085a_emu.h @@ -12,6 +12,12 @@ #define CONFIG_IDENT_STRING " LS2085A-EMU" #define CONFIG_BOOTP_VCI_STRING "U-boot.LS2085A-EMU" +#define CONFIG_SYS_CLK_FREQ 100000000 +#define CONFIG_DDR_CLK_FREQ 133333333 + +#define CONFIG_SYS_MXC_I2C1_SPEED 40000000 +#define CONFIG_SYS_MXC_I2C2_SPEED 40000000 + #define CONFIG_DDR_SPD #define CONFIG_SYS_FSL_DDR_EMU /* Support emulator */ #define SPD_EEPROM_ADDRESS1 0x51 @@ -19,6 +25,65 @@ #define SPD_EEPROM_ADDRESS3 0x53 #define SPD_EEPROM_ADDRESS SPD_EEPROM_ADDRESS1 #define CONFIG_SYS_SPD_BUS_NUM 1 /* SPD on I2C bus 1 */ +#define CONFIG_DIMM_SLOTS_PER_CTLR 1 +#define CONFIG_CHIP_SELECTS_PER_CTRL 4 +#define CONFIG_DP_DDR_DIMM_SLOTS_PER_CTLR 1 #define CONFIG_FSL_DDR_SYNC_REFRESH + +#define CONFIG_SYS_NOR0_CSPR_EXT (0x0) +#define CONFIG_SYS_NOR_AMASK IFC_AMASK(128*1024*1024) +/* + * NOR Flash Timing Params + */ +#define CONFIG_SYS_NOR0_CSPR \ + (CSPR_PHYS_ADDR(CONFIG_SYS_FLASH_BASE_PHYS) | \ + CSPR_PORT_SIZE_16 | \ + CSPR_MSEL_NOR | \ + CSPR_V) +#define CONFIG_SYS_NOR0_CSPR_EARLY \ + (CSPR_PHYS_ADDR(CONFIG_SYS_FLASH_BASE_PHYS_EARLY) | \ + CSPR_PORT_SIZE_16 | \ + CSPR_MSEL_NOR | \ + CSPR_V) +#define CONFIG_SYS_NOR_CSOR CSOR_NOR_ADM_SHIFT(12) +#define CONFIG_SYS_NOR_FTIM0 (FTIM0_NOR_TACSE(0x1) | \ + FTIM0_NOR_TEADC(0x1) | \ + FTIM0_NOR_TEAHC(0x1)) +#define CONFIG_SYS_NOR_FTIM1 (FTIM1_NOR_TACO(0x1) | \ + FTIM1_NOR_TRAD_NOR(0x1)) +#define CONFIG_SYS_NOR_FTIM2 (FTIM2_NOR_TCS(0x0) | \ + FTIM2_NOR_TCH(0x0) | \ + FTIM2_NOR_TWP(0x1)) +#define CONFIG_SYS_NOR_FTIM3 0x04000000 +#define CONFIG_SYS_IFC_CCR 0x01000000 + +#define CONFIG_SYS_CSPR0_EXT CONFIG_SYS_NOR0_CSPR_EXT +#define CONFIG_SYS_CSPR0 CONFIG_SYS_NOR0_CSPR_EARLY +#define CONFIG_SYS_CSPR0_FINAL CONFIG_SYS_NOR0_CSPR +#define CONFIG_SYS_AMASK0 CONFIG_SYS_NOR_AMASK +#define CONFIG_SYS_CSOR0 CONFIG_SYS_NOR_CSOR +#define CONFIG_SYS_CS0_FTIM0 CONFIG_SYS_NOR_FTIM0 +#define CONFIG_SYS_CS0_FTIM1 CONFIG_SYS_NOR_FTIM1 +#define CONFIG_SYS_CS0_FTIM2 CONFIG_SYS_NOR_FTIM2 +#define CONFIG_SYS_CS0_FTIM3 CONFIG_SYS_NOR_FTIM3 + +/* Debug Server firmware */ +#define CONFIG_SYS_DEBUG_SERVER_FW_IN_NOR +#define CONFIG_SYS_DEBUG_SERVER_FW_ADDR 0x580C00000ULL + +/* + * This trick allows users to load MC images into DDR directly without + * copying from NOR flash. It dramatically improves speed. + */ +#define CONFIG_SYS_LS_MC_FW_IN_DDR +#define CONFIG_SYS_LS_MC_DPL_IN_DDR +#define CONFIG_SYS_LS_MC_DPC_IN_DDR + +#define CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS 200000 + +/* Store environment at top of flash */ +#define CONFIG_ENV_IS_NOWHERE 1 +#define CONFIG_ENV_SIZE 0x1000 + #endif /* __LS2_EMU_H */ diff --git a/include/configs/ls2085a_simu.h b/include/configs/ls2085a_simu.h index af34f3f..d0d2eed 100644 --- a/include/configs/ls2085a_simu.h +++ b/include/configs/ls2085a_simu.h @@ -12,10 +12,112 @@ #define CONFIG_IDENT_STRING " LS2085A-SIMU" #define CONFIG_BOOTP_VCI_STRING "U-boot.LS2085A-SIMU" +#define CONFIG_SYS_CLK_FREQ 100000000 +#define CONFIG_DDR_CLK_FREQ 133333333 + +#define CONFIG_SYS_MXC_I2C1_SPEED 40000000 +#define CONFIG_SYS_MXC_I2C2_SPEED 40000000 + +#define CONFIG_DIMM_SLOTS_PER_CTLR 1 +#define CONFIG_CHIP_SELECTS_PER_CTRL 4 +#define CONFIG_DP_DDR_DIMM_SLOTS_PER_CTLR 1 + /* SMSC 91C111 ethernet configuration */ #define CONFIG_SMC91111 #define CONFIG_SMC91111_BASE (0x2210000) +#define CONFIG_SYS_NOR0_CSPR_EXT (0x0) +#define CONFIG_SYS_NOR_AMASK IFC_AMASK(128*1024*1024) + +/* + * NOR Flash Timing Params + */ +#define CONFIG_SYS_NOR0_CSPR \ + (CSPR_PHYS_ADDR(CONFIG_SYS_FLASH_BASE_PHYS) | \ + CSPR_PORT_SIZE_16 | \ + CSPR_MSEL_NOR | \ + CSPR_V) +#define CONFIG_SYS_NOR0_CSPR_EARLY \ + (CSPR_PHYS_ADDR(CONFIG_SYS_FLASH_BASE_PHYS_EARLY) | \ + CSPR_PORT_SIZE_16 | \ + CSPR_MSEL_NOR | \ + CSPR_V) +#define CONFIG_SYS_NOR_CSOR CSOR_NOR_ADM_SHIFT(12) +#define CONFIG_SYS_NOR_FTIM0 (FTIM0_NOR_TACSE(0x1) | \ + FTIM0_NOR_TEADC(0x1) | \ + FTIM0_NOR_TEAHC(0x1)) +#define CONFIG_SYS_NOR_FTIM1 (FTIM1_NOR_TACO(0x1) | \ + FTIM1_NOR_TRAD_NOR(0x1)) +#define CONFIG_SYS_NOR_FTIM2 (FTIM2_NOR_TCS(0x0) | \ + FTIM2_NOR_TCH(0x0) | \ + FTIM2_NOR_TWP(0x1)) +#define CONFIG_SYS_NOR_FTIM3 0x04000000 +#define CONFIG_SYS_IFC_CCR 0x01000000 + +#ifndef CONFIG_SYS_NO_FLASH +#define CONFIG_FLASH_SHOW_PROGRESS 45 /* count down from 45/5: 9..1 */ + +#define CONFIG_SYS_MAX_FLASH_BANKS 1 /* number of banks */ +#define CONFIG_SYS_MAX_FLASH_SECT 1024 /* sectors per device */ +#define CONFIG_SYS_FLASH_ERASE_TOUT 60000 /* Flash Erase Timeout (ms) */ +#define CONFIG_SYS_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (ms) */ + +#define CONFIG_SYS_FLASH_EMPTY_INFO +#define CONFIG_SYS_FLASH_BANKS_LIST { CONFIG_SYS_FLASH_BASE } +#endif + +#define CONFIG_NAND_FSL_IFC +#define CONFIG_SYS_NAND_MAX_ECCPOS 256 +#define CONFIG_SYS_NAND_MAX_OOBFREE 2 + + +#define CONFIG_SYS_NAND_CSPR_EXT (0x0) +#define CONFIG_SYS_NAND_CSPR (CSPR_PHYS_ADDR(CONFIG_SYS_NAND_BASE_PHYS) \ + | CSPR_PORT_SIZE_8 /* Port Size = 8 bit */ \ + | CSPR_MSEL_NAND /* MSEL = NAND */ \ + | CSPR_V) +#define CONFIG_SYS_NAND_AMASK IFC_AMASK(64 * 1024) + +#define CONFIG_SYS_NAND_CSOR (CSOR_NAND_ECC_ENC_EN /* ECC on encode */ \ + | CSOR_NAND_ECC_DEC_EN /* ECC on decode */ \ + | CSOR_NAND_ECC_MODE_4 /* 4-bit ECC */ \ + | CSOR_NAND_RAL_3 /* RAL = 2Byes */ \ + | CSOR_NAND_PGS_2K /* Page Size = 2K */ \ + | CSOR_NAND_SPRZ_64/* Spare size = 64 */ \ + | CSOR_NAND_PB(64)) /*Pages Per Block = 64*/ + +#define CONFIG_SYS_NAND_ONFI_DETECTION + +/* ONFI NAND Flash mode0 Timing Params */ +#define CONFIG_SYS_NAND_FTIM0 (FTIM0_NAND_TCCST(0x07) | \ + FTIM0_NAND_TWP(0x18) | \ + FTIM0_NAND_TWCHT(0x07) | \ + FTIM0_NAND_TWH(0x0a)) +#define CONFIG_SYS_NAND_FTIM1 (FTIM1_NAND_TADLE(0x32) | \ + FTIM1_NAND_TWBE(0x39) | \ + FTIM1_NAND_TRR(0x0e) | \ + FTIM1_NAND_TRP(0x18)) +#define CONFIG_SYS_NAND_FTIM2 (FTIM2_NAND_TRAD(0x0f) | \ + FTIM2_NAND_TREH(0x0a) | \ + FTIM2_NAND_TWHRE(0x1e)) +#define CONFIG_SYS_NAND_FTIM3 0x0 + +#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE } +#define CONFIG_SYS_MAX_NAND_DEVICE 1 +#define CONFIG_MTD_NAND_VERIFY_WRITE +#define CONFIG_CMD_NAND + +#define CONFIG_SYS_NAND_BLOCK_SIZE (128 * 1024) + +#define CONFIG_SYS_CSPR0_EXT CONFIG_SYS_NOR0_CSPR_EXT +#define CONFIG_SYS_CSPR0 CONFIG_SYS_NOR0_CSPR_EARLY +#define CONFIG_SYS_CSPR0_FINAL CONFIG_SYS_NOR0_CSPR +#define CONFIG_SYS_AMASK0 CONFIG_SYS_NOR_AMASK +#define CONFIG_SYS_CSOR0 CONFIG_SYS_NOR_CSOR +#define CONFIG_SYS_CS0_FTIM0 CONFIG_SYS_NOR_FTIM0 +#define CONFIG_SYS_CS0_FTIM1 CONFIG_SYS_NOR_FTIM1 +#define CONFIG_SYS_CS0_FTIM2 CONFIG_SYS_NOR_FTIM2 +#define CONFIG_SYS_CS0_FTIM3 CONFIG_SYS_NOR_FTIM3 #define CONFIG_SYS_CSPR1_EXT CONFIG_SYS_NAND_CSPR_EXT #define CONFIG_SYS_CSPR1 CONFIG_SYS_NAND_CSPR #define CONFIG_SYS_AMASK1 CONFIG_SYS_NAND_AMASK @@ -25,4 +127,24 @@ #define CONFIG_SYS_CS1_FTIM2 CONFIG_SYS_NAND_FTIM2 #define CONFIG_SYS_CS1_FTIM3 CONFIG_SYS_NAND_FTIM3 +/* Debug Server firmware */ +#define CONFIG_SYS_DEBUG_SERVER_FW_IN_NOR +#define CONFIG_SYS_DEBUG_SERVER_FW_ADDR 0x580C00000ULL + +/* MC firmware */ +#define CONFIG_SYS_LS_MC_FW_IN_NOR +#define CONFIG_SYS_LS_MC_FW_ADDR 0x580200000ULL + +#define CONFIG_SYS_LS_MC_DPL_IN_NOR +#define CONFIG_SYS_LS_MC_DPL_ADDR 0x5806C0000ULL + +#define CONFIG_SYS_LS_MC_DPC_IN_NOR +#define CONFIG_SYS_LS_MC_DPC_ADDR 0x5806F8000ULL + +#define CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS 200000 + +/* Store environment at top of flash */ +#define CONFIG_ENV_IS_NOWHERE 1 +#define CONFIG_ENV_SIZE 0x1000 + #endif /* __LS2_SIMU_H */ diff --git a/include/configs/ls2085aqds.h b/include/configs/ls2085aqds.h new file mode 100644 index 0000000..711d529 --- /dev/null +++ b/include/configs/ls2085aqds.h @@ -0,0 +1,359 @@ +/* + * Copyright 2015 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __LS2_QDS_H +#define __LS2_QDS_H + +#include "ls2085a_common.h" +#include <config_cmd_default.h> + +#define CONFIG_IDENT_STRING " LS2085A-QDS" +#define CONFIG_BOOTP_VCI_STRING "U-boot.LS2085A-QDS" + +#define CONFIG_DISPLAY_BOARDINFO + +#ifndef __ASSEMBLY__ +unsigned long get_board_sys_clk(void); +unsigned long get_board_ddr_clk(void); +#endif + +#define CONFIG_SYS_CLK_FREQ get_board_sys_clk() +#define CONFIG_DDR_CLK_FREQ get_board_ddr_clk() +#define COUNTER_FREQUENCY_REAL (CONFIG_SYS_CLK_FREQ/4) + +#define CONFIG_DDR_SPD +#define CONFIG_DDR_ECC +#define CONFIG_ECC_INIT_VIA_DDRCONTROLLER +#define CONFIG_MEM_INIT_VALUE 0xdeadbeef +#define SPD_EEPROM_ADDRESS1 0x51 +#define SPD_EEPROM_ADDRESS2 0x52 +#define SPD_EEPROM_ADDRESS3 0x53 +#define SPD_EEPROM_ADDRESS4 0x54 +#define SPD_EEPROM_ADDRESS5 0x55 +#define SPD_EEPROM_ADDRESS6 0x56 /* dummy address */ +#define SPD_EEPROM_ADDRESS SPD_EEPROM_ADDRESS1 +#define CONFIG_SYS_SPD_BUS_NUM 0 /* SPD on I2C bus 0 */ +#define CONFIG_DIMM_SLOTS_PER_CTLR 2 +#define CONFIG_CHIP_SELECTS_PER_CTRL 4 +#define CONFIG_DP_DDR_DIMM_SLOTS_PER_CTLR 1 +#define CONFIG_FSL_DDR_BIST /* enable built-in memory test */ + +/* undefined CONFIG_FSL_DDR_SYNC_REFRESH for simulator */ + +#define CONFIG_SYS_NOR0_CSPR_EXT (0x0) +#define CONFIG_SYS_NOR_AMASK IFC_AMASK(128*1024*1024) +#define CONFIG_SYS_NOR_AMASK_EARLY IFC_AMASK(64*1024*1024) + +#define CONFIG_SYS_NOR0_CSPR \ + (CSPR_PHYS_ADDR(CONFIG_SYS_FLASH_BASE_PHYS) | \ + CSPR_PORT_SIZE_16 | \ + CSPR_MSEL_NOR | \ + CSPR_V) +#define CONFIG_SYS_NOR0_CSPR_EARLY \ + (CSPR_PHYS_ADDR(CONFIG_SYS_FLASH_BASE_PHYS_EARLY) | \ + CSPR_PORT_SIZE_16 | \ + CSPR_MSEL_NOR | \ + CSPR_V) +#define CONFIG_SYS_NOR1_CSPR \ + (CSPR_PHYS_ADDR(CONFIG_SYS_FLASH1_BASE_PHYS) | \ + CSPR_PORT_SIZE_16 | \ + CSPR_MSEL_NOR | \ + CSPR_V) +#define CONFIG_SYS_NOR1_CSPR_EARLY \ + (CSPR_PHYS_ADDR(CONFIG_SYS_FLASH1_BASE_PHYS_EARLY) | \ + CSPR_PORT_SIZE_16 | \ + CSPR_MSEL_NOR | \ + CSPR_V) +#define CONFIG_SYS_NOR_CSOR CSOR_NOR_ADM_SHIFT(12) +#define CONFIG_SYS_NOR_FTIM0 (FTIM0_NOR_TACSE(0x4) | \ + FTIM0_NOR_TEADC(0x5) | \ + FTIM0_NOR_TEAHC(0x5)) +#define CONFIG_SYS_NOR_FTIM1 (FTIM1_NOR_TACO(0x35) | \ + FTIM1_NOR_TRAD_NOR(0x1a) |\ + FTIM1_NOR_TSEQRAD_NOR(0x13)) +#define CONFIG_SYS_NOR_FTIM2 (FTIM2_NOR_TCS(0x4) | \ + FTIM2_NOR_TCH(0x4) | \ + FTIM2_NOR_TWPH(0x0E) | \ + FTIM2_NOR_TWP(0x1c)) +#define CONFIG_SYS_NOR_FTIM3 0x04000000 +#define CONFIG_SYS_IFC_CCR 0x01000000 + +#ifndef CONFIG_SYS_NO_FLASH +#define CONFIG_FLASH_CFI_DRIVER +#define CONFIG_SYS_FLASH_CFI +#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE +#define CONFIG_SYS_FLASH_QUIET_TEST +#define CONFIG_FLASH_SHOW_PROGRESS 45 /* count down from 45/5: 9..1 */ + +#define CONFIG_SYS_MAX_FLASH_BANKS 2 /* number of banks */ +#define CONFIG_SYS_MAX_FLASH_SECT 1024 /* sectors per device */ +#define CONFIG_SYS_FLASH_ERASE_TOUT 60000 /* Flash Erase Timeout (ms) */ +#define CONFIG_SYS_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (ms) */ + +#define CONFIG_SYS_FLASH_EMPTY_INFO +#define CONFIG_SYS_FLASH_BANKS_LIST { CONFIG_SYS_FLASH_BASE,\ + CONFIG_SYS_FLASH_BASE + 0x40000000} +#endif + +#define CONFIG_NAND_FSL_IFC +#define CONFIG_SYS_NAND_MAX_ECCPOS 256 +#define CONFIG_SYS_NAND_MAX_OOBFREE 2 + + +#define CONFIG_SYS_NAND_CSPR_EXT (0x0) +#define CONFIG_SYS_NAND_CSPR (CSPR_PHYS_ADDR(CONFIG_SYS_NAND_BASE_PHYS) \ + | CSPR_PORT_SIZE_8 /* Port Size = 8 bit */ \ + | CSPR_MSEL_NAND /* MSEL = NAND */ \ + | CSPR_V) +#define CONFIG_SYS_NAND_AMASK IFC_AMASK(64 * 1024) + +#define CONFIG_SYS_NAND_CSOR (CSOR_NAND_ECC_ENC_EN /* ECC on encode */ \ + | CSOR_NAND_ECC_DEC_EN /* ECC on decode */ \ + | CSOR_NAND_ECC_MODE_4 /* 4-bit ECC */ \ + | CSOR_NAND_RAL_3 /* RAL = 3Byes */ \ + | CSOR_NAND_PGS_2K /* Page Size = 2K */ \ + | CSOR_NAND_SPRZ_64/* Spare size = 64 */ \ + | CSOR_NAND_PB(64)) /*Pages Per Block = 64*/ + +#define CONFIG_SYS_NAND_ONFI_DETECTION + +/* ONFI NAND Flash mode0 Timing Params */ +#define CONFIG_SYS_NAND_FTIM0 (FTIM0_NAND_TCCST(0x07) | \ + FTIM0_NAND_TWP(0x18) | \ + FTIM0_NAND_TWCHT(0x07) | \ + FTIM0_NAND_TWH(0x0a)) +#define CONFIG_SYS_NAND_FTIM1 (FTIM1_NAND_TADLE(0x32) | \ + FTIM1_NAND_TWBE(0x39) | \ + FTIM1_NAND_TRR(0x0e) | \ + FTIM1_NAND_TRP(0x18)) +#define CONFIG_SYS_NAND_FTIM2 (FTIM2_NAND_TRAD(0x0f) | \ + FTIM2_NAND_TREH(0x0a) | \ + FTIM2_NAND_TWHRE(0x1e)) +#define CONFIG_SYS_NAND_FTIM3 0x0 + +#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE } +#define CONFIG_SYS_MAX_NAND_DEVICE 1 +#define CONFIG_MTD_NAND_VERIFY_WRITE +#define CONFIG_CMD_NAND + +#define CONFIG_SYS_NAND_BLOCK_SIZE (128 * 1024) + +#define CONFIG_FSL_QIXIS /* use common QIXIS code */ +#define QIXIS_LBMAP_SWITCH 0x06 +#define QIXIS_LBMAP_MASK 0x0f +#define QIXIS_LBMAP_SHIFT 0 +#define QIXIS_LBMAP_DFLTBANK 0x00 +#define QIXIS_LBMAP_ALTBANK 0x04 +#define QIXIS_LBMAP_NAND 0x09 +#define QIXIS_RST_CTL_RESET 0x31 +#define QIXIS_RCFG_CTL_RECONFIG_IDLE 0x20 +#define QIXIS_RCFG_CTL_RECONFIG_START 0x21 +#define QIXIS_RCFG_CTL_WATCHDOG_ENBLE 0x08 +#define QIXIS_RCW_SRC_NAND 0x107 +#define QIXIS_RST_FORCE_MEM 0x01 + +#define CONFIG_SYS_CSPR3_EXT (0x0) +#define CONFIG_SYS_CSPR3 (CSPR_PHYS_ADDR(QIXIS_BASE_PHYS_EARLY) \ + | CSPR_PORT_SIZE_8 \ + | CSPR_MSEL_GPCM \ + | CSPR_V) +#define CONFIG_SYS_CSPR3_FINAL (CSPR_PHYS_ADDR(QIXIS_BASE_PHYS) \ + | CSPR_PORT_SIZE_8 \ + | CSPR_MSEL_GPCM \ + | CSPR_V) + +#define CONFIG_SYS_AMASK3 IFC_AMASK(64*1024) +#define CONFIG_SYS_CSOR3 CSOR_GPCM_ADM_SHIFT(12) +/* QIXIS Timing parameters for IFC CS3 */ +#define CONFIG_SYS_CS3_FTIM0 (FTIM0_GPCM_TACSE(0x0e) | \ + FTIM0_GPCM_TEADC(0x0e) | \ + FTIM0_GPCM_TEAHC(0x0e)) +#define CONFIG_SYS_CS3_FTIM1 (FTIM1_GPCM_TACO(0xff) | \ + FTIM1_GPCM_TRAD(0x3f)) +#define CONFIG_SYS_CS3_FTIM2 (FTIM2_GPCM_TCS(0xf) | \ + FTIM2_GPCM_TCH(0xf) | \ + FTIM2_GPCM_TWP(0x3E)) +#define CONFIG_SYS_CS3_FTIM3 0x0 + +#if defined(CONFIG_SPL) && defined(CONFIG_NAND) +#define CONFIG_SYS_CSPR1_EXT CONFIG_SYS_NOR0_CSPR_EXT +#define CONFIG_SYS_CSPR1 CONFIG_SYS_NOR0_CSPR_EARLY +#define CONFIG_SYS_CSPR1_FINAL CONFIG_SYS_NOR0_CSPR +#define CONFIG_SYS_AMASK1 CONFIG_SYS_NOR_AMASK +#define CONFIG_SYS_CSOR1 CONFIG_SYS_NOR_CSOR +#define CONFIG_SYS_CS1_FTIM0 CONFIG_SYS_NOR_FTIM0 +#define CONFIG_SYS_CS1_FTIM1 CONFIG_SYS_NOR_FTIM1 +#define CONFIG_SYS_CS1_FTIM2 CONFIG_SYS_NOR_FTIM2 +#define CONFIG_SYS_CS1_FTIM3 CONFIG_SYS_NOR_FTIM3 +#define CONFIG_SYS_CSPR2_EXT CONFIG_SYS_NOR0_CSPR_EXT +#define CONFIG_SYS_CSPR2 CONFIG_SYS_NOR1_CSPR_EARLY +#define CONFIG_SYS_CSPR2_FINAL CONFIG_SYS_NOR1_CSPR +#define CONFIG_SYS_AMASK2 CONFIG_SYS_NOR_AMASK_EARLY +#define CONFIG_SYS_AMASK2_FINAL CONFIG_SYS_NOR_AMASK +#define CONFIG_SYS_CSOR2 CONFIG_SYS_NOR_CSOR +#define CONFIG_SYS_CS2_FTIM0 CONFIG_SYS_NOR_FTIM0 +#define CONFIG_SYS_CS2_FTIM1 CONFIG_SYS_NOR_FTIM1 +#define CONFIG_SYS_CS2_FTIM2 CONFIG_SYS_NOR_FTIM2 +#define CONFIG_SYS_CS2_FTIM3 CONFIG_SYS_NOR_FTIM3 +#define CONFIG_SYS_CSPR0_EXT CONFIG_SYS_NAND_CSPR_EXT +#define CONFIG_SYS_CSPR0 CONFIG_SYS_NAND_CSPR +#define CONFIG_SYS_AMASK0 CONFIG_SYS_NAND_AMASK +#define CONFIG_SYS_CSOR0 CONFIG_SYS_NAND_CSOR +#define CONFIG_SYS_CS0_FTIM0 CONFIG_SYS_NAND_FTIM0 +#define CONFIG_SYS_CS0_FTIM1 CONFIG_SYS_NAND_FTIM1 +#define CONFIG_SYS_CS0_FTIM2 CONFIG_SYS_NAND_FTIM2 +#define CONFIG_SYS_CS0_FTIM3 CONFIG_SYS_NAND_FTIM3 + +#define CONFIG_ENV_IS_IN_NAND +#define CONFIG_ENV_OFFSET (896 * 1024) +#define CONFIG_ENV_SECT_SIZE 0x20000 +#define CONFIG_ENV_SIZE 0x2000 +#define CONFIG_SPL_PAD_TO 0x20000 +#define CONFIG_SYS_NAND_U_BOOT_OFFS (256 * 1024) +#define CONFIG_SYS_NAND_U_BOOT_SIZE (512 * 1024) +#else +#define CONFIG_SYS_CSPR0_EXT CONFIG_SYS_NOR0_CSPR_EXT +#define CONFIG_SYS_CSPR0 CONFIG_SYS_NOR0_CSPR_EARLY +#define CONFIG_SYS_CSPR0_FINAL CONFIG_SYS_NOR0_CSPR +#define CONFIG_SYS_AMASK0 CONFIG_SYS_NOR_AMASK +#define CONFIG_SYS_CSOR0 CONFIG_SYS_NOR_CSOR +#define CONFIG_SYS_CS0_FTIM0 CONFIG_SYS_NOR_FTIM0 +#define CONFIG_SYS_CS0_FTIM1 CONFIG_SYS_NOR_FTIM1 +#define CONFIG_SYS_CS0_FTIM2 CONFIG_SYS_NOR_FTIM2 +#define CONFIG_SYS_CS0_FTIM3 CONFIG_SYS_NOR_FTIM3 +#define CONFIG_SYS_CSPR1_EXT CONFIG_SYS_NOR0_CSPR_EXT +#define CONFIG_SYS_CSPR1 CONFIG_SYS_NOR1_CSPR_EARLY +#define CONFIG_SYS_CSPR1_FINAL CONFIG_SYS_NOR1_CSPR +#define CONFIG_SYS_AMASK1 CONFIG_SYS_NOR_AMASK_EARLY +#define CONFIG_SYS_AMASK1_FINAL CONFIG_SYS_NOR_AMASK +#define CONFIG_SYS_CSOR1 CONFIG_SYS_NOR_CSOR +#define CONFIG_SYS_CS1_FTIM0 CONFIG_SYS_NOR_FTIM0 +#define CONFIG_SYS_CS1_FTIM1 CONFIG_SYS_NOR_FTIM1 +#define CONFIG_SYS_CS1_FTIM2 CONFIG_SYS_NOR_FTIM2 +#define CONFIG_SYS_CS1_FTIM3 CONFIG_SYS_NOR_FTIM3 +#define CONFIG_SYS_CSPR2_EXT CONFIG_SYS_NAND_CSPR_EXT +#define CONFIG_SYS_CSPR2 CONFIG_SYS_NAND_CSPR +#define CONFIG_SYS_AMASK2 CONFIG_SYS_NAND_AMASK +#define CONFIG_SYS_CSOR2 CONFIG_SYS_NAND_CSOR +#define CONFIG_SYS_CS2_FTIM0 CONFIG_SYS_NAND_FTIM0 +#define CONFIG_SYS_CS2_FTIM1 CONFIG_SYS_NAND_FTIM1 +#define CONFIG_SYS_CS2_FTIM2 CONFIG_SYS_NAND_FTIM2 +#define CONFIG_SYS_CS2_FTIM3 CONFIG_SYS_NAND_FTIM3 + +#define CONFIG_ENV_IS_IN_FLASH +#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x200000) +#define CONFIG_ENV_SECT_SIZE 0x20000 +#define CONFIG_ENV_SIZE 0x2000 +#endif + +/* Debug Server firmware */ +#define CONFIG_SYS_DEBUG_SERVER_FW_IN_NOR +#define CONFIG_SYS_DEBUG_SERVER_FW_ADDR 0x580D00000ULL + +/* MC firmware */ +#define CONFIG_SYS_LS_MC_FW_IN_NOR +#define CONFIG_SYS_LS_MC_FW_ADDR 0x580300000ULL + +#define CONFIG_SYS_LS_MC_DPL_IN_NOR +#define CONFIG_SYS_LS_MC_DPL_ADDR 0x580700000ULL + +#define CONFIG_SYS_LS_MC_DPC_IN_NOR +#define CONFIG_SYS_LS_MC_DPC_ADDR 0x580800000ULL + +#define CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS 5000 + +/* + * I2C + */ +#define I2C_MUX_PCA_ADDR 0x77 +#define I2C_MUX_PCA_ADDR_PRI 0x77 /* Primary Mux*/ + +/* I2C bus multiplexer */ +#define I2C_MUX_CH_DEFAULT 0x8 + +/* + * MMC + */ +#ifdef CONFIG_MMC +#define CONFIG_ESDHC_DETECT_QUIRK ((readb(QIXIS_BASE + QIXIS_STAT_PRES1) & \ + QIXIS_SDID_MASK) != QIXIS_ESDHC_NO_ADAPTER) +#endif + +/* + * RTC configuration + */ +#define RTC +#define CONFIG_RTC_DS3231 1 +#define CONFIG_SYS_I2C_RTC_ADDR 0x68 + +/* EEPROM */ +#define CONFIG_ID_EEPROM +#define CONFIG_CMD_EEPROM +#define CONFIG_SYS_I2C_EEPROM_NXID +#define CONFIG_SYS_EEPROM_BUS_NUM 0 +#define CONFIG_SYS_I2C_EEPROM_ADDR 0x57 +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 3 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5 + +#define CONFIG_FSL_MEMAC +#define CONFIG_PCI /* Enable PCIE */ +#define CONFIG_PCIE_LAYERSCAPE /* Use common FSL Layerscape PCIe code */ + +#ifdef CONFIG_PCI +#define CONFIG_NET_MULTI +#define CONFIG_PCI_PNP +#define CONFIG_E1000 +#define CONFIG_PCI_SCAN_SHOW +#define CONFIG_CMD_PCI +#define CONFIG_CMD_NET +#endif + +/* MMC */ +#define CONFIG_MMC +#ifdef CONFIG_MMC +#define CONFIG_CMD_MMC +#define CONFIG_FSL_ESDHC +#define CONFIG_SYS_FSL_MMC_HAS_CAPBLT_VS33 +#define CONFIG_GENERIC_MMC +#define CONFIG_CMD_FAT +#define CONFIG_DOS_PARTITION +#endif + +/* Initial environment variables */ +#undef CONFIG_EXTRA_ENV_SETTINGS +#define CONFIG_EXTRA_ENV_SETTINGS \ + "hwconfig=fsl_ddr:bank_intlv=auto\0" \ + "loadaddr=0x80100000\0" \ + "kernel_addr=0x100000\0" \ + "ramdisk_addr=0x800000\0" \ + "ramdisk_size=0x2000000\0" \ + "fdt_high=0xa0000000\0" \ + "initrd_high=0xffffffffffffffff\0" \ + "kernel_start=0x581100000\0" \ + "kernel_load=0xa0000000\0" \ + "kernel_size=0x1000000\0" + +#ifdef CONFIG_FSL_MC_ENET +#define CONFIG_FSL_MEMAC +#define CONFIG_PHYLIB +#define CONFIG_PHYLIB_10G +#define CONFIG_CMD_MII +#define CONFIG_PHY_VITESSE +#define CONFIG_PHY_REALTEK +#define CONFIG_PHY_TERANETICS +#define SGMII_CARD_PORT1_PHY_ADDR 0x1C +#define SGMII_CARD_PORT2_PHY_ADDR 0x1d +#define SGMII_CARD_PORT3_PHY_ADDR 0x1E +#define SGMII_CARD_PORT4_PHY_ADDR 0x1F + +#define CONFIG_MII /* MII PHY management */ +#define CONFIG_ETHPRIME "DPNI1" +#define CONFIG_PHY_GIGE /* Include GbE speed/duplex detection */ + +#endif + +#endif /* __LS2_QDS_H */ diff --git a/include/configs/ls2085ardb.h b/include/configs/ls2085ardb.h new file mode 100644 index 0000000..d1c2548 --- /dev/null +++ b/include/configs/ls2085ardb.h @@ -0,0 +1,305 @@ +/* + * Copyright 2015 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __LS2_RDB_H +#define __LS2_RDB_H + +#include "ls2085a_common.h" +#include <config_cmd_default.h> + +#define CONFIG_IDENT_STRING " LS2085A-RDB" +#define CONFIG_BOOTP_VCI_STRING "U-boot.LS2085A-RDB" + +#undef CONFIG_CONS_INDEX +#define CONFIG_CONS_INDEX 2 + +#define CONFIG_DISPLAY_BOARDINFO + +#ifndef __ASSEMBLY__ +unsigned long get_board_sys_clk(void); +#endif + +#define CONFIG_SYS_CLK_FREQ get_board_sys_clk() +#define CONFIG_DDR_CLK_FREQ 133333333 +#define COUNTER_FREQUENCY_REAL (CONFIG_SYS_CLK_FREQ/4) + +#define CONFIG_DDR_SPD +#define CONFIG_DDR_ECC +#define CONFIG_ECC_INIT_VIA_DDRCONTROLLER +#define CONFIG_MEM_INIT_VALUE 0xdeadbeef +#define SPD_EEPROM_ADDRESS1 0x51 +#define SPD_EEPROM_ADDRESS2 0x52 +#define SPD_EEPROM_ADDRESS3 0x54 +#define SPD_EEPROM_ADDRESS4 0x53 /* Board error */ +#define SPD_EEPROM_ADDRESS5 0x55 +#define SPD_EEPROM_ADDRESS6 0x56 /* dummy address */ +#define SPD_EEPROM_ADDRESS SPD_EEPROM_ADDRESS1 +#define CONFIG_SYS_SPD_BUS_NUM 0 /* SPD on I2C bus 0 */ +#define CONFIG_DIMM_SLOTS_PER_CTLR 2 +#define CONFIG_CHIP_SELECTS_PER_CTRL 4 +#define CONFIG_DP_DDR_DIMM_SLOTS_PER_CTLR 1 +#define CONFIG_FSL_DDR_BIST /* enable built-in memory test */ + +/* undefined CONFIG_FSL_DDR_SYNC_REFRESH for simulator */ + +#define CONFIG_SYS_NOR0_CSPR_EXT (0x0) +#define CONFIG_SYS_NOR_AMASK IFC_AMASK(128*1024*1024) +#define CONFIG_SYS_NOR_AMASK_EARLY IFC_AMASK(64*1024*1024) + +#define CONFIG_SYS_NOR0_CSPR \ + (CSPR_PHYS_ADDR(CONFIG_SYS_FLASH_BASE_PHYS) | \ + CSPR_PORT_SIZE_16 | \ + CSPR_MSEL_NOR | \ + CSPR_V) +#define CONFIG_SYS_NOR0_CSPR_EARLY \ + (CSPR_PHYS_ADDR(CONFIG_SYS_FLASH_BASE_PHYS_EARLY) | \ + CSPR_PORT_SIZE_16 | \ + CSPR_MSEL_NOR | \ + CSPR_V) +#define CONFIG_SYS_NOR_CSOR CSOR_NOR_ADM_SHIFT(12) +#define CONFIG_SYS_NOR_FTIM0 (FTIM0_NOR_TACSE(0x4) | \ + FTIM0_NOR_TEADC(0x5) | \ + FTIM0_NOR_TEAHC(0x5)) +#define CONFIG_SYS_NOR_FTIM1 (FTIM1_NOR_TACO(0x35) | \ + FTIM1_NOR_TRAD_NOR(0x1a) |\ + FTIM1_NOR_TSEQRAD_NOR(0x13)) +#define CONFIG_SYS_NOR_FTIM2 (FTIM2_NOR_TCS(0x4) | \ + FTIM2_NOR_TCH(0x4) | \ + FTIM2_NOR_TWPH(0x0E) | \ + FTIM2_NOR_TWP(0x1c)) +#define CONFIG_SYS_NOR_FTIM3 0x04000000 +#define CONFIG_SYS_IFC_CCR 0x01000000 + +#ifndef CONFIG_SYS_NO_FLASH +#define CONFIG_FLASH_CFI_DRIVER +#define CONFIG_SYS_FLASH_CFI +#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE +#define CONFIG_SYS_FLASH_QUIET_TEST +#define CONFIG_FLASH_SHOW_PROGRESS 45 /* count down from 45/5: 9..1 */ + +#define CONFIG_SYS_MAX_FLASH_BANKS 1 /* number of banks */ +#define CONFIG_SYS_MAX_FLASH_SECT 1024 /* sectors per device */ +#define CONFIG_SYS_FLASH_ERASE_TOUT 60000 /* Flash Erase Timeout (ms) */ +#define CONFIG_SYS_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (ms) */ + +#define CONFIG_SYS_FLASH_EMPTY_INFO +#define CONFIG_SYS_FLASH_BANKS_LIST { CONFIG_SYS_FLASH_BASE,\ + CONFIG_SYS_FLASH_BASE + 0x40000000} +#endif + +#define CONFIG_NAND_FSL_IFC +#define CONFIG_SYS_NAND_MAX_ECCPOS 256 +#define CONFIG_SYS_NAND_MAX_OOBFREE 2 + + +#define CONFIG_SYS_NAND_CSPR_EXT (0x0) +#define CONFIG_SYS_NAND_CSPR (CSPR_PHYS_ADDR(CONFIG_SYS_NAND_BASE_PHYS) \ + | CSPR_PORT_SIZE_8 /* Port Size = 8 bit */ \ + | CSPR_MSEL_NAND /* MSEL = NAND */ \ + | CSPR_V) +#define CONFIG_SYS_NAND_AMASK IFC_AMASK(64 * 1024) + +#define CONFIG_SYS_NAND_CSOR (CSOR_NAND_ECC_ENC_EN /* ECC on encode */ \ + | CSOR_NAND_ECC_DEC_EN /* ECC on decode */ \ + | CSOR_NAND_ECC_MODE_4 /* 4-bit ECC */ \ + | CSOR_NAND_RAL_3 /* RAL = 3Byes */ \ + | CSOR_NAND_PGS_4K /* Page Size = 4K */ \ + | CSOR_NAND_SPRZ_224 /* Spare size = 224 */ \ + | CSOR_NAND_PB(128)) /* Pages Per Block 128*/ + +#define CONFIG_SYS_NAND_ONFI_DETECTION + +/* ONFI NAND Flash mode0 Timing Params */ +#define CONFIG_SYS_NAND_FTIM0 (FTIM0_NAND_TCCST(0x0e) | \ + FTIM0_NAND_TWP(0x30) | \ + FTIM0_NAND_TWCHT(0x0e) | \ + FTIM0_NAND_TWH(0x14)) +#define CONFIG_SYS_NAND_FTIM1 (FTIM1_NAND_TADLE(0x64) | \ + FTIM1_NAND_TWBE(0xab) | \ + FTIM1_NAND_TRR(0x1c) | \ + FTIM1_NAND_TRP(0x30)) +#define CONFIG_SYS_NAND_FTIM2 (FTIM2_NAND_TRAD(0x1e) | \ + FTIM2_NAND_TREH(0x14) | \ + FTIM2_NAND_TWHRE(0x3c)) +#define CONFIG_SYS_NAND_FTIM3 0x0 + +#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE } +#define CONFIG_SYS_MAX_NAND_DEVICE 1 +#define CONFIG_MTD_NAND_VERIFY_WRITE +#define CONFIG_CMD_NAND + +#define CONFIG_SYS_NAND_BLOCK_SIZE (512 * 1024) + +#define CONFIG_FSL_QIXIS /* use common QIXIS code */ +#define QIXIS_LBMAP_SWITCH 0x06 +#define QIXIS_LBMAP_MASK 0x0f +#define QIXIS_LBMAP_SHIFT 0 +#define QIXIS_LBMAP_DFLTBANK 0x00 +#define QIXIS_LBMAP_ALTBANK 0x04 +#define QIXIS_LBMAP_NAND 0x09 +#define QIXIS_RST_CTL_RESET 0x31 +#define QIXIS_RST_CTL_RESET_EN 0x30 +#define QIXIS_RCFG_CTL_RECONFIG_IDLE 0x20 +#define QIXIS_RCFG_CTL_RECONFIG_START 0x21 +#define QIXIS_RCFG_CTL_WATCHDOG_ENBLE 0x08 +#define QIXIS_RCW_SRC_NAND 0x119 +#define QIXIS_RST_FORCE_MEM 0x01 + +#define CONFIG_SYS_CSPR3_EXT (0x0) +#define CONFIG_SYS_CSPR3 (CSPR_PHYS_ADDR(QIXIS_BASE_PHYS_EARLY) \ + | CSPR_PORT_SIZE_8 \ + | CSPR_MSEL_GPCM \ + | CSPR_V) +#define CONFIG_SYS_CSPR3_FINAL (CSPR_PHYS_ADDR(QIXIS_BASE_PHYS) \ + | CSPR_PORT_SIZE_8 \ + | CSPR_MSEL_GPCM \ + | CSPR_V) + +#define CONFIG_SYS_AMASK3 IFC_AMASK(64*1024) +#define CONFIG_SYS_CSOR3 CSOR_GPCM_ADM_SHIFT(12) +/* QIXIS Timing parameters for IFC CS3 */ +#define CONFIG_SYS_CS3_FTIM0 (FTIM0_GPCM_TACSE(0x0e) | \ + FTIM0_GPCM_TEADC(0x0e) | \ + FTIM0_GPCM_TEAHC(0x0e)) +#define CONFIG_SYS_CS3_FTIM1 (FTIM1_GPCM_TACO(0xff) | \ + FTIM1_GPCM_TRAD(0x3f)) +#define CONFIG_SYS_CS3_FTIM2 (FTIM2_GPCM_TCS(0xf) | \ + FTIM2_GPCM_TCH(0xf) | \ + FTIM2_GPCM_TWP(0x3E)) +#define CONFIG_SYS_CS3_FTIM3 0x0 + +#if defined(CONFIG_SPL) && defined(CONFIG_NAND) +#define CONFIG_SYS_CSPR2_EXT CONFIG_SYS_NOR0_CSPR_EXT +#define CONFIG_SYS_CSPR2 CONFIG_SYS_NOR0_CSPR_EARLY +#define CONFIG_SYS_CSPR2_FINAL CONFIG_SYS_NOR0_CSPR +#define CONFIG_SYS_AMASK2 CONFIG_SYS_NOR_AMASK +#define CONFIG_SYS_CSOR2 CONFIG_SYS_NOR_CSOR +#define CONFIG_SYS_CS2_FTIM0 CONFIG_SYS_NOR_FTIM0 +#define CONFIG_SYS_CS2_FTIM1 CONFIG_SYS_NOR_FTIM1 +#define CONFIG_SYS_CS2_FTIM2 CONFIG_SYS_NOR_FTIM2 +#define CONFIG_SYS_CS2_FTIM3 CONFIG_SYS_NOR_FTIM3 +#define CONFIG_SYS_CSPR0_EXT CONFIG_SYS_NAND_CSPR_EXT +#define CONFIG_SYS_CSPR0 CONFIG_SYS_NAND_CSPR +#define CONFIG_SYS_AMASK0 CONFIG_SYS_NAND_AMASK +#define CONFIG_SYS_CSOR0 CONFIG_SYS_NAND_CSOR +#define CONFIG_SYS_CS0_FTIM0 CONFIG_SYS_NAND_FTIM0 +#define CONFIG_SYS_CS0_FTIM1 CONFIG_SYS_NAND_FTIM1 +#define CONFIG_SYS_CS0_FTIM2 CONFIG_SYS_NAND_FTIM2 +#define CONFIG_SYS_CS0_FTIM3 CONFIG_SYS_NAND_FTIM3 + +#define CONFIG_ENV_IS_IN_NAND +#define CONFIG_ENV_OFFSET (2048 * 1024) +#define CONFIG_ENV_SECT_SIZE 0x20000 +#define CONFIG_ENV_SIZE 0x2000 +#define CONFIG_SPL_PAD_TO 0x80000 +#define CONFIG_SYS_NAND_U_BOOT_OFFS (1024 * 1024) +#define CONFIG_SYS_NAND_U_BOOT_SIZE (512 * 1024) +#else +#define CONFIG_SYS_CSPR0_EXT CONFIG_SYS_NOR0_CSPR_EXT +#define CONFIG_SYS_CSPR0 CONFIG_SYS_NOR0_CSPR_EARLY +#define CONFIG_SYS_CSPR0_FINAL CONFIG_SYS_NOR0_CSPR +#define CONFIG_SYS_AMASK0 CONFIG_SYS_NOR_AMASK +#define CONFIG_SYS_CSOR0 CONFIG_SYS_NOR_CSOR +#define CONFIG_SYS_CS0_FTIM0 CONFIG_SYS_NOR_FTIM0 +#define CONFIG_SYS_CS0_FTIM1 CONFIG_SYS_NOR_FTIM1 +#define CONFIG_SYS_CS0_FTIM2 CONFIG_SYS_NOR_FTIM2 +#define CONFIG_SYS_CS0_FTIM3 CONFIG_SYS_NOR_FTIM3 +#define CONFIG_SYS_CSPR2_EXT CONFIG_SYS_NAND_CSPR_EXT +#define CONFIG_SYS_CSPR2 CONFIG_SYS_NAND_CSPR +#define CONFIG_SYS_AMASK2 CONFIG_SYS_NAND_AMASK +#define CONFIG_SYS_CSOR2 CONFIG_SYS_NAND_CSOR +#define CONFIG_SYS_CS2_FTIM0 CONFIG_SYS_NAND_FTIM0 +#define CONFIG_SYS_CS2_FTIM1 CONFIG_SYS_NAND_FTIM1 +#define CONFIG_SYS_CS2_FTIM2 CONFIG_SYS_NAND_FTIM2 +#define CONFIG_SYS_CS2_FTIM3 CONFIG_SYS_NAND_FTIM3 + +#define CONFIG_ENV_IS_IN_FLASH +#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x200000) +#define CONFIG_ENV_SECT_SIZE 0x20000 +#define CONFIG_ENV_SIZE 0x2000 +#endif + +/* Debug Server firmware */ +#define CONFIG_SYS_DEBUG_SERVER_FW_IN_NOR +#define CONFIG_SYS_DEBUG_SERVER_FW_ADDR 0x580D00000ULL + +/* MC firmware */ +#define CONFIG_SYS_LS_MC_FW_IN_NOR +#define CONFIG_SYS_LS_MC_FW_ADDR 0x580300000ULL + +#define CONFIG_SYS_LS_MC_DPL_IN_NOR +#define CONFIG_SYS_LS_MC_DPL_ADDR 0x580700000ULL + +#define CONFIG_SYS_LS_MC_DPC_IN_NOR +#define CONFIG_SYS_LS_MC_DPC_ADDR 0x580800000ULL + +#define CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS 5000 + +/* + * I2C + */ +#define I2C_MUX_PCA_ADDR 0x77 +#define I2C_MUX_PCA_ADDR_PRI 0x77 /* Primary Mux*/ + +/* I2C bus multiplexer */ +#define I2C_MUX_CH_DEFAULT 0x8 + +/* + * RTC configuration + */ +#define RTC +#define CONFIG_RTC_DS3231 1 +#define CONFIG_SYS_I2C_RTC_ADDR 0x68 + +/* EEPROM */ +#define CONFIG_ID_EEPROM +#define CONFIG_CMD_EEPROM +#define CONFIG_SYS_I2C_EEPROM_NXID +#define CONFIG_SYS_EEPROM_BUS_NUM 0 +#define CONFIG_SYS_I2C_EEPROM_ADDR 0x57 +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 3 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5 + +#define CONFIG_FSL_MEMAC +#define CONFIG_PCI /* Enable PCIE */ +#define CONFIG_PCIE_LAYERSCAPE /* Use common FSL Layerscape PCIe code */ + +#ifdef CONFIG_PCI +#define CONFIG_NET_MULTI +#define CONFIG_PCI_PNP +#define CONFIG_E1000 +#define CONFIG_PCI_SCAN_SHOW +#define CONFIG_CMD_PCI +#define CONFIG_CMD_NET +#endif + +/* MMC */ +#define CONFIG_MMC +#ifdef CONFIG_MMC +#define CONFIG_CMD_MMC +#define CONFIG_FSL_ESDHC +#define CONFIG_SYS_FSL_MMC_HAS_CAPBLT_VS33 +#define CONFIG_GENERIC_MMC +#define CONFIG_CMD_FAT +#define CONFIG_DOS_PARTITION +#endif + +/* Initial environment variables */ +#undef CONFIG_EXTRA_ENV_SETTINGS +#define CONFIG_EXTRA_ENV_SETTINGS \ + "hwconfig=fsl_ddr:bank_intlv=auto\0" \ + "loadaddr=0x80100000\0" \ + "kernel_addr=0x100000\0" \ + "ramdisk_addr=0x800000\0" \ + "ramdisk_size=0x2000000\0" \ + "fdt_high=0xa0000000\0" \ + "initrd_high=0xffffffffffffffff\0" \ + "kernel_start=0x581100000\0" \ + "kernel_load=0xa0000000\0" \ + "kernel_size=0x1000000\0" + +#endif /* __LS2_RDB_H */ diff --git a/include/configs/m53evk.h b/include/configs/m53evk.h index c133ba9..c348d38 100644 --- a/include/configs/m53evk.h +++ b/include/configs/m53evk.h @@ -176,6 +176,7 @@ #ifdef CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_RTC_BUS_NUM 1 /* I2C2 */ #endif diff --git a/include/configs/mx35pdk.h b/include/configs/mx35pdk.h index f8cd39d..244a9ab 100644 --- a/include/configs/mx35pdk.h +++ b/include/configs/mx35pdk.h @@ -42,6 +42,7 @@ */ #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_MXC_SPI #define CONFIG_MXC_GPIO diff --git a/include/configs/mx53ard.h b/include/configs/mx53ard.h index 9b003fc..7c3dc20 100644 --- a/include/configs/mx53ard.h +++ b/include/configs/mx53ard.h @@ -48,6 +48,7 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ /* MMC Configs */ #define CONFIG_FSL_ESDHC diff --git a/include/configs/mx53evk.h b/include/configs/mx53evk.h index fb2072d..22a9fc4 100644 --- a/include/configs/mx53evk.h +++ b/include/configs/mx53evk.h @@ -41,6 +41,7 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ /* PMIC Configs */ #define CONFIG_POWER diff --git a/include/configs/mx53loco.h b/include/configs/mx53loco.h index 3551e02..a56e72e 100644 --- a/include/configs/mx53loco.h +++ b/include/configs/mx53loco.h @@ -76,6 +76,7 @@ /* I2C Configs */ #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ /* PMIC Controller */ #define CONFIG_POWER diff --git a/include/configs/mx53smd.h b/include/configs/mx53smd.h index 3da0ef4..0785491 100644 --- a/include/configs/mx53smd.h +++ b/include/configs/mx53smd.h @@ -38,6 +38,7 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ /* MMC Configs */ #define CONFIG_FSL_ESDHC diff --git a/include/configs/mx6qsabreauto.h b/include/configs/mx6qsabreauto.h index 51042ca..2260344 100644 --- a/include/configs/mx6qsabreauto.h +++ b/include/configs/mx6qsabreauto.h @@ -56,6 +56,7 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_I2C_SPEED 100000 /* NAND flash command */ diff --git a/include/configs/mx6sabresd.h b/include/configs/mx6sabresd.h index 99d9d4d..dab2fd2 100644 --- a/include/configs/mx6sabresd.h +++ b/include/configs/mx6sabresd.h @@ -52,6 +52,7 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_I2C_SPEED 100000 /* PMIC */ diff --git a/include/configs/mx6slevk.h b/include/configs/mx6slevk.h index dad49f9..cd023de 100644 --- a/include/configs/mx6slevk.h +++ b/include/configs/mx6slevk.h @@ -52,6 +52,7 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_I2C_SPEED 100000 /* PMIC */ diff --git a/include/configs/mx6sxsabresd.h b/include/configs/mx6sxsabresd.h index a29d62f..248303c 100644 --- a/include/configs/mx6sxsabresd.h +++ b/include/configs/mx6sxsabresd.h @@ -176,6 +176,7 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_I2C_SPEED 100000 /* PMIC */ diff --git a/include/configs/nitrogen6x.h b/include/configs/nitrogen6x.h index 8ef4b73..883d8a7 100644 --- a/include/configs/nitrogen6x.h +++ b/include/configs/nitrogen6x.h @@ -63,6 +63,7 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_I2C_EDID diff --git a/include/configs/novena.h b/include/configs/novena.h index 3809c6c..5f83469 100644 --- a/include/configs/novena.h +++ b/include/configs/novena.h @@ -141,6 +141,7 @@ /* I2C */ #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_I2C_MULTI_BUS #define CONFIG_I2C_MXC #define CONFIG_SYS_I2C_SPEED 100000 diff --git a/include/configs/ot1200.h b/include/configs/ot1200.h index 3c60b4f..200f40a 100644 --- a/include/configs/ot1200.h +++ b/include/configs/ot1200.h @@ -62,6 +62,7 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_I2C_SPEED 100000 /* OCOTP Configs */ diff --git a/include/configs/platinum.h b/include/configs/platinum.h index 134bb45..91ffc7c 100644 --- a/include/configs/platinum.h +++ b/include/configs/platinum.h @@ -62,6 +62,7 @@ /* I2C config */ #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_I2C_SPEED 100000 /* MMC config */ diff --git a/include/configs/tbs2910.h b/include/configs/tbs2910.h index 7089378..3a88f22 100644 --- a/include/configs/tbs2910.h +++ b/include/configs/tbs2910.h @@ -199,6 +199,7 @@ #ifdef CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_I2C_EDID #endif diff --git a/include/configs/titanium.h b/include/configs/titanium.h index f9e00c5..320d76c 100644 --- a/include/configs/titanium.h +++ b/include/configs/titanium.h @@ -44,6 +44,7 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_I2C_SPEED 100000 /* MMC Configs */ diff --git a/include/configs/tqma6.h b/include/configs/tqma6.h index a099687..99c5f82 100644 --- a/include/configs/tqma6.h +++ b/include/configs/tqma6.h @@ -80,6 +80,7 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_I2C_MULTI_BUS #define CONFIG_SYS_I2C_SPEED 100000 diff --git a/include/configs/wandboard.h b/include/configs/wandboard.h index b586803..b2c3614 100644 --- a/include/configs/wandboard.h +++ b/include/configs/wandboard.h @@ -62,6 +62,7 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_I2C_SPEED 100000 /* MMC Configuration */ diff --git a/include/configs/woodburn_common.h b/include/configs/woodburn_common.h index 48b8692..d0895cf 100644 --- a/include/configs/woodburn_common.h +++ b/include/configs/woodburn_common.h @@ -47,6 +47,7 @@ */ #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ #define CONFIG_SYS_SPD_BUS_NUM 0 #define CONFIG_MXC_SPI #define CONFIG_MXC_GPIO diff --git a/include/fsl-mc/fsl_dpaa_fd.h b/include/fsl-mc/fsl_dpaa_fd.h new file mode 100644 index 0000000..6d0ffa8 --- /dev/null +++ b/include/fsl-mc/fsl_dpaa_fd.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef __FSL_DPAA_FD_H +#define __FSL_DPAA_FD_H + +/* Place-holder for FDs, we represent it via the simplest form that we need for + * now. Different overlays may be needed to support different options, etc. (It + * is impractical to define One True Struct, because the resulting encoding + * routines (lots of read-modify-writes) would be worst-case performance whether + * or not circumstances required them.) */ +struct dpaa_fd { + union { + u32 words[8]; + struct dpaa_fd_simple { + u32 addr_lo; + u32 addr_hi; + u32 len; + /* offset in the MS 16 bits, BPID in the LS 16 bits */ + u32 bpid_offset; + u32 frc; /* frame context */ + /* "err", "va", "cbmt", "asal", [...] */ + u32 ctrl; + /* flow context */ + u32 flc_lo; + u32 flc_hi; + } simple; + }; +}; + +enum dpaa_fd_format { + dpaa_fd_single = 0, + dpaa_fd_list, + dpaa_fd_sg +}; + +static inline u64 ldpaa_fd_get_addr(const struct dpaa_fd *fd) +{ + return (u64)((((uint64_t)fd->simple.addr_hi) << 32) + + fd->simple.addr_lo); +} + +static inline void ldpaa_fd_set_addr(struct dpaa_fd *fd, u64 addr) +{ + fd->simple.addr_hi = upper_32_bits(addr); + fd->simple.addr_lo = lower_32_bits(addr); +} + +static inline u32 ldpaa_fd_get_len(const struct dpaa_fd *fd) +{ + return fd->simple.len; +} + +static inline void ldpaa_fd_set_len(struct dpaa_fd *fd, u32 len) +{ + fd->simple.len = len; +} + +static inline uint16_t ldpaa_fd_get_offset(const struct dpaa_fd *fd) +{ + return (uint16_t)(fd->simple.bpid_offset >> 16) & 0x0FFF; +} + +static inline void ldpaa_fd_set_offset(struct dpaa_fd *fd, uint16_t offset) +{ + fd->simple.bpid_offset &= 0xF000FFFF; + fd->simple.bpid_offset |= (u32)offset << 16; +} + +static inline uint16_t ldpaa_fd_get_bpid(const struct dpaa_fd *fd) +{ + return (uint16_t)(fd->simple.bpid_offset & 0xFFFF); +} + +static inline void ldpaa_fd_set_bpid(struct dpaa_fd *fd, uint16_t bpid) +{ + fd->simple.bpid_offset &= 0xFFFF0000; + fd->simple.bpid_offset |= (u32)bpid; +} + +/* When frames are dequeued, the FDs show up inside "dequeue" result structures + * (if at all, not all dequeue results contain valid FDs). This structure type + * is intentionally defined without internal detail, and the only reason it + * isn't declared opaquely (without size) is to allow the user to provide + * suitably-sized (and aligned) memory for these entries. */ +struct ldpaa_dq { + uint32_t dont_manipulate_directly[16]; +}; + +/* Parsing frame dequeue results */ +#define LDPAA_DQ_STAT_FQEMPTY 0x80 +#define LDPAA_DQ_STAT_HELDACTIVE 0x40 +#define LDPAA_DQ_STAT_FORCEELIGIBLE 0x20 +#define LDPAA_DQ_STAT_VALIDFRAME 0x10 +#define LDPAA_DQ_STAT_ODPVALID 0x04 +#define LDPAA_DQ_STAT_VOLATILE 0x02 +#define LDPAA_DQ_STAT_EXPIRED 0x01 +uint32_t ldpaa_dq_flags(const struct ldpaa_dq *); +static inline int ldpaa_dq_is_pull(const struct ldpaa_dq *dq) +{ + return (int)(ldpaa_dq_flags(dq) & LDPAA_DQ_STAT_VOLATILE); +} +static inline int ldpaa_dq_is_pull_complete( + const struct ldpaa_dq *dq) +{ + return (int)(ldpaa_dq_flags(dq) & LDPAA_DQ_STAT_EXPIRED); +} +/* seqnum/odpid are valid only if VALIDFRAME and ODPVALID flags are TRUE */ +uint16_t ldpaa_dq_seqnum(const struct ldpaa_dq *); +uint16_t ldpaa_dq_odpid(const struct ldpaa_dq *); +uint32_t ldpaa_dq_fqid(const struct ldpaa_dq *); +uint32_t ldpaa_dq_byte_count(const struct ldpaa_dq *); +uint32_t ldpaa_dq_frame_count(const struct ldpaa_dq *); +uint32_t ldpaa_dq_fqd_ctx_hi(const struct ldpaa_dq *); +uint32_t ldpaa_dq_fqd_ctx_lo(const struct ldpaa_dq *); +/* get the Frame Descriptor */ +const struct dpaa_fd *ldpaa_dq_fd(const struct ldpaa_dq *); + +#endif /* __FSL_DPAA_FD_H */ diff --git a/include/fsl-mc/fsl_dpbp.h b/include/fsl-mc/fsl_dpbp.h new file mode 100644 index 0000000..7f0075c --- /dev/null +++ b/include/fsl-mc/fsl_dpbp.h @@ -0,0 +1,143 @@ +/* + * Freescale Layerscape MC I/O wrapper + * + * Copyright (C) 2013-2015 Freescale Semiconductor, Inc. + * Author: German Rivera <German.Rivera@freescale.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +/*! + * @file fsl_dpbp.h + * @brief Data Path Buffer Pool API + */ +#ifndef __FSL_DPBP_H +#define __FSL_DPBP_H + +/* DPBP Version */ +#define DPBP_VER_MAJOR 2 +#define DPBP_VER_MINOR 0 + +/* Command IDs */ +#define DPBP_CMDID_CLOSE 0x800 +#define DPBP_CMDID_OPEN 0x804 + +#define DPBP_CMDID_ENABLE 0x002 +#define DPBP_CMDID_DISABLE 0x003 +#define DPBP_CMDID_GET_ATTR 0x004 +#define DPBP_CMDID_RESET 0x005 + +/* cmd, param, offset, width, type, arg_name */ +#define DPBP_CMD_OPEN(cmd, dpbp_id) \ + MC_CMD_OP(cmd, 0, 0, 32, int, dpbp_id) + +/* cmd, param, offset, width, type, arg_name */ +#define DPBP_RSP_GET_ATTRIBUTES(cmd, attr) \ +do { \ + MC_RSP_OP(cmd, 0, 16, 16, uint16_t, attr->bpid); \ + MC_RSP_OP(cmd, 0, 32, 32, int, attr->id);\ + MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ + MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ +} while (0) + +/* Data Path Buffer Pool API + * Contains initialization APIs and runtime control APIs for DPBP + */ + +struct fsl_mc_io; + +/** + * dpbp_open() - Open a control session for the specified object. + * @mc_io: Pointer to MC portal's I/O object + * @dpbp_id: DPBP unique ID + * @token: Returned token; use in subsequent API calls + * + * This function can be used to open a control session for an + * already created object; an object may have been declared in + * the DPL or by calling the dpbp_create function. + * This function returns a unique authentication token, + * associated with the specific object ID and the specific MC + * portal; this token must be used in all subsequent commands for + * this specific object + * + * Return: '0' on Success; Error code otherwise. + */ +int dpbp_open(struct fsl_mc_io *mc_io, int dpbp_id, uint16_t *token); + +/** + * dpbp_close() - Close the control session of the object + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPBP object + * + * After this function is called, no further operations are + * allowed on the object without opening a new control session. + * + * Return: '0' on Success; Error code otherwise. + */ +int dpbp_close(struct fsl_mc_io *mc_io, uint16_t token); + +/** + * dpbp_enable() - Enable the DPBP. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPBP object + * + * Return: '0' on Success; Error code otherwise. + */ + +int dpbp_enable(struct fsl_mc_io *mc_io, uint16_t token); + +/** + * dpbp_disable() - Disable the DPBP. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPBP object + * + * Return: '0' on Success; Error code otherwise. + */ +int dpbp_disable(struct fsl_mc_io *mc_io, uint16_t token); + +/** + * dpbp_reset() - Reset the DPBP, returns the object to initial state. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPBP object + * + * Return: '0' on Success; Error code otherwise. + */ +int dpbp_reset(struct fsl_mc_io *mc_io, uint16_t token); + +/** + * struct dpbp_attr - Structure representing DPBP attributes + * @id: DPBP object ID + * @version: DPBP version + * @bpid: Hardware buffer pool ID; should be used as an argument in + * acquire/release operations on buffers + */ +struct dpbp_attr { + int id; + /** + * struct version - Structure representing DPBP version + * @major: DPBP major version + * @minor: DPBP minor version + */ + struct { + uint16_t major; + uint16_t minor; + } version; + uint16_t bpid; +}; + + +/** + * dpbp_get_attributes - Retrieve DPBP attributes. + * + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPBP object + * @attr: Returned object's attributes + * + * Return: '0' on Success; Error code otherwise. + */ +int dpbp_get_attributes(struct fsl_mc_io *mc_io, + uint16_t token, + struct dpbp_attr *attr); + +/** @} */ + +#endif /* __FSL_DPBP_H */ diff --git a/include/fsl-mc/fsl_dpio.h b/include/fsl-mc/fsl_dpio.h new file mode 100644 index 0000000..e84b419 --- /dev/null +++ b/include/fsl-mc/fsl_dpio.h @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2013-2015 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _FSL_DPIO_H +#define _FSL_DPIO_H + +/* DPIO Version */ +#define DPIO_VER_MAJOR 2 +#define DPIO_VER_MINOR 1 + +/* Command IDs */ +#define DPIO_CMDID_CLOSE 0x800 +#define DPIO_CMDID_OPEN 0x803 + +#define DPIO_CMDID_ENABLE 0x002 +#define DPIO_CMDID_DISABLE 0x003 +#define DPIO_CMDID_GET_ATTR 0x004 +#define DPIO_CMDID_RESET 0x005 + +/* cmd, param, offset, width, type, arg_name */ +#define DPIO_CMD_OPEN(cmd, dpio_id) \ + MC_CMD_OP(cmd, 0, 0, 32, int, dpio_id) + +/* cmd, param, offset, width, type, arg_name */ +#define DPIO_RSP_GET_ATTR(cmd, attr) \ +do { \ + MC_RSP_OP(cmd, 0, 0, 32, int, attr->id);\ + MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->qbman_portal_id);\ + MC_RSP_OP(cmd, 0, 48, 8, uint8_t, attr->num_priorities);\ + MC_RSP_OP(cmd, 0, 56, 4, enum dpio_channel_mode, attr->channel_mode);\ + MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->qbman_portal_ce_paddr);\ + MC_RSP_OP(cmd, 2, 0, 64, uint64_t, attr->qbman_portal_ci_paddr);\ + MC_RSP_OP(cmd, 3, 0, 16, uint16_t, attr->version.major);\ + MC_RSP_OP(cmd, 3, 16, 16, uint16_t, attr->version.minor);\ +} while (0) + +/* Data Path I/O Portal API + * Contains initialization APIs and runtime control APIs for DPIO + */ + +struct fsl_mc_io; +/** + * dpio_open() - Open a control session for the specified object + * @mc_io: Pointer to MC portal's I/O object + * @dpio_id: DPIO unique ID + * @token: Returned token; use in subsequent API calls + * + * This function can be used to open a control session for an + * already created object; an object may have been declared in + * the DPL or by calling the dpio_create() function. + * This function returns a unique authentication token, + * associated with the specific object ID and the specific MC + * portal; this token must be used in all subsequent commands for + * this specific object. + * + * Return: '0' on Success; Error code otherwise. + */ +int dpio_open(struct fsl_mc_io *mc_io, int dpio_id, uint16_t *token); + +/** + * dpio_open() - Open a control session for the specified object + * @mc_io: Pointer to MC portal's I/O object + * @dpio_id: DPIO unique ID + * @token: Returned token; use in subsequent API calls + * + * This function can be used to open a control session for an + * already created object; an object may have been declared in + * the DPL or by calling the dpio_create() function. + * This function returns a unique authentication token, + * associated with the specific object ID and the specific MC + * portal; this token must be used in all subsequent commands for + * this specific object. + * + * Return: '0' on Success; Error code otherwise. + */ +int dpio_close(struct fsl_mc_io *mc_io, uint16_t token); + +/** + * enum dpio_channel_mode - DPIO notification channel mode + * @DPIO_NO_CHANNEL: No support for notification channel + * @DPIO_LOCAL_CHANNEL: Notifications on data availability can be received by a + * dedicated channel in the DPIO; user should point the queue's + * destination in the relevant interface to this DPIO + */ +enum dpio_channel_mode { + DPIO_NO_CHANNEL = 0, + DPIO_LOCAL_CHANNEL = 1, +}; + +/** + * dpio_enable() - Enable the DPIO, allow I/O portal operations. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPIO object + * + * Return: '0' on Success; Error code otherwise + */ +int dpio_enable(struct fsl_mc_io *mc_io, uint16_t token); + +/** + * dpio_disable() - Disable the DPIO, stop any I/O portal operation. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPIO object + * + * Return: '0' on Success; Error code otherwise + */ +int dpio_disable(struct fsl_mc_io *mc_io, uint16_t token); + +/** + * dpio_reset() - Reset the DPIO, returns the object to initial state. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPIO object + * + * Return: '0' on Success; Error code otherwise. + */ +int dpio_reset(struct fsl_mc_io *mc_io, uint16_t token); + +/** + * struct dpio_attr - Structure representing DPIO attributes + * @id: DPIO object ID + * @version: DPIO version + * @qbman_portal_ce_paddr: Physical address of the software portal + * cache-enabled area + * @qbman_portal_ci_paddr: Physical address of the software portal + * cache-inhibited area + * @qbman_portal_id: Software portal ID + * @channel_mode: Notification channel mode + * @num_priorities: Number of priorities for the notification channel (1-8); + * relevant only if 'channel_mode = DPIO_LOCAL_CHANNEL' + */ +struct dpio_attr { + int id; + /** + * struct version - DPIO version + * @major: DPIO major version + * @minor: DPIO minor version + */ + struct { + uint16_t major; + uint16_t minor; + } version; + uint64_t qbman_portal_ce_paddr; + uint64_t qbman_portal_ci_paddr; + uint16_t qbman_portal_id; + enum dpio_channel_mode channel_mode; + uint8_t num_priorities; +}; + +/** + * dpio_get_attributes() - Retrieve DPIO attributes + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPIO object + * @attr: Returned object's attributes + * + * Return: '0' on Success; Error code otherwise + */ +int dpio_get_attributes(struct fsl_mc_io *mc_io, + uint16_t token, + struct dpio_attr *attr); + +#endif /* _FSL_DPIO_H */ diff --git a/include/fsl-mc/fsl_dpmng.h b/include/fsl-mc/fsl_dpmng.h index c2e1ddd..986e7c8 100644 --- a/include/fsl-mc/fsl_dpmng.h +++ b/include/fsl-mc/fsl_dpmng.h @@ -1,121 +1,44 @@ -/* Copyright 2014 Freescale Semiconductor Inc. +/* Copyright 2013-2015 Freescale Semiconductor Inc. * * SPDX-License-Identifier: GPL-2.0+ */ -/*! - * @file fsl_dpmng.h - * @brief Management Complex General API - */ - #ifndef __FSL_DPMNG_H #define __FSL_DPMNG_H -/*! - * @Group grp_dpmng Management Complex General API - * - * @brief Contains general API for the Management Complex firmware - * @{ +/* Management Complex General API + * Contains general API for the Management Complex firmware */ struct fsl_mc_io; /** - * @brief Management Complex firmware version information + * Management Complex firmware version information */ -#define MC_VER_MAJOR 4 +#define MC_VER_MAJOR 6 #define MC_VER_MINOR 0 +/** + * struct mc_versoin + * @major: Major version number: incremented on API compatibility changes + * @minor: Minor version number: incremented on API additions (that are + * backward compatible); reset when major version is incremented + * @revision: Internal revision number: incremented on implementation changes + * and/or bug fixes that have no impact on API + */ struct mc_version { uint32_t major; - /*!< Major version number: incremented on API compatibility changes */ uint32_t minor; - /*!< Minor version number: incremented on API additions (that are - * backward compatible); reset when major version is incremented - */ uint32_t revision; - /*!< Internal revision number: incremented on implementation changes - * and/or bug fixes that have no impact on API - */ }; /** - * @brief Retrieves the Management Complex firmware version information - * - * @param[in] mc_io Pointer to opaque I/O object - * @param[out] mc_ver_info Pointer to version information structure + * mc_get_version() - Retrieves the Management Complex firmware + * version information + * @mc_io: Pointer to opaque I/O object + * @mc_ver_info: Returned version information structure * - * @returns '0' on Success; Error code otherwise. + * Return: '0' on Success; Error code otherwise. */ int mc_get_version(struct fsl_mc_io *mc_io, struct mc_version *mc_ver_info); -/** - * @brief Resets an AIOP tile - * - * @param[in] mc_io Pointer to opaque I/O object - * @param[in] container_id AIOP container ID - * @param[in] aiop_tile_id AIOP tile ID to reset - * - * @returns '0' on Success; Error code otherwise. - */ -int dpmng_reset_aiop(struct fsl_mc_io *mc_io, - int container_id, - int aiop_tile_id); - -/** - * @brief Loads an image to AIOP tile - * - * @param[in] mc_io Pointer to opaque I/O object - * @param[in] container_id AIOP container ID - * @param[in] aiop_tile_id AIOP tile ID to reset - * @param[in] img_iova I/O virtual address of AIOP ELF image - * @param[in] img_size Size of AIOP ELF image in memory (in bytes) - * - * @returns '0' on Success; Error code otherwise. - */ -int dpmng_load_aiop(struct fsl_mc_io *mc_io, - int container_id, - int aiop_tile_id, - uint64_t img_iova, - uint32_t img_size); - -/** - * @brief AIOP run configuration - */ -struct dpmng_aiop_run_cfg { - uint32_t cores_mask; - /*!< Mask of AIOP cores to run (core 0 in most significant bit) */ - uint64_t options; - /*!< Execution options (currently none defined) */ -}; - -/** - * @brief Starts AIOP tile execution - * - * @param[in] mc_io Pointer to MC portal's I/O object - * @param[in] container_id AIOP container ID - * @param[in] aiop_tile_id AIOP tile ID to reset - * @param[in] cfg AIOP run configuration - * - * @returns '0' on Success; Error code otherwise. - */ -int dpmng_run_aiop(struct fsl_mc_io *mc_io, - int container_id, - int aiop_tile_id, - const struct dpmng_aiop_run_cfg *cfg); - -/** - * @brief Resets MC portal - * - * This function closes all object handles (tokens) that are currently - * open in the MC portal on which the command is submitted. This allows - * cleanup of stale handles that belong to non-functional user processes. - * - * @param[in] mc_io Pointer to MC portal's I/O object - * - * @returns '0' on Success; Error code otherwise. - */ -int dpmng_reset_mc_portal(struct fsl_mc_io *mc_io); - -/** @} */ - #endif /* __FSL_DPMNG_H */ diff --git a/include/fsl-mc/fsl_dpni.h b/include/fsl-mc/fsl_dpni.h new file mode 100644 index 0000000..67c087d --- /dev/null +++ b/include/fsl-mc/fsl_dpni.h @@ -0,0 +1,1093 @@ +/* + * Copyright (C) 2013-2015 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef _FSL_DPNI_H +#define _FSL_DPNI_H + +/* DPNI Version */ +#define DPNI_VER_MAJOR 4 +#define DPNI_VER_MINOR 0 + +/* Command IDs */ +#define DPNI_CMDID_OPEN 0x801 +#define DPNI_CMDID_CLOSE 0x800 + +#define DPNI_CMDID_ENABLE 0x002 +#define DPNI_CMDID_DISABLE 0x003 +#define DPNI_CMDID_GET_ATTR 0x004 +#define DPNI_CMDID_RESET 0x005 + +#define DPNI_CMDID_SET_POOLS 0x200 +#define DPNI_CMDID_GET_RX_BUFFER_LAYOUT 0x201 +#define DPNI_CMDID_SET_RX_BUFFER_LAYOUT 0x202 +#define DPNI_CMDID_GET_TX_BUFFER_LAYOUT 0x203 +#define DPNI_CMDID_SET_TX_BUFFER_LAYOUT 0x204 +#define DPNI_CMDID_SET_TX_CONF_BUFFER_LAYOUT 0x205 +#define DPNI_CMDID_GET_TX_CONF_BUFFER_LAYOUT 0x206 + +#define DPNI_CMDID_GET_QDID 0x210 +#define DPNI_CMDID_GET_TX_DATA_OFFSET 0x212 +#define DPNI_CMDID_GET_COUNTER 0x213 +#define DPNI_CMDID_SET_COUNTER 0x214 +#define DPNI_CMDID_GET_LINK_STATE 0x215 +#define DPNI_CMDID_SET_LINK_CFG 0x21A + +#define DPNI_CMDID_SET_PRIM_MAC 0x224 +#define DPNI_CMDID_GET_PRIM_MAC 0x225 +#define DPNI_CMDID_ADD_MAC_ADDR 0x226 +#define DPNI_CMDID_REMOVE_MAC_ADDR 0x227 + +#define DPNI_CMDID_SET_TX_FLOW 0x236 +#define DPNI_CMDID_GET_TX_FLOW 0x237 +#define DPNI_CMDID_SET_RX_FLOW 0x238 +#define DPNI_CMDID_GET_RX_FLOW 0x239 + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_CMD_OPEN(cmd, dpni_id) \ + MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id) + + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_CMD_SET_POOLS(cmd, cfg) \ +do { \ + MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->num_dpbp); \ + MC_CMD_OP(cmd, 0, 32, 32, int, cfg->pools[0].dpbp_id); \ + MC_CMD_OP(cmd, 4, 32, 16, uint16_t, cfg->pools[0].buffer_size);\ + MC_CMD_OP(cmd, 1, 0, 32, int, cfg->pools[1].dpbp_id); \ + MC_CMD_OP(cmd, 4, 48, 16, uint16_t, cfg->pools[1].buffer_size);\ + MC_CMD_OP(cmd, 1, 32, 32, int, cfg->pools[2].dpbp_id); \ + MC_CMD_OP(cmd, 5, 0, 16, uint16_t, cfg->pools[2].buffer_size);\ + MC_CMD_OP(cmd, 2, 0, 32, int, cfg->pools[3].dpbp_id); \ + MC_CMD_OP(cmd, 5, 16, 16, uint16_t, cfg->pools[3].buffer_size);\ + MC_CMD_OP(cmd, 2, 32, 32, int, cfg->pools[4].dpbp_id); \ + MC_CMD_OP(cmd, 5, 32, 16, uint16_t, cfg->pools[4].buffer_size);\ + MC_CMD_OP(cmd, 3, 0, 32, int, cfg->pools[5].dpbp_id); \ + MC_CMD_OP(cmd, 5, 48, 16, uint16_t, cfg->pools[5].buffer_size);\ + MC_CMD_OP(cmd, 3, 32, 32, int, cfg->pools[6].dpbp_id); \ + MC_CMD_OP(cmd, 6, 0, 16, uint16_t, cfg->pools[6].buffer_size);\ + MC_CMD_OP(cmd, 4, 0, 32, int, cfg->pools[7].dpbp_id); \ + MC_CMD_OP(cmd, 6, 16, 16, uint16_t, cfg->pools[7].buffer_size);\ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_RSP_GET_ATTR(cmd, attr) \ +do { \ + MC_RSP_OP(cmd, 0, 0, 32, int, attr->id);\ + MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->max_tcs); \ + MC_RSP_OP(cmd, 0, 40, 8, uint8_t, attr->max_senders); \ + MC_RSP_OP(cmd, 0, 48, 8, enum net_prot, attr->start_hdr); \ + MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->options); \ + MC_RSP_OP(cmd, 2, 0, 8, uint8_t, attr->max_unicast_filters); \ + MC_RSP_OP(cmd, 2, 8, 8, uint8_t, attr->max_multicast_filters);\ + MC_RSP_OP(cmd, 2, 16, 8, uint8_t, attr->max_vlan_filters); \ + MC_RSP_OP(cmd, 2, 24, 8, uint8_t, attr->max_qos_entries); \ + MC_RSP_OP(cmd, 2, 32, 8, uint8_t, attr->max_qos_key_size); \ + MC_RSP_OP(cmd, 2, 40, 8, uint8_t, attr->max_dist_key_size); \ + MC_RSP_OP(cmd, 3, 0, 8, uint8_t, attr->max_dist_per_tc[0]); \ + MC_RSP_OP(cmd, 3, 8, 8, uint8_t, attr->max_dist_per_tc[1]); \ + MC_RSP_OP(cmd, 3, 16, 8, uint8_t, attr->max_dist_per_tc[2]); \ + MC_RSP_OP(cmd, 3, 24, 8, uint8_t, attr->max_dist_per_tc[3]); \ + MC_RSP_OP(cmd, 3, 32, 8, uint8_t, attr->max_dist_per_tc[4]); \ + MC_RSP_OP(cmd, 3, 40, 8, uint8_t, attr->max_dist_per_tc[5]); \ + MC_RSP_OP(cmd, 3, 48, 8, uint8_t, attr->max_dist_per_tc[6]); \ + MC_RSP_OP(cmd, 3, 56, 8, uint8_t, attr->max_dist_per_tc[7]); \ + MC_RSP_OP(cmd, 4, 0, 16, uint16_t, \ + attr->ipr_cfg.max_reass_frm_size); \ + MC_RSP_OP(cmd, 4, 16, 16, uint16_t, \ + attr->ipr_cfg.min_frag_size_ipv4); \ + MC_RSP_OP(cmd, 4, 32, 16, uint16_t, \ + attr->ipr_cfg.min_frag_size_ipv6); \ + MC_RSP_OP(cmd, 5, 0, 16, uint16_t, \ + attr->ipr_cfg.max_open_frames_ipv4); \ + MC_RSP_OP(cmd, 5, 16, 16, uint16_t, \ + attr->ipr_cfg.max_open_frames_ipv6); \ + MC_RSP_OP(cmd, 5, 32, 16, uint16_t, attr->version.major);\ + MC_RSP_OP(cmd, 5, 48, 16, uint16_t, attr->version.minor);\ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_RSP_GET_RX_BUFFER_LAYOUT(cmd, layout) \ +do { \ + MC_RSP_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ + MC_RSP_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ + MC_RSP_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ + MC_RSP_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ + MC_RSP_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ + MC_RSP_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ + MC_RSP_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_CMD_SET_RX_BUFFER_LAYOUT(cmd, layout) \ +do { \ + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ + MC_CMD_OP(cmd, 0, 32, 32, uint32_t, layout->options); \ + MC_CMD_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ + MC_CMD_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ + MC_CMD_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ + MC_CMD_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ + MC_CMD_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_RSP_GET_TX_BUFFER_LAYOUT(cmd, layout) \ +do { \ + MC_RSP_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ + MC_RSP_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ + MC_RSP_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ + MC_RSP_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ + MC_RSP_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ + MC_RSP_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ + MC_RSP_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_CMD_SET_TX_BUFFER_LAYOUT(cmd, layout) \ +do { \ + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ + MC_CMD_OP(cmd, 0, 32, 32, uint32_t, layout->options); \ + MC_CMD_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ + MC_CMD_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ + MC_CMD_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ + MC_CMD_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ + MC_CMD_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_RSP_GET_TX_CONF_BUFFER_LAYOUT(cmd, layout) \ +do { \ + MC_RSP_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ + MC_RSP_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ + MC_RSP_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ + MC_RSP_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ + MC_RSP_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ + MC_RSP_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ + MC_RSP_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_CMD_SET_TX_CONF_BUFFER_LAYOUT(cmd, layout) \ +do { \ + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ + MC_CMD_OP(cmd, 0, 32, 32, uint32_t, layout->options); \ + MC_CMD_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ + MC_CMD_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ + MC_CMD_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ + MC_CMD_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ + MC_CMD_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_RSP_GET_QDID(cmd, qdid) \ + MC_RSP_OP(cmd, 0, 0, 16, uint16_t, qdid) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_RSP_GET_TX_DATA_OFFSET(cmd, data_offset) \ + MC_RSP_OP(cmd, 0, 0, 16, uint16_t, data_offset) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_CMD_GET_COUNTER(cmd, counter) \ + MC_CMD_OP(cmd, 0, 0, 16, enum dpni_counter, counter) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_RSP_GET_COUNTER(cmd, value) \ + MC_RSP_OP(cmd, 1, 0, 64, uint64_t, value) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_CMD_SET_COUNTER(cmd, counter, value) \ +do { \ + MC_CMD_OP(cmd, 0, 0, 16, enum dpni_counter, counter); \ + MC_CMD_OP(cmd, 1, 0, 64, uint64_t, value); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_CMD_SET_LINK_CFG(cmd, cfg) \ +do { \ + MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->rate);\ + MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options);\ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_RSP_GET_LINK_STATE(cmd, state) \ +do { \ + MC_RSP_OP(cmd, 0, 32, 1, int, state->up);\ + MC_RSP_OP(cmd, 1, 0, 64, uint64_t, state->rate);\ + MC_RSP_OP(cmd, 2, 0, 64, uint64_t, state->options);\ +} while (0) + + + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_CMD_SET_PRIMARY_MAC_ADDR(cmd, mac_addr) \ +do { \ + MC_CMD_OP(cmd, 0, 16, 8, uint8_t, mac_addr[5]); \ + MC_CMD_OP(cmd, 0, 24, 8, uint8_t, mac_addr[4]); \ + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, mac_addr[3]); \ + MC_CMD_OP(cmd, 0, 40, 8, uint8_t, mac_addr[2]); \ + MC_CMD_OP(cmd, 0, 48, 8, uint8_t, mac_addr[1]); \ + MC_CMD_OP(cmd, 0, 56, 8, uint8_t, mac_addr[0]); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_RSP_GET_PRIMARY_MAC_ADDR(cmd, mac_addr) \ +do { \ + MC_RSP_OP(cmd, 0, 16, 8, uint8_t, mac_addr[5]); \ + MC_RSP_OP(cmd, 0, 24, 8, uint8_t, mac_addr[4]); \ + MC_RSP_OP(cmd, 0, 32, 8, uint8_t, mac_addr[3]); \ + MC_RSP_OP(cmd, 0, 40, 8, uint8_t, mac_addr[2]); \ + MC_RSP_OP(cmd, 0, 48, 8, uint8_t, mac_addr[1]); \ + MC_RSP_OP(cmd, 0, 56, 8, uint8_t, mac_addr[0]); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_CMD_ADD_MAC_ADDR(cmd, mac_addr) \ +do { \ + MC_CMD_OP(cmd, 0, 16, 8, uint8_t, mac_addr[5]); \ + MC_CMD_OP(cmd, 0, 24, 8, uint8_t, mac_addr[4]); \ + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, mac_addr[3]); \ + MC_CMD_OP(cmd, 0, 40, 8, uint8_t, mac_addr[2]); \ + MC_CMD_OP(cmd, 0, 48, 8, uint8_t, mac_addr[1]); \ + MC_CMD_OP(cmd, 0, 56, 8, uint8_t, mac_addr[0]); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_CMD_REMOVE_MAC_ADDR(cmd, mac_addr) \ +do { \ + MC_CMD_OP(cmd, 0, 16, 8, uint8_t, mac_addr[5]); \ + MC_CMD_OP(cmd, 0, 24, 8, uint8_t, mac_addr[4]); \ + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, mac_addr[3]); \ + MC_CMD_OP(cmd, 0, 40, 8, uint8_t, mac_addr[2]); \ + MC_CMD_OP(cmd, 0, 48, 8, uint8_t, mac_addr[1]); \ + MC_CMD_OP(cmd, 0, 56, 8, uint8_t, mac_addr[0]); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_CMD_SET_TX_FLOW(cmd, flow_id, cfg) \ +do { \ + MC_CMD_OP(cmd, 0, 0, 32, int, \ + cfg->conf_err_cfg.queue_cfg.dest_cfg.dest_id);\ + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, \ + cfg->conf_err_cfg.queue_cfg.dest_cfg.priority);\ + MC_CMD_OP(cmd, 0, 40, 2, enum dpni_dest, \ + cfg->conf_err_cfg.queue_cfg.dest_cfg.dest_type);\ + MC_CMD_OP(cmd, 0, 42, 1, int, cfg->conf_err_cfg.errors_only);\ + MC_CMD_OP(cmd, 0, 43, 1, int, cfg->l3_chksum_gen);\ + MC_CMD_OP(cmd, 0, 44, 1, int, cfg->l4_chksum_gen);\ + MC_CMD_OP(cmd, 0, 45, 1, int, \ + cfg->conf_err_cfg.use_default_queue);\ + MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id);\ + MC_CMD_OP(cmd, 1, 0, 64, uint64_t, \ + cfg->conf_err_cfg.queue_cfg.user_ctx);\ + MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->options);\ + MC_CMD_OP(cmd, 2, 32, 32, uint32_t, \ + cfg->conf_err_cfg.queue_cfg.options);\ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_RSP_SET_TX_FLOW(cmd, flow_id) \ + MC_RSP_OP(cmd, 0, 48, 16, uint16_t, flow_id) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_CMD_GET_TX_FLOW(cmd, flow_id) \ + MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_RSP_GET_TX_FLOW(cmd, attr) \ +do { \ + MC_RSP_OP(cmd, 0, 0, 32, int, \ + attr->conf_err_attr.queue_attr.dest_cfg.dest_id);\ + MC_RSP_OP(cmd, 0, 32, 8, uint8_t, \ + attr->conf_err_attr.queue_attr.dest_cfg.priority);\ + MC_RSP_OP(cmd, 0, 40, 2, enum dpni_dest, \ + attr->conf_err_attr.queue_attr.dest_cfg.dest_type);\ + MC_RSP_OP(cmd, 0, 42, 1, int, attr->conf_err_attr.errors_only);\ + MC_RSP_OP(cmd, 0, 43, 1, int, attr->l3_chksum_gen);\ + MC_RSP_OP(cmd, 0, 44, 1, int, attr->l4_chksum_gen);\ + MC_RSP_OP(cmd, 0, 45, 1, int, \ + attr->conf_err_attr.use_default_queue);\ + MC_RSP_OP(cmd, 1, 0, 64, uint64_t, \ + attr->conf_err_attr.queue_attr.user_ctx);\ + MC_RSP_OP(cmd, 2, 32, 32, uint32_t, \ + attr->conf_err_attr.queue_attr.fqid);\ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_CMD_SET_RX_FLOW(cmd, tc_id, flow_id, cfg) \ +do { \ + MC_CMD_OP(cmd, 0, 0, 32, int, cfg->dest_cfg.dest_id); \ + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->dest_cfg.priority);\ + MC_CMD_OP(cmd, 0, 40, 2, enum dpni_dest, cfg->dest_cfg.dest_type);\ + MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \ + MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx); \ + MC_CMD_OP(cmd, 2, 16, 8, uint8_t, tc_id); \ + MC_CMD_OP(cmd, 2, 32, 32, uint32_t, cfg->options); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_CMD_GET_RX_FLOW(cmd, tc_id, flow_id) \ +do { \ + MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id); \ + MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPNI_RSP_GET_RX_FLOW(cmd, attr) \ +do { \ + MC_RSP_OP(cmd, 0, 0, 32, int, attr->dest_cfg.dest_id); \ + MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->dest_cfg.priority);\ + MC_RSP_OP(cmd, 0, 40, 2, enum dpni_dest, attr->dest_cfg.dest_type); \ + MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->user_ctx); \ + MC_RSP_OP(cmd, 2, 32, 32, uint32_t, attr->fqid); \ +} while (0) + +enum net_prot { + NET_PROT_NONE = 0, + NET_PROT_PAYLOAD, + NET_PROT_ETH, + NET_PROT_VLAN, + NET_PROT_IPV4, + NET_PROT_IPV6, + NET_PROT_IP, + NET_PROT_TCP, + NET_PROT_UDP, + NET_PROT_UDP_LITE, + NET_PROT_IPHC, + NET_PROT_SCTP, + NET_PROT_SCTP_CHUNK_DATA, + NET_PROT_PPPOE, + NET_PROT_PPP, + NET_PROT_PPPMUX, + NET_PROT_PPPMUX_SUBFRM, + NET_PROT_L2TPV2, + NET_PROT_L2TPV3_CTRL, + NET_PROT_L2TPV3_SESS, + NET_PROT_LLC, + NET_PROT_LLC_SNAP, + NET_PROT_NLPID, + NET_PROT_SNAP, + NET_PROT_MPLS, + NET_PROT_IPSEC_AH, + NET_PROT_IPSEC_ESP, + NET_PROT_UDP_ENC_ESP, /* RFC 3948 */ + NET_PROT_MACSEC, + NET_PROT_GRE, + NET_PROT_MINENCAP, + NET_PROT_DCCP, + NET_PROT_ICMP, + NET_PROT_IGMP, + NET_PROT_ARP, + NET_PROT_CAPWAP_DATA, + NET_PROT_CAPWAP_CTRL, + NET_PROT_RFC2684, + NET_PROT_ICMPV6, + NET_PROT_FCOE, + NET_PROT_FIP, + NET_PROT_ISCSI, + NET_PROT_GTP, + NET_PROT_USER_DEFINED_L2, + NET_PROT_USER_DEFINED_L3, + NET_PROT_USER_DEFINED_L4, + NET_PROT_USER_DEFINED_L5, + NET_PROT_USER_DEFINED_SHIM1, + NET_PROT_USER_DEFINED_SHIM2, + + NET_PROT_DUMMY_LAST +}; + +/* Data Path Network Interface API + * Contains initialization APIs and runtime control APIs for DPNI + */ + +struct fsl_mc_io; + +/* General DPNI macros */ + +/* Maximum number of traffic classes */ +#define DPNI_MAX_TC 8 +/* Maximum number of buffer pools per DPNI */ +#define DPNI_MAX_DPBP 8 + +/* All traffic classes considered; see dpni_set_rx_flow() */ +#define DPNI_ALL_TCS (uint8_t)(-1) +/* All flows within traffic class considered; see dpni_set_rx_flow() */ +#define DPNI_ALL_TC_FLOWS (uint16_t)(-1) +/* Generate new flow ID; see dpni_set_tx_flow() */ +#define DPNI_NEW_FLOW_ID (uint16_t)(-1) + +/** + * dpni_open() - Open a control session for the specified object + * @mc_io: Pointer to MC portal's I/O object + * @dpni_id: DPNI unique ID + * @token: Returned token; use in subsequent API calls + * + * This function can be used to open a control session for an + * already created object; an object may have been declared in + * the DPL or by calling the dpni_create() function. + * This function returns a unique authentication token, + * associated with the specific object ID and the specific MC + * portal; this token must be used in all subsequent commands for + * this specific object. + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_open(struct fsl_mc_io *mc_io, int dpni_id, uint16_t *token); + +/** + * dpni_close() - Close the control session of the object + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * + * After this function is called, no further operations are + * allowed on the object without opening a new control session. + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_close(struct fsl_mc_io *mc_io, uint16_t token); + +/** + * struct dpni_ipr_cfg - Structure representing IP reassembly configuration + * @max_reass_frm_size: Maximum size of the reassembled frame + * @min_frag_size_ipv4: Minimum fragment size of IPv4 fragments + * @min_frag_size_ipv6: Minimum fragment size of IPv6 fragments + * @max_open_frames_ipv4: Maximum concurrent IPv4 packets in reassembly process + * @max_open_frames_ipv6: Maximum concurrent IPv6 packets in reassembly process + */ +struct dpni_ipr_cfg { + uint16_t max_reass_frm_size; + uint16_t min_frag_size_ipv4; + uint16_t min_frag_size_ipv6; + uint16_t max_open_frames_ipv4; + uint16_t max_open_frames_ipv6; +}; + +/** + * struct dpni_pools_cfg - Structure representing buffer pools configuration + * @num_dpbp: Number of DPBPs + * @pools: Array of buffer pools parameters; The number of valid entries + * must match 'num_dpbp' value + */ +struct dpni_pools_cfg { + uint8_t num_dpbp; + /** + * struct pools - Buffer pools parameters + * @dpbp_id: DPBP object ID + * @buffer_size: Buffer size + */ + struct { + int dpbp_id; + uint16_t buffer_size; + } pools[DPNI_MAX_DPBP]; +}; + +/** + * dpni_set_pools() - Set buffer pools configuration + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @cfg: Buffer pools configuration + * + * mandatory for DPNI operation + * warning:Allowed only when DPNI is disabled + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_set_pools(struct fsl_mc_io *mc_io, + uint16_t token, + const struct dpni_pools_cfg *cfg); + +/** + * dpni_enable() - Enable the DPNI, allow sending and receiving frames. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_enable(struct fsl_mc_io *mc_io, uint16_t token); + +/** + * dpni_disable() - Disable the DPNI, stop sending and receiving frames. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_disable(struct fsl_mc_io *mc_io, uint16_t token); + + +/** + * @dpni_reset() - Reset the DPNI, returns the object to initial state. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_reset(struct fsl_mc_io *mc_io, uint16_t token); + +/** + * struct dpni_attr - Structure representing DPNI attributes + * @id: DPNI object ID + * @version: DPNI version + * @start_hdr: Indicates the packet starting header for parsing + * @options: Mask of available options; reflects the value as was given in + * object's creation + * @max_senders: Maximum number of different senders; used as the number + * of dedicated Tx flows; + * @max_tcs: Maximum number of traffic classes (for both Tx and Rx) + * @max_dist_per_tc: Maximum distribution size per Rx traffic class; + * Set to the required value minus 1 + * @max_unicast_filters: Maximum number of unicast filters + * @max_multicast_filters: Maximum number of multicast filters + * @max_vlan_filters: Maximum number of VLAN filters + * @max_qos_entries: if 'max_tcs > 1', declares the maximum entries in QoS table + * @max_qos_key_size: Maximum key size for the QoS look-up + * @max_dist_key_size: Maximum key size for the distribution look-up + * @ipr_cfg: IP reassembly configuration + */ +struct dpni_attr { + int id; + /** + * struct version - DPNI version + * @major: DPNI major version + * @minor: DPNI minor version + */ + struct { + uint16_t major; + uint16_t minor; + } version; + enum net_prot start_hdr; + uint64_t options; + uint8_t max_senders; + uint8_t max_tcs; + uint8_t max_dist_per_tc[DPNI_MAX_TC]; + uint8_t max_unicast_filters; + uint8_t max_multicast_filters; + uint8_t max_vlan_filters; + uint8_t max_qos_entries; + uint8_t max_qos_key_size; + uint8_t max_dist_key_size; + struct dpni_ipr_cfg ipr_cfg; +}; +/** + * dpni_get_attributes() - Retrieve DPNI attributes. + * @mc_io: Pointer to MC portal's I/O objec + * @token: Token of DPNI object + * @attr: Returned object's attributes + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_get_attributes(struct fsl_mc_io *mc_io, + uint16_t token, + struct dpni_attr *attr); + +/* DPNI buffer layout modification options */ + +/* Select to modify the time-stamp setting */ +#define DPNI_BUF_LAYOUT_OPT_TIMESTAMP 0x00000001 +/* Select to modify the parser-result setting; not applicable for Tx */ +#define DPNI_BUF_LAYOUT_OPT_PARSER_RESULT 0x00000002 +/* Select to modify the frame-status setting */ +#define DPNI_BUF_LAYOUT_OPT_FRAME_STATUS 0x00000004 +/* Select to modify the private-data-size setting */ +#define DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE 0x00000008 +/* Select to modify the data-alignment setting */ +#define DPNI_BUF_LAYOUT_OPT_DATA_ALIGN 0x00000010 +/* Select to modify the data-head-room setting */ +#define DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM 0x00000020 +/*!< Select to modify the data-tail-room setting */ +#define DPNI_BUF_LAYOUT_OPT_DATA_TAIL_ROOM 0x00000040 + +/** + * struct dpni_buffer_layout - Structure representing DPNI buffer layout + * @options: Flags representing the suggested modifications to the buffer + * layout; Use any combination of 'DPNI_BUF_LAYOUT_OPT_<X>' flags + * @pass_timestamp: Pass timestamp value + * @pass_parser_result: Pass parser results + * @pass_frame_status: Pass frame status + * @private_data_size: Size kept for private data (in bytes) + * @data_align: Data alignment + * @data_head_room: Data head room + * @data_tail_room: Data tail room + */ +struct dpni_buffer_layout { + uint32_t options; + int pass_timestamp; + int pass_parser_result; + int pass_frame_status; + uint16_t private_data_size; + uint16_t data_align; + uint16_t data_head_room; + uint16_t data_tail_room; +}; + +/** + * dpni_get_rx_buffer_layout() - Retrieve Rx buffer layout attributes. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @layout: Returns buffer layout attributes + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_get_rx_buffer_layout(struct fsl_mc_io *mc_io, + uint16_t token, + struct dpni_buffer_layout *layout); +/** + * dpni_set_rx_buffer_layout() - Set Rx buffer layout configuration. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @layout: Buffer layout configuration + * + * Return: '0' on Success; Error code otherwise. + * + * @warning Allowed only when DPNI is disabled + */ +int dpni_set_rx_buffer_layout(struct fsl_mc_io *mc_io, + uint16_t token, + const struct dpni_buffer_layout *layout); + +/** + * dpni_get_tx_buffer_layout() - Retrieve Tx buffer layout attributes. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @layout: Returns buffer layout attributes + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_get_tx_buffer_layout(struct fsl_mc_io *mc_io, + uint16_t token, + struct dpni_buffer_layout *layout); + +/** + * @brief Set Tx buffer layout configuration. + * + * @param[in] mc_io Pointer to MC portal's I/O object + * @param[in] token Token of DPNI object + * @param[in] layout Buffer layout configuration + * + * @returns '0' on Success; Error code otherwise. + * + * @warning Allowed only when DPNI is disabled + */ +int dpni_set_tx_buffer_layout(struct fsl_mc_io *mc_io, + uint16_t token, + const struct dpni_buffer_layout *layout); +/** + * dpni_get_tx_conf_buffer_layout() - Retrieve Tx confirmation buffer layout + * attributes. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @layout: Returns buffer layout attributes + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_get_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, + uint16_t token, + struct dpni_buffer_layout *layout); +/** + * dpni_set_tx_conf_buffer_layout() - Set Tx confirmation buffer layout + * configuration. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @layout: Buffer layout configuration + * + * Return: '0' on Success; Error code otherwise. + * + * @warning Allowed only when DPNI is disabled + */ +int dpni_set_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, + uint16_t token, + const struct dpni_buffer_layout *layout); +/** + * dpni_get_spid() - Get the AIOP storage profile ID associated with the DPNI + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @spid: Returned aiop storage-profile ID + * + * Return: '0' on Success; Error code otherwise. + * + * @warning Only relevant for DPNI that belongs to AIOP container. + */ +int dpni_get_qdid(struct fsl_mc_io *mc_io, uint16_t token, uint16_t *qdid); + +/** + * dpni_get_tx_data_offset() - Get the Tx data offset (from start of buffer) + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @data_offset: Tx data offset (from start of buffer) + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io, + uint16_t token, + uint16_t *data_offset); + +/** + * enum dpni_counter - DPNI counter types + * @DPNI_CNT_ING_FRAME: Counts ingress frames + * @DPNI_CNT_ING_BYTE: Counts ingress bytes + * @DPNI_CNT_ING_FRAME_DROP: Counts ingress frames dropped due to explicit + * 'drop' setting + * @DPNI_CNT_ING_FRAME_DISCARD: Counts ingress frames discarded due to errors + * @DPNI_CNT_ING_MCAST_FRAME: Counts ingress multicast frames + * @DPNI_CNT_ING_MCAST_BYTE: Counts ingress multicast bytes + * @DPNI_CNT_ING_BCAST_FRAME: Counts ingress broadcast frames + * @DPNI_CNT_ING_BCAST_BYTES: Counts ingress broadcast bytes + * @DPNI_CNT_EGR_FRAME: Counts egress frames + * @DPNI_CNT_EGR_BYTE: Counts egress bytes + * @DPNI_CNT_EGR_FRAME_DISCARD: Counts egress frames discarded due to errors + */ +enum dpni_counter { + DPNI_CNT_ING_FRAME = 0x0, + DPNI_CNT_ING_BYTE = 0x1, + DPNI_CNT_ING_FRAME_DROP = 0x2, + DPNI_CNT_ING_FRAME_DISCARD = 0x3, + DPNI_CNT_ING_MCAST_FRAME = 0x4, + DPNI_CNT_ING_MCAST_BYTE = 0x5, + DPNI_CNT_ING_BCAST_FRAME = 0x6, + DPNI_CNT_ING_BCAST_BYTES = 0x7, + DPNI_CNT_EGR_FRAME = 0x8, + DPNI_CNT_EGR_BYTE = 0x9, + DPNI_CNT_EGR_FRAME_DISCARD = 0xa +}; + +/** + * dpni_get_counter() - Read a specific DPNI counter + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @counter: The requested counter + * @value: Returned counter's current value + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_get_counter(struct fsl_mc_io *mc_io, + uint16_t token, + enum dpni_counter counter, + uint64_t *value); + +/** + * dpni_set_counter() - Set (or clear) a specific DPNI counter + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @counter: The requested counter + * @value: New counter value; typically pass '0' for resetting + * the counter. + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_set_counter(struct fsl_mc_io *mc_io, + uint16_t token, + enum dpni_counter counter, + uint64_t value); +/** + * struct - Structure representing DPNI link configuration + * @rate: Rate + * @options: Mask of available options; use 'DPNI_LINK_OPT_<X>' values + */ +struct dpni_link_cfg { + uint64_t rate; + uint64_t options; +}; + +/** + * dpni_set_link_cfg() - set the link configuration. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @cfg: Link configuration + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_set_link_cfg(struct fsl_mc_io *mc_io, + uint16_t token, + struct dpni_link_cfg *cfg); + +/** + * struct dpni_link_state - Structure representing DPNI link state + * @rate: Rate + * @options: Mask of available options; use 'DPNI_LINK_OPT_<X>' values + * @up: Link state; '0' for down, '1' for up + */ +struct dpni_link_state { + uint64_t rate; + uint64_t options; + int up; +}; + +/** + * dpni_get_link_state() - Return the link state (either up or down) + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @state: Returned link state; + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_get_link_state(struct fsl_mc_io *mc_io, + uint16_t token, + struct dpni_link_state *state); + +/** + * dpni_set_primary_mac_addr() - Set the primary MAC address + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @mac_addr: MAC address to set as primary address + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_set_primary_mac_addr(struct fsl_mc_io *mc_io, + uint16_t token, + const uint8_t mac_addr[6]); +/** + * dpni_get_primary_mac_addr() - Get the primary MAC address + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @mac_addr: Returned MAC address + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_get_primary_mac_addr(struct fsl_mc_io *mc_io, + uint16_t token, + uint8_t mac_addr[6]); +/** + * dpni_add_mac_addr() - Add MAC address filter + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @mac_addr: MAC address to add + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_add_mac_addr(struct fsl_mc_io *mc_io, + uint16_t token, + const uint8_t mac_addr[6]); + +/** + * dpni_remove_mac_addr() - Remove MAC address filter + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @mac_addr: MAC address to remove + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_remove_mac_addr(struct fsl_mc_io *mc_io, + uint16_t token, + const uint8_t mac_addr[6]); + +/** + * enum dpni_dest - DPNI destination types + * DPNI_DEST_NONE: Unassigned destination; The queue is set in parked mode and + * does not generate FQDAN notifications; user is expected to + * dequeue from the queue based on polling or other user-defined + * method + * @DPNI_DEST_DPIO: The queue is set in schedule mode and generates FQDAN + * notifications to the specified DPIO; user is expected to dequeue + * from the queue only after notification is received + * @DPNI_DEST_DPCON: The queue is set in schedule mode and does not generate + * FQDAN notifications, but is connected to the specified DPCON + * object; user is expected to dequeue from the DPCON channel + */ +enum dpni_dest { + DPNI_DEST_NONE = 0, + DPNI_DEST_DPIO = 1, + DPNI_DEST_DPCON = 2 +}; + +/** + * struct dpni_dest_cfg - Structure representing DPNI destination parameters + * @dest_type: Destination type + * @dest_id: Either DPIO ID or DPCON ID, depending on the destination type + * @priority: Priority selection within the DPIO or DPCON channel; valid values + * are 0-1 or 0-7, depending on the number of priorities in that + * channel; not relevant for 'DPNI_DEST_NONE' option + */ +struct dpni_dest_cfg { + enum dpni_dest dest_type; + int dest_id; + uint8_t priority; +}; + +/* DPNI queue modification options */ + +/* Select to modify the user's context associated with the queue */ +#define DPNI_QUEUE_OPT_USER_CTX 0x00000001 +/* Select to modify the queue's destination */ +#define DPNI_QUEUE_OPT_DEST 0x00000002 + +/** + * struct dpni_queue_cfg - Structure representing queue configuration + * @options: Flags representing the suggested modifications to the queue; + * Use any combination of 'DPNI_QUEUE_OPT_<X>' flags + * @user_ctx: User context value provided in the frame descriptor of each + * dequeued frame; valid only if 'DPNI_QUEUE_OPT_USER_CTX' + * is contained in 'options' + * @dest_cfg: Queue destination parameters; + * valid only if 'DPNI_QUEUE_OPT_DEST' is contained in 'options' + */ +struct dpni_queue_cfg { + uint32_t options; + uint64_t user_ctx; + struct dpni_dest_cfg dest_cfg; +}; + +/** + * struct dpni_queue_attr - Structure representing queue attributes + * @user_ctx: User context value provided in the frame descriptor of each + * dequeued frame + * @dest_cfg: Queue destination configuration + * @fqid: Virtual fqid value to be used for dequeue operations + */ +struct dpni_queue_attr { + uint64_t user_ctx; + struct dpni_dest_cfg dest_cfg; + uint32_t fqid; +}; + +/* DPNI Tx flow modification options */ + +/* Select to modify the settings for dedicate Tx confirmation/error */ +#define DPNI_TX_FLOW_OPT_TX_CONF_ERROR 0x00000001 +/*!< Select to modify the Tx confirmation and/or error setting */ +#define DPNI_TX_FLOW_OPT_ONLY_TX_ERROR 0x00000002 +/*!< Select to modify the queue configuration */ +#define DPNI_TX_FLOW_OPT_QUEUE 0x00000004 +/*!< Select to modify the L3 checksum generation setting */ +#define DPNI_TX_FLOW_OPT_L3_CHKSUM_GEN 0x00000010 +/*!< Select to modify the L4 checksum generation setting */ +#define DPNI_TX_FLOW_OPT_L4_CHKSUM_GEN 0x00000020 + +/** + * struct dpni_tx_flow_cfg - Structure representing Tx flow configuration + * @options: Flags representing the suggested modifications to the Tx flow; + * Use any combination 'DPNI_TX_FLOW_OPT_<X>' flags + * @conf_err_cfg: Tx confirmation and error configuration; these settings are + * ignored if 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' was set at + * DPNI creation + * @l3_chksum_gen: Set to '1' to enable L3 checksum generation; '0' to disable; + * valid only if 'DPNI_TX_FLOW_OPT_L3_CHKSUM_GEN' is contained in + * 'options' + * @l4_chksum_gen: Set to '1' to enable L4 checksum generation; '0' to disable; + * valid only if 'DPNI_TX_FLOW_OPT_L4_CHKSUM_GEN' is contained in + * 'options' + */ +struct dpni_tx_flow_cfg { + uint32_t options; + /** + * struct cnf_err_cfg - Tx confirmation and error configuration + * @use_default_queue: Set to '1' to use the common (default) Tx + * confirmation and error queue; Set to '0' to use the + * private Tx confirmation and error queue; valid only if + * 'DPNI_TX_FLOW_OPT_TX_CONF_ERROR' is contained in + * 'options' + * @errors_only: Set to '1' to report back only error frames; + * Set to '0' to confirm transmission/error for all + * transmitted frames; + * valid only if 'DPNI_TX_FLOW_OPT_ONLY_TX_ERROR' is + * contained in 'options' and 'use_default_queue = 0'; + * @queue_cfg: Queue configuration; valid only if + * 'DPNI_TX_FLOW_OPT_QUEUE' is contained in 'options' + */ + struct { + int use_default_queue; + int errors_only; + struct dpni_queue_cfg queue_cfg; + } conf_err_cfg; + int l3_chksum_gen; + int l4_chksum_gen; +}; + +/** + * dpni_set_tx_flow() - Set Tx flow configuration + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @flow_id: Provides (or returns) the sender's flow ID; + * for each new sender set (*flow_id) to + * 'DPNI_NEW_FLOW_ID' to generate a new flow_id; + * this ID should be used as the QDBIN argument + * in enqueue operations + * @cfg: Tx flow configuration + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_set_tx_flow(struct fsl_mc_io *mc_io, + uint16_t token, + uint16_t *flow_id, + const struct dpni_tx_flow_cfg *cfg); + +/** + * struct dpni_tx_flow_attr - Structure representing Tx flow attributes + * @conf_err_attr: Tx confirmation and error attributes + * @l3_chksum_gen: '1' if L3 checksum generation is enabled; '0' if disabled + * @l4_chksum_gen: '1' if L4 checksum generation is enabled; '0' if disabled + */ +struct dpni_tx_flow_attr { + /** + * struct conf_err_attr - Tx confirmation and error attributes + * @use_default_queue: '1' if using common (default) Tx confirmation and + * error queue; + * '0' if using private Tx confirmation and error + * queue + * @errors_only: '1' if only error frames are reported back; '0' if all + * transmitted frames are confirmed + * @queue_attr: Queue attributes + */ + struct { + int use_default_queue; + int errors_only; + struct dpni_queue_attr queue_attr; + } conf_err_attr; + int l3_chksum_gen; + int l4_chksum_gen; +}; + +/** + * dpni_get_tx_flow() - Get Tx flow attributes + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @flow_id: The sender's flow ID, as returned by the + * dpni_set_tx_flow() function + * @attr: Returned Tx flow attributes + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_get_tx_flow(struct fsl_mc_io *mc_io, + uint16_t token, + uint16_t flow_id, + struct dpni_tx_flow_attr *attr); + +/** + * dpni_set_rx_flow() - Set Rx flow configuration + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @tc_id: Traffic class selection (0-7); + * use 'DPNI_ALL_TCS' to set all TCs and all flows + * @flow_id Rx flow id within the traffic class; use + * 'DPNI_ALL_TC_FLOWS' to set all flows within + * this tc_id; ignored if tc_id is set to + * 'DPNI_ALL_TCS'; + * @cfg: Rx flow configuration + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_set_rx_flow(struct fsl_mc_io *mc_io, + uint16_t token, + uint8_t tc_id, + uint16_t flow_id, + const struct dpni_queue_cfg *cfg); + +/** + * dpni_get_rx_flow() - Get Rx flow attributes + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPNI object + * @tc_id: Traffic class selection (0-7) + * @flow_id: Rx flow id within the traffic class + * @attr: Returned Rx flow attributes + * + * Return: '0' on Success; Error code otherwise. + */ +int dpni_get_rx_flow(struct fsl_mc_io *mc_io, + uint16_t token, + uint8_t tc_id, + uint16_t flow_id, + struct dpni_queue_attr *attr); + +#endif /* _FSL_DPNI_H */ diff --git a/include/fsl-mc/fsl_dprc.h b/include/fsl-mc/fsl_dprc.h new file mode 100644 index 0000000..f837e89 --- /dev/null +++ b/include/fsl-mc/fsl_dprc.h @@ -0,0 +1,659 @@ +/* + * Freescale Layerscape MC I/O wrapper + * + * Copyright (C) 2013-2015 Freescale Semiconductor, Inc. + * Author: German Rivera <German.Rivera@freescale.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef _FSL_DPRC_H +#define _FSL_DPRC_H + +/* DPRC Version */ +#define DPRC_VER_MAJOR 2 +#define DPRC_VER_MINOR 0 + +/* Command IDs */ +#define DPRC_CMDID_CLOSE 0x800 +#define DPRC_CMDID_OPEN 0x805 + +#define DPRC_CMDID_GET_ATTR 0x004 +#define DPRC_CMDID_RESET_CONT 0x005 + +#define DPRC_CMDID_GET_CONT_ID 0x830 +#define DPRC_CMDID_GET_OBJ_COUNT 0x159 +#define DPRC_CMDID_GET_OBJ 0x15A +#define DPRC_CMDID_GET_RES_COUNT 0x15B +#define DPRC_CMDID_GET_RES_IDS 0x15C +#define DPRC_CMDID_GET_OBJ_REG 0x15E + +#define DPRC_CMDID_CONNECT 0x167 +#define DPRC_CMDID_DISCONNECT 0x168 +#define DPRC_CMDID_GET_CONNECTION 0x16C + +/* cmd, param, offset, width, type, arg_name */ +#define DPRC_RSP_GET_CONTAINER_ID(cmd, container_id) \ + MC_RSP_OP(cmd, 0, 0, 32, int, container_id) + +/* cmd, param, offset, width, type, arg_name */ +#define DPRC_CMD_OPEN(cmd, container_id) \ + MC_CMD_OP(cmd, 0, 0, 32, int, container_id) + +/* cmd, param, offset, width, type, arg_name */ +#define DPRC_CMD_RESET_CONTAINER(cmd, child_container_id) \ + MC_CMD_OP(cmd, 0, 0, 32, int, child_container_id) + +/* cmd, param, offset, width, type, arg_name */ +#define DPRC_RSP_GET_ATTRIBUTES(cmd, attr) \ +do { \ + MC_RSP_OP(cmd, 0, 0, 32, int, attr->container_id); \ + MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->icid); \ + MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->options);\ + MC_RSP_OP(cmd, 1, 32, 32, int, attr->portal_id); \ + MC_RSP_OP(cmd, 2, 0, 16, uint16_t, attr->version.major);\ + MC_RSP_OP(cmd, 2, 16, 16, uint16_t, attr->version.minor);\ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPRC_RSP_GET_OBJ_COUNT(cmd, obj_count) \ + MC_RSP_OP(cmd, 0, 32, 32, int, obj_count) + +/* cmd, param, offset, width, type, arg_name */ +#define DPRC_CMD_GET_OBJ(cmd, obj_index) \ + MC_CMD_OP(cmd, 0, 0, 32, int, obj_index) + +/* cmd, param, offset, width, type, arg_name */ +#define DPRC_RSP_GET_OBJ(cmd, obj_desc) \ +do { \ + MC_RSP_OP(cmd, 0, 32, 32, int, obj_desc->id); \ + MC_RSP_OP(cmd, 1, 0, 16, uint16_t, obj_desc->vendor); \ + MC_RSP_OP(cmd, 1, 16, 8, uint8_t, obj_desc->irq_count); \ + MC_RSP_OP(cmd, 1, 24, 8, uint8_t, obj_desc->region_count); \ + MC_RSP_OP(cmd, 1, 32, 32, uint32_t, obj_desc->state);\ + MC_RSP_OP(cmd, 2, 0, 16, uint16_t, obj_desc->ver_major);\ + MC_RSP_OP(cmd, 2, 16, 16, uint16_t, obj_desc->ver_minor);\ + MC_RSP_OP(cmd, 3, 0, 8, char, obj_desc->type[0]);\ + MC_RSP_OP(cmd, 3, 8, 8, char, obj_desc->type[1]);\ + MC_RSP_OP(cmd, 3, 16, 8, char, obj_desc->type[2]);\ + MC_RSP_OP(cmd, 3, 24, 8, char, obj_desc->type[3]);\ + MC_RSP_OP(cmd, 3, 32, 8, char, obj_desc->type[4]);\ + MC_RSP_OP(cmd, 3, 40, 8, char, obj_desc->type[5]);\ + MC_RSP_OP(cmd, 3, 48, 8, char, obj_desc->type[6]);\ + MC_RSP_OP(cmd, 3, 56, 8, char, obj_desc->type[7]);\ + MC_RSP_OP(cmd, 4, 0, 8, char, obj_desc->type[8]);\ + MC_RSP_OP(cmd, 4, 8, 8, char, obj_desc->type[9]);\ + MC_RSP_OP(cmd, 4, 16, 8, char, obj_desc->type[10]);\ + MC_RSP_OP(cmd, 4, 24, 8, char, obj_desc->type[11]);\ + MC_RSP_OP(cmd, 4, 32, 8, char, obj_desc->type[12]);\ + MC_RSP_OP(cmd, 4, 40, 8, char, obj_desc->type[13]);\ + MC_RSP_OP(cmd, 4, 48, 8, char, obj_desc->type[14]);\ + MC_RSP_OP(cmd, 4, 56, 8, char, obj_desc->type[15]);\ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPRC_CMD_GET_RES_COUNT(cmd, type) \ +do { \ + MC_CMD_OP(cmd, 1, 0, 8, char, type[0]);\ + MC_CMD_OP(cmd, 1, 8, 8, char, type[1]);\ + MC_CMD_OP(cmd, 1, 16, 8, char, type[2]);\ + MC_CMD_OP(cmd, 1, 24, 8, char, type[3]);\ + MC_CMD_OP(cmd, 1, 32, 8, char, type[4]);\ + MC_CMD_OP(cmd, 1, 40, 8, char, type[5]);\ + MC_CMD_OP(cmd, 1, 48, 8, char, type[6]);\ + MC_CMD_OP(cmd, 1, 56, 8, char, type[7]);\ + MC_CMD_OP(cmd, 2, 0, 8, char, type[8]);\ + MC_CMD_OP(cmd, 2, 8, 8, char, type[9]);\ + MC_CMD_OP(cmd, 2, 16, 8, char, type[10]);\ + MC_CMD_OP(cmd, 2, 24, 8, char, type[11]);\ + MC_CMD_OP(cmd, 2, 32, 8, char, type[12]);\ + MC_CMD_OP(cmd, 2, 40, 8, char, type[13]);\ + MC_CMD_OP(cmd, 2, 48, 8, char, type[14]);\ + MC_CMD_OP(cmd, 2, 56, 8, char, type[15]);\ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPRC_RSP_GET_RES_COUNT(cmd, res_count) \ + MC_RSP_OP(cmd, 0, 0, 32, int, res_count) + +/* cmd, param, offset, width, type, arg_name */ +#define DPRC_CMD_GET_RES_IDS(cmd, range_desc, type) \ +do { \ + MC_CMD_OP(cmd, 0, 42, 7, enum dprc_iter_status, \ + range_desc->iter_status); \ + MC_CMD_OP(cmd, 1, 0, 32, int, range_desc->base_id); \ + MC_CMD_OP(cmd, 1, 32, 32, int, range_desc->last_id);\ + MC_CMD_OP(cmd, 2, 0, 8, char, type[0]);\ + MC_CMD_OP(cmd, 2, 8, 8, char, type[1]);\ + MC_CMD_OP(cmd, 2, 16, 8, char, type[2]);\ + MC_CMD_OP(cmd, 2, 24, 8, char, type[3]);\ + MC_CMD_OP(cmd, 2, 32, 8, char, type[4]);\ + MC_CMD_OP(cmd, 2, 40, 8, char, type[5]);\ + MC_CMD_OP(cmd, 2, 48, 8, char, type[6]);\ + MC_CMD_OP(cmd, 2, 56, 8, char, type[7]);\ + MC_CMD_OP(cmd, 3, 0, 8, char, type[8]);\ + MC_CMD_OP(cmd, 3, 8, 8, char, type[9]);\ + MC_CMD_OP(cmd, 3, 16, 8, char, type[10]);\ + MC_CMD_OP(cmd, 3, 24, 8, char, type[11]);\ + MC_CMD_OP(cmd, 3, 32, 8, char, type[12]);\ + MC_CMD_OP(cmd, 3, 40, 8, char, type[13]);\ + MC_CMD_OP(cmd, 3, 48, 8, char, type[14]);\ + MC_CMD_OP(cmd, 3, 56, 8, char, type[15]);\ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPRC_RSP_GET_RES_IDS(cmd, range_desc) \ +do { \ + MC_RSP_OP(cmd, 0, 42, 7, enum dprc_iter_status, \ + range_desc->iter_status);\ + MC_RSP_OP(cmd, 1, 0, 32, int, range_desc->base_id); \ + MC_RSP_OP(cmd, 1, 32, 32, int, range_desc->last_id);\ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPRC_CMD_GET_OBJ_REGION(cmd, obj_type, obj_id, region_index) \ +do { \ + MC_CMD_OP(cmd, 0, 0, 32, int, obj_id); \ + MC_CMD_OP(cmd, 0, 48, 8, uint8_t, region_index);\ + MC_CMD_OP(cmd, 3, 0, 8, char, obj_type[0]);\ + MC_CMD_OP(cmd, 3, 8, 8, char, obj_type[1]);\ + MC_CMD_OP(cmd, 3, 16, 8, char, obj_type[2]);\ + MC_CMD_OP(cmd, 3, 24, 8, char, obj_type[3]);\ + MC_CMD_OP(cmd, 3, 32, 8, char, obj_type[4]);\ + MC_CMD_OP(cmd, 3, 40, 8, char, obj_type[5]);\ + MC_CMD_OP(cmd, 3, 48, 8, char, obj_type[6]);\ + MC_CMD_OP(cmd, 3, 56, 8, char, obj_type[7]);\ + MC_CMD_OP(cmd, 4, 0, 8, char, obj_type[8]);\ + MC_CMD_OP(cmd, 4, 8, 8, char, obj_type[9]);\ + MC_CMD_OP(cmd, 4, 16, 8, char, obj_type[10]);\ + MC_CMD_OP(cmd, 4, 24, 8, char, obj_type[11]);\ + MC_CMD_OP(cmd, 4, 32, 8, char, obj_type[12]);\ + MC_CMD_OP(cmd, 4, 40, 8, char, obj_type[13]);\ + MC_CMD_OP(cmd, 4, 48, 8, char, obj_type[14]);\ + MC_CMD_OP(cmd, 4, 56, 8, char, obj_type[15]);\ +} while (0) + +/* param, offset, width, type, arg_name */ +#define DPRC_RSP_GET_OBJ_REGION(cmd, region_desc) \ +do { \ + MC_RSP_OP(cmd, 1, 0, 64, uint64_t, region_desc->base_paddr);\ + MC_RSP_OP(cmd, 2, 0, 32, uint32_t, region_desc->size); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPRC_CMD_CONNECT(cmd, endpoint1, endpoint2) \ +do { \ + MC_CMD_OP(cmd, 0, 0, 32, int, endpoint1->id); \ + MC_CMD_OP(cmd, 0, 32, 32, int, endpoint1->interface_id); \ + MC_CMD_OP(cmd, 1, 0, 32, int, endpoint2->id); \ + MC_CMD_OP(cmd, 1, 32, 32, int, endpoint2->interface_id); \ + MC_CMD_OP(cmd, 2, 0, 8, char, endpoint1->type[0]); \ + MC_CMD_OP(cmd, 2, 8, 8, char, endpoint1->type[1]); \ + MC_CMD_OP(cmd, 2, 16, 8, char, endpoint1->type[2]); \ + MC_CMD_OP(cmd, 2, 24, 8, char, endpoint1->type[3]); \ + MC_CMD_OP(cmd, 2, 32, 8, char, endpoint1->type[4]); \ + MC_CMD_OP(cmd, 2, 40, 8, char, endpoint1->type[5]); \ + MC_CMD_OP(cmd, 2, 48, 8, char, endpoint1->type[6]); \ + MC_CMD_OP(cmd, 2, 56, 8, char, endpoint1->type[7]); \ + MC_CMD_OP(cmd, 3, 0, 8, char, endpoint1->type[8]); \ + MC_CMD_OP(cmd, 3, 8, 8, char, endpoint1->type[9]); \ + MC_CMD_OP(cmd, 3, 16, 8, char, endpoint1->type[10]); \ + MC_CMD_OP(cmd, 3, 24, 8, char, endpoint1->type[11]); \ + MC_CMD_OP(cmd, 3, 32, 8, char, endpoint1->type[12]); \ + MC_CMD_OP(cmd, 3, 40, 8, char, endpoint1->type[13]); \ + MC_CMD_OP(cmd, 3, 48, 8, char, endpoint1->type[14]); \ + MC_CMD_OP(cmd, 3, 56, 8, char, endpoint1->type[15]); \ + MC_CMD_OP(cmd, 5, 0, 8, char, endpoint2->type[0]); \ + MC_CMD_OP(cmd, 5, 8, 8, char, endpoint2->type[1]); \ + MC_CMD_OP(cmd, 5, 16, 8, char, endpoint2->type[2]); \ + MC_CMD_OP(cmd, 5, 24, 8, char, endpoint2->type[3]); \ + MC_CMD_OP(cmd, 5, 32, 8, char, endpoint2->type[4]); \ + MC_CMD_OP(cmd, 5, 40, 8, char, endpoint2->type[5]); \ + MC_CMD_OP(cmd, 5, 48, 8, char, endpoint2->type[6]); \ + MC_CMD_OP(cmd, 5, 56, 8, char, endpoint2->type[7]); \ + MC_CMD_OP(cmd, 6, 0, 8, char, endpoint2->type[8]); \ + MC_CMD_OP(cmd, 6, 8, 8, char, endpoint2->type[9]); \ + MC_CMD_OP(cmd, 6, 16, 8, char, endpoint2->type[10]); \ + MC_CMD_OP(cmd, 6, 24, 8, char, endpoint2->type[11]); \ + MC_CMD_OP(cmd, 6, 32, 8, char, endpoint2->type[12]); \ + MC_CMD_OP(cmd, 6, 40, 8, char, endpoint2->type[13]); \ + MC_CMD_OP(cmd, 6, 48, 8, char, endpoint2->type[14]); \ + MC_CMD_OP(cmd, 6, 56, 8, char, endpoint2->type[15]); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPRC_CMD_DISCONNECT(cmd, endpoint) \ +do { \ + MC_CMD_OP(cmd, 0, 0, 32, int, endpoint->id); \ + MC_CMD_OP(cmd, 0, 32, 32, int, endpoint->interface_id); \ + MC_CMD_OP(cmd, 1, 0, 8, char, endpoint->type[0]); \ + MC_CMD_OP(cmd, 1, 8, 8, char, endpoint->type[1]); \ + MC_CMD_OP(cmd, 1, 16, 8, char, endpoint->type[2]); \ + MC_CMD_OP(cmd, 1, 24, 8, char, endpoint->type[3]); \ + MC_CMD_OP(cmd, 1, 32, 8, char, endpoint->type[4]); \ + MC_CMD_OP(cmd, 1, 40, 8, char, endpoint->type[5]); \ + MC_CMD_OP(cmd, 1, 48, 8, char, endpoint->type[6]); \ + MC_CMD_OP(cmd, 1, 56, 8, char, endpoint->type[7]); \ + MC_CMD_OP(cmd, 2, 0, 8, char, endpoint->type[8]); \ + MC_CMD_OP(cmd, 2, 8, 8, char, endpoint->type[9]); \ + MC_CMD_OP(cmd, 2, 16, 8, char, endpoint->type[10]); \ + MC_CMD_OP(cmd, 2, 24, 8, char, endpoint->type[11]); \ + MC_CMD_OP(cmd, 2, 32, 8, char, endpoint->type[12]); \ + MC_CMD_OP(cmd, 2, 40, 8, char, endpoint->type[13]); \ + MC_CMD_OP(cmd, 2, 48, 8, char, endpoint->type[14]); \ + MC_CMD_OP(cmd, 2, 56, 8, char, endpoint->type[15]); \ +} while (0) + +/* cmd, param, offset, width, type, arg_name */ +#define DPRC_CMD_GET_CONNECTION(cmd, endpoint1) \ +do { \ + MC_CMD_OP(cmd, 0, 0, 32, int, endpoint1->id); \ + MC_CMD_OP(cmd, 0, 32, 32, int, endpoint1->interface_id); \ + MC_CMD_OP(cmd, 1, 0, 8, char, endpoint1->type[0]); \ + MC_CMD_OP(cmd, 1, 8, 8, char, endpoint1->type[1]); \ + MC_CMD_OP(cmd, 1, 16, 8, char, endpoint1->type[2]); \ + MC_CMD_OP(cmd, 1, 24, 8, char, endpoint1->type[3]); \ + MC_CMD_OP(cmd, 1, 32, 8, char, endpoint1->type[4]); \ + MC_CMD_OP(cmd, 1, 40, 8, char, endpoint1->type[5]); \ + MC_CMD_OP(cmd, 1, 48, 8, char, endpoint1->type[6]); \ + MC_CMD_OP(cmd, 1, 56, 8, char, endpoint1->type[7]); \ + MC_CMD_OP(cmd, 2, 0, 8, char, endpoint1->type[8]); \ + MC_CMD_OP(cmd, 2, 8, 8, char, endpoint1->type[9]); \ + MC_CMD_OP(cmd, 2, 16, 8, char, endpoint1->type[10]); \ + MC_CMD_OP(cmd, 2, 24, 8, char, endpoint1->type[11]); \ + MC_CMD_OP(cmd, 2, 32, 8, char, endpoint1->type[12]); \ + MC_CMD_OP(cmd, 2, 40, 8, char, endpoint1->type[13]); \ + MC_CMD_OP(cmd, 2, 48, 8, char, endpoint1->type[14]); \ + MC_CMD_OP(cmd, 2, 56, 8, char, endpoint1->type[15]); \ +} while (0) + + +/* cmd, param, offset, width, type, arg_name */ +#define DPRC_RSP_GET_CONNECTION(cmd, endpoint2, state) \ +do { \ + MC_RSP_OP(cmd, 3, 0, 32, int, endpoint2->id); \ + MC_RSP_OP(cmd, 3, 32, 32, int, endpoint2->interface_id); \ + MC_RSP_OP(cmd, 4, 0, 8, char, endpoint2->type[0]); \ + MC_RSP_OP(cmd, 4, 8, 8, char, endpoint2->type[1]); \ + MC_RSP_OP(cmd, 4, 16, 8, char, endpoint2->type[2]); \ + MC_RSP_OP(cmd, 4, 24, 8, char, endpoint2->type[3]); \ + MC_RSP_OP(cmd, 4, 32, 8, char, endpoint2->type[4]); \ + MC_RSP_OP(cmd, 4, 40, 8, char, endpoint2->type[5]); \ + MC_RSP_OP(cmd, 4, 48, 8, char, endpoint2->type[6]); \ + MC_RSP_OP(cmd, 4, 56, 8, char, endpoint2->type[7]); \ + MC_RSP_OP(cmd, 5, 0, 8, char, endpoint2->type[8]); \ + MC_RSP_OP(cmd, 5, 8, 8, char, endpoint2->type[9]); \ + MC_RSP_OP(cmd, 5, 16, 8, char, endpoint2->type[10]); \ + MC_RSP_OP(cmd, 5, 24, 8, char, endpoint2->type[11]); \ + MC_RSP_OP(cmd, 5, 32, 8, char, endpoint2->type[12]); \ + MC_RSP_OP(cmd, 5, 40, 8, char, endpoint2->type[13]); \ + MC_RSP_OP(cmd, 5, 48, 8, char, endpoint2->type[14]); \ + MC_RSP_OP(cmd, 5, 56, 8, char, endpoint2->type[15]); \ + MC_RSP_OP(cmd, 6, 0, 32, int, state); \ +} while (0) + +/* Data Path Resource Container API + * Contains DPRC API for managing and querying DPAA resources + */ +struct fsl_mc_io; + +/** + * Set this value as the icid value in dprc_cfg structure when creating a + * container, in case the ICID is not selected by the user and should be + * allocated by the DPRC from the pool of ICIDs. + */ +#define DPRC_GET_ICID_FROM_POOL (uint16_t)(~(0)) + +/** + * Set this value as the portal_id value in dprc_cfg structure when creating a + * container, in case the portal ID is not specifically selected by the + * user and should be allocated by the DPRC from the pool of portal ids. + */ +#define DPRC_GET_PORTAL_ID_FROM_POOL (int)(~(0)) + +/** + * dprc_get_container_id() - Get container ID associated with a given portal. + * @mc_io: Pointer to MC portal's I/O object + * @container_id: Requested container ID + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_get_container_id(struct fsl_mc_io *mc_io, int *container_id); + +/** + * dprc_open() - Open DPRC object for use + * @mc_io: Pointer to MC portal's I/O object + * @container_id: Container ID to open + * @token: Returned token of DPRC object + * + * Return: '0' on Success; Error code otherwise. + * + * @warning Required before any operation on the object. + */ +int dprc_open(struct fsl_mc_io *mc_io, int container_id, uint16_t *token); + +/** + * dprc_close() - Close the control session of the object + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPRC object + * + * After this function is called, no further operations are + * allowed on the object without opening a new control session. + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_close(struct fsl_mc_io *mc_io, uint16_t token); + +/** + * Container general options + * + * These options may be selected at container creation by the container creator + * and can be retrieved using dprc_get_attributes() + */ + +/* Spawn Policy Option allowed - Indicates that the new container is allowed + * to spawn and have its own child containers. + */ +#define DPRC_CFG_OPT_SPAWN_ALLOWED 0x00000001 + +/* General Container allocation policy - Indicates that the new container is + * allowed to allocate requested resources from its parent container; if not + * set, the container is only allowed to use resources in its own pools; Note + * that this is a container's global policy, but the parent container may + * override it and set specific quota per resource type. + */ +#define DPRC_CFG_OPT_ALLOC_ALLOWED 0x00000002 + +/* Object initialization allowed - software context associated with this + * container is allowed to invoke object initialization operations. + */ +#define DPRC_CFG_OPT_OBJ_CREATE_ALLOWED 0x00000004 + +/* Topology change allowed - software context associated with this + * container is allowed to invoke topology operations, such as attach/detach + * of network objects. + */ +#define DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED 0x00000008 + +/* IOMMU bypass - indicates whether objects of this container are permitted + * to bypass the IOMMU. + */ +#define DPRC_CFG_OPT_IOMMU_BYPASS 0x00000010 + +/* AIOP - Indicates that container belongs to AIOP. */ +#define DPRC_CFG_OPT_AIOP 0x00000020 + +/** + * struct dprc_cfg - Container configuration options + * @icid: Container's ICID; if set to 'DPRC_GET_ICID_FROM_POOL', a free + * ICID value is allocated by the DPRC + * @portal_id: Portal ID; if set to 'DPRC_GET_PORTAL_ID_FROM_POOL', a free + * portal ID is allocated by the DPRC + * @options: Combination of 'DPRC_CFG_OPT_<X>' options + */ +struct dprc_cfg { + uint16_t icid; + int portal_id; + uint64_t options; +}; + +/** + * dprc_reset_container - Reset child container. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPRC object + * @child_container_id: ID of the container to reset + * + * In case a software context crashes or becomes non-responsive, the parent + * may wish to reset its resources container before the software context is + * restarted. + * + * This routine informs all objects assigned to the child container that the + * container is being reset, so they may perform any cleanup operations that are + * needed. All objects handles that were owned by the child container shall be + * closed. + * + * Note that such request may be submitted even if the child software context + * has not crashed, but the resulting object cleanup operations will not be + * aware of that. + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_reset_container(struct fsl_mc_io *mc_io, + uint16_t token, + int child_container_id); + +/** + * struct dprc_attributes - Container attributes + * @container_id: Container's ID + * @icid: Container's ICID + * @portal_id: Container's portal ID + * @options: Container's options as set at container's creation + * @version: DPRC version + */ +struct dprc_attributes { + int container_id; + uint16_t icid; + int portal_id; + uint64_t options; + /** + * struct version - DPRC version + * @major: DPRC major version + * @minor: DPRC minor version + */ + struct { + uint16_t major; + uint16_t minor; + } version; +}; + +/** + * dprc_get_attributes() - Obtains container attributes + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPRC object + * @attributes Returned container attributes + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_get_attributes(struct fsl_mc_io *mc_io, + uint16_t token, + struct dprc_attributes *attributes); + +/** + * dprc_get_obj_count() - Obtains the number of objects in the DPRC + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPRC object + * @obj_count: Number of objects assigned to the DPRC + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_get_obj_count(struct fsl_mc_io *mc_io, uint16_t token, int *obj_count); + +/* Objects Attributes Flags */ + +/* Opened state - Indicates that an object is open by at least one owner */ +#define DPRC_OBJ_STATE_OPEN 0x00000001 +/* Plugged state - Indicates that the object is plugged */ +#define DPRC_OBJ_STATE_PLUGGED 0x00000002 + +/** + * struct dprc_obj_desc - Object descriptor, returned from dprc_get_obj() + * @type: Type of object: NULL terminated string + * @id: ID of logical object resource + * @vendor: Object vendor identifier + * @ver_major: Major version number + * @ver_minor: Minor version number + * @irq_count: Number of interrupts supported by the object + * @region_count: Number of mappable regions supported by the object + * @state: Object state: combination of DPRC_OBJ_STATE_ states + */ +struct dprc_obj_desc { + char type[16]; + int id; + uint16_t vendor; + uint16_t ver_major; + uint16_t ver_minor; + uint8_t irq_count; + uint8_t region_count; + uint32_t state; +}; + +/** + * dprc_get_obj() - Get general information on an object + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPRC object + * @obj_index: Index of the object to be queried (< obj_count) + * @obj_desc: Returns the requested object descriptor + * + * The object descriptors are retrieved one by one by incrementing + * obj_index up to (not including) the value of obj_count returned + * from dprc_get_obj_count(). dprc_get_obj_count() must + * be called prior to dprc_get_obj(). + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_get_obj(struct fsl_mc_io *mc_io, + uint16_t token, + int obj_index, + struct dprc_obj_desc *obj_desc); + +/** + * dprc_get_res_count() - Obtains the number of free resources that are assigned + * to this container, by pool type + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPRC object + * @type: pool type + * @res_count: Returned number of free resources of the given + * resource type that are assigned to this DPRC + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_get_res_count(struct fsl_mc_io *mc_io, + uint16_t token, + char *type, + int *res_count); + +/** + * enum dprc_iter_status - Iteration status + * @DPRC_ITER_STATUS_FIRST: Perform first iteration + * @DPRC_ITER_STATUS_MORE: Indicates more/next iteration is needed + * @DPRC_ITER_STATUS_LAST: Indicates last iteration + */ +enum dprc_iter_status { + DPRC_ITER_STATUS_FIRST = 0, + DPRC_ITER_STATUS_MORE = 1, + DPRC_ITER_STATUS_LAST = 2 +}; + +/** + * struct dprc_res_ids_range_desc - Resource ID range descriptor + * @base_id: Base resource ID of this range + * @last_id: Last resource ID of this range + * @iter_status: Iteration status - should be set to DPRC_ITER_STATUS_FIRST at + * first iteration; while the returned marker is DPRC_ITER_STATUS_MORE, + * additional iterations are needed, until the returned marker is + * DPRC_ITER_STATUS_LAST + */ +struct dprc_res_ids_range_desc { + int base_id; + int last_id; + enum dprc_iter_status iter_status; +}; + +/** + * dprc_get_res_ids() - Obtains IDs of free resources in the container + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPRC object + * @type: pool type + * @range_desc: range descriptor + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_get_res_ids(struct fsl_mc_io *mc_io, + uint16_t token, + char *type, + struct dprc_res_ids_range_desc *range_desc); + +/** + * struct dprc_region_desc - Mappable region descriptor + * @base_paddr: Region base physical address + * @size: Region size (in bytes) + */ +struct dprc_region_desc { + uint64_t base_paddr; + uint32_t size; +}; + +/** + * dprc_get_obj_region() - Get region information for a specified object. + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPRC object + * @obj_type; Object type as returned in dprc_get_obj() + * @obj_id: Unique object instance as returned in dprc_get_obj() + * @region_index: The specific region to query + * @region_desc: Returns the requested region descriptor + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_get_obj_region(struct fsl_mc_io *mc_io, + uint16_t token, + char *obj_type, + int obj_id, + uint8_t region_index, + struct dprc_region_desc *region_desc); +/** + * struct dprc_endpoint - Endpoint description for link connect/disconnect + * operations + * @type: Endpoint object type: NULL terminated string + * @id: Endpoint object ID + * @interface_id: Interface ID; should be set for endpoints with multiple + * interfaces ("dpsw", "dpdmux"); for others, always set to 0 + */ +struct dprc_endpoint { + char type[16]; + int id; + int interface_id; +}; + +/** + * dprc_connect() - Connect two endpoints to create a network link between them + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPRC object + * @endpoint1: Endpoint 1 configuration parameters + * @endpoint2: Endpoint 2 configuration parameters + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_connect(struct fsl_mc_io *mc_io, + uint16_t token, + const struct dprc_endpoint *endpoint1, + const struct dprc_endpoint *endpoint2); + +/** + * dprc_disconnect() - Disconnect one endpoint to remove its network connection + * @mc_io: Pointer to MC portal's I/O object + * @token: Token of DPRC object + * @endpoint: Endpoint configuration parameters + * + * Return: '0' on Success; Error code otherwise. + */ +int dprc_disconnect(struct fsl_mc_io *mc_io, + uint16_t token, + const struct dprc_endpoint *endpoint); + +/** +* dprc_get_connection() - Get connected endpoint and link status if connection +* exists. +* @mc_io Pointer to MC portal's I/O object +* @token Token of DPRC object +* @endpoint1 Endpoint 1 configuration parameters +* @endpoint2 Returned endpoint 2 configuration parameters +* @state: Returned link state: 1 - link is up, 0 - link is down +* +* Return: '0' on Success; -ENAVAIL if connection does not exist. +*/ +int dprc_get_connection(struct fsl_mc_io *mc_io, + uint16_t token, + const struct dprc_endpoint *endpoint1, + struct dprc_endpoint *endpoint2, + int *state); + +#endif /* _FSL_DPRC_H */ diff --git a/include/fsl-mc/fsl_mc.h b/include/fsl-mc/fsl_mc.h index b9f089e..ec24415 100644 --- a/include/fsl-mc/fsl_mc.h +++ b/include/fsl-mc/fsl_mc.h @@ -53,7 +53,8 @@ struct mc_ccsr_registers { u32 reg_error[]; }; -int mc_init(bd_t *bis); - int get_mc_boot_status(void); +unsigned long mc_get_dram_block_size(void); +int fsl_mc_ldpaa_init(bd_t *bis); +void fsl_mc_ldpaa_exit(bd_t *bis); #endif diff --git a/include/fsl-mc/fsl_mc_cmd.h b/include/fsl-mc/fsl_mc_cmd.h index e7fcb5b..cb39c39 100644 --- a/include/fsl-mc/fsl_mc_cmd.h +++ b/include/fsl-mc/fsl_mc_cmd.h @@ -1,4 +1,4 @@ -/* Copyright 2014 Freescale Semiconductor Inc. +/* Copyright 2013-2015 Freescale Semiconductor Inc. * * SPDX-License-Identifier: GPL-2.0+ */ @@ -41,9 +41,9 @@ enum mc_cmd_status { #define MC_CMD_HDR_CMDID_O 52 /* Command ID field offset */ #define MC_CMD_HDR_CMDID_S 12 /* Command ID field size */ -#define MC_CMD_HDR_AUTHID_O 38 /* Authentication ID field offset */ -#define MC_CMD_HDR_AUTHID_S 10 /* Authentication ID field size */ #define MC_CMD_HDR_STATUS_O 16 /* Status field offset */ +#define MC_CMD_HDR_TOKEN_O 38 /* Token field offset */ +#define MC_CMD_HDR_TOKEN_S 10 /* Token field size */ #define MC_CMD_HDR_STATUS_S 8 /* Status field size*/ #define MC_CMD_HDR_PRI_O 15 /* Priority field offset */ #define MC_CMD_HDR_PRI_S 1 /* Priority field size */ @@ -52,12 +52,15 @@ enum mc_cmd_status { ((enum mc_cmd_status)u64_dec((_hdr), \ MC_CMD_HDR_STATUS_O, MC_CMD_HDR_STATUS_S)) -#define MC_CMD_HDR_READ_AUTHID(_hdr) \ - ((uint16_t)u64_dec((_hdr), MC_CMD_HDR_AUTHID_O, MC_CMD_HDR_AUTHID_S)) +#define MC_CMD_HDR_READ_TOKEN(_hdr) \ + ((uint16_t)u64_dec((_hdr), MC_CMD_HDR_TOKEN_O, MC_CMD_HDR_TOKEN_S)) #define MC_CMD_PRI_LOW 0 /*!< Low Priority command indication */ #define MC_CMD_PRI_HIGH 1 /*!< High Priority command indication */ +#define MC_EXT_OP(_ext, _param, _offset, _width, _type, _arg) \ + ((_ext)[_param] |= u64_enc((_offset), (_width), _arg)) + #define MC_CMD_OP(_cmd, _param, _offset, _width, _type, _arg) \ ((_cmd).params[_param] |= u64_enc((_offset), (_width), _arg)) @@ -66,12 +69,12 @@ enum mc_cmd_status { static inline uint64_t mc_encode_cmd_header(uint16_t cmd_id, uint8_t priority, - uint16_t auth_id) + uint16_t token) { uint64_t hdr; hdr = u64_enc(MC_CMD_HDR_CMDID_O, MC_CMD_HDR_CMDID_S, cmd_id); - hdr |= u64_enc(MC_CMD_HDR_AUTHID_O, MC_CMD_HDR_AUTHID_S, auth_id); + hdr |= u64_enc(MC_CMD_HDR_TOKEN_O, MC_CMD_HDR_TOKEN_S, token); hdr |= u64_enc(MC_CMD_HDR_PRI_O, MC_CMD_HDR_PRI_S, priority); hdr |= u64_enc(MC_CMD_HDR_STATUS_O, MC_CMD_HDR_STATUS_S, MC_CMD_STATUS_READY); diff --git a/include/fsl-mc/fsl_mc_private.h b/include/fsl-mc/fsl_mc_private.h new file mode 100644 index 0000000..9f06978 --- /dev/null +++ b/include/fsl-mc/fsl_mc_private.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _FSL_MC_PRIVATE_H_ +#define _FSL_MC_PRIVATE_H_ + +#include <errno.h> +#include <malloc.h> +#include <asm/io.h> +#include <linux/compat.h> +#include <linux/types.h> +#include <linux/stringify.h> + +#include <fsl-mc/fsl_mc_sys.h> +#include <fsl-mc/fsl_mc_cmd.h> +#include <fsl-mc/fsl_dprc.h> +#include <fsl-mc/fsl_dpbp.h> + +extern struct fsl_mc_io *dflt_mc_io; + +/** + * struct dpbp_node - DPBP strucuture + * @uint16_t handle: DPBP object handle + * @int dpbp_id: DPBP id + */ +struct fsl_dpbp_obj { + uint16_t dpbp_handle; + struct dpbp_attr dpbp_attr; +}; + +extern struct fsl_dpbp_obj *dflt_dpbp; + +/** + * struct fsl_dpio_obj - DPIO strucuture + * @int dpio_id: DPIO id + * @struct qbman_swp *sw_portal: SW portal object + */ +struct fsl_dpio_obj { + int dpio_id; + struct qbman_swp *sw_portal; /** SW portal object */ +}; + +extern struct fsl_dpio_obj *dflt_dpio; + +int mc_init(void); +int ldpaa_eth_init(struct dprc_obj_desc obj_desc); +#endif /* _FSL_MC_PRIVATE_H_ */ diff --git a/include/fsl-mc/fsl_qbman_base.h b/include/fsl-mc/fsl_qbman_base.h new file mode 100644 index 0000000..c92cbe1 --- /dev/null +++ b/include/fsl-mc/fsl_qbman_base.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _FSL_QBMAN_BASE_H +#define _FSL_QBMAN_BASE_H + +/* Descriptor for a QBMan instance on the SoC. On partitions/targets that do not + * control this QBMan instance, these values may simply be place-holders. The + * idea is simply that we be able to distinguish between them, eg. so that SWP + * descriptors can identify which QBMan instance they belong to. */ +struct qbman_block_desc { + void *ccsr_reg_bar; /* CCSR register map */ + int irq_rerr; /* Recoverable error interrupt line */ + int irq_nrerr; /* Non-recoverable error interrupt line */ +}; + +/* Descriptor for a QBMan software portal, expressed in terms that make sense to + * the user context. Ie. on MC, this information is likely to be true-physical, + * and instantiated statically at compile-time. On GPP, this information is + * likely to be obtained via "discovery" over a partition's "layerscape bus" + * (ie. in response to a MC portal command), and would take into account any + * virtualisation of the GPP user's address space and/or interrupt numbering. */ +struct qbman_swp_desc { + const struct qbman_block_desc *block; /* The QBMan instance */ + void *cena_bar; /* Cache-enabled portal register map */ + void *cinh_bar; /* Cache-inhibited portal register map */ +}; + +/* Driver object for managing a QBMan portal */ +struct qbman_swp; + +/* Place-holder for FDs, we represent it via the simplest form that we need for + * now. Different overlays may be needed to support different options, etc. (It + * is impractical to define One True Struct, because the resulting encoding + * routines (lots of read-modify-writes) would be worst-case performance whether + * or not circumstances required them.) + * + * Note, as with all data-structures exchanged between software and hardware (be + * they located in the portal register map or DMA'd to and from main-memory), + * the driver ensures that the caller of the driver API sees the data-structures + * in host-endianness. "struct qbman_fd" is no exception. The 32-bit words + * contained within this structure are represented in host-endianness, even if + * hardware always treats them as little-endian. As such, if any of these fields + * are interpreted in a binary (rather than numerical) fashion by hardware + * blocks (eg. accelerators), then the user should be careful. We illustrate + * with an example; + * + * Suppose the desired behaviour of an accelerator is controlled by the "frc" + * field of the FDs that are sent to it. Suppose also that the behaviour desired + * by the user corresponds to an "frc" value which is expressed as the literal + * sequence of bytes 0xfe, 0xed, 0xab, and 0xba. So "frc" should be the 32-bit + * value in which 0xfe is the first byte and 0xba is the last byte, and as + * hardware is little-endian, this amounts to a 32-bit "value" of 0xbaabedfe. If + * the software is little-endian also, this can simply be achieved by setting + * frc=0xbaabedfe. On the other hand, if software is big-endian, it should set + * frc=0xfeedabba! The best away of avoiding trouble with this sort of thing is + * to treat the 32-bit words as numerical values, in which the offset of a field + * from the beginning of the first byte (as required or generated by hardware) + * is numerically encoded by a left-shift (ie. by raising the field to a + * corresponding power of 2). Ie. in the current example, software could set + * "frc" in the following way, and it would work correctly on both little-endian + * and big-endian operation; + * fd.frc = (0xfe << 0) | (0xed << 8) | (0xab << 16) | (0xba << 24); + */ +struct qbman_fd { + union { + uint32_t words[8]; + struct qbman_fd_simple { + uint32_t addr_lo; + uint32_t addr_hi; + uint32_t len; + /* offset in the MS 16 bits, BPID in the LS 16 bits */ + uint32_t bpid_offset; + uint32_t frc; /* frame context */ + /* "err", "va", "cbmt", "asal", [...] */ + uint32_t ctrl; + /* flow context */ + uint32_t flc_lo; + uint32_t flc_hi; + } simple; + }; +}; + +#endif /* !_FSL_QBMAN_BASE_H */ diff --git a/include/fsl-mc/fsl_qbman_portal.h b/include/fsl-mc/fsl_qbman_portal.h new file mode 100644 index 0000000..2aadad8 --- /dev/null +++ b/include/fsl-mc/fsl_qbman_portal.h @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _FSL_QBMAN_PORTAL_H +#define _FSL_QBMAN_PORTAL_H + +#include <fsl-mc/fsl_qbman_base.h> + +/* Create and destroy a functional object representing the given QBMan portal + * descriptor. */ +struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *); + + /************/ + /* Dequeues */ + /************/ + +/* See the QBMan driver API documentation for details on the enqueue + * mechanisms. NB: the use of a 'ldpaa_' prefix for this type is because it is + * primarily used by the "DPIO" layer that sits above (and hides) the QBMan + * driver. The structure is defined in the DPIO interface, but to avoid circular + * dependencies we just pre/re-declare it here opaquely. */ +struct ldpaa_dq; + + +/* ------------------- */ +/* Pull-mode dequeuing */ +/* ------------------- */ + +struct qbman_pull_desc { + uint32_t dont_manipulate_directly[6]; +}; + +/* Clear the contents of a descriptor to default/starting state. */ +void qbman_pull_desc_clear(struct qbman_pull_desc *); +/* If not called, or if called with 'storage' as NULL, the result pull dequeues + * will produce results to DQRR. If 'storage' is non-NULL, then results are + * produced to the given memory location (using the physical/DMA address which + * the caller provides in 'storage_phys'), and 'stash' controls whether or not + * those writes to main-memory express a cache-warming attribute. */ +void qbman_pull_desc_set_storage(struct qbman_pull_desc *, + struct ldpaa_dq *storage, + dma_addr_t storage_phys, + int stash); +/* numframes must be between 1 and 16, inclusive */ +void qbman_pull_desc_set_numframes(struct qbman_pull_desc *, uint8_t numframes); +/* token is the value that shows up in the dequeue results that can be used to + * detect when the results have been published, and is not really used when + * dequeue results go to DQRR. The easiest technique is to zero result "storage" + * before issuing a pull dequeue, and use any non-zero 'token' value. */ +void qbman_pull_desc_set_token(struct qbman_pull_desc *, uint8_t token); +/* Exactly one of the following descriptor "actions" should be set. (Calling any + * one of these will replace the effect of any prior call to one of these.) + * - pull dequeue from the given frame queue (FQ) + * - pull dequeue from any FQ in the given work queue (WQ) + * - pull dequeue from any FQ in any WQ in the given channel + */ +void qbman_pull_desc_set_fq(struct qbman_pull_desc *, uint32_t fqid); + +/* Issue the pull dequeue command */ +int qbman_swp_pull(struct qbman_swp *, struct qbman_pull_desc *); + +/* -------------------------------- */ +/* Polling DQRR for dequeue results */ +/* -------------------------------- */ + +/* NULL return if there are no unconsumed DQRR entries. Returns a DQRR entry + * only once, so repeated calls can return a sequence of DQRR entries, without + * requiring they be consumed immediately or in any particular order. */ +const struct ldpaa_dq *qbman_swp_dqrr_next(struct qbman_swp *); +/* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). */ +void qbman_swp_dqrr_consume(struct qbman_swp *, const struct ldpaa_dq *); + +/* ------------------------------------------------- */ +/* Polling user-provided storage for dequeue results */ +/* ------------------------------------------------- */ + +/* Only used for user-provided storage of dequeue results, not DQRR. Prior to + * being used, the storage must set "oldtoken", so that the driver notices when + * hardware has filled it in with results using a "newtoken". NB, for efficiency + * purposes, the driver will perform any required endianness conversion to + * ensure that the user's dequeue result storage is in host-endian format + * (whether or not that is the same as the little-endian format that hardware + * DMA'd to the user's storage). As such, once the user has called + * qbman_dq_entry_has_newtoken() and been returned a valid dequeue result, they + * should not call it again on the same memory location (except of course if + * another dequeue command has been executed to produce a new result to that + * location). + */ +void qbman_dq_entry_set_oldtoken(struct ldpaa_dq *, + unsigned int num_entries, + uint8_t oldtoken); +int qbman_dq_entry_has_newtoken(struct qbman_swp *, + const struct ldpaa_dq *, + uint8_t newtoken); + +/* -------------------------------------------------------- */ +/* Parsing dequeue entries (DQRR and user-provided storage) */ +/* -------------------------------------------------------- */ + +/* DQRR entries may contain non-dequeue results, ie. notifications */ +int qbman_dq_entry_is_DQ(const struct ldpaa_dq *); + + /************/ + /* Enqueues */ + /************/ + +struct qbman_eq_desc { + uint32_t dont_manipulate_directly[8]; +}; + + +/* Clear the contents of a descriptor to default/starting state. */ +void qbman_eq_desc_clear(struct qbman_eq_desc *); +/* Exactly one of the following descriptor "actions" should be set. (Calling + * any one of these will replace the effect of any prior call to one of these.) + * - enqueue without order-restoration + * - enqueue with order-restoration + * - fill a hole in the order-restoration sequence, without any enqueue + * - advance NESN (Next Expected Sequence Number), without any enqueue + * 'respond_success' indicates whether an enqueue response should be DMA'd + * after success (otherwise a response is DMA'd only after failure). + * 'incomplete' indicates that other fragments of the same 'seqnum' are yet to + * be enqueued. + */ +void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *, int respond_success); +void qbman_eq_desc_set_response(struct qbman_eq_desc *, + dma_addr_t storage_phys, + int stash); +/* token is the value that shows up in an enqueue response that can be used to + * detect when the results have been published. The easiest technique is to zero + * result "storage" before issuing an enqueue, and use any non-zero 'token' + * value. */ +void qbman_eq_desc_set_token(struct qbman_eq_desc *, uint8_t token); +/* Exactly one of the following descriptor "targets" should be set. (Calling any + * one of these will replace the effect of any prior call to one of these.) + * - enqueue to a frame queue + * - enqueue to a queuing destination + * Note, that none of these will have any affect if the "action" type has been + * set to "orp_hole" or "orp_nesn". + */ +void qbman_eq_desc_set_fq(struct qbman_eq_desc *, uint32_t fqid); +void qbman_eq_desc_set_qd(struct qbman_eq_desc *, uint32_t qdid, + uint32_t qd_bin, uint32_t qd_prio); + +/* Issue an enqueue command. ('fd' should only be NULL if the "action" of the + * descriptor is "orp_hole" or "orp_nesn".) */ +int qbman_swp_enqueue(struct qbman_swp *, const struct qbman_eq_desc *, + const struct qbman_fd *fd); + + /*******************/ + /* Buffer releases */ + /*******************/ + +struct qbman_release_desc { + uint32_t dont_manipulate_directly[1]; +}; + +/* Clear the contents of a descriptor to default/starting state. */ +void qbman_release_desc_clear(struct qbman_release_desc *); +/* Set the ID of the buffer pool to release to */ +void qbman_release_desc_set_bpid(struct qbman_release_desc *, uint32_t bpid); +/* Issue a release command. 'num_buffers' must be less than 8. */ +int qbman_swp_release(struct qbman_swp *, const struct qbman_release_desc *, + const uint64_t *buffers, unsigned int num_buffers); + + /*******************/ + /* Buffer acquires */ + /*******************/ + +int qbman_swp_acquire(struct qbman_swp *, uint32_t bpid, uint64_t *buffers, + unsigned int num_buffers); +#endif /* !_FSL_QBMAN_PORTAL_H */ diff --git a/include/fsl-mc/ldpaa_wriop.h b/include/fsl-mc/ldpaa_wriop.h new file mode 100644 index 0000000..ca8e440 --- /dev/null +++ b/include/fsl-mc/ldpaa_wriop.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2015 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __LDPAA_WRIOP_H +#define __LDPAA_WRIOP_H + + #include <phy.h> + +enum wriop_port { + WRIOP1_DPMAC1 = 1, + WRIOP1_DPMAC2, + WRIOP1_DPMAC3, + WRIOP1_DPMAC4, + WRIOP1_DPMAC5, + WRIOP1_DPMAC6, + WRIOP1_DPMAC7, + WRIOP1_DPMAC8, + WRIOP1_DPMAC9, + WRIOP1_DPMAC10, + WRIOP1_DPMAC11, + WRIOP1_DPMAC12, + WRIOP1_DPMAC13, + WRIOP1_DPMAC14, + WRIOP1_DPMAC15, + WRIOP1_DPMAC16, + WRIOP1_DPMAC17, + WRIOP1_DPMAC18, + WRIOP1_DPMAC19, + WRIOP1_DPMAC20, + WRIOP1_DPMAC21, + WRIOP1_DPMAC22, + WRIOP1_DPMAC23, + WRIOP1_DPMAC24, + NUM_WRIOP_PORTS, +}; + +struct wriop_dpmac_info { + u8 enabled; + u8 id; + u8 phy_addr; + u8 board_mux; + void *phy_regs; + phy_interface_t enet_if; + struct phy_device *phydev; + struct mii_dev *bus; +}; + +extern struct wriop_dpmac_info dpmac_info[NUM_WRIOP_PORTS]; + +#define DEFAULT_WRIOP_MDIO1_NAME "FSL_MDIO0" +#define DEFAULT_WRIOP_MDIO2_NAME "FSL_MDIO1" + +void wriop_init_dpmac(int, int, int); +void wriop_disable_dpmac(int); +void wriop_enable_dpmac(int); +void wriop_set_mdio(int, struct mii_dev *); +struct mii_dev *wriop_get_mdio(int); +void wriop_set_phy_address(int, int); +int wriop_get_phy_address(int); +void wriop_set_phy_dev(int, struct phy_device *); +struct phy_device *wriop_get_phy_dev(int); +phy_interface_t wriop_get_enet_if(int); + +void wriop_dpmac_disable(int); +void wriop_dpmac_enable(int); +phy_interface_t wriop_dpmac_enet_if(int, int); +#endif /* __LDPAA_WRIOP_H */ diff --git a/include/fsl_ddr.h b/include/fsl_ddr.h index feccef9..4099a74 100644 --- a/include/fsl_ddr.h +++ b/include/fsl_ddr.h @@ -34,9 +34,7 @@ #define ddr_clrsetbits32(a, clear, set) clrsetbits_be32(a, clear, set) #endif -#define _DDR_ADDR CONFIG_SYS_FSL_DDR_ADDR - -u32 fsl_ddr_get_version(void); +u32 fsl_ddr_get_version(unsigned int ctrl_num); #if defined(CONFIG_DDR_SPD) || defined(CONFIG_SPD_EEPROM) /* diff --git a/include/fsl_ddr_sdram.h b/include/fsl_ddr_sdram.h index 095b33e..e5b6e03 100644 --- a/include/fsl_ddr_sdram.h +++ b/include/fsl_ddr_sdram.h @@ -155,6 +155,8 @@ typedef struct ddr4_spd_eeprom_s generic_spd_eeprom_t; #define MD_CNTL_CKE_CNTL_HIGH 0x00200000 #define MD_CNTL_WRCW 0x00080000 #define MD_CNTL_MD_VALUE(x) (x & 0x0000FFFF) +#define MD_CNTL_CS_SEL(x) (((x) & 0x7) << 28) +#define MD_CNTL_MD_SEL(x) (((x) & 0xf) << 24) /* DDR_CDR1 */ #define DDR_CDR1_DHC_EN 0x80000000 @@ -165,6 +167,7 @@ typedef struct ddr4_spd_eeprom_s generic_spd_eeprom_t; #define DDR_CDR2_ODT(x) (x & DDR_CDR2_ODT_MASK) #define DDR_CDR2_VREF_OVRD(x) (0x00008080 | ((((x) - 37) & 0x3F) << 8)) #define DDR_CDR2_VREF_TRAIN_EN 0x00000080 +#define DDR_CDR2_VREF_RANGE_2 0x00000040 #if (defined(CONFIG_SYS_FSL_DDR_VER) && \ (CONFIG_SYS_FSL_DDR_VER >= FSL_DDR_VER_4_7)) diff --git a/include/fsl_debug_server.h b/include/fsl_debug_server.h new file mode 100644 index 0000000..28d8adb --- /dev/null +++ b/include/fsl_debug_server.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __FSL_DBG_SERVER_H__ +#define __FSL_DBG_SERVER_H__ + +#include <asm/io.h> +#include <common.h> + +/* + * Define Debug Server firmware version information + */ + +/* Major version number: incremented on API compatibility changes */ +#define DEBUG_SERVER_VER_MAJOR 0 + +/* Minor version number: incremented on API additions (backward + * compatible); reset when major version is incremented. + */ +#define DEBUG_SERVER_VER_MINOR 1 + +#define DEBUG_SERVER_INIT_STATUS (1 << 0) +#define DEBUG_SERVER_INIT_STATUS_MASK (0x00000001) + +int debug_server_init(void); +unsigned long debug_server_get_dram_block_size(void); + +#endif /* __FSL_DBG_SERVER_H__ */ + diff --git a/include/fsl_esdhc.h b/include/fsl_esdhc.h index 57295b4..41bf05b 100644 --- a/include/fsl_esdhc.h +++ b/include/fsl_esdhc.h @@ -158,7 +158,11 @@ #define ESDHC_VENDORSPEC_VSELECT 0x00000002 /* Use 1.8V */ struct fsl_esdhc_cfg { +#ifdef CONFIG_LS2085A + u64 esdhc_base; +#else u32 esdhc_base; +#endif u32 sdhc_clk; u8 max_bus_width; struct mmc_config cfg; diff --git a/include/fsl_ifc.h b/include/fsl_ifc.h index 11474b7..a7ddd5f 100644 --- a/include/fsl_ifc.h +++ b/include/fsl_ifc.h @@ -790,24 +790,36 @@ extern void print_ifc_regs(void); extern void init_early_memctl_regs(void); void init_final_memctl_regs(void); -#define IFC_BASE_ADDR ((struct fsl_ifc *)CONFIG_SYS_IFC_ADDR) - -#define get_ifc_cspr_ext(i) (ifc_in32(&(IFC_BASE_ADDR)->cspr_cs[i].cspr_ext)) -#define get_ifc_cspr(i) (ifc_in32(&(IFC_BASE_ADDR)->cspr_cs[i].cspr)) -#define get_ifc_csor_ext(i) (ifc_in32(&(IFC_BASE_ADDR)->csor_cs[i].csor_ext)) -#define get_ifc_csor(i) (ifc_in32(&(IFC_BASE_ADDR)->csor_cs[i].csor)) -#define get_ifc_amask(i) (ifc_in32(&(IFC_BASE_ADDR)->amask_cs[i].amask)) -#define get_ifc_ftim(i, j) (ifc_in32(&(IFC_BASE_ADDR)->ftim_cs[i].ftim[j])) - -#define set_ifc_cspr_ext(i, v) \ - (ifc_out32(&(IFC_BASE_ADDR)->cspr_cs[i].cspr_ext, v)) -#define set_ifc_cspr(i, v) (ifc_out32(&(IFC_BASE_ADDR)->cspr_cs[i].cspr, v)) -#define set_ifc_csor_ext(i, v) \ - (ifc_out32(&(IFC_BASE_ADDR)->csor_cs[i].csor_ext, v)) -#define set_ifc_csor(i, v) (ifc_out32(&(IFC_BASE_ADDR)->csor_cs[i].csor, v)) -#define set_ifc_amask(i, v) (ifc_out32(&(IFC_BASE_ADDR)->amask_cs[i].amask, v)) -#define set_ifc_ftim(i, j, v) \ - (ifc_out32(&(IFC_BASE_ADDR)->ftim_cs[i].ftim[j], v)) +#define IFC_RREGS_4KOFFSET (4*1024) +#define IFC_RREGS_64KOFFSET (64*1024) + +#define IFC_FCM_BASE_ADDR \ + ((struct fsl_ifc_fcm *)CONFIG_SYS_IFC_ADDR) + +#define get_ifc_cspr_ext(i) \ + (ifc_in32(&(IFC_FCM_BASE_ADDR)->cspr_cs[i].cspr_ext)) +#define get_ifc_cspr(i) \ + (ifc_in32(&(IFC_FCM_BASE_ADDR)->cspr_cs[i].cspr)) +#define get_ifc_csor_ext(i) \ + (ifc_in32(&(IFC_FCM_BASE_ADDR)->csor_cs[i].csor_ext)) +#define get_ifc_csor(i) \ + (ifc_in32(&(IFC_FCM_BASE_ADDR)->csor_cs[i].csor)) +#define get_ifc_amask(i) \ + (ifc_in32(&(IFC_FCM_BASE_ADDR)->amask_cs[i].amask)) +#define get_ifc_ftim(i, j) \ + (ifc_in32(&(IFC_FCM_BASE_ADDR)->ftim_cs[i].ftim[j])) +#define set_ifc_cspr_ext(i, v) \ + (ifc_out32(&(IFC_FCM_BASE_ADDR)->cspr_cs[i].cspr_ext, v)) +#define set_ifc_cspr(i, v) \ + (ifc_out32(&(IFC_FCM_BASE_ADDR)->cspr_cs[i].cspr, v)) +#define set_ifc_csor_ext(i, v) \ + (ifc_out32(&(IFC_FCM_BASE_ADDR)->csor_cs[i].csor_ext, v)) +#define set_ifc_csor(i, v) \ + (ifc_out32(&(IFC_FCM_BASE_ADDR)->csor_cs[i].csor, v)) +#define set_ifc_amask(i, v) \ + (ifc_out32(&(IFC_FCM_BASE_ADDR)->amask_cs[i].amask, v)) +#define set_ifc_ftim(i, j, v) \ + (ifc_out32(&(IFC_FCM_BASE_ADDR)->ftim_cs[i].ftim[j], v)) enum ifc_chip_sel { IFC_CS0, @@ -869,20 +881,26 @@ struct fsl_ifc_nand { u32 nand_evter_en; u32 res17[0x2]; u32 nand_evter_intr_en; - u32 res18[0x2]; + u32 nand_vol_addr_stat; + u32 res18; u32 nand_erattr0; u32 nand_erattr1; u32 res19[0x10]; u32 nand_fsr; - u32 res20; - u32 nand_eccstat[4]; - u32 res21[0x20]; + u32 res20[0x3]; + u32 nand_eccstat[6]; + u32 res21[0x1c]; u32 nanndcr; u32 res22[0x2]; u32 nand_autoboot_trgr; u32 res23; u32 nand_mdr; - u32 res24[0x5C]; + u32 res24[0x1c]; + u32 nand_dll_lowcfg0; + u32 nand_dll_lowcfg1; + u32 res25; + u32 nand_dll_lowstat; + u32 res26[0x3C]; }; /* @@ -917,7 +935,6 @@ struct fsl_ifc_gpcm { u32 gpcm_erattr1; u32 gpcm_erattr2; u32 gpcm_stat; - u32 res4[0x1F3]; }; #ifdef CONFIG_SYS_FSL_IFC_BANK_COUNT @@ -965,9 +982,11 @@ struct fsl_ifc_ftim { }; /* - * IFC Controller Registers + * IFC Controller Global Registers + * FCM - Flash control machine */ -struct fsl_ifc { + +struct fsl_ifc_fcm { u32 ifc_rev; u32 res1[0x2]; struct fsl_ifc_cspr cspr_cs[CONFIG_SYS_FSL_IFC_BANK_COUNT]; @@ -979,7 +998,8 @@ struct fsl_ifc { struct fsl_ifc_ftim ftim_cs[CONFIG_SYS_FSL_IFC_BANK_COUNT]; u8 res5[IFC_FTIM_REG_LEN - IFC_FTIM_USED_LEN]; u32 rb_stat; - u32 res6[0x2]; + u32 rb_map; + u32 wp_map; u32 ifc_gcr; u32 res7[0x2]; u32 cm_evter_stat; @@ -993,12 +1013,20 @@ struct fsl_ifc { u32 res11[0x2]; u32 ifc_ccr; u32 ifc_csr; - u32 res12[0x2EB]; + u32 ddr_ccr_low; +}; + +struct fsl_ifc_runtime { struct fsl_ifc_nand ifc_nand; struct fsl_ifc_nor ifc_nor; struct fsl_ifc_gpcm ifc_gpcm; }; +struct fsl_ifc { + struct fsl_ifc_fcm *gregs; + struct fsl_ifc_runtime *rregs; +}; + #ifdef CONFIG_SYS_FSL_ERRATUM_IFC_A002769 #undef CSPR_MSEL_NOR #define CSPR_MSEL_NOR CSPR_MSEL_GPCM diff --git a/arch/powerpc/include/asm/fsl_memac.h b/include/fsl_memac.h index bed2a40..bed2a40 100644 --- a/arch/powerpc/include/asm/fsl_memac.h +++ b/include/fsl_memac.h diff --git a/include/fsl_usb.h b/include/fsl_usb.h index d251f5d..33d9f03 100644 --- a/include/fsl_usb.h +++ b/include/fsl_usb.h @@ -87,6 +87,33 @@ struct ccsr_usb_phy { /* USB Erratum Checking code */ #ifdef CONFIG_PPC +static inline bool has_dual_phy(void) +{ + u32 svr = get_svr(); + u32 soc = SVR_SOC_VER(svr); + + switch (soc) { + case SVR_T1023: + case SVR_T1024: + case SVR_T1013: + case SVR_T1014: + return IS_SVR_REV(svr, 1, 0); + case SVR_T1040: + case SVR_T1042: + case SVR_T1020: + case SVR_T1022: + case SVR_T2080: + case SVR_T2081: + return IS_SVR_REV(svr, 1, 0) || IS_SVR_REV(svr, 1, 1); + case SVR_T4240: + case SVR_T4160: + case SVR_T4080: + return IS_SVR_REV(svr, 1, 0) || IS_SVR_REV(svr, 2, 0); + } + + return false; +} + static inline bool has_erratum_a006261(void) { u32 svr = get_svr(); @@ -155,8 +182,13 @@ static inline bool has_erratum_a007792(void) case SVR_T4240: case SVR_T4160: return IS_SVR_REV(svr, 2, 0); - case SVR_T1040: + case SVR_T1024: + case SVR_T1023: return IS_SVR_REV(svr, 1, 0); + case SVR_T1040: + case SVR_T1042: + case SVR_T1020: + case SVR_T1022: case SVR_T2080: case SVR_T2081: return IS_SVR_REV(svr, 1, 0) || IS_SVR_REV(svr, 1, 1); @@ -164,7 +196,25 @@ static inline bool has_erratum_a007792(void) return false; } +static inline bool has_erratum_a005697(void) +{ + u32 svr = get_svr(); + u32 soc = SVR_SOC_VER(svr); + + switch (soc) { + case SVR_9131: + case SVR_9132: + return IS_SVR_REV(svr, 1, 0) || IS_SVR_REV(svr, 1, 1); + } + return false; +} + #else +static inline bool has_dual_phy(void) +{ + return false; +} + static inline bool has_erratum_a006261(void) { return false; @@ -184,5 +234,10 @@ static inline bool has_erratum_a007792(void) { return false; } + +static inline bool has_erratum_a005697(void) +{ + return false; +} #endif #endif /*_ASM_FSL_USB_H_ */ diff --git a/include/linux/immap_qe.h b/include/linux/immap_qe.h index b317dcb..6d1f88e 100644 --- a/include/linux/immap_qe.h +++ b/include/linux/immap_qe.h @@ -24,6 +24,18 @@ #endif #endif +#ifdef CONFIG_LS102XA +#define QE_MURAM_SIZE 0x6000UL +#define MAX_QE_RISC 1 +#define QE_NUM_OF_SNUM 28 +#endif + +#ifdef CONFIG_PPC +#define QE_IMMR_OFFSET 0x00140000 +#else +#define QE_IMMR_OFFSET 0x01400000 +#endif + /* QE I-RAM */ typedef struct qe_iram { u32 iadd; /* I-RAM Address Register */ |