blob: b42537529de85c10e44c522e2a5775523473e0cb [file] [log] [blame]
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +00001/*
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +02002 * Copyright (C) 2011-2015 Vladimir Zapolskiy <vz@mleia.com>
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +00003 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02004 * SPDX-License-Identifier: GPL-2.0+
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +00005 */
6
7#include <common.h>
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +02008#include <dm.h>
Marek Vasuta1207aa2012-09-13 16:51:02 +02009#include <serial.h>
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +020010#include <dm/platform_data/lpc32xx_hsuart.h>
11
12#include <asm/arch/uart.h>
Marek Vasuta1207aa2012-09-13 16:51:02 +020013#include <linux/compiler.h>
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +000014
15DECLARE_GLOBAL_DATA_PTR;
16
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +020017struct lpc32xx_hsuart_priv {
18 struct hsuart_regs *hsuart;
19};
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +000020
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +020021static int lpc32xx_serial_setbrg(struct udevice *dev, int baudrate)
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +000022{
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +020023 struct lpc32xx_hsuart_priv *priv = dev_get_priv(dev);
24 struct hsuart_regs *hsuart = priv->hsuart;
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +000025 u32 div;
26
27 /* UART rate = PERIPH_CLK / ((HSU_RATE + 1) x 14) */
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +020028 div = (get_serial_clock() / 14 + baudrate / 2) / baudrate - 1;
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +000029 if (div > 255)
30 div = 255;
31
32 writel(div, &hsuart->rate);
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +020033
34 return 0;
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +000035}
36
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +020037static int lpc32xx_serial_getc(struct udevice *dev)
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +000038{
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +020039 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;
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +000044
45 return readl(&hsuart->rx) & HSUART_RX_DATA;
46}
47
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +020048static int lpc32xx_serial_putc(struct udevice *dev, const char c)
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +000049{
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +020050 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;
Vladimir Zapolskiyf1e43bd2013-11-30 16:47:01 +020056
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +000057 writel(c, &hsuart->tx);
58
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +020059 return 0;
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +000060}
61
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +020062static int lpc32xx_serial_pending(struct udevice *dev, bool input)
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +000063{
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +020064 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 }
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +000074
75 return 0;
76}
77
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +020078static int lpc32xx_serial_init(struct hsuart_regs *hsuart)
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +000079{
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +000080 /* 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);
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +020084
Marek Vasuta1207aa2012-09-13 16:51:02 +020085 return 0;
Vladimir Zapolskiy8597d072012-04-19 04:33:09 +000086}
87
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +020088static 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
100static const struct dm_serial_ops lpc32xx_hsuart_ops = {
Marek Vasuta1207aa2012-09-13 16:51:02 +0200101 .setbrg = lpc32xx_serial_setbrg,
Marek Vasuta1207aa2012-09-13 16:51:02 +0200102 .getc = lpc32xx_serial_getc,
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +0200103 .putc = lpc32xx_serial_putc,
104 .pending = lpc32xx_serial_pending,
Marek Vasuta1207aa2012-09-13 16:51:02 +0200105};
106
Vladimir Zapolskiyf20d4c02015-12-19 23:29:24 +0200107U_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};