]> git.ipfire.org Git - people/ms/u-boot.git/commitdiff
serial: stm32x7: prepare the ground to STM32F4 support
authorPatrice Chotard <patrice.chotard@st.com>
Wed, 27 Sep 2017 13:44:50 +0000 (15:44 +0200)
committerTom Rini <trini@konsulko.com>
Sun, 8 Oct 2017 20:19:56 +0000 (16:19 -0400)
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@st.com>
drivers/serial/serial_stm32x7.c
drivers/serial/serial_stm32x7.h

index bafcc36efc4a13581d999f7d10221354f3e1729e..81a230860dacaf12e68393417a1a49b1966edd7e 100644 (file)
@@ -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
index 6d36b748b0023fc61e743424e8c34002f8a2dc14..4c6b7d4206dc7a93d86a054859369a3fde9897d8 100644 (file)
@@ -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)