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