diff options
author | Tom Rini <trini@konsulko.com> | 2020-10-05 13:05:46 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2020-10-05 14:10:59 -0400 |
commit | b7e7831e5d5be047f421ddc1f308afc22764a893 (patch) | |
tree | 7d5f27c82b260278ed0b3ea96bce592b0505b898 /arch/riscv/lib | |
parent | 050acee119b3757fee3bd128f55d720fdd9bb890 (diff) | |
parent | caebff09efe8c061b4d99b82262c67fb2db9bbcf (diff) | |
download | u-boot-b7e7831e5d5be047f421ddc1f308afc22764a893.tar.gz |
Merge branch 'next'
Bring in the assorted changes that have been staged in the 'next' branch
prior to release.
Signed-off-by: Tom Rini <trini@konsulko.com>
Diffstat (limited to 'arch/riscv/lib')
-rw-r--r-- | arch/riscv/lib/Makefile | 1 | ||||
-rw-r--r-- | arch/riscv/lib/andes_plic.c | 58 | ||||
-rw-r--r-- | arch/riscv/lib/andes_plmt.c | 44 | ||||
-rw-r--r-- | arch/riscv/lib/fdt_fixup.c | 2 | ||||
-rw-r--r-- | arch/riscv/lib/interrupts.c | 3 | ||||
-rw-r--r-- | arch/riscv/lib/rdtime.c | 38 | ||||
-rw-r--r-- | arch/riscv/lib/sifive_clint.c | 62 | ||||
-rw-r--r-- | arch/riscv/lib/smp.c | 16 |
8 files changed, 98 insertions, 126 deletions
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile index 6c503ff2b2..10ac5b06d3 100644 --- a/arch/riscv/lib/Makefile +++ b/arch/riscv/lib/Makefile @@ -15,7 +15,6 @@ obj-$(CONFIG_SIFIVE_CLINT) += sifive_clint.o obj-$(CONFIG_ANDES_PLIC) += andes_plic.o obj-$(CONFIG_ANDES_PLMT) += andes_plmt.o else -obj-$(CONFIG_RISCV_RDTIME) += rdtime.o obj-$(CONFIG_SBI) += sbi.o obj-$(CONFIG_SBI_IPI) += sbi_ipi.o endif diff --git a/arch/riscv/lib/andes_plic.c b/arch/riscv/lib/andes_plic.c index c2a8fe4d9e..267d6a191b 100644 --- a/arch/riscv/lib/andes_plic.c +++ b/arch/riscv/lib/andes_plic.c @@ -41,53 +41,45 @@ static int enable_ipi(int hart) return 0; } -static int init_plic(void) +int riscv_init_ipi(void) { - struct udevice *dev; - ofnode node; int ret; + long *base = syscon_get_first_range(RISCV_SYSCON_PLIC); + ofnode node; + struct udevice *dev; u32 reg; + if (IS_ERR(base)) + return PTR_ERR(base); + gd->arch.plic = base; + ret = uclass_find_first_device(UCLASS_CPU, &dev); if (ret) return ret; + else if (!dev) + return -ENODEV; - if (dev) { - 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; + ofnode_for_each_subnode(node, dev_ofnode(dev->parent)) { + const char *device_type; - if (strcmp(device_type, "cpu")) - continue; + device_type = ofnode_read_string(node, "device_type"); + if (!device_type) + continue; - /* skip if hart is marked as not available */ - if (!ofnode_is_available(node)) - continue; + if (strcmp(device_type, "cpu")) + continue; - /* read hart ID of CPU */ - ret = ofnode_read_u32(node, "reg", ®); - if (ret == 0) - enable_ipi(reg); - } + /* skip if hart is marked as not available */ + if (!ofnode_is_available(node)) + continue; - return 0; + /* read hart ID of CPU */ + ret = ofnode_read_u32(node, "reg", ®); + if (ret == 0) + enable_ipi(reg); } - return -ENODEV; -} - -int riscv_init_ipi(void) -{ - long *ret = syscon_get_first_range(RISCV_SYSCON_PLIC); - - if (IS_ERR(ret)) - return PTR_ERR(ret); - gd->arch.plic = ret; - - return init_plic(); + return 0; } int riscv_send_ipi(int hart) diff --git a/arch/riscv/lib/andes_plmt.c b/arch/riscv/lib/andes_plmt.c index a7e90ca992..a28c14c1eb 100644 --- a/arch/riscv/lib/andes_plmt.c +++ b/arch/riscv/lib/andes_plmt.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2019, Rick Chen <rick@andestech.com> + * Copyright (C) 2020, Sean Anderson <seanga2@gmail.com> * * U-Boot syscon driver for Andes's Platform Level Machine Timer (PLMT). * The PLMT block holds memory-mapped mtime register @@ -9,46 +10,43 @@ #include <common.h> #include <dm.h> -#include <regmap.h> -#include <syscon.h> +#include <timer.h> #include <asm/io.h> -#include <asm/syscon.h> #include <linux/err.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) +static int andes_plmt_get_count(struct udevice *dev, u64 *count) { - PLMT_BASE_GET(); - - *time = readq((void __iomem *)MTIME_REG(gd->arch.plmt)); + *count = readq((void __iomem *)MTIME_REG(dev->priv)); return 0; } +static const struct timer_ops andes_plmt_ops = { + .get_count = andes_plmt_get_count, +}; + +static int andes_plmt_probe(struct udevice *dev) +{ + dev->priv = dev_read_addr_ptr(dev); + if (!dev->priv) + return -EINVAL; + + return timer_timebase_fallback(dev); +} + static const struct udevice_id andes_plmt_ids[] = { - { .compatible = "riscv,plmt0", .data = RISCV_SYSCON_PLMT }, + { .compatible = "riscv,plmt0" }, { } }; U_BOOT_DRIVER(andes_plmt) = { .name = "andes_plmt", - .id = UCLASS_SYSCON, + .id = UCLASS_TIMER, .of_match = andes_plmt_ids, + .ops = &andes_plmt_ops, + .probe = andes_plmt_probe, .flags = DM_FLAG_PRE_RELOC, }; diff --git a/arch/riscv/lib/fdt_fixup.c b/arch/riscv/lib/fdt_fixup.c index 5b2420243f..d02062fd5b 100644 --- a/arch/riscv/lib/fdt_fixup.c +++ b/arch/riscv/lib/fdt_fixup.c @@ -75,7 +75,7 @@ int riscv_fdt_copy_resv_mem_node(const void *src, void *dst) pmp_mem.start = addr; pmp_mem.end = addr + size - 1; err = fdtdec_add_reserved_memory(dst, basename, &pmp_mem, - &phandle); + &phandle, false); if (err < 0 && err != -FDT_ERR_EXISTS) { log_err("failed to add reserved memory: %d\n", err); return err; diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c index 8ff40f0f36..35de98e8ce 100644 --- a/arch/riscv/lib/interrupts.c +++ b/arch/riscv/lib/interrupts.c @@ -78,7 +78,8 @@ static void _exit_trap(ulong code, ulong epc, ulong tval, struct pt_regs *regs) printf("EPC: " REG_FMT " RA: " REG_FMT " TVAL: " REG_FMT "\n", epc, regs->ra, tval); - if (gd->flags & GD_FLG_RELOC) + /* Print relocation adjustments, but only if gd is initialized */ + if (gd && gd->flags & GD_FLG_RELOC) printf("EPC: " REG_FMT " RA: " REG_FMT " reloc adjusted\n\n", epc - gd->reloc_off, regs->ra - gd->reloc_off); diff --git a/arch/riscv/lib/rdtime.c b/arch/riscv/lib/rdtime.c deleted file mode 100644 index e128d7fce6..0000000000 --- a/arch/riscv/lib/rdtime.c +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2018, Anup Patel <anup@brainfault.org> - * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com> - * - * The riscv_get_time() API implementation that is using the - * standard rdtime instruction. - */ - -#include <common.h> - -/* Implement the API required by RISC-V timer driver */ -int riscv_get_time(u64 *time) -{ -#ifdef CONFIG_64BIT - u64 n; - - __asm__ __volatile__ ( - "rdtime %0" - : "=r" (n)); - - *time = n; -#else - u32 lo, hi, tmp; - - __asm__ __volatile__ ( - "1:\n" - "rdtimeh %0\n" - "rdtime %1\n" - "rdtimeh %2\n" - "bne %0, %2, 1b" - : "=&r" (hi), "=&r" (lo), "=&r" (tmp)); - - *time = ((u64)hi << 32) | lo; -#endif - - return 0; -} diff --git a/arch/riscv/lib/sifive_clint.c b/arch/riscv/lib/sifive_clint.c index b9a2c649cc..c9704c596f 100644 --- a/arch/riscv/lib/sifive_clint.c +++ b/arch/riscv/lib/sifive_clint.c @@ -8,9 +8,9 @@ */ #include <common.h> +#include <clk.h> #include <dm.h> -#include <regmap.h> -#include <syscon.h> +#include <timer.h> #include <asm/io.h> #include <asm/syscon.h> #include <linux/err.h> @@ -24,68 +24,74 @@ DECLARE_GLOBAL_DATA_PTR; -int riscv_get_time(u64 *time) +int riscv_init_ipi(void) { - /* ensure timer register base has a sane value */ - riscv_init_ipi(); + int ret; + struct udevice *dev; + + ret = uclass_get_device_by_driver(UCLASS_TIMER, + DM_GET_DRIVER(sifive_clint), &dev); + if (ret) + return ret; - *time = readq((void __iomem *)MTIME_REG(gd->arch.clint)); + gd->arch.clint = dev_read_addr_ptr(dev); + if (!gd->arch.clint) + return -EINVAL; return 0; } -int riscv_set_timecmp(int hart, u64 cmp) +int riscv_send_ipi(int hart) { - /* ensure timer register base has a sane value */ - riscv_init_ipi(); - - writeq(cmp, (void __iomem *)MTIMECMP_REG(gd->arch.clint, hart)); + writel(1, (void __iomem *)MSIP_REG(gd->arch.clint, hart)); return 0; } -int riscv_init_ipi(void) +int riscv_clear_ipi(int hart) { - if (!gd->arch.clint) { - long *ret = syscon_get_first_range(RISCV_SYSCON_CLINT); - - if (IS_ERR(ret)) - return PTR_ERR(ret); - gd->arch.clint = ret; - } + writel(0, (void __iomem *)MSIP_REG(gd->arch.clint, hart)); return 0; } -int riscv_send_ipi(int hart) +int riscv_get_ipi(int hart, int *pending) { - writel(1, (void __iomem *)MSIP_REG(gd->arch.clint, hart)); + *pending = readl((void __iomem *)MSIP_REG(gd->arch.clint, hart)); return 0; } -int riscv_clear_ipi(int hart) +static int sifive_clint_get_count(struct udevice *dev, u64 *count) { - writel(0, (void __iomem *)MSIP_REG(gd->arch.clint, hart)); + *count = readq((void __iomem *)MTIME_REG(dev->priv)); return 0; } -int riscv_get_ipi(int hart, int *pending) +static const struct timer_ops sifive_clint_ops = { + .get_count = sifive_clint_get_count, +}; + +static int sifive_clint_probe(struct udevice *dev) { - *pending = readl((void __iomem *)MSIP_REG(gd->arch.clint, hart)); + dev->priv = dev_read_addr_ptr(dev); + if (!dev->priv) + return -EINVAL; - return 0; + return timer_timebase_fallback(dev); } static const struct udevice_id sifive_clint_ids[] = { - { .compatible = "riscv,clint0", .data = RISCV_SYSCON_CLINT }, + { .compatible = "riscv,clint0" }, { } }; U_BOOT_DRIVER(sifive_clint) = { .name = "sifive_clint", - .id = UCLASS_SYSCON, + .id = UCLASS_TIMER, .of_match = sifive_clint_ids, + .probe = sifive_clint_probe, + .ops = &sifive_clint_ops, .flags = DM_FLAG_PRE_RELOC, }; diff --git a/arch/riscv/lib/smp.c b/arch/riscv/lib/smp.c index ac22136314..8f33ce1fe3 100644 --- a/arch/riscv/lib/smp.c +++ b/arch/riscv/lib/smp.c @@ -54,6 +54,14 @@ static int send_ipi_many(struct ipi_data *ipi, int wait) gd->arch.ipi[reg].arg0 = ipi->arg0; gd->arch.ipi[reg].arg1 = ipi->arg1; + /* + * Ensure valid only becomes set when the IPI parameters are + * set. An IPI may already be pending on other harts, so we + * need a way to signal that the IPI device has been + * initialized, and that it is ok to call the function. + */ + __smp_store_release(&gd->arch.ipi[reg].valid, 1); + ret = riscv_send_ipi(reg); if (ret) { pr_err("Cannot send IPI to hart %d\n", reg); @@ -81,7 +89,13 @@ void handle_ipi(ulong hart) if (hart >= CONFIG_NR_CPUS) return; - __smp_mb(); + /* + * If valid is not set, then U-Boot has not requested the IPI. The + * IPI device may not be initialized, so all we can do is wait for + * U-Boot to initialize it and send an IPI + */ + if (!__smp_load_acquire(&gd->arch.ipi[hart].valid)) + return; smp_function = (void (*)(ulong, ulong, ulong))gd->arch.ipi[hart].addr; invalidate_icache_all(); |