diff options
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/Kconfig | 2 | ||||
-rw-r--r-- | drivers/serial/Makefile | 2 | ||||
-rw-r--r-- | drivers/serial/serial_lpuart.c | 18 | ||||
-rw-r--r-- | drivers/serial/serial_stm32.c | 150 | ||||
-rw-r--r-- | drivers/serial/serial_stm32.h (renamed from drivers/serial/serial_stm32x7.h) | 4 | ||||
-rw-r--r-- | drivers/serial/serial_stm32x7.c | 159 |
6 files changed, 107 insertions, 228 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 122b8e786a..7b20b47964 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -529,7 +529,7 @@ config STI_ASC_SERIAL on STiH410 SoC. This is a basic implementation, it supports following baudrate 9600, 19200, 38400, 57600 and 115200. -config STM32X7_SERIAL +config STM32_SERIAL bool "STMicroelectronics STM32 SoCs on-chip UART" depends on DM_SERIAL && (STM32F4 || STM32F7 || STM32H7) help diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 7adcee3e10..5ef603ab15 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -44,7 +44,7 @@ obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o obj-$(CONFIG_STI_ASC_SERIAL) += serial_sti_asc.o obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o -obj-$(CONFIG_STM32X7_SERIAL) += serial_stm32x7.o +obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o obj-$(CONFIG_BCM283X_MU_SERIAL) += serial_bcm283x_mu.o obj-$(CONFIG_MSM_SERIAL) += serial_msm.o obj-$(CONFIG_MVEBU_A3700_UART) += serial_mvebu_a3700.o diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c index 382f8ba5b5..536d30f66a 100644 --- a/drivers/serial/serial_lpuart.c +++ b/drivers/serial/serial_lpuart.c @@ -265,11 +265,9 @@ static int _lpuart32_serial_getc(struct lpuart_serial_platdata *plat) lpuart_read32(plat->flags, &base->data, &val); - if (plat->devtype & DEV_MX7ULP) { - lpuart_read32(plat->flags, &base->stat, &stat); - if (stat & STAT_OR) - lpuart_write32(plat->flags, &base->stat, STAT_OR); - } + lpuart_read32(plat->flags, &base->stat, &stat); + if (stat & STAT_OR) + lpuart_write32(plat->flags, &base->stat, STAT_OR); return val & 0x3ff; } @@ -280,10 +278,8 @@ static void _lpuart32_serial_putc(struct lpuart_serial_platdata *plat, struct lpuart_fsl_reg32 *base = plat->reg; u32 stat; - if (plat->devtype & DEV_MX7ULP) { - if (c == '\n') - serial_putc('\r'); - } + if (c == '\n') + serial_putc('\r'); while (true) { lpuart_read32(plat->flags, &base->stat, &stat); @@ -330,7 +326,7 @@ static int _lpuart32_serial_init(struct lpuart_serial_platdata *plat) lpuart_write32(plat->flags, &base->match, 0); - if (plat->devtype & DEV_MX7ULP) { + if (plat->devtype == DEV_MX7ULP) { _lpuart32_serial_setbrg_7ulp(plat, gd->baudrate); } else { /* provide data bits, parity, stop bit, etc */ @@ -347,7 +343,7 @@ static int lpuart_serial_setbrg(struct udevice *dev, int baudrate) struct lpuart_serial_platdata *plat = dev->platdata; if (is_lpuart32(dev)) { - if (plat->devtype & DEV_MX7ULP) + if (plat->devtype == DEV_MX7ULP) _lpuart32_serial_setbrg_7ulp(plat, baudrate); else _lpuart32_serial_setbrg(plat, baudrate); diff --git a/drivers/serial/serial_stm32.c b/drivers/serial/serial_stm32.c index c793ba6e90..286b954fdd 100644 --- a/drivers/serial/serial_stm32.c +++ b/drivers/serial/serial_stm32.c @@ -1,102 +1,141 @@ /* - * (C) Copyright 2015 - * Kamil Lulko, <kamil.lulko@gmail.com> + * Copyright (C) 2016, STMicroelectronics - All Rights Reserved + * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics. * * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> +#include <clk.h> #include <dm.h> #include <asm/io.h> #include <serial.h> #include <asm/arch/stm32.h> -#include <dm/platform_data/serial_stm32.h> - -struct stm32_usart { - u32 sr; - u32 dr; - u32 brr; - u32 cr1; - u32 cr2; - u32 cr3; - u32 gtpr; -}; - -#define USART_CR1_RE (1 << 2) -#define USART_CR1_TE (1 << 3) -#define USART_CR1_UE (1 << 13) - -#define USART_SR_FLAG_RXNE (1 << 5) -#define USART_SR_FLAG_TXE (1 << 7) - -#define USART_BRR_F_MASK 0xF -#define USART_BRR_M_SHIFT 4 -#define USART_BRR_M_MASK 0xFFF0 +#include "serial_stm32.h" DECLARE_GLOBAL_DATA_PTR; static int stm32_serial_setbrg(struct udevice *dev, int baudrate) { - struct stm32_serial_platdata *plat = dev->platdata; - struct stm32_usart *const usart = plat->base; - u32 clock, int_div, frac_div, tmp; - - if (((u32)usart & STM32_BUS_MASK) == STM32_APB1PERIPH_BASE) - clock = clock_get(CLOCK_APB1); - else if (((u32)usart & STM32_BUS_MASK) == STM32_APB2PERIPH_BASE) - clock = clock_get(CLOCK_APB2); - else - return -EINVAL; + struct stm32x7_serial_platdata *plat = dev_get_platdata(dev); + bool stm32f4 = plat->uart_info->stm32f4; + fdt_addr_t base = plat->base; + u32 int_div, mantissa, fraction, oversampling; + + int_div = DIV_ROUND_CLOSEST(plat->clock_rate, baudrate); + + if (int_div < 16) { + oversampling = 8; + setbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_OVER8); + } else { + oversampling = 16; + clrbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_OVER8); + } + + mantissa = (int_div / oversampling) << USART_BRR_M_SHIFT; + fraction = int_div % oversampling; - int_div = (25 * clock) / (4 * baudrate); - tmp = ((int_div / 100) << USART_BRR_M_SHIFT) & USART_BRR_M_MASK; - frac_div = int_div - (100 * (tmp >> USART_BRR_M_SHIFT)); - tmp |= (((frac_div * 16) + 50) / 100) & USART_BRR_F_MASK; - writel(tmp, &usart->brr); + writel(mantissa | fraction, base + BRR_OFFSET(stm32f4)); return 0; } static int stm32_serial_getc(struct udevice *dev) { - struct stm32_serial_platdata *plat = dev->platdata; - struct stm32_usart *const usart = plat->base; + struct stm32x7_serial_platdata *plat = dev_get_platdata(dev); + bool stm32f4 = plat->uart_info->stm32f4; + fdt_addr_t base = plat->base; - if ((readl(&usart->sr) & USART_SR_FLAG_RXNE) == 0) + if ((readl(base + ISR_OFFSET(stm32f4)) & USART_SR_FLAG_RXNE) == 0) return -EAGAIN; - return readl(&usart->dr); + return readl(base + RDR_OFFSET(stm32f4)); } static int stm32_serial_putc(struct udevice *dev, const char c) { - struct stm32_serial_platdata *plat = dev->platdata; - struct stm32_usart *const usart = plat->base; + struct stm32x7_serial_platdata *plat = dev_get_platdata(dev); + bool stm32f4 = plat->uart_info->stm32f4; + fdt_addr_t base = plat->base; - if ((readl(&usart->sr) & USART_SR_FLAG_TXE) == 0) + if ((readl(base + ISR_OFFSET(stm32f4)) & USART_SR_FLAG_TXE) == 0) return -EAGAIN; - writel(c, &usart->dr); + writel(c, base + TDR_OFFSET(stm32f4)); return 0; } static int stm32_serial_pending(struct udevice *dev, bool input) { - struct stm32_serial_platdata *plat = dev->platdata; - struct stm32_usart *const usart = plat->base; + struct stm32x7_serial_platdata *plat = dev_get_platdata(dev); + bool stm32f4 = plat->uart_info->stm32f4; + fdt_addr_t base = plat->base; if (input) - return readl(&usart->sr) & USART_SR_FLAG_RXNE ? 1 : 0; + return readl(base + ISR_OFFSET(stm32f4)) & + USART_SR_FLAG_RXNE ? 1 : 0; else - return readl(&usart->sr) & USART_SR_FLAG_TXE ? 0 : 1; + return readl(base + ISR_OFFSET(stm32f4)) & + USART_SR_FLAG_TXE ? 0 : 1; } static int stm32_serial_probe(struct udevice *dev) { - struct stm32_serial_platdata *plat = dev->platdata; - struct stm32_usart *const usart = plat->base; - setbits_le32(&usart->cr1, USART_CR1_RE | USART_CR1_TE | USART_CR1_UE); + struct stm32x7_serial_platdata *plat = dev_get_platdata(dev); + struct clk clk; + fdt_addr_t base = plat->base; + int ret; + bool stm32f4; + u8 uart_enable_bit; + + plat->uart_info = (struct stm32_uart_info *)dev_get_driver_data(dev); + stm32f4 = plat->uart_info->stm32f4; + uart_enable_bit = plat->uart_info->uart_enable_bit; + + ret = clk_get_by_index(dev, 0, &clk); + if (ret < 0) + return ret; + + ret = clk_enable(&clk); + if (ret) { + dev_err(dev, "failed to enable clock\n"); + return ret; + } + + plat->clock_rate = clk_get_rate(&clk); + if (plat->clock_rate < 0) { + clk_disable(&clk); + return plat->clock_rate; + }; + + /* Disable uart-> disable overrun-> enable uart */ + clrbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_RE | USART_CR1_TE | + BIT(uart_enable_bit)); + if (plat->uart_info->has_overrun_disable) + setbits_le32(base + CR3_OFFSET(stm32f4), USART_CR3_OVRDIS); + if (plat->uart_info->has_fifo) + setbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_FIFOEN); + setbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_RE | USART_CR1_TE | + BIT(uart_enable_bit)); + + return 0; +} + +static const struct udevice_id stm32_serial_id[] = { + { .compatible = "st,stm32-uart", .data = (ulong)&stm32f4_info}, + { .compatible = "st,stm32f7-uart", .data = (ulong)&stm32f7_info}, + { .compatible = "st,stm32h7-uart", .data = (ulong)&stm32h7_info}, + {} +}; + +static int stm32_serial_ofdata_to_platdata(struct udevice *dev) +{ + struct stm32x7_serial_platdata *plat = dev_get_platdata(dev); + + plat->base = devfdt_get_addr(dev); + if (plat->base == FDT_ADDR_T_NONE) + return -EINVAL; return 0; } @@ -111,6 +150,9 @@ static const struct dm_serial_ops stm32_serial_ops = { U_BOOT_DRIVER(serial_stm32) = { .name = "serial_stm32", .id = UCLASS_SERIAL, + .of_match = of_match_ptr(stm32_serial_id), + .ofdata_to_platdata = of_match_ptr(stm32_serial_ofdata_to_platdata), + .platdata_auto_alloc_size = sizeof(struct stm32x7_serial_platdata), .ops = &stm32_serial_ops, .probe = stm32_serial_probe, .flags = DM_FLAG_PRE_RELOC, diff --git a/drivers/serial/serial_stm32x7.h b/drivers/serial/serial_stm32.h index f7dca39103..d08ba1f55f 100644 --- a/drivers/serial/serial_stm32x7.h +++ b/drivers/serial/serial_stm32.h @@ -5,8 +5,8 @@ * SPDX-License-Identifier: GPL-2.0+ */ -#ifndef _SERIAL_STM32_X7_ -#define _SERIAL_STM32_X7_ +#ifndef _SERIAL_STM32_ +#define _SERIAL_STM32_ #define CR1_OFFSET(x) (x ? 0x0c : 0x00) #define CR3_OFFSET(x) (x ? 0x14 : 0x08) diff --git a/drivers/serial/serial_stm32x7.c b/drivers/serial/serial_stm32x7.c deleted file mode 100644 index d1580e3cb5..0000000000 --- a/drivers/serial/serial_stm32x7.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (C) 2016, STMicroelectronics - All Rights Reserved - * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <clk.h> -#include <dm.h> -#include <asm/io.h> -#include <serial.h> -#include <asm/arch/stm32.h> -#include "serial_stm32x7.h" - -DECLARE_GLOBAL_DATA_PTR; - -static int stm32_serial_setbrg(struct udevice *dev, int baudrate) -{ - struct stm32x7_serial_platdata *plat = dev_get_platdata(dev); - bool stm32f4 = plat->uart_info->stm32f4; - fdt_addr_t base = plat->base; - u32 int_div, mantissa, fraction, oversampling; - - int_div = DIV_ROUND_CLOSEST(plat->clock_rate, baudrate); - - if (int_div < 16) { - oversampling = 8; - setbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_OVER8); - } else { - oversampling = 16; - clrbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_OVER8); - } - - mantissa = (int_div / oversampling) << USART_BRR_M_SHIFT; - fraction = int_div % oversampling; - - writel(mantissa | fraction, base + BRR_OFFSET(stm32f4)); - - return 0; -} - -static int stm32_serial_getc(struct udevice *dev) -{ - struct stm32x7_serial_platdata *plat = dev_get_platdata(dev); - bool stm32f4 = plat->uart_info->stm32f4; - fdt_addr_t base = plat->base; - - if ((readl(base + ISR_OFFSET(stm32f4)) & USART_SR_FLAG_RXNE) == 0) - return -EAGAIN; - - return readl(base + RDR_OFFSET(stm32f4)); -} - -static int stm32_serial_putc(struct udevice *dev, const char c) -{ - struct stm32x7_serial_platdata *plat = dev_get_platdata(dev); - bool stm32f4 = plat->uart_info->stm32f4; - fdt_addr_t base = plat->base; - - if ((readl(base + ISR_OFFSET(stm32f4)) & USART_SR_FLAG_TXE) == 0) - return -EAGAIN; - - writel(c, base + TDR_OFFSET(stm32f4)); - - return 0; -} - -static int stm32_serial_pending(struct udevice *dev, bool input) -{ - struct stm32x7_serial_platdata *plat = dev_get_platdata(dev); - bool stm32f4 = plat->uart_info->stm32f4; - fdt_addr_t base = plat->base; - - if (input) - return readl(base + ISR_OFFSET(stm32f4)) & - USART_SR_FLAG_RXNE ? 1 : 0; - else - return readl(base + ISR_OFFSET(stm32f4)) & - USART_SR_FLAG_TXE ? 0 : 1; -} - -static int stm32_serial_probe(struct udevice *dev) -{ - struct stm32x7_serial_platdata *plat = dev_get_platdata(dev); - struct clk clk; - fdt_addr_t base = plat->base; - int ret; - bool stm32f4; - u8 uart_enable_bit; - - plat->uart_info = (struct stm32_uart_info *)dev_get_driver_data(dev); - stm32f4 = plat->uart_info->stm32f4; - uart_enable_bit = plat->uart_info->uart_enable_bit; - - ret = clk_get_by_index(dev, 0, &clk); - if (ret < 0) - return ret; - - ret = clk_enable(&clk); - if (ret) { - dev_err(dev, "failed to enable clock\n"); - return ret; - } - - plat->clock_rate = clk_get_rate(&clk); - if (plat->clock_rate < 0) { - clk_disable(&clk); - return plat->clock_rate; - }; - - /* Disable uart-> disable overrun-> enable uart */ - clrbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_RE | USART_CR1_TE | - BIT(uart_enable_bit)); - if (plat->uart_info->has_overrun_disable) - setbits_le32(base + CR3_OFFSET(stm32f4), USART_CR3_OVRDIS); - if (plat->uart_info->has_fifo) - setbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_FIFOEN); - setbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_RE | USART_CR1_TE | - BIT(uart_enable_bit)); - - return 0; -} - -static const struct udevice_id stm32_serial_id[] = { - { .compatible = "st,stm32-uart", .data = (ulong)&stm32f4_info}, - { .compatible = "st,stm32f7-uart", .data = (ulong)&stm32f7_info}, - { .compatible = "st,stm32h7-uart", .data = (ulong)&stm32h7_info}, - {} -}; - -static int stm32_serial_ofdata_to_platdata(struct udevice *dev) -{ - struct stm32x7_serial_platdata *plat = dev_get_platdata(dev); - - plat->base = devfdt_get_addr(dev); - if (plat->base == FDT_ADDR_T_NONE) - return -EINVAL; - - return 0; -} - -static const struct dm_serial_ops stm32_serial_ops = { - .putc = stm32_serial_putc, - .pending = stm32_serial_pending, - .getc = stm32_serial_getc, - .setbrg = stm32_serial_setbrg, -}; - -U_BOOT_DRIVER(serial_stm32) = { - .name = "serial_stm32x7", - .id = UCLASS_SERIAL, - .of_match = of_match_ptr(stm32_serial_id), - .ofdata_to_platdata = of_match_ptr(stm32_serial_ofdata_to_platdata), - .platdata_auto_alloc_size = sizeof(struct stm32x7_serial_platdata), - .ops = &stm32_serial_ops, - .probe = stm32_serial_probe, - .flags = DM_FLAG_PRE_RELOC, -}; |