diff options
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/Kconfig | 4 | ||||
-rw-r--r-- | drivers/serial/serial_stm32x7.c | 84 | ||||
-rw-r--r-- | drivers/serial/serial_stm32x7.h | 71 |
3 files changed, 97 insertions, 62 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 9bf2e26e9d..7c54a49bb3 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -531,9 +531,9 @@ config STI_ASC_SERIAL config STM32X7_SERIAL bool "STMicroelectronics STM32 SoCs on-chip UART" - depends on DM_SERIAL && (STM32F7 || STM32H7) + depends on DM_SERIAL && (STM32F4 || STM32F7 || STM32H7) help - If you have a machine based on a STM32 F7 or H7 SoC you can + If you have a machine based on a STM32 F4, F7 or H7 SoC you can enable its onboard serial ports, say Y to this option. If unsure, say N. diff --git a/drivers/serial/serial_stm32x7.c b/drivers/serial/serial_stm32x7.c index 2f4eafa885..a5d529cab2 100644 --- a/drivers/serial/serial_stm32x7.c +++ b/drivers/serial/serial_stm32x7.c @@ -17,71 +17,81 @@ DECLARE_GLOBAL_DATA_PTR; static int stm32_serial_setbrg(struct udevice *dev, int baudrate) { - struct stm32x7_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; u32 int_div, mantissa, fraction, oversampling; int_div = DIV_ROUND_CLOSEST(plat->clock_rate, baudrate); if (int_div < 16) { oversampling = 8; - setbits_le32(&usart->cr1, USART_CR1_OVER8); + setbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_OVER8); } else { oversampling = 16; - clrbits_le32(&usart->cr1, USART_CR1_OVER8); + clrbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_OVER8); } mantissa = (int_div / oversampling) << USART_BRR_M_SHIFT; fraction = int_div % oversampling; - writel(mantissa | fraction, &usart->brr); + writel(mantissa | fraction, base + BRR_OFFSET(stm32f4)); return 0; } static int stm32_serial_getc(struct udevice *dev) { - struct stm32x7_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->rd_dr); + return readl(base + RDR_OFFSET(stm32f4)); } static int stm32_serial_putc(struct udevice *dev, const char c) { - struct stm32x7_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->tx_dr); + writel(c, base + TDR_OFFSET(stm32f4)); return 0; } static int stm32_serial_pending(struct udevice *dev, bool input) { - struct stm32x7_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 stm32x7_serial_platdata *plat = dev->platdata; - struct stm32_usart *const usart = plat->base; - -#ifdef CONFIG_CLK - int ret; + 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) @@ -92,7 +102,6 @@ static int stm32_serial_probe(struct udevice *dev) dev_err(dev, "failed to enable clock\n"); return ret; } -#endif plat->clock_rate = clk_get_rate(&clk); if (plat->clock_rate < 0) { @@ -100,37 +109,36 @@ static int stm32_serial_probe(struct udevice *dev) return plat->clock_rate; }; - /* Disable usart-> disable overrun-> enable usart */ - clrbits_le32(&usart->cr1, USART_CR1_RE | USART_CR1_TE | USART_CR1_UE); - setbits_le32(&usart->cr3, USART_CR3_OVRDIS); - setbits_le32(&usart->cr1, USART_CR1_RE | USART_CR1_TE | USART_CR1_UE); + /* 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; } -#if CONFIG_IS_ENABLED(OF_CONTROL) static const struct udevice_id stm32_serial_id[] = { - {.compatible = "st,stm32f7-usart"}, - {.compatible = "st,stm32f7-uart"}, - {.compatible = "st,stm32h7-usart"}, - {.compatible = "st,stm32h7-uart"}, + { .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); - fdt_addr_t addr; - addr = devfdt_get_addr(dev); - if (addr == FDT_ADDR_T_NONE) + plat->base = devfdt_get_addr(dev); + if (plat->base == FDT_ADDR_T_NONE) return -EINVAL; - plat->base = (struct stm32_usart *)addr; - return 0; } -#endif static const struct dm_serial_ops stm32_serial_ops = { .putc = stm32_serial_putc, diff --git a/drivers/serial/serial_stm32x7.h b/drivers/serial/serial_stm32x7.h index 9fe37af5cc..b914edf28a 100644 --- a/drivers/serial/serial_stm32x7.h +++ b/drivers/serial/serial_stm32x7.h @@ -8,38 +8,65 @@ #ifndef _SERIAL_STM32_X7_ #define _SERIAL_STM32_X7_ -struct stm32_usart { - u32 cr1; - u32 cr2; - u32 cr3; - u32 brr; - u32 gtpr; - u32 rtor; - u32 rqr; - u32 sr; - u32 icr; - u32 rd_dr; - u32 tx_dr; +#define CR1_OFFSET(x) (x ? 0x0c : 0x00) +#define CR3_OFFSET(x) (x ? 0x14 : 0x08) +#define BRR_OFFSET(x) (x ? 0x08 : 0x0c) +#define ISR_OFFSET(x) (x ? 0x00 : 0x1c) +/* + * STM32F4 has one Data Register (DR) for received or transmitted + * data, so map Receive Data Register (RDR) and Transmit Data + * Register (TDR) at the same offset + */ +#define RDR_OFFSET(x) (x ? 0x04 : 0x24) +#define TDR_OFFSET(x) (x ? 0x04 : 0x28) + +struct stm32_uart_info { + u8 uart_enable_bit; /* UART_CR1_UE */ + bool stm32f4; /* true for STM32F4, false otherwise */ + bool has_overrun_disable; + bool has_fifo; +}; + +struct stm32_uart_info stm32f4_info = { + .stm32f4 = true, + .uart_enable_bit = 13, + .has_overrun_disable = false, + .has_fifo = false, +}; + +struct stm32_uart_info stm32f7_info = { + .uart_enable_bit = 0, + .stm32f4 = false, + .has_overrun_disable = true, + .has_fifo = false, +}; + +struct stm32_uart_info stm32h7_info = { + .uart_enable_bit = 0, + .stm32f4 = false, + .has_overrun_disable = true, + .has_fifo = true, }; /* Information about a serial port */ struct stm32x7_serial_platdata { - struct stm32_usart *base; /* address of registers in physical memory */ + fdt_addr_t base; /* address of registers in physical memory */ + struct stm32_uart_info *uart_info; unsigned long int clock_rate; }; -#define USART_CR1_OVER8 (1 << 15) -#define USART_CR1_TE (1 << 3) -#define USART_CR1_RE (1 << 2) -#define USART_CR1_UE (1 << 0) +#define USART_CR1_FIFOEN BIT(29) +#define USART_CR1_OVER8 BIT(15) +#define USART_CR1_TE BIT(3) +#define USART_CR1_RE BIT(2) -#define USART_CR3_OVRDIS (1 << 12) +#define USART_CR3_OVRDIS BIT(12) -#define USART_SR_FLAG_RXNE (1 << 5) -#define USART_SR_FLAG_TXE (1 << 7) +#define USART_SR_FLAG_RXNE BIT(5) +#define USART_SR_FLAG_TXE BIT(7) -#define USART_BRR_F_MASK 0xFF +#define USART_BRR_F_MASK GENMASK(7, 0) #define USART_BRR_M_SHIFT 4 -#define USART_BRR_M_MASK 0xFFF0 +#define USART_BRR_M_MASK GENMASK(15, 4) #endif |