1*142a20c3SMateusz Kulikowski /* 2*142a20c3SMateusz Kulikowski * Qualcomm UART driver 3*142a20c3SMateusz Kulikowski * 4*142a20c3SMateusz Kulikowski * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com> 5*142a20c3SMateusz Kulikowski * 6*142a20c3SMateusz Kulikowski * UART will work in Data Mover mode. 7*142a20c3SMateusz Kulikowski * Based on Linux driver. 8*142a20c3SMateusz Kulikowski * 9*142a20c3SMateusz Kulikowski * SPDX-License-Identifier: GPL-2.0+ 10*142a20c3SMateusz Kulikowski */ 11*142a20c3SMateusz Kulikowski 12*142a20c3SMateusz Kulikowski #include <common.h> 13*142a20c3SMateusz Kulikowski #include <clk.h> 14*142a20c3SMateusz Kulikowski #include <dm.h> 15*142a20c3SMateusz Kulikowski #include <errno.h> 16*142a20c3SMateusz Kulikowski #include <serial.h> 17*142a20c3SMateusz Kulikowski #include <watchdog.h> 18*142a20c3SMateusz Kulikowski #include <asm/io.h> 19*142a20c3SMateusz Kulikowski #include <linux/compiler.h> 20*142a20c3SMateusz Kulikowski 21*142a20c3SMateusz Kulikowski /* Serial registers - this driver works in uartdm mode*/ 22*142a20c3SMateusz Kulikowski 23*142a20c3SMateusz Kulikowski #define UARTDM_DMRX 0x34 /* Max RX transfer length */ 24*142a20c3SMateusz Kulikowski #define UARTDM_NCF_TX 0x40 /* Number of chars to TX */ 25*142a20c3SMateusz Kulikowski 26*142a20c3SMateusz Kulikowski #define UARTDM_RXFS 0x50 /* RX channel status register */ 27*142a20c3SMateusz Kulikowski #define UARTDM_RXFS_BUF_SHIFT 0x7 /* Number of bytes in the packing buffer */ 28*142a20c3SMateusz Kulikowski #define UARTDM_RXFS_BUF_MASK 0x7 29*142a20c3SMateusz Kulikowski 30*142a20c3SMateusz Kulikowski #define UARTDM_SR 0xA4 /* Status register */ 31*142a20c3SMateusz Kulikowski #define UARTDM_SR_RX_READY (1 << 0) /* Word is the receiver FIFO */ 32*142a20c3SMateusz Kulikowski #define UARTDM_SR_TX_EMPTY (1 << 3) /* Transmitter underrun */ 33*142a20c3SMateusz Kulikowski #define UARTDM_SR_UART_OVERRUN (1 << 4) /* Receive overrun */ 34*142a20c3SMateusz Kulikowski 35*142a20c3SMateusz Kulikowski #define UARTDM_CR 0xA8 /* Command register */ 36*142a20c3SMateusz Kulikowski #define UARTDM_CR_CMD_RESET_ERR (3 << 4) /* Clear overrun error */ 37*142a20c3SMateusz Kulikowski #define UARTDM_CR_CMD_RESET_STALE_INT (8 << 4) /* Clears stale irq */ 38*142a20c3SMateusz Kulikowski #define UARTDM_CR_CMD_RESET_TX_READY (3 << 8) /* Clears TX Ready irq*/ 39*142a20c3SMateusz Kulikowski #define UARTDM_CR_CMD_FORCE_STALE (4 << 8) /* Causes stale event */ 40*142a20c3SMateusz Kulikowski #define UARTDM_CR_CMD_STALE_EVENT_DISABLE (6 << 8) /* Disable stale event */ 41*142a20c3SMateusz Kulikowski 42*142a20c3SMateusz Kulikowski #define UARTDM_IMR 0xB0 /* Interrupt mask register */ 43*142a20c3SMateusz Kulikowski #define UARTDM_ISR 0xB4 /* Interrupt status register */ 44*142a20c3SMateusz Kulikowski #define UARTDM_ISR_TX_READY 0x80 /* TX FIFO empty */ 45*142a20c3SMateusz Kulikowski 46*142a20c3SMateusz Kulikowski #define UARTDM_TF 0x100 /* UART Transmit FIFO register */ 47*142a20c3SMateusz Kulikowski #define UARTDM_RF 0x140 /* UART Receive FIFO register */ 48*142a20c3SMateusz Kulikowski 49*142a20c3SMateusz Kulikowski 50*142a20c3SMateusz Kulikowski DECLARE_GLOBAL_DATA_PTR; 51*142a20c3SMateusz Kulikowski 52*142a20c3SMateusz Kulikowski struct msm_serial_data { 53*142a20c3SMateusz Kulikowski phys_addr_t base; 54*142a20c3SMateusz Kulikowski unsigned chars_cnt; /* number of buffered chars */ 55*142a20c3SMateusz Kulikowski uint32_t chars_buf; /* buffered chars */ 56*142a20c3SMateusz Kulikowski }; 57*142a20c3SMateusz Kulikowski 58*142a20c3SMateusz Kulikowski static int msm_serial_fetch(struct udevice *dev) 59*142a20c3SMateusz Kulikowski { 60*142a20c3SMateusz Kulikowski struct msm_serial_data *priv = dev_get_priv(dev); 61*142a20c3SMateusz Kulikowski unsigned sr; 62*142a20c3SMateusz Kulikowski 63*142a20c3SMateusz Kulikowski if (priv->chars_cnt) 64*142a20c3SMateusz Kulikowski return priv->chars_cnt; 65*142a20c3SMateusz Kulikowski 66*142a20c3SMateusz Kulikowski /* Clear error in case of buffer overrun */ 67*142a20c3SMateusz Kulikowski if (readl(priv->base + UARTDM_SR) & UARTDM_SR_UART_OVERRUN) 68*142a20c3SMateusz Kulikowski writel(UARTDM_CR_CMD_RESET_ERR, priv->base + UARTDM_CR); 69*142a20c3SMateusz Kulikowski 70*142a20c3SMateusz Kulikowski /* We need to fetch new character */ 71*142a20c3SMateusz Kulikowski sr = readl(priv->base + UARTDM_SR); 72*142a20c3SMateusz Kulikowski 73*142a20c3SMateusz Kulikowski if (sr & UARTDM_SR_RX_READY) { 74*142a20c3SMateusz Kulikowski /* There are at least 4 bytes in fifo */ 75*142a20c3SMateusz Kulikowski priv->chars_buf = readl(priv->base + UARTDM_RF); 76*142a20c3SMateusz Kulikowski priv->chars_cnt = 4; 77*142a20c3SMateusz Kulikowski } else { 78*142a20c3SMateusz Kulikowski /* Check if there is anything in fifo */ 79*142a20c3SMateusz Kulikowski priv->chars_cnt = readl(priv->base + UARTDM_RXFS); 80*142a20c3SMateusz Kulikowski /* Extract number of characters in UART packing buffer*/ 81*142a20c3SMateusz Kulikowski priv->chars_cnt = (priv->chars_cnt >> 82*142a20c3SMateusz Kulikowski UARTDM_RXFS_BUF_SHIFT) & 83*142a20c3SMateusz Kulikowski UARTDM_RXFS_BUF_MASK; 84*142a20c3SMateusz Kulikowski if (!priv->chars_cnt) 85*142a20c3SMateusz Kulikowski return 0; 86*142a20c3SMateusz Kulikowski 87*142a20c3SMateusz Kulikowski /* There is at least one charcter, move it to fifo */ 88*142a20c3SMateusz Kulikowski writel(UARTDM_CR_CMD_FORCE_STALE, 89*142a20c3SMateusz Kulikowski priv->base + UARTDM_CR); 90*142a20c3SMateusz Kulikowski 91*142a20c3SMateusz Kulikowski priv->chars_buf = readl(priv->base + UARTDM_RF); 92*142a20c3SMateusz Kulikowski writel(UARTDM_CR_CMD_RESET_STALE_INT, 93*142a20c3SMateusz Kulikowski priv->base + UARTDM_CR); 94*142a20c3SMateusz Kulikowski writel(0x7, priv->base + UARTDM_DMRX); 95*142a20c3SMateusz Kulikowski } 96*142a20c3SMateusz Kulikowski 97*142a20c3SMateusz Kulikowski return priv->chars_cnt; 98*142a20c3SMateusz Kulikowski } 99*142a20c3SMateusz Kulikowski 100*142a20c3SMateusz Kulikowski static int msm_serial_getc(struct udevice *dev) 101*142a20c3SMateusz Kulikowski { 102*142a20c3SMateusz Kulikowski struct msm_serial_data *priv = dev_get_priv(dev); 103*142a20c3SMateusz Kulikowski char c; 104*142a20c3SMateusz Kulikowski 105*142a20c3SMateusz Kulikowski if (!msm_serial_fetch(dev)) 106*142a20c3SMateusz Kulikowski return -EAGAIN; 107*142a20c3SMateusz Kulikowski 108*142a20c3SMateusz Kulikowski c = priv->chars_buf & 0xFF; 109*142a20c3SMateusz Kulikowski priv->chars_buf >>= 8; 110*142a20c3SMateusz Kulikowski priv->chars_cnt--; 111*142a20c3SMateusz Kulikowski 112*142a20c3SMateusz Kulikowski return c; 113*142a20c3SMateusz Kulikowski } 114*142a20c3SMateusz Kulikowski 115*142a20c3SMateusz Kulikowski static int msm_serial_putc(struct udevice *dev, const char ch) 116*142a20c3SMateusz Kulikowski { 117*142a20c3SMateusz Kulikowski struct msm_serial_data *priv = dev_get_priv(dev); 118*142a20c3SMateusz Kulikowski 119*142a20c3SMateusz Kulikowski if (!(readl(priv->base + UARTDM_SR) & UARTDM_SR_TX_EMPTY) && 120*142a20c3SMateusz Kulikowski !(readl(priv->base + UARTDM_ISR) & UARTDM_ISR_TX_READY)) 121*142a20c3SMateusz Kulikowski return -EAGAIN; 122*142a20c3SMateusz Kulikowski 123*142a20c3SMateusz Kulikowski writel(UARTDM_CR_CMD_RESET_TX_READY, priv->base + UARTDM_CR); 124*142a20c3SMateusz Kulikowski 125*142a20c3SMateusz Kulikowski writel(1, priv->base + UARTDM_NCF_TX); 126*142a20c3SMateusz Kulikowski writel(ch, priv->base + UARTDM_TF); 127*142a20c3SMateusz Kulikowski 128*142a20c3SMateusz Kulikowski return 0; 129*142a20c3SMateusz Kulikowski } 130*142a20c3SMateusz Kulikowski 131*142a20c3SMateusz Kulikowski static int msm_serial_pending(struct udevice *dev, bool input) 132*142a20c3SMateusz Kulikowski { 133*142a20c3SMateusz Kulikowski if (input) { 134*142a20c3SMateusz Kulikowski if (msm_serial_fetch(dev)) 135*142a20c3SMateusz Kulikowski return 1; 136*142a20c3SMateusz Kulikowski } 137*142a20c3SMateusz Kulikowski 138*142a20c3SMateusz Kulikowski return 0; 139*142a20c3SMateusz Kulikowski } 140*142a20c3SMateusz Kulikowski 141*142a20c3SMateusz Kulikowski static const struct dm_serial_ops msm_serial_ops = { 142*142a20c3SMateusz Kulikowski .putc = msm_serial_putc, 143*142a20c3SMateusz Kulikowski .pending = msm_serial_pending, 144*142a20c3SMateusz Kulikowski .getc = msm_serial_getc, 145*142a20c3SMateusz Kulikowski }; 146*142a20c3SMateusz Kulikowski 147*142a20c3SMateusz Kulikowski static int msm_uart_clk_init(struct udevice *dev) 148*142a20c3SMateusz Kulikowski { 149*142a20c3SMateusz Kulikowski uint clk_rate = fdtdec_get_uint(gd->fdt_blob, dev->of_offset, 150*142a20c3SMateusz Kulikowski "clock-frequency", 115200); 151*142a20c3SMateusz Kulikowski uint clkd[2]; /* clk_id and clk_no */ 152*142a20c3SMateusz Kulikowski int clk_offset; 153*142a20c3SMateusz Kulikowski struct udevice *clk; 154*142a20c3SMateusz Kulikowski int ret; 155*142a20c3SMateusz Kulikowski 156*142a20c3SMateusz Kulikowski ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clock", clkd, 157*142a20c3SMateusz Kulikowski 2); 158*142a20c3SMateusz Kulikowski if (ret) 159*142a20c3SMateusz Kulikowski return ret; 160*142a20c3SMateusz Kulikowski 161*142a20c3SMateusz Kulikowski clk_offset = fdt_node_offset_by_phandle(gd->fdt_blob, clkd[0]); 162*142a20c3SMateusz Kulikowski if (clk_offset < 0) 163*142a20c3SMateusz Kulikowski return clk_offset; 164*142a20c3SMateusz Kulikowski 165*142a20c3SMateusz Kulikowski ret = uclass_get_device_by_of_offset(UCLASS_CLK, clk_offset, &clk); 166*142a20c3SMateusz Kulikowski if (ret) 167*142a20c3SMateusz Kulikowski return ret; 168*142a20c3SMateusz Kulikowski 169*142a20c3SMateusz Kulikowski ret = clk_set_periph_rate(clk, clkd[1], clk_rate); 170*142a20c3SMateusz Kulikowski if (ret < 0) 171*142a20c3SMateusz Kulikowski return ret; 172*142a20c3SMateusz Kulikowski 173*142a20c3SMateusz Kulikowski return 0; 174*142a20c3SMateusz Kulikowski } 175*142a20c3SMateusz Kulikowski 176*142a20c3SMateusz Kulikowski static int msm_serial_probe(struct udevice *dev) 177*142a20c3SMateusz Kulikowski { 178*142a20c3SMateusz Kulikowski struct msm_serial_data *priv = dev_get_priv(dev); 179*142a20c3SMateusz Kulikowski 180*142a20c3SMateusz Kulikowski msm_uart_clk_init(dev); /* Ignore return value and hope clock was 181*142a20c3SMateusz Kulikowski properly initialized by earlier loaders */ 182*142a20c3SMateusz Kulikowski 183*142a20c3SMateusz Kulikowski if (readl(priv->base + UARTDM_SR) & UARTDM_SR_UART_OVERRUN) 184*142a20c3SMateusz Kulikowski writel(UARTDM_CR_CMD_RESET_ERR, priv->base + UARTDM_CR); 185*142a20c3SMateusz Kulikowski 186*142a20c3SMateusz Kulikowski writel(0, priv->base + UARTDM_IMR); 187*142a20c3SMateusz Kulikowski writel(UARTDM_CR_CMD_STALE_EVENT_DISABLE, priv->base + UARTDM_CR); 188*142a20c3SMateusz Kulikowski msm_serial_fetch(dev); 189*142a20c3SMateusz Kulikowski 190*142a20c3SMateusz Kulikowski return 0; 191*142a20c3SMateusz Kulikowski } 192*142a20c3SMateusz Kulikowski 193*142a20c3SMateusz Kulikowski static int msm_serial_ofdata_to_platdata(struct udevice *dev) 194*142a20c3SMateusz Kulikowski { 195*142a20c3SMateusz Kulikowski struct msm_serial_data *priv = dev_get_priv(dev); 196*142a20c3SMateusz Kulikowski 197*142a20c3SMateusz Kulikowski priv->base = dev_get_addr(dev); 198*142a20c3SMateusz Kulikowski if (priv->base == FDT_ADDR_T_NONE) 199*142a20c3SMateusz Kulikowski return -EINVAL; 200*142a20c3SMateusz Kulikowski 201*142a20c3SMateusz Kulikowski return 0; 202*142a20c3SMateusz Kulikowski } 203*142a20c3SMateusz Kulikowski 204*142a20c3SMateusz Kulikowski static const struct udevice_id msm_serial_ids[] = { 205*142a20c3SMateusz Kulikowski { .compatible = "qcom,msm-uartdm-v1.4" }, 206*142a20c3SMateusz Kulikowski { } 207*142a20c3SMateusz Kulikowski }; 208*142a20c3SMateusz Kulikowski 209*142a20c3SMateusz Kulikowski U_BOOT_DRIVER(serial_msm) = { 210*142a20c3SMateusz Kulikowski .name = "serial_msm", 211*142a20c3SMateusz Kulikowski .id = UCLASS_SERIAL, 212*142a20c3SMateusz Kulikowski .of_match = msm_serial_ids, 213*142a20c3SMateusz Kulikowski .ofdata_to_platdata = msm_serial_ofdata_to_platdata, 214*142a20c3SMateusz Kulikowski .priv_auto_alloc_size = sizeof(struct msm_serial_data), 215*142a20c3SMateusz Kulikowski .probe = msm_serial_probe, 216*142a20c3SMateusz Kulikowski .ops = &msm_serial_ops, 217*142a20c3SMateusz Kulikowski }; 218