source: rtems/bsps/riscv/riscv/start/bspstart.c @ 26853a06

Last change on this file since 26853a06 was 26853a06, checked in by Alan Cudmore <alan.cudmore@…>, on 03/15/23 at 13:41:53

bsps/riscv: add riscv/kendrytek210 BSP variant source changes

This patch adds support for the Kendryte K210 RISC-V BSP variant.
The SoC uses the existing Interrupt Controller, Timer, and console UART.
It only needs SoC specific initialization and an embedded device tree binary
similar to the polarfire SoC BSP.

Updates #4876

  • Property mode set to 100644
File size: 6.4 KB
Line 
1/*
2 * Copyright (c) 2018 embedded brains GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#include <bsp/bootcard.h>
27#include <bsp/fatal.h>
28#include <bsp/fdt.h>
29#include <bsp/irq-generic.h>
30#include <bsp/riscv.h>
31
32#include <libfdt.h>
33#include <string.h>
34
35static uint32_t riscv_core_freq;
36
37void *riscv_fdt_get_address(const void *fdt, int node)
38{
39  int parent;
40  int ac;
41  int len;
42  const uint32_t *reg;
43  uint64_t addr;
44
45  parent = fdt_parent_offset(fdt, node);
46  if (parent < 0) {
47    return NULL;
48  }
49
50  ac = fdt_address_cells(fdt, parent);
51  if (ac != 1 && ac != 2) {
52    return NULL;
53  }
54
55  reg = fdt_getprop(fdt, node, "reg", &len);
56  if (reg == NULL || len < ac) {
57    return NULL;
58  }
59
60  addr = 0;
61
62  while (ac > 0) {
63    addr = (addr << 32) | fdt32_to_cpu(*reg);
64    ++reg;
65    --ac;
66  }
67
68#if __riscv_xlen < 64
69  if (addr > 0xffffffff) {
70    return NULL;
71  }
72#endif
73
74  return (void *)(uintptr_t) addr;
75}
76
77#if RISCV_ENABLE_MPFS_SUPPORT != 0
78uint32_t riscv_hart_count;
79static uint32_t riscv_hart_phandles[5];
80#else
81#ifdef RTEMS_SMP
82uint32_t riscv_hart_count;
83
84static uint32_t riscv_hart_phandles[CPU_MAXIMUM_PROCESSORS];
85#else
86static uint32_t riscv_hart_phandles[1];
87#endif
88#endif
89
90static void riscv_find_harts(void)
91{
92  const void *fdt;
93  int node;
94  uint32_t max_hart_index;
95
96  fdt = bsp_fdt_get();
97  max_hart_index = 0;
98  node = -1;
99
100  while ((node = fdt_node_offset_by_compatible(fdt, node, "riscv")) >= 0) {
101    int subnode;
102    const uint32_t *val;
103    int len;
104    uint32_t phandle;
105    uint32_t hart_index;
106
107    val = fdt_getprop(fdt, node, "reg", &len);
108    if (val == NULL || len != 4) {
109      bsp_fatal(RISCV_FATAL_INVALID_HART_REG_IN_DEVICE_TREE);
110    }
111
112    hart_index = fdt32_to_cpu(val[0]);
113
114#if RISCV_BOOT_HARTID != 0
115    if (hart_index < RISCV_BOOT_HARTID) {
116      continue;
117    }
118
119    hart_index -= RISCV_BOOT_HARTID;
120#endif
121
122    if (hart_index >= RTEMS_ARRAY_SIZE(riscv_hart_phandles)) {
123      continue;
124    }
125
126    if (hart_index > max_hart_index) {
127      max_hart_index = hart_index;
128    }
129
130    phandle = 0;
131
132    fdt_for_each_subnode(subnode, fdt, node) {
133      int propoff;
134      bool interrupt_controller;
135      uint32_t potential_phandle;
136
137      interrupt_controller = false;
138      potential_phandle = 0;
139
140      fdt_for_each_property_offset(propoff, fdt, subnode) {
141        const char *name;
142
143        val = fdt_getprop_by_offset(fdt, propoff, &name, &len);
144        if (val != NULL) {
145          if (strcmp(name, "interrupt-controller") == 0) {
146            interrupt_controller = true;
147          } else if (len == 4 && strcmp(name, "phandle") == 0) {
148            potential_phandle = fdt32_to_cpu(val[0]);
149          }
150        }
151      }
152
153      if (interrupt_controller) {
154        phandle = potential_phandle;
155        break;
156      }
157    }
158
159    riscv_hart_phandles[hart_index] = phandle;
160  }
161
162#if RISCV_ENABLE_MPFS_SUPPORT != 0
163  riscv_hart_count = max_hart_index + 1;
164#else
165#ifdef RTEMS_SMP
166  riscv_hart_count = max_hart_index + 1;
167#endif
168#endif
169}
170
171uint32_t riscv_get_hart_index_by_phandle(uint32_t phandle)
172{
173  uint32_t hart_index;
174
175  for (hart_index = 0; hart_index < riscv_hart_count; ++hart_index) {
176    if (riscv_hart_phandles[hart_index] == phandle) {
177      return hart_index + RISCV_BOOT_HARTID;
178    }
179  }
180
181  return UINT32_MAX;
182}
183
184static uint32_t get_core_frequency(void)
185{
186#if RISCV_ENABLE_FRDME310ARTY_SUPPORT != 0 || RISCV_ENABLE_MPFS_SUPPORT != 0
187  uint32_t node;
188  const char *fdt;
189  const char *tlclk;
190  int len;
191  const fdt32_t *val;
192
193  fdt = bsp_fdt_get();
194  node = fdt_node_offset_by_compatible(fdt, -1,"fixed-clock");
195  tlclk = fdt_getprop(fdt, node, "clock-output-names", &len);
196
197#if RISCV_ENABLE_FRDME310ARTY_SUPPORT != 0
198  if (strcmp(tlclk,"tlclk") != 0)
199#endif
200#if RISCV_ENABLE_MPFS_SUPPORT != 0
201  if (strcmp(tlclk,"msspllclk") != 0)
202#endif
203  {
204    bsp_fatal(RISCV_FATAL_NO_TLCLOCK_FREQUENCY_IN_DEVICE_TREE);
205  }
206
207  val = fdt_getprop(fdt, node, "clock-frequency", &len);
208  if (val != NULL && len == 4) {
209    return fdt32_to_cpu(*val);
210  }
211#endif
212
213#if RISCV_ENABLE_KENDRYTE_K210_SUPPORT != 0
214  uint32_t cpu_clock;
215
216  cpu_clock = k210_get_frequency();
217  return cpu_clock;
218#else
219  return 0;
220#endif
221
222}
223
224uint32_t riscv_get_core_frequency(void)
225{
226  return riscv_core_freq;
227}
228
229uint32_t bsp_fdt_map_intr(const uint32_t *intr, size_t icells)
230{
231  (void) icells;
232  return RISCV_INTERRUPT_VECTOR_EXTERNAL(intr[0]);
233}
234
235#if RISCV_ENABLE_KENDRYTE_K210_SUPPORT != 0
236uint32_t k210_get_frequency(void)
237{
238  k210_sysctl_t *sysctl = (k210_sysctl_t *)K210_SYSCTL_BASE;
239  uint32_t cpu_clock = 0;
240  uint32_t clk_freq;
241  uint32_t pll0, nr, nf, od;
242  uint32_t node;
243  const char *fdt;
244  const fdt32_t *val;
245  int len;
246
247  fdt = bsp_fdt_get();
248  node = fdt_node_offset_by_compatible(fdt, -1,"fixed-clock");
249  val = fdt_getprop(fdt, node, "clock-frequency", &len);
250  if (val != NULL && len == 4) {
251    clk_freq = fdt32_to_cpu(*val);
252
253    if (CLKSEL0_ACLK_SEL(sysctl->clk_sel0) == 1) {
254       /* PLL0 selected */
255       pll0 = sysctl->pll0;
256       nr = PLL_CLK_R(pll0) + 1;
257       nf = PLL_CLK_F(pll0) + 1;
258       od = PLL_CLK_OD(pll0) + 1;
259       cpu_clock = (clk_freq / nr * nf / od)/2;
260    } else {
261       /* OSC selected */
262       cpu_clock = clk_freq;
263    }
264  }
265  return cpu_clock;
266}
267#endif
268
269void bsp_start(void)
270{
271  riscv_find_harts();
272  bsp_interrupt_initialize();
273  riscv_core_freq = get_core_frequency();
274}
Note: See TracBrowser for help on using the repository browser.