Merge tag 'dm-pull-6feb20' of https://gitlab.denx.de/u-boot/custodians/u-boot-dm
[platform/kernel/u-boot.git] / drivers / serial / serial_stm32.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
4  * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
5  */
6
7 #include <common.h>
8 #include <clk.h>
9 #include <dm.h>
10 #include <reset.h>
11 #include <serial.h>
12 #include <watchdog.h>
13 #include <asm/io.h>
14 #include <asm/arch/stm32.h>
15 #include "serial_stm32.h"
16 #include <dm/device_compat.h>
17
18 static void _stm32_serial_setbrg(fdt_addr_t base,
19                                  struct stm32_uart_info *uart_info,
20                                  u32 clock_rate,
21                                  int baudrate)
22 {
23         bool stm32f4 = uart_info->stm32f4;
24         u32 int_div, mantissa, fraction, oversampling;
25
26         int_div = DIV_ROUND_CLOSEST(clock_rate, baudrate);
27
28         if (int_div < 16) {
29                 oversampling = 8;
30                 setbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_OVER8);
31         } else {
32                 oversampling = 16;
33                 clrbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_OVER8);
34         }
35
36         mantissa = (int_div / oversampling) << USART_BRR_M_SHIFT;
37         fraction = int_div % oversampling;
38
39         writel(mantissa | fraction, base + BRR_OFFSET(stm32f4));
40 }
41
42 static int stm32_serial_setbrg(struct udevice *dev, int baudrate)
43 {
44         struct stm32x7_serial_platdata *plat = dev_get_platdata(dev);
45
46         _stm32_serial_setbrg(plat->base, plat->uart_info,
47                              plat->clock_rate, baudrate);
48
49         return 0;
50 }
51
52 static int stm32_serial_setconfig(struct udevice *dev, uint serial_config)
53 {
54         struct stm32x7_serial_platdata *plat = dev_get_platdata(dev);
55         bool stm32f4 = plat->uart_info->stm32f4;
56         u8 uart_enable_bit = plat->uart_info->uart_enable_bit;
57         u32 cr1 = plat->base + CR1_OFFSET(stm32f4);
58         u32 config = 0;
59         uint parity = SERIAL_GET_PARITY(serial_config);
60         uint bits = SERIAL_GET_BITS(serial_config);
61         uint stop = SERIAL_GET_STOP(serial_config);
62
63         /*
64          * only parity config is implemented, check if other serial settings
65          * are the default one.
66          * (STM32F4 serial IP didn't support parity setting)
67          */
68         if (bits != SERIAL_8_BITS || stop != SERIAL_ONE_STOP || stm32f4)
69                 return -ENOTSUPP; /* not supported in driver*/
70
71         clrbits_le32(cr1, USART_CR1_RE | USART_CR1_TE | BIT(uart_enable_bit));
72         /* update usart configuration (uart need to be disable)
73          * PCE: parity check enable
74          * PS : '0' : Even / '1' : Odd
75          * M[1:0] = '00' : 8 Data bits
76          * M[1:0] = '01' : 9 Data bits with parity
77          */
78         switch (parity) {
79         default:
80         case SERIAL_PAR_NONE:
81                 config = 0;
82                 break;
83         case SERIAL_PAR_ODD:
84                 config = USART_CR1_PCE | USART_CR1_PS | USART_CR1_M0;
85                 break;
86         case SERIAL_PAR_EVEN:
87                 config = USART_CR1_PCE | USART_CR1_M0;
88                 break;
89         }
90
91         clrsetbits_le32(cr1,
92                         USART_CR1_PCE | USART_CR1_PS | USART_CR1_M1 |
93                         USART_CR1_M0,
94                         config);
95         setbits_le32(cr1, USART_CR1_RE | USART_CR1_TE | BIT(uart_enable_bit));
96
97         return 0;
98 }
99
100 static int stm32_serial_getc(struct udevice *dev)
101 {
102         struct stm32x7_serial_platdata *plat = dev_get_platdata(dev);
103         bool stm32f4 = plat->uart_info->stm32f4;
104         fdt_addr_t base = plat->base;
105         u32 isr = readl(base + ISR_OFFSET(stm32f4));
106
107         if ((isr & USART_ISR_RXNE) == 0)
108                 return -EAGAIN;
109
110         if (isr & (USART_ISR_PE | USART_ISR_ORE | USART_ISR_FE)) {
111                 if (!stm32f4)
112                         setbits_le32(base + ICR_OFFSET,
113                                      USART_ICR_PCECF | USART_ICR_ORECF |
114                                      USART_ICR_FECF);
115                 else
116                         readl(base + RDR_OFFSET(stm32f4));
117                 return -EIO;
118         }
119
120         return readl(base + RDR_OFFSET(stm32f4));
121 }
122
123 static int _stm32_serial_putc(fdt_addr_t base,
124                               struct stm32_uart_info *uart_info,
125                               const char c)
126 {
127         bool stm32f4 = uart_info->stm32f4;
128
129         if ((readl(base + ISR_OFFSET(stm32f4)) & USART_ISR_TXE) == 0)
130                 return -EAGAIN;
131
132         writel(c, base + TDR_OFFSET(stm32f4));
133
134         return 0;
135 }
136
137 static int stm32_serial_putc(struct udevice *dev, const char c)
138 {
139         struct stm32x7_serial_platdata *plat = dev_get_platdata(dev);
140
141         return _stm32_serial_putc(plat->base, plat->uart_info, c);
142 }
143
144 static int stm32_serial_pending(struct udevice *dev, bool input)
145 {
146         struct stm32x7_serial_platdata *plat = dev_get_platdata(dev);
147         bool stm32f4 = plat->uart_info->stm32f4;
148         fdt_addr_t base = plat->base;
149
150         if (input)
151                 return readl(base + ISR_OFFSET(stm32f4)) &
152                         USART_ISR_RXNE ? 1 : 0;
153         else
154                 return readl(base + ISR_OFFSET(stm32f4)) &
155                         USART_ISR_TXE ? 0 : 1;
156 }
157
158 static void _stm32_serial_init(fdt_addr_t base,
159                                struct stm32_uart_info *uart_info)
160 {
161         bool stm32f4 = uart_info->stm32f4;
162         u8 uart_enable_bit = uart_info->uart_enable_bit;
163
164         /* Disable uart-> enable fifo -> enable uart */
165         clrbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_RE | USART_CR1_TE |
166                      BIT(uart_enable_bit));
167         if (uart_info->has_fifo)
168                 setbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_FIFOEN);
169         setbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_RE | USART_CR1_TE |
170                      BIT(uart_enable_bit));
171 }
172
173 static int stm32_serial_probe(struct udevice *dev)
174 {
175         struct stm32x7_serial_platdata *plat = dev_get_platdata(dev);
176         struct clk clk;
177         struct reset_ctl reset;
178         int ret;
179
180         plat->uart_info = (struct stm32_uart_info *)dev_get_driver_data(dev);
181
182         ret = clk_get_by_index(dev, 0, &clk);
183         if (ret < 0)
184                 return ret;
185
186         ret = clk_enable(&clk);
187         if (ret) {
188                 dev_err(dev, "failed to enable clock\n");
189                 return ret;
190         }
191
192         ret = reset_get_by_index(dev, 0, &reset);
193         if (!ret) {
194                 reset_assert(&reset);
195                 udelay(2);
196                 reset_deassert(&reset);
197         }
198
199         plat->clock_rate = clk_get_rate(&clk);
200         if (!plat->clock_rate) {
201                 clk_disable(&clk);
202                 return -EINVAL;
203         };
204
205         _stm32_serial_init(plat->base, plat->uart_info);
206
207         return 0;
208 }
209
210 static const struct udevice_id stm32_serial_id[] = {
211         { .compatible = "st,stm32-uart", .data = (ulong)&stm32f4_info},
212         { .compatible = "st,stm32f7-uart", .data = (ulong)&stm32f7_info},
213         { .compatible = "st,stm32h7-uart", .data = (ulong)&stm32h7_info},
214         {}
215 };
216
217 static int stm32_serial_ofdata_to_platdata(struct udevice *dev)
218 {
219         struct stm32x7_serial_platdata *plat = dev_get_platdata(dev);
220
221         plat->base = devfdt_get_addr(dev);
222         if (plat->base == FDT_ADDR_T_NONE)
223                 return -EINVAL;
224
225         return 0;
226 }
227
228 static const struct dm_serial_ops stm32_serial_ops = {
229         .putc = stm32_serial_putc,
230         .pending = stm32_serial_pending,
231         .getc = stm32_serial_getc,
232         .setbrg = stm32_serial_setbrg,
233         .setconfig = stm32_serial_setconfig
234 };
235
236 U_BOOT_DRIVER(serial_stm32) = {
237         .name = "serial_stm32",
238         .id = UCLASS_SERIAL,
239         .of_match = of_match_ptr(stm32_serial_id),
240         .ofdata_to_platdata = of_match_ptr(stm32_serial_ofdata_to_platdata),
241         .platdata_auto_alloc_size = sizeof(struct stm32x7_serial_platdata),
242         .ops = &stm32_serial_ops,
243         .probe = stm32_serial_probe,
244 #if !CONFIG_IS_ENABLED(OF_CONTROL)
245         .flags = DM_FLAG_PRE_RELOC,
246 #endif
247 };
248
249 #ifdef CONFIG_DEBUG_UART_STM32
250 #include <debug_uart.h>
251 static inline struct stm32_uart_info *_debug_uart_info(void)
252 {
253         struct stm32_uart_info *uart_info;
254
255 #if defined(CONFIG_STM32F4)
256         uart_info = &stm32f4_info;
257 #elif defined(CONFIG_STM32F7)
258         uart_info = &stm32f7_info;
259 #else
260         uart_info = &stm32h7_info;
261 #endif
262         return uart_info;
263 }
264
265 static inline void _debug_uart_init(void)
266 {
267         fdt_addr_t base = CONFIG_DEBUG_UART_BASE;
268         struct stm32_uart_info *uart_info = _debug_uart_info();
269
270         _stm32_serial_init(base, uart_info);
271         _stm32_serial_setbrg(base, uart_info,
272                              CONFIG_DEBUG_UART_CLOCK,
273                              CONFIG_BAUDRATE);
274 }
275
276 static inline void _debug_uart_putc(int c)
277 {
278         fdt_addr_t base = CONFIG_DEBUG_UART_BASE;
279         struct stm32_uart_info *uart_info = _debug_uart_info();
280
281         while (_stm32_serial_putc(base, uart_info, c) == -EAGAIN)
282                 ;
283 }
284
285 DEBUG_UART_FUNCS
286 #endif