blob: 8dcd4f8d250c6bc556d7dfaac76910427e563144 [file] [log] [blame]
Patrice Chotard42d742b2017-02-21 13:37:07 +01001/*
2 * Support for Serial I/O using STMicroelectronics' on-chip ASC.
3 *
4 * Copyright (c) 2017
5 * Patrice Chotard <patrice.chotard@st.com>
6 *
7 * SPDX-License-Identifier: GPL-2.0
8 */
9
10#include <common.h>
11#include <dm.h>
12#include <serial.h>
13#include <asm/io.h>
14
15DECLARE_GLOBAL_DATA_PTR;
16
17#define BAUDMODE 0x00001000
18#define RXENABLE 0x00000100
19#define RUN 0x00000080
20#define MODE 0x00000001
21#define MODE_8BIT 0x0001
22#define STOP_1BIT 0x0008
23#define PARITYODD 0x0020
24
25#define STA_TF BIT(9)
26#define STA_RBF BIT(0)
27
28struct sti_asc_uart {
29 u32 baudrate;
30 u32 txbuf;
31 u32 rxbuf;
32 u32 control;
33 u32 inten;
34 u32 status;
35 u32 guardtime;
36 u32 timeout;
37 u32 txreset;
38 u32 rxreset;
39};
40
41struct sti_asc_serial {
42 /* address of registers in physical memory */
43 struct sti_asc_uart *regs;
44};
45
46/* Values for the BAUDRATE Register */
47#define PCLK (200ul * 1000000ul)
48#define BAUDRATE_VAL_M0(bps) (PCLK / (16 * (bps)))
49#define BAUDRATE_VAL_M1(bps) ((bps * (1 << 14)) + (1<<13)) / (PCLK/(1 << 6))
50
51/*
52 * MODE 0
53 * ICCLK
54 * ASCBaudRate = ----------------
55 * baudrate * 16
56 *
57 * MODE 1
58 * baudrate * 16 * 2^16
59 * ASCBaudRate = ------------------------
60 * ICCLK
61 *
62 * NOTE:
63 * Mode 1 should be used for baudrates of 19200, and above, as it
64 * has a lower deviation error than Mode 0 for higher frequencies.
65 * Mode 0 should be used for all baudrates below 19200.
66 */
67
68static int sti_asc_pending(struct udevice *dev, bool input)
69{
70 struct sti_asc_serial *priv = dev_get_priv(dev);
71 struct sti_asc_uart *const uart = priv->regs;
72 unsigned long status;
73
74 status = readl(&uart->status);
75 if (input)
76 return status & STA_RBF;
77 else
78 return status & STA_TF;
79}
80
81static int _sti_asc_serial_setbrg(struct sti_asc_uart *uart, int baudrate)
82{
83 unsigned long val;
84 int t, mode = 1;
85
86 switch (baudrate) {
87 case 9600:
88 t = BAUDRATE_VAL_M0(9600);
89 mode = 0;
90 break;
91 case 19200:
92 t = BAUDRATE_VAL_M1(19200);
93 break;
94 case 38400:
95 t = BAUDRATE_VAL_M1(38400);
96 break;
97 case 57600:
98 t = BAUDRATE_VAL_M1(57600);
99 break;
100 default:
101 debug("ASC: unsupported baud rate: %d, using 115200 instead.\n",
102 baudrate);
103 case 115200:
104 t = BAUDRATE_VAL_M1(115200);
105 break;
106 }
107
108 /* disable the baudrate generator */
109 val = readl(&uart->control);
110 writel(val & ~RUN, &uart->control);
111
112 /* set baud generator reload value */
113 writel(t, &uart->baudrate);
114 /* reset the RX & TX buffers */
115 writel(1, &uart->txreset);
116 writel(1, &uart->rxreset);
117
118 /* set baud generator mode */
119 if (mode)
120 val |= BAUDMODE;
121
122 /* finally, write value and enable ASC */
123 writel(val, &uart->control);
124
125 return 0;
126}
127
128/* called to adjust baud-rate */
129static int sti_asc_serial_setbrg(struct udevice *dev, int baudrate)
130{
131 struct sti_asc_serial *priv = dev_get_priv(dev);
132 struct sti_asc_uart *const uart = priv->regs;
133
134 return _sti_asc_serial_setbrg(uart, baudrate);
135}
136
137/* blocking function, that returns next char */
138static int sti_asc_serial_getc(struct udevice *dev)
139{
140 struct sti_asc_serial *priv = dev_get_priv(dev);
141 struct sti_asc_uart *const uart = priv->regs;
142
143 /* polling wait: for a char to be read */
144 if (!sti_asc_pending(dev, true))
145 return -EAGAIN;
146
147 return readl(&uart->rxbuf);
148}
149
150/* write write out a single char */
151static int sti_asc_serial_putc(struct udevice *dev, const char c)
152{
153 struct sti_asc_serial *priv = dev_get_priv(dev);
154 struct sti_asc_uart *const uart = priv->regs;
155
156 /* wait till safe to write next char */
157 if (sti_asc_pending(dev, false))
158 return -EAGAIN;
159
160 /* finally, write next char */
161 writel(c, &uart->txbuf);
162
163 return 0;
164}
165
166/* initialize the ASC */
167static int sti_asc_serial_probe(struct udevice *dev)
168{
169 struct sti_asc_serial *priv = dev_get_priv(dev);
170 unsigned long val;
171 fdt_addr_t base;
172
Simon Glassba1dea42017-05-17 17:18:05 -0600173 base = devfdt_get_addr(dev);
Patrice Chotard42d742b2017-02-21 13:37:07 +0100174 if (base == FDT_ADDR_T_NONE)
175 return -EINVAL;
176
177 priv->regs = (struct sti_asc_uart *)base;
178 sti_asc_serial_setbrg(dev, gd->baudrate);
179
180 /*
181 * build up the value to be written to CONTROL
182 * set character length, bit stop number, odd parity
183 */
184 val = RXENABLE | RUN | MODE_8BIT | STOP_1BIT | PARITYODD;
185 writel(val, &priv->regs->control);
186
187 return 0;
188}
189
190static const struct dm_serial_ops sti_asc_serial_ops = {
191 .putc = sti_asc_serial_putc,
192 .pending = sti_asc_pending,
193 .getc = sti_asc_serial_getc,
194 .setbrg = sti_asc_serial_setbrg,
195};
196
197static const struct udevice_id sti_serial_of_match[] = {
198 { .compatible = "st,asc" },
199 { }
200};
201
202U_BOOT_DRIVER(serial_sti_asc) = {
203 .name = "serial_sti_asc",
204 .id = UCLASS_SERIAL,
205 .of_match = sti_serial_of_match,
206 .ops = &sti_asc_serial_ops,
207 .probe = sti_asc_serial_probe,
208 .priv_auto_alloc_size = sizeof(struct sti_asc_serial),
209 .flags = DM_FLAG_PRE_RELOC,
210};
211