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

From: Patrice Chotard patrice.chotard@st.com
This series adds : _ add reset driver _ 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 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): reset: Add STi reset support 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 phy: Add STi phy usb support usb: ehci: Add STi ehci support usb: ohci: Add STi ohci support board: STiH410-B2260: add OHCI related defines usb: xhci: Add STi xhci support board: STiH410-B2260: add XHCI related define usb: dwc3: Add dwc3 support for STi board: STiH410-B2260: add fastboot support STiH410-B2260: enable USB Host Networking STiH410-B2260: enable USB, fastboot, reset related flags
arch/arm/Kconfig | 1 + arch/arm/dts/stih407-family.dtsi | 1 + arch/arm/include/asm/arch-stih410/sys_proto.h | 11 + board/st/stih410-b2260/board.c | 44 ++++ configs/stih410-b2260_defconfig | 36 ++- drivers/mmc/sti_sdhci.c | 60 +++-- drivers/reset/Kconfig | 8 + drivers/reset/Makefile | 1 + drivers/reset/sti-reset.c | 320 ++++++++++++++++++++++++++ drivers/usb/Kconfig | 4 + drivers/usb/dwc3/Kconfig | 8 + drivers/usb/dwc3/Makefile | 1 + drivers/usb/dwc3/dwc3-sti.c | 135 +++++++++++ drivers/usb/host/Kconfig | 26 +++ drivers/usb/host/Makefile | 3 + drivers/usb/host/ehci-sti.c | 115 +++++++++ drivers/usb/host/ohci-sti.c | 90 ++++++++ drivers/usb/host/xhci-sti.c | 156 +++++++++++++ drivers/usb/phy/Kconfig | 11 + drivers/usb/phy/Makefile | 1 + drivers/usb/phy/sti_phy_usb.c | 153 ++++++++++++ include/configs/stih410-b2260.h | 16 ++ include/dwc3-sti-uboot.h | 50 ++++ 23 files changed, 1225 insertions(+), 26 deletions(-) create mode 100644 arch/arm/include/asm/arch-stih410/sys_proto.h create mode 100644 drivers/reset/sti-reset.c create mode 100644 drivers/usb/dwc3/dwc3-sti.c create mode 100644 drivers/usb/host/ehci-sti.c create mode 100644 drivers/usb/host/ohci-sti.c create mode 100644 drivers/usb/host/xhci-sti.c create mode 100644 drivers/usb/phy/Kconfig create mode 100644 drivers/usb/phy/sti_phy_usb.c create mode 100644 include/dwc3-sti-uboot.h

From: Patrice Chotard patrice.chotard@st.com
This patch adds a reset controller implementation for STMicroelectronics STi family SoCs; it allows a group of related reset like controls found in multiple system configuration registers to be represented by a single controller device.
Driver code has been mainly extracted from kernel drivers/reset/sti/reset-stih407.c
Signed-off-by: Patrice Chotard patrice.chotard@st.com --- arch/arm/Kconfig | 1 + drivers/reset/Kconfig | 8 ++ drivers/reset/Makefile | 1 + drivers/reset/sti-reset.c | 320 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 330 insertions(+) create mode 100644 drivers/reset/sti-reset.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 20434dc..af5157e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1100,6 +1100,7 @@ config ARCH_STI select DM_SERIAL select BLK select DM_MMC + select DM_RESET help Support for STMicroelectronics STiH407/10 SoC family. This SoC is used on Linaro 96Board STiH410-B2260 diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index c42b0bc..fa77ee4 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -20,6 +20,14 @@ config SANDBOX_RESET simply accepts requests to reset various HW modules without actually doing anything beyond a little error checking.
+config STI_RESET + bool "Enable the STi reset" + depends on ARCH_STI + help + Support for reset controllers on STMicroelectronics STiH407 family SoCs. + Say Y if you want to control reset signals provided by system config + block. + config TEGRA_CAR_RESET bool "Enable Tegra CAR-based reset driver" depends on TEGRA_CAR diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 5c4305c..2b96396 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_DM_RESET) += reset-uclass.o obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset.o obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset-test.o +obj-$(CONFIG_STI_RESET) += sti-reset.o obj-$(CONFIG_TEGRA_CAR_RESET) += tegra-car-reset.o obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o diff --git a/drivers/reset/sti-reset.c b/drivers/reset/sti-reset.c new file mode 100644 index 0000000..0c32a3d --- /dev/null +++ b/drivers/reset/sti-reset.c @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2017 + * Patrice Chotard patrice.chotard@st.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <errno.h> +#include <wait_bit.h> +#include <dm.h> +#include <reset-uclass.h> +#include <regmap.h> +#include <syscon.h> +#include <dt-bindings/reset/stih407-resets.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct sti_reset { + const struct syscfg_reset_controller_data *data; +}; + +/** + * Reset channel description for a system configuration register based + * reset controller. + * + * @compatible: Compatible string of the syscon containing this + * channel's control and ack (status) bits. + * @reset_offset: Reset register offset in sysconf bank. + * @reset_bit: Bit number in reset register. + * @ack_offset: Ack reset register offset in syscon bank. + * @ack_bit: Bit number in Ack reset register. + */ + +struct syscfg_reset_channel_data { + const char *compatible; + int reset_offset; + int reset_bit; + int ack_offset; + int ack_bit; +}; + +/** + * Description of a system configuration register based reset controller. + * + * @wait_for_ack: The controller will wait for reset assert and de-assert to + * be "ack'd" in a channel's ack field. + * @active_low: Are the resets in this controller active low, i.e. clearing + * the reset bit puts the hardware into reset. + * @nr_channels: The number of reset channels in this controller. + * @channels: An array of reset channel descriptions. + */ +struct syscfg_reset_controller_data { + bool wait_for_ack; + bool active_low; + int nr_channels; + const struct syscfg_reset_channel_data *channels; +}; + +/* STiH407 Peripheral powerdown definitions. */ +static const char stih407_core[] = "st,stih407-core-syscfg"; +static const char stih407_sbc_reg[] = "st,stih407-sbc-reg-syscfg"; +static const char stih407_lpm[] = "st,stih407-lpm-syscfg"; + +#define _SYSCFG_RST_CH(_c, _rr, _rb, _ar, _ab) \ + { .compatible = _c, \ + .reset_offset = _rr, \ + .reset_bit = _rb, \ + .ack_offset = _ar, \ + .ack_bit = _ab, } + +#define _SYSCFG_RST_CH_NO_ACK(_c, _rr, _rb) \ + { .compatible = _c, \ + .reset_offset = _rr, \ + .reset_bit = _rb, } + +#define STIH407_SRST_CORE(_reg, _bit) \ + _SYSCFG_RST_CH_NO_ACK(stih407_core, _reg, _bit) + +#define STIH407_SRST_SBC(_reg, _bit) \ + _SYSCFG_RST_CH_NO_ACK(stih407_sbc_reg, _reg, _bit) + +#define STIH407_SRST_LPM(_reg, _bit) \ + _SYSCFG_RST_CH_NO_ACK(stih407_lpm, _reg, _bit) + +#define STIH407_PDN_0(_bit) \ + _SYSCFG_RST_CH(stih407_core, SYSCFG_5000, _bit, SYSSTAT_5500, _bit) +#define STIH407_PDN_1(_bit) \ + _SYSCFG_RST_CH(stih407_core, SYSCFG_5001, _bit, SYSSTAT_5501, _bit) +#define STIH407_PDN_ETH(_bit, _stat) \ + _SYSCFG_RST_CH(stih407_sbc_reg, SYSCFG_4032, _bit, SYSSTAT_4520, _stat) + +/* Powerdown requests control 0 */ +#define SYSCFG_5000 0x0 +#define SYSSTAT_5500 0x7d0 +/* Powerdown requests control 1 (High Speed Links) */ +#define SYSCFG_5001 0x4 +#define SYSSTAT_5501 0x7d4 + +/* Ethernet powerdown/status/reset */ +#define SYSCFG_4032 0x80 +#define SYSSTAT_4520 0x820 +#define SYSCFG_4002 0x8 + +static const struct syscfg_reset_channel_data stih407_powerdowns[] = { + [STIH407_EMISS_POWERDOWN] = STIH407_PDN_0(1), + [STIH407_NAND_POWERDOWN] = STIH407_PDN_0(0), + [STIH407_USB3_POWERDOWN] = STIH407_PDN_1(6), + [STIH407_USB2_PORT1_POWERDOWN] = STIH407_PDN_1(5), + [STIH407_USB2_PORT0_POWERDOWN] = STIH407_PDN_1(4), + [STIH407_PCIE1_POWERDOWN] = STIH407_PDN_1(3), + [STIH407_PCIE0_POWERDOWN] = STIH407_PDN_1(2), + [STIH407_SATA1_POWERDOWN] = STIH407_PDN_1(1), + [STIH407_SATA0_POWERDOWN] = STIH407_PDN_1(0), + [STIH407_ETH1_POWERDOWN] = STIH407_PDN_ETH(0, 2), +}; + +/* Reset Generator control 0/1 */ +#define SYSCFG_5128 0x200 +#define SYSCFG_5131 0x20c +#define SYSCFG_5132 0x210 + +#define LPM_SYSCFG_1 0x4 /* Softreset IRB & SBC UART */ + +static const struct syscfg_reset_channel_data stih407_softresets[] = { + [STIH407_ETH1_SOFTRESET] = STIH407_SRST_SBC(SYSCFG_4002, 4), + [STIH407_MMC1_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 3), + [STIH407_USB2_PORT0_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 28), + [STIH407_USB2_PORT1_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 29), + [STIH407_PICOPHY_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 30), + [STIH407_IRB_SOFTRESET] = STIH407_SRST_LPM(LPM_SYSCFG_1, 6), + [STIH407_PCIE0_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 6), + [STIH407_PCIE1_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 15), + [STIH407_SATA0_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 7), + [STIH407_SATA1_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 16), + [STIH407_MIPHY0_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 4), + [STIH407_MIPHY1_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 13), + [STIH407_MIPHY2_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 22), + [STIH407_SATA0_PWR_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 5), + [STIH407_SATA1_PWR_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 14), + [STIH407_DELTA_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 3), + [STIH407_BLITTER_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 10), + [STIH407_HDTVOUT_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 11), + [STIH407_HDQVDP_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 12), + [STIH407_VDP_AUX_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 14), + [STIH407_COMPO_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 15), + [STIH407_HDMI_TX_PHY_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 21), + [STIH407_JPEG_DEC_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 23), + [STIH407_VP8_DEC_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 24), + [STIH407_GPU_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 30), + [STIH407_HVA_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 0), + [STIH407_ERAM_HVA_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 1), + [STIH407_LPM_SOFTRESET] = STIH407_SRST_SBC(SYSCFG_4002, 2), + [STIH407_KEYSCAN_SOFTRESET] = STIH407_SRST_LPM(LPM_SYSCFG_1, 8), + [STIH407_ST231_AUD_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 26), + [STIH407_ST231_DMU_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 27), + [STIH407_ST231_GP0_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 28), + [STIH407_ST231_GP1_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5128, 2), +}; + +/* PicoPHY reset/control */ +#define SYSCFG_5061 0x0f4 + +static const struct syscfg_reset_channel_data stih407_picophyresets[] = { + [STIH407_PICOPHY0_RESET] = STIH407_SRST_CORE(SYSCFG_5061, 5), + [STIH407_PICOPHY1_RESET] = STIH407_SRST_CORE(SYSCFG_5061, 6), + [STIH407_PICOPHY2_RESET] = STIH407_SRST_CORE(SYSCFG_5061, 7), +}; + +static const struct +syscfg_reset_controller_data stih407_powerdown_controller = { + .wait_for_ack = true, + .nr_channels = ARRAY_SIZE(stih407_powerdowns), + .channels = stih407_powerdowns, +}; + +static const struct +syscfg_reset_controller_data stih407_softreset_controller = { + .wait_for_ack = false, + .active_low = true, + .nr_channels = ARRAY_SIZE(stih407_softresets), + .channels = stih407_softresets, +}; + +static const struct +syscfg_reset_controller_data stih407_picophyreset_controller = { + .wait_for_ack = false, + .nr_channels = ARRAY_SIZE(stih407_picophyresets), + .channels = stih407_picophyresets, +}; + +phys_addr_t sti_reset_get_regmap(const char *compatible) +{ + struct udevice *syscon; + struct regmap *regmap; + int node, ret; + + node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, + compatible); + if (node < 0) { + error("unable to find %s node\n", compatible); + return node; + } + + ret = uclass_get_device_by_of_offset(UCLASS_SYSCON, node, &syscon); + if (ret) { + error("%s: uclass_get_device_by_of_offset failed: %d\n", + __func__, ret); + return ret; + } + + regmap = syscon_get_regmap(syscon); + if (!regmap) { + error("unable to get regmap for %s\n", syscon->name); + return -ENODEV; + } + + return regmap->base; +} + +static int sti_reset_program_hw(struct reset_ctl *reset_ctl, int assert) +{ + struct udevice *dev = reset_ctl->dev; + struct syscfg_reset_controller_data *reset_desc = + (struct syscfg_reset_controller_data *)(dev->driver_data); + struct syscfg_reset_channel_data ch; + phys_addr_t base; + u32 ctrl_val = reset_desc->active_low ? !assert : !!assert; + void __iomem *reg; + + /* check if reset id is inside available range */ + if (reset_ctl->id >= reset_desc->nr_channels) + return -EINVAL; + + /* get reset sysconf register base address */ + base = sti_reset_get_regmap(reset_desc->channels[reset_ctl->id].compatible); + + ch = reset_desc->channels[reset_ctl->id]; + reg = (void __iomem *)base + ch.reset_offset; + + if (ctrl_val) + generic_set_bit(ch.reset_bit, reg); + else + generic_clear_bit(ch.reset_bit, reg); + + if (!reset_desc->wait_for_ack) + return 0; + + reg = (void __iomem *)base + ch.ack_offset; + if (wait_for_bit(__func__, reg, BIT(ch.ack_bit), ctrl_val, + 1000, false)) { + error("Stuck on waiting ack reset_ctl=%p dev=%p id=%lu\n", + reset_ctl, reset_ctl->dev, reset_ctl->id); + + return -ETIMEDOUT; + } + + return 0; +} + +static int sti_reset_request(struct reset_ctl *reset_ctl) +{ + return 0; +} + +static int sti_reset_free(struct reset_ctl *reset_ctl) +{ + return 0; +} + +static int sti_reset_assert(struct reset_ctl *reset_ctl) +{ + return sti_reset_program_hw(reset_ctl, true); +} + +static int sti_reset_deassert(struct reset_ctl *reset_ctl) +{ + return sti_reset_program_hw(reset_ctl, false); +} + +struct reset_ops sti_reset_ops = { + .request = sti_reset_request, + .free = sti_reset_free, + .rst_assert = sti_reset_assert, + .rst_deassert = sti_reset_deassert, +}; + +static int sti_reset_probe(struct udevice *dev) +{ + struct sti_reset *priv = dev_get_priv(dev); + + priv->data = (void *)dev_get_driver_data(dev); + + return 0; +} + +static const struct udevice_id sti_reset_ids[] = { + { + .compatible = "st,stih407-picophyreset", + .data = (ulong)&stih407_picophyreset_controller, + }, + { + .compatible = "st,stih407-powerdown", + .data = (ulong)&stih407_powerdown_controller, + }, + { + .compatible = "st,stih407-softreset", + .data = (ulong)&stih407_softreset_controller, + }, + { } +}; + +U_BOOT_DRIVER(sti_reset) = { + .name = "sti_reset", + .id = UCLASS_RESET, + .of_match = sti_reset_ids, + .probe = sti_reset_probe, + .priv_auto_alloc_size = sizeof(struct sti_reset), + .ops = &sti_reset_ops, +};

On 22 March 2017 at 03:54, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
This patch adds a reset controller implementation for STMicroelectronics STi family SoCs; it allows a group of related reset like controls found in multiple system configuration registers to be represented by a single controller device.
Driver code has been mainly extracted from kernel drivers/reset/sti/reset-stih407.c
Signed-off-by: Patrice Chotard patrice.chotard@st.com
arch/arm/Kconfig | 1 + drivers/reset/Kconfig | 8 ++ drivers/reset/Makefile | 1 + drivers/reset/sti-reset.c | 320 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 330 insertions(+) create mode 100644 drivers/reset/sti-reset.c
Applied to u-boot-dm, thanks!

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 --- 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 |

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 --- 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>; };

From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com Reviewed-by: Jaehoon Chung jh80.chung@samsung.com --- 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 |

From: Patrice Chotard patrice.chotard@st.com
This is the generic phy driver for the picoPHY ports used by USB2 and USB3 Host controllers available on STiH407 SoC families.
Signed-off-by: Patrice Chotard patrice.chotard@st.com ---
v2: replace bitfield_replace() by clrsetbits_le32()
configs/stih410-b2260_defconfig | 1 + drivers/usb/Kconfig | 4 ++ drivers/usb/phy/Kconfig | 11 +++ drivers/usb/phy/Makefile | 1 + drivers/usb/phy/sti_phy_usb.c | 153 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 170 insertions(+) create mode 100644 drivers/usb/phy/Kconfig create mode 100644 drivers/usb/phy/sti_phy_usb.c
diff --git a/configs/stih410-b2260_defconfig b/configs/stih410-b2260_defconfig index 4e6942f..d3cfdca 100644 --- a/configs/stih410-b2260_defconfig +++ b/configs/stih410-b2260_defconfig @@ -17,6 +17,7 @@ CONFIG_CMD_FS_GENERIC=y CONFIG_OF_CONTROL=y CONFIG_REGMAP=y CONFIG_SYSCON=y +CONFIG_MISC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_STI=y CONFIG_PINCTRL=y diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index da3ec2f..e30c9d6 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -94,4 +94,8 @@ endif
source "drivers/usb/gadget/Kconfig"
+comment "USB PHY" + +source "drivers/usb/phy/Kconfig" + endif diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig new file mode 100644 index 0000000..1a86c6e --- /dev/null +++ b/drivers/usb/phy/Kconfig @@ -0,0 +1,11 @@ +menu "USB PHY drivers" + +config STI_PHY_USB + bool "STMicroelectronics USB2 picoPHY driver for STiH407 family" + default n + 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/usb/phy/Makefile b/drivers/usb/phy/Makefile index 4e548c2..b50fb5a 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_TWL4030_USB) += twl4030.o obj-$(CONFIG_OMAP_USB_PHY) += omap_usb_phy.o obj-$(CONFIG_ROCKCHIP_USB2_PHY) += rockchip_usb2_phy.o +obj-$(CONFIG_STI_PHY_USB) += sti_phy_usb.o diff --git a/drivers/usb/phy/sti_phy_usb.c b/drivers/usb/phy/sti_phy_usb.c new file mode 100644 index 0000000..59b0b47 --- /dev/null +++ b/drivers/usb/phy/sti_phy_usb.c @@ -0,0 +1,153 @@ +/* + * 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 <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_phy_usb { + struct regmap *regmap; + struct reset_ctl global_ctl; + struct reset_ctl port_ctl; + int param; + int ctrl; +}; + +static int sti_phy_usb_deassert(struct sti_phy_usb *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 void sti_phy_usb_init(struct sti_phy_usb *phy) +{ + 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); +} + +int sti_phy_usb_probe(struct udevice *dev) +{ + struct sti_phy_usb *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; + } + + sti_phy_usb_init(priv); + + return sti_phy_usb_deassert(priv); +} + +static const struct udevice_id sti_phy_usb_ids[] = { + { .compatible = "st,stih407-usb2-phy" }, + { } +}; + +U_BOOT_DRIVER(sti_phy_usb) = { + .name = "sti_phy_usb", + .id = UCLASS_MISC, + .of_match = sti_phy_usb_ids, + .probe = sti_phy_usb_probe, + .priv_auto_alloc_size = sizeof(struct sti_phy_usb), +};

From: Patrice Chotard patrice.chotard@st.com
Add support for on-chip ehci controller available on STMicrolectronics SoCs. ehci support will be then available on both type A USB 2.0 connectors.
Signed-off-by: Patrice Chotard patrice.chotard@st.com ---
v2: _ update error messages _ add remove callback to put core into reset
drivers/usb/host/Kconfig | 9 ++++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ehci-sti.c | 115 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 drivers/usb/host/ehci-sti.c
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 5129a57..d66f49e 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -120,6 +120,15 @@ config USB_EHCI_MSM This driver supports combination of Chipidea USB controller and Synapsys USB PHY in host mode only.
+config USB_EHCI_STI + bool "Support for STMicroelectronics on-chip EHCI USB controller" + depends on ARCH_STI + select STI_PHY_USB + default y + ---help--- + Enables support for the on-chip EHCI controller on + STMicroelectronics SoCs. + config USB_EHCI_ZYNQ bool "Support for Xilinx Zynq on-chip EHCI USB controller" depends on ARCH_ZYNQ diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 58c0cf5..303aa32 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_USB_EHCI_MARVELL) += ehci-marvell.o obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o obj-$(CONFIG_USB_EHCI_SPEAR) += ehci-spear.o +obj-$(CONFIG_USB_EHCI_STI) += ehci-sti.o obj-$(CONFIG_USB_EHCI_SUNXI) += ehci-sunxi.o obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o obj-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o diff --git a/drivers/usb/host/ehci-sti.c b/drivers/usb/host/ehci-sti.c new file mode 100644 index 0000000..390709d --- /dev/null +++ b/drivers/usb/host/ehci-sti.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2017 + * Patrice Chotard patrice.chotard@st.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <dm.h> +#include <errno.h> +#include "ehci.h" +#include <reset-uclass.h> +#include <usb.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct sti_ehci_priv { + struct ehci_ctrl ctrl; + struct reset_ctl power_ctl; + struct reset_ctl softreset_ctl; +}; + +static int sti_ehci_probe(struct udevice *dev) +{ + struct sti_ehci_priv *priv = dev_get_priv(dev); + struct ehci_hccr *hccr = priv->ctrl.hccr; + struct ehci_hcor *hcor; + struct udevice *dev_phy; + int ret, phy_node; + + hccr = (struct ehci_hccr *)dev_get_addr(dev); + + if (hccr == (void *)FDT_ADDR_T_NONE) + return -EINVAL; + + ret = reset_get_by_name(dev, "power", &priv->power_ctl); + if (ret) { + error("can't get power for %s (%d)", dev->name, ret); + return ret; + } + + ret = reset_get_by_name(dev, "softreset", &priv->softreset_ctl); + if (ret) { + error("can't get soft reset for %s (%d)", dev->name, ret); + return ret; + } + + ret = reset_deassert(&priv->softreset_ctl); + if (ret < 0) { + error("EHCI soft reset deassert failed: %d", ret); + return ret; + } + + ret = reset_deassert(&priv->power_ctl); + if (ret < 0) { + error("EHCI power deassert failed: %d", ret); + return ret; + } + + /* get phy node */ + phy_node = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset, "phys"); + if (phy_node <= 0) { + error("USB PHY DT node not found.\n"); + return -ENODEV; + } + + /* probe associated phy */ + ret = uclass_get_device_by_of_offset(UCLASS_MISC, phy_node, &dev_phy); + + hcor = (struct ehci_hcor *)((phys_addr_t)hccr + + HC_LENGTH(ehci_readl(&(hccr)->cr_capbase))); + + return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST); +} + +static int sti_ehci_remove(struct udevice *dev) +{ + struct sti_ehci_priv *priv = dev_get_priv(dev); + int ret; + + ret = ehci_deregister(dev); + if (ret) + return ret; + + ret = reset_assert(&priv->power_ctl); + if (ret < 0) { + error("EHCI power assert failed: %d", ret); + return ret; + } + + ret = reset_assert(&priv->softreset_ctl); + if (ret < 0) { + error("EHCI soft reset assert failed: %d", ret); + return ret; + } + + return 0; +} + +static const struct udevice_id sti_usb_ids[] = { + { .compatible = "st,st-ehci-300x" }, + { } +}; + +U_BOOT_DRIVER(ehci_sti) = { + .name = "ehci_sti", + .id = UCLASS_USB, + .of_match = sti_usb_ids, + .probe = sti_ehci_probe, + .remove = sti_ehci_remove, + .ops = &ehci_usb_ops, + .priv_auto_alloc_size = sizeof(struct sti_ehci_priv), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +};

Hi Patrice,
On 22 March 2017 at 03:54, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Add support for on-chip ehci controller available on STMicrolectronics SoCs. ehci support will be then available on both type A USB 2.0 connectors.
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v2: _ update error messages _ add remove callback to put core into reset
drivers/usb/host/Kconfig | 9 ++++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ehci-sti.c | 115 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 drivers/usb/host/ehci-sti.c
Reviewed-by: Simon Glass sjg@chromium.org
Please see below.
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 5129a57..d66f49e 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -120,6 +120,15 @@ config USB_EHCI_MSM This driver supports combination of Chipidea USB controller and Synapsys USB PHY in host mode only.
+config USB_EHCI_STI
bool "Support for STMicroelectronics on-chip EHCI USB controller"
depends on ARCH_STI
select STI_PHY_USB
default y
---help---
Enables support for the on-chip EHCI controller on
STMicroelectronics SoCs.
config USB_EHCI_ZYNQ bool "Support for Xilinx Zynq on-chip EHCI USB controller" depends on ARCH_ZYNQ diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 58c0cf5..303aa32 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_USB_EHCI_MARVELL) += ehci-marvell.o obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o obj-$(CONFIG_USB_EHCI_SPEAR) += ehci-spear.o +obj-$(CONFIG_USB_EHCI_STI) += ehci-sti.o obj-$(CONFIG_USB_EHCI_SUNXI) += ehci-sunxi.o obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o obj-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o diff --git a/drivers/usb/host/ehci-sti.c b/drivers/usb/host/ehci-sti.c new file mode 100644 index 0000000..390709d --- /dev/null +++ b/drivers/usb/host/ehci-sti.c @@ -0,0 +1,115 @@ +/*
- Copyright (c) 2017
- Patrice Chotard patrice.chotard@st.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <asm/io.h> +#include <dm.h> +#include <errno.h> +#include "ehci.h" +#include <reset-uclass.h> +#include <usb.h>
+DECLARE_GLOBAL_DATA_PTR;
+struct sti_ehci_priv {
struct ehci_ctrl ctrl;
struct reset_ctl power_ctl;
struct reset_ctl softreset_ctl;
+};
+static int sti_ehci_probe(struct udevice *dev) +{
struct sti_ehci_priv *priv = dev_get_priv(dev);
struct ehci_hccr *hccr = priv->ctrl.hccr;
struct ehci_hcor *hcor;
struct udevice *dev_phy;
int ret, phy_node;
hccr = (struct ehci_hccr *)dev_get_addr(dev);
if (hccr == (void *)FDT_ADDR_T_NONE)
return -EINVAL;
ret = reset_get_by_name(dev, "power", &priv->power_ctl);
if (ret) {
error("can't get power for %s (%d)", dev->name, ret);
return ret;
}
ret = reset_get_by_name(dev, "softreset", &priv->softreset_ctl);
if (ret) {
error("can't get soft reset for %s (%d)", dev->name, ret);
return ret;
}
ret = reset_deassert(&priv->softreset_ctl);
if (ret < 0) {
error("EHCI soft reset deassert failed: %d", ret);
return ret;
}
ret = reset_deassert(&priv->power_ctl);
if (ret < 0) {
error("EHCI power deassert failed: %d", ret);
return ret;
}
/* get phy node */
phy_node = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset, "phys");
if (phy_node <= 0) {
error("USB PHY DT node not found.\n");
return -ENODEV;
}
/* probe associated phy */
ret = uclass_get_device_by_of_offset(UCLASS_MISC, phy_node, &dev_phy);
Is it possible to replace the above two calls with uclass_get_device_by_phandle()?
hcor = (struct ehci_hcor *)((phys_addr_t)hccr +
HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
+}
+static int sti_ehci_remove(struct udevice *dev) +{
struct sti_ehci_priv *priv = dev_get_priv(dev);
int ret;
ret = ehci_deregister(dev);
if (ret)
return ret;
ret = reset_assert(&priv->power_ctl);
if (ret < 0) {
error("EHCI power assert failed: %d", ret);
return ret;
}
ret = reset_assert(&priv->softreset_ctl);
if (ret < 0) {
error("EHCI soft reset assert failed: %d", ret);
return ret;
}
return 0;
+}
+static const struct udevice_id sti_usb_ids[] = {
{ .compatible = "st,st-ehci-300x" },
{ }
+};
+U_BOOT_DRIVER(ehci_sti) = {
.name = "ehci_sti",
.id = UCLASS_USB,
.of_match = sti_usb_ids,
.probe = sti_ehci_probe,
.remove = sti_ehci_remove,
.ops = &ehci_usb_ops,
.priv_auto_alloc_size = sizeof(struct sti_ehci_priv),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
1.9.1
Regards, Simon

Hi Simon
On 04/01/2017 06:20 AM, Simon Glass wrote:
Hi Patrice,
On 22 March 2017 at 03:54, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Add support for on-chip ehci controller available on STMicrolectronics SoCs. ehci support will be then available on both type A USB 2.0 connectors.
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v2: _ update error messages _ add remove callback to put core into reset
drivers/usb/host/Kconfig | 9 ++++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ehci-sti.c | 115 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 drivers/usb/host/ehci-sti.c
Reviewed-by: Simon Glass sjg@chromium.org
Please see below.
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 5129a57..d66f49e 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -120,6 +120,15 @@ config USB_EHCI_MSM This driver supports combination of Chipidea USB controller and Synapsys USB PHY in host mode only.
+config USB_EHCI_STI
bool "Support for STMicroelectronics on-chip EHCI USB controller"
depends on ARCH_STI
select STI_PHY_USB
default y
---help---
Enables support for the on-chip EHCI controller on
STMicroelectronics SoCs.
config USB_EHCI_ZYNQ bool "Support for Xilinx Zynq on-chip EHCI USB controller" depends on ARCH_ZYNQ diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 58c0cf5..303aa32 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_USB_EHCI_MARVELL) += ehci-marvell.o obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o obj-$(CONFIG_USB_EHCI_SPEAR) += ehci-spear.o +obj-$(CONFIG_USB_EHCI_STI) += ehci-sti.o obj-$(CONFIG_USB_EHCI_SUNXI) += ehci-sunxi.o obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o obj-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o diff --git a/drivers/usb/host/ehci-sti.c b/drivers/usb/host/ehci-sti.c new file mode 100644 index 0000000..390709d --- /dev/null +++ b/drivers/usb/host/ehci-sti.c @@ -0,0 +1,115 @@ +/*
- Copyright (c) 2017
- Patrice Chotard patrice.chotard@st.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <asm/io.h> +#include <dm.h> +#include <errno.h> +#include "ehci.h" +#include <reset-uclass.h> +#include <usb.h>
+DECLARE_GLOBAL_DATA_PTR;
+struct sti_ehci_priv {
struct ehci_ctrl ctrl;
struct reset_ctl power_ctl;
struct reset_ctl softreset_ctl;
+};
+static int sti_ehci_probe(struct udevice *dev) +{
struct sti_ehci_priv *priv = dev_get_priv(dev);
struct ehci_hccr *hccr = priv->ctrl.hccr;
struct ehci_hcor *hcor;
struct udevice *dev_phy;
int ret, phy_node;
hccr = (struct ehci_hccr *)dev_get_addr(dev);
if (hccr == (void *)FDT_ADDR_T_NONE)
return -EINVAL;
ret = reset_get_by_name(dev, "power", &priv->power_ctl);
if (ret) {
error("can't get power for %s (%d)", dev->name, ret);
return ret;
}
ret = reset_get_by_name(dev, "softreset", &priv->softreset_ctl);
if (ret) {
error("can't get soft reset for %s (%d)", dev->name, ret);
return ret;
}
ret = reset_deassert(&priv->softreset_ctl);
if (ret < 0) {
error("EHCI soft reset deassert failed: %d", ret);
return ret;
}
ret = reset_deassert(&priv->power_ctl);
if (ret < 0) {
error("EHCI power deassert failed: %d", ret);
return ret;
}
/* get phy node */
phy_node = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset, "phys");
if (phy_node <= 0) {
error("USB PHY DT node not found.\n");
return -ENODEV;
}
/* probe associated phy */
ret = uclass_get_device_by_of_offset(UCLASS_MISC, phy_node, &dev_phy);
Is it possible to replace the above two calls with uclass_get_device_by_phandle()?
I have send a v3 of this series on 28th April in which i have implemented a simple USB PHY UCLASS as you requested in [1]
[1] https://www.mail-archive.com/u-boot@lists.denx.de/msg242330.html
Patrice
hcor = (struct ehci_hcor *)((phys_addr_t)hccr +
HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
+}
+static int sti_ehci_remove(struct udevice *dev) +{
struct sti_ehci_priv *priv = dev_get_priv(dev);
int ret;
ret = ehci_deregister(dev);
if (ret)
return ret;
ret = reset_assert(&priv->power_ctl);
if (ret < 0) {
error("EHCI power assert failed: %d", ret);
return ret;
}
ret = reset_assert(&priv->softreset_ctl);
if (ret < 0) {
error("EHCI soft reset assert failed: %d", ret);
return ret;
}
return 0;
+}
+static const struct udevice_id sti_usb_ids[] = {
{ .compatible = "st,st-ehci-300x" },
{ }
+};
+U_BOOT_DRIVER(ehci_sti) = {
.name = "ehci_sti",
.id = UCLASS_USB,
.of_match = sti_usb_ids,
.probe = sti_ehci_probe,
.remove = sti_ehci_remove,
.ops = &ehci_usb_ops,
.priv_auto_alloc_size = sizeof(struct sti_ehci_priv),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
1.9.1
Regards, Simon

From: Patrice Chotard patrice.chotard@st.com
Add support for on-chip ohci controller available on STMicrolectronics SoCs. Ohci support will be then available on both type A USB 2.0 connectors.
Signed-off-by: Patrice Chotard patrice.chotard@st.com ---
v2: _ put board specific defines in a separate patch (patch 8)
drivers/usb/host/Kconfig | 9 +++++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-sti.c | 90 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 drivers/usb/host/ohci-sti.c
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index d66f49e..33ded5d 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -168,6 +168,15 @@ config USB_OHCI_GENERIC ---help--- Enables support for generic OHCI controller.
+config USB_OHCI_STI + bool "Support for STMicroelectronics OHCI USB controller" + depends on ARCH_STI + depends on OF_CONTROL + depends on DM_USB + select USB_HOST + ---help--- + Enables support for the on-chip OHCI controller on STMicroelectronics SoCs. + endif # USB_OHCI_HCD
config USB_UHCI_HCD diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 303aa32..b78e632 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_USB_OHCI_EP93XX) += ohci-ep93xx.o obj-$(CONFIG_USB_OHCI_SUNXI) += ohci-sunxi.o obj-$(CONFIG_USB_OHCI_LPC32XX) += ohci-lpc32xx.o obj-$(CONFIG_USB_OHCI_GENERIC) += ohci-generic.o +obj-$(CONFIG_USB_OHCI_STI) += ohci-sti.o
# echi obj-$(CONFIG_USB_EHCI) += ehci-hcd.o diff --git a/drivers/usb/host/ohci-sti.c b/drivers/usb/host/ohci-sti.c new file mode 100644 index 0000000..62b63cd --- /dev/null +++ b/drivers/usb/host/ohci-sti.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2017 + * Patrice Chotard patrice.chotard@st.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <dm.h> +#include <errno.h> +#include "ohci.h" +#include <reset-uclass.h> +#include <usb.h> + +DECLARE_GLOBAL_DATA_PTR; + +#if !defined(CONFIG_USB_OHCI_NEW) +# error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW" +#endif + +struct sti_ohci_priv { + ohci_t ohci; + struct reset_ctl power_ctl; + struct reset_ctl softreset_ctl; +}; + +static int ohci_usb_probe(struct udevice *dev) +{ + struct sti_ohci_priv *priv = dev_get_priv(dev); + struct ohci_regs *regs; + struct udevice *dev_phy; + int ret, phy_node; + + regs = (struct ohci_regs *)dev_get_addr(dev); + if (regs == (void *)FDT_ADDR_T_NONE) + return -EINVAL; + + ret = reset_get_by_name(dev, "power", &priv->power_ctl); + if (ret) { + error("can't get power reset for %s (%d)", dev->name, ret); + return ret; + } + + ret = reset_get_by_name(dev, "softreset", &priv->softreset_ctl); + if (ret) { + error("can't get soft reset for %s (%d)", dev->name, ret); + return ret; + } + + ret = reset_deassert(&priv->power_ctl); + if (ret < 0) { + error("OHCI power reset deassert failed: %d", ret); + return ret; + } + + ret = reset_deassert(&priv->softreset_ctl); + if (ret < 0) { + error("OHCI soft reset deassert failed: %d", ret); + return ret; + } + + /* get phy node */ + phy_node = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset, "phys"); + if (phy_node <= 0) { + error("Not found usb phy device\n"); + return -ENODEV; + } + + /* probe associated phy node */ + ret = uclass_get_device_by_of_offset(UCLASS_MISC, phy_node, &dev_phy); + + return ohci_register(dev, regs); +} + +static const struct udevice_id sti_usb_ids[] = { + { .compatible = "st,st-ohci-300x" }, + { } +}; + +U_BOOT_DRIVER(ohci_sti) = { + .name = "ohci_sti", + .id = UCLASS_USB, + .of_match = sti_usb_ids, + .probe = ohci_usb_probe, + .remove = ohci_deregister, + .ops = &ohci_usb_ops, + .priv_auto_alloc_size = sizeof(struct sti_ohci_priv), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +};

On 22 March 2017 at 03:54, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
Add support for on-chip ohci controller available on STMicrolectronics SoCs. Ohci support will be then available on both type A USB 2.0 connectors.
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v2: _ put board specific defines in a separate patch (patch 8)
drivers/usb/host/Kconfig | 9 +++++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-sti.c | 90 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 drivers/usb/host/ohci-sti.c
Reviewed-by: Simon Glass sjg@chromium.org
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index d66f49e..33ded5d 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -168,6 +168,15 @@ config USB_OHCI_GENERIC ---help--- Enables support for generic OHCI controller.
+config USB_OHCI_STI
bool "Support for STMicroelectronics OHCI USB controller"
depends on ARCH_STI
depends on OF_CONTROL
depends on DM_USB
select USB_HOST
---help---
Enables support for the on-chip OHCI controller on STMicroelectronics SoCs.
endif # USB_OHCI_HCD
config USB_UHCI_HCD diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 303aa32..b78e632 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_USB_OHCI_EP93XX) += ohci-ep93xx.o obj-$(CONFIG_USB_OHCI_SUNXI) += ohci-sunxi.o obj-$(CONFIG_USB_OHCI_LPC32XX) += ohci-lpc32xx.o obj-$(CONFIG_USB_OHCI_GENERIC) += ohci-generic.o +obj-$(CONFIG_USB_OHCI_STI) += ohci-sti.o
# echi obj-$(CONFIG_USB_EHCI) += ehci-hcd.o diff --git a/drivers/usb/host/ohci-sti.c b/drivers/usb/host/ohci-sti.c new file mode 100644 index 0000000..62b63cd --- /dev/null +++ b/drivers/usb/host/ohci-sti.c @@ -0,0 +1,90 @@ +/*
- Copyright (c) 2017
- Patrice Chotard patrice.chotard@st.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <asm/io.h> +#include <dm.h> +#include <errno.h> +#include "ohci.h" +#include <reset-uclass.h> +#include <usb.h>
+DECLARE_GLOBAL_DATA_PTR;
+#if !defined(CONFIG_USB_OHCI_NEW) +# error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW" +#endif
+struct sti_ohci_priv {
ohci_t ohci;
struct reset_ctl power_ctl;
struct reset_ctl softreset_ctl;
+};
+static int ohci_usb_probe(struct udevice *dev) +{
struct sti_ohci_priv *priv = dev_get_priv(dev);
struct ohci_regs *regs;
struct udevice *dev_phy;
int ret, phy_node;
regs = (struct ohci_regs *)dev_get_addr(dev);
if (regs == (void *)FDT_ADDR_T_NONE)
return -EINVAL;
ret = reset_get_by_name(dev, "power", &priv->power_ctl);
if (ret) {
error("can't get power reset for %s (%d)", dev->name, ret);
return ret;
}
ret = reset_get_by_name(dev, "softreset", &priv->softreset_ctl);
if (ret) {
error("can't get soft reset for %s (%d)", dev->name, ret);
return ret;
}
ret = reset_deassert(&priv->power_ctl);
if (ret < 0) {
error("OHCI power reset deassert failed: %d", ret);
return ret;
}
ret = reset_deassert(&priv->softreset_ctl);
if (ret < 0) {
error("OHCI soft reset deassert failed: %d", ret);
return ret;
}
/* get phy node */
phy_node = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset, "phys");
if (phy_node <= 0) {
error("Not found usb phy device\n");
return -ENODEV;
}
/* probe associated phy node */
ret = uclass_get_device_by_of_offset(UCLASS_MISC, phy_node, &dev_phy);
Again, can you use uclass_get_device_by_phandle()?
return ohci_register(dev, regs);
+}
+static const struct udevice_id sti_usb_ids[] = {
{ .compatible = "st,st-ohci-300x" },
{ }
+};
+U_BOOT_DRIVER(ohci_sti) = {
.name = "ohci_sti",
.id = UCLASS_USB,
.of_match = sti_usb_ids,
.probe = ohci_usb_probe,
.remove = ohci_deregister,
.ops = &ohci_usb_ops,
.priv_auto_alloc_size = sizeof(struct sti_ohci_priv),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
1.9.1
Regards, Simon

From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com ---
include/configs/stih410-b2260.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/include/configs/stih410-b2260.h b/include/configs/stih410-b2260.h index 28e2f7f..4a5da82 100644 --- a/include/configs/stih410-b2260.h +++ b/include/configs/stih410-b2260.h @@ -57,4 +57,7 @@
#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_USB_OHCI_NEW +#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 2 + #endif /* __CONFIG_H */

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 --- drivers/usb/host/Kconfig | 8 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/xhci-sti.c | 156 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 drivers/usb/host/xhci-sti.c
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 33ded5d..58b64df 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -37,6 +37,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 b78e632..40ff830 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -66,6 +66,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..00f17ce --- /dev/null +++ b/drivers/usb/host/xhci-sti.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2017 + * Patrice Chotard patrice.chotard@st.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <dm.h> +#include <errno.h> +#include <fdtdec.h> +#include <libfdt.h> +#include <reset-uclass.h> +#include <usb.h> + +#include <linux/usb/dwc3.h> + +#include "xhci.h" + +DECLARE_GLOBAL_DATA_PTR; + +struct sti_xhci_platdata { + struct reset_ctl powerdown_ctl; + struct reset_ctl softreset_ctl; + phys_addr_t dwc3_regs; +}; + +struct sti_xhci_priv { + struct xhci_ctrl ctrl; +}; + + +static int sti_xhci_ofdata_to_platdata(struct udevice *dev) +{ + struct sti_xhci_platdata *plat = dev_get_platdata(dev); + struct udevice *dev_phy; + int ret; + int phy_node; + int dwc3_node; + u32 reg[2]; + + /* 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; + } + + /* 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; + } + + /* check if dwc3 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 st_dwc3 glue driver\n"); + return -ENODEV; + } + + if (fdt_node_check_compatible(gd->fdt_blob, dwc3_node, + "snps,dwc3") != 0) { + error("Can't find dwv3 subnode for st_dwc3 glue driver\n"); + return -ENODEV; + } + + /* + * now parse the dwc3 node + * first get the phy node: only usb2-phy, no need to get usb3-phy as + * usb3 is not wired + */ + phy_node = fdtdec_lookup_phandle(gd->fdt_blob, dwc3_node, "phys"); + if (phy_node <= 0) { + error("Can't find usb phy device\n"); + return -ENODEV; + } + + /* get the dwc3 register space base address */ + if (fdtdec_get_int_array(gd->fdt_blob, dwc3_node, "reg", reg, + ARRAY_SIZE(reg))) { + debug("dwc3 node has bad/missing 'reg' property\n"); + return -FDT_ERR_NOTFOUND; + } + plat->dwc3_regs = reg[0]; + + /* probe associated phy */ + return uclass_get_device_by_of_offset(UCLASS_MISC, phy_node, &dev_phy); +}; + +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_dwc3_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; + + hccr = (struct xhci_hccr *)plat->dwc3_regs; + hcor = (struct xhci_hcor *)((phys_addr_t)hccr + + HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); + + dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET); + + sti_xhci_core_init(dwc3_reg); + + return xhci_register(dev, hccr, hcor); +} + +static const struct udevice_id sti_dwc3_ids[] = { + { .compatible = "st,stih407-dwc3" }, + { } +}; + +U_BOOT_DRIVER(xhci_sti) = { + .name = "xhci_sti", + .id = UCLASS_USB, + .of_match = sti_dwc3_ids, + .ofdata_to_platdata = sti_xhci_ofdata_to_platdata, + .probe = sti_dwc3_probe, + .remove = xhci_deregister, + .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, +};

From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com --- include/configs/stih410-b2260.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/include/configs/stih410-b2260.h b/include/configs/stih410-b2260.h index 4a5da82..bbf64d7 100644 --- a/include/configs/stih410-b2260.h +++ b/include/configs/stih410-b2260.h @@ -59,5 +59,6 @@
#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 */

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

Hi Patrice,
On 22 March 2017 at 03:54, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
This patch adds the ST glue logic to manage the DWC3 HC on STiH407 SoC family. It configures the internal glue logic and syscfg registers.
Part of this code been extracted from kernel.org driver (drivers/usb/dwc3/dwc3-st.c)
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v2: _ use setbits_le32() instead of read, modify, write sequence _ add missing parenthesis
arch/arm/include/asm/arch-stih410/sys_proto.h | 11 +++ drivers/usb/dwc3/Kconfig | 8 ++ drivers/usb/dwc3/Makefile | 1 + drivers/usb/dwc3/dwc3-sti.c | 135 ++++++++++++++++++++++++++ include/dwc3-sti-uboot.h | 50 ++++++++++ 5 files changed, 205 insertions(+) create mode 100644 arch/arm/include/asm/arch-stih410/sys_proto.h create mode 100644 drivers/usb/dwc3/dwc3-sti.c create mode 100644 include/dwc3-sti-uboot.h
diff --git a/arch/arm/include/asm/arch-stih410/sys_proto.h b/arch/arm/include/asm/arch-stih410/sys_proto.h new file mode 100644 index 0000000..5c40d3b --- /dev/null +++ b/arch/arm/include/asm/arch-stih410/sys_proto.h @@ -0,0 +1,11 @@ +/*
- Copyright (c) 2017
- Patrice Chotard patrice.chotard@st.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef _ASM_ARCH_SYS_PROTO_H +#define _ASM_ARCH_SYS_PROTO_H
+#endif /* _ASM_ARCH_SYS_PROTO_H */ diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index e93398f..51a7a00 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -37,6 +37,14 @@ config USB_DWC3_OMAP
Say 'Y' here if you have one such device
+config USB_DWC3_STI
bool "STMicroelectronics STiH407 family glue driver"
help
STMicroelectronics STiH407 family SoCs use this IP for
USB2/3 functionality.
Say 'Y' here if you have one such device
menu "PHY Subsystem"
config USB_DWC3_PHY_OMAP diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index 2964bae..753912d 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_USB_DWC3_GADGET) += gadget.o ep0.o obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o obj-$(CONFIG_USB_DWC3_PHY_OMAP) += ti_usb_phy.o obj-$(CONFIG_USB_DWC3_PHY_SAMSUNG) += samsung_usb_phy.o +obj-$(CONFIG_USB_DWC3_STI) += dwc3-sti.o diff --git a/drivers/usb/dwc3/dwc3-sti.c b/drivers/usb/dwc3/dwc3-sti.c new file mode 100644 index 0000000..4b6b91b --- /dev/null +++ b/drivers/usb/dwc3/dwc3-sti.c @@ -0,0 +1,135 @@ +/*
- dwc3-sti.c - STiH407 family DWC3 specific Glue layer
- Copyright (c) 2017
- Patrice Chotard patrice.chotard@st.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <asm/io.h> +#include <common.h> +#include <dm.h> +#include <dwc3-sti-uboot.h> +#include <fdtdec.h> +#include <regmap.h> +#include <syscon.h> +#include <usb.h>
+DECLARE_GLOBAL_DATA_PTR;
+__weak int __board_usb_init(int index, enum usb_init_type init) +{
return 0;
+} +/*int board_usb_init(int index, enum usb_init_type init)*/ +/* __attribute__((weak, alias("__board_usb_init")));*/
+static int sti_dwc3_drd_init(struct sti_dwc3_platdata *plat) +{
unsigned long val;
val = readl(plat->syscfg_base + plat->syscfg_offset);
val &= USB3_CONTROL_MASK;
switch (plat->mode) {
case USB_DR_MODE_PERIPHERAL:
val &= ~(USB3_DELAY_VBUSVALID
| USB3_SEL_FORCE_OPMODE | USB3_FORCE_OPMODE(0x3)
| USB3_SEL_FORCE_DPPULLDOWN2 | USB3_FORCE_DPPULLDOWN2
| USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2);
val |= USB3_DEVICE_NOT_HOST | USB3_FORCE_VBUSVALID;
break;
case USB_DR_MODE_HOST:
val &= ~(USB3_DEVICE_NOT_HOST | USB3_FORCE_VBUSVALID
| USB3_SEL_FORCE_OPMODE | USB3_FORCE_OPMODE(0x3)
| USB3_SEL_FORCE_DPPULLDOWN2 | USB3_FORCE_DPPULLDOWN2
| USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2);
val |= USB3_DELAY_VBUSVALID;
break;
default:
error("Unsupported mode of operation %d\n", plat->mode);
return -EINVAL;
}
return writel(val, plat->syscfg_base + plat->syscfg_offset);
+}
+static void sti_dwc3_init(struct sti_dwc3_platdata *plat) +{
unsigned long reg;
reg = readl(plat->glue_base + CLKRST_CTRL);
reg |= AUX_CLK_EN | EXT_CFG_RESET_N | XHCI_REVISION;
reg &= ~SW_PIPEW_RESET_N;
writel(reg, plat->glue_base + CLKRST_CTRL);
/* configure mux for vbus, powerpresent and bvalid signals */
reg = readl(plat->glue_base + USB2_VBUS_MNGMNT_SEL1);
reg |= SEL_OVERRIDE_VBUSVALID(USB2_VBUS_UTMIOTG) |
SEL_OVERRIDE_POWERPRESENT(USB2_VBUS_UTMIOTG) |
SEL_OVERRIDE_BVALID(USB2_VBUS_UTMIOTG);
writel(reg, plat->glue_base + USB2_VBUS_MNGMNT_SEL1);
setbits_le32(plat->glue_base + CLKRST_CTRL, SW_PIPEW_RESET_N);
+}
+int sti_dwc3_glue_init(enum usb_dr_mode mode) +{
struct sti_dwc3_platdata plat;
struct fdtdec_phandle_args syscfg_phandle;
struct udevice *syscon;
struct regmap *regmap;
int node, ret;
const void *blob = gd->fdt_blob;
u32 reg[4];
/* find the dwc3 node */
node = fdt_node_offset_by_compatible(blob, -1, "st,stih407-dwc3");
ret = fdtdec_get_int_array(blob, node, "reg", reg, ARRAY_SIZE(reg));
if (ret) {
error("unable to find st,stih407-dwc3 reg property(%d)\n", ret);
return ret;
}
plat.glue_base = reg[0];
plat.syscfg_offset = reg[2];
plat.mode = mode;
/* get corresponding syscon phandle */
ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, node,
"st,syscfg", NULL, 0, 0,
&syscfg_phandle);
if (ret < 0) {
error("Can't get syscfg phandle: %d\n", ret);
return ret;
}
ret = uclass_get_device_by_of_offset(UCLASS_SYSCON, syscfg_phandle.node,
&syscon);
if (ret) {
error("unable to find syscon device (%d)\n", ret);
return ret;
}
/* get syscfg-reg base address */
regmap = syscon_get_regmap(syscon);
if (!regmap) {
error("unable to find regmap\n");
return -ENODEV;
}
plat.syscfg_base = regmap->base;
sti_dwc3_drd_init(&plat);
sti_dwc3_init(&plat);
return 0;
+} diff --git a/include/dwc3-sti-uboot.h b/include/dwc3-sti-uboot.h new file mode 100644 index 0000000..62a05f1 --- /dev/null +++ b/include/dwc3-sti-uboot.h @@ -0,0 +1,50 @@ +/*
- Copyright (c) 2017
- Patrice Chotard patrice.chotard@st.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef __DWC3_STI_UBOOT_H_ +#define __DWC3_STI_UBOOT_H_
+#include <linux/usb/otg.h>
+/* glue registers */ +#define CLKRST_CTRL 0x00 +#define AUX_CLK_EN BIT(0) +#define SW_PIPEW_RESET_N BIT(4) +#define EXT_CFG_RESET_N BIT(8)
+#define XHCI_REVISION BIT(12)
+#define USB2_VBUS_MNGMNT_SEL1 0x2C +#define USB2_VBUS_UTMIOTG 0x1
+#define SEL_OVERRIDE_VBUSVALID(n) ((n) << 0) +#define SEL_OVERRIDE_POWERPRESENT(n) ((n) << 4) +#define SEL_OVERRIDE_BVALID(n) ((n) << 8)
+/* Static DRD configuration */ +#define USB3_CONTROL_MASK 0xf77
+#define USB3_DEVICE_NOT_HOST BIT(0) +#define USB3_FORCE_VBUSVALID BIT(1) +#define USB3_DELAY_VBUSVALID BIT(2) +#define USB3_SEL_FORCE_OPMODE BIT(4) +#define USB3_FORCE_OPMODE(n) ((n) << 5) +#define USB3_SEL_FORCE_DPPULLDOWN2 BIT(8) +#define USB3_FORCE_DPPULLDOWN2 BIT(9) +#define USB3_SEL_FORCE_DMPULLDOWN2 BIT(10) +#define USB3_FORCE_DMPULLDOWN2 BIT(11)
+struct sti_dwc3_platdata {
phys_addr_t syscfg_base;
phys_addr_t glue_base;
phys_addr_t syscfg_offset;
enum usb_dr_mode mode;
+};
+int sti_dwc3_glue_init(enum usb_dr_mode mode);
Where will this be called from? We want to avoid calling directly into drivers from outside code (rather than through a uclass).
+#endif /* __DWC3_STI_UBOOT_H_ */
1.9.1
Regards, Simon

Hi Simon
On 04/01/2017 06:21 AM, Simon Glass wrote:
Hi Patrice,
On 22 March 2017 at 03:54, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
This patch adds the ST glue logic to manage the DWC3 HC on STiH407 SoC family. It configures the internal glue logic and syscfg registers.
Part of this code been extracted from kernel.org driver (drivers/usb/dwc3/dwc3-st.c)
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v2: _ use setbits_le32() instead of read, modify, write sequence _ add missing parenthesis
arch/arm/include/asm/arch-stih410/sys_proto.h | 11 +++ drivers/usb/dwc3/Kconfig | 8 ++ drivers/usb/dwc3/Makefile | 1 + drivers/usb/dwc3/dwc3-sti.c | 135 ++++++++++++++++++++++++++ include/dwc3-sti-uboot.h | 50 ++++++++++ 5 files changed, 205 insertions(+) create mode 100644 arch/arm/include/asm/arch-stih410/sys_proto.h create mode 100644 drivers/usb/dwc3/dwc3-sti.c create mode 100644 include/dwc3-sti-uboot.h
diff --git a/arch/arm/include/asm/arch-stih410/sys_proto.h b/arch/arm/include/asm/arch-stih410/sys_proto.h new file mode 100644 index 0000000..5c40d3b --- /dev/null +++ b/arch/arm/include/asm/arch-stih410/sys_proto.h @@ -0,0 +1,11 @@ +/*
- Copyright (c) 2017
- Patrice Chotard patrice.chotard@st.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef _ASM_ARCH_SYS_PROTO_H +#define _ASM_ARCH_SYS_PROTO_H
+#endif /* _ASM_ARCH_SYS_PROTO_H */ diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index e93398f..51a7a00 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -37,6 +37,14 @@ config USB_DWC3_OMAP
Say 'Y' here if you have one such device
+config USB_DWC3_STI
bool "STMicroelectronics STiH407 family glue driver"
help
STMicroelectronics STiH407 family SoCs use this IP for
USB2/3 functionality.
Say 'Y' here if you have one such device
menu "PHY Subsystem"
config USB_DWC3_PHY_OMAP diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index 2964bae..753912d 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_USB_DWC3_GADGET) += gadget.o ep0.o obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o obj-$(CONFIG_USB_DWC3_PHY_OMAP) += ti_usb_phy.o obj-$(CONFIG_USB_DWC3_PHY_SAMSUNG) += samsung_usb_phy.o +obj-$(CONFIG_USB_DWC3_STI) += dwc3-sti.o diff --git a/drivers/usb/dwc3/dwc3-sti.c b/drivers/usb/dwc3/dwc3-sti.c new file mode 100644 index 0000000..4b6b91b --- /dev/null +++ b/drivers/usb/dwc3/dwc3-sti.c @@ -0,0 +1,135 @@ +/*
- dwc3-sti.c - STiH407 family DWC3 specific Glue layer
- Copyright (c) 2017
- Patrice Chotard patrice.chotard@st.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <asm/io.h> +#include <common.h> +#include <dm.h> +#include <dwc3-sti-uboot.h> +#include <fdtdec.h> +#include <regmap.h> +#include <syscon.h> +#include <usb.h>
+DECLARE_GLOBAL_DATA_PTR;
+__weak int __board_usb_init(int index, enum usb_init_type init) +{
return 0;
+} +/*int board_usb_init(int index, enum usb_init_type init)*/ +/* __attribute__((weak, alias("__board_usb_init")));*/
+static int sti_dwc3_drd_init(struct sti_dwc3_platdata *plat) +{
unsigned long val;
val = readl(plat->syscfg_base + plat->syscfg_offset);
val &= USB3_CONTROL_MASK;
switch (plat->mode) {
case USB_DR_MODE_PERIPHERAL:
val &= ~(USB3_DELAY_VBUSVALID
| USB3_SEL_FORCE_OPMODE | USB3_FORCE_OPMODE(0x3)
| USB3_SEL_FORCE_DPPULLDOWN2 | USB3_FORCE_DPPULLDOWN2
| USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2);
val |= USB3_DEVICE_NOT_HOST | USB3_FORCE_VBUSVALID;
break;
case USB_DR_MODE_HOST:
val &= ~(USB3_DEVICE_NOT_HOST | USB3_FORCE_VBUSVALID
| USB3_SEL_FORCE_OPMODE | USB3_FORCE_OPMODE(0x3)
| USB3_SEL_FORCE_DPPULLDOWN2 | USB3_FORCE_DPPULLDOWN2
| USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2);
val |= USB3_DELAY_VBUSVALID;
break;
default:
error("Unsupported mode of operation %d\n", plat->mode);
return -EINVAL;
}
return writel(val, plat->syscfg_base + plat->syscfg_offset);
+}
+static void sti_dwc3_init(struct sti_dwc3_platdata *plat) +{
unsigned long reg;
reg = readl(plat->glue_base + CLKRST_CTRL);
reg |= AUX_CLK_EN | EXT_CFG_RESET_N | XHCI_REVISION;
reg &= ~SW_PIPEW_RESET_N;
writel(reg, plat->glue_base + CLKRST_CTRL);
/* configure mux for vbus, powerpresent and bvalid signals */
reg = readl(plat->glue_base + USB2_VBUS_MNGMNT_SEL1);
reg |= SEL_OVERRIDE_VBUSVALID(USB2_VBUS_UTMIOTG) |
SEL_OVERRIDE_POWERPRESENT(USB2_VBUS_UTMIOTG) |
SEL_OVERRIDE_BVALID(USB2_VBUS_UTMIOTG);
writel(reg, plat->glue_base + USB2_VBUS_MNGMNT_SEL1);
setbits_le32(plat->glue_base + CLKRST_CTRL, SW_PIPEW_RESET_N);
+}
+int sti_dwc3_glue_init(enum usb_dr_mode mode) +{
struct sti_dwc3_platdata plat;
struct fdtdec_phandle_args syscfg_phandle;
struct udevice *syscon;
struct regmap *regmap;
int node, ret;
const void *blob = gd->fdt_blob;
u32 reg[4];
/* find the dwc3 node */
node = fdt_node_offset_by_compatible(blob, -1, "st,stih407-dwc3");
ret = fdtdec_get_int_array(blob, node, "reg", reg, ARRAY_SIZE(reg));
if (ret) {
error("unable to find st,stih407-dwc3 reg property(%d)\n", ret);
return ret;
}
plat.glue_base = reg[0];
plat.syscfg_offset = reg[2];
plat.mode = mode;
/* get corresponding syscon phandle */
ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, node,
"st,syscfg", NULL, 0, 0,
&syscfg_phandle);
if (ret < 0) {
error("Can't get syscfg phandle: %d\n", ret);
return ret;
}
ret = uclass_get_device_by_of_offset(UCLASS_SYSCON, syscfg_phandle.node,
&syscon);
if (ret) {
error("unable to find syscon device (%d)\n", ret);
return ret;
}
/* get syscfg-reg base address */
regmap = syscon_get_regmap(syscon);
if (!regmap) {
error("unable to find regmap\n");
return -ENODEV;
}
plat.syscfg_base = regmap->base;
sti_dwc3_drd_init(&plat);
sti_dwc3_init(&plat);
return 0;
+} diff --git a/include/dwc3-sti-uboot.h b/include/dwc3-sti-uboot.h new file mode 100644 index 0000000..62a05f1 --- /dev/null +++ b/include/dwc3-sti-uboot.h @@ -0,0 +1,50 @@ +/*
- Copyright (c) 2017
- Patrice Chotard patrice.chotard@st.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef __DWC3_STI_UBOOT_H_ +#define __DWC3_STI_UBOOT_H_
+#include <linux/usb/otg.h>
+/* glue registers */ +#define CLKRST_CTRL 0x00 +#define AUX_CLK_EN BIT(0) +#define SW_PIPEW_RESET_N BIT(4) +#define EXT_CFG_RESET_N BIT(8)
+#define XHCI_REVISION BIT(12)
+#define USB2_VBUS_MNGMNT_SEL1 0x2C +#define USB2_VBUS_UTMIOTG 0x1
+#define SEL_OVERRIDE_VBUSVALID(n) ((n) << 0) +#define SEL_OVERRIDE_POWERPRESENT(n) ((n) << 4) +#define SEL_OVERRIDE_BVALID(n) ((n) << 8)
+/* Static DRD configuration */ +#define USB3_CONTROL_MASK 0xf77
+#define USB3_DEVICE_NOT_HOST BIT(0) +#define USB3_FORCE_VBUSVALID BIT(1) +#define USB3_DELAY_VBUSVALID BIT(2) +#define USB3_SEL_FORCE_OPMODE BIT(4) +#define USB3_FORCE_OPMODE(n) ((n) << 5) +#define USB3_SEL_FORCE_DPPULLDOWN2 BIT(8) +#define USB3_FORCE_DPPULLDOWN2 BIT(9) +#define USB3_SEL_FORCE_DMPULLDOWN2 BIT(10) +#define USB3_FORCE_DMPULLDOWN2 BIT(11)
+struct sti_dwc3_platdata {
phys_addr_t syscfg_base;
phys_addr_t glue_base;
phys_addr_t syscfg_offset;
enum usb_dr_mode mode;
+};
+int sti_dwc3_glue_init(enum usb_dr_mode mode);
Where will this be called from? We want to avoid calling directly into drivers from outside code (rather than through a uclass).
This function is needed for fastboot feature. When using "fastboot" command the do_fastboot() call board_usb_init() implemented in each architecture board file.
It will be called from board_usb_init() in board/st/stih410-b2260/board.c
But, please refer to my last series (v3 send on 28th April 2017)
Thanks
Patrice
+#endif /* __DWC3_STI_UBOOT_H_ */
1.9.1
Regards, Simon

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 --- 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 0c06bca..363c016 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-uboot.h> +#include <dwc3-uboot.h> +#include <usb.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -26,3 +29,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_glue_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

From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com --- 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 bbf64d7..0a52af3 100644 --- a/include/configs/stih410-b2260.h +++ b/include/configs/stih410-b2260.h @@ -57,8 +57,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 */

From: Patrice Chotard patrice.chotard@st.com
Signed-off-by: Patrice Chotard patrice.chotard@st.com --- v2 : _ squash patch 7,9,11,12,14,16,17,18,19,20 and 21
configs/stih410-b2260_defconfig | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-)
diff --git a/configs/stih410-b2260_defconfig b/configs/stih410-b2260_defconfig index d3cfdca..549a8fd 100644 --- a/configs/stih410-b2260_defconfig +++ b/configs/stih410-b2260_defconfig @@ -2,18 +2,27 @@ 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 @@ -21,7 +30,25 @@ CONFIG_MISC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_STI=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_OHCI_HCD=y +CONFIG_USB_OHCI_STI=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_GADGET=y +CONFIG_USB_DWC3_STI=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

fyi , a v3 has been send
On 03/22/2017 10:54 AM, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
This series adds : _ add reset driver _ 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
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): reset: Add STi reset support 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 phy: Add STi phy usb support usb: ehci: Add STi ehci support usb: ohci: Add STi ohci support board: STiH410-B2260: add OHCI related defines usb: xhci: Add STi xhci support board: STiH410-B2260: add XHCI related define usb: dwc3: Add dwc3 support for STi board: STiH410-B2260: add fastboot support STiH410-B2260: enable USB Host Networking STiH410-B2260: enable USB, fastboot, reset related flags
arch/arm/Kconfig | 1 + arch/arm/dts/stih407-family.dtsi | 1 + arch/arm/include/asm/arch-stih410/sys_proto.h | 11 + board/st/stih410-b2260/board.c | 44 ++++ configs/stih410-b2260_defconfig | 36 ++- drivers/mmc/sti_sdhci.c | 60 +++-- drivers/reset/Kconfig | 8 + drivers/reset/Makefile | 1 + drivers/reset/sti-reset.c | 320 ++++++++++++++++++++++++++ drivers/usb/Kconfig | 4 + drivers/usb/dwc3/Kconfig | 8 + drivers/usb/dwc3/Makefile | 1 + drivers/usb/dwc3/dwc3-sti.c | 135 +++++++++++ drivers/usb/host/Kconfig | 26 +++ drivers/usb/host/Makefile | 3 + drivers/usb/host/ehci-sti.c | 115 +++++++++ drivers/usb/host/ohci-sti.c | 90 ++++++++ drivers/usb/host/xhci-sti.c | 156 +++++++++++++ drivers/usb/phy/Kconfig | 11 + drivers/usb/phy/Makefile | 1 + drivers/usb/phy/sti_phy_usb.c | 153 ++++++++++++ include/configs/stih410-b2260.h | 16 ++ include/dwc3-sti-uboot.h | 50 ++++ 23 files changed, 1225 insertions(+), 26 deletions(-) create mode 100644 arch/arm/include/asm/arch-stih410/sys_proto.h create mode 100644 drivers/reset/sti-reset.c create mode 100644 drivers/usb/dwc3/dwc3-sti.c create mode 100644 drivers/usb/host/ehci-sti.c create mode 100644 drivers/usb/host/ohci-sti.c create mode 100644 drivers/usb/host/xhci-sti.c create mode 100644 drivers/usb/phy/Kconfig create mode 100644 drivers/usb/phy/sti_phy_usb.c create mode 100644 include/dwc3-sti-uboot.h
participants (3)
-
Patrice CHOTARD
-
patrice.chotard@st.com
-
Simon Glass