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

Bo Shen voice.shen at gmail.com
Fri Sep 29 06:24:22 UTC 2017


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<---

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