From: Patrice Chotard <patrice.chot...@st.com>

This patch adds support to ASC (asynchronous serial controller)
driver, which is basically a standard serial driver. This IP
is common across other STMicroelectronics SoCs

Signed-off-by: Patrice Chotard <patrice.chot...@st.com>
---
 arch/arm/Kconfig                          |   2 +
 arch/arm/include/asm/arch-stih410/sti.h   |   6 +
 board/st/stih410-b2260/board.c            |  13 ++
 drivers/serial/Kconfig                    |   7 +
 drivers/serial/Makefile                   |   1 +
 drivers/serial/serial_sti_asc.c           | 219 ++++++++++++++++++++++++++++++
 include/configs/stih410-b2260.h           |   1 +
 include/dm/platform_data/serial_sti_asc.h |  17 +++
 8 files changed, 266 insertions(+)
 create mode 100644 drivers/serial/serial_sti_asc.c
 create mode 100644 include/dm/platform_data/serial_sti_asc.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 56a017c..98546ae 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -895,6 +895,8 @@ config STM32
 config ARCH_STI
        bool "Support STMicrolectronics SoCs"
        select CPU_V7
+       select DM
+       select DM_SERIAL
        help
          Support for STMicroelectronics STiH407/10 SoC family.
          This SoC is used on Linaro 96Board STiH410-B2260
diff --git a/arch/arm/include/asm/arch-stih410/sti.h 
b/arch/arm/include/asm/arch-stih410/sti.h
index d35c4f0..f167560 100644
--- a/arch/arm/include/asm/arch-stih410/sti.h
+++ b/arch/arm/include/asm/arch-stih410/sti.h
@@ -11,4 +11,10 @@
 #define STI_A9_CONFIG_BASE                     0x08760000
 #define STI_A9_GLOBAL_TIMER_BASE               (STI_A9_CONFIG_BASE + 0x0200)
 
+/* STiH410 control registers */
+#define STIH410_COMMS_BASE                     0x09800000
+
+/* ASC UART located in the main "COMMs" block */
+#define STIH410_ASC1_BASE (STIH410_COMMS_BASE + 0x00031000)
+
 #endif /* _STI_H_ */
diff --git a/board/st/stih410-b2260/board.c b/board/st/stih410-b2260/board.c
index 0c06bca..72b0042 100644
--- a/board/st/stih410-b2260/board.c
+++ b/board/st/stih410-b2260/board.c
@@ -7,6 +7,9 @@
  */
 
 #include <common.h>
+#include <asm/arch/sti.h>
+#include <dm/platdata.h>
+#include <dm/platform_data/serial_sti_asc.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -26,3 +29,13 @@ int board_init(void)
 {
        return 0;
 }
+
+
+static const struct sti_asc_serial_platdata serial_platdata = {
+       .base = (struct sti_asc_uart *)STIH410_ASC1_BASE,
+};
+
+U_BOOT_DEVICE(sti_asc) = {
+       .name = "serial_sti_asc",
+       .platdata = &serial_platdata,
+};
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index b11f3ff..7557632 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -413,4 +413,11 @@ config PXA_SERIAL
          If you have a machine based on a Marvell XScale PXA2xx CPU you
          can enable its onboard serial ports by enabling this option.
 
+config STI_ASC_SERIAL
+       bool "STMicroelectronics on-chip UART"
+       depends on DM_SERIAL && ARCH_STI
+       help
+         Select this to enable Asynchronous Serial Controller available
+         on STiH410 SoC.
+
 endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 8430668..84a22ce 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_FSL_LINFLEXUART) += serial_linflexuart.o
 obj-$(CONFIG_ARC_SERIAL) += serial_arc.o
 obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o
 obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o
+obj-$(CONFIG_STI_ASC_SERIAL) += serial_sti_asc.o
 obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o
 obj-$(CONFIG_STM32X7_SERIAL) += serial_stm32x7.o
 obj-$(CONFIG_BCM283X_MU_SERIAL) += serial_bcm283x_mu.o
diff --git a/drivers/serial/serial_sti_asc.c b/drivers/serial/serial_sti_asc.c
new file mode 100644
index 0000000..5279836
--- /dev/null
+++ b/drivers/serial/serial_sti_asc.c
@@ -0,0 +1,219 @@
+/*
+ * Support for Serial I/O using STMicroelectronics' on-chip ASC.
+ *
+ *  Copyright (c) 2017
+ *  Patrice Chotard <patrice.chot...@st.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <serial.h>
+#include <asm/arch/sti.h>
+#include <asm/io.h>
+#include <dm/platform_data/serial_sti_asc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define BAUDMODE       0x00001000
+#define RXENABLE       0x00000100
+#define RUN            0x00000080
+#define MODE           0x00000001
+#define MODE_8BIT      0x0001
+#define STOP_1BIT      0x0008
+#define PARITYODD      0x0020
+
+#define STA_TF         0x0200
+#define STA_RBF                0x0001
+
+struct sti_asc_uart {
+       u32 baudrate;
+       u32 txbuf;
+       u32 rxbuf;
+       u32 control;
+       u32 inten;
+       u32 status;
+       u32 guardtime;
+       u32 timeout;
+       u32 txreset;
+       u32 rxreset;
+};
+
+/*---- Values for the BAUDRATE Register -----------------------*/
+#define PCLK                   (200ul * 1000000ul)
+#define BAUDRATE_VAL_M0(bps)   (PCLK / (16 * (bps)))
+#define BAUDRATE_VAL_M1(bps)   ((bps * (1 << 14)) + (1<<13)) / (PCLK/(1 << 6))
+
+/*
+ * MODE 0
+ *                       ICCLK
+ * ASCBaudRate =   ----------------
+ *                   baudrate * 16
+ *
+ * MODE 1
+ *                   baudrate * 16 * 2^16
+ * ASCBaudRate =   ------------------------
+ *                          ICCLK
+ *
+ * NOTE:
+ * Mode 1 should be used for baudrates of 19200, and above, as it
+ * has a lower deviation error than Mode 0 for higher frequencies.
+ * Mode 0 should be used for all baudrates below 19200.
+ */
+
+static int sti_asc_pending(struct udevice *dev, bool input)
+{
+       struct sti_asc_serial_platdata *plat = dev->platdata;
+       struct sti_asc_uart *const uart = plat->base;
+       unsigned long status;
+
+       status = readl(&uart->status);
+       if (input)
+               return status & STA_RBF;
+       else
+               return status & STA_TF;
+}
+
+/* called to adjust baud-rate */
+static int sti_asc_serial_setbrg(struct udevice *dev, int baudrate)
+{
+       struct sti_asc_serial_platdata *plat = dev->platdata;
+       struct sti_asc_uart *const uart = plat->base;
+
+       unsigned long val;
+       int t, mode = 1;
+
+       switch (baudrate) {
+       case 9600:
+               t = BAUDRATE_VAL_M0(9600);
+               mode = 0;
+               break;
+       case 19200:
+               t = BAUDRATE_VAL_M1(19200);
+               break;
+       case 38400:
+               t = BAUDRATE_VAL_M1(38400);
+               break;
+       case 57600:
+               t = BAUDRATE_VAL_M1(57600);
+               break;
+       default:
+               printf("ASC: unsupported baud rate: %d, using 115200 
instead.\n",
+                      baudrate);
+       case 115200:
+               t = BAUDRATE_VAL_M1(115200);
+               break;
+       }
+
+       /* wait for end of current transmission */
+       while (sti_asc_pending(dev, false))
+               ;
+
+       /* disable the baudrate generator */
+       val = readl(&uart->control);
+       writel((val & ~RUN), &uart->control);
+
+       /* set baud generator reload value */
+       writel(t, &uart->baudrate);
+       /* reset the RX & TX buffers */
+       writel(1, &uart->txreset);
+       writel(1, &uart->rxreset);
+
+       /* set baud generator mode */
+       if (mode)
+               val |= BAUDMODE;
+
+       /* finally, write value and enable ASC */
+       writel(val, &uart->control);
+
+       return 0;
+}
+
+/* initialize the ASC */
+static int sti_asc_serial_probe(struct udevice *dev)
+{
+       struct sti_asc_serial_platdata *plat = dev->platdata;
+       struct sti_asc_uart *const uart = plat->base;
+       unsigned long val;
+
+       sti_asc_serial_setbrg(dev, gd->baudrate);
+
+       /*
+        * build up the value to be written to CONTROL
+        * set character length, bit stop number, odd parity
+        */
+       val = RXENABLE | RUN | MODE_8BIT | STOP_1BIT | PARITYODD;
+       writel(val, &uart->control);
+
+       return 0;
+}
+
+/* blocking function, that returns next char */
+static int sti_asc_serial_getc(struct udevice *dev)
+{
+       struct sti_asc_serial_platdata *plat = dev->platdata;
+       struct sti_asc_uart *const uart = plat->base;
+
+       /* polling wait: for a char to be read */
+       if (!sti_asc_pending(dev, true))
+               return -EAGAIN;
+
+       return readl(&uart->rxbuf);
+}
+
+/* write write out a single char */
+static int sti_asc_serial_putc(struct udevice *dev, const char c)
+{
+       struct sti_asc_serial_platdata *plat = dev->platdata;
+       struct sti_asc_uart *const uart = plat->base;
+
+       /* Stream-LF to CR+LF conversion */
+       if (c == 10)
+               sti_asc_serial_putc(dev, '\r');
+
+       /* wait till safe to write next char */
+       while (sti_asc_pending(dev, false))
+               ;
+
+       /* finally, write next char */
+       writel(c, &uart->txbuf);
+
+       return 0;
+}
+
+static int sti_ofdata_to_platdata(struct udevice *dev)
+{
+       struct sti_asc_serial_platdata *priv = dev_get_priv(dev);
+       fdt_addr_t base;
+
+       base = dev_get_addr(dev);
+       if (base == FDT_ADDR_T_NONE)
+               return -EINVAL;
+
+       priv->base = (struct sti_asc_uart *)base;
+
+       return 0;
+}
+
+static const struct dm_serial_ops sti_asc_serial_ops = {
+       .putc = sti_asc_serial_putc,
+       .pending = sti_asc_pending,
+       .getc = sti_asc_serial_getc,
+       .setbrg = sti_asc_serial_setbrg,
+};
+
+static const struct udevice_id sti_serial_of_match[] = {
+       { .compatible = "st,asc" },
+       { }
+};
+
+U_BOOT_DRIVER(serial_sti_asc) = {
+       .name = "serial_sti_asc",
+       .id = UCLASS_SERIAL,
+       .of_match = sti_serial_of_match,
+       .ops = &sti_asc_serial_ops,
+       .ofdata_to_platdata = sti_ofdata_to_platdata,
+       .probe = sti_asc_serial_probe,
+       .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/include/configs/stih410-b2260.h b/include/configs/stih410-b2260.h
index 78103c6..b4b3d75 100644
--- a/include/configs/stih410-b2260.h
+++ b/include/configs/stih410-b2260.h
@@ -17,6 +17,7 @@
 #define CONFIG_SYS_LOAD_ADDR           PHYS_SDRAM_1    /* default load addr */
 
 #define CONFIG_BAUDRATE                        115200
+#define CONFIG_SYS_BAUDRATE_TABLE       { 9600, 19200, 38400, 57600, 115200 }
 
 #define CONFIG_SYS_HZ_CLOCK            1000000000      /* 1 GHz */
 
diff --git a/include/dm/platform_data/serial_sti_asc.h 
b/include/dm/platform_data/serial_sti_asc.h
new file mode 100644
index 0000000..c8631f1
--- /dev/null
+++ b/include/dm/platform_data/serial_sti_asc.h
@@ -0,0 +1,17 @@
+/*
+ * (C) Copyright 2017
+ * Patrice Chotard <patrice.chot...@st.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __SERIAL_STI_ASC_H
+#define __SERIAL_STI_ASC_H
+
+/* Information about a serial port */
+struct sti_asc_serial_platdata {
+       /* address of registers in physical memory */
+       struct sti_asc_uart *base;
+};
+
+#endif /* __SERIAL_STI_ASC_H */
-- 
1.9.1

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to