Merge tag 'efi-2019-07-rc1' of git://git.denx.de/u-boot-efi
authorTom Rini <trini@konsulko.com>
Tue, 9 Apr 2019 02:32:45 +0000 (22:32 -0400)
committerTom Rini <trini@konsulko.com>
Tue, 9 Apr 2019 02:32:45 +0000 (22:32 -0400)
Pull request for UEFI sub-system for v2019.07-rc1

The patch series adds support for the BootNext and BootCurrent variables.

The rest is mostly bug fixes. With the bug fixes in place it becomes
possible to use the EFI Shell `edit` command.

A new unit test is supplied to check the image base and size fields of the
loaded image protocol.

An inline check when freeing memory from the pool safeguards against double
frees.

37 files changed:
Makefile
arch/arm/Kconfig
arch/arm/dts/fsl-imx8qxp-mek.dts
arch/arm/mach-sunxi/Kconfig
arch/mips/mach-mt7620/cpu.c
arch/riscv/Kconfig
arch/riscv/cpu/ax25/Kconfig
arch/riscv/cpu/cpu.c
arch/riscv/cpu/start.S
arch/riscv/dts/Makefile
arch/riscv/dts/ae350_32.dts
arch/riscv/dts/ae350_64.dts
arch/riscv/include/asm/csr.h
arch/riscv/include/asm/global_data.h
arch/riscv/include/asm/sbi.h [new file with mode: 0644]
arch/riscv/include/asm/smp.h [new file with mode: 0644]
arch/riscv/include/asm/syscon.h
arch/riscv/lib/Makefile
arch/riscv/lib/andes_plic.c [new file with mode: 0644]
arch/riscv/lib/andes_plmt.c [new file with mode: 0644]
arch/riscv/lib/asm-offsets.c
arch/riscv/lib/bootm.c
arch/riscv/lib/sbi_ipi.c [new file with mode: 0644]
arch/riscv/lib/smp.c [new file with mode: 0644]
board/AndesTech/ax25-ae350/Kconfig
board/CZ.NIC/turris_mox/turris_mox.c
board/CZ.NIC/turris_omnia/turris_omnia.c
board/emulation/qemu-riscv/Kconfig
board/sifive/fu540/Kconfig
board/xilinx/microblaze-generic/microblaze-generic.c
board/xilinx/zynq/board.c
board/xilinx/zynqmp/zynqmp.c
configs/ae350_rv32_defconfig
configs/ae350_rv64_defconfig
drivers/net/fec_mxc.c
drivers/net/fec_mxc.h
drivers/net/phy/phy.c

index 92e04dd..aedc2ea 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@
 VERSION = 2019
 PATCHLEVEL = 04
 SUBLEVEL =
-EXTRAVERSION = -rc4
+EXTRAVERSION =
 NAME =
 
 # *DOCUMENTATION*
index f42ecce..4a23e32 100644 (file)
@@ -857,7 +857,6 @@ config ARCH_SUNXI
        select DM_ETH
        select DM_GPIO
        select DM_KEYBOARD
-       select DM_MMC if MMC
        select DM_SERIAL
        select DM_USB if DISTRO_DEFAULTS
        select OF_BOARD_SETUP
index 41f7ec1..4f35fbe 100644 (file)
        status = "okay";
        phy-reset-gpios = <&pca9557_a 4 GPIO_ACTIVE_LOW>;
        phy-reset-duration = <10>;
+       phy-reset-post-delay = <150>;
 
        mdio {
                #address-cells = <1>;
index 74e234c..152deb0 100644 (file)
@@ -154,6 +154,7 @@ config MACH_SUN4I
        bool "sun4i (Allwinner A10)"
        select CPU_V7A
        select ARM_CORTEX_CPU_IS_UP
+       select DM_MMC if MMC
        select DM_SCSI if SCSI
        select PHY_SUN4I_USB
        select DRAM_SUN4I
@@ -164,6 +165,7 @@ config MACH_SUN5I
        bool "sun5i (Allwinner A13)"
        select CPU_V7A
        select ARM_CORTEX_CPU_IS_UP
+       select DM_MMC if MMC
        select DRAM_SUN4I
        select PHY_SUN4I_USB
        select SUNXI_GEN_SUN4I
@@ -176,6 +178,7 @@ config MACH_SUN6I
        select CPU_V7_HAS_NONSEC
        select CPU_V7_HAS_VIRT
        select ARCH_SUPPORT_PSCI
+       select DM_MMC if MMC
        select DRAM_SUN6I
        select PHY_SUN4I_USB
        select SUN6I_P2WI
@@ -202,6 +205,7 @@ config MACH_SUN8I_A23
        select CPU_V7_HAS_NONSEC
        select CPU_V7_HAS_VIRT
        select ARCH_SUPPORT_PSCI
+       select DM_MMC if MMC
        select DRAM_SUN8I_A23
        select PHY_SUN4I_USB
        select SUNXI_GEN_SUN6I
@@ -215,6 +219,7 @@ config MACH_SUN8I_A33
        select CPU_V7_HAS_NONSEC
        select CPU_V7_HAS_VIRT
        select ARCH_SUPPORT_PSCI
+       select DM_MMC if MMC
        select DRAM_SUN8I_A33
        select PHY_SUN4I_USB
        select SUNXI_GEN_SUN6I
@@ -225,6 +230,7 @@ config MACH_SUN8I_A33
 config MACH_SUN8I_A83T
        bool "sun8i (Allwinner A83T)"
        select CPU_V7A
+       select DM_MMC if MMC
        select DRAM_SUN8I_A83T
        select PHY_SUN4I_USB
        select SUNXI_GEN_SUN6I
@@ -240,6 +246,7 @@ config MACH_SUN8I_H3
        select ARCH_SUPPORT_PSCI
        select MACH_SUNXI_H3_H5
        select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT
+       select DM_MMC if MMC
 
 config MACH_SUN8I_R40
        bool "sun8i (Allwinner R40)"
@@ -258,6 +265,7 @@ config MACH_SUN8I_V3S
        select CPU_V7_HAS_NONSEC
        select CPU_V7_HAS_VIRT
        select ARCH_SUPPORT_PSCI
+       select DM_MMC if MMC
        select SUNXI_GEN_SUN6I
        select SUNXI_DRAM_DW
        select SUNXI_DRAM_DW_16BIT
@@ -272,11 +280,13 @@ config MACH_SUN9I
        select SUNXI_GEN_SUN6I
        select SUN8I_RSB
        select SUPPORT_SPL
+       select DM_MMC if MMC
 
 config MACH_SUN50I
        bool "sun50i (Allwinner A64)"
        select ARM64
        select DM_I2C
+       select DM_MMC if MMC
        select PHY_SUN4I_USB
        select SUN6I_PRCM
        select SUNXI_DE2
@@ -293,6 +303,7 @@ config MACH_SUN50I_H5
        bool "sun50i (Allwinner H5)"
        select ARM64
        select MACH_SUNXI_H3_H5
+       select DM_MMC if MMC
        select FIT
        select SPL_LOAD_FIT
 
@@ -300,6 +311,7 @@ config MACH_SUN50I_H6
        bool "sun50i (Allwinner H6)"
        select ARM64
        select SUPPORT_SPL
+       select DM_MMC if MMC
        select FIT
        select SPL_LOAD_FIT
        select DRAM_SUN50I_H6
index 9e0ca71..fe74f26 100644 (file)
@@ -70,7 +70,7 @@ int print_cpuinfo(void)
 }
 
 #ifdef CONFIG_WATCHDOG
-static struct udevice *watchdog_dev;
+static struct udevice *watchdog_dev __attribute__((section(".data"))) = NULL;
 
 /* Called by macro WATCHDOG_RESET */
 void watchdog_reset(void)
index 36512a8..ae8ff7b 100644 (file)
@@ -109,6 +109,24 @@ config SIFIVE_CLINT
          The SiFive CLINT block holds memory-mapped control and status registers
          associated with software and timer interrupts.
 
+config ANDES_PLIC
+       bool
+       depends on RISCV_MMODE
+       select REGMAP
+       select SYSCON
+       help
+         The Andes PLIC block holds memory-mapped claim and pending registers
+         associated with software interrupt.
+
+config ANDES_PLMT
+       bool
+       depends on RISCV_MMODE
+       select REGMAP
+       select SYSCON
+       help
+         The Andes PLMT block holds memory-mapped mtime register
+         associated with timer tick.
+
 config RISCV_RDTIME
        bool
        default y if RISCV_SMODE
@@ -120,4 +138,32 @@ config RISCV_RDTIME
 config SYS_MALLOC_F_LEN
        default 0x1000
 
+config SMP
+       bool "Symmetric Multi-Processing"
+       help
+         This enables support for systems with more than one CPU. If
+         you say N here, U-Boot will run on single and multiprocessor
+         machines, but will use only one CPU of a multiprocessor
+         machine. If you say Y here, U-Boot will run on many, but not
+         all, single processor machines.
+
+config NR_CPUS
+       int "Maximum number of CPUs (2-32)"
+       range 2 32
+       depends on SMP
+       default 8
+       help
+         On multiprocessor machines, U-Boot sets up a stack for each CPU.
+         Stack memory is pre-allocated. U-Boot must therefore know the
+         maximum number of CPUs that may be present.
+
+config SBI_IPI
+       bool
+       default y if RISCV_SMODE
+       depends on SMP
+
+config STACK_SIZE_SHIFT
+       int
+       default 13
+
 endmenu
index e9dbca2..6b4b92e 100644 (file)
@@ -1,5 +1,11 @@
 config RISCV_NDS
        bool
+       select ARCH_EARLY_INIT_R
+       imply CPU
+       imply CPU_RISCV
+       imply RISCV_TIMER
+       imply ANDES_PLIC if RISCV_MMODE
+       imply ANDES_PLMT if RISCV_MMODE
        help
          Run U-Boot on AndeStar V5 platforms and use some specific features
          which are provided by Andes Technology AndeStar V5 families.
@@ -8,6 +14,7 @@ if RISCV_NDS
 
 config RISCV_NDS_CACHE
        bool "AndeStar V5 families specific cache support"
+       depends on RISCV_MMODE
        help
          Provide Andes Technology AndeStar V5 families specific cache support.
 
index e662140..c32de8a 100644 (file)
 #include <dm/uclass-internal.h>
 
 /*
- * prior_stage_fdt_address must be stored in the data section since it is used
+ * The variables here must be stored in the data section since they are used
  * before the bss section is available.
  */
 phys_addr_t prior_stage_fdt_address __attribute__((section(".data")));
+u32 hart_lottery __attribute__((section(".data"))) = 0;
+
+/*
+ * The main hart running U-Boot has acquired available_harts_lock until it has
+ * finished initialization of global data.
+ */
+u32 available_harts_lock = 1;
 
 static inline bool supports_extension(char ext)
 {
index 81ea52b..a4433fb 100644 (file)
@@ -13,6 +13,7 @@
 #include <config.h>
 #include <common.h>
 #include <elf.h>
+#include <asm/csr.h>
 #include <asm/encoding.h>
 #include <generated/asm-offsets.h>
 
 #define SYM_SIZE               0x18
 #endif
 
+.section .data
+secondary_harts_relocation_error:
+       .ascii "Relocation of secondary harts has failed, error %d\n"
+
 .section .text
 .globl _start
 _start:
+#ifdef CONFIG_RISCV_MMODE
+       csrr    a0, mhartid
+#endif
+
        /* save hart id and dtb pointer */
-       mv      s0, a0
+       mv      tp, a0
        mv      s1, a1
 
        la      t0, trap_entry
@@ -45,9 +54,22 @@ _start:
        /* mask all interrupts */
        csrw    MODE_PREFIX(ie), zero
 
-       /* Enable cache */
-       jal     icache_enable
-       jal     dcache_enable
+#ifdef CONFIG_SMP
+       /* check if hart is within range */
+       /* tp: hart id */
+       li      t0, CONFIG_NR_CPUS
+       bge     tp, t0, hart_out_of_bounds_loop
+#endif
+
+#ifdef CONFIG_SMP
+       /* set xSIE bit to receive IPIs */
+#ifdef CONFIG_RISCV_MMODE
+       li      t0, MIE_MSIE
+#else
+       li      t0, SIE_SSIE
+#endif
+       csrs    MODE_PREFIX(ie), t0
+#endif
 
 /*
  * Set stackpointer in internal/ex RAM to call board_init_f
@@ -57,14 +79,33 @@ call_board_init_f:
        li      t1, CONFIG_SYS_INIT_SP_ADDR
        and     sp, t1, t0              /* force 16 byte alignment */
 
-#ifdef CONFIG_DEBUG_UART
-       jal     debug_uart_init
-#endif
-
 call_board_init_f_0:
        mv      a0, sp
        jal     board_init_f_alloc_reserve
+
+       /*
+        * Set global data pointer here for all harts, uninitialized at this
+        * point.
+        */
+       mv      gp, a0
+
+       /* setup stack */
+#ifdef CONFIG_SMP
+       /* tp: hart id */
+       slli    t0, tp, CONFIG_STACK_SIZE_SHIFT
+       sub     sp, a0, t0
+#else
        mv      sp, a0
+#endif
+
+       /*
+        * Pick hart to initialize global data and run U-Boot. The other harts
+        * wait for initialization to complete.
+        */
+       la      t0, hart_lottery
+       li      s2, 1
+       amoswap.w s2, t1, 0(t0)
+       bnez    s2, wait_for_gd_init
 
        la      t0, prior_stage_fdt_address
        SREG    s1, 0(t0)
@@ -72,7 +113,42 @@ call_board_init_f_0:
        jal     board_init_f_init_reserve
 
        /* save the boot hart id to global_data */
-       SREG    s0, GD_BOOT_HART(gp)
+       SREG    tp, GD_BOOT_HART(gp)
+
+       la      t0, available_harts_lock
+       fence   rw, w
+       amoswap.w zero, zero, 0(t0)
+
+wait_for_gd_init:
+       la      t0, available_harts_lock
+       li      t1, 1
+1:     amoswap.w t1, t1, 0(t0)
+       fence   r, rw
+       bnez    t1, 1b
+
+       /* register available harts in the available_harts mask */
+       li      t1, 1
+       sll     t1, t1, tp
+       LREG    t2, GD_AVAILABLE_HARTS(gp)
+       or      t2, t2, t1
+       SREG    t2, GD_AVAILABLE_HARTS(gp)
+
+       fence   rw, w
+       amoswap.w zero, zero, 0(t0)
+
+       /*
+        * Continue on hart lottery winner, others branch to
+        * secondary_hart_loop.
+        */
+       bnez    s2, secondary_hart_loop
+
+       /* Enable cache */
+       jal     icache_enable
+       jal     dcache_enable
+
+#ifdef CONFIG_DEBUG_UART
+       jal     debug_uart_init
+#endif
 
        mv      a0, zero                /* a0 <-- boot_flags = 0 */
        la      t5, board_init_f
@@ -95,7 +171,14 @@ relocate_code:
  *Set up the stack
  */
 stack_setup:
+#ifdef CONFIG_SMP
+       /* tp: hart id */
+       slli    t0, tp, CONFIG_STACK_SIZE_SHIFT
+       sub     sp, s2, t0
+#else
        mv      sp, s2
+#endif
+
        la      t0, _start
        sub     t6, s4, t0              /* t6 <- relocation offset */
        beq     t0, s4, clear_bss       /* skip relocation */
@@ -175,13 +258,37 @@ clear_bss:
        add     t0, t0, t6              /* t0 <- rel __bss_start in RAM */
        la      t1, __bss_end           /* t1 <- rel __bss_end in FLASH */
        add     t1, t1, t6              /* t1 <- rel __bss_end in RAM */
-       beq     t0, t1, call_board_init_r
+       beq     t0, t1, relocate_secondary_harts
 
 clbss_l:
        SREG    zero, 0(t0)             /* clear loop... */
        addi    t0, t0, REGBYTES
        bne     t0, t1, clbss_l
 
+relocate_secondary_harts:
+#ifdef CONFIG_SMP
+       /* send relocation IPI */
+       la      t0, secondary_hart_relocate
+       add     a0, t0, t6
+
+       /* store relocation offset */
+       mv      s5, t6
+
+       mv      a1, s2
+       mv      a2, s3
+       jal     smp_call_function
+
+       /* hang if relocation of secondary harts has failed */
+       beqz    a0, 1f
+       mv      a1, a0
+       la      a0, secondary_harts_relocation_error
+       jal     printf
+       jal     hang
+
+       /* restore relocation offset */
+1:     mv      t6, s5
+#endif
+
 /*
  * We are done. Do not return, instead branch to second part of board
  * initialization, now running from RAM.
@@ -202,3 +309,43 @@ call_board_init_r:
  * jump to it ...
  */
        jr      t4                      /* jump to board_init_r() */
+
+#ifdef CONFIG_SMP
+hart_out_of_bounds_loop:
+       /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */
+       wfi
+       j       hart_out_of_bounds_loop
+#endif
+
+#ifdef CONFIG_SMP
+/* SMP relocation entry */
+secondary_hart_relocate:
+       /* a1: new sp */
+       /* a2: new gd */
+       /* tp: hart id */
+
+       /* setup stack */
+       slli    t0, tp, CONFIG_STACK_SIZE_SHIFT
+       sub     sp, a1, t0
+
+       /* update global data pointer */
+       mv      gp, a2
+#endif
+
+secondary_hart_loop:
+       wfi
+
+#ifdef CONFIG_SMP
+       csrr    t0, MODE_PREFIX(ip)
+#ifdef CONFIG_RISCV_MMODE
+       andi    t0, t0, MIE_MSIE
+#else
+       andi    t0, t0, SIE_SSIE
+#endif
+       beqz    t0, secondary_hart_loop
+
+       mv      a0, tp
+       jal     handle_ipi
+#endif
+
+       j       secondary_hart_loop
index b400def..f9cd606 100644 (file)
@@ -1,5 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 
+dtb-$(CONFIG_TARGET_AX25_AE350) += ae350_32.dtb ae350_64.dtb
+
 targets += $(dtb-y)
 
 DTC_FLAGS += -R 4 -p 0x1000
index 0679827..2ec01a5 100644 (file)
                        status = "okay";
                        compatible = "riscv";
                        riscv,isa = "rv32imafdc";
+                       riscv,priv-major = <1>;
+                       riscv,priv-minor = <10>;
                        mmu-type = "riscv,sv32";
                        clock-frequency = <60000000>;
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <32>;
                        d-cache-size = <0x8000>;
                        d-cache-line-size = <32>;
+                       next-level-cache = <&L2>;
                        CPU0_intc: interrupt-controller {
                                #interrupt-cells = <1>;
                                interrupt-controller;
                                compatible = "riscv,cpu-intc";
                        };
                };
+               CPU1: cpu@1 {
+                       device_type = "cpu";
+                       reg = <1>;
+                       status = "okay";
+                       compatible = "riscv";
+                       riscv,isa = "rv32imafdc";
+                       riscv,priv-major = <1>;
+                       riscv,priv-minor = <10>;
+                       mmu-type = "riscv,sv32";
+                       clock-frequency = <60000000>;
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <32>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <32>;
+                       next-level-cache = <&L2>;
+                       CPU1_intc: interrupt-controller {
+                               #interrupt-cells = <1>;
+                               interrupt-controller;
+                               compatible = "riscv,cpu-intc";
+                       };
+               };
+
+               L2: l2-cache@e0500000 {
+                       compatible = "cache";
+                       cache-level = <2>;
+                       cache-size = <0x40000>;
+                       reg = <0x0 0xe0500000 0x0 0x40000>;
+               };
        };
 
        memory@0 {
        soc {
                #address-cells = <1>;
                #size-cells = <1>;
-               compatible = "andestech,riscv-ae350-soc";
+               compatible = "simple-bus";
                ranges;
 
-       plic0: interrupt-controller@e4000000 {
-               compatible = "riscv,plic0";
-               #address-cells = <1>;
-               #interrupt-cells = <1>;
-               interrupt-controller;
-               reg = <0xe4000000 0x2000000>;
-               riscv,ndev=<71>;
-               interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>;
-       };
+               plic0: interrupt-controller@e4000000 {
+                       compatible = "riscv,plic0";
+                       #address-cells = <1>;
+                       #interrupt-cells = <1>;
+                       interrupt-controller;
+                       reg = <0xe4000000 0x2000000>;
+                       riscv,ndev=<71>;
+                       interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9 &CPU1_intc 11 &CPU1_intc 9>;
+               };
 
-       plic1: interrupt-controller@e6400000 {
-               compatible = "riscv,plic1";
-               #address-cells = <1>;
-               #interrupt-cells = <1>;
-               interrupt-controller;
-               reg = <0xe6400000 0x400000>;
-               riscv,ndev=<1>;
-               interrupts-extended = <&CPU0_intc 3>;
-       };
+               plic1: interrupt-controller@e6400000 {
+                       compatible = "riscv,plic1";
+                       #address-cells = <1>;
+                       #interrupt-cells = <1>;
+                       interrupt-controller;
+                       reg = <0xe6400000 0x400000>;
+                       riscv,ndev=<2>;
+                       interrupts-extended = <&CPU0_intc 3 &CPU1_intc 3>;
+               };
 
-       plmt0@e6000000 {
-               compatible = "riscv,plmt0";
-                       interrupts-extended = <&CPU0_intc 7>;
+               plmt0@e6000000 {
+                       compatible = "riscv,plmt0";
+                       interrupts-extended = <&CPU0_intc 7 &CPU1_intc 7>;
                        reg = <0xe6000000 0x100000>;
                };
        };
                interrupt-parent = <&plic0>;
        };
 
+       pmu {
+               compatible = "riscv,base-pmu";
+       };
+
        virtio_mmio@fe007000 {
                interrupts = <0x17 0x4>;
                interrupt-parent = <0x2>;
index e48c298..cde5cde 100644 (file)
                        status = "okay";
                        compatible = "riscv";
                        riscv,isa = "rv64imafdc";
+                       riscv,priv-major = <1>;
+                       riscv,priv-minor = <10>;
                        mmu-type = "riscv,sv39";
                        clock-frequency = <60000000>;
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <32>;
                        d-cache-size = <0x8000>;
                        d-cache-line-size = <32>;
+                       next-level-cache = <&L2>;
                        CPU0_intc: interrupt-controller {
                                #interrupt-cells = <1>;
                                interrupt-controller;
                                compatible = "riscv,cpu-intc";
                        };
                };
+               CPU1: cpu@1 {
+                       device_type = "cpu";
+                       reg = <1>;
+                       status = "okay";
+                       compatible = "riscv";
+                       riscv,isa = "rv64imafdc";
+                       riscv,priv-major = <1>;
+                       riscv,priv-minor = <10>;
+                       mmu-type = "riscv,sv39";
+                       clock-frequency = <60000000>;
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <32>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <32>;
+                       next-level-cache = <&L2>;
+                       CPU1_intc: interrupt-controller {
+                               #interrupt-cells = <1>;
+                               interrupt-controller;
+                               compatible = "riscv,cpu-intc";
+                       };
+               };
+
+               L2: l2-cache@e0500000 {
+                       compatible = "cache";
+                       cache-level = <2>;
+                       cache-size = <0x40000>;
+                       reg = <0x0 0xe0500000 0x0 0x40000>;
+               };
        };
 
        memory@0 {
        soc {
                #address-cells = <2>;
                #size-cells = <2>;
-               compatible = "andestech,riscv-ae350-soc";
+               compatible = "simple-bus";
                ranges;
 
-       plic0: interrupt-controller@e4000000 {
-               compatible = "riscv,plic0";
-               #address-cells = <2>;
-               #interrupt-cells = <2>;
-               interrupt-controller;
-               reg = <0x0 0xe4000000 0x0 0x2000000>;
-               riscv,ndev=<71>;
-               interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>;
-       };
+               plic0: interrupt-controller@e4000000 {
+                       compatible = "riscv,plic0";
+                       #address-cells = <2>;
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+                       reg = <0x0 0xe4000000 0x0 0x2000000>;
+                       riscv,ndev=<71>;
+                       interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9 &CPU1_intc 11 &CPU1_intc 9>;
+               };
 
-       plic1: interrupt-controller@e6400000 {
-               compatible = "riscv,plic1";
-               #address-cells = <2>;
-               #interrupt-cells = <2>;
-               interrupt-controller;
-               reg = <0x0 0xe6400000 0x0 0x400000>;
-               riscv,ndev=<1>;
-               interrupts-extended = <&CPU0_intc 3>;
-       };
+               plic1: interrupt-controller@e6400000 {
+                       compatible = "riscv,plic1";
+                       #address-cells = <2>;
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+                       reg = <0x0 0xe6400000 0x0 0x400000>;
+                       riscv,ndev=<2>;
+                       interrupts-extended = <&CPU0_intc 3 &CPU1_intc 3>;
+               };
 
-       plmt0@e6000000 {
-               compatible = "riscv,plmt0";
-                       interrupts-extended = <&CPU0_intc 7>;
+               plmt0@e6000000 {
+                       compatible = "riscv,plmt0";
+                       interrupts-extended = <&CPU0_intc 7 &CPU1_intc 7>;
                        reg = <0x0 0xe6000000 0x0 0x100000>;
                };
        };
                interrupt-parent = <&plic0>;
        };
 
+       pmu {
+               compatible = "riscv,base-pmu";
+       };
+
        virtio_mmio@fe007000 {
                interrupts = <0x17 0x4>;
                interrupt-parent = <0x2>;
index 86136f5..644e6ba 100644 (file)
@@ -46,6 +46,7 @@
 #endif
 
 /* Interrupt Enable and Interrupt Pending flags */
+#define MIE_MSIE       _AC(0x00000008, UL) /* Software Interrupt Enable */
 #define SIE_SSIE       _AC(0x00000002, UL) /* Software Interrupt Enable */
 #define SIE_STIE       _AC(0x00000020, UL) /* Timer Interrupt Enable */
 
index a3a342c..dffcd45 100644 (file)
 #ifndef        __ASM_GBL_DATA_H
 #define __ASM_GBL_DATA_H
 
+#include <asm/smp.h>
+
 /* Architecture-specific global data */
 struct arch_global_data {
        long boot_hart;         /* boot hart id */
 #ifdef CONFIG_SIFIVE_CLINT
        void __iomem *clint;    /* clint base address */
 #endif
+#ifdef CONFIG_ANDES_PLIC
+       void __iomem *plic;     /* plic base address */
+#endif
+#ifdef CONFIG_ANDES_PLMT
+       void __iomem *plmt;     /* plmt base address */
+#endif
+#ifdef CONFIG_SMP
+       struct ipi_data ipi[CONFIG_NR_CPUS];
+#endif
+       ulong available_harts;
 };
 
 #include <asm-generic/global_data.h>
diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
new file mode 100644 (file)
index 0000000..ced57de
--- /dev/null
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2015 Regents of the University of California
+ *
+ * Taken from Linux arch/riscv/include/asm/sbi.h
+ */
+
+#ifndef _ASM_RISCV_SBI_H
+#define _ASM_RISCV_SBI_H
+
+#include <linux/types.h>
+
+#define SBI_SET_TIMER 0
+#define SBI_CONSOLE_PUTCHAR 1
+#define SBI_CONSOLE_GETCHAR 2
+#define SBI_CLEAR_IPI 3
+#define SBI_SEND_IPI 4
+#define SBI_REMOTE_FENCE_I 5
+#define SBI_REMOTE_SFENCE_VMA 6
+#define SBI_REMOTE_SFENCE_VMA_ASID 7
+#define SBI_SHUTDOWN 8
+
+#define SBI_CALL(which, arg0, arg1, arg2) ({                   \
+       register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0);   \
+       register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1);   \
+       register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2);   \
+       register uintptr_t a7 asm ("a7") = (uintptr_t)(which);  \
+       asm volatile ("ecall"                                   \
+                     : "+r" (a0)                               \
+                     : "r" (a1), "r" (a2), "r" (a7)            \
+                     : "memory");                              \
+       a0;                                                     \
+})
+
+/* Lazy implementations until SBI is finalized */
+#define SBI_CALL_0(which) SBI_CALL(which, 0, 0, 0)
+#define SBI_CALL_1(which, arg0) SBI_CALL(which, arg0, 0, 0)
+#define SBI_CALL_2(which, arg0, arg1) SBI_CALL(which, arg0, arg1, 0)
+
+static inline void sbi_console_putchar(int ch)
+{
+       SBI_CALL_1(SBI_CONSOLE_PUTCHAR, ch);
+}
+
+static inline int sbi_console_getchar(void)
+{
+       return SBI_CALL_0(SBI_CONSOLE_GETCHAR);
+}
+
+static inline void sbi_set_timer(uint64_t stime_value)
+{
+#if __riscv_xlen == 32
+       SBI_CALL_2(SBI_SET_TIMER, stime_value, stime_value >> 32);
+#else
+       SBI_CALL_1(SBI_SET_TIMER, stime_value);
+#endif
+}
+
+static inline void sbi_shutdown(void)
+{
+       SBI_CALL_0(SBI_SHUTDOWN);
+}
+
+static inline void sbi_clear_ipi(void)
+{
+       SBI_CALL_0(SBI_CLEAR_IPI);
+}
+
+static inline void sbi_send_ipi(const unsigned long *hart_mask)
+{
+       SBI_CALL_1(SBI_SEND_IPI, hart_mask);
+}
+
+static inline void sbi_remote_fence_i(const unsigned long *hart_mask)
+{
+       SBI_CALL_1(SBI_REMOTE_FENCE_I, hart_mask);
+}
+
+static inline void sbi_remote_sfence_vma(const unsigned long *hart_mask,
+                                        unsigned long start,
+                                        unsigned long size)
+{
+       SBI_CALL_1(SBI_REMOTE_SFENCE_VMA, hart_mask);
+}
+
+static inline void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask,
+                                             unsigned long start,
+                                             unsigned long size,
+                                             unsigned long asid)
+{
+       SBI_CALL_1(SBI_REMOTE_SFENCE_VMA_ASID, hart_mask);
+}
+
+#endif
diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h
new file mode 100644 (file)
index 0000000..bc863fd
--- /dev/null
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 Fraunhofer AISEC,
+ * Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+ */
+
+#ifndef _ASM_RISCV_SMP_H
+#define _ASM_RISCV_SMP_H
+
+/**
+ * struct ipi_data - Inter-processor interrupt (IPI) data structure
+ *
+ * IPIs are used for SMP support to communicate to other harts what function to
+ * call. Functions are in the form
+ * void (*addr)(ulong hart, ulong arg0, ulong arg1).
+ *
+ * The function address and the two arguments, arg0 and arg1, are stored in the
+ * IPI data structure. The hart ID is inserted by the hart handling the IPI and
+ * calling the function.
+ *
+ * @addr: Address of function
+ * @arg0: First argument of function
+ * @arg1: Second argument of function
+ */
+struct ipi_data {
+       ulong addr;
+       ulong arg0;
+       ulong arg1;
+};
+
+/**
+ * handle_ipi() - interrupt handler for software interrupts
+ *
+ * The IPI interrupt handler must be called to handle software interrupts. It
+ * calls the function specified in the hart's IPI data structure.
+ *
+ * @hart: Hart ID of the current hart
+ */
+void handle_ipi(ulong hart);
+
+/**
+ * smp_call_function() - Call a function on all other harts
+ *
+ * Send IPIs with the specified function call to all harts.
+ *
+ * @addr: Address of function
+ * @arg0: First argument of function
+ * @arg1: Second argument of function
+ * @return 0 if OK, -ve on error
+ */
+int smp_call_function(ulong addr, ulong arg0, ulong arg1);
+
+#endif
index d311ee6..26a008c 100644 (file)
@@ -8,12 +8,12 @@
 
 /*
  * System controllers in a RISC-V system
- *
- * So far only SiFive's Core Local Interruptor (CLINT) is defined.
  */
 enum {
        RISCV_NONE,
        RISCV_SYSCON_CLINT,     /* Core Local Interruptor (CLINT) */
+       RISCV_SYSCON_PLIC,      /* Platform Level Interrupt Controller (PLIC) */
+       RISCV_SYSCON_PLMT,      /* Platform Level Machine Timer (PLMT) */
 };
 
 #endif /* _ASM_SYSCON_H */
index edfa616..1c332db 100644 (file)
@@ -11,9 +11,13 @@ obj-$(CONFIG_CMD_GO) += boot.o
 obj-y  += cache.o
 obj-$(CONFIG_RISCV_RDTIME) += rdtime.o
 obj-$(CONFIG_SIFIVE_CLINT) += sifive_clint.o
+obj-$(CONFIG_ANDES_PLIC) += andes_plic.o
+obj-$(CONFIG_ANDES_PLMT) += andes_plmt.o
 obj-y  += interrupts.o
 obj-y  += reset.o
+obj-$(CONFIG_SBI_IPI) += sbi_ipi.o
 obj-y   += setjmp.o
+obj-$(CONFIG_SMP) += smp.o
 
 # For building EFI apps
 CFLAGS_$(EFI_CRT0) := $(CFLAGS_EFI)
diff --git a/arch/riscv/lib/andes_plic.c b/arch/riscv/lib/andes_plic.c
new file mode 100644 (file)
index 0000000..2ffe49a
--- /dev/null
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019, Rick Chen <rick@andestech.com>
+ *
+ * U-Boot syscon driver for Andes's Platform Level Interrupt Controller (PLIC).
+ * The PLIC block holds memory-mapped claim and pending registers
+ * associated with software interrupt.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/uclass-internal.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/syscon.h>
+#include <cpu.h>
+
+/* pending register */
+#define PENDING_REG(base, hart)        ((ulong)(base) + 0x1000 + (hart) * 8)
+/* enable register */
+#define ENABLE_REG(base, hart) ((ulong)(base) + 0x2000 + (hart) * 0x80)
+/* claim register */
+#define CLAIM_REG(base, hart)  ((ulong)(base) + 0x200004 + (hart) * 0x1000)
+
+#define ENABLE_HART_IPI         (0x80808080)
+#define SEND_IPI_TO_HART(hart)  (0x80 >> (hart))
+
+DECLARE_GLOBAL_DATA_PTR;
+static int init_plic(void);
+
+#define PLIC_BASE_GET(void)                                            \
+       do {                                                            \
+               long *ret;                                              \
+                                                                       \
+               if (!gd->arch.plic) {                                   \
+                       ret = syscon_get_first_range(RISCV_SYSCON_PLIC); \
+                       if (IS_ERR(ret))                                \
+                               return PTR_ERR(ret);                    \
+                       gd->arch.plic = ret;                            \
+                       init_plic();                                    \
+               }                                                       \
+       } while (0)
+
+static int enable_ipi(int harts)
+{
+       int i;
+       int en = ENABLE_HART_IPI;
+
+       for (i = 0; i < harts; i++) {
+               en = en >> i;
+               writel(en, (void __iomem *)ENABLE_REG(gd->arch.plic, i));
+       }
+
+       return 0;
+}
+
+static int init_plic(void)
+{
+       struct udevice *dev;
+       int ret;
+
+       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;
+
+               enable_ipi(ret);
+               return 0;
+       }
+
+       return -ENODEV;
+}
+
+int riscv_send_ipi(int hart)
+{
+       PLIC_BASE_GET();
+
+       writel(SEND_IPI_TO_HART(hart),
+              (void __iomem *)PENDING_REG(gd->arch.plic, gd->arch.boot_hart));
+
+       return 0;
+}
+
+int riscv_clear_ipi(int hart)
+{
+       u32 source_id;
+
+       PLIC_BASE_GET();
+
+       source_id = readl((void __iomem *)CLAIM_REG(gd->arch.plic, hart));
+       writel(source_id, (void __iomem *)CLAIM_REG(gd->arch.plic, hart));
+
+       return 0;
+}
+
+static const struct udevice_id andes_plic_ids[] = {
+       { .compatible = "riscv,plic1", .data = RISCV_SYSCON_PLIC },
+       { }
+};
+
+U_BOOT_DRIVER(andes_plic) = {
+       .name           = "andes_plic",
+       .id             = UCLASS_SYSCON,
+       .of_match       = andes_plic_ids,
+       .flags          = DM_FLAG_PRE_RELOC,
+};
diff --git a/arch/riscv/lib/andes_plmt.c b/arch/riscv/lib/andes_plmt.c
new file mode 100644 (file)
index 0000000..84f4607
--- /dev/null
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019, Rick Chen <rick@andestech.com>
+ *
+ * U-Boot syscon driver for Andes's Platform Level Machine Timer (PLMT).
+ * The PLMT block holds memory-mapped mtime register
+ * associated with timer tick.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/syscon.h>
+
+/* mtime register */
+#define MTIME_REG(base)                        ((ulong)(base))
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define PLMT_BASE_GET(void)                                            \
+       do {                                                            \
+               long *ret;                                              \
+                                                                       \
+               if (!gd->arch.plmt) {                                   \
+                       ret = syscon_get_first_range(RISCV_SYSCON_PLMT); \
+                       if (IS_ERR(ret))                                \
+                               return PTR_ERR(ret);                    \
+                       gd->arch.plmt = ret;                            \
+               }                                                       \
+       } while (0)
+
+int riscv_get_time(u64 *time)
+{
+       PLMT_BASE_GET();
+
+       *time = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
+
+       return 0;
+}
+
+static const struct udevice_id andes_plmt_ids[] = {
+       { .compatible = "riscv,plmt0", .data = RISCV_SYSCON_PLMT },
+       { }
+};
+
+U_BOOT_DRIVER(andes_plmt) = {
+       .name           = "andes_plmt",
+       .id             = UCLASS_SYSCON,
+       .of_match       = andes_plmt_ids,
+       .flags          = DM_FLAG_PRE_RELOC,
+};
index e0b71f5..f998402 100644 (file)
@@ -14,6 +14,7 @@
 int main(void)
 {
        DEFINE(GD_BOOT_HART, offsetof(gd_t, arch.boot_hart));
+       DEFINE(GD_AVAILABLE_HARTS, offsetof(gd_t, arch.available_harts));
 
        return 0;
 }
index f36b870..efbd3e2 100644 (file)
@@ -13,6 +13,7 @@
 #include <image.h>
 #include <asm/byteorder.h>
 #include <asm/csr.h>
+#include <asm/smp.h>
 #include <dm/device.h>
 #include <dm/root.h>
 #include <u-boot/zlib.h>
@@ -81,6 +82,9 @@ static void boot_jump_linux(bootm_headers_t *images, int flag)
 {
        void (*kernel)(ulong hart, void *dtb);
        int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
+#ifdef CONFIG_SMP
+       int ret;
+#endif
 
        kernel = (void (*)(ulong, void *))images->ep;
 
@@ -92,8 +96,15 @@ static void boot_jump_linux(bootm_headers_t *images, int flag)
        announce_and_cleanup(fake);
 
        if (!fake) {
-               if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
+               if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) {
+#ifdef CONFIG_SMP
+                       ret = smp_call_function(images->ep,
+                                               (ulong)images->ft_addr, 0);
+                       if (ret)
+                               hang();
+#endif
                        kernel(gd->arch.boot_hart, images->ft_addr);
+               }
        }
 }
 
diff --git a/arch/riscv/lib/sbi_ipi.c b/arch/riscv/lib/sbi_ipi.c
new file mode 100644 (file)
index 0000000..170346d
--- /dev/null
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Fraunhofer AISEC,
+ * Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+ */
+
+#include <common.h>
+#include <asm/sbi.h>
+
+int riscv_send_ipi(int hart)
+{
+       ulong mask;
+
+       mask = 1UL << hart;
+       sbi_send_ipi(&mask);
+
+       return 0;
+}
+
+int riscv_clear_ipi(int hart)
+{
+       sbi_clear_ipi();
+
+       return 0;
+}
diff --git a/arch/riscv/lib/smp.c b/arch/riscv/lib/smp.c
new file mode 100644 (file)
index 0000000..caa292c
--- /dev/null
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Fraunhofer AISEC,
+ * Lukas Auer <lukas.auer@aisec.fraunhofer.de>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/barrier.h>
+#include <asm/smp.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * riscv_send_ipi() - Send inter-processor interrupt (IPI)
+ *
+ * Platform code must provide this function.
+ *
+ * @hart: Hart ID of receiving hart
+ * @return 0 if OK, -ve on error
+ */
+extern int riscv_send_ipi(int hart);
+
+/**
+ * riscv_clear_ipi() - Clear inter-processor interrupt (IPI)
+ *
+ * Platform code must provide this function.
+ *
+ * @hart: Hart ID of hart to be cleared
+ * @return 0 if OK, -ve on error
+ */
+extern int riscv_clear_ipi(int hart);
+
+static int send_ipi_many(struct ipi_data *ipi)
+{
+       ofnode node, cpus;
+       u32 reg;
+       int ret;
+
+       cpus = ofnode_path("/cpus");
+       if (!ofnode_valid(cpus)) {
+               pr_err("Can't find cpus node!\n");
+               return -EINVAL;
+       }
+
+       ofnode_for_each_subnode(node, cpus) {
+               /* skip if hart is marked as not available in the device tree */
+               if (!ofnode_is_available(node))
+                       continue;
+
+               /* read hart ID of CPU */
+               ret = ofnode_read_u32(node, "reg", &reg);
+               if (ret)
+                       continue;
+
+               /* skip if it is the hart we are running on */
+               if (reg == gd->arch.boot_hart)
+                       continue;
+
+               if (reg >= CONFIG_NR_CPUS) {
+                       pr_err("Hart ID %d is out of range, increase CONFIG_NR_CPUS\n",
+                              reg);
+                       continue;
+               }
+
+               /* skip if hart is not available */
+               if (!(gd->arch.available_harts & (1 << reg)))
+                       continue;
+
+               gd->arch.ipi[reg].addr = ipi->addr;
+               gd->arch.ipi[reg].arg0 = ipi->arg0;
+               gd->arch.ipi[reg].arg1 = ipi->arg1;
+
+               ret = riscv_send_ipi(reg);
+               if (ret) {
+                       pr_err("Cannot send IPI to hart %d\n", reg);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+void handle_ipi(ulong hart)
+{
+       int ret;
+       void (*smp_function)(ulong hart, ulong arg0, ulong arg1);
+
+       if (hart >= CONFIG_NR_CPUS)
+               return;
+
+       ret = riscv_clear_ipi(hart);
+       if (ret) {
+               pr_err("Cannot clear IPI of hart %ld\n", hart);
+               return;
+       }
+
+       __smp_mb();
+
+       smp_function = (void (*)(ulong, ulong, ulong))gd->arch.ipi[hart].addr;
+       invalidate_icache_all();
+
+       smp_function(hart, gd->arch.ipi[hart].arg0, gd->arch.ipi[hart].arg1);
+}
+
+int smp_call_function(ulong addr, ulong arg0, ulong arg1)
+{
+       int ret = 0;
+       struct ipi_data ipi;
+
+       ipi.addr = addr;
+       ipi.arg0 = arg0;
+       ipi.arg1 = arg1;
+
+       ret = send_ipi_many(&ipi);
+
+       return ret;
+}
index 44cb302..5e682b6 100644 (file)
@@ -24,5 +24,6 @@ config ENV_OFFSET
 config BOARD_SPECIFIC_OPTIONS # dummy
        def_bool y
        select RISCV_NDS
+       imply SMP
 
 endif
index 65d50a9..96cb9c7 100644 (file)
@@ -120,7 +120,7 @@ int board_fix_fdt(void *blob)
 #endif
 
 #ifdef CONFIG_WDT_ARMADA_37XX
-static struct udevice *watchdog_dev;
+static struct udevice *watchdog_dev __attribute__((section(".data"))) = NULL;
 
 void watchdog_reset(void)
 {
index 1f7650c..c7f6479 100644 (file)
@@ -365,7 +365,7 @@ static bool disable_mcu_watchdog(void)
 #endif
 
 #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT_ORION)
-static struct udevice *watchdog_dev = NULL;
+static struct udevice *watchdog_dev __attribute__((section(".data"))) = NULL;
 #endif
 
 int board_init(void)
index 88d07d5..cf057e7 100644 (file)
@@ -34,5 +34,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
        imply BOARD_LATE_INIT
        imply OF_BOARD_SETUP
        imply SIFIVE_SERIAL
+       imply SMP
 
 endif
index 6be3d88..f464379 100644 (file)
@@ -38,5 +38,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
        imply PHY_LIB
        imply PHY_MSCC
        imply SIFIVE_SERIAL
+       imply SMP
 
 endif
index c946ec3..28c9efa 100644 (file)
@@ -25,7 +25,7 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT)
-static struct udevice *watchdog_dev;
+static struct udevice *watchdog_dev __attribute__((section(".data"))) = NULL;
 #endif /* !CONFIG_SPL_BUILD && CONFIG_WDT */
 
 ulong ram_base;
index b4b84df..ea26aad 100644 (file)
 DECLARE_GLOBAL_DATA_PTR;
 
 #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT)
-static struct udevice *watchdog_dev;
+static struct udevice *watchdog_dev __attribute__((section(".data"))) = NULL;
 #endif
 
 #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_BOARD_EARLY_INIT_F)
 int board_early_init_f(void)
 {
-# if defined(CONFIG_WDT)
-       /* bss is not cleared at time when watchdog_reset() is called */
-       watchdog_dev = NULL;
-# endif
-
        return 0;
 }
 #endif
index 5e1d211..db27247 100644 (file)
@@ -25,7 +25,7 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT)
-static struct udevice *watchdog_dev;
+static struct udevice *watchdog_dev __attribute__((section(".data"))) = NULL;
 #endif
 
 #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
@@ -322,11 +322,6 @@ int board_early_init_f(void)
        ret = psu_init();
 #endif
 
-#if defined(CONFIG_WDT) && !defined(CONFIG_SPL_BUILD)
-       /* bss is not cleared at time when watchdog_reset() is called */
-       watchdog_dev = NULL;
-#endif
-
        return ret;
 }
 
index 6e0be88..f029455 100644 (file)
@@ -34,4 +34,3 @@ CONFIG_BAUDRATE=38400
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
 CONFIG_ATCSPI200_SPI=y
-CONFIG_ATCPIT100_TIMER=y
index b472a76..98635a2 100644 (file)
@@ -35,4 +35,3 @@ CONFIG_BAUDRATE=38400
 CONFIG_SYS_NS16550=y
 CONFIG_SPI=y
 CONFIG_ATCSPI200_SPI=y
-CONFIG_ATCPIT100_TIMER=y
index f991b40..84f010d 100644 (file)
@@ -1309,6 +1309,8 @@ static void fec_gpio_reset(struct fec_priv *priv)
                dm_gpio_set_value(&priv->phy_reset_gpio, 1);
                mdelay(priv->reset_delay);
                dm_gpio_set_value(&priv->phy_reset_gpio, 0);
+               if (priv->reset_post_delay)
+                       mdelay(priv->reset_post_delay);
        }
 }
 #endif
@@ -1468,6 +1470,15 @@ static int fecmxc_ofdata_to_platdata(struct udevice *dev)
                /* property value wrong, use default value */
                priv->reset_delay = 1;
        }
+
+       priv->reset_post_delay = dev_read_u32_default(dev,
+                                                     "phy-reset-post-delay",
+                                                     0);
+       if (priv->reset_post_delay > 1000) {
+               printf("FEC MXC: phy reset post delay should be <= 1000ms\n");
+               /* property value wrong, use default value */
+               priv->reset_post_delay = 0;
+       }
 #endif
 
        return 0;
index e9a661f..e5f2dd7 100644 (file)
@@ -258,6 +258,7 @@ struct fec_priv {
 #ifdef CONFIG_DM_GPIO
        struct gpio_desc phy_reset_gpio;
        uint32_t reset_delay;
+       uint32_t reset_post_delay;
 #endif
 #ifdef CONFIG_DM_ETH
        u32 interface;
index 0c8b29d..4e8d294 100644 (file)
@@ -922,13 +922,14 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr,
 #endif
 {
        struct phy_device *phydev = NULL;
+       uint mask = (addr > 0) ? (1 << addr) : 0xffffffff;
 
 #ifdef CONFIG_PHY_FIXED
        phydev = phy_connect_fixed(bus, dev, interface);
 #endif
 
        if (!phydev)
-               phydev = phy_find_by_mask(bus, 1 << addr, interface);
+               phydev = phy_find_by_mask(bus, mask, interface);
 
        if (phydev)
                phy_connect_dev(phydev, dev);