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