1 /* 2 * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <errno.h> 9 #include <string.h> 10 11 #include <common/bl_common.h> 12 #include <drivers/delay_timer.h> 13 #include <drivers/st/stm32_uart.h> 14 #include <drivers/st/stm32_uart_regs.h> 15 #include <drivers/st/stm32mp_clkfunc.h> 16 #include <lib/mmio.h> 17 18 #include <platform_def.h> 19 20 /* UART time-out value */ 21 #define STM32_UART_TIMEOUT_US 20000U 22 23 /* Mask to clear ALL the configuration registers */ 24 25 #define STM32_UART_CR1_FIELDS \ 26 (USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | \ 27 USART_CR1_RE | USART_CR1_OVER8 | USART_CR1_FIFOEN) 28 29 #define STM32_UART_CR2_FIELDS \ 30 (USART_CR2_SLVEN | USART_CR2_DIS_NSS | USART_CR2_ADDM7 | \ 31 USART_CR2_LBDL | USART_CR2_LBDIE | USART_CR2_LBCL | \ 32 USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | \ 33 USART_CR2_STOP | USART_CR2_LINEN | USART_CR2_SWAP | \ 34 USART_CR2_RXINV | USART_CR2_TXINV | USART_CR2_DATAINV | \ 35 USART_CR2_MSBFIRST | USART_CR2_ABREN | USART_CR2_ABRMODE | \ 36 USART_CR2_RTOEN | USART_CR2_ADD) 37 38 #define STM32_UART_CR3_FIELDS \ 39 (USART_CR3_EIE | USART_CR3_IREN | USART_CR3_IRLP | \ 40 USART_CR3_HDSEL | USART_CR3_NACK | USART_CR3_SCEN | \ 41 USART_CR3_DMAR | USART_CR3_DMAT | USART_CR3_RTSE | \ 42 USART_CR3_CTSE | USART_CR3_CTSIE | USART_CR3_ONEBIT | \ 43 USART_CR3_OVRDIS | USART_CR3_DDRE | USART_CR3_DEM | \ 44 USART_CR3_DEP | USART_CR3_SCARCNT | USART_CR3_WUS | \ 45 USART_CR3_WUFIE | USART_CR3_TXFTIE | USART_CR3_TCBGTIE | \ 46 USART_CR3_RXFTCFG | USART_CR3_RXFTIE | USART_CR3_TXFTCFG) 47 48 #define STM32_UART_ISR_ERRORS \ 49 (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE | USART_ISR_PE) 50 51 static const uint16_t presc_table[STM32_UART_PRESCALER_NB] = { 52 1U, 2U, 4U, 6U, 8U, 10U, 12U, 16U, 32U, 64U, 128U, 256U 53 }; 54 55 /* @brief BRR division operation to set BRR register in 8-bit oversampling 56 * mode. 57 * @param clockfreq: UART clock. 58 * @param baud_rate: Baud rate set by the user. 59 * @param prescaler: UART prescaler value. 60 * @retval Division result. 61 */ 62 static uint32_t uart_div_sampling8(unsigned long clockfreq, 63 uint32_t baud_rate, 64 uint32_t prescaler) 65 { 66 uint32_t scaled_freq = clockfreq / presc_table[prescaler]; 67 68 return ((scaled_freq * 2) + (baud_rate / 2)) / baud_rate; 69 70 } 71 72 /* @brief BRR division operation to set BRR register in 16-bit oversampling 73 * mode. 74 * @param clockfreq: UART clock. 75 * @param baud_rate: Baud rate set by the user. 76 * @param prescaler: UART prescaler value. 77 * @retval Division result. 78 */ 79 static uint32_t uart_div_sampling16(unsigned long clockfreq, 80 uint32_t baud_rate, 81 uint32_t prescaler) 82 { 83 uint32_t scaled_freq = clockfreq / presc_table[prescaler]; 84 85 return (scaled_freq + (baud_rate / 2)) / baud_rate; 86 87 } 88 89 /* 90 * @brief Return the UART clock frequency. 91 * @param huart: UART handle. 92 * @retval Frequency value in Hz. 93 */ 94 static unsigned long uart_get_clock_freq(struct stm32_uart_handle_s *huart) 95 { 96 return fdt_get_uart_clock_freq((uintptr_t)huart->base); 97 } 98 99 /* 100 * @brief Configure the UART peripheral. 101 * @param huart: UART handle. 102 * @retval UART status. 103 */ 104 static int uart_set_config(struct stm32_uart_handle_s *huart, 105 const struct stm32_uart_init_s *init) 106 { 107 uint32_t tmpreg; 108 unsigned long clockfreq; 109 unsigned long int_div; 110 uint32_t brrtemp; 111 uint32_t over_sampling; 112 113 /*---------------------- USART BRR configuration --------------------*/ 114 clockfreq = uart_get_clock_freq(huart); 115 if (clockfreq == 0UL) { 116 return -ENODEV; 117 } 118 119 int_div = clockfreq / init->baud_rate; 120 if (int_div < 16U) { 121 uint32_t usartdiv = uart_div_sampling8(clockfreq, 122 init->baud_rate, 123 init->prescaler); 124 125 brrtemp = (usartdiv & USART_BRR_DIV_MANTISSA) | 126 ((usartdiv & USART_BRR_DIV_FRACTION) >> 1); 127 over_sampling = USART_CR1_OVER8; 128 } else { 129 brrtemp = uart_div_sampling16(clockfreq, 130 init->baud_rate, 131 init->prescaler) & 132 (USART_BRR_DIV_FRACTION | USART_BRR_DIV_MANTISSA); 133 over_sampling = 0x0U; 134 } 135 mmio_write_32(huart->base + USART_BRR, brrtemp); 136 137 /* 138 * ---------------------- USART CR1 Configuration -------------------- 139 * Clear M, PCE, PS, TE, RE and OVER8 bits and configure 140 * the UART word length, parity, mode and oversampling: 141 * - set the M bits according to init->word_length value, 142 * - set PCE and PS bits according to init->parity value, 143 * - set TE and RE bits according to init->mode value, 144 * - set OVER8 bit according baudrate and clock. 145 */ 146 tmpreg = init->word_length | 147 init->parity | 148 init->mode | 149 over_sampling | 150 init->fifo_mode; 151 mmio_clrsetbits_32(huart->base + USART_CR1, STM32_UART_CR1_FIELDS, tmpreg); 152 153 /* 154 * --------------------- USART CR2 Configuration --------------------- 155 * Configure the UART Stop Bits: Set STOP[13:12] bits according 156 * to init->stop_bits value. 157 */ 158 mmio_clrsetbits_32(huart->base + USART_CR2, STM32_UART_CR2_FIELDS, 159 init->stop_bits); 160 161 /* 162 * --------------------- USART CR3 Configuration --------------------- 163 * Configure: 164 * - UART HardWare Flow Control: set CTSE and RTSE bits according 165 * to init->hw_flow_control value, 166 * - one-bit sampling method versus three samples' majority rule 167 * according to init->one_bit_sampling (not applicable to 168 * LPUART), 169 * - set TXFTCFG bit according to init->tx_fifo_threshold value, 170 * - set RXFTCFG bit according to init->rx_fifo_threshold value. 171 */ 172 tmpreg = init->hw_flow_control | init->one_bit_sampling; 173 174 if (init->fifo_mode == USART_CR1_FIFOEN) { 175 tmpreg |= init->tx_fifo_threshold | 176 init->rx_fifo_threshold; 177 } 178 179 mmio_clrsetbits_32(huart->base + USART_CR3, STM32_UART_CR3_FIELDS, tmpreg); 180 181 /* 182 * --------------------- USART PRESC Configuration ------------------- 183 * Configure UART Clock Prescaler : set PRESCALER according to 184 * init->prescaler value. 185 */ 186 assert(init->prescaler < STM32_UART_PRESCALER_NB); 187 mmio_clrsetbits_32(huart->base + USART_PRESC, USART_PRESC_PRESCALER, 188 init->prescaler); 189 190 return 0; 191 } 192 193 /* 194 * @brief Handle UART communication timeout. 195 * @param huart: UART handle. 196 * @param flag: Specifies the UART flag to check. 197 * @retval UART status. 198 */ 199 static int stm32_uart_wait_flag(struct stm32_uart_handle_s *huart, uint32_t flag) 200 { 201 uint64_t timeout_ref = timeout_init_us(STM32_UART_TIMEOUT_US); 202 203 while ((mmio_read_32(huart->base + USART_ISR) & flag) == 0U) { 204 if (timeout_elapsed(timeout_ref)) { 205 return -ETIMEDOUT; 206 } 207 } 208 209 return 0; 210 } 211 212 /* 213 * @brief Check the UART idle State. 214 * @param huart: UART handle. 215 * @retval UART status. 216 */ 217 static int stm32_uart_check_idle(struct stm32_uart_handle_s *huart) 218 { 219 int ret; 220 221 /* Check if the transmitter is enabled */ 222 if ((mmio_read_32(huart->base + USART_CR1) & USART_CR1_TE) == USART_CR1_TE) { 223 ret = stm32_uart_wait_flag(huart, USART_ISR_TEACK); 224 if (ret != 0) { 225 return ret; 226 } 227 } 228 229 /* Check if the receiver is enabled */ 230 if ((mmio_read_32(huart->base + USART_CR1) & USART_CR1_RE) == USART_CR1_RE) { 231 ret = stm32_uart_wait_flag(huart, USART_ISR_REACK); 232 if (ret != 0) { 233 return ret; 234 } 235 } 236 237 return 0; 238 } 239 240 /* 241 * @brief Compute RDR register mask depending on word length. 242 * @param huart: UART handle. 243 * @retval Mask value. 244 */ 245 static unsigned int stm32_uart_rdr_mask(const struct stm32_uart_init_s *init) 246 { 247 unsigned int mask = 0U; 248 249 switch (init->word_length) { 250 case STM32_UART_WORDLENGTH_9B: 251 mask = GENMASK(8, 0); 252 break; 253 case STM32_UART_WORDLENGTH_8B: 254 mask = GENMASK(7, 0); 255 break; 256 case STM32_UART_WORDLENGTH_7B: 257 mask = GENMASK(6, 0); 258 break; 259 default: 260 break; /* not reached */ 261 } 262 263 if (init->parity != STM32_UART_PARITY_NONE) { 264 mask >>= 1; 265 } 266 267 return mask; 268 } 269 270 /* 271 * @brief Check interrupt and status errors. 272 * @retval True if error detected, false otherwise. 273 */ 274 static bool stm32_uart_error_detected(struct stm32_uart_handle_s *huart) 275 { 276 return (mmio_read_32(huart->base + USART_ISR) & STM32_UART_ISR_ERRORS) != 0U; 277 } 278 279 /* 280 * @brief Clear status errors. 281 */ 282 static void stm32_uart_error_clear(struct stm32_uart_handle_s *huart) 283 { 284 mmio_write_32(huart->base + USART_ICR, STM32_UART_ISR_ERRORS); 285 } 286 287 /* 288 * @brief Stop the UART. 289 * @param base: UART base address. 290 */ 291 void stm32_uart_stop(uintptr_t base) 292 { 293 mmio_clrbits_32(base + USART_CR1, USART_CR1_UE); 294 } 295 296 /* 297 * @brief Initialize UART. 298 * @param huart: UART handle. 299 * @param base_addr: base address of UART. 300 * @param init: UART initialization parameter. 301 * @retval UART status. 302 */ 303 304 int stm32_uart_init(struct stm32_uart_handle_s *huart, 305 uintptr_t base_addr, 306 const struct stm32_uart_init_s *init) 307 { 308 int ret; 309 310 if (huart == NULL || init == NULL || base_addr == 0U) { 311 return -EINVAL; 312 } 313 314 huart->base = base_addr; 315 316 /* Disable the peripheral */ 317 stm32_uart_stop(huart->base); 318 319 /* Computation of UART mask to apply to RDR register */ 320 huart->rdr_mask = stm32_uart_rdr_mask(init); 321 322 /* Init the peripheral */ 323 ret = uart_set_config(huart, init); 324 if (ret != 0) { 325 return ret; 326 } 327 328 /* Enable the peripheral */ 329 mmio_setbits_32(huart->base + USART_CR1, USART_CR1_UE); 330 331 /* TEACK and/or REACK to check */ 332 return stm32_uart_check_idle(huart); 333 } 334 335 /* 336 * @brief Transmit one data in no blocking mode. 337 * @param huart: UART handle. 338 * @param c: data to sent. 339 * @retval UART status. 340 */ 341 int stm32_uart_putc(struct stm32_uart_handle_s *huart, int c) 342 { 343 int ret; 344 345 if (huart == NULL) { 346 return -EINVAL; 347 } 348 349 ret = stm32_uart_wait_flag(huart, USART_ISR_TXE); 350 if (ret != 0) { 351 return ret; 352 } 353 354 mmio_write_32(huart->base + USART_TDR, c); 355 if (stm32_uart_error_detected(huart)) { 356 stm32_uart_error_clear(huart); 357 return -EFAULT; 358 } 359 360 return 0; 361 } 362 363 /* 364 * @brief Flush TX Transmit fifo 365 * @param huart: UART handle. 366 * @retval UART status. 367 */ 368 int stm32_uart_flush(struct stm32_uart_handle_s *huart) 369 { 370 int ret; 371 372 if (huart == NULL) { 373 return -EINVAL; 374 } 375 376 ret = stm32_uart_wait_flag(huart, USART_ISR_TXE); 377 if (ret != 0) { 378 return ret; 379 } 380 381 return stm32_uart_wait_flag(huart, USART_ISR_TC); 382 } 383 384 /* 385 * @brief Receive a data in no blocking mode. 386 * @retval value if >0 or UART status. 387 */ 388 int stm32_uart_getc(struct stm32_uart_handle_s *huart) 389 { 390 uint32_t data; 391 392 if (huart == NULL) { 393 return -EINVAL; 394 } 395 396 /* Check if data is available */ 397 if ((mmio_read_32(huart->base + USART_ISR) & USART_ISR_RXNE) == 0U) { 398 return -EAGAIN; 399 } 400 401 data = mmio_read_32(huart->base + USART_RDR) & huart->rdr_mask; 402 403 if (stm32_uart_error_detected(huart)) { 404 stm32_uart_error_clear(huart); 405 return -EFAULT; 406 } 407 408 return (int)data; 409 } 410