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