Hi Bo On 09/29/2017 08:24 AM, Bo Shen wrote: > Hi Patrice, > For this patch, overall I think you can use more generic method like > define the parameter called ip_version in stm32_uart_info structure, and > according to this information to covert base to different register map > as following, then we can get rid of "stm32f4" in stm32_uart_info > structure, and easy to extend if you have more versions. > > --->8--- > struct stm32_usart_v1 { }; (version 1 register map) > struct stm32_usart_v2 { }; (version 2 register map) > > switch (ip_version) { > case v1: > struct stm32_usart_v1 *ptr = (struct stm32_usart_v1 *)base; > break; > case v2: > struct stm32_usart_v1 *ptr = (struct stm32_usart_v1 *)base; > break; > } > ---8<---
It's another way to solve this problem, i will check if it's more efficient regarding code/data size Thanks for the tips. Patrice > > Best Regards, > Bo Shen > > On 09/27/2017 06:44 AM, patrice.chot...@st.com wrote: >> From: Patrice Chotard <patrice.chot...@st.com> >> >> STM32F4 serial IP is similar to F7 and H7, but registers >> are not located at the same offset and some feature are >> only supported by F7 and H7 version. >> >> Registers offset must be added for each version and also >> some flags indicated the supported feature. >> >> Update registers name to match with datasheet (sr to isr, >> rx_dr to rdr and tx_dr to tdr) and remove unused regs >> (cr2, gtpr, rtor, and rqr). >> >> Signed-off-by: Patrice Chotard <patrice.chot...@st.com> >> --- >> drivers/serial/serial_stm32x7.c | 72 >> ++++++++++++++++++++++++----------------- >> drivers/serial/serial_stm32x7.h | 38 ++++++++++++++-------- >> 2 files changed, 66 insertions(+), 44 deletions(-) >> >> diff --git a/drivers/serial/serial_stm32x7.c >> b/drivers/serial/serial_stm32x7.c >> index bafcc36..81a2308 100644 >> --- a/drivers/serial/serial_stm32x7.c >> +++ b/drivers/serial/serial_stm32x7.c >> @@ -17,67 +17,79 @@ 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; >> + struct stm32x7_serial_platdata *plat = dev_get_platdata(dev); >> + fdt_addr_t base = plat->base; >> + 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; >> #ifdef CONFIG_CLK >> int ret; >> @@ -100,32 +112,32 @@ 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); >> + 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-uart"}, >> - {.compatible = "st,stm32h7-uart"}, >> + { .compatible = "st,stm32f7-uart", .data = (ulong)&stm32x7_info}, >> + { .compatible = "st,stm32h7-uart", .data = (ulong)&stm32x7_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 >> diff --git a/drivers/serial/serial_stm32x7.h >> b/drivers/serial/serial_stm32x7.h >> index 6d36b74..4c6b7d4 100644 >> --- a/drivers/serial/serial_stm32x7.h >> +++ b/drivers/serial/serial_stm32x7.h >> @@ -8,30 +8,40 @@ >> #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; >> +}; >> + >> +struct stm32_uart_info stm32x7_info = { >> + .uart_enable_bit = 0, >> + .stm32f4 = false, >> + .has_overrun_disable = 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 BIT(15) >> #define USART_CR1_TE BIT(3) >> #define USART_CR1_RE BIT(2) >> -#define USART_CR1_UE BIT(0) >> #define USART_CR3_OVRDIS BIT(12) >> _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot