Message ID | 1490176456-24813-12-git-send-email-patrice.chotard@st.com |
---|---|
State | Superseded |
Delegated to: | Marek Vasut |
Headers | show |
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). > + > +#endif /* __DWC3_STI_UBOOT_H_ */ > -- > 1.9.1 > Regards, Simon
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 >
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); + +#endif /* __DWC3_STI_UBOOT_H_ */