1 /* 2 * (C) Copyright 2016 3 * Vikas Manocha, <vikas.manocha@st.com> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <dm.h> 10 #include <asm/io.h> 11 #include <serial.h> 12 #include <asm/arch/stm32.h> 13 #include <dm/platform_data/serial_stm32x7.h> 14 #include "serial_stm32x7.h" 15 16 DECLARE_GLOBAL_DATA_PTR; 17 18 static int stm32_serial_setbrg(struct udevice *dev, int baudrate) 19 { 20 struct stm32x7_serial_platdata *plat = dev->platdata; 21 struct stm32_usart *const usart = plat->base; 22 u32 clock, int_div, frac_div, tmp; 23 24 if (((u32)usart & STM32_BUS_MASK) == APB1_PERIPH_BASE) 25 clock = clock_get(CLOCK_APB1); 26 else if (((u32)usart & STM32_BUS_MASK) == APB2_PERIPH_BASE) 27 clock = clock_get(CLOCK_APB2); 28 else 29 return -EINVAL; 30 31 int_div = (25 * clock) / (4 * baudrate); 32 tmp = ((int_div / 100) << USART_BRR_M_SHIFT) & USART_BRR_M_MASK; 33 frac_div = int_div - (100 * (tmp >> USART_BRR_M_SHIFT)); 34 tmp |= (((frac_div * 16) + 50) / 100) & USART_BRR_F_MASK; 35 writel(tmp, &usart->brr); 36 37 return 0; 38 } 39 40 static int stm32_serial_getc(struct udevice *dev) 41 { 42 struct stm32x7_serial_platdata *plat = dev->platdata; 43 struct stm32_usart *const usart = plat->base; 44 45 if ((readl(&usart->sr) & USART_SR_FLAG_RXNE) == 0) 46 return -EAGAIN; 47 48 return readl(&usart->rd_dr); 49 } 50 51 static int stm32_serial_putc(struct udevice *dev, const char c) 52 { 53 struct stm32x7_serial_platdata *plat = dev->platdata; 54 struct stm32_usart *const usart = plat->base; 55 56 if ((readl(&usart->sr) & USART_SR_FLAG_TXE) == 0) 57 return -EAGAIN; 58 59 writel(c, &usart->tx_dr); 60 61 return 0; 62 } 63 64 static int stm32_serial_pending(struct udevice *dev, bool input) 65 { 66 struct stm32x7_serial_platdata *plat = dev->platdata; 67 struct stm32_usart *const usart = plat->base; 68 69 if (input) 70 return readl(&usart->sr) & USART_SR_FLAG_RXNE ? 1 : 0; 71 else 72 return readl(&usart->sr) & USART_SR_FLAG_TXE ? 0 : 1; 73 } 74 75 static int stm32_serial_probe(struct udevice *dev) 76 { 77 struct stm32x7_serial_platdata *plat = dev->platdata; 78 struct stm32_usart *const usart = plat->base; 79 setbits_le32(&usart->cr1, USART_CR1_RE | USART_CR1_TE | USART_CR1_UE); 80 81 return 0; 82 } 83 84 #if CONFIG_IS_ENABLED(OF_CONTROL) 85 static const struct udevice_id stm32_serial_id[] = { 86 {.compatible = "st,stm32-usart"}, 87 {.compatible = "st,stm32-uart"}, 88 {} 89 }; 90 91 static int stm32_serial_ofdata_to_platdata(struct udevice *dev) 92 { 93 struct stm32x7_serial_platdata *plat = dev_get_platdata(dev); 94 fdt_addr_t addr; 95 96 addr = dev_get_addr(dev); 97 if (addr == FDT_ADDR_T_NONE) 98 return -EINVAL; 99 100 plat->base = (struct stm32_usart *)addr; 101 return 0; 102 } 103 #endif 104 105 static const struct dm_serial_ops stm32_serial_ops = { 106 .putc = stm32_serial_putc, 107 .pending = stm32_serial_pending, 108 .getc = stm32_serial_getc, 109 .setbrg = stm32_serial_setbrg, 110 }; 111 112 U_BOOT_DRIVER(serial_stm32) = { 113 .name = "serial_stm32x7", 114 .id = UCLASS_SERIAL, 115 .of_match = of_match_ptr(stm32_serial_id), 116 .ofdata_to_platdata = of_match_ptr(stm32_serial_ofdata_to_platdata), 117 .platdata_auto_alloc_size = sizeof(struct stm32x7_serial_platdata), 118 .ops = &stm32_serial_ops, 119 .probe = stm32_serial_probe, 120 .flags = DM_FLAG_PRE_RELOC, 121 }; 122