
Hi Simon
On 04/01/2017 06:21 AM, Simon Glass wrote:
Hi Patrice,
On 22 March 2017 at 03:54, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@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@st.com
v2: _ use setbits_le32() instead of read, modify, write sequence _ add missing parenthesis
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 | 135 ++++++++++++++++++++++++++ include/dwc3-sti-uboot.h | 50 ++++++++++ 5 files changed, 205 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@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..4b6b91b --- /dev/null +++ b/drivers/usb/dwc3/dwc3-sti.c @@ -0,0 +1,135 @@ +/*
- dwc3-sti.c - STiH407 family DWC3 specific Glue layer
- Copyright (c) 2017
- Patrice Chotard patrice.chotard@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);
setbits_le32(plat->glue_base + CLKRST_CTRL, SW_PIPEW_RESET_N);
+}
+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..62a05f1 --- /dev/null +++ b/include/dwc3-sti-uboot.h @@ -0,0 +1,50 @@ +/*
- Copyright (c) 2017
- Patrice Chotard patrice.chotard@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);
Where will this be called from? We want to avoid calling directly into drivers from outside code (rather than through a uclass).
This function is needed for fastboot feature. When using "fastboot" command the do_fastboot() call board_usb_init() implemented in each architecture board file.
It will be called from board_usb_init() in board/st/stih410-b2260/board.c
But, please refer to my last series (v3 send on 28th April 2017)
Thanks
Patrice
+#endif /* __DWC3_STI_UBOOT_H_ */
1.9.1
Regards, Simon