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 <clk.h> 10 #include <dm.h> 11 #include <asm/io.h> 12 #include <serial.h> 13 #include <asm/arch/stm32.h> 14 #include <dm/platform_data/serial_stm32x7.h> 15 #include "serial_stm32x7.h" 16 17 DECLARE_GLOBAL_DATA_PTR; 18 19 static int stm32_serial_setbrg(struct udevice *dev, int baudrate) 20 { 21 struct stm32x7_serial_platdata *plat = dev->platdata; 22 struct stm32_usart *const usart = plat->base; 23 u32 clock, int_div, mantissa, fraction, oversampling; 24 25 if (((u32)usart & STM32_BUS_MASK) == APB1_PERIPH_BASE) 26 clock = clock_get(CLOCK_APB1); 27 else if (((u32)usart & STM32_BUS_MASK) == APB2_PERIPH_BASE) 28 clock = clock_get(CLOCK_APB2); 29 else 30 return -EINVAL; 31 32 int_div = DIV_ROUND_CLOSEST(clock, baudrate); 33 34 if (int_div < 16) { 35 oversampling = 8; 36 setbits_le32(&usart->cr1, USART_CR1_OVER8); 37 } else { 38 oversampling = 16; 39 clrbits_le32(&usart->cr1, USART_CR1_OVER8); 40 } 41 42 mantissa = (int_div / oversampling) << USART_BRR_M_SHIFT; 43 fraction = int_div % oversampling; 44 45 writel(mantissa | fraction, &usart->brr); 46 47 return 0; 48 } 49 50 static int stm32_serial_getc(struct udevice *dev) 51 { 52 struct stm32x7_serial_platdata *plat = dev->platdata; 53 struct stm32_usart *const usart = plat->base; 54 55 if ((readl(&usart->sr) & USART_SR_FLAG_RXNE) == 0) 56 return -EAGAIN; 57 58 return readl(&usart->rd_dr); 59 } 60 61 static int stm32_serial_putc(struct udevice *dev, const char c) 62 { 63 struct stm32x7_serial_platdata *plat = dev->platdata; 64 struct stm32_usart *const usart = plat->base; 65 66 if ((readl(&usart->sr) & USART_SR_FLAG_TXE) == 0) 67 return -EAGAIN; 68 69 writel(c, &usart->tx_dr); 70 71 return 0; 72 } 73 74 static int stm32_serial_pending(struct udevice *dev, bool input) 75 { 76 struct stm32x7_serial_platdata *plat = dev->platdata; 77 struct stm32_usart *const usart = plat->base; 78 79 if (input) 80 return readl(&usart->sr) & USART_SR_FLAG_RXNE ? 1 : 0; 81 else 82 return readl(&usart->sr) & USART_SR_FLAG_TXE ? 0 : 1; 83 } 84 85 static int stm32_serial_probe(struct udevice *dev) 86 { 87 struct stm32x7_serial_platdata *plat = dev->platdata; 88 struct stm32_usart *const usart = plat->base; 89 90 #ifdef CONFIG_CLK 91 int ret; 92 struct clk clk; 93 94 ret = clk_get_by_index(dev, 0, &clk); 95 if (ret < 0) 96 return ret; 97 98 ret = clk_enable(&clk); 99 if (ret) { 100 dev_err(dev, "failed to enable clock\n"); 101 return ret; 102 } 103 #endif 104 105 /* Disable usart-> disable overrun-> enable usart */ 106 clrbits_le32(&usart->cr1, USART_CR1_RE | USART_CR1_TE | USART_CR1_UE); 107 setbits_le32(&usart->cr3, USART_CR3_OVRDIS); 108 setbits_le32(&usart->cr1, USART_CR1_RE | USART_CR1_TE | USART_CR1_UE); 109 110 return 0; 111 } 112 113 #if CONFIG_IS_ENABLED(OF_CONTROL) 114 static const struct udevice_id stm32_serial_id[] = { 115 {.compatible = "st,stm32f7-usart"}, 116 {.compatible = "st,stm32f7-uart"}, 117 {} 118 }; 119 120 static int stm32_serial_ofdata_to_platdata(struct udevice *dev) 121 { 122 struct stm32x7_serial_platdata *plat = dev_get_platdata(dev); 123 fdt_addr_t addr; 124 125 addr = devfdt_get_addr(dev); 126 if (addr == FDT_ADDR_T_NONE) 127 return -EINVAL; 128 129 plat->base = (struct stm32_usart *)addr; 130 131 return 0; 132 } 133 #endif 134 135 static const struct dm_serial_ops stm32_serial_ops = { 136 .putc = stm32_serial_putc, 137 .pending = stm32_serial_pending, 138 .getc = stm32_serial_getc, 139 .setbrg = stm32_serial_setbrg, 140 }; 141 142 U_BOOT_DRIVER(serial_stm32) = { 143 .name = "serial_stm32x7", 144 .id = UCLASS_SERIAL, 145 .of_match = of_match_ptr(stm32_serial_id), 146 .ofdata_to_platdata = of_match_ptr(stm32_serial_ofdata_to_platdata), 147 .platdata_auto_alloc_size = sizeof(struct stm32x7_serial_platdata), 148 .ops = &stm32_serial_ops, 149 .probe = stm32_serial_probe, 150 .flags = DM_FLAG_PRE_RELOC, 151 }; 152