1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Actions Semi OWL SoCs UART driver 4 * 5 * Copyright (C) 2015 Actions Semi Co., Ltd. 6 * Copyright (C) 2018 Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> 7 */ 8 9 #include <common.h> 10 #include <clk.h> 11 #include <dm.h> 12 #include <errno.h> 13 #include <fdtdec.h> 14 #include <serial.h> 15 #include <asm/io.h> 16 #include <asm/types.h> 17 18 /* UART Registers */ 19 #define OWL_UART_CTL (0x0000) 20 #define OWL_UART_RXDAT (0x0004) 21 #define OWL_UART_TXDAT (0x0008) 22 #define OWL_UART_STAT (0x000C) 23 24 /* UART_CTL Register Definitions */ 25 #define OWL_UART_CTL_PRS_NONE GENMASK(6, 4) 26 #define OWL_UART_CTL_STPS BIT(2) 27 #define OWL_UART_CTL_DWLS 3 28 29 /* UART_STAT Register Definitions */ 30 #define OWL_UART_STAT_TFES BIT(10) /* TX FIFO Empty Status */ 31 #define OWL_UART_STAT_RFFS BIT(9) /* RX FIFO full Status */ 32 #define OWL_UART_STAT_TFFU BIT(6) /* TX FIFO full Status */ 33 #define OWL_UART_STAT_RFEM BIT(5) /* RX FIFO Empty Status */ 34 35 struct owl_serial_priv { 36 phys_addr_t base; 37 }; 38 39 int owl_serial_setbrg(struct udevice *dev, int baudrate) 40 { 41 /* Driver supports only fixed baudrate */ 42 return 0; 43 } 44 45 static int owl_serial_getc(struct udevice *dev) 46 { 47 struct owl_serial_priv *priv = dev_get_priv(dev); 48 49 if (readl(priv->base + OWL_UART_STAT) & OWL_UART_STAT_RFEM) 50 return -EAGAIN; 51 52 return (int)(readl(priv->base + OWL_UART_RXDAT)); 53 } 54 55 static int owl_serial_putc(struct udevice *dev, const char ch) 56 { 57 struct owl_serial_priv *priv = dev_get_priv(dev); 58 59 if (readl(priv->base + OWL_UART_STAT) & OWL_UART_STAT_TFFU) 60 return -EAGAIN; 61 62 writel(ch, priv->base + OWL_UART_TXDAT); 63 64 return 0; 65 } 66 67 static int owl_serial_pending(struct udevice *dev, bool input) 68 { 69 struct owl_serial_priv *priv = dev_get_priv(dev); 70 unsigned int stat = readl(priv->base + OWL_UART_STAT); 71 72 if (input) 73 return !(stat & OWL_UART_STAT_RFEM); 74 else 75 return !(stat & OWL_UART_STAT_TFES); 76 } 77 78 static int owl_serial_probe(struct udevice *dev) 79 { 80 struct owl_serial_priv *priv = dev_get_priv(dev); 81 struct clk clk; 82 u32 uart_ctl; 83 int ret; 84 85 /* Set data, parity and stop bits */ 86 uart_ctl = readl(priv->base + OWL_UART_CTL); 87 uart_ctl &= ~(OWL_UART_CTL_PRS_NONE); 88 uart_ctl &= ~(OWL_UART_CTL_STPS); 89 uart_ctl |= OWL_UART_CTL_DWLS; 90 writel(uart_ctl, priv->base + OWL_UART_CTL); 91 92 /* Enable UART clock */ 93 ret = clk_get_by_index(dev, 0, &clk); 94 if (ret < 0) 95 return ret; 96 97 ret = clk_enable(&clk); 98 if (ret < 0) 99 return ret; 100 101 return 0; 102 } 103 104 static int owl_serial_ofdata_to_platdata(struct udevice *dev) 105 { 106 struct owl_serial_priv *priv = dev_get_priv(dev); 107 108 priv->base = dev_read_addr(dev); 109 if (priv->base == FDT_ADDR_T_NONE) 110 return -EINVAL; 111 112 return 0; 113 } 114 115 static const struct dm_serial_ops owl_serial_ops = { 116 .putc = owl_serial_putc, 117 .pending = owl_serial_pending, 118 .getc = owl_serial_getc, 119 .setbrg = owl_serial_setbrg, 120 }; 121 122 static const struct udevice_id owl_serial_ids[] = { 123 { .compatible = "actions,s900-serial" }, 124 { } 125 }; 126 127 U_BOOT_DRIVER(serial_owl) = { 128 .name = "serial_owl", 129 .id = UCLASS_SERIAL, 130 .of_match = owl_serial_ids, 131 .ofdata_to_platdata = owl_serial_ofdata_to_platdata, 132 .priv_auto_alloc_size = sizeof(struct owl_serial_priv), 133 .probe = owl_serial_probe, 134 .ops = &owl_serial_ops, 135 .flags = DM_FLAG_PRE_RELOC, 136 }; 137