diff options
92 files changed, 2040 insertions, 238 deletions
@@ -1026,6 +1026,17 @@ ifneq ($(CONFIG_WDT),y) @echo >&2 "====================================================" endif endif +ifneq ($(CONFIG_NET),) +ifneq ($(CONFIG_DM_ETH),y) + @echo >&2 "===================== WARNING ======================" + @echo >&2 "This board does not use CONFIG_DM_ETH (Driver Model" + @echo >&2 "for Ethernet drivers). Please update the board to use" + @echo >&2 "CONFIG_DM_ETH before the v2020.07 release. Failure to" + @echo >&2 "update by the deadline may result in board removal." + @echo >&2 "See doc/driver-model/migration.rst for more info." + @echo >&2 "====================================================" +endif +endif @# Check that this build does not use CONFIG options that we do not @# know about unless they are in Kconfig. All the existing CONFIG @# options are whitelisted, so new ones should not be added. diff --git a/arch/arc/lib/libgcc2.c b/arch/arc/lib/libgcc2.c index b92a841a37..ab1dbe1c13 100644 --- a/arch/arc/lib/libgcc2.c +++ b/arch/arc/lib/libgcc2.c @@ -158,3 +158,78 @@ __umodsi3(long a, long b) { return udivmodsi4(a, b, 1); } + +UDWtype +__udivmoddi4(UDWtype n, UDWtype d, UDWtype *rp) +{ + UDWtype q = 0, r = n, y = d; + UWtype lz1, lz2, i, k; + + /* + * Implements align divisor shift dividend method. This algorithm + * aligns the divisor under the dividend and then perform number of + * test-subtract iterations which shift the dividend left. Number of + * iterations is k + 1 where k is the number of bit positions the + * divisor must be shifted left to align it under the dividend. + * quotient bits can be saved in the rightmost positions of the + * dividend as it shifts left on each test-subtract iteration. + */ + + if (y <= r) { + lz1 = __builtin_clzll(d); + lz2 = __builtin_clzll(n); + + k = lz1 - lz2; + y = (y << k); + + /* + * Dividend can exceed 2 ^ (width - 1) - 1 but still be less + * than the aligned divisor. Normal iteration can drops the + * high order bit of the dividend. Therefore, first + * test-subtract iteration is a special case, saving its + * quotient bit in a separate location and not shifting + * the dividend. + */ + + if (r >= y) { + r = r - y; + q = (1ULL << k); + } + + if (k > 0) { + y = y >> 1; + + /* + * k additional iterations where k regular test + * subtract shift dividend iterations are done. + */ + i = k; + do { + if (r >= y) + r = ((r - y) << 1) + 1; + else + r = (r << 1); + i = i - 1; + } while (i != 0); + + /* + * First quotient bit is combined with the quotient + * bits resulting from the k regular iterations. + */ + q = q + r; + r = r >> k; + q = q - (r << k); + } + } + + if (rp) + *rp = r; + + return q; +} + +UDWtype +__udivdi3(UDWtype n, UDWtype d) +{ + return __udivmoddi4(n, d, (UDWtype *)0); +} diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig index 42d31fdab0..54d03ae622 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig +++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig @@ -245,14 +245,6 @@ config FSL_LSCH3 config NXP_LSCH3_2 bool -config FSL_MC_ENET - bool "Management Complex network" - depends on ARCH_LS2080A || ARCH_LS1088A || ARCH_LX2160A - default y - select RESV_RAM - help - Enable Management Complex (MC) network - menu "Layerscape architecture" depends on FSL_LSCH2 || FSL_LSCH3 @@ -593,15 +585,6 @@ config SYS_FSL_HAS_RGMII bool depends on SYS_FSL_EC1 || SYS_FSL_EC2 - -config SYS_MC_RSV_MEM_ALIGN - hex "Management Complex reserved memory alignment" - depends on RESV_RAM - default 0x20000000 if ARCH_LS2080A || ARCH_LS1088A || ARCH_LX2160A - help - Reserved memory needs to be aligned for MC to use. Default value - is 512MB. - config SPL_LDSCRIPT default "arch/arm/cpu/armv8/u-boot-spl.lds" if ARCH_LS1043A || ARCH_LS1046A || ARCH_LS2080A diff --git a/arch/arm/dts/armada-cp110-master.dtsi b/arch/arm/dts/armada-cp110-master.dtsi index 551d00d774..e4c17e9f4b 100644 --- a/arch/arm/dts/armada-cp110-master.dtsi +++ b/arch/arm/dts/armada-cp110-master.dtsi @@ -96,6 +96,7 @@ #size-cells = <0>; compatible = "marvell,orion-mdio"; reg = <0x12a200 0x10>; + device-name = "cpm-mdio"; }; cpm_syscon0: system-controller@440000 { diff --git a/arch/arm/dts/armada-cp110-slave.dtsi b/arch/arm/dts/armada-cp110-slave.dtsi index 2ea9004f1d..2fbd7b5514 100644 --- a/arch/arm/dts/armada-cp110-slave.dtsi +++ b/arch/arm/dts/armada-cp110-slave.dtsi @@ -96,6 +96,7 @@ #size-cells = <0>; compatible = "marvell,orion-mdio"; reg = <0x12a200 0x10>; + device-name = "cps-mdio"; }; cps_syscon0: system-controller@440000 { diff --git a/arch/arm/include/asm/mach-imx/mxc_i2c.h b/arch/arm/include/asm/mach-imx/mxc_i2c.h index 8e1ea9af19..81fd981444 100644 --- a/arch/arm/include/asm/mach-imx/mxc_i2c.h +++ b/arch/arm/include/asm/mach-imx/mxc_i2c.h @@ -6,6 +6,9 @@ #define __ASM_ARCH_MXC_MXC_I2C_H__ #include <asm-generic/gpio.h> #include <asm/mach-imx/iomux-v3.h> +#if CONFIG_IS_ENABLED(CLK) +#include <clk.h> +#endif struct i2c_pin_ctrl { iomux_v3_cfg_t i2c_mode; @@ -47,6 +50,9 @@ struct mxc_i2c_bus { ulong driver_data; int speed; struct i2c_pads_info *pads_info; +#if CONFIG_IS_ENABLED(CLK) + struct clk per_clk; +#endif #ifndef CONFIG_DM_I2C int (*idle_bus_fn)(void *p); void *idle_bus_data; diff --git a/arch/arm/mach-bcm283x/Kconfig b/arch/arm/mach-bcm283x/Kconfig index 3eb5a9a897..b08275f598 100644 --- a/arch/arm/mach-bcm283x/Kconfig +++ b/arch/arm/mach-bcm283x/Kconfig @@ -26,6 +26,23 @@ config BCM2837_64B select BCM2837 select ARM64 +config BCM2711 + bool "Broadcom BCM2711 SoC support" + depends on ARCH_BCM283X + +config BCM2711_32B + bool "Broadcom BCM2711 SoC 32-bit support" + depends on ARCH_BCM283X + select BCM2711 + select ARMV7_LPAE + select CPU_V7A + +config BCM2711_64B + bool "Broadcom BCM2711 SoC 64-bit support" + depends on ARCH_BCM283X + select BCM2711 + select ARM64 + menu "Broadcom BCM283X family" depends on ARCH_BCM283X @@ -127,6 +144,50 @@ config TARGET_RPI_3 This option creates a build targeting the ARMv8/AArch64 ISA. select BCM2837_64B +config TARGET_RPI_4_32B + bool "Raspberry Pi 4 32-bit build" + help + Support for all BCM2711-based Raspberry Pi variants, such as + the RPi 4 model B, in AArch32 (32-bit) mode. + + This option assumes the VideoCore firmware is configured to use the + mini UART (rather than PL011) for the serial console. This is the + default on the RPi 4. To enable the UART console, the following non- + default option must be present in config.txt: enable_uart=1. This is + required for U-Boot to operate correctly, even if you only care + about the HDMI/usbkbd console. + + Due to hardware incompatibilities, this can't be used with + BCM283/5/6/7. + + This option creates a build targeting the ARMv7/AArch32 ISA. + select BCM2711_32B + +config TARGET_RPI_4 + bool "Raspberry Pi 4 64-bit build" + help + Support for all BCM2711-based Raspberry Pi variants, such as + the RPi 4 model B, in AArch64 (64-bit) mode. + + This option assumes the VideoCore firmware is configured to use the + mini UART (rather than PL011) for the serial console. This is the + default on the RPi 4. To enable the UART console, the following non- + default option must be present in config.txt: enable_uart=1. This is + required for U-Boot to operate correctly, even if you only care + about the HDMI/usbkbd console. + + Due to hardware incompatibilities, this can't be used with + BCM283/5/6/7. + + Also, due to a bug in firmware, switching to 64bit mode doesn't + happen automatically based on the kernel's image filename. See + https://github.com/raspberrypi/firmware/issues/1193 for more details. + Until that is resolved, the configuration (config.txt) needs to + explicitly set: arm_64bit=1. + + This option creates a build targeting the ARMv8/AArch64 ISA. + select BCM2711_64B + endchoice config SYS_BOARD @@ -141,4 +202,10 @@ config SYS_SOC config SYS_CONFIG_NAME default "rpi" +config BCM283x_BASE + hex + default "0x20000000" if BCM2835 + default "0x3f000000" if BCM2836 || BCM2837 + default "0xfe000000" if BCM2711 + endmenu diff --git a/arch/arm/mach-bcm283x/include/mach/mbox.h b/arch/arm/mach-bcm283x/include/mach/mbox.h index e3a893e49c..0b6c2543d5 100644 --- a/arch/arm/mach-bcm283x/include/mach/mbox.h +++ b/arch/arm/mach-bcm283x/include/mach/mbox.h @@ -37,18 +37,17 @@ /* Raw mailbox HW */ -#ifndef CONFIG_BCM2835 -#define BCM2835_MBOX_PHYSADDR 0x3f00b880 -#else -#define BCM2835_MBOX_PHYSADDR 0x2000b880 -#endif +#define BCM2835_MBOX_PHYSADDR (CONFIG_BCM283x_BASE + 0x0000b880) struct bcm2835_mbox_regs { u32 read; u32 rsvd0[5]; - u32 status; - u32 config; + u32 mail0_status; + u32 mail0_config; u32 write; + u32 rsvd1[5]; + u32 mail1_status; + u32 mail1_config; }; #define BCM2835_MBOX_STATUS_WR_FULL 0x80000000 @@ -234,6 +233,7 @@ struct bcm2835_mbox_tag_set_power_state { #define BCM2835_MBOX_CLOCK_ID_SDRAM 8 #define BCM2835_MBOX_CLOCK_ID_PIXEL 9 #define BCM2835_MBOX_CLOCK_ID_PWM 10 +#define BCM2835_MBOX_CLOCK_ID_EMMC2 12 struct bcm2835_mbox_tag_get_clock_rate { struct bcm2835_mbox_tag_hdr tag_hdr; diff --git a/arch/arm/mach-bcm283x/include/mach/sdhci.h b/arch/arm/mach-bcm283x/include/mach/sdhci.h index 5cb6ec3340..b443c379d8 100644 --- a/arch/arm/mach-bcm283x/include/mach/sdhci.h +++ b/arch/arm/mach-bcm283x/include/mach/sdhci.h @@ -6,11 +6,7 @@ #ifndef _BCM2835_SDHCI_H_ #define _BCM2835_SDHCI_H_ -#ifndef CONFIG_BCM2835 -#define BCM2835_SDHCI_BASE 0x3f300000 -#else -#define BCM2835_SDHCI_BASE 0x20300000 -#endif +#define BCM2835_SDHCI_BASE (CONFIG_BCM283x_BASE + 0x00300000) int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq); diff --git a/arch/arm/mach-bcm283x/include/mach/timer.h b/arch/arm/mach-bcm283x/include/mach/timer.h index 56b0c356bb..014355e759 100644 --- a/arch/arm/mach-bcm283x/include/mach/timer.h +++ b/arch/arm/mach-bcm283x/include/mach/timer.h @@ -6,11 +6,7 @@ #ifndef _BCM2835_TIMER_H #define _BCM2835_TIMER_H -#ifndef CONFIG_BCM2835 -#define BCM2835_TIMER_PHYSADDR 0x3f003000 -#else -#define BCM2835_TIMER_PHYSADDR 0x20003000 -#endif +#define BCM2835_TIMER_PHYSADDR (CONFIG_BCM283x_BASE + 0x00003000) #define BCM2835_TIMER_CS_M3 (1 << 3) #define BCM2835_TIMER_CS_M2 (1 << 2) diff --git a/arch/arm/mach-bcm283x/include/mach/wdog.h b/arch/arm/mach-bcm283x/include/mach/wdog.h index 99c88e5df7..8292b3cf1f 100644 --- a/arch/arm/mach-bcm283x/include/mach/wdog.h +++ b/arch/arm/mach-bcm283x/include/mach/wdog.h @@ -6,11 +6,7 @@ #ifndef _BCM2835_WDOG_H #define _BCM2835_WDOG_H -#ifndef CONFIG_BCM2835 -#define BCM2835_WDOG_PHYSADDR 0x3f100000 -#else -#define BCM2835_WDOG_PHYSADDR 0x20100000 -#endif +#define BCM2835_WDOG_PHYSADDR (CONFIG_BCM283x_BASE + 0x00100000) struct bcm2835_wdog_regs { u32 unknown0[7]; diff --git a/arch/arm/mach-bcm283x/mbox.c b/arch/arm/mach-bcm283x/mbox.c index 1642ebd103..3c67f68c17 100644 --- a/arch/arm/mach-bcm283x/mbox.c +++ b/arch/arm/mach-bcm283x/mbox.c @@ -27,7 +27,7 @@ int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv) /* Drain any stale responses */ for (;;) { - val = readl(®s->status); + val = readl(®s->mail0_status); if (val & BCM2835_MBOX_STATUS_RD_EMPTY) break; if (get_timer(0) >= endtime) { @@ -40,7 +40,7 @@ int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv) /* Wait for space to send */ for (;;) { - val = readl(®s->status); + val = readl(®s->mail1_status); if (!(val & BCM2835_MBOX_STATUS_WR_FULL)) break; if (get_timer(0) >= endtime) { @@ -58,7 +58,7 @@ int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv) /* Wait for the response */ for (;;) { - val = readl(®s->status); + val = readl(®s->mail0_status); if (!(val & BCM2835_MBOX_STATUS_RD_EMPTY)) break; if (get_timer(0) >= endtime) { diff --git a/arch/riscv/cpu/ax25/Kconfig b/arch/riscv/cpu/ax25/Kconfig index f4b59cb71d..d411a79c21 100644 --- a/arch/riscv/cpu/ax25/Kconfig +++ b/arch/riscv/cpu/ax25/Kconfig @@ -6,6 +6,7 @@ config RISCV_NDS imply RISCV_TIMER imply ANDES_PLIC if (RISCV_MMODE || SPL_RISCV_MMODE) imply ANDES_PLMT if (RISCV_MMODE || SPL_RISCV_MMODE) + imply V5L2_CACHE help Run U-Boot on AndeStar V5 platforms and use some specific features which are provided by Andes Technology AndeStar V5 families. diff --git a/arch/riscv/cpu/ax25/cache.c b/arch/riscv/cpu/ax25/cache.c index cd95058d9d..41de30cc02 100644 --- a/arch/riscv/cpu/ax25/cache.c +++ b/arch/riscv/cpu/ax25/cache.c @@ -5,17 +5,24 @@ */ #include <common.h> +#include <dm.h> +#include <dm/uclass-internal.h> +#include <cache.h> +#include <asm/csr.h> + +#ifdef CONFIG_RISCV_NDS_CACHE +/* mcctlcommand */ +#define CCTL_REG_MCCTLCOMMAND_NUM 0x7cc + +/* D-cache operation */ +#define CCTL_L1D_WBINVAL_ALL 6 +#endif void flush_dcache_all(void) { - /* - * Andes' AX25 does not have a coherence agent. U-Boot must use data - * cache flush and invalidate functions to keep data in the system - * coherent. - * The implementation of the fence instruction in the AX25 flushes the - * data cache and is used for this purpose. - */ - asm volatile ("fence" ::: "memory"); +#ifdef CONFIG_RISCV_NDS_CACHE + csr_write(CCTL_REG_MCCTLCOMMAND_NUM, CCTL_L1D_WBINVAL_ALL); +#endif } void flush_dcache_range(unsigned long start, unsigned long end) @@ -59,11 +66,18 @@ void dcache_enable(void) { #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) #ifdef CONFIG_RISCV_NDS_CACHE + struct udevice *dev = NULL; + asm volatile ( "csrr t1, mcache_ctl\n\t" "ori t0, t1, 0x2\n\t" "csrw mcache_ctl, t0\n\t" ); + + uclass_find_first_device(UCLASS_CACHE, &dev); + + if (dev) + cache_enable(dev); #endif #endif } @@ -72,12 +86,19 @@ void dcache_disable(void) { #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) #ifdef CONFIG_RISCV_NDS_CACHE + struct udevice *dev = NULL; + + csr_write(CCTL_REG_MCCTLCOMMAND_NUM, CCTL_L1D_WBINVAL_ALL); asm volatile ( - "fence\n\t" "csrr t1, mcache_ctl\n\t" "andi t0, t1, ~0x2\n\t" "csrw mcache_ctl, t0\n\t" ); + + uclass_find_first_device(UCLASS_CACHE, &dev); + + if (dev) + cache_disable(dev); #endif #endif } diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S index b15209d623..0a2ce6d691 100644 --- a/arch/riscv/cpu/start.S +++ b/arch/riscv/cpu/start.S @@ -269,7 +269,7 @@ fix_rela_dyn: /* * skip first reserved entry: address, type, addend */ - bne t1, t2, 7f + j 10f 6: LREG t5, -(REGBYTES*2)(t1) /* t5 <-- relocation info:type */ @@ -280,9 +280,7 @@ fix_rela_dyn: add t5, t5, t6 /* t5 <-- location to fix up in RAM */ add t3, t3, t6 /* t3 <-- location to fix up in RAM */ SREG t5, 0(t3) -7: - addi t1, t1, (REGBYTES*3) - ble t1, t2, 6b + j 10f 8: la t4, __dyn_sym_start @@ -299,13 +297,15 @@ fix_rela_dyn: li t5, SYM_SIZE mul t0, t0, t5 add s5, t4, t0 + LREG t0, -(REGBYTES)(t1) /* t0 <-- addend */ LREG t5, REGBYTES(s5) + add t5, t5, t0 add t5, t5, t6 /* t5 <-- location to fix up in RAM */ add t3, t3, t6 /* t3 <-- location to fix up in RAM */ SREG t5, 0(t3) 10: addi t1, t1, (REGBYTES*3) - ble t1, t2, 9b + ble t1, t2, 6b /* * trap update diff --git a/arch/riscv/dts/ae350_32.dts b/arch/riscv/dts/ae350_32.dts index cb6ee13f16..97b7cee983 100644 --- a/arch/riscv/dts/ae350_32.dts +++ b/arch/riscv/dts/ae350_32.dts @@ -62,13 +62,18 @@ compatible = "riscv,cpu-intc"; }; }; + }; - L2: l2-cache@e0500000 { - compatible = "cache"; - cache-level = <2>; - cache-size = <0x40000>; - reg = <0x0 0xe0500000 0x0 0x40000>; - }; + L2: l2-cache@e0500000 { + compatible = "v5l2cache"; + cache-level = <2>; + cache-size = <0x40000>; + reg = <0xe0500000 0x40000>; + andes,inst-prefetch = <3>; + andes,data-prefetch = <3>; + /* The value format is <XRAMOCTL XRAMICTL> */ + andes,tag-ram-ctl = <0 0>; + andes,data-ram-ctl = <0 0>; }; memory@0 { diff --git a/arch/riscv/dts/ae350_64.dts b/arch/riscv/dts/ae350_64.dts index 705491a8e4..d8f00f8d3a 100644 --- a/arch/riscv/dts/ae350_64.dts +++ b/arch/riscv/dts/ae350_64.dts @@ -62,13 +62,18 @@ compatible = "riscv,cpu-intc"; }; }; + }; - L2: l2-cache@e0500000 { - compatible = "cache"; - cache-level = <2>; - cache-size = <0x40000>; - reg = <0x0 0xe0500000 0x0 0x40000>; - }; + L2: l2-cache@e0500000 { + compatible = "v5l2cache"; + cache-level = <2>; + cache-size = <0x40000>; + reg = <0x0 0xe0500000 0x0 0x40000>; + andes,inst-prefetch = <3>; + andes,data-prefetch = <3>; + /* The value format is <XRAMOCTL XRAMICTL> */ + andes,tag-ram-ctl = <0 0>; + andes,data-ram-ctl = <0 0>; }; memory@0 { diff --git a/arch/riscv/lib/andes_plic.c b/arch/riscv/lib/andes_plic.c index 2ffe49ac90..28568e4e2b 100644 --- a/arch/riscv/lib/andes_plic.c +++ b/arch/riscv/lib/andes_plic.c @@ -44,15 +44,12 @@ static int init_plic(void); } \ } while (0) -static int enable_ipi(int harts) +static int enable_ipi(int hart) { - int i; - int en = ENABLE_HART_IPI; + int en; - for (i = 0; i < harts; i++) { - en = en >> i; - writel(en, (void __iomem *)ENABLE_REG(gd->arch.plic, i)); - } + en = ENABLE_HART_IPI >> hart; + writel(en, (void __iomem *)ENABLE_REG(gd->arch.plic, hart)); return 0; } @@ -60,18 +57,35 @@ static int enable_ipi(int harts) static int init_plic(void) { struct udevice *dev; + ofnode node; int ret; + u32 reg; ret = uclass_find_first_device(UCLASS_CPU, &dev); if (ret) return ret; if (ret == 0 && dev) { - ret = cpu_get_count(dev); - if (ret < 0) - return ret; + ofnode_for_each_subnode(node, dev_ofnode(dev->parent)) { + const char *device_type; + + device_type = ofnode_read_string(node, "device_type"); + if (!device_type) + continue; + + if (strcmp(device_type, "cpu")) + continue; + + /* skip if hart is marked as not available */ + if (!ofnode_is_available(node)) + continue; + + /* read hart ID of CPU */ + ret = ofnode_read_u32(node, "reg", ®); + if (ret == 0) + enable_ipi(reg); + } - enable_ipi(ret); return 0; } diff --git a/board/AndesTech/ax25-ae350/ax25-ae350.c b/board/AndesTech/ax25-ae350/ax25-ae350.c index 3d65ce7b75..b43eebb7a6 100644 --- a/board/AndesTech/ax25-ae350/ax25-ae350.c +++ b/board/AndesTech/ax25-ae350/ax25-ae350.c @@ -11,6 +11,7 @@ #include <linux/io.h> #include <faraday/ftsmc020.h> #include <fdtdec.h> +#include <dm.h> DECLARE_GLOBAL_DATA_PTR; @@ -93,10 +94,18 @@ int smc_init(void) return 0; } +static void v5l2_init(void) +{ + struct udevice *dev; + + uclass_get_device(UCLASS_CACHE, 0, &dev); +} + #ifdef CONFIG_BOARD_EARLY_INIT_F int board_early_init_f(void) { smc_init(); + v5l2_init(); return 0; } diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index 7a6ca8f759..fa57d50c95 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -148,6 +148,11 @@ static const struct rpi_model rpi_models_new_scheme[] = { DTB_DIR "bcm2837-rpi-cm3.dtb", false, }, + [0x11] = { + "4 Model B", + DTB_DIR "bcm2711-rpi-4-b.dtb", + true, + }, }; static const struct rpi_model rpi_models_old_scheme[] = { @@ -244,7 +249,8 @@ static uint32_t rev_type; static const struct rpi_model *model; #ifdef CONFIG_ARM64 -static struct mm_region bcm2837_mem_map[] = { +#ifndef CONFIG_BCM2711 +static struct mm_region bcm283x_mem_map[] = { { .virt = 0x00000000UL, .phys = 0x00000000UL, @@ -263,8 +269,28 @@ static struct mm_region bcm2837_mem_map[] = { 0, } }; - -struct mm_region *mem_map = bcm2837_mem_map; +#else +static struct mm_region bcm283x_mem_map[] = { + { + .virt = 0x00000000UL, + .phys = 0x00000000UL, + .size = 0xfe000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + .virt = 0xfe000000UL, + .phys = 0xfe000000UL, + .size = 0x01800000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* List terminator */ + 0, + } +}; +#endif +struct mm_region *mem_map = bcm283x_mem_map; #endif int dram_init(void) diff --git a/board/sifive/fu540/fu540.c b/board/sifive/fu540/fu540.c index 11daf1a75a..47a2090251 100644 --- a/board/sifive/fu540/fu540.c +++ b/board/sifive/fu540/fu540.c @@ -122,10 +122,20 @@ static void fu540_setup_macaddr(u32 serialnum) int misc_init_r(void) { - /* Set ethaddr environment variable if not set */ - if (!env_get("ethaddr")) - fu540_setup_macaddr(fu540_read_serialnum()); - + u32 serial_num; + char buf[9] = {0}; + + /* Set ethaddr environment variable from board serial number */ + if (!env_get("serial#")) { + serial_num = fu540_read_serialnum(); + if (!serial_num) { + WARN(true, "Board serial number should not be 0 !!\n"); + return 0; + } + snprintf(buf, sizeof(buf), "%08x", serial_num); + env_set("serial#", buf); + fu540_setup_macaddr(serial_num); + } return 0; } diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index fc14ad375c..18f9b84876 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -17,6 +17,7 @@ #include <misc.h> #include <mtd.h> #include <mtd_node.h> +#include <netdev.h> #include <phy.h> #include <remoteproc.h> #include <reset.h> @@ -683,12 +684,21 @@ void board_quiesce_devices(void) #endif } -/* board interface eth init */ -int board_interface_eth_init(phy_interface_t interface_type, - bool eth_clk_sel_reg, bool eth_ref_clk_sel_reg) +/* eth init function : weak called in eqos driver */ +int board_interface_eth_init(struct udevice *dev, + phy_interface_t interface_type) { u8 *syscfg; u32 value; + bool eth_clk_sel_reg = false; + bool eth_ref_clk_sel_reg = false; + + /* Gigabit Ethernet 125MHz clock selection. */ + eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel"); + + /* Ethernet 50Mhz RMII clock selection */ + eth_ref_clk_sel_reg = + dev_read_bool(dev, "st,eth_ref_clk_sel"); syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG); diff --git a/board/synopsys/emsdp/config.mk b/board/synopsys/emsdp/config.mk new file mode 100644 index 0000000000..67fd7bf82a --- /dev/null +++ b/board/synopsys/emsdp/config.mk @@ -0,0 +1,2 @@ +PLATFORM_CPPFLAGS += -mlittle-endian -mnorm -mswap -mmpy-option=3 \ + -mbarrel-shifter -mfpu=fpuda_all -mcode-density diff --git a/board/synopsys/emsdp/emsdp.c b/board/synopsys/emsdp/emsdp.c index c0770b58c1..7a3fd5b7f2 100644 --- a/board/synopsys/emsdp/emsdp.c +++ b/board/synopsys/emsdp/emsdp.c @@ -48,6 +48,43 @@ int mach_cpu_init(void) return 0; } +int board_early_init_r(void) +{ +#define EMSDP_PSRAM_BASE 0xf2001000 +#define PSRAM_FLASH_CONFIG_REG_0 (void *)(EMSDP_PSRAM_BASE + 0x10) +#define PSRAM_FLASH_CONFIG_REG_1 (void *)(EMSDP_PSRAM_BASE + 0x14) +#define CRE_ENABLE BIT(31) +#define CRE_DRIVE_CMD BIT(6) + +#define PSRAM_RCR_DPD BIT(1) +#define PSRAM_RCR_PAGE_MODE BIT(7) + +/* + * PSRAM_FLASH_CONFIG_REG_x[30:15] to the address lines[16:1] of flash, + * thus "<< 1". + */ +#define PSRAM_RCR_SETUP ((PSRAM_RCR_DPD | PSRAM_RCR_PAGE_MODE) << 1) + + // Switch PSRAM controller to command mode + writel(CRE_ENABLE | CRE_DRIVE_CMD, PSRAM_FLASH_CONFIG_REG_0); + // Program Refresh Configuration Register (RCR) for BANK0 + writew(0, (void *)(0x10000000 + PSRAM_RCR_SETUP)); + // Switch PSRAM controller back to memory mode + writel(0, PSRAM_FLASH_CONFIG_REG_0); + + + // Switch PSRAM controller to command mode + writel(CRE_ENABLE | CRE_DRIVE_CMD, PSRAM_FLASH_CONFIG_REG_1); + // Program Refresh Configuration Register (RCR) for BANK1 + writew(0, (void *)(0x10800000 + PSRAM_RCR_SETUP)); + // Switch PSRAM controller back to memory mode + writel(0, PSRAM_FLASH_CONFIG_REG_1); + + printf("PSRAM initialized.\n"); + + return 0; +} + int board_mmc_init(bd_t *bis) { struct dwmci_host *host = NULL; diff --git a/cmd/Kconfig b/cmd/Kconfig index 05872fa0d7..98647f58b7 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1339,6 +1339,13 @@ config BOOTP_NTPSERVER bool "Request & store 'ntpserverip' from BOOTP/DHCP server" depends on CMD_BOOTP +config CMD_PCAP + bool "pcap capture" + help + Selecting this will allow capturing all Ethernet packets and store + them in physical memory in a PCAP formated file, + later to be analyzed by PCAP reader application (IE. WireShark). + config BOOTP_PXE bool "Send PXE client arch to BOOTP/DHCP server" default y diff --git a/cmd/Makefile b/cmd/Makefile index 58827b5679..ac843b4b16 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -103,6 +103,7 @@ obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o obj-$(CONFIG_CMD_ONENAND) += onenand.o obj-$(CONFIG_CMD_OSD) += osd.o obj-$(CONFIG_CMD_PART) += part.o +obj-$(CONFIG_CMD_PCAP) += pcap.o ifdef CONFIG_PCI obj-$(CONFIG_CMD_PCI) += pci.o endif diff --git a/cmd/mdio.c b/cmd/mdio.c index add6440813..22c8fbe856 100644 --- a/cmd/mdio.c +++ b/cmd/mdio.c @@ -253,12 +253,13 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) case 'w': if (pos > 1) data = simple_strtoul(argv[pos--], NULL, 16); + /* Intentional fall-through - Get reg for read and write */ case 'r': if (pos > 1) if (extract_reg_range(argv[pos--], &devadlo, &devadhi, ®lo, ®hi)) return CMD_RET_FAILURE; - + /* Intentional fall-through - Get phy for all commands */ default: if (pos > 1) if (extract_phy_range(&argv[2], pos - 1, &bus, diff --git a/cmd/pcap.c b/cmd/pcap.c new file mode 100644 index 0000000000..980603f7bd --- /dev/null +++ b/cmd/pcap.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2019 + * Ramon Fried <rfried.dev@gmail.com> + */ + +#include <common.h> +#include <command.h> +#include <net.h> +#include <net/pcap.h> + +static int do_pcap_init(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + phys_addr_t addr; + unsigned int size; + + if (argc != 3) + return CMD_RET_USAGE; + + addr = simple_strtoul(argv[1], NULL, 16); + size = simple_strtoul(argv[2], NULL, 10); + + return pcap_init(addr, size) ? CMD_RET_FAILURE : CMD_RET_SUCCESS; +} + +static int do_pcap_start(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + return pcap_start_stop(true) ? CMD_RET_FAILURE : CMD_RET_SUCCESS; +} + +static int do_pcap_stop(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + return pcap_start_stop(false) ? CMD_RET_FAILURE : CMD_RET_SUCCESS; +} + +static int do_pcap_status(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + return pcap_print_status() ? CMD_RET_FAILURE : CMD_RET_SUCCESS; +} + +static int do_pcap_clear(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + return pcap_clear() ? CMD_RET_FAILURE : CMD_RET_SUCCESS; +} + +static char pcap_help_text[] = + "- network packet capture\n\n" + "pcap\n" + "pcap init\t\t\t<addr> <max_size>\n" + "pcap start\t\t\tstart capture\n" + "pcap stop\t\t\tstop capture\n" + "pcap status\t\t\tprint status\n" + "pcap clear\t\t\tclear capture buffer\n" + "\n" + "With:\n" + "\t<addr>: user address to which pcap will be stored (hexedcimal)\n" + "\t<max_size>: Maximum size of pcap file (decimal)\n" + "\n"; + +U_BOOT_CMD_WITH_SUBCMDS(pcap, "pcap", pcap_help_text, + U_BOOT_SUBCMD_MKENT(init, 3, 0, do_pcap_init), + U_BOOT_SUBCMD_MKENT(start, 1, 0, do_pcap_start), + U_BOOT_SUBCMD_MKENT(stop, 1, 0, do_pcap_stop), + U_BOOT_SUBCMD_MKENT(status, 1, 0, do_pcap_status), + U_BOOT_SUBCMD_MKENT(clear, 1, 0, do_pcap_clear), +); diff --git a/configs/emsdp_defconfig b/configs/emsdp_defconfig index 64281d0529..5e55e3e2b2 100644 --- a/configs/emsdp_defconfig +++ b/configs/emsdp_defconfig @@ -7,6 +7,7 @@ CONFIG_ENV_SIZE=0x1000 CONFIG_SYS_CLK_FREQ=40000000 # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set CONFIG_VERSION_VARIABLE=y +CONFIG_BOARD_EARLY_INIT_R=y CONFIG_HUSH_PARSER=y CONFIG_SYS_PROMPT="emsdp# " # CONFIG_CMD_BOOTD is not set diff --git a/configs/qemu-riscv32_defconfig b/configs/qemu-riscv32_defconfig index d5b33b5c2b..fe09a0da88 100644 --- a/configs/qemu-riscv32_defconfig +++ b/configs/qemu-riscv32_defconfig @@ -5,5 +5,6 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT=y CONFIG_DISPLAY_CPUINFO=y CONFIG_DISPLAY_BOARDINFO=y +CONFIG_CMD_BOOTEFI_SELFTEST=y # CONFIG_CMD_MII is not set CONFIG_OF_PRIOR_STAGE=y diff --git a/configs/qemu-riscv32_smode_defconfig b/configs/qemu-riscv32_smode_defconfig index a80e68b8c7..7103324421 100644 --- a/configs/qemu-riscv32_smode_defconfig +++ b/configs/qemu-riscv32_smode_defconfig @@ -6,5 +6,6 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT=y CONFIG_DISPLAY_CPUINFO=y CONFIG_DISPLAY_BOARDINFO=y +CONFIG_CMD_BOOTEFI_SELFTEST=y # CONFIG_CMD_MII is not set CONFIG_OF_PRIOR_STAGE=y diff --git a/configs/qemu-riscv64_defconfig b/configs/qemu-riscv64_defconfig index 19a5849226..ef84dfded2 100644 --- a/configs/qemu-riscv64_defconfig +++ b/configs/qemu-riscv64_defconfig @@ -6,5 +6,6 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT=y CONFIG_DISPLAY_CPUINFO=y CONFIG_DISPLAY_BOARDINFO=y +CONFIG_CMD_BOOTEFI_SELFTEST=y # CONFIG_CMD_MII is not set CONFIG_OF_PRIOR_STAGE=y diff --git a/configs/qemu-riscv64_smode_defconfig b/configs/qemu-riscv64_smode_defconfig index 74743a5ebe..1c7a2d150c 100644 --- a/configs/qemu-riscv64_smode_defconfig +++ b/configs/qemu-riscv64_smode_defconfig @@ -7,5 +7,6 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT=y CONFIG_DISPLAY_CPUINFO=y CONFIG_DISPLAY_BOARDINFO=y +CONFIG_CMD_BOOTEFI_SELFTEST=y # CONFIG_CMD_MII is not set CONFIG_OF_PRIOR_STAGE=y diff --git a/configs/rpi_4_32b_defconfig b/configs/rpi_4_32b_defconfig new file mode 100644 index 0000000000..a31a617a5f --- /dev/null +++ b/configs/rpi_4_32b_defconfig @@ -0,0 +1,33 @@ +CONFIG_ARM=y +CONFIG_ARCH_BCM283X=y +CONFIG_SYS_TEXT_BASE=0x00008000 +CONFIG_TARGET_RPI_4_32B=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_DISTRO_DEFAULTS=y +CONFIG_NR_DRAM_BANKS=1 +# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set +CONFIG_OF_BOARD=y +CONFIG_OF_BOARD_SETUP=y +CONFIG_MISC_INIT_R=y +# CONFIG_DISPLAY_CPUINFO is not set +# CONFIG_DISPLAY_BOARDINFO is not set +CONFIG_SYS_PROMPT="U-Boot> " +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_MMC=y +CONFIG_CMD_FS_UUID=y +CONFIG_ENV_FAT_INTERFACE="mmc" +CONFIG_ENV_FAT_DEVICE_AND_PART="0:1" +CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y +CONFIG_DM_KEYBOARD=y +CONFIG_DM_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_BCM2835=y +CONFIG_PINCTRL=y +# CONFIG_PINCTRL_GENERIC is not set +# CONFIG_REQUIRE_SERIAL_CONSOLE is not set +CONFIG_DM_VIDEO=y +CONFIG_SYS_WHITE_ON_BLACK=y +CONFIG_CONSOLE_SCROLL_LINES=10 +CONFIG_PHYS_TO_BUS=y +CONFIG_OF_LIBFDT_OVERLAY=y diff --git a/configs/rpi_4_defconfig b/configs/rpi_4_defconfig new file mode 100644 index 0000000000..da8c960a2a --- /dev/null +++ b/configs/rpi_4_defconfig @@ -0,0 +1,33 @@ +CONFIG_ARM=y +CONFIG_ARCH_BCM283X=y +CONFIG_SYS_TEXT_BASE=0x00080000 +CONFIG_TARGET_RPI_4=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_DISTRO_DEFAULTS=y +CONFIG_NR_DRAM_BANKS=1 +# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set +CONFIG_OF_BOARD=y +CONFIG_OF_BOARD_SETUP=y +CONFIG_MISC_INIT_R=y +# CONFIG_DISPLAY_CPUINFO is not set +# CONFIG_DISPLAY_BOARDINFO is not set +CONFIG_SYS_PROMPT="U-Boot> " +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_MMC=y +CONFIG_CMD_FS_UUID=y +CONFIG_ENV_FAT_INTERFACE="mmc" +CONFIG_ENV_FAT_DEVICE_AND_PART="0:1" +CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y +CONFIG_DM_KEYBOARD=y +CONFIG_DM_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_BCM2835=y +CONFIG_PINCTRL=y +# CONFIG_PINCTRL_GENERIC is not set +# CONFIG_REQUIRE_SERIAL_CONSOLE is not set +CONFIG_DM_VIDEO=y +CONFIG_SYS_WHITE_ON_BLACK=y +CONFIG_CONSOLE_SCROLL_LINES=10 +CONFIG_PHYS_TO_BUS=y +CONFIG_OF_LIBFDT_OVERLAY=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 7355e3aa1e..968ffdab61 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -49,6 +49,7 @@ CONFIG_CMD_SPI=y CONFIG_CMD_USB=y CONFIG_CMD_AXI=y CONFIG_CMD_AB_SELECT=y +CONFIG_CMD_PCAP=y CONFIG_CMD_TFTPPUT=y CONFIG_CMD_TFTPSRV=y CONFIG_CMD_RARP=y diff --git a/doc/README.pcap b/doc/README.pcap new file mode 100644 index 0000000000..97b3e55fd8 --- /dev/null +++ b/doc/README.pcap @@ -0,0 +1,62 @@ +PCAP: + +U-boot supports live Ethernet packet capture in PCAP(2.4) format. +This is enabled by CONFIG_CMD_PCAP. + +The capture is stored on physical memory, and should be copied to +a machine capable of parsing and displaying PCAP files (IE. wireshark) +If networking works properly one can copy the capture file from physical memory +using tftpput, or save it to local storage with (sf write, mmc write, fatwrite, etc) + +the pcap capturing requires maximum buffer size. +when the buffer is full an error message will be displayed and then packets +will silently drop. +the actual capture file size is populate in the environment variable "pcapsize". + +Usage example: + +# Initialize pcap capture to physical address (0x100000) with maximum size of +# 100000 bytes. + +# Start capture +pcap start + +# Initialize network activity +env set ipaddr 10.0.2.15; env set serverip 10.0.2.2; tftp uImage64 + +# Stop capture +pcap stop + +# pcap init 0x100000 100000 +PCAP capture initialized: addr: 0xffffffff80100000 max length: 100000 + +# pcap start +# env set ipaddr 10.0.2.15; env set serverip 10.0.2.2; tftp uImage64 +eth0@10000000: PHY present at 0 +eth0@10000000: link up, 1000Mbps full-duplex (lpa: 0x7c00) +Using eth0@10000000 device +TFTP from server 10.0.2.2; our IP address is 10.0.2.15 +Filename 'uImage64'. +Load address: 0xffffffff88000000 +Loading: ################################################################# + ################################################################# + ################################################################# + ################################################################# +!!! Buffer is full, consider increasing buffer size !!! + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + # + 18.2 MiB/s +done +Bytes transferred = 8359376 (7f8dd0 hex) +PCAP status: + Initialized addr: 0xffffffff80100000 max length: 100000 + Status: Active. file size: 99991 + Incoming packets: 66 Outgoing packets: 67 + +# pcap stop +# tftpput 0xffffffff80100000 $pcapsize 10.0.2.2:capture.pcap + diff --git a/doc/api/efi.rst b/doc/api/efi.rst index 39e2dbae0b..2ca344932e 100644 --- a/doc/api/efi.rst +++ b/doc/api/efi.rst @@ -103,3 +103,36 @@ Block device driver .. kernel-doc:: lib/efi_driver/efi_block_device.c :internal: + +Protocols +--------- + +Block IO protocol +~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: lib/efi_loader/efi_disk.c + :internal: + +File protocol +~~~~~~~~~~~~~ + +.. kernel-doc:: lib/efi_loader/efi_file.c + :internal: + +Graphical output protocol +~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: lib/efi_loader/efi_gop.c + :internal: + +Network protocols +~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: lib/efi_loader/efi_net.c + :internal: + +Text IO protocols +~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: lib/efi_loader/efi_console.c + :internal: diff --git a/doc/device-tree-bindings/net/marvell-mdio.txt b/doc/device-tree-bindings/net/marvell-mdio.txt new file mode 100644 index 0000000000..e2038e2145 --- /dev/null +++ b/doc/device-tree-bindings/net/marvell-mdio.txt @@ -0,0 +1,15 @@ +* Marvell MDIO Ethernet Controller interface + +The Ethernet controllers of the Marvel Armada 3700 and Armada 7k/8k +have an identical unit that provides an interface with the MDIO bus. +This driver handles this MDIO interface. + +Mandatory properties: +SoC specific: + - #address-cells: Must be <1>. + - #size-cells: Must be <0>. + - compatible: Should be "marvell,orion-mdio" (for SMI) + "marvell,xmdio" (for XSMI) + - reg: Base address and size SMI/XMSI bus. + +Please refer to "mdio.txt" for generic MDIO bus bindings. diff --git a/doc/device-tree-bindings/net/mdio.txt b/doc/device-tree-bindings/net/mdio.txt new file mode 100644 index 0000000000..1595325050 --- /dev/null +++ b/doc/device-tree-bindings/net/mdio.txt @@ -0,0 +1,36 @@ +Common MDIO bus properties. + +These are generic properties that can apply to any MDIO bus. + +Optional properties: + - device-name - If present it is used to name the device and MDIO bus. + The name must be unique and must not contain spaces. + +A list of child nodes, one per device on the bus is expected. These could be +PHYs, switches or similar devices and child nodes should follow the specific +binding for the device type. + +Example : +This example shows the structure used for the external MDIO bus on NXP LS1028A +RDB board. Note that this MDIO device is an integrated PCI function and +requires no compatible property for probing. + +/* definition in SoC dtsi file */ + pcie@1f0000000 { + + mdio0: pci@0,3 { + #address-cells=<0>; + #size-cells=<1>; + reg = <0x000300 0 0 0 0>; + status = "disabled"; + device-name = "emdio"; + }; + }; +/* definition of PHYs in RDB dts file */ +&mdio0 { + status = "okay"; + rdb_phy0: phy@2 { + reg = <2>; + }; +}; + diff --git a/doc/driver-model/migration.rst b/doc/driver-model/migration.rst index a26e7ab7e1..75b85235ef 100644 --- a/doc/driver-model/migration.rst +++ b/doc/driver-model/migration.rst @@ -97,3 +97,11 @@ Deadline: 2019.07 The video subsystem has supported driver model since early 2016. Maintainers should submit patches switching over to using CONFIG_DM_VIDEO and other base driver model options in time for inclusion in the 2019.07 release. + +CONFIG_DM_ETH +------------- +Deadline: 2020.07 + +The network subsystem has supported the driver model since early 2015. +Maintainers should submit patches switching over to using CONFIG_DM_ETH and +other base driver model options in time for inclusion in the 2020.07 release. diff --git a/doc/git-mailrc b/doc/git-mailrc index a63b76befc..1d36f5845a 100644 --- a/doc/git-mailrc +++ b/doc/git-mailrc @@ -35,6 +35,7 @@ alias mariosix Mario Six <mario.six@gdsys.cc> alias masahiro Masahiro Yamada <yamada.masahiro@socionext.com> alias mateusz Mateusz Kulikowski <mateusz.kulikowski@gmail.com> alias maxime Maxime Ripard <maxime.ripard@free-electrons.com> +alias mbrugger Matthias Brugger <mbrugger@suse.com> alias monstr Michal Simek <monstr@monstr.eu> alias prom Minkyu Kang <mk7.kang@samsung.com> alias ptomsich Philipp Tomsich <philipp.tomsich@theobroma-systems.com> @@ -74,6 +75,9 @@ alias uniphier uboot, masahiro alias zynq uboot, monstr alias rockchip uboot, sjg, kevery, ptomsich +alias bcm283x uboot, mbrugger +alias rpi uboot, mbrugger + alias m68k uboot, alisonwang, angelo_ts alias coldfire m68k diff --git a/drivers/cache/Kconfig b/drivers/cache/Kconfig index 24def7ac0f..629039e7a8 100644 --- a/drivers/cache/Kconfig +++ b/drivers/cache/Kconfig @@ -22,4 +22,13 @@ config L2X0_CACHE ARMv7(32-bit) devices. The driver configures the cache settings found in the device tree. +config V5L2_CACHE + bool "Andes V5L2 cache driver" + select CACHE + depends on RISCV_NDS_CACHE + help + Support Andes V5L2 cache controller in AE350 platform. + It will configure tag and data ram timing control from the + device tree and enable L2 cache. + endmenu diff --git a/drivers/cache/Makefile b/drivers/cache/Makefile index 9deb961d91..4a6458c602 100644 --- a/drivers/cache/Makefile +++ b/drivers/cache/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_CACHE) += cache-uclass.o obj-$(CONFIG_SANDBOX) += sandbox_cache.o obj-$(CONFIG_L2X0_CACHE) += cache-l2x0.o +obj-$(CONFIG_V5L2_CACHE) += cache-v5l2.o diff --git a/drivers/cache/cache-uclass.c b/drivers/cache/cache-uclass.c index 97ce0249a4..3b20a10f08 100644 --- a/drivers/cache/cache-uclass.c +++ b/drivers/cache/cache-uclass.c @@ -17,6 +17,26 @@ int cache_get_info(struct udevice *dev, struct cache_info *info) return ops->get_info(dev, info); } +int cache_enable(struct udevice *dev) +{ + struct cache_ops *ops = cache_get_ops(dev); + + if (!ops->enable) + return -ENOSYS; + + return ops->enable(dev); +} + +int cache_disable(struct udevice *dev) +{ + struct cache_ops *ops = cache_get_ops(dev); + + if (!ops->disable) + return -ENOSYS; + + return ops->disable(dev); +} + UCLASS_DRIVER(cache) = { .id = UCLASS_CACHE, .name = "cache", diff --git a/drivers/cache/cache-v5l2.c b/drivers/cache/cache-v5l2.c new file mode 100644 index 0000000000..d367171b36 --- /dev/null +++ b/drivers/cache/cache-v5l2.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 Andes Technology Corporation + * Rick Chen, Andes Technology Corporation <rick@andestech.com> + */ + +#include <common.h> +#include <command.h> +#include <cache.h> +#include <dm.h> +#include <asm/io.h> +#include <dm/ofnode.h> + +struct l2cache { + volatile u64 configure; + volatile u64 control; + volatile u64 hpm0; + volatile u64 hpm1; + volatile u64 hpm2; + volatile u64 hpm3; + volatile u64 error_status; + volatile u64 ecc_error; + volatile u64 cctl_command0; + volatile u64 cctl_access_line0; + volatile u64 cctl_command1; + volatile u64 cctl_access_line1; + volatile u64 cctl_command2; + volatile u64 cctl_access_line2; + volatile u64 cctl_command3; + volatile u64 cctl_access_line4; + volatile u64 cctl_status; +}; + +/* Control Register */ +#define L2_ENABLE 0x1 +/* prefetch */ +#define IPREPETCH_OFF 3 +#define DPREPETCH_OFF 5 +#define IPREPETCH_MSK (3 << IPREPETCH_OFF) +#define DPREPETCH_MSK (3 << DPREPETCH_OFF) +/* tag ram */ +#define TRAMOCTL_OFF 8 +#define TRAMICTL_OFF 10 +#define TRAMOCTL_MSK (3 << TRAMOCTL_OFF) +#define TRAMICTL_MSK BIT(TRAMICTL_OFF) +/* data ram */ +#define DRAMOCTL_OFF 11 +#define DRAMICTL_OFF 13 +#define DRAMOCTL_MSK (3 << DRAMOCTL_OFF) +#define DRAMICTL_MSK BIT(DRAMICTL_OFF) + +/* CCTL Command Register */ +#define CCTL_CMD_REG(base, hart) ((ulong)(base) + 0x40 + (hart) * 0x10) +#define L2_WBINVAL_ALL 0x12 + +/* CCTL Status Register */ +#define CCTL_STATUS_MSK(hart) (0xf << ((hart) * 4)) +#define CCTL_STATUS_IDLE(hart) (0 << ((hart) * 4)) +#define CCTL_STATUS_PROCESS(hart) (1 << ((hart) * 4)) +#define CCTL_STATUS_ILLEGAL(hart) (2 << ((hart) * 4)) + +DECLARE_GLOBAL_DATA_PTR; + +struct v5l2_plat { + struct l2cache *regs; + u32 iprefetch; + u32 dprefetch; + u32 tram_ctl[2]; + u32 dram_ctl[2]; +}; + +static int v5l2_enable(struct udevice *dev) +{ + struct v5l2_plat *plat = dev_get_platdata(dev); + volatile struct l2cache *regs = plat->regs; + + if (regs) + setbits_le32(®s->control, L2_ENABLE); + + return 0; +} + +static int v5l2_disable(struct udevice *dev) +{ + struct v5l2_plat *plat = dev_get_platdata(dev); + volatile struct l2cache *regs = plat->regs; + u8 hart = gd->arch.boot_hart; + void __iomem *cctlcmd = (void __iomem *)CCTL_CMD_REG(regs, hart); + + if ((regs) && (readl(®s->control) & L2_ENABLE)) { + writel(L2_WBINVAL_ALL, cctlcmd); + + while ((readl(®s->cctl_status) & CCTL_STATUS_MSK(hart))) { + if ((readl(®s->cctl_status) & CCTL_STATUS_ILLEGAL(hart))) { + printf("L2 flush illegal! hanging..."); + hang(); + } + } + clrbits_le32(®s->control, L2_ENABLE); + } + + return 0; +} + +static int v5l2_ofdata_to_platdata(struct udevice *dev) +{ + struct v5l2_plat *plat = dev_get_platdata(dev); + struct l2cache *regs; + + regs = (struct l2cache *)dev_read_addr(dev); + plat->regs = regs; + + plat->iprefetch = -EINVAL; + plat->dprefetch = -EINVAL; + plat->tram_ctl[0] = -EINVAL; + plat->dram_ctl[0] = -EINVAL; + + /* Instruction and data fetch prefetch depth */ + dev_read_u32(dev, "andes,inst-prefetch", &plat->iprefetch); + dev_read_u32(dev, "andes,data-prefetch", &plat->dprefetch); + + /* Set tag RAM and data RAM setup and output cycle */ + dev_read_u32_array(dev, "andes,tag-ram-ctl", plat->tram_ctl, 2); + dev_read_u32_array(dev, "andes,data-ram-ctl", plat->dram_ctl, 2); + + return 0; +} + +static int v5l2_probe(struct udevice *dev) +{ + struct v5l2_plat *plat = dev_get_platdata(dev); + struct l2cache *regs = plat->regs; + u32 ctl_val; + + ctl_val = readl(®s->control); + + if (!(ctl_val & L2_ENABLE)) + ctl_val |= L2_ENABLE; + + if (plat->iprefetch != -EINVAL) { + ctl_val &= ~(IPREPETCH_MSK); + ctl_val |= (plat->iprefetch << IPREPETCH_OFF); + } + + if (plat->dprefetch != -EINVAL) { + ctl_val &= ~(DPREPETCH_MSK); + ctl_val |= (plat->dprefetch << DPREPETCH_OFF); + } + + if (plat->tram_ctl[0] != -EINVAL) { + ctl_val &= ~(TRAMOCTL_MSK | TRAMICTL_MSK); + ctl_val |= plat->tram_ctl[0] << TRAMOCTL_OFF; + ctl_val |= plat->tram_ctl[1] << TRAMICTL_OFF; + } + + if (plat->dram_ctl[0] != -EINVAL) { + ctl_val &= ~(DRAMOCTL_MSK | DRAMICTL_MSK); + ctl_val |= plat->dram_ctl[0] << DRAMOCTL_OFF; + ctl_val |= plat->dram_ctl[1] << DRAMICTL_OFF; + } + + writel(ctl_val, ®s->control); + + return 0; +} + +static const struct udevice_id v5l2_cache_ids[] = { + { .compatible = "v5l2cache" }, + {} +}; + +static const struct cache_ops v5l2_cache_ops = { + .enable = v5l2_enable, + .disable = v5l2_disable, +}; + +U_BOOT_DRIVER(v5l2_cache) = { + .name = "v5l2_cache", + .id = UCLASS_CACHE, + .of_match = v5l2_cache_ids, + .ofdata_to_platdata = v5l2_ofdata_to_platdata, + .probe = v5l2_probe, + .platdata_auto_alloc_size = sizeof(struct v5l2_plat), + .ops = &v5l2_cache_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/cache/sandbox_cache.c b/drivers/cache/sandbox_cache.c index 14cc6b0c0a..9050c4cf34 100644 --- a/drivers/cache/sandbox_cache.c +++ b/drivers/cache/sandbox_cache.c @@ -17,8 +17,21 @@ static int sandbox_get_info(struct udevice *dev, struct cache_info *info) return 0; } +static int sandbox_enable(struct udevice *dev) +{ + return 0; +} + +static int snadbox_disable(struct udevice *dev) +{ + return 0; +} + + static const struct cache_ops sandbox_cache_ops = { .get_info = sandbox_get_info, + .enable = sandbox_enable, + .disable = snadbox_disable, }; static const struct udevice_id sandbox_cache_ids[] = { diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c index f77c126499..28ad0aa30f 100644 --- a/drivers/cpu/riscv_cpu.c +++ b/drivers/cpu/riscv_cpu.c @@ -46,6 +46,10 @@ static int riscv_cpu_get_count(struct udevice *dev) ofnode_for_each_subnode(node, dev_ofnode(dev->parent)) { const char *device_type; + /* skip if hart is marked as not available in the device tree */ + if (!ofnode_is_available(node)) + continue; + device_type = ofnode_read_string(node, "device_type"); if (!device_type) continue; diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c index 20f6dc4ecb..786b5a2226 100644 --- a/drivers/i2c/mxc_i2c.c +++ b/drivers/i2c/mxc_i2c.c @@ -149,7 +149,12 @@ static uint8_t i2c_imx_get_clk(struct mxc_i2c_bus *i2c_bus, unsigned int rate) #endif /* Divider value calculation */ +#if CONFIG_IS_ENABLED(CLK) + i2c_clk_rate = clk_get_rate(&i2c_bus->per_clk); +#else i2c_clk_rate = mxc_get_clock(MXC_I2C_CLK); +#endif + div = (i2c_clk_rate + rate - 1) / rate; if (div < i2c_clk_div[0][0]) clk_div = 0; @@ -891,9 +896,22 @@ static int mxc_i2c_probe(struct udevice *bus) i2c_bus->bus = bus; /* Enable clk */ +#if CONFIG_IS_ENABLED(CLK) + ret = clk_get_by_index(bus, 0, &i2c_bus->per_clk); + if (ret) { + printf("Failed to get i2c clk\n"); + return ret; + } + ret = clk_enable(&i2c_bus->per_clk); + if (ret) { + printf("Failed to enable i2c clk\n"); + return ret; + } +#else ret = enable_i2c_clk(1, bus->seq); if (ret < 0) return ret; +#endif /* * See Documentation/devicetree/bindings/i2c/i2c-imx.txt diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index bf3304c4dc..bc9ee95fd5 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -178,12 +178,13 @@ static int bcm2835_sdhci_probe(struct udevice *dev) fdt_addr_t base; int emmc_freq; int ret; + int clock_id = (int)dev_get_driver_data(dev); base = devfdt_get_addr(dev); if (base == FDT_ADDR_T_NONE) return -EINVAL; - ret = bcm2835_get_mmc_clock(BCM2835_MBOX_CLOCK_ID_EMMC); + ret = bcm2835_get_mmc_clock(clock_id); if (ret < 0) { debug("%s: Failed to set MMC clock (err=%d)\n", __func__, ret); return ret; @@ -230,7 +231,14 @@ static int bcm2835_sdhci_probe(struct udevice *dev) } static const struct udevice_id bcm2835_sdhci_match[] = { - { .compatible = "brcm,bcm2835-sdhci" }, + { + .compatible = "brcm,bcm2835-sdhci", + .data = BCM2835_MBOX_CLOCK_ID_EMMC + }, + { + .compatible = "brcm,bcm2711-emmc2", + .data = BCM2835_MBOX_CLOCK_ID_EMMC2 + }, { /* sentinel */ } }; diff --git a/drivers/mmc/bcm2835_sdhost.c b/drivers/mmc/bcm2835_sdhost.c index 1ce019af57..7f70acaf39 100644 --- a/drivers/mmc/bcm2835_sdhost.c +++ b/drivers/mmc/bcm2835_sdhost.c @@ -234,7 +234,7 @@ static void bcm2835_reset_internal(struct bcm2835_host *host) static int bcm2835_wait_transfer_complete(struct bcm2835_host *host) { - int timediff = 0; + ulong tstart_ms = get_timer(0); while (1) { u32 edm, fsm; @@ -254,11 +254,13 @@ static int bcm2835_wait_transfer_complete(struct bcm2835_host *host) break; } - /* Error out after 100000 register reads (~1s) */ - if (timediff++ == 100000) { + /* Error out after ~1s */ + ulong tlapse_ms = get_timer(tstart_ms); + if ( tlapse_ms > 1000 /* ms */ ) { + dev_err(host->dev, - "wait_transfer_complete - still waiting after %d retries\n", - timediff); + "wait_transfer_complete - still waiting after %lu ms\n", + tlapse_ms); bcm2835_dumpregs(host); return -ETIMEDOUT; } diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 084e095229..2ce3092db0 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1,5 +1,6 @@ source "drivers/net/phy/Kconfig" source "drivers/net/pfe_eth/Kconfig" +source "drivers/net/fsl-mc/Kconfig" config DM_ETH bool "Enable Driver Model for Ethernet drivers" @@ -603,4 +604,14 @@ config MDIO_MUX_I2CREG an I2C chip. The board it was developed for uses a mux controlled by on-board FPGA which in turn is accessed as a chip over I2C. +config MVMDIO + bool "Marvell MDIO interface support" + depends on DM_MDIO + help + This driver supports the MDIO interface found in the network + interface units of the Marvell EBU SoCs (Kirkwood, Orion5x, + Dove, Armada 370, Armada XP, Armada 37xx and Armada7K/8K/8KP). + + This driver is used by the MVPP2 and MVNETA drivers. + endif # NETDEVICES diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 71c0889355..30991834ec 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_MDIO_MUX_SANDBOX) += mdio_mux_sandbox.o obj-$(CONFIG_MPC8XX_FEC) += mpc8xx_fec.o obj-$(CONFIG_MT7628_ETH) += mt7628-eth.o obj-$(CONFIG_MVGBE) += mvgbe.o +obj-$(CONFIG_MVMDIO) += mvmdio.o obj-$(CONFIG_MVNETA) += mvneta.o obj-$(CONFIG_MVPP2) += mvpp2.o obj-$(CONFIG_NATSEMI) += natsemi.o diff --git a/drivers/net/designware.c b/drivers/net/designware.c index c4fe40b19a..145eeac45f 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -847,7 +847,6 @@ int designware_eth_ofdata_to_platdata(struct udevice *dev) static const struct udevice_id designware_eth_ids[] = { { .compatible = "allwinner,sun7i-a20-gmac" }, - { .compatible = "altr,socfpga-stmmac" }, { .compatible = "amlogic,meson6-dwmac" }, { .compatible = "amlogic,meson-gx-dwmac" }, { .compatible = "amlogic,meson-gxbb-dwmac" }, diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 07b36675a7..455709338c 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -621,7 +621,7 @@ err: return ret; } -void eqos_stop_clks_tegra186(struct udevice *dev) +static void eqos_stop_clks_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -636,7 +636,7 @@ void eqos_stop_clks_tegra186(struct udevice *dev) debug("%s: OK\n", __func__); } -void eqos_stop_clks_stm32(struct udevice *dev) +static void eqos_stop_clks_stm32(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -1290,7 +1290,7 @@ err: return ret; } -void eqos_stop(struct udevice *dev) +static void eqos_stop(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); int i; @@ -1344,7 +1344,7 @@ void eqos_stop(struct udevice *dev) debug("%s: OK\n", __func__); } -int eqos_send(struct udevice *dev, void *packet, int length) +static int eqos_send(struct udevice *dev, void *packet, int length) { struct eqos_priv *eqos = dev_get_priv(dev); struct eqos_desc *tx_desc; @@ -1385,7 +1385,7 @@ int eqos_send(struct udevice *dev, void *packet, int length) return -ETIMEDOUT; } -int eqos_recv(struct udevice *dev, int flags, uchar **packetp) +static int eqos_recv(struct udevice *dev, int flags, uchar **packetp) { struct eqos_priv *eqos = dev_get_priv(dev); struct eqos_desc *rx_desc; @@ -1409,7 +1409,7 @@ int eqos_recv(struct udevice *dev, int flags, uchar **packetp) return length; } -int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) +static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) { struct eqos_priv *eqos = dev_get_priv(dev); uchar *packet_expected; @@ -1591,8 +1591,8 @@ err_free_reset_eqos: } /* board-specific Ethernet Interface initializations. */ -__weak int board_interface_eth_init(int interface_type, bool eth_clk_sel_reg, - bool eth_ref_clk_sel_reg) +__weak int board_interface_eth_init(struct udevice *dev, + phy_interface_t interface_type) { return 0; } @@ -1602,8 +1602,6 @@ static int eqos_probe_resources_stm32(struct udevice *dev) struct eqos_priv *eqos = dev_get_priv(dev); int ret; phy_interface_t interface; - bool eth_clk_sel_reg = false; - bool eth_ref_clk_sel_reg = false; debug("%s(dev=%p):\n", __func__, dev); @@ -1614,15 +1612,7 @@ static int eqos_probe_resources_stm32(struct udevice *dev) return -EINVAL; } - /* Gigabit Ethernet 125MHz clock selection. */ - eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel"); - - /* Ethernet 50Mhz RMII clock selection */ - eth_ref_clk_sel_reg = - dev_read_bool(dev, "st,eth_ref_clk_sel"); - - ret = board_interface_eth_init(interface, eth_clk_sel_reg, - eth_ref_clk_sel_reg); + ret = board_interface_eth_init(dev, interface); if (ret) return -EINVAL; diff --git a/drivers/net/fsl-mc/Kconfig b/drivers/net/fsl-mc/Kconfig new file mode 100644 index 0000000000..25a2cb8ffa --- /dev/null +++ b/drivers/net/fsl-mc/Kconfig @@ -0,0 +1,25 @@ +# +# NXP Management Complex +# + +menuconfig FSL_MC_ENET + bool "NXP Management Complex" + depends on ARCH_LS2080A || ARCH_LS1088A || ARCH_LX2160A + default y + select RESV_RAM + help + Enable Management Complex (MC) network + This is NXP Management Complex menuconfig + that contains all MC related config options + +if FSL_MC_ENET + +config SYS_MC_RSV_MEM_ALIGN + hex "Management Complex reserved memory alignment" + depends on RESV_RAM + default 0x20000000 if ARCH_LS2080A || ARCH_LS1088A || ARCH_LX2160A + help + Reserved memory needs to be aligned for MC to use. Default value + is 512MB. + +endif # FSL_MC_ENET diff --git a/drivers/net/fsl_enetc_mdio.c b/drivers/net/fsl_enetc_mdio.c index 60d21537b8..b4463a58a5 100644 --- a/drivers/net/fsl_enetc_mdio.c +++ b/drivers/net/fsl_enetc_mdio.c @@ -144,6 +144,7 @@ U_BOOT_DRIVER(enetc_mdio) = { static struct pci_device_id enetc_mdio_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_ENETC_MDIO) }, + { } }; U_BOOT_PCI_DEVICE(enetc_mdio, enetc_mdio_ids); diff --git a/drivers/net/macb.c b/drivers/net/macb.c index c99cf663a4..377188e361 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -296,13 +296,15 @@ static inline void macb_flush_ring_desc(struct macb_device *macb, bool rx) static inline void macb_flush_rx_buffer(struct macb_device *macb) { flush_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma + - ALIGN(MACB_RX_BUFFER_SIZE, PKTALIGN)); + ALIGN(macb->rx_buffer_size * MACB_RX_RING_SIZE, + PKTALIGN)); } static inline void macb_invalidate_rx_buffer(struct macb_device *macb) { invalidate_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma + - ALIGN(MACB_RX_BUFFER_SIZE, PKTALIGN)); + ALIGN(macb->rx_buffer_size * MACB_RX_RING_SIZE, + PKTALIGN)); } #if defined(CONFIG_CMD_NET) @@ -643,7 +645,7 @@ static int macb_phy_init(struct macb_device *macb, const char *name) /* First check for GMAC and that it is GiB capable */ if (gem_is_gigabit_capable(macb)) { - lpa = macb_mdio_read(macb, MII_LPA); + lpa = macb_mdio_read(macb, MII_STAT1000); if (lpa & (LPA_1000FULL | LPA_1000HALF | LPA_1000XFULL | LPA_1000XHALF)) { diff --git a/drivers/net/mdio_mux_i2creg.c b/drivers/net/mdio_mux_i2creg.c new file mode 100644 index 0000000000..3e82898f46 --- /dev/null +++ b/drivers/net/mdio_mux_i2creg.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2019 + * Alex Marginean, NXP + */ + +#include <dm.h> +#include <errno.h> +#include <miiphy.h> +#include <i2c.h> + +/* + * This driver is used for MDIO muxes driven by writing to a register of an I2C + * chip. The board it was developed for uses a mux controlled by on-board FPGA + * which in turn is accessed as a chip over I2C. + */ + +struct mdio_mux_i2creg_priv { + struct udevice *chip; + int reg; + int mask; +}; + +static int mdio_mux_i2creg_select(struct udevice *mux, int cur, int sel) +{ + struct mdio_mux_i2creg_priv *priv = dev_get_priv(mux); + u8 val, val_old; + + /* if last selection didn't change we're good to go */ + if (cur == sel) + return 0; + + val_old = dm_i2c_reg_read(priv->chip, priv->reg); + val = (val_old & ~priv->mask) | (sel & priv->mask); + debug("%s: chip %s, reg %x, val %x => %x\n", __func__, priv->chip->name, + priv->reg, val_old, val); + dm_i2c_reg_write(priv->chip, priv->reg, val); + + return 0; +} + +static const struct mdio_mux_ops mdio_mux_i2creg_ops = { + .select = mdio_mux_i2creg_select, +}; + +static int mdio_mux_i2creg_probe(struct udevice *dev) +{ + struct mdio_mux_i2creg_priv *priv = dev_get_priv(dev); + ofnode chip_node, bus_node; + struct udevice *i2c_bus; + u32 reg_mask[2]; + u32 chip_addr; + int err; + + /* read the register addr/mask pair */ + err = dev_read_u32_array(dev, "mux-reg-masks", reg_mask, 2); + if (err) { + debug("%s: error reading mux-reg-masks property\n", __func__); + return err; + } + + /* parent should be an I2C chip, grandparent should be an I2C bus */ + chip_node = ofnode_get_parent(dev->node); + bus_node = ofnode_get_parent(chip_node); + + err = uclass_get_device_by_ofnode(UCLASS_I2C, bus_node, &i2c_bus); + if (err) { + debug("%s: can't find I2C bus for node %s\n", __func__, + ofnode_get_name(bus_node)); + return err; + } + + err = ofnode_read_u32(chip_node, "reg", &chip_addr); + if (err) { + debug("%s: can't read chip address in %s\n", __func__, + ofnode_get_name(chip_node)); + return err; + } + + err = i2c_get_chip(i2c_bus, (uint)chip_addr, 1, &priv->chip); + if (err) { + debug("%s: can't find i2c chip device for addr %x\n", __func__, + chip_addr); + return err; + } + + priv->reg = (int)reg_mask[0]; + priv->mask = (int)reg_mask[1]; + + debug("%s: chip %s, reg %x, mask %x\n", __func__, priv->chip->name, + priv->reg, priv->mask); + + return 0; +} + +static const struct udevice_id mdio_mux_i2creg_ids[] = { + { .compatible = "mdio-mux-i2creg" }, + { } +}; + +U_BOOT_DRIVER(mdio_mux_i2creg) = { + .name = "mdio_mux_i2creg", + .id = UCLASS_MDIO_MUX, + .of_match = mdio_mux_i2creg_ids, + .probe = mdio_mux_i2creg_probe, + .ops = &mdio_mux_i2creg_ops, + .priv_auto_alloc_size = sizeof(struct mdio_mux_i2creg_priv), +}; diff --git a/drivers/net/mdio_sandbox.c b/drivers/net/mdio_sandbox.c index df053f5381..b731f60a98 100644 --- a/drivers/net/mdio_sandbox.c +++ b/drivers/net/mdio_sandbox.c @@ -27,7 +27,7 @@ static int mdio_sandbox_read(struct udevice *dev, int addr, int devad, int reg) return -ENODEV; if (devad != MDIO_DEVAD_NONE) return -ENODEV; - if (reg < 0 || reg > SANDBOX_PHY_REG_CNT) + if (reg < 0 || reg >= SANDBOX_PHY_REG_CNT) return -ENODEV; return priv->reg[reg]; @@ -45,7 +45,7 @@ static int mdio_sandbox_write(struct udevice *dev, int addr, int devad, int reg, return -ENODEV; if (devad != MDIO_DEVAD_NONE) return -ENODEV; - if (reg < 0 || reg > SANDBOX_PHY_REG_CNT) + if (reg < 0 || reg >= SANDBOX_PHY_REG_CNT) return -ENODEV; priv->reg[reg] = val; diff --git a/drivers/net/mvmdio.c b/drivers/net/mvmdio.c new file mode 100644 index 0000000000..ec6805e536 --- /dev/null +++ b/drivers/net/mvmdio.c @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Marvell International Ltd. + * Author: Ken Ma<make@marvell.com> + */ + +#include <common.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <miiphy.h> +#include <phy.h> +#include <asm/io.h> +#include <wait_bit.h> + +#define MVMDIO_SMI_DATA_SHIFT 0 +#define MVMDIO_SMI_PHY_ADDR_SHIFT 16 +#define MVMDIO_SMI_PHY_REG_SHIFT 21 +#define MVMDIO_SMI_READ_OPERATION BIT(26) +#define MVMDIO_SMI_WRITE_OPERATION 0 +#define MVMDIO_SMI_READ_VALID BIT(27) +#define MVMDIO_SMI_BUSY BIT(28) + +#define MVMDIO_XSMI_MGNT_REG 0x0 +#define MVMDIO_XSMI_PHYADDR_SHIFT 16 +#define MVMDIO_XSMI_DEVADDR_SHIFT 21 +#define MVMDIO_XSMI_WRITE_OPERATION (0x5 << 26) +#define MVMDIO_XSMI_READ_OPERATION (0x7 << 26) +#define MVMDIO_XSMI_READ_VALID BIT(29) +#define MVMDIO_XSMI_BUSY BIT(30) +#define MVMDIO_XSMI_ADDR_REG 0x8 + +enum mvmdio_bus_type { + BUS_TYPE_SMI, + BUS_TYPE_XSMI +}; + +struct mvmdio_priv { + void *mdio_base; + enum mvmdio_bus_type type; +}; + +static int mvmdio_smi_read(struct udevice *dev, int addr, + int devad, int reg) +{ + struct mvmdio_priv *priv = dev_get_priv(dev); + u32 val; + int ret; + + if (devad != MDIO_DEVAD_NONE) + return -EOPNOTSUPP; + + ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY, + false, CONFIG_SYS_HZ, false); + if (ret < 0) + return ret; + + writel(((addr << MVMDIO_SMI_PHY_ADDR_SHIFT) | + (reg << MVMDIO_SMI_PHY_REG_SHIFT) | + MVMDIO_SMI_READ_OPERATION), + priv->mdio_base); + + ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY, + false, CONFIG_SYS_HZ, false); + if (ret < 0) + return ret; + + val = readl(priv->mdio_base); + if (!(val & MVMDIO_SMI_READ_VALID)) { + pr_err("SMI bus read not valid\n"); + return -ENODEV; + } + + return val & GENMASK(15, 0); +} + +static int mvmdio_smi_write(struct udevice *dev, int addr, int devad, + int reg, u16 value) +{ + struct mvmdio_priv *priv = dev_get_priv(dev); + int ret; + + if (devad != MDIO_DEVAD_NONE) + return -EOPNOTSUPP; + + ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY, + false, CONFIG_SYS_HZ, false); + if (ret < 0) + return ret; + + writel(((addr << MVMDIO_SMI_PHY_ADDR_SHIFT) | + (reg << MVMDIO_SMI_PHY_REG_SHIFT) | + MVMDIO_SMI_WRITE_OPERATION | + (value << MVMDIO_SMI_DATA_SHIFT)), + priv->mdio_base); + + return 0; +} + +static int mvmdio_xsmi_read(struct udevice *dev, int addr, + int devad, int reg) +{ + struct mvmdio_priv *priv = dev_get_priv(dev); + int ret; + + if (devad == MDIO_DEVAD_NONE) + return -EOPNOTSUPP; + + ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY, + false, CONFIG_SYS_HZ, false); + if (ret < 0) + return ret; + + writel(reg & GENMASK(15, 0), priv->mdio_base + MVMDIO_XSMI_ADDR_REG); + writel(((addr << MVMDIO_XSMI_PHYADDR_SHIFT) | + (devad << MVMDIO_XSMI_DEVADDR_SHIFT) | + MVMDIO_XSMI_READ_OPERATION), + priv->mdio_base + MVMDIO_XSMI_MGNT_REG); + + ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY, + false, CONFIG_SYS_HZ, false); + if (ret < 0) + return ret; + + if (!(readl(priv->mdio_base + MVMDIO_XSMI_MGNT_REG) & + MVMDIO_XSMI_READ_VALID)) { + pr_err("XSMI bus read not valid\n"); + return -ENODEV; + } + + return readl(priv->mdio_base + MVMDIO_XSMI_MGNT_REG) & GENMASK(15, 0); +} + +static int mvmdio_xsmi_write(struct udevice *dev, int addr, int devad, + int reg, u16 value) +{ + struct mvmdio_priv *priv = dev_get_priv(dev); + int ret; + + if (devad == MDIO_DEVAD_NONE) + return -EOPNOTSUPP; + + ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY, + false, CONFIG_SYS_HZ, false); + if (ret < 0) + return ret; + + writel(reg & GENMASK(15, 0), priv->mdio_base + MVMDIO_XSMI_ADDR_REG); + writel(((addr << MVMDIO_XSMI_PHYADDR_SHIFT) | + (devad << MVMDIO_XSMI_DEVADDR_SHIFT) | + MVMDIO_XSMI_WRITE_OPERATION | value), + priv->mdio_base + MVMDIO_XSMI_MGNT_REG); + + return 0; +} + +static int mvmdio_read(struct udevice *dev, int addr, int devad, int reg) +{ + struct mvmdio_priv *priv = dev_get_priv(dev); + int err = -ENOTSUPP; + + switch (priv->type) { + case BUS_TYPE_SMI: + err = mvmdio_smi_read(dev, addr, devad, reg); + break; + case BUS_TYPE_XSMI: + err = mvmdio_xsmi_read(dev, addr, devad, reg); + break; + } + + return err; +} + +static int mvmdio_write(struct udevice *dev, int addr, int devad, int reg, + u16 value) +{ + struct mvmdio_priv *priv = dev_get_priv(dev); + int err = -ENOTSUPP; + + switch (priv->type) { + case BUS_TYPE_SMI: + err = mvmdio_smi_write(dev, addr, devad, reg, value); + break; + case BUS_TYPE_XSMI: + err = mvmdio_xsmi_write(dev, addr, devad, reg, value); + break; + } + + return err; +} + +/* + * Name the device, we use the device tree node name. + * This can be overwritten by MDIO class code if device-name property is + * present. + */ +static int mvmdio_bind(struct udevice *dev) +{ + if (ofnode_valid(dev->node)) + device_set_name(dev, ofnode_get_name(dev->node)); + + return 0; +} + +/* Get device base address and type, either C22 SMII or C45 XSMI */ +static int mvmdio_probe(struct udevice *dev) +{ + struct mvmdio_priv *priv = dev_get_priv(dev); + + priv->mdio_base = (void *)dev_read_addr(dev); + priv->type = (enum mvmdio_bus_type)dev_get_driver_data(dev); + + return 0; +} + +static const struct mdio_ops mvmdio_ops = { + .read = mvmdio_read, + .write = mvmdio_write, +}; + +static const struct udevice_id mvmdio_ids[] = { + { .compatible = "marvell,orion-mdio", .data = BUS_TYPE_SMI }, + { .compatible = "marvell,xmdio", .data = BUS_TYPE_XSMI }, + { } +}; + +U_BOOT_DRIVER(mvmdio) = { + .name = "mvmdio", + .id = UCLASS_MDIO, + .of_match = mvmdio_ids, + .bind = mvmdio_bind, + .probe = mvmdio_probe, + .ops = &mvmdio_ops, + .priv_auto_alloc_size = sizeof(struct mvmdio_priv), +}; + diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index bcc6fe92a9..bd89725e77 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -5321,6 +5321,13 @@ static void mvpp2_stop(struct udevice *dev) mvpp2_cleanup_txqs(port); } +static int mvpp2_write_hwaddr(struct udevice *dev) +{ + struct mvpp2_port *port = dev_get_priv(dev); + + return mvpp2_prs_update_mac_da(port, port->dev_addr); +} + static int mvpp22_smi_phy_addr_cfg(struct mvpp2_port *port) { writel(port->phyaddr, port->priv->iface_base + @@ -5525,6 +5532,7 @@ static const struct eth_ops mvpp2_ops = { .send = mvpp2_send, .recv = mvpp2_recv, .stop = mvpp2_stop, + .write_hwaddr = mvpp2_write_hwaddr }; static struct driver mvpp2_driver = { diff --git a/drivers/net/pfe_eth/pfe_mdio.c b/drivers/net/pfe_eth/pfe_mdio.c index 2dde9e7ac8..62309670fa 100644 --- a/drivers/net/pfe_eth/pfe_mdio.c +++ b/drivers/net/pfe_eth/pfe_mdio.c @@ -110,7 +110,6 @@ static int pfe_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr, 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) << @@ -150,7 +149,7 @@ static int pfe_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr, debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phy_addr, reg_addr, data); - return val; + return 0; } static void pfe_configure_serdes(struct pfe_eth_dev *priv) diff --git a/include/cache.h b/include/cache.h index c6334ca27f..32f59fd8f7 100644 --- a/include/cache.h +++ b/include/cache.h @@ -22,6 +22,22 @@ struct cache_ops { * @return 0 if OK, -ve on error */ int (*get_info)(struct udevice *dev, struct cache_info *info); + + /** + * enable() - Enable cache + * + * @dev: Device to check (UCLASS_CACHE) + * @return 0 if OK, -ve on error + */ + int (*enable)(struct udevice *dev); + + /** + * disable() - Flush and disable cache + * + * @dev: Device to check (UCLASS_CACHE) + * @return 0 if OK, -ve on error + */ + int (*disable)(struct udevice *dev); }; #define cache_get_ops(dev) ((struct cache_ops *)(dev)->driver->ops) @@ -35,4 +51,19 @@ struct cache_ops { */ int cache_get_info(struct udevice *dev, struct cache_info *info); +/** + * cache_enable() - Enable cache + * + * @dev: Device to check (UCLASS_CACHE) + * @return 0 if OK, -ve on error + */ +int cache_enable(struct udevice *dev); + +/** + * cache_disable() - Flush and disable cache + * + * @dev: Device to check (UCLASS_CACHE) + * @return 0 if OK, -ve on error + */ +int cache_disable(struct udevice *dev); #endif diff --git a/include/configs/exynos5-common.h b/include/configs/exynos5-common.h index 397bbf6d9d..e0a4d76d53 100644 --- a/include/configs/exynos5-common.h +++ b/include/configs/exynos5-common.h @@ -128,9 +128,9 @@ #define EXYNOS_IRAM_SECONDARY_BASE 0x02020018 #define BOOT_TARGET_DEVICES(func) \ + func(MMC, mmc, 2) \ func(MMC, mmc, 1) \ func(MMC, mmc, 0) \ - func(MMC, mmc, 2) \ func(PXE, pxe, na) \ func(DHCP, dhcp, na) diff --git a/include/configs/rpi.h b/include/configs/rpi.h index 8473cecd94..77d2d5458a 100644 --- a/include/configs/rpi.h +++ b/include/configs/rpi.h @@ -55,6 +55,10 @@ #define CONFIG_SYS_MEMTEST_END 0x00200000 #define CONFIG_LOADADDR 0x00200000 +#ifdef CONFIG_ARM64 +#define CONFIG_SYS_BOOTM_LEN SZ_64M +#endif + /* Devices */ /* GPIO */ #define CONFIG_BCM2835_GPIO diff --git a/include/configs/sifive-fu540.h b/include/configs/sifive-fu540.h index 858b7a7da1..736ceb1f48 100644 --- a/include/configs/sifive-fu540.h +++ b/include/configs/sifive-fu540.h @@ -26,6 +26,7 @@ #define CONFIG_ENV_SIZE SZ_128K #define BOOT_TARGET_DEVICES(func) \ + func(MMC, mmc, 0) \ func(DHCP, dhcp, na) #include <config_distro_bootcmd.h> diff --git a/include/efi_api.h b/include/efi_api.h index 43778197af..cb895f31e5 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -483,7 +483,7 @@ struct efi_device_path_cdrom_path { struct efi_device_path dp; u32 boot_entry; u64 partition_start; - u64 partition_end; + u64 partition_size; } __packed; struct efi_device_path_file_path { @@ -1281,6 +1281,8 @@ struct efi_simple_network { struct efi_mac_address *dest_addr, u16 *protocol); struct efi_event *wait_for_packet; struct efi_simple_network_mode *mode; + /* private fields */ + u32 int_status; }; #define EFI_PXE_BASE_CODE_PROTOCOL_GUID \ diff --git a/include/efi_loader.h b/include/efi_loader.h index 5298ea7997..00eba8afa4 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -478,6 +478,10 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size, /* Adds a range into the EFI memory map */ efi_status_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, bool overlap_only_ram); +/* Adds a conventional range into the EFI memory map */ +efi_status_t efi_add_conventional_memory_map(u64 ram_start, u64 ram_end, + u64 ram_top); + /* Called by board init to initialize the EFI drivers */ efi_status_t efi_driver_init(void); /* Called by board init to initialize the EFI memory map */ diff --git a/include/env_callback.h b/include/env_callback.h index 982c07854d..74da20eec3 100644 --- a/include/env_callback.h +++ b/include/env_callback.h @@ -42,7 +42,7 @@ #define DNS_CALLBACK #endif -#ifdef CONFIG_CMD_NET +#ifdef CONFIG_NET #define NET_CALLBACKS \ "bootfile:bootfile," \ "ipaddr:ipaddr," \ diff --git a/include/env_flags.h b/include/env_flags.h index e5380f2948..725841a891 100644 --- a/include/env_flags.h +++ b/include/env_flags.h @@ -36,7 +36,7 @@ enum env_flags_varaccess { #define CONFIG_ENV_FLAGS_LIST_STATIC "" #endif -#ifdef CONFIG_CMD_NET +#ifdef CONFIG_NET #ifdef CONFIG_REGEX #define ETHADDR_WILDCARD "\\d*" #else diff --git a/include/net.h b/include/net.h index a54d5eeac5..75a16e4c8f 100644 --- a/include/net.h +++ b/include/net.h @@ -816,7 +816,7 @@ static inline int is_valid_ethaddr(const u8 *addr) static inline void net_random_ethaddr(uchar *addr) { int i; - unsigned int seed = get_timer(0); + unsigned int seed = get_ticks(); for (i = 0; i < 6; i++) addr[i] = rand_r(&seed); diff --git a/include/net/pcap.h b/include/net/pcap.h new file mode 100644 index 0000000000..512ba982f1 --- /dev/null +++ b/include/net/pcap.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2019 + * Ramon Fried <rfried.dev@gmail.com> + */ + +/** + * pcap_init() - Initialize PCAP memory buffer + * + * @paddr physicaly memory address to store buffer + * @size maximum size of capture file in memory + * + * @return 0 on success, -ERROR on error + */ +int pcap_init(phys_addr_t paddr, unsigned long size); + +/** + * pcap_start_stop() - start / stop pcap capture + * + * @start if true, start capture if false stop capture + * + * @return 0 on success, -ERROR on error + */ +int pcap_start_stop(bool start); + +/** + * pcap_clear() - clear pcap capture buffer and statistics + * + * @return 0 on success, -ERROR on error + */ +int pcap_clear(void); + +/** + * pcap_print_status() - print status of pcap capture + * + * @return 0 on success, -ERROR on error + */ +int pcap_print_status(void); + +/** + * pcap_active() - check if pcap is enabled + * + * @return TRUE if active, FALSE if not. + */ +bool pcap_active(void); + +/** + * pcap_post() - Post a packet to PCAP file + * + * @packet: packet to post + * @len: packet length in bytes + * @outgoing packet direction (outgoing/incoming) + * @return 0 on success, -ERROR on error + */ +int pcap_post(const void *packet, size_t len, bool outgoing); diff --git a/include/netdev.h b/include/netdev.h index a40c4adaad..68a3fceab6 100644 --- a/include/netdev.h +++ b/include/netdev.h @@ -10,6 +10,7 @@ #ifndef _NETDEV_H_ #define _NETDEV_H_ +#include <phy_interface.h> /* * Board and CPU-specific initialization functions @@ -21,6 +22,8 @@ */ int board_eth_init(bd_t *bis); +int board_interface_eth_init(struct udevice *dev, + phy_interface_t interface_type); int cpu_eth_init(bd_t *bis); /* Driver initialization prototypes */ diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index d4765afb98..a55e4b33ec 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -156,13 +156,14 @@ static efi_status_t EFIAPI efi_cout_output_string( * Update the cursor position. * * The UEFI spec provides advance rules for U+0000, U+0008, U+000A, - * and U000D. All other characters, including control characters - * U+0007 (BEL) and U+0009 (TAB), have to increase the column by one. + * and U000D. All other control characters are ignored. Any non-control + * character increase the column by one. */ for (p = string; *p; ++p) { switch (*p) { case '\b': /* U+0008, backspace */ - con->cursor_column = max(0, con->cursor_column - 1); + if (con->cursor_column) + con->cursor_column--; break; case '\n': /* U+000A, newline */ con->cursor_column = 0; @@ -178,14 +179,21 @@ static efi_status_t EFIAPI efi_cout_output_string( */ break; default: - con->cursor_column++; + /* Exclude control codes */ + if (*p > 0x1f) + con->cursor_column++; break; } if (con->cursor_column >= mode->columns) { con->cursor_column = 0; con->cursor_row++; } - con->cursor_row = min(con->cursor_row, (s32)mode->rows - 1); + /* + * When we exceed the row count the terminal will scroll up one + * line. We have to adjust the cursor position. + */ + if (con->cursor_row >= mode->rows && con->cursor_row) + con->cursor_row--; } out: @@ -211,9 +219,9 @@ static bool cout_mode_matches(struct cout_mode *mode, int rows, int cols) /** * query_console_serial() - query console size * - * @rows pointer to return number of rows - * @columns pointer to return number of columns - * Returns 0 on success + * @rows: pointer to return number of rows + * @cols: pointer to return number of columns + * Returns: 0 on success */ static int query_console_serial(int *rows, int *cols) { @@ -371,6 +379,10 @@ static efi_status_t EFIAPI efi_cout_set_mode( if (mode_number >= efi_con_mode.max_mode) return EFI_EXIT(EFI_UNSUPPORTED); + + if (!efi_cout_modes[mode_number].present) + return EFI_EXIT(EFI_UNSUPPORTED); + efi_con_mode.mode = mode_number; EFI_CALL(efi_cout_clear_screen(this)); @@ -452,7 +464,7 @@ struct efi_simple_text_output_protocol efi_con_out = { * struct efi_cin_notify_function - registered console input notify function * * @link: link to list - * @data: key to notify + * @key: key to notify * @function: function to call */ struct efi_cin_notify_function { @@ -470,6 +482,7 @@ static LIST_HEAD(cin_notify_functions); * set_shift_mask() - set shift mask * * @mod: Xterm shift mask + * @key_state: receives the state of the shift, alt, control, and logo keys */ void set_shift_mask(int mod, struct efi_key_state *key_state) { @@ -492,7 +505,7 @@ void set_shift_mask(int mod, struct efi_key_state *key_state) * * This gets called when we have already parsed CSI. * - * @modifiers: bit mask (shift, alt, ctrl) + * @key_state: receives the state of the shift, alt, control, and logo keys * @return: the unmodified code */ static int analyze_modifiers(struct efi_key_state *key_state) diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index eeeb806836..ea39f13b73 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -665,7 +665,7 @@ static void *dp_part_node(void *buf, struct blk_desc *desc, int part) cddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CDROM_PATH; cddp->dp.length = sizeof(*cddp); cddp->partition_start = info.start; - cddp->partition_end = info.size; + cddp->partition_size = info.size; buf = &cddp[1]; } else { diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index 96fd08971b..b20b7c097c 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -60,9 +60,18 @@ static char *dp_hardware(char *s, struct efi_device_path *dp) break; } case DEVICE_PATH_SUB_TYPE_VENDOR: { + int i, n; struct efi_device_path_vendor *vdp = (struct efi_device_path_vendor *)dp; - s += sprintf(s, "VenHw(%pUl)", &vdp->guid); + + s += sprintf(s, "VenHw(%pUl", &vdp->guid); + n = (int)vdp->dp.length - sizeof(struct efi_device_path_vendor); + if (n > 0) { + s += sprintf(s, ","); + for (i = 0; i < n; ++i) + s += sprintf(s, "%02x", vdp->vendor_data[i]); + } + s += sprintf(s, ")"); break; } default: @@ -115,17 +124,16 @@ static char *dp_msging(char *s, struct efi_device_path *dp) break; } case DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR: { + int i, n = sizeof(struct efi_mac_addr); struct efi_device_path_mac_addr *mdp = (struct efi_device_path_mac_addr *)dp; - if (mdp->if_type != 0 && mdp->if_type != 1) - break; - - s += sprintf(s, "MAC(%02x%02x%02x%02x%02x%02x,0x%1x)", - mdp->mac.addr[0], mdp->mac.addr[1], - mdp->mac.addr[2], mdp->mac.addr[3], - mdp->mac.addr[4], mdp->mac.addr[5], - mdp->if_type); + if (mdp->if_type <= 1) + n = 6; + s += sprintf(s, "MAC("); + for (i = 0; i < n; ++i) + s += sprintf(s, "%02x", mdp->mac.addr[i]); + s += sprintf(s, ",%u)", mdp->if_type); break; } @@ -133,7 +141,7 @@ static char *dp_msging(char *s, struct efi_device_path *dp) struct efi_device_path_usb_class *ucdp = (struct efi_device_path_usb_class *)dp; - s += sprintf(s, "USBClass(%x,%x,%x,%x,%x)", + s += sprintf(s, "UsbClass(0x%x,0x%x,0x%x,0x%x,0x%x)", ucdp->vendor_id, ucdp->product_id, ucdp->device_class, ucdp->device_subclass, ucdp->device_protocol); @@ -206,7 +214,8 @@ static char *dp_media(char *s, struct efi_device_path *dp) case DEVICE_PATH_SUB_TYPE_CDROM_PATH: { struct efi_device_path_cdrom_path *cddp = (struct efi_device_path_cdrom_path *)dp; - s += sprintf(s, "CDROM(0x%x)", cddp->boot_entry); + s += sprintf(s, "CDROM(%u,0x%llx,0x%llx)", cddp->boot_entry, + cddp->partition_start, cddp->partition_size); break; } case DEVICE_PATH_SUB_TYPE_FILE_PATH: { diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 7a6b06821a..9007a5f77f 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -41,11 +41,26 @@ struct efi_disk_obj { struct blk_desc *desc; }; +/** + * efi_disk_reset() - reset block device + * + * This function implements the Reset service of the EFI_BLOCK_IO_PROTOCOL. + * + * As U-Boot's block devices do not have a reset function simply return + * EFI_SUCCESS. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @this: pointer to the BLOCK_IO_PROTOCOL + * @extended_verification: extended verification + * Return: status code + */ static efi_status_t EFIAPI efi_disk_reset(struct efi_block_io *this, char extended_verification) { EFI_ENTRY("%p, %x", this, extended_verification); - return EFI_EXIT(EFI_DEVICE_ERROR); + return EFI_EXIT(EFI_SUCCESS); } enum efi_disk_direction { @@ -69,12 +84,12 @@ static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this, blocks = buffer_size / blksz; lba += diskobj->offset; - debug("EFI: %s:%d blocks=%x lba=%llx blksz=%x dir=%d\n", __func__, - __LINE__, blocks, lba, blksz, direction); + EFI_PRINT("blocks=%x lba=%llx blksz=%x dir=%d\n", + blocks, lba, blksz, direction); /* We only support full block access */ if (buffer_size & (blksz - 1)) - return EFI_DEVICE_ERROR; + return EFI_BAD_BUFFER_SIZE; if (direction == EFI_DISK_READ) n = blk_dread(desc, lba, blocks, buffer); @@ -84,7 +99,7 @@ static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this, /* We don't do interrupts, so check for timers cooperatively */ efi_timer_check(); - debug("EFI: %s:%d n=%lx blocks=%x\n", __func__, __LINE__, n, blocks); + EFI_PRINT("n=%lx blocks=%x\n", n, blocks); if (n != blocks) return EFI_DEVICE_ERROR; @@ -99,6 +114,20 @@ static efi_status_t EFIAPI efi_disk_read_blocks(struct efi_block_io *this, void *real_buffer = buffer; efi_status_t r; + if (!this) + return EFI_INVALID_PARAMETER; + /* TODO: check for media changes */ + if (media_id != this->media->media_id) + return EFI_MEDIA_CHANGED; + if (!this->media->media_present) + return EFI_NO_MEDIA; + /* media->io_align is a power of 2 */ + if ((uintptr_t)buffer & (this->media->io_align - 1)) + return EFI_INVALID_PARAMETER; + if (lba * this->media->block_size + buffer_size > + this->media->last_block * this->media->block_size) + return EFI_INVALID_PARAMETER; + #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER if (buffer_size > EFI_LOADER_BOUNCE_BUFFER_SIZE) { r = efi_disk_read_blocks(this, media_id, lba, @@ -134,6 +163,22 @@ static efi_status_t EFIAPI efi_disk_write_blocks(struct efi_block_io *this, void *real_buffer = buffer; efi_status_t r; + if (!this) + return EFI_INVALID_PARAMETER; + if (this->media->read_only) + return EFI_WRITE_PROTECTED; + /* TODO: check for media changes */ + if (media_id != this->media->media_id) + return EFI_MEDIA_CHANGED; + if (!this->media->media_present) + return EFI_NO_MEDIA; + /* media->io_align is a power of 2 */ + if ((uintptr_t)buffer & (this->media->io_align - 1)) + return EFI_INVALID_PARAMETER; + if (lba * this->media->block_size + buffer_size > + this->media->last_block * this->media->block_size) + return EFI_INVALID_PARAMETER; + #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER if (buffer_size > EFI_LOADER_BOUNCE_BUFFER_SIZE) { r = efi_disk_write_blocks(this, media_id, lba, @@ -288,6 +333,11 @@ static efi_status_t efi_disk_add_dev( /* Fill in EFI IO Media info (for read/write callbacks) */ diskobj->media.removable_media = desc->removable; diskobj->media.media_present = 1; + /* + * MediaID is just an arbitrary counter. + * We have to change it if the medium is removed or changed. + */ + diskobj->media.media_id = 1; diskobj->media.block_size = desc->blksz; diskobj->media.io_align = desc->blksz; diskobj->media.last_block = desc->lba - offset; diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c index cad509bfea..1511e3bdb4 100644 --- a/lib/efi_loader/efi_gop.c +++ b/lib/efi_loader/efi_gop.c @@ -319,7 +319,7 @@ static efi_status_t gop_blt_vid_to_buf(struct efi_gop *this, * details. * * @this: the graphical output protocol - * @model_number: the mode to be set + * @mode_number: the mode to be set * Return: status code */ static efi_status_t EFIAPI gop_set_mode(struct efi_gop *this, u32 mode_number) diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index b5775e0399..83cbc9154f 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -655,6 +655,54 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size, return EFI_SUCCESS; } +/** + * efi_add_conventional_memory_map() - add a RAM memory area to the map + * + * @ram_start: start address of a RAM memory area + * @ram_end: end address of a RAM memory area + * @ram_top: max address to be used as conventional memory + * Return: status code + */ +efi_status_t efi_add_conventional_memory_map(u64 ram_start, u64 ram_end, + u64 ram_top) +{ + u64 pages; + + /* Remove partial pages */ + ram_end &= ~EFI_PAGE_MASK; + ram_start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK; + + if (ram_end <= ram_start) { + /* Invalid mapping */ + return EFI_INVALID_PARAMETER; + } + + pages = (ram_end - ram_start) >> EFI_PAGE_SHIFT; + + efi_add_memory_map(ram_start, pages, + EFI_CONVENTIONAL_MEMORY, false); + + /* + * Boards may indicate to the U-Boot memory core that they + * can not support memory above ram_top. Let's honor this + * in the efi_loader subsystem too by declaring any memory + * above ram_top as "already occupied by firmware". + */ + if (ram_top < ram_start) { + /* ram_top is before this region, reserve all */ + efi_add_memory_map(ram_start, pages, + EFI_BOOT_SERVICES_DATA, true); + } else if ((ram_top >= ram_start) && (ram_top < ram_end)) { + /* ram_top is inside this region, reserve parts */ + pages = (ram_end - ram_top) >> EFI_PAGE_SHIFT; + + efi_add_memory_map(ram_top, pages, + EFI_BOOT_SERVICES_DATA, true); + } + + return EFI_SUCCESS; +} + __weak void efi_add_known_memory(void) { u64 ram_top = board_get_usable_ram_top(0) & ~EFI_PAGE_MASK; @@ -672,42 +720,12 @@ __weak void efi_add_known_memory(void) /* Add RAM */ for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - u64 ram_end, ram_start, pages; + u64 ram_end, ram_start; ram_start = (uintptr_t)map_sysmem(gd->bd->bi_dram[i].start, 0); ram_end = ram_start + gd->bd->bi_dram[i].size; - /* Remove partial pages */ - ram_end &= ~EFI_PAGE_MASK; - ram_start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK; - - if (ram_end <= ram_start) { - /* Invalid mapping, keep going. */ - continue; - } - - pages = (ram_end - ram_start) >> EFI_PAGE_SHIFT; - - efi_add_memory_map(ram_start, pages, - EFI_CONVENTIONAL_MEMORY, false); - - /* - * Boards may indicate to the U-Boot memory core that they - * can not support memory above ram_top. Let's honor this - * in the efi_loader subsystem too by declaring any memory - * above ram_top as "already occupied by firmware". - */ - if (ram_top < ram_start) { - /* ram_top is before this region, reserve all */ - efi_add_memory_map(ram_start, pages, - EFI_BOOT_SERVICES_DATA, true); - } else if ((ram_top >= ram_start) && (ram_top < ram_end)) { - /* ram_top is inside this region, reserve parts */ - pages = (ram_end - ram_top) >> EFI_PAGE_SHIFT; - - efi_add_memory_map(ram_top, pages, - EFI_BOOT_SERVICES_DATA, true); - } + efi_add_conventional_memory_map(ram_start, ram_end, ram_top); } } diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index 825e064f9a..82d2595847 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -1,8 +1,18 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * EFI application network access support + * Simple network protocol + * PXE base code protocol * - * Copyright (c) 2016 Alexander Graf + * Copyright (c) 2016 Alexander Graf + * + * The simple network protocol has the following statuses and services + * to move between them: + * + * Start(): EfiSimpleNetworkStopped -> EfiSimpleNetworkStarted + * Initialize(): EfiSimpleNetworkStarted -> EfiSimpleNetworkInitialized + * Shutdown(): EfiSimpleNetworkInitialized -> EfiSimpleNetworkStarted + * Stop(): EfiSimpleNetworkStarted -> EfiSimpleNetworkStopped + * Reset(): EfiSimpleNetworkInitialized -> EfiSimpleNetworkInitialized */ #include <common.h> @@ -66,10 +76,13 @@ static efi_status_t EFIAPI efi_net_start(struct efi_simple_network *this) goto out; } - if (this->mode->state != EFI_NETWORK_STOPPED) + if (this->mode->state != EFI_NETWORK_STOPPED) { ret = EFI_ALREADY_STARTED; - else + } else { + this->int_status = 0; + wait_for_packet->is_signaled = false; this->mode->state = EFI_NETWORK_STARTED; + } out: return EFI_EXIT(ret); } @@ -96,10 +109,13 @@ static efi_status_t EFIAPI efi_net_stop(struct efi_simple_network *this) goto out; } - if (this->mode->state == EFI_NETWORK_STOPPED) + if (this->mode->state == EFI_NETWORK_STOPPED) { ret = EFI_NOT_STARTED; - else + } else { + /* Disable hardware and put it into the reset state */ + eth_halt(); this->mode->state = EFI_NETWORK_STOPPED; + } out: return EFI_EXIT(ret); } @@ -130,6 +146,15 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this, goto out; } + switch (this->mode->state) { + case EFI_NETWORK_INITIALIZED: + case EFI_NETWORK_STARTED: + break; + default: + r = EFI_NOT_STARTED; + goto out; + } + /* Setup packet buffers */ net_init(); /* Disable hardware and put it into the reset state */ @@ -144,6 +169,8 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this, r = EFI_DEVICE_ERROR; goto out; } else { + this->int_status = 0; + wait_for_packet->is_signaled = false; this->mode->state = EFI_NETWORK_INITIALIZED; } out: @@ -164,9 +191,31 @@ out: static efi_status_t EFIAPI efi_net_reset(struct efi_simple_network *this, int extended_verification) { + efi_status_t ret; + EFI_ENTRY("%p, %x", this, extended_verification); - return EFI_EXIT(EFI_CALL(efi_net_initialize(this, 0, 0))); + /* Check parameters */ + if (!this) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + switch (this->mode->state) { + case EFI_NETWORK_INITIALIZED: + break; + case EFI_NETWORK_STOPPED: + ret = EFI_NOT_STARTED; + goto out; + default: + ret = EFI_DEVICE_ERROR; + goto out; + } + + this->mode->state = EFI_NETWORK_STARTED; + ret = EFI_CALL(efi_net_initialize(this, 0, 0)); +out: + return EFI_EXIT(ret); } /* @@ -191,8 +240,21 @@ static efi_status_t EFIAPI efi_net_shutdown(struct efi_simple_network *this) goto out; } + switch (this->mode->state) { + case EFI_NETWORK_INITIALIZED: + break; + case EFI_NETWORK_STOPPED: + ret = EFI_NOT_STARTED; + goto out; + default: + ret = EFI_DEVICE_ERROR; + goto out; + } + eth_halt(); - this->mode->state = EFI_NETWORK_STOPPED; + this->int_status = 0; + wait_for_packet->is_signaled = false; + this->mode->state = EFI_NETWORK_STARTED; out: return EFI_EXIT(ret); @@ -270,7 +332,7 @@ static efi_status_t EFIAPI efi_net_statistics(struct efi_simple_network *this, /* * efi_net_mcastiptomac() - translate multicast IP address to MAC address * - * This function implements the Statistics service of the + * This function implements the MCastIPtoMAC service of the * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface * (UEFI) specification for details. * @@ -285,9 +347,49 @@ static efi_status_t EFIAPI efi_net_mcastiptomac(struct efi_simple_network *this, struct efi_ip_address *ip, struct efi_mac_address *mac) { + efi_status_t ret = EFI_SUCCESS; + EFI_ENTRY("%p, %x, %p, %p", this, ipv6, ip, mac); - return EFI_EXIT(EFI_INVALID_PARAMETER); + if (!this || !ip || !mac) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + if (ipv6) { + ret = EFI_UNSUPPORTED; + goto out; + } + + /* Multi-cast addresses are in the range 224.0.0.0 - 239.255.255.255 */ + if ((ip->ip_addr[0] & 0xf0) != 0xe0) { + ret = EFI_INVALID_PARAMETER; + goto out; + }; + + switch (this->mode->state) { + case EFI_NETWORK_INITIALIZED: + case EFI_NETWORK_STARTED: + break; + default: + ret = EFI_NOT_STARTED; + goto out; + } + + memset(mac, 0, sizeof(struct efi_mac_address)); + + /* + * Copy lower 23 bits of IPv4 multi-cast address + * RFC 1112, RFC 7042 2.1.1. + */ + mac->mac_addr[0] = 0x01; + mac->mac_addr[1] = 0x00; + mac->mac_addr[2] = 0x5E; + mac->mac_addr[3] = ip->ip_addr[1] & 0x7F; + mac->mac_addr[4] = ip->ip_addr[2]; + mac->mac_addr[5] = ip->ip_addr[3]; +out: + return EFI_EXIT(ret); } /** @@ -297,7 +399,7 @@ static efi_status_t EFIAPI efi_net_mcastiptomac(struct efi_simple_network *this, * Protocol. See the UEFI spec for details. * * @this: the instance of the Simple Network Protocol - * @readwrite: true for read, false for write + * @read_write: true for read, false for write * @offset: offset in NVRAM * @buffer_size: size of buffer * @buffer: buffer @@ -350,10 +452,8 @@ static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this, } if (int_status) { - /* We send packets synchronously, so nothing is outstanding */ - *int_status = EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT; - if (new_rx_packet) - *int_status |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; + *int_status = this->int_status; + this->int_status = 0; } if (txbuf) *txbuf = new_tx_packet; @@ -404,15 +504,33 @@ static efi_status_t EFIAPI efi_net_transmit goto out; } - if (header_size) { - /* - * TODO: We would need to create the header - * if header_size != 0 - */ - ret = EFI_UNSUPPORTED; + /* At least the IP header has to fit into the buffer */ + if (buffer_size < this->mode->media_header_size) { + ret = EFI_BUFFER_TOO_SMALL; goto out; } + /* + * TODO: + * Support VLANs. Use net_set_ether() for copying the header. Use a + * U_BOOT_ENV_CALLBACK to update the media header size. + */ + if (header_size) { + struct ethernet_hdr *header = buffer; + + if (!dest_addr || !protocol || + header_size != this->mode->media_header_size) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + if (!src_addr) + src_addr = &this->mode->current_address; + + memcpy(header->et_dest, dest_addr, ARP_HLEN); + memcpy(header->et_src, src_addr, ARP_HLEN); + header->et_protlen = htons(*protocol); + } + switch (this->mode->state) { case EFI_NETWORK_STOPPED: ret = EFI_NOT_STARTED; @@ -429,7 +547,7 @@ static efi_status_t EFIAPI efi_net_transmit net_send_packet(transmit_buffer, buffer_size); new_tx_packet = buffer; - + this->int_status |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT; out: return EFI_EXIT(ret); } @@ -487,12 +605,6 @@ static efi_status_t EFIAPI efi_net_receive ret = EFI_NOT_READY; goto out; } - /* Check that we at least received an Ethernet header */ - if (net_rx_packet_len < sizeof(struct ethernet_hdr)) { - new_rx_packet = false; - ret = EFI_NOT_READY; - goto out; - } /* Fill export parameters */ eth_hdr = (struct ethernet_hdr *)net_rx_packet; protlen = ntohs(eth_hdr->et_protlen); @@ -517,7 +629,8 @@ static efi_status_t EFIAPI efi_net_receive /* Copy packet */ memcpy(buffer, net_rx_packet, net_rx_packet_len); *buffer_size = net_rx_packet_len; - new_rx_packet = false; + new_rx_packet = 0; + this->int_status &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; out: return EFI_EXIT(ret); } @@ -526,6 +639,9 @@ out: * efi_net_set_dhcp_ack() - take note of a selected DHCP IP address * * This function is called by dhcp_handler(). + * + * @pkt: packet received by dhcp_handler() + * @len: length of the packet received */ void efi_net_set_dhcp_ack(void *pkt, int len) { @@ -548,7 +664,6 @@ void efi_net_set_dhcp_ack(void *pkt, int len) static void efi_net_push(void *pkt, int len) { new_rx_packet = true; - wait_for_packet->is_signaled = true; } /** @@ -556,8 +671,8 @@ static void efi_net_push(void *pkt, int len) * * This notification function is called in every timer cycle. * - * @event the event for which this notification function is registered - * @context event context - not used in this function + * @event: the event for which this notification function is registered + * @context: event context - not used in this function */ static void EFIAPI efi_network_timer_notify(struct efi_event *event, void *context) @@ -577,6 +692,17 @@ static void EFIAPI efi_network_timer_notify(struct efi_event *event, push_packet = efi_net_push; eth_rx(); push_packet = NULL; + if (new_rx_packet) { + /* Check that we at least received an Ethernet header */ + if (net_rx_packet_len >= + sizeof(struct ethernet_hdr)) { + this->int_status |= + EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; + wait_for_packet->is_signaled = true; + } else { + new_rx_packet = 0; + } + } } out: EFI_EXIT(EFI_SUCCESS); @@ -751,9 +877,10 @@ efi_status_t efi_net_register(void) netobj->net.transmit = efi_net_transmit; netobj->net.receive = efi_net_receive; netobj->net.mode = &netobj->net_mode; - netobj->net_mode.state = EFI_NETWORK_STARTED; + netobj->net_mode.state = EFI_NETWORK_STOPPED; memcpy(netobj->net_mode.current_address.mac_addr, eth_get_ethaddr(), 6); netobj->net_mode.hwaddr_size = ARP_HLEN; + netobj->net_mode.media_header_size = ETHER_HDR_SIZE; netobj->net_mode.max_packet_size = PKTSIZE; netobj->net_mode.if_type = ARP_ETHER; diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c index 4c26619001..9797ecaf42 100644 --- a/lib/efi_selftest/efi_selftest_snp.c +++ b/lib/efi_selftest/efi_selftest_snp.c @@ -228,6 +228,26 @@ static int setup(const efi_handle_t handle, efi_st_error("WaitForPacket event missing\n"); return EFI_ST_FAILURE; } + if (net->mode->state == EFI_NETWORK_INITIALIZED) { + /* + * Shut down network adapter. + */ + ret = net->shutdown(net); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to shut down network adapter\n"); + return EFI_ST_FAILURE; + } + } + if (net->mode->state == EFI_NETWORK_STARTED) { + /* + * Stop network adapter. + */ + ret = net->stop(net); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to stop network adapter\n"); + return EFI_ST_FAILURE; + } + } /* * Start network adapter. */ @@ -236,6 +256,10 @@ static int setup(const efi_handle_t handle, efi_st_error("Failed to start network adapter\n"); return EFI_ST_FAILURE; } + if (net->mode->state != EFI_NETWORK_STARTED) { + efi_st_error("Failed to start network adapter\n"); + return EFI_ST_FAILURE; + } /* * Initialize network adapter. */ @@ -244,6 +268,10 @@ static int setup(const efi_handle_t handle, efi_st_error("Failed to initialize network adapter\n"); return EFI_ST_FAILURE; } + if (net->mode->state != EFI_NETWORK_INITIALIZED) { + efi_st_error("Failed to initialize network adapter\n"); + return EFI_ST_FAILURE; + } return EFI_ST_SUCCESS; } @@ -268,6 +296,7 @@ static int execute(void) struct efi_mac_address destaddr; size_t buffer_size; u8 *addr; + /* * The timeout is to occur after 10 s. */ @@ -298,6 +327,8 @@ static int execute(void) events[0] = timer; events[1] = net->wait_for_packet; for (;;) { + u32 int_status; + /* * Wait for packet to be received or timer event. */ @@ -323,8 +354,17 @@ static int execute(void) * Receive packet */ buffer_size = sizeof(buffer); - net->receive(net, NULL, &buffer_size, &buffer, - &srcaddr, &destaddr, NULL); + ret = net->get_status(net, &int_status, NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to get status"); + return EFI_ST_FAILURE; + } + if (!(int_status & EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT)) { + efi_st_error("RX interrupt not set"); + return EFI_ST_FAILURE; + } + ret = net->receive(net, NULL, &buffer_size, &buffer, + &srcaddr, &destaddr, NULL); if (ret != EFI_SUCCESS) { efi_st_error("Failed to receive packet"); return EFI_ST_FAILURE; @@ -400,21 +440,29 @@ static int teardown(void) } if (net) { /* - * Stop network adapter. + * Shut down network adapter. */ - ret = net->stop(net); + ret = net->shutdown(net); if (ret != EFI_SUCCESS) { - efi_st_error("Failed to stop network adapter\n"); + efi_st_error("Failed to shut down network adapter\n"); exit_status = EFI_ST_FAILURE; } + if (net->mode->state != EFI_NETWORK_STARTED) { + efi_st_error("Failed to shutdown network adapter\n"); + return EFI_ST_FAILURE; + } /* - * Shut down network adapter. + * Stop network adapter. */ - ret = net->shutdown(net); + ret = net->stop(net); if (ret != EFI_SUCCESS) { - efi_st_error("Failed to shut down network adapter\n"); + efi_st_error("Failed to stop network adapter\n"); exit_status = EFI_ST_FAILURE; } + if (net->mode->state != EFI_NETWORK_STOPPED) { + efi_st_error("Failed to stop network adapter\n"); + return EFI_ST_FAILURE; + } } return exit_status; diff --git a/net/Makefile b/net/Makefile index 826544f05f..2a700c8401 100644 --- a/net/Makefile +++ b/net/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o obj-$(CONFIG_NET) += net.o obj-$(CONFIG_CMD_NFS) += nfs.o obj-$(CONFIG_CMD_PING) += ping.o +obj-$(CONFIG_CMD_PCAP) += pcap.o obj-$(CONFIG_CMD_RARP) += rarp.o obj-$(CONFIG_CMD_SNTP) += sntp.o obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o diff --git a/net/eth-uclass.c b/net/eth-uclass.c index 1d5d2f03b7..3bd98b01ad 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -11,6 +11,7 @@ #include <net.h> #include <dm/device-internal.h> #include <dm/uclass-internal.h> +#include <net/pcap.h> #include "eth_internal.h" DECLARE_GLOBAL_DATA_PTR; @@ -344,6 +345,10 @@ int eth_send(void *packet, int length) /* We cannot completely return the error at present */ debug("%s: send() returned error %d\n", __func__, ret); } +#if defined(CONFIG_CMD_PCAP) + if (ret >= 0) + pcap_post(packet, length, true); +#endif return ret; } diff --git a/net/eth_legacy.c b/net/eth_legacy.c index 850f362d87..41f5263526 100644 --- a/net/eth_legacy.c +++ b/net/eth_legacy.c @@ -11,6 +11,7 @@ #include <net.h> #include <phy.h> #include <linux/errno.h> +#include <net/pcap.h> #include "eth_internal.h" DECLARE_GLOBAL_DATA_PTR; @@ -352,10 +353,17 @@ int eth_is_active(struct eth_device *dev) int eth_send(void *packet, int length) { + int ret; + if (!eth_current) return -ENODEV; - return eth_current->send(eth_current, packet, length); + ret = eth_current->send(eth_current, packet, length); +#if defined(CONFIG_CMD_PCAP) + if (ret >= 0) + pcap_post(packet, lengeth, true); +#endif + return ret; } int eth_rx(void) diff --git a/net/mdio-uclass.c b/net/mdio-uclass.c index 36a404ff44..6f922e80b6 100644 --- a/net/mdio-uclass.c +++ b/net/mdio-uclass.c @@ -23,6 +23,17 @@ void dm_mdio_probe_devices(void) static int dm_mdio_post_bind(struct udevice *dev) { + const char *dt_name; + + /* set a custom name for the MDIO device, if present in DT */ + if (ofnode_valid(dev->node)) { + dt_name = ofnode_read_string(dev->node, "device-name"); + if (dt_name) { + debug("renaming dev %s to %s\n", dev->name, dt_name); + device_set_name(dev, dt_name); + } + } + /* * MDIO command doesn't like spaces in names, don't allow them to keep * it happy @@ -75,7 +86,7 @@ static int dm_mdio_post_probe(struct udevice *dev) pdata->mii_bus->write = mdio_write; pdata->mii_bus->reset = mdio_reset; pdata->mii_bus->priv = dev; - strncpy(pdata->mii_bus->name, dev->name, MDIO_NAME_LEN); + strncpy(pdata->mii_bus->name, dev->name, MDIO_NAME_LEN - 1); return mdio_register(pdata->mii_bus); } @@ -96,6 +96,9 @@ #include <net.h> #include <net/fastboot.h> #include <net/tftp.h> +#if defined(CONFIG_CMD_PCAP) +#include <net/pcap.h> +#endif #if defined(CONFIG_LED_STATUS) #include <miiphy.h> #include <status_led.h> @@ -672,6 +675,11 @@ done: net_set_icmp_handler(NULL); #endif net_set_state(prev_net_state); + +#if defined(CONFIG_CMD_PCAP) + if (pcap_active()) + pcap_print_status(); +#endif return ret; } @@ -1084,6 +1092,9 @@ void net_process_received_packet(uchar *in_packet, int len) debug_cond(DEBUG_NET_PKT, "packet received\n"); +#if defined(CONFIG_CMD_PCAP) + pcap_post(in_packet, len, false); +#endif net_rx_packet = in_packet; net_rx_packet_len = len; et = (struct ethernet_hdr *)in_packet; @@ -1253,6 +1264,9 @@ void net_process_received_packet(uchar *in_packet, int len) return; } + if (ntohs(ip->udp_len) < UDP_HDR_SIZE || ntohs(ip->udp_len) > ntohs(ip->ip_len)) + return; + debug_cond(DEBUG_DEV_PKT, "received UDP (to=%pI4, from=%pI4, len=%d)\n", &dst_ip, &src_ip, len); @@ -196,10 +196,10 @@ static void rpc_req(int rpc_prog, int rpc_proc, uint32_t *data, int datalen) rpc_pkt.u.call.vers = htonl(2); /* portmapper is version 2 */ } rpc_pkt.u.call.proc = htonl(rpc_proc); - p = (uint32_t *)&(rpc_pkt.u.call.data); + p = rpc_pkt.u.call.data; if (datalen) - memcpy((char *)p, (char *)data, datalen*sizeof(uint32_t)); + memcpy(p, data, datalen * sizeof(uint32_t)); pktlen = (char *)p + datalen * sizeof(uint32_t) - (char *)&rpc_pkt; @@ -566,11 +566,15 @@ static int nfs_lookup_reply(uchar *pkt, unsigned len) } if (supported_nfs_versions & NFSV2_FLAG) { + if (((uchar *)&(rpc_pkt.u.reply.data[0]) - (uchar *)(&rpc_pkt) + NFS_FHSIZE) > len) + return -NFS_RPC_DROP; memcpy(filefh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE); } else { /* NFSV3_FLAG */ filefh3_length = ntohl(rpc_pkt.u.reply.data[1]); if (filefh3_length > NFS3_FHSIZE) filefh3_length = NFS3_FHSIZE; + if (((uchar *)&(rpc_pkt.u.reply.data[0]) - (uchar *)(&rpc_pkt) + filefh3_length) > len) + return -NFS_RPC_DROP; memcpy(filefh, rpc_pkt.u.reply.data + 2, filefh3_length); } @@ -579,7 +583,7 @@ static int nfs_lookup_reply(uchar *pkt, unsigned len) static int nfs3_get_attributes_offset(uint32_t *data) { - if (ntohl(data[1]) != 0) { + if (data[1]) { /* 'attributes_follow' flag is TRUE, * so we have attributes on 21 dwords */ /* Skip unused values : @@ -634,6 +638,9 @@ static int nfs_readlink_reply(uchar *pkt, unsigned len) /* new path length */ rlen = ntohl(rpc_pkt.u.reply.data[1 + nfsv3_data_offset]); + if (((uchar *)&(rpc_pkt.u.reply.data[0]) - (uchar *)(&rpc_pkt) + rlen) > len) + return -NFS_RPC_DROP; + if (*((char *)&(rpc_pkt.u.reply.data[2 + nfsv3_data_offset])) != '/') { int pathlen; @@ -701,6 +708,9 @@ static int nfs_read_reply(uchar *pkt, unsigned len) &(rpc_pkt.u.reply.data[4 + nfsv3_data_offset]); } + if (((uchar *)&(rpc_pkt.u.reply.data[0]) - (uchar *)(&rpc_pkt) + rlen) > len) + return -9999; + if (store_block(data_ptr, nfs_offset, rlen)) return -9999; @@ -732,6 +742,9 @@ static void nfs_handler(uchar *pkt, unsigned dest, struct in_addr sip, debug("%s\n", __func__); + if (len > sizeof(struct rpc_t)) + return; + if (dest != nfs_our_port) return; @@ -78,7 +78,7 @@ struct rpc_t { NFS_MAX_ATTRS]; } reply; } u; -} __attribute__((packed)); +}; void nfs_start(void); /* Begin NFS */ diff --git a/net/pcap.c b/net/pcap.c new file mode 100644 index 0000000000..4036d8a3fa --- /dev/null +++ b/net/pcap.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Ramon Fried <rfried.dev@gmail.com> + */ + +#include <common.h> +#include <net.h> +#include <net/pcap.h> +#include <time.h> +#include <asm/io.h> + +#define LINKTYPE_ETHERNET 1 + +static bool initialized; +static bool running; +static bool buffer_full; +static void *buf; +static unsigned int max_size; +static unsigned int pos; + +static unsigned long incoming_count; +static unsigned long outgoing_count; + +struct pcap_header { + u32 magic; + u16 version_major; + u16 version_minor; + s32 thiszone; + u32 sigfigs; + u32 snaplen; + u32 network; +}; + +struct pcap_packet_header { + u32 ts_sec; + u32 ts_usec; + u32 incl_len; + u32 orig_len; +}; + +static struct pcap_header file_header = { + .magic = 0xa1b2c3d4, + .version_major = 2, + .version_minor = 4, + .snaplen = 65535, + .network = LINKTYPE_ETHERNET, +}; + +int pcap_init(phys_addr_t paddr, unsigned long size) +{ + buf = map_physmem(paddr, size, 0); + if (!buf) { + printf("Failed mapping PCAP memory\n"); + return -ENOMEM; + } + + printf("PCAP capture initialized: addr: 0x%lx max length: %lu\n", + (unsigned long)buf, size); + + memcpy(buf, &file_header, sizeof(file_header)); + pos = sizeof(file_header); + max_size = size; + initialized = true; + running = false; + buffer_full = false; + incoming_count = 0; + outgoing_count = 0; + return 0; +} + +int pcap_start_stop(bool start) +{ + if (!initialized) { + printf("error: pcap was not initialized\n"); + return -ENODEV; + } + + running = start; + + return 0; +} + +int pcap_clear(void) +{ + if (!initialized) { + printf("error: pcap was not initialized\n"); + return -ENODEV; + } + + pos = sizeof(file_header); + incoming_count = 0; + outgoing_count = 0; + buffer_full = false; + + printf("pcap capture cleared\n"); + return 0; +} + +int pcap_post(const void *packet, size_t len, bool outgoing) +{ + struct pcap_packet_header header; + u64 cur_time = timer_get_us(); + + if (!initialized || !running || !buf) + return -ENODEV; + + if (buffer_full) + return -ENOMEM; + + if ((pos + len + sizeof(header)) >= max_size) { + buffer_full = true; + printf("\n!!! Buffer is full, consider increasing buffer size !!!\n"); + return -ENOMEM; + } + + header.ts_sec = cur_time / 1000000; + header.ts_usec = cur_time % 1000000; + header.incl_len = len; + header.orig_len = len; + + memcpy(buf + pos, &header, sizeof(header)); + pos += sizeof(header); + memcpy(buf + pos, packet, len); + pos += len; + + if (outgoing) + outgoing_count++; + else + incoming_count++; + + env_set_hex("pcapsize", pos); + + return 0; +} + +int pcap_print_status(void) +{ + if (!initialized) { + printf("pcap was not initialized\n"); + return -ENODEV; + } + printf("PCAP status:\n"); + printf("\tInitialized addr: 0x%lx\tmax length: %u\n", + (unsigned long)buf, max_size); + printf("\tStatus: %s.\t file size: %u\n", running ? "Active" : "Idle", + pos); + printf("\tIncoming packets: %lu Outgoing packets: %lu\n", + incoming_count, outgoing_count); + + return 0; +} + +bool pcap_active(void) +{ + return running; +} diff --git a/test/dm/cache.c b/test/dm/cache.c index d4144aab76..2e244b109f 100644 --- a/test/dm/cache.c +++ b/test/dm/cache.c @@ -14,6 +14,8 @@ static int dm_test_reset(struct unit_test_state *uts) ut_assertok(uclass_get_device(UCLASS_CACHE, 0, &dev_cache)); ut_assertok(cache_get_info(dev, &info)); + ut_assertok(cache_enable(dev)); + ut_assertok(cache_disable(dev)); return 0; } diff --git a/tools/prelink-riscv.inc b/tools/prelink-riscv.inc index 8b40ec430a..f2b5467f5b 100644 --- a/tools/prelink-riscv.inc +++ b/tools/prelink-riscv.inc @@ -27,6 +27,8 @@ #define target32_to_cpu CONCAT(PRELINK_BYTEORDER, 32_to_cpu) #define target64_to_cpu CONCAT(PRELINK_BYTEORDER, 64_to_cpu) #define targetnn_to_cpu CONCAT3(PRELINK_BYTEORDER, PRELINK_INC_BITS, _to_cpu) +#define cpu_to_target32 CONCAT3(cpu_to_, PRELINK_BYTEORDER, 32) +#define cpu_to_target64 CONCAT3(cpu_to_, PRELINK_BYTEORDER, 64) static void* get_offset_bonn (void* data, Elf_Phdr* phdrs, size_t phnum, Elf_Addr addr) { @@ -92,9 +94,9 @@ static void prelink_bonn(void *data) if (ELF_R_TYPE(targetnn_to_cpu(r->r_info)) == R_RISCV_RELATIVE) *((uintnn_t*) buf) = r->r_addend; else if (ELF_R_TYPE(targetnn_to_cpu(r->r_info)) == R_RISCV_32) - *((uint32_t*) buf) = dynsym[ELF_R_SYM(targetnn_to_cpu(r->r_info))].st_value; + *((uint32_t*) buf) = cpu_to_target32(targetnn_to_cpu(dynsym[ELF_R_SYM(targetnn_to_cpu(r->r_info))].st_value) + targetnn_to_cpu(r->r_addend)); else if (ELF_R_TYPE(targetnn_to_cpu(r->r_info)) == R_RISCV_64) - *((uint64_t*) buf) = dynsym[ELF_R_SYM(targetnn_to_cpu(r->r_info))].st_value; + *((uint64_t*) buf) = cpu_to_target64(targetnn_to_cpu(dynsym[ELF_R_SYM(targetnn_to_cpu(r->r_info))].st_value) + targetnn_to_cpu(r->r_addend)); } } @@ -113,6 +115,8 @@ static void prelink_bonn(void *data) #undef target32_to_cpu #undef target64_to_cpu #undef targetnn_to_cpu +#undef cpu_to_target32 +#undef cpu_to_target64 #undef CONCAT_IMPL #undef CONCAT |