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