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