1 /* 2 * Copyright (C) 2011-2015 Vladimir Zapolskiy <vz@mleia.com> 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <serial.h> 10 #include <dm/platform_data/lpc32xx_hsuart.h> 11 12 #include <asm/arch/uart.h> 13 #include <linux/compiler.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 struct lpc32xx_hsuart_priv { 18 struct hsuart_regs *hsuart; 19 }; 20 21 static int lpc32xx_serial_setbrg(struct udevice *dev, int baudrate) 22 { 23 struct lpc32xx_hsuart_priv *priv = dev_get_priv(dev); 24 struct hsuart_regs *hsuart = priv->hsuart; 25 u32 div; 26 27 /* UART rate = PERIPH_CLK / ((HSU_RATE + 1) x 14) */ 28 div = (get_serial_clock() / 14 + baudrate / 2) / baudrate - 1; 29 if (div > 255) 30 div = 255; 31 32 writel(div, &hsuart->rate); 33 34 return 0; 35 } 36 37 static int lpc32xx_serial_getc(struct udevice *dev) 38 { 39 struct lpc32xx_hsuart_priv *priv = dev_get_priv(dev); 40 struct hsuart_regs *hsuart = priv->hsuart; 41 42 if (!(readl(&hsuart->level) & HSUART_LEVEL_RX)) 43 return -EAGAIN; 44 45 return readl(&hsuart->rx) & HSUART_RX_DATA; 46 } 47 48 static int lpc32xx_serial_putc(struct udevice *dev, const char c) 49 { 50 struct lpc32xx_hsuart_priv *priv = dev_get_priv(dev); 51 struct hsuart_regs *hsuart = priv->hsuart; 52 53 /* Wait for empty FIFO */ 54 if (readl(&hsuart->level) & HSUART_LEVEL_TX) 55 return -EAGAIN; 56 57 writel(c, &hsuart->tx); 58 59 return 0; 60 } 61 62 static int lpc32xx_serial_pending(struct udevice *dev, bool input) 63 { 64 struct lpc32xx_hsuart_priv *priv = dev_get_priv(dev); 65 struct hsuart_regs *hsuart = priv->hsuart; 66 67 if (input) { 68 if (readl(&hsuart->level) & HSUART_LEVEL_RX) 69 return 1; 70 } else { 71 if (readl(&hsuart->level) & HSUART_LEVEL_TX) 72 return 1; 73 } 74 75 return 0; 76 } 77 78 static int lpc32xx_serial_init(struct hsuart_regs *hsuart) 79 { 80 /* Disable hardware RTS and CTS flow control, set up RX and TX FIFO */ 81 writel(HSUART_CTRL_TMO_16 | HSUART_CTRL_HSU_OFFSET(20) | 82 HSUART_CTRL_HSU_RX_TRIG_32 | HSUART_CTRL_HSU_TX_TRIG_0, 83 &hsuart->ctrl); 84 85 return 0; 86 } 87 88 static int lpc32xx_hsuart_probe(struct udevice *dev) 89 { 90 struct lpc32xx_hsuart_platdata *platdata = dev_get_platdata(dev); 91 struct lpc32xx_hsuart_priv *priv = dev_get_priv(dev); 92 93 priv->hsuart = (struct hsuart_regs *)platdata->base; 94 95 lpc32xx_serial_init(priv->hsuart); 96 97 return 0; 98 } 99 100 static const struct dm_serial_ops lpc32xx_hsuart_ops = { 101 .setbrg = lpc32xx_serial_setbrg, 102 .getc = lpc32xx_serial_getc, 103 .putc = lpc32xx_serial_putc, 104 .pending = lpc32xx_serial_pending, 105 }; 106 107 U_BOOT_DRIVER(lpc32xx_hsuart) = { 108 .name = "lpc32xx_hsuart", 109 .id = UCLASS_SERIAL, 110 .probe = lpc32xx_hsuart_probe, 111 .ops = &lpc32xx_hsuart_ops, 112 .priv_auto_alloc_size = sizeof(struct lpc32xx_hsuart_priv), 113 .flags = DM_FLAG_PRE_RELOC, 114 }; 115