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