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