blob: ebd39cb41a60a11113a95c0b9ba1a731df5c957d [file] [log] [blame]
Bin Meng2fab2e92018-09-26 06:55:14 -07001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
4 */
5
Bin Meng39cad5b2018-12-12 06:12:34 -08006#include <cpu.h>
Bin Mengaef59e52018-12-12 06:12:38 -08007#include <dm.h>
Heinrich Schuchardt24ed5312021-09-12 21:11:46 +02008#include <dm/lists.h>
Simon Glass7fe32b32022-03-04 08:43:05 -07009#include <event.h>
Simon Glass691d7192020-05-10 11:40:02 -060010#include <init.h>
Bin Meng39cad5b2018-12-12 06:12:34 -080011#include <log.h>
Bin Meng485e8222018-12-12 06:12:40 -080012#include <asm/encoding.h>
Simon Glass7fe32b32022-03-04 08:43:05 -070013#include <asm/system.h>
Bin Mengaef59e52018-12-12 06:12:38 -080014#include <dm/uclass-internal.h>
Simon Glasscd93d622020-05-10 11:40:13 -060015#include <linux/bitops.h>
Bin Meng2fab2e92018-09-26 06:55:14 -070016
Lukas Auer5d8b2e72018-11-22 11:26:29 +010017/*
Lukas Auer3dea63c2019-03-17 19:28:37 +010018 * The variables here must be stored in the data section since they are used
Lukas Auer5d8b2e72018-11-22 11:26:29 +010019 * before the bss section is available.
20 */
Nikita Shubinc2bdf022022-09-02 11:47:39 +030021#if !CONFIG_IS_ENABLED(XIP)
Marek BehĂșn236f2ec2021-05-20 13:23:52 +020022u32 hart_lottery __section(".data") = 0;
Lukas Auer3dea63c2019-03-17 19:28:37 +010023
Rick Chene0465f82022-09-21 14:34:54 +080024#ifdef CONFIG_AVAILABLE_HARTS
Lukas Auer3dea63c2019-03-17 19:28:37 +010025/*
26 * The main hart running U-Boot has acquired available_harts_lock until it has
27 * finished initialization of global data.
28 */
29u32 available_harts_lock = 1;
Rick Chenbdce3892019-04-30 13:49:33 +080030#endif
Rick Chene0465f82022-09-21 14:34:54 +080031#endif
Lukas Auer5d8b2e72018-11-22 11:26:29 +010032
Bin Meng2fab2e92018-09-26 06:55:14 -070033static inline bool supports_extension(char ext)
34{
Nikita Shubin81b56a52022-12-14 08:58:43 +030035#if CONFIG_IS_ENABLED(RISCV_MMODE)
36 return csr_read(CSR_MISA) & (1 << (ext - 'a'));
37#elif CONFIG_CPU
Bin Mengaef59e52018-12-12 06:12:38 -080038 struct udevice *dev;
39 char desc[32];
Yu Chien Peter Linc277c782022-11-05 14:02:14 +080040 int i;
Bin Mengaef59e52018-12-12 06:12:38 -080041
42 uclass_find_first_device(UCLASS_CPU, &dev);
43 if (!dev) {
44 debug("unable to find the RISC-V cpu device\n");
45 return false;
46 }
47 if (!cpu_get_desc(dev, desc, sizeof(desc))) {
Yu Chien Peter Linc277c782022-11-05 14:02:14 +080048 /*
49 * skip the first 4 characters (rv32|rv64) and
50 * check until underscore
51 */
52 for (i = 4; i < sizeof(desc); i++) {
53 if (desc[i] == '_' || desc[i] == '\0')
54 break;
55 if (desc[i] == ext)
56 return true;
57 }
Bin Mengaef59e52018-12-12 06:12:38 -080058 }
59
60 return false;
61#else /* !CONFIG_CPU */
Bin Mengaef59e52018-12-12 06:12:38 -080062#warning "There is no way to determine the available extensions in S-mode."
63#warning "Please convert your board to use the RISC-V CPU driver."
64 return false;
Bin Mengaef59e52018-12-12 06:12:38 -080065#endif /* CONFIG_CPU */
Bin Meng2fab2e92018-09-26 06:55:14 -070066}
67
Tom Rini68f446f2023-09-04 15:06:34 -040068static int riscv_cpu_probe(void)
Bin Meng39cad5b2018-12-12 06:12:34 -080069{
70#ifdef CONFIG_CPU
71 int ret;
72
73 /* probe cpus so that RISC-V timer can be bound */
74 ret = cpu_probe_all();
75 if (ret)
76 return log_msg_ret("RISC-V cpus probe failed\n", ret);
77#endif
78
79 return 0;
80}
Tom Rini68f446f2023-09-04 15:06:34 -040081EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_R, riscv_cpu_probe);
Bin Meng39cad5b2018-12-12 06:12:34 -080082
Sean Anderson768502e2020-09-21 07:51:38 -040083/*
84 * This is called on secondary harts just after the IPI is init'd. Currently
85 * there's nothing to do, since we just need to clear any existing IPIs, and
86 * that is handled by the sending of an ipi itself.
87 */
88#if CONFIG_IS_ENABLED(SMP)
89static void dummy_pending_ipi_clear(ulong hart, ulong arg0, ulong arg1)
90{
91}
92#endif
93
Simon Glassf72d0d42023-08-21 21:16:56 -060094int riscv_cpu_setup(void)
Bin Meng39cad5b2018-12-12 06:12:34 -080095{
Tom Rini59d2a7d2023-09-04 15:06:35 -040096 int __maybe_unused ret;
Bin Meng485e8222018-12-12 06:12:40 -080097
98 /* Enable FPU */
99 if (supports_extension('d') || supports_extension('f')) {
100 csr_set(MODE_PREFIX(status), MSTATUS_FS);
Bin Meng4d2583d2019-07-10 23:43:13 -0700101 csr_write(CSR_FCSR, 0);
Bin Meng485e8222018-12-12 06:12:40 -0800102 }
103
104 if (CONFIG_IS_ENABLED(RISCV_MMODE)) {
105 /*
106 * Enable perf counters for cycle, time,
107 * and instret counters only
108 */
Nikita Shubin81b56a52022-12-14 08:58:43 +0300109 if (supports_extension('u')) {
Sean Andersonb8bc1202020-06-24 06:41:19 -0400110#ifdef CONFIG_RISCV_PRIV_1_9
Nikita Shubin81b56a52022-12-14 08:58:43 +0300111 csr_write(CSR_MSCOUNTEREN, GENMASK(2, 0));
112 csr_write(CSR_MUCOUNTEREN, GENMASK(2, 0));
Sean Andersonb8bc1202020-06-24 06:41:19 -0400113#else
Nikita Shubin81b56a52022-12-14 08:58:43 +0300114 csr_write(CSR_MCOUNTEREN, GENMASK(2, 0));
Sean Andersonb8bc1202020-06-24 06:41:19 -0400115#endif
Nikita Shubin81b56a52022-12-14 08:58:43 +0300116 }
Bin Meng485e8222018-12-12 06:12:40 -0800117
118 /* Disable paging */
119 if (supports_extension('s'))
Sean Andersonb8bc1202020-06-24 06:41:19 -0400120#ifdef CONFIG_RISCV_PRIV_1_9
121 csr_read_clear(CSR_MSTATUS, SR_VM);
122#else
Bin Meng4d2583d2019-07-10 23:43:13 -0700123 csr_write(CSR_SATP, 0);
Sean Andersonb8bc1202020-06-24 06:41:19 -0400124#endif
Bin Meng485e8222018-12-12 06:12:40 -0800125 }
126
Bin Menga0018fc2020-07-19 23:17:07 -0700127#if CONFIG_IS_ENABLED(SMP)
Sean Anderson40686c32020-06-24 06:41:18 -0400128 ret = riscv_init_ipi();
129 if (ret)
130 return ret;
Sean Anderson768502e2020-09-21 07:51:38 -0400131
132 /*
133 * Clear all pending IPIs on secondary harts. We don't do anything on
134 * the boot hart, since we never send an IPI to ourselves, and no
135 * interrupts are enabled
136 */
137 ret = smp_call_function((ulong)dummy_pending_ipi_clear, 0, 0, 0);
138 if (ret)
139 return ret;
Sean Anderson40686c32020-06-24 06:41:18 -0400140#endif
141
Bin Meng485e8222018-12-12 06:12:40 -0800142 return 0;
Bin Meng39cad5b2018-12-12 06:12:34 -0800143}
Simon Glassf72d0d42023-08-21 21:16:56 -0600144EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_F, riscv_cpu_setup);
Bin Meng39cad5b2018-12-12 06:12:34 -0800145
146int arch_early_init_r(void)
147{
Heinrich Schuchardt24ed5312021-09-12 21:11:46 +0200148 if (IS_ENABLED(CONFIG_SYSRESET_SBI))
149 device_bind_driver(gd->dm_root, "sbi-sysreset",
150 "sbi-sysreset", NULL);
151
152 return 0;
Bin Meng39cad5b2018-12-12 06:12:34 -0800153}
Green Wanedd9ad82021-05-02 23:23:04 -0700154
155/**
156 * harts_early_init() - A callback function called by start.S to configure
157 * feature settings of each hart.
158 *
159 * In a multi-core system, memory access shall be careful here, it shall
160 * take care of race conditions.
161 */
162__weak void harts_early_init(void)
163{
164}