source: rtems/bsps/riscv/riscv/console/console-config.c @ d46366a

Last change on this file since d46366a was d46366a, checked in by Sebastian Huber <sebastian.huber@…>, on 01/11/23 at 07:27:40

riscv: Resurrect RISCV_ENABLE_HTIF_SUPPORT

Low-end configurations may want to have the HTIF support removed.
Enable the option by default. Fix formatting. Fix node validity
checks.

Updates #4779.

  • 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_FRDME310ARTY_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_FRDME310ARTY_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, "FE310UART");
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_FRDME310ARTY_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_FRDME310ARTY_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.