[U-Boot] [PATCH v7 0/5] Extend xhci-dwc3

From: Patrice Chotard patrice.chotard@st.com
This series extend xhci-dwc3.c drivers by : _ converting it to DM model, _ adding dual role mode support from DT _ adding new generic_phy_valid() method in PHY framework _ adding support of generic PHY framework
v7: _ add Reviewed-by in patch 1 _ declare bool generic_phy_valid(struct phy *phy) as static inline in patch 4 v6: _ remove useless struct xhci_dwc3 in patch 1 v5: _ rebase on top of dm/master in order to use the last livetree update _ replace dev_get_addr() by devfdt_get_addr() in patch 1 v4: _ set phy->dev to NULL in case of generic_phy_get_by_index() v3: _ introduce generic_phy_valid() method _ add Reviewed-by v2: _ use dev_get_addr() in PATCH 1 and removed useless piece of code
Patrice Chotard (5): usb: host: xhci-dwc3: Convert driver to DM usb: host: xhci-dwc3: Add dual role mode support from DT drivers: phy: Set phy->dev to NULL when generic_phy_get_by_index() fails drivers: phy: add generic_phy_valid() method usb: host: xhci-dwc3: Add generic PHY support
drivers/phy/phy-uclass.c | 1 + drivers/usb/host/xhci-dwc3.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ include/generic-phy.h | 11 ++++++ 3 files changed, 99 insertions(+)

From: Patrice Chotard patrice.chotard@st.com
Add Driver Model support with use of generic DT compatible string "snps,dwc3"
Signed-off-by: Patrice Chotard patrice.chotard@st.com Reviewed-by: Bin Meng bmeng.cn@gmail.com --- v7: _ add Reviewed-by v6: _ remove useless struct xhci_dwc3 v5: _ replace dev_get_addr() by devfdt_get_addr() v4: _ none v3: _ none v2: _ use dev_get_addr() and removed useless piece of code
drivers/usb/host/xhci-dwc3.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c index 33961cd..89b66b3 100644 --- a/drivers/usb/host/xhci-dwc3.c +++ b/drivers/usb/host/xhci-dwc3.c @@ -9,9 +9,15 @@ */
#include <common.h> +#include <dm.h> +#include <usb.h> + +#include "xhci.h" #include <asm/io.h> #include <linux/usb/dwc3.h>
+DECLARE_GLOBAL_DATA_PTR; + void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) { clrsetbits_le32(&dwc3_reg->g_ctl, @@ -97,3 +103,43 @@ void dwc3_set_fladj(struct dwc3 *dwc3_reg, u32 val) setbits_le32(&dwc3_reg->g_fladj, GFLADJ_30MHZ_REG_SEL | GFLADJ_30MHZ(val)); } + +static int xhci_dwc3_probe(struct udevice *dev) +{ + struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); + struct xhci_hcor *hcor; + struct xhci_hccr *hccr; + struct dwc3 *dwc3_reg; + + hccr = (struct xhci_hccr *)devfdt_get_addr(dev); + hcor = (struct xhci_hcor *)((phys_addr_t)hccr + + HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); + + dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET); + + dwc3_core_init(dwc3_reg); + + return xhci_register(dev, hccr, hcor); +} + +static int xhci_dwc3_remove(struct udevice *dev) +{ + return xhci_deregister(dev); +} + +static const struct udevice_id xhci_dwc3_ids[] = { + { .compatible = "snps,dwc3" }, + { } +}; + +U_BOOT_DRIVER(xhci_dwc3) = { + .name = "xhci-dwc3", + .id = UCLASS_USB, + .of_match = xhci_dwc3_ids, + .probe = xhci_dwc3_probe, + .remove = xhci_dwc3_remove, + .ops = &xhci_usb_ops, + .priv_auto_alloc_size = sizeof(struct xhci_ctrl), + .platdata_auto_alloc_size = sizeof(struct xhci_dwc3_platdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +};

From: Patrice Chotard patrice.chotard@st.com
DWC3 dual role mode is selected using DT "dr_mode" property. If not found, DWC3 controller is configured in HOST mode by default
Signed-off-by: Patrice Chotard patrice.chotard@st.com Reviewed-by: Marek Vasut marex@denx.de Reviewed-by: Simon Glass sjg@chromium.org --- v7: _ none v6: _ none v5: _ none v4: _ none v3: _ none v2: _ none
drivers/usb/host/xhci-dwc3.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c index 89b66b3..97b57a9 100644 --- a/drivers/usb/host/xhci-dwc3.c +++ b/drivers/usb/host/xhci-dwc3.c @@ -15,6 +15,7 @@ #include "xhci.h" #include <asm/io.h> #include <linux/usb/dwc3.h> +#include <linux/usb/otg.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -110,6 +111,7 @@ static int xhci_dwc3_probe(struct udevice *dev) struct xhci_hcor *hcor; struct xhci_hccr *hccr; struct dwc3 *dwc3_reg; + enum usb_dr_mode dr_mode;
hccr = (struct xhci_hccr *)devfdt_get_addr(dev); hcor = (struct xhci_hcor *)((phys_addr_t)hccr + @@ -119,6 +121,13 @@ static int xhci_dwc3_probe(struct udevice *dev)
dwc3_core_init(dwc3_reg);
+ dr_mode = usb_get_dr_mode(dev_of_offset(dev)); + if (dr_mode == USB_DR_MODE_UNKNOWN) + /* by default set dual role mode to HOST */ + dr_mode = USB_DR_MODE_HOST; + + dwc3_set_mode(dwc3_reg, dr_mode); + return xhci_register(dev, hccr, hcor); }

From: Patrice Chotard patrice.chotard@st.com
phy->dev need to be set to NULL in case of generic_phy_get_by_index() fails. Then phy->dev can be used to check if the phy is valid
Reported-by: Jean-Jacques Hiblot jjhiblot@ti.com Signed-off-by: Patrice Chotard patrice.chotard@st.com Reviewed-by: Simon Glass sjg@chromium.org --- v7: _ none v6: _ none v5: _ none v4: _ ensure that phy->dev is set to NULL in case of generic_phy_get_by_index() fails
drivers/phy/phy-uclass.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c index d8b8d58..68e518f 100644 --- a/drivers/phy/phy-uclass.c +++ b/drivers/phy/phy-uclass.c @@ -45,6 +45,7 @@ int generic_phy_get_by_index(struct udevice *dev, int index, debug("%s(dev=%p, index=%d, phy=%p)\n", __func__, dev, index, phy);
assert(phy); + phy->dev = NULL; ret = dev_read_phandle_with_args(dev, "phys", "#phy-cells", 0, index, &args); if (ret) {

On 18/07/2017 11:38, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
phy->dev need to be set to NULL in case of generic_phy_get_by_index() fails. Then phy->dev can be used to check if the phy is valid
Reported-by: Jean-Jacques Hiblot jjhiblot@ti.com Signed-off-by: Patrice Chotard patrice.chotard@st.com Reviewed-by: Simon Glass sjg@chromium.org
v7: _ none v6: _ none v5: _ none v4: _ ensure that phy->dev is set to NULL in case of generic_phy_get_by_index() fails
drivers/phy/phy-uclass.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c index d8b8d58..68e518f 100644 --- a/drivers/phy/phy-uclass.c +++ b/drivers/phy/phy-uclass.c @@ -45,6 +45,7 @@ int generic_phy_get_by_index(struct udevice *dev, int index, debug("%s(dev=%p, index=%d, phy=%p)\n", __func__, dev, index, phy);
assert(phy);
- phy->dev = NULL; ret = dev_read_phandle_with_args(dev, "phys", "#phy-cells", 0, index, &args); if (ret) {
Reviewed-by: Jean-Jacques Hiblot jjhiblot@ti.com

From: Patrice Chotard patrice.chotard@st.com
This allow to check if a PHY has been correctly initialised and avoid to get access to phy struct.
Signed-off-by: Patrice Chotard patrice.chotard@st.com --- v7: _ declare bool generic_phy_valid(struct phy *phy) as static inline v6: _ none v5: _ none v4: _ none
include/generic-phy.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/include/generic-phy.h b/include/generic-phy.h index 762704c..58cd2b2 100644 --- a/include/generic-phy.h +++ b/include/generic-phy.h @@ -220,4 +220,15 @@ int generic_phy_get_by_index(struct udevice *user, int index, int generic_phy_get_by_name(struct udevice *user, const char *phy_name, struct phy *phy);
+/** + * generic_phy_valid() - check if PHY port is valid + * + * @phy: the PHY port to check + * @return TRUE if valid, or FALSE + */ +static inline bool generic_phy_valid(struct phy *phy) +{ + return phy->dev != NULL; +} + #endif /*__GENERIC_PHY_H */

On 18/07/2017 11:38, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
This allow to check if a PHY has been correctly initialised and avoid to get access to phy struct.
Signed-off-by: Patrice Chotard patrice.chotard@st.com
v7: _ declare bool generic_phy_valid(struct phy *phy) as static inline v6: _ none v5: _ none v4: _ none
include/generic-phy.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/include/generic-phy.h b/include/generic-phy.h index 762704c..58cd2b2 100644 --- a/include/generic-phy.h +++ b/include/generic-phy.h @@ -220,4 +220,15 @@ int generic_phy_get_by_index(struct udevice *user, int index, int generic_phy_get_by_name(struct udevice *user, const char *phy_name, struct phy *phy);
+/**
- generic_phy_valid() - check if PHY port is valid
- @phy: the PHY port to check
- @return TRUE if valid, or FALSE
- */
+static inline bool generic_phy_valid(struct phy *phy) +{
- return phy->dev != NULL;
+}
- #endif /*__GENERIC_PHY_H */
Reviewed-by: Jean-Jacques Hiblot jjhiblot@ti.com

From: Patrice Chotard patrice.chotard@st.com
Add support of generic PHY framework support
Signed-off-by: Patrice Chotard patrice.chotard@st.com Reviewed-by: Marek Vasut marex@denx.de Reviewed-by: Simon Glass sjg@chromium.org --- v7: _ none v6: _ none v5: _ none v4: _ none v3: _ use generic_phy_valid() method v2: _ none
drivers/usb/host/xhci-dwc3.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+)
diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c index 97b57a9..4200403 100644 --- a/drivers/usb/host/xhci-dwc3.c +++ b/drivers/usb/host/xhci-dwc3.c @@ -10,6 +10,8 @@
#include <common.h> #include <dm.h> +#include <fdtdec.h> +#include <generic-phy.h> #include <usb.h>
#include "xhci.h" @@ -19,6 +21,10 @@
DECLARE_GLOBAL_DATA_PTR;
+struct xhci_dwc3_platdata { + struct phy usb_phy; +}; + void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) { clrsetbits_le32(&dwc3_reg->g_ctl, @@ -112,11 +118,26 @@ static int xhci_dwc3_probe(struct udevice *dev) struct xhci_hccr *hccr; struct dwc3 *dwc3_reg; enum usb_dr_mode dr_mode; + int ret;
hccr = (struct xhci_hccr *)devfdt_get_addr(dev); hcor = (struct xhci_hcor *)((phys_addr_t)hccr + HC_LENGTH(xhci_readl(&(hccr)->cr_capbase)));
+ ret = generic_phy_get_by_index(dev, 0, &plat->usb_phy); + if (ret) { + if (ret != -ENOENT) { + error("Failed to get USB PHY for %s\n", dev->name); + return ret; + } + } else { + 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);
dwc3_core_init(dwc3_reg); @@ -133,6 +154,17 @@ static int xhci_dwc3_probe(struct udevice *dev)
static int xhci_dwc3_remove(struct udevice *dev) { + struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); + int ret; + + if (generic_phy_valid(&plat->usb_phy)) { + 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); }

On 07/18/2017 11:38 AM, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
This series extend xhci-dwc3.c drivers by : _ converting it to DM model, _ adding dual role mode support from DT _ adding new generic_phy_valid() method in PHY framework _ adding support of generic PHY framework
v7: _ add Reviewed-by in patch 1 _ declare bool generic_phy_valid(struct phy *phy) as static inline in patch 4 v6: _ remove useless struct xhci_dwc3 in patch 1 v5: _ rebase on top of dm/master in order to use the last livetree update _ replace dev_get_addr() by devfdt_get_addr() in patch 1 v4: _ set phy->dev to NULL in case of generic_phy_get_by_index() v3: _ introduce generic_phy_valid() method _ add Reviewed-by v2: _ use dev_get_addr() in PATCH 1 and removed useless piece of code
Patrice Chotard (5): usb: host: xhci-dwc3: Convert driver to DM usb: host: xhci-dwc3: Add dual role mode support from DT drivers: phy: Set phy->dev to NULL when generic_phy_get_by_index() fails drivers: phy: add generic_phy_valid() method usb: host: xhci-dwc3: Add generic PHY support
drivers/phy/phy-uclass.c | 1 + drivers/usb/host/xhci-dwc3.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ include/generic-phy.h | 11 ++++++ 3 files changed, 99 insertions(+)
Applied all, thanks.

Hi.
2017-07-18 18:40 GMT+09:00 Marek Vasut marex@denx.de:
On 07/18/2017 11:38 AM, patrice.chotard@st.com wrote:
From: Patrice Chotard patrice.chotard@st.com
This series extend xhci-dwc3.c drivers by : _ converting it to DM model, _ adding dual role mode support from DT _ adding new generic_phy_valid() method in PHY framework _ adding support of generic PHY framework
v7: _ add Reviewed-by in patch 1 _ declare bool generic_phy_valid(struct phy *phy) as static inline in patch 4 v6: _ remove useless struct xhci_dwc3 in patch 1 v5: _ rebase on top of dm/master in order to use the last livetree update _ replace dev_get_addr() by devfdt_get_addr() in patch 1 v4: _ set phy->dev to NULL in case of generic_phy_get_by_index() v3: _ introduce generic_phy_valid() method _ add Reviewed-by v2: _ use dev_get_addr() in PATCH 1 and removed useless piece of code
Patrice Chotard (5): usb: host: xhci-dwc3: Convert driver to DM usb: host: xhci-dwc3: Add dual role mode support from DT drivers: phy: Set phy->dev to NULL when generic_phy_get_by_index() fails drivers: phy: add generic_phy_valid() method usb: host: xhci-dwc3: Add generic PHY support
drivers/phy/phy-uclass.c | 1 + drivers/usb/host/xhci-dwc3.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ include/generic-phy.h | 11 ++++++ 3 files changed, 99 insertions(+)
Applied all, thanks.
--
I tried to convert xhci-dwc3.c into a DM driver one year before: http://patchwork.ozlabs.org/patch/622563/
After our discussion, a problem was duplication between drivers/usb/host/xhci-dwc3.c and drivers/usb/dwc3/.
I has been too busy to track this work, but was that problem solved?
How will glue-layers work?
participants (4)
-
Jean-Jacques Hiblot
-
Marek Vasut
-
Masahiro Yamada
-
patrice.chotard@st.com