[U-Boot] [PATCH v1 3/6] serial: stm32x7: prepare the ground to STM32F4 support

Patrice CHOTARD patrice.chotard at st.com
Fri Sep 29 11:45:38 UTC 2017


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.chotard at st.com wrote:
>> From: Patrice Chotard <patrice.chotard at 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.chotard at 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)
>>


More information about the U-Boot mailing list