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