blob: 8e49b6d7364d6a12ae557d8ea9e4ae57f445f182 [file] [log] [blame]
Bin Meng055700e2018-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
6#include <common.h>
Bin Meng7a3bbfb2018-12-12 06:12:34 -08007#include <cpu.h>
Bin Mengedfe9a92018-12-12 06:12:38 -08008#include <dm.h>
Heinrich Schuchardtcc382ff2021-09-12 21:11:46 +02009#include <dm/lists.h>
Simon Glass97589732020-05-10 11:40:02 -060010#include <init.h>
Bin Meng7a3bbfb2018-12-12 06:12:34 -080011#include <log.h>
Bin Menga7544ed2018-12-12 06:12:40 -080012#include <asm/encoding.h>
Bin Mengedfe9a92018-12-12 06:12:38 -080013#include <dm/uclass-internal.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060014#include <linux/bitops.h>
Bin Meng055700e2018-09-26 06:55:14 -070015
Lukas Auer39a652b2018-11-22 11:26:29 +010016/*
Lukas Auera3596652019-03-17 19:28:37 +010017 * The variables here must be stored in the data section since they are used
Lukas Auer39a652b2018-11-22 11:26:29 +010018 * before the bss section is available.
19 */
Rick Chen3043b902019-04-30 13:49:35 +080020#ifdef CONFIG_OF_PRIOR_STAGE
Marek BehĂșn4bebdd32021-05-20 13:23:52 +020021phys_addr_t prior_stage_fdt_address __section(".data");
Rick Chen3043b902019-04-30 13:49:35 +080022#endif
Rick Chene5e6c362019-04-30 13:49:33 +080023#ifndef CONFIG_XIP
Marek BehĂșn4bebdd32021-05-20 13:23:52 +020024u32 hart_lottery __section(".data") = 0;
Lukas Auera3596652019-03-17 19:28:37 +010025
26/*
27 * The main hart running U-Boot has acquired available_harts_lock until it has
28 * finished initialization of global data.
29 */
30u32 available_harts_lock = 1;
Rick Chene5e6c362019-04-30 13:49:33 +080031#endif
Lukas Auer39a652b2018-11-22 11:26:29 +010032
Bin Meng055700e2018-09-26 06:55:14 -070033static inline bool supports_extension(char ext)
34{
Bin Mengedfe9a92018-12-12 06:12:38 -080035#ifdef CONFIG_CPU
36 struct udevice *dev;
37 char desc[32];
38
39 uclass_find_first_device(UCLASS_CPU, &dev);
40 if (!dev) {
41 debug("unable to find the RISC-V cpu device\n");
42 return false;
43 }
44 if (!cpu_get_desc(dev, desc, sizeof(desc))) {
45 /* skip the first 4 characters (rv32|rv64) */
46 if (strchr(desc + 4, ext))
47 return true;
48 }
49
50 return false;
51#else /* !CONFIG_CPU */
Lukas Auer61346592019-08-21 21:14:43 +020052#if CONFIG_IS_ENABLED(RISCV_MMODE)
Bin Mengf9426362019-07-10 23:43:13 -070053 return csr_read(CSR_MISA) & (1 << (ext - 'a'));
Lukas Auer61346592019-08-21 21:14:43 +020054#else /* !CONFIG_IS_ENABLED(RISCV_MMODE) */
Bin Mengedfe9a92018-12-12 06:12:38 -080055#warning "There is no way to determine the available extensions in S-mode."
56#warning "Please convert your board to use the RISC-V CPU driver."
57 return false;
Lukas Auer61346592019-08-21 21:14:43 +020058#endif /* CONFIG_IS_ENABLED(RISCV_MMODE) */
Bin Mengedfe9a92018-12-12 06:12:38 -080059#endif /* CONFIG_CPU */
Bin Meng055700e2018-09-26 06:55:14 -070060}
61
Bin Meng7a3bbfb2018-12-12 06:12:34 -080062static int riscv_cpu_probe(void)
63{
64#ifdef CONFIG_CPU
65 int ret;
66
67 /* probe cpus so that RISC-V timer can be bound */
68 ret = cpu_probe_all();
69 if (ret)
70 return log_msg_ret("RISC-V cpus probe failed\n", ret);
71#endif
72
73 return 0;
74}
75
Sean Andersondd1cd702020-09-21 07:51:38 -040076/*
77 * This is called on secondary harts just after the IPI is init'd. Currently
78 * there's nothing to do, since we just need to clear any existing IPIs, and
79 * that is handled by the sending of an ipi itself.
80 */
81#if CONFIG_IS_ENABLED(SMP)
82static void dummy_pending_ipi_clear(ulong hart, ulong arg0, ulong arg1)
83{
84}
85#endif
86
Bin Meng7a3bbfb2018-12-12 06:12:34 -080087int arch_cpu_init_dm(void)
88{
Bin Menga7544ed2018-12-12 06:12:40 -080089 int ret;
90
91 ret = riscv_cpu_probe();
92 if (ret)
93 return ret;
94
95 /* Enable FPU */
96 if (supports_extension('d') || supports_extension('f')) {
97 csr_set(MODE_PREFIX(status), MSTATUS_FS);
Bin Mengf9426362019-07-10 23:43:13 -070098 csr_write(CSR_FCSR, 0);
Bin Menga7544ed2018-12-12 06:12:40 -080099 }
100
101 if (CONFIG_IS_ENABLED(RISCV_MMODE)) {
102 /*
103 * Enable perf counters for cycle, time,
104 * and instret counters only
105 */
Sean Anderson7f4b6662020-06-24 06:41:19 -0400106#ifdef CONFIG_RISCV_PRIV_1_9
107 csr_write(CSR_MSCOUNTEREN, GENMASK(2, 0));
108 csr_write(CSR_MUCOUNTEREN, GENMASK(2, 0));
109#else
Bin Mengf9426362019-07-10 23:43:13 -0700110 csr_write(CSR_MCOUNTEREN, GENMASK(2, 0));
Sean Anderson7f4b6662020-06-24 06:41:19 -0400111#endif
Bin Menga7544ed2018-12-12 06:12:40 -0800112
113 /* Disable paging */
114 if (supports_extension('s'))
Sean Anderson7f4b6662020-06-24 06:41:19 -0400115#ifdef CONFIG_RISCV_PRIV_1_9
116 csr_read_clear(CSR_MSTATUS, SR_VM);
117#else
Bin Mengf9426362019-07-10 23:43:13 -0700118 csr_write(CSR_SATP, 0);
Sean Anderson7f4b6662020-06-24 06:41:19 -0400119#endif
Bin Menga7544ed2018-12-12 06:12:40 -0800120 }
121
Bin Meng257875d2020-07-19 23:17:07 -0700122#if CONFIG_IS_ENABLED(SMP)
Sean Andersonb1d0cb32020-06-24 06:41:18 -0400123 ret = riscv_init_ipi();
124 if (ret)
125 return ret;
Sean Andersondd1cd702020-09-21 07:51:38 -0400126
127 /*
128 * Clear all pending IPIs on secondary harts. We don't do anything on
129 * the boot hart, since we never send an IPI to ourselves, and no
130 * interrupts are enabled
131 */
132 ret = smp_call_function((ulong)dummy_pending_ipi_clear, 0, 0, 0);
133 if (ret)
134 return ret;
Sean Andersonb1d0cb32020-06-24 06:41:18 -0400135#endif
136
Bin Menga7544ed2018-12-12 06:12:40 -0800137 return 0;
Bin Meng7a3bbfb2018-12-12 06:12:34 -0800138}
139
140int arch_early_init_r(void)
141{
Heinrich Schuchardtcc382ff2021-09-12 21:11:46 +0200142 int ret;
143
144 ret = riscv_cpu_probe();
145 if (ret)
146 return ret;
147
148 if (IS_ENABLED(CONFIG_SYSRESET_SBI))
149 device_bind_driver(gd->dm_root, "sbi-sysreset",
150 "sbi-sysreset", NULL);
151
152 return 0;
Bin Meng7a3bbfb2018-12-12 06:12:34 -0800153}
Green Wan26120802021-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}