1/*
2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7#include <devices_gen.h>
8#include <drivers/common.h>
9#include <drivers/uart.h>
10
11#include <elfloader_common.h>
12
13#define UART_WFIFO  0x0
14#define UART_STATUS 0xC
15#define UART_TX_FULL        BIT(21)
16#define UART_REG(mmio, x) ((volatile uint32_t *)(mmio + (x)))
17
18static int meson_uart_putchar(struct elfloader_device *dev, unsigned int c)
19{
20    volatile void *mmio = dev->region_bases[0];
21
22    /* Wait to be able to transmit. */
23    while ((*UART_REG(mmio, UART_STATUS) & UART_TX_FULL));
24
25    /* Transmit. */
26    *UART_REG(mmio, UART_WFIFO) = c;
27
28    return 0;
29}
30
31static int meson_uart_init(struct elfloader_device *dev, UNUSED void *match_data)
32{
33    uart_set_out(dev);
34    return 0;
35}
36
37static const struct dtb_match_table meson_uart_matches[] = {
38    { .compatible = "amlogic,meson-gx-uart" },
39    { .compatible = NULL /* sentinel */ },
40};
41
42static const struct elfloader_uart_ops meson_uart_ops = {
43    .putc = &meson_uart_putchar,
44};
45
46static const struct elfloader_driver meson_uart = {
47    .match_table = meson_uart_matches,
48    .type = DRIVER_UART,
49    .init = &meson_uart_init,
50    .ops = &meson_uart_ops,
51};
52
53ELFLOADER_DRIVER(meson_uart);
54