1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 2bfcef28aSBeniamino Galvani /* 3bfcef28aSBeniamino Galvani * (C) Copyright 2016 Beniamino Galvani <b.galvani@gmail.com> 4bfcef28aSBeniamino Galvani */ 5bfcef28aSBeniamino Galvani 6bfcef28aSBeniamino Galvani #include <common.h> 7bfcef28aSBeniamino Galvani #include <dm.h> 8bfcef28aSBeniamino Galvani #include <errno.h> 9bfcef28aSBeniamino Galvani #include <fdtdec.h> 10bfcef28aSBeniamino Galvani #include <linux/compiler.h> 11bfcef28aSBeniamino Galvani #include <serial.h> 12bfcef28aSBeniamino Galvani 13bfcef28aSBeniamino Galvani struct meson_uart { 14bfcef28aSBeniamino Galvani u32 wfifo; 15bfcef28aSBeniamino Galvani u32 rfifo; 16bfcef28aSBeniamino Galvani u32 control; 17bfcef28aSBeniamino Galvani u32 status; 18bfcef28aSBeniamino Galvani u32 misc; 19bfcef28aSBeniamino Galvani }; 20bfcef28aSBeniamino Galvani 21bfcef28aSBeniamino Galvani struct meson_serial_platdata { 22bfcef28aSBeniamino Galvani struct meson_uart *reg; 23bfcef28aSBeniamino Galvani }; 24bfcef28aSBeniamino Galvani 25bfcef28aSBeniamino Galvani /* AML_UART_STATUS bits */ 26bfcef28aSBeniamino Galvani #define AML_UART_PARITY_ERR BIT(16) 27bfcef28aSBeniamino Galvani #define AML_UART_FRAME_ERR BIT(17) 28bfcef28aSBeniamino Galvani #define AML_UART_TX_FIFO_WERR BIT(18) 29bfcef28aSBeniamino Galvani #define AML_UART_RX_EMPTY BIT(20) 30bfcef28aSBeniamino Galvani #define AML_UART_TX_FULL BIT(21) 31bfcef28aSBeniamino Galvani #define AML_UART_TX_EMPTY BIT(22) 32bfcef28aSBeniamino Galvani #define AML_UART_XMIT_BUSY BIT(25) 33bfcef28aSBeniamino Galvani #define AML_UART_ERR (AML_UART_PARITY_ERR | \ 34bfcef28aSBeniamino Galvani AML_UART_FRAME_ERR | \ 35bfcef28aSBeniamino Galvani AML_UART_TX_FIFO_WERR) 36bfcef28aSBeniamino Galvani 37bfcef28aSBeniamino Galvani /* AML_UART_CONTROL bits */ 38bfcef28aSBeniamino Galvani #define AML_UART_TX_EN BIT(12) 39bfcef28aSBeniamino Galvani #define AML_UART_RX_EN BIT(13) 40bfcef28aSBeniamino Galvani #define AML_UART_TX_RST BIT(22) 41bfcef28aSBeniamino Galvani #define AML_UART_RX_RST BIT(23) 42bfcef28aSBeniamino Galvani #define AML_UART_CLR_ERR BIT(24) 43bfcef28aSBeniamino Galvani 44bfcef28aSBeniamino Galvani static void meson_serial_init(struct meson_uart *uart) 45bfcef28aSBeniamino Galvani { 46bfcef28aSBeniamino Galvani u32 val; 47bfcef28aSBeniamino Galvani 48bfcef28aSBeniamino Galvani val = readl(&uart->control); 49bfcef28aSBeniamino Galvani val |= (AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR); 50bfcef28aSBeniamino Galvani writel(val, &uart->control); 51bfcef28aSBeniamino Galvani val &= ~(AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR); 52bfcef28aSBeniamino Galvani writel(val, &uart->control); 53bfcef28aSBeniamino Galvani val |= (AML_UART_RX_EN | AML_UART_TX_EN); 54bfcef28aSBeniamino Galvani writel(val, &uart->control); 55bfcef28aSBeniamino Galvani } 56bfcef28aSBeniamino Galvani 57bfcef28aSBeniamino Galvani static int meson_serial_probe(struct udevice *dev) 58bfcef28aSBeniamino Galvani { 59bfcef28aSBeniamino Galvani struct meson_serial_platdata *plat = dev->platdata; 60bfcef28aSBeniamino Galvani struct meson_uart *const uart = plat->reg; 61bfcef28aSBeniamino Galvani 62bfcef28aSBeniamino Galvani meson_serial_init(uart); 63bfcef28aSBeniamino Galvani 64bfcef28aSBeniamino Galvani return 0; 65bfcef28aSBeniamino Galvani } 66bfcef28aSBeniamino Galvani 67bfcef28aSBeniamino Galvani static int meson_serial_getc(struct udevice *dev) 68bfcef28aSBeniamino Galvani { 69bfcef28aSBeniamino Galvani struct meson_serial_platdata *plat = dev->platdata; 70bfcef28aSBeniamino Galvani struct meson_uart *const uart = plat->reg; 71bfcef28aSBeniamino Galvani 72bfcef28aSBeniamino Galvani if (readl(&uart->status) & AML_UART_RX_EMPTY) 73bfcef28aSBeniamino Galvani return -EAGAIN; 74bfcef28aSBeniamino Galvani 75bfcef28aSBeniamino Galvani return readl(&uart->rfifo) & 0xff; 76bfcef28aSBeniamino Galvani } 77bfcef28aSBeniamino Galvani 78bfcef28aSBeniamino Galvani static int meson_serial_putc(struct udevice *dev, const char ch) 79bfcef28aSBeniamino Galvani { 80bfcef28aSBeniamino Galvani struct meson_serial_platdata *plat = dev->platdata; 81bfcef28aSBeniamino Galvani struct meson_uart *const uart = plat->reg; 82bfcef28aSBeniamino Galvani 83bfcef28aSBeniamino Galvani if (readl(&uart->status) & AML_UART_TX_FULL) 84bfcef28aSBeniamino Galvani return -EAGAIN; 85bfcef28aSBeniamino Galvani 86bfcef28aSBeniamino Galvani writel(ch, &uart->wfifo); 87bfcef28aSBeniamino Galvani 88bfcef28aSBeniamino Galvani return 0; 89bfcef28aSBeniamino Galvani } 90bfcef28aSBeniamino Galvani 91bfcef28aSBeniamino Galvani static int meson_serial_pending(struct udevice *dev, bool input) 92bfcef28aSBeniamino Galvani { 93bfcef28aSBeniamino Galvani struct meson_serial_platdata *plat = dev->platdata; 94bfcef28aSBeniamino Galvani struct meson_uart *const uart = plat->reg; 95bfcef28aSBeniamino Galvani uint32_t status = readl(&uart->status); 96bfcef28aSBeniamino Galvani 97bfcef28aSBeniamino Galvani if (input) 98bfcef28aSBeniamino Galvani return !(status & AML_UART_RX_EMPTY); 99bfcef28aSBeniamino Galvani else 100bfcef28aSBeniamino Galvani return !(status & AML_UART_TX_FULL); 101bfcef28aSBeniamino Galvani } 102bfcef28aSBeniamino Galvani 103bfcef28aSBeniamino Galvani static int meson_serial_ofdata_to_platdata(struct udevice *dev) 104bfcef28aSBeniamino Galvani { 105bfcef28aSBeniamino Galvani struct meson_serial_platdata *plat = dev->platdata; 106bfcef28aSBeniamino Galvani fdt_addr_t addr; 107bfcef28aSBeniamino Galvani 108a821c4afSSimon Glass addr = devfdt_get_addr(dev); 109bfcef28aSBeniamino Galvani if (addr == FDT_ADDR_T_NONE) 110bfcef28aSBeniamino Galvani return -EINVAL; 111bfcef28aSBeniamino Galvani 112bfcef28aSBeniamino Galvani plat->reg = (struct meson_uart *)addr; 113bfcef28aSBeniamino Galvani 114bfcef28aSBeniamino Galvani return 0; 115bfcef28aSBeniamino Galvani } 116bfcef28aSBeniamino Galvani 117bfcef28aSBeniamino Galvani static const struct dm_serial_ops meson_serial_ops = { 118bfcef28aSBeniamino Galvani .putc = meson_serial_putc, 119bfcef28aSBeniamino Galvani .pending = meson_serial_pending, 120bfcef28aSBeniamino Galvani .getc = meson_serial_getc, 121bfcef28aSBeniamino Galvani }; 122bfcef28aSBeniamino Galvani 123bfcef28aSBeniamino Galvani static const struct udevice_id meson_serial_ids[] = { 124bfcef28aSBeniamino Galvani { .compatible = "amlogic,meson-uart" }, 125e1e1e852SNeil Armstrong { .compatible = "amlogic,meson-gx-uart" }, 126bfcef28aSBeniamino Galvani { } 127bfcef28aSBeniamino Galvani }; 128bfcef28aSBeniamino Galvani 129bfcef28aSBeniamino Galvani U_BOOT_DRIVER(serial_meson) = { 130bfcef28aSBeniamino Galvani .name = "serial_meson", 131bfcef28aSBeniamino Galvani .id = UCLASS_SERIAL, 132bfcef28aSBeniamino Galvani .of_match = meson_serial_ids, 133bfcef28aSBeniamino Galvani .probe = meson_serial_probe, 134bfcef28aSBeniamino Galvani .ops = &meson_serial_ops, 135bfcef28aSBeniamino Galvani .flags = DM_FLAG_PRE_RELOC, 136bfcef28aSBeniamino Galvani .ofdata_to_platdata = meson_serial_ofdata_to_platdata, 137bfcef28aSBeniamino Galvani .platdata_auto_alloc_size = sizeof(struct meson_serial_platdata), 138bfcef28aSBeniamino Galvani }; 139bfcef28aSBeniamino Galvani 140bfcef28aSBeniamino Galvani #ifdef CONFIG_DEBUG_UART_MESON 141bfcef28aSBeniamino Galvani 142bfcef28aSBeniamino Galvani #include <debug_uart.h> 143bfcef28aSBeniamino Galvani 144bfcef28aSBeniamino Galvani static inline void _debug_uart_init(void) 145bfcef28aSBeniamino Galvani { 146bfcef28aSBeniamino Galvani } 147bfcef28aSBeniamino Galvani 148bfcef28aSBeniamino Galvani static inline void _debug_uart_putc(int ch) 149bfcef28aSBeniamino Galvani { 150bfcef28aSBeniamino Galvani struct meson_uart *regs = (struct meson_uart *)CONFIG_DEBUG_UART_BASE; 151bfcef28aSBeniamino Galvani 152bfcef28aSBeniamino Galvani while (readl(®s->status) & AML_UART_TX_FULL) 153bfcef28aSBeniamino Galvani ; 154bfcef28aSBeniamino Galvani 155bfcef28aSBeniamino Galvani writel(ch, ®s->wfifo); 156bfcef28aSBeniamino Galvani } 157bfcef28aSBeniamino Galvani 158bfcef28aSBeniamino Galvani DEBUG_UART_FUNCS 159bfcef28aSBeniamino Galvani 160bfcef28aSBeniamino Galvani #endif 161