source: rtems/bsps/riscv/riscv/start/bspstart.c @ cbddf5de

Last change on this file since cbddf5de was cbddf5de, checked in by Sebastian Huber <sebastian.huber@…>, on 03/15/23 at 13:31:20

bsps/riscv: Fix riscv_get_hart_index_by_phandle()

Take a non-zero RISCV_BOOT_HARTID into account.

  • Property mode set to 100644
File size: 5.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  return 0;
213}
214
215uint32_t riscv_get_core_frequency(void)
216{
217  return riscv_core_freq;
218}
219
220uint32_t bsp_fdt_map_intr(const uint32_t *intr, size_t icells)
221{
222  (void) icells;
223  return RISCV_INTERRUPT_VECTOR_EXTERNAL(intr[0]);
224}
225
226void bsp_start(void)
227{
228  riscv_find_harts();
229  bsp_interrupt_initialize();
230  riscv_core_freq = get_core_frequency();
231}
Note: See TracBrowser for help on using the repository browser.