[U-Boot] [PATCH v5 00/14] STiH410-B2260: add reset, usb and fastboot support

From: Patrice Chotard patrice.chotard@st.com
This series adds : _ update existing sdhci driver to use reset framework _ add usb phy driver _ add ehci support _ add ohci support _ add xhci support _ add fastboot support
With all this feature enable, it's now possible to _ boot on usb mass storage device _ boot from kernel image and dtb previously loaded using tftp _ update mmc partiton using fastboot
v5: _ extend generic ehci with phy _ extend generic ohci with clock, reset and phy _ remove specifi STi ehci and ohci drivers and use generic ohci/ehci ones _ update stih410-b2260 device tree to use ehci and ohci generic drivers
v4: _ use PHY uclass currently available on dm-next branch, update sti ehci, ohci and xhci drivers to use new PHY uclass.
v3: _ remove reset driver (already applied on u-boot-dm tree by Simon Glass) _ patch 4: add new USB PHY uclass requested by Simon Glass _ patch 5: convert STi usb phy driver to new USB PHY uclass _ patch 6/7: update echi/ohci drivers to use USB PHY uclass _ patch 8/9: rework xhci-sti.c and dwc3-sti.c. Previously, xhci-sti driver binded dwc3-sti (STi glue driver) which was not correct. Now we respect the device tree hierarchy, ie the STi dwc3 glue driver is first probed, then bind the xhci-sti driver. v2: _ add Reviewed-by: Jaehoon Chung jh80.chung@samsung.com in patches 2,3 and 4 _ fix remarks done by Marek Vasut : _ patch 5 : replace bitfield_replace() by clrsetbits_le32() _ patch 6 : update error messages and add remove callback _ patch 8 : put board specific defines in a separate patch _ patch 7: use setbits_le32() instead of read, modify, write sequence and add missing parenthesis _ squash previous patches 7,9,11,12,14,16,17,18,19,20 and 21 in patch 14
Patrice Chotard (14): mmc: sti_sdhci: Rework sti_mmc_core_config() ARM: dts: stih410-family: Add missing reset_names for mmc1 node mmc: sti_sdhci: Use reset framework usb: phy: Add STi USB2 PHY usb: xhci: Add STi xhci support usb: dwc3: Add dwc3 glue driver support for STi board: STiH410-B2260: add OHCI and XHCI related defines board: STiH410-B2260: add fastboot support STiH410-B2260: enable USB Host Networking usb: extend generic EHCI with PHY ARM: DTS: STiH410: rework ehci nodes usb: extend generic OHCI with clock, reset and phy ARM: DTS: STiH410: rework ohci nodes STiH410-B2260: enable USB, fastboot, reset related flags
arch/arm/dts/stih407-family.dtsi | 1 + arch/arm/dts/stih410.dtsi | 16 +- arch/arm/include/asm/arch-stih410/sys_proto.h | 11 + board/st/stih410-b2260/board.c | 44 ++++ configs/stih410-b2260_defconfig | 38 +++- doc/device-tree-bindings/phy/phy-stih407-usb.txt | 24 ++ doc/device-tree-bindings/usb/dwc3-st.txt | 60 +++++ drivers/mmc/sti_sdhci.c | 60 +++-- drivers/phy/Kconfig | 8 + drivers/phy/Makefile | 1 + drivers/phy/sti_usb_phy.c | 181 +++++++++++++++ drivers/usb/host/Kconfig | 8 + drivers/usb/host/Makefile | 1 + drivers/usb/host/dwc3-sti-glue.c | 278 +++++++++++++++++++++++ drivers/usb/host/ehci-generic.c | 13 ++ drivers/usb/host/ohci-generic.c | 48 +++- drivers/usb/host/xhci-sti.c | 128 +++++++++++ include/configs/stih410-b2260.h | 16 ++ include/dwc3-sti-glue.h | 43 ++++ 19 files changed, 939 insertions(+), 40 deletions(-) create mode 100644 arch/arm/include/asm/arch-stih410/sys_proto.h create mode 100644 doc/device-tree-bindings/phy/phy-stih407-usb.txt create mode 100644 doc/device-tree-bindings/usb/dwc3-st.txt create mode 100644 drivers/phy/sti_usb_phy.c create mode 100644 drivers/usb/host/dwc3-sti-glue.c create mode 100644 drivers/usb/host/xhci-sti.c create mode 100644 include/dwc3-sti-glue.h

From: Patrice Chotard patrice.chotard@st.com
Use struct udevice* as input parameter. Previous parameters are retrieved through plat and priv data.
This to prepare to use the reset framework.
Signed-off-by: Patrice Chotard patrice.chotard@st.com Reviewed-by: Jaehoon Chung jh80.chung@samsung.com --- v5: _ none v4: _ none v3: _ none v2: _ none
drivers/mmc/sti_sdhci.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-)
diff --git a/drivers/mmc/sti_sdhci.c b/drivers/mmc/sti_sdhci.c index 2a07082..d6c4d67 100644 --- a/drivers/mmc/sti_sdhci.c +++ b/drivers/mmc/sti_sdhci.c @@ -16,6 +16,7 @@ DECLARE_GLOBAL_DATA_PTR; struct sti_sdhci_plat { struct mmc_config cfg; struct mmc mmc; + int instance; };
/* @@ -26,8 +27,8 @@ struct sti_sdhci_plat {
/** * sti_mmc_core_config: configure the Arasan HC - * @regbase: base address - * @mmc_instance: mmc instance id + * @dev : udevice + * * Description: this function is to configure the Arasan MMC HC. * This should be called when the system starts in case of, on the SoC, * it is needed to configure the host controller. @@ -36,33 +37,35 @@ struct sti_sdhci_plat { * W/o these settings the SDHCI could configure and use the embedded controller * with limited features. */ -static void sti_mmc_core_config(const u32 regbase, int mmc_instance) +static void sti_mmc_core_config(struct udevice *dev) { + struct sti_sdhci_plat *plat = dev_get_platdata(dev); + struct sdhci_host *host = dev_get_priv(dev); unsigned long *sysconf;
/* only MMC1 has a reset line */ - if (mmc_instance) { + if (plat->instance) { sysconf = (unsigned long *)(STIH410_SYSCONF5_BASE + ST_MMC_CCONFIG_REG_5); generic_set_bit(SYSCONF_MMC1_ENABLE_BIT, sysconf); }
writel(STI_FLASHSS_MMC_CORE_CONFIG_1, - regbase + FLASHSS_MMC_CORE_CONFIG_1); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_1);
- if (mmc_instance) { + if (plat->instance) { writel(STI_FLASHSS_MMC_CORE_CONFIG2, - regbase + FLASHSS_MMC_CORE_CONFIG_2); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_2); writel(STI_FLASHSS_MMC_CORE_CONFIG3, - regbase + FLASHSS_MMC_CORE_CONFIG_3); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_3); } else { writel(STI_FLASHSS_SDCARD_CORE_CONFIG2, - regbase + FLASHSS_MMC_CORE_CONFIG_2); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_2); writel(STI_FLASHSS_SDCARD_CORE_CONFIG3, - regbase + FLASHSS_MMC_CORE_CONFIG_3); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_3); } writel(STI_FLASHSS_MMC_CORE_CONFIG4, - regbase + FLASHSS_MMC_CORE_CONFIG_4); + host->ioaddr + FLASHSS_MMC_CORE_CONFIG_4); }
static int sti_sdhci_probe(struct udevice *dev) @@ -70,7 +73,7 @@ static int sti_sdhci_probe(struct udevice *dev) struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct sti_sdhci_plat *plat = dev_get_platdata(dev); struct sdhci_host *host = dev_get_priv(dev); - int ret, mmc_instance; + int ret;
/* * identify current mmc instance, mmc1 has a reset, not mmc0 @@ -79,11 +82,11 @@ static int sti_sdhci_probe(struct udevice *dev) */
if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "resets", NULL)) - mmc_instance = 1; + plat->instance = 1; else - mmc_instance = 0; + plat->instance = 0;
- sti_mmc_core_config((const u32) host->ioaddr, mmc_instance); + sti_mmc_core_config(dev);
host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_32BIT_DMA_ADDR |

On 10 May 2017 at 10:09, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Use struct udevice* as input parameter. Previous parameters are retrieved through plat and priv data.
This to prepare to use the reset framework.
Signed-off-by: Patrice Chotard patrice.chotard@st.com Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
v5: _ none v4: _ none v3: _ none v2: _ none
drivers/mmc/sti_sdhci.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

From: Patrice Chotard patrice.chotard@st.com
reset-names property is needed to use the reset API for STi sdhci driver.
Signed-off-by: Patrice Chotard patrice.chotard@st.com Reviewed-by: Jaehoon Chung jh80.chung@samsung.com ---
v5: _ none v4: _ none v3: _ none v2: _ none
arch/arm/dts/stih407-family.dtsi | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm/dts/stih407-family.dtsi b/arch/arm/dts/stih407-family.dtsi index af66b53..452ac1c 100644 --- a/arch/arm/dts/stih407-family.dtsi +++ b/arch/arm/dts/stih407-family.dtsi @@ -563,6 +563,7 @@ clocks = <&clk_s_c0_flexgen CLK_MMC_1>, <&clk_s_c0_flexgen CLK_RX_ICN_HVA>; resets = <&softreset STIH407_MMC1_SOFTRESET>; + reset-names = "softreset"; bus-width = <4>; };

On 10 May 2017 at 10:09, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
reset-names property is needed to use the reset API for STi sdhci driver.
Signed-off-by: Patrice Chotard patrice.chotard@st.com Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
v5: _ none v4: _ none v3: _ none v2: _ none
arch/arm/dts/stih407-family.dtsi | 1 + 1 file changed, 1 insertion(+)
Reviewed-by: Simon Glass sjg@chromium.org

From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com Reviewed-by: Jaehoon Chung jh80.chung@samsung.com ---
v5: _ none v4: _ none v3: _ none v2: _ none
drivers/mmc/sti_sdhci.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-)
diff --git a/drivers/mmc/sti_sdhci.c b/drivers/mmc/sti_sdhci.c index d6c4d67..8b1b2c0 100644 --- a/drivers/mmc/sti_sdhci.c +++ b/drivers/mmc/sti_sdhci.c @@ -8,6 +8,7 @@ #include <common.h> #include <dm.h> #include <mmc.h> +#include <reset-uclass.h> #include <sdhci.h> #include <asm/arch/sdhci.h>
@@ -16,6 +17,7 @@ DECLARE_GLOBAL_DATA_PTR; struct sti_sdhci_plat { struct mmc_config cfg; struct mmc mmc; + struct reset_ctl reset; int instance; };
@@ -37,17 +39,19 @@ struct sti_sdhci_plat { * W/o these settings the SDHCI could configure and use the embedded controller * with limited features. */ -static void sti_mmc_core_config(struct udevice *dev) +static int sti_mmc_core_config(struct udevice *dev) { struct sti_sdhci_plat *plat = dev_get_platdata(dev); struct sdhci_host *host = dev_get_priv(dev); - unsigned long *sysconf; + int ret;
/* only MMC1 has a reset line */ if (plat->instance) { - sysconf = (unsigned long *)(STIH410_SYSCONF5_BASE + - ST_MMC_CCONFIG_REG_5); - generic_set_bit(SYSCONF_MMC1_ENABLE_BIT, sysconf); + ret = reset_deassert(&plat->reset); + if (ret < 0) { + error("MMC1 deassert failed: %d", ret); + return ret; + } }
writel(STI_FLASHSS_MMC_CORE_CONFIG_1, @@ -66,6 +70,8 @@ static void sti_mmc_core_config(struct udevice *dev) } writel(STI_FLASHSS_MMC_CORE_CONFIG4, host->ioaddr + FLASHSS_MMC_CORE_CONFIG_4); + + return 0; }
static int sti_sdhci_probe(struct udevice *dev) @@ -80,13 +86,20 @@ static int sti_sdhci_probe(struct udevice *dev) * MMC0 is wired to the SD slot, * MMC1 is wired on the high speed connector */ - - if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "resets", NULL)) + if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "resets", NULL)) { plat->instance = 1; - else + ret = reset_get_by_name(dev, "softreset", &plat->reset); + if (ret) { + error("can't get reset for %s (%d)", dev->name, ret); + return ret; + } + } else { plat->instance = 0; + }
- sti_mmc_core_config(dev); + ret = sti_mmc_core_config(dev); + if (ret) + return ret;
host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_32BIT_DMA_ADDR |

Hi Patrice,
On 10 May 2017 at 10:09, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
v5: _ none v4: _ none v3: _ none v2: _ none
drivers/mmc/sti_sdhci.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
This is fine as is. But please see questions below.
diff --git a/drivers/mmc/sti_sdhci.c b/drivers/mmc/sti_sdhci.c index d6c4d67..8b1b2c0 100644 --- a/drivers/mmc/sti_sdhci.c +++ b/drivers/mmc/sti_sdhci.c @@ -8,6 +8,7 @@ #include <common.h> #include <dm.h> #include <mmc.h> +#include <reset-uclass.h> #include <sdhci.h> #include <asm/arch/sdhci.h>
@@ -16,6 +17,7 @@ DECLARE_GLOBAL_DATA_PTR; struct sti_sdhci_plat { struct mmc_config cfg; struct mmc mmc;
struct reset_ctl reset; int instance;
};
@@ -37,17 +39,19 @@ struct sti_sdhci_plat {
- W/o these settings the SDHCI could configure and use the embedded controller
- with limited features.
*/ -static void sti_mmc_core_config(struct udevice *dev) +static int sti_mmc_core_config(struct udevice *dev) { struct sti_sdhci_plat *plat = dev_get_platdata(dev); struct sdhci_host *host = dev_get_priv(dev);
unsigned long *sysconf;
int ret; /* only MMC1 has a reset line */ if (plat->instance) {
sysconf = (unsigned long *)(STIH410_SYSCONF5_BASE +
ST_MMC_CCONFIG_REG_5);
generic_set_bit(SYSCONF_MMC1_ENABLE_BIT, sysconf);
ret = reset_deassert(&plat->reset);
if (ret < 0) {
error("MMC1 deassert failed: %d", ret);
return ret;
} } writel(STI_FLASHSS_MMC_CORE_CONFIG_1,
@@ -66,6 +70,8 @@ static void sti_mmc_core_config(struct udevice *dev) } writel(STI_FLASHSS_MMC_CORE_CONFIG4, host->ioaddr + FLASHSS_MMC_CORE_CONFIG_4);
return 0;
}
static int sti_sdhci_probe(struct udevice *dev) @@ -80,13 +86,20 @@ static int sti_sdhci_probe(struct udevice *dev) * MMC0 is wired to the SD slot, * MMC1 is wired on the high speed connector */
if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "resets", NULL))
if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "resets", NULL)) { plat->instance = 1;
else
ret = reset_get_by_name(dev, "softreset", &plat->reset);
Two questions:
1. The name "softreset" is in the "resets" property, isn't it? If so, can you use it instead of hard-coding "softreset" here? 2. Can you not call reset_get_by_name() and deal with the error return (-ENOENT I think) if there is no such reset?
if (ret) {
error("can't get reset for %s (%d)", dev->name, ret);
return ret;
}
} else { plat->instance = 0;
}
sti_mmc_core_config(dev);
ret = sti_mmc_core_config(dev);
if (ret)
return ret; host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_32BIT_DMA_ADDR |
-- 1.9.1
Regards, Simon

Hi Simon
On 05/15/2017 05:02 AM, Simon Glass wrote:
Hi Patrice,
On 10 May 2017 at 10:09, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
v5: _ none v4: _ none v3: _ none v2: _ none
drivers/mmc/sti_sdhci.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
This is fine as is. But please see questions below.
diff --git a/drivers/mmc/sti_sdhci.c b/drivers/mmc/sti_sdhci.c index d6c4d67..8b1b2c0 100644 --- a/drivers/mmc/sti_sdhci.c +++ b/drivers/mmc/sti_sdhci.c @@ -8,6 +8,7 @@ #include <common.h> #include <dm.h> #include <mmc.h> +#include <reset-uclass.h> #include <sdhci.h> #include <asm/arch/sdhci.h>
@@ -16,6 +17,7 @@ DECLARE_GLOBAL_DATA_PTR; struct sti_sdhci_plat { struct mmc_config cfg; struct mmc mmc;
struct reset_ctl reset; int instance;
};
@@ -37,17 +39,19 @@ struct sti_sdhci_plat {
- W/o these settings the SDHCI could configure and use the embedded controller
- with limited features.
*/ -static void sti_mmc_core_config(struct udevice *dev) +static int sti_mmc_core_config(struct udevice *dev) { struct sti_sdhci_plat *plat = dev_get_platdata(dev); struct sdhci_host *host = dev_get_priv(dev);
unsigned long *sysconf;
int ret; /* only MMC1 has a reset line */ if (plat->instance) {
sysconf = (unsigned long *)(STIH410_SYSCONF5_BASE +
ST_MMC_CCONFIG_REG_5);
generic_set_bit(SYSCONF_MMC1_ENABLE_BIT, sysconf);
ret = reset_deassert(&plat->reset);
if (ret < 0) {
error("MMC1 deassert failed: %d", ret);
return ret;
} } writel(STI_FLASHSS_MMC_CORE_CONFIG_1,
@@ -66,6 +70,8 @@ static void sti_mmc_core_config(struct udevice *dev) } writel(STI_FLASHSS_MMC_CORE_CONFIG4, host->ioaddr + FLASHSS_MMC_CORE_CONFIG_4);
return 0;
}
static int sti_sdhci_probe(struct udevice *dev) @@ -80,13 +86,20 @@ static int sti_sdhci_probe(struct udevice *dev) * MMC0 is wired to the SD slot, * MMC1 is wired on the high speed connector */
if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "resets", NULL))
if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "resets", NULL)) { plat->instance = 1;
else
ret = reset_get_by_name(dev, "softreset", &plat->reset);
Two questions:
- The name "softreset" is in the "resets" property, isn't it? If so,
can you use it instead of hard-coding "softreset" here?
Sorry, i didn't understand what you mean by "can you use it instead of hard-coding "softreset" here"
- Can you not call reset_get_by_name() and deal with the error return
(-ENOENT I think) if there is no such reset?
if (ret) {
error("can't get reset for %s (%d)", dev->name, ret);
return ret;
}
} else { plat->instance = 0;
}
sti_mmc_core_config(dev);
ret = sti_mmc_core_config(dev);
if (ret)
return ret; host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_32BIT_DMA_ADDR |
-- 1.9.1
Regards, Simon

Hi Patrice,
On 15 May 2017 at 03:21, Patrice CHOTARD patrice.chotard@st.com wrote:
Hi Simon
On 05/15/2017 05:02 AM, Simon Glass wrote:
Hi Patrice,
On 10 May 2017 at 10:09, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
v5: _ none v4: _ none v3: _ none v2: _ none
drivers/mmc/sti_sdhci.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
This is fine as is. But please see questions below.
diff --git a/drivers/mmc/sti_sdhci.c b/drivers/mmc/sti_sdhci.c index d6c4d67..8b1b2c0 100644 --- a/drivers/mmc/sti_sdhci.c +++ b/drivers/mmc/sti_sdhci.c @@ -8,6 +8,7 @@ #include <common.h> #include <dm.h> #include <mmc.h> +#include <reset-uclass.h> #include <sdhci.h> #include <asm/arch/sdhci.h>
@@ -16,6 +17,7 @@ DECLARE_GLOBAL_DATA_PTR; struct sti_sdhci_plat { struct mmc_config cfg; struct mmc mmc;
struct reset_ctl reset; int instance;
};
@@ -37,17 +39,19 @@ struct sti_sdhci_plat {
- W/o these settings the SDHCI could configure and use the embedded controller
- with limited features.
*/ -static void sti_mmc_core_config(struct udevice *dev) +static int sti_mmc_core_config(struct udevice *dev) { struct sti_sdhci_plat *plat = dev_get_platdata(dev); struct sdhci_host *host = dev_get_priv(dev);
unsigned long *sysconf;
int ret; /* only MMC1 has a reset line */ if (plat->instance) {
sysconf = (unsigned long *)(STIH410_SYSCONF5_BASE +
ST_MMC_CCONFIG_REG_5);
generic_set_bit(SYSCONF_MMC1_ENABLE_BIT, sysconf);
ret = reset_deassert(&plat->reset);
if (ret < 0) {
error("MMC1 deassert failed: %d", ret);
return ret;
} } writel(STI_FLASHSS_MMC_CORE_CONFIG_1,
@@ -66,6 +70,8 @@ static void sti_mmc_core_config(struct udevice *dev) } writel(STI_FLASHSS_MMC_CORE_CONFIG4, host->ioaddr + FLASHSS_MMC_CORE_CONFIG_4);
return 0;
}
static int sti_sdhci_probe(struct udevice *dev) @@ -80,13 +86,20 @@ static int sti_sdhci_probe(struct udevice *dev) * MMC0 is wired to the SD slot, * MMC1 is wired on the high speed connector */
if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "resets", NULL))
if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "resets", NULL)) { plat->instance = 1;
else
ret = reset_get_by_name(dev, "softreset", &plat->reset);
Two questions:
- The name "softreset" is in the "resets" property, isn't it? If so,
can you use it instead of hard-coding "softreset" here?
Sorry, i didn't understand what you mean by "can you use it instead of hard-coding "softreset" here"
I am wondering if the value of the 'resets' property is 'softtreset'? If so, you could perhaps use that value instead of the string 'softreset'.
- Can you not call reset_get_by_name() and deal with the error return
(-ENOENT I think) if there is no such reset?
if (ret) {
error("can't get reset for %s (%d)", dev->name, ret);
return ret;
}
} else { plat->instance = 0;
}
sti_mmc_core_config(dev);
ret = sti_mmc_core_config(dev);
if (ret)
return ret; host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_32BIT_DMA_ADDR |
-- 1.9.1
Regards, Simon

Hi Simon
On 05/17/2017 03:38 AM, Simon Glass wrote:
Hi Patrice,
On 15 May 2017 at 03:21, Patrice CHOTARD patrice.chotard@st.com wrote:
Hi Simon
On 05/15/2017 05:02 AM, Simon Glass wrote:
Hi Patrice,
On 10 May 2017 at 10:09, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
v5: _ none v4: _ none v3: _ none v2: _ none
drivers/mmc/sti_sdhci.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
This is fine as is. But please see questions below.
diff --git a/drivers/mmc/sti_sdhci.c b/drivers/mmc/sti_sdhci.c index d6c4d67..8b1b2c0 100644 --- a/drivers/mmc/sti_sdhci.c +++ b/drivers/mmc/sti_sdhci.c @@ -8,6 +8,7 @@ #include <common.h> #include <dm.h> #include <mmc.h> +#include <reset-uclass.h> #include <sdhci.h> #include <asm/arch/sdhci.h>
@@ -16,6 +17,7 @@ DECLARE_GLOBAL_DATA_PTR; struct sti_sdhci_plat { struct mmc_config cfg; struct mmc mmc;
struct reset_ctl reset; int instance;
};
@@ -37,17 +39,19 @@ struct sti_sdhci_plat {
- W/o these settings the SDHCI could configure and use the embedded controller
- with limited features.
*/ -static void sti_mmc_core_config(struct udevice *dev) +static int sti_mmc_core_config(struct udevice *dev) { struct sti_sdhci_plat *plat = dev_get_platdata(dev); struct sdhci_host *host = dev_get_priv(dev);
unsigned long *sysconf;
int ret; /* only MMC1 has a reset line */ if (plat->instance) {
sysconf = (unsigned long *)(STIH410_SYSCONF5_BASE +
ST_MMC_CCONFIG_REG_5);
generic_set_bit(SYSCONF_MMC1_ENABLE_BIT, sysconf);
ret = reset_deassert(&plat->reset);
if (ret < 0) {
error("MMC1 deassert failed: %d", ret);
return ret;
} } writel(STI_FLASHSS_MMC_CORE_CONFIG_1,
@@ -66,6 +70,8 @@ static void sti_mmc_core_config(struct udevice *dev) } writel(STI_FLASHSS_MMC_CORE_CONFIG4, host->ioaddr + FLASHSS_MMC_CORE_CONFIG_4);
return 0;
}
static int sti_sdhci_probe(struct udevice *dev) @@ -80,13 +86,20 @@ static int sti_sdhci_probe(struct udevice *dev) * MMC0 is wired to the SD slot, * MMC1 is wired on the high speed connector */
if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "resets", NULL))
if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "resets", NULL)) { plat->instance = 1;
else
ret = reset_get_by_name(dev, "softreset", &plat->reset);
Two questions:
- The name "softreset" is in the "resets" property, isn't it? If so,
can you use it instead of hard-coding "softreset" here?
Sorry, i didn't understand what you mean by "can you use it instead of hard-coding "softreset" here"
I am wondering if the value of the 'resets' property is 'softtreset'?
"softreset" is the value of the "reset-names" property.
resets = <&softreset STIH407_MMC1_SOFTRESET>; reset-names = "softreset";
But i am thinking to simplify this part.
Patrice
If so, you could perhaps use that value instead of the string 'softreset'.
- Can you not call reset_get_by_name() and deal with the error return
(-ENOENT I think) if there is no such reset?
if (ret) {
error("can't get reset for %s (%d)", dev->name, ret);
return ret;
}
} else { plat->instance = 0;
}
sti_mmc_core_config(dev);
ret = sti_mmc_core_config(dev);
if (ret)
return ret; host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_32BIT_DMA_ADDR |
-- 1.9.1
Regards, Simon

Hi Patrice,
On 17 May 2017 at 01:14, Patrice CHOTARD patrice.chotard@st.com wrote:
Hi Simon
On 05/17/2017 03:38 AM, Simon Glass wrote:
Hi Patrice,
On 15 May 2017 at 03:21, Patrice CHOTARD patrice.chotard@st.com wrote:
Hi Simon
On 05/15/2017 05:02 AM, Simon Glass wrote:
Hi Patrice,
On 10 May 2017 at 10:09, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
v5: _ none v4: _ none v3: _ none v2: _ none
drivers/mmc/sti_sdhci.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
This is fine as is. But please see questions below.
diff --git a/drivers/mmc/sti_sdhci.c b/drivers/mmc/sti_sdhci.c index d6c4d67..8b1b2c0 100644 --- a/drivers/mmc/sti_sdhci.c +++ b/drivers/mmc/sti_sdhci.c @@ -8,6 +8,7 @@ #include <common.h> #include <dm.h> #include <mmc.h> +#include <reset-uclass.h> #include <sdhci.h> #include <asm/arch/sdhci.h>
@@ -16,6 +17,7 @@ DECLARE_GLOBAL_DATA_PTR; struct sti_sdhci_plat { struct mmc_config cfg; struct mmc mmc;
struct reset_ctl reset; int instance;
};
@@ -37,17 +39,19 @@ struct sti_sdhci_plat {
- W/o these settings the SDHCI could configure and use the embedded controller
- with limited features.
*/ -static void sti_mmc_core_config(struct udevice *dev) +static int sti_mmc_core_config(struct udevice *dev) { struct sti_sdhci_plat *plat = dev_get_platdata(dev); struct sdhci_host *host = dev_get_priv(dev);
unsigned long *sysconf;
int ret; /* only MMC1 has a reset line */ if (plat->instance) {
sysconf = (unsigned long *)(STIH410_SYSCONF5_BASE +
ST_MMC_CCONFIG_REG_5);
generic_set_bit(SYSCONF_MMC1_ENABLE_BIT, sysconf);
ret = reset_deassert(&plat->reset);
if (ret < 0) {
error("MMC1 deassert failed: %d", ret);
return ret;
} } writel(STI_FLASHSS_MMC_CORE_CONFIG_1,
@@ -66,6 +70,8 @@ static void sti_mmc_core_config(struct udevice *dev) } writel(STI_FLASHSS_MMC_CORE_CONFIG4, host->ioaddr + FLASHSS_MMC_CORE_CONFIG_4);
return 0;
}
static int sti_sdhci_probe(struct udevice *dev) @@ -80,13 +86,20 @@ static int sti_sdhci_probe(struct udevice *dev) * MMC0 is wired to the SD slot, * MMC1 is wired on the high speed connector */
if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "resets", NULL))
if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "resets", NULL)) { plat->instance = 1;
else
ret = reset_get_by_name(dev, "softreset", &plat->reset);
Two questions:
- The name "softreset" is in the "resets" property, isn't it? If so,
can you use it instead of hard-coding "softreset" here?
Sorry, i didn't understand what you mean by "can you use it instead of hard-coding "softreset" here"
I am wondering if the value of the 'resets' property is 'softtreset'?
"softreset" is the value of the "reset-names" property.
resets = <&softreset STIH407_MMC1_SOFTRESET>; reset-names = "softreset";
But i am thinking to simplify this part.
OK I see. Well, from me:
Reviewed-by: Simon Glass sjg@chromium.org
Patrice
If so, you could perhaps use that value instead of the string 'softreset'.
- Can you not call reset_get_by_name() and deal with the error return
(-ENOENT I think) if there is no such reset?
if (ret) {
error("can't get reset for %s (%d)", dev->name, ret);
return ret;
}
} else { plat->instance = 0;
}
sti_mmc_core_config(dev);
ret = sti_mmc_core_config(dev);
if (ret)
return ret; host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_32BIT_DMA_ADDR |
-- 1.9.1
Regards, Simon

From: Patrice Chotard patrice.chotard@st.com
This is the generic phy driver for the picoPHY ports used by USB2/1.1 controllers. It is found on STiH407 SoC family from STMicroelectronics.
Signed-off-by: Patrice Chotard patrice.chotard@st.com Reviewed-by: Marek Vasut marex@denx.de
---
v5: _ add Reviewed-by: Marek Vasut marex@denx.de v4: _ update to use the new PHY uclass currently available on dm-next branch v3: _ convert driver to USB PHY uclass v2: _ replace bitfield_replace() by clrsetbits_le32()
doc/device-tree-bindings/phy/phy-stih407-usb.txt | 24 +++ drivers/phy/Kconfig | 8 + drivers/phy/Makefile | 1 + drivers/phy/sti_usb_phy.c | 181 +++++++++++++++++++++++ 4 files changed, 214 insertions(+) create mode 100644 doc/device-tree-bindings/phy/phy-stih407-usb.txt create mode 100644 drivers/phy/sti_usb_phy.c
diff --git a/doc/device-tree-bindings/phy/phy-stih407-usb.txt b/doc/device-tree-bindings/phy/phy-stih407-usb.txt new file mode 100644 index 0000000..de6a706 --- /dev/null +++ b/doc/device-tree-bindings/phy/phy-stih407-usb.txt @@ -0,0 +1,24 @@ +ST STiH407 USB PHY controller + +This file documents the dt bindings for the usb picoPHY driver which is the PHY for both USB2 and USB3 +host controllers (when controlling usb2/1.1 devices) available on STiH407 SoC family from STMicroelectronics. + +Required properties: +- compatible : should be "st,stih407-usb2-phy" +- st,syscfg : phandle of sysconfig bank plus integer array containing phyparam and phyctrl register offsets +- resets : list of phandle and reset specifier pairs. There should be two entries, one + for the whole phy and one for the port +- reset-names : list of reset signal names. Should be "global" and "port" +See: Documentation/devicetree/bindings/reset/st,sti-powerdown.txt +See: Documentation/devicetree/bindings/reset/reset.txt + +Example: + +usb2_picophy0: usbpicophy@f8 { + compatible = "st,stih407-usb2-phy"; + #phy-cells = <0>; + st,syscfg = <&syscfg_core 0x100 0xf4>; + resets = <&softreset STIH407_PICOPHY_SOFTRESET>, + <&picophyreset STIH407_PICOPHY0_RESET>; + reset-names = "global", "port"; +}; diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index a91a694..4330b36 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -59,4 +59,12 @@ config SPL_PIPE3_PHY This PHY is found on omap devices supporting SATA such as dra7, am57x and omap5
+config STI_USB_PHY + bool "STMicroelectronics USB2 picoPHY driver for STiH407 family" + depends on PHY && ARCH_STI + help + This is the generic phy driver for the picoPHY ports + used by USB2 and USB3 Host controllers available on + STiH407 SoC families. + endmenu diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 6ce96d2..22d92d3 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_$(SPL_)PHY) += phy-uclass.o obj-$(CONFIG_PHY_SANDBOX) += sandbox-phy.o obj-$(CONFIG_$(SPL_)PIPE3_PHY) += ti-pipe3-phy.o +obj-$(CONFIG_STI_USB_PHY) += sti_usb_phy.o diff --git a/drivers/phy/sti_usb_phy.c b/drivers/phy/sti_usb_phy.c new file mode 100644 index 0000000..c164062 --- /dev/null +++ b/drivers/phy/sti_usb_phy.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2017 + * Patrice Chotard patrice.chotard@st.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <bitfield.h> +#include <dm.h> +#include <errno.h> +#include <fdtdec.h> +#include <generic-phy.h> +#include <libfdt.h> +#include <regmap.h> +#include <reset-uclass.h> +#include <syscon.h> +#include <wait_bit.h> + +#include <linux/bitops.h> +#include <linux/compat.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Default PHY_SEL and REFCLKSEL configuration */ +#define STIH407_USB_PICOPHY_CTRL_PORT_CONF 0x6 + +/* ports parameters overriding */ +#define STIH407_USB_PICOPHY_PARAM_DEF 0x39a4dc + +#define PHYPARAM_REG 1 +#define PHYCTRL_REG 2 +#define PHYPARAM_NB 3 + +struct sti_usb_phy { + struct regmap *regmap; + struct reset_ctl global_ctl; + struct reset_ctl port_ctl; + int param; + int ctrl; +}; + +static int sti_usb_phy_deassert(struct sti_usb_phy *phy) +{ + int ret; + + ret = reset_deassert(&phy->global_ctl); + if (ret < 0) { + error("PHY global deassert failed: %d", ret); + return ret; + } + + ret = reset_deassert(&phy->port_ctl); + if (ret < 0) + error("PHY port deassert failed: %d", ret); + + return ret; +} + +static int sti_usb_phy_init(struct phy *usb_phy) +{ + struct udevice *dev = usb_phy->dev; + struct sti_usb_phy *phy = dev_get_priv(dev); + void __iomem *reg; + + /* set ctrl picophy value */ + reg = (void __iomem *)phy->regmap->base + phy->ctrl; + /* CTRL_PORT mask is 0x1f */ + clrsetbits_le32(reg, 0x1f, STIH407_USB_PICOPHY_CTRL_PORT_CONF); + + /* set ports parameters overriding */ + reg = (void __iomem *)phy->regmap->base + phy->param; + /* PARAM_DEF mask is 0xffffffff */ + clrsetbits_le32(reg, 0xffffffff, STIH407_USB_PICOPHY_PARAM_DEF); + + return sti_usb_phy_deassert(phy); +} + +static int sti_usb_phy_exit(struct phy *usb_phy) +{ + struct udevice *dev = usb_phy->dev; + struct sti_usb_phy *phy = dev_get_priv(dev); + int ret; + + ret = reset_deassert(&phy->port_ctl); + if (ret < 0) { + error("PHY port deassert failed: %d", ret); + return ret; + } + + ret = reset_deassert(&phy->global_ctl); + if (ret < 0) + error("PHY global deassert failed: %d", ret); + + return ret; +} + +struct phy_ops sti_usb_phy_ops = { + .init = sti_usb_phy_init, + .exit = sti_usb_phy_exit, +}; + +int sti_usb_phy_probe(struct udevice *dev) +{ + struct sti_usb_phy *priv = dev_get_priv(dev); + struct udevice *syscon; + struct fdtdec_phandle_args syscfg_phandle; + u32 cells[PHYPARAM_NB]; + int ret, count; + + /* get corresponding syscon phandle */ + ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset, + "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; + } + + priv->regmap = syscon_get_regmap(syscon); + if (!priv->regmap) { + error("unable to find regmap\n"); + return -ENODEV; + } + + /* get phy param offset */ + count = fdtdec_get_int_array_count(gd->fdt_blob, dev->of_offset, + "st,syscfg", cells, + ARRAY_SIZE(cells)); + + if (count < 0) { + error("Bad PHY st,syscfg property %d\n", count); + return -EINVAL; + } + + if (count > PHYPARAM_NB) { + error("Unsupported PHY param count %d\n", count); + return -EINVAL; + } + + priv->param = cells[PHYPARAM_REG]; + priv->ctrl = cells[PHYCTRL_REG]; + + /* get global reset control */ + ret = reset_get_by_name(dev, "global", &priv->global_ctl); + if (ret) { + error("can't get global reset for %s (%d)", dev->name, ret); + return ret; + } + + /* get port reset control */ + ret = reset_get_by_name(dev, "port", &priv->port_ctl); + if (ret) { + error("can't get port reset for %s (%d)", dev->name, ret); + return ret; + } + + return 0; +} + +static const struct udevice_id sti_usb_phy_ids[] = { + { .compatible = "st,stih407-usb2-phy" }, + { } +}; + +U_BOOT_DRIVER(sti_usb_phy) = { + .name = "sti_usb_phy", + .id = UCLASS_PHY, + .of_match = sti_usb_phy_ids, + .probe = sti_usb_phy_probe, + .ops = &sti_usb_phy_ops, + .priv_auto_alloc_size = sizeof(struct sti_usb_phy), +};

From: Patrice Chotard patrice.chotard@st.com
Add support for on-chip DWC3 controller available on STMicrolectronics STiH407 family SoCs. On B2260 board, the type AB USB connector is managed by a DWC3 IP. As USB3 signals are not wired, only USB2 is supported.
Signed-off-by: Patrice Chotard patrice.chotard@st.com --- v5: _ none
v4: _ update to use the new PHY uclass currently available on dm-next branch
v3: _ update to use the new USB PHY uclass _ previously, xhci-sti driver binded dwc3-sti (STi glue driver) which was not correct. Now we respect the device tree hierarchy, ie the STi dwc3 glue driver is first probed, then bind the xhci-sti driver.
v2: _ none
drivers/usb/host/Kconfig | 8 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/xhci-sti.c | 128 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 drivers/usb/host/xhci-sti.c
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 0bf8274..bf12ba7 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -38,6 +38,14 @@ config USB_XHCI_ROCKCHIP help Enables support for the on-chip xHCI controller on Rockchip SoCs.
+config USB_XHCI_STI + bool "Support for STMicroelectronics STiH407 family on-chip xHCI USB controller" + depends on ARCH_STI + default y + help + Enables support for the on-chip xHCI controller on STMicroelectronics + STiH407 family SoCs. + config USB_XHCI_ZYNQMP bool "Support for Xilinx ZynqMP on-chip xHCI USB controller" depends on ARCH_ZYNQMP diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 58c0cf5..48a99f4 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o +obj-$(CONFIG_USB_XHCI_STI) += xhci-sti.o
# designware obj-$(CONFIG_USB_DWC2) += dwc2.o diff --git a/drivers/usb/host/xhci-sti.c b/drivers/usb/host/xhci-sti.c new file mode 100644 index 0000000..3ad149c --- /dev/null +++ b/drivers/usb/host/xhci-sti.c @@ -0,0 +1,128 @@ +/* + * 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 <fdtdec.h> +#include <generic-phy.h> +#include <usb.h> + +#include "xhci.h" +#include <linux/usb/dwc3.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")));*/ + +struct sti_xhci_platdata { + struct phy usb_phy; + phys_addr_t dwc3_regs; +}; + +struct sti_xhci_priv { + struct xhci_ctrl ctrl; +}; + +static int sti_xhci_core_init(struct dwc3 *dwc3_reg) +{ + int ret; + + ret = dwc3_core_init(dwc3_reg); + if (ret) { + debug("failed to initialize core\n"); + return ret; + } + + /* We are hard-coding DWC3 core to Host Mode */ + dwc3_set_mode(dwc3_reg, DWC3_GCTL_PRTCAP_HOST); + + return 0; +} + +static int sti_xhci_ofdata_to_platdata(struct udevice *dev) +{ + struct sti_xhci_platdata *plat = dev_get_platdata(dev); + u32 reg[2]; + int ret; + + /* get the dwc3 register space base address */ + if (fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), "reg", reg, + ARRAY_SIZE(reg))) { + debug("dwc3 node has bad/missing 'reg' property\n"); + return -FDT_ERR_NOTFOUND; + } + plat->dwc3_regs = reg[0]; + + ret = generic_phy_get_by_name(dev, "usb2-phy", &plat->usb_phy); + if (ret) + error("USB PHY DT node not found for %s\n", dev->name); + + return 0; +} + +static int sti_xhci_probe(struct udevice *dev) +{ + struct sti_xhci_platdata *plat = dev_get_platdata(dev); + struct xhci_hcor *hcor; + struct xhci_hccr *hccr; + struct dwc3 *dwc3_reg; + int ret; + + hccr = (struct xhci_hccr *)plat->dwc3_regs; + hcor = (struct xhci_hcor *)((phys_addr_t)hccr + + HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); + + ret = generic_phy_init(&plat->usb_phy); + if (ret) { + error("Can't init USB PHY for %s\n", dev->name); + return ret; + } + + dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET); + + sti_xhci_core_init(dwc3_reg); + + return xhci_register(dev, hccr, hcor); +} + +static int sti_xhci_remove(struct udevice *dev) +{ + struct sti_xhci_platdata *plat = dev_get_platdata(dev); + int ret; + + ret = generic_phy_exit(&plat->usb_phy); + if (ret) { + error("Can't deinit USB PHY for %s\n", dev->name); + return ret; + } + + return xhci_deregister(dev); +} + +static const struct udevice_id sti_xhci_ids[] = { + { .compatible = "snps,dwc3" }, + { } +}; + +U_BOOT_DRIVER(xhci_sti) = { + .name = "xhci_sti", + .id = UCLASS_USB, + .of_match = sti_xhci_ids, + .ofdata_to_platdata = sti_xhci_ofdata_to_platdata, + .probe = sti_xhci_probe, + .remove = sti_xhci_remove, + .ops = &xhci_usb_ops, + .priv_auto_alloc_size = sizeof(struct sti_xhci_priv), + .platdata_auto_alloc_size = sizeof(struct sti_xhci_platdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +};

On 05/10/2017 06:09 PM, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Add support for on-chip DWC3 controller available on STMicrolectronics STiH407 family SoCs. On B2260 board, the type AB USB connector is managed by a DWC3 IP. As USB3 signals are not wired, only USB2 is supported.
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ none
v4: _ update to use the new PHY uclass currently available on dm-next branch
v3: _ update to use the new USB PHY uclass _ previously, xhci-sti driver binded dwc3-sti (STi glue driver) which was not correct. Now we respect the device tree hierarchy, ie the STi dwc3 glue driver is first probed, then bind the xhci-sti driver.
v2: _ none
drivers/usb/host/Kconfig | 8 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/xhci-sti.c | 128 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 drivers/usb/host/xhci-sti.c
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 0bf8274..bf12ba7 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -38,6 +38,14 @@ config USB_XHCI_ROCKCHIP help Enables support for the on-chip xHCI controller on Rockchip SoCs.
+config USB_XHCI_STI
- bool "Support for STMicroelectronics STiH407 family on-chip xHCI USB controller"
- depends on ARCH_STI
- default y
- help
Enables support for the on-chip xHCI controller on STMicroelectronics
STiH407 family SoCs.
config USB_XHCI_ZYNQMP bool "Support for Xilinx ZynqMP on-chip xHCI USB controller" depends on ARCH_ZYNQMP diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 58c0cf5..48a99f4 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o +obj-$(CONFIG_USB_XHCI_STI) += xhci-sti.o
# designware obj-$(CONFIG_USB_DWC2) += dwc2.o diff --git a/drivers/usb/host/xhci-sti.c b/drivers/usb/host/xhci-sti.c new file mode 100644 index 0000000..3ad149c --- /dev/null +++ b/drivers/usb/host/xhci-sti.c @@ -0,0 +1,128 @@ +/*
- 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 <fdtdec.h> +#include <generic-phy.h> +#include <usb.h>
+#include "xhci.h" +#include <linux/usb/dwc3.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")));*/
+struct sti_xhci_platdata {
- struct phy usb_phy;
- phys_addr_t dwc3_regs;
+};
+struct sti_xhci_priv {
- struct xhci_ctrl ctrl;
+};
+static int sti_xhci_core_init(struct dwc3 *dwc3_reg) +{
- int ret;
- ret = dwc3_core_init(dwc3_reg);
- if (ret) {
debug("failed to initialize core\n");
return ret;
- }
- /* We are hard-coding DWC3 core to Host Mode */
- dwc3_set_mode(dwc3_reg, DWC3_GCTL_PRTCAP_HOST);
- return 0;
+}
+static int sti_xhci_ofdata_to_platdata(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- u32 reg[2];
- int ret;
- /* get the dwc3 register space base address */
- if (fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), "reg", reg,
ARRAY_SIZE(reg))) {
debug("dwc3 node has bad/missing 'reg' property\n");
return -FDT_ERR_NOTFOUND;
- }
- plat->dwc3_regs = reg[0];
- ret = generic_phy_get_by_name(dev, "usb2-phy", &plat->usb_phy);
- if (ret)
error("USB PHY DT node not found for %s\n", dev->name);
- return 0;
+}
+static int sti_xhci_probe(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- struct xhci_hcor *hcor;
- struct xhci_hccr *hccr;
- struct dwc3 *dwc3_reg;
- int ret;
- hccr = (struct xhci_hccr *)plat->dwc3_regs;
- hcor = (struct xhci_hcor *)((phys_addr_t)hccr +
HC_LENGTH(xhci_readl(&(hccr)->cr_capbase)));
- ret = generic_phy_init(&plat->usb_phy);
- if (ret) {
error("Can't init USB PHY for %s\n", dev->name);
return ret;
- }
- dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET);
- sti_xhci_core_init(dwc3_reg);
- return xhci_register(dev, hccr, hcor);
+}
+static int sti_xhci_remove(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- int ret;
- ret = generic_phy_exit(&plat->usb_phy);
- if (ret) {
error("Can't deinit USB PHY for %s\n", dev->name);
return ret;
- }
- return xhci_deregister(dev);
+}
+static const struct udevice_id sti_xhci_ids[] = {
- { .compatible = "snps,dwc3" },
You probably want some more descriptive compatible string here ...
- { }
+};
+U_BOOT_DRIVER(xhci_sti) = {
- .name = "xhci_sti",
- .id = UCLASS_USB,
- .of_match = sti_xhci_ids,
- .ofdata_to_platdata = sti_xhci_ofdata_to_platdata,
- .probe = sti_xhci_probe,
- .remove = sti_xhci_remove,
- .ops = &xhci_usb_ops,
- .priv_auto_alloc_size = sizeof(struct sti_xhci_priv),
- .platdata_auto_alloc_size = sizeof(struct sti_xhci_platdata),
- .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};

Hi Marek
On 05/10/2017 11:16 PM, Marek Vasut wrote:
On 05/10/2017 06:09 PM, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Add support for on-chip DWC3 controller available on STMicrolectronics STiH407 family SoCs. On B2260 board, the type AB USB connector is managed by a DWC3 IP. As USB3 signals are not wired, only USB2 is supported.
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ none
v4: _ update to use the new PHY uclass currently available on dm-next branch
v3: _ update to use the new USB PHY uclass _ previously, xhci-sti driver binded dwc3-sti (STi glue driver) which was not correct. Now we respect the device tree hierarchy, ie the STi dwc3 glue driver is first probed, then bind the xhci-sti driver.
v2: _ none
drivers/usb/host/Kconfig | 8 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/xhci-sti.c | 128 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 drivers/usb/host/xhci-sti.c
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 0bf8274..bf12ba7 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -38,6 +38,14 @@ config USB_XHCI_ROCKCHIP help Enables support for the on-chip xHCI controller on Rockchip SoCs.
+config USB_XHCI_STI
- bool "Support for STMicroelectronics STiH407 family on-chip xHCI USB controller"
- depends on ARCH_STI
- default y
- help
Enables support for the on-chip xHCI controller on STMicroelectronics
STiH407 family SoCs.
config USB_XHCI_ZYNQMP bool "Support for Xilinx ZynqMP on-chip xHCI USB controller" depends on ARCH_ZYNQMP diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 58c0cf5..48a99f4 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o +obj-$(CONFIG_USB_XHCI_STI) += xhci-sti.o
# designware obj-$(CONFIG_USB_DWC2) += dwc2.o diff --git a/drivers/usb/host/xhci-sti.c b/drivers/usb/host/xhci-sti.c new file mode 100644 index 0000000..3ad149c --- /dev/null +++ b/drivers/usb/host/xhci-sti.c @@ -0,0 +1,128 @@ +/*
- 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 <fdtdec.h> +#include <generic-phy.h> +#include <usb.h>
+#include "xhci.h" +#include <linux/usb/dwc3.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")));*/
+struct sti_xhci_platdata {
- struct phy usb_phy;
- phys_addr_t dwc3_regs;
+};
+struct sti_xhci_priv {
- struct xhci_ctrl ctrl;
+};
+static int sti_xhci_core_init(struct dwc3 *dwc3_reg) +{
- int ret;
- ret = dwc3_core_init(dwc3_reg);
- if (ret) {
debug("failed to initialize core\n");
return ret;
- }
- /* We are hard-coding DWC3 core to Host Mode */
- dwc3_set_mode(dwc3_reg, DWC3_GCTL_PRTCAP_HOST);
- return 0;
+}
+static int sti_xhci_ofdata_to_platdata(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- u32 reg[2];
- int ret;
- /* get the dwc3 register space base address */
- if (fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), "reg", reg,
ARRAY_SIZE(reg))) {
debug("dwc3 node has bad/missing 'reg' property\n");
return -FDT_ERR_NOTFOUND;
- }
- plat->dwc3_regs = reg[0];
- ret = generic_phy_get_by_name(dev, "usb2-phy", &plat->usb_phy);
- if (ret)
error("USB PHY DT node not found for %s\n", dev->name);
- return 0;
+}
+static int sti_xhci_probe(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- struct xhci_hcor *hcor;
- struct xhci_hccr *hccr;
- struct dwc3 *dwc3_reg;
- int ret;
- hccr = (struct xhci_hccr *)plat->dwc3_regs;
- hcor = (struct xhci_hcor *)((phys_addr_t)hccr +
HC_LENGTH(xhci_readl(&(hccr)->cr_capbase)));
- ret = generic_phy_init(&plat->usb_phy);
- if (ret) {
error("Can't init USB PHY for %s\n", dev->name);
return ret;
- }
- dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET);
- sti_xhci_core_init(dwc3_reg);
- return xhci_register(dev, hccr, hcor);
+}
+static int sti_xhci_remove(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- int ret;
- ret = generic_phy_exit(&plat->usb_phy);
- if (ret) {
error("Can't deinit USB PHY for %s\n", dev->name);
return ret;
- }
- return xhci_deregister(dev);
+}
+static const struct udevice_id sti_xhci_ids[] = {
- { .compatible = "snps,dwc3" },
You probably want some more descriptive compatible string here ...
I simply reuse the same compatible string used by kernel driver and DT.
It's already used in fsl-dt-fixup.c : #define SNPS_DWC3 "snps,dwc3"
Patrice
- { }
+};
+U_BOOT_DRIVER(xhci_sti) = {
- .name = "xhci_sti",
- .id = UCLASS_USB,
- .of_match = sti_xhci_ids,
- .ofdata_to_platdata = sti_xhci_ofdata_to_platdata,
- .probe = sti_xhci_probe,
- .remove = sti_xhci_remove,
- .ops = &xhci_usb_ops,
- .priv_auto_alloc_size = sizeof(struct sti_xhci_priv),
- .platdata_auto_alloc_size = sizeof(struct sti_xhci_platdata),
- .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};

On 05/11/2017 09:08 AM, Patrice CHOTARD wrote:
Hi Marek
On 05/10/2017 11:16 PM, Marek Vasut wrote:
On 05/10/2017 06:09 PM, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Add support for on-chip DWC3 controller available on STMicrolectronics STiH407 family SoCs. On B2260 board, the type AB USB connector is managed by a DWC3 IP. As USB3 signals are not wired, only USB2 is supported.
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ none
v4: _ update to use the new PHY uclass currently available on dm-next branch
v3: _ update to use the new USB PHY uclass _ previously, xhci-sti driver binded dwc3-sti (STi glue driver) which was not correct. Now we respect the device tree hierarchy, ie the STi dwc3 glue driver is first probed, then bind the xhci-sti driver.
v2: _ none
drivers/usb/host/Kconfig | 8 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/xhci-sti.c | 128 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 drivers/usb/host/xhci-sti.c
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 0bf8274..bf12ba7 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -38,6 +38,14 @@ config USB_XHCI_ROCKCHIP help Enables support for the on-chip xHCI controller on Rockchip SoCs.
+config USB_XHCI_STI
- bool "Support for STMicroelectronics STiH407 family on-chip xHCI USB controller"
- depends on ARCH_STI
- default y
- help
Enables support for the on-chip xHCI controller on STMicroelectronics
STiH407 family SoCs.
config USB_XHCI_ZYNQMP bool "Support for Xilinx ZynqMP on-chip xHCI USB controller" depends on ARCH_ZYNQMP diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 58c0cf5..48a99f4 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o +obj-$(CONFIG_USB_XHCI_STI) += xhci-sti.o
# designware obj-$(CONFIG_USB_DWC2) += dwc2.o diff --git a/drivers/usb/host/xhci-sti.c b/drivers/usb/host/xhci-sti.c new file mode 100644 index 0000000..3ad149c --- /dev/null +++ b/drivers/usb/host/xhci-sti.c @@ -0,0 +1,128 @@ +/*
- 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 <fdtdec.h> +#include <generic-phy.h> +#include <usb.h>
+#include "xhci.h" +#include <linux/usb/dwc3.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")));*/
+struct sti_xhci_platdata {
- struct phy usb_phy;
- phys_addr_t dwc3_regs;
+};
+struct sti_xhci_priv {
- struct xhci_ctrl ctrl;
+};
+static int sti_xhci_core_init(struct dwc3 *dwc3_reg) +{
- int ret;
- ret = dwc3_core_init(dwc3_reg);
- if (ret) {
debug("failed to initialize core\n");
return ret;
- }
- /* We are hard-coding DWC3 core to Host Mode */
- dwc3_set_mode(dwc3_reg, DWC3_GCTL_PRTCAP_HOST);
- return 0;
+}
+static int sti_xhci_ofdata_to_platdata(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- u32 reg[2];
- int ret;
- /* get the dwc3 register space base address */
- if (fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), "reg", reg,
ARRAY_SIZE(reg))) {
debug("dwc3 node has bad/missing 'reg' property\n");
return -FDT_ERR_NOTFOUND;
- }
- plat->dwc3_regs = reg[0];
- ret = generic_phy_get_by_name(dev, "usb2-phy", &plat->usb_phy);
- if (ret)
error("USB PHY DT node not found for %s\n", dev->name);
- return 0;
+}
+static int sti_xhci_probe(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- struct xhci_hcor *hcor;
- struct xhci_hccr *hccr;
- struct dwc3 *dwc3_reg;
- int ret;
- hccr = (struct xhci_hccr *)plat->dwc3_regs;
- hcor = (struct xhci_hcor *)((phys_addr_t)hccr +
HC_LENGTH(xhci_readl(&(hccr)->cr_capbase)));
- ret = generic_phy_init(&plat->usb_phy);
- if (ret) {
error("Can't init USB PHY for %s\n", dev->name);
return ret;
- }
- dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET);
- sti_xhci_core_init(dwc3_reg);
- return xhci_register(dev, hccr, hcor);
+}
+static int sti_xhci_remove(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- int ret;
- ret = generic_phy_exit(&plat->usb_phy);
- if (ret) {
error("Can't deinit USB PHY for %s\n", dev->name);
return ret;
- }
- return xhci_deregister(dev);
+}
+static const struct udevice_id sti_xhci_ids[] = {
- { .compatible = "snps,dwc3" },
You probably want some more descriptive compatible string here ...
I simply reuse the same compatible string used by kernel driver and DT.
It's already used in fsl-dt-fixup.c : #define SNPS_DWC3 "snps,dwc3"
And how does this allow you to discern this ST controller from other (potential) DWC3 controllers in your system ? Answer: it does not. Why? Because it's the generic compatible and if your controller has some sort of quirks, you won't be able to identify that. On the other hand, if this really is generic dwc3, then this should be called something like xhci-dwc3-generic and not xhci-sti .

Hi Marek
On 05/11/2017 01:54 PM, Marek Vasut wrote:
On 05/11/2017 09:08 AM, Patrice CHOTARD wrote:
Hi Marek
On 05/10/2017 11:16 PM, Marek Vasut wrote:
On 05/10/2017 06:09 PM, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Add support for on-chip DWC3 controller available on STMicrolectronics STiH407 family SoCs. On B2260 board, the type AB USB connector is managed by a DWC3 IP. As USB3 signals are not wired, only USB2 is supported.
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ none
v4: _ update to use the new PHY uclass currently available on dm-next branch
v3: _ update to use the new USB PHY uclass _ previously, xhci-sti driver binded dwc3-sti (STi glue driver) which was not correct. Now we respect the device tree hierarchy, ie the STi dwc3 glue driver is first probed, then bind the xhci-sti driver.
v2: _ none
drivers/usb/host/Kconfig | 8 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/xhci-sti.c | 128 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 drivers/usb/host/xhci-sti.c
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 0bf8274..bf12ba7 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -38,6 +38,14 @@ config USB_XHCI_ROCKCHIP help Enables support for the on-chip xHCI controller on Rockchip SoCs.
+config USB_XHCI_STI
- bool "Support for STMicroelectronics STiH407 family on-chip xHCI USB controller"
- depends on ARCH_STI
- default y
- help
Enables support for the on-chip xHCI controller on STMicroelectronics
STiH407 family SoCs.
config USB_XHCI_ZYNQMP bool "Support for Xilinx ZynqMP on-chip xHCI USB controller" depends on ARCH_ZYNQMP diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 58c0cf5..48a99f4 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o +obj-$(CONFIG_USB_XHCI_STI) += xhci-sti.o
# designware obj-$(CONFIG_USB_DWC2) += dwc2.o diff --git a/drivers/usb/host/xhci-sti.c b/drivers/usb/host/xhci-sti.c new file mode 100644 index 0000000..3ad149c --- /dev/null +++ b/drivers/usb/host/xhci-sti.c @@ -0,0 +1,128 @@ +/*
- 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 <fdtdec.h> +#include <generic-phy.h> +#include <usb.h>
+#include "xhci.h" +#include <linux/usb/dwc3.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")));*/
+struct sti_xhci_platdata {
- struct phy usb_phy;
- phys_addr_t dwc3_regs;
+};
+struct sti_xhci_priv {
- struct xhci_ctrl ctrl;
+};
+static int sti_xhci_core_init(struct dwc3 *dwc3_reg) +{
- int ret;
- ret = dwc3_core_init(dwc3_reg);
- if (ret) {
debug("failed to initialize core\n");
return ret;
- }
- /* We are hard-coding DWC3 core to Host Mode */
- dwc3_set_mode(dwc3_reg, DWC3_GCTL_PRTCAP_HOST);
- return 0;
+}
+static int sti_xhci_ofdata_to_platdata(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- u32 reg[2];
- int ret;
- /* get the dwc3 register space base address */
- if (fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), "reg", reg,
ARRAY_SIZE(reg))) {
debug("dwc3 node has bad/missing 'reg' property\n");
return -FDT_ERR_NOTFOUND;
- }
- plat->dwc3_regs = reg[0];
- ret = generic_phy_get_by_name(dev, "usb2-phy", &plat->usb_phy);
- if (ret)
error("USB PHY DT node not found for %s\n", dev->name);
- return 0;
+}
+static int sti_xhci_probe(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- struct xhci_hcor *hcor;
- struct xhci_hccr *hccr;
- struct dwc3 *dwc3_reg;
- int ret;
- hccr = (struct xhci_hccr *)plat->dwc3_regs;
- hcor = (struct xhci_hcor *)((phys_addr_t)hccr +
HC_LENGTH(xhci_readl(&(hccr)->cr_capbase)));
- ret = generic_phy_init(&plat->usb_phy);
- if (ret) {
error("Can't init USB PHY for %s\n", dev->name);
return ret;
- }
- dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET);
- sti_xhci_core_init(dwc3_reg);
- return xhci_register(dev, hccr, hcor);
+}
+static int sti_xhci_remove(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- int ret;
- ret = generic_phy_exit(&plat->usb_phy);
- if (ret) {
error("Can't deinit USB PHY for %s\n", dev->name);
return ret;
- }
- return xhci_deregister(dev);
+}
+static const struct udevice_id sti_xhci_ids[] = {
- { .compatible = "snps,dwc3" },
You probably want some more descriptive compatible string here ...
I simply reuse the same compatible string used by kernel driver and DT.
It's already used in fsl-dt-fixup.c : #define SNPS_DWC3 "snps,dwc3"
And how does this allow you to discern this ST controller from other (potential) DWC3 controllers in your system ? Answer: it does not. Why? Because it's the generic compatible and if your controller has some sort of quirks, you won't be able to identify that. On the other hand, if this really is generic dwc3, then this should be called something like xhci-dwc3-generic and not xhci-sti .
Ok i get your point, yes it's a generic dwc3 driver.
It could make sense to merge xhci-sti.c (this patch) into existing xhci-dwc3.c ? What do you think ?
Thanks
Patrice

On 05/12/2017 10:40 AM, Patrice CHOTARD wrote:
Hi Marek
On 05/11/2017 01:54 PM, Marek Vasut wrote:
On 05/11/2017 09:08 AM, Patrice CHOTARD wrote:
Hi Marek
On 05/10/2017 11:16 PM, Marek Vasut wrote:
On 05/10/2017 06:09 PM, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Add support for on-chip DWC3 controller available on STMicrolectronics STiH407 family SoCs. On B2260 board, the type AB USB connector is managed by a DWC3 IP. As USB3 signals are not wired, only USB2 is supported.
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ none
v4: _ update to use the new PHY uclass currently available on dm-next branch
v3: _ update to use the new USB PHY uclass _ previously, xhci-sti driver binded dwc3-sti (STi glue driver) which was not correct. Now we respect the device tree hierarchy, ie the STi dwc3 glue driver is first probed, then bind the xhci-sti driver.
v2: _ none
drivers/usb/host/Kconfig | 8 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/xhci-sti.c | 128 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 drivers/usb/host/xhci-sti.c
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 0bf8274..bf12ba7 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -38,6 +38,14 @@ config USB_XHCI_ROCKCHIP help Enables support for the on-chip xHCI controller on Rockchip SoCs.
+config USB_XHCI_STI
- bool "Support for STMicroelectronics STiH407 family on-chip xHCI USB controller"
- depends on ARCH_STI
- default y
- help
Enables support for the on-chip xHCI controller on STMicroelectronics
STiH407 family SoCs.
config USB_XHCI_ZYNQMP bool "Support for Xilinx ZynqMP on-chip xHCI USB controller" depends on ARCH_ZYNQMP diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 58c0cf5..48a99f4 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o +obj-$(CONFIG_USB_XHCI_STI) += xhci-sti.o
# designware obj-$(CONFIG_USB_DWC2) += dwc2.o diff --git a/drivers/usb/host/xhci-sti.c b/drivers/usb/host/xhci-sti.c new file mode 100644 index 0000000..3ad149c --- /dev/null +++ b/drivers/usb/host/xhci-sti.c @@ -0,0 +1,128 @@ +/*
- 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 <fdtdec.h> +#include <generic-phy.h> +#include <usb.h>
+#include "xhci.h" +#include <linux/usb/dwc3.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")));*/
+struct sti_xhci_platdata {
- struct phy usb_phy;
- phys_addr_t dwc3_regs;
+};
+struct sti_xhci_priv {
- struct xhci_ctrl ctrl;
+};
+static int sti_xhci_core_init(struct dwc3 *dwc3_reg) +{
- int ret;
- ret = dwc3_core_init(dwc3_reg);
- if (ret) {
debug("failed to initialize core\n");
return ret;
- }
- /* We are hard-coding DWC3 core to Host Mode */
- dwc3_set_mode(dwc3_reg, DWC3_GCTL_PRTCAP_HOST);
- return 0;
+}
+static int sti_xhci_ofdata_to_platdata(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- u32 reg[2];
- int ret;
- /* get the dwc3 register space base address */
- if (fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), "reg", reg,
ARRAY_SIZE(reg))) {
debug("dwc3 node has bad/missing 'reg' property\n");
return -FDT_ERR_NOTFOUND;
- }
- plat->dwc3_regs = reg[0];
- ret = generic_phy_get_by_name(dev, "usb2-phy", &plat->usb_phy);
- if (ret)
error("USB PHY DT node not found for %s\n", dev->name);
- return 0;
+}
+static int sti_xhci_probe(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- struct xhci_hcor *hcor;
- struct xhci_hccr *hccr;
- struct dwc3 *dwc3_reg;
- int ret;
- hccr = (struct xhci_hccr *)plat->dwc3_regs;
- hcor = (struct xhci_hcor *)((phys_addr_t)hccr +
HC_LENGTH(xhci_readl(&(hccr)->cr_capbase)));
- ret = generic_phy_init(&plat->usb_phy);
- if (ret) {
error("Can't init USB PHY for %s\n", dev->name);
return ret;
- }
- dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET);
- sti_xhci_core_init(dwc3_reg);
- return xhci_register(dev, hccr, hcor);
+}
+static int sti_xhci_remove(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- int ret;
- ret = generic_phy_exit(&plat->usb_phy);
- if (ret) {
error("Can't deinit USB PHY for %s\n", dev->name);
return ret;
- }
- return xhci_deregister(dev);
+}
+static const struct udevice_id sti_xhci_ids[] = {
- { .compatible = "snps,dwc3" },
You probably want some more descriptive compatible string here ...
I simply reuse the same compatible string used by kernel driver and DT.
It's already used in fsl-dt-fixup.c : #define SNPS_DWC3 "snps,dwc3"
And how does this allow you to discern this ST controller from other (potential) DWC3 controllers in your system ? Answer: it does not. Why? Because it's the generic compatible and if your controller has some sort of quirks, you won't be able to identify that. On the other hand, if this really is generic dwc3, then this should be called something like xhci-dwc3-generic and not xhci-sti .
Ok i get your point, yes it's a generic dwc3 driver.
It could make sense to merge xhci-sti.c (this patch) into existing xhci-dwc3.c ? What do you think ?
Might be even better, yes

Hi Marek
On 05/12/2017 12:54 PM, Marek Vasut wrote:
On 05/12/2017 10:40 AM, Patrice CHOTARD wrote:
Hi Marek
On 05/11/2017 01:54 PM, Marek Vasut wrote:
On 05/11/2017 09:08 AM, Patrice CHOTARD wrote:
Hi Marek
On 05/10/2017 11:16 PM, Marek Vasut wrote:
On 05/10/2017 06:09 PM, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Add support for on-chip DWC3 controller available on STMicrolectronics STiH407 family SoCs. On B2260 board, the type AB USB connector is managed by a DWC3 IP. As USB3 signals are not wired, only USB2 is supported.
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ none
v4: _ update to use the new PHY uclass currently available on dm-next branch
v3: _ update to use the new USB PHY uclass _ previously, xhci-sti driver binded dwc3-sti (STi glue driver) which was not correct. Now we respect the device tree hierarchy, ie the STi dwc3 glue driver is first probed, then bind the xhci-sti driver.
v2: _ none
drivers/usb/host/Kconfig | 8 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/xhci-sti.c | 128 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 drivers/usb/host/xhci-sti.c
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 0bf8274..bf12ba7 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -38,6 +38,14 @@ config USB_XHCI_ROCKCHIP help Enables support for the on-chip xHCI controller on Rockchip SoCs.
+config USB_XHCI_STI
- bool "Support for STMicroelectronics STiH407 family on-chip xHCI USB controller"
- depends on ARCH_STI
- default y
- help
Enables support for the on-chip xHCI controller on STMicroelectronics
STiH407 family SoCs.
config USB_XHCI_ZYNQMP bool "Support for Xilinx ZynqMP on-chip xHCI USB controller" depends on ARCH_ZYNQMP diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 58c0cf5..48a99f4 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o +obj-$(CONFIG_USB_XHCI_STI) += xhci-sti.o
# designware obj-$(CONFIG_USB_DWC2) += dwc2.o diff --git a/drivers/usb/host/xhci-sti.c b/drivers/usb/host/xhci-sti.c new file mode 100644 index 0000000..3ad149c --- /dev/null +++ b/drivers/usb/host/xhci-sti.c @@ -0,0 +1,128 @@ +/*
- 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 <fdtdec.h> +#include <generic-phy.h> +#include <usb.h>
+#include "xhci.h" +#include <linux/usb/dwc3.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")));*/
+struct sti_xhci_platdata {
- struct phy usb_phy;
- phys_addr_t dwc3_regs;
+};
+struct sti_xhci_priv {
- struct xhci_ctrl ctrl;
+};
+static int sti_xhci_core_init(struct dwc3 *dwc3_reg) +{
- int ret;
- ret = dwc3_core_init(dwc3_reg);
- if (ret) {
debug("failed to initialize core\n");
return ret;
- }
- /* We are hard-coding DWC3 core to Host Mode */
- dwc3_set_mode(dwc3_reg, DWC3_GCTL_PRTCAP_HOST);
- return 0;
+}
+static int sti_xhci_ofdata_to_platdata(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- u32 reg[2];
- int ret;
- /* get the dwc3 register space base address */
- if (fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), "reg", reg,
ARRAY_SIZE(reg))) {
debug("dwc3 node has bad/missing 'reg' property\n");
return -FDT_ERR_NOTFOUND;
- }
- plat->dwc3_regs = reg[0];
- ret = generic_phy_get_by_name(dev, "usb2-phy", &plat->usb_phy);
- if (ret)
error("USB PHY DT node not found for %s\n", dev->name);
- return 0;
+}
+static int sti_xhci_probe(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- struct xhci_hcor *hcor;
- struct xhci_hccr *hccr;
- struct dwc3 *dwc3_reg;
- int ret;
- hccr = (struct xhci_hccr *)plat->dwc3_regs;
- hcor = (struct xhci_hcor *)((phys_addr_t)hccr +
HC_LENGTH(xhci_readl(&(hccr)->cr_capbase)));
- ret = generic_phy_init(&plat->usb_phy);
- if (ret) {
error("Can't init USB PHY for %s\n", dev->name);
return ret;
- }
- dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET);
- sti_xhci_core_init(dwc3_reg);
- return xhci_register(dev, hccr, hcor);
+}
+static int sti_xhci_remove(struct udevice *dev) +{
- struct sti_xhci_platdata *plat = dev_get_platdata(dev);
- int ret;
- ret = generic_phy_exit(&plat->usb_phy);
- if (ret) {
error("Can't deinit USB PHY for %s\n", dev->name);
return ret;
- }
- return xhci_deregister(dev);
+}
+static const struct udevice_id sti_xhci_ids[] = {
- { .compatible = "snps,dwc3" },
You probably want some more descriptive compatible string here ...
I simply reuse the same compatible string used by kernel driver and DT.
It's already used in fsl-dt-fixup.c : #define SNPS_DWC3 "snps,dwc3"
And how does this allow you to discern this ST controller from other (potential) DWC3 controllers in your system ? Answer: it does not. Why? Because it's the generic compatible and if your controller has some sort of quirks, you won't be able to identify that. On the other hand, if this really is generic dwc3, then this should be called something like xhci-dwc3-generic and not xhci-sti .
Ok i get your point, yes it's a generic dwc3 driver.
It could make sense to merge xhci-sti.c (this patch) into existing xhci-dwc3.c ? What do you think ?
Might be even better, yes
Do you prefer i include this merge into this series or to send it separately as for ehci/hci generic update ?
Patrice

On 05/12/2017 01:15 PM, Patrice CHOTARD wrote:
Hi Marek
On 05/12/2017 12:54 PM, Marek Vasut wrote:
On 05/12/2017 10:40 AM, Patrice CHOTARD wrote:
Hi Marek
On 05/11/2017 01:54 PM, Marek Vasut wrote:
On 05/11/2017 09:08 AM, Patrice CHOTARD wrote:
Hi Marek
On 05/10/2017 11:16 PM, Marek Vasut wrote:
On 05/10/2017 06:09 PM, patrice.chotard@st.com wrote: > From: Patrice Chotard patrice.chotard@st.com > > Add support for on-chip DWC3 controller available > on STMicrolectronics STiH407 family SoCs. > On B2260 board, the type AB USB connector is managed > by a DWC3 IP. As USB3 signals are not wired, only USB2 > is supported. > > Signed-off-by: Patrice Chotard patrice.chotard@st.com > --- > v5: _ none > > v4: _ update to use the new PHY uclass currently available on dm-next branch > > v3: _ update to use the new USB PHY uclass > _ previously, xhci-sti driver binded dwc3-sti (STi glue driver) which was not correct. > Now we respect the device tree hierarchy, ie the STi dwc3 glue driver is first probed, > then bind the xhci-sti driver. > > v2: _ none > > drivers/usb/host/Kconfig | 8 +++ > drivers/usb/host/Makefile | 1 + > drivers/usb/host/xhci-sti.c | 128 ++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 137 insertions(+) > create mode 100644 drivers/usb/host/xhci-sti.c > > diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig > index 0bf8274..bf12ba7 100644 > --- a/drivers/usb/host/Kconfig > +++ b/drivers/usb/host/Kconfig > @@ -38,6 +38,14 @@ config USB_XHCI_ROCKCHIP > help > Enables support for the on-chip xHCI controller on Rockchip SoCs. > > +config USB_XHCI_STI > + bool "Support for STMicroelectronics STiH407 family on-chip xHCI USB controller" > + depends on ARCH_STI > + default y > + help > + Enables support for the on-chip xHCI controller on STMicroelectronics > + STiH407 family SoCs. > + > config USB_XHCI_ZYNQMP > bool "Support for Xilinx ZynqMP on-chip xHCI USB controller" > depends on ARCH_ZYNQMP > diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile > index 58c0cf5..48a99f4 100644 > --- a/drivers/usb/host/Makefile > +++ b/drivers/usb/host/Makefile > @@ -64,6 +64,7 @@ obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o > obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o > obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o > obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o > +obj-$(CONFIG_USB_XHCI_STI) += xhci-sti.o > > # designware > obj-$(CONFIG_USB_DWC2) += dwc2.o > diff --git a/drivers/usb/host/xhci-sti.c b/drivers/usb/host/xhci-sti.c > new file mode 100644 > index 0000000..3ad149c > --- /dev/null > +++ b/drivers/usb/host/xhci-sti.c > @@ -0,0 +1,128 @@ > +/* > + * 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 <fdtdec.h> > +#include <generic-phy.h> > +#include <usb.h> > + > +#include "xhci.h" > +#include <linux/usb/dwc3.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")));*/ > + > +struct sti_xhci_platdata { > + struct phy usb_phy; > + phys_addr_t dwc3_regs; > +}; > + > +struct sti_xhci_priv { > + struct xhci_ctrl ctrl; > +}; > + > +static int sti_xhci_core_init(struct dwc3 *dwc3_reg) > +{ > + int ret; > + > + ret = dwc3_core_init(dwc3_reg); > + if (ret) { > + debug("failed to initialize core\n"); > + return ret; > + } > + > + /* We are hard-coding DWC3 core to Host Mode */ > + dwc3_set_mode(dwc3_reg, DWC3_GCTL_PRTCAP_HOST); > + > + return 0; > +} > + > +static int sti_xhci_ofdata_to_platdata(struct udevice *dev) > +{ > + struct sti_xhci_platdata *plat = dev_get_platdata(dev); > + u32 reg[2]; > + int ret; > + > + /* get the dwc3 register space base address */ > + if (fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), "reg", reg, > + ARRAY_SIZE(reg))) { > + debug("dwc3 node has bad/missing 'reg' property\n"); > + return -FDT_ERR_NOTFOUND; > + } > + plat->dwc3_regs = reg[0]; > + > + ret = generic_phy_get_by_name(dev, "usb2-phy", &plat->usb_phy); > + if (ret) > + error("USB PHY DT node not found for %s\n", dev->name); > + > + return 0; > +} > + > +static int sti_xhci_probe(struct udevice *dev) > +{ > + struct sti_xhci_platdata *plat = dev_get_platdata(dev); > + struct xhci_hcor *hcor; > + struct xhci_hccr *hccr; > + struct dwc3 *dwc3_reg; > + int ret; > + > + hccr = (struct xhci_hccr *)plat->dwc3_regs; > + hcor = (struct xhci_hcor *)((phys_addr_t)hccr + > + HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); > + > + ret = generic_phy_init(&plat->usb_phy); > + if (ret) { > + error("Can't init USB PHY for %s\n", dev->name); > + return ret; > + } > + > + dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET); > + > + sti_xhci_core_init(dwc3_reg); > + > + return xhci_register(dev, hccr, hcor); > +} > + > +static int sti_xhci_remove(struct udevice *dev) > +{ > + struct sti_xhci_platdata *plat = dev_get_platdata(dev); > + int ret; > + > + ret = generic_phy_exit(&plat->usb_phy); > + if (ret) { > + error("Can't deinit USB PHY for %s\n", dev->name); > + return ret; > + } > + > + return xhci_deregister(dev); > +} > + > +static const struct udevice_id sti_xhci_ids[] = { > + { .compatible = "snps,dwc3" },
You probably want some more descriptive compatible string here ...
I simply reuse the same compatible string used by kernel driver and DT.
It's already used in fsl-dt-fixup.c : #define SNPS_DWC3 "snps,dwc3"
And how does this allow you to discern this ST controller from other (potential) DWC3 controllers in your system ? Answer: it does not. Why? Because it's the generic compatible and if your controller has some sort of quirks, you won't be able to identify that. On the other hand, if this really is generic dwc3, then this should be called something like xhci-dwc3-generic and not xhci-sti .
Ok i get your point, yes it's a generic dwc3 driver.
It could make sense to merge xhci-sti.c (this patch) into existing xhci-dwc3.c ? What do you think ?
Might be even better, yes
Do you prefer i include this merge into this series or to send it separately as for ehci/hci generic update ?
Split it so the stuff can go in independently as it matures ...

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 --- v5: _ none
v4: _ none
v3: _ rename dwc3-sti.c to dwc3-sti-glue.c _ respect device tree hierarchy, this driver is now responsible for xhci-sti binding (done in sti_dwc3_glue_bind())
v2: _ use setbits_le32() instead of read, modify, write sequence _ add missing parenthesis
arch/arm/include/asm/arch-stih410/sys_proto.h | 11 + doc/device-tree-bindings/usb/dwc3-st.txt | 60 ++++++ drivers/usb/host/Makefile | 2 +- drivers/usb/host/dwc3-sti-glue.c | 278 ++++++++++++++++++++++++++ include/dwc3-sti-glue.h | 43 ++++ 5 files changed, 393 insertions(+), 1 deletion(-) create mode 100644 arch/arm/include/asm/arch-stih410/sys_proto.h create mode 100644 doc/device-tree-bindings/usb/dwc3-st.txt create mode 100644 drivers/usb/host/dwc3-sti-glue.c create mode 100644 include/dwc3-sti-glue.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/doc/device-tree-bindings/usb/dwc3-st.txt b/doc/device-tree-bindings/usb/dwc3-st.txt new file mode 100644 index 0000000..a26a139 --- /dev/null +++ b/doc/device-tree-bindings/usb/dwc3-st.txt @@ -0,0 +1,60 @@ +ST DWC3 glue logic + +This file documents the parameters for the dwc3-st driver. +This driver controls the glue logic used to configure the dwc3 core on +STiH407 based platforms. + +Required properties: + - compatible : must be "st,stih407-dwc3" + - reg : glue logic base address and USB syscfg ctrl register offset + - reg-names : should be "reg-glue" and "syscfg-reg" + - st,syscon : should be phandle to system configuration node which + encompasses the glue registers + - resets : list of phandle and reset specifier pairs. There should be two entries, one + for the powerdown and softreset lines of the usb3 IP + - reset-names : list of reset signal names. Names should be "powerdown" and "softreset" + + - #address-cells, #size-cells : should be '1' if the device has sub-nodes + with 'reg' property + + - pinctl-names : A pinctrl state named "default" must be defined + + - pinctrl-0 : Pin control group + + - ranges : allows valid 1:1 translation between child's address space and + parent's address space + +Sub-nodes: +The dwc3 core should be added as subnode to ST DWC3 glue as shown in the +example below. + +NB: The dr_mode property is NOT optional for this driver, as the default value +is "otg", which isn't supported by this SoC. Valid dr_mode values for dwc3-st are +either "host" or "device". + +Example: + +st_dwc3: dwc3@8f94000 { + status = "disabled"; + compatible = "st,stih407-dwc3"; + reg = <0x08f94000 0x1000>, <0x110 0x4>; + reg-names = "reg-glue", "syscfg-reg"; + st,syscfg = <&syscfg_core>; + resets = <&powerdown STIH407_USB3_POWERDOWN>, + <&softreset STIH407_MIPHY2_SOFTRESET>; + reset-names = "powerdown", "softreset"; + #address-cells = <1>; + #size-cells = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb3>; + ranges; + + dwc3: dwc3@9900000 { + compatible = "snps,dwc3"; + reg = <0x09900000 0x100000>; + interrupts = <GIC_SPI 155 IRQ_TYPE_NONE>; + dr_mode = "host"; + phy-names = "usb2-phy", "usb3-phy"; + phys = <&usb2_picophy2>, <&phy_port2 PHY_TYPE_USB3>; + }; +}; diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 48a99f4..af7b7fb 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -64,7 +64,7 @@ obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o -obj-$(CONFIG_USB_XHCI_STI) += xhci-sti.o +obj-$(CONFIG_USB_XHCI_STI) += xhci-sti.o dwc3-sti-glue.o
# designware obj-$(CONFIG_USB_DWC2) += dwc2.o diff --git a/drivers/usb/host/dwc3-sti-glue.c b/drivers/usb/host/dwc3-sti-glue.c new file mode 100644 index 0000000..368d7ef --- /dev/null +++ b/drivers/usb/host/dwc3-sti-glue.c @@ -0,0 +1,278 @@ +/* + * 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-glue.h> +#include <errno.h> +#include <fdtdec.h> +#include <libfdt.h> +#include <dm/lists.h> +#include <regmap.h> +#include <reset-uclass.h> +#include <syscon.h> +#include <usb.h> + +#include <linux/usb/dwc3.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct sti_dwc3_glue_platdata { + phys_addr_t syscfg_base; + phys_addr_t glue_base; + phys_addr_t syscfg_offset; + struct reset_ctl powerdown_ctl; + struct reset_ctl softreset_ctl; + enum usb_dr_mode mode; +}; + +static int sti_dwc3_glue_drd_init(struct sti_dwc3_glue_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_glue_init(struct sti_dwc3_glue_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_init(enum usb_dr_mode mode) +{ + struct sti_dwc3_glue_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_glue_drd_init(&plat); + sti_dwc3_glue_init(&plat); + + return 0; +} + +static int sti_dwc3_glue_ofdata_to_platdata(struct udevice *dev) +{ + struct sti_dwc3_glue_platdata *plat = dev_get_platdata(dev); + struct fdtdec_phandle_args syscfg_phandle; + struct udevice *syscon; + struct regmap *regmap; + int ret; + u32 reg[4]; + + ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), + "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]; + + /* get corresponding syscon phandle */ + ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev), + "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; + + /* get powerdown reset */ + ret = reset_get_by_name(dev, "powerdown", &plat->powerdown_ctl); + if (ret) { + error("can't get powerdown reset for %s (%d)", dev->name, ret); + return ret; + } + + /* get softreset reset */ + ret = reset_get_by_name(dev, "softreset", &plat->softreset_ctl); + if (ret) + error("can't get soft reset for %s (%d)", dev->name, ret); + + return ret; +}; + +static int sti_dwc3_glue_bind(struct udevice *dev) +{ + int dwc3_node; + + /* check if one subnode is present */ + dwc3_node = fdt_first_subnode(gd->fdt_blob, dev_of_offset(dev)); + if (dwc3_node <= 0) { + error("Can't find subnode for %s\n", dev->name); + return -ENODEV; + } + + /* check if the subnode compatible string is the dwc3 one*/ + if (fdt_node_check_compatible(gd->fdt_blob, dwc3_node, + "snps,dwc3") != 0) { + error("Can't find dwc3 subnode for %s\n", dev->name); + return -ENODEV; + } + + return dm_scan_fdt_dev(dev); +} + +static int sti_dwc3_glue_probe(struct udevice *dev) +{ + struct sti_dwc3_glue_platdata *plat = dev_get_platdata(dev); + int ret; + + /* deassert both powerdown and softreset */ + ret = reset_deassert(&plat->powerdown_ctl); + if (ret < 0) { + error("DWC3 powerdown reset deassert failed: %d", ret); + return ret; + } + + ret = reset_deassert(&plat->softreset_ctl); + if (ret < 0) + error("DWC3 soft reset deassert failed: %d", ret); + + return ret; +} + +static int sti_dwc3_glue_remove(struct udevice *dev) +{ + struct sti_dwc3_glue_platdata *plat = dev_get_platdata(dev); + int ret; + + /* assert both powerdown and softreset */ + ret = reset_assert(&plat->powerdown_ctl); + if (ret < 0) { + error("DWC3 powerdown reset deassert failed: %d", ret); + return ret; + } + + ret = reset_assert(&plat->softreset_ctl); + if (ret < 0) + error("DWC3 soft reset deassert failed: %d", ret); + + return ret; +} + +static const struct udevice_id sti_dwc3_glue_ids[] = { + { .compatible = "st,stih407-dwc3" }, + { } +}; + +U_BOOT_DRIVER(dwc3_sti_glue) = { + .name = "dwc3_sti_glue", + .id = UCLASS_MISC, + .of_match = sti_dwc3_glue_ids, + .ofdata_to_platdata = sti_dwc3_glue_ofdata_to_platdata, + .probe = sti_dwc3_glue_probe, + .remove = sti_dwc3_glue_remove, + .bind = sti_dwc3_glue_bind, + .platdata_auto_alloc_size = sizeof(struct sti_dwc3_glue_platdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; diff --git a/include/dwc3-sti-glue.h b/include/dwc3-sti-glue.h new file mode 100644 index 0000000..2083427 --- /dev/null +++ b/include/dwc3-sti-glue.h @@ -0,0 +1,43 @@ +/* + * 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) + +int sti_dwc3_init(enum usb_dr_mode mode); + +#endif /* __DWC3_STI_UBOOT_H_ */

Hi Patrice,
On 10 May 2017 at 10:09, 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
v5: _ none
v4: _ none
v3: _ rename dwc3-sti.c to dwc3-sti-glue.c _ respect device tree hierarchy, this driver is now responsible for xhci-sti binding (done in sti_dwc3_glue_bind())
v2: _ use setbits_le32() instead of read, modify, write sequence _ add missing parenthesis
arch/arm/include/asm/arch-stih410/sys_proto.h | 11 + doc/device-tree-bindings/usb/dwc3-st.txt | 60 ++++++ drivers/usb/host/Makefile | 2 +- drivers/usb/host/dwc3-sti-glue.c | 278 ++++++++++++++++++++++++++ include/dwc3-sti-glue.h | 43 ++++ 5 files changed, 393 insertions(+), 1 deletion(-) create mode 100644 arch/arm/include/asm/arch-stih410/sys_proto.h create mode 100644 doc/device-tree-bindings/usb/dwc3-st.txt create mode 100644 drivers/usb/host/dwc3-sti-glue.c create mode 100644 include/dwc3-sti-glue.h
Reviewed-by: Simon Glass sjg@chromium.org
Please see below.
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/doc/device-tree-bindings/usb/dwc3-st.txt b/doc/device-tree-bindings/usb/dwc3-st.txt new file mode 100644 index 0000000..a26a139 --- /dev/null +++ b/doc/device-tree-bindings/usb/dwc3-st.txt @@ -0,0 +1,60 @@ +ST DWC3 glue logic
+This file documents the parameters for the dwc3-st driver. +This driver controls the glue logic used to configure the dwc3 core on +STiH407 based platforms.
+Required properties:
- compatible : must be "st,stih407-dwc3"
- reg : glue logic base address and USB syscfg ctrl register offset
- reg-names : should be "reg-glue" and "syscfg-reg"
- st,syscon : should be phandle to system configuration node which
encompasses the glue registers
- resets : list of phandle and reset specifier pairs. There should be two entries, one
for the powerdown and softreset lines of the usb3 IP
- reset-names : list of reset signal names. Names should be "powerdown" and "softreset"
- #address-cells, #size-cells : should be '1' if the device has sub-nodes
- with 'reg' property
- pinctl-names : A pinctrl state named "default" must be defined
- pinctrl-0 : Pin control group
- ranges : allows valid 1:1 translation between child's address space and
parent's address space
+Sub-nodes: +The dwc3 core should be added as subnode to ST DWC3 glue as shown in the +example below.
+NB: The dr_mode property is NOT optional for this driver, as the default value +is "otg", which isn't supported by this SoC. Valid dr_mode values for dwc3-st are +either "host" or "device".
+Example:
+st_dwc3: dwc3@8f94000 {
status = "disabled";
compatible = "st,stih407-dwc3";
reg = <0x08f94000 0x1000>, <0x110 0x4>;
reg-names = "reg-glue", "syscfg-reg";
st,syscfg = <&syscfg_core>;
resets = <&powerdown STIH407_USB3_POWERDOWN>,
<&softreset STIH407_MIPHY2_SOFTRESET>;
reset-names = "powerdown", "softreset";
#address-cells = <1>;
#size-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usb3>;
ranges;
dwc3: dwc3@9900000 {
compatible = "snps,dwc3";
reg = <0x09900000 0x100000>;
interrupts = <GIC_SPI 155 IRQ_TYPE_NONE>;
dr_mode = "host";
phy-names = "usb2-phy", "usb3-phy";
phys = <&usb2_picophy2>, <&phy_port2 PHY_TYPE_USB3>;
};
+};
Is this the binding used in Linux?
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 48a99f4..af7b7fb 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -64,7 +64,7 @@ obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o -obj-$(CONFIG_USB_XHCI_STI) += xhci-sti.o +obj-$(CONFIG_USB_XHCI_STI) += xhci-sti.o dwc3-sti-glue.o
# designware obj-$(CONFIG_USB_DWC2) += dwc2.o diff --git a/drivers/usb/host/dwc3-sti-glue.c b/drivers/usb/host/dwc3-sti-glue.c new file mode 100644 index 0000000..368d7ef --- /dev/null +++ b/drivers/usb/host/dwc3-sti-glue.c @@ -0,0 +1,278 @@ +/*
- 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>
common.h should always go first. See http://www.denx.de/wiki/U-Boot/CodingStyle
+#include <dm.h> +#include <dwc3-sti-glue.h> +#include <errno.h> +#include <fdtdec.h> +#include <libfdt.h> +#include <dm/lists.h> +#include <regmap.h> +#include <reset-uclass.h> +#include <syscon.h> +#include <usb.h>
+#include <linux/usb/dwc3.h>
+DECLARE_GLOBAL_DATA_PTR;
+struct sti_dwc3_glue_platdata {
struct comment? What do these fields mean?
phys_addr_t syscfg_base;
phys_addr_t glue_base;
phys_addr_t syscfg_offset;
struct reset_ctl powerdown_ctl;
struct reset_ctl softreset_ctl;
enum usb_dr_mode mode;
+};
+static int sti_dwc3_glue_drd_init(struct sti_dwc3_glue_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_glue_init(struct sti_dwc3_glue_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_init(enum usb_dr_mode mode) +{
struct sti_dwc3_glue_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);
Can you use uclass_get_device_by_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;
}
[..]
diff --git a/include/dwc3-sti-glue.h b/include/dwc3-sti-glue.h new file mode 100644 index 0000000..2083427 --- /dev/null +++ b/include/dwc3-sti-glue.h @@ -0,0 +1,43 @@ +/*
- 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)
+int sti_dwc3_init(enum usb_dr_mode mode);
We really need to move the USB device stuff over the driver model. Any ideas on how we could do that?
+#endif /* __DWC3_STI_UBOOT_H_ */
1.9.1
Regards, Simon

Hi Simon
On 05/15/2017 05:02 AM, Simon Glass wrote:
Hi Patrice,
On 10 May 2017 at 10:09, 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
v5: _ none
v4: _ none
v3: _ rename dwc3-sti.c to dwc3-sti-glue.c _ respect device tree hierarchy, this driver is now responsible for xhci-sti binding (done in sti_dwc3_glue_bind())
v2: _ use setbits_le32() instead of read, modify, write sequence _ add missing parenthesis
arch/arm/include/asm/arch-stih410/sys_proto.h | 11 + doc/device-tree-bindings/usb/dwc3-st.txt | 60 ++++++ drivers/usb/host/Makefile | 2 +- drivers/usb/host/dwc3-sti-glue.c | 278 ++++++++++++++++++++++++++ include/dwc3-sti-glue.h | 43 ++++ 5 files changed, 393 insertions(+), 1 deletion(-) create mode 100644 arch/arm/include/asm/arch-stih410/sys_proto.h create mode 100644 doc/device-tree-bindings/usb/dwc3-st.txt create mode 100644 drivers/usb/host/dwc3-sti-glue.c create mode 100644 include/dwc3-sti-glue.h
Reviewed-by: Simon Glass sjg@chromium.org
Please see below.
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/doc/device-tree-bindings/usb/dwc3-st.txt b/doc/device-tree-bindings/usb/dwc3-st.txt new file mode 100644 index 0000000..a26a139 --- /dev/null +++ b/doc/device-tree-bindings/usb/dwc3-st.txt @@ -0,0 +1,60 @@ +ST DWC3 glue logic
+This file documents the parameters for the dwc3-st driver. +This driver controls the glue logic used to configure the dwc3 core on +STiH407 based platforms.
+Required properties:
- compatible : must be "st,stih407-dwc3"
- reg : glue logic base address and USB syscfg ctrl register offset
- reg-names : should be "reg-glue" and "syscfg-reg"
- st,syscon : should be phandle to system configuration node which
encompasses the glue registers
- resets : list of phandle and reset specifier pairs. There should be two entries, one
for the powerdown and softreset lines of the usb3 IP
- reset-names : list of reset signal names. Names should be "powerdown" and "softreset"
- #address-cells, #size-cells : should be '1' if the device has sub-nodes
- with 'reg' property
- pinctl-names : A pinctrl state named "default" must be defined
- pinctrl-0 : Pin control group
- ranges : allows valid 1:1 translation between child's address space and
parent's address space
+Sub-nodes: +The dwc3 core should be added as subnode to ST DWC3 glue as shown in the +example below.
+NB: The dr_mode property is NOT optional for this driver, as the default value +is "otg", which isn't supported by this SoC. Valid dr_mode values for dwc3-st are +either "host" or "device".
+Example:
+st_dwc3: dwc3@8f94000 {
status = "disabled";
compatible = "st,stih407-dwc3";
reg = <0x08f94000 0x1000>, <0x110 0x4>;
reg-names = "reg-glue", "syscfg-reg";
st,syscfg = <&syscfg_core>;
resets = <&powerdown STIH407_USB3_POWERDOWN>,
<&softreset STIH407_MIPHY2_SOFTRESET>;
reset-names = "powerdown", "softreset";
#address-cells = <1>;
#size-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usb3>;
ranges;
dwc3: dwc3@9900000 {
compatible = "snps,dwc3";
reg = <0x09900000 0x100000>;
interrupts = <GIC_SPI 155 IRQ_TYPE_NONE>;
dr_mode = "host";
phy-names = "usb2-phy", "usb3-phy";
phys = <&usb2_picophy2>, <&phy_port2 PHY_TYPE_USB3>;
};
+};
Is this the binding used in Linux?
Yes, exactly the same
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 48a99f4..af7b7fb 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -64,7 +64,7 @@ obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o -obj-$(CONFIG_USB_XHCI_STI) += xhci-sti.o +obj-$(CONFIG_USB_XHCI_STI) += xhci-sti.o dwc3-sti-glue.o
# designware obj-$(CONFIG_USB_DWC2) += dwc2.o diff --git a/drivers/usb/host/dwc3-sti-glue.c b/drivers/usb/host/dwc3-sti-glue.c new file mode 100644 index 0000000..368d7ef --- /dev/null +++ b/drivers/usb/host/dwc3-sti-glue.c @@ -0,0 +1,278 @@ +/*
- 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>
common.h should always go first. See http://www.denx.de/wiki/U-Boot/CodingStyle
ok will fix it
+#include <dm.h> +#include <dwc3-sti-glue.h> +#include <errno.h> +#include <fdtdec.h> +#include <libfdt.h> +#include <dm/lists.h> +#include <regmap.h> +#include <reset-uclass.h> +#include <syscon.h> +#include <usb.h>
+#include <linux/usb/dwc3.h>
+DECLARE_GLOBAL_DATA_PTR;
+struct sti_dwc3_glue_platdata {
struct comment? What do these fields mean?
ok, will add it
phys_addr_t syscfg_base;
phys_addr_t glue_base;
phys_addr_t syscfg_offset;
struct reset_ctl powerdown_ctl;
struct reset_ctl softreset_ctl;
enum usb_dr_mode mode;
+};
+static int sti_dwc3_glue_drd_init(struct sti_dwc3_glue_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_glue_init(struct sti_dwc3_glue_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_init(enum usb_dr_mode mode) +{
struct sti_dwc3_glue_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);
Can you use uclass_get_device_by_phandle()?
Ok
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;
}
[..]
diff --git a/include/dwc3-sti-glue.h b/include/dwc3-sti-glue.h new file mode 100644 index 0000000..2083427 --- /dev/null +++ b/include/dwc3-sti-glue.h @@ -0,0 +1,43 @@ +/*
- 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)
+int sti_dwc3_init(enum usb_dr_mode mode);
We really need to move the USB device stuff over the driver model. Any ideas on how we could do that?
+#endif /* __DWC3_STI_UBOOT_H_ */
1.9.1
Regards, Simon

From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com ---
v5: _ none v4: _ none v3: _ none v2: _ none
include/configs/stih410-b2260.h | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/include/configs/stih410-b2260.h b/include/configs/stih410-b2260.h index 6f4070f..3df0e04 100644 --- a/include/configs/stih410-b2260.h +++ b/include/configs/stih410-b2260.h @@ -52,4 +52,8 @@
#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_USB_OHCI_NEW +#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 2 +#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 + #endif /* __CONFIG_H */

On 10 May 2017 at 10:09, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ none v4: _ none v3: _ none v2: _ none
include/configs/stih410-b2260.h | 4 ++++ 1 file changed, 4 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

From: Patrice Chotard patrice.chotard@st.com
Add usb_gadget_handle_interrupts(), board_usb_init(), board_usb_cleanup() and g_dnl_board_usb_cable_connected() callbacks needed for FASTBOOT support
Signed-off-by: Patrice Chotard patrice.chotard@st.com --- v5: _ none v4: _ none v3: _ none v2: _ none
board/st/stih410-b2260/board.c | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/board/st/stih410-b2260/board.c b/board/st/stih410-b2260/board.c index 92b0695..899a3e9 100644 --- a/board/st/stih410-b2260/board.c +++ b/board/st/stih410-b2260/board.c @@ -7,6 +7,9 @@ */
#include <common.h> +#include <dwc3-sti-glue.h> +#include <dwc3-uboot.h> +#include <usb.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -36,3 +39,44 @@ int board_init(void) { return 0; } + +#ifdef CONFIG_USB_DWC3 +static struct dwc3_device dwc3_device_data = { + .maximum_speed = USB_SPEED_HIGH, + .dr_mode = USB_DR_MODE_PERIPHERAL, + .index = 0, +}; + +int usb_gadget_handle_interrupts(int index) +{ + dwc3_uboot_handle_interrupt(index); + return 0; +} + +int board_usb_init(int index, enum usb_init_type init) +{ + int node; + const void *blob = gd->fdt_blob; + + /* find the snps,dwc3 node */ + node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc3"); + + dwc3_device_data.base = fdtdec_get_addr(blob, node, "reg"); + + /* init dwc3 glue with mode forced to PERIPHERAL */ + sti_dwc3_init(USB_DR_MODE_PERIPHERAL); + + return dwc3_uboot_init(&dwc3_device_data); +} + +int board_usb_cleanup(int index, enum usb_init_type init) +{ + dwc3_uboot_exit(index); + return 0; +} + +int g_dnl_board_usb_cable_connected(void) +{ + return 1; +} +#endif

On 10 May 2017 at 10:09, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Add usb_gadget_handle_interrupts(), board_usb_init(), board_usb_cleanup() and g_dnl_board_usb_cable_connected() callbacks needed for FASTBOOT support
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ none v4: _ none v3: _ none v2: _ none
board/st/stih410-b2260/board.c | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com ---
v5: _ none v4: _ none v3: _ none v2: _ none
include/configs/stih410-b2260.h | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/include/configs/stih410-b2260.h b/include/configs/stih410-b2260.h index 3df0e04..6c84e9b 100644 --- a/include/configs/stih410-b2260.h +++ b/include/configs/stih410-b2260.h @@ -52,8 +52,20 @@
#define CONFIG_SKIP_LOWLEVEL_INIT
+/* USB Configs */ #define CONFIG_USB_OHCI_NEW #define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 2 #define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2
+#define CONFIG_USB_HOST_ETHER +#define CONFIG_USB_ETHER_ASIX +#define CONFIG_USB_ETHER_MCS7830 +#define CONFIG_USB_ETHER_SMSC95XX + +/* NET Configs */ +#define CONFIG_BOOTP_SUBNETMASK +#define CONFIG_BOOTP_GATEWAY +#define CONFIG_BOOTP_HOSTNAME +#define CONFIG_BOOTP_BOOTPATH + #endif /* __CONFIG_H */

On 10 May 2017 at 10:09, patrice.chotard@st.com wrote:
It's a good idea to always have a commit message.
From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ none v4: _ none v3: _ none v2: _ none
include/configs/stih410-b2260.h | 12 ++++++++++++ 1 file changed, 12 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

Hi Simon
On 05/15/2017 05:03 AM, Simon Glass wrote:
On 10 May 2017 at 10:09, patrice.chotard@st.com wrote:
It's a good idea to always have a commit message.
Will fix it
From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ none v4: _ none v3: _ none v2: _ none
include/configs/stih410-b2260.h | 12 ++++++++++++ 1 file changed, 12 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com ---
v5: _ add support of new generic PHY UCLASS
drivers/usb/host/ehci-generic.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index 2190adb..3c2f5a7 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -6,6 +6,8 @@
#include <common.h> #include <clk.h> +#include <fdtdec.h> +#include <generic-phy.h> #include <reset.h> #include <asm/io.h> #include <dm.h> @@ -50,6 +52,17 @@ static int ehci_usb_probe(struct udevice *dev) reset_free(&reset); }
+ for (i = 0; ; i++) { + struct phy usb_phy; + int ret; + + ret = generic_phy_get_by_index(dev, i, &usb_phy); + if (ret < 0) + break; + if (generic_phy_init(&usb_phy)) + printf("failed to init usb phy %d\n", i); + } + hccr = map_physmem(dev_get_addr(dev), 0x100, MAP_NOCACHE); hcor = (struct ehci_hcor *)((uintptr_t)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));

On 05/10/2017 06:09 PM, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Commit message missing.
You should also break this patchset up into smaller pieces.
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ add support of new generic PHY UCLASS
drivers/usb/host/ehci-generic.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index 2190adb..3c2f5a7 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -6,6 +6,8 @@
#include <common.h> #include <clk.h> +#include <fdtdec.h> +#include <generic-phy.h> #include <reset.h> #include <asm/io.h> #include <dm.h> @@ -50,6 +52,17 @@ static int ehci_usb_probe(struct udevice *dev) reset_free(&reset); }
- for (i = 0; ; i++) {
struct phy usb_phy;
int ret;
ret = generic_phy_get_by_index(dev, i, &usb_phy);
if (ret < 0)
break;
if (generic_phy_init(&usb_phy))
printf("failed to init usb phy %d\n", i);
How does this whole block work ? What is this about ?
- }
- hccr = map_physmem(dev_get_addr(dev), 0x100, MAP_NOCACHE); hcor = (struct ehci_hcor *)((uintptr_t)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));

Hi Marek
On 05/10/2017 11:18 PM, Marek Vasut wrote:
On 05/10/2017 06:09 PM, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Commit message missing.
ok i will fix it
You should also break this patchset up into smaller pieces.
You mean, extract the update of generic OHCI and >EHCI driver from this series ?
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ add support of new generic PHY UCLASS
drivers/usb/host/ehci-generic.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index 2190adb..3c2f5a7 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -6,6 +6,8 @@
#include <common.h> #include <clk.h> +#include <fdtdec.h> +#include <generic-phy.h> #include <reset.h> #include <asm/io.h> #include <dm.h> @@ -50,6 +52,17 @@ static int ehci_usb_probe(struct udevice *dev) reset_free(&reset); }
- for (i = 0; ; i++) {
struct phy usb_phy;
int ret;
ret = generic_phy_get_by_index(dev, i, &usb_phy);
if (ret < 0)
break;
if (generic_phy_init(&usb_phy))
printf("failed to init usb phy %d\n", i);
How does this whole block work ? What is this about ?
It allows to retrieve any present USB phys node and call the associated init callback. see patch 4 of this series ([PATCH v5 04/14] usb: phy: Add STi USB2 PHY)
FYI, in dm next branch, there is a new generic PHY framework implementation. See 0ace7fe60d5c258324ef4b2caaa556616b96d1d9 drivers: phy: add generic PHY framework
Thanks
Patrice
- }
- hccr = map_physmem(dev_get_addr(dev), 0x100, MAP_NOCACHE); hcor = (struct ehci_hcor *)((uintptr_t)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));

On 05/11/2017 09:19 AM, Patrice CHOTARD wrote:
Hi Marek
On 05/10/2017 11:18 PM, Marek Vasut wrote:
On 05/10/2017 06:09 PM, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Commit message missing.
ok i will fix it
You should also break this patchset up into smaller pieces.
You mean, extract the update of generic OHCI and >EHCI driver from this series ?
Yes, split the patchset into independent pieces so it's not such a massive drop of code.
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ add support of new generic PHY UCLASS
drivers/usb/host/ehci-generic.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index 2190adb..3c2f5a7 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -6,6 +6,8 @@
#include <common.h> #include <clk.h> +#include <fdtdec.h> +#include <generic-phy.h> #include <reset.h> #include <asm/io.h> #include <dm.h> @@ -50,6 +52,17 @@ static int ehci_usb_probe(struct udevice *dev) reset_free(&reset); }
- for (i = 0; ; i++) {
struct phy usb_phy;
int ret;
ret = generic_phy_get_by_index(dev, i, &usb_phy);
if (ret < 0)
break;
if (generic_phy_init(&usb_phy))
printf("failed to init usb phy %d\n", i);
How does this whole block work ? What is this about ?
It allows to retrieve any present USB phys node and call the associated init callback. see patch 4 of this series ([PATCH v5 04/14] usb: phy: Add STi USB2 PHY)
FYI, in dm next branch, there is a new generic PHY framework implementation. See 0ace7fe60d5c258324ef4b2caaa556616b96d1d9 drivers: phy: add generic PHY framework
And why do you need to iterate over indexes ? Why don't you just parse a phandle ?

Hi Marek
On 05/11/2017 01:55 PM, Marek Vasut wrote:
On 05/11/2017 09:19 AM, Patrice CHOTARD wrote:
Hi Marek
On 05/10/2017 11:18 PM, Marek Vasut wrote:
On 05/10/2017 06:09 PM, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Commit message missing.
ok i will fix it
You should also break this patchset up into smaller pieces.
You mean, extract the update of generic OHCI and >EHCI driver from this series ?
Yes, split the patchset into independent pieces so it's not such a massive drop of code.
Ok
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ add support of new generic PHY UCLASS
drivers/usb/host/ehci-generic.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index 2190adb..3c2f5a7 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -6,6 +6,8 @@
#include <common.h> #include <clk.h> +#include <fdtdec.h> +#include <generic-phy.h> #include <reset.h> #include <asm/io.h> #include <dm.h> @@ -50,6 +52,17 @@ static int ehci_usb_probe(struct udevice *dev) reset_free(&reset); }
- for (i = 0; ; i++) {
struct phy usb_phy;
int ret;
ret = generic_phy_get_by_index(dev, i, &usb_phy);
if (ret < 0)
break;
if (generic_phy_init(&usb_phy))
printf("failed to init usb phy %d\n", i);
How does this whole block work ? What is this about ?
It allows to retrieve any present USB phys node and call the associated init callback. see patch 4 of this series ([PATCH v5 04/14] usb: phy: Add STi USB2 PHY)
FYI, in dm next branch, there is a new generic PHY framework implementation. See 0ace7fe60d5c258324ef4b2caaa556616b96d1d9 drivers: phy: add generic PHY framework
And why do you need to iterate over indexes ? Why don't you just parse a phandle ?
As for clocks or resets, in case there is more than 1 phy connected.
Patrice

On 05/12/2017 10:49 AM, Patrice CHOTARD wrote:
Hi Marek
On 05/11/2017 01:55 PM, Marek Vasut wrote:
On 05/11/2017 09:19 AM, Patrice CHOTARD wrote:
Hi Marek
On 05/10/2017 11:18 PM, Marek Vasut wrote:
On 05/10/2017 06:09 PM, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Commit message missing.
ok i will fix it
You should also break this patchset up into smaller pieces.
You mean, extract the update of generic OHCI and >EHCI driver from this series ?
Yes, split the patchset into independent pieces so it's not such a massive drop of code.
Ok
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ add support of new generic PHY UCLASS
drivers/usb/host/ehci-generic.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index 2190adb..3c2f5a7 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -6,6 +6,8 @@
#include <common.h> #include <clk.h> +#include <fdtdec.h> +#include <generic-phy.h> #include <reset.h> #include <asm/io.h> #include <dm.h> @@ -50,6 +52,17 @@ static int ehci_usb_probe(struct udevice *dev) reset_free(&reset); }
- for (i = 0; ; i++) {
struct phy usb_phy;
int ret;
ret = generic_phy_get_by_index(dev, i, &usb_phy);
if (ret < 0)
break;
if (generic_phy_init(&usb_phy))
printf("failed to init usb phy %d\n", i);
How does this whole block work ? What is this about ?
It allows to retrieve any present USB phys node and call the associated init callback. see patch 4 of this series ([PATCH v5 04/14] usb: phy: Add STi USB2 PHY)
FYI, in dm next branch, there is a new generic PHY framework implementation. See 0ace7fe60d5c258324ef4b2caaa556616b96d1d9 drivers: phy: add generic PHY framework
And why do you need to iterate over indexes ? Why don't you just parse a phandle ?
As for clocks or resets, in case there is more than 1 phy connected.
Can that ever happen or is that hypothetical possibility ? I haven't seen EHCI hardware with multiple PHYs yet.
Patrice

Hi Marek
On 05/12/2017 12:54 PM, Marek Vasut wrote:
On 05/12/2017 10:49 AM, Patrice CHOTARD wrote:
Hi Marek
On 05/11/2017 01:55 PM, Marek Vasut wrote:
On 05/11/2017 09:19 AM, Patrice CHOTARD wrote:
Hi Marek
On 05/10/2017 11:18 PM, Marek Vasut wrote:
On 05/10/2017 06:09 PM, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Commit message missing.
ok i will fix it
You should also break this patchset up into smaller pieces.
You mean, extract the update of generic OHCI and >EHCI driver from this series ?
Yes, split the patchset into independent pieces so it's not such a massive drop of code.
Ok
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ add support of new generic PHY UCLASS
drivers/usb/host/ehci-generic.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c index 2190adb..3c2f5a7 100644 --- a/drivers/usb/host/ehci-generic.c +++ b/drivers/usb/host/ehci-generic.c @@ -6,6 +6,8 @@
#include <common.h> #include <clk.h> +#include <fdtdec.h> +#include <generic-phy.h> #include <reset.h> #include <asm/io.h> #include <dm.h> @@ -50,6 +52,17 @@ static int ehci_usb_probe(struct udevice *dev) reset_free(&reset); }
- for (i = 0; ; i++) {
struct phy usb_phy;
int ret;
ret = generic_phy_get_by_index(dev, i, &usb_phy);
if (ret < 0)
break;
if (generic_phy_init(&usb_phy))
printf("failed to init usb phy %d\n", i);
How does this whole block work ? What is this about ?
It allows to retrieve any present USB phys node and call the associated init callback. see patch 4 of this series ([PATCH v5 04/14] usb: phy: Add STi USB2 PHY)
FYI, in dm next branch, there is a new generic PHY framework implementation. See 0ace7fe60d5c258324ef4b2caaa556616b96d1d9 drivers: phy: add generic PHY framework
And why do you need to iterate over indexes ? Why don't you just parse a phandle ?
As for clocks or resets, in case there is more than 1 phy connected.
Can that ever happen or is that hypothetical possibility ? I haven't seen EHCI hardware with multiple PHYs yet.
For EHCI, i agree, i didn't see multiple PHYs too. I will remove the loop.
Thanks
Patrice
Patrice

From: Patrice Chotard patrice.chotard@st.com
Update the compatible string in order to use ehci-generic driver instead of a STi specific one
Reverse the order of resets, due to the fact that softreset must be deasserted first.
Signed-off-by: Patrice Chotard patrice.chotard@st.com ---
v5: _ update compatible and reset order to fit with ehci_generic driver
arch/arm/dts/stih410.dtsi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/arm/dts/stih410.dtsi b/arch/arm/dts/stih410.dtsi index f118a9e..9997396 100644 --- a/arch/arm/dts/stih410.dtsi +++ b/arch/arm/dts/stih410.dtsi @@ -98,15 +98,15 @@ };
ehci0: usb@9a03e00 { - compatible = "st,st-ehci-300x"; + compatible = "generic-ehci"; reg = <0x9a03e00 0x100>; interrupts = <GIC_SPI 151 IRQ_TYPE_NONE>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usb0>; clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>, <&clk_s_c0_flexgen CLK_RX_ICN_DISP_0>; - resets = <&powerdown STIH407_USB2_PORT0_POWERDOWN>, - <&softreset STIH407_USB2_PORT0_SOFTRESET>; + resets = <&softreset STIH407_USB2_PORT0_SOFTRESET>, + <&powerdown STIH407_USB2_PORT0_POWERDOWN>; reset-names = "power", "softreset"; phys = <&usb2_picophy1>; phy-names = "usb"; @@ -130,15 +130,15 @@ };
ehci1: usb@9a83e00 { - compatible = "st,st-ehci-300x"; + compatible = "generic-ehci"; reg = <0x9a83e00 0x100>; interrupts = <GIC_SPI 153 IRQ_TYPE_NONE>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usb1>; clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>, <&clk_s_c0_flexgen CLK_RX_ICN_DISP_0>; - resets = <&powerdown STIH407_USB2_PORT1_POWERDOWN>, - <&softreset STIH407_USB2_PORT1_SOFTRESET>; + resets = <&softreset STIH407_USB2_PORT1_SOFTRESET>, + <&powerdown STIH407_USB2_PORT1_POWERDOWN>; reset-names = "power", "softreset"; phys = <&usb2_picophy2>; phy-names = "usb";

On 10 May 2017 at 10:09, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Update the compatible string in order to use ehci-generic driver instead of a STi specific one
Reverse the order of resets, due to the fact that softreset must be deasserted first.
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ update compatible and reset order to fit with ehci_generic driver
arch/arm/dts/stih410.dtsi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

From: Patrice Chotard patrice.chotard@st.com
Make this driver more generic as echi-generic
Signed-off-by: Patrice Chotard patrice.chotard@st.com ---
v5: _ add clock, reset and generic phy support
drivers/usb/host/ohci-generic.c | 48 +++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c index f3307f4..33e8095 100644 --- a/drivers/usb/host/ohci-generic.c +++ b/drivers/usb/host/ohci-generic.c @@ -5,7 +5,12 @@ */
#include <common.h> +#include <clk.h> #include <dm.h> +#include <fdtdec.h> +#include <generic-phy.h> +#include <reset.h> + #include "ohci.h"
#if !defined(CONFIG_USB_OHCI_NEW) @@ -19,13 +24,44 @@ struct generic_ohci { static int ohci_usb_probe(struct udevice *dev) { struct ohci_regs *regs = (struct ohci_regs *)dev_get_addr(dev); + int i;
- return ohci_register(dev, regs); -} + for (i = 0; ; i++) { + struct clk clk; + int ret;
-static int ohci_usb_remove(struct udevice *dev) -{ - return ohci_deregister(dev); + ret = clk_get_by_index(dev, i, &clk); + if (ret < 0) + break; + if (clk_enable(&clk)) + printf("failed to enable clock %d\n", i); + clk_free(&clk); + } + + for (i = 0; ; i++) { + struct reset_ctl reset; + int ret; + + ret = reset_get_by_index(dev, i, &reset); + if (ret < 0) + break; + if (reset_deassert(&reset)) + printf("failed to deassert reset %d\n", i); + reset_free(&reset); + } + + for (i = 0; ; i++) { + struct phy usb_phy; + int ret; + + ret = generic_phy_get_by_index(dev, i, &usb_phy); + if (ret < 0) + break; + if (generic_phy_init(&usb_phy)) + printf("failed to init usb phy %d\n", i); + } + + return ohci_register(dev, regs); }
static const struct udevice_id ohci_usb_ids[] = { @@ -38,7 +74,7 @@ U_BOOT_DRIVER(ohci_generic) = { .id = UCLASS_USB, .of_match = ohci_usb_ids, .probe = ohci_usb_probe, - .remove = ohci_usb_remove, + .remove = ohci_deregister, .ops = &ohci_usb_ops, .priv_auto_alloc_size = sizeof(struct generic_ohci), .flags = DM_FLAG_ALLOC_PRIV_DMA,

On 05/10/2017 06:09 PM, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Make this driver more generic as echi-generic
EHCI , although the typo is kinda funny .
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ add clock, reset and generic phy support
drivers/usb/host/ohci-generic.c | 48 +++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c index f3307f4..33e8095 100644 --- a/drivers/usb/host/ohci-generic.c +++ b/drivers/usb/host/ohci-generic.c @@ -5,7 +5,12 @@ */
#include <common.h> +#include <clk.h> #include <dm.h> +#include <fdtdec.h> +#include <generic-phy.h> +#include <reset.h>
#include "ohci.h"
#if !defined(CONFIG_USB_OHCI_NEW) @@ -19,13 +24,44 @@ struct generic_ohci { static int ohci_usb_probe(struct udevice *dev) { struct ohci_regs *regs = (struct ohci_regs *)dev_get_addr(dev);
- int i;
- return ohci_register(dev, regs);
-}
- for (i = 0; ; i++) {
struct clk clk;
int ret;
-static int ohci_usb_remove(struct udevice *dev) -{
- return ohci_deregister(dev);
ret = clk_get_by_index(dev, i, &clk);
if (ret < 0)
break;
if (clk_enable(&clk))
printf("failed to enable clock %d\n", i);
clk_free(&clk);
- }
- for (i = 0; ; i++) {
struct reset_ctl reset;
int ret;
ret = reset_get_by_index(dev, i, &reset);
if (ret < 0)
break;
if (reset_deassert(&reset))
printf("failed to deassert reset %d\n", i);
You should look up the resets and clock and whatnot by phandle .
reset_free(&reset);
- }
- for (i = 0; ; i++) {
struct phy usb_phy;
int ret;
ret = generic_phy_get_by_index(dev, i, &usb_phy);
if (ret < 0)
break;
if (generic_phy_init(&usb_phy))
printf("failed to init usb phy %d\n", i);
- }
- return ohci_register(dev, regs);
}
static const struct udevice_id ohci_usb_ids[] = { @@ -38,7 +74,7 @@ U_BOOT_DRIVER(ohci_generic) = { .id = UCLASS_USB, .of_match = ohci_usb_ids, .probe = ohci_usb_probe,
- .remove = ohci_usb_remove,
- .remove = ohci_deregister, .ops = &ohci_usb_ops, .priv_auto_alloc_size = sizeof(struct generic_ohci), .flags = DM_FLAG_ALLOC_PRIV_DMA,

Hi Marek
On 05/10/2017 11:20 PM, Marek Vasut wrote:
On 05/10/2017 06:09 PM, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Make this driver more generic as echi-generic
EHCI , although the typo is kinda funny .
ok i will fix it
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ add clock, reset and generic phy support
drivers/usb/host/ohci-generic.c | 48 +++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c index f3307f4..33e8095 100644 --- a/drivers/usb/host/ohci-generic.c +++ b/drivers/usb/host/ohci-generic.c @@ -5,7 +5,12 @@ */
#include <common.h> +#include <clk.h> #include <dm.h> +#include <fdtdec.h> +#include <generic-phy.h> +#include <reset.h>
#include "ohci.h"
#if !defined(CONFIG_USB_OHCI_NEW) @@ -19,13 +24,44 @@ struct generic_ohci { static int ohci_usb_probe(struct udevice *dev) { struct ohci_regs *regs = (struct ohci_regs *)dev_get_addr(dev);
- int i;
- return ohci_register(dev, regs);
-}
- for (i = 0; ; i++) {
struct clk clk;
int ret;
-static int ohci_usb_remove(struct udevice *dev) -{
- return ohci_deregister(dev);
ret = clk_get_by_index(dev, i, &clk);
if (ret < 0)
break;
if (clk_enable(&clk))
printf("failed to enable clock %d\n", i);
clk_free(&clk);
- }
- for (i = 0; ; i++) {
struct reset_ctl reset;
int ret;
ret = reset_get_by_index(dev, i, &reset);
if (ret < 0)
break;
if (reset_deassert(&reset))
printf("failed to deassert reset %d\n", i);
You should look up the resets and clock and whatnot by phandle .
Sorry, i didn't understand what you mean.
If you have a look at clk_get_by_index(), reset_get_by_index() and generic_phy_get_by_index() implementations, these functions already looks up respectively to clock, reset and phy through phandle.
Patrice
reset_free(&reset);
- }
- for (i = 0; ; i++) {
struct phy usb_phy;
int ret;
ret = generic_phy_get_by_index(dev, i, &usb_phy);
if (ret < 0)
break;
if (generic_phy_init(&usb_phy))
printf("failed to init usb phy %d\n", i);
- }
- return ohci_register(dev, regs);
}
static const struct udevice_id ohci_usb_ids[] = { @@ -38,7 +74,7 @@ U_BOOT_DRIVER(ohci_generic) = { .id = UCLASS_USB, .of_match = ohci_usb_ids, .probe = ohci_usb_probe,
- .remove = ohci_usb_remove,
- .remove = ohci_deregister, .ops = &ohci_usb_ops, .priv_auto_alloc_size = sizeof(struct generic_ohci), .flags = DM_FLAG_ALLOC_PRIV_DMA,

On 10 May 2017 at 10:09, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Make this driver more generic as echi-generic
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ add clock, reset and generic phy support
drivers/usb/host/ohci-generic.c | 48 +++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c index f3307f4..33e8095 100644 --- a/drivers/usb/host/ohci-generic.c +++ b/drivers/usb/host/ohci-generic.c @@ -5,7 +5,12 @@ */
#include <common.h> +#include <clk.h> #include <dm.h> +#include <fdtdec.h> +#include <generic-phy.h> +#include <reset.h>
#include "ohci.h"
#if !defined(CONFIG_USB_OHCI_NEW) @@ -19,13 +24,44 @@ struct generic_ohci { static int ohci_usb_probe(struct udevice *dev) { struct ohci_regs *regs = (struct ohci_regs *)dev_get_addr(dev);
int i;
return ohci_register(dev, regs);
-}
for (i = 0; ; i++) {
struct clk clk;
int ret;
-static int ohci_usb_remove(struct udevice *dev) -{
return ohci_deregister(dev);
ret = clk_get_by_index(dev, i, &clk);
if (ret < 0)
break;
if (clk_enable(&clk))
printf("failed to enable clock %d\n", i);
clk_free(&clk);
}
Don't you want to store these clocks in your private data so you can disable them at the end?
for (i = 0; ; i++) {
struct reset_ctl reset;
int ret;
ret = reset_get_by_index(dev, i, &reset);
if (ret < 0)
break;
if (reset_deassert(&reset))
printf("failed to deassert reset %d\n", i);
reset_free(&reset);
}
for (i = 0; ; i++) {
struct phy usb_phy;
int ret;
ret = generic_phy_get_by_index(dev, i, &usb_phy);
if (ret < 0)
break;
if (generic_phy_init(&usb_phy))
printf("failed to init usb phy %d\n", i);
}
return ohci_register(dev, regs);
}
static const struct udevice_id ohci_usb_ids[] = { @@ -38,7 +74,7 @@ U_BOOT_DRIVER(ohci_generic) = { .id = UCLASS_USB, .of_match = ohci_usb_ids, .probe = ohci_usb_probe,
.remove = ohci_usb_remove,
.remove = ohci_deregister, .ops = &ohci_usb_ops, .priv_auto_alloc_size = sizeof(struct generic_ohci), .flags = DM_FLAG_ALLOC_PRIV_DMA,
-- 1.9.1
Regards, Simon

Hi Simon
On 05/14/2017 11:13 AM, Simon Glass wrote:
On 10 May 2017 at 10:09, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Make this driver more generic as echi-generic
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ add clock, reset and generic phy support
drivers/usb/host/ohci-generic.c | 48 +++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c index f3307f4..33e8095 100644 --- a/drivers/usb/host/ohci-generic.c +++ b/drivers/usb/host/ohci-generic.c @@ -5,7 +5,12 @@ */
#include <common.h> +#include <clk.h> #include <dm.h> +#include <fdtdec.h> +#include <generic-phy.h> +#include <reset.h>
#include "ohci.h"
#if !defined(CONFIG_USB_OHCI_NEW) @@ -19,13 +24,44 @@ struct generic_ohci { static int ohci_usb_probe(struct udevice *dev) { struct ohci_regs *regs = (struct ohci_regs *)dev_get_addr(dev);
int i;
return ohci_register(dev, regs);
-}
for (i = 0; ; i++) {
struct clk clk;
int ret;
-static int ohci_usb_remove(struct udevice *dev) -{
return ohci_deregister(dev);
ret = clk_get_by_index(dev, i, &clk);
if (ret < 0)
break;
if (clk_enable(&clk))
printf("failed to enable clock %d\n", i);
clk_free(&clk);
}
Don't you want to store these clocks in your private data so you can disable them at the end?
Marek made me similar remark, i already submitted a v2 implemented this.
Thanks
Patrice
for (i = 0; ; i++) {
struct reset_ctl reset;
int ret;
ret = reset_get_by_index(dev, i, &reset);
if (ret < 0)
break;
if (reset_deassert(&reset))
printf("failed to deassert reset %d\n", i);
reset_free(&reset);
}
for (i = 0; ; i++) {
struct phy usb_phy;
int ret;
ret = generic_phy_get_by_index(dev, i, &usb_phy);
if (ret < 0)
break;
if (generic_phy_init(&usb_phy))
printf("failed to init usb phy %d\n", i);
}
return ohci_register(dev, regs);
}
static const struct udevice_id ohci_usb_ids[] = { @@ -38,7 +74,7 @@ U_BOOT_DRIVER(ohci_generic) = { .id = UCLASS_USB, .of_match = ohci_usb_ids, .probe = ohci_usb_probe,
.remove = ohci_usb_remove,
.remove = ohci_deregister, .ops = &ohci_usb_ops, .priv_auto_alloc_size = sizeof(struct generic_ohci), .flags = DM_FLAG_ALLOC_PRIV_DMA,
-- 1.9.1
Regards, Simon

From: Patrice Chotard patrice.chotard@st.com
Update the compatible string in order to use ehci-generic driver instead of a STi specific one
Signed-off-by: Patrice Chotard patrice.chotard@st.com ---
v5: _ update compatible to fit with ohci-generic driver
arch/arm/dts/stih410.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/dts/stih410.dtsi b/arch/arm/dts/stih410.dtsi index 9997396..7c0e0fb 100644 --- a/arch/arm/dts/stih410.dtsi +++ b/arch/arm/dts/stih410.dtsi @@ -83,7 +83,7 @@ };
ohci0: usb@9a03c00 { - compatible = "st,st-ohci-300x"; + compatible = "generic-ohci"; reg = <0x9a03c00 0x100>; interrupts = <GIC_SPI 180 IRQ_TYPE_NONE>; clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>, @@ -115,7 +115,7 @@ };
ohci1: usb@9a83c00 { - compatible = "st,st-ohci-300x"; + compatible = "generic-ohci"; reg = <0x9a83c00 0x100>; interrupts = <GIC_SPI 181 IRQ_TYPE_NONE>; clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>,

On 10 May 2017 at 10:09, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Update the compatible string in order to use ehci-generic driver instead of a STi specific one
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ update compatible to fit with ohci-generic driver
arch/arm/dts/stih410.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com --- v5: _ remove CONFIG_USB_OHCI_STI and CONFIG_USB_EHCI_STI _ enable CONFIG_USB_EHCI_GENERIC and CONFIG_USB_OHCI_GENERIC
v4: _ enable CONFIG_PHY and CONFIG_STI_USB_PHY
v3: _ none
v2: _ none
configs/stih410-b2260_defconfig | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-)
diff --git a/configs/stih410-b2260_defconfig b/configs/stih410-b2260_defconfig index 4e6942f..cb17578 100644 --- a/configs/stih410-b2260_defconfig +++ b/configs/stih410-b2260_defconfig @@ -2,25 +2,55 @@ CONFIG_ARM=y CONFIG_ARCH_STI=y CONFIG_IDENT_STRING="STMicroelectronics STiH410-B2260" CONFIG_DEFAULT_DEVICE_TREE="stih410-b2260" +CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT=y CONFIG_FIT_VERBOSE=y # CONFIG_DISPLAY_CPUINFO is not set CONFIG_SYS_PROMPT="stih410-b2260 => " +CONFIG_FASTBOOT=y +CONFIG_USB_FUNCTION_FASTBOOT=y +CONFIG_CMD_FASTBOOT=y +CONFIG_ANDROID_BOOT_IMAGE=y +CONFIG_FASTBOOT_BUF_ADDR=0x40000000 +CONFIG_FASTBOOT_BUF_SIZE=0x3DF00000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 # CONFIG_CMD_IMLS is not set +CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y +CONFIG_CMD_USB=y CONFIG_CMD_TIME=y CONFIG_CMD_TIMER=y -CONFIG_CMD_EXT2=y -CONFIG_CMD_EXT4=y -CONFIG_CMD_FAT=y -CONFIG_CMD_FS_GENERIC=y +CONFIG_CMD_EXT4_WRITE=y +# CONFIG_ISO_PARTITION is not set CONFIG_OF_CONTROL=y CONFIG_REGMAP=y CONFIG_SYSCON=y +CONFIG_MISC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_STI=y +CONFIG_PHY=y +CONFIG_STI_USB_PHY=y CONFIG_PINCTRL=y +CONFIG_STI_RESET=y CONFIG_STI_ASC_SERIAL=y CONFIG_SYSRESET=y CONFIG_TIMER=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_DWC3=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_GENERIC=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_GADGET=y +CONFIG_USB_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_G_DNL_MANUFACTURER="STMicroelectronics" +CONFIG_G_DNL_VENDOR_NUM=0x483 +CONFIG_G_DNL_PRODUCT_NUM=0x7270 +CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_SPL_OF_LIBFDT=y

On 10 May 2017 at 10:09, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v5: _ remove CONFIG_USB_OHCI_STI and CONFIG_USB_EHCI_STI _ enable CONFIG_USB_EHCI_GENERIC and CONFIG_USB_OHCI_GENERIC
v4: _ enable CONFIG_PHY and CONFIG_STI_USB_PHY
v3: _ none
v2: _ none
configs/stih410-b2260_defconfig | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
participants (4)
-
Marek Vasut
-
Patrice CHOTARD
-
patrice.chotard@st.com
-
Simon Glass