From ab24017a19b482d9026d21a2ec03416c5c4a388d Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 24 Jun 2020 06:41:21 -0400 Subject: riscv: Try to get cpu frequency from a "clocks" node if it exists Instead of always using the "clock-frequency" property to determine cpu frequency, try using a clock in "clocks" if it exists. This patch also fixes a bug where there could be spurious higher frequencies if sizeof(u32) != sizeof(ulong). Signed-off-by: Sean Anderson Reviewed-by: Bin Meng --- drivers/cpu/riscv_cpu.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers/cpu') diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c index cb04f5638db..2d44d1c17b1 100644 --- a/drivers/cpu/riscv_cpu.c +++ b/drivers/cpu/riscv_cpu.c @@ -3,6 +3,7 @@ * Copyright (C) 2018, Bin Meng */ +#include #include #include #include @@ -11,6 +12,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -29,9 +31,24 @@ static int riscv_cpu_get_desc(struct udevice *dev, char *buf, int size) static int riscv_cpu_get_info(struct udevice *dev, struct cpu_info *info) { + int ret; + struct clk clk; const char *mmu; - dev_read_u32(dev, "clock-frequency", (u32 *)&info->cpu_freq); + /* Zero out the frequency, in case sizeof(ulong) != sizeof(u32) */ + info->cpu_freq = 0; + + /* First try getting the frequency from the assigned clock */ + ret = clk_get_by_index(dev, 0, &clk); + if (!ret) { + ret = clk_get_rate(&clk); + if (!IS_ERR_VALUE(ret)) + info->cpu_freq = ret; + clk_free(&clk); + } + + if (!info->cpu_freq) + dev_read_u32(dev, "clock-frequency", (u32 *)&info->cpu_freq); mmu = dev_read_string(dev, "mmu-type"); if (!mmu) -- cgit v1.3.1 From 627718626b05f715da555cc005426ab10f44bb98 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 24 Jun 2020 06:41:22 -0400 Subject: riscv: Enable cpu clock if it is present The cpu clock is probably already enabled if we are executing code (though we could be executing from a different core). This patch prevents the cpu clock or its parents from being disabled. Signed-off-by: Sean Anderson Reviewed-by: Bin Meng --- drivers/cpu/riscv_cpu.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/cpu') diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c index 2d44d1c17b1..76b0489d2a0 100644 --- a/drivers/cpu/riscv_cpu.c +++ b/drivers/cpu/riscv_cpu.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2018, Bin Meng + * Copyright (C) 2020, Sean Anderson */ #include @@ -119,6 +120,24 @@ static int riscv_cpu_bind(struct udevice *dev) return 0; } +static int riscv_cpu_probe(struct udevice *dev) +{ + int ret = 0; + struct clk clk; + + /* Get a clock if it exists */ + ret = clk_get_by_index(dev, 0, &clk); + if (ret) + return 0; + + ret = clk_enable(&clk); + clk_free(&clk); + if (ret == -ENOSYS || ret == -ENOTSUPP) + return 0; + else + return ret; +} + static const struct cpu_ops riscv_cpu_ops = { .get_desc = riscv_cpu_get_desc, .get_info = riscv_cpu_get_info, @@ -135,6 +154,7 @@ U_BOOT_DRIVER(riscv_cpu) = { .id = UCLASS_CPU, .of_match = riscv_cpu_ids, .bind = riscv_cpu_bind, + .probe = riscv_cpu_probe, .ops = &riscv_cpu_ops, .flags = DM_FLAG_PRE_RELOC, }; -- cgit v1.3.1 From 969251a5a4d3515abc233621bc8ca6f1c93d6dd4 Mon Sep 17 00:00:00 2001 From: Sagar Shrikant Kadam Date: Sun, 28 Jun 2020 07:45:01 -0700 Subject: uclass: cpu: fix to display proper CPU features The cmd "cpu detail" fetches uninitialized cpu feature information and thus displays wrong / inconsitent details as below. For eg: FU540-C000 doesn't have any microcode, yet the cmd display's it. => cpu detail 1: cpu@1 rv64imafdc ID = 1, freq = 999.100 MHz: L1 cache, MMU, Microcode, Device ID Microcode version 0x0 Device ID 0x0 2: cpu@2 rv64imafdc ID = 2, freq = 999.100 MHz: L1 cache, MMU, Microcode, Device ID Microcode version 0x0 Device ID 0x0 3: cpu@3 rv64imafdc ID = 3, freq = 999.100 MHz: L1 cache, MMU, Microcode, Device ID Microcode version 0x0 Device ID 0x0 4: cpu@4 rv64imafdc ID = 4, freq = 999.100 MHz: L1 cache, MMU, Microcode, Device ID Microcode version 0x0 Device ID 0x0 The L1 cache or MMU entry seen above is also displayed inconsistently. So initialize cpu information to zero into cpu-uclass itself so that similar issues can be avoided for other CPU drivers. We now see correct features as: => cpu detail 1: cpu@1 rv64imafdc ID = 1, freq = 999.100 MHz 2: cpu@2 rv64imafdc ID = 2, freq = 999.100 MHz 3: cpu@3 rv64imafdc ID = 3, freq = 999.100 MHz 4: cpu@4 rv64imafdc ID = 4, freq = 999.100 MHz Signed-off-by: Sagar Shrikant Kadam Reviewed-by: Pragnesh Patel Reviewed-by: Bin Meng --- drivers/cpu/cpu-uclass.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/cpu') diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c index 7418c26ed8b..cbb4419ec0c 100644 --- a/drivers/cpu/cpu-uclass.c +++ b/drivers/cpu/cpu-uclass.c @@ -86,6 +86,9 @@ int cpu_get_info(struct udevice *dev, struct cpu_info *info) if (!ops->get_info) return -ENOSYS; + /* Init cpu_info to 0 */ + memset(info, 0, sizeof(struct cpu_info)); + return ops->get_info(dev, info); } -- cgit v1.3.1 From b6b233ddb78205abc76dde60179bd129368dc3e8 Mon Sep 17 00:00:00 2001 From: Sagar Shrikant Kadam Date: Sun, 28 Jun 2020 07:45:02 -0700 Subject: riscv: cpu: correctly handle the setting of CPU_FEAT_MMU bit The conditional check to read "mmu-type" from the device tree is not rightly handled due to which the cpu feature doesn't include CPU_FEAT_MMU even if it's corresponding entry is present in the device tree. The initialization of cpu features is now taken care in cpu-uclass driver, so no need to zero out cpu_freq in riscv_cpu driver and can be removed. Signed-off-by: Sagar Shrikant Kadam Reviewed-by: Pragnesh Patel Reviewed-by: Bin Meng --- drivers/cpu/riscv_cpu.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/cpu') diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c index 76b0489d2a0..112690fe3a4 100644 --- a/drivers/cpu/riscv_cpu.c +++ b/drivers/cpu/riscv_cpu.c @@ -36,9 +36,6 @@ static int riscv_cpu_get_info(struct udevice *dev, struct cpu_info *info) struct clk clk; const char *mmu; - /* Zero out the frequency, in case sizeof(ulong) != sizeof(u32) */ - info->cpu_freq = 0; - /* First try getting the frequency from the assigned clock */ ret = clk_get_by_index(dev, 0, &clk); if (!ret) { @@ -52,7 +49,7 @@ static int riscv_cpu_get_info(struct udevice *dev, struct cpu_info *info) dev_read_u32(dev, "clock-frequency", (u32 *)&info->cpu_freq); mmu = dev_read_string(dev, "mmu-type"); - if (!mmu) + if (mmu) info->features |= BIT(CPU_FEAT_MMU); return 0; -- cgit v1.3.1 From add0dc1f7de91112d9e738f9482b09b75fa86acb Mon Sep 17 00:00:00 2001 From: Sagar Shrikant Kadam Date: Sun, 28 Jun 2020 07:45:03 -0700 Subject: riscv: cpu: check and append L1 cache to cpu features All cpu cores within FU540-C000 having split I/D caches. Set the L1 cache feature bit using the i-cache-size or d-cache-size as one of the property from device tree indicating that L1 cache is present on the cpu core. => cpu detail 1: cpu@1 rv64imafdc ID = 1, freq = 999.100 MHz: L1 cache, MMU 2: cpu@2 rv64imafdc ID = 2, freq = 999.100 MHz: L1 cache, MMU 3: cpu@3 rv64imafdc ID = 3, freq = 999.100 MHz: L1 cache, MMU 4: cpu@4 rv64imafdc ID = 4, freq = 999.100 MHz: L1 cache, MMU Signed-off-by: Sagar Shrikant Kadam Reviewed-by: Pragnesh Patel Reviewed-by: Bin Meng --- drivers/cpu/riscv_cpu.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/cpu') diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c index 112690fe3a4..100fe5542e4 100644 --- a/drivers/cpu/riscv_cpu.c +++ b/drivers/cpu/riscv_cpu.c @@ -35,6 +35,8 @@ static int riscv_cpu_get_info(struct udevice *dev, struct cpu_info *info) int ret; struct clk clk; const char *mmu; + u32 i_cache_size; + u32 d_cache_size; /* First try getting the frequency from the assigned clock */ ret = clk_get_by_index(dev, 0, &clk); @@ -52,6 +54,16 @@ static int riscv_cpu_get_info(struct udevice *dev, struct cpu_info *info) if (mmu) info->features |= BIT(CPU_FEAT_MMU); + /* check if I cache is present */ + ret = dev_read_u32(dev, "i-cache-size", &i_cache_size); + if (ret) + /* if not found check if d-cache is present */ + ret = dev_read_u32(dev, "d-cache-size", &d_cache_size); + + /* if either I or D cache is present set L1 cache feature */ + if (!ret) + info->features |= BIT(CPU_FEAT_L1_CACHE); + return 0; } -- cgit v1.3.1