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

This patch adds the ST glue logic to manage the DWC3 HC
on STiH407 SoC family. It configures the internal glue
logic and syscfg registers.

Part of this code been extracted from kernel.org driver
(drivers/usb/dwc3/dwc3-st.c)

Signed-off-by: Patrice Chotard <patrice.chot...@st.com>
---
 arch/arm/include/asm/arch-stih410/sys_proto.h |  11 +++
 drivers/usb/dwc3/Kconfig                      |   8 ++
 drivers/usb/dwc3/Makefile                     |   1 +
 drivers/usb/dwc3/dwc3-sti.c                   | 137 ++++++++++++++++++++++++++
 include/dwc3-sti-uboot.h                      |  50 ++++++++++
 5 files changed, 207 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-stih410/sys_proto.h
 create mode 100644 drivers/usb/dwc3/dwc3-sti.c
 create mode 100644 include/dwc3-sti-uboot.h

diff --git a/arch/arm/include/asm/arch-stih410/sys_proto.h 
b/arch/arm/include/asm/arch-stih410/sys_proto.h
new file mode 100644
index 0000000..5c40d3b
--- /dev/null
+++ b/arch/arm/include/asm/arch-stih410/sys_proto.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2017
+ * Patrice Chotard <patrice.chot...@st.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _ASM_ARCH_SYS_PROTO_H
+#define _ASM_ARCH_SYS_PROTO_H
+
+#endif /* _ASM_ARCH_SYS_PROTO_H */
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index e93398f..51a7a00 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -37,6 +37,14 @@ config USB_DWC3_OMAP
 
          Say 'Y' here if you have one such device
 
+config USB_DWC3_STI
+       bool "STMicroelectronics STiH407 family glue driver"
+       help
+         STMicroelectronics STiH407 family SoCs use this IP for
+         USB2/3 functionality.
+
+         Say 'Y' here if you have one such device
+
 menu "PHY Subsystem"
 
 config USB_DWC3_PHY_OMAP
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index 2964bae..753912d 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_USB_DWC3_GADGET)         += gadget.o ep0.o
 obj-$(CONFIG_USB_DWC3_OMAP)            += dwc3-omap.o
 obj-$(CONFIG_USB_DWC3_PHY_OMAP)                += ti_usb_phy.o
 obj-$(CONFIG_USB_DWC3_PHY_SAMSUNG)     += samsung_usb_phy.o
+obj-$(CONFIG_USB_DWC3_STI)             += dwc3-sti.o
diff --git a/drivers/usb/dwc3/dwc3-sti.c b/drivers/usb/dwc3/dwc3-sti.c
new file mode 100644
index 0000000..5ff3e76
--- /dev/null
+++ b/drivers/usb/dwc3/dwc3-sti.c
@@ -0,0 +1,137 @@
+/*
+ * dwc3-sti.c - STiH407 family DWC3 specific Glue layer
+ * Copyright (c) 2017
+ * Patrice Chotard <patrice.chot...@st.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <asm/io.h>
+#include <common.h>
+#include <dm.h>
+#include <dwc3-sti-uboot.h>
+#include <fdtdec.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <usb.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+__weak int __board_usb_init(int index, enum usb_init_type init)
+{
+       return 0;
+}
+/*int board_usb_init(int index, enum usb_init_type init)*/
+/*        __attribute__((weak, alias("__board_usb_init")));*/
+
+static int sti_dwc3_drd_init(struct sti_dwc3_platdata *plat)
+{
+       unsigned long val;
+
+       val = readl(plat->syscfg_base + plat->syscfg_offset);
+
+       val &= USB3_CONTROL_MASK;
+
+       switch (plat->mode) {
+       case USB_DR_MODE_PERIPHERAL:
+               val &= ~(USB3_DELAY_VBUSVALID
+                       | USB3_SEL_FORCE_OPMODE | USB3_FORCE_OPMODE(0x3)
+                       | USB3_SEL_FORCE_DPPULLDOWN2 | USB3_FORCE_DPPULLDOWN2
+                       | USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2);
+
+               val |= USB3_DEVICE_NOT_HOST | USB3_FORCE_VBUSVALID;
+               break;
+
+       case USB_DR_MODE_HOST:
+               val &= ~(USB3_DEVICE_NOT_HOST | USB3_FORCE_VBUSVALID
+                       | USB3_SEL_FORCE_OPMODE | USB3_FORCE_OPMODE(0x3)
+                       | USB3_SEL_FORCE_DPPULLDOWN2 | USB3_FORCE_DPPULLDOWN2
+                       | USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2);
+
+               val |= USB3_DELAY_VBUSVALID;
+               break;
+
+       default:
+               error("Unsupported mode of operation %d\n", plat->mode);
+               return -EINVAL;
+       }
+       return writel(val, plat->syscfg_base + plat->syscfg_offset);
+}
+
+static void sti_dwc3_init(struct sti_dwc3_platdata *plat)
+{
+       unsigned long reg;
+
+       reg = readl(plat->glue_base + CLKRST_CTRL);
+
+       reg |= AUX_CLK_EN | EXT_CFG_RESET_N | XHCI_REVISION;
+       reg &= ~SW_PIPEW_RESET_N;
+
+       writel(reg, plat->glue_base + CLKRST_CTRL);
+
+       /* configure mux for vbus, powerpresent and bvalid signals */
+       reg = readl(plat->glue_base + USB2_VBUS_MNGMNT_SEL1);
+
+       reg |= SEL_OVERRIDE_VBUSVALID(USB2_VBUS_UTMIOTG) |
+              SEL_OVERRIDE_POWERPRESENT(USB2_VBUS_UTMIOTG) |
+              SEL_OVERRIDE_BVALID(USB2_VBUS_UTMIOTG);
+
+       writel(reg, plat->glue_base + USB2_VBUS_MNGMNT_SEL1);
+
+       reg = readl(plat->glue_base + CLKRST_CTRL);
+       reg |= SW_PIPEW_RESET_N;
+       writel(reg, plat->glue_base + CLKRST_CTRL);
+}
+
+int sti_dwc3_glue_init(enum usb_dr_mode mode)
+{
+       struct sti_dwc3_platdata plat;
+       struct fdtdec_phandle_args syscfg_phandle;
+       struct udevice *syscon;
+       struct regmap *regmap;
+       int node, ret;
+       const void *blob = gd->fdt_blob;
+       u32 reg[4];
+
+       /* find the dwc3 node */
+       node = fdt_node_offset_by_compatible(blob, -1, "st,stih407-dwc3");
+
+       ret = fdtdec_get_int_array(blob, node, "reg", reg, ARRAY_SIZE(reg));
+       if (ret) {
+               error("unable to find st,stih407-dwc3 reg property(%d)\n", ret);
+               return ret;
+       }
+
+       plat.glue_base = reg[0];
+       plat.syscfg_offset = reg[2];
+       plat.mode = mode;
+
+       /* get corresponding syscon phandle */
+       ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, node,
+                                            "st,syscfg", NULL, 0, 0,
+                                            &syscfg_phandle);
+       if (ret < 0) {
+               error("Can't get syscfg phandle: %d\n", ret);
+               return ret;
+       }
+
+       ret = uclass_get_device_by_of_offset(UCLASS_SYSCON, syscfg_phandle.node,
+                                            &syscon);
+       if (ret) {
+               error("unable to find syscon device (%d)\n", ret);
+               return ret;
+       }
+
+       /* get syscfg-reg base address */
+       regmap = syscon_get_regmap(syscon);
+       if (!regmap) {
+               error("unable to find regmap\n");
+               return -ENODEV;
+       }
+       plat.syscfg_base = regmap->base;
+
+       sti_dwc3_drd_init(&plat);
+       sti_dwc3_init(&plat);
+
+       return 0;
+}
diff --git a/include/dwc3-sti-uboot.h b/include/dwc3-sti-uboot.h
new file mode 100644
index 0000000..c7bb770
--- /dev/null
+++ b/include/dwc3-sti-uboot.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017
+ * Patrice Chotard <patrice.chot...@st.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __DWC3_STI_UBOOT_H_
+#define __DWC3_STI_UBOOT_H_
+
+#include <linux/usb/otg.h>
+
+/* glue registers */
+#define CLKRST_CTRL            0x00
+#define AUX_CLK_EN             BIT(0)
+#define SW_PIPEW_RESET_N       BIT(4)
+#define EXT_CFG_RESET_N                BIT(8)
+
+#define XHCI_REVISION          BIT(12)
+
+#define USB2_VBUS_MNGMNT_SEL1  0x2C
+#define USB2_VBUS_UTMIOTG      0x1
+
+#define SEL_OVERRIDE_VBUSVALID(n)      (n << 0)
+#define SEL_OVERRIDE_POWERPRESENT(n)   (n << 4)
+#define SEL_OVERRIDE_BVALID(n)         (n << 8)
+
+/* Static DRD configuration */
+#define USB3_CONTROL_MASK              0xf77
+
+#define USB3_DEVICE_NOT_HOST           BIT(0)
+#define USB3_FORCE_VBUSVALID           BIT(1)
+#define USB3_DELAY_VBUSVALID           BIT(2)
+#define USB3_SEL_FORCE_OPMODE          BIT(4)
+#define USB3_FORCE_OPMODE(n)           (n << 5)
+#define USB3_SEL_FORCE_DPPULLDOWN2     BIT(8)
+#define USB3_FORCE_DPPULLDOWN2         BIT(9)
+#define USB3_SEL_FORCE_DMPULLDOWN2     BIT(10)
+#define USB3_FORCE_DMPULLDOWN2         BIT(11)
+
+struct sti_dwc3_platdata {
+       phys_addr_t syscfg_base;
+       phys_addr_t glue_base;
+       phys_addr_t syscfg_offset;
+       enum usb_dr_mode mode;
+};
+
+int sti_dwc3_glue_init(enum usb_dr_mode mode);
+
+#endif /* __DWC3_STI_UBOOT_H_ */
-- 
1.9.1

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

Reply via email to