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

5
Last change on this file since c344e58 was c344e58, checked in by Sebastian Huber <sebastian.huber@…>, on 02/02/20 at 10:00:54

Use RTEMS_SYSINIT_ORDER_LAST_BUT_5

Use RTEMS_SYSINIT_ORDER_LAST_BUT_5 instead of RTEMS_SYSINIT_ORDER_LAST
to allow applications and support functions to place system
initialization handlers behind the standard handlers.

Update #3838.

  • Property mode set to 100644
File size: 7.8 KB
Line 
1/*
2 * Copyright (c) 2018 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <info@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#include <rtems/bspIo.h>
16#include <rtems/console.h>
17#include <rtems/sysinit.h>
18#include <rtems/termiostypes.h>
19
20#include <bsp/fatal.h>
21#include <bsp/fdt.h>
22#include <bsp/irq.h>
23#include <bsp/riscv.h>
24
25#include <dev/serial/htif.h>
26#include <libchip/ns16550.h>
27
28#include <libfdt.h>
29#include <string.h>
30
31#if RISCV_ENABLE_FRDME310ARTY_SUPPORT != 0
32#include <bsp/fe310-uart.h>
33fe310_uart_context fe310_uart_instance;
34#endif
35
36#if RISCV_ENABLE_HTIF_SUPPORT != 0
37static htif_console_context htif_console_instance;
38#endif
39
40#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
41static ns16550_context ns16550_instances[RISCV_CONSOLE_MAX_NS16550_DEVICES];
42#endif
43
44static struct {
45  rtems_termios_device_context *context;
46  void (*putchar)(rtems_termios_device_context *base, char c);
47  int (*getchar)(rtems_termios_device_context *base);
48} riscv_console;
49
50static void riscv_output_char(char c)
51{
52  (*riscv_console.putchar)(riscv_console.context, c);
53}
54
55static int riscv_get_console_node(const void *fdt)
56{
57  const char *stdout_path;
58  int node;
59
60  node = fdt_path_offset(fdt, "/chosen");
61
62  stdout_path = fdt_getprop(fdt, node, "stdout-path", NULL);
63  if (stdout_path == NULL) {
64    stdout_path = "";
65  }
66
67#if RISCV_ENABLE_FRDME310ARTY_SUPPORT != 0
68  int root;
69  int soc;
70  root = fdt_path_offset(fdt, "/");
71  soc = fdt_subnode_offset(fdt, root, "soc");
72
73  int offset=fdt_subnode_offset(fdt, soc,stdout_path);
74
75  return offset;
76#else
77  return fdt_path_offset(fdt, stdout_path);
78#endif
79}
80
81#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
82static uint8_t riscv_console_get_reg_8(uintptr_t addr, uint8_t i)
83{
84  volatile uint8_t *reg;
85
86  reg = (uint8_t *) addr;
87  return reg[i];
88}
89
90static void riscv_console_set_reg_8(uintptr_t addr, uint8_t i, uint8_t val)
91{
92  volatile uint8_t *reg;
93
94  reg = (uint8_t *)addr;
95  reg[i] = val;
96}
97
98static uint8_t riscv_console_get_reg_32(uintptr_t addr, uint8_t i)
99{
100  volatile uint32_t *reg;
101
102  reg = (uint32_t *) addr;
103  return reg[i];
104}
105
106static void riscv_console_set_reg_32(uintptr_t addr, uint8_t i, uint8_t val)
107{
108  volatile uint32_t *reg;
109
110  reg = (uint32_t *)addr;
111  reg[i] = val;
112}
113#endif
114
115#define RISCV_CONSOLE_IS_COMPATIBLE(actual, actual_len, desired) \
116  (actual_len == sizeof(desired) \
117     && memcmp(actual, desired, sizeof(desired) - 1) == 0)
118
119static void riscv_console_probe(void)
120{
121  const void *fdt;
122  int node;
123  int console_node;
124#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
125  size_t ns16550_devices;
126#endif
127
128  fdt = bsp_fdt_get();
129  console_node = riscv_get_console_node(fdt);
130#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
131  ns16550_devices = 0;
132#endif
133
134  node = fdt_next_node(fdt, -1, NULL);
135
136  while (node >= 0) {
137    const char *compat;
138    int compat_len;
139
140    compat = fdt_getprop(fdt, node, "compatible", &compat_len);
141    if (compat == NULL) {
142      compat_len = 0;
143    }
144
145#if RISCV_ENABLE_HTIF_SUPPORT != 0
146    if (RISCV_CONSOLE_IS_COMPATIBLE(compat, compat_len, "ucb,htif0")) {
147      htif_console_context_init(&htif_console_instance.base, node);
148
149      riscv_console.context = &htif_console_instance.base;
150      riscv_console.putchar = htif_console_putchar;
151      riscv_console.getchar = htif_console_getchar;
152    };
153#endif
154
155#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
156    if (
157      (RISCV_CONSOLE_IS_COMPATIBLE(compat, compat_len, "ns16550a")
158          || RISCV_CONSOLE_IS_COMPATIBLE(compat, compat_len, "ns16750"))
159        && ns16550_devices < RISCV_CONSOLE_MAX_NS16550_DEVICES
160    ) {
161      ns16550_context *ctx;
162      fdt32_t *val;
163      int len;
164
165      ctx = &ns16550_instances[ns16550_devices];
166      ctx->initial_baud = BSP_CONSOLE_BAUD;
167
168      /* Get register shift property of the UART device */
169      val = (fdt32_t *) fdt_getprop(fdt, node, "reg-shift", &len);
170
171      if (val != NULL && fdt32_to_cpu(val[0]) == 2) {
172        ctx->get_reg = riscv_console_get_reg_32;
173        ctx->set_reg = riscv_console_set_reg_32;
174      } else {
175        ctx->get_reg = riscv_console_get_reg_8;
176        ctx->set_reg = riscv_console_set_reg_8;
177      }
178
179      if (RISCV_CONSOLE_IS_COMPATIBLE(compat, compat_len, "ns16750")) {
180        ctx->has_precision_clock_synthesizer = true;
181      }
182
183      ctx->port = (uintptr_t) riscv_fdt_get_address(fdt, node);
184
185      if (ctx->port == 0) {
186        bsp_fatal(RISCV_FATAL_NO_NS16550_REG_IN_DEVICE_TREE);
187      }
188
189      val = (fdt32_t *) fdt_getprop(fdt, node, "clock-frequency", &len);
190
191      if (val == NULL || len != 4) {
192        bsp_fatal(RISCV_FATAL_NO_NS16550_CLOCK_FREQUENCY_IN_DEVICE_TREE);
193      }
194
195      ctx->clock = fdt32_to_cpu(val[0]);
196
197      val = (fdt32_t *) fdt_getprop(fdt, node, "interrupts", &len);
198
199      if (val == NULL || len != 4) {
200        bsp_fatal(RISCV_FATAL_NO_NS16550_INTERRUPTS_IN_DEVICE_TREE);
201      }
202
203      ctx->irq = RISCV_INTERRUPT_VECTOR_EXTERNAL(fdt32_to_cpu(val[0]));
204
205      if (node == console_node) {
206        riscv_console.context = &ctx->base;
207        riscv_console.putchar = ns16550_polled_putchar;
208        riscv_console.getchar = ns16550_polled_getchar;
209      }
210
211      rtems_termios_device_context_initialize(&ctx->base, "NS16550");
212      ns16550_probe(&ctx->base);
213
214      ++ns16550_devices;
215    }
216#endif
217
218#if RISCV_ENABLE_FRDME310ARTY_SUPPORT != 0
219    if (RISCV_CONSOLE_IS_COMPATIBLE(compat, compat_len, "sifive,uart0")) {
220      fe310_uart_context *ctx;
221
222      ctx = &fe310_uart_instance;
223      ctx->regs = riscv_fdt_get_address(fdt, node);
224      if (ctx->regs == NULL) {
225        bsp_fatal(RISCV_FATAL_NO_NS16550_REG_IN_DEVICE_TREE);
226      }
227
228      if (node == console_node) {
229        riscv_console.context = &ctx->base;
230        riscv_console.putchar = fe310_console_putchar;
231        riscv_console.getchar = fe310_uart_read;
232      }
233
234      rtems_termios_device_context_initialize(&ctx->base, "FE310UART");
235    }
236#endif
237
238    node = fdt_next_node(fdt, node, NULL);
239  }
240
241  BSP_output_char = riscv_output_char;
242}
243
244static void riscv_output_char_init(char c)
245{
246  riscv_console_probe();
247  riscv_output_char(c);
248}
249
250BSP_output_char_function_type BSP_output_char = riscv_output_char_init;
251
252BSP_polling_getchar_function_type BSP_poll_char = NULL;
253
254rtems_status_code console_initialize(
255  rtems_device_major_number major,
256  rtems_device_minor_number minor,
257  void *arg
258)
259{
260#if RISCV_ENABLE_HTIF_SUPPORT != 0
261  rtems_termios_device_context *base;
262  char htif_path[] = "/dev/ttyShtif";
263#endif
264#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
265  char path[] = "/dev/ttyS?";
266  size_t i;
267#endif
268
269#if RISCV_ENABLE_FRDME310ARTY_SUPPORT != 0
270  fe310_uart_context *ctx;
271  char fe310_path[] = "/dev/ttyS0";
272#endif
273
274  rtems_termios_initialize();
275
276#if RISCV_ENABLE_HTIF_SUPPORT != 0
277  base = &htif_console_instance.base;
278  rtems_termios_device_install(htif_path, &htif_console_handler, NULL, base);
279
280  if (base == riscv_console.context) {
281    link(htif_path, CONSOLE_DEVICE_NAME);
282  }
283#endif
284
285#if RISCV_CONSOLE_MAX_NS16550_DEVICES > 0
286  for (i = 0; i < RISCV_CONSOLE_MAX_NS16550_DEVICES; ++i) {
287    ns16550_context *ctx;
288
289    ctx = &ns16550_instances[i];
290    path[sizeof(path) - 2] = (char) ('0' + i);
291
292    rtems_termios_device_install(
293      path,
294      &ns16550_handler_interrupt,
295      NULL,
296      &ctx->base
297    );
298
299    if (&ctx->base == riscv_console.context) {
300      link(path, CONSOLE_DEVICE_NAME);
301    }
302  }
303#endif
304
305#if RISCV_ENABLE_FRDME310ARTY_SUPPORT != 0
306  ctx = &fe310_uart_instance;
307  rtems_termios_device_install(
308    fe310_path,
309    &fe310_uart_handler,
310    NULL,
311    &ctx->base
312  );
313
314  if (&ctx->base == riscv_console.context) {
315    link(fe310_path, CONSOLE_DEVICE_NAME);
316  }
317#endif
318
319  return RTEMS_SUCCESSFUL;
320}
321
322RTEMS_SYSINIT_ITEM(
323  riscv_console_probe,
324  RTEMS_SYSINIT_BSP_START,
325  RTEMS_SYSINIT_ORDER_LAST_BUT_5
326);
Note: See TracBrowser for help on using the repository browser.