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

Last change on this file since 88b80a5f was 88b80a5f, checked in by Hesham Almatary <hesham.almatary@…>, on 12/18/22 at 15:07:16

RISC-V: Always probe for HTIF and remove RISCV_ENABLE_HTIF_SUPPORT

Updates #4779

  • Property mode set to 100644
File size: 8.8 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
63static htif_console_context htif_console_instance;
64
65#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
66static ns16550_context ns16550_instances[RISCV_CONSOLE_MAX_NS16550_DEVICES];
67#endif
68
69static struct {
70  rtems_termios_device_context *context;
71  void (*putchar)(rtems_termios_device_context *base, char c);
72  int (*getchar)(rtems_termios_device_context *base);
73} riscv_console;
74
75static void riscv_output_char(char c)
76{
77  (*riscv_console.putchar)(riscv_console.context, c);
78}
79
80static int riscv_get_console_node(const void *fdt)
81{
82  const char *stdout_path;
83  int node;
84
85  node = fdt_path_offset(fdt, "/chosen");
86
87  stdout_path = fdt_getprop(fdt, node, "stdout-path", NULL);
88  if (stdout_path == NULL) {
89    stdout_path = "";
90  }
91
92#if RISCV_ENABLE_FRDME310ARTY_SUPPORT != 0
93  int root;
94  int soc;
95  root = fdt_path_offset(fdt, "/");
96  soc = fdt_subnode_offset(fdt, root, "soc");
97
98  int offset=fdt_subnode_offset(fdt, soc,stdout_path);
99
100  return offset;
101#else
102  return fdt_path_offset(fdt, stdout_path);
103#endif
104}
105
106#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
107static uint8_t riscv_console_get_reg_8(uintptr_t addr, uint8_t i)
108{
109  volatile uint8_t *reg;
110
111  reg = (uint8_t *) addr;
112  return reg[i];
113}
114
115static void riscv_console_set_reg_8(uintptr_t addr, uint8_t i, uint8_t val)
116{
117  volatile uint8_t *reg;
118
119  reg = (uint8_t *)addr;
120  reg[i] = val;
121}
122
123static uint8_t riscv_console_get_reg_32(uintptr_t addr, uint8_t i)
124{
125  volatile uint32_t *reg;
126
127  reg = (uint32_t *) addr;
128  return reg[i];
129}
130
131static void riscv_console_set_reg_32(uintptr_t addr, uint8_t i, uint8_t val)
132{
133  volatile uint32_t *reg;
134
135  reg = (uint32_t *)addr;
136  reg[i] = val;
137}
138#endif
139
140static void riscv_console_probe(void)
141{
142  const void *fdt;
143  int node;
144  int console_node;
145#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
146  size_t ns16550_devices;
147#endif
148
149  fdt = bsp_fdt_get();
150  console_node = riscv_get_console_node(fdt);
151#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
152  ns16550_devices = 0;
153#endif
154
155  node = fdt_next_node(fdt, -1, NULL);
156
157  while (node >= 0) {
158    const char *compat;
159    int compat_len;
160
161    compat = fdt_getprop(fdt, node, "compatible", &compat_len);
162    if (compat == NULL) {
163      compat_len = 0;
164    }
165
166    /* Search for HTIF (eg. on Spike) and use it if found */
167    if (fdt_stringlist_contains(compat, compat_len, "ucb,htif0")) {
168      htif_console_context_init(&htif_console_instance.base, node);
169
170      riscv_console.context = &htif_console_instance.base;
171      riscv_console.putchar = htif_console_putchar;
172      riscv_console.getchar = htif_console_getchar;
173    };
174
175#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
176    if (
177        (fdt_stringlist_contains(compat, compat_len, "ns16550a")
178        || fdt_stringlist_contains(compat, compat_len, "ns16750"))
179        && ns16550_devices < RISCV_CONSOLE_MAX_NS16550_DEVICES
180    ) {
181      ns16550_context *ctx;
182      fdt32_t *val;
183      int len;
184
185      ctx = &ns16550_instances[ns16550_devices];
186      ctx->initial_baud = BSP_CONSOLE_BAUD;
187
188      /* Get register shift property of the UART device */
189      val = (fdt32_t *) fdt_getprop(fdt, node, "reg-shift", &len);
190
191      if (val != NULL && fdt32_to_cpu(val[0]) == 2) {
192        ctx->get_reg = riscv_console_get_reg_32;
193        ctx->set_reg = riscv_console_set_reg_32;
194      } else {
195        ctx->get_reg = riscv_console_get_reg_8;
196        ctx->set_reg = riscv_console_set_reg_8;
197      }
198
199      if (fdt_stringlist_contains(compat, compat_len, "ns16750")) {
200        ctx->has_precision_clock_synthesizer = true;
201      }
202
203      ctx->port = (uintptr_t) riscv_fdt_get_address(fdt, node);
204
205      if (ctx->port == 0) {
206        bsp_fatal(RISCV_FATAL_NO_NS16550_REG_IN_DEVICE_TREE);
207      }
208
209      val = (fdt32_t *) fdt_getprop(fdt, node, "clock-frequency", &len);
210
211      if (val == NULL || len != 4) {
212        bsp_fatal(RISCV_FATAL_NO_NS16550_CLOCK_FREQUENCY_IN_DEVICE_TREE);
213      }
214
215      ctx->clock = fdt32_to_cpu(val[0]);
216
217      val = (fdt32_t *) fdt_getprop(fdt, node, "interrupts", &len);
218
219      if (val == NULL || len != 4) {
220        bsp_fatal(RISCV_FATAL_NO_NS16550_INTERRUPTS_IN_DEVICE_TREE);
221      }
222
223      ctx->irq = RISCV_INTERRUPT_VECTOR_EXTERNAL(fdt32_to_cpu(val[0]));
224
225      if (node == console_node) {
226        riscv_console.context = &ctx->base;
227        riscv_console.putchar = ns16550_polled_putchar;
228        riscv_console.getchar = ns16550_polled_getchar;
229      }
230
231      rtems_termios_device_context_initialize(&ctx->base, "NS16550");
232      ns16550_probe(&ctx->base);
233
234      ++ns16550_devices;
235    }
236#endif
237
238#if RISCV_ENABLE_FRDME310ARTY_SUPPORT != 0
239    if (fdt_stringlist_contains(compat, compat_len, "sifive,uart0")) {
240      fe310_uart_context *ctx;
241
242      ctx = &fe310_uart_instance;
243      ctx->regs = riscv_fdt_get_address(fdt, node);
244      if (ctx->regs == NULL) {
245        bsp_fatal(RISCV_FATAL_NO_NS16550_REG_IN_DEVICE_TREE);
246      }
247
248      if (node == console_node) {
249        riscv_console.context = &ctx->base;
250        riscv_console.putchar = fe310_console_putchar;
251        riscv_console.getchar = fe310_uart_read;
252      }
253
254      rtems_termios_device_context_initialize(&ctx->base, "FE310UART");
255    }
256#endif
257
258    node = fdt_next_node(fdt, node, NULL);
259  }
260
261  BSP_output_char = riscv_output_char;
262}
263
264static void riscv_output_char_init(char c)
265{
266  riscv_console_probe();
267  riscv_output_char(c);
268}
269
270BSP_output_char_function_type BSP_output_char = riscv_output_char_init;
271
272BSP_polling_getchar_function_type BSP_poll_char = NULL;
273
274rtems_status_code console_initialize(
275  rtems_device_major_number major,
276  rtems_device_minor_number minor,
277  void *arg
278)
279{
280  rtems_termios_device_context *base;
281  char htif_path[] = "/dev/ttyShtif";
282
283#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
284  char path[] = "/dev/ttyS?";
285  size_t i;
286#endif
287
288#if RISCV_ENABLE_FRDME310ARTY_SUPPORT != 0
289  fe310_uart_context *ctx;
290  char fe310_path[] = "/dev/ttyS0";
291#endif
292
293  rtems_termios_initialize();
294
295  base = &htif_console_instance.base;
296  rtems_termios_device_install(htif_path, &htif_console_handler, NULL, base);
297
298  if (base == riscv_console.context) {
299    link(htif_path, CONSOLE_DEVICE_NAME);
300  }
301
302#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
303  for (i = 0; i < RISCV_CONSOLE_MAX_NS16550_DEVICES; ++i) {
304    ns16550_context *ctx;
305
306    ctx = &ns16550_instances[i];
307    path[sizeof(path) - 2] = (char) ('0' + i);
308
309    rtems_termios_device_install(
310      path,
311      &ns16550_handler_interrupt,
312      NULL,
313      &ctx->base
314    );
315
316    if (&ctx->base == riscv_console.context) {
317      link(path, CONSOLE_DEVICE_NAME);
318    }
319  }
320#endif
321
322#if RISCV_ENABLE_FRDME310ARTY_SUPPORT != 0
323  ctx = &fe310_uart_instance;
324  rtems_termios_device_install(
325    fe310_path,
326    &fe310_uart_handler,
327    NULL,
328    &ctx->base
329  );
330
331  if (&ctx->base == riscv_console.context) {
332    link(fe310_path, CONSOLE_DEVICE_NAME);
333  }
334#endif
335
336  return RTEMS_SUCCESSFUL;
337}
338
339RTEMS_SYSINIT_ITEM(
340  riscv_console_probe,
341  RTEMS_SYSINIT_BSP_START,
342  RTEMS_SYSINIT_ORDER_LAST_BUT_5
343);
Note: See TracBrowser for help on using the repository browser.