[U-Boot] [PATCH 13/21] usb: dwc3: Add dwc3 support for STi

patrice.chotard at st.com patrice.chotard at st.com
Fri Mar 17 16:25:24 UTC 2017


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



More information about the U-Boot mailing list