16a12cebdSVikas Manocha /* 26a12cebdSVikas Manocha * (C) Copyright 2016 36a12cebdSVikas Manocha * Vikas Manocha, <vikas.manocha@st.com> 46a12cebdSVikas Manocha * 56a12cebdSVikas Manocha * SPDX-License-Identifier: GPL-2.0+ 66a12cebdSVikas Manocha */ 76a12cebdSVikas Manocha 86a12cebdSVikas Manocha #include <common.h> 9fd03b83aSVikas Manocha #include <clk.h> 106a12cebdSVikas Manocha #include <dm.h> 116a12cebdSVikas Manocha #include <asm/io.h> 126a12cebdSVikas Manocha #include <serial.h> 13ba0a3c16SToshifumi NISHINAGA #include <asm/arch/stm32.h> 146a12cebdSVikas Manocha #include <dm/platform_data/serial_stm32x7.h> 156a12cebdSVikas Manocha #include "serial_stm32x7.h" 166a12cebdSVikas Manocha 176a12cebdSVikas Manocha DECLARE_GLOBAL_DATA_PTR; 186a12cebdSVikas Manocha 196a12cebdSVikas Manocha static int stm32_serial_setbrg(struct udevice *dev, int baudrate) 206a12cebdSVikas Manocha { 216a12cebdSVikas Manocha struct stm32x7_serial_platdata *plat = dev->platdata; 226a12cebdSVikas Manocha struct stm32_usart *const usart = plat->base; 23ba0a3c16SToshifumi NISHINAGA u32 clock, int_div, frac_div, tmp; 24ba0a3c16SToshifumi NISHINAGA 25ba0a3c16SToshifumi NISHINAGA if (((u32)usart & STM32_BUS_MASK) == APB1_PERIPH_BASE) 26ba0a3c16SToshifumi NISHINAGA clock = clock_get(CLOCK_APB1); 27ba0a3c16SToshifumi NISHINAGA else if (((u32)usart & STM32_BUS_MASK) == APB2_PERIPH_BASE) 28ba0a3c16SToshifumi NISHINAGA clock = clock_get(CLOCK_APB2); 29ba0a3c16SToshifumi NISHINAGA else 30ba0a3c16SToshifumi NISHINAGA return -EINVAL; 31ba0a3c16SToshifumi NISHINAGA 32ba0a3c16SToshifumi NISHINAGA int_div = (25 * clock) / (4 * baudrate); 33ba0a3c16SToshifumi NISHINAGA tmp = ((int_div / 100) << USART_BRR_M_SHIFT) & USART_BRR_M_MASK; 34ba0a3c16SToshifumi NISHINAGA frac_div = int_div - (100 * (tmp >> USART_BRR_M_SHIFT)); 35ba0a3c16SToshifumi NISHINAGA tmp |= (((frac_div * 16) + 50) / 100) & USART_BRR_F_MASK; 36ba0a3c16SToshifumi NISHINAGA writel(tmp, &usart->brr); 376a12cebdSVikas Manocha 386a12cebdSVikas Manocha return 0; 396a12cebdSVikas Manocha } 406a12cebdSVikas Manocha 416a12cebdSVikas Manocha static int stm32_serial_getc(struct udevice *dev) 426a12cebdSVikas Manocha { 436a12cebdSVikas Manocha struct stm32x7_serial_platdata *plat = dev->platdata; 446a12cebdSVikas Manocha struct stm32_usart *const usart = plat->base; 456a12cebdSVikas Manocha 466a12cebdSVikas Manocha if ((readl(&usart->sr) & USART_SR_FLAG_RXNE) == 0) 476a12cebdSVikas Manocha return -EAGAIN; 486a12cebdSVikas Manocha 496a12cebdSVikas Manocha return readl(&usart->rd_dr); 506a12cebdSVikas Manocha } 516a12cebdSVikas Manocha 526a12cebdSVikas Manocha static int stm32_serial_putc(struct udevice *dev, const char c) 536a12cebdSVikas Manocha { 546a12cebdSVikas Manocha struct stm32x7_serial_platdata *plat = dev->platdata; 556a12cebdSVikas Manocha struct stm32_usart *const usart = plat->base; 566a12cebdSVikas Manocha 576a12cebdSVikas Manocha if ((readl(&usart->sr) & USART_SR_FLAG_TXE) == 0) 586a12cebdSVikas Manocha return -EAGAIN; 596a12cebdSVikas Manocha 606a12cebdSVikas Manocha writel(c, &usart->tx_dr); 616a12cebdSVikas Manocha 626a12cebdSVikas Manocha return 0; 636a12cebdSVikas Manocha } 646a12cebdSVikas Manocha 656a12cebdSVikas Manocha static int stm32_serial_pending(struct udevice *dev, bool input) 666a12cebdSVikas Manocha { 676a12cebdSVikas Manocha struct stm32x7_serial_platdata *plat = dev->platdata; 686a12cebdSVikas Manocha struct stm32_usart *const usart = plat->base; 696a12cebdSVikas Manocha 706a12cebdSVikas Manocha if (input) 716a12cebdSVikas Manocha return readl(&usart->sr) & USART_SR_FLAG_RXNE ? 1 : 0; 726a12cebdSVikas Manocha else 736a12cebdSVikas Manocha return readl(&usart->sr) & USART_SR_FLAG_TXE ? 0 : 1; 746a12cebdSVikas Manocha } 756a12cebdSVikas Manocha 766a12cebdSVikas Manocha static int stm32_serial_probe(struct udevice *dev) 776a12cebdSVikas Manocha { 786a12cebdSVikas Manocha struct stm32x7_serial_platdata *plat = dev->platdata; 796a12cebdSVikas Manocha struct stm32_usart *const usart = plat->base; 80fd03b83aSVikas Manocha 81fd03b83aSVikas Manocha #ifdef CONFIG_CLK 82fd03b83aSVikas Manocha int ret; 83fd03b83aSVikas Manocha struct clk clk; 84fd03b83aSVikas Manocha 85fd03b83aSVikas Manocha ret = clk_get_by_index(dev, 0, &clk); 86fd03b83aSVikas Manocha if (ret < 0) 87fd03b83aSVikas Manocha return ret; 88fd03b83aSVikas Manocha 89fd03b83aSVikas Manocha ret = clk_enable(&clk); 90fd03b83aSVikas Manocha if (ret) { 91fd03b83aSVikas Manocha dev_err(dev, "failed to enable clock\n"); 92fd03b83aSVikas Manocha return ret; 93fd03b83aSVikas Manocha } 94fd03b83aSVikas Manocha #endif 95fd03b83aSVikas Manocha 96*6c0c3ce8SVikas Manocha /* Disable usart-> disable overrun-> enable usart */ 97*6c0c3ce8SVikas Manocha clrbits_le32(&usart->cr1, USART_CR1_RE | USART_CR1_TE | USART_CR1_UE); 98*6c0c3ce8SVikas Manocha setbits_le32(&usart->cr3, USART_CR3_OVRDIS); 996a12cebdSVikas Manocha setbits_le32(&usart->cr1, USART_CR1_RE | USART_CR1_TE | USART_CR1_UE); 1006a12cebdSVikas Manocha 1016a12cebdSVikas Manocha return 0; 1026a12cebdSVikas Manocha } 1036a12cebdSVikas Manocha 10442bf5e7cSVikas Manocha #if CONFIG_IS_ENABLED(OF_CONTROL) 10542bf5e7cSVikas Manocha static const struct udevice_id stm32_serial_id[] = { 10642bf5e7cSVikas Manocha {.compatible = "st,stm32-usart"}, 10742bf5e7cSVikas Manocha {.compatible = "st,stm32-uart"}, 10842bf5e7cSVikas Manocha {} 10942bf5e7cSVikas Manocha }; 11042bf5e7cSVikas Manocha 11142bf5e7cSVikas Manocha static int stm32_serial_ofdata_to_platdata(struct udevice *dev) 11242bf5e7cSVikas Manocha { 11342bf5e7cSVikas Manocha struct stm32x7_serial_platdata *plat = dev_get_platdata(dev); 11442bf5e7cSVikas Manocha fdt_addr_t addr; 11542bf5e7cSVikas Manocha 116a821c4afSSimon Glass addr = devfdt_get_addr(dev); 11742bf5e7cSVikas Manocha if (addr == FDT_ADDR_T_NONE) 11842bf5e7cSVikas Manocha return -EINVAL; 11942bf5e7cSVikas Manocha 12042bf5e7cSVikas Manocha plat->base = (struct stm32_usart *)addr; 121fd03b83aSVikas Manocha 12242bf5e7cSVikas Manocha return 0; 12342bf5e7cSVikas Manocha } 12442bf5e7cSVikas Manocha #endif 12542bf5e7cSVikas Manocha 1266a12cebdSVikas Manocha static const struct dm_serial_ops stm32_serial_ops = { 1276a12cebdSVikas Manocha .putc = stm32_serial_putc, 1286a12cebdSVikas Manocha .pending = stm32_serial_pending, 1296a12cebdSVikas Manocha .getc = stm32_serial_getc, 1306a12cebdSVikas Manocha .setbrg = stm32_serial_setbrg, 1316a12cebdSVikas Manocha }; 1326a12cebdSVikas Manocha 1336a12cebdSVikas Manocha U_BOOT_DRIVER(serial_stm32) = { 1346a12cebdSVikas Manocha .name = "serial_stm32x7", 1356a12cebdSVikas Manocha .id = UCLASS_SERIAL, 13642bf5e7cSVikas Manocha .of_match = of_match_ptr(stm32_serial_id), 13742bf5e7cSVikas Manocha .ofdata_to_platdata = of_match_ptr(stm32_serial_ofdata_to_platdata), 13842bf5e7cSVikas Manocha .platdata_auto_alloc_size = sizeof(struct stm32x7_serial_platdata), 1396a12cebdSVikas Manocha .ops = &stm32_serial_ops, 1406a12cebdSVikas Manocha .probe = stm32_serial_probe, 1416a12cebdSVikas Manocha .flags = DM_FLAG_PRE_RELOC, 1426a12cebdSVikas Manocha }; 143