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