diff options
170 files changed, 7505 insertions, 2845 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 6c7f3ae2a5..7cc3b06c44 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -245,14 +245,50 @@ N: uniphier ARM ZYNQ M: Michal Simek <monstr@monstr.eu> S: Maintained -F: arch/arm/cpu/armv7/zynq/ -F: arch/arm/include/asm/arch-zynq/ +T: git git://git.denx.de/u-boot-microblaze.git +F: arch/arm/mach-zynq/ +F: drivers/clk/clk_zynq.c +F: drivers/fpga/zynqpl.c +F: drivers/gpio/zynq_gpio.c +F: drivers/i2c/i2c-cdns.c +F: drivers/i2c/muxes/pca954x.c +F: drivers/i2c/zynq_i2c.c +F: drivers/mmc/zynq_sdhci.c +F: drivers/mtd/nand/zynq_nand.c +F: drivers/net/phy/xilinx_phy.c +F: drivers/net/zynq_gem.c +F: drivers/serial/serial_zynq.c +F: drivers/spi/zynq_qspi.c +F: drivers/spi/zynq_spi.c +F: drivers/usb/host/ehci-zynq.c +F: drivers/watchdog/cdns_wdt.c +F: include/zynqmp.h +F: tools/zynqimage.c +N: zynq ARM ZYNQMP M: Michal Simek <michal.simek@xilinx.com> S: Maintained -F: arch/arm/cpu/armv8/zynqmp/ -F: arch/arm/include/asm/arch-zynqmp/ +T: git git://git.denx.de/u-boot-microblaze.git +F: arch/arm/mach-zynq/ +F: drivers/clk/clk_zynq.c +F: drivers/fpga/zynqpl.c +F: drivers/gpio/zynq_gpio.c +F: drivers/i2c/i2c-cdns.c +F: drivers/i2c/muxes/pca954x.c +F: drivers/i2c/zynq_i2c.c +F: drivers/mmc/zynq_sdhci.c +F: drivers/mtd/nand/zynq_nand.c +F: drivers/net/phy/xilinx_phy.c +F: drivers/net/zynq_gem.c +F: drivers/serial/serial_zynq.c +F: drivers/spi/zynq_qspi.c +F: drivers/spi/zynq_spi.c +F: drivers/usb/host/ehci-zynq.c +F: drivers/watchdog/cdns_wdt.c +F: include/zynqmp.h +F: tools/zynqimage.c +N: zynqmp BUILDMAN M: Simon Glass <sjg@chromium.org> @@ -343,6 +379,14 @@ M: Michal Simek <monstr@monstr.eu> S: Maintained T: git git://git.denx.de/u-boot-microblaze.git F: arch/microblaze/ +F: cmd/mfsl.c +F: drivers/gpio/xilinx_gpio.c +F: drivers/net/xilinx_axi_emac.c +F: drivers/net/xilinx_emaclite.c +F: drivers/serial/serial_xuartlite.c +F: drivers/spi/xilinx_spi.c +F: drivers/watchdog/xilinx_tb_wdt.c +N: xilinx MIPS M: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index e3f9db7b29..aee15d5353 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -116,6 +116,24 @@ config SYS_DCACHE_OFF bool "Do not use Data Cache" default n +menuconfig ARC_DBG + bool "ARC debugging" + default n + +if ARC_DBG + +config ARC_DBG_IOC_ENABLE + bool "Enable IO coherency unit" + depends on CPU_ARCHS38 + default n + help + Enable IO coherency unit to debug problems with caches and + DMA peripherals. + NOTE: as of today linux will not work properly if this option + is enabled in u-boot! + +endif + choice prompt "Target select" default TARGET_AXS103 diff --git a/arch/arc/config.mk b/arch/arc/config.mk index 3ed0c282ba..d040454d1a 100644 --- a/arch/arc/config.mk +++ b/arch/arc/config.mk @@ -51,9 +51,10 @@ PLATFORM_CPPFLAGS += -mcpu=archs endif PLATFORM_CPPFLAGS += -ffixed-r25 -D__ARC__ -gdwarf-2 -mno-sdata +PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections # Needed for relocation -LDFLAGS_FINAL += -pie +LDFLAGS_FINAL += -pie --gc-sections # Load address for standalone apps CONFIG_STANDALONE_LOAD_ADDR ?= 0x82000000 diff --git a/arch/arc/include/asm/arc-bcr.h b/arch/arc/include/asm/arc-bcr.h new file mode 100644 index 0000000000..823906d946 --- /dev/null +++ b/arch/arc/include/asm/arc-bcr.h @@ -0,0 +1,77 @@ +/* + * ARC Build Configuration Registers, with encoded hardware config + * + * Copyright (C) 2018 Synopsys + * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __ARC_BCR_H +#define __ARC_BCR_H +#ifndef __ASSEMBLY__ + +#include <config.h> + +union bcr_di_cache { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:12, line_len:4, sz:4, config:4, ver:8; +#else + unsigned int ver:8, config:4, sz:4, line_len:4, pad:12; +#endif + } fields; + unsigned int word; +}; + +union bcr_slc_cfg { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:24, way:2, lsz:2, sz:4; +#else + unsigned int sz:4, lsz:2, way:2, pad:24; +#endif + } fields; + unsigned int word; +}; + +union bcr_generic { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:24, ver:8; +#else + unsigned int ver:8, pad:24; +#endif + } fields; + unsigned int word; +}; + +union bcr_clust_cfg { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:7, c:1, num_entries:8, num_cores:8, ver:8; +#else + unsigned int ver:8, num_cores:8, num_entries:8, c:1, pad:7; +#endif + } fields; + unsigned int word; +}; + +union bcr_mmu_4 { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int ver:8, sasid:1, sz1:4, sz0:4, res:2, pae:1, + n_ways:2, n_entry:2, n_super:2, u_itlb:3, u_dtlb:3; +#else + /* DTLB ITLB JES JE JA */ + unsigned int u_dtlb:3, u_itlb:3, n_super:2, n_entry:2, n_ways:2, + pae:1, res:2, sz0:4, sz1:4, sasid:1, ver:8; +#endif + } fields; + unsigned int word; +}; + +#endif /* __ASSEMBLY__ */ +#endif /* __ARC_BCR_H */ diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index 67f416305d..3a513149f5 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -8,6 +8,7 @@ #define _ASM_ARC_ARCREGS_H #include <asm/cache.h> +#include <config.h> /* * ARC architecture has additional address space - auxiliary registers. @@ -88,6 +89,16 @@ /* ARCNUM [15:8] - field to identify each core in a multi-core system */ #define CPU_ID_GET() ((read_aux_reg(ARC_AUX_IDENTITY) & 0xFF00) >> 8) + +static const inline int is_isa_arcv2(void) +{ + return IS_ENABLED(CONFIG_ISA_ARCV2); +} + +static const inline int is_isa_arcompact(void) +{ + return IS_ENABLED(CONFIG_ISA_ARCOMPACT); +} #endif /* __ASSEMBLY__ */ #endif /* _ASM_ARC_ARCREGS_H */ diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index d26d9fb18d..2269183615 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -30,6 +30,13 @@ #ifndef __ASSEMBLY__ void cache_init(void); +void flush_n_invalidate_dcache_all(void); +void sync_n_cleanup_cache_all(void); + +static const inline int is_ioc_enabled(void) +{ + return IS_ENABLED(CONFIG_ARC_DBG_IOC_ENABLE); +} #endif /* __ASSEMBLY__ */ diff --git a/arch/arc/include/asm/global_data.h b/arch/arc/include/asm/global_data.h index f0242f1ad6..43e1343095 100644 --- a/arch/arc/include/asm/global_data.h +++ b/arch/arc/include/asm/global_data.h @@ -7,9 +7,15 @@ #ifndef __ASM_ARC_GLOBAL_DATA_H #define __ASM_ARC_GLOBAL_DATA_H +#include <config.h> + #ifndef __ASSEMBLY__ /* Architecture-specific global data */ struct arch_global_data { + int l1_line_sz; +#if defined(CONFIG_ISA_ARCV2) + int slc_line_sz; +#endif }; #endif /* __ASSEMBLY__ */ diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h index a12303bc73..060cdf637b 100644 --- a/arch/arc/include/asm/io.h +++ b/arch/arc/include/asm/io.h @@ -10,7 +10,7 @@ #include <linux/types.h> #include <asm/byteorder.h> -#ifdef CONFIG_ISA_ARCV2 +#ifdef __ARCHS__ /* * ARCv2 based HS38 cores are in-order issue, but still weakly ordered @@ -42,12 +42,12 @@ #define mb() asm volatile("sync\n" : : : "memory") #endif -#ifdef CONFIG_ISA_ARCV2 +#ifdef __ARCHS__ #define __iormb() rmb() #define __iowmb() wmb() #else -#define __iormb() do { } while (0) -#define __iowmb() do { } while (0) +#define __iormb() asm volatile("" : : : "memory") +#define __iowmb() asm volatile("" : : : "memory") #endif static inline void sync(void) diff --git a/arch/arc/include/asm/string.h b/arch/arc/include/asm/string.h index 909129c333..8b13789179 100644 --- a/arch/arc/include/asm/string.h +++ b/arch/arc/include/asm/string.h @@ -1,27 +1 @@ -/* - * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#ifndef __ASM_ARC_STRING_H -#define __ASM_ARC_STRING_H - -#define __HAVE_ARCH_MEMSET -#define __HAVE_ARCH_MEMCPY -#define __HAVE_ARCH_MEMCMP -#define __HAVE_ARCH_STRCHR -#define __HAVE_ARCH_STRCPY -#define __HAVE_ARCH_STRCMP -#define __HAVE_ARCH_STRLEN - -extern void *memset(void *ptr, int, __kernel_size_t); -extern void *memcpy(void *, const void *, __kernel_size_t); -extern void memzero(void *ptr, __kernel_size_t n); -extern int memcmp(const void *, const void *, __kernel_size_t); -extern char *strchr(const char *s, int c); -extern char *strcpy(char *dest, const char *src); -extern int strcmp(const char *cs, const char *ct); -extern __kernel_size_t strlen(const char *); - -#endif /* __ASM_ARC_STRING_H */ diff --git a/arch/arc/lib/Makefile b/arch/arc/lib/Makefile index 12097bf3be..6b7fb0fdff 100644 --- a/arch/arc/lib/Makefile +++ b/arch/arc/lib/Makefile @@ -10,13 +10,6 @@ obj-y += cache.o obj-y += cpu.o obj-y += interrupts.o obj-y += relocate.o -obj-y += strchr-700.o -obj-y += strcmp.o -obj-y += strcpy-700.o -obj-y += strlen.o -obj-y += memcmp.o -obj-y += memcpy-700.o -obj-y += memset.o obj-y += reset.o obj-y += ints_low.o obj-y += init_helpers.o diff --git a/arch/arc/lib/bootm.c b/arch/arc/lib/bootm.c index 4d4acff239..4f04aad34a 100644 --- a/arch/arc/lib/bootm.c +++ b/arch/arc/lib/bootm.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: GPL-2.0+ */ +#include <asm/cache.h> #include <common.h> DECLARE_GLOBAL_DATA_PTR; @@ -40,41 +41,52 @@ void arch_lmb_reserve(struct lmb *lmb) static int cleanup_before_linux(void) { disable_interrupts(); - flush_dcache_all(); - invalidate_icache_all(); + sync_n_cleanup_cache_all(); return 0; } +__weak int board_prep_linux(bootm_headers_t *images) { return 0; } + /* Subcommand: PREP */ -static void boot_prep_linux(bootm_headers_t *images) +static int boot_prep_linux(bootm_headers_t *images) { - if (image_setup_linux(images)) - hang(); + int ret; + + ret = image_setup_linux(images); + if (ret) + return ret; + + return board_prep_linux(images); } -__weak void smp_set_core_boot_addr(unsigned long addr, int corenr) {} -__weak void smp_kick_all_cpus(void) {} +/* Generic implementation for single core CPU */ +__weak void board_jump_and_run(ulong entry, int zero, int arch, uint params) +{ + void (*kernel_entry)(int zero, int arch, uint params); + + kernel_entry = (void (*)(int, int, uint))entry; + + kernel_entry(zero, arch, params); +} /* Subcommand: GO */ static void boot_jump_linux(bootm_headers_t *images, int flag) { - void (*kernel_entry)(int zero, int arch, uint params); + ulong kernel_entry; unsigned int r0, r2; int fake = (flag & BOOTM_STATE_OS_FAKE_GO); - kernel_entry = (void (*)(int, int, uint))images->ep; + kernel_entry = images->ep; debug("## Transferring control to Linux (at address %08lx)...\n", - (ulong) kernel_entry); + kernel_entry); bootstage_mark(BOOTSTAGE_ID_RUN_OS); printf("\nStarting kernel ...%s\n\n", fake ? "(fake run for tracing)" : ""); bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel"); - cleanup_before_linux(); - if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) { r0 = 2; r2 = (unsigned int)images->ft_addr; @@ -83,11 +95,10 @@ static void boot_jump_linux(bootm_headers_t *images, int flag) r2 = (unsigned int)env_get("bootargs"); } - if (!fake) { - smp_set_core_boot_addr((unsigned long)kernel_entry, -1); - smp_kick_all_cpus(); - kernel_entry(r0, 0, r2); - } + cleanup_before_linux(); + + if (!fake) + board_jump_and_run(kernel_entry, r0, 0, r2); } int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) @@ -96,17 +107,13 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) if ((flag & BOOTM_STATE_OS_BD_T) || (flag & BOOTM_STATE_OS_CMDLINE)) return -1; - if (flag & BOOTM_STATE_OS_PREP) { - boot_prep_linux(images); - return 0; - } + if (flag & BOOTM_STATE_OS_PREP) + return boot_prep_linux(images); if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) { boot_jump_linux(images, flag); return 0; } - boot_prep_linux(images); - boot_jump_linux(images, flag); - return 0; + return -1; } diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index 04f1d9d59b..8203fae145 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -10,8 +10,145 @@ #include <linux/kernel.h> #include <linux/log2.h> #include <asm/arcregs.h> +#include <asm/arc-bcr.h> #include <asm/cache.h> +/* + * [ NOTE 1 ]: + * Data cache (L1 D$ or SL$) entire invalidate operation or data cache disable + * operation may result in unexpected behavior and data loss even if we flush + * data cache right before invalidation. That may happens if we store any context + * on stack (like we store BLINK register on stack before function call). + * BLINK register is the register where return address is automatically saved + * when we do function call with instructions like 'bl'. + * + * There is the real example: + * We may hang in the next code as we store any BLINK register on stack in + * invalidate_dcache_all() function. + * + * void flush_dcache_all() { + * __dc_entire_op(OP_FLUSH); + * // Other code // + * } + * + * void invalidate_dcache_all() { + * __dc_entire_op(OP_INV); + * // Other code // + * } + * + * void foo(void) { + * flush_dcache_all(); + * invalidate_dcache_all(); + * } + * + * Now let's see what really happens during that code execution: + * + * foo() + * |->> call flush_dcache_all + * [return address is saved to BLINK register] + * [push BLINK] (save to stack) ![point 1] + * |->> call __dc_entire_op(OP_FLUSH) + * [return address is saved to BLINK register] + * [flush L1 D$] + * return [jump to BLINK] + * <<------ + * [other flush_dcache_all code] + * [pop BLINK] (get from stack) + * return [jump to BLINK] + * <<------ + * |->> call invalidate_dcache_all + * [return address is saved to BLINK register] + * [push BLINK] (save to stack) ![point 2] + * |->> call __dc_entire_op(OP_FLUSH) + * [return address is saved to BLINK register] + * [invalidate L1 D$] ![point 3] + * // Oops!!! + * // We lose return address from invalidate_dcache_all function: + * // we save it to stack and invalidate L1 D$ after that! + * return [jump to BLINK] + * <<------ + * [other invalidate_dcache_all code] + * [pop BLINK] (get from stack) + * // we don't have this data in L1 dcache as we invalidated it in [point 3] + * // so we get it from next memory level (for example DDR memory) + * // but in the memory we have value which we save in [point 1], which + * // is return address from flush_dcache_all function (instead of + * // address from current invalidate_dcache_all function which we + * // saved in [point 2] !) + * return [jump to BLINK] + * <<------ + * // As BLINK points to invalidate_dcache_all, we call it again and + * // loop forever. + * + * Fortunately we may fix that by using flush & invalidation of D$ with a single + * one instruction (instead of flush and invalidation instructions pair) and + * enabling force function inline with '__attribute__((always_inline))' gcc + * attribute to avoid any function call (and BLINK store) between cache flush + * and disable. + * + * + * [ NOTE 2 ]: + * As of today we only support the following cache configurations on ARC. + * Other configurations may exist in HW (for example, since version 3.0 HS + * supports SL$ (L2 system level cache) disable) but we don't support it in SW. + * Configuration 1: + * ______________________ + * | | + * | ARC CPU | + * |______________________| + * ___|___ ___|___ + * | | | | + * | L1 I$ | | L1 D$ | + * |_______| |_______| + * on/off on/off + * ___|______________|____ + * | | + * | main memory | + * |______________________| + * + * Configuration 2: + * ______________________ + * | | + * | ARC CPU | + * |______________________| + * ___|___ ___|___ + * | | | | + * | L1 I$ | | L1 D$ | + * |_______| |_______| + * on/off on/off + * ___|______________|____ + * | | + * | L2 (SL$) | + * |______________________| + * always must be on + * ___|______________|____ + * | | + * | main memory | + * |______________________| + * + * Configuration 3: + * ______________________ + * | | + * | ARC CPU | + * |______________________| + * ___|___ ___|___ + * | | | | + * | L1 I$ | | L1 D$ | + * |_______| |_______| + * on/off must be on + * ___|______________|____ _______ + * | | | | + * | L2 (SL$) |-----| IOC | + * |______________________| |_______| + * always must be on on/off + * ___|______________|____ + * | | + * | main memory | + * |______________________| + */ + +DECLARE_GLOBAL_DATA_PTR; + /* Bit values in IC_CTRL */ #define IC_CTRL_CACHE_DISABLE BIT(0) @@ -19,11 +156,10 @@ #define DC_CTRL_CACHE_DISABLE BIT(0) #define DC_CTRL_INV_MODE_FLUSH BIT(6) #define DC_CTRL_FLUSH_STATUS BIT(8) -#define CACHE_VER_NUM_MASK 0xF -#define OP_INV 0x1 -#define OP_FLUSH 0x2 -#define OP_INV_IC 0x3 +#define OP_INV BIT(0) +#define OP_FLUSH BIT(1) +#define OP_FLUSH_N_INV (OP_FLUSH | OP_INV) /* Bit val in SLC_CONTROL */ #define SLC_CTRL_DIS 0x001 @@ -31,55 +167,117 @@ #define SLC_CTRL_BUSY 0x100 #define SLC_CTRL_RGN_OP_INV 0x200 +#define CACHE_LINE_MASK (~(gd->arch.l1_line_sz - 1)) + /* - * By default that variable will fall into .bss section. - * But .bss section is not relocated and so it will be initilized before - * relocation but will be used after being zeroed. + * We don't want to use '__always_inline' macro here as it can be redefined + * to simple 'inline' in some cases which breaks stuff. See [ NOTE 1 ] for more + * details about the reasons we need to use always_inline functions. */ -int l1_line_sz __section(".data"); -bool dcache_exists __section(".data") = false; -bool icache_exists __section(".data") = false; - -#define CACHE_LINE_MASK (~(l1_line_sz - 1)) - -#ifdef CONFIG_ISA_ARCV2 -int slc_line_sz __section(".data"); -bool slc_exists __section(".data") = false; -bool ioc_exists __section(".data") = false; -bool pae_exists __section(".data") = false; +#define inlined_cachefunc inline __attribute__((always_inline)) -/* To force enable IOC set ioc_enable to 'true' */ -bool ioc_enable __section(".data") = false; +static inlined_cachefunc void __ic_entire_invalidate(void); +static inlined_cachefunc void __dc_entire_op(const int cacheop); -void read_decode_mmu_bcr(void) +static inline bool pae_exists(void) { /* TODO: should we compare mmu version from BCR and from CONFIG? */ #if (CONFIG_ARC_MMU_VER >= 4) - u32 tmp; + union bcr_mmu_4 mmu4; - tmp = read_aux_reg(ARC_AUX_MMU_BCR); + mmu4.word = read_aux_reg(ARC_AUX_MMU_BCR); - struct bcr_mmu_4 { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int ver:8, sasid:1, sz1:4, sz0:4, res:2, pae:1, - n_ways:2, n_entry:2, n_super:2, u_itlb:3, u_dtlb:3; -#else - /* DTLB ITLB JES JE JA */ - unsigned int u_dtlb:3, u_itlb:3, n_super:2, n_entry:2, n_ways:2, - pae:1, res:2, sz0:4, sz1:4, sasid:1, ver:8; -#endif /* CONFIG_CPU_BIG_ENDIAN */ - } *mmu4; + if (mmu4.fields.pae) + return true; +#endif /* (CONFIG_ARC_MMU_VER >= 4) */ - mmu4 = (struct bcr_mmu_4 *)&tmp; + return false; +} - pae_exists = !!mmu4->pae; -#endif /* (CONFIG_ARC_MMU_VER >= 4) */ +static inlined_cachefunc bool icache_exists(void) +{ + union bcr_di_cache ibcr; + + ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD); + return !!ibcr.fields.ver; } -static void __slc_entire_op(const int op) +static inlined_cachefunc bool icache_enabled(void) +{ + if (!icache_exists()) + return false; + + return !(read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE); +} + +static inlined_cachefunc bool dcache_exists(void) +{ + union bcr_di_cache dbcr; + + dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD); + return !!dbcr.fields.ver; +} + +static inlined_cachefunc bool dcache_enabled(void) +{ + if (!dcache_exists()) + return false; + + return !(read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE); +} + +static inlined_cachefunc bool slc_exists(void) +{ + if (is_isa_arcv2()) { + union bcr_generic sbcr; + + sbcr.word = read_aux_reg(ARC_BCR_SLC); + return !!sbcr.fields.ver; + } + + return false; +} + +static inlined_cachefunc bool slc_data_bypass(void) +{ + /* + * If L1 data cache is disabled SL$ is bypassed and all load/store + * requests are sent directly to main memory. + */ + return !dcache_enabled(); +} + +static inline bool ioc_exists(void) +{ + if (is_isa_arcv2()) { + union bcr_clust_cfg cbcr; + + cbcr.word = read_aux_reg(ARC_BCR_CLUSTER); + return cbcr.fields.c; + } + + return false; +} + +static inline bool ioc_enabled(void) +{ + /* + * We check only CONFIG option instead of IOC HW state check as IOC + * must be disabled by default. + */ + if (is_ioc_enabled()) + return ioc_exists(); + + return false; +} + +static inlined_cachefunc void __slc_entire_op(const int op) { unsigned int ctrl; + if (!slc_exists()) + return; + ctrl = read_aux_reg(ARC_AUX_SLC_CTRL); if (!(op & OP_FLUSH)) /* i.e. OP_INV */ @@ -104,6 +302,14 @@ static void __slc_entire_op(const int op) static void slc_upper_region_init(void) { /* + * ARC_AUX_SLC_RGN_START1 and ARC_AUX_SLC_RGN_END1 register exist + * only if PAE exists in current HW. So we had to check pae_exist + * before using them. + */ + if (!pae_exists()) + return; + + /* * ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1 are always == 0 * as we don't use PAE40. */ @@ -113,9 +319,14 @@ static void slc_upper_region_init(void) static void __slc_rgn_op(unsigned long paddr, unsigned long sz, const int op) { +#ifdef CONFIG_ISA_ARCV2 + unsigned int ctrl; unsigned long end; + if (!slc_exists()) + return; + /* * The Region Flush operation is specified by CTRL.RGN_OP[11..9] * - b'000 (default) is Flush, @@ -142,7 +353,7 @@ static void __slc_rgn_op(unsigned long paddr, unsigned long sz, const int op) * END needs to be setup before START (latter triggers the operation) * END can't be same as START, so add (l2_line_sz - 1) to sz */ - end = paddr + sz + slc_line_sz - 1; + end = paddr + sz + gd->arch.slc_line_sz - 1; /* * Upper addresses (ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1) @@ -156,85 +367,82 @@ static void __slc_rgn_op(unsigned long paddr, unsigned long sz, const int op) read_aux_reg(ARC_AUX_SLC_CTRL); while (read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_BUSY); -} + #endif /* CONFIG_ISA_ARCV2 */ +} + +static void arc_ioc_setup(void) +{ + /* IOC Aperture start is equal to DDR start */ + unsigned int ap_base = CONFIG_SYS_SDRAM_BASE; + /* IOC Aperture size is equal to DDR size */ + long ap_size = CONFIG_SYS_SDRAM_SIZE; + + /* Unsupported configuration. See [ NOTE 2 ] for more details. */ + if (!slc_exists()) + panic("Try to enable IOC but SLC is not present"); + + /* Unsupported configuration. See [ NOTE 2 ] for more details. */ + if (!dcache_enabled()) + panic("Try to enable IOC but L1 D$ is disabled"); + + if (!is_power_of_2(ap_size) || ap_size < 4096) + panic("IOC Aperture size must be power of 2 and bigger 4Kib"); + + /* IOC Aperture start must be aligned to the size of the aperture */ + if (ap_base % ap_size != 0) + panic("IOC Aperture start must be aligned to the size of the aperture"); + + flush_n_invalidate_dcache_all(); + + /* + * IOC Aperture size decoded as 2 ^ (SIZE + 2) KB, + * so setting 0x11 implies 512M, 0x12 implies 1G... + */ + write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE, + order_base_2(ap_size / 1024) - 2); + + write_aux_reg(ARC_AUX_IO_COH_AP0_BASE, ap_base >> 12); + write_aux_reg(ARC_AUX_IO_COH_PARTIAL, 1); + write_aux_reg(ARC_AUX_IO_COH_ENABLE, 1); +} -#ifdef CONFIG_ISA_ARCV2 static void read_decode_cache_bcr_arcv2(void) { - union { - struct { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:24, way:2, lsz:2, sz:4; -#else - unsigned int sz:4, lsz:2, way:2, pad:24; -#endif - } fields; - unsigned int word; - } slc_cfg; - - union { - struct { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:24, ver:8; -#else - unsigned int ver:8, pad:24; -#endif - } fields; - unsigned int word; - } sbcr; +#ifdef CONFIG_ISA_ARCV2 - sbcr.word = read_aux_reg(ARC_BCR_SLC); - if (sbcr.fields.ver) { + union bcr_slc_cfg slc_cfg; + + if (slc_exists()) { slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG); - slc_exists = true; - slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64; - } + gd->arch.slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64; - union { - struct bcr_clust_cfg { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:7, c:1, num_entries:8, num_cores:8, ver:8; -#else - unsigned int ver:8, num_cores:8, num_entries:8, c:1, pad:7; -#endif - } fields; - unsigned int word; - } cbcr; + /* + * We don't support configuration where L1 I$ or L1 D$ is + * absent but SL$ exists. See [ NOTE 2 ] for more details. + */ + if (!icache_exists() || !dcache_exists()) + panic("Unsupported cache configuration: SLC exists but one of L1 caches is absent"); + } - cbcr.word = read_aux_reg(ARC_BCR_CLUSTER); - if (cbcr.fields.c && ioc_enable) - ioc_exists = true; +#endif /* CONFIG_ISA_ARCV2 */ } -#endif void read_decode_cache_bcr(void) { int dc_line_sz = 0, ic_line_sz = 0; - - union { - struct { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:12, line_len:4, sz:4, config:4, ver:8; -#else - unsigned int ver:8, config:4, sz:4, line_len:4, pad:12; -#endif - } fields; - unsigned int word; - } ibcr, dbcr; + union bcr_di_cache ibcr, dbcr; ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD); if (ibcr.fields.ver) { - icache_exists = true; - l1_line_sz = ic_line_sz = 8 << ibcr.fields.line_len; + gd->arch.l1_line_sz = ic_line_sz = 8 << ibcr.fields.line_len; if (!ic_line_sz) panic("Instruction exists but line length is 0\n"); } dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD); if (dbcr.fields.ver) { - dcache_exists = true; - l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len; + gd->arch.l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len; if (!dc_line_sz) panic("Data cache exists but line length is 0\n"); } @@ -247,109 +455,79 @@ void cache_init(void) { read_decode_cache_bcr(); -#ifdef CONFIG_ISA_ARCV2 - read_decode_cache_bcr_arcv2(); - - if (ioc_exists) { - /* IOC Aperture start is equal to DDR start */ - unsigned int ap_base = CONFIG_SYS_SDRAM_BASE; - /* IOC Aperture size is equal to DDR size */ - long ap_size = CONFIG_SYS_SDRAM_SIZE; - - flush_dcache_all(); - invalidate_dcache_all(); + if (is_isa_arcv2()) + read_decode_cache_bcr_arcv2(); - if (!is_power_of_2(ap_size) || ap_size < 4096) - panic("IOC Aperture size must be power of 2 and bigger 4Kib"); - - /* - * IOC Aperture size decoded as 2 ^ (SIZE + 2) KB, - * so setting 0x11 implies 512M, 0x12 implies 1G... - */ - write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE, - order_base_2(ap_size / 1024) - 2); - - /* IOC Aperture start must be aligned to the size of the aperture */ - if (ap_base % ap_size != 0) - panic("IOC Aperture start must be aligned to the size of the aperture"); - - write_aux_reg(ARC_AUX_IO_COH_AP0_BASE, ap_base >> 12); - write_aux_reg(ARC_AUX_IO_COH_PARTIAL, 1); - write_aux_reg(ARC_AUX_IO_COH_ENABLE, 1); - } + if (is_isa_arcv2() && ioc_enabled()) + arc_ioc_setup(); - read_decode_mmu_bcr(); - - /* - * ARC_AUX_SLC_RGN_START1 and ARC_AUX_SLC_RGN_END1 register exist - * only if PAE exists in current HW. So we had to check pae_exist - * before using them. - */ - if (slc_exists && pae_exists) + if (is_isa_arcv2() && slc_exists()) slc_upper_region_init(); -#endif /* CONFIG_ISA_ARCV2 */ } int icache_status(void) { - if (!icache_exists) - return 0; - - if (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) - return 0; - else - return 1; + return icache_enabled(); } void icache_enable(void) { - if (icache_exists) + if (icache_exists()) write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) & ~IC_CTRL_CACHE_DISABLE); } void icache_disable(void) { - if (icache_exists) - write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) | - IC_CTRL_CACHE_DISABLE); + if (!icache_exists()) + return; + + __ic_entire_invalidate(); + + write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) | + IC_CTRL_CACHE_DISABLE); } -void invalidate_icache_all(void) +/* IC supports only invalidation */ +static inlined_cachefunc void __ic_entire_invalidate(void) { + if (!icache_enabled()) + return; + /* Any write to IC_IVIC register triggers invalidation of entire I$ */ - if (icache_status()) { - write_aux_reg(ARC_AUX_IC_IVIC, 1); - /* - * As per ARC HS databook (see chapter 5.3.3.2) - * it is required to add 3 NOPs after each write to IC_IVIC. - */ - __builtin_arc_nop(); - __builtin_arc_nop(); - __builtin_arc_nop(); - read_aux_reg(ARC_AUX_IC_CTRL); /* blocks */ - } + write_aux_reg(ARC_AUX_IC_IVIC, 1); + /* + * As per ARC HS databook (see chapter 5.3.3.2) + * it is required to add 3 NOPs after each write to IC_IVIC. + */ + __builtin_arc_nop(); + __builtin_arc_nop(); + __builtin_arc_nop(); + read_aux_reg(ARC_AUX_IC_CTRL); /* blocks */ +} -#ifdef CONFIG_ISA_ARCV2 - if (slc_exists) +void invalidate_icache_all(void) +{ + __ic_entire_invalidate(); + + /* + * If SL$ is bypassed for data it is used only for instructions, + * so we need to invalidate it too. + * TODO: HS 3.0 supports SLC disable so we need to check slc + * enable/disable status here. + */ + if (is_isa_arcv2() && slc_data_bypass()) __slc_entire_op(OP_INV); -#endif } int dcache_status(void) { - if (!dcache_exists) - return 0; - - if (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) - return 0; - else - return 1; + return dcache_enabled(); } void dcache_enable(void) { - if (!dcache_exists) + if (!dcache_exists()) return; write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) & @@ -358,83 +536,77 @@ void dcache_enable(void) void dcache_disable(void) { - if (!dcache_exists) + if (!dcache_exists()) return; + __dc_entire_op(OP_FLUSH_N_INV); + + /* + * As SLC will be bypassed for data after L1 D$ disable we need to + * flush it first before L1 D$ disable. Also we invalidate SLC to + * avoid any inconsistent data problems after enabling L1 D$ again with + * dcache_enable function. + */ + if (is_isa_arcv2()) + __slc_entire_op(OP_FLUSH_N_INV); + write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) | DC_CTRL_CACHE_DISABLE); } -#ifndef CONFIG_SYS_DCACHE_OFF -/* - * Common Helper for Line Operations on {I,D}-Cache - */ -static inline void __cache_line_loop(unsigned long paddr, unsigned long sz, - const int cacheop) +/* Common Helper for Line Operations on D-cache */ +static inline void __dcache_line_loop(unsigned long paddr, unsigned long sz, + const int cacheop) { unsigned int aux_cmd; -#if (CONFIG_ARC_MMU_VER == 3) - unsigned int aux_tag; -#endif int num_lines; - if (cacheop == OP_INV_IC) { - aux_cmd = ARC_AUX_IC_IVIL; -#if (CONFIG_ARC_MMU_VER == 3) - aux_tag = ARC_AUX_IC_PTAG; -#endif - } else { - /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ - aux_cmd = cacheop & OP_INV ? ARC_AUX_DC_IVDL : ARC_AUX_DC_FLDL; -#if (CONFIG_ARC_MMU_VER == 3) - aux_tag = ARC_AUX_DC_PTAG; -#endif - } + /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ + aux_cmd = cacheop & OP_INV ? ARC_AUX_DC_IVDL : ARC_AUX_DC_FLDL; sz += paddr & ~CACHE_LINE_MASK; paddr &= CACHE_LINE_MASK; - num_lines = DIV_ROUND_UP(sz, l1_line_sz); + num_lines = DIV_ROUND_UP(sz, gd->arch.l1_line_sz); while (num_lines-- > 0) { #if (CONFIG_ARC_MMU_VER == 3) - write_aux_reg(aux_tag, paddr); + write_aux_reg(ARC_AUX_DC_PTAG, paddr); #endif write_aux_reg(aux_cmd, paddr); - paddr += l1_line_sz; + paddr += gd->arch.l1_line_sz; } } -static unsigned int __before_dc_op(const int op) +static inlined_cachefunc void __before_dc_op(const int op) { - unsigned int reg; + unsigned int ctrl; - if (op == OP_INV) { - /* - * IM is set by default and implies Flush-n-inv - * Clear it here for vanilla inv - */ - reg = read_aux_reg(ARC_AUX_DC_CTRL); - write_aux_reg(ARC_AUX_DC_CTRL, reg & ~DC_CTRL_INV_MODE_FLUSH); - } + ctrl = read_aux_reg(ARC_AUX_DC_CTRL); - return reg; + /* IM bit implies flush-n-inv, instead of vanilla inv */ + if (op == OP_INV) + ctrl &= ~DC_CTRL_INV_MODE_FLUSH; + else + ctrl |= DC_CTRL_INV_MODE_FLUSH; + + write_aux_reg(ARC_AUX_DC_CTRL, ctrl); } -static void __after_dc_op(const int op, unsigned int reg) +static inlined_cachefunc void __after_dc_op(const int op) { if (op & OP_FLUSH) /* flush / flush-n-inv both wait */ while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS); - - /* Switch back to default Invalidate mode */ - if (op == OP_INV) - write_aux_reg(ARC_AUX_DC_CTRL, reg | DC_CTRL_INV_MODE_FLUSH); } -static inline void __dc_entire_op(const int cacheop) +static inlined_cachefunc void __dc_entire_op(const int cacheop) { int aux; - unsigned int ctrl_reg = __before_dc_op(cacheop); + + if (!dcache_enabled()) + return; + + __before_dc_op(cacheop); if (cacheop & OP_INV) /* Inv or flush-n-inv use same cmd reg */ aux = ARC_AUX_DC_IVDC; @@ -443,36 +615,36 @@ static inline void __dc_entire_op(const int cacheop) write_aux_reg(aux, 0x1); - __after_dc_op(cacheop, ctrl_reg); + __after_dc_op(cacheop); } static inline void __dc_line_op(unsigned long paddr, unsigned long sz, const int cacheop) { - unsigned int ctrl_reg = __before_dc_op(cacheop); + if (!dcache_enabled()) + return; - __cache_line_loop(paddr, sz, cacheop); - __after_dc_op(cacheop, ctrl_reg); + __before_dc_op(cacheop); + __dcache_line_loop(paddr, sz, cacheop); + __after_dc_op(cacheop); } -#else -#define __dc_entire_op(cacheop) -#define __dc_line_op(paddr, sz, cacheop) -#endif /* !CONFIG_SYS_DCACHE_OFF */ void invalidate_dcache_range(unsigned long start, unsigned long end) { if (start >= end) return; -#ifdef CONFIG_ISA_ARCV2 - if (!ioc_exists) -#endif + /* + * ARCv1 -> call __dc_line_op + * ARCv2 && L1 D$ disabled -> nothing + * ARCv2 && L1 D$ enabled && IOC enabled -> nothing + * ARCv2 && L1 D$ enabled && no IOC -> call __dc_line_op; call __slc_rgn_op + */ + if (!is_isa_arcv2() || !ioc_enabled()) __dc_line_op(start, end - start, OP_INV); -#ifdef CONFIG_ISA_ARCV2 - if (slc_exists && !ioc_exists) + if (is_isa_arcv2() && !ioc_enabled() && !slc_data_bypass()) __slc_rgn_op(start, end - start, OP_INV); -#endif } void flush_dcache_range(unsigned long start, unsigned long end) @@ -480,15 +652,17 @@ void flush_dcache_range(unsigned long start, unsigned long end) if (start >= end) return; -#ifdef CONFIG_ISA_ARCV2 - if (!ioc_exists) -#endif + /* + * ARCv1 -> call __dc_line_op + * ARCv2 && L1 D$ disabled -> nothing + * ARCv2 && L1 D$ enabled && IOC enabled -> nothing + * ARCv2 && L1 D$ enabled && no IOC -> call __dc_line_op; call __slc_rgn_op + */ + if (!is_isa_arcv2() || !ioc_enabled()) __dc_line_op(start, end - start, OP_FLUSH); -#ifdef CONFIG_ISA_ARCV2 - if (slc_exists && !ioc_exists) + if (is_isa_arcv2() && !ioc_enabled() && !slc_data_bypass()) __slc_rgn_op(start, end - start, OP_FLUSH); -#endif } void flush_cache(unsigned long start, unsigned long size) @@ -496,22 +670,47 @@ void flush_cache(unsigned long start, unsigned long size) flush_dcache_range(start, start + size); } -void invalidate_dcache_all(void) +/* + * As invalidate_dcache_all() is not used in generic U-Boot code and as we + * don't need it in arch/arc code alone (invalidate without flush) we implement + * flush_n_invalidate_dcache_all (flush and invalidate in 1 operation) because + * it's much safer. See [ NOTE 1 ] for more details. + */ +void flush_n_invalidate_dcache_all(void) { - __dc_entire_op(OP_INV); + __dc_entire_op(OP_FLUSH_N_INV); -#ifdef CONFIG_ISA_ARCV2 - if (slc_exists) - __slc_entire_op(OP_INV); -#endif + if (is_isa_arcv2() && !slc_data_bypass()) + __slc_entire_op(OP_FLUSH_N_INV); } void flush_dcache_all(void) { __dc_entire_op(OP_FLUSH); -#ifdef CONFIG_ISA_ARCV2 - if (slc_exists) + if (is_isa_arcv2() && !slc_data_bypass()) __slc_entire_op(OP_FLUSH); -#endif +} + +/* + * This is function to cleanup all caches (and therefore sync I/D caches) which + * can be used for cleanup before linux launch or to sync caches during + * relocation. + */ +void sync_n_cleanup_cache_all(void) +{ + __dc_entire_op(OP_FLUSH_N_INV); + + /* + * If SL$ is bypassed for data it is used only for instructions, + * and we shouldn't flush it. So invalidate it instead of flush_n_inv. + */ + if (is_isa_arcv2()) { + if (slc_data_bypass()) + __slc_entire_op(OP_INV); + else + __slc_entire_op(OP_FLUSH_N_INV); + } + + __ic_entire_invalidate(); } diff --git a/arch/arc/lib/init_helpers.c b/arch/arc/lib/init_helpers.c index dbc8d68ffb..435fe96ef4 100644 --- a/arch/arc/lib/init_helpers.c +++ b/arch/arc/lib/init_helpers.c @@ -4,14 +4,14 @@ * SPDX-License-Identifier: GPL-2.0+ */ +#include <asm/cache.h> #include <common.h> DECLARE_GLOBAL_DATA_PTR; int init_cache_f_r(void) { -#ifndef CONFIG_SYS_DCACHE_OFF - flush_dcache_all(); -#endif + sync_n_cleanup_cache_all(); + return 0; } diff --git a/arch/arc/lib/memcmp.S b/arch/arc/lib/memcmp.S deleted file mode 100644 index 87bccab51d..0000000000 --- a/arch/arc/lib/memcmp.S +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2004, 2007-2010, 2011-2014 Synopsys, Inc. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifdef __LITTLE_ENDIAN__ -#define WORD2 r2 -#define SHIFT r3 -#else /* __BIG_ENDIAN__ */ -#define WORD2 r3 -#define SHIFT r2 -#endif /* _ENDIAN__ */ - -.global memcmp -.align 4 -memcmp: - or %r12, %r0, %r1 - asl_s %r12, %r12, 30 - sub %r3, %r2, 1 - brls %r2, %r12, .Lbytewise - ld %r4, [%r0, 0] - ld %r5, [%r1, 0] - lsr.f %lp_count, %r3, 3 - lpne .Loop_end - ld_s WORD2, [%r0, 4] - ld_s %r12, [%r1, 4] - brne %r4, %r5, .Leven - ld.a %r4, [%r0, 8] - ld.a %r5, [%r1, 8] - brne WORD2, %r12, .Lodd - nop -.Loop_end: - asl_s SHIFT, SHIFT, 3 - bhs_s .Last_cmp - brne %r4, %r5, .Leven - ld %r4, [%r0, 4] - ld %r5, [%r1, 4] -#ifdef __LITTLE_ENDIAN__ - nop_s - /* one more load latency cycle */ -.Last_cmp: - xor %r0, %r4, %r5 - bset %r0, %r0, SHIFT - sub_s %r1, %r0, 1 - bic_s %r1, %r1, %r0 - norm %r1, %r1 - b.d .Leven_cmp - and %r1, %r1, 24 -.Leven: - xor %r0, %r4, %r5 - sub_s %r1, %r0, 1 - bic_s %r1, %r1, %r0 - norm %r1, %r1 - /* slow track insn */ - and %r1, %r1, 24 -.Leven_cmp: - asl %r2, %r4, %r1 - asl %r12, %r5, %r1 - lsr_s %r2, %r2, 1 - lsr_s %r12, %r12, 1 - j_s.d [%blink] - sub %r0, %r2, %r12 - .balign 4 -.Lodd: - xor %r0, WORD2, %r12 - sub_s %r1, %r0, 1 - bic_s %r1, %r1, %r0 - norm %r1, %r1 - /* slow track insn */ - and %r1, %r1, 24 - asl_s %r2, %r2, %r1 - asl_s %r12, %r12, %r1 - lsr_s %r2, %r2, 1 - lsr_s %r12, %r12, 1 - j_s.d [%blink] - sub %r0, %r2, %r12 -#else /* __BIG_ENDIAN__ */ -.Last_cmp: - neg_s SHIFT, SHIFT - lsr %r4, %r4, SHIFT - lsr %r5, %r5, SHIFT - /* slow track insn */ -.Leven: - sub.f %r0, %r4, %r5 - mov.ne %r0, 1 - j_s.d [%blink] - bset.cs %r0, %r0, 31 -.Lodd: - cmp_s WORD2, %r12 - - mov_s %r0, 1 - j_s.d [%blink] - bset.cs %r0, %r0, 31 -#endif /* _ENDIAN__ */ - .balign 4 -.Lbytewise: - breq %r2, 0, .Lnil - ldb %r4, [%r0, 0] - ldb %r5, [%r1, 0] - lsr.f %lp_count, %r3 - lpne .Lbyte_end - ldb_s %r3, [%r0, 1] - ldb %r12, [%r1, 1] - brne %r4, %r5, .Lbyte_even - ldb.a %r4, [%r0, 2] - ldb.a %r5, [%r1, 2] - brne %r3, %r12, .Lbyte_odd - nop -.Lbyte_end: - bcc .Lbyte_even - brne %r4, %r5, .Lbyte_even - ldb_s %r3, [%r0, 1] - ldb_s %r12, [%r1, 1] -.Lbyte_odd: - j_s.d [%blink] - sub %r0, %r3, %r12 -.Lbyte_even: - j_s.d [%blink] - sub %r0, %r4, %r5 -.Lnil: - j_s.d [%blink] - mov %r0, 0 diff --git a/arch/arc/lib/memcpy-700.S b/arch/arc/lib/memcpy-700.S deleted file mode 100644 index 51dd73ab8f..0000000000 --- a/arch/arc/lib/memcpy-700.S +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2004, 2007-2010, 2011-2014 Synopsys, Inc. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -.global memcpy -.align 4 -memcpy: - or %r3, %r0, %r1 - asl_s %r3, %r3, 30 - mov_s %r5, %r0 - brls.d %r2, %r3, .Lcopy_bytewise - sub.f %r3, %r2, 1 - ld_s %r12, [%r1, 0] - asr.f %lp_count, %r3, 3 - bbit0.d %r3, 2, .Lnox4 - bmsk_s %r2, %r2, 1 - st.ab %r12, [%r5, 4] - ld.a %r12, [%r1, 4] -.Lnox4: - lppnz .Lendloop - ld_s %r3, [%r1, 4] - st.ab %r12, [%r5, 4] - ld.a %r12, [%r1, 8] - st.ab %r3, [%r5, 4] -.Lendloop: - breq %r2, 0, .Last_store - ld %r3, [%r5, 0] -#ifdef __LITTLE_ENDIAN__ - add3 %r2, -1, %r2 - /* uses long immediate */ - xor_s %r12, %r12, %r3 - bmsk %r12, %r12, %r2 - xor_s %r12, %r12, %r3 -#else /* __BIG_ENDIAN__ */ - sub3 %r2, 31, %r2 - /* uses long immediate */ - xor_s %r3, %r3, %r12 - bmsk %r3, %r3, %r2 - xor_s %r12, %r12, %r3 -#endif /* _ENDIAN__ */ -.Last_store: - j_s.d [%blink] - st %r12, [%r5, 0] - - .balign 4 -.Lcopy_bytewise: - jcs [%blink] - ldb_s %r12, [%r1, 0] - lsr.f %lp_count, %r3 - bhs_s .Lnox1 - stb.ab %r12, [%r5, 1] - ldb.a %r12, [%r1, 1] -.Lnox1: - lppnz .Lendbloop - ldb_s %r3, [%r1, 1] - stb.ab %r12, [%r5, 1] - ldb.a %r12, [%r1, 2] - stb.ab %r3, [%r5, 1] -.Lendbloop: - j_s.d [%blink] - stb %r12, [%r5, 0] diff --git a/arch/arc/lib/memset.S b/arch/arc/lib/memset.S deleted file mode 100644 index 017e8af0e8..0000000000 --- a/arch/arc/lib/memset.S +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2004, 2007-2010, 2011-2014 Synopsys, Inc. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#define SMALL 7 /* Must be at least 6 to deal with alignment/loop issues. */ - -.global memset -.align 4 -memset: - mov_s %r4, %r0 - or %r12, %r0, %r2 - bmsk.f %r12, %r12, 1 - extb_s %r1, %r1 - asl %r3, %r1, 8 - beq.d .Laligned - or_s %r1, %r1, %r3 - brls %r2, SMALL, .Ltiny - add %r3, %r2, %r0 - stb %r1, [%r3, -1] - bclr_s %r3, %r3, 0 - stw %r1, [%r3, -2] - bmsk.f %r12, %r0, 1 - add_s %r2, %r2, %r12 - sub.ne %r2, %r2, 4 - stb.ab %r1, [%r4, 1] - and %r4, %r4, -2 - stw.ab %r1, [%r4, 2] - and %r4, %r4, -4 - - .balign 4 -.Laligned: - asl %r3, %r1, 16 - lsr.f %lp_count, %r2, 2 - or_s %r1, %r1, %r3 - lpne .Loop_end - st.ab %r1, [%r4, 4] -.Loop_end: - j_s [%blink] - - .balign 4 -.Ltiny: - mov.f %lp_count, %r2 - lpne .Ltiny_end - stb.ab %r1, [%r4, 1] -.Ltiny_end: - j_s [%blink] - -/* - * memzero: @r0 = mem, @r1 = size_t - * memset: @r0 = mem, @r1 = char, @r2 = size_t - */ - -.global memzero -.align 4 -memzero: - /* adjust bzero args to memset args */ - mov %r2, %r1 - mov %r1, 0 - /* tail call so need to tinker with blink */ - b memset diff --git a/arch/arc/lib/relocate.c b/arch/arc/lib/relocate.c index 7802f40545..96b4bd3d8f 100644 --- a/arch/arc/lib/relocate.c +++ b/arch/arc/lib/relocate.c @@ -17,6 +17,9 @@ int copy_uboot_to_ram(void) { size_t len = (size_t)&__image_copy_end - (size_t)&__image_copy_start; + if (gd->flags & GD_FLG_SKIP_RELOC) + return 0; + memcpy((void *)gd->relocaddr, (void *)&__image_copy_start, len); return 0; @@ -40,6 +43,9 @@ int do_elf_reloc_fixups(void) Elf32_Rela *re_src = (Elf32_Rela *)(&__rel_dyn_start); Elf32_Rela *re_end = (Elf32_Rela *)(&__rel_dyn_end); + if (gd->flags & GD_FLG_SKIP_RELOC) + return 0; + debug("Section .rela.dyn is located at %08x-%08x\n", (unsigned int)re_src, (unsigned int)re_end); diff --git a/arch/arc/lib/start.S b/arch/arc/lib/start.S index 0d72fe71d4..c78dd001d8 100644 --- a/arch/arc/lib/start.S +++ b/arch/arc/lib/start.S @@ -10,26 +10,6 @@ #include <asm/arcregs.h> ENTRY(_start) -; ARCompact devices are not supposed to be SMP so master/slave check -; makes no sense. -#ifdef CONFIG_ISA_ARCV2 - ; Non-masters will be halted immediately, they might be kicked later - ; by platform code right before passing control to the Linux kernel - ; in bootm.c:boot_jump_linux(). - lr r5, [identity] - lsr r5, r5, 8 - bmsk r5, r5, 7 - cmp r5, 0 - mov.nz r0, r5 - bz .Lmaster_proceed - flag 1 - nop - nop - nop - -.Lmaster_proceed: -#endif - /* Setup interrupt vector base that matches "__text_start" */ sr __ivt_start, [ARC_AUX_INTR_VEC_BASE] @@ -98,7 +78,13 @@ ENTRY(_start) /* Zero the one and only argument of "board_init_f" */ mov_s %r0, 0 - j board_init_f + bl board_init_f + + /* We only get here if relocation is disabled by GD_FLG_SKIP_RELOC */ + /* Make sure we don't lose GD overwritten by zero new GD */ + mov %r0, %r25 + mov %r1, 0 + bl board_init_r ENDPROC(_start) /* diff --git a/arch/arc/lib/strchr-700.S b/arch/arc/lib/strchr-700.S deleted file mode 100644 index 55fcc9fb00..0000000000 --- a/arch/arc/lib/strchr-700.S +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2004, 2007-2010, 2011-2014 Synopsys, Inc. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * ARC700 has a relatively long pipeline and branch prediction, so we want - * to avoid branches that are hard to predict. On the other hand, the - * presence of the norm instruction makes it easier to operate on whole - * words branch-free. - */ - -.global strchr -.align 4 -strchr: - extb_s %r1, %r1 - asl %r5, %r1, 8 - bmsk %r2, %r0, 1 - or %r5, %r5, %r1 - mov_s %r3, 0x01010101 - breq.d %r2, %r0, .Laligned - asl %r4, %r5, 16 - sub_s %r0, %r0, %r2 - asl %r7, %r2, 3 - ld_s %r2, [%r0] -#ifdef __LITTLE_ENDIAN__ - asl %r7, %r3, %r7 -#else /* __BIG_ENDIAN__ */ - lsr %r7, %r3, %r7 -#endif /* _ENDIAN__ */ - or %r5, %r5, %r4 - ror %r4, %r3 - sub %r12, %r2, %r7 - bic_s %r12, %r12, %r2 - and %r12, %r12, %r4 - brne.d %r12, 0, .Lfound0_ua - xor %r6, %r2, %r5 - ld.a %r2, [%r0, 4] - sub %r12, %r6, %r7 - bic %r12, %r12, %r6 -#ifdef __LITTLE_ENDIAN__ - and %r7, %r12, %r4 - /* For speed, we want this branch to be unaligned. */ - breq %r7, 0, .Loop - /* Likewise this one */ - b .Lfound_char -#else /* __BIG_ENDIAN__ */ - and %r12, %r12, %r4 - /* For speed, we want this branch to be unaligned. */ - breq %r12, 0, .Loop - lsr_s %r12, %r12, 7 - bic %r2, %r7, %r6 - b.d .Lfound_char_b - and_s %r2, %r2, %r12 -#endif /* _ENDIAN__ */ - /* We require this code address to be unaligned for speed... */ -.Laligned: - ld_s %r2, [%r0] - or %r5, %r5, %r4 - ror %r4, %r3 - /* ... so that this code address is aligned, for itself and ... */ -.Loop: - sub %r12, %r2, %r3 - bic_s %r12, %r12, %r2 - and %r12, %r12, %r4 - brne.d %r12, 0, .Lfound0 - xor %r6, %r2, %r5 - ld.a %r2, [%r0, 4] - sub %r12, %r6, %r3 - bic %r12, %r12, %r6 - and %r7, %r12, %r4 - breq %r7, 0, .Loop - /* - *... so that this branch is unaligned. - * Found searched-for character. - * r0 has already advanced to next word. - */ -#ifdef __LITTLE_ENDIAN__ - /* - * We only need the information about the first matching byte - * (i.e. the least significant matching byte) to be exact, - * hence there is no problem with carry effects. - */ -.Lfound_char: - sub %r3, %r7, 1 - bic %r3, %r3, %r7 - norm %r2, %r3 - sub_s %r0, %r0, 1 - asr_s %r2, %r2, 3 - j.d [%blink] - sub_s %r0, %r0, %r2 - - .balign 4 -.Lfound0_ua: - mov %r3, %r7 -.Lfound0: - sub %r3, %r6, %r3 - bic %r3, %r3, %r6 - and %r2, %r3, %r4 - or_s %r12, %r12, %r2 - sub_s %r3, %r12, 1 - bic_s %r3, %r3, %r12 - norm %r3, %r3 - add_s %r0, %r0, 3 - asr_s %r12, %r3, 3 - asl.f 0, %r2, %r3 - sub_s %r0, %r0, %r12 - j_s.d [%blink] - mov.pl %r0, 0 -#else /* __BIG_ENDIAN__ */ -.Lfound_char: - lsr %r7, %r7, 7 - - bic %r2, %r7, %r6 -.Lfound_char_b: - norm %r2, %r2 - sub_s %r0, %r0, 4 - asr_s %r2, %r2, 3 - j.d [%blink] - add_s %r0, %r0, %r2 - -.Lfound0_ua: - mov_s %r3, %r7 -.Lfound0: - asl_s %r2, %r2, 7 - or %r7, %r6, %r4 - bic_s %r12, %r12, %r2 - sub %r2, %r7, %r3 - or %r2, %r2, %r6 - bic %r12, %r2, %r12 - bic.f %r3, %r4, %r12 - norm %r3, %r3 - - add.pl %r3, %r3, 1 - asr_s %r12, %r3, 3 - asl.f 0, %r2, %r3 - add_s %r0, %r0, %r12 - j_s.d [%blink] - mov.mi %r0, 0 -#endif /* _ENDIAN__ */ diff --git a/arch/arc/lib/strcmp.S b/arch/arc/lib/strcmp.S deleted file mode 100644 index 8cb7d2f18c..0000000000 --- a/arch/arc/lib/strcmp.S +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2004, 2007-2010, 2011-2014 Synopsys, Inc. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * This is optimized primarily for the ARC700. - * It would be possible to speed up the loops by one cycle / word - * respective one cycle / byte by forcing double source 1 alignment, unrolling - * by a factor of two, and speculatively loading the second word / byte of - * source 1; however, that would increase the overhead for loop setup / finish, - * and strcmp might often terminate early. - */ - -.global strcmp -.align 4 -strcmp: - or %r2, %r0, %r1 - bmsk_s %r2, %r2, 1 - brne %r2, 0, .Lcharloop - mov_s %r12, 0x01010101 - ror %r5, %r12 -.Lwordloop: - ld.ab %r2, [%r0, 4] - ld.ab %r3, [%r1, 4] - nop_s - sub %r4, %r2, %r12 - bic %r4, %r4, %r2 - and %r4, %r4, %r5 - brne %r4, 0, .Lfound0 - breq %r2 ,%r3, .Lwordloop -#ifdef __LITTLE_ENDIAN__ - xor %r0, %r2, %r3 /* mask for difference */ - sub_s %r1, %r0, 1 - bic_s %r0, %r0, %r1 /* mask for least significant difference bit */ - sub %r1, %r5, %r0 - xor %r0, %r5, %r1 /* mask for least significant difference byte */ - and_s %r2, %r2, %r0 - and_s %r3, %r3, %r0 -#endif /* _ENDIAN__ */ - cmp_s %r2, %r3 - mov_s %r0, 1 - j_s.d [%blink] - bset.lo %r0, %r0, 31 - - .balign 4 -#ifdef __LITTLE_ENDIAN__ -.Lfound0: - xor %r0, %r2, %r3 /* mask for difference */ - or %r0, %r0, %r4 /* or in zero indicator */ - sub_s %r1, %r0, 1 - bic_s %r0, %r0, %r1 /* mask for least significant difference bit */ - sub %r1, %r5, %r0 - xor %r0, %r5, %r1 /* mask for least significant difference byte */ - and_s %r2, %r2, %r0 - and_s %r3, %r3, %r0 - sub.f %r0, %r2, %r3 - mov.hi %r0, 1 - j_s.d [%blink] - bset.lo %r0, %r0, 31 -#else /* __BIG_ENDIAN__ */ - /* - * The zero-detection above can mis-detect 0x01 bytes as zeroes - * because of carry-propagateion from a lower significant zero byte. - * We can compensate for this by checking that bit0 is zero. - * This compensation is not necessary in the step where we - * get a low estimate for r2, because in any affected bytes - * we already have 0x00 or 0x01, which will remain unchanged - * when bit 7 is cleared. - */ - .balign 4 -.Lfound0: - lsr %r0, %r4, 8 - lsr_s %r1, %r2 - bic_s %r2, %r2, %r0 /* get low estimate for r2 and get ... */ - bic_s %r0, %r0, %r1 /* <this is the adjusted mask for zeros> */ - or_s %r3, %r3, %r0 /* ... high estimate r3 so that r2 > r3 will */ - cmp_s %r3, %r2 /* ... be independent of trailing garbage */ - or_s %r2, %r2, %r0 /* likewise for r3 > r2 */ - bic_s %r3, %r3, %r0 - rlc %r0, 0 /* r0 := r2 > r3 ? 1 : 0 */ - cmp_s %r2, %r3 - j_s.d [%blink] - bset.lo %r0, %r0, 31 -#endif /* _ENDIAN__ */ - - .balign 4 -.Lcharloop: - ldb.ab %r2,[%r0,1] - ldb.ab %r3,[%r1,1] - nop_s - breq %r2, 0, .Lcmpend - breq %r2, %r3, .Lcharloop -.Lcmpend: - j_s.d [%blink] - sub %r0, %r2, %r3 diff --git a/arch/arc/lib/strcpy-700.S b/arch/arc/lib/strcpy-700.S deleted file mode 100644 index 41bb53e501..0000000000 --- a/arch/arc/lib/strcpy-700.S +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2004, 2007-2010, 2011-2014 Synopsys, Inc. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * If dst and src are 4 byte aligned, copy 8 bytes at a time. - * If the src is 4, but not 8 byte aligned, we first read 4 bytes to get - * it 8 byte aligned. Thus, we can do a little read-ahead, without - * dereferencing a cache line that we should not touch. - * Note that short and long instructions have been scheduled to avoid - * branch stalls. - * The beq_s to r3z could be made unaligned & long to avoid a stall - * there, but it is not likely to be taken often, and it would also be likely - * to cost an unaligned mispredict at the next call. - */ - -.global strcpy -.align 4 -strcpy: - or %r2, %r0, %r1 - bmsk_s %r2, %r2, 1 - brne.d %r2, 0, charloop - mov_s %r10, %r0 - ld_s %r3, [%r1, 0] - mov %r8, 0x01010101 - bbit0.d %r1, 2, loop_start - ror %r12, %r8 - sub %r2, %r3, %r8 - bic_s %r2, %r2, %r3 - tst_s %r2,%r12 - bne r3z - mov_s %r4,%r3 - .balign 4 -loop: - ld.a %r3, [%r1, 4] - st.ab %r4, [%r10, 4] -loop_start: - ld.a %r4, [%r1, 4] - sub %r2, %r3, %r8 - bic_s %r2, %r2, %r3 - tst_s %r2, %r12 - bne_s r3z - st.ab %r3, [%r10, 4] - sub %r2, %r4, %r8 - bic %r2, %r2, %r4 - tst %r2, %r12 - beq loop - mov_s %r3, %r4 -#ifdef __LITTLE_ENDIAN__ -r3z: bmsk.f %r1, %r3, 7 - lsr_s %r3, %r3, 8 -#else /* __BIG_ENDIAN__ */ -r3z: lsr.f %r1, %r3, 24 - asl_s %r3, %r3, 8 -#endif /* _ENDIAN__ */ - bne.d r3z - stb.ab %r1, [%r10, 1] - j_s [%blink] - - .balign 4 -charloop: - ldb.ab %r3, [%r1, 1] - brne.d %r3, 0, charloop - stb.ab %r3, [%r10, 1] - j [%blink] diff --git a/arch/arc/lib/strlen.S b/arch/arc/lib/strlen.S deleted file mode 100644 index 666e22c0d5..0000000000 --- a/arch/arc/lib/strlen.S +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2004, 2007-2010, 2011-2014 Synopsys, Inc. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -.global strlen -.align 4 -strlen: - or %r3, %r0, 7 - ld %r2, [%r3, -7] - ld.a %r6, [%r3, -3] - mov %r4, 0x01010101 - /* uses long immediate */ -#ifdef __LITTLE_ENDIAN__ - asl_s %r1, %r0, 3 - btst_s %r0, 2 - asl %r7, %r4, %r1 - ror %r5, %r4 - sub %r1, %r2, %r7 - bic_s %r1, %r1, %r2 - mov.eq %r7, %r4 - sub %r12, %r6, %r7 - bic %r12, %r12, %r6 - or.eq %r12, %r12, %r1 - and %r12, %r12, %r5 - brne %r12, 0, .Learly_end -#else /* __BIG_ENDIAN__ */ - ror %r5, %r4 - btst_s %r0, 2 - mov_s %r1, 31 - sub3 %r7, %r1, %r0 - sub %r1, %r2, %r4 - bic_s %r1, %r1, %r2 - bmsk %r1, %r1, %r7 - sub %r12, %r6, %r4 - bic %r12, %r12, %r6 - bmsk.ne %r12, %r12, %r7 - or.eq %r12, %r12, %r1 - and %r12, %r12, %r5 - brne %r12, 0, .Learly_end -#endif /* _ENDIAN__ */ - -.Loop: - ld_s %r2, [%r3, 4] - ld.a %r6, [%r3, 8] - /* stall for load result */ - sub %r1, %r2, %r4 - bic_s %r1, %r1, %r2 - sub %r12, %r6, %r4 - bic %r12, %r12, %r6 - or %r12, %r12, %r1 - and %r12, %r12, %r5 - breq %r12, 0, .Loop -.Lend: - and.f %r1, %r1, %r5 - sub.ne %r3, %r3, 4 - mov.eq %r1, %r12 -#ifdef __LITTLE_ENDIAN__ - sub_s %r2, %r1, 1 - bic_s %r2, %r2, %r1 - norm %r1, %r2 - sub_s %r0, %r0, 3 - lsr_s %r1, %r1, 3 - sub %r0, %r3, %r0 - j_s.d [%blink] - sub %r0, %r0, %r1 -#else /* __BIG_ENDIAN__ */ - lsr_s %r1, %r1, 7 - mov.eq %r2, %r6 - bic_s %r1, %r1, %r2 - norm %r1, %r1 - sub %r0, %r3, %r0 - lsr_s %r1, %r1, 3 - j_s.d [%blink] - add %r0, %r0, %r1 -#endif /* _ENDIAN */ -.Learly_end: - b.d .Lend - sub_s.ne %r1, %r1, %r1 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index b8f7a982d9..068ea1e877 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -762,6 +762,7 @@ config ARCH_ZYNQ select SUPPORT_SPL select OF_CONTROL select SPL_BOARD_INIT if SPL + select BOARD_EARLY_INIT_F if WDT select SPL_OF_CONTROL if SPL select DM select DM_ETH if NET @@ -1359,6 +1360,7 @@ source "board/toradex/colibri_pxa270/Kconfig" source "board/vscom/baltos/Kconfig" source "board/woodburn/Kconfig" source "board/work-microwave/work_92105/Kconfig" +source "board/xilinx/zynqmp/Kconfig" source "board/zipitz2/Kconfig" source "arch/arm/Kconfig.debug" diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c index b9f837d58d..18fb937a3a 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c @@ -612,6 +612,29 @@ int setup_chip_volt(void) return 0; } +#ifdef CONFIG_FSL_PFE +void init_pfe_scfg_dcfg_regs(void) +{ + struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR; + u32 ecccr2; + + out_be32(&scfg->pfeasbcr, + in_be32(&scfg->pfeasbcr) | SCFG_PFEASBCR_AWCACHE0); + out_be32(&scfg->pfebsbcr, + in_be32(&scfg->pfebsbcr) | SCFG_PFEASBCR_AWCACHE0); + + /* CCI-400 QoS settings for PFE */ + out_be32(&scfg->wr_qos1, (unsigned int)(SCFG_WR_QOS1_PFE1_QOS + | SCFG_WR_QOS1_PFE2_QOS)); + out_be32(&scfg->rd_qos1, (unsigned int)(SCFG_RD_QOS1_PFE1_QOS + | SCFG_RD_QOS1_PFE2_QOS)); + + ecccr2 = in_be32(CONFIG_SYS_DCSR_DCFG_ADDR + DCFG_DCSR_ECCCR2); + out_be32((void *)CONFIG_SYS_DCSR_DCFG_ADDR + DCFG_DCSR_ECCCR2, + ecccr2 | (unsigned int)DISABLE_PFE_ECC); +} +#endif + void fsl_lsch2_early_init_f(void) { struct ccsr_cci400 *cci = (struct ccsr_cci400 *)(CONFIG_SYS_IMMR + diff --git a/arch/arm/cpu/armv8/zynqmp/cpu.c b/arch/arm/cpu/armv8/zynqmp/cpu.c index bc77dd03c3..14e7d40064 100644 --- a/arch/arm/cpu/armv8/zynqmp/cpu.c +++ b/arch/arm/cpu/armv8/zynqmp/cpu.c @@ -185,7 +185,7 @@ void zynqmp_pmufw_version(void) pm_api_version >> ZYNQMP_PM_VERSION_MAJOR_SHIFT, pm_api_version & ZYNQMP_PM_VERSION_MINOR_MASK); - if (pm_api_version != ZYNQMP_PM_VERSION) + if (pm_api_version < ZYNQMP_PM_VERSION) panic("PMUFW version error. Expected: v%d.%d\n", ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR); } diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 7dd1dffae5..e983622fea 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -146,7 +146,6 @@ dtb-$(CONFIG_ARCH_ZYNQ) += \ zynq-zturn-myir.dtb \ zynq-zybo.dtb dtb-$(CONFIG_ARCH_ZYNQMP) += \ - zynqmp-ep108.dtb \ zynqmp-mini-emmc.dtb \ zynqmp-mini-nand.dtb \ zynqmp-zcu102-revA.dtb \ diff --git a/arch/arm/dts/da850-lcdk-u-boot.dtsi b/arch/arm/dts/da850-lcdk-u-boot.dtsi new file mode 100644 index 0000000000..c67c3ddbf7 --- /dev/null +++ b/arch/arm/dts/da850-lcdk-u-boot.dtsi @@ -0,0 +1,13 @@ +/* + * da850-lcdk U-Boot Additions + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/ { + aliases { + i2c0 = &i2c0; + }; +}; diff --git a/arch/arm/dts/da850-lcdk.dts b/arch/arm/dts/da850-lcdk.dts new file mode 100644 index 0000000000..a1f4d6d5a5 --- /dev/null +++ b/arch/arm/dts/da850-lcdk.dts @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2016 BayLibre, Inc. + * + * Licensed under GPLv2. + */ +/dts-v1/; +#include "da850.dtsi" +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> + +/ { + model = "DA850/AM1808/OMAP-L138 LCDK"; + compatible = "ti,da850-lcdk", "ti,da850"; + + aliases { + serial2 = &serial2; + ethernet0 = ð0; + }; + + chosen { + stdout-path = "serial2:115200n8"; + }; + + memory { + device_type = "memory"; + reg = <0xc0000000 0x08000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + dsp_memory_region: dsp-memory@c3000000 { + compatible = "shared-dma-pool"; + reg = <0xc3000000 0x1000000>; + reusable; + status = "okay"; + }; + }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "DA850/OMAP-L138 LCDK"; + simple-audio-card,widgets = + "Line", "Line In", + "Line", "Line Out"; + simple-audio-card,routing = + "LINE1L", "Line In", + "LINE1R", "Line In", + "Line Out", "LLOUT", + "Line Out", "RLOUT"; + simple-audio-card,format = "dsp_b"; + simple-audio-card,bitclock-master = <&link0_codec>; + simple-audio-card,frame-master = <&link0_codec>; + simple-audio-card,bitclock-inversion; + + simple-audio-card,cpu { + sound-dai = <&mcasp0>; + system-clock-frequency = <24576000>; + }; + + link0_codec: simple-audio-card,codec { + sound-dai = <&tlv320aic3106>; + system-clock-frequency = <24576000>; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + autorepeat; + + user1 { + label = "GPIO Key USER1"; + linux,code = <BTN_0>; + gpios = <&gpio 36 GPIO_ACTIVE_LOW>; + }; + + user2 { + label = "GPIO Key USER2"; + linux,code = <BTN_1>; + gpios = <&gpio 37 GPIO_ACTIVE_LOW>; + }; + }; + + vga-bridge { + compatible = "ti,ths8135"; + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + vga_bridge_in: endpoint { + remote-endpoint = <&lcdc_out_vga>; + }; + }; + + port@1 { + reg = <1>; + + vga_bridge_out: endpoint { + remote-endpoint = <&vga_con_in>; + }; + }; + }; + }; + + vga { + compatible = "vga-connector"; + + ddc-i2c-bus = <&i2c0>; + + port { + vga_con_in: endpoint { + remote-endpoint = <&vga_bridge_out>; + }; + }; + }; +}; + +&pmx_core { + status = "okay"; + + mcasp0_pins: pinmux_mcasp0_pins { + pinctrl-single,bits = < + /* AHCLKX AFSX ACLKX */ + 0x00 0x00101010 0x00f0f0f0 + /* ARX13 ARX14 */ + 0x04 0x00000110 0x00000ff0 + >; + }; + + nand_pins: nand_pins { + pinctrl-single,bits = < + /* EMA_WAIT[0], EMA_OE, EMA_WE, EMA_CS[3] */ + 0x1c 0x10110010 0xf0ff00f0 + /* + * EMA_D[0], EMA_D[1], EMA_D[2], + * EMA_D[3], EMA_D[4], EMA_D[5], + * EMA_D[6], EMA_D[7] + */ + 0x24 0x11111111 0xffffffff + /* + * EMA_D[8], EMA_D[9], EMA_D[10], + * EMA_D[11], EMA_D[12], EMA_D[13], + * EMA_D[14], EMA_D[15] + */ + 0x20 0x11111111 0xffffffff + /* EMA_A[1], EMA_A[2] */ + 0x30 0x01100000 0x0ff00000 + >; + }; +}; + +&serial2 { + pinctrl-names = "default"; + pinctrl-0 = <&serial2_rxtx_pins>; + status = "okay"; +}; + +&wdt { + status = "okay"; +}; + +&rtc0 { + status = "okay"; +}; + +&gpio { + status = "okay"; +}; + +&sata { + status = "okay"; +}; + +&mdio { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + bus_freq = <2200000>; + status = "okay"; +}; + +ð0 { + pinctrl-names = "default"; + pinctrl-0 = <&mii_pins>; + status = "okay"; +}; + +&mmc0 { + max-frequency = <50000000>; + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins>; + cd-gpios = <&gpio 64 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + clock-frequency = <100000>; + status = "okay"; + + tlv320aic3106: tlv320aic3106@18 { + #sound-dai-cells = <0>; + compatible = "ti,tlv320aic3106"; + reg = <0x18>; + status = "okay"; + }; +}; + +&mcasp0 { + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&mcasp0_pins>; + status = "okay"; + + op-mode = <0>; /* DAVINCI_MCASP_IIS_MODE */ + tdm-slots = <2>; + serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ + 0 0 0 0 + 0 0 0 0 + 0 0 0 0 + 0 1 2 0 + >; + tx-num-evt = <32>; + rx-num-evt = <32>; +}; + +&usb_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; + +&aemif { + pinctrl-names = "default"; + pinctrl-0 = <&nand_pins>; + status = "okay"; + cs3 { + #address-cells = <2>; + #size-cells = <1>; + clock-ranges; + ranges; + + ti,cs-chipselect = <3>; + + nand@2000000,0 { + compatible = "ti,davinci-nand"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0 0x02000000 0x02000000 + 1 0x00000000 0x00008000>; + + ti,davinci-chipselect = <1>; + ti,davinci-mask-ale = <0>; + ti,davinci-mask-cle = <0>; + ti,davinci-mask-chipsel = <0>; + + ti,davinci-nand-buswidth = <16>; + ti,davinci-ecc-mode = "hw"; + ti,davinci-ecc-bits = <4>; + ti,davinci-nand-use-bbt; + + /* + * The OMAP-L132/L138 Bootloader doc SPRAB41E reads: + * "To boot from NAND Flash, the AIS should be written + * to NAND block 1 (NAND block 0 is not used by default)". + * The same doc mentions that for ROM "Silicon Revision 2.1", + * "Updated NAND boot mode to offer boot from block 0 or block 1". + * However the limitaion is left here by default for compatibility + * with older silicon and because it needs new boot pin settings + * not possible in stock LCDK. + */ + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot env"; + reg = <0 0x020000>; + }; + partition@20000 { + /* The LCDK defaults to booting from this partition */ + label = "u-boot"; + reg = <0x020000 0x080000>; + }; + partition@a0000 { + label = "free space"; + reg = <0x0a0000 0>; + }; + }; + }; + }; +}; + +&prictrl { + status = "okay"; +}; + +&memctrl { + status = "okay"; +}; + +&lcdc { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_pins>; + + port { + lcdc_out_vga: endpoint { + remote-endpoint = <&vga_bridge_in>; + }; + }; +}; + +&vpif { + pinctrl-names = "default"; + pinctrl-0 = <&vpif_capture_pins>; + status = "okay"; +}; + +&dsp { + memory-region = <&dsp_memory_region>; + status = "okay"; +}; diff --git a/arch/arm/dts/da850.dtsi b/arch/arm/dts/da850.dtsi index 02e2f8f258..c66cf78953 100644 --- a/arch/arm/dts/da850.dtsi +++ b/arch/arm/dts/da850.dtsi @@ -23,11 +23,18 @@ reg = <0xfffee000 0x2000>; }; }; - - aliases { - spi0 = &spi0; + dsp: dsp@11800000 { + compatible = "ti,da850-dsp"; + reg = <0x11800000 0x40000>, + <0x11e00000 0x8000>, + <0x11f00000 0x8000>, + <0x01c14044 0x4>, + <0x01c14174 0x8>; + reg-names = "l2sram", "l1pram", "l1dram", "host1cfg", "chipsig"; + interrupt-parent = <&intc>; + interrupts = <28>; + status = "disabled"; }; - soc@1c00000 { compatible = "simple-bus"; model = "da850"; diff --git a/arch/arm/dts/zynq-zc706.dts b/arch/arm/dts/zynq-zc706.dts index d342306293..a88a83c166 100644 --- a/arch/arm/dts/zynq-zc706.dts +++ b/arch/arm/dts/zynq-zc706.dts @@ -333,3 +333,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usb0_default>; }; + +&watchdog0 { + reset-on-timeout; +}; diff --git a/arch/arm/dts/zynqmp-clk-ccf.dtsi b/arch/arm/dts/zynqmp-clk-ccf.dtsi new file mode 100644 index 0000000000..4449d5b93d --- /dev/null +++ b/arch/arm/dts/zynqmp-clk-ccf.dtsi @@ -0,0 +1,290 @@ +/* + * Clock specification for Xilinx ZynqMP + * + * (C) Copyright 2017, Xilinx, Inc. + * + * Michal Simek <michal.simek@xilinx.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/ { + fclk0: fclk0 { + status = "disabled"; + compatible = "xlnx,fclk"; + clocks = <&clkc 71>; + }; + + fclk1: fclk1 { + status = "disabled"; + compatible = "xlnx,fclk"; + clocks = <&clkc 72>; + }; + + fclk2: fclk2 { + status = "disabled"; + compatible = "xlnx,fclk"; + clocks = <&clkc 73>; + }; + + fclk3: fclk3 { + status = "disabled"; + compatible = "xlnx,fclk"; + clocks = <&clkc 74>; + }; + + pss_ref_clk: pss_ref_clk { + u-boot,dm-pre-reloc; + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <33333333>; + }; + + video_clk: video_clk { + u-boot,dm-pre-reloc; + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <27000000>; + }; + + pss_alt_ref_clk: pss_alt_ref_clk { + u-boot,dm-pre-reloc; + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + + gt_crx_ref_clk: gt_crx_ref_clk { + u-boot,dm-pre-reloc; + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <108000000>; + }; + + aux_ref_clk: aux_ref_clk { + u-boot,dm-pre-reloc; + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <27000000>; + }; + + clkc: clkc { + u-boot,dm-pre-reloc; + #clock-cells = <1>; + compatible = "xlnx,zynqmp-clkc"; + clocks = <&pss_ref_clk>, <&video_clk>, <&pss_alt_ref_clk>, <&aux_ref_clk>, <>_crx_ref_clk>; + clock-names = "pss_ref_clk", "video_clk", "pss_alt_ref_clk", "aux_ref_clk", "gt_crx_ref_clk"; + clock-output-names = "iopll", "rpll", "apll", "dpll", + "vpll", "iopll_to_fpd", "rpll_to_fpd", + "apll_to_lpd", "dpll_to_lpd", "vpll_to_lpd", + "acpu", "acpu_half", "dbf_fpd", "dbf_lpd", + "dbg_trace", "dbg_tstmp", "dp_video_ref", + "dp_audio_ref", "dp_stc_ref", "gdma_ref", + "dpdma_ref", "ddr_ref", "sata_ref", "pcie_ref", + "gpu_ref", "gpu_pp0_ref", "gpu_pp1_ref", + "topsw_main", "topsw_lsbus", "gtgref0_ref", + "lpd_switch", "lpd_lsbus", "usb0_bus_ref", + "usb1_bus_ref", "usb3_dual_ref", "usb0", + "usb1", "cpu_r5", "cpu_r5_core", "csu_spb", + "csu_pll", "pcap", "iou_switch", "gem_tsu_ref", + "gem_tsu", "gem0_ref", "gem1_ref", "gem2_ref", + "gem3_ref", "gem0_tx", "gem1_tx", "gem2_tx", + "gem3_tx", "qspi_ref", "sdio0_ref", "sdio1_ref", + "uart0_ref", "uart1_ref", "spi0_ref", + "spi1_ref", "nand_ref", "i2c0_ref", "i2c1_ref", + "can0_ref", "can1_ref", "can0", "can1", + "dll_ref", "adma_ref", "timestamp_ref", + "ams_ref", "pl0", "pl1", "pl2", "pl3", "wdt"; + }; + + dp_aclk: dp_aclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + clock-accuracy = <100>; + }; +}; + +&can0 { + clocks = <&clkc 63>, <&clkc 31>; +}; + +&can1 { + clocks = <&clkc 64>, <&clkc 31>; +}; + +&cpu0 { + clocks = <&clkc 10>; +}; + +&fpd_dma_chan1 { + clocks = <&clkc 19>, <&clkc 31>; +}; + +&fpd_dma_chan2 { + clocks = <&clkc 19>, <&clkc 31>; +}; + +&fpd_dma_chan3 { + clocks = <&clkc 19>, <&clkc 31>; +}; + +&fpd_dma_chan4 { + clocks = <&clkc 19>, <&clkc 31>; +}; + +&fpd_dma_chan5 { + clocks = <&clkc 19>, <&clkc 31>; +}; + +&fpd_dma_chan6 { + clocks = <&clkc 19>, <&clkc 31>; +}; + +&fpd_dma_chan7 { + clocks = <&clkc 19>, <&clkc 31>; +}; + +&fpd_dma_chan8 { + clocks = <&clkc 19>, <&clkc 31>; +}; + +&gpu { + clocks = <&clkc 24>, <&clkc 25>, <&clkc 26>; +}; + +&lpd_dma_chan1 { + clocks = <&clkc 68>, <&clkc 31>; +}; + +&lpd_dma_chan2 { + clocks = <&clkc 68>, <&clkc 31>; +}; + +&lpd_dma_chan3 { + clocks = <&clkc 68>, <&clkc 31>; +}; + +&lpd_dma_chan4 { + clocks = <&clkc 68>, <&clkc 31>; +}; + +&lpd_dma_chan5 { + clocks = <&clkc 68>, <&clkc 31>; +}; + +&lpd_dma_chan6 { + clocks = <&clkc 68>, <&clkc 31>; +}; + +&lpd_dma_chan7 { + clocks = <&clkc 68>, <&clkc 31>; +}; + +&lpd_dma_chan8 { + clocks = <&clkc 68>, <&clkc 31>; +}; + +&nand0 { + clocks = <&clkc 60>, <&clkc 31>; +}; + +&gem0 { + clocks = <&clkc 31>, <&clkc 49>, <&clkc 45>, <&clkc 49>, <&clkc 44>; + clock-names = "pclk", "hclk", "tx_clk", "rx_clk", "tsu_clk"; +}; + +&gem1 { + clocks = <&clkc 31>, <&clkc 50>, <&clkc 46>, <&clkc 50>, <&clkc 44>; + clock-names = "pclk", "hclk", "tx_clk", "rx_clk", "tsu_clk"; +}; + +&gem2 { + clocks = <&clkc 31>, <&clkc 51>, <&clkc 47>, <&clkc 51>, <&clkc 44>; + clock-names = "pclk", "hclk", "tx_clk", "rx_clk", "tsu_clk"; +}; + +&gem3 { + clocks = <&clkc 31>, <&clkc 52>, <&clkc 48>, <&clkc 52>, <&clkc 44>; + clock-names = "pclk", "hclk", "tx_clk", "rx_clk", "tsu_clk"; +}; + +&gpio { + clocks = <&clkc 31>; +}; + +&i2c0 { + clocks = <&clkc 61>; +}; + +&i2c1 { + clocks = <&clkc 62>; +}; + +&pcie { + clocks = <&clkc 23>; +}; + +&qspi { + clocks = <&clkc 53>, <&clkc 31>; +}; + +&sata { + clocks = <&clkc 22>; +}; + +&sdhci0 { + clocks = <&clkc 54>, <&clkc 31>; +}; + +&sdhci1 { + clocks = <&clkc 55>, <&clkc 31>; +}; + +&spi0 { + clocks = <&clkc 58>, <&clkc 31>; +}; + +&spi1 { + clocks = <&clkc 59>, <&clkc 31>; +}; + +&uart0 { + clocks = <&clkc 56>, <&clkc 31>; +}; + +&uart1 { + clocks = <&clkc 57>, <&clkc 31>; +}; + +&usb0 { + clocks = <&clkc 32>, <&clkc 34>; +}; + +&usb1 { + clocks = <&clkc 33>, <&clkc 34>; +}; + +&watchdog0 { + clocks = <&clkc 75>; +}; + +&xilinx_ams { + clocks = <&clkc 70>; +}; + +&xilinx_drm { + clocks = <&clkc 16>; +}; + +&xlnx_dp { + clocks = <&dp_aclk>, <&clkc 17>; +}; + +&xlnx_dpdma { + clocks = <&clkc 20>; +}; + +&xlnx_dp_snd_codec0 { + clocks = <&clkc 17>; +}; diff --git a/arch/arm/dts/zynqmp-ep108-clk.dtsi b/arch/arm/dts/zynqmp-ep108-clk.dtsi deleted file mode 100644 index 12d9fe1498..0000000000 --- a/arch/arm/dts/zynqmp-ep108-clk.dtsi +++ /dev/null @@ -1,172 +0,0 @@ -/* - * clock specification for Xilinx ZynqMP ep108 development board - * - * (C) Copyright 2015, Xilinx, Inc. - * - * Michal Simek <michal.simek@xilinx.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/ { - misc_clk: misc_clk { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <25000000>; - u-boot,dm-pre-reloc; - }; - - i2c_clk: i2c_clk { - compatible = "fixed-clock"; - #clock-cells = <0x0>; - clock-frequency = <111111111>; - }; - - sata_clk: sata_clk { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <75000000>; - }; - - dp_aclk: clock0 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <50000000>; - clock-accuracy = <100>; - }; - - clk100: clk100 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <100000000>; - }; - - clk600: clk600 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <600000000>; - }; - - dp_aud_clk: clock1 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <22579200>; - clock-accuracy = <100>; - }; -}; - -&can0 { - clocks = <&misc_clk &misc_clk>; -}; - -&can1 { - clocks = <&misc_clk &misc_clk>; -}; - -&fpd_dma_chan1 { - clocks = <&clk600>, <&clk100>; -}; - -&fpd_dma_chan2 { - clocks = <&clk600>, <&clk100>; -}; - -&fpd_dma_chan3 { - clocks = <&clk600>, <&clk100>; -}; - -&fpd_dma_chan4 { - clocks = <&clk600>, <&clk100>; -}; - -&fpd_dma_chan5 { - clocks = <&clk600>, <&clk100>; -}; - -&fpd_dma_chan6 { - clocks = <&clk600>, <&clk100>; -}; - -&fpd_dma_chan7 { - clocks = <&clk600>, <&clk100>; -}; - -&fpd_dma_chan8 { - clocks = <&clk600>, <&clk100>; -}; - -&gem0 { - clocks = <&misc_clk>, <&misc_clk>, <&misc_clk>; -}; - -&gpio { - clocks = <&misc_clk>; -}; - -&i2c0 { - clocks = <&i2c_clk>; -}; - -&i2c1 { - clocks = <&i2c_clk>; -}; - -&nand0 { - clocks = <&misc_clk &misc_clk>; -}; - -&qspi { - clocks = <&misc_clk &misc_clk>; -}; - -&sata { - clocks = <&sata_clk>; -}; - -&sdhci0 { - clocks = <&misc_clk>, <&misc_clk>; -}; - -&sdhci1 { - clocks = <&misc_clk>, <&misc_clk>; -}; - -&spi0 { - clocks = <&misc_clk &misc_clk>; -}; - -&spi1 { - clocks = <&misc_clk &misc_clk>; -}; - -&uart0 { - clocks = <&misc_clk &misc_clk>; -}; - -&usb0 { - clocks = <&misc_clk>, <&misc_clk>; -}; - -&usb1 { - clocks = <&misc_clk>, <&misc_clk>; -}; - -&watchdog0 { - clocks= <&misc_clk>; -}; - -&xilinx_drm { - clocks = <&misc_clk>; -}; - -&xlnx_dp { - clocks = <&dp_aclk>, <&dp_aud_clk>; -}; - -&xlnx_dp_snd_codec0 { - clocks = <&dp_aud_clk>; -}; - -&xlnx_dpdma { - clocks = <&misc_clk>; -}; diff --git a/arch/arm/dts/zynqmp-ep108.dts b/arch/arm/dts/zynqmp-ep108.dts deleted file mode 100644 index a16ffdc3f0..0000000000 --- a/arch/arm/dts/zynqmp-ep108.dts +++ /dev/null @@ -1,235 +0,0 @@ -/* - * dts file for Xilinx ZynqMP ep108 development board - * - * (C) Copyright 2014 - 2015, Xilinx, Inc. - * - * Michal Simek <michal.simek@xilinx.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/dts-v1/; - -#include "zynqmp.dtsi" -#include "zynqmp-ep108-clk.dtsi" - -/ { - model = "ZynqMP EP108"; - - aliases { - ethernet0 = &gem0; - mmc0 = &sdhci0; - mmc1 = &sdhci1; - serial0 = &uart0; - spi0 = &qspi; - spi1 = &spi0; - spi2 = &spi1; - usb0 = &usb0; - usb1 = &usb1; - }; - - chosen { - bootargs = "earlycon"; - stdout-path = "serial0:115200n8"; - }; - - memory@0 { - device_type = "memory"; - reg = <0x0 0x0 0x0 0x40000000>; - }; -}; - -&can0 { - status = "okay"; -}; - -&can1 { - status = "okay"; -}; - -&gem0 { - status = "okay"; - phy-handle = <&phy0>; - phy-mode = "rgmii-id"; - phy0: phy@0 { - reg = <0>; - max-speed = <100>; - }; -}; - -&gpio { - status = "okay"; -}; - -&i2c0 { - status = "okay"; - clock-frequency = <400000>; - eeprom@54 { - compatible = "atmel,24c64"; - reg = <0x54>; - }; -}; - -&i2c1 { - status = "okay"; - clock-frequency = <400000>; - eeprom@55 { - compatible = "atmel,24c64"; - reg = <0x55>; - }; -}; - -&nand0 { - status = "okay"; - arasan,has-mdma; - num-cs = <1>; - - partition@0 { /* for testing purpose */ - label = "nand-fsbl-uboot"; - reg = <0x0 0x0 0x400000>; - }; - partition@1 { /* for testing purpose */ - label = "nand-linux"; - reg = <0x0 0x400000 0x1400000>; - }; - partition@2 { /* for testing purpose */ - label = "nand-device-tree"; - reg = <0x0 0x1800000 0x400000>; - }; - partition@3 { /* for testing purpose */ - label = "nand-rootfs"; - reg = <0x0 0x1C00000 0x1400000>; - }; - partition@4 { /* for testing purpose */ - label = "nand-bitstream"; - reg = <0x0 0x3000000 0x400000>; - }; - partition@5 { /* for testing purpose */ - label = "nand-misc"; - reg = <0x0 0x3400000 0xFCC00000>; - }; -}; - -&qspi { - status = "okay"; - flash@0 { - compatible = "m25p80"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0x0>; - spi-tx-bus-width = <1>; - spi-rx-bus-width = <4>; - spi-max-frequency = <10000000>; - partition@qspi-fsbl-uboot { /* for testing purpose */ - label = "qspi-fsbl-uboot"; - reg = <0x0 0x100000>; - }; - partition@qspi-linux { /* for testing purpose */ - label = "qspi-linux"; - reg = <0x100000 0x500000>; - }; - partition@qspi-device-tree { /* for testing purpose */ - label = "qspi-device-tree"; - reg = <0x600000 0x20000>; - }; - partition@qspi-rootfs { /* for testing purpose */ - label = "qspi-rootfs"; - reg = <0x620000 0x5E0000>; - }; - }; -}; - -&sata { - status = "okay"; - ceva,broken-gen2; - /* SATA Phy OOB timing settings */ - ceva,p0-cominit-params = /bits/ 8 <0x0F 0x25 0x18 0x29>; - ceva,p0-comwake-params = /bits/ 8 <0x04 0x0B 0x08 0x0F>; - ceva,p0-burst-params = /bits/ 8 <0x0A 0x08 0x4A 0x06>; - ceva,p0-retry-params = /bits/ 16 <0x0216 0x7F06>; - ceva,p1-cominit-params = /bits/ 8 <0x0F 0x25 0x18 0x29>; - ceva,p1-comwake-params = /bits/ 8 <0x04 0x0B 0x08 0x0F>; - ceva,p1-burst-params = /bits/ 8 <0x0A 0x08 0x4A 0x06>; - ceva,p1-retry-params = /bits/ 16 <0x0216 0x7F06>; -}; - -&sdhci0 { - status = "okay"; - bus-width = <8>; - xlnx,mio_bank = <2>; -}; - -&sdhci1 { - status = "okay"; - xlnx,mio_bank = <1>; -}; - -&spi0 { - status = "okay"; - num-cs = <1>; - spi0_flash0: spi0_flash0@0 { - compatible = "m25p80"; - #address-cells = <1>; - #size-cells = <1>; - spi-max-frequency = <50000000>; - reg = <0>; - - spi0_flash0@0 { - label = "spi0_flash0"; - reg = <0x0 0x100000>; - }; - }; -}; - -&spi1 { - status = "okay"; - num-cs = <1>; - spi1_flash0: spi1_flash0@0 { - compatible = "m25p80"; - #address-cells = <1>; - #size-cells = <1>; - spi-max-frequency = <50000000>; - reg = <0>; - - spi1_flash0@0 { - label = "spi1_flash0"; - reg = <0x0 0x100000>; - }; - }; -}; - -&uart0 { - status = "okay"; -}; - -&usb0 { - status = "okay"; -}; - -&dwc3_0 { - status = "okay"; - dr_mode = "peripheral"; - maximum-speed = "high-speed"; -}; - -&usb1 { - status = "okay"; -}; - -&dwc3_1 { - status = "okay"; - dr_mode = "host"; - maximum-speed = "high-speed"; -}; - -&watchdog0 { - status = "okay"; -}; - -&xlnx_dp { - xlnx,max-pclock-frequency = <200000>; -}; - -&xlnx_dpdma { - xlnx,axi-clock-freq = <200000000>; -}; diff --git a/arch/arm/dts/zynqmp-zc1751-xm015-dc1.dts b/arch/arm/dts/zynqmp-zc1751-xm015-dc1.dts index 04d82c4d2e..9062ffe919 100644 --- a/arch/arm/dts/zynqmp-zc1751-xm015-dc1.dts +++ b/arch/arm/dts/zynqmp-zc1751-xm015-dc1.dts @@ -11,7 +11,7 @@ /dts-v1/; #include "zynqmp.dtsi" -#include "zynqmp-clk.dtsi" +#include "zynqmp-clk-ccf.dtsi" / { model = "ZynqMP zc1751-xm015-dc1 RevA"; diff --git a/arch/arm/dts/zynqmp-zc1751-xm016-dc2.dts b/arch/arm/dts/zynqmp-zc1751-xm016-dc2.dts index 7dfe960135..bf43bf8748 100644 --- a/arch/arm/dts/zynqmp-zc1751-xm016-dc2.dts +++ b/arch/arm/dts/zynqmp-zc1751-xm016-dc2.dts @@ -11,7 +11,7 @@ /dts-v1/; #include "zynqmp.dtsi" -#include "zynqmp-clk.dtsi" +#include "zynqmp-clk-ccf.dtsi" / { model = "ZynqMP zc1751-xm016-dc2 RevA"; diff --git a/arch/arm/dts/zynqmp-zc1751-xm018-dc4.dts b/arch/arm/dts/zynqmp-zc1751-xm018-dc4.dts index 648e3ba799..39c82c592f 100644 --- a/arch/arm/dts/zynqmp-zc1751-xm018-dc4.dts +++ b/arch/arm/dts/zynqmp-zc1751-xm018-dc4.dts @@ -11,7 +11,7 @@ /dts-v1/; #include "zynqmp.dtsi" -#include "zynqmp-clk.dtsi" +#include "zynqmp-clk-ccf.dtsi" / { model = "ZynqMP zc1751-xm018-dc4"; diff --git a/arch/arm/dts/zynqmp-zc1751-xm019-dc5.dts b/arch/arm/dts/zynqmp-zc1751-xm019-dc5.dts index f3020a5760..c774b866fb 100644 --- a/arch/arm/dts/zynqmp-zc1751-xm019-dc5.dts +++ b/arch/arm/dts/zynqmp-zc1751-xm019-dc5.dts @@ -12,7 +12,7 @@ /dts-v1/; #include "zynqmp.dtsi" -#include "zynqmp-clk.dtsi" +#include "zynqmp-clk-ccf.dtsi" / { model = "ZynqMP zc1751-xm019-dc5 RevA"; compatible = "xlnx,zynqmp-zc1751", "xlnx,zynqmp"; diff --git a/arch/arm/dts/zynqmp-zcu102-revA.dts b/arch/arm/dts/zynqmp-zcu102-revA.dts index 64a883b96e..2be6eb0eb5 100644 --- a/arch/arm/dts/zynqmp-zcu102-revA.dts +++ b/arch/arm/dts/zynqmp-zcu102-revA.dts @@ -11,7 +11,7 @@ /dts-v1/; #include "zynqmp.dtsi" -#include "zynqmp-clk.dtsi" +#include "zynqmp-clk-ccf.dtsi" #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/pinctrl/pinctrl-zynqmp.h> #include <dt-bindings/phy/phy.h> diff --git a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h index 1ff5cac344..af68af471e 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h @@ -82,6 +82,11 @@ #define QSPI0_BASE_ADDR (CONFIG_SYS_IMMR + 0x00550000) #define DSPI1_BASE_ADDR (CONFIG_SYS_IMMR + 0x01100000) +#define GPIO1_BASE_ADDR (CONFIG_SYS_IMMR + 0x1300000) +#define GPIO2_BASE_ADDR (CONFIG_SYS_IMMR + 0x1310000) +#define GPIO3_BASE_ADDR (CONFIG_SYS_IMMR + 0x1320000) +#define GPIO4_BASE_ADDR (CONFIG_SYS_IMMR + 0x1330000) + #define LPUART_BASE (CONFIG_SYS_IMMR + 0x01950000) #define AHCI_BASE_ADDR (CONFIG_SYS_IMMR + 0x02200000) @@ -200,6 +205,8 @@ struct sys_info { /* Device Configuration and Pin Control */ #define DCFG_DCSR_PORCR1 0x0 +#define DCFG_DCSR_ECCCR2 0x524 +#define DISABLE_PFE_ECC BIT(13) struct ccsr_gur { u32 porsr1; /* POR status 1 */ @@ -390,6 +397,29 @@ struct ccsr_gur { #define SCFG_SNPCNFGCR_SATARDSNP 0x00800000 #define SCFG_SNPCNFGCR_SATAWRSNP 0x00400000 +/* RGMIIPCR bit definitions*/ +#define SCFG_RGMIIPCR_EN_AUTO BIT(3) +#define SCFG_RGMIIPCR_SETSP_1000M BIT(2) +#define SCFG_RGMIIPCR_SETSP_100M 0 +#define SCFG_RGMIIPCR_SETSP_10M BIT(1) +#define SCFG_RGMIIPCR_SETFD BIT(0) + +/* PFEASBCR bit definitions */ +#define SCFG_PFEASBCR_ARCACHE0 BIT(31) +#define SCFG_PFEASBCR_AWCACHE0 BIT(30) +#define SCFG_PFEASBCR_ARCACHE1 BIT(29) +#define SCFG_PFEASBCR_AWCACHE1 BIT(28) +#define SCFG_PFEASBCR_ARSNP BIT(27) +#define SCFG_PFEASBCR_AWSNP BIT(26) + +/* WR_QoS1 PFE bit definitions */ +#define SCFG_WR_QOS1_PFE1_QOS GENMASK(27, 24) +#define SCFG_WR_QOS1_PFE2_QOS GENMASK(23, 20) + +/* RD_QoS1 PFE bit definitions */ +#define SCFG_RD_QOS1_PFE1_QOS GENMASK(27, 24) +#define SCFG_RD_QOS1_PFE2_QOS GENMASK(23, 20) + /* Supplemental Configuration Unit */ struct ccsr_scfg { u8 res_000[0x100-0x000]; @@ -407,7 +437,12 @@ struct ccsr_scfg { u8 res_140[0x158-0x140]; u32 altcbar; u32 qspi_cfg; - u8 res_160[0x180-0x160]; + u8 res_160[0x164 - 0x160]; + u32 wr_qos1; + u32 wr_qos2; + u32 rd_qos1; + u32 rd_qos2; + u8 res_174[0x180 - 0x174]; u32 dmamcr; u8 res_184[0x188-0x184]; u32 gic_align; @@ -438,7 +473,21 @@ struct ccsr_scfg { u32 usb_refclk_selcr1; u32 usb_refclk_selcr2; u32 usb_refclk_selcr3; - u8 res_424[0x600-0x424]; + u8 res_424[0x434 - 0x424]; + u32 rgmiipcr; + u32 res_438; + u32 rgmiipsr; + u32 pfepfcssr1; + u32 pfeintencr1; + u32 pfepfcssr2; + u32 pfeintencr2; + u32 pfeerrcr; + u32 pfeeerrintencr; + u32 pfeasbcr; + u32 pfebsbcr; + u8 res_460[0x484 - 0x460]; + u32 mdioselcr; + u8 res_468[0x600 - 0x488]; u32 scratchrw[4]; u8 res_610[0x680-0x610]; u32 corebcr; @@ -591,6 +640,16 @@ struct ccsr_serdes { u8 res_19a0[0x2000-0x19a0]; /* from 0x19a0 to 0x1fff */ }; +struct ccsr_gpio { + u32 gpdir; + u32 gpodr; + u32 gpdat; + u32 gpier; + u32 gpimr; + u32 gpicr; + u32 gpibe; +}; + /* MMU 500 */ #define SMMU_SCR0 (SMMU_BASE + 0x0) #define SMMU_SCR1 (SMMU_BASE + 0x4) diff --git a/arch/arm/include/asm/arch-fsl-layerscape/ns_access.h b/arch/arm/include/asm/arch-fsl-layerscape/ns_access.h index f46f1d866a..fe97a930e5 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/ns_access.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/ns_access.h @@ -26,6 +26,7 @@ enum csu_cslx_ind { CSU_CSLX_PCIE3_IO, CSU_CSLX_USB3 = 20, CSU_CSLX_USB2, + CSU_CSLX_PFE = 23, CSU_CSLX_SERDES = 32, CSU_CSLX_QDMA, CSU_CSLX_LPUART2, @@ -105,6 +106,7 @@ static struct csu_ns_dev ns_dev[] = { {CSU_CSLX_PCIE3_IO, CSU_ALL_RW}, {CSU_CSLX_USB3, CSU_ALL_RW}, {CSU_CSLX_USB2, CSU_ALL_RW}, + {CSU_CSLX_PFE, CSU_ALL_RW}, {CSU_CSLX_SERDES, CSU_ALL_RW}, {CSU_CSLX_QDMA, CSU_ALL_RW}, {CSU_CSLX_LPUART2, CSU_ALL_RW}, diff --git a/arch/arm/include/asm/arch-fsl-layerscape/soc.h b/arch/arm/include/asm/arch-fsl-layerscape/soc.h index cb760b5b38..d9bfddb23b 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/soc.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/soc.h @@ -127,6 +127,9 @@ void fsl_lsch2_early_init_f(void); int setup_chip_volt(void); /* Setup core vdd in unit mV */ int board_setup_core_volt(u32 vdd); +#ifdef CONFIG_FSL_PFE +void init_pfe_scfg_dcfg_regs(void); +#endif #endif void cpu_name(char *name); diff --git a/arch/arm/include/asm/arch-zynqmp/sys_proto.h b/arch/arm/include/asm/arch-zynqmp/sys_proto.h index 084d55a2b0..ad3dc9aba5 100644 --- a/arch/arm/include/asm/arch-zynqmp/sys_proto.h +++ b/arch/arm/include/asm/arch-zynqmp/sys_proto.h @@ -11,6 +11,8 @@ #define PAYLOAD_ARG_CNT 5 #define ZYNQMP_CSU_SILICON_VER_MASK 0xF +#define ZYNQMP_SIP_SVC_PM_SECURE_IMG_LOAD 0xC200002D +#define KEY_PTR_LEN 32 enum { IDCODE, diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 30752839a3..5e7baba3fe 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -58,6 +58,7 @@ config SOC_DA850 config SOC_DA8XX bool select SYS_DA850_PLL_INIT if SUPPORT_SPL || DA850_LOWLEVEL + select SYS_DA850_DDR_INIT if SUPPORT_SPL || DA850_LOWLEVEL config MACH_DAVINCI_DA850_EVM bool diff --git a/board/freescale/ls1012afrdm/Kconfig b/board/freescale/ls1012afrdm/Kconfig index 38bd91b191..22d521b6cf 100644 --- a/board/freescale/ls1012afrdm/Kconfig +++ b/board/freescale/ls1012afrdm/Kconfig @@ -12,6 +12,35 @@ config SYS_SOC config SYS_CONFIG_NAME default "ls1012afrdm" +if FSL_PFE + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select PHYLIB + imply PHY_REALTEK + +config SYS_LS_PFE_FW_ADDR + hex "Flash address of PFE firmware" + default 0x40a00000 + +config DDR_PFE_PHYS_BASEADDR + hex "PFE DDR physical base address" + default 0x03800000 + +config DDR_PFE_BASEADDR + hex "PFE DDR base address" + default 0x83800000 + +config PFE_EMAC1_PHY_ADDR + hex "PFE DDR base address" + default 0x2 + +config PFE_EMAC2_PHY_ADDR + hex "PFE DDR base address" + default 0x1 + +endif + source "board/freescale/common/Kconfig" endif diff --git a/board/freescale/ls1012afrdm/Makefile b/board/freescale/ls1012afrdm/Makefile index dbfa2cea38..1e53c96730 100644 --- a/board/freescale/ls1012afrdm/Makefile +++ b/board/freescale/ls1012afrdm/Makefile @@ -5,3 +5,4 @@ # obj-y += ls1012afrdm.o +obj-$(CONFIG_FSL_PFE) += eth.o diff --git a/board/freescale/ls1012afrdm/eth.c b/board/freescale/ls1012afrdm/eth.c new file mode 100644 index 0000000000..cc6deb2c04 --- /dev/null +++ b/board/freescale/ls1012afrdm/eth.c @@ -0,0 +1,124 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <asm/io.h> +#include <netdev.h> +#include <fm_eth.h> +#include <fsl_mdio.h> +#include <malloc.h> +#include <asm/types.h> +#include <fsl_dtsec.h> +#include <asm/arch/soc.h> +#include <asm/arch-fsl-layerscape/config.h> +#include <asm/arch-fsl-layerscape/immap_lsch2.h> +#include <asm/arch/fsl_serdes.h> +#include <net/pfe_eth/pfe_eth.h> +#include <dm/platform_data/pfe_dm_eth.h> + +#define DEFAULT_PFE_MDIO_NAME "PFE_MDIO" +#define DEFAULT_PFE_MDIO1_NAME "PFE_MDIO1" + +#define MASK_ETH_PHY_RST 0x00000100 + +static inline void ls1012afrdm_reset_phy(void) +{ + unsigned int val; + struct ccsr_gpio *pgpio = (void *)(GPIO1_BASE_ADDR); + + setbits_be32(&pgpio->gpdir, MASK_ETH_PHY_RST); + + val = in_be32(&pgpio->gpdat); + setbits_be32(&pgpio->gpdat, val & ~MASK_ETH_PHY_RST); + mdelay(10); + + val = in_be32(&pgpio->gpdat); + setbits_be32(&pgpio->gpdat, val | MASK_ETH_PHY_RST); + mdelay(50); +} + +int pfe_eth_board_init(struct udevice *dev) +{ + static int init_done; + struct mii_dev *bus; + struct pfe_mdio_info mac_mdio_info; + struct pfe_eth_dev *priv = dev_get_priv(dev); + + if (!init_done) { + ls1012afrdm_reset_phy(); + + mac_mdio_info.reg_base = (void *)EMAC1_BASE_ADDR; + mac_mdio_info.name = DEFAULT_PFE_MDIO_NAME; + + bus = pfe_mdio_init(&mac_mdio_info); + if (!bus) { + printf("Failed to register mdio\n"); + return -1; + } + + init_done = 1; + } + + if (priv->gemac_port) { + mac_mdio_info.reg_base = (void *)EMAC2_BASE_ADDR; + mac_mdio_info.name = DEFAULT_PFE_MDIO1_NAME; + bus = pfe_mdio_init(&mac_mdio_info); + if (!bus) { + printf("Failed to register mdio\n"); + return -1; + } + } + + pfe_set_mdio(priv->gemac_port, + miiphy_get_dev_by_name(DEFAULT_PFE_MDIO_NAME)); + if (!priv->gemac_port) + /* MAC1 */ + pfe_set_phy_address_mode(priv->gemac_port, + CONFIG_PFE_EMAC1_PHY_ADDR, + PHY_INTERFACE_MODE_SGMII); + else + /* MAC2 */ + pfe_set_phy_address_mode(priv->gemac_port, + CONFIG_PFE_EMAC2_PHY_ADDR, + PHY_INTERFACE_MODE_SGMII); + return 0; +} + +static struct pfe_eth_pdata pfe_pdata0 = { + .pfe_eth_pdata_mac = { + .iobase = (phys_addr_t)EMAC1_BASE_ADDR, + .phy_interface = 0, + }, + + .pfe_ddr_addr = { + .ddr_pfe_baseaddr = (void *)CONFIG_DDR_PFE_BASEADDR, + .ddr_pfe_phys_baseaddr = CONFIG_DDR_PFE_PHYS_BASEADDR, + }, +}; + +static struct pfe_eth_pdata pfe_pdata1 = { + .pfe_eth_pdata_mac = { + .iobase = (phys_addr_t)EMAC2_BASE_ADDR, + .phy_interface = 1, + }, + + .pfe_ddr_addr = { + .ddr_pfe_baseaddr = (void *)CONFIG_DDR_PFE_BASEADDR, + .ddr_pfe_phys_baseaddr = CONFIG_DDR_PFE_PHYS_BASEADDR, + }, +}; + +U_BOOT_DEVICE(ls1012a_pfe0) = { + .name = "pfe_eth", + .platdata = &pfe_pdata0, +}; + +U_BOOT_DEVICE(ls1012a_pfe1) = { + .name = "pfe_eth", + .platdata = &pfe_pdata1, +}; diff --git a/board/freescale/ls1012afrdm/ls1012afrdm.c b/board/freescale/ls1012afrdm/ls1012afrdm.c index 9afd1c469e..0145886e67 100644 --- a/board/freescale/ls1012afrdm/ls1012afrdm.c +++ b/board/freescale/ls1012afrdm/ls1012afrdm.c @@ -57,11 +57,6 @@ int dram_init(void) return 0; } -int board_eth_init(bd_t *bis) -{ - return pci_eth_init(bis); -} - int board_early_init_f(void) { fsl_lsch2_early_init_f(); diff --git a/board/freescale/ls1012aqds/Kconfig b/board/freescale/ls1012aqds/Kconfig index fc9250b253..c0b12ed78f 100644 --- a/board/freescale/ls1012aqds/Kconfig +++ b/board/freescale/ls1012aqds/Kconfig @@ -12,6 +12,51 @@ config SYS_SOC config SYS_CONFIG_NAME default "ls1012aqds" + +if FSL_PFE + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select PHYLIB + imply PHY_VITESSE + imply PHY_REALTEK + imply PHY_AQUANTIA + imply PHYLIB_10G + +config PFE_RGMII_RESET_WA + def_bool y + +config SYS_LS_PFE_FW_ADDR + hex "Flash address of PFE firmware" + default 0x40a00000 + +config DDR_PFE_PHYS_BASEADDR + hex "PFE DDR physical base address" + default 0x03800000 + +config DDR_PFE_BASEADDR + hex "PFE DDR base address" + default 0x83800000 + +config PFE_EMAC1_PHY_ADDR + hex "PFE DDR base address" + default 0x1e + +config PFE_EMAC2_PHY_ADDR + hex "PFE DDR base address" + default 0x1 + +config PFE_SGMII_2500_PHY1_ADDR + hex "PFE DDR base address" + default 0x1 + +config PFE_SGMII_2500_PHY2_ADDR + hex "PFE DDR base address" + default 0x2 + +endif + + source "board/freescale/common/Kconfig" endif diff --git a/board/freescale/ls1012aqds/Makefile b/board/freescale/ls1012aqds/Makefile index 0b813f9784..5aba9caf92 100644 --- a/board/freescale/ls1012aqds/Makefile +++ b/board/freescale/ls1012aqds/Makefile @@ -5,3 +5,4 @@ # obj-y += ls1012aqds.o +obj-$(CONFIG_FSL_PFE) += eth.o diff --git a/board/freescale/ls1012aqds/eth.c b/board/freescale/ls1012aqds/eth.c new file mode 100644 index 0000000000..f8026a21a1 --- /dev/null +++ b/board/freescale/ls1012aqds/eth.c @@ -0,0 +1,309 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <asm/io.h> +#include <netdev.h> +#include <fm_eth.h> +#include <fsl_mdio.h> +#include <malloc.h> +#include <asm/types.h> +#include <fsl_dtsec.h> +#include <asm/arch/soc.h> +#include <asm/arch-fsl-layerscape/config.h> +#include <asm/arch-fsl-layerscape/immap_lsch2.h> +#include <asm/arch/fsl_serdes.h> +#include "../common/qixis.h" +#include <net/pfe_eth/pfe_eth.h> +#include <dm/platform_data/pfe_dm_eth.h> +#include "ls1012aqds_qixis.h" + +#define EMI_NONE 0xFF +#define EMI1_RGMII 1 +#define EMI1_SLOT1 2 +#define EMI1_SLOT2 3 + +#define DEFAULT_PFE_MDIO_NAME "PFE_MDIO" +#define DEFAULT_PFE_MDIO1_NAME "PFE_MDIO1" + +static const char * const mdio_names[] = { + "NULL", + "LS1012AQDS_MDIO_RGMII", + "LS1012AQDS_MDIO_SLOT1", + "LS1012AQDS_MDIO_SLOT2", + "NULL", +}; + +static const char *ls1012aqds_mdio_name_for_muxval(u8 muxval) +{ + return mdio_names[muxval]; +} + +struct ls1012aqds_mdio { + u8 muxval; + struct mii_dev *realbus; +}; + +static void ls1012aqds_mux_mdio(u8 muxval) +{ + u8 brdcfg4; + + if (muxval < 7) { + brdcfg4 = QIXIS_READ(brdcfg[4]); + brdcfg4 &= ~BRDCFG4_EMISEL_MASK; + brdcfg4 |= (muxval << BRDCFG4_EMISEL_SHIFT); + QIXIS_WRITE(brdcfg[4], brdcfg4); + } +} + +static int ls1012aqds_mdio_read(struct mii_dev *bus, int addr, int devad, + int regnum) +{ + struct ls1012aqds_mdio *priv = bus->priv; + + ls1012aqds_mux_mdio(priv->muxval); + + return priv->realbus->read(priv->realbus, addr, devad, regnum); +} + +static int ls1012aqds_mdio_write(struct mii_dev *bus, int addr, int devad, + int regnum, u16 value) +{ + struct ls1012aqds_mdio *priv = bus->priv; + + ls1012aqds_mux_mdio(priv->muxval); + + return priv->realbus->write(priv->realbus, addr, devad, regnum, value); +} + +static int ls1012aqds_mdio_reset(struct mii_dev *bus) +{ + struct ls1012aqds_mdio *priv = bus->priv; + + if (priv->realbus->reset) + return priv->realbus->reset(priv->realbus); + else + return -1; +} + +static int ls1012aqds_mdio_init(char *realbusname, u8 muxval) +{ + struct ls1012aqds_mdio *pmdio; + struct mii_dev *bus = mdio_alloc(); + + if (!bus) { + printf("Failed to allocate ls1012aqds MDIO bus\n"); + return -1; + } + + pmdio = malloc(sizeof(*pmdio)); + if (!pmdio) { + printf("Failed to allocate ls1012aqds private data\n"); + free(bus); + return -1; + } + + bus->read = ls1012aqds_mdio_read; + bus->write = ls1012aqds_mdio_write; + bus->reset = ls1012aqds_mdio_reset; + sprintf(bus->name, ls1012aqds_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); +} + +int pfe_eth_board_init(struct udevice *dev) +{ + static int init_done; + struct mii_dev *bus; + static const char *mdio_name; + struct pfe_mdio_info mac_mdio_info; + struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; + u8 data8; + struct pfe_eth_dev *priv = dev_get_priv(dev); + + int srds_s1 = in_be32(&gur->rcwsr[4]) & + FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK; + srds_s1 >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT; + + ls1012aqds_mux_mdio(EMI1_SLOT1); + + if (!init_done) { + mac_mdio_info.reg_base = (void *)EMAC1_BASE_ADDR; + mac_mdio_info.name = DEFAULT_PFE_MDIO_NAME; + + bus = pfe_mdio_init(&mac_mdio_info); + if (!bus) { + printf("Failed to register mdio\n"); + return -1; + } + init_done = 1; + } + + if (priv->gemac_port) { + mac_mdio_info.reg_base = (void *)EMAC2_BASE_ADDR; + mac_mdio_info.name = DEFAULT_PFE_MDIO1_NAME; + + bus = pfe_mdio_init(&mac_mdio_info); + if (!bus) { + printf("Failed to register mdio\n"); + return -1; + } + } + + switch (srds_s1) { + case 0x3508: + printf("ls1012aqds:supported SerDes PRCTL= %d\n", srds_s1); +#ifdef CONFIG_PFE_RGMII_RESET_WA + /* + * Work around for FPGA registers initialization + * This is needed for RGMII to work. + */ + printf("Reset RGMII WA....\n"); + data8 = QIXIS_READ(rst_frc[0]); + data8 |= 0x2; + QIXIS_WRITE(rst_frc[0], data8); + data8 = QIXIS_READ(rst_frc[0]); + + data8 = QIXIS_READ(res8[6]); + data8 |= 0xff; + QIXIS_WRITE(res8[6], data8); + data8 = QIXIS_READ(res8[6]); +#endif + if (priv->gemac_port) { + mdio_name = ls1012aqds_mdio_name_for_muxval(EMI1_RGMII); + if (ls1012aqds_mdio_init(DEFAULT_PFE_MDIO_NAME, EMI1_RGMII) + < 0) { + printf("Failed to register mdio for %s\n", mdio_name); + } + + /* MAC2 */ + mdio_name = ls1012aqds_mdio_name_for_muxval(EMI1_RGMII); + bus = miiphy_get_dev_by_name(mdio_name); + pfe_set_mdio(priv->gemac_port, bus); + pfe_set_phy_address_mode(priv->gemac_port, + CONFIG_PFE_EMAC2_PHY_ADDR, + PHY_INTERFACE_MODE_RGMII); + + } else { + mdio_name = ls1012aqds_mdio_name_for_muxval(EMI1_SLOT1); + if (ls1012aqds_mdio_init(DEFAULT_PFE_MDIO_NAME, EMI1_SLOT1) + < 0) { + printf("Failed to register mdio for %s\n", mdio_name); + } + + /* MAC1 */ + mdio_name = ls1012aqds_mdio_name_for_muxval(EMI1_SLOT1); + bus = miiphy_get_dev_by_name(mdio_name); + pfe_set_mdio(priv->gemac_port, bus); + pfe_set_phy_address_mode(priv->gemac_port, + CONFIG_PFE_EMAC1_PHY_ADDR, + PHY_INTERFACE_MODE_SGMII); + } + + break; + + case 0x2205: + printf("ls1012aqds:supported SerDes PRCTL= %d\n", srds_s1); + /* + * Work around for FPGA registers initialization + * This is needed for RGMII to work. + */ + printf("Reset SLOT1 SLOT2....\n"); + data8 = QIXIS_READ(rst_frc[2]); + data8 |= 0xc0; + QIXIS_WRITE(rst_frc[2], data8); + mdelay(100); + data8 = QIXIS_READ(rst_frc[2]); + data8 &= 0x3f; + QIXIS_WRITE(rst_frc[2], data8); + + if (priv->gemac_port) { + mdio_name = ls1012aqds_mdio_name_for_muxval(EMI1_SLOT2); + if (ls1012aqds_mdio_init(DEFAULT_PFE_MDIO_NAME, EMI1_SLOT2) + < 0) { + printf("Failed to register mdio for %s\n", mdio_name); + } + /* MAC2 */ + mdio_name = ls1012aqds_mdio_name_for_muxval(EMI1_SLOT2); + bus = miiphy_get_dev_by_name(mdio_name); + pfe_set_mdio(1, bus); + pfe_set_phy_address_mode(1, CONFIG_PFE_SGMII_2500_PHY2_ADDR, + PHY_INTERFACE_MODE_SGMII_2500); + + data8 = QIXIS_READ(brdcfg[12]); + data8 |= 0x20; + QIXIS_WRITE(brdcfg[12], data8); + + } else { + mdio_name = ls1012aqds_mdio_name_for_muxval(EMI1_SLOT1); + if (ls1012aqds_mdio_init(DEFAULT_PFE_MDIO_NAME, EMI1_SLOT1) + < 0) { + printf("Failed to register mdio for %s\n", mdio_name); + } + + /* MAC1 */ + mdio_name = ls1012aqds_mdio_name_for_muxval(EMI1_SLOT1); + bus = miiphy_get_dev_by_name(mdio_name); + pfe_set_mdio(0, bus); + pfe_set_phy_address_mode(0, + CONFIG_PFE_SGMII_2500_PHY1_ADDR, + PHY_INTERFACE_MODE_SGMII_2500); + } + break; + + default: + printf("ls1012aqds:unsupported SerDes PRCTL= %d\n", srds_s1); + break; + } + return 0; +} + +static struct pfe_eth_pdata pfe_pdata0 = { + .pfe_eth_pdata_mac = { + .iobase = (phys_addr_t)EMAC1_BASE_ADDR, + .phy_interface = 0, + }, + + .pfe_ddr_addr = { + .ddr_pfe_baseaddr = (void *)CONFIG_DDR_PFE_BASEADDR, + .ddr_pfe_phys_baseaddr = CONFIG_DDR_PFE_PHYS_BASEADDR, + }, +}; + +static struct pfe_eth_pdata pfe_pdata1 = { + .pfe_eth_pdata_mac = { + .iobase = (phys_addr_t)EMAC2_BASE_ADDR, + .phy_interface = 1, + }, + + .pfe_ddr_addr = { + .ddr_pfe_baseaddr = (void *)CONFIG_DDR_PFE_BASEADDR, + .ddr_pfe_phys_baseaddr = CONFIG_DDR_PFE_PHYS_BASEADDR, + }, +}; + +U_BOOT_DEVICE(ls1012a_pfe0) = { + .name = "pfe_eth", + .platdata = &pfe_pdata0, +}; + +U_BOOT_DEVICE(ls1012a_pfe1) = { + .name = "pfe_eth", + .platdata = &pfe_pdata1, +}; diff --git a/board/freescale/ls1012aqds/ls1012aqds.c b/board/freescale/ls1012aqds/ls1012aqds.c index 406194da27..4577917e8d 100644 --- a/board/freescale/ls1012aqds/ls1012aqds.c +++ b/board/freescale/ls1012aqds/ls1012aqds.c @@ -25,9 +25,9 @@ #include <fsl_mmdc.h> #include <spl.h> #include <netdev.h> - #include "../common/qixis.h" #include "ls1012aqds_qixis.h" +#include "ls1012aqds_pfe.h" DECLARE_GLOBAL_DATA_PTR; @@ -128,11 +128,6 @@ int board_init(void) return 0; } -int board_eth_init(bd_t *bis) -{ - return pci_eth_init(bis); -} - int esdhc_status_fixup(void *blob, const char *compat) { char esdhc0_path[] = "/soc/esdhc@1560000"; @@ -161,12 +156,102 @@ int esdhc_status_fixup(void *blob, const char *compat) return 0; } +static int pfe_set_properties(void *set_blob, struct pfe_prop_val prop_val, + char *enet_path, char *mdio_path) +{ + do_fixup_by_path(set_blob, enet_path, "fsl,gemac-bus-id", + &prop_val.busid, PFE_PROP_LEN, 1); + do_fixup_by_path(set_blob, enet_path, "fsl,gemac-phy-id", + &prop_val.phyid, PFE_PROP_LEN, 1); + do_fixup_by_path(set_blob, enet_path, "fsl,mdio-mux-val", + &prop_val.mux_val, PFE_PROP_LEN, 1); + do_fixup_by_path(set_blob, enet_path, "phy-mode", + prop_val.phy_mode, strlen(prop_val.phy_mode) + 1, 1); + do_fixup_by_path(set_blob, mdio_path, "fsl,mdio-phy-mask", + &prop_val.phy_mask, PFE_PROP_LEN, 1); + return 0; +} + +static void fdt_fsl_fixup_of_pfe(void *blob) +{ + int i = 0; + struct pfe_prop_val prop_val; + void *l_blob = blob; + + struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; + unsigned int srds_s1 = in_be32(&gur->rcwsr[4]) & + FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK; + srds_s1 >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT; + + for (i = 0; i < NUM_ETH_NODE; i++) { + switch (srds_s1) { + case SERDES_1_G_PROTOCOL: + if (i == 0) { + prop_val.busid = cpu_to_fdt32( + ETH_1_1G_BUS_ID); + prop_val.phyid = cpu_to_fdt32( + ETH_1_1G_PHY_ID); + prop_val.mux_val = cpu_to_fdt32( + ETH_1_1G_MDIO_MUX); + prop_val.phy_mask = cpu_to_fdt32( + ETH_1G_MDIO_PHY_MASK); + prop_val.phy_mode = "sgmii"; + pfe_set_properties(l_blob, prop_val, ETH_1_PATH, + ETH_1_MDIO); + } else { + prop_val.busid = cpu_to_fdt32( + ETH_2_1G_BUS_ID); + prop_val.phyid = cpu_to_fdt32( + ETH_2_1G_PHY_ID); + prop_val.mux_val = cpu_to_fdt32( + ETH_2_1G_MDIO_MUX); + prop_val.phy_mask = cpu_to_fdt32( + ETH_1G_MDIO_PHY_MASK); + prop_val.phy_mode = "rgmii"; + pfe_set_properties(l_blob, prop_val, ETH_2_PATH, + ETH_2_MDIO); + } + break; + case SERDES_2_5_G_PROTOCOL: + if (i == 0) { + prop_val.busid = cpu_to_fdt32( + ETH_1_2_5G_BUS_ID); + prop_val.phyid = cpu_to_fdt32( + ETH_1_2_5G_PHY_ID); + prop_val.mux_val = cpu_to_fdt32( + ETH_1_2_5G_MDIO_MUX); + prop_val.phy_mask = cpu_to_fdt32( + ETH_2_5G_MDIO_PHY_MASK); + prop_val.phy_mode = "sgmii-2500"; + pfe_set_properties(l_blob, prop_val, ETH_1_PATH, + ETH_1_MDIO); + } else { + prop_val.busid = cpu_to_fdt32( + ETH_2_2_5G_BUS_ID); + prop_val.phyid = cpu_to_fdt32( + ETH_2_2_5G_PHY_ID); + prop_val.mux_val = cpu_to_fdt32( + ETH_2_2_5G_MDIO_MUX); + prop_val.phy_mask = cpu_to_fdt32( + ETH_2_5G_MDIO_PHY_MASK); + prop_val.phy_mode = "sgmii-2500"; + pfe_set_properties(l_blob, prop_val, ETH_2_PATH, + ETH_2_MDIO); + } + break; + default: + printf("serdes:[%d]\n", srds_s1); + } + } +} + #ifdef CONFIG_OF_BOARD_SETUP int ft_board_setup(void *blob, bd_t *bd) { arch_fixup_fdt(blob); ft_cpu_setup(blob, bd); + fdt_fsl_fixup_of_pfe(blob); return 0; } diff --git a/board/freescale/ls1012aqds/ls1012aqds_pfe.h b/board/freescale/ls1012aqds/ls1012aqds_pfe.h new file mode 100644 index 0000000000..b06f722940 --- /dev/null +++ b/board/freescale/ls1012aqds/ls1012aqds_pfe.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#define ETH_1_1G_BUS_ID 0x1 +#define ETH_1_1G_PHY_ID 0x1e +#define ETH_1_1G_MDIO_MUX 0x2 +#define ETH_1G_MDIO_PHY_MASK 0xBFFFFFFD +#define ETH_1_1G_PHY_MODE "sgmii" +#define ETH_2_1G_BUS_ID 0x1 +#define ETH_2_1G_PHY_ID 0x1 +#define ETH_2_1G_MDIO_MUX 0x1 +#define ETH_2_1G_PHY_MODE "rgmii" + +#define ETH_1_2_5G_BUS_ID 0x0 +#define ETH_1_2_5G_PHY_ID 0x1 +#define ETH_1_2_5G_MDIO_MUX 0x2 +#define ETH_2_5G_MDIO_PHY_MASK 0xFFFFFFF9 +#define ETH_2_5G_PHY_MODE "sgmii-2500" +#define ETH_2_2_5G_BUS_ID 0x1 +#define ETH_2_2_5G_PHY_ID 0x2 +#define ETH_2_2_5G_MDIO_MUX 0x3 + +#define SERDES_1_G_PROTOCOL 0x3508 +#define SERDES_2_5_G_PROTOCOL 0x2205 + +#define PFE_PROP_LEN 4 + +#define ETH_1_PATH "/pfe@04000000/ethernet@0" +#define ETH_1_MDIO ETH_1_PATH "/mdio@0" + +#define ETH_2_PATH "/pfe@04000000/ethernet@1" +#define ETH_2_MDIO ETH_2_PATH "/mdio@0" + +#define NUM_ETH_NODE 2 + +struct pfe_prop_val { + int busid; + int phyid; + int mux_val; + int phy_mask; + char *phy_mode; +}; diff --git a/board/freescale/ls1012aqds/ls1012aqds_qixis.h b/board/freescale/ls1012aqds/ls1012aqds_qixis.h index 584f604aa8..7a1ba3d938 100644 --- a/board/freescale/ls1012aqds/ls1012aqds_qixis.h +++ b/board/freescale/ls1012aqds/ls1012aqds_qixis.h @@ -11,7 +11,7 @@ /* BRDCFG4[4:7] select EC1 and EC2 as a pair */ #define BRDCFG4_EMISEL_MASK 0xe0 -#define BRDCFG4_EMISEL_SHIFT 5 +#define BRDCFG4_EMISEL_SHIFT 6 /* SYSCLK */ #define QIXIS_SYSCLK_66 0x0 diff --git a/board/freescale/ls1012ardb/Kconfig b/board/freescale/ls1012ardb/Kconfig index d13b08ebe5..493d4779bc 100644 --- a/board/freescale/ls1012ardb/Kconfig +++ b/board/freescale/ls1012ardb/Kconfig @@ -12,6 +12,35 @@ config SYS_SOC config SYS_CONFIG_NAME default "ls1012ardb" +if FSL_PFE + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select PHYLIB + imply PHY_REALTEK + +config SYS_LS_PFE_FW_ADDR + hex "Flash address of PFE firmware" + default 0x40a00000 + +config DDR_PFE_PHYS_BASEADDR + hex "PFE DDR physical base address" + default 0x03800000 + +config DDR_PFE_BASEADDR + hex "PFE DDR base address" + default 0x83800000 + +config PFE_EMAC1_PHY_ADDR + hex "PFE DDR base address" + default 0x2 + +config PFE_EMAC2_PHY_ADDR + hex "PFE DDR base address" + default 0x1 + +endif + source "board/freescale/common/Kconfig" endif @@ -30,6 +59,36 @@ config SYS_SOC config SYS_CONFIG_NAME default "ls1012a2g5rdb" +if FSL_PFE + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select PHYLIB + imply CONFIG_PHYLIB_10G + imply CONFIG_PHY_AQUANTIA + +config SYS_LS_PFE_FW_ADDR + hex "Flash address of PFE firmware" + default 0x40a00000 + +config DDR_PFE_PHYS_BASEADDR + hex "PFE DDR physical base address" + default 0x03800000 + +config DDR_PFE_BASEADDR + hex "PFE DDR base address" + default 0x83800000 + +config PFE_EMAC1_PHY_ADDR + hex "PFE DDR base address" + default 0x2 + +config PFE_EMAC2_PHY_ADDR + hex "PFE DDR base address" + default 0x1 + +endif + source "board/freescale/common/Kconfig" endif diff --git a/board/freescale/ls1012ardb/Makefile b/board/freescale/ls1012ardb/Makefile index 05fa9d9c5b..70c7b33273 100644 --- a/board/freescale/ls1012ardb/Makefile +++ b/board/freescale/ls1012ardb/Makefile @@ -5,3 +5,4 @@ # obj-y += ls1012ardb.o +obj-$(CONFIG_FSL_PFE) += eth.o diff --git a/board/freescale/ls1012ardb/eth.c b/board/freescale/ls1012ardb/eth.c new file mode 100644 index 0000000000..8e6cd0ac3b --- /dev/null +++ b/board/freescale/ls1012ardb/eth.c @@ -0,0 +1,135 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier:GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <asm/io.h> +#include <netdev.h> +#include <fm_eth.h> +#include <fsl_mdio.h> +#include <malloc.h> +#include <asm/types.h> +#include <fsl_dtsec.h> +#include <asm/arch/soc.h> +#include <asm/arch-fsl-layerscape/config.h> +#include <asm/arch-fsl-layerscape/immap_lsch2.h> +#include <asm/arch/fsl_serdes.h> +#include <net/pfe_eth/pfe_eth.h> +#include <dm/platform_data/pfe_dm_eth.h> +#include <i2c.h> + +#define DEFAULT_PFE_MDIO_NAME "PFE_MDIO" + +static inline void ls1012ardb_reset_phy(void) +{ +#ifdef CONFIG_TARGET_LS1012ARDB + /* Through reset IO expander reset both RGMII and SGMII PHYs */ + i2c_reg_write(I2C_MUX_IO2_ADDR, 6, __PHY_MASK); + i2c_reg_write(I2C_MUX_IO2_ADDR, 2, __PHY_ETH2_MASK); + mdelay(10); + i2c_reg_write(I2C_MUX_IO2_ADDR, 2, __PHY_ETH1_MASK); + mdelay(10); + i2c_reg_write(I2C_MUX_IO2_ADDR, 2, 0xFF); + mdelay(50); +#endif +} + +int pfe_eth_board_init(struct udevice *dev) +{ + static int init_done; + struct mii_dev *bus; + struct pfe_mdio_info mac_mdio_info; + struct pfe_eth_dev *priv = dev_get_priv(dev); + struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; + + int srds_s1 = in_be32(&gur->rcwsr[4]) & + FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK; + srds_s1 >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT; + + if (!init_done) { + ls1012ardb_reset_phy(); + mac_mdio_info.reg_base = (void *)EMAC1_BASE_ADDR; + mac_mdio_info.name = DEFAULT_PFE_MDIO_NAME; + + bus = pfe_mdio_init(&mac_mdio_info); + if (!bus) { + printf("Failed to register mdio\n"); + return -1; + } + init_done = 1; + } + + pfe_set_mdio(priv->gemac_port, + miiphy_get_dev_by_name(DEFAULT_PFE_MDIO_NAME)); + + switch (srds_s1) { + case 0x3508: + if (!priv->gemac_port) { + /* MAC1 */ + pfe_set_phy_address_mode(priv->gemac_port, + CONFIG_PFE_EMAC1_PHY_ADDR, + PHY_INTERFACE_MODE_SGMII); + } else { + /* MAC2 */ + pfe_set_phy_address_mode(priv->gemac_port, + CONFIG_PFE_EMAC2_PHY_ADDR, + PHY_INTERFACE_MODE_RGMII_TXID); + } + break; + case 0x2208: + if (!priv->gemac_port) { + /* MAC1 */ + pfe_set_phy_address_mode(priv->gemac_port, + CONFIG_PFE_EMAC1_PHY_ADDR, + PHY_INTERFACE_MODE_SGMII_2500); + } else { + /* MAC2 */ + pfe_set_phy_address_mode(priv->gemac_port, + CONFIG_PFE_EMAC2_PHY_ADDR, + PHY_INTERFACE_MODE_SGMII_2500); + } + break; + default: + printf("unsupported SerDes PRCTL= %d\n", srds_s1); + break; + } + return 0; +} + +static struct pfe_eth_pdata pfe_pdata0 = { + .pfe_eth_pdata_mac = { + .iobase = (phys_addr_t)EMAC1_BASE_ADDR, + .phy_interface = 0, + }, + + .pfe_ddr_addr = { + .ddr_pfe_baseaddr = (void *)CONFIG_DDR_PFE_BASEADDR, + .ddr_pfe_phys_baseaddr = CONFIG_DDR_PFE_PHYS_BASEADDR, + }, +}; + +static struct pfe_eth_pdata pfe_pdata1 = { + .pfe_eth_pdata_mac = { + .iobase = (phys_addr_t)EMAC2_BASE_ADDR, + .phy_interface = 1, + }, + + .pfe_ddr_addr = { + .ddr_pfe_baseaddr = (void *)CONFIG_DDR_PFE_BASEADDR, + .ddr_pfe_phys_baseaddr = CONFIG_DDR_PFE_PHYS_BASEADDR, + }, +}; + +U_BOOT_DEVICE(ls1012a_pfe0) = { + .name = "pfe_eth", + .platdata = &pfe_pdata0, +}; + +U_BOOT_DEVICE(ls1012a_pfe1) = { + .name = "pfe_eth", + .platdata = &pfe_pdata1, +}; diff --git a/board/freescale/ls1012ardb/ls1012ardb.c b/board/freescale/ls1012ardb/ls1012ardb.c index c9557bb262..ed5a8e6fc2 100644 --- a/board/freescale/ls1012ardb/ls1012ardb.c +++ b/board/freescale/ls1012ardb/ls1012ardb.c @@ -114,10 +114,6 @@ int dram_init(void) return 0; } -int board_eth_init(bd_t *bis) -{ - return pci_eth_init(bis); -} int board_early_init_f(void) { diff --git a/board/synopsys/axs10x/axs10x.c b/board/synopsys/axs10x/axs10x.c index e6b69da3da..18f7666b15 100644 --- a/board/synopsys/axs10x/axs10x.c +++ b/board/synopsys/axs10x/axs10x.c @@ -47,6 +47,18 @@ int board_early_init_f(void) } #ifdef CONFIG_ISA_ARCV2 + +void board_jump_and_run(ulong entry, int zero, int arch, uint params) +{ + void (*kernel_entry)(int zero, int arch, uint params); + + kernel_entry = (void (*)(int, int, uint))entry; + + smp_set_core_boot_addr(entry, -1); + smp_kick_all_cpus(); + kernel_entry(zero, arch, params); +} + #define RESET_VECTOR_ADDR 0x0 void smp_set_core_boot_addr(unsigned long addr, int corenr) diff --git a/board/synopsys/hsdk/hsdk.c b/board/synopsys/hsdk/hsdk.c index 7641978a7b..5b3a063b69 100644 --- a/board/synopsys/hsdk/hsdk.c +++ b/board/synopsys/hsdk/hsdk.c @@ -58,6 +58,17 @@ int board_mmc_init(bd_t *bis) return 0; } +void board_jump_and_run(ulong entry, int zero, int arch, uint params) +{ + void (*kernel_entry)(int zero, int arch, uint params); + + kernel_entry = (void (*)(int, int, uint))entry; + + smp_set_core_boot_addr(entry, -1); + smp_kick_all_cpus(); + kernel_entry(zero, arch, params); +} + #define RESET_VECTOR_ADDR 0x0 void smp_set_core_boot_addr(unsigned long addr, int corenr) diff --git a/board/xilinx/zynq/MAINTAINERS b/board/xilinx/zynq/MAINTAINERS index e0dc4fed48..fc6463a8c6 100644 --- a/board/xilinx/zynq/MAINTAINERS +++ b/board/xilinx/zynq/MAINTAINERS @@ -1,6 +1,7 @@ ZYNQ BOARD M: Michal Simek <monstr@monstr.eu> S: Maintained +F: arch/arm/dts/zynq-* F: board/xilinx/zynq/ F: include/configs/zynq*.h F: configs/zynq_*_defconfig diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c index fb8eab07d7..838ac0f4c4 100644 --- a/board/xilinx/zynq/board.c +++ b/board/xilinx/zynq/board.c @@ -6,9 +6,11 @@ */ #include <common.h> +#include <dm/uclass.h> #include <fdtdec.h> #include <fpga.h> #include <mmc.h> +#include <wdt.h> #include <zynqpl.h> #include <asm/arch/hardware.h> #include <asm/arch/sys_proto.h> @@ -33,6 +35,22 @@ static xilinx_desc fpga045 = XILINX_XC7Z045_DESC(0x45); static xilinx_desc fpga100 = XILINX_XC7Z100_DESC(0x100); #endif +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT) +static struct udevice *watchdog_dev; +#endif + +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_BOARD_EARLY_INIT_F) +int board_early_init_f(void) +{ +# if defined(CONFIG_WDT) + /* bss is not cleared at time when watchdog_reset() is called */ + watchdog_dev = NULL; +# endif + + return 0; +} +#endif + int board_init(void) { #if (defined(CONFIG_FPGA) && !defined(CONFIG_SPL_BUILD)) || \ @@ -75,6 +93,15 @@ int board_init(void) } #endif +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT) + if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) { + puts("Watchdog: Not found!\n"); + } else { + wdt_start(watchdog_dev, 0, 0); + puts("Watchdog: Started\n"); + } +# endif + #if (defined(CONFIG_FPGA) && !defined(CONFIG_SPL_BUILD)) || \ (defined(CONFIG_SPL_FPGA_SUPPORT) && defined(CONFIG_SPL_BUILD)) fpga_init(); @@ -164,3 +191,25 @@ int dram_init(void) return 0; } #endif + +#if defined(CONFIG_WATCHDOG) +/* Called by macro WATCHDOG_RESET */ +void watchdog_reset(void) +{ +# if !defined(CONFIG_SPL_BUILD) + static ulong next_reset; + ulong now; + + if (!watchdog_dev) + return; + + now = timer_get_us(); + + /* Do not reset the watchdog too often */ + if (now > next_reset) { + wdt_reset(watchdog_dev); + next_reset = now + 1000; + } +# endif +} +#endif diff --git a/board/xilinx/zynqmp/Kconfig b/board/xilinx/zynqmp/Kconfig new file mode 100644 index 0000000000..7d1f7398c3 --- /dev/null +++ b/board/xilinx/zynqmp/Kconfig @@ -0,0 +1,18 @@ +# Copyright (c) 2018, Xilinx, Inc. +# +# SPDX-License-Identifier: GPL-2.0 + +if ARCH_ZYNQMP + +config CMD_ZYNQMP + bool "Enable ZynqMP specific commands" + default y + help + Enable ZynqMP specific commands like "zynqmp secure" + which is used for zynqmp secure image verification. + The secure image is a xilinx specific BOOT.BIN with + either authentication or encryption or both encryption + and authentication feature enabled while generating + BOOT.BIN using Xilinx bootgen tool. + +endif diff --git a/board/xilinx/zynqmp/MAINTAINERS b/board/xilinx/zynqmp/MAINTAINERS index 69edbf21f9..bb39f875fe 100644 --- a/board/xilinx/zynqmp/MAINTAINERS +++ b/board/xilinx/zynqmp/MAINTAINERS @@ -1,6 +1,7 @@ XILINX_ZYNQMP BOARDS M: Michal Simek <michal.simek@xilinx.com> S: Maintained +F: arch/arm/dts/zynqmp-* F: board/xilinx/zynqmp/ F: include/configs/xilinx_zynqmp* F: configs/xilinx_zynqmp* diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile index 75aab92f04..3b7a10e202 100644 --- a/board/xilinx/zynqmp/Makefile +++ b/board/xilinx/zynqmp/Makefile @@ -26,6 +26,10 @@ ifneq ($(call ifdef_any_of, CONFIG_ZYNQMP_PSU_INIT_ENABLED CONFIG_SPL_BUILD),) obj-y += $(init-objs) endif +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_CMD_ZYNQMP) += cmds.o +endif + # Suppress "warning: function declaration isn't a prototype" CFLAGS_REMOVE_psu_init_gpl.o := -Wstrict-prototypes diff --git a/board/xilinx/zynqmp/cmds.c b/board/xilinx/zynqmp/cmds.c new file mode 100644 index 0000000000..6712d7b8cf --- /dev/null +++ b/board/xilinx/zynqmp/cmds.c @@ -0,0 +1,105 @@ +/* + * (C) Copyright 2018 Xilinx, Inc. + * Siva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <malloc.h> +#include <asm/arch/sys_proto.h> +#include <asm/io.h> + +static int zynqmp_verify_secure(u8 *key_ptr, u8 *src_ptr, u32 len) +{ + int ret; + u32 src_lo, src_hi; + u32 key_lo = 0; + u32 key_hi = 0; + u32 ret_payload[PAYLOAD_ARG_CNT]; + u64 addr; + + if ((ulong)src_ptr != ALIGN((ulong)src_ptr, + CONFIG_SYS_CACHELINE_SIZE)) { + printf("Failed: source address not aligned:%p\n", src_ptr); + return -EINVAL; + } + + src_lo = lower_32_bits((ulong)src_ptr); + src_hi = upper_32_bits((ulong)src_ptr); + flush_dcache_range((ulong)src_ptr, (ulong)(src_ptr + len)); + + if (key_ptr) { + key_lo = lower_32_bits((ulong)key_ptr); + key_hi = upper_32_bits((ulong)key_ptr); + flush_dcache_range((ulong)key_ptr, + (ulong)(key_ptr + KEY_PTR_LEN)); + } + + ret = invoke_smc(ZYNQMP_SIP_SVC_PM_SECURE_IMG_LOAD, src_lo, src_hi, + key_lo, key_hi, ret_payload); + if (ret) { + printf("Failed: secure op status:0x%x\n", ret); + } else { + addr = (u64)ret_payload[1] << 32 | ret_payload[2]; + printf("Verified image at 0x%llx\n", addr); + env_set_hex("zynqmp_verified_img_addr", addr); + } + + return ret; +} + +/** + * do_zynqmp - Handle the "zynqmp" command-line command + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * Processes the zynqmp specific commands + * + * Return: return 0 on success and CMD_RET_USAGE incase of misuse and error + */ +static int do_zynqmp(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + u64 src_addr; + u32 len; + u8 *key_ptr = NULL; + u8 *src_ptr; + int ret; + + if (argc > 5 || argc < 4 || strncmp(argv[1], "secure", 6)) + return CMD_RET_USAGE; + + src_addr = simple_strtoull(argv[2], NULL, 16); + + len = simple_strtoul(argv[3], NULL, 16); + + if (argc > 4) + key_ptr = (uint8_t *)(uintptr_t)simple_strtoull(argv[4], + NULL, 16); + + src_ptr = (uint8_t *)(uintptr_t)src_addr; + + ret = zynqmp_verify_secure(key_ptr, src_ptr, len); + if (ret) + return CMD_RET_FAILURE; + + return CMD_RET_SUCCESS; +} + +/***************************************************/ +#ifdef CONFIG_SYS_LONGHELP +static char zynqmp_help_text[] = + "secure src len [key_addr] - verifies secure images of $len bytes\n" + " long at address $src. Optional key_addr\n" + " can be specified if user key needs to\n" + " be used for decryption\n"; +#endif + +U_BOOT_CMD( + zynqmp, 5, 1, do_zynqmp, + "Verify and load secure images", + zynqmp_help_text +) diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index ff0b3c75f5..0d1bd5412b 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -31,6 +31,7 @@ static const struct { u32 id; u32 ver; char *name; + bool evexists; } zynqmp_devices[] = { { .id = 0x10, @@ -53,11 +54,13 @@ static const struct { { .id = 0x20, .name = "5ev", + .evexists = 1, }, { .id = 0x20, .ver = 0x100, .name = "5eg", + .evexists = 1, }, { .id = 0x20, @@ -67,11 +70,13 @@ static const struct { { .id = 0x21, .name = "4ev", + .evexists = 1, }, { .id = 0x21, .ver = 0x100, .name = "4eg", + .evexists = 1, }, { .id = 0x21, @@ -81,11 +86,13 @@ static const struct { { .id = 0x30, .name = "7ev", + .evexists = 1, }, { .id = 0x30, .ver = 0x100, .name = "7eg", + .evexists = 1, }, { .id = 0x30, @@ -219,20 +226,48 @@ int chip_id(unsigned char id) return val; } +#define ZYNQMP_VERSION_SIZE 9 +#define ZYNQMP_PL_STATUS_BIT 9 +#define ZYNQMP_PL_STATUS_MASK BIT(ZYNQMP_PL_STATUS_BIT) +#define ZYNQMP_CSU_VERSION_MASK ~(ZYNQMP_PL_STATUS_MASK) + #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \ !defined(CONFIG_SPL_BUILD) static char *zynqmp_get_silicon_idcode_name(void) { u32 i, id, ver; + char *buf; + static char name[ZYNQMP_VERSION_SIZE]; id = chip_id(IDCODE); ver = chip_id(IDCODE2); for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { - if (zynqmp_devices[i].id == id && zynqmp_devices[i].ver == ver) - return zynqmp_devices[i].name; + if ((zynqmp_devices[i].id == id) && + (zynqmp_devices[i].ver == (ver & + ZYNQMP_CSU_VERSION_MASK))) { + strncat(name, "zu", 2); + strncat(name, zynqmp_devices[i].name, + ZYNQMP_VERSION_SIZE - 3); + break; + } + } + + if (i >= ARRAY_SIZE(zynqmp_devices)) + return "unknown"; + + if (!zynqmp_devices[i].evexists) + return name; + + if (ver & ZYNQMP_PL_STATUS_MASK) + return name; + + if (strstr(name, "eg") || strstr(name, "ev")) { + buf = strstr(name, "e"); + *buf = '\0'; } - return "unknown"; + + return name; } #endif @@ -250,8 +285,6 @@ int board_early_init_f(void) return ret; } -#define ZYNQMP_VERSION_SIZE 9 - int board_init(void) { printf("EL Level:\tEL%d\n", current_el()); @@ -260,12 +293,7 @@ int board_init(void) !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_FPGA_SUPPORT) && \ defined(CONFIG_SPL_BUILD)) if (current_el() != 3) { - static char version[ZYNQMP_VERSION_SIZE]; - - strncat(version, "zu", 2); - zynqmppl.name = strncat(version, - zynqmp_get_silicon_idcode_name(), - ZYNQMP_VERSION_SIZE - 3); + zynqmppl.name = zynqmp_get_silicon_idcode_name(); printf("Chip ID:\t%s\n", zynqmppl.name); fpga_init(); fpga_add(fpga_xilinx, &zynqmppl); @@ -316,6 +344,23 @@ int zynq_board_read_rom_ethaddr(unsigned char *ethaddr) return 0; } +unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc, + char * const argv[]) +{ + int ret = 0; + + if (current_el() > 1) { + smp_kick_all_cpus(); + dcache_disable(); + armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry, + ES_TO_AARCH64); + } else { + printf("FAIL: current EL is not above EL1\n"); + ret = EINVAL; + } + return ret; +} + #if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE) int dram_init_banksize(void) { @@ -287,7 +287,7 @@ static int do_spi_flash_read_write(int argc, char * const argv[]) } buf = map_physmem(addr, len, MAP_WRBACK); - if (!buf) { + if (!buf && addr) { puts("Failed to map physical memory\n"); return 1; } diff --git a/common/board_f.c b/common/board_f.c index 62588c5bad..ae8bdb7c5c 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -900,7 +900,8 @@ void board_init_f(ulong boot_flags) hang(); #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \ - !defined(CONFIG_EFI_APP) && !CONFIG_IS_ENABLED(X86_64) + !defined(CONFIG_EFI_APP) && !CONFIG_IS_ENABLED(X86_64) && \ + !defined(CONFIG_ARC) /* NOTREACHED - jump_to_copy() does not return */ hang(); #endif diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig index 60120bf163..d1c78fa489 100644 --- a/configs/am335x_evm_defconfig +++ b/configs/am335x_evm_defconfig @@ -4,6 +4,7 @@ CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_AM33XX=y CONFIG_DEFAULT_DEVICE_TREE="am335x-evm" CONFIG_DISTRO_DEFAULTS=y +CONFIG_SPL_SYS_MALLOC_F_LEN=0x1000 CONFIG_SPL_LOAD_FIT=y CONFIG_BOOTCOMMAND="if test ${boot_fit} -eq 1; then run update_to_fit; fi; run findfdt; run init_console; run envboot; run distro_bootcmd" CONFIG_SYS_CONSOLE_INFO_QUIET=y diff --git a/configs/am335x_hs_evm_defconfig b/configs/am335x_hs_evm_defconfig index c903cc780d..a8ab3e6206 100644 --- a/configs/am335x_hs_evm_defconfig +++ b/configs/am335x_hs_evm_defconfig @@ -9,6 +9,7 @@ CONFIG_ISW_ENTRY_ADDR=0x40300350 # CONFIG_SPL_NAND_SUPPORT is not set CONFIG_DEFAULT_DEVICE_TREE="am335x-evm" CONFIG_DISTRO_DEFAULTS=y +CONFIG_SPL_SYS_MALLOC_F_LEN=0x1000 CONFIG_ANDROID_BOOT_IMAGE=y CONFIG_FIT_IMAGE_POST_PROCESS=y CONFIG_SPL_LOAD_FIT=y diff --git a/configs/ls1012a2g5rdb_qspi_defconfig b/configs/ls1012a2g5rdb_qspi_defconfig index 26dcb1abb1..af676e2898 100644 --- a/configs/ls1012a2g5rdb_qspi_defconfig +++ b/configs/ls1012a2g5rdb_qspi_defconfig @@ -31,7 +31,9 @@ CONFIG_DM=y CONFIG_DM_MMC=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y +CONFIG_DM_ETH=y CONFIG_NETDEVICES=y +CONFIG_FSL_PFE=y CONFIG_SYS_NS16550=y CONFIG_DM_SPI=y CONFIG_USB=y diff --git a/configs/ls1012afrdm_qspi_defconfig b/configs/ls1012afrdm_qspi_defconfig index 1164361b50..c02e5205f6 100644 --- a/configs/ls1012afrdm_qspi_defconfig +++ b/configs/ls1012afrdm_qspi_defconfig @@ -29,8 +29,10 @@ CONFIG_DM=y # CONFIG_MMC is not set CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y +CONFIG_DM_ETH=y CONFIG_NETDEVICES=y CONFIG_E1000=y +CONFIG_FSL_PFE=y CONFIG_PCI=y CONFIG_DM_PCI=y CONFIG_DM_PCI_COMPAT=y diff --git a/configs/ls1012aqds_qspi_defconfig b/configs/ls1012aqds_qspi_defconfig index 9fdf3330ae..25470cb5fd 100644 --- a/configs/ls1012aqds_qspi_defconfig +++ b/configs/ls1012aqds_qspi_defconfig @@ -36,8 +36,10 @@ CONFIG_SCSI_AHCI=y CONFIG_DM_MMC=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y +CONFIG_DM_ETH=y CONFIG_NETDEVICES=y CONFIG_E1000=y +CONFIG_FSL_PFE=y CONFIG_PCI=y CONFIG_DM_PCI=y CONFIG_DM_PCI_COMPAT=y diff --git a/configs/ls1012ardb_qspi_defconfig b/configs/ls1012ardb_qspi_defconfig index 43472635be..1f629536eb 100644 --- a/configs/ls1012ardb_qspi_defconfig +++ b/configs/ls1012ardb_qspi_defconfig @@ -32,8 +32,10 @@ CONFIG_DM=y CONFIG_DM_MMC=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y +CONFIG_DM_ETH=y CONFIG_NETDEVICES=y CONFIG_E1000=y +CONFIG_FSL_PFE=y CONFIG_PCI=y CONFIG_DM_PCI=y CONFIG_DM_PCI_COMPAT=y diff --git a/configs/microblaze-generic_defconfig b/configs/microblaze-generic_defconfig index 699dc447f0..18bec1f2e5 100644 --- a/configs/microblaze-generic_defconfig +++ b/configs/microblaze-generic_defconfig @@ -3,6 +3,7 @@ CONFIG_SYS_TEXT_BASE=0x29000000 CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL=y CONFIG_TARGET_MICROBLAZE_GENERIC=y CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1 CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1 @@ -15,7 +16,6 @@ CONFIG_BOOTDELAY=-1 CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="root=romfs" CONFIG_SYS_CONSOLE_IS_IN_ENV=y -CONFIG_SPL=y CONFIG_SPL_BOARD_INIT=y CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_NOR_SUPPORT=y diff --git a/configs/omapl138_lcdk_defconfig b/configs/omapl138_lcdk_defconfig index ccb308bf01..2c1bdb2e29 100644 --- a/configs/omapl138_lcdk_defconfig +++ b/configs/omapl138_lcdk_defconfig @@ -2,6 +2,7 @@ CONFIG_ARM=y CONFIG_ARCH_DAVINCI=y CONFIG_SYS_TEXT_BASE=0xc1080000 CONFIG_TARGET_OMAPL138_LCDK=y +CONFIG_SYS_DA850_PLL0_POSTDIV=0 CONFIG_SYS_DA850_PLL1_PLLDIV3=0x8003 CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_SPL_LIBCOMMON_SUPPORT=y @@ -9,11 +10,11 @@ CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_SPL_MMC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_NAND_SUPPORT=y +CONFIG_DEFAULT_DEVICE_TREE="da850-lcdk" CONFIG_BOOTDELAY=3 CONFIG_LOGLEVEL=3 CONFIG_VERSION_VARIABLE=y # CONFIG_DISPLAY_CPUINFO is not set -# CONFIG_DISPLAY_BOARDINFO is not set CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SPL=y CONFIG_SPL_BOARD_INIT=y @@ -27,9 +28,13 @@ CONFIG_CMD_NAND=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DIAG=y CONFIG_CMD_UBI=y +CONFIG_OF_CONTROL=y CONFIG_ENV_IS_IN_NAND=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_BOOTP_DNS=y +CONFIG_DM=y +CONFIG_DM_I2C=y +CONFIG_DM_I2C_COMPAT=y CONFIG_NAND=y CONFIG_SYS_NAND_BUSWIDTH_16BIT=y CONFIG_SYS_NAND_U_BOOT_LOCATIONS=y @@ -38,6 +43,6 @@ CONFIG_SPL_NAND_SIMPLE=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_WINBOND=y +CONFIG_DM_SERIAL=y CONFIG_SYS_NS16550=y CONFIG_DAVINCI_SPI=y -CONFIG_OF_LIBFDT=y diff --git a/configs/pine64_plus_defconfig b/configs/pine64_plus_defconfig index a8d4e2b0aa..e98740aec0 100644 --- a/configs/pine64_plus_defconfig +++ b/configs/pine64_plus_defconfig @@ -12,3 +12,5 @@ CONFIG_SPL=y CONFIG_SUN8I_EMAC=y CONFIG_USB_EHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y +CONFIG_PHY_REALTEK=y +CONFIG_RTL8211E_PINE64_GIGABIT_FIX=y diff --git a/configs/syzygy_hub_defconfig b/configs/syzygy_hub_defconfig index 67d1f545d7..005cb9ce2e 100644 --- a/configs/syzygy_hub_defconfig +++ b/configs/syzygy_hub_defconfig @@ -3,6 +3,7 @@ CONFIG_SYS_VENDOR="opalkelly" CONFIG_SYS_CONFIG_NAME="syzygy_hub" CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0x4000000 +CONFIG_SPL=y CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_DEFAULT_DEVICE_TREE="zynq-syzygy-hub" CONFIG_DEBUG_UART=y @@ -12,7 +13,6 @@ CONFIG_FIT_SIGNATURE=y CONFIG_FIT_VERBOSE=y CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd" # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SPL_OS_BOOT=y CONFIG_SYS_PROMPT="Zynq> " diff --git a/configs/topic_miami_defconfig b/configs/topic_miami_defconfig index 8b02599b26..2dd938d09a 100644 --- a/configs/topic_miami_defconfig +++ b/configs/topic_miami_defconfig @@ -3,6 +3,7 @@ CONFIG_SYS_VENDOR="topic" CONFIG_SYS_CONFIG_NAME="topic_miami" CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0x4000000 +CONFIG_SPL=y CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_BOOT_INIT_FILE="board/topic/zynq/zynq-topic-miami/ps7_regs.txt" CONFIG_DEFAULT_DEVICE_TREE="zynq-topic-miami" @@ -11,7 +12,6 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_BOOTDELAY=0 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd" # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SYS_PROMPT="zynq-uboot> " CONFIG_CMD_THOR_DOWNLOAD=y diff --git a/configs/topic_miamilite_defconfig b/configs/topic_miamilite_defconfig index 572b2f5149..638cc34ac9 100644 --- a/configs/topic_miamilite_defconfig +++ b/configs/topic_miamilite_defconfig @@ -3,6 +3,7 @@ CONFIG_SYS_VENDOR="topic" CONFIG_SYS_CONFIG_NAME="topic_miami" CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0x4000000 +CONFIG_SPL=y CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_BOOT_INIT_FILE="board/topic/zynq/zynq-topic-miamilite/ps7_regs.txt" CONFIG_DEFAULT_DEVICE_TREE="zynq-topic-miamilite" @@ -11,7 +12,6 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_BOOTDELAY=0 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd" # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SYS_PROMPT="zynq-uboot> " CONFIG_CMD_THOR_DOWNLOAD=y diff --git a/configs/topic_miamiplus_defconfig b/configs/topic_miamiplus_defconfig index 3e8504d6a0..ef91bd5825 100644 --- a/configs/topic_miamiplus_defconfig +++ b/configs/topic_miamiplus_defconfig @@ -3,6 +3,7 @@ CONFIG_SYS_VENDOR="topic" CONFIG_SYS_CONFIG_NAME="topic_miami" CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0x4000000 +CONFIG_SPL=y CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_BOOT_INIT_FILE="board/topic/zynq/zynq-topic-miamiplus/ps7_regs.txt" CONFIG_DEFAULT_DEVICE_TREE="zynq-topic-miamiplus" @@ -11,7 +12,6 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_BOOTDELAY=0 CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd" # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SYS_PROMPT="zynq-uboot> " CONFIG_CMD_THOR_DOWNLOAD=y diff --git a/configs/xilinx_zynqmp_ep_defconfig b/configs/xilinx_zynqmp_ep_defconfig deleted file mode 100644 index a0c8f28b97..0000000000 --- a/configs/xilinx_zynqmp_ep_defconfig +++ /dev/null @@ -1,102 +0,0 @@ -CONFIG_ARM=y -CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_ep" -CONFIG_ARCH_ZYNQMP=y -CONFIG_SYS_TEXT_BASE=0x8000000 -CONFIG_SYS_MALLOC_F_LEN=0x8000 -CONFIG_ZYNQ_SDHCI_MAX_FREQ=52000000 -CONFIG_ZYNQMP_USB=y -CONFIG_DEFAULT_DEVICE_TREE="zynqmp-ep108" -CONFIG_DEBUG_UART=y -CONFIG_AHCI=y -CONFIG_DISTRO_DEFAULTS=y -CONFIG_FIT=y -CONFIG_FIT_VERBOSE=y -CONFIG_SPL_LOAD_FIT=y -# CONFIG_DISPLAY_CPUINFO is not set -# CONFIG_DISPLAY_BOARDINFO is not set -CONFIG_SPL=y -CONFIG_SPL_OS_BOOT=y -CONFIG_SYS_PROMPT="ZynqMP> " -CONFIG_FASTBOOT=y -CONFIG_FASTBOOT_FLASH=y -CONFIG_FASTBOOT_FLASH_MMC_DEV=0 -# CONFIG_CMD_CONSOLE is not set -# CONFIG_CMD_XIMG is not set -CONFIG_CMD_THOR_DOWNLOAD=y -# CONFIG_CMD_EDITENV is not set -# CONFIG_CMD_ENV_EXISTS is not set -CONFIG_CMD_CLK=y -CONFIG_CMD_DFU=y -# CONFIG_CMD_FPGA is not set -CONFIG_CMD_GPIO=y -CONFIG_CMD_GPT=y -CONFIG_CMD_I2C=y -# CONFIG_CMD_LOADB is not set -# CONFIG_CMD_LOADS is not set -CONFIG_CMD_MMC=y -CONFIG_CMD_NAND_LOCK_UNLOCK=y -CONFIG_CMD_USB=y -# CONFIG_CMD_ITEST is not set -# CONFIG_CMD_SETEXPR is not set -CONFIG_CMD_TFTPPUT=y -# CONFIG_CMD_NFS is not set -CONFIG_CMD_TIME=y -CONFIG_CMD_TIMER=y -CONFIG_CMD_EXT4_WRITE=y -# CONFIG_SPL_ISO_PARTITION is not set -CONFIG_SPL_OF_CONTROL=y -CONFIG_OF_EMBED=y -CONFIG_ENV_IS_IN_FAT=y -CONFIG_NET_RANDOM_ETHADDR=y -CONFIG_SPL_DM=y -CONFIG_SPL_DM_SEQ_ALIAS=y -CONFIG_SCSI_AHCI=y -CONFIG_SATA_CEVA=y -CONFIG_DFU_RAM=y -CONFIG_FPGA_XILINX=y -CONFIG_FPGA_ZYNQMPPL=y -CONFIG_DM_GPIO=y -CONFIG_DM_I2C=y -CONFIG_SYS_I2C_CADENCE=y -CONFIG_MISC=y -CONFIG_DM_MMC=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_ZYNQ=y -CONFIG_ZYNQ_SDHCI_MIN_FREQ=100000 -CONFIG_NAND=y -CONFIG_NAND_ARASAN=y -CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_BAR=y -CONFIG_SPI_FLASH_SPANSION=y -CONFIG_SPI_FLASH_STMICRO=y -CONFIG_SPI_FLASH_WINBOND=y -# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set -CONFIG_PHY_MARVELL=y -CONFIG_PHY_NATSEMI=y -CONFIG_PHY_REALTEK=y -CONFIG_PHY_TI=y -CONFIG_PHY_VITESSE=y -CONFIG_DM_ETH=y -CONFIG_PHY_GIGE=y -CONFIG_ZYNQ_GEM=y -CONFIG_SCSI=y -CONFIG_DM_SCSI=y -CONFIG_DEBUG_UART_ZYNQ=y -CONFIG_DEBUG_UART_BASE=0xff000000 -CONFIG_DEBUG_UART_CLOCK=25000000 -CONFIG_DEBUG_UART_ANNOUNCE=y -CONFIG_ZYNQ_SERIAL=y -CONFIG_USB=y -CONFIG_USB_XHCI_HCD=y -CONFIG_USB_XHCI_DWC3=y -CONFIG_USB_XHCI_ZYNQMP=y -CONFIG_USB_DWC3=y -CONFIG_USB_DWC3_GADGET=y -CONFIG_USB_STORAGE=y -CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_MANUFACTURER="Xilinx" -CONFIG_USB_GADGET_VENDOR_NUM=0x03fd -CONFIG_USB_GADGET_PRODUCT_NUM=0x0300 -CONFIG_USB_FUNCTION_THOR=y -# CONFIG_REGEX is not set -CONFIG_EFI_LOADER_BOUNCE_BUFFER=y diff --git a/configs/xilinx_zynqmp_mini_emmc_defconfig b/configs/xilinx_zynqmp_mini_emmc_defconfig index b15120e0fa..8f2596a894 100644 --- a/configs/xilinx_zynqmp_mini_emmc_defconfig +++ b/configs/xilinx_zynqmp_mini_emmc_defconfig @@ -2,6 +2,7 @@ CONFIG_ARM=y CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_mini_emmc" CONFIG_ARCH_ZYNQMP=y CONFIG_SYS_TEXT_BASE=0x10000 +# CONFIG_CMD_ZYNQMP is not set CONFIG_DEFAULT_DEVICE_TREE="zynqmp-mini-emmc" CONFIG_ENV_VARS_UBOOT_CONFIG=y CONFIG_FIT=y diff --git a/configs/xilinx_zynqmp_mini_nand_defconfig b/configs/xilinx_zynqmp_mini_nand_defconfig index 55200bcb05..1fec9bab7c 100644 --- a/configs/xilinx_zynqmp_mini_nand_defconfig +++ b/configs/xilinx_zynqmp_mini_nand_defconfig @@ -2,6 +2,7 @@ CONFIG_ARM=y CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_mini_nand" CONFIG_ARCH_ZYNQMP=y CONFIG_SYS_TEXT_BASE=0x10000 +# CONFIG_CMD_ZYNQMP is not set CONFIG_DEFAULT_DEVICE_TREE="zynqmp-mini-nand" CONFIG_ENV_VARS_UBOOT_CONFIG=y CONFIG_FIT=y diff --git a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig index 7da0ca8789..1125ebda8a 100644 --- a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig +++ b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig @@ -3,6 +3,7 @@ CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zc1751_xm015_dc1" CONFIG_ARCH_ZYNQMP=y CONFIG_SYS_TEXT_BASE=0x8000000 CONFIG_SYS_MALLOC_F_LEN=0x8000 +CONFIG_SPL=y CONFIG_IDENT_STRING=" Xilinx ZynqMP ZC1751 xm015 dc1" CONFIG_ZYNQMP_USB=y CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm015-dc1" @@ -14,7 +15,6 @@ CONFIG_FIT_VERBOSE=y CONFIG_SPL_LOAD_FIT=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set -CONFIG_SPL=y CONFIG_SPL_OS_BOOT=y CONFIG_SPL_RAM_SUPPORT=y CONFIG_SPL_RAM_DEVICE=y @@ -45,6 +45,7 @@ CONFIG_ENV_IS_IN_FAT=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_CLK_ZYNQMP=y CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y diff --git a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig index 3e531661eb..8fc13ef0ec 100644 --- a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig +++ b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig @@ -4,6 +4,7 @@ CONFIG_ARCH_ZYNQMP=y CONFIG_SYS_TEXT_BASE=0x8000000 CONFIG_SYS_MALLOC_F_LEN=0x8000 # CONFIG_SPL_LIBDISK_SUPPORT is not set +CONFIG_SPL=y CONFIG_IDENT_STRING=" Xilinx ZynqMP ZC1751 xm016 dc2" # CONFIG_SPL_FAT_SUPPORT is not set CONFIG_ZYNQMP_USB=y @@ -15,7 +16,6 @@ CONFIG_FIT_VERBOSE=y CONFIG_SPL_LOAD_FIT=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set -CONFIG_SPL=y CONFIG_SPL_OS_BOOT=y CONFIG_SPL_RAM_SUPPORT=y CONFIG_SPL_RAM_DEVICE=y @@ -44,6 +44,7 @@ CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_CLK_ZYNQMP=y CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y diff --git a/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig b/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig index 9bc0b77c2c..0a057bf3fe 100644 --- a/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig +++ b/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig @@ -2,6 +2,7 @@ CONFIG_ARM=y CONFIG_ARCH_ZYNQMP=y CONFIG_SYS_TEXT_BASE=0x8000000 CONFIG_SYS_MALLOC_F_LEN=0x8000 +CONFIG_SPL=y CONFIG_IDENT_STRING=" Xilinx ZynqMP ZC1751 xm018 dc4" CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm018-dc4" CONFIG_DEBUG_UART=y @@ -11,7 +12,6 @@ CONFIG_FIT_VERBOSE=y CONFIG_SPL_LOAD_FIT=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set -CONFIG_SPL=y CONFIG_SPL_OS_BOOT=y CONFIG_SPL_RAM_SUPPORT=y CONFIG_SPL_RAM_DEVICE=y @@ -34,6 +34,7 @@ CONFIG_ENV_IS_IN_FAT=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_CLK_ZYNQMP=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y diff --git a/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig b/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig index ac565ecf8f..47edf519f9 100644 --- a/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig +++ b/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig @@ -3,6 +3,7 @@ CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zc1751_xm019_dc5" CONFIG_ARCH_ZYNQMP=y CONFIG_SYS_TEXT_BASE=0x8000000 CONFIG_SYS_MALLOC_F_LEN=0x8000 +CONFIG_SPL=y CONFIG_IDENT_STRING=" Xilinx ZynqMP ZC1751 xm019 dc5" CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm019-dc5" CONFIG_DEBUG_UART=y @@ -12,7 +13,6 @@ CONFIG_FIT_VERBOSE=y CONFIG_SPL_LOAD_FIT=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set -CONFIG_SPL=y CONFIG_SPL_OS_BOOT=y CONFIG_SPL_RAM_SUPPORT=y CONFIG_SPL_RAM_DEVICE=y @@ -34,6 +34,7 @@ CONFIG_OF_EMBED=y CONFIG_ENV_IS_IN_FAT=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_CLK_ZYNQMP=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y @@ -44,6 +45,8 @@ CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_DM_ETH=y +CONFIG_PHY_GIGE=y +CONFIG_ZYNQ_GEM=y CONFIG_DEBUG_UART_ZYNQ=y CONFIG_DEBUG_UART_BASE=0xff000000 CONFIG_DEBUG_UART_CLOCK=100000000 diff --git a/configs/xilinx_zynqmp_zcu102_rev1_0_defconfig b/configs/xilinx_zynqmp_zcu102_rev1_0_defconfig index 1df5b0b5c6..cb3e2f5ca9 100644 --- a/configs/xilinx_zynqmp_zcu102_rev1_0_defconfig +++ b/configs/xilinx_zynqmp_zcu102_rev1_0_defconfig @@ -3,6 +3,7 @@ CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zcu102" CONFIG_ARCH_ZYNQMP=y CONFIG_SYS_TEXT_BASE=0x8000000 CONFIG_SYS_MALLOC_F_LEN=0x8000 +CONFIG_SPL=y CONFIG_IDENT_STRING=" Xilinx ZynqMP ZCU102 rev1.0" CONFIG_ZYNQMP_USB=y CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102-rev1.0" @@ -14,7 +15,6 @@ CONFIG_FIT_VERBOSE=y CONFIG_SPL_LOAD_FIT=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set -CONFIG_SPL=y CONFIG_SPL_OS_BOOT=y CONFIG_SPL_RAM_SUPPORT=y CONFIG_SPL_RAM_DEVICE=y @@ -48,6 +48,7 @@ CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_SCSI_AHCI=y CONFIG_SATA_CEVA=y +CONFIG_CLK_ZYNQMP=y CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y diff --git a/configs/xilinx_zynqmp_zcu102_revA_defconfig b/configs/xilinx_zynqmp_zcu102_revA_defconfig index c8a8362148..19b9683f02 100644 --- a/configs/xilinx_zynqmp_zcu102_revA_defconfig +++ b/configs/xilinx_zynqmp_zcu102_revA_defconfig @@ -3,6 +3,7 @@ CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zcu102" CONFIG_ARCH_ZYNQMP=y CONFIG_SYS_TEXT_BASE=0x8000000 CONFIG_SYS_MALLOC_F_LEN=0x8000 +CONFIG_SPL=y CONFIG_IDENT_STRING=" Xilinx ZynqMP ZCU102 revA" CONFIG_ZYNQMP_USB=y CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102-revA" @@ -14,7 +15,6 @@ CONFIG_FIT_VERBOSE=y CONFIG_SPL_LOAD_FIT=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set -CONFIG_SPL=y CONFIG_SPL_OS_BOOT=y CONFIG_SPL_RAM_SUPPORT=y CONFIG_SPL_RAM_DEVICE=y @@ -48,6 +48,7 @@ CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_SCSI_AHCI=y CONFIG_SATA_CEVA=y +CONFIG_CLK_ZYNQMP=y CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y diff --git a/configs/xilinx_zynqmp_zcu102_revB_defconfig b/configs/xilinx_zynqmp_zcu102_revB_defconfig index 8f85b5f675..b660200508 100644 --- a/configs/xilinx_zynqmp_zcu102_revB_defconfig +++ b/configs/xilinx_zynqmp_zcu102_revB_defconfig @@ -3,6 +3,7 @@ CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zcu102" CONFIG_ARCH_ZYNQMP=y CONFIG_SYS_TEXT_BASE=0x8000000 CONFIG_SYS_MALLOC_F_LEN=0x8000 +CONFIG_SPL=y CONFIG_IDENT_STRING=" Xilinx ZynqMP ZCU102 revB" CONFIG_ZYNQMP_USB=y CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102-revB" @@ -14,7 +15,6 @@ CONFIG_FIT_VERBOSE=y CONFIG_SPL_LOAD_FIT=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set -CONFIG_SPL=y CONFIG_SPL_OS_BOOT=y CONFIG_SPL_RAM_SUPPORT=y CONFIG_SPL_RAM_DEVICE=y @@ -48,6 +48,7 @@ CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_SCSI_AHCI=y CONFIG_SATA_CEVA=y +CONFIG_CLK_ZYNQMP=y CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y diff --git a/configs/zynq_cc108_defconfig b/configs/zynq_cc108_defconfig index 3a4de92e4c..d328fe6cfe 100644 --- a/configs/zynq_cc108_defconfig +++ b/configs/zynq_cc108_defconfig @@ -1,6 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0x4000000 +CONFIG_SPL=y CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_DEFAULT_DEVICE_TREE="zynq-cc108" CONFIG_DEBUG_UART=y @@ -10,7 +11,6 @@ CONFIG_FIT_SIGNATURE=y CONFIG_FIT_VERBOSE=y CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd" # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SYS_PROMPT="Zynq> " CONFIG_CMD_DFU=y diff --git a/configs/zynq_cse_qspi_defconfig b/configs/zynq_cse_qspi_defconfig index 80bb26c69f..d93cdbfba5 100644 --- a/configs/zynq_cse_qspi_defconfig +++ b/configs/zynq_cse_qspi_defconfig @@ -2,6 +2,7 @@ CONFIG_ARM=y CONFIG_SYS_CONFIG_NAME="zynq_cse" CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0xFFFC0000 +CONFIG_SPL=y CONFIG_SPL_STACK_R_ADDR=0x200000 # CONFIG_ZYNQ_DDRC_INIT is not set CONFIG_DEFAULT_DEVICE_TREE="zynq-cse-qspi-single" @@ -11,7 +12,6 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_BOOTDELAY=-1 # CONFIG_USE_BOOTCOMMAND is not set # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SYS_PROMPT="Zynq> " # CONFIG_CMD_BDI is not set diff --git a/configs/zynq_microzed_defconfig b/configs/zynq_microzed_defconfig index 94a1a40efb..25331cac86 100644 --- a/configs/zynq_microzed_defconfig +++ b/configs/zynq_microzed_defconfig @@ -1,6 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0x4000000 +CONFIG_SPL=y CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_DEFAULT_DEVICE_TREE="zynq-microzed" CONFIG_DISTRO_DEFAULTS=y @@ -9,7 +10,6 @@ CONFIG_FIT_SIGNATURE=y CONFIG_FIT_VERBOSE=y CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd" # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SPL_OS_BOOT=y CONFIG_SYS_PROMPT="Zynq> " diff --git a/configs/zynq_picozed_defconfig b/configs/zynq_picozed_defconfig index f9ee904bd4..6a841f8ecd 100644 --- a/configs/zynq_picozed_defconfig +++ b/configs/zynq_picozed_defconfig @@ -1,12 +1,12 @@ CONFIG_ARM=y CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0x4000000 +CONFIG_SPL=y CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_DEFAULT_DEVICE_TREE="zynq-picozed" CONFIG_DISTRO_DEFAULTS=y CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd" # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SPL_OS_BOOT=y CONFIG_SYS_PROMPT="Zynq> " diff --git a/configs/zynq_z_turn_defconfig b/configs/zynq_z_turn_defconfig index 7a51b85ac8..9013239a8f 100644 --- a/configs/zynq_z_turn_defconfig +++ b/configs/zynq_z_turn_defconfig @@ -1,6 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0x4000000 +CONFIG_SPL=y CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_DEFAULT_DEVICE_TREE="zynq-zturn-myir" CONFIG_DEBUG_UART=y @@ -10,7 +11,6 @@ CONFIG_FIT_SIGNATURE=y CONFIG_FIT_VERBOSE=y CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd" # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SPL_OS_BOOT=y CONFIG_SYS_PROMPT="Zynq> " diff --git a/configs/zynq_zc702_defconfig b/configs/zynq_zc702_defconfig index 8e8b80053a..72c109b2e3 100644 --- a/configs/zynq_zc702_defconfig +++ b/configs/zynq_zc702_defconfig @@ -2,6 +2,7 @@ CONFIG_ARM=y CONFIG_SYS_CONFIG_NAME="zynq_zc70x" CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0x4000000 +CONFIG_SPL=y CONFIG_IDENT_STRING=" Xilinx Zynq ZC702" CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc702" @@ -12,7 +13,6 @@ CONFIG_FIT_SIGNATURE=y CONFIG_FIT_VERBOSE=y CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd" # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SPL_OS_BOOT=y CONFIG_SYS_PROMPT="Zynq> " diff --git a/configs/zynq_zc706_defconfig b/configs/zynq_zc706_defconfig index 8f83d173c5..825a7263d2 100644 --- a/configs/zynq_zc706_defconfig +++ b/configs/zynq_zc706_defconfig @@ -2,6 +2,7 @@ CONFIG_ARM=y CONFIG_SYS_CONFIG_NAME="zynq_zc70x" CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0x4000000 +CONFIG_SPL=y CONFIG_IDENT_STRING=" Xilinx Zynq ZC706" CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc706" @@ -12,7 +13,6 @@ CONFIG_FIT_SIGNATURE=y CONFIG_FIT_VERBOSE=y CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd" # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SPL_OS_BOOT=y CONFIG_SYS_PROMPT="Zynq> " @@ -73,3 +73,5 @@ CONFIG_USB_GADGET_PRODUCT_NUM=0x0300 CONFIG_CI_UDC=y CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_USB_FUNCTION_THOR=y +CONFIG_WDT=y +CONFIG_WDT_CDNS=y diff --git a/configs/zynq_zc770_xm010_defconfig b/configs/zynq_zc770_xm010_defconfig index 8db30d0818..683dfe8d19 100644 --- a/configs/zynq_zc770_xm010_defconfig +++ b/configs/zynq_zc770_xm010_defconfig @@ -1,6 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0x4000000 +CONFIG_SPL=y CONFIG_IDENT_STRING=" Xilinx Zynq ZC770 XM010" CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm010" @@ -11,7 +12,6 @@ CONFIG_FIT_SIGNATURE=y CONFIG_FIT_VERBOSE=y CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd" # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SPL_OS_BOOT=y CONFIG_SYS_PROMPT="Zynq> " diff --git a/configs/zynq_zc770_xm011_defconfig b/configs/zynq_zc770_xm011_defconfig index b6ddf986c5..9613b8af25 100644 --- a/configs/zynq_zc770_xm011_defconfig +++ b/configs/zynq_zc770_xm011_defconfig @@ -1,6 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0x4000000 +CONFIG_SPL=y CONFIG_IDENT_STRING=" Xilinx Zynq ZC770 XM011" CONFIG_SPL_STACK_R_ADDR=0x200000 # CONFIG_SPL_FAT_SUPPORT is not set @@ -12,7 +13,6 @@ CONFIG_FIT_SIGNATURE=y CONFIG_FIT_VERBOSE=y CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd" # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SPL_OS_BOOT=y CONFIG_SYS_PROMPT="Zynq> " diff --git a/configs/zynq_zc770_xm011_x16_defconfig b/configs/zynq_zc770_xm011_x16_defconfig index bd0ec7b33b..884186a460 100644 --- a/configs/zynq_zc770_xm011_x16_defconfig +++ b/configs/zynq_zc770_xm011_x16_defconfig @@ -1,6 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0x4000000 +CONFIG_SPL=y CONFIG_IDENT_STRING=" Xilinx Zynq ZC770 XM011 x16" CONFIG_SPL_STACK_R_ADDR=0x200000 # CONFIG_SPL_FAT_SUPPORT is not set @@ -10,9 +11,8 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT=y CONFIG_FIT_SIGNATURE=y CONFIG_FIT_VERBOSE=y -# CONFIG_USE_BOOTCOMMAND is not set +CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd" # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SPL_OS_BOOT=y CONFIG_SYS_PROMPT="Zynq> " @@ -29,7 +29,6 @@ CONFIG_CMD_CACHE=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_ISO_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set -CONFIG_OF_EMBED=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQPL=y diff --git a/configs/zynq_zc770_xm012_defconfig b/configs/zynq_zc770_xm012_defconfig index 8dbba6589d..0b3db398f9 100644 --- a/configs/zynq_zc770_xm012_defconfig +++ b/configs/zynq_zc770_xm012_defconfig @@ -1,6 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0x4000000 +CONFIG_SPL=y CONFIG_IDENT_STRING=" Xilinx Zynq ZC770 XM012" CONFIG_SPL_STACK_R_ADDR=0x200000 # CONFIG_SPL_FAT_SUPPORT is not set @@ -11,7 +12,6 @@ CONFIG_FIT_SIGNATURE=y CONFIG_FIT_VERBOSE=y CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd" # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SPL_OS_BOOT=y CONFIG_SYS_PROMPT="Zynq> " diff --git a/configs/zynq_zc770_xm013_defconfig b/configs/zynq_zc770_xm013_defconfig index f9eabb12b5..d7d9d80ce6 100644 --- a/configs/zynq_zc770_xm013_defconfig +++ b/configs/zynq_zc770_xm013_defconfig @@ -1,6 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0x4000000 +CONFIG_SPL=y CONFIG_IDENT_STRING=" Xilinx Zynq ZC770 XM013" CONFIG_SPL_STACK_R_ADDR=0x200000 # CONFIG_SPL_FAT_SUPPORT is not set @@ -11,7 +12,6 @@ CONFIG_FIT_SIGNATURE=y CONFIG_FIT_VERBOSE=y CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd" # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SPL_OS_BOOT=y CONFIG_SYS_PROMPT="Zynq> " diff --git a/configs/zynq_zed_defconfig b/configs/zynq_zed_defconfig index 7ed012833a..9f76e5ed8f 100644 --- a/configs/zynq_zed_defconfig +++ b/configs/zynq_zed_defconfig @@ -1,15 +1,16 @@ CONFIG_ARM=y CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0x4000000 +CONFIG_SPL=y CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_DEFAULT_DEVICE_TREE="zynq-zed" +CONFIG_DEBUG_UART=y CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT=y CONFIG_FIT_SIGNATURE=y CONFIG_FIT_VERBOSE=y CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd" # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SPL_OS_BOOT=y CONFIG_SYS_PROMPT="Zynq> " @@ -47,6 +48,9 @@ CONFIG_PHY_MARVELL=y CONFIG_PHY_REALTEK=y CONFIG_PHY_XILINX=y CONFIG_ZYNQ_GEM=y +CONFIG_DEBUG_UART_ZYNQ=y +CONFIG_DEBUG_UART_BASE=0xe0001000 +CONFIG_DEBUG_UART_CLOCK=50000000 CONFIG_ZYNQ_SERIAL=y CONFIG_ZYNQ_QSPI=y CONFIG_USB=y diff --git a/configs/zynq_zybo_defconfig b/configs/zynq_zybo_defconfig index 92f3e1ec26..15922d2fa1 100644 --- a/configs/zynq_zybo_defconfig +++ b/configs/zynq_zybo_defconfig @@ -2,6 +2,7 @@ CONFIG_ARM=y CONFIG_SYS_CONFIG_NAME="zynq_zybo" CONFIG_ARCH_ZYNQ=y CONFIG_SYS_TEXT_BASE=0x4000000 +CONFIG_SPL=y CONFIG_SPL_STACK_R_ADDR=0x200000 CONFIG_DEFAULT_DEVICE_TREE="zynq-zybo" CONFIG_DEBUG_UART=y @@ -11,7 +12,6 @@ CONFIG_FIT_SIGNATURE=y CONFIG_FIT_VERBOSE=y CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd" # CONFIG_DISPLAY_CPUINFO is not set -CONFIG_SPL=y CONFIG_SPL_STACK_R=y CONFIG_SPL_OS_BOOT=y CONFIG_SYS_PROMPT="Zynq> " diff --git a/drivers/clk/clk_zynq.c b/drivers/clk/clk_zynq.c index 50f2a65c20..3845e07309 100644 --- a/drivers/clk/clk_zynq.c +++ b/drivers/clk/clk_zynq.c @@ -394,7 +394,7 @@ static ulong zynq_clk_get_rate(struct clk *clk) return zynq_clk_get_peripheral_rate(priv, id, two_divs); case dma_clk: return zynq_clk_get_cpu_rate(priv, cpu_2x_clk); - case usb0_aper_clk ... smc_aper_clk: + case usb0_aper_clk ... swdt_clk: return zynq_clk_get_cpu_rate(priv, cpu_1x_clk); default: return -ENXIO; diff --git a/drivers/clk/clk_zynqmp.c b/drivers/clk/clk_zynqmp.c index bcc62904f1..4ef8662af5 100644 --- a/drivers/clk/clk_zynqmp.c +++ b/drivers/clk/clk_zynqmp.c @@ -226,6 +226,18 @@ static u32 zynqmp_clk_get_register(enum zynqmp_clk id) return CRL_APB_CAN0_REF_CTRL; case can1_ref: return CRL_APB_CAN1_REF_CTRL; + case pl0: + return CRL_APB_PL0_REF_CTRL; + case pl1: + return CRL_APB_PL1_REF_CTRL; + case pl2: + return CRL_APB_PL2_REF_CTRL; + case pl3: + return CRL_APB_PL3_REF_CTRL; + case wdt: + return CRF_APB_TOPSW_LSBUS_CTRL; + case iopll_to_fpd: + return CRL_APB_IOPLL_TO_FPD_CTRL; default: debug("Invalid clk id%d\n", id); } @@ -278,6 +290,22 @@ static enum zynqmp_clk zynqmp_clk_get_peripheral_pll(u32 clk_ctrl) } } +static enum zynqmp_clk zynqmp_clk_get_wdt_pll(u32 clk_ctrl) +{ + u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >> + CLK_CTRL_SRCSEL_SHIFT; + + switch (srcsel) { + case 2: + return iopll_to_fpd; + case 3: + return dpll; + case 0 ... 1: + default: + return apll; + } +} + static ulong zynqmp_clk_get_pll_src(ulong clk_ctrl, struct zynqmp_clk_priv *priv, bool is_pre_src) @@ -420,6 +448,49 @@ static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv, DIV_ROUND_CLOSEST(pllrate, div0), div1); } +static ulong zynqmp_clk_get_wdt_rate(struct zynqmp_clk_priv *priv, + enum zynqmp_clk id, bool two_divs) +{ + enum zynqmp_clk pll; + u32 clk_ctrl, div0; + u32 div1 = 1; + int ret; + ulong pllrate; + + ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl); + if (ret) { + printf("%d %s mio read fail\n", __LINE__, __func__); + return -EIO; + } + + div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT; + if (!div0) + div0 = 1; + + pll = zynqmp_clk_get_wdt_pll(clk_ctrl); + if (two_divs) { + ret = zynqmp_mmio_read(zynqmp_clk_get_register(pll), &clk_ctrl); + if (ret) { + printf("%d %s mio read fail\n", __LINE__, __func__); + return -EIO; + } + div1 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT; + if (!div1) + div1 = 1; + } + + if (pll == iopll_to_fpd) + pll = iopll; + + pllrate = zynqmp_clk_get_pll_rate(priv, pll); + if (IS_ERR_VALUE(pllrate)) + return pllrate; + + return + DIV_ROUND_CLOSEST( + DIV_ROUND_CLOSEST(pllrate, div0), div1); +} + static unsigned long zynqmp_clk_calc_peripheral_two_divs(ulong rate, ulong pll_rate, u32 *div0, u32 *div1) @@ -510,8 +581,12 @@ static ulong zynqmp_clk_get_rate(struct clk *clk) return zynqmp_clk_get_ddr_rate(priv); case gem0_ref ... gem3_ref: case qspi_ref ... can1_ref: + case pl0 ... pl3: two_divs = true; return zynqmp_clk_get_peripheral_rate(priv, id, two_divs); + case wdt: + two_divs = true; + return zynqmp_clk_get_wdt_rate(priv, id, two_divs); default: return -ENXIO; } diff --git a/drivers/fpga/fpga.c b/drivers/fpga/fpga.c index 6aead27f16..ac01612d75 100644 --- a/drivers/fpga/fpga.c +++ b/drivers/fpga/fpga.c @@ -148,20 +148,21 @@ int fpga_add(fpga_type devtype, void *desc) { int devnum = FPGA_INVALID_DEVICE; + if (!desc) { + printf("%s: NULL device descriptor\n", __func__); + return devnum; + } + if (next_desc < 0) { printf("%s: FPGA support not initialized!\n", __func__); } else if ((devtype > fpga_min_type) && (devtype < fpga_undefined)) { - if (desc) { - if (next_desc < CONFIG_MAX_FPGA_DEVICES) { - devnum = next_desc; - desc_table[next_desc].devtype = devtype; - desc_table[next_desc++].devdesc = desc; - } else { - printf("%s: Exceeded Max FPGA device count\n", - __func__); - } + if (next_desc < CONFIG_MAX_FPGA_DEVICES) { + devnum = next_desc; + desc_table[next_desc].devtype = devtype; + desc_table[next_desc++].devdesc = desc; } else { - printf("%s: NULL device descriptor\n", __func__); + printf("%s: Exceeded Max FPGA device count\n", + __func__); } } else { printf("%s: Unsupported FPGA type %d\n", __func__, devtype); diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c index 7243100219..559f29b801 100644 --- a/drivers/gpio/omap_gpio.c +++ b/drivers/gpio/omap_gpio.c @@ -345,6 +345,7 @@ U_BOOT_DRIVER(gpio_omap) = { .bind = omap_gpio_bind, .probe = omap_gpio_probe, .priv_auto_alloc_size = sizeof(struct gpio_bank), + .flags = DM_FLAG_PRE_RELOC, }; #endif /* CONFIG_DM_GPIO */ diff --git a/drivers/i2c/imx_lpi2c.c b/drivers/i2c/imx_lpi2c.c index de74e89efd..32d7809dba 100644 --- a/drivers/i2c/imx_lpi2c.c +++ b/drivers/i2c/imx_lpi2c.c @@ -156,7 +156,7 @@ static int bus_i2c_receive(struct imx_lpi2c_reg *regs, u8 *rxbuf, int len) static int bus_i2c_start(struct imx_lpi2c_reg *regs, u8 addr, u8 dir) { - lpi2c_status_t result = LPI2C_SUCESS; + lpi2c_status_t result; u32 val; result = imx_lpci2c_check_busy_bus(regs); @@ -184,7 +184,7 @@ static int bus_i2c_start(struct imx_lpi2c_reg *regs, u8 addr, u8 dir) static int bus_i2c_stop(struct imx_lpi2c_reg *regs) { - lpi2c_status_t result = LPI2C_SUCESS; + lpi2c_status_t result; u32 status; result = bus_i2c_wait_for_tx_ready(regs); @@ -213,7 +213,7 @@ static int bus_i2c_stop(struct imx_lpi2c_reg *regs) static int bus_i2c_read(struct imx_lpi2c_reg *regs, u32 chip, u8 *buf, int len) { - lpi2c_status_t result = LPI2C_SUCESS; + lpi2c_status_t result; result = bus_i2c_start(regs, chip, 1); if (result) @@ -230,7 +230,7 @@ static int bus_i2c_read(struct imx_lpi2c_reg *regs, u32 chip, u8 *buf, int len) static int bus_i2c_write(struct imx_lpi2c_reg *regs, u32 chip, u8 *buf, int len) { - lpi2c_status_t result = LPI2C_SUCESS; + lpi2c_status_t result; result = bus_i2c_start(regs, chip, 0); if (result) @@ -354,7 +354,7 @@ static int imx_lpi2c_probe_chip(struct udevice *bus, u32 chip, u32 chip_flags) { struct imx_lpi2c_reg *regs; - lpi2c_status_t result = LPI2C_SUCESS; + lpi2c_status_t result; regs = (struct imx_lpi2c_reg *)devfdt_get_addr(bus); result = bus_i2c_start(regs, chip, 0); diff --git a/drivers/mtd/nand/arasan_nfc.c b/drivers/mtd/nand/arasan_nfc.c index 3c9a0215c5..9c82c7db33 100644 --- a/drivers/mtd/nand/arasan_nfc.c +++ b/drivers/mtd/nand/arasan_nfc.c @@ -86,7 +86,7 @@ struct arasan_nand_command_format { #define ARASAN_NAND_CMD_ADDR_CYCL_MASK 0x70000000 #define ARASAN_NAND_CMD_ADDR_CYCL_SHIFT 28 -#define ARASAN_NAND_MEM_ADDR1_PAGE_MASK 0xFFFF0000 +#define ARASAN_NAND_MEM_ADDR1_PAGE_MASK 0xFFFF #define ARASAN_NAND_MEM_ADDR1_COL_MASK 0xFFFF #define ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT 16 #define ARASAN_NAND_MEM_ADDR2_PAGE_MASK 0xFF @@ -795,10 +795,11 @@ static int arasan_nand_erase(struct arasan_nand_command_format *curr_cmd, writel(reg_val, &arasan_nand_base->cmd_reg); - page = (page_addr << ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT) & + page = (page_addr >> ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT) & ARASAN_NAND_MEM_ADDR1_PAGE_MASK; column = page_addr & ARASAN_NAND_MEM_ADDR1_COL_MASK; - writel(page | column, &arasan_nand_base->memadr_reg1); + writel(column | (page << ARASAN_NAND_MEM_ADDR1_PAGE_SHIFT), + &arasan_nand_base->memadr_reg1); reg_val = readl(&arasan_nand_base->memadr_reg2); reg_val &= ~ARASAN_NAND_MEM_ADDR2_PAGE_MASK; diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 294d9f9d79..2e61685d3e 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -320,7 +320,7 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) erase_size = flash->erase_size; if (offset % erase_size || len % erase_size) { - debug("SF: Erase offset/length not multiple of erase size\n"); + printf("SF: Erase offset/length not multiple of erase size\n"); return -1; } diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index de1947ccc1..f589978b43 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1,4 +1,5 @@ source "drivers/net/phy/Kconfig" +source "drivers/net/pfe_eth/Kconfig" config DM_ETH bool "Enable Driver Model for Ethernet drivers" diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 4a16c62bac..2687fbbdb2 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -23,7 +23,6 @@ obj-$(CONFIG_E1000_SPI) += e1000_spi.o obj-$(CONFIG_EEPRO100) += eepro100.o obj-$(CONFIG_SUN4I_EMAC) += sunxi_emac.o obj-$(CONFIG_SUN8I_EMAC) += sun8i_emac.o -obj-$(CONFIG_ENC28J60) += enc28j60.o obj-$(CONFIG_EP93XX) += ep93xx_eth.o obj-$(CONFIG_ETHOC) += ethoc.o obj-$(CONFIG_FEC_MXC) += fec_mxc.o @@ -73,3 +72,4 @@ obj-$(CONFIG_FSL_MEMAC) += fm/memac_phy.o obj-$(CONFIG_VSC9953) += vsc9953.o obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o +obj-$(CONFIG_FSL_PFE) += pfe_eth/ diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c index b72258f83b..e2395dbeb9 100644 --- a/drivers/net/cpsw.c +++ b/drivers/net/cpsw.c @@ -949,7 +949,7 @@ static int _cpsw_recv(struct cpsw_priv *priv, uchar **pkt) { void *buffer; int len; - int ret = -EAGAIN; + int ret; ret = cpdma_process(priv, &priv->rx_chan, &buffer, &len); if (ret < 0) diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c deleted file mode 100644 index 588a84d7a9..0000000000 --- a/drivers/net/enc28j60.c +++ /dev/null @@ -1,959 +0,0 @@ -/* - * (C) Copyright 2010 - * Reinhard Meyer, EMK Elektronik, reinhard.meyer@emk-elektronik.de - * Martin Krause, Martin.Krause@tqs.de - * reworked original enc28j60.c - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <net.h> -#include <spi.h> -#include <malloc.h> -#include <netdev.h> -#include <miiphy.h> -#include "enc28j60.h" - -/* - * IMPORTANT: spi_claim_bus() and spi_release_bus() - * are called at begin and end of each of the following functions: - * enc_miiphy_read(), enc_miiphy_write(), enc_write_hwaddr(), - * enc_init(), enc_recv(), enc_send(), enc_halt() - * ALL other functions assume that the bus has already been claimed! - * Since net_process_received_packet() might call enc_send() in return, the bus - * must be released, net_process_received_packet() called and claimed again. - */ - -/* - * Controller memory layout. - * We only allow 1 frame for transmission and reserve the rest - * for reception to handle as many broadcast packets as possible. - * Also use the memory from 0x0000 for receiver buffer. See errata pt. 5 - * 0x0000 - 0x19ff 6656 bytes receive buffer - * 0x1a00 - 0x1fff 1536 bytes transmit buffer = - * control(1)+frame(1518)+status(7)+reserve(10). - */ -#define ENC_RX_BUF_START 0x0000 -#define ENC_RX_BUF_END 0x19ff -#define ENC_TX_BUF_START 0x1a00 -#define ENC_TX_BUF_END 0x1fff -#define ENC_MAX_FRM_LEN 1518 -#define RX_RESET_COUNTER 1000 - -/* - * For non data transfer functions, like phy read/write, set hwaddr, init - * we do not need a full, time consuming init including link ready wait. - * This enum helps to bring the chip through the minimum necessary inits. - */ -enum enc_initstate {none=0, setupdone, linkready}; -typedef struct enc_device { - struct eth_device *dev; /* back pointer */ - struct spi_slave *slave; - int rx_reset_counter; - u16 next_pointer; - u8 bank; /* current bank in enc28j60 */ - enum enc_initstate initstate; -} enc_dev_t; - -/* - * enc_bset: set bits in a common register - * enc_bclr: clear bits in a common register - * - * making the reg parameter u8 will give a compile time warning if the - * functions are called with a register not accessible in all Banks - */ -static void enc_bset(enc_dev_t *enc, const u8 reg, const u8 data) -{ - u8 dout[2]; - - dout[0] = CMD_BFS(reg); - dout[1] = data; - spi_xfer(enc->slave, 2 * 8, dout, NULL, - SPI_XFER_BEGIN | SPI_XFER_END); -} - -static void enc_bclr(enc_dev_t *enc, const u8 reg, const u8 data) -{ - u8 dout[2]; - - dout[0] = CMD_BFC(reg); - dout[1] = data; - spi_xfer(enc->slave, 2 * 8, dout, NULL, - SPI_XFER_BEGIN | SPI_XFER_END); -} - -/* - * high byte of the register contains bank number: - * 0: no bank switch necessary - * 1: switch to bank 0 - * 2: switch to bank 1 - * 3: switch to bank 2 - * 4: switch to bank 3 - */ -static void enc_set_bank(enc_dev_t *enc, const u16 reg) -{ - u8 newbank = reg >> 8; - - if (newbank == 0 || newbank == enc->bank) - return; - switch (newbank) { - case 1: - enc_bclr(enc, CTL_REG_ECON1, - ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1); - break; - case 2: - enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_BSEL0); - enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_BSEL1); - break; - case 3: - enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_BSEL0); - enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_BSEL1); - break; - case 4: - enc_bset(enc, CTL_REG_ECON1, - ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1); - break; - } - enc->bank = newbank; -} - -/* - * local functions to access SPI - * - * reg: register inside ENC28J60 - * data: 8/16 bits to write - * c: number of retries - * - * enc_r8: read 8 bits - * enc_r16: read 16 bits - * enc_w8: write 8 bits - * enc_w16: write 16 bits - * enc_w8_retry: write 8 bits, verify and retry - * enc_rbuf: read from ENC28J60 into buffer - * enc_wbuf: write from buffer into ENC28J60 - */ - -/* - * MAC and MII registers need a 3 byte SPI transfer to read, - * all other registers need a 2 byte SPI transfer. - */ -static int enc_reg2nbytes(const u16 reg) -{ - /* check if MAC or MII register */ - return ((reg >= CTL_REG_MACON1 && reg <= CTL_REG_MIRDH) || - (reg >= CTL_REG_MAADR1 && reg <= CTL_REG_MAADR4) || - (reg == CTL_REG_MISTAT)) ? 3 : 2; -} - -/* - * Read a byte register - */ -static u8 enc_r8(enc_dev_t *enc, const u16 reg) -{ - u8 dout[3]; - u8 din[3]; - int nbytes = enc_reg2nbytes(reg); - - enc_set_bank(enc, reg); - dout[0] = CMD_RCR(reg); - spi_xfer(enc->slave, nbytes * 8, dout, din, - SPI_XFER_BEGIN | SPI_XFER_END); - return din[nbytes-1]; -} - -/* - * Read a L/H register pair and return a word. - * Must be called with the L register's address. - */ -static u16 enc_r16(enc_dev_t *enc, const u16 reg) -{ - u8 dout[3]; - u8 din[3]; - u16 result; - int nbytes = enc_reg2nbytes(reg); - - enc_set_bank(enc, reg); - dout[0] = CMD_RCR(reg); - spi_xfer(enc->slave, nbytes * 8, dout, din, - SPI_XFER_BEGIN | SPI_XFER_END); - result = din[nbytes-1]; - dout[0]++; /* next register */ - spi_xfer(enc->slave, nbytes * 8, dout, din, - SPI_XFER_BEGIN | SPI_XFER_END); - result |= din[nbytes-1] << 8; - return result; -} - -/* - * Write a byte register - */ -static void enc_w8(enc_dev_t *enc, const u16 reg, const u8 data) -{ - u8 dout[2]; - - enc_set_bank(enc, reg); - dout[0] = CMD_WCR(reg); - dout[1] = data; - spi_xfer(enc->slave, 2 * 8, dout, NULL, - SPI_XFER_BEGIN | SPI_XFER_END); -} - -/* - * Write a L/H register pair. - * Must be called with the L register's address. - */ -static void enc_w16(enc_dev_t *enc, const u16 reg, const u16 data) -{ - u8 dout[2]; - - enc_set_bank(enc, reg); - dout[0] = CMD_WCR(reg); - dout[1] = data; - spi_xfer(enc->slave, 2 * 8, dout, NULL, - SPI_XFER_BEGIN | SPI_XFER_END); - dout[0]++; /* next register */ - dout[1] = data >> 8; - spi_xfer(enc->slave, 2 * 8, dout, NULL, - SPI_XFER_BEGIN | SPI_XFER_END); -} - -/* - * Write a byte register, verify and retry - */ -static void enc_w8_retry(enc_dev_t *enc, const u16 reg, const u8 data, const int c) -{ - u8 dout[2]; - u8 readback; - int i; - - enc_set_bank(enc, reg); - for (i = 0; i < c; i++) { - dout[0] = CMD_WCR(reg); - dout[1] = data; - spi_xfer(enc->slave, 2 * 8, dout, NULL, - SPI_XFER_BEGIN | SPI_XFER_END); - readback = enc_r8(enc, reg); - if (readback == data) - break; - /* wait 1ms */ - udelay(1000); - } - if (i == c) { - printf("%s: write reg 0x%03x failed\n", enc->dev->name, reg); - } -} - -/* - * Read ENC RAM into buffer - */ -static void enc_rbuf(enc_dev_t *enc, const u16 length, u8 *buf) -{ - u8 dout[1]; - - dout[0] = CMD_RBM; - spi_xfer(enc->slave, 8, dout, NULL, SPI_XFER_BEGIN); - spi_xfer(enc->slave, length * 8, NULL, buf, SPI_XFER_END); -#ifdef DEBUG - puts("Rx:\n"); - print_buffer(0, buf, 1, length, 0); -#endif -} - -/* - * Write buffer into ENC RAM - */ -static void enc_wbuf(enc_dev_t *enc, const u16 length, const u8 *buf, const u8 control) -{ - u8 dout[2]; - dout[0] = CMD_WBM; - dout[1] = control; - spi_xfer(enc->slave, 2 * 8, dout, NULL, SPI_XFER_BEGIN); - spi_xfer(enc->slave, length * 8, buf, NULL, SPI_XFER_END); -#ifdef DEBUG - puts("Tx:\n"); - print_buffer(0, buf, 1, length, 0); -#endif -} - -/* - * Try to claim the SPI bus. - * Print error message on failure. - */ -static int enc_claim_bus(enc_dev_t *enc) -{ - int rc = spi_claim_bus(enc->slave); - if (rc) - printf("%s: failed to claim SPI bus\n", enc->dev->name); - return rc; -} - -/* - * Release previously claimed SPI bus. - * This function is mainly for symmetry to enc_claim_bus(). - * Let the toolchain decide to inline it... - */ -static void enc_release_bus(enc_dev_t *enc) -{ - spi_release_bus(enc->slave); -} - -/* - * Read PHY register - */ -static u16 enc_phy_read(enc_dev_t *enc, const u8 addr) -{ - uint64_t etime; - u8 status; - - enc_w8(enc, CTL_REG_MIREGADR, addr); - enc_w8(enc, CTL_REG_MICMD, ENC_MICMD_MIIRD); - /* 1 second timeout - only happens on hardware problem */ - etime = get_ticks() + get_tbclk(); - /* poll MISTAT.BUSY bit until operation is complete */ - do - { - status = enc_r8(enc, CTL_REG_MISTAT); - } while (get_ticks() <= etime && (status & ENC_MISTAT_BUSY)); - if (status & ENC_MISTAT_BUSY) { - printf("%s: timeout reading phy\n", enc->dev->name); - return 0; - } - enc_w8(enc, CTL_REG_MICMD, 0); - return enc_r16(enc, CTL_REG_MIRDL); -} - -/* - * Write PHY register - */ -static void enc_phy_write(enc_dev_t *enc, const u8 addr, const u16 data) -{ - uint64_t etime; - u8 status; - - enc_w8(enc, CTL_REG_MIREGADR, addr); - enc_w16(enc, CTL_REG_MIWRL, data); - /* 1 second timeout - only happens on hardware problem */ - etime = get_ticks() + get_tbclk(); - /* poll MISTAT.BUSY bit until operation is complete */ - do - { - status = enc_r8(enc, CTL_REG_MISTAT); - } while (get_ticks() <= etime && (status & ENC_MISTAT_BUSY)); - if (status & ENC_MISTAT_BUSY) { - printf("%s: timeout writing phy\n", enc->dev->name); - return; - } -} - -/* - * Verify link status, wait if necessary - * - * Note: with a 10 MBit/s only PHY there is no autonegotiation possible, - * half/full duplex is a pure setup matter. For the time being, this driver - * will setup in half duplex mode only. - */ -static int enc_phy_link_wait(enc_dev_t *enc) -{ - u16 status; - int duplex; - uint64_t etime; - -#ifdef CONFIG_ENC_SILENTLINK - /* check if we have a link, then just return */ - status = enc_phy_read(enc, PHY_REG_PHSTAT1); - if (status & ENC_PHSTAT1_LLSTAT) - return 0; -#endif - - /* wait for link with 1 second timeout */ - etime = get_ticks() + get_tbclk(); - while (get_ticks() <= etime) { - status = enc_phy_read(enc, PHY_REG_PHSTAT1); - if (status & ENC_PHSTAT1_LLSTAT) { - /* now we have a link */ - status = enc_phy_read(enc, PHY_REG_PHSTAT2); - duplex = (status & ENC_PHSTAT2_DPXSTAT) ? 1 : 0; - printf("%s: link up, 10Mbps %s-duplex\n", - enc->dev->name, duplex ? "full" : "half"); - return 0; - } - udelay(1000); - } - - /* timeout occurred */ - printf("%s: link down\n", enc->dev->name); - return 1; -} - -/* - * This function resets the receiver only. - */ -static void enc_reset_rx(enc_dev_t *enc) -{ - u8 econ1; - - econ1 = enc_r8(enc, CTL_REG_ECON1); - if ((econ1 & ENC_ECON1_RXRST) == 0) { - enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_RXRST); - enc->rx_reset_counter = RX_RESET_COUNTER; - } -} - -/* - * Reset receiver and reenable it. - */ -static void enc_reset_rx_call(enc_dev_t *enc) -{ - enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_RXRST); - enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_RXEN); -} - -/* - * Copy a packet from the receive ring and forward it to - * the protocol stack. - */ -static void enc_receive(enc_dev_t *enc) -{ - u8 *packet = (u8 *)net_rx_packets[0]; - u16 pkt_len; - u16 copy_len; - u16 status; - u8 pkt_cnt = 0; - u16 rxbuf_rdpt; - u8 hbuf[6]; - - enc_w16(enc, CTL_REG_ERDPTL, enc->next_pointer); - do { - enc_rbuf(enc, 6, hbuf); - enc->next_pointer = hbuf[0] | (hbuf[1] << 8); - pkt_len = hbuf[2] | (hbuf[3] << 8); - status = hbuf[4] | (hbuf[5] << 8); - debug("next_pointer=$%04x pkt_len=%u status=$%04x\n", - enc->next_pointer, pkt_len, status); - if (pkt_len <= ENC_MAX_FRM_LEN) - copy_len = pkt_len; - else - copy_len = 0; - if ((status & (1L << 7)) == 0) /* check Received Ok bit */ - copy_len = 0; - /* check if next pointer is resonable */ - if (enc->next_pointer >= ENC_TX_BUF_START) - copy_len = 0; - if (copy_len > 0) { - enc_rbuf(enc, copy_len, packet); - } - /* advance read pointer to next pointer */ - enc_w16(enc, CTL_REG_ERDPTL, enc->next_pointer); - /* decrease packet counter */ - enc_bset(enc, CTL_REG_ECON2, ENC_ECON2_PKTDEC); - /* - * Only odd values should be written to ERXRDPTL, - * see errata B4 pt.13 - */ - rxbuf_rdpt = enc->next_pointer - 1; - if ((rxbuf_rdpt < enc_r16(enc, CTL_REG_ERXSTL)) || - (rxbuf_rdpt > enc_r16(enc, CTL_REG_ERXNDL))) { - enc_w16(enc, CTL_REG_ERXRDPTL, - enc_r16(enc, CTL_REG_ERXNDL)); - } else { - enc_w16(enc, CTL_REG_ERXRDPTL, rxbuf_rdpt); - } - /* read pktcnt */ - pkt_cnt = enc_r8(enc, CTL_REG_EPKTCNT); - if (copy_len == 0) { - (void)enc_r8(enc, CTL_REG_EIR); - enc_reset_rx(enc); - printf("%s: receive copy_len=0\n", enc->dev->name); - continue; - } - /* - * Because net_process_received_packet() might call enc_send(), - * we need to release the SPI bus, call - * net_process_received_packet(), reclaim the bus. - */ - enc_release_bus(enc); - net_process_received_packet(packet, pkt_len); - if (enc_claim_bus(enc)) - return; - (void)enc_r8(enc, CTL_REG_EIR); - } while (pkt_cnt); - /* Use EPKTCNT not EIR.PKTIF flag, see errata pt. 6 */ -} - -/* - * Poll for completely received packets. - */ -static void enc_poll(enc_dev_t *enc) -{ - u8 eir_reg; - u8 pkt_cnt; - - (void)enc_r8(enc, CTL_REG_ESTAT); - eir_reg = enc_r8(enc, CTL_REG_EIR); - if (eir_reg & ENC_EIR_TXIF) { - /* clear TXIF bit in EIR */ - enc_bclr(enc, CTL_REG_EIR, ENC_EIR_TXIF); - } - /* We have to use pktcnt and not pktif bit, see errata pt. 6 */ - pkt_cnt = enc_r8(enc, CTL_REG_EPKTCNT); - if (pkt_cnt > 0) { - if ((eir_reg & ENC_EIR_PKTIF) == 0) { - debug("enc_poll: pkt cnt > 0, but pktif not set\n"); - } - enc_receive(enc); - /* - * clear PKTIF bit in EIR, this should not need to be done - * but it seems like we get problems if we do not - */ - enc_bclr(enc, CTL_REG_EIR, ENC_EIR_PKTIF); - } - if (eir_reg & ENC_EIR_RXERIF) { - printf("%s: rx error\n", enc->dev->name); - enc_bclr(enc, CTL_REG_EIR, ENC_EIR_RXERIF); - } - if (eir_reg & ENC_EIR_TXERIF) { - printf("%s: tx error\n", enc->dev->name); - enc_bclr(enc, CTL_REG_EIR, ENC_EIR_TXERIF); - } -} - -/* - * Completely Reset the ENC - */ -static void enc_reset(enc_dev_t *enc) -{ - u8 dout[1]; - - dout[0] = CMD_SRC; - spi_xfer(enc->slave, 8, dout, NULL, - SPI_XFER_BEGIN | SPI_XFER_END); - /* sleep 1 ms. See errata pt. 2 */ - udelay(1000); -} - -/* - * Initialisation data for most of the ENC registers - */ -static const u16 enc_initdata[] = { - /* - * Setup the buffer space. The reset values are valid for the - * other pointers. - * - * We shall not write to ERXST, see errata pt. 5. Instead we - * have to make sure that ENC_RX_BUS_START is 0. - */ - CTL_REG_ERXSTL, ENC_RX_BUF_START, - CTL_REG_ERXSTH, ENC_RX_BUF_START >> 8, - CTL_REG_ERXNDL, ENC_RX_BUF_END, - CTL_REG_ERXNDH, ENC_RX_BUF_END >> 8, - CTL_REG_ERDPTL, ENC_RX_BUF_START, - CTL_REG_ERDPTH, ENC_RX_BUF_START >> 8, - /* - * Set the filter to receive only good-CRC, unicast and broadcast - * frames. - * Note: some DHCP servers return their answers as broadcasts! - * So its unwise to remove broadcast from this. This driver - * might incur receiver overruns with packet loss on a broadcast - * flooded network. - */ - CTL_REG_ERXFCON, ENC_RFR_BCEN | ENC_RFR_UCEN | ENC_RFR_CRCEN, - - /* enable MAC to receive frames */ - CTL_REG_MACON1, - ENC_MACON1_MARXEN | ENC_MACON1_TXPAUS | ENC_MACON1_RXPAUS, - - /* configure pad, tx-crc and duplex */ - CTL_REG_MACON3, - ENC_MACON3_PADCFG0 | ENC_MACON3_TXCRCEN | - ENC_MACON3_FRMLNEN, - - /* Allow infinite deferals if the medium is continously busy */ - CTL_REG_MACON4, ENC_MACON4_DEFER, - - /* Late collisions occur beyond 63 bytes */ - CTL_REG_MACLCON2, 63, - - /* - * Set (low byte) Non-Back-to_Back Inter-Packet Gap. - * Recommended 0x12 - */ - CTL_REG_MAIPGL, 0x12, - - /* - * Set (high byte) Non-Back-to_Back Inter-Packet Gap. - * Recommended 0x0c for half-duplex. Nothing for full-duplex - */ - CTL_REG_MAIPGH, 0x0C, - - /* set maximum frame length */ - CTL_REG_MAMXFLL, ENC_MAX_FRM_LEN, - CTL_REG_MAMXFLH, ENC_MAX_FRM_LEN >> 8, - - /* - * Set MAC back-to-back inter-packet gap. - * Recommended 0x12 for half duplex - * and 0x15 for full duplex. - */ - CTL_REG_MABBIPG, 0x12, - - /* end of table */ - 0xffff -}; - -/* - * Wait for the XTAL oscillator to become ready - */ -static int enc_clock_wait(enc_dev_t *enc) -{ - uint64_t etime; - - /* one second timeout */ - etime = get_ticks() + get_tbclk(); - - /* - * Wait for CLKRDY to become set (i.e., check that we can - * communicate with the ENC) - */ - do - { - if (enc_r8(enc, CTL_REG_ESTAT) & ENC_ESTAT_CLKRDY) - return 0; - } while (get_ticks() <= etime); - - printf("%s: timeout waiting for CLKRDY\n", enc->dev->name); - return -1; -} - -/* - * Write the MAC address into the ENC - */ -static int enc_write_macaddr(enc_dev_t *enc) -{ - unsigned char *p = enc->dev->enetaddr; - - enc_w8_retry(enc, CTL_REG_MAADR5, *p++, 5); - enc_w8_retry(enc, CTL_REG_MAADR4, *p++, 5); - enc_w8_retry(enc, CTL_REG_MAADR3, *p++, 5); - enc_w8_retry(enc, CTL_REG_MAADR2, *p++, 5); - enc_w8_retry(enc, CTL_REG_MAADR1, *p++, 5); - enc_w8_retry(enc, CTL_REG_MAADR0, *p, 5); - return 0; -} - -/* - * Setup most of the ENC registers - */ -static int enc_setup(enc_dev_t *enc) -{ - u16 phid1 = 0; - u16 phid2 = 0; - const u16 *tp; - - /* reset enc struct values */ - enc->next_pointer = ENC_RX_BUF_START; - enc->rx_reset_counter = RX_RESET_COUNTER; - enc->bank = 0xff; /* invalidate current bank in enc28j60 */ - - /* verify PHY identification */ - phid1 = enc_phy_read(enc, PHY_REG_PHID1); - phid2 = enc_phy_read(enc, PHY_REG_PHID2) & ENC_PHID2_MASK; - if (phid1 != ENC_PHID1_VALUE || phid2 != ENC_PHID2_VALUE) { - printf("%s: failed to identify PHY. Found %04x:%04x\n", - enc->dev->name, phid1, phid2); - return -1; - } - - /* now program registers */ - for (tp = enc_initdata; *tp != 0xffff; tp += 2) - enc_w8_retry(enc, tp[0], tp[1], 10); - - /* - * Prevent automatic loopback of data beeing transmitted by setting - * ENC_PHCON2_HDLDIS - */ - enc_phy_write(enc, PHY_REG_PHCON2, (1<<8)); - - /* - * LEDs configuration - * LEDA: LACFG = 0100 -> display link status - * LEDB: LBCFG = 0111 -> display TX & RX activity - * STRCH = 1 -> LED pulses - */ - enc_phy_write(enc, PHY_REG_PHLCON, 0x0472); - - /* Reset PDPXMD-bit => half duplex */ - enc_phy_write(enc, PHY_REG_PHCON1, 0); - - return 0; -} - -/* - * Check if ENC has been initialized. - * If not, try to initialize it. - * Remember initialized state in struct. - */ -static int enc_initcheck(enc_dev_t *enc, const enum enc_initstate requiredstate) -{ - if (enc->initstate >= requiredstate) - return 0; - - if (enc->initstate < setupdone) { - /* Initialize the ENC only */ - enc_reset(enc); - /* if any of functions fails, skip the rest and return an error */ - if (enc_clock_wait(enc) || enc_setup(enc) || enc_write_macaddr(enc)) { - return -1; - } - enc->initstate = setupdone; - } - /* if that's all we need, return here */ - if (enc->initstate >= requiredstate) - return 0; - - /* now wait for link ready condition */ - if (enc_phy_link_wait(enc)) { - return -1; - } - enc->initstate = linkready; - return 0; -} - -#if defined(CONFIG_CMD_MII) -/* - * Read a PHY register. - * - * This function is registered with miiphy_register(). - */ -int enc_miiphy_read(struct mii_dev *bus, int phy_adr, int devad, int reg) -{ - u16 value = 0; - struct eth_device *dev = eth_get_dev_by_name(bus->name); - enc_dev_t *enc; - - if (!dev || phy_adr != 0) - return -1; - - enc = dev->priv; - if (enc_claim_bus(enc)) - return -1; - if (enc_initcheck(enc, setupdone)) { - enc_release_bus(enc); - return -1; - } - value = enc_phy_read(enc, reg); - enc_release_bus(enc); - return value; -} - -/* - * Write a PHY register. - * - * This function is registered with miiphy_register(). - */ -int enc_miiphy_write(struct mii_dev *bus, int phy_adr, int devad, int reg, - u16 value) -{ - struct eth_device *dev = eth_get_dev_by_name(bus->name); - enc_dev_t *enc; - - if (!dev || phy_adr != 0) - return -1; - - enc = dev->priv; - if (enc_claim_bus(enc)) - return -1; - if (enc_initcheck(enc, setupdone)) { - enc_release_bus(enc); - return -1; - } - enc_phy_write(enc, reg, value); - enc_release_bus(enc); - return 0; -} -#endif - -/* - * Write hardware (MAC) address. - * - * This function entered into eth_device structure. - */ -static int enc_write_hwaddr(struct eth_device *dev) -{ - enc_dev_t *enc = dev->priv; - - if (enc_claim_bus(enc)) - return -1; - if (enc_initcheck(enc, setupdone)) { - enc_release_bus(enc); - return -1; - } - enc_release_bus(enc); - return 0; -} - -/* - * Initialize ENC28J60 for use. - * - * This function entered into eth_device structure. - */ -static int enc_init(struct eth_device *dev, bd_t *bis) -{ - enc_dev_t *enc = dev->priv; - - if (enc_claim_bus(enc)) - return -1; - if (enc_initcheck(enc, linkready)) { - enc_release_bus(enc); - return -1; - } - /* enable receive */ - enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_RXEN); - enc_release_bus(enc); - return 0; -} - -/* - * Check for received packets. - * - * This function entered into eth_device structure. - */ -static int enc_recv(struct eth_device *dev) -{ - enc_dev_t *enc = dev->priv; - - if (enc_claim_bus(enc)) - return -1; - if (enc_initcheck(enc, linkready)) { - enc_release_bus(enc); - return -1; - } - /* Check for dead receiver */ - if (enc->rx_reset_counter > 0) - enc->rx_reset_counter--; - else - enc_reset_rx_call(enc); - enc_poll(enc); - enc_release_bus(enc); - return 0; -} - -/* - * Send a packet. - * - * This function entered into eth_device structure. - * - * Should we wait here until we have a Link? Or shall we leave that to - * protocol retries? - */ -static int enc_send( - struct eth_device *dev, - void *packet, - int length) -{ - enc_dev_t *enc = dev->priv; - - if (enc_claim_bus(enc)) - return -1; - if (enc_initcheck(enc, linkready)) { - enc_release_bus(enc); - return -1; - } - /* setup transmit pointers */ - enc_w16(enc, CTL_REG_EWRPTL, ENC_TX_BUF_START); - enc_w16(enc, CTL_REG_ETXNDL, length + ENC_TX_BUF_START); - enc_w16(enc, CTL_REG_ETXSTL, ENC_TX_BUF_START); - /* write packet to ENC */ - enc_wbuf(enc, length, (u8 *) packet, 0x00); - /* - * Check that the internal transmit logic has not been altered - * by excessive collisions. Reset transmitter if so. - * See Errata B4 12 and 14. - */ - if (enc_r8(enc, CTL_REG_EIR) & ENC_EIR_TXERIF) { - enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_TXRST); - enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_TXRST); - } - enc_bclr(enc, CTL_REG_EIR, (ENC_EIR_TXERIF | ENC_EIR_TXIF)); - /* start transmitting */ - enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_TXRTS); - enc_release_bus(enc); - return 0; -} - -/* - * Finish use of ENC. - * - * This function entered into eth_device structure. - */ -static void enc_halt(struct eth_device *dev) -{ - enc_dev_t *enc = dev->priv; - - if (enc_claim_bus(enc)) - return; - /* Just disable receiver */ - enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_RXEN); - enc_release_bus(enc); -} - -/* - * This is the only exported function. - * - * It may be called several times with different bus:cs combinations. - */ -int enc28j60_initialize(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) -{ - struct eth_device *dev; - enc_dev_t *enc; - - /* try to allocate, check and clear eth_device object */ - dev = malloc(sizeof(*dev)); - if (!dev) { - return -1; - } - memset(dev, 0, sizeof(*dev)); - - /* try to allocate, check and clear enc_dev_t object */ - enc = malloc(sizeof(*enc)); - if (!enc) { - free(dev); - return -1; - } - memset(enc, 0, sizeof(*enc)); - - /* try to setup the SPI slave */ - enc->slave = spi_setup_slave(bus, cs, max_hz, mode); - if (!enc->slave) { - printf("enc28j60: invalid SPI device %i:%i\n", bus, cs); - free(enc); - free(dev); - return -1; - } - - enc->dev = dev; - /* now fill the eth_device object */ - dev->priv = enc; - dev->init = enc_init; - dev->halt = enc_halt; - dev->send = enc_send; - dev->recv = enc_recv; - dev->write_hwaddr = enc_write_hwaddr; - sprintf(dev->name, "enc%i.%i", bus, cs); - eth_register(dev); -#if defined(CONFIG_CMD_MII) - int retval; - struct mii_dev *mdiodev = mdio_alloc(); - if (!mdiodev) - return -ENOMEM; - strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN); - mdiodev->read = enc_miiphy_read; - mdiodev->write = enc_miiphy_write; - - retval = mdio_register(mdiodev); - if (retval < 0) - return retval; -#endif - return 0; -} diff --git a/drivers/net/enc28j60.h b/drivers/net/enc28j60.h deleted file mode 100644 index 289e41288e..0000000000 --- a/drivers/net/enc28j60.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - * (X) extracted from enc28j60.c - * Reinhard Meyer, EMK Elektronik, reinhard.meyer@emk-elektronik.de - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef _enc28j60_h -#define _enc28j60_h - -/* - * SPI Commands - * - * Bits 7-5: Command - * Bits 4-0: Register - */ -#define CMD_RCR(x) (0x00+((x)&0x1f)) /* Read Control Register */ -#define CMD_RBM 0x3a /* Read Buffer Memory */ -#define CMD_WCR(x) (0x40+((x)&0x1f)) /* Write Control Register */ -#define CMD_WBM 0x7a /* Write Buffer Memory */ -#define CMD_BFS(x) (0x80+((x)&0x1f)) /* Bit Field Set */ -#define CMD_BFC(x) (0xa0+((x)&0x1f)) /* Bit Field Clear */ -#define CMD_SRC 0xff /* System Reset Command */ - -/* NEW: encode (bank number+1) in upper byte */ - -/* Common Control Registers accessible in all Banks */ -#define CTL_REG_EIE 0x01B -#define CTL_REG_EIR 0x01C -#define CTL_REG_ESTAT 0x01D -#define CTL_REG_ECON2 0x01E -#define CTL_REG_ECON1 0x01F - -/* Control Registers accessible in Bank 0 */ -#define CTL_REG_ERDPTL 0x100 -#define CTL_REG_ERDPTH 0x101 -#define CTL_REG_EWRPTL 0x102 -#define CTL_REG_EWRPTH 0x103 -#define CTL_REG_ETXSTL 0x104 -#define CTL_REG_ETXSTH 0x105 -#define CTL_REG_ETXNDL 0x106 -#define CTL_REG_ETXNDH 0x107 -#define CTL_REG_ERXSTL 0x108 -#define CTL_REG_ERXSTH 0x109 -#define CTL_REG_ERXNDL 0x10A -#define CTL_REG_ERXNDH 0x10B -#define CTL_REG_ERXRDPTL 0x10C -#define CTL_REG_ERXRDPTH 0x10D -#define CTL_REG_ERXWRPTL 0x10E -#define CTL_REG_ERXWRPTH 0x10F -#define CTL_REG_EDMASTL 0x110 -#define CTL_REG_EDMASTH 0x111 -#define CTL_REG_EDMANDL 0x112 -#define CTL_REG_EDMANDH 0x113 -#define CTL_REG_EDMADSTL 0x114 -#define CTL_REG_EDMADSTH 0x115 -#define CTL_REG_EDMACSL 0x116 -#define CTL_REG_EDMACSH 0x117 - -/* Control Registers accessible in Bank 1 */ -#define CTL_REG_EHT0 0x200 -#define CTL_REG_EHT1 0x201 -#define CTL_REG_EHT2 0x202 -#define CTL_REG_EHT3 0x203 -#define CTL_REG_EHT4 0x204 -#define CTL_REG_EHT5 0x205 -#define CTL_REG_EHT6 0x206 -#define CTL_REG_EHT7 0x207 -#define CTL_REG_EPMM0 0x208 -#define CTL_REG_EPMM1 0x209 -#define CTL_REG_EPMM2 0x20A -#define CTL_REG_EPMM3 0x20B -#define CTL_REG_EPMM4 0x20C -#define CTL_REG_EPMM5 0x20D -#define CTL_REG_EPMM6 0x20E -#define CTL_REG_EPMM7 0x20F -#define CTL_REG_EPMCSL 0x210 -#define CTL_REG_EPMCSH 0x211 -#define CTL_REG_EPMOL 0x214 -#define CTL_REG_EPMOH 0x215 -#define CTL_REG_EWOLIE 0x216 -#define CTL_REG_EWOLIR 0x217 -#define CTL_REG_ERXFCON 0x218 -#define CTL_REG_EPKTCNT 0x219 - -/* Control Registers accessible in Bank 2 */ -#define CTL_REG_MACON1 0x300 -#define CTL_REG_MACON2 0x301 -#define CTL_REG_MACON3 0x302 -#define CTL_REG_MACON4 0x303 -#define CTL_REG_MABBIPG 0x304 -#define CTL_REG_MAIPGL 0x306 -#define CTL_REG_MAIPGH 0x307 -#define CTL_REG_MACLCON1 0x308 -#define CTL_REG_MACLCON2 0x309 -#define CTL_REG_MAMXFLL 0x30A -#define CTL_REG_MAMXFLH 0x30B -#define CTL_REG_MAPHSUP 0x30D -#define CTL_REG_MICON 0x311 -#define CTL_REG_MICMD 0x312 -#define CTL_REG_MIREGADR 0x314 -#define CTL_REG_MIWRL 0x316 -#define CTL_REG_MIWRH 0x317 -#define CTL_REG_MIRDL 0x318 -#define CTL_REG_MIRDH 0x319 - -/* Control Registers accessible in Bank 3 */ -#define CTL_REG_MAADR1 0x400 -#define CTL_REG_MAADR0 0x401 -#define CTL_REG_MAADR3 0x402 -#define CTL_REG_MAADR2 0x403 -#define CTL_REG_MAADR5 0x404 -#define CTL_REG_MAADR4 0x405 -#define CTL_REG_EBSTSD 0x406 -#define CTL_REG_EBSTCON 0x407 -#define CTL_REG_EBSTCSL 0x408 -#define CTL_REG_EBSTCSH 0x409 -#define CTL_REG_MISTAT 0x40A -#define CTL_REG_EREVID 0x412 -#define CTL_REG_ECOCON 0x415 -#define CTL_REG_EFLOCON 0x417 -#define CTL_REG_EPAUSL 0x418 -#define CTL_REG_EPAUSH 0x419 - -/* PHY Register */ -#define PHY_REG_PHCON1 0x00 -#define PHY_REG_PHSTAT1 0x01 -#define PHY_REG_PHID1 0x02 -#define PHY_REG_PHID2 0x03 -#define PHY_REG_PHCON2 0x10 -#define PHY_REG_PHSTAT2 0x11 -#define PHY_REG_PHLCON 0x14 - -/* Receive Filter Register (ERXFCON) bits */ -#define ENC_RFR_UCEN 0x80 -#define ENC_RFR_ANDOR 0x40 -#define ENC_RFR_CRCEN 0x20 -#define ENC_RFR_PMEN 0x10 -#define ENC_RFR_MPEN 0x08 -#define ENC_RFR_HTEN 0x04 -#define ENC_RFR_MCEN 0x02 -#define ENC_RFR_BCEN 0x01 - -/* ECON1 Register Bits */ -#define ENC_ECON1_TXRST 0x80 -#define ENC_ECON1_RXRST 0x40 -#define ENC_ECON1_DMAST 0x20 -#define ENC_ECON1_CSUMEN 0x10 -#define ENC_ECON1_TXRTS 0x08 -#define ENC_ECON1_RXEN 0x04 -#define ENC_ECON1_BSEL1 0x02 -#define ENC_ECON1_BSEL0 0x01 - -/* ECON2 Register Bits */ -#define ENC_ECON2_AUTOINC 0x80 -#define ENC_ECON2_PKTDEC 0x40 -#define ENC_ECON2_PWRSV 0x20 -#define ENC_ECON2_VRPS 0x08 - -/* EIR Register Bits */ -#define ENC_EIR_PKTIF 0x40 -#define ENC_EIR_DMAIF 0x20 -#define ENC_EIR_LINKIF 0x10 -#define ENC_EIR_TXIF 0x08 -#define ENC_EIR_WOLIF 0x04 -#define ENC_EIR_TXERIF 0x02 -#define ENC_EIR_RXERIF 0x01 - -/* ESTAT Register Bits */ -#define ENC_ESTAT_INT 0x80 -#define ENC_ESTAT_LATECOL 0x10 -#define ENC_ESTAT_RXBUSY 0x04 -#define ENC_ESTAT_TXABRT 0x02 -#define ENC_ESTAT_CLKRDY 0x01 - -/* EIE Register Bits */ -#define ENC_EIE_INTIE 0x80 -#define ENC_EIE_PKTIE 0x40 -#define ENC_EIE_DMAIE 0x20 -#define ENC_EIE_LINKIE 0x10 -#define ENC_EIE_TXIE 0x08 -#define ENC_EIE_WOLIE 0x04 -#define ENC_EIE_TXERIE 0x02 -#define ENC_EIE_RXERIE 0x01 - -/* MACON1 Register Bits */ -#define ENC_MACON1_LOOPBK 0x10 -#define ENC_MACON1_TXPAUS 0x08 -#define ENC_MACON1_RXPAUS 0x04 -#define ENC_MACON1_PASSALL 0x02 -#define ENC_MACON1_MARXEN 0x01 - -/* MACON2 Register Bits */ -#define ENC_MACON2_MARST 0x80 -#define ENC_MACON2_RNDRST 0x40 -#define ENC_MACON2_MARXRST 0x08 -#define ENC_MACON2_RFUNRST 0x04 -#define ENC_MACON2_MATXRST 0x02 -#define ENC_MACON2_TFUNRST 0x01 - -/* MACON3 Register Bits */ -#define ENC_MACON3_PADCFG2 0x80 -#define ENC_MACON3_PADCFG1 0x40 -#define ENC_MACON3_PADCFG0 0x20 -#define ENC_MACON3_TXCRCEN 0x10 -#define ENC_MACON3_PHDRLEN 0x08 -#define ENC_MACON3_HFRMEN 0x04 -#define ENC_MACON3_FRMLNEN 0x02 -#define ENC_MACON3_FULDPX 0x01 - -/* MACON4 Register Bits */ -#define ENC_MACON4_DEFER 0x40 - -/* MICMD Register Bits */ -#define ENC_MICMD_MIISCAN 0x02 -#define ENC_MICMD_MIIRD 0x01 - -/* MISTAT Register Bits */ -#define ENC_MISTAT_NVALID 0x04 -#define ENC_MISTAT_SCAN 0x02 -#define ENC_MISTAT_BUSY 0x01 - -/* PHID1 and PHID2 values */ -#define ENC_PHID1_VALUE 0x0083 -#define ENC_PHID2_VALUE 0x1400 -#define ENC_PHID2_MASK 0xFC00 - -/* PHCON1 values */ -#define ENC_PHCON1_PDPXMD 0x0100 - -/* PHSTAT1 values */ -#define ENC_PHSTAT1_LLSTAT 0x0004 - -/* PHSTAT2 values */ -#define ENC_PHSTAT2_LSTAT 0x0400 -#define ENC_PHSTAT2_DPXSTAT 0x0200 - -#endif diff --git a/drivers/net/macb.c b/drivers/net/macb.c index e62aefcd0d..fe370bf728 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -915,7 +915,7 @@ static int macb_recv(struct eth_device *netdev) if (length >= 0) { net_process_received_packet(packet, length); reclaim_rx_buffers(macb, macb->next_rx_tail); - } else if (length < 0) { + } else { return length; } } diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index e3d31a560d..62c0c2be06 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -5598,6 +5598,10 @@ static int mvpp2_base_bind(struct udevice *parent) id += base_id_add; name = calloc(1, 16); + if (!name) { + free(plat); + return -ENOMEM; + } sprintf(name, "mvpp2-%d", id); /* Create child device UCLASS_ETH and bind it */ diff --git a/drivers/net/pfe_eth/Kconfig b/drivers/net/pfe_eth/Kconfig new file mode 100644 index 0000000000..a13b331a50 --- /dev/null +++ b/drivers/net/pfe_eth/Kconfig @@ -0,0 +1,12 @@ +menuconfig FSL_PFE + bool "NXP PFE Ethernet driver" + help + This driver provides support for NXP's Packet Forwarding Engine. + +if FSL_PFE + +config SYS_FSL_PFE_ADDR + hex "PFE base address" + default 0x04000000 + +endif diff --git a/drivers/net/pfe_eth/Makefile b/drivers/net/pfe_eth/Makefile new file mode 100644 index 0000000000..6b5248f659 --- /dev/null +++ b/drivers/net/pfe_eth/Makefile @@ -0,0 +1,12 @@ +# Copyright 2015-2016 Freescale Semiconductor, Inc. +# Copyright 2017 NXP +# +# SPDX-License-Identifier:GPL-2.0+ + +# Layerscape PFE driver +obj-y += pfe_cmd.o \ + pfe_driver.o \ + pfe_eth.o \ + pfe_firmware.o \ + pfe_hw.o \ + pfe_mdio.o diff --git a/drivers/net/pfe_eth/pfe_cmd.c b/drivers/net/pfe_eth/pfe_cmd.c new file mode 100644 index 0000000000..822dc0f141 --- /dev/null +++ b/drivers/net/pfe_eth/pfe_cmd.c @@ -0,0 +1,497 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * @file + * @brief PFE utility commands + */ + +#include <net/pfe_eth/pfe_eth.h> + +static inline void pfe_command_help(void) +{ + printf("Usage: pfe [pe | status | expt ] <options>\n"); +} + +static void pfe_command_pe(int argc, char * const argv[]) +{ + if (argc >= 3 && strcmp(argv[2], "pmem") == 0) { + if (argc >= 4 && strcmp(argv[3], "read") == 0) { + int i; + int num; + int id; + u32 addr; + u32 size; + u32 val; + + if (argc == 7) { + num = simple_strtoul(argv[6], NULL, 0); + } else if (argc == 6) { + num = 1; + } else { + printf("Usage: pfe pe pmem read <id> <addr> [<num>]\n"); + return; + } + + id = simple_strtoul(argv[4], NULL, 0); + addr = simple_strtoul(argv[5], NULL, 16); + size = 4; + + for (i = 0; i < num; i++, addr += 4) { + val = pe_pmem_read(id, addr, size); + val = be32_to_cpu(val); + if (!(i & 3)) + printf("%08x: ", addr); + printf("%08x%s", val, i == num - 1 || (i & 3) + == 3 ? "\n" : " "); + } + + } else { + printf("Usage: pfe pe pmem read <parameters>\n"); + } + } else if (argc >= 3 && strcmp(argv[2], "dmem") == 0) { + if (argc >= 4 && strcmp(argv[3], "read") == 0) { + int i; + int num; + int id; + u32 addr; + u32 size; + u32 val; + + if (argc == 7) { + num = simple_strtoul(argv[6], NULL, 0); + } else if (argc == 6) { + num = 1; + } else { + printf("Usage: pfe pe dmem read <id> <addr> [<num>]\n"); + return; + } + + id = simple_strtoul(argv[4], NULL, 0); + addr = simple_strtoul(argv[5], NULL, 16); + size = 4; + + for (i = 0; i < num; i++, addr += 4) { + val = pe_dmem_read(id, addr, size); + val = be32_to_cpu(val); + if (!(i & 3)) + printf("%08x: ", addr); + printf("%08x%s", val, i == num - 1 || (i & 3) + == 3 ? "\n" : " "); + } + + } else if (argc >= 4 && strcmp(argv[3], "write") == 0) { + int id; + u32 val; + u32 addr; + u32 size; + + if (argc != 7) { + printf("Usage: pfe pe dmem write <id> <val> <addr>\n"); + return; + } + + id = simple_strtoul(argv[4], NULL, 0); + val = simple_strtoul(argv[5], NULL, 16); + val = cpu_to_be32(val); + addr = simple_strtoul(argv[6], NULL, 16); + size = 4; + pe_dmem_write(id, val, addr, size); + } else { + printf("Usage: pfe pe dmem [read | write] <parameters>\n"); + } + } else if (argc >= 3 && strcmp(argv[2], "lmem") == 0) { + if (argc >= 4 && strcmp(argv[3], "read") == 0) { + int i; + int num; + u32 val; + u32 offset; + + if (argc == 6) { + num = simple_strtoul(argv[5], NULL, 0); + } else if (argc == 5) { + num = 1; + } else { + printf("Usage: pfe pe lmem read <offset> [<num>]\n"); + return; + } + + offset = simple_strtoul(argv[4], NULL, 16); + + for (i = 0; i < num; i++, offset += 4) { + pe_lmem_read(&val, 4, offset); + val = be32_to_cpu(val); + printf("%08x%s", val, i == num - 1 || (i & 7) + == 7 ? "\n" : " "); + } + + } else if (argc >= 4 && strcmp(argv[3], "write") == 0) { + u32 val; + u32 offset; + + if (argc != 6) { + printf("Usage: pfe pe lmem write <val> <offset>\n"); + return; + } + + val = simple_strtoul(argv[4], NULL, 16); + val = cpu_to_be32(val); + offset = simple_strtoul(argv[5], NULL, 16); + pe_lmem_write(&val, 4, offset); + } else { + printf("Usage: pfe pe lmem [read | write] <parameters>\n"); + } + } else { + if (strcmp(argv[2], "help") != 0) + printf("Unknown option: %s\n", argv[2]); + + printf("Usage: pfe pe <parameters>\n"); + } +} + +#define NUM_QUEUES 16 + +/* + * qm_read_drop_stat + * This function is used to read the drop statistics from the TMU + * hw drop counter. Since the hw counter is always cleared afer + * reading, this function maintains the previous drop count, and + * adds the new value to it. That value can be retrieved by + * passing a pointer to it with the total_drops arg. + * + * @param tmu TMU number (0 - 3) + * @param queue queue number (0 - 15) + * @param total_drops pointer to location to store total drops (or NULL) + * @param do_reset if TRUE, clear total drops after updating + * + */ +u32 qm_read_drop_stat(u32 tmu, u32 queue, u32 *total_drops, int do_reset) +{ + static u32 qtotal[TMU_MAX_ID + 1][NUM_QUEUES]; + u32 val; + + writel((tmu << 8) | queue, TMU_TEQ_CTRL); + writel((tmu << 8) | queue, TMU_LLM_CTRL); + val = readl(TMU_TEQ_DROP_STAT); + qtotal[tmu][queue] += val; + if (total_drops) + *total_drops = qtotal[tmu][queue]; + if (do_reset) + qtotal[tmu][queue] = 0; + return val; +} + +static ssize_t tmu_queue_stats(char *buf, int tmu, int queue) +{ + ssize_t len = 0; + u32 drops; + + printf("%d-%02d, ", tmu, queue); + + drops = qm_read_drop_stat(tmu, queue, NULL, 0); + + /* Select queue */ + writel((tmu << 8) | queue, TMU_TEQ_CTRL); + writel((tmu << 8) | queue, TMU_LLM_CTRL); + + printf("(teq) drop: %10u, tx: %10u (llm) head: %08x, tail: %08x, drop: %10u\n", + drops, readl(TMU_TEQ_TRANS_STAT), + readl(TMU_LLM_QUE_HEADPTR), readl(TMU_LLM_QUE_TAILPTR), + readl(TMU_LLM_QUE_DROPCNT)); + + return len; +} + +static ssize_t tmu_queues(char *buf, int tmu) +{ + ssize_t len = 0; + int queue; + + for (queue = 0; queue < 16; queue++) + len += tmu_queue_stats(buf + len, tmu, queue); + + return len; +} + +static inline void hif_status(void) +{ + printf("hif:\n"); + + printf(" tx curr bd: %x\n", readl(HIF_TX_CURR_BD_ADDR)); + printf(" tx status: %x\n", readl(HIF_TX_STATUS)); + printf(" tx dma status: %x\n", readl(HIF_TX_DMA_STATUS)); + + printf(" rx curr bd: %x\n", readl(HIF_RX_CURR_BD_ADDR)); + printf(" rx status: %x\n", readl(HIF_RX_STATUS)); + printf(" rx dma status: %x\n", readl(HIF_RX_DMA_STATUS)); + + printf("hif nocopy:\n"); + + printf(" tx curr bd: %x\n", readl(HIF_NOCPY_TX_CURR_BD_ADDR)); + printf(" tx status: %x\n", readl(HIF_NOCPY_TX_STATUS)); + printf(" tx dma status: %x\n", readl(HIF_NOCPY_TX_DMA_STATUS)); + + printf(" rx curr bd: %x\n", readl(HIF_NOCPY_RX_CURR_BD_ADDR)); + printf(" rx status: %x\n", readl(HIF_NOCPY_RX_STATUS)); + printf(" rx dma status: %x\n", readl(HIF_NOCPY_RX_DMA_STATUS)); +} + +static void gpi(int id, void *base) +{ + u32 val; + + printf("%s%d:\n", __func__, id); + + printf(" tx under stick: %x\n", readl(base + GPI_FIFO_STATUS)); + val = readl(base + GPI_FIFO_DEBUG); + printf(" tx pkts: %x\n", (val >> 23) & 0x3f); + printf(" rx pkts: %x\n", (val >> 18) & 0x3f); + printf(" tx bytes: %x\n", (val >> 9) & 0x1ff); + printf(" rx bytes: %x\n", (val >> 0) & 0x1ff); + printf(" overrun: %x\n", readl(base + GPI_OVERRUN_DROPCNT)); +} + +static void bmu(int id, void *base) +{ + printf("%s%d:\n", __func__, id); + + printf(" buf size: %x\n", (1 << readl(base + BMU_BUF_SIZE))); + printf(" buf count: %x\n", readl(base + BMU_BUF_CNT)); + printf(" buf rem: %x\n", readl(base + BMU_REM_BUF_CNT)); + printf(" buf curr: %x\n", readl(base + BMU_CURR_BUF_CNT)); + printf(" free err: %x\n", readl(base + BMU_FREE_ERR_ADDR)); +} + +#define PESTATUS_ADDR_CLASS 0x800 +#define PEMBOX_ADDR_CLASS 0x890 +#define PESTATUS_ADDR_TMU 0x80 +#define PEMBOX_ADDR_TMU 0x290 +#define PESTATUS_ADDR_UTIL 0x0 + +static void pfe_pe_status(int argc, char * const argv[]) +{ + int do_clear = 0; + u32 id; + u32 dmem_addr; + u32 cpu_state; + u32 activity_counter; + u32 rx; + u32 tx; + u32 drop; + char statebuf[5]; + u32 class_debug_reg = 0; + + if (argc == 4 && strcmp(argv[3], "clear") == 0) + do_clear = 1; + + for (id = CLASS0_ID; id < MAX_PE; id++) { + if (id >= TMU0_ID) { + if (id == TMU2_ID) + continue; + if (id == TMU0_ID) + printf("tmu:\n"); + dmem_addr = PESTATUS_ADDR_TMU; + } else { + if (id == CLASS0_ID) + printf("class:\n"); + dmem_addr = PESTATUS_ADDR_CLASS; + class_debug_reg = readl(CLASS_PE0_DEBUG + id * 4); + } + + cpu_state = pe_dmem_read(id, dmem_addr, 4); + dmem_addr += 4; + memcpy(statebuf, (char *)&cpu_state, 4); + statebuf[4] = '\0'; + activity_counter = pe_dmem_read(id, dmem_addr, 4); + dmem_addr += 4; + rx = pe_dmem_read(id, dmem_addr, 4); + if (do_clear) + pe_dmem_write(id, 0, dmem_addr, 4); + dmem_addr += 4; + tx = pe_dmem_read(id, dmem_addr, 4); + if (do_clear) + pe_dmem_write(id, 0, dmem_addr, 4); + dmem_addr += 4; + drop = pe_dmem_read(id, dmem_addr, 4); + if (do_clear) + pe_dmem_write(id, 0, dmem_addr, 4); + dmem_addr += 4; + + if (id >= TMU0_ID) { + printf("%d: state=%4s ctr=%08x rx=%x qstatus=%x\n", + id - TMU0_ID, statebuf, + cpu_to_be32(activity_counter), + cpu_to_be32(rx), cpu_to_be32(tx)); + } else { + printf("%d: pc=1%04x ldst=%04x state=%4s ctr=%08x rx=%x tx=%x drop=%x\n", + id - CLASS0_ID, class_debug_reg & 0xFFFF, + class_debug_reg >> 16, + statebuf, cpu_to_be32(activity_counter), + cpu_to_be32(rx), cpu_to_be32(tx), + cpu_to_be32(drop)); + } + } +} + +static void pfe_command_status(int argc, char * const argv[]) +{ + if (argc >= 3 && strcmp(argv[2], "pe") == 0) { + pfe_pe_status(argc, argv); + } else if (argc == 3 && strcmp(argv[2], "bmu") == 0) { + bmu(1, BMU1_BASE_ADDR); + bmu(2, BMU2_BASE_ADDR); + } else if (argc == 3 && strcmp(argv[2], "hif") == 0) { + hif_status(); + } else if (argc == 3 && strcmp(argv[2], "gpi") == 0) { + gpi(0, EGPI1_BASE_ADDR); + gpi(1, EGPI2_BASE_ADDR); + gpi(3, HGPI_BASE_ADDR); + } else if (argc == 3 && strcmp(argv[2], "tmu0_queues") == 0) { + tmu_queues(NULL, 0); + } else if (argc == 3 && strcmp(argv[2], "tmu1_queues") == 0) { + tmu_queues(NULL, 1); + } else if (argc == 3 && strcmp(argv[2], "tmu3_queues") == 0) { + tmu_queues(NULL, 3); + } else { + printf("Usage: pfe status [pe <clear> | bmu | gpi | hif | tmuX_queues ]\n"); + } +} + +#define EXPT_DUMP_ADDR 0x1fa8 +#define EXPT_REG_COUNT 20 +static const char *register_names[EXPT_REG_COUNT] = { + " pc", "ECAS", " EID", " ED", + " sp", " r1", " r2", " r3", + " r4", " r5", " r6", " r7", + " r8", " r9", " r10", " r11", + " r12", " r13", " r14", " r15" +}; + +static void pfe_command_expt(int argc, char * const argv[]) +{ + unsigned int id, i, val, addr; + + if (argc == 3) { + id = simple_strtoul(argv[2], NULL, 0); + addr = EXPT_DUMP_ADDR; + printf("Exception information for PE %d:\n", id); + for (i = 0; i < EXPT_REG_COUNT; i++) { + val = pe_dmem_read(id, addr, 4); + val = be32_to_cpu(val); + printf("%s:%08x%s", register_names[i], val, + (i & 3) == 3 ? "\n" : " "); + addr += 4; + } + } else { + printf("Usage: pfe expt <id>\n"); + } +} + +#ifdef PFE_RESET_WA +/*This function sends a dummy packet to HIF through TMU3 */ +static void send_dummy_pkt_to_hif(void) +{ + u32 buf; + static u32 dummy_pkt[] = { + 0x4200800a, 0x01000003, 0x00018100, 0x00000000, + 0x33221100, 0x2b785544, 0xd73093cb, 0x01000608, + 0x04060008, 0x2b780200, 0xd73093cb, 0x0a01a8c0, + 0x33221100, 0xa8c05544, 0x00000301, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xbe86c51f }; + + /*Allocate BMU2 buffer */ + buf = readl(BMU2_BASE_ADDR + BMU_ALLOC_CTRL); + + debug("Sending a dummy pkt to HIF %x\n", buf); + buf += 0x80; + memcpy((void *)DDR_PFE_TO_VIRT(buf), dummy_pkt, sizeof(dummy_pkt)); + + /*Write length and pkt to TMU*/ + writel(0x03000042, TMU_PHY_INQ_PKTPTR); + writel(buf, TMU_PHY_INQ_PKTINFO); +} + +static void pfe_command_stop(int argc, char * const argv[]) +{ + int pfe_pe_id, hif_stop_loop = 10; + u32 rx_status; + + printf("Stopping PFE...\n"); + + /*Mark all descriptors as LAST_BD */ + hif_rx_desc_disable(); + + /*If HIF Rx BDP is busy send a dummy packet */ + do { + rx_status = readl(HIF_RX_STATUS); + if (rx_status & BDP_CSR_RX_DMA_ACTV) + send_dummy_pkt_to_hif(); + udelay(10); + } while (hif_stop_loop--); + + if (readl(HIF_RX_STATUS) & BDP_CSR_RX_DMA_ACTV) + printf("Unable to stop HIF\n"); + + /*Disable Class PEs */ + for (pfe_pe_id = CLASS0_ID; pfe_pe_id <= CLASS_MAX_ID; pfe_pe_id++) { + /*Inform PE to stop */ + pe_dmem_write(pfe_pe_id, cpu_to_be32(1), PEMBOX_ADDR_CLASS, 4); + udelay(10); + + /*Read status */ + if (!pe_dmem_read(pfe_pe_id, PEMBOX_ADDR_CLASS + 4, 4)) + printf("Failed to stop PE%d\n", pfe_pe_id); + } + + /*Disable TMU PEs */ + for (pfe_pe_id = TMU0_ID; pfe_pe_id <= TMU_MAX_ID; pfe_pe_id++) { + if (pfe_pe_id == TMU2_ID) + continue; + + /*Inform PE to stop */ + pe_dmem_write(pfe_pe_id, 1, PEMBOX_ADDR_TMU, 4); + udelay(10); + + /*Read status */ + if (!pe_dmem_read(pfe_pe_id, PEMBOX_ADDR_TMU + 4, 4)) + printf("Failed to stop PE%d\n", pfe_pe_id); + } +} +#endif + +static int pfe_command(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + if (argc == 1 || strcmp(argv[1], "help") == 0) { + pfe_command_help(); + return CMD_RET_SUCCESS; + } + + if (strcmp(argv[1], "pe") == 0) { + pfe_command_pe(argc, argv); + } else if (strcmp(argv[1], "status") == 0) { + pfe_command_status(argc, argv); + } else if (strcmp(argv[1], "expt") == 0) { + pfe_command_expt(argc, argv); +#ifdef PFE_RESET_WA + } else if (strcmp(argv[1], "stop") == 0) { + pfe_command_stop(argc, argv); +#endif + } else { + printf("Unknown option: %s\n", argv[1]); + pfe_command_help(); + return CMD_RET_FAILURE; + } + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD( + pfe, 7, 1, pfe_command, + "Performs PFE lib utility functions", + "Usage:\n" + "pfe <options>" +); diff --git a/drivers/net/pfe_eth/pfe_driver.c b/drivers/net/pfe_eth/pfe_driver.c new file mode 100644 index 0000000000..a9991f5c2b --- /dev/null +++ b/drivers/net/pfe_eth/pfe_driver.c @@ -0,0 +1,643 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <net/pfe_eth/pfe_eth.h> +#include <net/pfe_eth/pfe_firmware.h> + +static struct tx_desc_s *g_tx_desc; +static struct rx_desc_s *g_rx_desc; + +/* + * HIF Rx interface function + * Reads the rx descriptor from the current location (rx_to_read). + * - If the descriptor has a valid data/pkt, then get the data pointer + * - check for the input rx phy number + * - increment the rx data pointer by pkt_head_room_size + * - decrement the data length by pkt_head_room_size + * - handover the packet to caller. + * + * @param[out] pkt_ptr - Pointer to store rx packet + * @param[out] phy_port - Pointer to store recv phy port + * + * @return -1 if no packet, else return length of packet. + */ +int pfe_recv(uchar **pkt_ptr, int *phy_port) +{ + struct rx_desc_s *rx_desc = g_rx_desc; + struct buf_desc *bd; + int len = 0; + + struct hif_header_s *hif_header; + + bd = rx_desc->rx_base + rx_desc->rx_to_read; + + if (readl(&bd->ctrl) & BD_CTRL_DESC_EN) + return len; /* No pending Rx packet */ + + /* this len include hif_header(8 bytes) */ + len = readl(&bd->ctrl) & 0xFFFF; + + hif_header = (struct hif_header_s *)DDR_PFE_TO_VIRT(readl(&bd->data)); + + /* Get the receive port info from the packet */ + debug("Pkt received:"); + debug(" Pkt ptr(%p), len(%d), gemac_port(%d) status(%08x)\n", + hif_header, len, hif_header->port_no, readl(&bd->status)); +#ifdef DEBUG + { + int i; + unsigned char *p = (unsigned char *)hif_header; + + for (i = 0; i < len; i++) { + if (!(i % 16)) + printf("\n"); + printf(" %02x", p[i]); + } + printf("\n"); + } +#endif + + *pkt_ptr = (uchar *)(hif_header + 1); + *phy_port = hif_header->port_no; + len -= sizeof(struct hif_header_s); + + return len; +} + +/* + * HIF function to check the Rx done + * This function will check the rx done indication of the current rx_to_read + * locations + * if success, moves the rx_to_read to next location. + */ +int pfe_eth_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct rx_desc_s *rx_desc = g_rx_desc; + struct buf_desc *bd; + + debug("%s:rx_base: %p, rx_to_read: %d\n", __func__, rx_desc->rx_base, + rx_desc->rx_to_read); + + bd = rx_desc->rx_base + rx_desc->rx_to_read; + + /* reset the control field */ + writel((MAX_FRAME_SIZE | BD_CTRL_LIFM | BD_CTRL_DESC_EN + | BD_CTRL_DIR), &bd->ctrl); + writel(0, &bd->status); + + debug("Rx Done : status: %08x, ctrl: %08x\n", readl(&bd->status), + readl(&bd->ctrl)); + + /* Give START_STROBE to BDP to fetch the descriptor __NOW__, + * BDP need not wait for rx_poll_cycle time to fetch the descriptor, + * In idle state (ie., no rx pkt), BDP will not fetch + * the descriptor even if strobe is given. + */ + writel((readl(HIF_RX_CTRL) | HIF_CTRL_BDP_CH_START_WSTB), HIF_RX_CTRL); + + /* increment the rx_to_read index to next location */ + rx_desc->rx_to_read = (rx_desc->rx_to_read + 1) + & (rx_desc->rx_ring_size - 1); + + debug("Rx next pkt location: %d\n", rx_desc->rx_to_read); + + return 0; +} + +/* + * HIF Tx interface function + * This function sends a single packet to PFE from HIF interface. + * - No interrupt indication on tx completion. + * - Data is copied to tx buffers before tx descriptor is updated + * and TX DMA is enabled. + * + * @param[in] phy_port Phy port number to send out this packet + * @param[in] data Pointer to the data + * @param[in] length Length of the ethernet packet to be transferred. + * + * @return -1 if tx Q is full, else returns the tx location where the pkt is + * placed. + */ +int pfe_send(int phy_port, void *data, int length) +{ + struct tx_desc_s *tx_desc = g_tx_desc; + struct buf_desc *bd; + struct hif_header_s hif_header; + u8 *tx_buf_va; + + debug("%s:pkt: %p, len: %d, tx_base: %p, tx_to_send: %d\n", __func__, + data, length, tx_desc->tx_base, tx_desc->tx_to_send); + + bd = tx_desc->tx_base + tx_desc->tx_to_send; + + /* check queue-full condition */ + if (readl(&bd->ctrl) & BD_CTRL_DESC_EN) + return -1; + + /* PFE checks for min pkt size */ + if (length < MIN_PKT_SIZE) + length = MIN_PKT_SIZE; + + tx_buf_va = (void *)DDR_PFE_TO_VIRT(readl(&bd->data)); + debug("%s: tx_buf_va: %p, tx_buf_pa: %08x\n", __func__, tx_buf_va, + readl(&bd->data)); + + /* Fill the gemac/phy port number to send this packet out */ + memset(&hif_header, 0, sizeof(struct hif_header_s)); + hif_header.port_no = phy_port; + + memcpy(tx_buf_va, (u8 *)&hif_header, sizeof(struct hif_header_s)); + memcpy(tx_buf_va + sizeof(struct hif_header_s), data, length); + length += sizeof(struct hif_header_s); + +#ifdef DEBUG + { + int i; + unsigned char *p = (unsigned char *)tx_buf_va; + + for (i = 0; i < length; i++) { + if (!(i % 16)) + printf("\n"); + printf("%02x ", p[i]); + } + } +#endif + + debug("Tx Done: status: %08x, ctrl: %08x\n", readl(&bd->status), + readl(&bd->ctrl)); + + /* fill the tx desc */ + writel((u32)(BD_CTRL_DESC_EN | BD_CTRL_LIFM | (length & 0xFFFF)), + &bd->ctrl); + writel(0, &bd->status); + + writel((HIF_CTRL_DMA_EN | HIF_CTRL_BDP_CH_START_WSTB), HIF_TX_CTRL); + + udelay(100); + + return tx_desc->tx_to_send; +} + +/* + * HIF function to check the Tx done + * This function will check the tx done indication of the current tx_to_send + * locations + * if success, moves the tx_to_send to next location. + * + * @return -1 if TX ownership bit is not cleared by hw. + * else on success (tx done completion) return zero. + */ +int pfe_tx_done(void) +{ + struct tx_desc_s *tx_desc = g_tx_desc; + struct buf_desc *bd; + + debug("%s:tx_base: %p, tx_to_send: %d\n", __func__, tx_desc->tx_base, + tx_desc->tx_to_send); + + bd = tx_desc->tx_base + tx_desc->tx_to_send; + + /* check queue-full condition */ + if (readl(&bd->ctrl) & BD_CTRL_DESC_EN) + return -1; + + /* reset the control field */ + writel(0, &bd->ctrl); + writel(0, &bd->status); + + debug("Tx Done : status: %08x, ctrl: %08x\n", readl(&bd->status), + readl(&bd->ctrl)); + + /* increment the txtosend index to next location */ + tx_desc->tx_to_send = (tx_desc->tx_to_send + 1) + & (tx_desc->tx_ring_size - 1); + + debug("Tx next pkt location: %d\n", tx_desc->tx_to_send); + + return 0; +} + +/* + * Helper function to dump Rx descriptors. + */ +static inline void hif_rx_desc_dump(void) +{ + struct buf_desc *bd_va; + int i; + struct rx_desc_s *rx_desc; + + if (!g_rx_desc) { + printf("%s: HIF Rx desc no init\n", __func__); + return; + } + + rx_desc = g_rx_desc; + bd_va = rx_desc->rx_base; + + debug("HIF rx desc: base_va: %p, base_pa: %08x\n", rx_desc->rx_base, + rx_desc->rx_base_pa); + for (i = 0; i < rx_desc->rx_ring_size; i++) { + debug("status: %08x, ctrl: %08x, data: %08x, next: 0x%08x\n", + readl(&bd_va->status), + readl(&bd_va->ctrl), + readl(&bd_va->data), + readl(&bd_va->next)); + bd_va++; + } +} + +/* + * This function mark all Rx descriptors as LAST_BD. + */ +void hif_rx_desc_disable(void) +{ + int i; + struct rx_desc_s *rx_desc; + struct buf_desc *bd_va; + + if (!g_rx_desc) { + printf("%s: HIF Rx desc not initialized\n", __func__); + return; + } + + rx_desc = g_rx_desc; + bd_va = rx_desc->rx_base; + + for (i = 0; i < rx_desc->rx_ring_size; i++) { + writel(readl(&bd_va->ctrl) | BD_CTRL_LAST_BD, &bd_va->ctrl); + bd_va++; + } +} + +/* + * HIF Rx Desc initialization function. + */ +static int hif_rx_desc_init(struct pfe_ddr_address *pfe_addr) +{ + u32 ctrl; + struct buf_desc *bd_va; + struct buf_desc *bd_pa; + struct rx_desc_s *rx_desc; + u32 rx_buf_pa; + int i; + + /* sanity check */ + if (g_rx_desc) { + printf("%s: HIF Rx desc re-init request\n", __func__); + return 0; + } + + rx_desc = (struct rx_desc_s *)malloc(sizeof(struct rx_desc_s)); + if (!rx_desc) { + printf("%s: Memory allocation failure\n", __func__); + return -ENOMEM; + } + memset(rx_desc, 0, sizeof(struct rx_desc_s)); + + /* init: Rx ring buffer */ + rx_desc->rx_ring_size = HIF_RX_DESC_NT; + + /* NOTE: must be 64bit aligned */ + bd_va = (struct buf_desc *)(pfe_addr->ddr_pfe_baseaddr + + RX_BD_BASEADDR); + bd_pa = (struct buf_desc *)(pfe_addr->ddr_pfe_phys_baseaddr + + RX_BD_BASEADDR); + + rx_desc->rx_base = bd_va; + rx_desc->rx_base_pa = (unsigned long)bd_pa; + + rx_buf_pa = pfe_addr->ddr_pfe_phys_baseaddr + HIF_RX_PKT_DDR_BASEADDR; + + debug("%s: Rx desc base: %p, base_pa: %08x, desc_count: %d\n", + __func__, rx_desc->rx_base, rx_desc->rx_base_pa, + rx_desc->rx_ring_size); + + memset(bd_va, 0, sizeof(struct buf_desc) * rx_desc->rx_ring_size); + + ctrl = (MAX_FRAME_SIZE | BD_CTRL_DESC_EN | BD_CTRL_DIR | BD_CTRL_LIFM); + + for (i = 0; i < rx_desc->rx_ring_size; i++) { + writel((unsigned long)(bd_pa + 1), &bd_va->next); + writel(ctrl, &bd_va->ctrl); + writel(rx_buf_pa + (i * MAX_FRAME_SIZE), &bd_va->data); + bd_va++; + bd_pa++; + } + --bd_va; + writel((u32)rx_desc->rx_base_pa, &bd_va->next); + + writel(rx_desc->rx_base_pa, HIF_RX_BDP_ADDR); + writel((readl(HIF_RX_CTRL) | HIF_CTRL_BDP_CH_START_WSTB), HIF_RX_CTRL); + + g_rx_desc = rx_desc; + + return 0; +} + +/* + * Helper function to dump Tx Descriptors. + */ +static inline void hif_tx_desc_dump(void) +{ + struct tx_desc_s *tx_desc; + int i; + struct buf_desc *bd_va; + + if (!g_tx_desc) { + printf("%s: HIF Tx desc no init\n", __func__); + return; + } + + tx_desc = g_tx_desc; + bd_va = tx_desc->tx_base; + + debug("HIF tx desc: base_va: %p, base_pa: %08x\n", tx_desc->tx_base, + tx_desc->tx_base_pa); + + for (i = 0; i < tx_desc->tx_ring_size; i++) + bd_va++; +} + +/* + * HIF Tx descriptor initialization function. + */ +static int hif_tx_desc_init(struct pfe_ddr_address *pfe_addr) +{ + struct buf_desc *bd_va; + struct buf_desc *bd_pa; + int i; + struct tx_desc_s *tx_desc; + u32 tx_buf_pa; + + /* sanity check */ + if (g_tx_desc) { + printf("%s: HIF Tx desc re-init request\n", __func__); + return 0; + } + + tx_desc = (struct tx_desc_s *)malloc(sizeof(struct tx_desc_s)); + if (!tx_desc) { + printf("%s:%d:Memory allocation failure\n", __func__, + __LINE__); + return -ENOMEM; + } + memset(tx_desc, 0, sizeof(struct tx_desc_s)); + + /* init: Tx ring buffer */ + tx_desc->tx_ring_size = HIF_TX_DESC_NT; + + /* NOTE: must be 64bit aligned */ + bd_va = (struct buf_desc *)(pfe_addr->ddr_pfe_baseaddr + + TX_BD_BASEADDR); + bd_pa = (struct buf_desc *)(pfe_addr->ddr_pfe_phys_baseaddr + + TX_BD_BASEADDR); + + tx_desc->tx_base_pa = (unsigned long)bd_pa; + tx_desc->tx_base = bd_va; + + debug("%s: Tx desc_base: %p, base_pa: %08x, desc_count: %d\n", + __func__, tx_desc->tx_base, tx_desc->tx_base_pa, + tx_desc->tx_ring_size); + + memset(bd_va, 0, sizeof(struct buf_desc) * tx_desc->tx_ring_size); + + tx_buf_pa = pfe_addr->ddr_pfe_phys_baseaddr + HIF_TX_PKT_DDR_BASEADDR; + + for (i = 0; i < tx_desc->tx_ring_size; i++) { + writel((unsigned long)(bd_pa + 1), &bd_va->next); + writel(tx_buf_pa + (i * MAX_FRAME_SIZE), &bd_va->data); + bd_va++; + bd_pa++; + } + --bd_va; + writel((u32)tx_desc->tx_base_pa, &bd_va->next); + + writel(tx_desc->tx_base_pa, HIF_TX_BDP_ADDR); + + g_tx_desc = tx_desc; + + return 0; +} + +/* + * PFE/Class initialization. + */ +static void pfe_class_init(struct pfe_ddr_address *pfe_addr) +{ + struct class_cfg class_cfg = { + .route_table_baseaddr = pfe_addr->ddr_pfe_phys_baseaddr + + ROUTE_TABLE_BASEADDR, + .route_table_hash_bits = ROUTE_TABLE_HASH_BITS, + }; + + class_init(&class_cfg); + + debug("class init complete\n"); +} + +/* + * PFE/TMU initialization. + */ +static void pfe_tmu_init(struct pfe_ddr_address *pfe_addr) +{ + struct tmu_cfg tmu_cfg = { + .llm_base_addr = pfe_addr->ddr_pfe_phys_baseaddr + + TMU_LLM_BASEADDR, + .llm_queue_len = TMU_LLM_QUEUE_LEN, + }; + + tmu_init(&tmu_cfg); + + debug("tmu init complete\n"); +} + +/* + * PFE/BMU (both BMU1 & BMU2) initialization. + */ +static void pfe_bmu_init(struct pfe_ddr_address *pfe_addr) +{ + struct bmu_cfg bmu1_cfg = { + .baseaddr = CBUS_VIRT_TO_PFE(LMEM_BASE_ADDR + + BMU1_LMEM_BASEADDR), + .count = BMU1_BUF_COUNT, + .size = BMU1_BUF_SIZE, + }; + + struct bmu_cfg bmu2_cfg = { + .baseaddr = pfe_addr->ddr_pfe_phys_baseaddr + BMU2_DDR_BASEADDR, + .count = BMU2_BUF_COUNT, + .size = BMU2_BUF_SIZE, + }; + + bmu_init(BMU1_BASE_ADDR, &bmu1_cfg); + debug("bmu1 init: done\n"); + + bmu_init(BMU2_BASE_ADDR, &bmu2_cfg); + debug("bmu2 init: done\n"); +} + +/* + * PFE/GPI initialization function. + * - egpi1, egpi2, egpi3, hgpi + */ +static void pfe_gpi_init(struct pfe_ddr_address *pfe_addr) +{ + struct gpi_cfg egpi1_cfg = { + .lmem_rtry_cnt = EGPI1_LMEM_RTRY_CNT, + .tmlf_txthres = EGPI1_TMLF_TXTHRES, + .aseq_len = EGPI1_ASEQ_LEN, + }; + + struct gpi_cfg egpi2_cfg = { + .lmem_rtry_cnt = EGPI2_LMEM_RTRY_CNT, + .tmlf_txthres = EGPI2_TMLF_TXTHRES, + .aseq_len = EGPI2_ASEQ_LEN, + }; + + struct gpi_cfg hgpi_cfg = { + .lmem_rtry_cnt = HGPI_LMEM_RTRY_CNT, + .tmlf_txthres = HGPI_TMLF_TXTHRES, + .aseq_len = HGPI_ASEQ_LEN, + }; + + gpi_init(EGPI1_BASE_ADDR, &egpi1_cfg); + debug("GPI1 init complete\n"); + + gpi_init(EGPI2_BASE_ADDR, &egpi2_cfg); + debug("GPI2 init complete\n"); + + gpi_init(HGPI_BASE_ADDR, &hgpi_cfg); + debug("HGPI init complete\n"); +} + +/* + * PFE/HIF initialization function. + */ +static int pfe_hif_init(struct pfe_ddr_address *pfe_addr) +{ + int ret = 0; + + hif_tx_disable(); + hif_rx_disable(); + + ret = hif_tx_desc_init(pfe_addr); + if (ret) + return ret; + ret = hif_rx_desc_init(pfe_addr); + if (ret) + return ret; + + hif_init(); + + hif_tx_enable(); + hif_rx_enable(); + + hif_rx_desc_dump(); + hif_tx_desc_dump(); + + debug("HIF init complete\n"); + return ret; +} + +/* + * PFE initialization + * - Firmware loading (CLASS-PE and TMU-PE) + * - BMU1 and BMU2 init + * - GEMAC init + * - GPI init + * - CLASS-PE init + * - TMU-PE init + * - HIF tx and rx descriptors init + * + * @param[in] edev Pointer to eth device structure. + * + * @return 0, on success. + */ +static int pfe_hw_init(struct pfe_ddr_address *pfe_addr) +{ + int ret = 0; + + debug("%s: start\n", __func__); + + writel(0x3, CLASS_PE_SYS_CLK_RATIO); + writel(0x3, TMU_PE_SYS_CLK_RATIO); + writel(0x3, UTIL_PE_SYS_CLK_RATIO); + udelay(10); + + pfe_class_init(pfe_addr); + + pfe_tmu_init(pfe_addr); + + pfe_bmu_init(pfe_addr); + + pfe_gpi_init(pfe_addr); + + ret = pfe_hif_init(pfe_addr); + if (ret) + return ret; + + bmu_enable(BMU1_BASE_ADDR); + debug("bmu1 enabled\n"); + + bmu_enable(BMU2_BASE_ADDR); + debug("bmu2 enabled\n"); + + debug("%s: done\n", __func__); + + return ret; +} + +/* + * PFE driver init function. + * - Initializes pfe_lib + * - pfe hw init + * - fw loading and enables PEs + * - should be executed once. + * + * @param[in] pfe Pointer the pfe control block + */ +int pfe_drv_init(struct pfe_ddr_address *pfe_addr) +{ + int ret = 0; + + pfe_lib_init(); + + ret = pfe_hw_init(pfe_addr); + if (ret) + return ret; + + /* Load the class,TM, Util fw. + * By now pfe is: + * - out of reset + disabled + configured. + * Fw loading should be done after pfe_hw_init() + */ + /* It loads default inbuilt sbl firmware */ + pfe_firmware_init(); + + return ret; +} + +/* + * PFE remove function + * - stops PEs + * - frees tx/rx descriptor resources + * - should be called once. + * + * @param[in] pfe Pointer to pfe control block. + */ +int pfe_eth_remove(struct udevice *dev) +{ + if (g_tx_desc) + free(g_tx_desc); + + if (g_rx_desc) + free(g_rx_desc); + + pfe_firmware_exit(); + + return 0; +} diff --git a/drivers/net/pfe_eth/pfe_eth.c b/drivers/net/pfe_eth/pfe_eth.c new file mode 100644 index 0000000000..e6c6c8c9ab --- /dev/null +++ b/drivers/net/pfe_eth/pfe_eth.c @@ -0,0 +1,297 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <dm/platform_data/pfe_dm_eth.h> +#include <net.h> +#include <net/pfe_eth/pfe_eth.h> +#include <net/pfe_eth/pfe_mdio.h> + +struct gemac_s gem_info[] = { + /* PORT_0 configuration */ + { + /* GEMAC config */ + .gemac_speed = PFE_MAC_SPEED_1000M, + .gemac_duplex = DUPLEX_FULL, + + /* phy iface */ + .phy_address = CONFIG_PFE_EMAC1_PHY_ADDR, + .phy_mode = PHY_INTERFACE_MODE_SGMII, + }, + /* PORT_1 configuration */ + { + /* GEMAC config */ + .gemac_speed = PFE_MAC_SPEED_1000M, + .gemac_duplex = DUPLEX_FULL, + + /* phy iface */ + .phy_address = CONFIG_PFE_EMAC2_PHY_ADDR, + .phy_mode = PHY_INTERFACE_MODE_RGMII_TXID, + }, +}; + +static inline void pfe_gemac_enable(void *gemac_base) +{ + writel(readl(gemac_base + EMAC_ECNTRL_REG) | + EMAC_ECNTRL_ETHER_EN, gemac_base + EMAC_ECNTRL_REG); +} + +static inline void pfe_gemac_disable(void *gemac_base) +{ + writel(readl(gemac_base + EMAC_ECNTRL_REG) & + ~EMAC_ECNTRL_ETHER_EN, gemac_base + EMAC_ECNTRL_REG); +} + +static inline void pfe_gemac_set_speed(void *gemac_base, u32 speed) +{ + struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR; + u32 ecr = readl(gemac_base + EMAC_ECNTRL_REG) & ~EMAC_ECNTRL_SPEED; + u32 rcr = readl(gemac_base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_RMII_10T; + u32 rgmii_pcr = in_be32(&scfg->rgmiipcr) & + ~(SCFG_RGMIIPCR_SETSP_1000M | SCFG_RGMIIPCR_SETSP_10M); + + if (speed == _1000BASET) { + ecr |= EMAC_ECNTRL_SPEED; + rgmii_pcr |= SCFG_RGMIIPCR_SETSP_1000M; + } else if (speed != _100BASET) { + rcr |= EMAC_RCNTRL_RMII_10T; + rgmii_pcr |= SCFG_RGMIIPCR_SETSP_10M; + } + + writel(ecr, gemac_base + EMAC_ECNTRL_REG); + out_be32(&scfg->rgmiipcr, rgmii_pcr | SCFG_RGMIIPCR_SETFD); + + /* remove loop back */ + rcr &= ~EMAC_RCNTRL_LOOP; + /* enable flow control */ + rcr |= EMAC_RCNTRL_FCE; + + /* Enable MII mode */ + rcr |= EMAC_RCNTRL_MII_MODE; + + writel(rcr, gemac_base + EMAC_RCNTRL_REG); + + /* Enable Tx full duplex */ + writel(readl(gemac_base + EMAC_TCNTRL_REG) | EMAC_TCNTRL_FDEN, + gemac_base + EMAC_TCNTRL_REG); +} + +static int pfe_eth_write_hwaddr(struct udevice *dev) +{ + struct pfe_eth_dev *priv = dev_get_priv(dev); + struct gemac_s *gem = priv->gem; + struct eth_pdata *pdata = dev_get_platdata(dev); + uchar *mac = pdata->enetaddr; + + writel((mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3], + gem->gemac_base + EMAC_PHY_ADDR_LOW); + writel((mac[4] << 24) + (mac[5] << 16) + 0x8808, gem->gemac_base + + EMAC_PHY_ADDR_HIGH); + return 0; +} + +/** Stops or Disables GEMAC pointing to this eth iface. + * + * @param[in] edev Pointer to eth device structure. + * + * @return none + */ +static inline void pfe_eth_stop(struct udevice *dev) +{ + struct pfe_eth_dev *priv = dev_get_priv(dev); + + pfe_gemac_disable(priv->gem->gemac_base); + + gpi_disable(priv->gem->egpi_base); +} + +static int pfe_eth_start(struct udevice *dev) +{ + struct pfe_eth_dev *priv = dev_get_priv(dev); + struct gemac_s *gem = priv->gem; + int speed; + + /* set ethernet mac address */ + pfe_eth_write_hwaddr(dev); + + writel(EMAC_TFWR, gem->gemac_base + EMAC_TFWR_STR_FWD); + writel(EMAC_RX_SECTION_FULL_32, gem->gemac_base + EMAC_RX_SECTIOM_FULL); + writel(EMAC_TRUNC_FL_16K, gem->gemac_base + EMAC_TRUNC_FL); + writel(EMAC_TX_SECTION_EMPTY_30, gem->gemac_base + + EMAC_TX_SECTION_EMPTY); + writel(EMAC_MIBC_NO_CLR_NO_DIS, gem->gemac_base + + EMAC_MIB_CTRL_STS_REG); + +#ifdef CONFIG_PHYLIB + /* Start up the PHY */ + if (phy_startup(priv->phydev)) { + printf("Could not initialize PHY %s\n", + priv->phydev->dev->name); + return -1; + } + speed = priv->phydev->speed; + printf("Speed detected %x\n", speed); + if (priv->phydev->duplex == DUPLEX_HALF) { + printf("Half duplex not supported\n"); + return -1; + } +#endif + + pfe_gemac_set_speed(gem->gemac_base, speed); + + /* Enable GPI */ + gpi_enable(gem->egpi_base); + + /* Enable GEMAC */ + pfe_gemac_enable(gem->gemac_base); + + return 0; +} + +static int pfe_eth_send(struct udevice *dev, void *packet, int length) +{ + struct pfe_eth_dev *priv = (struct pfe_eth_dev *)dev->priv; + + int rc; + int i = 0; + + rc = pfe_send(priv->gemac_port, packet, length); + + if (rc < 0) { + printf("Tx Queue full\n"); + return rc; + } + + while (1) { + rc = pfe_tx_done(); + if (rc == 0) + break; + + udelay(100); + i++; + if (i == 30000) + printf("Tx timeout, send failed\n"); + break; + } + + return 0; +} + +static int pfe_eth_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct pfe_eth_dev *priv = dev_get_priv(dev); + uchar *pkt_buf; + int len; + int phy_port; + + len = pfe_recv(&pkt_buf, &phy_port); + + if (len == 0) + return -EAGAIN; /* no packet in rx */ + else if (len < 0) + return -EAGAIN; + + debug("Rx pkt: pkt_buf(0x%p), phy_port(%d), len(%d)\n", pkt_buf, + phy_port, len); + if (phy_port != priv->gemac_port) { + printf("Rx pkt not on expected port\n"); + return -EAGAIN; + } + + *packetp = pkt_buf; + + return len; +} + +static int pfe_eth_probe(struct udevice *dev) +{ + struct pfe_eth_dev *priv = dev_get_priv(dev); + struct pfe_ddr_address *pfe_addr; + struct pfe_eth_pdata *pdata = dev_get_platdata(dev); + int ret = 0; + static int init_done; + + if (!init_done) { + pfe_addr = (struct pfe_ddr_address *)malloc(sizeof + (struct pfe_ddr_address)); + if (!pfe_addr) + return -ENOMEM; + + pfe_addr->ddr_pfe_baseaddr = + (void *)pdata->pfe_ddr_addr.ddr_pfe_baseaddr; + pfe_addr->ddr_pfe_phys_baseaddr = + (unsigned long)pdata->pfe_ddr_addr.ddr_pfe_phys_baseaddr; + + debug("ddr_pfe_baseaddr: %p, ddr_pfe_phys_baseaddr: %08x\n", + pfe_addr->ddr_pfe_baseaddr, + (u32)pfe_addr->ddr_pfe_phys_baseaddr); + + ret = pfe_drv_init(pfe_addr); + if (ret) + return ret; + + init_pfe_scfg_dcfg_regs(); + init_done = 1; + } + + priv->gemac_port = pdata->pfe_eth_pdata_mac.phy_interface; + priv->gem = &gem_info[priv->gemac_port]; + priv->dev = dev; + + switch (priv->gemac_port) { + case EMAC_PORT_0: + default: + priv->gem->gemac_base = EMAC1_BASE_ADDR; + priv->gem->egpi_base = EGPI1_BASE_ADDR; + break; + case EMAC_PORT_1: + priv->gem->gemac_base = EMAC2_BASE_ADDR; + priv->gem->egpi_base = EGPI2_BASE_ADDR; + break; + } + + ret = pfe_eth_board_init(dev); + if (ret) + return ret; + +#if defined(CONFIG_PHYLIB) + ret = pfe_phy_configure(priv, pdata->pfe_eth_pdata_mac.phy_interface, + gem_info[priv->gemac_port].phy_address); +#endif + return ret; +} + +static int pfe_eth_bind(struct udevice *dev) +{ + struct pfe_eth_pdata *pdata = dev_get_platdata(dev); + char name[20]; + + sprintf(name, "pfe_eth%u", pdata->pfe_eth_pdata_mac.phy_interface); + + return device_set_name(dev, name); +} + +static const struct eth_ops pfe_eth_ops = { + .start = pfe_eth_start, + .send = pfe_eth_send, + .recv = pfe_eth_recv, + .free_pkt = pfe_eth_free_pkt, + .stop = pfe_eth_stop, + .write_hwaddr = pfe_eth_write_hwaddr, +}; + +U_BOOT_DRIVER(pfe_eth) = { + .name = "pfe_eth", + .id = UCLASS_ETH, + .bind = pfe_eth_bind, + .probe = pfe_eth_probe, + .remove = pfe_eth_remove, + .ops = &pfe_eth_ops, + .priv_auto_alloc_size = sizeof(struct pfe_eth_dev), + .platdata_auto_alloc_size = sizeof(struct pfe_eth_pdata) +}; diff --git a/drivers/net/pfe_eth/pfe_firmware.c b/drivers/net/pfe_eth/pfe_firmware.c new file mode 100644 index 0000000000..9dc063dc75 --- /dev/null +++ b/drivers/net/pfe_eth/pfe_firmware.c @@ -0,0 +1,230 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * @file + * Contains all the functions to handle parsing and loading of PE firmware + * files. + */ + +#include <net/pfe_eth/pfe_eth.h> +#include <net/pfe_eth/pfe_firmware.h> + +#define PFE_FIRMEWARE_FIT_CNF_NAME "config@1" + +static const void *pfe_fit_addr = (void *)CONFIG_SYS_LS_PFE_FW_ADDR; + +/* + * PFE elf firmware loader. + * Loads an elf firmware image into a list of PE's (specified using a bitmask) + * + * @param pe_mask Mask of PE id's to load firmware to + * @param pfe_firmware Pointer to the firmware image + * + * @return 0 on success, a negative value on error + */ +static int pfe_load_elf(int pe_mask, uint8_t *pfe_firmware) +{ + Elf32_Ehdr *elf_hdr = (Elf32_Ehdr *)pfe_firmware; + Elf32_Half sections = be16_to_cpu(elf_hdr->e_shnum); + Elf32_Shdr *shdr = (Elf32_Shdr *)(pfe_firmware + + be32_to_cpu(elf_hdr->e_shoff)); + int id, section; + int ret; + + debug("%s: no of sections: %d\n", __func__, sections); + + /* Some sanity checks */ + if (strncmp((char *)&elf_hdr->e_ident[EI_MAG0], ELFMAG, SELFMAG)) { + printf("%s: incorrect elf magic number\n", __func__); + return -1; + } + + if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32) { + printf("%s: incorrect elf class(%x)\n", __func__, + elf_hdr->e_ident[EI_CLASS]); + return -1; + } + + if (elf_hdr->e_ident[EI_DATA] != ELFDATA2MSB) { + printf("%s: incorrect elf data(%x)\n", __func__, + elf_hdr->e_ident[EI_DATA]); + return -1; + } + + if (be16_to_cpu(elf_hdr->e_type) != ET_EXEC) { + printf("%s: incorrect elf file type(%x)\n", __func__, + be16_to_cpu(elf_hdr->e_type)); + return -1; + } + + for (section = 0; section < sections; section++, shdr++) { + if (!(be32_to_cpu(shdr->sh_flags) & (SHF_WRITE | SHF_ALLOC | + SHF_EXECINSTR))) + continue; + for (id = 0; id < MAX_PE; id++) + if (pe_mask & BIT(id)) { + ret = pe_load_elf_section(id, + pfe_firmware, shdr); + if (ret < 0) + goto err; + } + } + return 0; + +err: + return ret; +} + +/* + * Get PFE firmware from FIT image + * + * @param data pointer to PFE firmware + * @param size pointer to size of the firmware + * @param fw_name pfe firmware name, either class or tmu + * + * @return 0 on success, a negative value on error + */ +static int pfe_get_fw(const void **data, + size_t *size, char *fw_name) +{ + int conf_node_off, fw_node_off; + char *conf_node_name = NULL; + char *desc; + int ret = 0; + + conf_node_name = PFE_FIRMEWARE_FIT_CNF_NAME; + + conf_node_off = fit_conf_get_node(pfe_fit_addr, conf_node_name); + if (conf_node_off < 0) { + printf("PFE Firmware: %s: no such config\n", conf_node_name); + return -ENOENT; + } + + fw_node_off = fit_conf_get_prop_node(pfe_fit_addr, conf_node_off, + fw_name); + if (fw_node_off < 0) { + printf("PFE Firmware: No '%s' in config\n", + fw_name); + return -ENOLINK; + } + + if (!(fit_image_verify(pfe_fit_addr, fw_node_off))) { + printf("PFE Firmware: Bad firmware image (bad CRC)\n"); + return -EINVAL; + } + + if (fit_image_get_data(pfe_fit_addr, fw_node_off, data, size)) { + printf("PFE Firmware: Can't get %s subimage data/size", + fw_name); + return -ENOENT; + } + + ret = fit_get_desc(pfe_fit_addr, fw_node_off, &desc); + if (ret) + printf("PFE Firmware: Can't get description\n"); + else + printf("%s\n", desc); + + return ret; +} + +/* + * Check PFE FIT image + * + * @return 0 on success, a negative value on error + */ +static int pfe_fit_check(void) +{ + int ret = 0; + + ret = fdt_check_header(pfe_fit_addr); + if (ret) { + printf("PFE Firmware: Bad firmware image (not a FIT image)\n"); + return ret; + } + + if (!fit_check_format(pfe_fit_addr)) { + printf("PFE Firmware: Bad firmware image (bad FIT header)\n"); + ret = -1; + return ret; + } + + return ret; +} + +/* + * PFE firmware initialization. + * Loads different firmware files from FIT image. + * Initializes PE IMEM/DMEM and UTIL-PE DDR + * Initializes control path symbol addresses (by looking them up in the elf + * firmware files + * Takes PE's out of reset + * + * @return 0 on success, a negative value on error + */ +int pfe_firmware_init(void) +{ + char *pfe_firmware_name; + const void *raw_image_addr; + size_t raw_image_size = 0; + u8 *pfe_firmware; + int ret = 0; + int fw_count; + + ret = pfe_fit_check(); + if (ret) + goto err; + + for (fw_count = 0; fw_count < 2; fw_count++) { + if (fw_count == 0) + pfe_firmware_name = "class"; + else if (fw_count == 1) + pfe_firmware_name = "tmu"; + + pfe_get_fw(&raw_image_addr, &raw_image_size, pfe_firmware_name); + pfe_firmware = malloc(raw_image_size); + if (!pfe_firmware) + return -ENOMEM; + memcpy((void *)pfe_firmware, (void *)raw_image_addr, + raw_image_size); + + if (fw_count == 0) + ret = pfe_load_elf(CLASS_MASK, pfe_firmware); + else if (fw_count == 1) + ret = pfe_load_elf(TMU_MASK, pfe_firmware); + + if (ret < 0) { + printf("%s: %s firmware load failed\n", __func__, + pfe_firmware_name); + goto err; + } + debug("%s: %s firmware loaded\n", __func__, pfe_firmware_name); + free(pfe_firmware); + } + + tmu_enable(0xb); + class_enable(); + gpi_enable(HGPI_BASE_ADDR); + +err: + return ret; +} + +/* + * PFE firmware cleanup + * Puts PE's in reset + */ +void pfe_firmware_exit(void) +{ + debug("%s\n", __func__); + + class_disable(); + tmu_disable(0xf); + hif_tx_disable(); + hif_rx_disable(); +} diff --git a/drivers/net/pfe_eth/pfe_hw.c b/drivers/net/pfe_eth/pfe_hw.c new file mode 100644 index 0000000000..12bb0da9b9 --- /dev/null +++ b/drivers/net/pfe_eth/pfe_hw.c @@ -0,0 +1,999 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier:GPL-2.0+ + */ +#include <net/pfe_eth/pfe_eth.h> +#include <net/pfe_eth/pfe/pfe_hw.h> + +static struct pe_info pe[MAX_PE]; + +/* + * Initializes the PFE library. + * Must be called before using any of the library functions. + */ +void pfe_lib_init(void) +{ + int pfe_pe_id; + + for (pfe_pe_id = CLASS0_ID; pfe_pe_id <= CLASS_MAX_ID; pfe_pe_id++) { + pe[pfe_pe_id].dmem_base_addr = + (u32)CLASS_DMEM_BASE_ADDR(pfe_pe_id); + pe[pfe_pe_id].pmem_base_addr = + (u32)CLASS_IMEM_BASE_ADDR(pfe_pe_id); + pe[pfe_pe_id].pmem_size = (u32)CLASS_IMEM_SIZE; + pe[pfe_pe_id].mem_access_wdata = + (void *)CLASS_MEM_ACCESS_WDATA; + pe[pfe_pe_id].mem_access_addr = (void *)CLASS_MEM_ACCESS_ADDR; + pe[pfe_pe_id].mem_access_rdata = (void *)CLASS_MEM_ACCESS_RDATA; + } + + for (pfe_pe_id = TMU0_ID; pfe_pe_id <= TMU_MAX_ID; pfe_pe_id++) { + if (pfe_pe_id == TMU2_ID) + continue; + pe[pfe_pe_id].dmem_base_addr = + (u32)TMU_DMEM_BASE_ADDR(pfe_pe_id - TMU0_ID); + pe[pfe_pe_id].pmem_base_addr = + (u32)TMU_IMEM_BASE_ADDR(pfe_pe_id - TMU0_ID); + pe[pfe_pe_id].pmem_size = (u32)TMU_IMEM_SIZE; + pe[pfe_pe_id].mem_access_wdata = (void *)TMU_MEM_ACCESS_WDATA; + pe[pfe_pe_id].mem_access_addr = (void *)TMU_MEM_ACCESS_ADDR; + pe[pfe_pe_id].mem_access_rdata = (void *)TMU_MEM_ACCESS_RDATA; + } +} + +/* + * Writes a buffer to PE internal memory from the host + * through indirect access registers. + * + * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, + * ..., UTIL_ID) + * @param[in] mem_access_addr DMEM destination address (must be 32bit + * aligned) + * @param[in] src Buffer source address + * @param[in] len Number of bytes to copy + */ +static void pe_mem_memcpy_to32(int id, u32 mem_access_addr, const void *src, + unsigned int len) +{ + u32 offset = 0, val, addr; + unsigned int len32 = len >> 2; + int i; + + addr = mem_access_addr | PE_MEM_ACCESS_WRITE | + PE_MEM_ACCESS_BYTE_ENABLE(0, 4); + + for (i = 0; i < len32; i++, offset += 4, src += 4) { + val = *(u32 *)src; + writel(cpu_to_be32(val), pe[id].mem_access_wdata); + writel(addr + offset, pe[id].mem_access_addr); + } + + len = (len & 0x3); + if (len) { + val = 0; + + addr = (mem_access_addr | PE_MEM_ACCESS_WRITE | + PE_MEM_ACCESS_BYTE_ENABLE(0, len)) + offset; + + for (i = 0; i < len; i++, src++) + val |= (*(u8 *)src) << (8 * i); + + writel(cpu_to_be32(val), pe[id].mem_access_wdata); + writel(addr, pe[id].mem_access_addr); + } +} + +/* + * Writes a buffer to PE internal data memory (DMEM) from the host + * through indirect access registers. + * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, + * ..., UTIL_ID) + * @param[in] dst DMEM destination address (must be 32bit + * aligned) + * @param[in] src Buffer source address + * @param[in] len Number of bytes to copy + */ +static void pe_dmem_memcpy_to32(int id, u32 dst, const void *src, + unsigned int len) +{ + pe_mem_memcpy_to32(id, pe[id].dmem_base_addr | dst | PE_MEM_ACCESS_DMEM, + src, len); +} + +/* + * Writes a buffer to PE internal program memory (PMEM) from the host + * through indirect access registers. + * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, + * ..., TMU3_ID) + * @param[in] dst PMEM destination address (must be 32bit + * aligned) + * @param[in] src Buffer source address + * @param[in] len Number of bytes to copy + */ +static void pe_pmem_memcpy_to32(int id, u32 dst, const void *src, + unsigned int len) +{ + pe_mem_memcpy_to32(id, pe[id].pmem_base_addr | (dst & (pe[id].pmem_size + - 1)) | PE_MEM_ACCESS_IMEM, src, len); +} + +/* + * Reads PE internal program memory (IMEM) from the host + * through indirect access registers. + * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, + * ..., TMU3_ID) + * @param[in] addr PMEM read address (must be aligned on size) + * @param[in] size Number of bytes to read (maximum 4, must not + * cross 32bit boundaries) + * @return the data read (in PE endianness, i.e BE). + */ +u32 pe_pmem_read(int id, u32 addr, u8 size) +{ + u32 offset = addr & 0x3; + u32 mask = 0xffffffff >> ((4 - size) << 3); + u32 val; + + addr = pe[id].pmem_base_addr | ((addr & ~0x3) & (pe[id].pmem_size - 1)) + | PE_MEM_ACCESS_READ | PE_MEM_ACCESS_IMEM | + PE_MEM_ACCESS_BYTE_ENABLE(offset, size); + + writel(addr, pe[id].mem_access_addr); + val = be32_to_cpu(readl(pe[id].mem_access_rdata)); + + return (val >> (offset << 3)) & mask; +} + +/* + * Writes PE internal data memory (DMEM) from the host + * through indirect access registers. + * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, + * ..., UTIL_ID) + * @param[in] val Value to write (in PE endianness, i.e BE) + * @param[in] addr DMEM write address (must be aligned on size) + * @param[in] size Number of bytes to write (maximum 4, must not + * cross 32bit boundaries) + */ +void pe_dmem_write(int id, u32 val, u32 addr, u8 size) +{ + u32 offset = addr & 0x3; + + addr = pe[id].dmem_base_addr | (addr & ~0x3) | PE_MEM_ACCESS_WRITE | + PE_MEM_ACCESS_DMEM | PE_MEM_ACCESS_BYTE_ENABLE(offset, size); + + /* Indirect access interface is byte swapping data being written */ + writel(cpu_to_be32(val << (offset << 3)), pe[id].mem_access_wdata); + writel(addr, pe[id].mem_access_addr); +} + +/* + * Reads PE internal data memory (DMEM) from the host + * through indirect access registers. + * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, + * ..., UTIL_ID) + * @param[in] addr DMEM read address (must be aligned on size) + * @param[in] size Number of bytes to read (maximum 4, must not + * cross 32bit boundaries) + * @return the data read (in PE endianness, i.e BE). + */ +u32 pe_dmem_read(int id, u32 addr, u8 size) +{ + u32 offset = addr & 0x3; + u32 mask = 0xffffffff >> ((4 - size) << 3); + u32 val; + + addr = pe[id].dmem_base_addr | (addr & ~0x3) | PE_MEM_ACCESS_READ | + PE_MEM_ACCESS_DMEM | PE_MEM_ACCESS_BYTE_ENABLE(offset, size); + + writel(addr, pe[id].mem_access_addr); + + /* Indirect access interface is byte swapping data being read */ + val = be32_to_cpu(readl(pe[id].mem_access_rdata)); + + return (val >> (offset << 3)) & mask; +} + +/* + * This function is used to write to CLASS internal bus peripherals (ccu, + * pe-lem) from the host + * through indirect access registers. + * @param[in] val value to write + * @param[in] addr Address to write to (must be aligned on size) + * @param[in] size Number of bytes to write (1, 2 or 4) + * + */ +static void class_bus_write(u32 val, u32 addr, u8 size) +{ + u32 offset = addr & 0x3; + + writel((addr & CLASS_BUS_ACCESS_BASE_MASK), CLASS_BUS_ACCESS_BASE); + + addr = (addr & ~CLASS_BUS_ACCESS_BASE_MASK) | PE_MEM_ACCESS_WRITE | + (size << 24); + + writel(cpu_to_be32(val << (offset << 3)), CLASS_BUS_ACCESS_WDATA); + writel(addr, CLASS_BUS_ACCESS_ADDR); +} + +/* + * Reads from CLASS internal bus peripherals (ccu, pe-lem) from the host + * through indirect access registers. + * @param[in] addr Address to read from (must be aligned on size) + * @param[in] size Number of bytes to read (1, 2 or 4) + * @return the read data + */ +static u32 class_bus_read(u32 addr, u8 size) +{ + u32 offset = addr & 0x3; + u32 mask = 0xffffffff >> ((4 - size) << 3); + u32 val; + + writel((addr & CLASS_BUS_ACCESS_BASE_MASK), CLASS_BUS_ACCESS_BASE); + + addr = (addr & ~CLASS_BUS_ACCESS_BASE_MASK) | (size << 24); + + writel(addr, CLASS_BUS_ACCESS_ADDR); + val = be32_to_cpu(readl(CLASS_BUS_ACCESS_RDATA)); + + return (val >> (offset << 3)) & mask; +} + +/* + * Writes data to the cluster memory (PE_LMEM) + * @param[in] dst PE LMEM destination address (must be 32bit aligned) + * @param[in] src Buffer source address + * @param[in] len Number of bytes to copy + */ +static void class_pe_lmem_memcpy_to32(u32 dst, const void *src, + unsigned int len) +{ + u32 len32 = len >> 2; + int i; + + for (i = 0; i < len32; i++, src += 4, dst += 4) + class_bus_write(*(u32 *)src, dst, 4); + + if (len & 0x2) { + class_bus_write(*(u16 *)src, dst, 2); + src += 2; + dst += 2; + } + + if (len & 0x1) { + class_bus_write(*(u8 *)src, dst, 1); + src++; + dst++; + } +} + +/* + * Writes value to the cluster memory (PE_LMEM) + * @param[in] dst PE LMEM destination address (must be 32bit aligned) + * @param[in] val Value to write + * @param[in] len Number of bytes to write + */ +static void class_pe_lmem_memset(u32 dst, int val, unsigned int len) +{ + u32 len32 = len >> 2; + int i; + + val = val | (val << 8) | (val << 16) | (val << 24); + + for (i = 0; i < len32; i++, dst += 4) + class_bus_write(val, dst, 4); + + if (len & 0x2) { + class_bus_write(val, dst, 2); + dst += 2; + } + + if (len & 0x1) { + class_bus_write(val, dst, 1); + dst++; + } +} + +/* + * Reads data from the cluster memory (PE_LMEM) + * @param[out] dst pointer to the source buffer data are copied to + * @param[in] len length in bytes of the amount of data to read + * from cluster memory + * @param[in] offset offset in bytes in the cluster memory where data are + * read from + */ +void pe_lmem_read(u32 *dst, u32 len, u32 offset) +{ + u32 len32 = len >> 2; + int i = 0; + + for (i = 0; i < len32; dst++, i++, offset += 4) + *dst = class_bus_read(PE_LMEM_BASE_ADDR + offset, 4); + + if (len & 0x03) + *dst = class_bus_read(PE_LMEM_BASE_ADDR + offset, (len & 0x03)); +} + +/* + * Writes data to the cluster memory (PE_LMEM) + * @param[in] src pointer to the source buffer data are copied from + * @param[in] len length in bytes of the amount of data to write to the + * cluster memory + * @param[in] offset offset in bytes in the cluster memory where data are + * written to + */ +void pe_lmem_write(u32 *src, u32 len, u32 offset) +{ + u32 len32 = len >> 2; + int i = 0; + + for (i = 0; i < len32; src++, i++, offset += 4) + class_bus_write(*src, PE_LMEM_BASE_ADDR + offset, 4); + + if (len & 0x03) + class_bus_write(*src, PE_LMEM_BASE_ADDR + offset, (len & + 0x03)); +} + +/* + * Loads an elf section into pmem + * Code needs to be at least 16bit aligned and only PROGBITS sections are + * supported + * + * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, ..., + * TMU3_ID) + * @param[in] data pointer to the elf firmware + * @param[in] shdr pointer to the elf section header + */ +static int pe_load_pmem_section(int id, const void *data, Elf32_Shdr *shdr) +{ + u32 offset = be32_to_cpu(shdr->sh_offset); + u32 addr = be32_to_cpu(shdr->sh_addr); + u32 size = be32_to_cpu(shdr->sh_size); + u32 type = be32_to_cpu(shdr->sh_type); + + if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) { + printf( + "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n", + __func__, addr, (unsigned long)data + offset); + + return -1; + } + + if (addr & 0x1) { + printf("%s: load address(%x) is not 16bit aligned\n", + __func__, addr); + return -1; + } + + if (size & 0x1) { + printf("%s: load size(%x) is not 16bit aligned\n", __func__, + size); + return -1; + } + + debug("pmem pe%d @%x len %d\n", id, addr, size); + switch (type) { + case SHT_PROGBITS: + pe_pmem_memcpy_to32(id, addr, data + offset, size); + break; + + default: + printf("%s: unsupported section type(%x)\n", __func__, type); + return -1; + } + + return 0; +} + +/* + * Loads an elf section into dmem + * Data needs to be at least 32bit aligned, NOBITS sections are correctly + * initialized to 0 + * + * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, + * ..., UTIL_ID) + * @param[in] data pointer to the elf firmware + * @param[in] shdr pointer to the elf section header + */ +static int pe_load_dmem_section(int id, const void *data, Elf32_Shdr *shdr) +{ + u32 offset = be32_to_cpu(shdr->sh_offset); + u32 addr = be32_to_cpu(shdr->sh_addr); + u32 size = be32_to_cpu(shdr->sh_size); + u32 type = be32_to_cpu(shdr->sh_type); + u32 size32 = size >> 2; + int i; + + if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) { + printf( + "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n", + __func__, addr, (unsigned long)data + offset); + + return -1; + } + + if (addr & 0x3) { + printf("%s: load address(%x) is not 32bit aligned\n", + __func__, addr); + return -1; + } + + switch (type) { + case SHT_PROGBITS: + debug("dmem pe%d @%x len %d\n", id, addr, size); + pe_dmem_memcpy_to32(id, addr, data + offset, size); + break; + + case SHT_NOBITS: + debug("dmem zero pe%d @%x len %d\n", id, addr, size); + for (i = 0; i < size32; i++, addr += 4) + pe_dmem_write(id, 0, addr, 4); + + if (size & 0x3) + pe_dmem_write(id, 0, addr, size & 0x3); + + break; + + default: + printf("%s: unsupported section type(%x)\n", __func__, type); + return -1; + } + + return 0; +} + +/* + * Loads an elf section into DDR + * Data needs to be at least 32bit aligned, NOBITS sections are correctly + * initialized to 0 + * + * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, + * ..., UTIL_ID) + * @param[in] data pointer to the elf firmware + * @param[in] shdr pointer to the elf section header + */ +static int pe_load_ddr_section(int id, const void *data, Elf32_Shdr *shdr) +{ + u32 offset = be32_to_cpu(shdr->sh_offset); + u32 addr = be32_to_cpu(shdr->sh_addr); + u32 size = be32_to_cpu(shdr->sh_size); + u32 type = be32_to_cpu(shdr->sh_type); + u32 flags = be32_to_cpu(shdr->sh_flags); + + switch (type) { + case SHT_PROGBITS: + debug("ddr pe%d @%x len %d\n", id, addr, size); + if (flags & SHF_EXECINSTR) { + if (id <= CLASS_MAX_ID) { + /* DO the loading only once in DDR */ + if (id == CLASS0_ID) { + debug( + "%s: load address(%x) and elf file address(%lx) rcvd\n" + , __func__, addr, + (unsigned long)data + offset); + if (((unsigned long)(data + offset) + & 0x3) != (addr & 0x3)) { + printf( + "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n", + __func__, addr, + (unsigned long)data + + offset); + + return -1; + } + + if (addr & 0x1) { + printf( + "%s: load address(%x) is not 16bit aligned\n" + , __func__, addr); + return -1; + } + + if (size & 0x1) { + printf( + "%s: load length(%x) is not 16bit aligned\n" + , __func__, size); + return -1; + } + + memcpy((void *)DDR_PFE_TO_VIRT(addr), + data + offset, size); + } + } else { + printf( + "%s: unsupported ddr section type(%x) for PE(%d)\n" + , __func__, type, id); + return -1; + } + + } else { + memcpy((void *)DDR_PFE_TO_VIRT(addr), data + offset, + size); + } + + break; + + case SHT_NOBITS: + debug("ddr zero pe%d @%x len %d\n", id, addr, size); + memset((void *)DDR_PFE_TO_VIRT(addr), 0, size); + + break; + + default: + printf("%s: unsupported section type(%x)\n", __func__, type); + return -1; + } + + return 0; +} + +/* + * Loads an elf section into pe lmem + * Data needs to be at least 32bit aligned, NOBITS sections are correctly + * initialized to 0 + * + * @param[in] id PE identification (CLASS0_ID,..., CLASS5_ID) + * @param[in] data pointer to the elf firmware + * @param[in] shdr pointer to the elf section header + */ +static int pe_load_pe_lmem_section(int id, const void *data, Elf32_Shdr *shdr) +{ + u32 offset = be32_to_cpu(shdr->sh_offset); + u32 addr = be32_to_cpu(shdr->sh_addr); + u32 size = be32_to_cpu(shdr->sh_size); + u32 type = be32_to_cpu(shdr->sh_type); + + if (id > CLASS_MAX_ID) { + printf("%s: unsupported pe-lmem section type(%x) for PE(%d)\n", + __func__, type, id); + return -1; + } + + if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) { + printf( + "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n", + __func__, addr, (unsigned long)data + offset); + + return -1; + } + + if (addr & 0x3) { + printf("%s: load address(%x) is not 32bit aligned\n", + __func__, addr); + return -1; + } + + debug("lmem pe%d @%x len %d\n", id, addr, size); + + switch (type) { + case SHT_PROGBITS: + class_pe_lmem_memcpy_to32(addr, data + offset, size); + break; + + case SHT_NOBITS: + class_pe_lmem_memset(addr, 0, size); + break; + + default: + printf("%s: unsupported section type(%x)\n", __func__, type); + return -1; + } + + return 0; +} + +/* + * Loads an elf section into a PE + * For now only supports loading a section to dmem (all PE's), pmem (class and + * tmu PE's), DDDR (util PE code) + * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, + * ..., UTIL_ID) + * @param[in] data pointer to the elf firmware + * @param[in] shdr pointer to the elf section header + */ +int pe_load_elf_section(int id, const void *data, Elf32_Shdr *shdr) +{ + u32 addr = be32_to_cpu(shdr->sh_addr); + u32 size = be32_to_cpu(shdr->sh_size); + + if (IS_DMEM(addr, size)) + return pe_load_dmem_section(id, data, shdr); + else if (IS_PMEM(addr, size)) + return pe_load_pmem_section(id, data, shdr); + else if (IS_PFE_LMEM(addr, size)) + return 0; + else if (IS_PHYS_DDR(addr, size)) + return pe_load_ddr_section(id, data, shdr); + else if (IS_PE_LMEM(addr, size)) + return pe_load_pe_lmem_section(id, data, shdr); + + printf("%s: unsupported memory range(%x)\n", __func__, addr); + + return 0; +} + +/**************************** BMU ***************************/ +/* + * Resets a BMU block. + * @param[in] base BMU block base address + */ +static inline void bmu_reset(void *base) +{ + writel(CORE_SW_RESET, base + BMU_CTRL); + + /* Wait for self clear */ + while (readl(base + BMU_CTRL) & CORE_SW_RESET) + ; +} + +/* + * Enabled a BMU block. + * @param[in] base BMU block base address + */ +void bmu_enable(void *base) +{ + writel(CORE_ENABLE, base + BMU_CTRL); +} + +/* + * Disables a BMU block. + * @param[in] base BMU block base address + */ +static inline void bmu_disable(void *base) +{ + writel(CORE_DISABLE, base + BMU_CTRL); +} + +/* + * Sets the configuration of a BMU block. + * @param[in] base BMU block base address + * @param[in] cfg BMU configuration + */ +static inline void bmu_set_config(void *base, struct bmu_cfg *cfg) +{ + writel(cfg->baseaddr, base + BMU_UCAST_BASE_ADDR); + writel(cfg->count & 0xffff, base + BMU_UCAST_CONFIG); + writel(cfg->size & 0xffff, base + BMU_BUF_SIZE); + + /* Interrupts are never used */ + writel(0x0, base + BMU_INT_ENABLE); +} + +/* + * Initializes a BMU block. + * @param[in] base BMU block base address + * @param[in] cfg BMU configuration + */ +void bmu_init(void *base, struct bmu_cfg *cfg) +{ + bmu_disable(base); + + bmu_set_config(base, cfg); + + bmu_reset(base); +} + +/**************************** GPI ***************************/ +/* + * Resets a GPI block. + * @param[in] base GPI base address + */ +static inline void gpi_reset(void *base) +{ + writel(CORE_SW_RESET, base + GPI_CTRL); +} + +/* + * Enables a GPI block. + * @param[in] base GPI base address + */ +void gpi_enable(void *base) +{ + writel(CORE_ENABLE, base + GPI_CTRL); +} + +/* + * Disables a GPI block. + * @param[in] base GPI base address + */ +void gpi_disable(void *base) +{ + writel(CORE_DISABLE, base + GPI_CTRL); +} + +/* + * Sets the configuration of a GPI block. + * @param[in] base GPI base address + * @param[in] cfg GPI configuration + */ +static inline void gpi_set_config(void *base, struct gpi_cfg *cfg) +{ + writel(CBUS_VIRT_TO_PFE(BMU1_BASE_ADDR + BMU_ALLOC_CTRL), base + + GPI_LMEM_ALLOC_ADDR); + writel(CBUS_VIRT_TO_PFE(BMU1_BASE_ADDR + BMU_FREE_CTRL), base + + GPI_LMEM_FREE_ADDR); + writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_ALLOC_CTRL), base + + GPI_DDR_ALLOC_ADDR); + writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_FREE_CTRL), base + + GPI_DDR_FREE_ADDR); + writel(CBUS_VIRT_TO_PFE(CLASS_INQ_PKTPTR), base + GPI_CLASS_ADDR); + writel(DDR_HDR_SIZE, base + GPI_DDR_DATA_OFFSET); + writel(LMEM_HDR_SIZE, base + GPI_LMEM_DATA_OFFSET); + writel(0, base + GPI_LMEM_SEC_BUF_DATA_OFFSET); + writel(0, base + GPI_DDR_SEC_BUF_DATA_OFFSET); + writel((DDR_HDR_SIZE << 16) | LMEM_HDR_SIZE, base + GPI_HDR_SIZE); + writel((DDR_BUF_SIZE << 16) | LMEM_BUF_SIZE, base + GPI_BUF_SIZE); + + writel(((cfg->lmem_rtry_cnt << 16) | (GPI_DDR_BUF_EN << 1) | + GPI_LMEM_BUF_EN), base + GPI_RX_CONFIG); + writel(cfg->tmlf_txthres, base + GPI_TMLF_TX); + writel(cfg->aseq_len, base + GPI_DTX_ASEQ); + + /*Make GPI AXI transactions non-bufferable */ + writel(0x1, base + GPI_AXI_CTRL); +} + +/* + * Initializes a GPI block. + * @param[in] base GPI base address + * @param[in] cfg GPI configuration + */ +void gpi_init(void *base, struct gpi_cfg *cfg) +{ + gpi_reset(base); + + gpi_disable(base); + + gpi_set_config(base, cfg); +} + +/**************************** CLASSIFIER ***************************/ +/* + * Resets CLASSIFIER block. + */ +static inline void class_reset(void) +{ + writel(CORE_SW_RESET, CLASS_TX_CTRL); +} + +/* + * Enables all CLASS-PE's cores. + */ +void class_enable(void) +{ + writel(CORE_ENABLE, CLASS_TX_CTRL); +} + +/* + * Disables all CLASS-PE's cores. + */ +void class_disable(void) +{ + writel(CORE_DISABLE, CLASS_TX_CTRL); +} + +/* + * Sets the configuration of the CLASSIFIER block. + * @param[in] cfg CLASSIFIER configuration + */ +static inline void class_set_config(struct class_cfg *cfg) +{ + if (PLL_CLK_EN == 0) { + /* Clock ratio: for 1:1 the value is 0 */ + writel(0x0, CLASS_PE_SYS_CLK_RATIO); + } else { + /* Clock ratio: for 1:2 the value is 1 */ + writel(0x1, CLASS_PE_SYS_CLK_RATIO); + } + writel((DDR_HDR_SIZE << 16) | LMEM_HDR_SIZE, CLASS_HDR_SIZE); + writel(LMEM_BUF_SIZE, CLASS_LMEM_BUF_SIZE); + writel(CLASS_ROUTE_ENTRY_SIZE(CLASS_ROUTE_SIZE) | + CLASS_ROUTE_HASH_SIZE(cfg->route_table_hash_bits), + CLASS_ROUTE_HASH_ENTRY_SIZE); + writel(HASH_CRC_PORT_IP | QB2BUS_LE, CLASS_ROUTE_MULTI); + + writel(cfg->route_table_baseaddr, CLASS_ROUTE_TABLE_BASE); + memset((void *)DDR_PFE_TO_VIRT(cfg->route_table_baseaddr), 0, + ROUTE_TABLE_SIZE); + + writel(CLASS_PE0_RO_DM_ADDR0_VAL, CLASS_PE0_RO_DM_ADDR0); + writel(CLASS_PE0_RO_DM_ADDR1_VAL, CLASS_PE0_RO_DM_ADDR1); + writel(CLASS_PE0_QB_DM_ADDR0_VAL, CLASS_PE0_QB_DM_ADDR0); + writel(CLASS_PE0_QB_DM_ADDR1_VAL, CLASS_PE0_QB_DM_ADDR1); + writel(CBUS_VIRT_TO_PFE(TMU_PHY_INQ_PKTPTR), CLASS_TM_INQ_ADDR); + + writel(23, CLASS_AFULL_THRES); + writel(23, CLASS_TSQ_FIFO_THRES); + + writel(24, CLASS_MAX_BUF_CNT); + writel(24, CLASS_TSQ_MAX_CNT); + + /*Make Class AXI transactions non-bufferable */ + writel(0x1, CLASS_AXI_CTRL); + + /*Make Util AXI transactions non-bufferable */ + /*Util is disabled in U-boot, do it from here */ + writel(0x1, UTIL_AXI_CTRL); +} + +/* + * Initializes CLASSIFIER block. + * @param[in] cfg CLASSIFIER configuration + */ +void class_init(struct class_cfg *cfg) +{ + class_reset(); + + class_disable(); + + class_set_config(cfg); +} + +/**************************** TMU ***************************/ +/* + * Enables TMU-PE cores. + * @param[in] pe_mask TMU PE mask + */ +void tmu_enable(u32 pe_mask) +{ + writel(readl(TMU_TX_CTRL) | (pe_mask & 0xF), TMU_TX_CTRL); +} + +/* + * Disables TMU cores. + * @param[in] pe_mask TMU PE mask + */ +void tmu_disable(u32 pe_mask) +{ + writel(readl(TMU_TX_CTRL) & ~(pe_mask & 0xF), TMU_TX_CTRL); +} + +/* + * Initializes TMU block. + * @param[in] cfg TMU configuration + */ +void tmu_init(struct tmu_cfg *cfg) +{ + int q, phyno; + + /* keep in soft reset */ + writel(SW_RESET, TMU_CTRL); + + /*Make Class AXI transactions non-bufferable */ + writel(0x1, TMU_AXI_CTRL); + + /* enable EMAC PHY ports */ + writel(0x3, TMU_SYS_GENERIC_CONTROL); + + writel(750, TMU_INQ_WATERMARK); + + writel(CBUS_VIRT_TO_PFE(EGPI1_BASE_ADDR + GPI_INQ_PKTPTR), + TMU_PHY0_INQ_ADDR); + writel(CBUS_VIRT_TO_PFE(EGPI2_BASE_ADDR + GPI_INQ_PKTPTR), + TMU_PHY1_INQ_ADDR); + + writel(CBUS_VIRT_TO_PFE(HGPI_BASE_ADDR + GPI_INQ_PKTPTR), + TMU_PHY3_INQ_ADDR); + writel(CBUS_VIRT_TO_PFE(HIF_NOCPY_RX_INQ0_PKTPTR), TMU_PHY4_INQ_ADDR); + writel(CBUS_VIRT_TO_PFE(UTIL_INQ_PKTPTR), TMU_PHY5_INQ_ADDR); + writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_FREE_CTRL), + TMU_BMU_INQ_ADDR); + + /* enabling all 10 schedulers [9:0] of each TDQ */ + writel(0x3FF, TMU_TDQ0_SCH_CTRL); + writel(0x3FF, TMU_TDQ1_SCH_CTRL); + writel(0x3FF, TMU_TDQ3_SCH_CTRL); + + if (PLL_CLK_EN == 0) { + /* Clock ratio: for 1:1 the value is 0 */ + writel(0x0, TMU_PE_SYS_CLK_RATIO); + } else { + /* Clock ratio: for 1:2 the value is 1 */ + writel(0x1, TMU_PE_SYS_CLK_RATIO); + } + + /* Extra packet pointers will be stored from this address onwards */ + debug("TMU_LLM_BASE_ADDR %x\n", cfg->llm_base_addr); + writel(cfg->llm_base_addr, TMU_LLM_BASE_ADDR); + + debug("TMU_LLM_QUE_LEN %x\n", cfg->llm_queue_len); + writel(cfg->llm_queue_len, TMU_LLM_QUE_LEN); + + writel(5, TMU_TDQ_IIFG_CFG); + writel(DDR_BUF_SIZE, TMU_BMU_BUF_SIZE); + + writel(0x0, TMU_CTRL); + + /* MEM init */ + writel(MEM_INIT, TMU_CTRL); + + while (!(readl(TMU_CTRL) & MEM_INIT_DONE)) + ; + + /* LLM init */ + writel(LLM_INIT, TMU_CTRL); + + while (!(readl(TMU_CTRL) & LLM_INIT_DONE)) + ; + + /* set up each queue for tail drop */ + for (phyno = 0; phyno < 4; phyno++) { + if (phyno == 2) + continue; + for (q = 0; q < 16; q++) { + u32 qmax; + + writel((phyno << 8) | q, TMU_TEQ_CTRL); + writel(BIT(22), TMU_TEQ_QCFG); + + if (phyno == 3) + qmax = DEFAULT_TMU3_QDEPTH; + else + qmax = (q == 0) ? DEFAULT_Q0_QDEPTH : + DEFAULT_MAX_QDEPTH; + + writel(qmax << 18, TMU_TEQ_HW_PROB_CFG2); + writel(qmax >> 14, TMU_TEQ_HW_PROB_CFG3); + } + } + writel(0x05, TMU_TEQ_DISABLE_DROPCHK); + writel(0, TMU_CTRL); +} + +/**************************** HIF ***************************/ +/* + * Enable hif tx DMA and interrupt + */ +void hif_tx_enable(void) +{ + writel(HIF_CTRL_DMA_EN, HIF_TX_CTRL); +} + +/* + * Disable hif tx DMA and interrupt + */ +void hif_tx_disable(void) +{ + u32 hif_int; + + writel(0, HIF_TX_CTRL); + + hif_int = readl(HIF_INT_ENABLE); + hif_int &= HIF_TXPKT_INT_EN; + writel(hif_int, HIF_INT_ENABLE); +} + +/* + * Enable hif rx DMA and interrupt + */ +void hif_rx_enable(void) +{ + writel((HIF_CTRL_DMA_EN | HIF_CTRL_BDP_CH_START_WSTB), HIF_RX_CTRL); +} + +/* + * Disable hif rx DMA and interrupt + */ +void hif_rx_disable(void) +{ + u32 hif_int; + + writel(0, HIF_RX_CTRL); + + hif_int = readl(HIF_INT_ENABLE); + hif_int &= HIF_RXPKT_INT_EN; + writel(hif_int, HIF_INT_ENABLE); +} + +/* + * Initializes HIF copy block. + */ +void hif_init(void) +{ + /* Initialize HIF registers */ + writel(HIF_RX_POLL_CTRL_CYCLE << 16 | HIF_TX_POLL_CTRL_CYCLE, + HIF_POLL_CTRL); + /* Make HIF AXI transactions non-bufferable */ + writel(0x1, HIF_AXI_CTRL); +} diff --git a/drivers/net/pfe_eth/pfe_mdio.c b/drivers/net/pfe_eth/pfe_mdio.c new file mode 100644 index 0000000000..a78a4d63f3 --- /dev/null +++ b/drivers/net/pfe_eth/pfe_mdio.c @@ -0,0 +1,291 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <dm.h> +#include <dm/platform_data/pfe_dm_eth.h> +#include <net.h> +#include <net/pfe_eth/pfe_eth.h> + +extern struct gemac_s gem_info[]; +#if defined(CONFIG_PHYLIB) + +#define MDIO_TIMEOUT 5000 +static int pfe_write_addr(struct mii_dev *bus, int phy_addr, int dev_addr, + int reg_addr) +{ + void *reg_base = bus->priv; + u32 devadr; + u32 phy; + u32 reg_data; + int timeout = MDIO_TIMEOUT; + + devadr = ((dev_addr & EMAC_MII_DATA_RA_MASK) << EMAC_MII_DATA_RA_SHIFT); + phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT); + + reg_data = (EMAC_MII_DATA_TA | phy | devadr | reg_addr); + + writel(reg_data, reg_base + EMAC_MII_DATA_REG); + + /* + * wait for the MII interrupt + */ + while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) { + if (timeout-- <= 0) { + printf("Phy MDIO read/write timeout\n"); + return -1; + } + } + + /* + * clear MII interrupt + */ + writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG); + + return 0; +} + +static int pfe_phy_read(struct mii_dev *bus, int phy_addr, int dev_addr, + int reg_addr) +{ + void *reg_base = bus->priv; + u32 reg; + u32 phy; + u32 reg_data; + u16 val; + int timeout = MDIO_TIMEOUT; + + if (dev_addr == MDIO_DEVAD_NONE) { + reg = ((reg_addr & EMAC_MII_DATA_RA_MASK) << + EMAC_MII_DATA_RA_SHIFT); + } else { + pfe_write_addr(bus, phy_addr, dev_addr, reg_addr); + reg = ((dev_addr & EMAC_MII_DATA_RA_MASK) << + EMAC_MII_DATA_RA_SHIFT); + } + + phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT); + + if (dev_addr == MDIO_DEVAD_NONE) + reg_data = (EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_RD | + EMAC_MII_DATA_TA | phy | reg); + else + reg_data = (EMAC_MII_DATA_OP_CL45_RD | EMAC_MII_DATA_TA | + phy | reg); + + writel(reg_data, reg_base + EMAC_MII_DATA_REG); + + /* + * wait for the MII interrupt + */ + while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) { + if (timeout-- <= 0) { + printf("Phy MDIO read/write timeout\n"); + return -1; + } + } + + /* + * clear MII interrupt + */ + writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG); + + /* + * it's now safe to read the PHY's register + */ + val = (u16)readl(reg_base + EMAC_MII_DATA_REG); + debug("%s: %p phy: 0x%x reg:0x%08x val:%#x\n", __func__, reg_base, + phy_addr, reg_addr, val); + + return val; +} + +static int pfe_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr, + int reg_addr, u16 data) +{ + void *reg_base = bus->priv; + u32 reg; + u32 phy; + u32 reg_data; + int timeout = MDIO_TIMEOUT; + int val; + + if (dev_addr == MDIO_DEVAD_NONE) { + reg = ((reg_addr & EMAC_MII_DATA_RA_MASK) << + EMAC_MII_DATA_RA_SHIFT); + } else { + pfe_write_addr(bus, phy_addr, dev_addr, reg_addr); + reg = ((dev_addr & EMAC_MII_DATA_RA_MASK) << + EMAC_MII_DATA_RA_SHIFT); + } + + phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT); + + if (dev_addr == MDIO_DEVAD_NONE) + reg_data = (EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_WR | + EMAC_MII_DATA_TA | phy | reg | data); + else + reg_data = (EMAC_MII_DATA_OP_CL45_WR | EMAC_MII_DATA_TA | + phy | reg | data); + + writel(reg_data, reg_base + EMAC_MII_DATA_REG); + + /* + * wait for the MII interrupt + */ + while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) { + if (timeout-- <= 0) { + printf("Phy MDIO read/write timeout\n"); + return -1; + } + } + + /* + * clear MII interrupt + */ + writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG); + + debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phy_addr, + reg_addr, data); + + return val; +} + +static void pfe_configure_serdes(struct pfe_eth_dev *priv) +{ + struct mii_dev bus; + int value, sgmii_2500 = 0; + struct gemac_s *gem = priv->gem; + + if (gem->phy_mode == PHY_INTERFACE_MODE_SGMII_2500) + sgmii_2500 = 1; + + printf("%s %d\n", __func__, priv->gemac_port); + + /* PCS configuration done with corresponding GEMAC */ + bus.priv = gem_info[priv->gemac_port].gemac_base; + + pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x0); + pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x1); + pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x2); + pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x3); + + /* Reset serdes */ + pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x0, 0x8000); + + /* SGMII IF mode + AN enable only for 1G SGMII, not for 2.5G */ + value = PHY_SGMII_IF_MODE_SGMII; + if (!sgmii_2500) + value |= PHY_SGMII_IF_MODE_AN; + else + value |= PHY_SGMII_IF_MODE_SGMII_GBT; + + pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x14, value); + + /* Dev ability according to SGMII specification */ + value = PHY_SGMII_DEV_ABILITY_SGMII; + pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x4, value); + + /* These values taken from validation team */ + if (!sgmii_2500) { + pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x13, 0x0); + pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x12, 0x400); + } else { + pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x13, 0x7); + pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x12, 0xa120); + } + + /* Restart AN */ + value = PHY_SGMII_CR_DEF_VAL; + if (!sgmii_2500) + value |= PHY_SGMII_CR_RESET_AN; + /* Disable Auto neg for 2.5G SGMII as it doesn't support auto neg*/ + if (sgmii_2500) + value &= ~PHY_SGMII_ENABLE_AN; + pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0, value); +} + +int pfe_phy_configure(struct pfe_eth_dev *priv, int dev_id, int phy_id) +{ + struct phy_device *phydev = NULL; + struct udevice *dev = priv->dev; + struct gemac_s *gem = priv->gem; + struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR; + + if (!gem->bus) + return -1; + + /* Configure SGMII PCS */ + if (gem->phy_mode == PHY_INTERFACE_MODE_SGMII || + gem->phy_mode == PHY_INTERFACE_MODE_SGMII_2500) { + out_be32(&scfg->mdioselcr, 0x00000000); + pfe_configure_serdes(priv); + } + + mdelay(100); + + /* By this time on-chip SGMII initialization is done + * we can switch mdio interface to external PHYs + */ + out_be32(&scfg->mdioselcr, 0x80000000); + + phydev = phy_connect(gem->bus, phy_id, dev, gem->phy_mode); + if (!phydev) { + printf("phy_connect failed\n"); + return -ENODEV; + } + + phy_config(phydev); + + priv->phydev = phydev; + + return 0; +} +#endif + +struct mii_dev *pfe_mdio_init(struct pfe_mdio_info *mdio_info) +{ + struct mii_dev *bus; + int ret; + u32 mdio_speed; + u32 pclk = 250000000; + + bus = mdio_alloc(); + if (!bus) { + printf("mdio_alloc failed\n"); + return NULL; + } + bus->read = pfe_phy_read; + bus->write = pfe_phy_write; + + /* MAC1 MDIO used to communicate with external PHYS */ + bus->priv = mdio_info->reg_base; + sprintf(bus->name, mdio_info->name); + + /* configure mdio speed */ + mdio_speed = (DIV_ROUND_UP(pclk, 4000000) << EMAC_MII_SPEED_SHIFT); + mdio_speed |= EMAC_HOLDTIME(0x5); + writel(mdio_speed, mdio_info->reg_base + EMAC_MII_CTRL_REG); + + ret = mdio_register(bus); + if (ret) { + printf("mdio_register failed\n"); + free(bus); + return NULL; + } + return bus; +} + +void pfe_set_mdio(int dev_id, struct mii_dev *bus) +{ + gem_info[dev_id].bus = bus; +} + +void pfe_set_phy_address_mode(int dev_id, int phy_id, int phy_mode) +{ + gem_info[dev_id].phy_address = phy_id; + gem_info[dev_id].phy_mode = phy_mode; +} diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 25de3fb226..179e0418bc 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -139,6 +139,16 @@ config PHY_NATSEMI config PHY_REALTEK bool "Realtek Ethernet PHYs support" +config RTL8211E_PINE64_GIGABIT_FIX + bool "Fix gigabit throughput on some Pine64+ models" + depends on PHY_REALTEK + help + Configure the Realtek RTL8211E found on some Pine64+ models differently to + fix throughput on Gigabit links, turning off all internal delays in the + process. The settings that this touches are not documented in the CONFREG + section of the RTL8211E datasheet, but come from Realtek by way of the + Pine64 engineering team. + config RTL8211X_PHY_FORCE_MASTER bool "Ethernet PHY RTL8211x: force 1000BASE-T master mode" depends on PHY_REALTEK diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index ad12f6d61f..6678147545 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -7,6 +7,7 @@ */ #include <config.h> #include <common.h> +#include <dm.h> #include <phy.h> #ifndef CONFIG_PHYLIB_10G diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c index 637d89a1e1..9cb3a52c20 100644 --- a/drivers/net/phy/cortina.c +++ b/drivers/net/phy/cortina.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: GPL-2.0+ * * Copyright 2014 Freescale Semiconductor, Inc. + * Copyright 2018 NXP * */ @@ -27,6 +28,7 @@ #error The Cortina PHY needs 10G support #endif +#ifndef CORTINA_NO_FW_UPLOAD struct cortina_reg_config cortina_reg_cfg[] = { /* CS4315_enable_sr_mode */ {VILLA_GLOBAL_MSEQCLKCTRL, 0x8004}, @@ -215,12 +217,22 @@ void cs4340_upload_firmware(struct phy_device *phydev) phy_write(phydev, 0x00, fw_temp.reg_addr, fw_temp.reg_value); } } +#endif int cs4340_phy_init(struct phy_device *phydev) { +#ifndef CORTINA_NO_FW_UPLOAD int timeout = 100; /* 100ms */ +#endif int reg_value; + /* + * Cortina phy has provision to store + * phy firmware in attached dedicated EEPROM. + * Boards designed with EEPROM attached to Cortina + * does not require FW upload. + */ +#ifndef CORTINA_NO_FW_UPLOAD /* step1: BIST test */ phy_write(phydev, 0x00, VILLA_GLOBAL_MSEQCLKCTRL, 0x0004); phy_write(phydev, 0x00, VILLA_GLOBAL_LINE_SOFT_RESET, 0x0000); @@ -241,6 +253,7 @@ int cs4340_phy_init(struct phy_device *phydev) /* setp2: upload ucode */ cs4340_upload_firmware(phydev); +#endif reg_value = phy_read(phydev, 0x00, VILLA_GLOBAL_DWNLD_CHECKSUM_STATUS); if (reg_value) { debug("%s checksum status failed.\n", __func__); @@ -295,45 +308,33 @@ int phy_cortina_init(void) int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id) { int phy_reg; - bool is_cortina_phy = false; - - switch (addr) { -#ifdef CORTINA_PHY_ADDR1 - case CORTINA_PHY_ADDR1: -#endif -#ifdef CORTINA_PHY_ADDR2 - case CORTINA_PHY_ADDR2: -#endif -#ifdef CORTINA_PHY_ADDR3 - case CORTINA_PHY_ADDR3: -#endif -#ifdef CORTINA_PHY_ADDR4 - case CORTINA_PHY_ADDR4: -#endif - is_cortina_phy = true; - break; - default: - break; - } /* Cortina PHY has non-standard offset of PHY ID registers */ - if (is_cortina_phy) - phy_reg = bus->read(bus, addr, 0, VILLA_GLOBAL_CHIP_ID_LSB); - else - phy_reg = bus->read(bus, addr, devad, MII_PHYSID1); + phy_reg = bus->read(bus, addr, 0, VILLA_GLOBAL_CHIP_ID_LSB); + if (phy_reg < 0) + return -EIO; + *phy_id = (phy_reg & 0xffff) << 16; + phy_reg = bus->read(bus, addr, 0, VILLA_GLOBAL_CHIP_ID_MSB); if (phy_reg < 0) return -EIO; + *phy_id |= (phy_reg & 0xffff); - *phy_id = (phy_reg & 0xffff) << 16; - if (is_cortina_phy) - phy_reg = bus->read(bus, addr, 0, VILLA_GLOBAL_CHIP_ID_MSB); - else - phy_reg = bus->read(bus, addr, devad, MII_PHYSID2); + if (*phy_id == PHY_UID_CS4340) + return 0; + /* + * If Cortina PHY not detected, + * try generic way to find PHY ID registers + */ + phy_reg = bus->read(bus, addr, devad, MII_PHYSID1); if (phy_reg < 0) return -EIO; + *phy_id = (phy_reg & 0xffff) << 16; + phy_reg = bus->read(bus, addr, devad, MII_PHYSID2); + if (phy_reg < 0) + return -EIO; *phy_id |= (phy_reg & 0xffff); return 0; diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index 6d917f86f4..d5c2a46c67 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -13,6 +13,7 @@ #include <phy.h> #define PHY_RTL8211x_FORCE_MASTER BIT(1) +#define PHY_RTL8211E_PINE64_GIGABIT_FIX BIT(2) #define PHY_AUTONEGOTIATE_TIMEOUT 5000 @@ -47,6 +48,13 @@ #define MIIM_RTL8211F_PHYSTAT_SPDDONE 0x0800 #define MIIM_RTL8211F_PHYSTAT_LINK 0x0004 +#define MIIM_RTL8211E_CONFREG 0x1c +#define MIIM_RTL8211E_CONFREG_TXD 0x0002 +#define MIIM_RTL8211E_CONFREG_RXD 0x0004 +#define MIIM_RTL8211E_CONFREG_MAGIC 0xb400 /* Undocumented */ + +#define MIIM_RTL8211E_EXT_PAGE_SELECT 0x1e + #define MIIM_RTL8211F_PAGE_SELECT 0x1f #define MIIM_RTL8211F_TX_DELAY 0x100 #define MIIM_RTL8211F_LCR 0x10 @@ -60,6 +68,15 @@ static int rtl8211b_probe(struct phy_device *phydev) return 0; } +static int rtl8211e_probe(struct phy_device *phydev) +{ +#ifdef CONFIG_RTL8211E_PINE64_GIGABIT_FIX + phydev->flags |= PHY_RTL8211E_PINE64_GIGABIT_FIX; +#endif + + return 0; +} + /* RealTek RTL8211x */ static int rtl8211x_config(struct phy_device *phydev) { @@ -81,6 +98,22 @@ static int rtl8211x_config(struct phy_device *phydev) reg |= MIIM_RTL8211x_CTRL1000T_MASTER; phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, reg); } + if (phydev->flags & PHY_RTL8211E_PINE64_GIGABIT_FIX) { + unsigned int reg; + + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, + 7); + phy_write(phydev, MDIO_DEVAD_NONE, + MIIM_RTL8211E_EXT_PAGE_SELECT, 0xa4); + reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211E_CONFREG); + /* Ensure both internal delays are turned off */ + reg &= ~(MIIM_RTL8211E_CONFREG_TXD | MIIM_RTL8211E_CONFREG_RXD); + /* Flip the magic undocumented bits */ + reg |= MIIM_RTL8211E_CONFREG_MAGIC; + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211E_CONFREG, reg); + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT, + 0); + } /* read interrupt status just to clear it */ phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER); @@ -279,6 +312,7 @@ static struct phy_driver RTL8211E_driver = { .uid = 0x1cc915, .mask = 0xffffff, .features = PHY_GBIT_FEATURES, + .probe = &rtl8211e_probe, .config = &rtl8211x_config, .startup = &rtl8211e_startup, .shutdown = &genphy_shutdown, diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 2cc49bca92..1390c36c61 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -325,7 +325,8 @@ static int zynq_phy_init(struct udevice *dev) /* Enable only MDIO bus */ writel(ZYNQ_GEM_NWCTRL_MDEN_MASK, ®s->nwctrl); - if (priv->interface != PHY_INTERFACE_MODE_SGMII) { + if ((priv->interface != PHY_INTERFACE_MODE_SGMII) && + (priv->interface != PHY_INTERFACE_MODE_GMII)) { ret = phy_detection(dev); if (ret) { printf("GEM PHY init failed\n"); diff --git a/drivers/usb/eth/Kconfig b/drivers/usb/eth/Kconfig index 496a6d1933..2f6bfa8e71 100644 --- a/drivers/usb/eth/Kconfig +++ b/drivers/usb/eth/Kconfig @@ -23,6 +23,7 @@ config USB_ETHER_ASIX88179 config USB_ETHER_LAN75XX bool "Microchip LAN75XX support" depends on USB_HOST_ETHER + depends on PHYLIB ---help--- Say Y here if you would like to support Microchip LAN75XX Hi-Speed USB 2.0 to 10/100/1000 Gigabit Ethernet controller. @@ -32,6 +33,7 @@ config USB_ETHER_LAN75XX config USB_ETHER_LAN78XX bool "Microchip LAN78XX support" depends on USB_HOST_ETHER + depends on PHYLIB ---help--- Say Y here if you would like to support Microchip LAN78XX USB 3.1 Gen 1 to 10/100/1000 Gigabit Ethernet controller. diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index fc46b6774d..8a66e479ab 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1,5 +1,13 @@ menu "Watchdog Timer Support" +config WATCHDOG + bool "Enable U-Boot watchdog reset" + help + This option enables U-Boot watchdog support where U-Boot is using + watchdog_reset function to service watchdog device in U-Boot. Enable + this option if you want to service enabled watchdog by U-Boot. Disable + this option if you want U-Boot to start watchdog but never service it. + config HW_WATCHDOG bool @@ -78,4 +86,12 @@ config WDT_ORION Select this to enable Orion watchdog timer, which can be found on some Marvell Armada chips. +config WDT_CDNS + bool "Cadence watchdog timer support" + depends on WDT + imply WATCHDOG + help + Select this to enable Cadence watchdog timer, which can be found on some + Xilinx Microzed Platform. + endmenu diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index ab6a6b79e1..4b97df3ab6 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -22,3 +22,4 @@ obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o obj-$(CONFIG_WDT_BCM6345) += bcm6345_wdt.o obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o obj-$(CONFIG_WDT_ORION) += orion_wdt.o +obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o diff --git a/drivers/watchdog/cdns_wdt.c b/drivers/watchdog/cdns_wdt.c new file mode 100644 index 0000000000..71733cf8ba --- /dev/null +++ b/drivers/watchdog/cdns_wdt.c @@ -0,0 +1,276 @@ +/* + * Cadence WDT driver - Used by Xilinx Zynq + * Reference: Linux kernel Cadence watchdog driver. + * + * Author(s): Shreenidhi Shedi <yesshedi@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <dm.h> +#include <wdt.h> +#include <clk.h> +#include <linux/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct cdns_regs { + u32 zmr; /* WD Zero mode register, offset - 0x0 */ + u32 ccr; /* Counter Control Register offset - 0x4 */ + u32 restart; /* Restart key register, offset - 0x8 */ + u32 status; /* Status Register, offset - 0xC */ +}; + +struct cdns_wdt_priv { + bool rst; + u32 timeout; + void __iomem *reg; + struct cdns_regs *regs; +}; + +#define CDNS_WDT_DEFAULT_TIMEOUT 10 + +/* Supports 1 - 516 sec */ +#define CDNS_WDT_MIN_TIMEOUT 1 +#define CDNS_WDT_MAX_TIMEOUT 516 + +/* Restart key */ +#define CDNS_WDT_RESTART_KEY 0x00001999 + +/* Counter register access key */ +#define CDNS_WDT_REGISTER_ACCESS_KEY 0x00920000 + +/* Counter value divisor */ +#define CDNS_WDT_COUNTER_VALUE_DIVISOR 0x1000 + +/* Clock prescaler value and selection */ +#define CDNS_WDT_PRESCALE_64 64 +#define CDNS_WDT_PRESCALE_512 512 +#define CDNS_WDT_PRESCALE_4096 4096 +#define CDNS_WDT_PRESCALE_SELECT_64 1 +#define CDNS_WDT_PRESCALE_SELECT_512 2 +#define CDNS_WDT_PRESCALE_SELECT_4096 3 + +/* Input clock frequency */ +#define CDNS_WDT_CLK_75MHZ 75000000 + +/* Counter maximum value */ +#define CDNS_WDT_COUNTER_MAX 0xFFF + +/********************* Register Map **********************************/ + +/* + * Zero Mode Register - This register controls how the time out is indicated + * and also contains the access code to allow writes to the register (0xABC). + */ +#define CDNS_WDT_ZMR_WDEN_MASK 0x00000001 /* Enable the WDT */ +#define CDNS_WDT_ZMR_RSTEN_MASK 0x00000002 /* Enable the reset output */ +#define CDNS_WDT_ZMR_IRQEN_MASK 0x00000004 /* Enable IRQ output */ +#define CDNS_WDT_ZMR_RSTLEN_16 0x00000030 /* Reset pulse of 16 pclk cycles */ +#define CDNS_WDT_ZMR_ZKEY_VAL 0x00ABC000 /* Access key, 0xABC << 12 */ + +/* + * Counter Control register - This register controls how fast the timer runs + * and the reset value and also contains the access code to allow writes to + * the register. + */ +#define CDNS_WDT_CCR_CRV_MASK 0x00003FFC /* Counter reset value */ + +/* Write access to Registers */ +static inline void cdns_wdt_writereg(u32 *addr, u32 val) +{ + writel(val, addr); +} + +/** + * cdns_wdt_reset - Reload the watchdog timer (i.e. pat the watchdog). + * + * @dev: Watchdog device + * + * Write the restart key value (0x00001999) to the restart register. + * + * Return: Always 0 + */ +static int cdns_wdt_reset(struct udevice *dev) +{ + struct cdns_wdt_priv *priv = dev_get_priv(dev); + + debug("%s\n", __func__); + + cdns_wdt_writereg(&priv->regs->restart, CDNS_WDT_RESTART_KEY); + + return 0; +} + +/** + * cdns_wdt_start - Enable and start the watchdog. + * + * @dev: Watchdog device + * @timeout: Timeout value + * @flags: Driver flags + * + * The counter value is calculated according to the formula: + * count = (timeout * clock) / prescaler + 1. + * + * The calculated count is divided by 0x1000 to obtain the field value + * to write to counter control register. + * + * Clears the contents of prescaler and counter reset value. Sets the + * prescaler to 4096 and the calculated count and access key + * to write to CCR Register. + * + * Sets the WDT (WDEN bit) and either the Reset signal(RSTEN bit) + * or Interrupt signal(IRQEN) with a specified cycles and the access + * key to write to ZMR Register. + * + * Return: Upon success 0, failure -1. + */ +static int cdns_wdt_start(struct udevice *dev, u64 timeout, ulong flags) +{ + ulong clk_f; + u32 count, prescaler, ctrl_clksel, data = 0; + struct clk clock; + struct cdns_wdt_priv *priv = dev_get_priv(dev); + + if (clk_get_by_index(dev, 0, &clock) < 0) { + dev_err(dev, "failed to get clock\n"); + return -1; + } + + clk_f = clk_get_rate(&clock); + if (IS_ERR_VALUE(clk_f)) { + dev_err(dev, "failed to get rate\n"); + return -1; + } + + debug("%s: CLK_FREQ %ld, timeout %lld\n", __func__, clk_f, timeout); + + if ((timeout < CDNS_WDT_MIN_TIMEOUT) || + (timeout > CDNS_WDT_MAX_TIMEOUT)) { + timeout = priv->timeout; + } + + if (clk_f <= CDNS_WDT_CLK_75MHZ) { + prescaler = CDNS_WDT_PRESCALE_512; + ctrl_clksel = CDNS_WDT_PRESCALE_SELECT_512; + } else { + prescaler = CDNS_WDT_PRESCALE_4096; + ctrl_clksel = CDNS_WDT_PRESCALE_SELECT_4096; + } + + /* + * Counter value divisor to obtain the value of + * counter reset to be written to control register. + */ + count = (timeout * (clk_f / prescaler)) / + CDNS_WDT_COUNTER_VALUE_DIVISOR + 1; + + if (count > CDNS_WDT_COUNTER_MAX) + count = CDNS_WDT_COUNTER_MAX; + + cdns_wdt_writereg(&priv->regs->zmr, CDNS_WDT_ZMR_ZKEY_VAL); + + count = (count << 2) & CDNS_WDT_CCR_CRV_MASK; + + /* Write counter access key first to be able write to register */ + data = count | CDNS_WDT_REGISTER_ACCESS_KEY | ctrl_clksel; + cdns_wdt_writereg(&priv->regs->ccr, data); + + data = CDNS_WDT_ZMR_WDEN_MASK | CDNS_WDT_ZMR_RSTLEN_16 | + CDNS_WDT_ZMR_ZKEY_VAL; + + /* Reset on timeout if specified in device tree. */ + if (priv->rst) { + data |= CDNS_WDT_ZMR_RSTEN_MASK; + data &= ~CDNS_WDT_ZMR_IRQEN_MASK; + } else { + data &= ~CDNS_WDT_ZMR_RSTEN_MASK; + data |= CDNS_WDT_ZMR_IRQEN_MASK; + } + + cdns_wdt_writereg(&priv->regs->zmr, data); + cdns_wdt_writereg(&priv->regs->restart, CDNS_WDT_RESTART_KEY); + + return 0; +} + +/** + * cdns_wdt_stop - Stop the watchdog. + * + * @dev: Watchdog device + * + * Read the contents of the ZMR register, clear the WDEN bit in the register + * and set the access key for successful write. + * + * Return: Always 0 + */ +static int cdns_wdt_stop(struct udevice *dev) +{ + struct cdns_wdt_priv *priv = dev_get_priv(dev); + + cdns_wdt_writereg(&priv->regs->zmr, + CDNS_WDT_ZMR_ZKEY_VAL & (~CDNS_WDT_ZMR_WDEN_MASK)); + + return 0; +} + +/** + * cdns_wdt_probe - Probe call for the device. + * + * @dev: Handle to the udevice structure. + * + * Return: Always 0. + */ +static int cdns_wdt_probe(struct udevice *dev) +{ + struct cdns_wdt_priv *priv = dev_get_priv(dev); + + debug("%s: Probing wdt%u\n", __func__, dev->seq); + + priv->reg = ioremap((u32)priv->regs, sizeof(struct cdns_regs)); + + cdns_wdt_stop(dev); + + return 0; +} + +static int cdns_wdt_ofdata_to_platdata(struct udevice *dev) +{ + int node = dev_of_offset(dev); + struct cdns_wdt_priv *priv = dev_get_priv(dev); + + priv->regs = devfdt_get_addr_ptr(dev); + if (IS_ERR(priv->regs)) + return PTR_ERR(priv->regs); + + priv->timeout = fdtdec_get_int(gd->fdt_blob, node, "timeout-sec", + CDNS_WDT_DEFAULT_TIMEOUT); + + priv->rst = fdtdec_get_bool(gd->fdt_blob, node, "reset-on-timeout"); + + debug("%s: timeout %d, reset %d\n", __func__, priv->timeout, priv->rst); + + return 0; +} + +static const struct wdt_ops cdns_wdt_ops = { + .start = cdns_wdt_start, + .reset = cdns_wdt_reset, + .stop = cdns_wdt_stop, +}; + +static const struct udevice_id cdns_wdt_ids[] = { + { .compatible = "cdns,wdt-r1p2" }, + {} +}; + +U_BOOT_DRIVER(cdns_wdt) = { + .name = "cdns_wdt", + .id = UCLASS_WDT, + .of_match = cdns_wdt_ids, + .probe = cdns_wdt_probe, + .priv_auto_alloc_size = sizeof(struct cdns_wdt_priv), + .ofdata_to_platdata = cdns_wdt_ofdata_to_platdata, + .ops = &cdns_wdt_ops, +}; diff --git a/include/command.h b/include/command.h index 767cabb3df..56499b8ad5 100644 --- a/include/command.h +++ b/include/command.h @@ -111,6 +111,8 @@ extern int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc, extern int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); extern int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); +extern unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc, + char * const argv[]); /* * Error codes that commands return to cmd_process(). We use the standard 0 * and 1 for success and failure, but add one more case - failure with a diff --git a/include/configs/ls1012a2g5rdb.h b/include/configs/ls1012a2g5rdb.h index 25df103983..dbb0fcc62b 100644 --- a/include/configs/ls1012a2g5rdb.h +++ b/include/configs/ls1012a2g5rdb.h @@ -9,15 +9,6 @@ #include "ls1012a_common.h" -/* PFE Ethernet */ -#ifdef CONFIG_FSL_PFE -#define EMAC1_PHY_ADDR 0x2 -#define EMAC2_PHY_ADDR 0x1 -#define CONFIG_PHYLIB -#define CONFIG_PHYLIB_10G -#define CONFIG_PHY_AQUANTIA -#endif - /* DDR */ #define CONFIG_DIMM_SLOTS_PER_CTLR 1 #define CONFIG_CHIP_SELECTS_PER_CTRL 1 @@ -110,7 +101,7 @@ #undef CONFIG_BOOTCOMMAND #if defined(CONFIG_QSPI_BOOT) || defined(CONFIG_SD_BOOT_QSPI) -#define CONFIG_BOOTCOMMAND "run distro_bootcmd; run qspi_bootcmd; " \ +#define CONFIG_BOOTCOMMAND "pfe stop;run distro_bootcmd; run qspi_bootcmd; " \ "env exists secureboot && esbc_halt;" #endif diff --git a/include/configs/ls1012a_common.h b/include/configs/ls1012a_common.h index a58b867c14..0f8033f5b4 100644 --- a/include/configs/ls1012a_common.h +++ b/include/configs/ls1012a_common.h @@ -112,9 +112,9 @@ "kernel_size=0x2800000\0" \ #undef CONFIG_BOOTCOMMAND -#define CONFIG_BOOTCOMMAND "sf probe 0:0; sf read $kernel_load "\ - "$kernel_start $kernel_size && "\ - "bootm $kernel_load" +#define CONFIG_BOOTCOMMAND "pfe stop; sf probe 0:0; sf read $kernel_load "\ + "$kernel_start $kernel_size && "\ + "bootm $kernel_load" /* Monitor Command Prompt */ #define CONFIG_SYS_CBSIZE 512 /* Console I/O Buffer Size */ diff --git a/include/configs/ls1012afrdm.h b/include/configs/ls1012afrdm.h index 297c057292..7c080a0cd3 100644 --- a/include/configs/ls1012afrdm.h +++ b/include/configs/ls1012afrdm.h @@ -68,7 +68,7 @@ "$kernel_addr $kernel_size && bootm $load_addr#$board\0" #undef CONFIG_BOOTCOMMAND -#define CONFIG_BOOTCOMMAND "run distro_bootcmd;run qspi_bootcmd" +#define CONFIG_BOOTCOMMAND "pfe stop;run distro_bootcmd;run qspi_bootcmd" #define CONFIG_CMD_MEMINFO #define CONFIG_CMD_MEMTEST diff --git a/include/configs/ls1012ardb.h b/include/configs/ls1012ardb.h index 97ed9092e0..442c95eb14 100644 --- a/include/configs/ls1012ardb.h +++ b/include/configs/ls1012ardb.h @@ -25,6 +25,7 @@ */ #define I2C_MUX_IO_ADDR 0x24 +#define I2C_MUX_IO2_ADDR 0x25 #define I2C_MUX_IO_0 0 #define I2C_MUX_IO_1 1 #define SW_BOOT_MASK 0x03 @@ -39,6 +40,9 @@ #define SW_REV_C2 0xD8 #define SW_REV_D 0xD0 #define SW_REV_E 0xC8 +#define __PHY_MASK 0xF9 +#define __PHY_ETH2_MASK 0xFB +#define __PHY_ETH1_MASK 0xFD /* MMC */ #ifdef CONFIG_MMC @@ -113,7 +117,7 @@ "bootm $load_addr#$board\0" #undef CONFIG_BOOTCOMMAND -#define CONFIG_BOOTCOMMAND "run distro_bootcmd; run qspi_bootcmd; " \ +#define CONFIG_BOOTCOMMAND "pfe stop; run distro_bootcmd; run qspi_bootcmd; "\ "env exists secureboot && esbc_halt;" #include <asm/fsl_secure_boot.h> diff --git a/include/configs/omapl138_lcdk.h b/include/configs/omapl138_lcdk.h index 12b266e515..77b89bc7a0 100644 --- a/include/configs/omapl138_lcdk.h +++ b/include/configs/omapl138_lcdk.h @@ -20,6 +20,14 @@ #define CONFIG_USE_NAND /* +* Disable DM_* for SPL build and can be re-enabled after adding +* DM support in SPL +*/ +#ifdef CONFIG_SPL_BUILD +#undef CONFIG_DM_I2C +#undef CONFIG_DM_I2C_COMPAT +#endif +/* * SoC Configuration */ #define CONFIG_MACH_OMAPL138_LCDK @@ -57,7 +65,8 @@ * PLL configuration */ -#define CONFIG_SYS_DA850_PLL0_PLLM 37 +/* Requires CONFIG_SYS_DA850_PLL0_POSTDIV=0, set in Kconfig */ +#define CONFIG_SYS_DA850_PLL0_PLLM 18 #define CONFIG_SYS_DA850_PLL1_PLLM 21 /* @@ -104,11 +113,14 @@ /* * Serial Driver info */ +#define CONFIG_SYS_NS16550_CLK clk_get(DAVINCI_UART2_CLKID) +#if !defined(CONFIG_DM_SERIAL) #define CONFIG_SYS_NS16550_SERIAL #define CONFIG_SYS_NS16550_REG_SIZE -4 /* NS16550 register size */ #define CONFIG_SYS_NS16550_COM1 DAVINCI_UART2_BASE /* Base address of UART2 */ #define CONFIG_SYS_NS16550_CLK clk_get(DAVINCI_UART2_CLKID) #define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } +#endif #define CONFIG_SPI #define CONFIG_SYS_SPI_BASE DAVINCI_SPI1_BASE @@ -125,7 +137,6 @@ /* * I2C Configuration */ -#define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_DAVINCI #define CONFIG_SYS_DAVINCI_I2C_SPEED 25000 #define CONFIG_SYS_DAVINCI_I2C_SLAVE 10 /* Bogus, master-only in U-Boot */ diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h index e23b0f2adb..8c0b5d9c06 100644 --- a/include/configs/xilinx_zynqmp.h +++ b/include/configs/xilinx_zynqmp.h @@ -21,7 +21,9 @@ #define GICC_BASE 0xF9020000 #define CONFIG_SYS_ALT_MEMTEST -#define CONFIG_SYS_MEMTEST_SCRATCH 0xfffc0000 +#ifndef CONFIG_SYS_MEMTEST_SCRATCH +# define CONFIG_SYS_MEMTEST_SCRATCH 0x10800000 +#endif #ifndef CONFIG_NR_DRAM_BANKS # define CONFIG_NR_DRAM_BANKS 2 diff --git a/include/configs/xilinx_zynqmp_ep.h b/include/configs/xilinx_zynqmp_ep.h deleted file mode 100644 index a26377a412..0000000000 --- a/include/configs/xilinx_zynqmp_ep.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Configuration for Xilinx ZynqMP emulation platforms - * - * (C) Copyright 2014 - 2015 Xilinx, Inc. - * Michal Simek <michal.simek@xilinx.com> - * Siva Durga Prasad Paladugu <sivadur@xilinx.com> - * - * Based on Configuration for Versatile Express - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __CONFIG_ZYNQMP_EP_H -#define __CONFIG_ZYNQMP_EP_H - -#define CONFIG_ZYNQ_EEPROM -#define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB0_XHCI_BASEADDR, \ - ZYNQMP_USB1_XHCI_BASEADDR} - -#define COUNTER_FREQUENCY 4000000 - -#include <configs/xilinx_zynqmp.h> - -#endif /* __CONFIG_ZYNQMP_EP_H */ diff --git a/include/configs/xilinx_zynqmp_mini.h b/include/configs/xilinx_zynqmp_mini.h index 00f4c1c087..4fbf85a9ed 100644 --- a/include/configs/xilinx_zynqmp_mini.h +++ b/include/configs/xilinx_zynqmp_mini.h @@ -11,6 +11,8 @@ #ifndef __CONFIG_ZYNQMP_MINI_H #define __CONFIG_ZYNQMP_MINI_H +#define CONFIG_SYS_MEMTEST_SCRATCH 0xfffc0000 + #include <configs/xilinx_zynqmp.h> /* Undef unneeded configs */ diff --git a/include/dm/platform_data/pfe_dm_eth.h b/include/dm/platform_data/pfe_dm_eth.h new file mode 100644 index 0000000000..7943c67688 --- /dev/null +++ b/include/dm/platform_data/pfe_dm_eth.h @@ -0,0 +1,21 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __PFE_DM_ETH_H__ +#define __PFE_DM_ETH_H__ +#include <net.h> + +struct pfe_ddr_address { + void *ddr_pfe_baseaddr; + unsigned long ddr_pfe_phys_baseaddr; +}; + +struct pfe_eth_pdata { + struct eth_pdata pfe_eth_pdata_mac; + struct pfe_ddr_address pfe_ddr_addr; +}; +#endif /* __PFE_DM_ETH_H__ */ diff --git a/include/net/pfe_eth/pfe/cbus.h b/include/net/pfe_eth/pfe/cbus.h new file mode 100644 index 0000000000..002041c3cd --- /dev/null +++ b/include/net/pfe_eth/pfe/cbus.h @@ -0,0 +1,77 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _CBUS_H_ +#define _CBUS_H_ + +#include "cbus/emac.h" +#include "cbus/gpi.h" +#include "cbus/bmu.h" +#include "cbus/hif.h" +#include "cbus/tmu_csr.h" +#include "cbus/class_csr.h" +#include "cbus/hif_nocpy.h" +#include "cbus/util_csr.h" + +#define CBUS_BASE_ADDR ((void *)CONFIG_SYS_FSL_PFE_ADDR) + +/* PFE Control and Status Register Desciption */ +#define EMAC1_BASE_ADDR (CBUS_BASE_ADDR + 0x200000) +#define EGPI1_BASE_ADDR (CBUS_BASE_ADDR + 0x210000) +#define EMAC2_BASE_ADDR (CBUS_BASE_ADDR + 0x220000) +#define EGPI2_BASE_ADDR (CBUS_BASE_ADDR + 0x230000) +#define BMU1_BASE_ADDR (CBUS_BASE_ADDR + 0x240000) +#define BMU2_BASE_ADDR (CBUS_BASE_ADDR + 0x250000) +#define ARB_BASE_ADDR (CBUS_BASE_ADDR + 0x260000) +#define DDR_CONFIG_BASE_ADDR (CBUS_BASE_ADDR + 0x270000) +#define HIF_BASE_ADDR (CBUS_BASE_ADDR + 0x280000) +#define HGPI_BASE_ADDR (CBUS_BASE_ADDR + 0x290000) +#define LMEM_BASE_ADDR (CBUS_BASE_ADDR + 0x300000) +#define LMEM_SIZE 0x10000 +#define LMEM_END (LMEM_BASE_ADDR + LMEM_SIZE) +#define TMU_CSR_BASE_ADDR (CBUS_BASE_ADDR + 0x310000) +#define CLASS_CSR_BASE_ADDR (CBUS_BASE_ADDR + 0x320000) +#define HIF_NOCPY_BASE_ADDR (CBUS_BASE_ADDR + 0x350000) +#define UTIL_CSR_BASE_ADDR (CBUS_BASE_ADDR + 0x360000) +#define CBUS_GPT_BASE_ADDR (CBUS_BASE_ADDR + 0x370000) + +/* + * defgroup XXX_MEM_ACCESS_ADDR PE memory access through CSR + * XXX_MEM_ACCESS_ADDR register bit definitions. + */ +/* Internal Memory Write. */ +#define PE_MEM_ACCESS_WRITE BIT(31) +/* Internal Memory Read. */ +#define PE_MEM_ACCESS_READ (0 << 31) + +#define PE_MEM_ACCESS_IMEM BIT(15) +#define PE_MEM_ACCESS_DMEM BIT(16) + +/* Byte Enables of the Internal memory access. These are interpred in BE */ +#define PE_MEM_ACCESS_BYTE_ENABLE(offset, size) (((((1 << (size)) - 1) << (4 \ + - (offset) - (size)))\ + & 0xf) << 24) + +/* PFE cores states */ +#define CORE_DISABLE 0x00000000 +#define CORE_ENABLE 0x00000001 +#define CORE_SW_RESET 0x00000002 + +/* LMEM defines */ +#define LMEM_HDR_SIZE 0x0010 +#define LMEM_BUF_SIZE_LN2 0x7 +#define LMEM_BUF_SIZE BIT(LMEM_BUF_SIZE_LN2) + +/* DDR defines */ +#define DDR_HDR_SIZE 0x0100 +#define DDR_BUF_SIZE_LN2 0xb +#define DDR_BUF_SIZE BIT(DDR_BUF_SIZE_LN2) + +/* Clock generation through PLL */ +#define PLL_CLK_EN 1 + +#endif /* _CBUS_H_ */ diff --git a/include/net/pfe_eth/pfe/cbus/bmu.h b/include/net/pfe_eth/pfe/cbus/bmu.h new file mode 100644 index 0000000000..f707cc3097 --- /dev/null +++ b/include/net/pfe_eth/pfe/cbus/bmu.h @@ -0,0 +1,40 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _BMU_H_ +#define _BMU_H_ + +#define BMU_VERSION 0x000 +#define BMU_CTRL 0x004 +#define BMU_UCAST_CONFIG 0x008 +#define BMU_UCAST_BASE_ADDR 0x00c +#define BMU_BUF_SIZE 0x010 +#define BMU_BUF_CNT 0x014 +#define BMU_THRES 0x018 +#define BMU_INT_SRC 0x020 +#define BMU_INT_ENABLE 0x024 +#define BMU_ALLOC_CTRL 0x030 +#define BMU_FREE_CTRL 0x034 +#define BMU_FREE_ERR_ADDR 0x038 +#define BMU_CURR_BUF_CNT 0x03c +#define BMU_MCAST_CNT 0x040 +#define BMU_MCAST_ALLOC_CTRL 0x044 +#define BMU_REM_BUF_CNT 0x048 +#define BMU_LOW_WATERMARK 0x050 +#define BMU_HIGH_WATERMARK 0x054 +#define BMU_INT_MEM_ACCESS 0x100 + +struct bmu_cfg { + u32 baseaddr; + u32 count; + u32 size; +}; + +#define BMU1_BUF_SIZE LMEM_BUF_SIZE_LN2 +#define BMU2_BUF_SIZE DDR_BUF_SIZE_LN2 + +#endif /* _BMU_H_ */ diff --git a/include/net/pfe_eth/pfe/cbus/class_csr.h b/include/net/pfe_eth/pfe/cbus/class_csr.h new file mode 100644 index 0000000000..eeca751a9d --- /dev/null +++ b/include/net/pfe_eth/pfe/cbus/class_csr.h @@ -0,0 +1,180 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _CLASS_CSR_H_ +#define _CLASS_CSR_H_ + +/* + * @file class_csr.h. + * class_csr - block containing all the classifier control and status register. + * Mapped on CBUS and accessible from all PE's and ARM. + */ +#define CLASS_VERSION (CLASS_CSR_BASE_ADDR + 0x000) +#define CLASS_TX_CTRL (CLASS_CSR_BASE_ADDR + 0x004) +#define CLASS_INQ_PKTPTR (CLASS_CSR_BASE_ADDR + 0x010) +/* (ddr_hdr_size[24:16], lmem_hdr_size[5:0]) */ +#define CLASS_HDR_SIZE (CLASS_CSR_BASE_ADDR + 0x014) +/* LMEM header size for the Classifier block. + * Data in the LMEM is written from this offset. + */ +#define CLASS_HDR_SIZE_LMEM(off) ((off) & 0x3f) +/* DDR header size for the Classifier block. + * Data in the DDR is written from this offset. + */ +#define CLASS_HDR_SIZE_DDR(off) (((off) & 0x1ff) << 16) + +/* DMEM address of first [15:0] and second [31:16] buffers on QB side. */ +#define CLASS_PE0_QB_DM_ADDR0 (CLASS_CSR_BASE_ADDR + 0x020) +/* DMEM address of third [15:0] and fourth [31:16] buffers on QB side. */ +#define CLASS_PE0_QB_DM_ADDR1 (CLASS_CSR_BASE_ADDR + 0x024) + +/* DMEM address of first [15:0] and second [31:16] buffers on RO side. */ +#define CLASS_PE0_RO_DM_ADDR0 (CLASS_CSR_BASE_ADDR + 0x060) +/* DMEM address of third [15:0] and fourth [31:16] buffers on RO side. */ +#define CLASS_PE0_RO_DM_ADDR1 (CLASS_CSR_BASE_ADDR + 0x064) + +/* + * @name Class PE memory access. Allows external PE's and HOST to + * read/write PMEM/DMEM memory ranges for each classifier PE. + */ +#define CLASS_MEM_ACCESS_ADDR (CLASS_CSR_BASE_ADDR + 0x100) +/* Internal Memory Access Write Data [31:0] */ +#define CLASS_MEM_ACCESS_WDATA (CLASS_CSR_BASE_ADDR + 0x104) +/* Internal Memory Access Read Data [31:0] */ +#define CLASS_MEM_ACCESS_RDATA (CLASS_CSR_BASE_ADDR + 0x108) +#define CLASS_TM_INQ_ADDR (CLASS_CSR_BASE_ADDR + 0x114) +#define CLASS_PE_STATUS (CLASS_CSR_BASE_ADDR + 0x118) + +#define CLASS_PE_SYS_CLK_RATIO (CLASS_CSR_BASE_ADDR + 0x200) +#define CLASS_AFULL_THRES (CLASS_CSR_BASE_ADDR + 0x204) +#define CLASS_GAP_BETWEEN_READS (CLASS_CSR_BASE_ADDR + 0x208) +#define CLASS_MAX_BUF_CNT (CLASS_CSR_BASE_ADDR + 0x20c) +#define CLASS_TSQ_FIFO_THRES (CLASS_CSR_BASE_ADDR + 0x210) +#define CLASS_TSQ_MAX_CNT (CLASS_CSR_BASE_ADDR + 0x214) +#define CLASS_IRAM_DATA_0 (CLASS_CSR_BASE_ADDR + 0x218) +#define CLASS_IRAM_DATA_1 (CLASS_CSR_BASE_ADDR + 0x21c) +#define CLASS_IRAM_DATA_2 (CLASS_CSR_BASE_ADDR + 0x220) +#define CLASS_IRAM_DATA_3 (CLASS_CSR_BASE_ADDR + 0x224) + +#define CLASS_BUS_ACCESS_ADDR (CLASS_CSR_BASE_ADDR + 0x228) +/* bit 23:0 of PE peripheral address are stored in CLASS_BUS_ACCESS_ADDR */ +#define CLASS_BUS_ACCESS_ADDR_MASK (0x0001FFFF) + +#define CLASS_BUS_ACCESS_WDATA (CLASS_CSR_BASE_ADDR + 0x22c) +#define CLASS_BUS_ACCESS_RDATA (CLASS_CSR_BASE_ADDR + 0x230) + +/* + * (route_entry_size[9:0], route_hash_size[23:16] + * (this is actually ln2(size))) + */ +#define CLASS_ROUTE_HASH_ENTRY_SIZE (CLASS_CSR_BASE_ADDR + 0x234) +#define CLASS_ROUTE_ENTRY_SIZE(size) ((size) & 0x1ff) +#define CLASS_ROUTE_HASH_SIZE(hash_bits) (((hash_bits) & 0xff) << 16) + +#define CLASS_ROUTE_TABLE_BASE (CLASS_CSR_BASE_ADDR + 0x238) +#define CLASS_ROUTE_MULTI (CLASS_CSR_BASE_ADDR + 0x23c) +#define CLASS_SMEM_OFFSET (CLASS_CSR_BASE_ADDR + 0x240) +#define CLASS_LMEM_BUF_SIZE (CLASS_CSR_BASE_ADDR + 0x244) +#define CLASS_VLAN_ID (CLASS_CSR_BASE_ADDR + 0x248) +#define CLASS_BMU1_BUF_FREE (CLASS_CSR_BASE_ADDR + 0x24c) +#define CLASS_USE_TMU_INQ (CLASS_CSR_BASE_ADDR + 0x250) +#define CLASS_VLAN_ID1 (CLASS_CSR_BASE_ADDR + 0x254) + +#define CLASS_BUS_ACCESS_BASE (CLASS_CSR_BASE_ADDR + 0x258) +/* bit 31:24 of PE peripheral address are stored in CLASS_BUS_ACCESS_BASE */ +#define CLASS_BUS_ACCESS_BASE_MASK (0xFF000000) + +#define CLASS_HIF_PARSE (CLASS_CSR_BASE_ADDR + 0x25c) + +#define CLASS_HOST_PE0_GP (CLASS_CSR_BASE_ADDR + 0x260) +#define CLASS_PE0_GP (CLASS_CSR_BASE_ADDR + 0x264) +#define CLASS_HOST_PE1_GP (CLASS_CSR_BASE_ADDR + 0x268) +#define CLASS_PE1_GP (CLASS_CSR_BASE_ADDR + 0x26c) +#define CLASS_HOST_PE2_GP (CLASS_CSR_BASE_ADDR + 0x270) +#define CLASS_PE2_GP (CLASS_CSR_BASE_ADDR + 0x274) +#define CLASS_HOST_PE3_GP (CLASS_CSR_BASE_ADDR + 0x278) +#define CLASS_PE3_GP (CLASS_CSR_BASE_ADDR + 0x27c) +#define CLASS_HOST_PE4_GP (CLASS_CSR_BASE_ADDR + 0x280) +#define CLASS_PE4_GP (CLASS_CSR_BASE_ADDR + 0x284) +#define CLASS_HOST_PE5_GP (CLASS_CSR_BASE_ADDR + 0x288) +#define CLASS_PE5_GP (CLASS_CSR_BASE_ADDR + 0x28c) + +#define CLASS_PE_INT_SRC (CLASS_CSR_BASE_ADDR + 0x290) +#define CLASS_PE_INT_ENABLE (CLASS_CSR_BASE_ADDR + 0x294) + +#define CLASS_TPID0_TPID1 (CLASS_CSR_BASE_ADDR + 0x298) +#define CLASS_TPID2 (CLASS_CSR_BASE_ADDR + 0x29c) + +#define CLASS_L4_CHKSUM_ADDR (CLASS_CSR_BASE_ADDR + 0x2a0) + +#define CLASS_PE0_DEBUG (CLASS_CSR_BASE_ADDR + 0x2a4) +#define CLASS_PE1_DEBUG (CLASS_CSR_BASE_ADDR + 0x2a8) +#define CLASS_PE2_DEBUG (CLASS_CSR_BASE_ADDR + 0x2ac) +#define CLASS_PE3_DEBUG (CLASS_CSR_BASE_ADDR + 0x2b0) +#define CLASS_PE4_DEBUG (CLASS_CSR_BASE_ADDR + 0x2b4) +#define CLASS_PE5_DEBUG (CLASS_CSR_BASE_ADDR + 0x2b8) + +#define CLASS_STATE (CLASS_CSR_BASE_ADDR + 0x2bc) +#define CLASS_AXI_CTRL (CLASS_CSR_BASE_ADDR + 0x2d0) + +/* CLASS defines */ +#define CLASS_PBUF_SIZE 0x100 /* Fixed by hardware */ +#define CLASS_PBUF_HEADER_OFFSET 0x80 /* Can be configured */ + +#define CLASS_PBUF0_BASE_ADDR 0x000 /* Can be configured */ +/* Can be configured */ +#define CLASS_PBUF1_BASE_ADDR (CLASS_PBUF0_BASE_ADDR + CLASS_PBUF_SIZE) +/* Can be configured */ +#define CLASS_PBUF2_BASE_ADDR (CLASS_PBUF1_BASE_ADDR + CLASS_PBUF_SIZE) +/* Can be configured */ +#define CLASS_PBUF3_BASE_ADDR (CLASS_PBUF2_BASE_ADDR + CLASS_PBUF_SIZE) + +#define CLASS_PBUF0_HEADER_BASE_ADDR (CLASS_PBUF0_BASE_ADDR +\ + CLASS_PBUF_HEADER_OFFSET) +#define CLASS_PBUF1_HEADER_BASE_ADDR (CLASS_PBUF1_BASE_ADDR +\ + CLASS_PBUF_HEADER_OFFSET) +#define CLASS_PBUF2_HEADER_BASE_ADDR (CLASS_PBUF2_BASE_ADDR +\ + CLASS_PBUF_HEADER_OFFSET) +#define CLASS_PBUF3_HEADER_BASE_ADDR (CLASS_PBUF3_BASE_ADDR +\ + CLASS_PBUF_HEADER_OFFSET) + +#define CLASS_PE0_RO_DM_ADDR0_VAL ((CLASS_PBUF1_BASE_ADDR << 16) |\ + CLASS_PBUF0_BASE_ADDR) +#define CLASS_PE0_RO_DM_ADDR1_VAL ((CLASS_PBUF3_BASE_ADDR << 16) |\ + CLASS_PBUF2_BASE_ADDR) + +#define CLASS_PE0_QB_DM_ADDR0_VAL ((CLASS_PBUF1_HEADER_BASE_ADDR << 16)\ + | CLASS_PBUF0_HEADER_BASE_ADDR) +#define CLASS_PE0_QB_DM_ADDR1_VAL ((CLASS_PBUF3_HEADER_BASE_ADDR << 16)\ + | CLASS_PBUF2_HEADER_BASE_ADDR) + +#define CLASS_ROUTE_SIZE 128 +#define CLASS_ROUTE_HASH_BITS 20 +#define CLASS_ROUTE_HASH_MASK (BIT(CLASS_ROUTE_HASH_BITS) - 1) + +#define TWO_LEVEL_ROUTE BIT(0) +#define PHYNO_IN_HASH BIT(1) +#define HW_ROUTE_FETCH BIT(3) +#define HW_BRIDGE_FETCH BIT(5) +#define IP_ALIGNED BIT(6) +#define ARC_HIT_CHECK_EN BIT(7) +#define CLASS_TOE BIT(11) +#define HASH_CRC_PORT BIT(12) +#define HASH_CRC_IP BIT(13) +#define HASH_CRC_PORT_IP GENMASK(13, 12) +#define QB2BUS_LE BIT(15) + +#define TCP_CHKSUM_DROP BIT(0) +#define UDP_CHKSUM_DROP BIT(1) +#define IPV4_CHKSUM_DROP BIT(9) + +struct class_cfg { + u32 route_table_baseaddr; + u32 route_table_hash_bits; +}; + +#endif /* _CLASS_CSR_H_ */ diff --git a/include/net/pfe_eth/pfe/cbus/emac.h b/include/net/pfe_eth/pfe/cbus/emac.h new file mode 100644 index 0000000000..f74bd96f23 --- /dev/null +++ b/include/net/pfe_eth/pfe/cbus/emac.h @@ -0,0 +1,140 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _EMAC_H_ +#define _EMAC_H_ + +#define EMAC_IEVENT_REG 0x004 +#define EMAC_IMASK_REG 0x008 +#define EMAC_R_DES_ACTIVE_REG 0x010 +#define EMAC_X_DES_ACTIVE_REG 0x014 +#define EMAC_ECNTRL_REG 0x024 +#define EMAC_MII_DATA_REG 0x040 +#define EMAC_MII_CTRL_REG 0x044 +#define EMAC_MIB_CTRL_STS_REG 0x064 +#define EMAC_RCNTRL_REG 0x084 +#define EMAC_TCNTRL_REG 0x0C4 +#define EMAC_PHY_ADDR_LOW 0x0E4 +#define EMAC_PHY_ADDR_HIGH 0x0E8 +#define EMAC_TFWR_STR_FWD 0x144 +#define EMAC_RX_SECTIOM_FULL 0x190 +#define EMAC_TX_SECTION_EMPTY 0x1A0 +#define EMAC_TRUNC_FL 0x1B0 + +/* GEMAC definitions and settings */ +#define EMAC_PORT_0 0 +#define EMAC_PORT_1 1 + +/* GEMAC Bit definitions */ +#define EMAC_IEVENT_HBERR BIT(31) +#define EMAC_IEVENT_BABR BIT(30) +#define EMAC_IEVENT_BABT BIT(29) +#define EMAC_IEVENT_GRA BIT(28) +#define EMAC_IEVENT_TXF BIT(27) +#define EMAC_IEVENT_TXB BIT(26) +#define EMAC_IEVENT_RXF BIT(25) +#define EMAC_IEVENT_RXB BIT(24) +#define EMAC_IEVENT_MII BIT(23) +#define EMAC_IEVENT_EBERR BIT(22) +#define EMAC_IEVENT_LC BIT(21) +#define EMAC_IEVENT_RL BIT(20) +#define EMAC_IEVENT_UN BIT(19) + +#define EMAC_IMASK_HBERR BIT(31) +#define EMAC_IMASK_BABR BIT(30) +#define EMAC_IMASKT_BABT BIT(29) +#define EMAC_IMASK_GRA BIT(28) +#define EMAC_IMASKT_TXF BIT(27) +#define EMAC_IMASK_TXB BIT(26) +#define EMAC_IMASKT_RXF BIT(25) +#define EMAC_IMASK_RXB BIT(24) +#define EMAC_IMASK_MII BIT(23) +#define EMAC_IMASK_EBERR BIT(22) +#define EMAC_IMASK_LC BIT(21) +#define EMAC_IMASKT_RL BIT(20) +#define EMAC_IMASK_UN BIT(19) + +#define EMAC_RCNTRL_MAX_FL_SHIFT 16 +#define EMAC_RCNTRL_LOOP BIT(0) +#define EMAC_RCNTRL_DRT BIT(1) +#define EMAC_RCNTRL_MII_MODE BIT(2) +#define EMAC_RCNTRL_PROM BIT(3) +#define EMAC_RCNTRL_BC_REJ BIT(4) +#define EMAC_RCNTRL_FCE BIT(5) +#define EMAC_RCNTRL_RGMII BIT(6) +#define EMAC_RCNTRL_SGMII BIT(7) +#define EMAC_RCNTRL_RMII BIT(8) +#define EMAC_RCNTRL_RMII_10T BIT(9) +#define EMAC_RCNTRL_CRC_FWD BIT(10) + +#define EMAC_TCNTRL_GTS BIT(0) +#define EMAC_TCNTRL_HBC BIT(1) +#define EMAC_TCNTRL_FDEN BIT(2) +#define EMAC_TCNTRL_TFC_PAUSE BIT(3) +#define EMAC_TCNTRL_RFC_PAUSE BIT(4) + +#define EMAC_ECNTRL_RESET BIT(0) /* reset the EMAC */ +#define EMAC_ECNTRL_ETHER_EN BIT(1) /* enable the EMAC */ +#define EMAC_ECNTRL_SPEED BIT(5) +#define EMAC_ECNTRL_DBSWAP BIT(8) + +#define EMAC_X_WMRK_STRFWD BIT(8) + +#define EMAC_X_DES_ACTIVE_TDAR BIT(24) +#define EMAC_R_DES_ACTIVE_RDAR BIT(24) + +#define EMAC_TFWR (0x4) +#define EMAC_RX_SECTION_FULL_32 (0x5) +#define EMAC_TRUNC_FL_16K (0x3FFF) +#define EMAC_TX_SECTION_EMPTY_30 (0x30) +#define EMAC_MIBC_NO_CLR_NO_DIS (0x0) + +/* + * The possible operating speeds of the MAC, currently supporting 10, 100 and + * 1000Mb modes. + */ +enum mac_speed {PFE_MAC_SPEED_10M, PFE_MAC_SPEED_100M, PFE_MAC_SPEED_1000M, + PFE_MAC_SPEED_1000M_PCS}; + +/* MII-related definitios */ +#define EMAC_MII_DATA_ST 0x40000000 /* Start of frame delimiter */ +#define EMAC_MII_DATA_OP_RD 0x20000000 /* Perform a read operation */ +#define EMAC_MII_DATA_OP_CL45_RD 0x30000000 /* Perform a read operation */ +#define EMAC_MII_DATA_OP_WR 0x10000000 /* Perform a write operation */ +#define EMAC_MII_DATA_OP_CL45_WR 0x10000000 /* Perform a write operation */ +#define EMAC_MII_DATA_PA_MSK 0x0f800000 /* PHY Address field mask */ +#define EMAC_MII_DATA_RA_MSK 0x007c0000 /* PHY Register field mask */ +#define EMAC_MII_DATA_TA 0x00020000 /* Turnaround */ +#define EMAC_MII_DATA_DATAMSK 0x0000ffff /* PHY data field */ + +#define EMAC_MII_DATA_RA_SHIFT 18 /* MII Register address bits */ +#define EMAC_MII_DATA_RA_MASK 0x1F /* MII Register address mask */ +#define EMAC_MII_DATA_PA_SHIFT 23 /* MII PHY address bits */ +#define EMAC_MII_DATA_PA_MASK 0x1F /* MII PHY address mask */ + +#define EMAC_MII_DATA_RA(v) ((v & EMAC_MII_DATA_RA_MASK) <<\ + EMAC_MII_DATA_RA_SHIFT) +#define EMAC_MII_DATA_PA(v) ((v & EMAC_MII_DATA_RA_MASK) <<\ + EMAC_MII_DATA_PA_SHIFT) +#define EMAC_MII_DATA(v) (v & 0xffff) + +#define EMAC_MII_SPEED_SHIFT 1 +#define EMAC_HOLDTIME_SHIFT 8 +#define EMAC_HOLDTIME_MASK 0x7 +#define EMAC_HOLDTIME(v) ((v & EMAC_HOLDTIME_MASK) << EMAC_HOLDTIME_SHIFT) + +/* Internal PHY Registers - SGMII */ +#define PHY_SGMII_CR_PHY_RESET 0x8000 +#define PHY_SGMII_CR_RESET_AN 0x0200 +#define PHY_SGMII_CR_DEF_VAL 0x1140 +#define PHY_SGMII_DEV_ABILITY_SGMII 0x4001 +#define PHY_SGMII_IF_MODE_AN 0x0002 +#define PHY_SGMII_IF_MODE_SGMII 0x0001 +#define PHY_SGMII_IF_MODE_SGMII_GBT 0x0008 +#define PHY_SGMII_ENABLE_AN 0x1000 + +#endif /* _EMAC_H_ */ diff --git a/include/net/pfe_eth/pfe/cbus/gpi.h b/include/net/pfe_eth/pfe/cbus/gpi.h new file mode 100644 index 0000000000..f86f3f9cff --- /dev/null +++ b/include/net/pfe_eth/pfe/cbus/gpi.h @@ -0,0 +1,62 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _GPI_H_ +#define _GPI_H_ + +#define GPI_VERSION 0x00 +#define GPI_CTRL 0x04 +#define GPI_RX_CONFIG 0x08 +#define GPI_HDR_SIZE 0x0c +#define GPI_BUF_SIZE 0x10 +#define GPI_LMEM_ALLOC_ADDR 0x14 +#define GPI_LMEM_FREE_ADDR 0x18 +#define GPI_DDR_ALLOC_ADDR 0x1c +#define GPI_DDR_FREE_ADDR 0x20 +#define GPI_CLASS_ADDR 0x24 +#define GPI_DRX_FIFO 0x28 +#define GPI_TRX_FIFO 0x2c +#define GPI_INQ_PKTPTR 0x30 +#define GPI_DDR_DATA_OFFSET 0x34 +#define GPI_LMEM_DATA_OFFSET 0x38 +#define GPI_TMLF_TX 0x4c +#define GPI_DTX_ASEQ 0x50 +#define GPI_FIFO_STATUS 0x54 +#define GPI_FIFO_DEBUG 0x58 +#define GPI_TX_PAUSE_TIME 0x5c +#define GPI_LMEM_SEC_BUF_DATA_OFFSET 0x60 +#define GPI_DDR_SEC_BUF_DATA_OFFSET 0x64 +#define GPI_TOE_CHKSUM_EN 0x68 +#define GPI_OVERRUN_DROPCNT 0x6c +#define GPI_AXI_CTRL 0x70 + +struct gpi_cfg { + u32 lmem_rtry_cnt; + u32 tmlf_txthres; + u32 aseq_len; +}; + +/* GPI commons defines */ +#define GPI_LMEM_BUF_EN 0x1 +#define GPI_DDR_BUF_EN 0x1 + +/* EGPI 1 defines */ +#define EGPI1_LMEM_RTRY_CNT 0x40 +#define EGPI1_TMLF_TXTHRES 0xBC +#define EGPI1_ASEQ_LEN 0x50 + +/* EGPI 2 defines */ +#define EGPI2_LMEM_RTRY_CNT 0x40 +#define EGPI2_TMLF_TXTHRES 0xBC +#define EGPI2_ASEQ_LEN 0x40 + +/* HGPI defines */ +#define HGPI_LMEM_RTRY_CNT 0x40 +#define HGPI_TMLF_TXTHRES 0xBC +#define HGPI_ASEQ_LEN 0x40 + +#endif /* _GPI_H_ */ diff --git a/include/net/pfe_eth/pfe/cbus/hif.h b/include/net/pfe_eth/pfe/cbus/hif.h new file mode 100644 index 0000000000..4b5cb3c5e0 --- /dev/null +++ b/include/net/pfe_eth/pfe/cbus/hif.h @@ -0,0 +1,68 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _HIF_H_ +#define _HIF_H_ + +/* + * @file hif.h. + * hif - PFE hif block control and status register. + * Mapped on CBUS and accessible from all PE's and ARM. + */ +#define HIF_VERSION (HIF_BASE_ADDR + 0x00) +#define HIF_TX_CTRL (HIF_BASE_ADDR + 0x04) +#define HIF_TX_CURR_BD_ADDR (HIF_BASE_ADDR + 0x08) +#define HIF_TX_ALLOC (HIF_BASE_ADDR + 0x0c) +#define HIF_TX_BDP_ADDR (HIF_BASE_ADDR + 0x10) +#define HIF_TX_STATUS (HIF_BASE_ADDR + 0x14) +#define HIF_RX_CTRL (HIF_BASE_ADDR + 0x20) +#define HIF_RX_BDP_ADDR (HIF_BASE_ADDR + 0x24) +#define HIF_RX_STATUS (HIF_BASE_ADDR + 0x30) +#define HIF_INT_SRC (HIF_BASE_ADDR + 0x34) +#define HIF_INT_ENABLE (HIF_BASE_ADDR + 0x38) +#define HIF_POLL_CTRL (HIF_BASE_ADDR + 0x3c) +#define HIF_RX_CURR_BD_ADDR (HIF_BASE_ADDR + 0x40) +#define HIF_RX_ALLOC (HIF_BASE_ADDR + 0x44) +#define HIF_TX_DMA_STATUS (HIF_BASE_ADDR + 0x48) +#define HIF_RX_DMA_STATUS (HIF_BASE_ADDR + 0x4c) +#define HIF_INT_COAL (HIF_BASE_ADDR + 0x50) +#define HIF_AXI_CTRL (HIF_BASE_ADDR + 0x54) + +/* HIF_TX_CTRL bits */ +#define HIF_CTRL_DMA_EN BIT(0) +#define HIF_CTRL_BDP_POLL_CTRL_EN BIT(1) +#define HIF_CTRL_BDP_CH_START_WSTB BIT(2) + +/* HIF_RX_STATUS bits */ +#define BDP_CSR_RX_DMA_ACTV BIT(16) + +/* HIF_INT_ENABLE bits */ +#define HIF_INT_EN BIT(0) +#define HIF_RXBD_INT_EN BIT(1) +#define HIF_RXPKT_INT_EN BIT(2) +#define HIF_TXBD_INT_EN BIT(3) +#define HIF_TXPKT_INT_EN BIT(4) + +/* HIF_POLL_CTRL bits*/ +#define HIF_RX_POLL_CTRL_CYCLE 0x0400 +#define HIF_TX_POLL_CTRL_CYCLE 0x0400 + +/* Buffer descriptor control bits */ +#define BD_CTRL_BUFLEN_MASK (0xffff) +#define BD_BUF_LEN(x) (x & BD_CTRL_BUFLEN_MASK) +#define BD_CTRL_CBD_INT_EN BIT(16) +#define BD_CTRL_PKT_INT_EN BIT(17) +#define BD_CTRL_LIFM BIT(18) +#define BD_CTRL_LAST_BD BIT(19) +#define BD_CTRL_DIR BIT(20) +#define BD_CTRL_PKT_XFER BIT(24) +#define BD_CTRL_DESC_EN BIT(31) +#define BD_CTRL_PARSE_DISABLE BIT(25) +#define BD_CTRL_BRFETCH_DISABLE BIT(26) +#define BD_CTRL_RTFETCH_DISABLE BIT(27) + +#endif /* _HIF_H_ */ diff --git a/include/net/pfe_eth/pfe/cbus/hif_nocpy.h b/include/net/pfe_eth/pfe/cbus/hif_nocpy.h new file mode 100644 index 0000000000..c2d6f6d66e --- /dev/null +++ b/include/net/pfe_eth/pfe/cbus/hif_nocpy.h @@ -0,0 +1,40 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _HIF_NOCPY_H_ +#define _HIF_NOCPY_H_ + +#define HIF_NOCPY_VERSION (HIF_NOCPY_BASE_ADDR + 0x00) +#define HIF_NOCPY_TX_CTRL (HIF_NOCPY_BASE_ADDR + 0x04) +#define HIF_NOCPY_TX_CURR_BD_ADDR (HIF_NOCPY_BASE_ADDR + 0x08) +#define HIF_NOCPY_TX_ALLOC (HIF_NOCPY_BASE_ADDR + 0x0c) +#define HIF_NOCPY_TX_BDP_ADDR (HIF_NOCPY_BASE_ADDR + 0x10) +#define HIF_NOCPY_TX_STATUS (HIF_NOCPY_BASE_ADDR + 0x14) +#define HIF_NOCPY_RX_CTRL (HIF_NOCPY_BASE_ADDR + 0x20) +#define HIF_NOCPY_RX_BDP_ADDR (HIF_NOCPY_BASE_ADDR + 0x24) +#define HIF_NOCPY_RX_STATUS (HIF_NOCPY_BASE_ADDR + 0x30) +#define HIF_NOCPY_INT_SRC (HIF_NOCPY_BASE_ADDR + 0x34) +#define HIF_NOCPY_INT_ENABLE (HIF_NOCPY_BASE_ADDR + 0x38) +#define HIF_NOCPY_POLL_CTRL (HIF_NOCPY_BASE_ADDR + 0x3c) +#define HIF_NOCPY_RX_CURR_BD_ADDR (HIF_NOCPY_BASE_ADDR + 0x40) +#define HIF_NOCPY_RX_ALLOC (HIF_NOCPY_BASE_ADDR + 0x44) +#define HIF_NOCPY_TX_DMA_STATUS (HIF_NOCPY_BASE_ADDR + 0x48) +#define HIF_NOCPY_RX_DMA_STATUS (HIF_NOCPY_BASE_ADDR + 0x4c) +#define HIF_NOCPY_RX_INQ0_PKTPTR (HIF_NOCPY_BASE_ADDR + 0x50) +#define HIF_NOCPY_RX_INQ1_PKTPTR (HIF_NOCPY_BASE_ADDR + 0x54) +#define HIF_NOCPY_TX_PORT_NO (HIF_NOCPY_BASE_ADDR + 0x60) +#define HIF_NOCPY_LMEM_ALLOC_ADDR (HIF_NOCPY_BASE_ADDR + 0x64) +#define HIF_NOCPY_CLASS_ADDR (HIF_NOCPY_BASE_ADDR + 0x68) +#define HIF_NOCPY_TMU_PORT0_ADDR (HIF_NOCPY_BASE_ADDR + 0x70) +#define HIF_NOCPY_TMU_PORT1_ADDR (HIF_NOCPY_BASE_ADDR + 0x74) +#define HIF_NOCPY_TMU_PORT2_ADDR (HIF_NOCPY_BASE_ADDR + 0x7c) +#define HIF_NOCPY_TMU_PORT3_ADDR (HIF_NOCPY_BASE_ADDR + 0x80) +#define HIF_NOCPY_TMU_PORT4_ADDR (HIF_NOCPY_BASE_ADDR + 0x84) +#define HIF_NOCPY_INT_COAL (HIF_NOCPY_BASE_ADDR + 0x90) +#define HIF_NOCPY_AXI_CTRL (HIF_NOCPY_BASE_ADDR + 0x94) + +#endif /* _HIF_NOCPY_H_ */ diff --git a/include/net/pfe_eth/pfe/cbus/tmu_csr.h b/include/net/pfe_eth/pfe/cbus/tmu_csr.h new file mode 100644 index 0000000000..e810b792ae --- /dev/null +++ b/include/net/pfe_eth/pfe/cbus/tmu_csr.h @@ -0,0 +1,148 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _TMU_CSR_H_ +#define _TMU_CSR_H_ + +#define TMU_VERSION (TMU_CSR_BASE_ADDR + 0x000) +#define TMU_INQ_WATERMARK (TMU_CSR_BASE_ADDR + 0x004) +#define TMU_PHY_INQ_PKTPTR (TMU_CSR_BASE_ADDR + 0x008) +#define TMU_PHY_INQ_PKTINFO (TMU_CSR_BASE_ADDR + 0x00c) +#define TMU_PHY_INQ_FIFO_CNT (TMU_CSR_BASE_ADDR + 0x010) +#define TMU_SYS_GENERIC_CONTROL (TMU_CSR_BASE_ADDR + 0x014) +#define TMU_SYS_GENERIC_STATUS (TMU_CSR_BASE_ADDR + 0x018) +#define TMU_SYS_GEN_CON0 (TMU_CSR_BASE_ADDR + 0x01c) +#define TMU_SYS_GEN_CON1 (TMU_CSR_BASE_ADDR + 0x020) +#define TMU_SYS_GEN_CON2 (TMU_CSR_BASE_ADDR + 0x024) +#define TMU_SYS_GEN_CON3 (TMU_CSR_BASE_ADDR + 0x028) +#define TMU_SYS_GEN_CON4 (TMU_CSR_BASE_ADDR + 0x02c) +#define TMU_TEQ_DISABLE_DROPCHK (TMU_CSR_BASE_ADDR + 0x030) +#define TMU_TEQ_CTRL (TMU_CSR_BASE_ADDR + 0x034) +#define TMU_TEQ_QCFG (TMU_CSR_BASE_ADDR + 0x038) +#define TMU_TEQ_DROP_STAT (TMU_CSR_BASE_ADDR + 0x03c) +#define TMU_TEQ_QAVG (TMU_CSR_BASE_ADDR + 0x040) +#define TMU_TEQ_WREG_PROB (TMU_CSR_BASE_ADDR + 0x044) +#define TMU_TEQ_TRANS_STAT (TMU_CSR_BASE_ADDR + 0x048) +#define TMU_TEQ_HW_PROB_CFG0 (TMU_CSR_BASE_ADDR + 0x04c) +#define TMU_TEQ_HW_PROB_CFG1 (TMU_CSR_BASE_ADDR + 0x050) +#define TMU_TEQ_HW_PROB_CFG2 (TMU_CSR_BASE_ADDR + 0x054) +#define TMU_TEQ_HW_PROB_CFG3 (TMU_CSR_BASE_ADDR + 0x058) +#define TMU_TEQ_HW_PROB_CFG4 (TMU_CSR_BASE_ADDR + 0x05c) +#define TMU_TEQ_HW_PROB_CFG5 (TMU_CSR_BASE_ADDR + 0x060) +#define TMU_TEQ_HW_PROB_CFG6 (TMU_CSR_BASE_ADDR + 0x064) +#define TMU_TEQ_HW_PROB_CFG7 (TMU_CSR_BASE_ADDR + 0x068) +#define TMU_TEQ_HW_PROB_CFG8 (TMU_CSR_BASE_ADDR + 0x06c) +#define TMU_TEQ_HW_PROB_CFG9 (TMU_CSR_BASE_ADDR + 0x070) +#define TMU_TEQ_HW_PROB_CFG10 (TMU_CSR_BASE_ADDR + 0x074) +#define TMU_TEQ_HW_PROB_CFG11 (TMU_CSR_BASE_ADDR + 0x078) +#define TMU_TEQ_HW_PROB_CFG12 (TMU_CSR_BASE_ADDR + 0x07c) +#define TMU_TEQ_HW_PROB_CFG13 (TMU_CSR_BASE_ADDR + 0x080) +#define TMU_TEQ_HW_PROB_CFG14 (TMU_CSR_BASE_ADDR + 0x084) +#define TMU_TEQ_HW_PROB_CFG15 (TMU_CSR_BASE_ADDR + 0x088) +#define TMU_TEQ_HW_PROB_CFG16 (TMU_CSR_BASE_ADDR + 0x08c) +#define TMU_TEQ_HW_PROB_CFG17 (TMU_CSR_BASE_ADDR + 0x090) +#define TMU_TEQ_HW_PROB_CFG18 (TMU_CSR_BASE_ADDR + 0x094) +#define TMU_TEQ_HW_PROB_CFG19 (TMU_CSR_BASE_ADDR + 0x098) +#define TMU_TEQ_HW_PROB_CFG20 (TMU_CSR_BASE_ADDR + 0x09c) +#define TMU_TEQ_HW_PROB_CFG21 (TMU_CSR_BASE_ADDR + 0x0a0) +#define TMU_TEQ_HW_PROB_CFG22 (TMU_CSR_BASE_ADDR + 0x0a4) +#define TMU_TEQ_HW_PROB_CFG23 (TMU_CSR_BASE_ADDR + 0x0a8) +#define TMU_TEQ_HW_PROB_CFG24 (TMU_CSR_BASE_ADDR + 0x0ac) +#define TMU_TEQ_HW_PROB_CFG25 (TMU_CSR_BASE_ADDR + 0x0b0) +#define TMU_TDQ_IIFG_CFG (TMU_CSR_BASE_ADDR + 0x0b4) +/* [9:0] Scheduler Enable for each of the scheduler in the TDQ. + * This is a global Enable for all schedulers in PHY0 + */ +#define TMU_TDQ0_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x0b8) +#define TMU_LLM_CTRL (TMU_CSR_BASE_ADDR + 0x0bc) +#define TMU_LLM_BASE_ADDR (TMU_CSR_BASE_ADDR + 0x0c0) +#define TMU_LLM_QUE_LEN (TMU_CSR_BASE_ADDR + 0x0c4) +#define TMU_LLM_QUE_HEADPTR (TMU_CSR_BASE_ADDR + 0x0c8) +#define TMU_LLM_QUE_TAILPTR (TMU_CSR_BASE_ADDR + 0x0cc) +#define TMU_LLM_QUE_DROPCNT (TMU_CSR_BASE_ADDR + 0x0d0) +#define TMU_INT_EN (TMU_CSR_BASE_ADDR + 0x0d4) +#define TMU_INT_SRC (TMU_CSR_BASE_ADDR + 0x0d8) +#define TMU_INQ_STAT (TMU_CSR_BASE_ADDR + 0x0dc) +#define TMU_CTRL (TMU_CSR_BASE_ADDR + 0x0e0) + +/* [31] Mem Access Command. 0 = Internal Memory Read, 1 = Internal + * memory Write [27:24] Byte Enables of the Internal memory access [23:0] + * Address of the internal memory. This address is used to access both the + * PM and DM of all the PE's + */ +#define TMU_MEM_ACCESS_ADDR (TMU_CSR_BASE_ADDR + 0x0e4) + +/* Internal Memory Access Write Data */ +#define TMU_MEM_ACCESS_WDATA (TMU_CSR_BASE_ADDR + 0x0e8) +/* Internal Memory Access Read Data. The commands are blocked at the + * mem_access only + */ +#define TMU_MEM_ACCESS_RDATA (TMU_CSR_BASE_ADDR + 0x0ec) + +/* [31:0] PHY0 in queue address (must be initialized with one of the + * xxx_INQ_PKTPTR cbus addresses) + */ +#define TMU_PHY0_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0f0) +/* [31:0] PHY1 in queue address (must be initialized with one of the + * xxx_INQ_PKTPTR cbus addresses) + */ +#define TMU_PHY1_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0f4) +/* [31:0] PHY3 in queue address (must be initialized with one of the + * xxx_INQ_PKTPTR cbus addresses) + */ +#define TMU_PHY3_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0fc) +#define TMU_BMU_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x100) +#define TMU_TX_CTRL (TMU_CSR_BASE_ADDR + 0x104) + +#define TMU_PE_SYS_CLK_RATIO (TMU_CSR_BASE_ADDR + 0x114) +#define TMU_PE_STATUS (TMU_CSR_BASE_ADDR + 0x118) +#define TMU_TEQ_MAX_THRESHOLD (TMU_CSR_BASE_ADDR + 0x11c) + +/* [31:0] PHY4 in queue address (must be initialized with one of the + * xxx_INQ_PKTPTR cbus addresses) + */ +#define TMU_PHY4_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x134) + +/* [9:0] Scheduler Enable for each of the scheduler in the TDQ. This + * is a global Enable for all schedulers in PHY1 + */ +#define TMU_TDQ1_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x138) +/* [9:0] Scheduler Enable for each of the scheduler in the TDQ. This + * is a global Enable for all schedulers in PHY3 + */ +#define TMU_TDQ3_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x140) + +#define TMU_BMU_BUF_SIZE (TMU_CSR_BASE_ADDR + 0x144) +/* [31:0] PHY5 in queue address (must be initialized with one of the + * xxx_INQ_PKTPTR cbus addresses) + */ +#define TMU_PHY5_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x148) + +#define TMU_AXI_CTRL (TMU_CSR_BASE_ADDR + 0x17c) + +#define SW_RESET BIT(0) /* Global software reset */ +#define INQ_RESET BIT(2) +#define TEQ_RESET BIT(3) +#define TDQ_RESET BIT(4) +#define PE_RESET BIT(5) +#define MEM_INIT BIT(6) +#define MEM_INIT_DONE BIT(7) +#define LLM_INIT BIT(8) +#define LLM_INIT_DONE BIT(9) +#define ECC_MEM_INIT_DONE BIT(10) + +struct tmu_cfg { + u32 llm_base_addr; + u32 llm_queue_len; +}; + +/* Not HW related for pfe_ctrl/pfe common defines */ +#define DEFAULT_MAX_QDEPTH 80 +#define DEFAULT_Q0_QDEPTH 511 /* We keep 1 large queue for host tx qos */ +#define DEFAULT_TMU3_QDEPTH 127 + +#endif /* _TMU_CSR_H_ */ diff --git a/include/net/pfe_eth/pfe/cbus/util_csr.h b/include/net/pfe_eth/pfe/cbus/util_csr.h new file mode 100644 index 0000000000..bac4114277 --- /dev/null +++ b/include/net/pfe_eth/pfe/cbus/util_csr.h @@ -0,0 +1,47 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _UTIL_CSR_H_ +#define _UTIL_CSR_H_ + +#define UTIL_VERSION (UTIL_CSR_BASE_ADDR + 0x000) +#define UTIL_TX_CTRL (UTIL_CSR_BASE_ADDR + 0x004) +#define UTIL_INQ_PKTPTR (UTIL_CSR_BASE_ADDR + 0x010) + +#define UTIL_HDR_SIZE (UTIL_CSR_BASE_ADDR + 0x014) + +#define UTIL_PE0_QB_DM_ADDR0 (UTIL_CSR_BASE_ADDR + 0x020) +#define UTIL_PE0_QB_DM_ADDR1 (UTIL_CSR_BASE_ADDR + 0x024) +#define UTIL_PE0_RO_DM_ADDR0 (UTIL_CSR_BASE_ADDR + 0x060) +#define UTIL_PE0_RO_DM_ADDR1 (UTIL_CSR_BASE_ADDR + 0x064) + +#define UTIL_MEM_ACCESS_ADDR (UTIL_CSR_BASE_ADDR + 0x100) +#define UTIL_MEM_ACCESS_WDATA (UTIL_CSR_BASE_ADDR + 0x104) +#define UTIL_MEM_ACCESS_RDATA (UTIL_CSR_BASE_ADDR + 0x108) + +#define UTIL_TM_INQ_ADDR (UTIL_CSR_BASE_ADDR + 0x114) +#define UTIL_PE_STATUS (UTIL_CSR_BASE_ADDR + 0x118) + +#define UTIL_PE_SYS_CLK_RATIO (UTIL_CSR_BASE_ADDR + 0x200) +#define UTIL_AFULL_THRES (UTIL_CSR_BASE_ADDR + 0x204) +#define UTIL_GAP_BETWEEN_READS (UTIL_CSR_BASE_ADDR + 0x208) +#define UTIL_MAX_BUF_CNT (UTIL_CSR_BASE_ADDR + 0x20c) +#define UTIL_TSQ_FIFO_THRES (UTIL_CSR_BASE_ADDR + 0x210) +#define UTIL_TSQ_MAX_CNT (UTIL_CSR_BASE_ADDR + 0x214) +#define UTIL_IRAM_DATA_0 (UTIL_CSR_BASE_ADDR + 0x218) +#define UTIL_IRAM_DATA_1 (UTIL_CSR_BASE_ADDR + 0x21c) +#define UTIL_IRAM_DATA_2 (UTIL_CSR_BASE_ADDR + 0x220) +#define UTIL_IRAM_DATA_3 (UTIL_CSR_BASE_ADDR + 0x224) + +#define UTIL_BUS_ACCESS_ADDR (UTIL_CSR_BASE_ADDR + 0x228) +#define UTIL_BUS_ACCESS_WDATA (UTIL_CSR_BASE_ADDR + 0x22c) +#define UTIL_BUS_ACCESS_RDATA (UTIL_CSR_BASE_ADDR + 0x230) + +#define UTIL_INQ_AFULL_THRES (UTIL_CSR_BASE_ADDR + 0x234) +#define UTIL_AXI_CTRL (UTIL_CSR_BASE_ADDR + 0x240) + +#endif /* _UTIL_CSR_H_ */ diff --git a/include/net/pfe_eth/pfe/pfe_hw.h b/include/net/pfe_eth/pfe/pfe_hw.h new file mode 100644 index 0000000000..992454f305 --- /dev/null +++ b/include/net/pfe_eth/pfe/pfe_hw.h @@ -0,0 +1,163 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _PFE_H_ +#define _PFE_H_ + +#include <elf.h> +#include "cbus.h" + +#define PFE_RESET_WA + +#define CLASS_DMEM_BASE_ADDR(i) (0x00000000 | ((i) << 20)) +/* Only valid for mem access register interface */ +#define CLASS_IMEM_BASE_ADDR(i) (0x00000000 | ((i) << 20)) +#define CLASS_DMEM_SIZE 0x00002000 +#define CLASS_IMEM_SIZE 0x00008000 + +#define TMU_DMEM_BASE_ADDR(i) (0x00000000 + ((i) << 20)) +/* Only valid for mem access register interface */ +#define TMU_IMEM_BASE_ADDR(i) (0x00000000 + ((i) << 20)) +#define TMU_DMEM_SIZE 0x00000800 +#define TMU_IMEM_SIZE 0x00002000 + +#define UTIL_DMEM_BASE_ADDR 0x00000000 +#define UTIL_DMEM_SIZE 0x00002000 + +#define PE_LMEM_BASE_ADDR 0xc3010000 +#define PE_LMEM_SIZE 0x8000 +#define PE_LMEM_END (PE_LMEM_BASE_ADDR + PE_LMEM_SIZE) + +#define DMEM_BASE_ADDR 0x00000000 +#define DMEM_SIZE 0x2000 /* TMU has less... */ +#define DMEM_END (DMEM_BASE_ADDR + DMEM_SIZE) + +#define PMEM_BASE_ADDR 0x00010000 +#define PMEM_SIZE 0x8000 /* TMU has less... */ +#define PMEM_END (PMEM_BASE_ADDR + PMEM_SIZE) + +/* Memory ranges check from PE point of view/memory map */ +#define IS_DMEM(addr, len) (((unsigned long)(addr) >= DMEM_BASE_ADDR) &&\ + (((unsigned long)(addr) +\ + (len)) <= DMEM_END)) +#define IS_PMEM(addr, len) (((unsigned long)(addr) >= PMEM_BASE_ADDR) &&\ + (((unsigned long)(addr) +\ + (len)) <= PMEM_END)) +#define IS_PE_LMEM(addr, len) (((unsigned long)(addr) >= PE_LMEM_BASE_ADDR\ + ) && (((unsigned long)(addr)\ + + (len)) <= PE_LMEM_END)) + +#define IS_PFE_LMEM(addr, len) (((unsigned long)(addr) >=\ + CBUS_VIRT_TO_PFE(LMEM_BASE_ADDR)) &&\ + (((unsigned long)(addr) + (len)) <=\ + CBUS_VIRT_TO_PFE(LMEM_END))) +#define IS_PHYS_DDR(addr, len) (((unsigned long)(addr) >=\ + PFE_DDR_PHYS_BASE_ADDR) &&\ + (((unsigned long)(addr) + (len)) <=\ + PFE_DDR_PHYS_END)) + +/* Host View Address */ +extern void *ddr_pfe_base_addr; + +/* PFE View Address */ +/* DDR physical base address as seen by PE's. */ +#define PFE_DDR_PHYS_BASE_ADDR 0x03800000 +#define PFE_DDR_PHYS_SIZE 0xC000000 +#define PFE_DDR_PHYS_END (PFE_DDR_PHYS_BASE_ADDR + PFE_DDR_PHYS_SIZE) +/* CBUS physical base address as seen by PE's. */ +#define PFE_CBUS_PHYS_BASE_ADDR 0xc0000000 + +/* Host<->PFE Mapping */ +#define DDR_PFE_TO_VIRT(p) ((unsigned long int)((p) + 0x80000000)) +#define CBUS_VIRT_TO_PFE(v) (((v) - CBUS_BASE_ADDR) +\ + PFE_CBUS_PHYS_BASE_ADDR) +#define CBUS_PFE_TO_VIRT(p) (((p) - PFE_CBUS_PHYS_BASE_ADDR) +\ + CBUS_BASE_ADDR) + +enum { + CLASS0_ID = 0, + CLASS1_ID, + CLASS2_ID, + CLASS3_ID, + CLASS4_ID, + CLASS5_ID, + + TMU0_ID, + TMU1_ID, + TMU2_ID, + TMU3_ID, + MAX_PE +}; + +#define CLASS_MASK (BIT(CLASS0_ID) | BIT(CLASS1_ID) | BIT(CLASS2_ID)\ + | BIT(CLASS3_ID) | BIT(CLASS4_ID) |\ + BIT(CLASS5_ID)) +#define CLASS_MAX_ID CLASS5_ID + +#define TMU_MASK (BIT(TMU0_ID) | BIT(TMU1_ID) | BIT(TMU3_ID)) +#define TMU_MAX_ID TMU3_ID + +/* + * PE information. + * Structure containing PE's specific information. It is used to create + * generic C functions common to all PEs. + * Before using the library functions this structure needs to be + * initialized with the different registers virtual addresses + * (according to the ARM MMU mmaping). The default initialization supports a + * virtual == physical mapping. + * + */ +struct pe_info { + u32 dmem_base_addr; /* PE's dmem base address */ + u32 pmem_base_addr; /* PE's pmem base address */ + u32 pmem_size; /* PE's pmem size */ + + void *mem_access_wdata; /* PE's _MEM_ACCESS_WDATA + * register address + */ + void *mem_access_addr; /* PE's _MEM_ACCESS_ADDR + * register address + */ + void *mem_access_rdata; /* PE's _MEM_ACCESS_RDATA + * register address + */ +}; + +void pe_lmem_read(u32 *dst, u32 len, u32 offset); +void pe_lmem_write(u32 *src, u32 len, u32 offset); + +u32 pe_pmem_read(int id, u32 addr, u8 size); +void pe_dmem_write(int id, u32 val, u32 addr, u8 size); +u32 pe_dmem_read(int id, u32 addr, u8 size); + +int pe_load_elf_section(int id, const void *data, Elf32_Shdr *shdr); + +void pfe_lib_init(void); + +void bmu_init(void *base, struct bmu_cfg *cfg); +void bmu_enable(void *base); + +void gpi_init(void *base, struct gpi_cfg *cfg); +void gpi_enable(void *base); +void gpi_disable(void *base); + +void class_init(struct class_cfg *cfg); +void class_enable(void); +void class_disable(void); + +void tmu_init(struct tmu_cfg *cfg); +void tmu_enable(u32 pe_mask); +void tmu_disable(u32 pe_mask); + +void hif_init(void); +void hif_tx_enable(void); +void hif_tx_disable(void); +void hif_rx_enable(void); +void hif_rx_disable(void); +void hif_rx_desc_disable(void); + +#endif /* _PFE_H_ */ diff --git a/include/net/pfe_eth/pfe_driver.h b/include/net/pfe_eth/pfe_driver.h new file mode 100644 index 0000000000..da7d2470b5 --- /dev/null +++ b/include/net/pfe_eth/pfe_driver.h @@ -0,0 +1,59 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __PFE_DRIVER_H__ +#define __PFE_DRIVER_H__ + +#include <net/pfe_eth/pfe/pfe_hw.h> +#include <dm/platform_data/pfe_dm_eth.h> + +#define HIF_RX_DESC_NT 64 +#define HIF_TX_DESC_NT 64 + +#define RX_BD_BASEADDR (HIF_DESC_BASEADDR) +#define TX_BD_BASEADDR (HIF_DESC_BASEADDR + HIF_TX_DESC_SIZE) + +#define MIN_PKT_SIZE 56 +#define MAX_FRAME_SIZE 2048 + +struct __packed hif_header_s { + u8 port_no; /* Carries input port no for host rx packets and + * output port no for tx pkts + */ + u8 reserved0; + u32 reserved2; +}; + +struct __packed buf_desc { + u32 ctrl; + u32 status; + u32 data; + u32 next; +}; + +struct rx_desc_s { + struct buf_desc *rx_base; + unsigned int rx_base_pa; + int rx_to_read; + int rx_ring_size; +}; + +struct tx_desc_s { + struct buf_desc *tx_base; + unsigned int tx_base_pa; + int tx_to_send; + int tx_ring_size; +}; + +int pfe_send(int phy_port, void *data, int length); +int pfe_recv(uchar **pkt_ptr, int *phy_port); +int pfe_tx_done(void); +int pfe_eth_free_pkt(struct udevice *dev, uchar *packet, int length); +int pfe_drv_init(struct pfe_ddr_address *pfe_addr); +int pfe_eth_remove(struct udevice *dev); + +#endif diff --git a/include/net/pfe_eth/pfe_eth.h b/include/net/pfe_eth/pfe_eth.h new file mode 100644 index 0000000000..f319365dc4 --- /dev/null +++ b/include/net/pfe_eth/pfe_eth.h @@ -0,0 +1,104 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __PFE_ETH_H__ +#define __PFE_ETH_H__ + +#include <linux/sizes.h> +#include <asm/io.h> +#include <miiphy.h> +#include <malloc.h> +#include "pfe_driver.h" + +#define BMU2_DDR_BASEADDR 0 +#define BMU2_BUF_COUNT (3 * SZ_1K) +#define BMU2_DDR_SIZE (DDR_BUF_SIZE * BMU2_BUF_COUNT) + +#define HIF_RX_PKT_DDR_BASEADDR (BMU2_DDR_BASEADDR + BMU2_DDR_SIZE) +#define HIF_RX_PKT_DDR_SIZE (HIF_RX_DESC_NT * DDR_BUF_SIZE) +#define HIF_TX_PKT_DDR_BASEADDR (HIF_RX_PKT_DDR_BASEADDR + HIF_RX_PKT_DDR_SIZE) +#define HIF_TX_PKT_DDR_SIZE (HIF_TX_DESC_NT * DDR_BUF_SIZE) + +#define HIF_DESC_BASEADDR (HIF_TX_PKT_DDR_BASEADDR + HIF_TX_PKT_DDR_SIZE) +#define HIF_RX_DESC_SIZE (16 * HIF_RX_DESC_NT) +#define HIF_TX_DESC_SIZE (16 * HIF_TX_DESC_NT) + +#define UTIL_CODE_BASEADDR 0x780000 +#define UTIL_CODE_SIZE (128 * SZ_1K) + +#define UTIL_DDR_DATA_BASEADDR (UTIL_CODE_BASEADDR + UTIL_CODE_SIZE) +#define UTIL_DDR_DATA_SIZE (64 * SZ_1K) + +#define CLASS_DDR_DATA_BASEADDR (UTIL_DDR_DATA_BASEADDR + UTIL_DDR_DATA_SIZE) +#define CLASS_DDR_DATA_SIZE (32 * SZ_1K) + +#define TMU_DDR_DATA_BASEADDR (CLASS_DDR_DATA_BASEADDR + CLASS_DDR_DATA_SIZE) +#define TMU_DDR_DATA_SIZE (32 * SZ_1K) + +#define TMU_LLM_BASEADDR (TMU_DDR_DATA_BASEADDR + TMU_DDR_DATA_SIZE) +#define TMU_LLM_QUEUE_LEN (16 * 256) + /* Must be power of two and at least 16 * 8 = 128 bytes */ +#define TMU_LLM_SIZE (4 * 16 * TMU_LLM_QUEUE_LEN) + /* (4 TMU's x 16 queues x queue_len) */ + +#define ROUTE_TABLE_BASEADDR 0x800000 +#define ROUTE_TABLE_HASH_BITS_MAX 15 /* 32K entries */ +#define ROUTE_TABLE_HASH_BITS 8 /* 256 entries */ +#define ROUTE_TABLE_SIZE (BIT(ROUTE_TABLE_HASH_BITS_MAX) \ + * CLASS_ROUTE_SIZE) + +#define PFE_TOTAL_DATA_SIZE (ROUTE_TABLE_BASEADDR + ROUTE_TABLE_SIZE) + +#if PFE_TOTAL_DATA_SIZE > (12 * SZ_1M) +#error DDR mapping above 12MiB +#endif + +/* LMEM Mapping */ +#define BMU1_LMEM_BASEADDR 0 +#define BMU1_BUF_COUNT 256 +#define BMU1_LMEM_SIZE (LMEM_BUF_SIZE * BMU1_BUF_COUNT) + +struct gemac_s { + void *gemac_base; + void *egpi_base; + + /* GEMAC config */ + int gemac_mode; + int gemac_speed; + int gemac_duplex; + int flags; + /* phy iface */ + int phy_address; + int phy_mode; + struct mii_dev *bus; + +}; + +struct pfe_mdio_info { + void *reg_base; + char *name; +}; + +struct pfe_eth_dev { + int gemac_port; + struct gemac_s *gem; + struct pfe_ddr_address pfe_addr; + struct udevice *dev; +#ifdef CONFIG_PHYLIB + struct phy_device *phydev; +#endif +}; + +int pfe_remove(struct pfe_ddr_address *pfe_addr); +struct mii_dev *pfe_mdio_init(struct pfe_mdio_info *mdio_info); +void pfe_set_mdio(int dev_id, struct mii_dev *bus); +void pfe_set_phy_address_mode(int dev_id, int phy_id, int phy_mode); +int gemac_initialize(bd_t *bis, int dev_id, char *devname); +int pfe_init(struct pfe_ddr_address *pfe_addr); +int pfe_eth_board_init(struct udevice *dev); + +#endif /* __PFE_ETH_H__ */ diff --git a/include/net/pfe_eth/pfe_firmware.h b/include/net/pfe_eth/pfe_firmware.h new file mode 100644 index 0000000000..588b2ae934 --- /dev/null +++ b/include/net/pfe_eth/pfe_firmware.h @@ -0,0 +1,17 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/** @file + * Contains all the defines to handle parsing and loading of PE firmware files. + */ +#ifndef __PFE_FIRMWARE_H__ +#define __PFE_FIRMWARE_H__ + +int pfe_firmware_init(void); +void pfe_firmware_exit(void); + +#endif diff --git a/include/net/pfe_eth/pfe_mdio.h b/include/net/pfe_eth/pfe_mdio.h new file mode 100644 index 0000000000..ab27ec3215 --- /dev/null +++ b/include/net/pfe_eth/pfe_mdio.h @@ -0,0 +1,13 @@ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _PFE_MDIO_H_ +#define _PFE_MDIO_H_ + +int pfe_phy_configure(struct pfe_eth_dev *priv, int dev_id, int phy_id); + +#endif /* _PFE_MDIO_H_ */ diff --git a/include/netdev.h b/include/netdev.h index 3958a4cd32..86d28ade14 100644 --- a/include/netdev.h +++ b/include/netdev.h @@ -39,8 +39,6 @@ int dm9000_initialize(bd_t *bis); int dnet_eth_initialize(int id, void *regs, unsigned int phy_addr); int e1000_initialize(bd_t *bis); int eepro100_initialize(bd_t *bis); -int enc28j60_initialize(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode); int ep93xx_eth_initialize(u8 dev_num, int base_addr); int eth_3com_initialize (bd_t * bis); int ethoc_initialize(u8 dev_num, int base_addr); diff --git a/net/eth-uclass.c b/net/eth-uclass.c index d30b04ba86..240b596534 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -336,7 +336,7 @@ int eth_send(void *packet, int length) if (!current) return -ENODEV; - if (!device_active(current)) + if (!eth_is_active(current)) return -EINVAL; ret = eth_get_ops(current)->send(current, packet, length); @@ -359,7 +359,7 @@ int eth_rx(void) if (!current) return -ENODEV; - if (!device_active(current)) + if (!eth_is_active(current)) return -EINVAL; /* Process up to 32 packets at one time */ @@ -683,7 +683,7 @@ int net_start_again(void) retry_forever = 0; } - if ((!retry_forever) && (net_try_count >= retrycnt)) { + if ((!retry_forever) && (net_try_count > retrycnt)) { eth_halt(); net_set_state(NETLOOP_FAIL); /* diff --git a/scripts/check-config.sh b/scripts/check-config.sh index 267758498b..4848ca6e25 100755 --- a/scripts/check-config.sh +++ b/scripts/check-config.sh @@ -14,6 +14,9 @@ # For example: # scripts/check-config.sh b/chromebook_link/u-boot.cfg kconfig_whitelist.txt . +set -e +set -u + path="$1" whitelist="$2" srctree="$3" diff --git a/test/py/README.md b/test/py/README.md index eefac37756..aed2fd063a 100644 --- a/test/py/README.md +++ b/test/py/README.md @@ -150,7 +150,7 @@ processing. option takes a single argument which is used to filter test names. Simple logical operators are supported. For example: - `'ums'` runs only tests with "ums" in their name. - - ``ut_dm'` runs only tests with "ut_dm" in their name. Note that in this + - `'ut_dm'` runs only tests with "ut_dm" in their name. Note that in this case, "ut_dm" is a parameter to a test rather than the test name. The full test name is e.g. "test_ut[ut_dm_leak]". - `'not reset'` runs everything except tests with "reset" in their name. @@ -320,7 +320,7 @@ If U-Boot has already been built: ```bash PATH=$HOME/ubtest/bin:$PATH \ - PYTHONPATH=${HOME}/ubtest/py:${PYTHONPATH} \ + PYTHONPATH=${HOME}/ubtest/py/${HOSTNAME}:${PYTHONPATH} \ ./test/py/test.py --bd seaboard ``` @@ -331,7 +331,7 @@ follow: ```bash CROSS_COMPILE=arm-none-eabi- \ PATH=$HOME/ubtest/bin:$PATH \ - PYTHONPATH=${HOME}/ubtest/py:${PYTHONPATH} \ + PYTHONPATH=${HOME}/ubtest/py/${HOSTNAME}:${PYTHONPATH} \ ./test/py/test.py --bd seaboard --build ``` diff --git a/test/py/tests/test_sf.py b/test/py/tests/test_sf.py new file mode 100644 index 0000000000..95a7564907 --- /dev/null +++ b/test/py/tests/test_sf.py @@ -0,0 +1,218 @@ +# Copyright (c) 2016, Xilinx Inc. Michal Simek +# Copyright (c) 2017, Xiphos Systems Corp. All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0 + +import re +import pytest +import random +import u_boot_utils + +""" +Note: This test relies on boardenv_* containing configuration values to define +which SPI Flash areas are available for testing. Without this, this test will +be automatically skipped. +For example: + +# A list of sections of Flash memory to be tested. +env__sf_configs = ( + { + # Where in SPI Flash should the test operate. + 'offset': 0x00000000, + # This value is optional. + # If present, specifies the [[bus:]cs] argument used in `sf probe` + # If missing, defaults to 0. + 'id': '0:1', + # This value is optional. + # If set as a number, specifies the speed of the SPI Flash. + # If set as an array of 2, specifies a range for a random speed. + # If missing, defaults to 0. + 'speed': 1000000, + # This value is optional. + # If present, specifies the size to use for read/write operations. + # If missing, the SPI Flash page size is used as a default (based on + # the `sf probe` output). + 'len': 0x10000, + # This value is optional. + # If present, specifies if the test can write to Flash offset + # If missing, defaults to False. + 'writeable': False, + # This value is optional. + # If present, specifies the expected CRC32 value of the flash area. + # If missing, extra check is ignored. + 'crc32': 0xCAFECAFE, + }, +) +""" + +def sf_prepare(u_boot_console, env__sf_config): + """Check global state of the SPI Flash before running any test. + + Args: + u_boot_console: A U-Boot console connection. + env__sf_config: The single SPI Flash device configuration on which to + run the tests. + + Returns: + sf_params: a dictionary of SPI Flash parameters. + """ + + sf_params = {} + sf_params['ram_base'] = u_boot_utils.find_ram_base(u_boot_console) + + probe_id = env__sf_config.get('id', 0) + speed = env__sf_config.get('speed', 0) + if isinstance(speed, int): + sf_params['speed'] = speed + else: + assert len(speed) == 2, "If speed is a list, it must have 2 entries" + sf_params['speed'] = random.randint(speed[0], speed[1]) + + cmd = 'sf probe %d %d' % (probe_id, sf_params['speed']) + + output = u_boot_console.run_command(cmd) + assert 'SF: Detected' in output, 'No Flash device available' + + m = re.search('page size (.+?) Bytes', output) + assert m, 'SPI Flash page size not recognized' + sf_params['page_size'] = int(m.group(1)) + + m = re.search('erase size (.+?) KiB', output) + assert m, 'SPI Flash erase size not recognized' + sf_params['erase_size'] = int(m.group(1)) + sf_params['erase_size'] *= 1024 + + m = re.search('total (.+?) MiB', output) + assert m, 'SPI Flash total size not recognized' + sf_params['total_size'] = int(m.group(1)) + sf_params['total_size'] *= 1024 * 1024 + + assert 'offset' in env__sf_config, \ + '\'offset\' is required for this test.' + sf_params['len'] = env__sf_config.get('len', sf_params['erase_size']) + + assert not env__sf_config['offset'] % sf_params['erase_size'], \ + 'offset not multiple of erase size.' + assert not sf_params['len'] % sf_params['erase_size'], \ + 'erase length not multiple of erase size.' + + assert not (env__sf_config.get('writeable', False) and + 'crc32' in env__sf_config), \ + 'Cannot check crc32 on writeable sections' + + return sf_params + +def sf_read(u_boot_console, env__sf_config, sf_params): + """Helper function used to read and compute the CRC32 value of a section of + SPI Flash memory. + + Args: + u_boot_console: A U-Boot console connection. + env__sf_config: The single SPI Flash device configuration on which to + run the tests. + sf_params: SPI Flash parameters. + + Returns: + CRC32 value of SPI Flash section + """ + + addr = sf_params['ram_base'] + offset = env__sf_config['offset'] + count = sf_params['len'] + pattern = random.randint(0, 0xFF) + crc_expected = env__sf_config.get('crc32', None) + + cmd = 'mw.b %08x %02x %x' % (addr, pattern, count) + u_boot_console.run_command(cmd) + crc_pattern = u_boot_utils.crc32(u_boot_console, addr, count) + if crc_expected: + assert crc_pattern != crc_expected + + cmd = 'sf read %08x %08x %x' % (addr, offset, count) + response = u_boot_console.run_command(cmd) + assert 'Read: OK' in response, 'Read operation failed' + crc_readback = u_boot_utils.crc32(u_boot_console, addr, count) + assert crc_pattern != crc_readback, 'sf read did not update RAM content.' + if crc_expected: + assert crc_readback == crc_expected + + return crc_readback + +def sf_update(u_boot_console, env__sf_config, sf_params): + """Helper function used to update a section of SPI Flash memory. + + Args: + u_boot_console: A U-Boot console connection. + env__sf_config: The single SPI Flash device configuration on which to + run the tests. + + Returns: + CRC32 value of SPI Flash section + """ + + addr = sf_params['ram_base'] + offset = env__sf_config['offset'] + count = sf_params['len'] + pattern = int(random.random() * 0xFF) + + cmd = 'mw.b %08x %02x %x' % (addr, pattern, count) + u_boot_console.run_command(cmd) + crc_pattern = u_boot_utils.crc32(u_boot_console, addr, count) + + cmd = 'sf update %08x %08x %x' % (addr, offset, count) + u_boot_console.run_command(cmd) + crc_readback = sf_read(u_boot_console, env__sf_config, sf_params) + + assert crc_readback == crc_pattern + +@pytest.mark.buildconfigspec('cmd_sf') +@pytest.mark.buildconfigspec('cmd_crc32') +@pytest.mark.buildconfigspec('cmd_memory') +def test_sf_read(u_boot_console, env__sf_config): + sf_params = sf_prepare(u_boot_console, env__sf_config) + sf_read(u_boot_console, env__sf_config, sf_params) + +@pytest.mark.buildconfigspec('cmd_sf') +@pytest.mark.buildconfigspec('cmd_crc32') +@pytest.mark.buildconfigspec('cmd_memory') +def test_sf_read_twice(u_boot_console, env__sf_config): + sf_params = sf_prepare(u_boot_console, env__sf_config) + + crc1 = sf_read(u_boot_console, env__sf_config, sf_params) + sf_params['ram_base'] += 0x100 + crc2 = sf_read(u_boot_console, env__sf_config, sf_params) + + assert crc1 == crc2, 'CRC32 of two successive read operation do not match' + +@pytest.mark.buildconfigspec('cmd_sf') +@pytest.mark.buildconfigspec('cmd_crc32') +@pytest.mark.buildconfigspec('cmd_memory') +def test_sf_erase(u_boot_console, env__sf_config): + if not env__sf_config.get('writeable', False): + pytest.skip('Flash config is tagged as not writeable') + + sf_params = sf_prepare(u_boot_console, env__sf_config) + addr = sf_params['ram_base'] + offset = env__sf_config['offset'] + count = sf_params['len'] + + cmd = 'sf erase %08x %x' % (offset, count) + output = u_boot_console.run_command(cmd) + assert 'Erased: OK' in output, 'Erase operation failed' + + cmd = 'mw.b %08x ff %x' % (addr, count) + u_boot_console.run_command(cmd) + crc_ffs = u_boot_utils.crc32(u_boot_console, addr, count) + + crc_read = sf_read(u_boot_console, env__sf_config, sf_params) + assert crc_ffs == crc_read, 'Unexpected CRC32 after erase operation.' + +@pytest.mark.buildconfigspec('cmd_sf') +@pytest.mark.buildconfigspec('cmd_crc32') +@pytest.mark.buildconfigspec('cmd_memory') +def test_sf_update(u_boot_console, env__sf_config): + if not env__sf_config.get('writeable', False): + pytest.skip('Flash config is tagged as not writeable') + + sf_params = sf_prepare(u_boot_console, env__sf_config) + sf_update(u_boot_console, env__sf_config, sf_params) diff --git a/test/py/u_boot_utils.py b/test/py/u_boot_utils.py index 9acb92ddc4..de9ee2643f 100644 --- a/test/py/u_boot_utils.py +++ b/test/py/u_boot_utils.py @@ -11,7 +11,7 @@ import os.path import pytest import sys import time -import pytest +import re def md5sum_data(data): """Calculate the MD5 hash of some data. @@ -311,3 +311,25 @@ def persistent_file_helper(u_boot_log, filename): """ return PersistentFileHelperCtxMgr(u_boot_log, filename) + +def crc32(u_boot_console, address, count): + """Helper function used to compute the CRC32 value of a section of RAM. + + Args: + u_boot_console: A U-Boot console connection. + address: Address where data starts. + count: Amount of data to use for calculation. + + Returns: + CRC32 value + """ + + bcfg = u_boot_console.config.buildconfig + has_cmd_crc32 = bcfg.get('config_cmd_crc32', 'n') == 'y' + assert has_cmd_crc32, 'Cannot compute crc32 without CONFIG_CMD_CRC32.' + output = u_boot_console.run_command('crc32 %08x %x' % (address, count)) + + m = re.search('==> ([0-9a-fA-F]{8})$', output) + assert m, 'CRC32 operation failed.' + + return m.group(1) diff --git a/tools/Makefile b/tools/Makefile index 55efb740b8..8143c25666 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -7,6 +7,7 @@ # Enable all the config-independent tools ifneq ($(HOST_TOOLS_ALL),) +CONFIG_KIRKWOOD = y CONFIG_LCD_LOGO = y CONFIG_CMD_LOADS = y CONFIG_CMD_NET = y diff --git a/tools/zynqimage.c b/tools/zynqimage.c index 021d2d3fc9..aa003a7543 100644 --- a/tools/zynqimage.c +++ b/tools/zynqimage.c @@ -147,6 +147,12 @@ static int zynqimage_verify_header(unsigned char *ptr, int image_size, if (image_size < sizeof(struct zynq_header)) return -1; + if (zynqhdr->__reserved1 != 0) + return -1; + + if (zynqhdr->__reserved2 != 0) + return -1; + if (zynqhdr->width_detection != HEADER_WIDTHDETECTION) return -1; if (zynqhdr->image_identifier != HEADER_IMAGEIDENTIFIER) diff --git a/tools/zynqmpimage.c b/tools/zynqmpimage.c index f48ac6dbe5..a61fb17c40 100644 --- a/tools/zynqmpimage.c +++ b/tools/zynqmpimage.c @@ -178,7 +178,7 @@ static void zynqmpimage_print_header(const void *ptr) struct zynqmp_header *zynqhdr = (struct zynqmp_header *)ptr; int i; - printf("Image Type : Xilinx Zynq Boot Image support\n"); + printf("Image Type : Xilinx ZynqMP Boot Image support\n"); printf("Image Offset : 0x%08x\n", le32_to_cpu(zynqhdr->image_offset)); printf("Image Size : %lu bytes (%lu bytes packed)\n", (unsigned long)le32_to_cpu(zynqhdr->image_size), |