diff options
author | Wesley W. Terpstra <wesley@sifive.com> | 2017-03-27 14:16:05 -0700 |
---|---|---|
committer | Wesley W. Terpstra <wesley@sifive.com> | 2017-03-27 15:50:22 -0700 |
commit | b394a92597a5ee766dca42478e12492aba399543 (patch) | |
tree | 05b0159a34e1b98a8b119e2b826e7b45b868285d /machine | |
parent | cfe60c100d103fc1547e1462522f08d8e6979e0c (diff) | |
download | riscv-pk-b394a92597a5ee766dca42478e12492aba399543.zip riscv-pk-b394a92597a5ee766dca42478e12492aba399543.tar.gz riscv-pk-b394a92597a5ee766dca42478e12492aba399543.tar.bz2 |
uart: find it using fdt
Diffstat (limited to 'machine')
-rw-r--r-- | machine/uart.c | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/machine/uart.c b/machine/uart.c index 28cc21c..a55e27e 100644 --- a/machine/uart.c +++ b/machine/uart.c @@ -1,3 +1,4 @@ +#include <string.h> #include "uart.h" #include "fdt.h" @@ -27,12 +28,49 @@ int uart_getchar() return ch; } -void query_uart(uintptr_t dtb) +struct uart_scan { - uart = 0; // (void*)fdt_get_reg(dtb, "sifive,uart0"); - if (!uart) return; + int compat; + uintptr_t reg; +}; + +static void uart_open(const struct fdt_scan_node *node, void *extra) +{ + struct uart_scan *scan = (struct uart_scan *)extra; + memset(scan, 0, sizeof(*scan)); +} + +static void uart_prop(const struct fdt_scan_prop *prop, void *extra) +{ + struct uart_scan *scan = (struct uart_scan *)extra; + if (!strcmp(prop->name, "compatible") && !strcmp((const char*)prop->value, "sifive,uart0")) { + scan->compat = 1; + } else if (!strcmp(prop->name, "reg")) { + fdt_get_address(prop->node->parent, prop->value, &scan->reg); + } +} + +static void uart_done(const struct fdt_scan_node *node, void *extra) +{ + struct uart_scan *scan = (struct uart_scan *)extra; + if (!scan->compat || !scan->reg || uart) return; // Enable Rx/Tx channels + uart = (void*)scan->reg; uart[UART_REG_TXCTRL] = UART_TXEN; uart[UART_REG_RXCTRL] = UART_RXEN; } + +void query_uart(uintptr_t fdt) +{ + struct fdt_cb cb; + struct uart_scan scan; + + memset(&cb, 0, sizeof(cb)); + cb.open = uart_open; + cb.prop = uart_prop; + cb.done = uart_done; + cb.extra = &scan; + + fdt_scan(fdt, &cb); +} |