source: rtems/bsps/riscv/riscv/console/console-config.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: 9.0 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup RTEMSBSPsRISCVGeneric
7 *
8 * @brief This source file contains definitions of
9 *   ::BSP_output_char_function_type and :: BSP_output_char and an
10 *   implementation of console_initialize().
11 */
12
13/*
14 * Copyright (C) 2018 embedded brains GmbH (http://www.embedded-brains.de)
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 *    notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 *    notice, this list of conditions and the following disclaimer in the
23 *    documentation and/or other materials provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifdef HAVE_CONFIG_H
39#include "config.h"
40#endif
41
42#include <rtems/bspIo.h>
43#include <rtems/console.h>
44#include <rtems/sysinit.h>
45#include <rtems/termiostypes.h>
46
47#include <bsp/fatal.h>
48#include <bsp/fdt.h>
49#include <bsp/irq.h>
50#include <bsp/riscv.h>
51
52#include <dev/serial/htif.h>
53#include <libchip/ns16550.h>
54
55#include <libfdt.h>
56#include <string.h>
57
58#if RISCV_ENABLE_SIFIVE_UART_SUPPORT != 0
59#include <bsp/fe310-uart.h>
60static fe310_uart_context fe310_uart_instance;
61#endif
62
63#ifdef RISCV_ENABLE_HTIF_SUPPORT
64static htif_console_context htif_console_instance;
65#endif
66
67#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
68static ns16550_context ns16550_instances[RISCV_CONSOLE_MAX_NS16550_DEVICES];
69#endif
70
71static struct {
72  rtems_termios_device_context *context;
73  void (*putchar)(rtems_termios_device_context *base, char c);
74  int (*getchar)(rtems_termios_device_context *base);
75} riscv_console;
76
77static void riscv_output_char(char c)
78{
79  (*riscv_console.putchar)(riscv_console.context, c);
80}
81
82static int riscv_get_console_node(const void *fdt)
83{
84  const char *stdout_path;
85  int node;
86
87  node = fdt_path_offset(fdt, "/chosen");
88
89  stdout_path = fdt_getprop(fdt, node, "stdout-path", NULL);
90  if (stdout_path == NULL) {
91    stdout_path = "";
92  }
93
94#if RISCV_ENABLE_FRDME310ARTY_SUPPORT != 0
95  int root;
96  int soc;
97  root = fdt_path_offset(fdt, "/");
98  soc = fdt_subnode_offset(fdt, root, "soc");
99
100  int offset=fdt_subnode_offset(fdt, soc,stdout_path);
101
102  return offset;
103#else
104  return fdt_path_offset(fdt, stdout_path);
105#endif
106}
107
108#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
109static uint8_t riscv_console_get_reg_8(uintptr_t addr, uint8_t i)
110{
111  volatile uint8_t *reg;
112
113  reg = (uint8_t *) addr;
114  return reg[i];
115}
116
117static void riscv_console_set_reg_8(uintptr_t addr, uint8_t i, uint8_t val)
118{
119  volatile uint8_t *reg;
120
121  reg = (uint8_t *)addr;
122  reg[i] = val;
123}
124
125static uint8_t riscv_console_get_reg_32(uintptr_t addr, uint8_t i)
126{
127  volatile uint32_t *reg;
128
129  reg = (uint32_t *) addr;
130  return reg[i];
131}
132
133static void riscv_console_set_reg_32(uintptr_t addr, uint8_t i, uint8_t val)
134{
135  volatile uint32_t *reg;
136
137  reg = (uint32_t *)addr;
138  reg[i] = val;
139}
140#endif
141
142static void riscv_console_probe(void)
143{
144  const void *fdt;
145  int node;
146  int console_node;
147#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
148  size_t ns16550_devices;
149#endif
150
151  fdt = bsp_fdt_get();
152  console_node = riscv_get_console_node(fdt);
153#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
154  ns16550_devices = 0;
155#endif
156
157  node = fdt_next_node(fdt, -1, NULL);
158
159  while (node >= 0) {
160    const char *compat;
161    int compat_len;
162
163    compat = fdt_getprop(fdt, node, "compatible", &compat_len);
164    if (compat == NULL) {
165      compat_len = 0;
166    }
167
168#ifdef RISCV_ENABLE_HTIF_SUPPORT
169    /* Search for HTIF (eg. on Spike) and use it if found */
170    if (fdt_stringlist_contains(compat, compat_len, "ucb,htif0")) {
171      htif_console_context_init(&htif_console_instance.base, node);
172
173      riscv_console.context = &htif_console_instance.base;
174      riscv_console.putchar = htif_console_putchar;
175      riscv_console.getchar = htif_console_getchar;
176    };
177#endif
178
179#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
180    if (
181        (fdt_stringlist_contains(compat, compat_len, "ns16550a")
182        || fdt_stringlist_contains(compat, compat_len, "ns16750"))
183        && ns16550_devices < RISCV_CONSOLE_MAX_NS16550_DEVICES
184    ) {
185      ns16550_context *ctx;
186      fdt32_t *val;
187      int len;
188
189      ctx = &ns16550_instances[ns16550_devices];
190      ctx->initial_baud = BSP_CONSOLE_BAUD;
191
192      /* Get register shift property of the UART device */
193      val = (fdt32_t *) fdt_getprop(fdt, node, "reg-shift", &len);
194
195      if (val != NULL && fdt32_to_cpu(val[0]) == 2) {
196        ctx->get_reg = riscv_console_get_reg_32;
197        ctx->set_reg = riscv_console_set_reg_32;
198      } else {
199        ctx->get_reg = riscv_console_get_reg_8;
200        ctx->set_reg = riscv_console_set_reg_8;
201      }
202
203      if (fdt_stringlist_contains(compat, compat_len, "ns16750")) {
204        ctx->has_precision_clock_synthesizer = true;
205      }
206
207      ctx->port = (uintptr_t) riscv_fdt_get_address(fdt, node);
208
209      if (ctx->port == 0) {
210        bsp_fatal(RISCV_FATAL_NO_NS16550_REG_IN_DEVICE_TREE);
211      }
212
213      val = (fdt32_t *) fdt_getprop(fdt, node, "clock-frequency", &len);
214
215      if (val == NULL || len != 4) {
216        bsp_fatal(RISCV_FATAL_NO_NS16550_CLOCK_FREQUENCY_IN_DEVICE_TREE);
217      }
218
219      ctx->clock = fdt32_to_cpu(val[0]);
220
221      val = (fdt32_t *) fdt_getprop(fdt, node, "interrupts", &len);
222
223      if (val == NULL || len != 4) {
224        bsp_fatal(RISCV_FATAL_NO_NS16550_INTERRUPTS_IN_DEVICE_TREE);
225      }
226
227      ctx->irq = RISCV_INTERRUPT_VECTOR_EXTERNAL(fdt32_to_cpu(val[0]));
228
229      if (node == console_node) {
230        riscv_console.context = &ctx->base;
231        riscv_console.putchar = ns16550_polled_putchar;
232        riscv_console.getchar = ns16550_polled_getchar;
233      }
234
235      rtems_termios_device_context_initialize(&ctx->base, "NS16550");
236      ns16550_probe(&ctx->base);
237
238      ++ns16550_devices;
239    }
240#endif
241
242#if RISCV_ENABLE_SIFIVE_UART_SUPPORT != 0
243    if (fdt_stringlist_contains(compat, compat_len, "sifive,uart0")) {
244      fe310_uart_context *ctx;
245
246      ctx = &fe310_uart_instance;
247      ctx->regs = riscv_fdt_get_address(fdt, node);
248      if (ctx->regs == NULL) {
249        bsp_fatal(RISCV_FATAL_NO_NS16550_REG_IN_DEVICE_TREE);
250      }
251
252      if (node == console_node) {
253        riscv_console.context = &ctx->base;
254        riscv_console.putchar = fe310_console_putchar;
255        riscv_console.getchar = fe310_uart_read;
256      }
257
258      rtems_termios_device_context_initialize(&ctx->base, "SIFIVEUART");
259    }
260#endif
261
262    node = fdt_next_node(fdt, node, NULL);
263  }
264
265  BSP_output_char = riscv_output_char;
266}
267
268static void riscv_output_char_init(char c)
269{
270  riscv_console_probe();
271  riscv_output_char(c);
272}
273
274BSP_output_char_function_type BSP_output_char = riscv_output_char_init;
275
276BSP_polling_getchar_function_type BSP_poll_char = NULL;
277
278rtems_status_code console_initialize(
279  rtems_device_major_number major,
280  rtems_device_minor_number minor,
281  void *arg
282)
283{
284#ifdef RISCV_ENABLE_HTIF_SUPPORT
285  rtems_termios_device_context *base;
286  char htif_path[] = "/dev/ttyShtif";
287#endif
288#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
289  char path[] = "/dev/ttyS?";
290  size_t i;
291#endif
292
293#if RISCV_ENABLE_SIFIVE_UART_SUPPORT != 0
294  fe310_uart_context *ctx;
295  char fe310_path[] = "/dev/ttyS0";
296#endif
297
298  rtems_termios_initialize();
299
300#ifdef RISCV_ENABLE_HTIF_SUPPORT
301  base = &htif_console_instance.base;
302  rtems_termios_device_install(htif_path, &htif_console_handler, NULL, base);
303
304  if (base == riscv_console.context) {
305    link(htif_path, CONSOLE_DEVICE_NAME);
306  }
307#endif
308
309#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
310  for (i = 0; i < RISCV_CONSOLE_MAX_NS16550_DEVICES; ++i) {
311    ns16550_context *ctx;
312
313    ctx = &ns16550_instances[i];
314    path[sizeof(path) - 2] = (char) ('0' + i);
315
316    rtems_termios_device_install(
317      path,
318      &ns16550_handler_interrupt,
319      NULL,
320      &ctx->base
321    );
322
323    if (&ctx->base == riscv_console.context) {
324      link(path, CONSOLE_DEVICE_NAME);
325    }
326  }
327#endif
328
329#if RISCV_ENABLE_SIFIVE_UART_SUPPORT != 0
330  ctx = &fe310_uart_instance;
331  rtems_termios_device_install(
332    fe310_path,
333    &fe310_uart_handler,
334    NULL,
335    &ctx->base
336  );
337
338  if (&ctx->base == riscv_console.context) {
339    link(fe310_path, CONSOLE_DEVICE_NAME);
340  }
341#endif
342
343  return RTEMS_SUCCESSFUL;
344}
345
346RTEMS_SYSINIT_ITEM(
347  riscv_console_probe,
348  RTEMS_SYSINIT_BSP_START,
349  RTEMS_SYSINIT_ORDER_LAST_BUT_5
350);
Note: See TracBrowser for help on using the repository browser.