2013-09-02 15:44:12

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [PATCH 0/7] Make dwc3 use Generic PHY Framework and misc cleanup

Modified dwc3 core to find PHYs only if the platform indicates that it has
to use a PHY. Adapted DWC3 and USB3 PHY to use Generic PHY framework. Also
changed the name of USB3 PHY driver to PIPE3 PHY driver since the same driver
has to be used for SATA and PCIE too.

This series also includes a bunch of misc cleanups and also renamed
omap_control_usb to omap_control_phy (done on top of rogers patches [1])

Did g_zero enumeration testing on OMAP4 PANDA and did xhci testing in
OMAP5 uEvm.

I have pushed this branch to http://git.gitorious.org/linuxphy/linuxphy.git
dwc3_generic_phy

[1] -> git://github.com/rogerq/linux.git usb-control-module

Kishon Vijay Abraham I (7):
usb: dwc3: get "usb_phy" only if the platform indicates the presence
of PHY
usb: dwc3: adapt dwc3 core to use Generic PHY Framework
drivers: phy: usb3/pipe3: Adapt pipe3 driver to Generic PHY Framework
Documentation: dt bindings: move ..usb/usb-phy.txt to
..phy/omap-phy.txt
phy: omap-usb2: move omap_usb.h from linux/usb/ to linux/phy/
arm/dts: added dt properties to adapt to the new phy framwork
drivers: phy: renamed struct omap_control_usb to struct
omap_control_phy

.../bindings/{usb/usb-phy.txt => phy/omap-phy.txt} | 7 +-
Documentation/devicetree/bindings/usb/dwc3.txt | 6 +-
arch/arm/boot/dts/omap5.dtsi | 5 +-
drivers/phy/Kconfig | 22 +-
drivers/phy/Makefile | 2 +
drivers/{usb => }/phy/phy-omap-control.c | 164 +++++++--------
.../phy/phy-omap-usb3.c => phy/phy-omap-pipe3.c} | 212 +++++++++++---------
drivers/phy/phy-omap-usb2.c | 10 +-
drivers/usb/dwc3/Kconfig | 2 +
drivers/usb/dwc3/core.c | 109 ++++++----
drivers/usb/dwc3/core.h | 7 +
drivers/usb/dwc3/platform_data.h | 1 +
drivers/usb/musb/omap2430.c | 2 +-
drivers/usb/phy/Kconfig | 11 -
drivers/usb/phy/Makefile | 2 -
drivers/usb/phy/phy-twl6030-usb.c | 2 +-
.../omap_control_usb.h => phy/omap_control_phy.h} | 32 +--
include/linux/{usb/omap_usb.h => phy/omap_pipe3.h} | 33 +--
include/linux/{usb => phy}/omap_usb.h | 3 -
19 files changed, 348 insertions(+), 284 deletions(-)
rename Documentation/devicetree/bindings/{usb/usb-phy.txt => phy/omap-phy.txt} (88%)
rename drivers/{usb => }/phy/phy-omap-control.c (55%)
rename drivers/{usb/phy/phy-omap-usb3.c => phy/phy-omap-pipe3.c} (55%)
rename include/linux/{usb/omap_control_usb.h => phy/omap_control_phy.h} (69%)
copy include/linux/{usb/omap_usb.h => phy/omap_pipe3.h} (52%)
rename include/linux/{usb => phy}/omap_usb.h (95%)

--
1.7.10.4


2013-09-02 15:44:29

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [PATCH 4/7] Documentation: dt bindings: move ..usb/usb-phy.txt to ..phy/omap-phy.txt

Since now we have a separate folder for phy, move the PHY dt binding
documentation of OMAP to that folder.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
.../devicetree/bindings/{usb/usb-phy.txt => phy/omap-phy.txt} | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
rename Documentation/devicetree/bindings/{usb/usb-phy.txt => phy/omap-phy.txt} (96%)

diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/phy/omap-phy.txt
similarity index 96%
rename from Documentation/devicetree/bindings/usb/usb-phy.txt
rename to Documentation/devicetree/bindings/phy/omap-phy.txt
index 36bdb17..2c485ee 100644
--- a/Documentation/devicetree/bindings/usb/usb-phy.txt
+++ b/Documentation/devicetree/bindings/phy/omap-phy.txt
@@ -1,4 +1,4 @@
-USB PHY
+OMAP PHY: DT DOCUMENTATION FOR PHYs in OMAP PLATFORM

OMAP USB2 PHY

--
1.7.10.4

2013-09-02 15:44:42

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [PATCH 5/7] phy: omap-usb2: move omap_usb.h from linux/usb/ to linux/phy/

No functional change. Moved omap_usb.h from linux/usb/ to linux/phy/.
Also removed the unused members of struct omap_usb (after phy-omap-pipe3
started using it's own header file)

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/phy/phy-omap-usb2.c | 2 +-
drivers/usb/phy/phy-twl6030-usb.c | 2 +-
include/linux/{usb => phy}/omap_usb.h | 3 ---
3 files changed, 2 insertions(+), 5 deletions(-)
rename include/linux/{usb => phy}/omap_usb.h (95%)

diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c
index b25d623..6c78584 100644
--- a/drivers/phy/phy-omap-usb2.c
+++ b/drivers/phy/phy-omap-usb2.c
@@ -21,7 +21,7 @@
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/io.h>
-#include <linux/usb/omap_usb.h>
+#include <linux/phy/omap_usb.h>
#include <linux/usb/phy_companion.h>
#include <linux/clk.h>
#include <linux/err.h>
diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c
index 16dbc93..b5ad3eb 100644
--- a/drivers/usb/phy/phy-twl6030-usb.c
+++ b/drivers/usb/phy/phy-twl6030-usb.c
@@ -26,8 +26,8 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/usb/musb-omap.h>
+#include <linux/phy/omap_usb.h>
#include <linux/usb/phy_companion.h>
-#include <linux/usb/omap_usb.h>
#include <linux/i2c/twl.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
diff --git a/include/linux/usb/omap_usb.h b/include/linux/phy/omap_usb.h
similarity index 95%
rename from include/linux/usb/omap_usb.h
rename to include/linux/phy/omap_usb.h
index 6ae2936..19d343c3 100644
--- a/include/linux/usb/omap_usb.h
+++ b/include/linux/phy/omap_usb.h
@@ -33,13 +33,10 @@ struct usb_dpll_params {
struct omap_usb {
struct usb_phy phy;
struct phy_companion *comparator;
- void __iomem *pll_ctrl_base;
struct device *dev;
struct device *control_dev;
struct clk *wkupclk;
- struct clk *sys_clk;
struct clk *optclk;
- u8 is_suspended:1;
};

#define phy_to_omapusb(x) container_of((x), struct omap_usb, phy)
--
1.7.10.4

2013-09-02 15:44:54

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [PATCH 7/7] drivers: phy: renamed struct omap_control_usb to struct omap_control_phy

renamed struct omap_control_usb to struct omap_control_phy since it can
be used to control PHY of USB, SATA and PCIE. Also moved the driver and
include files under *phy* and made the corresponding changes in the users
of phy-omap-control.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/phy/Kconfig | 14 +-
drivers/phy/Makefile | 1 +
drivers/{usb => }/phy/phy-omap-control.c | 164 ++++++++++----------
drivers/phy/phy-omap-pipe3.c | 8 +-
drivers/phy/phy-omap-usb2.c | 8 +-
drivers/usb/musb/omap2430.c | 2 +-
drivers/usb/phy/Makefile | 1 -
.../omap_control_usb.h => phy/omap_control_phy.h} | 32 ++--
8 files changed, 120 insertions(+), 110 deletions(-)
rename drivers/{usb => }/phy/phy-omap-control.c (55%)
rename include/linux/{usb/omap_control_usb.h => phy/omap_control_phy.h} (69%)

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 5c2e7a0..fd11294 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -15,12 +15,22 @@ config GENERIC_PHY
phy users can obtain reference to the PHY. All the users of this
framework should select this config.

+config OMAP_CONTROL_PHY
+ tristate "OMAP CONTROL PHY Driver"
+ depends on ARCH_OMAP2PLUS || COMPILE_TEST
+ help
+ Enable this to add support for the PHY part present in the control
+ module. This driver has API to power on the USB2 PHY and to write to
+ the mailbox. The mailbox is present only in omap4 and the register to
+ power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has
+ additional registers to power on PIPE3 PHYs.
+
config OMAP_USB2
tristate "OMAP USB2 PHY Driver"
depends on ARCH_OMAP2PLUS
select GENERIC_PHY
select USB_PHY
- select OMAP_CONTROL_USB
+ select OMAP_CONTROL_PHY
help
Enable this to support the transceiver that is part of SOC. This
driver takes care of all the PHY functionality apart from comparator.
@@ -30,7 +40,7 @@ config OMAP_USB2
config OMAP_PIPE3
tristate "OMAP PIPE3 PHY Driver"
select GENERIC_PHY
- select OMAP_CONTROL_USB
+ select OMAP_CONTROL_PHY
help
Enable this to support the PIPE3 PHY that is part of SOC. This
driver takes care of all the PHY functionality apart from comparator.
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 48bf9f2..f0127f6 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -3,6 +3,7 @@
#

obj-$(CONFIG_GENERIC_PHY) += phy-core.o
+obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o
obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
obj-$(CONFIG_OMAP_PIPE3) += phy-omap-pipe3.o
obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
diff --git a/drivers/usb/phy/phy-omap-control.c b/drivers/phy/phy-omap-control.c
similarity index 55%
rename from drivers/usb/phy/phy-omap-control.c
rename to drivers/phy/phy-omap-control.c
index 1a7e19a..ece3573 100644
--- a/drivers/usb/phy/phy-omap-control.c
+++ b/drivers/phy/phy-omap-control.c
@@ -1,5 +1,5 @@
/*
- * omap-control-usb.c - The USB part of control module.
+ * phy-omap-control.c - The USB part of control module.
*
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
* This program is free software; you can redistribute it and/or modify
@@ -24,36 +24,36 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/clk.h>
-#include <linux/usb/omap_control_usb.h>
+#include <linux/phy/omap_control_phy.h>

/**
- * omap_control_usb_phy_power - power on/off the phy using control module reg
+ * omap_control_phy_power - power on/off the phy using control module reg
* @dev: the control module device
* @on: 0 or 1, based on powering on or off the PHY
*/
-void omap_control_usb_phy_power(struct device *dev, int on)
+void omap_control_phy_power(struct device *dev, int on)
{
u32 val, val_aux;
unsigned long rate;
- struct omap_control_usb *control_usb;
+ struct omap_control_phy *control_phy;

if (IS_ERR(dev) || !dev) {
pr_err("%s: invalid device\n", __func__);
return;
}

- control_usb = dev_get_drvdata(dev);
- if (!control_usb) {
+ control_phy = dev_get_drvdata(dev);
+ if (!control_phy) {
dev_err(dev, "%s: invalid control usb device\n", __func__);
return;
}

- if (control_usb->type == OMAP_CTRL_TYPE_OMAP4)
+ if (control_phy->type == OMAP_CTRL_TYPE_OMAP4)
return;

- val = readl(control_usb->power);
+ val = readl(control_phy->power);

- switch (control_usb->type) {
+ switch (control_phy->type) {
case OMAP_CTRL_TYPE_USB2:
if (on)
val &= ~OMAP_CTRL_DEV_PHY_PD;
@@ -62,24 +62,24 @@ void omap_control_usb_phy_power(struct device *dev, int on)
break;

case OMAP_CTRL_TYPE_USB3:
- rate = clk_get_rate(control_usb->sys_clk);
+ rate = clk_get_rate(control_phy->sys_clk);
rate = rate/1000000;

if (on) {
- val &= ~(OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK |
- OMAP_CTRL_USB_PWRCTL_CLK_FREQ_MASK);
- val |= OMAP_CTRL_USB3_PHY_TX_RX_POWERON <<
- OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT;
- val |= rate << OMAP_CTRL_USB_PWRCTL_CLK_FREQ_SHIFT;
+ val &= ~(OMAP_CTRL_PIPE3_PWRCTL_CLK_CMD_MASK |
+ OMAP_CTRL_PIPE3_PWRCTL_CLK_FREQ_MASK);
+ val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON <<
+ OMAP_CTRL_PIPE3_PWRCTL_CLK_CMD_SHIFT;
+ val |= rate << OMAP_CTRL_PIPE3_PWRCTL_CLK_FREQ_SHIFT;
} else {
- val &= ~OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK;
- val |= OMAP_CTRL_USB3_PHY_TX_RX_POWEROFF <<
- OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT;
+ val &= ~OMAP_CTRL_PIPE3_PWRCTL_CLK_CMD_MASK;
+ val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF <<
+ OMAP_CTRL_PIPE3_PWRCTL_CLK_CMD_SHIFT;
}
break;

case OMAP_CTRL_TYPE_DRA7:
- val_aux = readl(control_usb->power_aux);
+ val_aux = readl(control_phy->power_aux);
if (on) {
val &= ~OMAP_CTRL_USB2_PHY_PD;
val_aux |= 0x100;
@@ -88,70 +88,70 @@ void omap_control_usb_phy_power(struct device *dev, int on)
val_aux &= ~0x100;
}

- writel(val_aux, control_usb->power_aux);
+ writel(val_aux, control_phy->power_aux);
break;
default:
dev_err(dev, "%s: type %d not recognized\n",
- __func__, control_usb->type);
+ __func__, control_phy->type);
break;
}

- writel(val, control_usb->power);
+ writel(val, control_phy->power);
}
-EXPORT_SYMBOL_GPL(omap_control_usb_phy_power);
+EXPORT_SYMBOL_GPL(omap_control_phy_power);

/**
* omap_control_usb_host_mode - set AVALID, VBUSVALID and ID pin in grounded
- * @ctrl_usb: struct omap_control_usb *
+ * @ctrl_phy: struct omap_control_phy *
*
* Writes to the mailbox register to notify the usb core that a usb
* device has been connected.
*/
-static void omap_control_usb_host_mode(struct omap_control_usb *ctrl_usb)
+static void omap_control_usb_host_mode(struct omap_control_phy *ctrl_phy)
{
u32 val;

- val = readl(ctrl_usb->otghs_control);
+ val = readl(ctrl_phy->otghs_control);
val &= ~(OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND);
val |= OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID;
- writel(val, ctrl_usb->otghs_control);
+ writel(val, ctrl_phy->otghs_control);
}

/**
* omap_control_usb_device_mode - set AVALID, VBUSVALID and ID pin in high
* impedance
- * @ctrl_usb: struct omap_control_usb *
+ * @ctrl_phy: struct omap_control_phy *
*
* Writes to the mailbox register to notify the usb core that it has been
* connected to a usb host.
*/
-static void omap_control_usb_device_mode(struct omap_control_usb *ctrl_usb)
+static void omap_control_usb_device_mode(struct omap_control_phy *ctrl_phy)
{
u32 val;

- val = readl(ctrl_usb->otghs_control);
+ val = readl(ctrl_phy->otghs_control);
val &= ~OMAP_CTRL_DEV_SESSEND;
val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_AVALID |
OMAP_CTRL_DEV_VBUSVALID;
- writel(val, ctrl_usb->otghs_control);
+ writel(val, ctrl_phy->otghs_control);
}

/**
* omap_control_usb_set_sessionend - Enable SESSIONEND and IDIG to high
* impedance
- * @ctrl_usb: struct omap_control_usb *
+ * @ctrl_phy: struct omap_control_phy *
*
* Writes to the mailbox register to notify the usb core it's now in
* disconnected state.
*/
-static void omap_control_usb_set_sessionend(struct omap_control_usb *ctrl_usb)
+static void omap_control_usb_set_sessionend(struct omap_control_phy *ctrl_phy)
{
u32 val;

- val = readl(ctrl_usb->otghs_control);
+ val = readl(ctrl_phy->otghs_control);
val &= ~(OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID);
val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND;
- writel(val, ctrl_usb->otghs_control);
+ writel(val, ctrl_phy->otghs_control);
}

/**
@@ -166,30 +166,30 @@ static void omap_control_usb_set_sessionend(struct omap_control_usb *ctrl_usb)
void omap_control_usb_set_mode(struct device *dev,
enum omap_control_usb_mode mode)
{
- struct omap_control_usb *ctrl_usb;
+ struct omap_control_phy *ctrl_phy;

if (IS_ERR(dev) || !dev)
return;

- ctrl_usb = dev_get_drvdata(dev);
+ ctrl_phy = dev_get_drvdata(dev);

- if (!ctrl_usb) {
+ if (!ctrl_phy) {
dev_err(dev, "Invalid control usb device\n");
return;
}

- if (ctrl_usb->type != OMAP_CTRL_TYPE_OMAP4)
+ if (ctrl_phy->type != OMAP_CTRL_TYPE_OMAP4)
return;

switch (mode) {
case USB_MODE_HOST:
- omap_control_usb_host_mode(ctrl_usb);
+ omap_control_usb_host_mode(ctrl_phy);
break;
case USB_MODE_DEVICE:
- omap_control_usb_device_mode(ctrl_usb);
+ omap_control_usb_device_mode(ctrl_phy);
break;
case USB_MODE_DISCONNECT:
- omap_control_usb_set_sessionend(ctrl_usb);
+ omap_control_usb_set_sessionend(ctrl_phy);
break;
default:
dev_vdbg(dev, "invalid omap control usb mode\n");
@@ -197,77 +197,77 @@ void omap_control_usb_set_mode(struct device *dev,
}
EXPORT_SYMBOL_GPL(omap_control_usb_set_mode);

-static const struct of_device_id omap_control_usb_id_table[];
+static const struct of_device_id omap_control_phy_id_table[];

-static int omap_control_usb_probe(struct platform_device *pdev)
+static int omap_control_phy_probe(struct platform_device *pdev)
{
struct resource *res;
const struct of_device_id *of_id;
- struct omap_control_usb *control_usb;
+ struct omap_control_phy *control_phy;

- of_id = of_match_device(omap_control_usb_id_table, &pdev->dev);
+ of_id = of_match_device(omap_control_phy_id_table, &pdev->dev);
if (!of_id)
return -EINVAL;

- control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb),
+ control_phy = devm_kzalloc(&pdev->dev, sizeof(*control_phy),
GFP_KERNEL);
- if (!control_usb) {
+ if (!control_phy) {
dev_err(&pdev->dev, "unable to alloc memory for control usb\n");
return -ENOMEM;
}

- control_usb->dev = &pdev->dev;
- control_usb->type = *(enum omap_control_usb_type *)of_id->data;
+ control_phy->dev = &pdev->dev;
+ control_phy->type = *(enum omap_control_phy_type *)of_id->data;

- if (control_usb->type == OMAP_CTRL_TYPE_OMAP4) {
+ if (control_phy->type == OMAP_CTRL_TYPE_OMAP4) {
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"otghs_control");
- control_usb->otghs_control = devm_ioremap_resource(
+ control_phy->otghs_control = devm_ioremap_resource(
&pdev->dev, res);
- if (IS_ERR(control_usb->otghs_control))
- return PTR_ERR(control_usb->otghs_control);
+ if (IS_ERR(control_phy->otghs_control))
+ return PTR_ERR(control_phy->otghs_control);
} else {
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"power");
- control_usb->power = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(control_usb->power)) {
+ control_phy->power = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(control_phy->power)) {
dev_err(&pdev->dev, "Couldn't get power register\n");
- return PTR_ERR(control_usb->power);
+ return PTR_ERR(control_phy->power);
}
}

- if (control_usb->type == OMAP_CTRL_TYPE_USB3) {
- control_usb->sys_clk = devm_clk_get(control_usb->dev,
+ if (control_phy->type == OMAP_CTRL_TYPE_USB3) {
+ control_phy->sys_clk = devm_clk_get(control_phy->dev,
"sys_clkin");
- if (IS_ERR(control_usb->sys_clk)) {
+ if (IS_ERR(control_phy->sys_clk)) {
pr_err("%s: unable to get sys_clkin\n", __func__);
return -EINVAL;
}
}

- if (control_usb->type == OMAP_CTRL_TYPE_DRA7) {
+ if (control_phy->type == OMAP_CTRL_TYPE_DRA7) {
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"power_aux");
- control_usb->power_aux = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(control_usb->power_aux)) {
+ control_phy->power_aux = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(control_phy->power_aux)) {
dev_err(&pdev->dev, "Couldn't get power_aux register\n");
- return PTR_ERR(control_usb->power_aux);
+ return PTR_ERR(control_phy->power_aux);
}
}

- dev_set_drvdata(control_usb->dev, control_usb);
+ dev_set_drvdata(control_phy->dev, control_phy);

return 0;
}

#ifdef CONFIG_OF

-static const enum omap_control_usb_type omap4_data = OMAP_CTRL_TYPE_OMAP4;
-static const enum omap_control_usb_type usb2_data = OMAP_CTRL_TYPE_USB2;
-static const enum omap_control_usb_type usb3_data = OMAP_CTRL_TYPE_USB3;
-static const enum omap_control_usb_type dra7_data = OMAP_CTRL_TYPE_DRA7;
+static const enum omap_control_phy_type omap4_data = OMAP_CTRL_TYPE_OMAP4;
+static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2;
+static const enum omap_control_phy_type usb3_data = OMAP_CTRL_TYPE_USB3;
+static const enum omap_control_phy_type dra7_data = OMAP_CTRL_TYPE_DRA7;

-static const struct of_device_id omap_control_usb_id_table[] = {
+static const struct of_device_id omap_control_phy_id_table[] = {
{
.compatible = "ti,omap4-control-usb",
.data = &omap4_data,
@@ -286,31 +286,31 @@ static const struct of_device_id omap_control_usb_id_table[] = {
},
{},
};
-MODULE_DEVICE_TABLE(of, omap_control_usb_id_table);
+MODULE_DEVICE_TABLE(of, omap_control_phy_id_table);
#endif

-static struct platform_driver omap_control_usb_driver = {
- .probe = omap_control_usb_probe,
+static struct platform_driver omap_control_phy_driver = {
+ .probe = omap_control_phy_probe,
.driver = {
.name = "omap-control-usb",
.owner = THIS_MODULE,
- .of_match_table = of_match_ptr(omap_control_usb_id_table),
+ .of_match_table = of_match_ptr(omap_control_phy_id_table),
},
};

-static int __init omap_control_usb_init(void)
+static int __init omap_control_phy_init(void)
{
- return platform_driver_register(&omap_control_usb_driver);
+ return platform_driver_register(&omap_control_phy_driver);
}
-subsys_initcall(omap_control_usb_init);
+subsys_initcall(omap_control_phy_init);

-static void __exit omap_control_usb_exit(void)
+static void __exit omap_control_phy_exit(void)
{
- platform_driver_unregister(&omap_control_usb_driver);
+ platform_driver_unregister(&omap_control_phy_driver);
}
-module_exit(omap_control_usb_exit);
+module_exit(omap_control_phy_exit);

-MODULE_ALIAS("platform: omap_control_usb");
+MODULE_ALIAS("platform: omap_control_phy");
MODULE_AUTHOR("Texas Instruments Inc.");
MODULE_DESCRIPTION("OMAP Control Module USB Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-omap-pipe3.c b/drivers/phy/phy-omap-pipe3.c
index ee9a901..63de0f8 100644
--- a/drivers/phy/phy-omap-pipe3.c
+++ b/drivers/phy/phy-omap-pipe3.c
@@ -26,7 +26,7 @@
#include <linux/err.h>
#include <linux/pm_runtime.h>
#include <linux/delay.h>
-#include <linux/usb/omap_control_usb.h>
+#include <linux/phy/omap_control_phy.h>
#include <linux/of_platform.h>

#define PLL_STATUS 0x00000004
@@ -101,7 +101,7 @@ static int omap_pipe3_power_off(struct phy *x)
udelay(1);
} while (--timeout);

- omap_control_usb_phy_power(phy->control_dev, 0);
+ omap_control_phy_power(phy->control_dev, 0);

return 0;
}
@@ -194,7 +194,7 @@ static int omap_pipe3_init(struct phy *x)
if (ret)
return ret;

- omap_control_usb_phy_power(phy->control_dev, 1);
+ omap_control_phy_power(phy->control_dev, 1);

return 0;
}
@@ -270,7 +270,7 @@ static int omap_pipe3_probe(struct platform_device *pdev)

phy->control_dev = &control_pdev->dev;

- omap_control_usb_phy_power(phy->control_dev, 0);
+ omap_control_phy_power(phy->control_dev, 0);

platform_set_drvdata(pdev, phy);
pm_runtime_enable(phy->dev);
diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c
index 6c78584..d3ea81d 100644
--- a/drivers/phy/phy-omap-usb2.c
+++ b/drivers/phy/phy-omap-usb2.c
@@ -27,7 +27,7 @@
#include <linux/err.h>
#include <linux/pm_runtime.h>
#include <linux/delay.h>
-#include <linux/usb/omap_control_usb.h>
+#include <linux/phy/omap_control_phy.h>
#include <linux/of_platform.h>
#include <linux/phy/phy.h>

@@ -102,7 +102,7 @@ static int omap_usb_power_off(struct phy *x)
{
struct omap_usb *phy = phy_get_drvdata(x);

- omap_control_usb_phy_power(phy->control_dev, 0);
+ omap_control_phy_power(phy->control_dev, 0);

return 0;
}
@@ -111,7 +111,7 @@ static int omap_usb_power_on(struct phy *x)
{
struct omap_usb *phy = phy_get_drvdata(x);

- omap_control_usb_phy_power(phy->control_dev, 1);
+ omap_control_phy_power(phy->control_dev, 1);

return 0;
}
@@ -172,7 +172,7 @@ static int omap_usb2_probe(struct platform_device *pdev)
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);

- omap_control_usb_phy_power(phy->control_dev, 0);
+ omap_control_phy_power(phy->control_dev, 0);

otg->set_host = omap_usb_set_host;
otg->set_peripheral = omap_usb_set_peripheral;
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 9eab645..4f5ef0b 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -37,7 +37,7 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/usb/musb-omap.h>
-#include <linux/usb/omap_control_usb.h>
+#include <linux/phy/omap_control_phy.h>
#include <linux/of_platform.h>

#include "musb_core.h"
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index d1c9683..255cda9 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -12,7 +12,6 @@ obj-$(CONFIG_FSL_USB2_OTG) += phy-fsl-usb2.o
obj-$(CONFIG_ISP1301_OMAP) += phy-isp1301-omap.o
obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o
obj-$(CONFIG_NOP_USB_XCEIV) += phy-generic.o
-obj-$(CONFIG_OMAP_CONTROL_USB) += phy-omap-control.o
obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o
obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o
obj-$(CONFIG_SAMSUNG_USB3PHY) += phy-samsung-usb3.o
diff --git a/include/linux/usb/omap_control_usb.h b/include/linux/phy/omap_control_phy.h
similarity index 69%
rename from include/linux/usb/omap_control_usb.h
rename to include/linux/phy/omap_control_phy.h
index 8008e8d..9d6b08f 100644
--- a/include/linux/usb/omap_control_usb.h
+++ b/include/linux/phy/omap_control_phy.h
@@ -1,5 +1,5 @@
/*
- * omap_control_usb.h - Header file for the USB part of control module.
+ * omap_control_phy.h - Header file for the USB part of control module.
*
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
* This program is free software; you can redistribute it and/or modify
@@ -16,17 +16,17 @@
*
*/

-#ifndef __OMAP_CONTROL_USB_H__
-#define __OMAP_CONTROL_USB_H__
+#ifndef __OMAP_CONTROL_PHY_H__
+#define __OMAP_CONTROL_PHY_H__

-enum omap_control_usb_type {
+enum omap_control_phy_type {
OMAP_CTRL_TYPE_OMAP4 = 1, /* Mailbox OTGHS_CONTROL */
OMAP_CTRL_TYPE_USB2, /* USB2_PHY, power down in CONTROL_DEV_CONF */
OMAP_CTRL_TYPE_USB3, /* USB3_PHY, DPLL & seperate Rx/Tx power */
OMAP_CTRL_TYPE_DRA7, /* USB2 PHY, power and power_aux e.g. DRA7 */
};

-struct omap_control_usb {
+struct omap_control_phy {
struct device *dev;

u32 __iomem *otghs_control;
@@ -35,7 +35,7 @@ struct omap_control_usb {

struct clk *sys_clk;

- enum omap_control_usb_type type;
+ enum omap_control_phy_type type;
};

enum omap_control_usb_mode {
@@ -53,24 +53,24 @@ enum omap_control_usb_mode {
#define OMAP_CTRL_DEV_SESSEND BIT(3)
#define OMAP_CTRL_DEV_IDDIG BIT(4)

-#define OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK 0x003FC000
-#define OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT 0xE
+#define OMAP_CTRL_PIPE3_PWRCTL_CLK_CMD_MASK 0x003FC000
+#define OMAP_CTRL_PIPE3_PWRCTL_CLK_CMD_SHIFT 0xE

-#define OMAP_CTRL_USB_PWRCTL_CLK_FREQ_MASK 0xFFC00000
-#define OMAP_CTRL_USB_PWRCTL_CLK_FREQ_SHIFT 0x16
+#define OMAP_CTRL_PIPE3_PWRCTL_CLK_FREQ_MASK 0xFFC00000
+#define OMAP_CTRL_PIPE3_PWRCTL_CLK_FREQ_SHIFT 0x16

-#define OMAP_CTRL_USB3_PHY_TX_RX_POWERON 0x3
-#define OMAP_CTRL_USB3_PHY_TX_RX_POWEROFF 0x0
+#define OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON 0x3
+#define OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF 0x0

#define OMAP_CTRL_USB2_PHY_PD BIT(28)

-#if IS_ENABLED(CONFIG_OMAP_CONTROL_USB)
-extern void omap_control_usb_phy_power(struct device *dev, int on);
+#if IS_ENABLED(CONFIG_OMAP_CONTROL_PHY)
+extern void omap_control_phy_power(struct device *dev, int on);
extern void omap_control_usb_set_mode(struct device *dev,
enum omap_control_usb_mode mode);
#else

-static inline void omap_control_usb_phy_power(struct device *dev, int on)
+static inline void omap_control_phy_power(struct device *dev, int on)
{
}

@@ -80,4 +80,4 @@ static inline void omap_control_usb_set_mode(struct device *dev,
}
#endif

-#endif /* __OMAP_CONTROL_USB_H__ */
+#endif /* __OMAP_CONTROL_PHY_H__ */
--
1.7.10.4

2013-09-02 15:44:39

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [PATCH 3/7] drivers: phy: usb3/pipe3: Adapt pipe3 driver to Generic PHY Framework

Adapted omap-usb3 PHY driver to Generic PHY Framework and moved phy-omap-usb3
driver in drivers/usb/phy to drivers/phy and also renamed the file to
phy-omap-pipe3 since this same driver will be used for SATA PHY and
PCIE PHY.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
Documentation/devicetree/bindings/usb/usb-phy.txt | 5 +-
drivers/phy/Kconfig | 10 +
drivers/phy/Makefile | 1 +
.../phy/phy-omap-usb3.c => phy/phy-omap-pipe3.c} | 206 +++++++++++---------
drivers/usb/phy/Kconfig | 11 --
drivers/usb/phy/Makefile | 1 -
include/linux/phy/omap_pipe3.h | 52 +++++
7 files changed, 177 insertions(+), 109 deletions(-)
rename drivers/{usb/phy/phy-omap-usb3.c => phy/phy-omap-pipe3.c} (57%)
create mode 100644 include/linux/phy/omap_pipe3.h

diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/usb/usb-phy.txt
index c0245c8..36bdb17 100644
--- a/Documentation/devicetree/bindings/usb/usb-phy.txt
+++ b/Documentation/devicetree/bindings/usb/usb-phy.txt
@@ -21,10 +21,11 @@ usb2phy@4a0ad080 {
#phy-cells = <0>;
};

-OMAP USB3 PHY
+OMAP PIPE3 PHY

Required properties:
- - compatible: Should be "ti,omap-usb3"
+ - compatible: Should be "ti,omap-usb3", "ti,omap-pipe3", "ti,omap-sata"
+ or "ti,omap-pcie"
- reg : Address and length of the register set for the device.
- reg-names: The names of the register addresses corresponding to the registers
filled in "reg".
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index ac239ac..5c2e7a0 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -27,6 +27,16 @@ config OMAP_USB2
The USB OTG controller communicates with the comparator using this
driver.

+config OMAP_PIPE3
+ tristate "OMAP PIPE3 PHY Driver"
+ select GENERIC_PHY
+ select OMAP_CONTROL_USB
+ help
+ Enable this to support the PIPE3 PHY that is part of SOC. This
+ driver takes care of all the PHY functionality apart from comparator.
+ This driver interacts with the "OMAP Control PHY Driver" to power
+ on/off the PHY.
+
config TWL4030_USB
tristate "TWL4030 USB Transceiver Driver"
depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 0dd8a98..48bf9f2 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -4,4 +4,5 @@

obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
+obj-$(CONFIG_OMAP_PIPE3) += phy-omap-pipe3.o
obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
diff --git a/drivers/usb/phy/phy-omap-usb3.c b/drivers/phy/phy-omap-pipe3.c
similarity index 57%
rename from drivers/usb/phy/phy-omap-usb3.c
rename to drivers/phy/phy-omap-pipe3.c
index 4004f82..ee9a901 100644
--- a/drivers/usb/phy/phy-omap-usb3.c
+++ b/drivers/phy/phy-omap-pipe3.c
@@ -1,5 +1,5 @@
/*
- * omap-usb3 - USB PHY, talking to dwc3 controller in OMAP.
+ * omap-pipe3 - PHY driver for SATA, USB and PCIE in OMAP platforms
*
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
* This program is free software; you can redistribute it and/or modify
@@ -19,7 +19,8 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <linux/usb/omap_usb.h>
+#include <linux/phy/omap_pipe3.h>
+#include <linux/phy/phy.h>
#include <linux/of.h>
#include <linux/clk.h>
#include <linux/err.h>
@@ -52,17 +53,17 @@

/*
* This is an Empirical value that works, need to confirm the actual
- * value required for the USB3PHY_PLL_CONFIGURATION2.PLL_IDLE status
- * to be correctly reflected in the USB3PHY_PLL_STATUS register.
+ * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status
+ * to be correctly reflected in the PIPE3PHY_PLL_STATUS register.
*/
# define PLL_IDLE_TIME 100;

-struct usb_dpll_map {
+struct pipe3_dpll_map {
unsigned long rate;
- struct usb_dpll_params params;
+ struct pipe3_dpll_params params;
};

-static struct usb_dpll_map dpll_map[] = {
+static struct pipe3_dpll_map dpll_map[] = {
{12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */
{16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */
{19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */
@@ -71,7 +72,7 @@ static struct usb_dpll_map dpll_map[] = {
{38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */
};

-static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate)
+static struct pipe3_dpll_params *omap_pipe3_get_dpll_params(unsigned long rate)
{
int i;

@@ -83,110 +84,113 @@ static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate)
return 0;
}

-static int omap_usb3_suspend(struct usb_phy *x, int suspend)
+static int omap_pipe3_power_off(struct phy *x)
{
- struct omap_usb *phy = phy_to_omapusb(x);
- int val;
+ struct omap_pipe3 *phy = phy_get_drvdata(x);
+ int val;
int timeout = PLL_IDLE_TIME;

- if (suspend && !phy->is_suspended) {
- val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
- val |= PLL_IDLE;
- omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
-
- do {
- val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
- if (val & PLL_TICOPWDN)
- break;
- udelay(1);
- } while (--timeout);
-
- omap_control_usb_phy_power(phy->control_dev, 0);
-
- phy->is_suspended = 1;
- } else if (!suspend && phy->is_suspended) {
- phy->is_suspended = 0;
-
- val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
- val &= ~PLL_IDLE;
- omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
-
- do {
- val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
- if (!(val & PLL_TICOPWDN))
- break;
- udelay(1);
- } while (--timeout);
- }
+ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
+ val |= PLL_IDLE;
+ omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
+
+ do {
+ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
+ if (val & PLL_TICOPWDN)
+ break;
+ udelay(1);
+ } while (--timeout);
+
+ omap_control_usb_phy_power(phy->control_dev, 0);
+
+ return 0;
+}
+
+static int omap_pipe3_power_on(struct phy *x)
+{
+ struct omap_pipe3 *phy = phy_get_drvdata(x);
+ int val;
+ int timeout = PLL_IDLE_TIME;
+
+ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
+ val &= ~PLL_IDLE;
+ omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
+
+ do {
+ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
+ if (!(val & PLL_TICOPWDN))
+ break;
+ udelay(1);
+ } while (--timeout);

return 0;
}

-static void omap_usb_dpll_relock(struct omap_usb *phy)
+static void omap_pipe3_dpll_relock(struct omap_pipe3 *phy)
{
u32 val;
unsigned long timeout;

- omap_usb_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
+ omap_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);

timeout = jiffies + msecs_to_jiffies(20);
do {
- val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
+ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
if (val & PLL_LOCK)
break;
} while (!WARN_ON(time_after(jiffies, timeout)));
}

-static int omap_usb_dpll_lock(struct omap_usb *phy)
+static int omap_pipe3_dpll_lock(struct omap_pipe3 *phy)
{
u32 val;
unsigned long rate;
- struct usb_dpll_params *dpll_params;
+ struct pipe3_dpll_params *dpll_params;

rate = clk_get_rate(phy->sys_clk);
- dpll_params = omap_usb3_get_dpll_params(rate);
+ dpll_params = omap_pipe3_get_dpll_params(rate);
if (!dpll_params) {
dev_err(phy->dev,
"No DPLL configuration for %lu Hz SYS CLK\n", rate);
return -EINVAL;
}

- val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
+ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
val &= ~PLL_REGN_MASK;
val |= dpll_params->n << PLL_REGN_SHIFT;
- omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
+ omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);

- val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
+ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
val &= ~PLL_SELFREQDCO_MASK;
val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
- omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
+ omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);

- val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
+ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
val &= ~PLL_REGM_MASK;
val |= dpll_params->m << PLL_REGM_SHIFT;
- omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
+ omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);

- val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
+ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
val &= ~PLL_REGM_F_MASK;
val |= dpll_params->mf << PLL_REGM_F_SHIFT;
- omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
+ omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);

- val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
+ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
val &= ~PLL_SD_MASK;
val |= dpll_params->sd << PLL_SD_SHIFT;
- omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
+ omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);

- omap_usb_dpll_relock(phy);
+ omap_pipe3_dpll_relock(phy);

return 0;
}

-static int omap_usb3_init(struct usb_phy *x)
+static int omap_pipe3_init(struct phy *x)
{
- struct omap_usb *phy = phy_to_omapusb(x);
+ struct omap_pipe3 *phy = phy_get_drvdata(x);
int ret;

- ret = omap_usb_dpll_lock(phy);
+ ret = omap_pipe3_dpll_lock(phy);
if (ret)
return ret;

@@ -195,9 +199,18 @@ static int omap_usb3_init(struct usb_phy *x)
return 0;
}

-static int omap_usb3_probe(struct platform_device *pdev)
+static struct phy_ops ops = {
+ .init = omap_pipe3_init,
+ .power_on = omap_pipe3_power_on,
+ .power_off = omap_pipe3_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int omap_pipe3_probe(struct platform_device *pdev)
{
- struct omap_usb *phy;
+ struct omap_pipe3 *phy;
+ struct phy *generic_phy;
+ struct phy_provider *phy_provider;
struct resource *res;
struct device_node *node = pdev->dev.of_node;
struct device_node *control_node;
@@ -208,7 +221,7 @@ static int omap_usb3_probe(struct platform_device *pdev)

phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
if (!phy) {
- dev_err(&pdev->dev, "unable to alloc mem for OMAP USB3 PHY\n");
+ dev_err(&pdev->dev, "unable to alloc mem for OMAP PIPE3 PHY\n");
return -ENOMEM;
}

@@ -219,13 +232,6 @@ static int omap_usb3_probe(struct platform_device *pdev)

phy->dev = &pdev->dev;

- phy->phy.dev = phy->dev;
- phy->phy.label = "omap-usb3";
- phy->phy.init = omap_usb3_init;
- phy->phy.set_suspend = omap_usb3_suspend;
- phy->phy.type = USB_PHY_TYPE_USB3;
-
- phy->is_suspended = 1;
phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
if (IS_ERR(phy->wkupclk)) {
dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
@@ -251,6 +257,11 @@ static int omap_usb3_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Failed to get control device phandle\n");
return -EINVAL;
}
+ phy_provider = devm_of_phy_provider_register(phy->dev,
+ of_phy_simple_xlate);
+ if (IS_ERR(phy_provider))
+ return PTR_ERR(phy_provider);
+
control_pdev = of_find_device_by_node(control_node);
if (!control_pdev) {
dev_err(&pdev->dev, "Failed to get control device\n");
@@ -260,23 +271,27 @@ static int omap_usb3_probe(struct platform_device *pdev)
phy->control_dev = &control_pdev->dev;

omap_control_usb_phy_power(phy->control_dev, 0);
- usb_add_phy_dev(&phy->phy);

platform_set_drvdata(pdev, phy);
-
pm_runtime_enable(phy->dev);
+
+ generic_phy = devm_phy_create(phy->dev, &ops, NULL);
+ if (IS_ERR(generic_phy))
+ return PTR_ERR(generic_phy);
+
+ phy_set_drvdata(generic_phy, phy);
+
pm_runtime_get(&pdev->dev);

return 0;
}

-static int omap_usb3_remove(struct platform_device *pdev)
+static int omap_pipe3_remove(struct platform_device *pdev)
{
- struct omap_usb *phy = platform_get_drvdata(pdev);
+ struct omap_pipe3 *phy = platform_get_drvdata(pdev);

clk_unprepare(phy->wkupclk);
clk_unprepare(phy->optclk);
- usb_remove_phy(&phy->phy);
if (!pm_runtime_suspended(&pdev->dev))
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
@@ -286,10 +301,9 @@ static int omap_usb3_remove(struct platform_device *pdev)

#ifdef CONFIG_PM_RUNTIME

-static int omap_usb3_runtime_suspend(struct device *dev)
+static int omap_pipe3_runtime_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct omap_usb *phy = platform_get_drvdata(pdev);
+ struct omap_pipe3 *phy = dev_get_drvdata(dev);

clk_disable(phy->wkupclk);
clk_disable(phy->optclk);
@@ -297,11 +311,10 @@ static int omap_usb3_runtime_suspend(struct device *dev)
return 0;
}

-static int omap_usb3_runtime_resume(struct device *dev)
+static int omap_pipe3_runtime_resume(struct device *dev)
{
u32 ret = 0;
- struct platform_device *pdev = to_platform_device(dev);
- struct omap_usb *phy = platform_get_drvdata(pdev);
+ struct omap_pipe3 *phy = dev_get_drvdata(dev);

ret = clk_enable(phy->optclk);
if (ret) {
@@ -324,38 +337,41 @@ err1:
return ret;
}

-static const struct dev_pm_ops omap_usb3_pm_ops = {
- SET_RUNTIME_PM_OPS(omap_usb3_runtime_suspend, omap_usb3_runtime_resume,
- NULL)
+static const struct dev_pm_ops omap_pipe3_pm_ops = {
+ SET_RUNTIME_PM_OPS(omap_pipe3_runtime_suspend,
+ omap_pipe3_runtime_resume, NULL)
};

-#define DEV_PM_OPS (&omap_usb3_pm_ops)
+#define DEV_PM_OPS (&omap_pipe3_pm_ops)
#else
#define DEV_PM_OPS NULL
#endif

#ifdef CONFIG_OF
-static const struct of_device_id omap_usb3_id_table[] = {
+static const struct of_device_id omap_pipe3_id_table[] = {
+ { .compatible = "ti,omap-pipe3" },
+ { .compatible = "ti,omap-sata" },
+ { .compatible = "ti,omap-pcie" },
{ .compatible = "ti,omap-usb3" },
{}
};
-MODULE_DEVICE_TABLE(of, omap_usb3_id_table);
+MODULE_DEVICE_TABLE(of, omap_pipe3_id_table);
#endif

-static struct platform_driver omap_usb3_driver = {
- .probe = omap_usb3_probe,
- .remove = omap_usb3_remove,
+static struct platform_driver omap_pipe3_driver = {
+ .probe = omap_pipe3_probe,
+ .remove = omap_pipe3_remove,
.driver = {
- .name = "omap-usb3",
+ .name = "omap-pipe3",
.owner = THIS_MODULE,
.pm = DEV_PM_OPS,
- .of_match_table = of_match_ptr(omap_usb3_id_table),
+ .of_match_table = of_match_ptr(omap_pipe3_id_table),
},
};

-module_platform_driver(omap_usb3_driver);
+module_platform_driver(omap_pipe3_driver);

-MODULE_ALIAS("platform: omap_usb3");
+MODULE_ALIAS("platform: omap_pipe3");
MODULE_AUTHOR("Texas Instruments Inc.");
-MODULE_DESCRIPTION("OMAP USB3 phy driver");
+MODULE_DESCRIPTION("OMAP PIPE3 phy driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index d69cdad..0210e03 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -66,17 +66,6 @@ config OMAP_CONTROL_USB
power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
additional register to power on USB3 PHY.

-config OMAP_USB3
- tristate "OMAP USB3 PHY Driver"
- depends on ARCH_OMAP2PLUS || COMPILE_TEST
- select OMAP_CONTROL_USB
- select USB_PHY
- help
- Enable this to support the USB3 PHY that is part of SOC. This
- driver takes care of all the PHY functionality apart from comparator.
- This driver interacts with the "OMAP Control USB Driver" to power
- on/off the PHY.
-
config AM335X_CONTROL_USB
tristate

diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index 51968d7..d1c9683 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -13,7 +13,6 @@ obj-$(CONFIG_ISP1301_OMAP) += phy-isp1301-omap.o
obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o
obj-$(CONFIG_NOP_USB_XCEIV) += phy-generic.o
obj-$(CONFIG_OMAP_CONTROL_USB) += phy-omap-control.o
-obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o
obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o
obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o
obj-$(CONFIG_SAMSUNG_USB3PHY) += phy-samsung-usb3.o
diff --git a/include/linux/phy/omap_pipe3.h b/include/linux/phy/omap_pipe3.h
new file mode 100644
index 0000000..7329056
--- /dev/null
+++ b/include/linux/phy/omap_pipe3.h
@@ -0,0 +1,52 @@
+/*
+ * omap_pipe3.h -- omap pipe3 phy header file
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <[email protected]>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __DRIVERS_OMAP_PIPE3_H
+#define __DRIVERS_OMAP_PIPE3_H
+
+#include <linux/io.h>
+
+struct pipe3_dpll_params {
+ u16 m;
+ u8 n;
+ u8 freq:3;
+ u8 sd;
+ u32 mf;
+};
+
+struct omap_pipe3 {
+ void __iomem *pll_ctrl_base;
+ struct device *dev;
+ struct device *control_dev;
+ struct clk *wkupclk;
+ struct clk *sys_clk;
+ struct clk *optclk;
+};
+
+static inline u32 omap_pipe3_readl(void __iomem *addr, unsigned offset)
+{
+ return __raw_readl(addr + offset);
+}
+
+static inline void omap_pipe3_writel(void __iomem *addr, unsigned offset,
+ u32 data)
+{
+ __raw_writel(data, addr + offset);
+}
+
+#endif /* __DRIVERS_OMAP_PIPE3_H */
--
1.7.10.4

2013-09-02 15:44:37

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

Adapted dwc3 core to use the Generic PHY Framework. So for init, exit,
power_on and power_off the following APIs are used phy_init(), phy_exit(),
phy_power_on() and phy_power_off().

However using the old USB phy library wont be removed till the PHYs of all
other SoC's using dwc3 core is adapted to the Generic PHY Framework.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
Documentation/devicetree/bindings/usb/dwc3.txt | 6 ++-
drivers/usb/dwc3/Kconfig | 1 +
drivers/usb/dwc3/core.c | 49 ++++++++++++++++++++++++
drivers/usb/dwc3/core.h | 7 ++++
4 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
index e807635..471366d 100644
--- a/Documentation/devicetree/bindings/usb/dwc3.txt
+++ b/Documentation/devicetree/bindings/usb/dwc3.txt
@@ -6,11 +6,13 @@ Required properties:
- compatible: must be "snps,dwc3"
- reg : Address and length of the register set for the device
- interrupts: Interrupts used by the dwc3 controller.
+
+Optional properties:
- usb-phy : array of phandle for the PHY device. The first element
in the array is expected to be a handle to the USB2/HS PHY and
the second element is expected to be a handle to the USB3/SS PHY
-
-Optional properties:
+ - phys: from the *Generic PHY* bindings
+ - phy-names: from the *Generic PHY* bindings
- tx-fifo-resize: determines if the FIFO *has* to be reallocated.

This is usually a subnode to DWC3 glue to which it is connected.
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index cfc16dd..ad7ce83 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -3,6 +3,7 @@ config USB_DWC3
depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
depends on EXTCON
select USB_PHY
+ select GENERIC_PHY
select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
help
Say Y or M here if your system has a Dual Role SuperSpeed
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 428c29e..485d365 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -82,6 +82,12 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)

usb_phy_init(dwc->usb2_phy);
usb_phy_init(dwc->usb3_phy);
+
+ if (dwc->usb2_generic_phy)
+ phy_init(dwc->usb2_generic_phy);
+ if (dwc->usb3_generic_phy)
+ phy_init(dwc->usb3_generic_phy);
+
mdelay(100);

/* Clear USB3 PHY reset */
@@ -343,6 +349,11 @@ static void dwc3_core_exit(struct dwc3 *dwc)
{
usb_phy_shutdown(dwc->usb2_phy);
usb_phy_shutdown(dwc->usb3_phy);
+
+ if (dwc->usb2_generic_phy)
+ phy_power_off(dwc->usb2_generic_phy);
+ if (dwc->usb3_generic_phy)
+ phy_power_off(dwc->usb3_generic_phy);
}

#define DWC3_ALIGN_MASK (16 - 1)
@@ -427,6 +438,23 @@ static int dwc3_probe(struct platform_device *pdev)
dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
}

+ if (of_property_read_bool(node, "phys") || pdata->has_phy) {
+ dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
+ if (IS_ERR(dwc->usb2_generic_phy)) {
+ dev_err(dev, "no usb2 phy configured yet");
+ return PTR_ERR(dwc->usb2_generic_phy);
+ }
+
+ dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
+ if (IS_ERR(dwc->usb3_generic_phy)) {
+ dev_err(dev, "no usb3 phy configured yet");
+ return PTR_ERR(dwc->usb3_generic_phy);
+ }
+ } else {
+ dwc->usb2_generic_phy = NULL;
+ dwc->usb3_generic_phy = NULL;
+ }
+
/* default to superspeed if no maximum_speed passed */
if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
dwc->maximum_speed = USB_SPEED_SUPER;
@@ -450,6 +478,11 @@ static int dwc3_probe(struct platform_device *pdev)
usb_phy_set_suspend(dwc->usb2_phy, 0);
usb_phy_set_suspend(dwc->usb3_phy, 0);

+ if (dwc->usb2_generic_phy)
+ phy_power_on(dwc->usb2_generic_phy);
+ if (dwc->usb3_generic_phy)
+ phy_power_on(dwc->usb3_generic_phy);
+
spin_lock_init(&dwc->lock);
platform_set_drvdata(pdev, dwc);

@@ -576,6 +609,11 @@ static int dwc3_remove(struct platform_device *pdev)
usb_phy_set_suspend(dwc->usb2_phy, 1);
usb_phy_set_suspend(dwc->usb3_phy, 1);

+ if (dwc->usb2_generic_phy)
+ phy_power_off(dwc->usb2_generic_phy);
+ if (dwc->usb3_generic_phy)
+ phy_power_off(dwc->usb3_generic_phy);
+
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);

@@ -673,6 +711,11 @@ static int dwc3_suspend(struct device *dev)
usb_phy_shutdown(dwc->usb3_phy);
usb_phy_shutdown(dwc->usb2_phy);

+ if (dwc->usb2_generic_phy)
+ phy_exit(dwc->usb2_generic_phy);
+ if (dwc->usb3_generic_phy)
+ phy_exit(dwc->usb3_generic_phy);
+
return 0;
}

@@ -683,6 +726,12 @@ static int dwc3_resume(struct device *dev)

usb_phy_init(dwc->usb3_phy);
usb_phy_init(dwc->usb2_phy);
+
+ if (dwc->usb2_generic_phy)
+ phy_init(dwc->usb2_generic_phy);
+ if (dwc->usb3_generic_phy)
+ phy_init(dwc->usb3_generic_phy);
+
msleep(100);

spin_lock_irqsave(&dwc->lock, flags);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index f8af8d4..01ec7d7 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -31,6 +31,8 @@
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>

+#include <linux/phy/phy.h>
+
/* Global constants */
#define DWC3_EP0_BOUNCE_SIZE 512
#define DWC3_ENDPOINTS_NUM 32
@@ -613,6 +615,8 @@ struct dwc3_scratchpad_array {
* @dr_mode: requested mode of operation
* @usb2_phy: pointer to USB2 PHY
* @usb3_phy: pointer to USB3 PHY
+ * @usb2_generic_phy: pointer to USB2 PHY
+ * @usb3_generic_phy: pointer to USB3 PHY
* @dcfg: saved contents of DCFG register
* @gctl: saved contents of GCTL register
* @is_selfpowered: true when we are selfpowered
@@ -665,6 +669,9 @@ struct dwc3 {
struct usb_phy *usb2_phy;
struct usb_phy *usb3_phy;

+ struct phy *usb2_generic_phy;
+ struct phy *usb3_generic_phy;
+
void __iomem *regs;
size_t regs_size;

--
1.7.10.4

2013-09-02 15:45:59

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [PATCH 6/7] arm/dts: added dt properties to adapt to the new phy framwork

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
arch/arm/boot/dts/omap5.dtsi | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 94abef5..9fe71ff 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -651,7 +651,8 @@
compatible = "snps,dwc3";
reg = <0x4a030000 0x10000>;
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
- usb-phy = <&usb2_phy>, <&usb3_phy>;
+ phys = <&usb2_phy>, <&usb3_phy>;
+ phy-names = "usb2-phy", "usb3-phy";
tx-fifo-resize;
};
};
@@ -667,6 +668,7 @@
compatible = "ti,omap-usb2";
reg = <0x4a084000 0x7c>;
ctrl-module = <&omap_control_usb2phy>;
+ #phy-cells = <0>;
};

usb3_phy: usb3phy@4a084400 {
@@ -676,6 +678,7 @@
<0x4a084c00 0x40>;
reg-names = "phy_rx", "phy_tx", "pll_ctrl";
ctrl-module = <&omap_control_usb3phy>;
+ #phy-cells = <0>;
};
};

--
1.7.10.4

2013-09-02 15:46:45

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: [PATCH 1/7] usb: dwc3: get "usb_phy" only if the platform indicates the presence of PHY

There can be systems which does not have a external usb_phy, so get
usb_phy only if usb-phy property is added in the case of dt boot or if
platform_data indicates the presence of PHY. Also remove checking if
return value is -ENXIO since it's now changed to always enable usb_phy layer.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/usb/dwc3/Kconfig | 1 +
drivers/usb/dwc3/core.c | 60 +++++++++++++++++---------------------
drivers/usb/dwc3/platform_data.h | 1 +
3 files changed, 28 insertions(+), 34 deletions(-)

diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index f969ea2..cfc16dd 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -2,6 +2,7 @@ config USB_DWC3
tristate "DesignWare USB3 DRD Core Support"
depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
depends on EXTCON
+ select USB_PHY
select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
help
Say Y or M here if your system has a Dual Role SuperSpeed
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 474162e..428c29e 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -387,16 +387,38 @@ static int dwc3_probe(struct platform_device *pdev)
if (node) {
dwc->maximum_speed = of_usb_get_maximum_speed(node);

- dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
- dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
+ if (of_property_read_bool(node, "usb-phy")) {
+ dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev,
+ "usb-phy", 0);
+ if (IS_ERR(dwc->usb2_phy))
+ return PTR_ERR(dwc->usb2_phy);
+ dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev,
+ "usb-phy", 1);
+ if (IS_ERR(dwc->usb3_phy))
+ return PTR_ERR(dwc->usb3_phy);
+ } else {
+ dwc->usb2_phy = NULL;
+ dwc->usb3_phy = NULL;
+ }

dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
dwc->dr_mode = of_usb_get_dr_mode(node);
} else if (pdata) {
dwc->maximum_speed = pdata->maximum_speed;

- dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
- dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
+ if (pdata->has_phy) {
+ dwc->usb2_phy = devm_usb_get_phy(dev,
+ USB_PHY_TYPE_USB2);
+ if (IS_ERR(dwc->usb2_phy))
+ return PTR_ERR(dwc->usb2_phy);
+ dwc->usb3_phy = devm_usb_get_phy(dev,
+ USB_PHY_TYPE_USB3);
+ if (IS_ERR(dwc->usb3_phy))
+ return PTR_ERR(dwc->usb3_phy);
+ } else {
+ dwc->usb2_phy = NULL;
+ dwc->usb3_phy = NULL;
+ }

dwc->needs_fifo_resize = pdata->tx_fifo_resize;
dwc->dr_mode = pdata->dr_mode;
@@ -409,36 +431,6 @@ static int dwc3_probe(struct platform_device *pdev)
if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
dwc->maximum_speed = USB_SPEED_SUPER;

- if (IS_ERR(dwc->usb2_phy)) {
- ret = PTR_ERR(dwc->usb2_phy);
-
- /*
- * if -ENXIO is returned, it means PHY layer wasn't
- * enabled, so it makes no sense to return -EPROBE_DEFER
- * in that case, since no PHY driver will ever probe.
- */
- if (ret == -ENXIO)
- return ret;
-
- dev_err(dev, "no usb2 phy configured\n");
- return -EPROBE_DEFER;
- }
-
- if (IS_ERR(dwc->usb3_phy)) {
- ret = PTR_ERR(dwc->usb3_phy);
-
- /*
- * if -ENXIO is returned, it means PHY layer wasn't
- * enabled, so it makes no sense to return -EPROBE_DEFER
- * in that case, since no PHY driver will ever probe.
- */
- if (ret == -ENXIO)
- return ret;
-
- dev_err(dev, "no usb3 phy configured\n");
- return -EPROBE_DEFER;
- }
-
dwc->xhci_resources[0].start = res->start;
dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
DWC3_XHCI_REGS_END;
diff --git a/drivers/usb/dwc3/platform_data.h b/drivers/usb/dwc3/platform_data.h
index 7db34f0..5a5e068 100644
--- a/drivers/usb/dwc3/platform_data.h
+++ b/drivers/usb/dwc3/platform_data.h
@@ -24,4 +24,5 @@ struct dwc3_platform_data {
enum usb_device_speed maximum_speed;
enum usb_dr_mode dr_mode;
bool tx_fifo_resize;
+ bool has_phy;
};
--
1.7.10.4

2013-09-12 09:27:42

by Vivek Gautam

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

Hi Kishon,


On Mon, Sep 2, 2013 at 9:13 PM, Kishon Vijay Abraham I <[email protected]> wrote:
> Adapted dwc3 core to use the Generic PHY Framework. So for init, exit,
> power_on and power_off the following APIs are used phy_init(), phy_exit(),
> phy_power_on() and phy_power_off().
>
> However using the old USB phy library wont be removed till the PHYs of all
> other SoC's using dwc3 core is adapted to the Generic PHY Framework.
>
> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
> ---
> Documentation/devicetree/bindings/usb/dwc3.txt | 6 ++-
> drivers/usb/dwc3/Kconfig | 1 +
> drivers/usb/dwc3/core.c | 49 ++++++++++++++++++++++++
> drivers/usb/dwc3/core.h | 7 ++++
> 4 files changed, 61 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
> index e807635..471366d 100644
> --- a/Documentation/devicetree/bindings/usb/dwc3.txt
> +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
> @@ -6,11 +6,13 @@ Required properties:
> - compatible: must be "snps,dwc3"
> - reg : Address and length of the register set for the device
> - interrupts: Interrupts used by the dwc3 controller.
> +
> +Optional properties:
> - usb-phy : array of phandle for the PHY device. The first element
> in the array is expected to be a handle to the USB2/HS PHY and
> the second element is expected to be a handle to the USB3/SS PHY
> -
> -Optional properties:
> + - phys: from the *Generic PHY* bindings
> + - phy-names: from the *Generic PHY* bindings
> - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
>
> This is usually a subnode to DWC3 glue to which it is connected.
> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
> index cfc16dd..ad7ce83 100644
> --- a/drivers/usb/dwc3/Kconfig
> +++ b/drivers/usb/dwc3/Kconfig
> @@ -3,6 +3,7 @@ config USB_DWC3
> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
> depends on EXTCON
> select USB_PHY
> + select GENERIC_PHY
> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
> help
> Say Y or M here if your system has a Dual Role SuperSpeed
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index 428c29e..485d365 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -82,6 +82,12 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
>
> usb_phy_init(dwc->usb2_phy);
> usb_phy_init(dwc->usb3_phy);
> +
> + if (dwc->usb2_generic_phy)
> + phy_init(dwc->usb2_generic_phy);
> + if (dwc->usb3_generic_phy)
> + phy_init(dwc->usb3_generic_phy);
> +
> mdelay(100);
>
> /* Clear USB3 PHY reset */
> @@ -343,6 +349,11 @@ static void dwc3_core_exit(struct dwc3 *dwc)
> {
> usb_phy_shutdown(dwc->usb2_phy);
> usb_phy_shutdown(dwc->usb3_phy);
> +
> + if (dwc->usb2_generic_phy)
> + phy_power_off(dwc->usb2_generic_phy);
> + if (dwc->usb3_generic_phy)
> + phy_power_off(dwc->usb3_generic_phy);
> }
>
> #define DWC3_ALIGN_MASK (16 - 1)
> @@ -427,6 +438,23 @@ static int dwc3_probe(struct platform_device *pdev)
> dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
> }
>
> + if (of_property_read_bool(node, "phys") || pdata->has_phy) {
> + dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
> + if (IS_ERR(dwc->usb2_generic_phy)) {
> + dev_err(dev, "no usb2 phy configured yet");
> + return PTR_ERR(dwc->usb2_generic_phy);
> + }

I have a doubt here.
As i can see in the current phy drivers structuring, for OMAP there
are two phy drivers :
omap phy-omap-usb2 (talking to musb controller)
and phy-omap-usb3(talking to dwc3 controller).

Now dwc3 controller requests both usb2-phy (supported by phy-omap-usb2
?) and usb3-phy (supported by phy-omap-usb3 ?).
But phy-omap-usb2 is not the one designated to talk to DWC3
controller, then why does still DWC3 want to request usb2-phy, which
end of the day will be phy-omap-usb2.
May be i am wrong here since i don't have knowledge about OMAP h/w architecture.

Is it like phy-omap-usb2 includes UTMI phys for both musb controller
as well as dwc3 controller ?
Because if it is just for musb controller then which usb2-phy will
DWC3 be getting when it requests that type of phy.

As of now phy-samsung-usb3 driver is the interface for both UTMI+ and
PIPE3 phys for DWC3 DRD controller, and phy-samsung-usb2 driver is the
interface
for a separate USB 2.0 controller itself (not DWC3). So we have
something to correct things up for Samsung, since dwc3 initializing
the phy-samsung-usb2 is not a valid scenerio.

Can you please clarify things here ?
Thanks !!

> +
> + dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
> + if (IS_ERR(dwc->usb3_generic_phy)) {
> + dev_err(dev, "no usb3 phy configured yet");
> + return PTR_ERR(dwc->usb3_generic_phy);
> + }
> + } else {
> + dwc->usb2_generic_phy = NULL;
> + dwc->usb3_generic_phy = NULL;
> + }
> +

[...]


--
Best Regards
Vivek

2013-09-12 10:11:13

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

On Thursday 12 September 2013 02:57 PM, Vivek Gautam wrote:
> Hi Kishon,
>
>
> On Mon, Sep 2, 2013 at 9:13 PM, Kishon Vijay Abraham I <[email protected]> wrote:
>> Adapted dwc3 core to use the Generic PHY Framework. So for init, exit,
>> power_on and power_off the following APIs are used phy_init(), phy_exit(),
>> phy_power_on() and phy_power_off().
>>
>> However using the old USB phy library wont be removed till the PHYs of all
>> other SoC's using dwc3 core is adapted to the Generic PHY Framework.
>>
>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>> ---
>> Documentation/devicetree/bindings/usb/dwc3.txt | 6 ++-
>> drivers/usb/dwc3/Kconfig | 1 +
>> drivers/usb/dwc3/core.c | 49 ++++++++++++++++++++++++
>> drivers/usb/dwc3/core.h | 7 ++++
>> 4 files changed, 61 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
>> index e807635..471366d 100644
>> --- a/Documentation/devicetree/bindings/usb/dwc3.txt
>> +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
>> @@ -6,11 +6,13 @@ Required properties:
>> - compatible: must be "snps,dwc3"
>> - reg : Address and length of the register set for the device
>> - interrupts: Interrupts used by the dwc3 controller.
>> +
>> +Optional properties:
>> - usb-phy : array of phandle for the PHY device. The first element
>> in the array is expected to be a handle to the USB2/HS PHY and
>> the second element is expected to be a handle to the USB3/SS PHY
>> -
>> -Optional properties:
>> + - phys: from the *Generic PHY* bindings
>> + - phy-names: from the *Generic PHY* bindings
>> - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
>>
>> This is usually a subnode to DWC3 glue to which it is connected.
>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>> index cfc16dd..ad7ce83 100644
>> --- a/drivers/usb/dwc3/Kconfig
>> +++ b/drivers/usb/dwc3/Kconfig
>> @@ -3,6 +3,7 @@ config USB_DWC3
>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
>> depends on EXTCON
>> select USB_PHY
>> + select GENERIC_PHY
>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
>> help
>> Say Y or M here if your system has a Dual Role SuperSpeed
>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>> index 428c29e..485d365 100644
>> --- a/drivers/usb/dwc3/core.c
>> +++ b/drivers/usb/dwc3/core.c
>> @@ -82,6 +82,12 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
>>
>> usb_phy_init(dwc->usb2_phy);
>> usb_phy_init(dwc->usb3_phy);
>> +
>> + if (dwc->usb2_generic_phy)
>> + phy_init(dwc->usb2_generic_phy);
>> + if (dwc->usb3_generic_phy)
>> + phy_init(dwc->usb3_generic_phy);
>> +
>> mdelay(100);
>>
>> /* Clear USB3 PHY reset */
>> @@ -343,6 +349,11 @@ static void dwc3_core_exit(struct dwc3 *dwc)
>> {
>> usb_phy_shutdown(dwc->usb2_phy);
>> usb_phy_shutdown(dwc->usb3_phy);
>> +
>> + if (dwc->usb2_generic_phy)
>> + phy_power_off(dwc->usb2_generic_phy);
>> + if (dwc->usb3_generic_phy)
>> + phy_power_off(dwc->usb3_generic_phy);
>> }
>>
>> #define DWC3_ALIGN_MASK (16 - 1)
>> @@ -427,6 +438,23 @@ static int dwc3_probe(struct platform_device *pdev)
>> dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
>> }
>>
>> + if (of_property_read_bool(node, "phys") || pdata->has_phy) {
>> + dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
>> + if (IS_ERR(dwc->usb2_generic_phy)) {
>> + dev_err(dev, "no usb2 phy configured yet");
>> + return PTR_ERR(dwc->usb2_generic_phy);
>> + }
>
> I have a doubt here.
> As i can see in the current phy drivers structuring, for OMAP there
> are two phy drivers :
> omap phy-omap-usb2 (talking to musb controller)

It talks to dwc3 controller also ;-)

> and phy-omap-usb3(talking to dwc3 controller).
>
> Now dwc3 controller requests both usb2-phy (supported by phy-omap-usb2
> ?) and usb3-phy (supported by phy-omap-usb3 ?).
> But phy-omap-usb2 is not the one designated to talk to DWC3
> controller, then why does still DWC3 want to request usb2-phy, which
> end of the day will be phy-omap-usb2.
> May be i am wrong here since i don't have knowledge about OMAP h/w architecture.
>
> Is it like phy-omap-usb2 includes UTMI phys for both musb controller
> as well as dwc3 controller ?

right. It's needed for dwc3 too. The same USB2 PHY IP is used for both MUSB in
OMAP2+ platforms and DWC3 in OMAP5.

Thanks
Kishon

2013-09-12 10:27:33

by Vivek Gautam

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

On Thu, Sep 12, 2013 at 3:40 PM, Kishon Vijay Abraham I <[email protected]> wrote:
> On Thursday 12 September 2013 02:57 PM, Vivek Gautam wrote:
>> Hi Kishon,
>>
>>
>> On Mon, Sep 2, 2013 at 9:13 PM, Kishon Vijay Abraham I <[email protected]> wrote:
>>> Adapted dwc3 core to use the Generic PHY Framework. So for init, exit,
>>> power_on and power_off the following APIs are used phy_init(), phy_exit(),
>>> phy_power_on() and phy_power_off().
>>>
>>> However using the old USB phy library wont be removed till the PHYs of all
>>> other SoC's using dwc3 core is adapted to the Generic PHY Framework.
>>>
>>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>>> ---
>>> Documentation/devicetree/bindings/usb/dwc3.txt | 6 ++-
>>> drivers/usb/dwc3/Kconfig | 1 +
>>> drivers/usb/dwc3/core.c | 49 ++++++++++++++++++++++++
>>> drivers/usb/dwc3/core.h | 7 ++++
>>> 4 files changed, 61 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
>>> index e807635..471366d 100644
>>> --- a/Documentation/devicetree/bindings/usb/dwc3.txt
>>> +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
>>> @@ -6,11 +6,13 @@ Required properties:
>>> - compatible: must be "snps,dwc3"
>>> - reg : Address and length of the register set for the device
>>> - interrupts: Interrupts used by the dwc3 controller.
>>> +
>>> +Optional properties:
>>> - usb-phy : array of phandle for the PHY device. The first element
>>> in the array is expected to be a handle to the USB2/HS PHY and
>>> the second element is expected to be a handle to the USB3/SS PHY
>>> -
>>> -Optional properties:
>>> + - phys: from the *Generic PHY* bindings
>>> + - phy-names: from the *Generic PHY* bindings
>>> - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
>>>
>>> This is usually a subnode to DWC3 glue to which it is connected.
>>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>>> index cfc16dd..ad7ce83 100644
>>> --- a/drivers/usb/dwc3/Kconfig
>>> +++ b/drivers/usb/dwc3/Kconfig
>>> @@ -3,6 +3,7 @@ config USB_DWC3
>>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
>>> depends on EXTCON
>>> select USB_PHY
>>> + select GENERIC_PHY
>>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
>>> help
>>> Say Y or M here if your system has a Dual Role SuperSpeed
>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>> index 428c29e..485d365 100644
>>> --- a/drivers/usb/dwc3/core.c
>>> +++ b/drivers/usb/dwc3/core.c
>>> @@ -82,6 +82,12 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
>>>
>>> usb_phy_init(dwc->usb2_phy);
>>> usb_phy_init(dwc->usb3_phy);
>>> +
>>> + if (dwc->usb2_generic_phy)
>>> + phy_init(dwc->usb2_generic_phy);
>>> + if (dwc->usb3_generic_phy)
>>> + phy_init(dwc->usb3_generic_phy);
>>> +
>>> mdelay(100);
>>>
>>> /* Clear USB3 PHY reset */
>>> @@ -343,6 +349,11 @@ static void dwc3_core_exit(struct dwc3 *dwc)
>>> {
>>> usb_phy_shutdown(dwc->usb2_phy);
>>> usb_phy_shutdown(dwc->usb3_phy);
>>> +
>>> + if (dwc->usb2_generic_phy)
>>> + phy_power_off(dwc->usb2_generic_phy);
>>> + if (dwc->usb3_generic_phy)
>>> + phy_power_off(dwc->usb3_generic_phy);
>>> }
>>>
>>> #define DWC3_ALIGN_MASK (16 - 1)
>>> @@ -427,6 +438,23 @@ static int dwc3_probe(struct platform_device *pdev)
>>> dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
>>> }
>>>
>>> + if (of_property_read_bool(node, "phys") || pdata->has_phy) {
>>> + dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
>>> + if (IS_ERR(dwc->usb2_generic_phy)) {
>>> + dev_err(dev, "no usb2 phy configured yet");
>>> + return PTR_ERR(dwc->usb2_generic_phy);
>>> + }
>>
>> I have a doubt here.
>> As i can see in the current phy drivers structuring, for OMAP there
>> are two phy drivers :
>> omap phy-omap-usb2 (talking to musb controller)
>
> It talks to dwc3 controller also ;-)

Ok

>
>> and phy-omap-usb3(talking to dwc3 controller).
>>
>> Now dwc3 controller requests both usb2-phy (supported by phy-omap-usb2
>> ?) and usb3-phy (supported by phy-omap-usb3 ?).
>> But phy-omap-usb2 is not the one designated to talk to DWC3
>> controller, then why does still DWC3 want to request usb2-phy, which
>> end of the day will be phy-omap-usb2.
>> May be i am wrong here since i don't have knowledge about OMAP h/w architecture.
>>
>> Is it like phy-omap-usb2 includes UTMI phys for both musb controller
>> as well as dwc3 controller ?
>
> right. It's needed for dwc3 too. The same USB2 PHY IP is used for both MUSB in
> OMAP2+ platforms and DWC3 in OMAP5.

Ok, but on Samsung's exynos5 series of SoCs, the USB2.0 controller has
a separate USB-PHY interface talking to phy-samsung-usb2 driver;
and DWC3 drd controller has separate USB-PHY interface (including both
UTMI+ and PIPE3 control registers) talking to phy-samsung-usb3 driver.
So in this case DWC3 doesn't need phy-samsung-usb2 at all. It's phy is
configured by just phy-samsung-usb3 driver only.
So don't you think DWC3 driver should have the flexibility to have
either (mostly usb3-phy) _or_ both "usb2-phy" and "usb3-phy".
Thereby,in case of Samsung driver, DWC3 will just have "usb3-phy" and
that will be enough to get things working.
Want your opinions about it.


--
Best Regards
Vivek

2013-09-12 10:36:54

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 1/7] usb: dwc3: get "usb_phy" only if the platform indicates the presence of PHY

Hi Kishon,

On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
> There can be systems which does not have a external usb_phy, so get
> usb_phy only if usb-phy property is added in the case of dt boot or if
> platform_data indicates the presence of PHY. Also remove checking if
> return value is -ENXIO since it's now changed to always enable usb_phy layer.
>
> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
> ---
> drivers/usb/dwc3/Kconfig | 1 +
> drivers/usb/dwc3/core.c | 60 +++++++++++++++++---------------------
> drivers/usb/dwc3/platform_data.h | 1 +
> 3 files changed, 28 insertions(+), 34 deletions(-)
>
> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
> index f969ea2..cfc16dd 100644
> --- a/drivers/usb/dwc3/Kconfig
> +++ b/drivers/usb/dwc3/Kconfig
> @@ -2,6 +2,7 @@ config USB_DWC3
> tristate "DesignWare USB3 DRD Core Support"
> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
> depends on EXTCON
> + select USB_PHY
> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
> help
> Say Y or M here if your system has a Dual Role SuperSpeed
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index 474162e..428c29e 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -387,16 +387,38 @@ static int dwc3_probe(struct platform_device *pdev)
> if (node) {
> dwc->maximum_speed = of_usb_get_maximum_speed(node);
>
> - dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
> - dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
> + if (of_property_read_bool(node, "usb-phy")) {
> + dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev,
> + "usb-phy", 0);
> + if (IS_ERR(dwc->usb2_phy))
> + return PTR_ERR(dwc->usb2_phy);
> + dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev,
> + "usb-phy", 1);
> + if (IS_ERR(dwc->usb3_phy))
> + return PTR_ERR(dwc->usb3_phy);

Some DWC3 instances use only usb2_phy. e.g. on DRA7 the 2nd dwc3 instance doesn't use usb3_phy.
This needs to be a valid case and driver shouldn't error out.

> + } else {
> + dwc->usb2_phy = NULL;
> + dwc->usb3_phy = NULL;
> + }
>
> dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
> dwc->dr_mode = of_usb_get_dr_mode(node);
> } else if (pdata) {
> dwc->maximum_speed = pdata->maximum_speed;
>
> - dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
> - dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
> + if (pdata->has_phy) {
> + dwc->usb2_phy = devm_usb_get_phy(dev,
> + USB_PHY_TYPE_USB2);
> + if (IS_ERR(dwc->usb2_phy))
> + return PTR_ERR(dwc->usb2_phy);
> + dwc->usb3_phy = devm_usb_get_phy(dev,
> + USB_PHY_TYPE_USB3);
> + if (IS_ERR(dwc->usb3_phy))
> + return PTR_ERR(dwc->usb3_phy);

same here?

> + } else {
> + dwc->usb2_phy = NULL;
> + dwc->usb3_phy = NULL;
> + }
>
> dwc->needs_fifo_resize = pdata->tx_fifo_resize;
> dwc->dr_mode = pdata->dr_mode;
> @@ -409,36 +431,6 @@ static int dwc3_probe(struct platform_device *pdev)
> if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
> dwc->maximum_speed = USB_SPEED_SUPER;
>
> - if (IS_ERR(dwc->usb2_phy)) {
> - ret = PTR_ERR(dwc->usb2_phy);
> -
> - /*
> - * if -ENXIO is returned, it means PHY layer wasn't
> - * enabled, so it makes no sense to return -EPROBE_DEFER
> - * in that case, since no PHY driver will ever probe.
> - */
> - if (ret == -ENXIO)
> - return ret;
> -
> - dev_err(dev, "no usb2 phy configured\n");
> - return -EPROBE_DEFER;
> - }
> -
> - if (IS_ERR(dwc->usb3_phy)) {
> - ret = PTR_ERR(dwc->usb3_phy);
> -
> - /*
> - * if -ENXIO is returned, it means PHY layer wasn't
> - * enabled, so it makes no sense to return -EPROBE_DEFER
> - * in that case, since no PHY driver will ever probe.
> - */
> - if (ret == -ENXIO)
> - return ret;
> -
> - dev_err(dev, "no usb3 phy configured\n");
> - return -EPROBE_DEFER;
> - }
> -
> dwc->xhci_resources[0].start = res->start;
> dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
> DWC3_XHCI_REGS_END;
> diff --git a/drivers/usb/dwc3/platform_data.h b/drivers/usb/dwc3/platform_data.h
> index 7db34f0..5a5e068 100644
> --- a/drivers/usb/dwc3/platform_data.h
> +++ b/drivers/usb/dwc3/platform_data.h
> @@ -24,4 +24,5 @@ struct dwc3_platform_data {
> enum usb_device_speed maximum_speed;
> enum usb_dr_mode dr_mode;
> bool tx_fifo_resize;
> + bool has_phy;
> };
>

cheers,
-roger

2013-09-12 10:47:14

by Vivek Gautam

[permalink] [raw]
Subject: Re: [PATCH 1/7] usb: dwc3: get "usb_phy" only if the platform indicates the presence of PHY

On Thu, Sep 12, 2013 at 4:06 PM, Roger Quadros <[email protected]> wrote:
> Hi Kishon,
>
> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>> There can be systems which does not have a external usb_phy, so get
>> usb_phy only if usb-phy property is added in the case of dt boot or if
>> platform_data indicates the presence of PHY. Also remove checking if
>> return value is -ENXIO since it's now changed to always enable usb_phy layer.
>>
>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>> ---
>> drivers/usb/dwc3/Kconfig | 1 +
>> drivers/usb/dwc3/core.c | 60 +++++++++++++++++---------------------
>> drivers/usb/dwc3/platform_data.h | 1 +
>> 3 files changed, 28 insertions(+), 34 deletions(-)
>>
>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>> index f969ea2..cfc16dd 100644
>> --- a/drivers/usb/dwc3/Kconfig
>> +++ b/drivers/usb/dwc3/Kconfig
>> @@ -2,6 +2,7 @@ config USB_DWC3
>> tristate "DesignWare USB3 DRD Core Support"
>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
>> depends on EXTCON
>> + select USB_PHY
>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
>> help
>> Say Y or M here if your system has a Dual Role SuperSpeed
>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>> index 474162e..428c29e 100644
>> --- a/drivers/usb/dwc3/core.c
>> +++ b/drivers/usb/dwc3/core.c
>> @@ -387,16 +387,38 @@ static int dwc3_probe(struct platform_device *pdev)
>> if (node) {
>> dwc->maximum_speed = of_usb_get_maximum_speed(node);
>>
>> - dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
>> - dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
>> + if (of_property_read_bool(node, "usb-phy")) {
>> + dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev,
>> + "usb-phy", 0);
>> + if (IS_ERR(dwc->usb2_phy))
>> + return PTR_ERR(dwc->usb2_phy);
>> + dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev,
>> + "usb-phy", 1);
>> + if (IS_ERR(dwc->usb3_phy))
>> + return PTR_ERR(dwc->usb3_phy);
>
> Some DWC3 instances use only usb2_phy. e.g. on DRA7 the 2nd dwc3 instance doesn't use usb3_phy.
> This needs to be a valid case and driver shouldn't error out.

So, i think adding flexibility to DWC3 to have either
usb2-phy/usb3-phy or both of them seems to be valid point.
Any suggestions ?

>
>> + } else {
>> + dwc->usb2_phy = NULL;
>> + dwc->usb3_phy = NULL;
>> + }
>>
>> dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
>> dwc->dr_mode = of_usb_get_dr_mode(node);
>> } else if (pdata) {
>> dwc->maximum_speed = pdata->maximum_speed;
>>
>> - dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
>> - dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
>> + if (pdata->has_phy) {
>> + dwc->usb2_phy = devm_usb_get_phy(dev,
>> + USB_PHY_TYPE_USB2);
>> + if (IS_ERR(dwc->usb2_phy))
>> + return PTR_ERR(dwc->usb2_phy);
>> + dwc->usb3_phy = devm_usb_get_phy(dev,
>> + USB_PHY_TYPE_USB3);
>> + if (IS_ERR(dwc->usb3_phy))
>> + return PTR_ERR(dwc->usb3_phy);
>
> same here?
>
>> + } else {
>> + dwc->usb2_phy = NULL;
>> + dwc->usb3_phy = NULL;
>> + }
>>
>> dwc->needs_fifo_resize = pdata->tx_fifo_resize;
>> dwc->dr_mode = pdata->dr_mode;
>> @@ -409,36 +431,6 @@ static int dwc3_probe(struct platform_device *pdev)
>> if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
>> dwc->maximum_speed = USB_SPEED_SUPER;
>>
>> - if (IS_ERR(dwc->usb2_phy)) {
>> - ret = PTR_ERR(dwc->usb2_phy);
>> -
>> - /*
>> - * if -ENXIO is returned, it means PHY layer wasn't
>> - * enabled, so it makes no sense to return -EPROBE_DEFER
>> - * in that case, since no PHY driver will ever probe.
>> - */
>> - if (ret == -ENXIO)
>> - return ret;
>> -
>> - dev_err(dev, "no usb2 phy configured\n");
>> - return -EPROBE_DEFER;
>> - }
>> -
>> - if (IS_ERR(dwc->usb3_phy)) {
>> - ret = PTR_ERR(dwc->usb3_phy);
>> -
>> - /*
>> - * if -ENXIO is returned, it means PHY layer wasn't
>> - * enabled, so it makes no sense to return -EPROBE_DEFER
>> - * in that case, since no PHY driver will ever probe.
>> - */
>> - if (ret == -ENXIO)
>> - return ret;
>> -
>> - dev_err(dev, "no usb3 phy configured\n");
>> - return -EPROBE_DEFER;
>> - }
>> -
>> dwc->xhci_resources[0].start = res->start;
>> dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
>> DWC3_XHCI_REGS_END;
>> diff --git a/drivers/usb/dwc3/platform_data.h b/drivers/usb/dwc3/platform_data.h
>> index 7db34f0..5a5e068 100644
>> --- a/drivers/usb/dwc3/platform_data.h
>> +++ b/drivers/usb/dwc3/platform_data.h
>> @@ -24,4 +24,5 @@ struct dwc3_platform_data {
>> enum usb_device_speed maximum_speed;
>> enum usb_dr_mode dr_mode;
>> bool tx_fifo_resize;
>> + bool has_phy;
>> };
>>
>
> cheers,
> -roger
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/



--
Best Regards
Vivek

2013-09-12 11:05:38

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 1/7] usb: dwc3: get "usb_phy" only if the platform indicates the presence of PHY

Hi,

On 09/12/2013 01:47 PM, Vivek Gautam wrote:
> On Thu, Sep 12, 2013 at 4:06 PM, Roger Quadros <[email protected]> wrote:
>> Hi Kishon,
>>
>> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>>> There can be systems which does not have a external usb_phy, so get
>>> usb_phy only if usb-phy property is added in the case of dt boot or if
>>> platform_data indicates the presence of PHY. Also remove checking if
>>> return value is -ENXIO since it's now changed to always enable usb_phy layer.
>>>
>>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>>> ---
>>> drivers/usb/dwc3/Kconfig | 1 +
>>> drivers/usb/dwc3/core.c | 60 +++++++++++++++++---------------------
>>> drivers/usb/dwc3/platform_data.h | 1 +
>>> 3 files changed, 28 insertions(+), 34 deletions(-)
>>>
>>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>>> index f969ea2..cfc16dd 100644
>>> --- a/drivers/usb/dwc3/Kconfig
>>> +++ b/drivers/usb/dwc3/Kconfig
>>> @@ -2,6 +2,7 @@ config USB_DWC3
>>> tristate "DesignWare USB3 DRD Core Support"
>>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
>>> depends on EXTCON
>>> + select USB_PHY
>>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
>>> help
>>> Say Y or M here if your system has a Dual Role SuperSpeed
>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>> index 474162e..428c29e 100644
>>> --- a/drivers/usb/dwc3/core.c
>>> +++ b/drivers/usb/dwc3/core.c
>>> @@ -387,16 +387,38 @@ static int dwc3_probe(struct platform_device *pdev)
>>> if (node) {
>>> dwc->maximum_speed = of_usb_get_maximum_speed(node);
>>>
>>> - dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
>>> - dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
>>> + if (of_property_read_bool(node, "usb-phy")) {
>>> + dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev,
>>> + "usb-phy", 0);
>>> + if (IS_ERR(dwc->usb2_phy))
>>> + return PTR_ERR(dwc->usb2_phy);
>>> + dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev,
>>> + "usb-phy", 1);
>>> + if (IS_ERR(dwc->usb3_phy))
>>> + return PTR_ERR(dwc->usb3_phy);
>>
>> Some DWC3 instances use only usb2_phy. e.g. on DRA7 the 2nd dwc3 instance doesn't use usb3_phy.
>> This needs to be a valid case and driver shouldn't error out.
>
> So, i think adding flexibility to DWC3 to have either
> usb2-phy/usb3-phy or both of them seems to be valid point.
> Any suggestions ?
>

For high speed operation we need only usb2_phy but for super speed we need both usb2_phy
and usb3_phy.

Why would a dwc3 controller use only usb3_phy? A USB3.0 interface has to be compatible with
USB2.0 as well, no?

cheers,
-roger

2013-09-12 11:20:59

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 3/7] drivers: phy: usb3/pipe3: Adapt pipe3 driver to Generic PHY Framework

Hi Kishon,

On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
> Adapted omap-usb3 PHY driver to Generic PHY Framework and moved phy-omap-usb3
> driver in drivers/usb/phy to drivers/phy and also renamed the file to
> phy-omap-pipe3 since this same driver will be used for SATA PHY and
> PCIE PHY.

I would suggest to split the renaming and PHY adaptation into 2 separate patches.

>
> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
> ---
> Documentation/devicetree/bindings/usb/usb-phy.txt | 5 +-
> drivers/phy/Kconfig | 10 +
> drivers/phy/Makefile | 1 +
> .../phy/phy-omap-usb3.c => phy/phy-omap-pipe3.c} | 206 +++++++++++---------

how about naming it to phy-ti-pipe3.c as it is used on OMAP as well as non-OMAP e.g. DRA7.

> drivers/usb/phy/Kconfig | 11 --
> drivers/usb/phy/Makefile | 1 -
> include/linux/phy/omap_pipe3.h | 52 +++++
> 7 files changed, 177 insertions(+), 109 deletions(-)
> rename drivers/{usb/phy/phy-omap-usb3.c => phy/phy-omap-pipe3.c} (57%)
> create mode 100644 include/linux/phy/omap_pipe3.h
>
> diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/usb/usb-phy.txt
> index c0245c8..36bdb17 100644
> --- a/Documentation/devicetree/bindings/usb/usb-phy.txt
> +++ b/Documentation/devicetree/bindings/usb/usb-phy.txt
> @@ -21,10 +21,11 @@ usb2phy@4a0ad080 {
> #phy-cells = <0>;
> };
>
> -OMAP USB3 PHY
> +OMAP PIPE3 PHY
>
> Required properties:
> - - compatible: Should be "ti,omap-usb3"
> + - compatible: Should be "ti,omap-usb3", "ti,omap-pipe3", "ti,omap-sata"
> + or "ti,omap-pcie"
> - reg : Address and length of the register set for the device.
> - reg-names: The names of the register addresses corresponding to the registers
> filled in "reg".
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index ac239ac..5c2e7a0 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -27,6 +27,16 @@ config OMAP_USB2
> The USB OTG controller communicates with the comparator using this
> driver.
>
> +config OMAP_PIPE3
> + tristate "OMAP PIPE3 PHY Driver"
> + select GENERIC_PHY
> + select OMAP_CONTROL_USB
how about
depends on OMAP_CONTROL_USB

Also, if this is TI/OMAP it might as well depend on ARCH_OMAP.

> + help
> + Enable this to support the PIPE3 PHY that is part of SOC. This

worth mentioning TI OMAP/DRA SoCs.

> + driver takes care of all the PHY functionality apart from comparator.
> + This driver interacts with the "OMAP Control PHY Driver" to power
> + on/off the PHY.
> +
> config TWL4030_USB
> tristate "TWL4030 USB Transceiver Driver"
> depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index 0dd8a98..48bf9f2 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -4,4 +4,5 @@
>
> obj-$(CONFIG_GENERIC_PHY) += phy-core.o
> obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
> +obj-$(CONFIG_OMAP_PIPE3) += phy-omap-pipe3.o
> obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
> diff --git a/drivers/usb/phy/phy-omap-usb3.c b/drivers/phy/phy-omap-pipe3.c
> similarity index 57%
> rename from drivers/usb/phy/phy-omap-usb3.c
> rename to drivers/phy/phy-omap-pipe3.c
> index 4004f82..ee9a901 100644
> --- a/drivers/usb/phy/phy-omap-usb3.c
> +++ b/drivers/phy/phy-omap-pipe3.c
> @@ -1,5 +1,5 @@
> /*
> - * omap-usb3 - USB PHY, talking to dwc3 controller in OMAP.
> + * omap-pipe3 - PHY driver for SATA, USB and PCIE in OMAP platforms
> *
> * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
> * This program is free software; you can redistribute it and/or modify
> @@ -19,7 +19,8 @@
> #include <linux/module.h>
> #include <linux/platform_device.h>
> #include <linux/slab.h>
> -#include <linux/usb/omap_usb.h>
> +#include <linux/phy/omap_pipe3.h>
> +#include <linux/phy/phy.h>
> #include <linux/of.h>
> #include <linux/clk.h>
> #include <linux/err.h>
> @@ -52,17 +53,17 @@
>
> /*
> * This is an Empirical value that works, need to confirm the actual
> - * value required for the USB3PHY_PLL_CONFIGURATION2.PLL_IDLE status
> - * to be correctly reflected in the USB3PHY_PLL_STATUS register.
> + * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status
> + * to be correctly reflected in the PIPE3PHY_PLL_STATUS register.
> */
> # define PLL_IDLE_TIME 100;
>
> -struct usb_dpll_map {
> +struct pipe3_dpll_map {
> unsigned long rate;
> - struct usb_dpll_params params;
> + struct pipe3_dpll_params params;
> };
>
> -static struct usb_dpll_map dpll_map[] = {
> +static struct pipe3_dpll_map dpll_map[] = {
> {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */
> {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */
> {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */
> @@ -71,7 +72,7 @@ static struct usb_dpll_map dpll_map[] = {
> {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */
> };
>
> -static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate)
> +static struct pipe3_dpll_params *omap_pipe3_get_dpll_params(unsigned long rate)
> {
> int i;
>
> @@ -83,110 +84,113 @@ static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate)
> return 0;
> }
>
> -static int omap_usb3_suspend(struct usb_phy *x, int suspend)
> +static int omap_pipe3_power_off(struct phy *x)
> {
> - struct omap_usb *phy = phy_to_omapusb(x);
> - int val;
> + struct omap_pipe3 *phy = phy_get_drvdata(x);
> + int val;
> int timeout = PLL_IDLE_TIME;
>
> - if (suspend && !phy->is_suspended) {
> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
> - val |= PLL_IDLE;
> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
> -
> - do {
> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
> - if (val & PLL_TICOPWDN)
> - break;
> - udelay(1);
> - } while (--timeout);
> -
> - omap_control_usb_phy_power(phy->control_dev, 0);
> -
> - phy->is_suspended = 1;
> - } else if (!suspend && phy->is_suspended) {
> - phy->is_suspended = 0;
> -
> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
> - val &= ~PLL_IDLE;
> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
> -
> - do {
> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
> - if (!(val & PLL_TICOPWDN))
> - break;
> - udelay(1);
> - } while (--timeout);
> - }
> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
> + val |= PLL_IDLE;
> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
> +
> + do {
> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
> + if (val & PLL_TICOPWDN)
> + break;
> + udelay(1);

Is it better to sleep instead of udelay?

> + } while (--timeout);
> +
> + omap_control_usb_phy_power(phy->control_dev, 0);
> +
> + return 0;
> +}
> +
> +static int omap_pipe3_power_on(struct phy *x)
> +{
> + struct omap_pipe3 *phy = phy_get_drvdata(x);
> + int val;
> + int timeout = PLL_IDLE_TIME;
> +
> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
> + val &= ~PLL_IDLE;
> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
> +
> + do {
> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
> + if (!(val & PLL_TICOPWDN))
> + break;
> + udelay(1);

here too.

> + } while (--timeout);
>
> return 0;
> }
>
> -static void omap_usb_dpll_relock(struct omap_usb *phy)
> +static void omap_pipe3_dpll_relock(struct omap_pipe3 *phy)
> {
> u32 val;
> unsigned long timeout;
>
> - omap_usb_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
>
> timeout = jiffies + msecs_to_jiffies(20);
> do {
> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
> if (val & PLL_LOCK)
> break;
> } while (!WARN_ON(time_after(jiffies, timeout)));
> }
>
> -static int omap_usb_dpll_lock(struct omap_usb *phy)
> +static int omap_pipe3_dpll_lock(struct omap_pipe3 *phy)
> {
> u32 val;
> unsigned long rate;
> - struct usb_dpll_params *dpll_params;
> + struct pipe3_dpll_params *dpll_params;
>
> rate = clk_get_rate(phy->sys_clk);
> - dpll_params = omap_usb3_get_dpll_params(rate);
> + dpll_params = omap_pipe3_get_dpll_params(rate);
> if (!dpll_params) {
> dev_err(phy->dev,
> "No DPLL configuration for %lu Hz SYS CLK\n", rate);
> return -EINVAL;
> }
>
> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
> val &= ~PLL_REGN_MASK;
> val |= dpll_params->n << PLL_REGN_SHIFT;
> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>
> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
> val &= ~PLL_SELFREQDCO_MASK;
> val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>
> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
> val &= ~PLL_REGM_MASK;
> val |= dpll_params->m << PLL_REGM_SHIFT;
> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>
> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
> val &= ~PLL_REGM_F_MASK;
> val |= dpll_params->mf << PLL_REGM_F_SHIFT;
> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
>
> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
> val &= ~PLL_SD_MASK;
> val |= dpll_params->sd << PLL_SD_SHIFT;
> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
>
> - omap_usb_dpll_relock(phy);
> + omap_pipe3_dpll_relock(phy);
>
> return 0;
> }
>
> -static int omap_usb3_init(struct usb_phy *x)
> +static int omap_pipe3_init(struct phy *x)
> {
> - struct omap_usb *phy = phy_to_omapusb(x);
> + struct omap_pipe3 *phy = phy_get_drvdata(x);
> int ret;
>
> - ret = omap_usb_dpll_lock(phy);
> + ret = omap_pipe3_dpll_lock(phy);
> if (ret)
> return ret;
>
> @@ -195,9 +199,18 @@ static int omap_usb3_init(struct usb_phy *x)
> return 0;
> }
>
> -static int omap_usb3_probe(struct platform_device *pdev)
> +static struct phy_ops ops = {
> + .init = omap_pipe3_init,
> + .power_on = omap_pipe3_power_on,
> + .power_off = omap_pipe3_power_off,
> + .owner = THIS_MODULE,
> +};
> +
> +static int omap_pipe3_probe(struct platform_device *pdev)
> {
> - struct omap_usb *phy;
> + struct omap_pipe3 *phy;
> + struct phy *generic_phy;
> + struct phy_provider *phy_provider;
> struct resource *res;
> struct device_node *node = pdev->dev.of_node;
> struct device_node *control_node;
> @@ -208,7 +221,7 @@ static int omap_usb3_probe(struct platform_device *pdev)
>
> phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
> if (!phy) {
> - dev_err(&pdev->dev, "unable to alloc mem for OMAP USB3 PHY\n");
> + dev_err(&pdev->dev, "unable to alloc mem for OMAP PIPE3 PHY\n");
> return -ENOMEM;
> }
>
> @@ -219,13 +232,6 @@ static int omap_usb3_probe(struct platform_device *pdev)
>
> phy->dev = &pdev->dev;
>
> - phy->phy.dev = phy->dev;
> - phy->phy.label = "omap-usb3";
> - phy->phy.init = omap_usb3_init;
> - phy->phy.set_suspend = omap_usb3_suspend;
> - phy->phy.type = USB_PHY_TYPE_USB3;
> -
> - phy->is_suspended = 1;
> phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");

As this is no longer USB specific, we need to make the clock binding generic as well.

> if (IS_ERR(phy->wkupclk)) {
> dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
> @@ -251,6 +257,11 @@ static int omap_usb3_probe(struct platform_device *pdev)
> dev_err(&pdev->dev, "Failed to get control device phandle\n");
> return -EINVAL;
> }
> + phy_provider = devm_of_phy_provider_register(phy->dev,
> + of_phy_simple_xlate);
> + if (IS_ERR(phy_provider))
> + return PTR_ERR(phy_provider);
> +
> control_pdev = of_find_device_by_node(control_node);
> if (!control_pdev) {
> dev_err(&pdev->dev, "Failed to get control device\n");
> @@ -260,23 +271,27 @@ static int omap_usb3_probe(struct platform_device *pdev)
> phy->control_dev = &control_pdev->dev;
>
> omap_control_usb_phy_power(phy->control_dev, 0);
> - usb_add_phy_dev(&phy->phy);
>
> platform_set_drvdata(pdev, phy);
> -
> pm_runtime_enable(phy->dev);
> +
> + generic_phy = devm_phy_create(phy->dev, &ops, NULL);
> + if (IS_ERR(generic_phy))
> + return PTR_ERR(generic_phy);
> +
> + phy_set_drvdata(generic_phy, phy);
> +
> pm_runtime_get(&pdev->dev);
>
> return 0;
> }
>
> -static int omap_usb3_remove(struct platform_device *pdev)
> +static int omap_pipe3_remove(struct platform_device *pdev)
> {
> - struct omap_usb *phy = platform_get_drvdata(pdev);
> + struct omap_pipe3 *phy = platform_get_drvdata(pdev);
>
> clk_unprepare(phy->wkupclk);
> clk_unprepare(phy->optclk);
> - usb_remove_phy(&phy->phy);
> if (!pm_runtime_suspended(&pdev->dev))
> pm_runtime_put(&pdev->dev);
> pm_runtime_disable(&pdev->dev);
> @@ -286,10 +301,9 @@ static int omap_usb3_remove(struct platform_device *pdev)
>
> #ifdef CONFIG_PM_RUNTIME
>
> -static int omap_usb3_runtime_suspend(struct device *dev)
> +static int omap_pipe3_runtime_suspend(struct device *dev)
> {
> - struct platform_device *pdev = to_platform_device(dev);
> - struct omap_usb *phy = platform_get_drvdata(pdev);
> + struct omap_pipe3 *phy = dev_get_drvdata(dev);
>
> clk_disable(phy->wkupclk);
> clk_disable(phy->optclk);
> @@ -297,11 +311,10 @@ static int omap_usb3_runtime_suspend(struct device *dev)
> return 0;
> }
>
> -static int omap_usb3_runtime_resume(struct device *dev)
> +static int omap_pipe3_runtime_resume(struct device *dev)
> {
> u32 ret = 0;
> - struct platform_device *pdev = to_platform_device(dev);
> - struct omap_usb *phy = platform_get_drvdata(pdev);
> + struct omap_pipe3 *phy = dev_get_drvdata(dev);
>
> ret = clk_enable(phy->optclk);
> if (ret) {
> @@ -324,38 +337,41 @@ err1:
> return ret;
> }
>
> -static const struct dev_pm_ops omap_usb3_pm_ops = {
> - SET_RUNTIME_PM_OPS(omap_usb3_runtime_suspend, omap_usb3_runtime_resume,
> - NULL)
> +static const struct dev_pm_ops omap_pipe3_pm_ops = {
> + SET_RUNTIME_PM_OPS(omap_pipe3_runtime_suspend,
> + omap_pipe3_runtime_resume, NULL)
> };
>
> -#define DEV_PM_OPS (&omap_usb3_pm_ops)
> +#define DEV_PM_OPS (&omap_pipe3_pm_ops)
> #else
> #define DEV_PM_OPS NULL
> #endif
>
> #ifdef CONFIG_OF
> -static const struct of_device_id omap_usb3_id_table[] = {
> +static const struct of_device_id omap_pipe3_id_table[] = {
> + { .compatible = "ti,omap-pipe3" },

why do you need "omap-pipe3", isn't sata, pcie and usb3 sufficient?

> + { .compatible = "ti,omap-sata" },
> + { .compatible = "ti,omap-pcie" },
> { .compatible = "ti,omap-usb3" },
> {}
> };
> -MODULE_DEVICE_TABLE(of, omap_usb3_id_table);
> +MODULE_DEVICE_TABLE(of, omap_pipe3_id_table);
> #endif
>
> -static struct platform_driver omap_usb3_driver = {
> - .probe = omap_usb3_probe,
> - .remove = omap_usb3_remove,
> +static struct platform_driver omap_pipe3_driver = {
> + .probe = omap_pipe3_probe,
> + .remove = omap_pipe3_remove,
> .driver = {
> - .name = "omap-usb3",
> + .name = "omap-pipe3",
> .owner = THIS_MODULE,
> .pm = DEV_PM_OPS,
> - .of_match_table = of_match_ptr(omap_usb3_id_table),
> + .of_match_table = of_match_ptr(omap_pipe3_id_table),
> },
> };
>
> -module_platform_driver(omap_usb3_driver);
> +module_platform_driver(omap_pipe3_driver);
>
> -MODULE_ALIAS("platform: omap_usb3");
> +MODULE_ALIAS("platform: omap_pipe3");
> MODULE_AUTHOR("Texas Instruments Inc.");
> -MODULE_DESCRIPTION("OMAP USB3 phy driver");
> +MODULE_DESCRIPTION("OMAP PIPE3 phy driver");
> MODULE_LICENSE("GPL v2");
> diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
> index d69cdad..0210e03 100644
> --- a/drivers/usb/phy/Kconfig
> +++ b/drivers/usb/phy/Kconfig
> @@ -66,17 +66,6 @@ config OMAP_CONTROL_USB
> power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
> additional register to power on USB3 PHY.
>
> -config OMAP_USB3
> - tristate "OMAP USB3 PHY Driver"
> - depends on ARCH_OMAP2PLUS || COMPILE_TEST
> - select OMAP_CONTROL_USB
> - select USB_PHY
> - help
> - Enable this to support the USB3 PHY that is part of SOC. This
> - driver takes care of all the PHY functionality apart from comparator.
> - This driver interacts with the "OMAP Control USB Driver" to power
> - on/off the PHY.
> -
> config AM335X_CONTROL_USB
> tristate
>
> diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
> index 51968d7..d1c9683 100644
> --- a/drivers/usb/phy/Makefile
> +++ b/drivers/usb/phy/Makefile
> @@ -13,7 +13,6 @@ obj-$(CONFIG_ISP1301_OMAP) += phy-isp1301-omap.o
> obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o
> obj-$(CONFIG_NOP_USB_XCEIV) += phy-generic.o
> obj-$(CONFIG_OMAP_CONTROL_USB) += phy-omap-control.o
> -obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o
> obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o
> obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o
> obj-$(CONFIG_SAMSUNG_USB3PHY) += phy-samsung-usb3.o
> diff --git a/include/linux/phy/omap_pipe3.h b/include/linux/phy/omap_pipe3.h
> new file mode 100644
> index 0000000..7329056
> --- /dev/null
> +++ b/include/linux/phy/omap_pipe3.h

ti_pipe3.h ?

> @@ -0,0 +1,52 @@
> +/*
> + * omap_pipe3.h -- omap pipe3 phy header file
> + *
> + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * Author: Kishon Vijay Abraham I <[email protected]>
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#ifndef __DRIVERS_OMAP_PIPE3_H
> +#define __DRIVERS_OMAP_PIPE3_H
> +
> +#include <linux/io.h>
> +
> +struct pipe3_dpll_params {
> + u16 m;
> + u8 n;
> + u8 freq:3;
> + u8 sd;
> + u32 mf;
> +};
> +
> +struct omap_pipe3 {
> + void __iomem *pll_ctrl_base;
> + struct device *dev;
> + struct device *control_dev;
> + struct clk *wkupclk;
> + struct clk *sys_clk;

sysclk. To be consistent with others?

> + struct clk *optclk;
> +};
> +
> +static inline u32 omap_pipe3_readl(void __iomem *addr, unsigned offset)
> +{
> + return __raw_readl(addr + offset);
> +}
> +
> +static inline void omap_pipe3_writel(void __iomem *addr, unsigned offset,
> + u32 data)
> +{
> + __raw_writel(data, addr + offset);
> +}
> +
> +#endif /* __DRIVERS_OMAP_PIPE3_H */
>

cheers,
-roger

2013-09-12 11:26:39

by Vivek Gautam

[permalink] [raw]
Subject: Re: [PATCH 1/7] usb: dwc3: get "usb_phy" only if the platform indicates the presence of PHY

Hi,


On Thu, Sep 12, 2013 at 4:34 PM, Roger Quadros <[email protected]> wrote:
> Hi,
>
> On 09/12/2013 01:47 PM, Vivek Gautam wrote:
>> On Thu, Sep 12, 2013 at 4:06 PM, Roger Quadros <[email protected]> wrote:
>>> Hi Kishon,
>>>
>>> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>>>> There can be systems which does not have a external usb_phy, so get
>>>> usb_phy only if usb-phy property is added in the case of dt boot or if
>>>> platform_data indicates the presence of PHY. Also remove checking if
>>>> return value is -ENXIO since it's now changed to always enable usb_phy layer.
>>>>
>>>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>>>> ---
>>>> drivers/usb/dwc3/Kconfig | 1 +
>>>> drivers/usb/dwc3/core.c | 60 +++++++++++++++++---------------------
>>>> drivers/usb/dwc3/platform_data.h | 1 +
>>>> 3 files changed, 28 insertions(+), 34 deletions(-)
>>>>
>>>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>>>> index f969ea2..cfc16dd 100644
>>>> --- a/drivers/usb/dwc3/Kconfig
>>>> +++ b/drivers/usb/dwc3/Kconfig
>>>> @@ -2,6 +2,7 @@ config USB_DWC3
>>>> tristate "DesignWare USB3 DRD Core Support"
>>>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
>>>> depends on EXTCON
>>>> + select USB_PHY
>>>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
>>>> help
>>>> Say Y or M here if your system has a Dual Role SuperSpeed
>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>>> index 474162e..428c29e 100644
>>>> --- a/drivers/usb/dwc3/core.c
>>>> +++ b/drivers/usb/dwc3/core.c
>>>> @@ -387,16 +387,38 @@ static int dwc3_probe(struct platform_device *pdev)
>>>> if (node) {
>>>> dwc->maximum_speed = of_usb_get_maximum_speed(node);
>>>>
>>>> - dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
>>>> - dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
>>>> + if (of_property_read_bool(node, "usb-phy")) {
>>>> + dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev,
>>>> + "usb-phy", 0);
>>>> + if (IS_ERR(dwc->usb2_phy))
>>>> + return PTR_ERR(dwc->usb2_phy);
>>>> + dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev,
>>>> + "usb-phy", 1);
>>>> + if (IS_ERR(dwc->usb3_phy))
>>>> + return PTR_ERR(dwc->usb3_phy);
>>>
>>> Some DWC3 instances use only usb2_phy. e.g. on DRA7 the 2nd dwc3 instance doesn't use usb3_phy.
>>> This needs to be a valid case and driver shouldn't error out.
>>
>> So, i think adding flexibility to DWC3 to have either
>> usb2-phy/usb3-phy or both of them seems to be valid point.
>> Any suggestions ?
>>
>
> For high speed operation we need only usb2_phy but for super speed we need both usb2_phy
> and usb3_phy.
>
> Why would a dwc3 controller use only usb3_phy? A USB3.0 interface has to be compatible with
> USB2.0 as well, no?

True and for that reason we need both UTMI+ interface as well as PIPE3
interface, right ?
But as also mentioned in the thread:
https://lkml.org/lkml/2013/9/12/181, on Samsung exynos5
architecturally same block is managing UTMI+ and PIPE3 interfaces,
which is handled by phy-samsung-usb3 driver and denoted by "usb3_phy:
usbphy@12100000" node in "arch/arm/boot/dts/exynos5250.dtsi".

So on exynos5250, DWC3 really needs just usb3-phy, which is compatible
for USB 2.0 as well.

>
> cheers,
> -roger
>



--
Best Regards
Vivek

2013-09-12 13:12:58

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 1/7] usb: dwc3: get "usb_phy" only if the platform indicates the presence of PHY

On 09/12/2013 02:26 PM, Vivek Gautam wrote:
> Hi,
>
>
> On Thu, Sep 12, 2013 at 4:34 PM, Roger Quadros <[email protected]> wrote:
>> Hi,
>>
>> On 09/12/2013 01:47 PM, Vivek Gautam wrote:
>>> On Thu, Sep 12, 2013 at 4:06 PM, Roger Quadros <[email protected]> wrote:
>>>> Hi Kishon,
>>>>
>>>> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>>>>> There can be systems which does not have a external usb_phy, so get
>>>>> usb_phy only if usb-phy property is added in the case of dt boot or if
>>>>> platform_data indicates the presence of PHY. Also remove checking if
>>>>> return value is -ENXIO since it's now changed to always enable usb_phy layer.
>>>>>
>>>>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>>>>> ---
>>>>> drivers/usb/dwc3/Kconfig | 1 +
>>>>> drivers/usb/dwc3/core.c | 60 +++++++++++++++++---------------------
>>>>> drivers/usb/dwc3/platform_data.h | 1 +
>>>>> 3 files changed, 28 insertions(+), 34 deletions(-)
>>>>>
>>>>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>>>>> index f969ea2..cfc16dd 100644
>>>>> --- a/drivers/usb/dwc3/Kconfig
>>>>> +++ b/drivers/usb/dwc3/Kconfig
>>>>> @@ -2,6 +2,7 @@ config USB_DWC3
>>>>> tristate "DesignWare USB3 DRD Core Support"
>>>>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
>>>>> depends on EXTCON
>>>>> + select USB_PHY
>>>>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
>>>>> help
>>>>> Say Y or M here if your system has a Dual Role SuperSpeed
>>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>>>> index 474162e..428c29e 100644
>>>>> --- a/drivers/usb/dwc3/core.c
>>>>> +++ b/drivers/usb/dwc3/core.c
>>>>> @@ -387,16 +387,38 @@ static int dwc3_probe(struct platform_device *pdev)
>>>>> if (node) {
>>>>> dwc->maximum_speed = of_usb_get_maximum_speed(node);
>>>>>
>>>>> - dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
>>>>> - dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
>>>>> + if (of_property_read_bool(node, "usb-phy")) {
>>>>> + dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev,
>>>>> + "usb-phy", 0);
>>>>> + if (IS_ERR(dwc->usb2_phy))
>>>>> + return PTR_ERR(dwc->usb2_phy);
>>>>> + dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev,
>>>>> + "usb-phy", 1);
>>>>> + if (IS_ERR(dwc->usb3_phy))
>>>>> + return PTR_ERR(dwc->usb3_phy);
>>>>
>>>> Some DWC3 instances use only usb2_phy. e.g. on DRA7 the 2nd dwc3 instance doesn't use usb3_phy.
>>>> This needs to be a valid case and driver shouldn't error out.
>>>
>>> So, i think adding flexibility to DWC3 to have either
>>> usb2-phy/usb3-phy or both of them seems to be valid point.
>>> Any suggestions ?
>>>
>>
>> For high speed operation we need only usb2_phy but for super speed we need both usb2_phy
>> and usb3_phy.
>>
>> Why would a dwc3 controller use only usb3_phy? A USB3.0 interface has to be compatible with
>> USB2.0 as well, no?
>
> True and for that reason we need both UTMI+ interface as well as PIPE3
> interface, right ?
> But as also mentioned in the thread:
> https://lkml.org/lkml/2013/9/12/181, on Samsung exynos5
> architecturally same block is managing UTMI+ and PIPE3 interfaces,
> which is handled by phy-samsung-usb3 driver and denoted by "usb3_phy:
> usbphy@12100000" node in "arch/arm/boot/dts/exynos5250.dtsi".
>
> So on exynos5250, DWC3 really needs just usb3-phy, which is compatible
> for USB 2.0 as well.

I'm not familiar with exynos5250 dwc3, but looking at the dts file I can see both usb3_phy
and usb2_phy nodes and both are referenced in the dwc3 node.

The ehci and ohci controllers don't reference any PHY.

cheers,
-roger

2013-09-12 13:20:48

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
> Adapted dwc3 core to use the Generic PHY Framework. So for init, exit,
> power_on and power_off the following APIs are used phy_init(), phy_exit(),
> phy_power_on() and phy_power_off().
>
> However using the old USB phy library wont be removed till the PHYs of all
> other SoC's using dwc3 core is adapted to the Generic PHY Framework.
>
> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
> ---
> Documentation/devicetree/bindings/usb/dwc3.txt | 6 ++-
> drivers/usb/dwc3/Kconfig | 1 +
> drivers/usb/dwc3/core.c | 49 ++++++++++++++++++++++++
> drivers/usb/dwc3/core.h | 7 ++++
> 4 files changed, 61 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
> index e807635..471366d 100644
> --- a/Documentation/devicetree/bindings/usb/dwc3.txt
> +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
> @@ -6,11 +6,13 @@ Required properties:
> - compatible: must be "snps,dwc3"
> - reg : Address and length of the register set for the device
> - interrupts: Interrupts used by the dwc3 controller.
> +
> +Optional properties:
> - usb-phy : array of phandle for the PHY device. The first element
> in the array is expected to be a handle to the USB2/HS PHY and
> the second element is expected to be a handle to the USB3/SS PHY
> -
> -Optional properties:
> + - phys: from the *Generic PHY* bindings
> + - phy-names: from the *Generic PHY* bindings
> - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
>
> This is usually a subnode to DWC3 glue to which it is connected.
> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
> index cfc16dd..ad7ce83 100644
> --- a/drivers/usb/dwc3/Kconfig
> +++ b/drivers/usb/dwc3/Kconfig
> @@ -3,6 +3,7 @@ config USB_DWC3
> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
> depends on EXTCON
> select USB_PHY
> + select GENERIC_PHY
> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
> help
> Say Y or M here if your system has a Dual Role SuperSpeed
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index 428c29e..485d365 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -82,6 +82,12 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
>
> usb_phy_init(dwc->usb2_phy);
> usb_phy_init(dwc->usb3_phy);
> +
> + if (dwc->usb2_generic_phy)
> + phy_init(dwc->usb2_generic_phy);
> + if (dwc->usb3_generic_phy)
> + phy_init(dwc->usb3_generic_phy);
> +
> mdelay(100);
>
> /* Clear USB3 PHY reset */
> @@ -343,6 +349,11 @@ static void dwc3_core_exit(struct dwc3 *dwc)
> {
> usb_phy_shutdown(dwc->usb2_phy);
> usb_phy_shutdown(dwc->usb3_phy);
> +
> + if (dwc->usb2_generic_phy)
> + phy_power_off(dwc->usb2_generic_phy);
> + if (dwc->usb3_generic_phy)
> + phy_power_off(dwc->usb3_generic_phy);
> }
>
> #define DWC3_ALIGN_MASK (16 - 1)
> @@ -427,6 +438,23 @@ static int dwc3_probe(struct platform_device *pdev)
> dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
> }
>
> + if (of_property_read_bool(node, "phys") || pdata->has_phy) {
> + dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
> + if (IS_ERR(dwc->usb2_generic_phy)) {
> + dev_err(dev, "no usb2 phy configured yet");
> + return PTR_ERR(dwc->usb2_generic_phy);
> + }
> +
> + dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
> + if (IS_ERR(dwc->usb3_generic_phy)) {
> + dev_err(dev, "no usb3 phy configured yet");
> + return PTR_ERR(dwc->usb3_generic_phy);
> + }
> + } else {
> + dwc->usb2_generic_phy = NULL;
> + dwc->usb3_generic_phy = NULL;
> + }
> +
> /* default to superspeed if no maximum_speed passed */
> if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
> dwc->maximum_speed = USB_SPEED_SUPER;
> @@ -450,6 +478,11 @@ static int dwc3_probe(struct platform_device *pdev)
> usb_phy_set_suspend(dwc->usb2_phy, 0);
> usb_phy_set_suspend(dwc->usb3_phy, 0);
>
> + if (dwc->usb2_generic_phy)
> + phy_power_on(dwc->usb2_generic_phy);
> + if (dwc->usb3_generic_phy)
> + phy_power_on(dwc->usb3_generic_phy);
> +
> spin_lock_init(&dwc->lock);
> platform_set_drvdata(pdev, dwc);
>
> @@ -576,6 +609,11 @@ static int dwc3_remove(struct platform_device *pdev)
> usb_phy_set_suspend(dwc->usb2_phy, 1);
> usb_phy_set_suspend(dwc->usb3_phy, 1);
>
> + if (dwc->usb2_generic_phy)

if (IS_ERR())

> + phy_power_off(dwc->usb2_generic_phy);
> + if (dwc->usb3_generic_phy)

if (IS_ERR())

here and everywhere else in this patch.

> + phy_power_off(dwc->usb3_generic_phy);
> +
> pm_runtime_put(&pdev->dev);
> pm_runtime_disable(&pdev->dev);
>
> @@ -673,6 +711,11 @@ static int dwc3_suspend(struct device *dev)
> usb_phy_shutdown(dwc->usb3_phy);
> usb_phy_shutdown(dwc->usb2_phy);
>
> + if (dwc->usb2_generic_phy)
> + phy_exit(dwc->usb2_generic_phy);
> + if (dwc->usb3_generic_phy)
> + phy_exit(dwc->usb3_generic_phy);
> +
> return 0;
> }
>
> @@ -683,6 +726,12 @@ static int dwc3_resume(struct device *dev)
>
> usb_phy_init(dwc->usb3_phy);
> usb_phy_init(dwc->usb2_phy);
> +
> + if (dwc->usb2_generic_phy)
> + phy_init(dwc->usb2_generic_phy);
> + if (dwc->usb3_generic_phy)
> + phy_init(dwc->usb3_generic_phy);
> +
> msleep(100);
>
> spin_lock_irqsave(&dwc->lock, flags);
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index f8af8d4..01ec7d7 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -31,6 +31,8 @@
> #include <linux/usb/gadget.h>
> #include <linux/usb/otg.h>
>
> +#include <linux/phy/phy.h>
> +
> /* Global constants */
> #define DWC3_EP0_BOUNCE_SIZE 512
> #define DWC3_ENDPOINTS_NUM 32
> @@ -613,6 +615,8 @@ struct dwc3_scratchpad_array {
> * @dr_mode: requested mode of operation
> * @usb2_phy: pointer to USB2 PHY
> * @usb3_phy: pointer to USB3 PHY
> + * @usb2_generic_phy: pointer to USB2 PHY
> + * @usb3_generic_phy: pointer to USB3 PHY

Why duplicate usbX_phy and usbX_generic_phy? Can't we just have one
for each type and call it usbX_phy?

> * @dcfg: saved contents of DCFG register
> * @gctl: saved contents of GCTL register
> * @is_selfpowered: true when we are selfpowered
> @@ -665,6 +669,9 @@ struct dwc3 {
> struct usb_phy *usb2_phy;
> struct usb_phy *usb3_phy;
>
> + struct phy *usb2_generic_phy;
> + struct phy *usb3_generic_phy;
> +
> void __iomem *regs;
> size_t regs_size;
>
>

cheers,
-roger

2013-09-12 13:24:08

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 4/7] Documentation: dt bindings: move ..usb/usb-phy.txt to ..phy/omap-phy.txt

On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
> Since now we have a separate folder for phy, move the PHY dt binding
> documentation of OMAP to that folder.
>
> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
> ---
> .../devicetree/bindings/{usb/usb-phy.txt => phy/omap-phy.txt} | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
> rename Documentation/devicetree/bindings/{usb/usb-phy.txt => phy/omap-phy.txt} (96%)
>
> diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/phy/omap-phy.txt
> similarity index 96%
> rename from Documentation/devicetree/bindings/usb/usb-phy.txt
> rename to Documentation/devicetree/bindings/phy/omap-phy.txt
> index 36bdb17..2c485ee 100644
> --- a/Documentation/devicetree/bindings/usb/usb-phy.txt
> +++ b/Documentation/devicetree/bindings/phy/omap-phy.txt

ti-phy.txt?

> @@ -1,4 +1,4 @@
> -USB PHY
> +OMAP PHY: DT DOCUMENTATION FOR PHYs in OMAP PLATFORM

TI PHY: PHYs in Texas Instruments SoCs

cheers,
-roger

2013-09-12 13:29:30

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 6/7] arm/dts: added dt properties to adapt to the new phy framwork

Hi,

Need some commit log.

cheers,
-roger

On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
> ---
> arch/arm/boot/dts/omap5.dtsi | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
> index 94abef5..9fe71ff 100644
> --- a/arch/arm/boot/dts/omap5.dtsi
> +++ b/arch/arm/boot/dts/omap5.dtsi
> @@ -651,7 +651,8 @@
> compatible = "snps,dwc3";
> reg = <0x4a030000 0x10000>;
> interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
> - usb-phy = <&usb2_phy>, <&usb3_phy>;
> + phys = <&usb2_phy>, <&usb3_phy>;
> + phy-names = "usb2-phy", "usb3-phy";
> tx-fifo-resize;
> };
> };
> @@ -667,6 +668,7 @@
> compatible = "ti,omap-usb2";
> reg = <0x4a084000 0x7c>;
> ctrl-module = <&omap_control_usb2phy>;
> + #phy-cells = <0>;
> };
>
> usb3_phy: usb3phy@4a084400 {
> @@ -676,6 +678,7 @@
> <0x4a084c00 0x40>;
> reg-names = "phy_rx", "phy_tx", "pll_ctrl";
> ctrl-module = <&omap_control_usb3phy>;
> + #phy-cells = <0>;
> };
> };
>
>

2013-09-12 13:43:34

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 7/7] drivers: phy: renamed struct omap_control_usb to struct omap_control_phy

Hi,

On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
> renamed struct omap_control_usb to struct omap_control_phy since it can
> be used to control PHY of USB, SATA and PCIE. Also moved the driver and
> include files under *phy* and made the corresponding changes in the users
> of phy-omap-control.
>
> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
> ---
> drivers/phy/Kconfig | 14 +-
> drivers/phy/Makefile | 1 +
> drivers/{usb => }/phy/phy-omap-control.c | 164 ++++++++++----------
> drivers/phy/phy-omap-pipe3.c | 8 +-
> drivers/phy/phy-omap-usb2.c | 8 +-
> drivers/usb/musb/omap2430.c | 2 +-
> drivers/usb/phy/Makefile | 1 -
> .../omap_control_usb.h => phy/omap_control_phy.h} | 32 ++--
> 8 files changed, 120 insertions(+), 110 deletions(-)
> rename drivers/{usb => }/phy/phy-omap-control.c (55%)
> rename include/linux/{usb/omap_control_usb.h => phy/omap_control_phy.h} (69%)
>
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index 5c2e7a0..fd11294 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -15,12 +15,22 @@ config GENERIC_PHY
> phy users can obtain reference to the PHY. All the users of this
> framework should select this config.
>
> +config OMAP_CONTROL_PHY
> + tristate "OMAP CONTROL PHY Driver"
> + depends on ARCH_OMAP2PLUS || COMPILE_TEST
> + help
> + Enable this to add support for the PHY part present in the control
> + module. This driver has API to power on the USB2 PHY and to write to
> + the mailbox. The mailbox is present only in omap4 and the register to
> + power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has
> + additional registers to power on PIPE3 PHYs.
> +
> config OMAP_USB2
> tristate "OMAP USB2 PHY Driver"
> depends on ARCH_OMAP2PLUS
> select GENERIC_PHY
> select USB_PHY
> - select OMAP_CONTROL_USB
> + select OMAP_CONTROL_PHY
> help
> Enable this to support the transceiver that is part of SOC. This
> driver takes care of all the PHY functionality apart from comparator.
> @@ -30,7 +40,7 @@ config OMAP_USB2
> config OMAP_PIPE3
> tristate "OMAP PIPE3 PHY Driver"
> select GENERIC_PHY
> - select OMAP_CONTROL_USB
> + select OMAP_CONTROL_PHY
> help
> Enable this to support the PIPE3 PHY that is part of SOC. This
> driver takes care of all the PHY functionality apart from comparator.
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index 48bf9f2..f0127f6 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -3,6 +3,7 @@
> #
>
> obj-$(CONFIG_GENERIC_PHY) += phy-core.o
> +obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o
> obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
> obj-$(CONFIG_OMAP_PIPE3) += phy-omap-pipe3.o
> obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
> diff --git a/drivers/usb/phy/phy-omap-control.c b/drivers/phy/phy-omap-control.c
> similarity index 55%
> rename from drivers/usb/phy/phy-omap-control.c
> rename to drivers/phy/phy-omap-control.c
> index 1a7e19a..ece3573 100644
> --- a/drivers/usb/phy/phy-omap-control.c
> +++ b/drivers/phy/phy-omap-control.c
> @@ -1,5 +1,5 @@
> /*
> - * omap-control-usb.c - The USB part of control module.
> + * phy-omap-control.c - The USB part of control module.
> *
> * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
> * This program is free software; you can redistribute it and/or modify
> @@ -24,36 +24,36 @@
> #include <linux/err.h>
> #include <linux/io.h>
> #include <linux/clk.h>
> -#include <linux/usb/omap_control_usb.h>
> +#include <linux/phy/omap_control_phy.h>
>

<snip>

> #ifdef CONFIG_OF
>
> -static const enum omap_control_usb_type omap4_data = OMAP_CTRL_TYPE_OMAP4;
> -static const enum omap_control_usb_type usb2_data = OMAP_CTRL_TYPE_USB2;
> -static const enum omap_control_usb_type usb3_data = OMAP_CTRL_TYPE_USB3;
> -static const enum omap_control_usb_type dra7_data = OMAP_CTRL_TYPE_DRA7;
> +static const enum omap_control_phy_type omap4_data = OMAP_CTRL_TYPE_OMAP4;
> +static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2;
> +static const enum omap_control_phy_type usb3_data = OMAP_CTRL_TYPE_USB3;
> +static const enum omap_control_phy_type dra7_data = OMAP_CTRL_TYPE_DRA7;
>
> -static const struct of_device_id omap_control_usb_id_table[] = {
> +static const struct of_device_id omap_control_phy_id_table[] = {
> {
> .compatible = "ti,omap4-control-usb",
> .data = &omap4_data,
> @@ -286,31 +286,31 @@ static const struct of_device_id omap_control_usb_id_table[] = {
> },
> {},
> };
> -MODULE_DEVICE_TABLE(of, omap_control_usb_id_table);
> +MODULE_DEVICE_TABLE(of, omap_control_phy_id_table);
> #endif
>
> -static struct platform_driver omap_control_usb_driver = {
> - .probe = omap_control_usb_probe,
> +static struct platform_driver omap_control_phy_driver = {
> + .probe = omap_control_phy_probe,
> .driver = {
> .name = "omap-control-usb",
> .owner = THIS_MODULE,
> - .of_match_table = of_match_ptr(omap_control_usb_id_table),
> + .of_match_table = of_match_ptr(omap_control_phy_id_table),
> },
> };
>
> -static int __init omap_control_usb_init(void)
> +static int __init omap_control_phy_init(void)
> {
> - return platform_driver_register(&omap_control_usb_driver);
> + return platform_driver_register(&omap_control_phy_driver);
> }
> -subsys_initcall(omap_control_usb_init);
> +subsys_initcall(omap_control_phy_init);

Any specific reason for having this as subsys_initcall?

If not then you can use module_platform_driver().

>
> -static void __exit omap_control_usb_exit(void)
> +static void __exit omap_control_phy_exit(void)
> {
> - platform_driver_unregister(&omap_control_usb_driver);
> + platform_driver_unregister(&omap_control_phy_driver);
> }
> -module_exit(omap_control_usb_exit);
> +module_exit(omap_control_phy_exit);
>
> -MODULE_ALIAS("platform: omap_control_usb");
> +MODULE_ALIAS("platform: omap_control_phy");
> MODULE_AUTHOR("Texas Instruments Inc.");
> MODULE_DESCRIPTION("OMAP Control Module USB Driver");
> MODULE_LICENSE("GPL v2");

cheers,
-roger

2013-09-16 02:53:15

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

On Thursday 12 September 2013 06:49 PM, Roger Quadros wrote:
> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>> Adapted dwc3 core to use the Generic PHY Framework. So for init, exit,
>> power_on and power_off the following APIs are used phy_init(), phy_exit(),
>> phy_power_on() and phy_power_off().
>>
>> However using the old USB phy library wont be removed till the PHYs of all
>> other SoC's using dwc3 core is adapted to the Generic PHY Framework.
>>
>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>> ---
>> Documentation/devicetree/bindings/usb/dwc3.txt | 6 ++-
>> drivers/usb/dwc3/Kconfig | 1 +
>> drivers/usb/dwc3/core.c | 49 ++++++++++++++++++++++++
>> drivers/usb/dwc3/core.h | 7 ++++
>> 4 files changed, 61 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
>> index e807635..471366d 100644
>> --- a/Documentation/devicetree/bindings/usb/dwc3.txt
>> +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
>> @@ -6,11 +6,13 @@ Required properties:
>> - compatible: must be "snps,dwc3"
>> - reg : Address and length of the register set for the device
>> - interrupts: Interrupts used by the dwc3 controller.
>> +
>> +Optional properties:
>> - usb-phy : array of phandle for the PHY device. The first element
>> in the array is expected to be a handle to the USB2/HS PHY and
>> the second element is expected to be a handle to the USB3/SS PHY
>> -
>> -Optional properties:
>> + - phys: from the *Generic PHY* bindings
>> + - phy-names: from the *Generic PHY* bindings
>> - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
>>
>> This is usually a subnode to DWC3 glue to which it is connected.
>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>> index cfc16dd..ad7ce83 100644
>> --- a/drivers/usb/dwc3/Kconfig
>> +++ b/drivers/usb/dwc3/Kconfig
>> @@ -3,6 +3,7 @@ config USB_DWC3
>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
>> depends on EXTCON
>> select USB_PHY
>> + select GENERIC_PHY
>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
>> help
>> Say Y or M here if your system has a Dual Role SuperSpeed
>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>> index 428c29e..485d365 100644
>> --- a/drivers/usb/dwc3/core.c
>> +++ b/drivers/usb/dwc3/core.c
>> @@ -82,6 +82,12 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
>>
>> usb_phy_init(dwc->usb2_phy);
>> usb_phy_init(dwc->usb3_phy);
>> +
>> + if (dwc->usb2_generic_phy)
>> + phy_init(dwc->usb2_generic_phy);
>> + if (dwc->usb3_generic_phy)
>> + phy_init(dwc->usb3_generic_phy);
>> +
>> mdelay(100);
>>
>> /* Clear USB3 PHY reset */
>> @@ -343,6 +349,11 @@ static void dwc3_core_exit(struct dwc3 *dwc)
>> {
>> usb_phy_shutdown(dwc->usb2_phy);
>> usb_phy_shutdown(dwc->usb3_phy);
>> +
>> + if (dwc->usb2_generic_phy)
>> + phy_power_off(dwc->usb2_generic_phy);
>> + if (dwc->usb3_generic_phy)
>> + phy_power_off(dwc->usb3_generic_phy);
>> }
>>
>> #define DWC3_ALIGN_MASK (16 - 1)
>> @@ -427,6 +438,23 @@ static int dwc3_probe(struct platform_device *pdev)
>> dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
>> }
>>
>> + if (of_property_read_bool(node, "phys") || pdata->has_phy) {
>> + dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
>> + if (IS_ERR(dwc->usb2_generic_phy)) {
>> + dev_err(dev, "no usb2 phy configured yet");
>> + return PTR_ERR(dwc->usb2_generic_phy);
>> + }
>> +
>> + dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
>> + if (IS_ERR(dwc->usb3_generic_phy)) {
>> + dev_err(dev, "no usb3 phy configured yet");
>> + return PTR_ERR(dwc->usb3_generic_phy);
>> + }
>> + } else {
>> + dwc->usb2_generic_phy = NULL;
>> + dwc->usb3_generic_phy = NULL;
>> + }
>> +
>> /* default to superspeed if no maximum_speed passed */
>> if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
>> dwc->maximum_speed = USB_SPEED_SUPER;
>> @@ -450,6 +478,11 @@ static int dwc3_probe(struct platform_device *pdev)
>> usb_phy_set_suspend(dwc->usb2_phy, 0);
>> usb_phy_set_suspend(dwc->usb3_phy, 0);
>>
>> + if (dwc->usb2_generic_phy)
>> + phy_power_on(dwc->usb2_generic_phy);
>> + if (dwc->usb3_generic_phy)
>> + phy_power_on(dwc->usb3_generic_phy);
>> +
>> spin_lock_init(&dwc->lock);
>> platform_set_drvdata(pdev, dwc);
>>
>> @@ -576,6 +609,11 @@ static int dwc3_remove(struct platform_device *pdev)
>> usb_phy_set_suspend(dwc->usb2_phy, 1);
>> usb_phy_set_suspend(dwc->usb3_phy, 1);
>>
>> + if (dwc->usb2_generic_phy)
>
> if (IS_ERR())

I assign NULL to usb2_generic_phy and usb3_generic_phy in case the dts
entry doesn't have a *phys* property.
The IS_ERR of usb2_generic_phy is treated as an error condition and
probe will fail.
>
>> + phy_power_off(dwc->usb2_generic_phy);
>> + if (dwc->usb3_generic_phy)
>
> if (IS_ERR())
>
> here and everywhere else in this patch.
>
>> + phy_power_off(dwc->usb3_generic_phy);
>> +
>> pm_runtime_put(&pdev->dev);
>> pm_runtime_disable(&pdev->dev);
>>
>> @@ -673,6 +711,11 @@ static int dwc3_suspend(struct device *dev)
>> usb_phy_shutdown(dwc->usb3_phy);
>> usb_phy_shutdown(dwc->usb2_phy);
>>
>> + if (dwc->usb2_generic_phy)
>> + phy_exit(dwc->usb2_generic_phy);
>> + if (dwc->usb3_generic_phy)
>> + phy_exit(dwc->usb3_generic_phy);
>> +
>> return 0;
>> }
>>
>> @@ -683,6 +726,12 @@ static int dwc3_resume(struct device *dev)
>>
>> usb_phy_init(dwc->usb3_phy);
>> usb_phy_init(dwc->usb2_phy);
>> +
>> + if (dwc->usb2_generic_phy)
>> + phy_init(dwc->usb2_generic_phy);
>> + if (dwc->usb3_generic_phy)
>> + phy_init(dwc->usb3_generic_phy);
>> +
>> msleep(100);
>>
>> spin_lock_irqsave(&dwc->lock, flags);
>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>> index f8af8d4..01ec7d7 100644
>> --- a/drivers/usb/dwc3/core.h
>> +++ b/drivers/usb/dwc3/core.h
>> @@ -31,6 +31,8 @@
>> #include <linux/usb/gadget.h>
>> #include <linux/usb/otg.h>
>>
>> +#include <linux/phy/phy.h>
>> +
>> /* Global constants */
>> #define DWC3_EP0_BOUNCE_SIZE 512
>> #define DWC3_ENDPOINTS_NUM 32
>> @@ -613,6 +615,8 @@ struct dwc3_scratchpad_array {
>> * @dr_mode: requested mode of operation
>> * @usb2_phy: pointer to USB2 PHY
>> * @usb3_phy: pointer to USB3 PHY
>> + * @usb2_generic_phy: pointer to USB2 PHY
>> + * @usb3_generic_phy: pointer to USB3 PHY
>
> Why duplicate usbX_phy and usbX_generic_phy? Can't we just have one
> for each type and call it usbX_phy?

There was an already existing phy library in usb which usesusb_phy.
There might still be users using the existing usb phy library. Until all
the users have completely migrated to the generic PHY framework, this
would co-exist.

Thanks
Kishon

2013-09-16 03:02:51

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: Re: [PATCH 3/7] drivers: phy: usb3/pipe3: Adapt pipe3 driver to Generic PHY Framework

On Thursday 12 September 2013 04:49 PM, Roger Quadros wrote:
> Hi Kishon,
>
> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>> Adapted omap-usb3 PHY driver to Generic PHY Framework and moved phy-omap-usb3
>> driver in drivers/usb/phy to drivers/phy and also renamed the file to
>> phy-omap-pipe3 since this same driver will be used for SATA PHY and
>> PCIE PHY.
>
> I would suggest to split the renaming and PHY adaptation into 2 separate patches.

Alright.
>
>>
>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>> ---
>> Documentation/devicetree/bindings/usb/usb-phy.txt | 5 +-
>> drivers/phy/Kconfig | 10 +
>> drivers/phy/Makefile | 1 +
>> .../phy/phy-omap-usb3.c => phy/phy-omap-pipe3.c} | 206 +++++++++++---------
>
> how about naming it to phy-ti-pipe3.c as it is used on OMAP as well as non-OMAP e.g. DRA7.

hmm.. I thought it would be consistent with other PHY drivers
(phy-omap-usb2). Moreover DRA7 is OMAP based platform ;-) Maybe we
should reserve that for later?
>
>> drivers/usb/phy/Kconfig | 11 --
>> drivers/usb/phy/Makefile | 1 -
>> include/linux/phy/omap_pipe3.h | 52 +++++
>> 7 files changed, 177 insertions(+), 109 deletions(-)
>> rename drivers/{usb/phy/phy-omap-usb3.c => phy/phy-omap-pipe3.c} (57%)
>> create mode 100644 include/linux/phy/omap_pipe3.h
>>
>> diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/usb/usb-phy.txt
>> index c0245c8..36bdb17 100644
>> --- a/Documentation/devicetree/bindings/usb/usb-phy.txt
>> +++ b/Documentation/devicetree/bindings/usb/usb-phy.txt
>> @@ -21,10 +21,11 @@ usb2phy@4a0ad080 {
>> #phy-cells = <0>;
>> };
>>
>> -OMAP USB3 PHY
>> +OMAP PIPE3 PHY
>>
>> Required properties:
>> - - compatible: Should be "ti,omap-usb3"
>> + - compatible: Should be "ti,omap-usb3", "ti,omap-pipe3", "ti,omap-sata"
>> + or "ti,omap-pcie"
>> - reg : Address and length of the register set for the device.
>> - reg-names: The names of the register addresses corresponding to the registers
>> filled in "reg".
>> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
>> index ac239ac..5c2e7a0 100644
>> --- a/drivers/phy/Kconfig
>> +++ b/drivers/phy/Kconfig
>> @@ -27,6 +27,16 @@ config OMAP_USB2
>> The USB OTG controller communicates with the comparator using this
>> driver.
>>
>> +config OMAP_PIPE3
>> + tristate "OMAP PIPE3 PHY Driver"
>> + select GENERIC_PHY
>> + select OMAP_CONTROL_USB
> how about
> depends on OMAP_CONTROL_USB

From whatever I could make out from comments of Greg in my Generic PHY
Framework, it's better to do a select of dependent modules instead of
depends on.
>
> Also, if this is TI/OMAP it might as well depend on ARCH_OMAP.
>
>> + help
>> + Enable this to support the PIPE3 PHY that is part of SOC. This
>
> worth mentioning TI OMAP/DRA SoCs.

right.
>
>> + driver takes care of all the PHY functionality apart from comparator.
>> + This driver interacts with the "OMAP Control PHY Driver" to power
>> + on/off the PHY.
>> +
>> config TWL4030_USB
>> tristate "TWL4030 USB Transceiver Driver"
>> depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
>> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
>> index 0dd8a98..48bf9f2 100644
>> --- a/drivers/phy/Makefile
>> +++ b/drivers/phy/Makefile
>> @@ -4,4 +4,5 @@
>>
>> obj-$(CONFIG_GENERIC_PHY) += phy-core.o
>> obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
>> +obj-$(CONFIG_OMAP_PIPE3) += phy-omap-pipe3.o
>> obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
>> diff --git a/drivers/usb/phy/phy-omap-usb3.c b/drivers/phy/phy-omap-pipe3.c
>> similarity index 57%
>> rename from drivers/usb/phy/phy-omap-usb3.c
>> rename to drivers/phy/phy-omap-pipe3.c
>> index 4004f82..ee9a901 100644
>> --- a/drivers/usb/phy/phy-omap-usb3.c
>> +++ b/drivers/phy/phy-omap-pipe3.c
>> @@ -1,5 +1,5 @@
>> /*
>> - * omap-usb3 - USB PHY, talking to dwc3 controller in OMAP.
>> + * omap-pipe3 - PHY driver for SATA, USB and PCIE in OMAP platforms
>> *
>> * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
>> * This program is free software; you can redistribute it and/or modify
>> @@ -19,7 +19,8 @@
>> #include <linux/module.h>
>> #include <linux/platform_device.h>
>> #include <linux/slab.h>
>> -#include <linux/usb/omap_usb.h>
>> +#include <linux/phy/omap_pipe3.h>
>> +#include <linux/phy/phy.h>
>> #include <linux/of.h>
>> #include <linux/clk.h>
>> #include <linux/err.h>
>> @@ -52,17 +53,17 @@
>>
>> /*
>> * This is an Empirical value that works, need to confirm the actual
>> - * value required for the USB3PHY_PLL_CONFIGURATION2.PLL_IDLE status
>> - * to be correctly reflected in the USB3PHY_PLL_STATUS register.
>> + * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status
>> + * to be correctly reflected in the PIPE3PHY_PLL_STATUS register.
>> */
>> # define PLL_IDLE_TIME 100;
>>
>> -struct usb_dpll_map {
>> +struct pipe3_dpll_map {
>> unsigned long rate;
>> - struct usb_dpll_params params;
>> + struct pipe3_dpll_params params;
>> };
>>
>> -static struct usb_dpll_map dpll_map[] = {
>> +static struct pipe3_dpll_map dpll_map[] = {
>> {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */
>> {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */
>> {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */
>> @@ -71,7 +72,7 @@ static struct usb_dpll_map dpll_map[] = {
>> {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */
>> };
>>
>> -static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate)
>> +static struct pipe3_dpll_params *omap_pipe3_get_dpll_params(unsigned long rate)
>> {
>> int i;
>>
>> @@ -83,110 +84,113 @@ static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate)
>> return 0;
>> }
>>
>> -static int omap_usb3_suspend(struct usb_phy *x, int suspend)
>> +static int omap_pipe3_power_off(struct phy *x)
>> {
>> - struct omap_usb *phy = phy_to_omapusb(x);
>> - int val;
>> + struct omap_pipe3 *phy = phy_get_drvdata(x);
>> + int val;
>> int timeout = PLL_IDLE_TIME;
>>
>> - if (suspend && !phy->is_suspended) {
>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>> - val |= PLL_IDLE;
>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>> -
>> - do {
>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
>> - if (val & PLL_TICOPWDN)
>> - break;
>> - udelay(1);
>> - } while (--timeout);
>> -
>> - omap_control_usb_phy_power(phy->control_dev, 0);
>> -
>> - phy->is_suspended = 1;
>> - } else if (!suspend && phy->is_suspended) {
>> - phy->is_suspended = 0;
>> -
>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>> - val &= ~PLL_IDLE;
>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>> -
>> - do {
>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
>> - if (!(val & PLL_TICOPWDN))
>> - break;
>> - udelay(1);
>> - } while (--timeout);
>> - }
>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>> + val |= PLL_IDLE;
>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>> +
>> + do {
>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
>> + if (val & PLL_TICOPWDN)
>> + break;
>> + udelay(1);
>
> Is it better to sleep instead of udelay?

hmm.. yeah, I guess this function wont be called from interrupt context.
>
>> + } while (--timeout);
>> +
>> + omap_control_usb_phy_power(phy->control_dev, 0);
>> +
>> + return 0;
>> +}
>> +
>> +static int omap_pipe3_power_on(struct phy *x)
>> +{
>> + struct omap_pipe3 *phy = phy_get_drvdata(x);
>> + int val;
>> + int timeout = PLL_IDLE_TIME;
>> +
>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>> + val &= ~PLL_IDLE;
>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>> +
>> + do {
>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
>> + if (!(val & PLL_TICOPWDN))
>> + break;
>> + udelay(1);
>
> here too.

Ok.
>
>> + } while (--timeout);
>>
>> return 0;
>> }
>>
>> -static void omap_usb_dpll_relock(struct omap_usb *phy)
>> +static void omap_pipe3_dpll_relock(struct omap_pipe3 *phy)
>> {
>> u32 val;
>> unsigned long timeout;
>>
>> - omap_usb_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
>>
>> timeout = jiffies + msecs_to_jiffies(20);
>> do {
>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
>> if (val & PLL_LOCK)
>> break;
>> } while (!WARN_ON(time_after(jiffies, timeout)));
>> }
>>
>> -static int omap_usb_dpll_lock(struct omap_usb *phy)
>> +static int omap_pipe3_dpll_lock(struct omap_pipe3 *phy)
>> {
>> u32 val;
>> unsigned long rate;
>> - struct usb_dpll_params *dpll_params;
>> + struct pipe3_dpll_params *dpll_params;
>>
>> rate = clk_get_rate(phy->sys_clk);
>> - dpll_params = omap_usb3_get_dpll_params(rate);
>> + dpll_params = omap_pipe3_get_dpll_params(rate);
>> if (!dpll_params) {
>> dev_err(phy->dev,
>> "No DPLL configuration for %lu Hz SYS CLK\n", rate);
>> return -EINVAL;
>> }
>>
>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
>> val &= ~PLL_REGN_MASK;
>> val |= dpll_params->n << PLL_REGN_SHIFT;
>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>>
>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>> val &= ~PLL_SELFREQDCO_MASK;
>> val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>
>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
>> val &= ~PLL_REGM_MASK;
>> val |= dpll_params->m << PLL_REGM_SHIFT;
>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>>
>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
>> val &= ~PLL_REGM_F_MASK;
>> val |= dpll_params->mf << PLL_REGM_F_SHIFT;
>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
>>
>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
>> val &= ~PLL_SD_MASK;
>> val |= dpll_params->sd << PLL_SD_SHIFT;
>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
>>
>> - omap_usb_dpll_relock(phy);
>> + omap_pipe3_dpll_relock(phy);
>>
>> return 0;
>> }
>>
>> -static int omap_usb3_init(struct usb_phy *x)
>> +static int omap_pipe3_init(struct phy *x)
>> {
>> - struct omap_usb *phy = phy_to_omapusb(x);
>> + struct omap_pipe3 *phy = phy_get_drvdata(x);
>> int ret;
>>
>> - ret = omap_usb_dpll_lock(phy);
>> + ret = omap_pipe3_dpll_lock(phy);
>> if (ret)
>> return ret;
>>
>> @@ -195,9 +199,18 @@ static int omap_usb3_init(struct usb_phy *x)
>> return 0;
>> }
>>
>> -static int omap_usb3_probe(struct platform_device *pdev)
>> +static struct phy_ops ops = {
>> + .init = omap_pipe3_init,
>> + .power_on = omap_pipe3_power_on,
>> + .power_off = omap_pipe3_power_off,
>> + .owner = THIS_MODULE,
>> +};
>> +
>> +static int omap_pipe3_probe(struct platform_device *pdev)
>> {
>> - struct omap_usb *phy;
>> + struct omap_pipe3 *phy;
>> + struct phy *generic_phy;
>> + struct phy_provider *phy_provider;
>> struct resource *res;
>> struct device_node *node = pdev->dev.of_node;
>> struct device_node *control_node;
>> @@ -208,7 +221,7 @@ static int omap_usb3_probe(struct platform_device *pdev)
>>
>> phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
>> if (!phy) {
>> - dev_err(&pdev->dev, "unable to alloc mem for OMAP USB3 PHY\n");
>> + dev_err(&pdev->dev, "unable to alloc mem for OMAP PIPE3 PHY\n");
>> return -ENOMEM;
>> }
>>
>> @@ -219,13 +232,6 @@ static int omap_usb3_probe(struct platform_device *pdev)
>>
>> phy->dev = &pdev->dev;
>>
>> - phy->phy.dev = phy->dev;
>> - phy->phy.label = "omap-usb3";
>> - phy->phy.init = omap_usb3_init;
>> - phy->phy.set_suspend = omap_usb3_suspend;
>> - phy->phy.type = USB_PHY_TYPE_USB3;
>> -
>> - phy->is_suspended = 1;
>> phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
>
> As this is no longer USB specific, we need to make the clock binding generic as well.

right. Its also needed when we have the same driver work for sata and
pcie. Maybe do that in a separate patch?
>
>> if (IS_ERR(phy->wkupclk)) {
>> dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
>> @@ -251,6 +257,11 @@ static int omap_usb3_probe(struct platform_device *pdev)
>> dev_err(&pdev->dev, "Failed to get control device phandle\n");
>> return -EINVAL;
>> }
>> + phy_provider = devm_of_phy_provider_register(phy->dev,
>> + of_phy_simple_xlate);
>> + if (IS_ERR(phy_provider))
>> + return PTR_ERR(phy_provider);
>> +
>> control_pdev = of_find_device_by_node(control_node);
>> if (!control_pdev) {
>> dev_err(&pdev->dev, "Failed to get control device\n");
>> @@ -260,23 +271,27 @@ static int omap_usb3_probe(struct platform_device *pdev)
>> phy->control_dev = &control_pdev->dev;
>>
>> omap_control_usb_phy_power(phy->control_dev, 0);
>> - usb_add_phy_dev(&phy->phy);
>>
>> platform_set_drvdata(pdev, phy);
>> -
>> pm_runtime_enable(phy->dev);
>> +
>> + generic_phy = devm_phy_create(phy->dev, &ops, NULL);
>> + if (IS_ERR(generic_phy))
>> + return PTR_ERR(generic_phy);
>> +
>> + phy_set_drvdata(generic_phy, phy);
>> +
>> pm_runtime_get(&pdev->dev);
>>
>> return 0;
>> }
>>
>> -static int omap_usb3_remove(struct platform_device *pdev)
>> +static int omap_pipe3_remove(struct platform_device *pdev)
>> {
>> - struct omap_usb *phy = platform_get_drvdata(pdev);
>> + struct omap_pipe3 *phy = platform_get_drvdata(pdev);
>>
>> clk_unprepare(phy->wkupclk);
>> clk_unprepare(phy->optclk);
>> - usb_remove_phy(&phy->phy);
>> if (!pm_runtime_suspended(&pdev->dev))
>> pm_runtime_put(&pdev->dev);
>> pm_runtime_disable(&pdev->dev);
>> @@ -286,10 +301,9 @@ static int omap_usb3_remove(struct platform_device *pdev)
>>
>> #ifdef CONFIG_PM_RUNTIME
>>
>> -static int omap_usb3_runtime_suspend(struct device *dev)
>> +static int omap_pipe3_runtime_suspend(struct device *dev)
>> {
>> - struct platform_device *pdev = to_platform_device(dev);
>> - struct omap_usb *phy = platform_get_drvdata(pdev);
>> + struct omap_pipe3 *phy = dev_get_drvdata(dev);
>>
>> clk_disable(phy->wkupclk);
>> clk_disable(phy->optclk);
>> @@ -297,11 +311,10 @@ static int omap_usb3_runtime_suspend(struct device *dev)
>> return 0;
>> }
>>
>> -static int omap_usb3_runtime_resume(struct device *dev)
>> +static int omap_pipe3_runtime_resume(struct device *dev)
>> {
>> u32 ret = 0;
>> - struct platform_device *pdev = to_platform_device(dev);
>> - struct omap_usb *phy = platform_get_drvdata(pdev);
>> + struct omap_pipe3 *phy = dev_get_drvdata(dev);
>>
>> ret = clk_enable(phy->optclk);
>> if (ret) {
>> @@ -324,38 +337,41 @@ err1:
>> return ret;
>> }
>>
>> -static const struct dev_pm_ops omap_usb3_pm_ops = {
>> - SET_RUNTIME_PM_OPS(omap_usb3_runtime_suspend, omap_usb3_runtime_resume,
>> - NULL)
>> +static const struct dev_pm_ops omap_pipe3_pm_ops = {
>> + SET_RUNTIME_PM_OPS(omap_pipe3_runtime_suspend,
>> + omap_pipe3_runtime_resume, NULL)
>> };
>>
>> -#define DEV_PM_OPS (&omap_usb3_pm_ops)
>> +#define DEV_PM_OPS (&omap_pipe3_pm_ops)
>> #else
>> #define DEV_PM_OPS NULL
>> #endif
>>
>> #ifdef CONFIG_OF
>> -static const struct of_device_id omap_usb3_id_table[] = {
>> +static const struct of_device_id omap_pipe3_id_table[] = {
>> + { .compatible = "ti,omap-pipe3" },
>
> why do you need "omap-pipe3", isn't sata, pcie and usb3 sufficient?

I thought it would be better if everyone uses omap-pipe3 and added pcie,
sata if there are any specific settings (for pcie or sata) that should
be done.
>
>> + { .compatible = "ti,omap-sata" },
>> + { .compatible = "ti,omap-pcie" },
>> { .compatible = "ti,omap-usb3" },
>> {}
>> };
>> -MODULE_DEVICE_TABLE(of, omap_usb3_id_table);
>> +MODULE_DEVICE_TABLE(of, omap_pipe3_id_table);
>> #endif
>>
>> -static struct platform_driver omap_usb3_driver = {
>> - .probe = omap_usb3_probe,
>> - .remove = omap_usb3_remove,
>> +static struct platform_driver omap_pipe3_driver = {
>> + .probe = omap_pipe3_probe,
>> + .remove = omap_pipe3_remove,
>> .driver = {
>> - .name = "omap-usb3",
>> + .name = "omap-pipe3",
>> .owner = THIS_MODULE,
>> .pm = DEV_PM_OPS,
>> - .of_match_table = of_match_ptr(omap_usb3_id_table),
>> + .of_match_table = of_match_ptr(omap_pipe3_id_table),
>> },
>> };
>>
>> -module_platform_driver(omap_usb3_driver);
>> +module_platform_driver(omap_pipe3_driver);
>>
>> -MODULE_ALIAS("platform: omap_usb3");
>> +MODULE_ALIAS("platform: omap_pipe3");
>> MODULE_AUTHOR("Texas Instruments Inc.");
>> -MODULE_DESCRIPTION("OMAP USB3 phy driver");
>> +MODULE_DESCRIPTION("OMAP PIPE3 phy driver");
>> MODULE_LICENSE("GPL v2");
>> diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
>> index d69cdad..0210e03 100644
>> --- a/drivers/usb/phy/Kconfig
>> +++ b/drivers/usb/phy/Kconfig
>> @@ -66,17 +66,6 @@ config OMAP_CONTROL_USB
>> power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
>> additional register to power on USB3 PHY.
>>
>> -config OMAP_USB3
>> - tristate "OMAP USB3 PHY Driver"
>> - depends on ARCH_OMAP2PLUS || COMPILE_TEST
>> - select OMAP_CONTROL_USB
>> - select USB_PHY
>> - help
>> - Enable this to support the USB3 PHY that is part of SOC. This
>> - driver takes care of all the PHY functionality apart from comparator.
>> - This driver interacts with the "OMAP Control USB Driver" to power
>> - on/off the PHY.
>> -
>> config AM335X_CONTROL_USB
>> tristate
>>
>> diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
>> index 51968d7..d1c9683 100644
>> --- a/drivers/usb/phy/Makefile
>> +++ b/drivers/usb/phy/Makefile
>> @@ -13,7 +13,6 @@ obj-$(CONFIG_ISP1301_OMAP) += phy-isp1301-omap.o
>> obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o
>> obj-$(CONFIG_NOP_USB_XCEIV) += phy-generic.o
>> obj-$(CONFIG_OMAP_CONTROL_USB) += phy-omap-control.o
>> -obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o
>> obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o
>> obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o
>> obj-$(CONFIG_SAMSUNG_USB3PHY) += phy-samsung-usb3.o
>> diff --git a/include/linux/phy/omap_pipe3.h b/include/linux/phy/omap_pipe3.h
>> new file mode 100644
>> index 0000000..7329056
>> --- /dev/null
>> +++ b/include/linux/phy/omap_pipe3.h
>
> ti_pipe3.h ?
>
>> @@ -0,0 +1,52 @@
>> +/*
>> + * omap_pipe3.h -- omap pipe3 phy header file
>> + *
>> + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * Author: Kishon Vijay Abraham I <[email protected]>
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + */
>> +
>> +#ifndef __DRIVERS_OMAP_PIPE3_H
>> +#define __DRIVERS_OMAP_PIPE3_H
>> +
>> +#include <linux/io.h>
>> +
>> +struct pipe3_dpll_params {
>> + u16 m;
>> + u8 n;
>> + u8 freq:3;
>> + u8 sd;
>> + u32 mf;
>> +};
>> +
>> +struct omap_pipe3 {
>> + void __iomem *pll_ctrl_base;
>> + struct device *dev;
>> + struct device *control_dev;
>> + struct clk *wkupclk;
>> + struct clk *sys_clk;
>
> sysclk. To be consistent with others?

Ok.

Thanks
Kishon

2013-09-16 03:04:50

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: Re: [PATCH 4/7] Documentation: dt bindings: move ..usb/usb-phy.txt to ..phy/omap-phy.txt

On Thursday 12 September 2013 06:53 PM, Roger Quadros wrote:
> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>> Since now we have a separate folder for phy, move the PHY dt binding
>> documentation of OMAP to that folder.
>>
>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>> ---
>> .../devicetree/bindings/{usb/usb-phy.txt => phy/omap-phy.txt} | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>> rename Documentation/devicetree/bindings/{usb/usb-phy.txt => phy/omap-phy.txt} (96%)
>>
>> diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/phy/omap-phy.txt
>> similarity index 96%
>> rename from Documentation/devicetree/bindings/usb/usb-phy.txt
>> rename to Documentation/devicetree/bindings/phy/omap-phy.txt
>> index 36bdb17..2c485ee 100644
>> --- a/Documentation/devicetree/bindings/usb/usb-phy.txt
>> +++ b/Documentation/devicetree/bindings/phy/omap-phy.txt
>
> ti-phy.txt?

maybe wait for that later?

Thanks
Kishon

2013-09-16 03:07:35

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: Re: [PATCH 7/7] drivers: phy: renamed struct omap_control_usb to struct omap_control_phy

On Thursday 12 September 2013 07:12 PM, Roger Quadros wrote:
> Hi,
>
> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>> renamed struct omap_control_usb to struct omap_control_phy since it can
>> be used to control PHY of USB, SATA and PCIE. Also moved the driver and
>> include files under *phy* and made the corresponding changes in the users
>> of phy-omap-control.
>>
>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>> ---
>> drivers/phy/Kconfig | 14 +-
>> drivers/phy/Makefile | 1 +
>> drivers/{usb => }/phy/phy-omap-control.c | 164 ++++++++++----------
>> drivers/phy/phy-omap-pipe3.c | 8 +-
>> drivers/phy/phy-omap-usb2.c | 8 +-
>> drivers/usb/musb/omap2430.c | 2 +-
>> drivers/usb/phy/Makefile | 1 -
>> .../omap_control_usb.h => phy/omap_control_phy.h} | 32 ++--
>> 8 files changed, 120 insertions(+), 110 deletions(-)
>> rename drivers/{usb => }/phy/phy-omap-control.c (55%)
>> rename include/linux/{usb/omap_control_usb.h => phy/omap_control_phy.h} (69%)
>>
>> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
>> index 5c2e7a0..fd11294 100644
>> --- a/drivers/phy/Kconfig
>> +++ b/drivers/phy/Kconfig
>> @@ -15,12 +15,22 @@ config GENERIC_PHY
>> phy users can obtain reference to the PHY. All the users of this
>> framework should select this config.
>>
>> +config OMAP_CONTROL_PHY
>> + tristate "OMAP CONTROL PHY Driver"
>> + depends on ARCH_OMAP2PLUS || COMPILE_TEST
>> + help
>> + Enable this to add support for the PHY part present in the control
>> + module. This driver has API to power on the USB2 PHY and to write to
>> + the mailbox. The mailbox is present only in omap4 and the register to
>> + power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has
>> + additional registers to power on PIPE3 PHYs.
>> +
>> config OMAP_USB2
>> tristate "OMAP USB2 PHY Driver"
>> depends on ARCH_OMAP2PLUS
>> select GENERIC_PHY
>> select USB_PHY
>> - select OMAP_CONTROL_USB
>> + select OMAP_CONTROL_PHY
>> help
>> Enable this to support the transceiver that is part of SOC. This
>> driver takes care of all the PHY functionality apart from comparator.
>> @@ -30,7 +40,7 @@ config OMAP_USB2
>> config OMAP_PIPE3
>> tristate "OMAP PIPE3 PHY Driver"
>> select GENERIC_PHY
>> - select OMAP_CONTROL_USB
>> + select OMAP_CONTROL_PHY
>> help
>> Enable this to support the PIPE3 PHY that is part of SOC. This
>> driver takes care of all the PHY functionality apart from comparator.
>> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
>> index 48bf9f2..f0127f6 100644
>> --- a/drivers/phy/Makefile
>> +++ b/drivers/phy/Makefile
>> @@ -3,6 +3,7 @@
>> #
>>
>> obj-$(CONFIG_GENERIC_PHY) += phy-core.o
>> +obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o
>> obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
>> obj-$(CONFIG_OMAP_PIPE3) += phy-omap-pipe3.o
>> obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
>> diff --git a/drivers/usb/phy/phy-omap-control.c b/drivers/phy/phy-omap-control.c
>> similarity index 55%
>> rename from drivers/usb/phy/phy-omap-control.c
>> rename to drivers/phy/phy-omap-control.c
>> index 1a7e19a..ece3573 100644
>> --- a/drivers/usb/phy/phy-omap-control.c
>> +++ b/drivers/phy/phy-omap-control.c
>> @@ -1,5 +1,5 @@
>> /*
>> - * omap-control-usb.c - The USB part of control module.
>> + * phy-omap-control.c - The USB part of control module.
>> *
>> * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
>> * This program is free software; you can redistribute it and/or modify
>> @@ -24,36 +24,36 @@
>> #include <linux/err.h>
>> #include <linux/io.h>
>> #include <linux/clk.h>
>> -#include <linux/usb/omap_control_usb.h>
>> +#include <linux/phy/omap_control_phy.h>
>>
>
> <snip>
>
>> #ifdef CONFIG_OF
>>
>> -static const enum omap_control_usb_type omap4_data = OMAP_CTRL_TYPE_OMAP4;
>> -static const enum omap_control_usb_type usb2_data = OMAP_CTRL_TYPE_USB2;
>> -static const enum omap_control_usb_type usb3_data = OMAP_CTRL_TYPE_USB3;
>> -static const enum omap_control_usb_type dra7_data = OMAP_CTRL_TYPE_DRA7;
>> +static const enum omap_control_phy_type omap4_data = OMAP_CTRL_TYPE_OMAP4;
>> +static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2;
>> +static const enum omap_control_phy_type usb3_data = OMAP_CTRL_TYPE_USB3;
>> +static const enum omap_control_phy_type dra7_data = OMAP_CTRL_TYPE_DRA7;
>>
>> -static const struct of_device_id omap_control_usb_id_table[] = {
>> +static const struct of_device_id omap_control_phy_id_table[] = {
>> {
>> .compatible = "ti,omap4-control-usb",
>> .data = &omap4_data,
>> @@ -286,31 +286,31 @@ static const struct of_device_id omap_control_usb_id_table[] = {
>> },
>> {},
>> };
>> -MODULE_DEVICE_TABLE(of, omap_control_usb_id_table);
>> +MODULE_DEVICE_TABLE(of, omap_control_phy_id_table);
>> #endif
>>
>> -static struct platform_driver omap_control_usb_driver = {
>> - .probe = omap_control_usb_probe,
>> +static struct platform_driver omap_control_phy_driver = {
>> + .probe = omap_control_phy_probe,
>> .driver = {
>> .name = "omap-control-usb",
>> .owner = THIS_MODULE,
>> - .of_match_table = of_match_ptr(omap_control_usb_id_table),
>> + .of_match_table = of_match_ptr(omap_control_phy_id_table),
>> },
>> };
>>
>> -static int __init omap_control_usb_init(void)
>> +static int __init omap_control_phy_init(void)
>> {
>> - return platform_driver_register(&omap_control_usb_driver);
>> + return platform_driver_register(&omap_control_phy_driver);
>> }
>> -subsys_initcall(omap_control_usb_init);
>> +subsys_initcall(omap_control_phy_init);
>
> Any specific reason for having this as subsys_initcall?

No. I think this driver was written when probe defer mechanism was not
introduced in the kernel.
>
> If not then you can use module_platform_driver().

right.

Thanks
Kishon

2013-09-16 07:26:07

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

Hi,

On 09/16/2013 05:52 AM, Kishon Vijay Abraham I wrote:
> On Thursday 12 September 2013 06:49 PM, Roger Quadros wrote:
>> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>>> Adapted dwc3 core to use the Generic PHY Framework. So for init, exit,
>>> power_on and power_off the following APIs are used phy_init(), phy_exit(),
>>> phy_power_on() and phy_power_off().
>>>
>>> However using the old USB phy library wont be removed till the PHYs of all
>>> other SoC's using dwc3 core is adapted to the Generic PHY Framework.
>>>
>>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>>> ---
>>> Documentation/devicetree/bindings/usb/dwc3.txt | 6 ++-
>>> drivers/usb/dwc3/Kconfig | 1 +
>>> drivers/usb/dwc3/core.c | 49 ++++++++++++++++++++++++
>>> drivers/usb/dwc3/core.h | 7 ++++
>>> 4 files changed, 61 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
>>> index e807635..471366d 100644
>>> --- a/Documentation/devicetree/bindings/usb/dwc3.txt
>>> +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
>>> @@ -6,11 +6,13 @@ Required properties:
>>> - compatible: must be "snps,dwc3"
>>> - reg : Address and length of the register set for the device
>>> - interrupts: Interrupts used by the dwc3 controller.
>>> +
>>> +Optional properties:
>>> - usb-phy : array of phandle for the PHY device. The first element
>>> in the array is expected to be a handle to the USB2/HS PHY and
>>> the second element is expected to be a handle to the USB3/SS PHY
>>> -
>>> -Optional properties:
>>> + - phys: from the *Generic PHY* bindings
>>> + - phy-names: from the *Generic PHY* bindings
>>> - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
>>>
>>> This is usually a subnode to DWC3 glue to which it is connected.
>>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>>> index cfc16dd..ad7ce83 100644
>>> --- a/drivers/usb/dwc3/Kconfig
>>> +++ b/drivers/usb/dwc3/Kconfig
>>> @@ -3,6 +3,7 @@ config USB_DWC3
>>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
>>> depends on EXTCON
>>> select USB_PHY
>>> + select GENERIC_PHY
>>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
>>> help
>>> Say Y or M here if your system has a Dual Role SuperSpeed
>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>> index 428c29e..485d365 100644
>>> --- a/drivers/usb/dwc3/core.c
>>> +++ b/drivers/usb/dwc3/core.c
>>> @@ -82,6 +82,12 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
>>>
>>> usb_phy_init(dwc->usb2_phy);
>>> usb_phy_init(dwc->usb3_phy);
>>> +
>>> + if (dwc->usb2_generic_phy)
>>> + phy_init(dwc->usb2_generic_phy);
>>> + if (dwc->usb3_generic_phy)
>>> + phy_init(dwc->usb3_generic_phy);
>>> +
>>> mdelay(100);
>>>
>>> /* Clear USB3 PHY reset */
>>> @@ -343,6 +349,11 @@ static void dwc3_core_exit(struct dwc3 *dwc)
>>> {
>>> usb_phy_shutdown(dwc->usb2_phy);
>>> usb_phy_shutdown(dwc->usb3_phy);
>>> +
>>> + if (dwc->usb2_generic_phy)
>>> + phy_power_off(dwc->usb2_generic_phy);
>>> + if (dwc->usb3_generic_phy)
>>> + phy_power_off(dwc->usb3_generic_phy);
>>> }
>>>
>>> #define DWC3_ALIGN_MASK (16 - 1)
>>> @@ -427,6 +438,23 @@ static int dwc3_probe(struct platform_device *pdev)
>>> dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
>>> }
>>>
>>> + if (of_property_read_bool(node, "phys") || pdata->has_phy) {
>>> + dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
>>> + if (IS_ERR(dwc->usb2_generic_phy)) {
>>> + dev_err(dev, "no usb2 phy configured yet");
>>> + return PTR_ERR(dwc->usb2_generic_phy);
>>> + }
>>> +
>>> + dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
>>> + if (IS_ERR(dwc->usb3_generic_phy)) {
>>> + dev_err(dev, "no usb3 phy configured yet");
>>> + return PTR_ERR(dwc->usb3_generic_phy);
>>> + }
>>> + } else {
>>> + dwc->usb2_generic_phy = NULL;
>>> + dwc->usb3_generic_phy = NULL;
>>> + }
>>> +
>>> /* default to superspeed if no maximum_speed passed */
>>> if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
>>> dwc->maximum_speed = USB_SPEED_SUPER;
>>> @@ -450,6 +478,11 @@ static int dwc3_probe(struct platform_device *pdev)
>>> usb_phy_set_suspend(dwc->usb2_phy, 0);
>>> usb_phy_set_suspend(dwc->usb3_phy, 0);
>>>
>>> + if (dwc->usb2_generic_phy)
>>> + phy_power_on(dwc->usb2_generic_phy);
>>> + if (dwc->usb3_generic_phy)
>>> + phy_power_on(dwc->usb3_generic_phy);
>>> +
>>> spin_lock_init(&dwc->lock);
>>> platform_set_drvdata(pdev, dwc);
>>>
>>> @@ -576,6 +609,11 @@ static int dwc3_remove(struct platform_device *pdev)
>>> usb_phy_set_suspend(dwc->usb2_phy, 1);
>>> usb_phy_set_suspend(dwc->usb3_phy, 1);
>>>
>>> + if (dwc->usb2_generic_phy)
>>
>> if (IS_ERR())
>
> I assign NULL to usb2_generic_phy and usb3_generic_phy in case the dts entry doesn't have a *phys* property.
> The IS_ERR of usb2_generic_phy is treated as an error condition and probe will fail.

OK.

>>
>>> + phy_power_off(dwc->usb2_generic_phy);
>>> + if (dwc->usb3_generic_phy)
>>
>> if (IS_ERR())
>>
>> here and everywhere else in this patch.
>>
>>> + phy_power_off(dwc->usb3_generic_phy);
>>> +
>>> pm_runtime_put(&pdev->dev);
>>> pm_runtime_disable(&pdev->dev);
>>>
>>> @@ -673,6 +711,11 @@ static int dwc3_suspend(struct device *dev)
>>> usb_phy_shutdown(dwc->usb3_phy);
>>> usb_phy_shutdown(dwc->usb2_phy);
>>>
>>> + if (dwc->usb2_generic_phy)
>>> + phy_exit(dwc->usb2_generic_phy);
>>> + if (dwc->usb3_generic_phy)
>>> + phy_exit(dwc->usb3_generic_phy);
>>> +
>>> return 0;
>>> }
>>>
>>> @@ -683,6 +726,12 @@ static int dwc3_resume(struct device *dev)
>>>
>>> usb_phy_init(dwc->usb3_phy);
>>> usb_phy_init(dwc->usb2_phy);
>>> +
>>> + if (dwc->usb2_generic_phy)
>>> + phy_init(dwc->usb2_generic_phy);
>>> + if (dwc->usb3_generic_phy)
>>> + phy_init(dwc->usb3_generic_phy);
>>> +
>>> msleep(100);
>>>
>>> spin_lock_irqsave(&dwc->lock, flags);
>>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>>> index f8af8d4..01ec7d7 100644
>>> --- a/drivers/usb/dwc3/core.h
>>> +++ b/drivers/usb/dwc3/core.h
>>> @@ -31,6 +31,8 @@
>>> #include <linux/usb/gadget.h>
>>> #include <linux/usb/otg.h>
>>>
>>> +#include <linux/phy/phy.h>
>>> +
>>> /* Global constants */
>>> #define DWC3_EP0_BOUNCE_SIZE 512
>>> #define DWC3_ENDPOINTS_NUM 32
>>> @@ -613,6 +615,8 @@ struct dwc3_scratchpad_array {
>>> * @dr_mode: requested mode of operation
>>> * @usb2_phy: pointer to USB2 PHY
>>> * @usb3_phy: pointer to USB3 PHY
>>> + * @usb2_generic_phy: pointer to USB2 PHY
>>> + * @usb3_generic_phy: pointer to USB3 PHY
>>
>> Why duplicate usbX_phy and usbX_generic_phy? Can't we just have one
>> for each type and call it usbX_phy?
>
> There was an already existing phy library in usb which usesusb_phy. There might still be users using the existing usb phy library. Until all the users have completely migrated to the generic PHY framework, this would co-exist.
>
OK.

cheers,
-roger

2013-09-16 07:38:19

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 3/7] drivers: phy: usb3/pipe3: Adapt pipe3 driver to Generic PHY Framework

On 09/16/2013 06:01 AM, Kishon Vijay Abraham I wrote:
> On Thursday 12 September 2013 04:49 PM, Roger Quadros wrote:
>> Hi Kishon,
>>
>> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>>> Adapted omap-usb3 PHY driver to Generic PHY Framework and moved phy-omap-usb3
>>> driver in drivers/usb/phy to drivers/phy and also renamed the file to
>>> phy-omap-pipe3 since this same driver will be used for SATA PHY and
>>> PCIE PHY.
>>
>> I would suggest to split the renaming and PHY adaptation into 2 separate patches.
>
> Alright.
>>
>>>
>>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>>> ---
>>> Documentation/devicetree/bindings/usb/usb-phy.txt | 5 +-
>>> drivers/phy/Kconfig | 10 +
>>> drivers/phy/Makefile | 1 +
>>> .../phy/phy-omap-usb3.c => phy/phy-omap-pipe3.c} | 206 +++++++++++---------
>>
>> how about naming it to phy-ti-pipe3.c as it is used on OMAP as well as non-OMAP e.g. DRA7.
>
> hmm.. I thought it would be consistent with other PHY drivers (phy-omap-usb2). Moreover DRA7 is OMAP based platform ;-) Maybe we should reserve that for later?

OK. Up to you.

>>
>>> drivers/usb/phy/Kconfig | 11 --
>>> drivers/usb/phy/Makefile | 1 -
>>> include/linux/phy/omap_pipe3.h | 52 +++++
>>> 7 files changed, 177 insertions(+), 109 deletions(-)
>>> rename drivers/{usb/phy/phy-omap-usb3.c => phy/phy-omap-pipe3.c} (57%)
>>> create mode 100644 include/linux/phy/omap_pipe3.h
>>>
>>> diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/usb/usb-phy.txt
>>> index c0245c8..36bdb17 100644
>>> --- a/Documentation/devicetree/bindings/usb/usb-phy.txt
>>> +++ b/Documentation/devicetree/bindings/usb/usb-phy.txt
>>> @@ -21,10 +21,11 @@ usb2phy@4a0ad080 {
>>> #phy-cells = <0>;
>>> };
>>>
>>> -OMAP USB3 PHY
>>> +OMAP PIPE3 PHY
>>>
>>> Required properties:
>>> - - compatible: Should be "ti,omap-usb3"
>>> + - compatible: Should be "ti,omap-usb3", "ti,omap-pipe3", "ti,omap-sata"
>>> + or "ti,omap-pcie"
>>> - reg : Address and length of the register set for the device.
>>> - reg-names: The names of the register addresses corresponding to the registers
>>> filled in "reg".
>>> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
>>> index ac239ac..5c2e7a0 100644
>>> --- a/drivers/phy/Kconfig
>>> +++ b/drivers/phy/Kconfig
>>> @@ -27,6 +27,16 @@ config OMAP_USB2
>>> The USB OTG controller communicates with the comparator using this
>>> driver.
>>>
>>> +config OMAP_PIPE3
>>> + tristate "OMAP PIPE3 PHY Driver"
>>> + select GENERIC_PHY
>>> + select OMAP_CONTROL_USB
>> how about
>> depends on OMAP_CONTROL_USB
>
> From whatever I could make out from comments of Greg in my Generic PHY Framework, it's better to do a select of dependent modules instead of depends on.

You can use select, provided the item you are selecting doesn't depend on anything else.
As OMAP_CONTROL_USB depends on ARCH_OMAP2PLUS, your configuration will fail if a user enables
OMAP_PIPE3 on non OMAP configuration.

Further, in this case since it is OMAP related driver, there is no point in showing/building it
if OMAP platform is not selected, so you at least need [depends on "ARCH_OMAP2PLUS"] to fix
both issue I mentioned.

>>
>> Also, if this is TI/OMAP it might as well depend on ARCH_OMAP.
>>
>>> + help
>>> + Enable this to support the PIPE3 PHY that is part of SOC. This
>>
>> worth mentioning TI OMAP/DRA SoCs.
>
> right.
>>
>>> + driver takes care of all the PHY functionality apart from comparator.
>>> + This driver interacts with the "OMAP Control PHY Driver" to power
>>> + on/off the PHY.
>>> +
>>> config TWL4030_USB
>>> tristate "TWL4030 USB Transceiver Driver"
>>> depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
>>> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
>>> index 0dd8a98..48bf9f2 100644
>>> --- a/drivers/phy/Makefile
>>> +++ b/drivers/phy/Makefile
>>> @@ -4,4 +4,5 @@
>>>
>>> obj-$(CONFIG_GENERIC_PHY) += phy-core.o
>>> obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
>>> +obj-$(CONFIG_OMAP_PIPE3) += phy-omap-pipe3.o
>>> obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
>>> diff --git a/drivers/usb/phy/phy-omap-usb3.c b/drivers/phy/phy-omap-pipe3.c
>>> similarity index 57%
>>> rename from drivers/usb/phy/phy-omap-usb3.c
>>> rename to drivers/phy/phy-omap-pipe3.c
>>> index 4004f82..ee9a901 100644
>>> --- a/drivers/usb/phy/phy-omap-usb3.c
>>> +++ b/drivers/phy/phy-omap-pipe3.c
>>> @@ -1,5 +1,5 @@
>>> /*
>>> - * omap-usb3 - USB PHY, talking to dwc3 controller in OMAP.
>>> + * omap-pipe3 - PHY driver for SATA, USB and PCIE in OMAP platforms
>>> *
>>> * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
>>> * This program is free software; you can redistribute it and/or modify
>>> @@ -19,7 +19,8 @@
>>> #include <linux/module.h>
>>> #include <linux/platform_device.h>
>>> #include <linux/slab.h>
>>> -#include <linux/usb/omap_usb.h>
>>> +#include <linux/phy/omap_pipe3.h>
>>> +#include <linux/phy/phy.h>
>>> #include <linux/of.h>
>>> #include <linux/clk.h>
>>> #include <linux/err.h>
>>> @@ -52,17 +53,17 @@
>>>
>>> /*
>>> * This is an Empirical value that works, need to confirm the actual
>>> - * value required for the USB3PHY_PLL_CONFIGURATION2.PLL_IDLE status
>>> - * to be correctly reflected in the USB3PHY_PLL_STATUS register.
>>> + * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status
>>> + * to be correctly reflected in the PIPE3PHY_PLL_STATUS register.
>>> */
>>> # define PLL_IDLE_TIME 100;
>>>
>>> -struct usb_dpll_map {
>>> +struct pipe3_dpll_map {
>>> unsigned long rate;
>>> - struct usb_dpll_params params;
>>> + struct pipe3_dpll_params params;
>>> };
>>>
>>> -static struct usb_dpll_map dpll_map[] = {
>>> +static struct pipe3_dpll_map dpll_map[] = {
>>> {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */
>>> {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */
>>> {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */
>>> @@ -71,7 +72,7 @@ static struct usb_dpll_map dpll_map[] = {
>>> {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */
>>> };
>>>
>>> -static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate)
>>> +static struct pipe3_dpll_params *omap_pipe3_get_dpll_params(unsigned long rate)
>>> {
>>> int i;
>>>
>>> @@ -83,110 +84,113 @@ static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate)
>>> return 0;
>>> }
>>>
>>> -static int omap_usb3_suspend(struct usb_phy *x, int suspend)
>>> +static int omap_pipe3_power_off(struct phy *x)
>>> {
>>> - struct omap_usb *phy = phy_to_omapusb(x);
>>> - int val;
>>> + struct omap_pipe3 *phy = phy_get_drvdata(x);
>>> + int val;
>>> int timeout = PLL_IDLE_TIME;
>>>
>>> - if (suspend && !phy->is_suspended) {
>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>> - val |= PLL_IDLE;
>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>> -
>>> - do {
>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
>>> - if (val & PLL_TICOPWDN)
>>> - break;
>>> - udelay(1);
>>> - } while (--timeout);
>>> -
>>> - omap_control_usb_phy_power(phy->control_dev, 0);
>>> -
>>> - phy->is_suspended = 1;
>>> - } else if (!suspend && phy->is_suspended) {
>>> - phy->is_suspended = 0;
>>> -
>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>> - val &= ~PLL_IDLE;
>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>> -
>>> - do {
>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
>>> - if (!(val & PLL_TICOPWDN))
>>> - break;
>>> - udelay(1);
>>> - } while (--timeout);
>>> - }
>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>> + val |= PLL_IDLE;
>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>> +
>>> + do {
>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
>>> + if (val & PLL_TICOPWDN)
>>> + break;
>>> + udelay(1);
>>
>> Is it better to sleep instead of udelay?
>
> hmm.. yeah, I guess this function wont be called from interrupt context.
>>
>>> + } while (--timeout);
>>> +
>>> + omap_control_usb_phy_power(phy->control_dev, 0);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int omap_pipe3_power_on(struct phy *x)
>>> +{
>>> + struct omap_pipe3 *phy = phy_get_drvdata(x);
>>> + int val;
>>> + int timeout = PLL_IDLE_TIME;
>>> +
>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>> + val &= ~PLL_IDLE;
>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>> +
>>> + do {
>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
>>> + if (!(val & PLL_TICOPWDN))
>>> + break;
>>> + udelay(1);
>>
>> here too.
>
> Ok.
>>
>>> + } while (--timeout);
>>>
>>> return 0;
>>> }
>>>
>>> -static void omap_usb_dpll_relock(struct omap_usb *phy)
>>> +static void omap_pipe3_dpll_relock(struct omap_pipe3 *phy)
>>> {
>>> u32 val;
>>> unsigned long timeout;
>>>
>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
>>>
>>> timeout = jiffies + msecs_to_jiffies(20);
>>> do {
>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
>>> if (val & PLL_LOCK)
>>> break;
>>> } while (!WARN_ON(time_after(jiffies, timeout)));
>>> }
>>>
>>> -static int omap_usb_dpll_lock(struct omap_usb *phy)
>>> +static int omap_pipe3_dpll_lock(struct omap_pipe3 *phy)
>>> {
>>> u32 val;
>>> unsigned long rate;
>>> - struct usb_dpll_params *dpll_params;
>>> + struct pipe3_dpll_params *dpll_params;
>>>
>>> rate = clk_get_rate(phy->sys_clk);
>>> - dpll_params = omap_usb3_get_dpll_params(rate);
>>> + dpll_params = omap_pipe3_get_dpll_params(rate);
>>> if (!dpll_params) {
>>> dev_err(phy->dev,
>>> "No DPLL configuration for %lu Hz SYS CLK\n", rate);
>>> return -EINVAL;
>>> }
>>>
>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
>>> val &= ~PLL_REGN_MASK;
>>> val |= dpll_params->n << PLL_REGN_SHIFT;
>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>>>
>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>> val &= ~PLL_SELFREQDCO_MASK;
>>> val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>>
>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
>>> val &= ~PLL_REGM_MASK;
>>> val |= dpll_params->m << PLL_REGM_SHIFT;
>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>>>
>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
>>> val &= ~PLL_REGM_F_MASK;
>>> val |= dpll_params->mf << PLL_REGM_F_SHIFT;
>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
>>>
>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
>>> val &= ~PLL_SD_MASK;
>>> val |= dpll_params->sd << PLL_SD_SHIFT;
>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
>>>
>>> - omap_usb_dpll_relock(phy);
>>> + omap_pipe3_dpll_relock(phy);
>>>
>>> return 0;
>>> }
>>>
>>> -static int omap_usb3_init(struct usb_phy *x)
>>> +static int omap_pipe3_init(struct phy *x)
>>> {
>>> - struct omap_usb *phy = phy_to_omapusb(x);
>>> + struct omap_pipe3 *phy = phy_get_drvdata(x);
>>> int ret;
>>>
>>> - ret = omap_usb_dpll_lock(phy);
>>> + ret = omap_pipe3_dpll_lock(phy);
>>> if (ret)
>>> return ret;
>>>
>>> @@ -195,9 +199,18 @@ static int omap_usb3_init(struct usb_phy *x)
>>> return 0;
>>> }
>>>
>>> -static int omap_usb3_probe(struct platform_device *pdev)
>>> +static struct phy_ops ops = {
>>> + .init = omap_pipe3_init,
>>> + .power_on = omap_pipe3_power_on,
>>> + .power_off = omap_pipe3_power_off,
>>> + .owner = THIS_MODULE,
>>> +};
>>> +
>>> +static int omap_pipe3_probe(struct platform_device *pdev)
>>> {
>>> - struct omap_usb *phy;
>>> + struct omap_pipe3 *phy;
>>> + struct phy *generic_phy;
>>> + struct phy_provider *phy_provider;
>>> struct resource *res;
>>> struct device_node *node = pdev->dev.of_node;
>>> struct device_node *control_node;
>>> @@ -208,7 +221,7 @@ static int omap_usb3_probe(struct platform_device *pdev)
>>>
>>> phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
>>> if (!phy) {
>>> - dev_err(&pdev->dev, "unable to alloc mem for OMAP USB3 PHY\n");
>>> + dev_err(&pdev->dev, "unable to alloc mem for OMAP PIPE3 PHY\n");
>>> return -ENOMEM;
>>> }
>>>
>>> @@ -219,13 +232,6 @@ static int omap_usb3_probe(struct platform_device *pdev)
>>>
>>> phy->dev = &pdev->dev;
>>>
>>> - phy->phy.dev = phy->dev;
>>> - phy->phy.label = "omap-usb3";
>>> - phy->phy.init = omap_usb3_init;
>>> - phy->phy.set_suspend = omap_usb3_suspend;
>>> - phy->phy.type = USB_PHY_TYPE_USB3;
>>> -
>>> - phy->is_suspended = 1;
>>> phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
>>
>> As this is no longer USB specific, we need to make the clock binding generic as well.
>
> right. Its also needed when we have the same driver work for sata and pcie. Maybe do that in a separate patch?

OK. up to you.
>>
>>> if (IS_ERR(phy->wkupclk)) {
>>> dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
>>> @@ -251,6 +257,11 @@ static int omap_usb3_probe(struct platform_device *pdev)
>>> dev_err(&pdev->dev, "Failed to get control device phandle\n");
>>> return -EINVAL;
>>> }
>>> + phy_provider = devm_of_phy_provider_register(phy->dev,
>>> + of_phy_simple_xlate);
>>> + if (IS_ERR(phy_provider))
>>> + return PTR_ERR(phy_provider);
>>> +
>>> control_pdev = of_find_device_by_node(control_node);
>>> if (!control_pdev) {
>>> dev_err(&pdev->dev, "Failed to get control device\n");
>>> @@ -260,23 +271,27 @@ static int omap_usb3_probe(struct platform_device *pdev)
>>> phy->control_dev = &control_pdev->dev;
>>>
>>> omap_control_usb_phy_power(phy->control_dev, 0);
>>> - usb_add_phy_dev(&phy->phy);
>>>
>>> platform_set_drvdata(pdev, phy);
>>> -
>>> pm_runtime_enable(phy->dev);
>>> +
>>> + generic_phy = devm_phy_create(phy->dev, &ops, NULL);
>>> + if (IS_ERR(generic_phy))
>>> + return PTR_ERR(generic_phy);
>>> +
>>> + phy_set_drvdata(generic_phy, phy);
>>> +
>>> pm_runtime_get(&pdev->dev);
>>>
>>> return 0;
>>> }
>>>
>>> -static int omap_usb3_remove(struct platform_device *pdev)
>>> +static int omap_pipe3_remove(struct platform_device *pdev)
>>> {
>>> - struct omap_usb *phy = platform_get_drvdata(pdev);
>>> + struct omap_pipe3 *phy = platform_get_drvdata(pdev);
>>>
>>> clk_unprepare(phy->wkupclk);
>>> clk_unprepare(phy->optclk);
>>> - usb_remove_phy(&phy->phy);
>>> if (!pm_runtime_suspended(&pdev->dev))
>>> pm_runtime_put(&pdev->dev);
>>> pm_runtime_disable(&pdev->dev);
>>> @@ -286,10 +301,9 @@ static int omap_usb3_remove(struct platform_device *pdev)
>>>
>>> #ifdef CONFIG_PM_RUNTIME
>>>
>>> -static int omap_usb3_runtime_suspend(struct device *dev)
>>> +static int omap_pipe3_runtime_suspend(struct device *dev)
>>> {
>>> - struct platform_device *pdev = to_platform_device(dev);
>>> - struct omap_usb *phy = platform_get_drvdata(pdev);
>>> + struct omap_pipe3 *phy = dev_get_drvdata(dev);
>>>
>>> clk_disable(phy->wkupclk);
>>> clk_disable(phy->optclk);
>>> @@ -297,11 +311,10 @@ static int omap_usb3_runtime_suspend(struct device *dev)
>>> return 0;
>>> }
>>>
>>> -static int omap_usb3_runtime_resume(struct device *dev)
>>> +static int omap_pipe3_runtime_resume(struct device *dev)
>>> {
>>> u32 ret = 0;
>>> - struct platform_device *pdev = to_platform_device(dev);
>>> - struct omap_usb *phy = platform_get_drvdata(pdev);
>>> + struct omap_pipe3 *phy = dev_get_drvdata(dev);
>>>
>>> ret = clk_enable(phy->optclk);
>>> if (ret) {
>>> @@ -324,38 +337,41 @@ err1:
>>> return ret;
>>> }
>>>
>>> -static const struct dev_pm_ops omap_usb3_pm_ops = {
>>> - SET_RUNTIME_PM_OPS(omap_usb3_runtime_suspend, omap_usb3_runtime_resume,
>>> - NULL)
>>> +static const struct dev_pm_ops omap_pipe3_pm_ops = {
>>> + SET_RUNTIME_PM_OPS(omap_pipe3_runtime_suspend,
>>> + omap_pipe3_runtime_resume, NULL)
>>> };
>>>
>>> -#define DEV_PM_OPS (&omap_usb3_pm_ops)
>>> +#define DEV_PM_OPS (&omap_pipe3_pm_ops)
>>> #else
>>> #define DEV_PM_OPS NULL
>>> #endif
>>>
>>> #ifdef CONFIG_OF
>>> -static const struct of_device_id omap_usb3_id_table[] = {
>>> +static const struct of_device_id omap_pipe3_id_table[] = {
>>> + { .compatible = "ti,omap-pipe3" },
>>
>> why do you need "omap-pipe3", isn't sata, pcie and usb3 sufficient?
>
> I thought it would be better if everyone uses omap-pipe3 and added pcie, sata if there are any specific settings (for pcie or sata) that should be done.

We can always add specialized options later when needed. AFAIK just the
DPLL data is different among the different PHYs.
>>
>>> + { .compatible = "ti,omap-sata" },
>>> + { .compatible = "ti,omap-pcie" },
>>> { .compatible = "ti,omap-usb3" },

I think compatible strings should be improved to indicate that it is a PHY.

e.g. "ti,omap-phy-sata" or just "ti,pipe3-phy-sata"

>>> {}
>>> };
>>> -MODULE_DEVICE_TABLE(of, omap_usb3_id_table);
>>> +MODULE_DEVICE_TABLE(of, omap_pipe3_id_table);
>>> #endif

cheers,
-roger

2013-09-16 08:40:31

by Vivek Gautam

[permalink] [raw]
Subject: Re: [PATCH 1/7] usb: dwc3: get "usb_phy" only if the platform indicates the presence of PHY

Hi,


On Thu, Sep 12, 2013 at 6:41 PM, Roger Quadros <[email protected]> wrote:
> On 09/12/2013 02:26 PM, Vivek Gautam wrote:
>> Hi,
>>
>>
>> On Thu, Sep 12, 2013 at 4:34 PM, Roger Quadros <[email protected]> wrote:
>>> Hi,
>>>
>>> On 09/12/2013 01:47 PM, Vivek Gautam wrote:
>>>> On Thu, Sep 12, 2013 at 4:06 PM, Roger Quadros <[email protected]> wrote:
>>>>> Hi Kishon,
>>>>>
>>>>> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>>>>>> There can be systems which does not have a external usb_phy, so get
>>>>>> usb_phy only if usb-phy property is added in the case of dt boot or if
>>>>>> platform_data indicates the presence of PHY. Also remove checking if
>>>>>> return value is -ENXIO since it's now changed to always enable usb_phy layer.
>>>>>>
>>>>>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>>>>>> ---
>>>>>> drivers/usb/dwc3/Kconfig | 1 +
>>>>>> drivers/usb/dwc3/core.c | 60 +++++++++++++++++---------------------
>>>>>> drivers/usb/dwc3/platform_data.h | 1 +
>>>>>> 3 files changed, 28 insertions(+), 34 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>>>>>> index f969ea2..cfc16dd 100644
>>>>>> --- a/drivers/usb/dwc3/Kconfig
>>>>>> +++ b/drivers/usb/dwc3/Kconfig
>>>>>> @@ -2,6 +2,7 @@ config USB_DWC3
>>>>>> tristate "DesignWare USB3 DRD Core Support"
>>>>>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
>>>>>> depends on EXTCON
>>>>>> + select USB_PHY
>>>>>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
>>>>>> help
>>>>>> Say Y or M here if your system has a Dual Role SuperSpeed
>>>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>>>>> index 474162e..428c29e 100644
>>>>>> --- a/drivers/usb/dwc3/core.c
>>>>>> +++ b/drivers/usb/dwc3/core.c
>>>>>> @@ -387,16 +387,38 @@ static int dwc3_probe(struct platform_device *pdev)
>>>>>> if (node) {
>>>>>> dwc->maximum_speed = of_usb_get_maximum_speed(node);
>>>>>>
>>>>>> - dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
>>>>>> - dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
>>>>>> + if (of_property_read_bool(node, "usb-phy")) {
>>>>>> + dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev,
>>>>>> + "usb-phy", 0);
>>>>>> + if (IS_ERR(dwc->usb2_phy))
>>>>>> + return PTR_ERR(dwc->usb2_phy);
>>>>>> + dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev,
>>>>>> + "usb-phy", 1);
>>>>>> + if (IS_ERR(dwc->usb3_phy))
>>>>>> + return PTR_ERR(dwc->usb3_phy);
>>>>>
>>>>> Some DWC3 instances use only usb2_phy. e.g. on DRA7 the 2nd dwc3 instance doesn't use usb3_phy.
>>>>> This needs to be a valid case and driver shouldn't error out.
>>>>
>>>> So, i think adding flexibility to DWC3 to have either
>>>> usb2-phy/usb3-phy or both of them seems to be valid point.
>>>> Any suggestions ?
>>>>
>>>
>>> For high speed operation we need only usb2_phy but for super speed we need both usb2_phy
>>> and usb3_phy.
>>>
>>> Why would a dwc3 controller use only usb3_phy? A USB3.0 interface has to be compatible with
>>> USB2.0 as well, no?
>>
>> True and for that reason we need both UTMI+ interface as well as PIPE3
>> interface, right ?
>> But as also mentioned in the thread:
>> https://lkml.org/lkml/2013/9/12/181, on Samsung exynos5
>> architecturally same block is managing UTMI+ and PIPE3 interfaces,
>> which is handled by phy-samsung-usb3 driver and denoted by "usb3_phy:
>> usbphy@12100000" node in "arch/arm/boot/dts/exynos5250.dtsi".
>>
>> So on exynos5250, DWC3 really needs just usb3-phy, which is compatible
>> for USB 2.0 as well.
>
> I'm not familiar with exynos5250 dwc3, but looking at the dts file I can see both usb3_phy
> and usb2_phy nodes and both are referenced in the dwc3 node.

Right, and that's what we intend to fix.
Exynos5250 dwc3 is not in the need of both usb2_phy and usb3_phy.
In fact usb3_phy handle (which is served by phy-samsung-usb3 driver)
sets up the UTMI+ as well as PIPE3 phy on DWC3.
I know this looks different from the usual OMAP style of phy for dwc3.

Hi Sylwester,
any suggestions here ? As contained in the exynos5250 user manual
too, there's only one block of PHY handling both UTMI+ and PIPE3
interfaces, and the set of registers (same base address) also indicate
one block of PHY. So we have the usb3_phy (phy-samsung-usb3 driver)
which setup the entire PHY require for DWC3 operation, and thereby we
__shouldn't__ need usb2_phy (phy-samsung-usb2 driver which actually
setup the PHY for a separate USB 2.0 controller on exynos5250) for
DWC3.

>
> The ehci and ohci controllers don't reference any PHY.

ehci-s5p and ohci-exynos are not using devm_usb_get_phy_by_phandle()
api until now, so they don't need to have the PHY handlers in their
node.

>
> cheers,
> -roger



--
Best Regards
Vivek

2013-09-17 15:49:08

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH 1/7] usb: dwc3: get "usb_phy" only if the platform indicates the presence of PHY

Hi,

On Thu, Sep 12, 2013 at 04:17:08PM +0530, Vivek Gautam wrote:
> On Thu, Sep 12, 2013 at 4:06 PM, Roger Quadros <[email protected]> wrote:
> > Hi Kishon,
> >
> > On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
> >> There can be systems which does not have a external usb_phy, so get
> >> usb_phy only if usb-phy property is added in the case of dt boot or if
> >> platform_data indicates the presence of PHY. Also remove checking if
> >> return value is -ENXIO since it's now changed to always enable usb_phy layer.
> >>
> >> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
> >> ---
> >> drivers/usb/dwc3/Kconfig | 1 +
> >> drivers/usb/dwc3/core.c | 60 +++++++++++++++++---------------------
> >> drivers/usb/dwc3/platform_data.h | 1 +
> >> 3 files changed, 28 insertions(+), 34 deletions(-)
> >>
> >> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
> >> index f969ea2..cfc16dd 100644
> >> --- a/drivers/usb/dwc3/Kconfig
> >> +++ b/drivers/usb/dwc3/Kconfig
> >> @@ -2,6 +2,7 @@ config USB_DWC3
> >> tristate "DesignWare USB3 DRD Core Support"
> >> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
> >> depends on EXTCON
> >> + select USB_PHY
> >> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
> >> help
> >> Say Y or M here if your system has a Dual Role SuperSpeed
> >> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> >> index 474162e..428c29e 100644
> >> --- a/drivers/usb/dwc3/core.c
> >> +++ b/drivers/usb/dwc3/core.c
> >> @@ -387,16 +387,38 @@ static int dwc3_probe(struct platform_device *pdev)
> >> if (node) {
> >> dwc->maximum_speed = of_usb_get_maximum_speed(node);
> >>
> >> - dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
> >> - dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
> >> + if (of_property_read_bool(node, "usb-phy")) {
> >> + dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev,
> >> + "usb-phy", 0);
> >> + if (IS_ERR(dwc->usb2_phy))
> >> + return PTR_ERR(dwc->usb2_phy);
> >> + dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev,
> >> + "usb-phy", 1);
> >> + if (IS_ERR(dwc->usb3_phy))
> >> + return PTR_ERR(dwc->usb3_phy);
> >
> > Some DWC3 instances use only usb2_phy. e.g. on DRA7 the 2nd dwc3 instance doesn't use usb3_phy.
> > This needs to be a valid case and driver shouldn't error out.
>
> So, i think adding flexibility to DWC3 to have either
> usb2-phy/usb3-phy or both of them seems to be valid point.
> Any suggestions ?

I've gone through that. There's no easy way to make USB3 PHY optional.

For platforms which actually have the USB3 side of things, not
initializing the PHY kills dwc3.

I've been trying to understand what it is that the USB3 PHY generates
and gets backfed into dwc3, but so far no luck.

I even have a patch for that, which I have dropped when I found out
about this problem.

--
balbi


Attachments:
(No filename) (3.09 kB)
signature.asc (836.00 B)
Digital signature
Download all attachments

2013-10-10 10:29:09

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

On Thursday 12 September 2013 03:57 PM, Vivek Gautam wrote:
> On Thu, Sep 12, 2013 at 3:40 PM, Kishon Vijay Abraham I <[email protected]> wrote:
>> On Thursday 12 September 2013 02:57 PM, Vivek Gautam wrote:
>>> Hi Kishon,
>>>
>>>
>>> On Mon, Sep 2, 2013 at 9:13 PM, Kishon Vijay Abraham I <[email protected]> wrote:
>>>> Adapted dwc3 core to use the Generic PHY Framework. So for init, exit,
>>>> power_on and power_off the following APIs are used phy_init(), phy_exit(),
>>>> phy_power_on() and phy_power_off().
>>>>
>>>> However using the old USB phy library wont be removed till the PHYs of all
>>>> other SoC's using dwc3 core is adapted to the Generic PHY Framework.
>>>>
>>>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>>>> ---
>>>> Documentation/devicetree/bindings/usb/dwc3.txt | 6 ++-
>>>> drivers/usb/dwc3/Kconfig | 1 +
>>>> drivers/usb/dwc3/core.c | 49 ++++++++++++++++++++++++
>>>> drivers/usb/dwc3/core.h | 7 ++++
>>>> 4 files changed, 61 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
>>>> index e807635..471366d 100644
>>>> --- a/Documentation/devicetree/bindings/usb/dwc3.txt
>>>> +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
>>>> @@ -6,11 +6,13 @@ Required properties:
>>>> - compatible: must be "snps,dwc3"
>>>> - reg : Address and length of the register set for the device
>>>> - interrupts: Interrupts used by the dwc3 controller.
>>>> +
>>>> +Optional properties:
>>>> - usb-phy : array of phandle for the PHY device. The first element
>>>> in the array is expected to be a handle to the USB2/HS PHY and
>>>> the second element is expected to be a handle to the USB3/SS PHY
>>>> -
>>>> -Optional properties:
>>>> + - phys: from the *Generic PHY* bindings
>>>> + - phy-names: from the *Generic PHY* bindings
>>>> - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
>>>>
>>>> This is usually a subnode to DWC3 glue to which it is connected.
>>>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>>>> index cfc16dd..ad7ce83 100644
>>>> --- a/drivers/usb/dwc3/Kconfig
>>>> +++ b/drivers/usb/dwc3/Kconfig
>>>> @@ -3,6 +3,7 @@ config USB_DWC3
>>>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
>>>> depends on EXTCON
>>>> select USB_PHY
>>>> + select GENERIC_PHY
>>>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
>>>> help
>>>> Say Y or M here if your system has a Dual Role SuperSpeed
>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>>> index 428c29e..485d365 100644
>>>> --- a/drivers/usb/dwc3/core.c
>>>> +++ b/drivers/usb/dwc3/core.c
>>>> @@ -82,6 +82,12 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
>>>>
>>>> usb_phy_init(dwc->usb2_phy);
>>>> usb_phy_init(dwc->usb3_phy);
>>>> +
>>>> + if (dwc->usb2_generic_phy)
>>>> + phy_init(dwc->usb2_generic_phy);
>>>> + if (dwc->usb3_generic_phy)
>>>> + phy_init(dwc->usb3_generic_phy);
>>>> +
>>>> mdelay(100);
>>>>
>>>> /* Clear USB3 PHY reset */
>>>> @@ -343,6 +349,11 @@ static void dwc3_core_exit(struct dwc3 *dwc)
>>>> {
>>>> usb_phy_shutdown(dwc->usb2_phy);
>>>> usb_phy_shutdown(dwc->usb3_phy);
>>>> +
>>>> + if (dwc->usb2_generic_phy)
>>>> + phy_power_off(dwc->usb2_generic_phy);
>>>> + if (dwc->usb3_generic_phy)
>>>> + phy_power_off(dwc->usb3_generic_phy);
>>>> }
>>>>
>>>> #define DWC3_ALIGN_MASK (16 - 1)
>>>> @@ -427,6 +438,23 @@ static int dwc3_probe(struct platform_device *pdev)
>>>> dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
>>>> }
>>>>
>>>> + if (of_property_read_bool(node, "phys") || pdata->has_phy) {
>>>> + dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
>>>> + if (IS_ERR(dwc->usb2_generic_phy)) {
>>>> + dev_err(dev, "no usb2 phy configured yet");
>>>> + return PTR_ERR(dwc->usb2_generic_phy);
>>>> + }
>>>
>>> I have a doubt here.
>>> As i can see in the current phy drivers structuring, for OMAP there
>>> are two phy drivers :
>>> omap phy-omap-usb2 (talking to musb controller)
>>
>> It talks to dwc3 controller also ;-)
>
> Ok
>
>>
>>> and phy-omap-usb3(talking to dwc3 controller).
>>>
>>> Now dwc3 controller requests both usb2-phy (supported by phy-omap-usb2
>>> ?) and usb3-phy (supported by phy-omap-usb3 ?).
>>> But phy-omap-usb2 is not the one designated to talk to DWC3
>>> controller, then why does still DWC3 want to request usb2-phy, which
>>> end of the day will be phy-omap-usb2.
>>> May be i am wrong here since i don't have knowledge about OMAP h/w architecture.
>>>
>>> Is it like phy-omap-usb2 includes UTMI phys for both musb controller
>>> as well as dwc3 controller ?
>>
>> right. It's needed for dwc3 too. The same USB2 PHY IP is used for both MUSB in
>> OMAP2+ platforms and DWC3 in OMAP5.
>
> Ok, but on Samsung's exynos5 series of SoCs, the USB2.0 controller has
> a separate USB-PHY interface talking to phy-samsung-usb2 driver;
> and DWC3 drd controller has separate USB-PHY interface (including both
> UTMI+ and PIPE3 control registers) talking to phy-samsung-usb3 driver.
> So in this case DWC3 doesn't need phy-samsung-usb2 at all. It's phy is
> configured by just phy-samsung-usb3 driver only.
> So don't you think DWC3 driver should have the flexibility to have
> either (mostly usb3-phy) _or_ both "usb2-phy" and "usb3-phy".
> Thereby,in case of Samsung driver, DWC3 will just have "usb3-phy" and
> that will be enough to get things working.
> Want your opinions about it.

Should we have separate properties to indicate whether it has a usb2-phy or
usb3-phy instead of checking for *phys* property?

Thanks
Kishon

2013-10-11 15:03:27

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 3/7] drivers: phy: usb3/pipe3: Adapt pipe3 driver to Generic PHY Framework

On 09/16/2013 10:37 AM, Roger Quadros wrote:
> On 09/16/2013 06:01 AM, Kishon Vijay Abraham I wrote:
>> On Thursday 12 September 2013 04:49 PM, Roger Quadros wrote:
>>> Hi Kishon,
>>>
>>> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>>>> Adapted omap-usb3 PHY driver to Generic PHY Framework and moved phy-omap-usb3
>>>> driver in drivers/usb/phy to drivers/phy and also renamed the file to
>>>> phy-omap-pipe3 since this same driver will be used for SATA PHY and
>>>> PCIE PHY.
>>>
>>> I would suggest to split the renaming and PHY adaptation into 2 separate patches.
>>
>> Alright.
>>>
>>>>
>>>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>>>> ---
>>>> Documentation/devicetree/bindings/usb/usb-phy.txt | 5 +-
>>>> drivers/phy/Kconfig | 10 +
>>>> drivers/phy/Makefile | 1 +
>>>> .../phy/phy-omap-usb3.c => phy/phy-omap-pipe3.c} | 206 +++++++++++---------
>>>
>>> how about naming it to phy-ti-pipe3.c as it is used on OMAP as well as non-OMAP e.g. DRA7.
>>
>> hmm.. I thought it would be consistent with other PHY drivers (phy-omap-usb2). Moreover DRA7 is OMAP based platform ;-) Maybe we should reserve that for later?
>
> OK. Up to you.
>
>>>
>>>> drivers/usb/phy/Kconfig | 11 --
>>>> drivers/usb/phy/Makefile | 1 -
>>>> include/linux/phy/omap_pipe3.h | 52 +++++
>>>> 7 files changed, 177 insertions(+), 109 deletions(-)
>>>> rename drivers/{usb/phy/phy-omap-usb3.c => phy/phy-omap-pipe3.c} (57%)
>>>> create mode 100644 include/linux/phy/omap_pipe3.h
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/usb/usb-phy.txt
>>>> index c0245c8..36bdb17 100644
>>>> --- a/Documentation/devicetree/bindings/usb/usb-phy.txt
>>>> +++ b/Documentation/devicetree/bindings/usb/usb-phy.txt
>>>> @@ -21,10 +21,11 @@ usb2phy@4a0ad080 {
>>>> #phy-cells = <0>;
>>>> };
>>>>
>>>> -OMAP USB3 PHY
>>>> +OMAP PIPE3 PHY
>>>>
>>>> Required properties:
>>>> - - compatible: Should be "ti,omap-usb3"
>>>> + - compatible: Should be "ti,omap-usb3", "ti,omap-pipe3", "ti,omap-sata"
>>>> + or "ti,omap-pcie"
>>>> - reg : Address and length of the register set for the device.
>>>> - reg-names: The names of the register addresses corresponding to the registers
>>>> filled in "reg".
>>>> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
>>>> index ac239ac..5c2e7a0 100644
>>>> --- a/drivers/phy/Kconfig
>>>> +++ b/drivers/phy/Kconfig
>>>> @@ -27,6 +27,16 @@ config OMAP_USB2
>>>> The USB OTG controller communicates with the comparator using this
>>>> driver.
>>>>
>>>> +config OMAP_PIPE3
>>>> + tristate "OMAP PIPE3 PHY Driver"
>>>> + select GENERIC_PHY
>>>> + select OMAP_CONTROL_USB
>>> how about
>>> depends on OMAP_CONTROL_USB
>>
>> From whatever I could make out from comments of Greg in my Generic PHY Framework, it's better to do a select of dependent modules instead of depends on.
>
> You can use select, provided the item you are selecting doesn't depend on anything else.
> As OMAP_CONTROL_USB depends on ARCH_OMAP2PLUS, your configuration will fail if a user enables
> OMAP_PIPE3 on non OMAP configuration.
>
> Further, in this case since it is OMAP related driver, there is no point in showing/building it
> if OMAP platform is not selected, so you at least need [depends on "ARCH_OMAP2PLUS"] to fix
> both issue I mentioned.
>
>>>
>>> Also, if this is TI/OMAP it might as well depend on ARCH_OMAP.
>>>
>>>> + help
>>>> + Enable this to support the PIPE3 PHY that is part of SOC. This
>>>
>>> worth mentioning TI OMAP/DRA SoCs.
>>
>> right.
>>>
>>>> + driver takes care of all the PHY functionality apart from comparator.
>>>> + This driver interacts with the "OMAP Control PHY Driver" to power
>>>> + on/off the PHY.
>>>> +
>>>> config TWL4030_USB
>>>> tristate "TWL4030 USB Transceiver Driver"
>>>> depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
>>>> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
>>>> index 0dd8a98..48bf9f2 100644
>>>> --- a/drivers/phy/Makefile
>>>> +++ b/drivers/phy/Makefile
>>>> @@ -4,4 +4,5 @@
>>>>
>>>> obj-$(CONFIG_GENERIC_PHY) += phy-core.o
>>>> obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
>>>> +obj-$(CONFIG_OMAP_PIPE3) += phy-omap-pipe3.o
>>>> obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
>>>> diff --git a/drivers/usb/phy/phy-omap-usb3.c b/drivers/phy/phy-omap-pipe3.c
>>>> similarity index 57%
>>>> rename from drivers/usb/phy/phy-omap-usb3.c
>>>> rename to drivers/phy/phy-omap-pipe3.c
>>>> index 4004f82..ee9a901 100644
>>>> --- a/drivers/usb/phy/phy-omap-usb3.c
>>>> +++ b/drivers/phy/phy-omap-pipe3.c
>>>> @@ -1,5 +1,5 @@
>>>> /*
>>>> - * omap-usb3 - USB PHY, talking to dwc3 controller in OMAP.
>>>> + * omap-pipe3 - PHY driver for SATA, USB and PCIE in OMAP platforms
>>>> *
>>>> * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
>>>> * This program is free software; you can redistribute it and/or modify
>>>> @@ -19,7 +19,8 @@
>>>> #include <linux/module.h>
>>>> #include <linux/platform_device.h>
>>>> #include <linux/slab.h>
>>>> -#include <linux/usb/omap_usb.h>
>>>> +#include <linux/phy/omap_pipe3.h>
>>>> +#include <linux/phy/phy.h>
>>>> #include <linux/of.h>
>>>> #include <linux/clk.h>
>>>> #include <linux/err.h>
>>>> @@ -52,17 +53,17 @@
>>>>
>>>> /*
>>>> * This is an Empirical value that works, need to confirm the actual
>>>> - * value required for the USB3PHY_PLL_CONFIGURATION2.PLL_IDLE status
>>>> - * to be correctly reflected in the USB3PHY_PLL_STATUS register.
>>>> + * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status
>>>> + * to be correctly reflected in the PIPE3PHY_PLL_STATUS register.
>>>> */
>>>> # define PLL_IDLE_TIME 100;
>>>>
>>>> -struct usb_dpll_map {
>>>> +struct pipe3_dpll_map {
>>>> unsigned long rate;
>>>> - struct usb_dpll_params params;
>>>> + struct pipe3_dpll_params params;
>>>> };
>>>>
>>>> -static struct usb_dpll_map dpll_map[] = {
>>>> +static struct pipe3_dpll_map dpll_map[] = {
>>>> {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */
>>>> {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */
>>>> {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */
>>>> @@ -71,7 +72,7 @@ static struct usb_dpll_map dpll_map[] = {
>>>> {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */
>>>> };
>>>>
>>>> -static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate)
>>>> +static struct pipe3_dpll_params *omap_pipe3_get_dpll_params(unsigned long rate)
>>>> {
>>>> int i;
>>>>
>>>> @@ -83,110 +84,113 @@ static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate)
>>>> return 0;
>>>> }
>>>>
>>>> -static int omap_usb3_suspend(struct usb_phy *x, int suspend)
>>>> +static int omap_pipe3_power_off(struct phy *x)
>>>> {
>>>> - struct omap_usb *phy = phy_to_omapusb(x);
>>>> - int val;
>>>> + struct omap_pipe3 *phy = phy_get_drvdata(x);
>>>> + int val;
>>>> int timeout = PLL_IDLE_TIME;
>>>>
>>>> - if (suspend && !phy->is_suspended) {
>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>>> - val |= PLL_IDLE;
>>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>>> -
>>>> - do {
>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
>>>> - if (val & PLL_TICOPWDN)
>>>> - break;
>>>> - udelay(1);
>>>> - } while (--timeout);
>>>> -
>>>> - omap_control_usb_phy_power(phy->control_dev, 0);
>>>> -
>>>> - phy->is_suspended = 1;
>>>> - } else if (!suspend && phy->is_suspended) {
>>>> - phy->is_suspended = 0;
>>>> -
>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>>> - val &= ~PLL_IDLE;
>>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>>> -
>>>> - do {
>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
>>>> - if (!(val & PLL_TICOPWDN))
>>>> - break;
>>>> - udelay(1);
>>>> - } while (--timeout);
>>>> - }
>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>>> + val |= PLL_IDLE;
>>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>>> +
>>>> + do {
>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
>>>> + if (val & PLL_TICOPWDN)
>>>> + break;
>>>> + udelay(1);
>>>
>>> Is it better to sleep instead of udelay?
>>
>> hmm.. yeah, I guess this function wont be called from interrupt context.
>>>
>>>> + } while (--timeout);
>>>> +
>>>> + omap_control_usb_phy_power(phy->control_dev, 0);
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static int omap_pipe3_power_on(struct phy *x)
>>>> +{
>>>> + struct omap_pipe3 *phy = phy_get_drvdata(x);
>>>> + int val;
>>>> + int timeout = PLL_IDLE_TIME;
>>>> +
>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>>> + val &= ~PLL_IDLE;
>>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>>> +
>>>> + do {
>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
>>>> + if (!(val & PLL_TICOPWDN))
>>>> + break;
>>>> + udelay(1);
>>>
>>> here too.
>>
>> Ok.
>>>
>>>> + } while (--timeout);
>>>>
>>>> return 0;
>>>> }
>>>>
>>>> -static void omap_usb_dpll_relock(struct omap_usb *phy)
>>>> +static void omap_pipe3_dpll_relock(struct omap_pipe3 *phy)
>>>> {
>>>> u32 val;
>>>> unsigned long timeout;
>>>>
>>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
>>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
>>>>
>>>> timeout = jiffies + msecs_to_jiffies(20);
>>>> do {
>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
>>>> if (val & PLL_LOCK)
>>>> break;
>>>> } while (!WARN_ON(time_after(jiffies, timeout)));
>>>> }
>>>>
>>>> -static int omap_usb_dpll_lock(struct omap_usb *phy)
>>>> +static int omap_pipe3_dpll_lock(struct omap_pipe3 *phy)
>>>> {
>>>> u32 val;
>>>> unsigned long rate;
>>>> - struct usb_dpll_params *dpll_params;
>>>> + struct pipe3_dpll_params *dpll_params;
>>>>
>>>> rate = clk_get_rate(phy->sys_clk);
>>>> - dpll_params = omap_usb3_get_dpll_params(rate);
>>>> + dpll_params = omap_pipe3_get_dpll_params(rate);
>>>> if (!dpll_params) {
>>>> dev_err(phy->dev,
>>>> "No DPLL configuration for %lu Hz SYS CLK\n", rate);
>>>> return -EINVAL;
>>>> }
>>>>
>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
>>>> val &= ~PLL_REGN_MASK;
>>>> val |= dpll_params->n << PLL_REGN_SHIFT;
>>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>>>>
>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>>> val &= ~PLL_SELFREQDCO_MASK;
>>>> val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
>>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>>>
>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
>>>> val &= ~PLL_REGM_MASK;
>>>> val |= dpll_params->m << PLL_REGM_SHIFT;
>>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>>>>
>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
>>>> val &= ~PLL_REGM_F_MASK;
>>>> val |= dpll_params->mf << PLL_REGM_F_SHIFT;
>>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
>>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
>>>>
>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
>>>> val &= ~PLL_SD_MASK;
>>>> val |= dpll_params->sd << PLL_SD_SHIFT;
>>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
>>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
>>>>
>>>> - omap_usb_dpll_relock(phy);
>>>> + omap_pipe3_dpll_relock(phy);
>>>>
>>>> return 0;
>>>> }
>>>>
>>>> -static int omap_usb3_init(struct usb_phy *x)
>>>> +static int omap_pipe3_init(struct phy *x)
>>>> {
>>>> - struct omap_usb *phy = phy_to_omapusb(x);
>>>> + struct omap_pipe3 *phy = phy_get_drvdata(x);
>>>> int ret;
>>>>
>>>> - ret = omap_usb_dpll_lock(phy);
>>>> + ret = omap_pipe3_dpll_lock(phy);
>>>> if (ret)
>>>> return ret;
>>>>
>>>> @@ -195,9 +199,18 @@ static int omap_usb3_init(struct usb_phy *x)
>>>> return 0;
>>>> }
>>>>
>>>> -static int omap_usb3_probe(struct platform_device *pdev)
>>>> +static struct phy_ops ops = {
>>>> + .init = omap_pipe3_init,
>>>> + .power_on = omap_pipe3_power_on,
>>>> + .power_off = omap_pipe3_power_off,
>>>> + .owner = THIS_MODULE,
>>>> +};
>>>> +
>>>> +static int omap_pipe3_probe(struct platform_device *pdev)
>>>> {
>>>> - struct omap_usb *phy;
>>>> + struct omap_pipe3 *phy;
>>>> + struct phy *generic_phy;
>>>> + struct phy_provider *phy_provider;
>>>> struct resource *res;
>>>> struct device_node *node = pdev->dev.of_node;
>>>> struct device_node *control_node;
>>>> @@ -208,7 +221,7 @@ static int omap_usb3_probe(struct platform_device *pdev)
>>>>
>>>> phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
>>>> if (!phy) {
>>>> - dev_err(&pdev->dev, "unable to alloc mem for OMAP USB3 PHY\n");
>>>> + dev_err(&pdev->dev, "unable to alloc mem for OMAP PIPE3 PHY\n");
>>>> return -ENOMEM;
>>>> }
>>>>
>>>> @@ -219,13 +232,6 @@ static int omap_usb3_probe(struct platform_device *pdev)
>>>>
>>>> phy->dev = &pdev->dev;
>>>>
>>>> - phy->phy.dev = phy->dev;
>>>> - phy->phy.label = "omap-usb3";
>>>> - phy->phy.init = omap_usb3_init;
>>>> - phy->phy.set_suspend = omap_usb3_suspend;
>>>> - phy->phy.type = USB_PHY_TYPE_USB3;
>>>> -
>>>> - phy->is_suspended = 1;
>>>> phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
>>>
>>> As this is no longer USB specific, we need to make the clock binding generic as well.
>>
>> right. Its also needed when we have the same driver work for sata and pcie. Maybe do that in a separate patch?
>
> OK. up to you.
>>>
>>>> if (IS_ERR(phy->wkupclk)) {
>>>> dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
>>>> @@ -251,6 +257,11 @@ static int omap_usb3_probe(struct platform_device *pdev)
>>>> dev_err(&pdev->dev, "Failed to get control device phandle\n");
>>>> return -EINVAL;
>>>> }
>>>> + phy_provider = devm_of_phy_provider_register(phy->dev,
>>>> + of_phy_simple_xlate);
>>>> + if (IS_ERR(phy_provider))
>>>> + return PTR_ERR(phy_provider);
>>>> +
>>>> control_pdev = of_find_device_by_node(control_node);
>>>> if (!control_pdev) {
>>>> dev_err(&pdev->dev, "Failed to get control device\n");
>>>> @@ -260,23 +271,27 @@ static int omap_usb3_probe(struct platform_device *pdev)
>>>> phy->control_dev = &control_pdev->dev;
>>>>
>>>> omap_control_usb_phy_power(phy->control_dev, 0);
>>>> - usb_add_phy_dev(&phy->phy);
>>>>
>>>> platform_set_drvdata(pdev, phy);
>>>> -
>>>> pm_runtime_enable(phy->dev);
>>>> +
>>>> + generic_phy = devm_phy_create(phy->dev, &ops, NULL);
>>>> + if (IS_ERR(generic_phy))
>>>> + return PTR_ERR(generic_phy);
>>>> +
>>>> + phy_set_drvdata(generic_phy, phy);
>>>> +
>>>> pm_runtime_get(&pdev->dev);
>>>>
>>>> return 0;
>>>> }
>>>>
>>>> -static int omap_usb3_remove(struct platform_device *pdev)
>>>> +static int omap_pipe3_remove(struct platform_device *pdev)
>>>> {
>>>> - struct omap_usb *phy = platform_get_drvdata(pdev);
>>>> + struct omap_pipe3 *phy = platform_get_drvdata(pdev);
>>>>
>>>> clk_unprepare(phy->wkupclk);
>>>> clk_unprepare(phy->optclk);
>>>> - usb_remove_phy(&phy->phy);
>>>> if (!pm_runtime_suspended(&pdev->dev))
>>>> pm_runtime_put(&pdev->dev);
>>>> pm_runtime_disable(&pdev->dev);
>>>> @@ -286,10 +301,9 @@ static int omap_usb3_remove(struct platform_device *pdev)
>>>>
>>>> #ifdef CONFIG_PM_RUNTIME
>>>>
>>>> -static int omap_usb3_runtime_suspend(struct device *dev)
>>>> +static int omap_pipe3_runtime_suspend(struct device *dev)
>>>> {
>>>> - struct platform_device *pdev = to_platform_device(dev);
>>>> - struct omap_usb *phy = platform_get_drvdata(pdev);
>>>> + struct omap_pipe3 *phy = dev_get_drvdata(dev);
>>>>
>>>> clk_disable(phy->wkupclk);
>>>> clk_disable(phy->optclk);
>>>> @@ -297,11 +311,10 @@ static int omap_usb3_runtime_suspend(struct device *dev)
>>>> return 0;
>>>> }
>>>>
>>>> -static int omap_usb3_runtime_resume(struct device *dev)
>>>> +static int omap_pipe3_runtime_resume(struct device *dev)
>>>> {
>>>> u32 ret = 0;
>>>> - struct platform_device *pdev = to_platform_device(dev);
>>>> - struct omap_usb *phy = platform_get_drvdata(pdev);
>>>> + struct omap_pipe3 *phy = dev_get_drvdata(dev);
>>>>
>>>> ret = clk_enable(phy->optclk);
>>>> if (ret) {
>>>> @@ -324,38 +337,41 @@ err1:
>>>> return ret;
>>>> }
>>>>
>>>> -static const struct dev_pm_ops omap_usb3_pm_ops = {
>>>> - SET_RUNTIME_PM_OPS(omap_usb3_runtime_suspend, omap_usb3_runtime_resume,
>>>> - NULL)
>>>> +static const struct dev_pm_ops omap_pipe3_pm_ops = {
>>>> + SET_RUNTIME_PM_OPS(omap_pipe3_runtime_suspend,
>>>> + omap_pipe3_runtime_resume, NULL)
>>>> };
>>>>
>>>> -#define DEV_PM_OPS (&omap_usb3_pm_ops)
>>>> +#define DEV_PM_OPS (&omap_pipe3_pm_ops)
>>>> #else
>>>> #define DEV_PM_OPS NULL
>>>> #endif
>>>>
>>>> #ifdef CONFIG_OF
>>>> -static const struct of_device_id omap_usb3_id_table[] = {
>>>> +static const struct of_device_id omap_pipe3_id_table[] = {
>>>> + { .compatible = "ti,omap-pipe3" },
>>>
>>> why do you need "omap-pipe3", isn't sata, pcie and usb3 sufficient?
>>
>> I thought it would be better if everyone uses omap-pipe3 and added pcie, sata if there are any specific settings (for pcie or sata) that should be done.
>
> We can always add specialized options later when needed. AFAIK just the
> DPLL data is different among the different PHYs.
>>>
>>>> + { .compatible = "ti,omap-sata" },
>>>> + { .compatible = "ti,omap-pcie" },
>>>> { .compatible = "ti,omap-usb3" },
>
> I think compatible strings should be improved to indicate that it is a PHY.
>
> e.g. "ti,omap-phy-sata" or just "ti,pipe3-phy-sata"
>

Please remove "ti,omap-pcie" for now, you can add it later whenever you add
dpll settings for pcie.

Also, please change the newly added compatible strings to

"ti,phy-pipe3-usb3" and "ti,phy-pipe3-sata"

Also you need to rearrange the patches so that the DT binding document is first
moded from usb/ to phy/ and then the change is done for pipe3.

cheers,
-roger

2013-10-11 15:10:17

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

Hi,

On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
> Adapted dwc3 core to use the Generic PHY Framework. So for init, exit,
> power_on and power_off the following APIs are used phy_init(), phy_exit(),
> phy_power_on() and phy_power_off().
>
> However using the old USB phy library wont be removed till the PHYs of all
> other SoC's using dwc3 core is adapted to the Generic PHY Framework.
>
> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
> ---
> Documentation/devicetree/bindings/usb/dwc3.txt | 6 ++-
> drivers/usb/dwc3/Kconfig | 1 +
> drivers/usb/dwc3/core.c | 49 ++++++++++++++++++++++++
> drivers/usb/dwc3/core.h | 7 ++++
> 4 files changed, 61 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
> index e807635..471366d 100644
> --- a/Documentation/devicetree/bindings/usb/dwc3.txt
> +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
> @@ -6,11 +6,13 @@ Required properties:
> - compatible: must be "snps,dwc3"
> - reg : Address and length of the register set for the device
> - interrupts: Interrupts used by the dwc3 controller.
> +
> +Optional properties:
> - usb-phy : array of phandle for the PHY device. The first element
> in the array is expected to be a handle to the USB2/HS PHY and
> the second element is expected to be a handle to the USB3/SS PHY
> -
> -Optional properties:
> + - phys: from the *Generic PHY* bindings
> + - phy-names: from the *Generic PHY* bindings
> - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
>
> This is usually a subnode to DWC3 glue to which it is connected.
> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
> index cfc16dd..ad7ce83 100644
> --- a/drivers/usb/dwc3/Kconfig
> +++ b/drivers/usb/dwc3/Kconfig
> @@ -3,6 +3,7 @@ config USB_DWC3
> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
> depends on EXTCON
> select USB_PHY
> + select GENERIC_PHY
> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
> help
> Say Y or M here if your system has a Dual Role SuperSpeed
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index 428c29e..485d365 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -82,6 +82,12 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
>
> usb_phy_init(dwc->usb2_phy);
> usb_phy_init(dwc->usb3_phy);

How about adding
+ if (dwc->usb2_phy)
+ usb_phy_init(dwc->usb2_phy);
+ if (dwc->usb3_phy)
+ usb_phy_init(dwc->usb3_phy);

both usb phy and generic phy shouldn't be present together.

> +
> + if (dwc->usb2_generic_phy)
> + phy_init(dwc->usb2_generic_phy);
> + if (dwc->usb3_generic_phy)
> + phy_init(dwc->usb3_generic_phy);
> +
> mdelay(100);
>
> /* Clear USB3 PHY reset */
> @@ -343,6 +349,11 @@ static void dwc3_core_exit(struct dwc3 *dwc)
> {
> usb_phy_shutdown(dwc->usb2_phy);
> usb_phy_shutdown(dwc->usb3_phy);

here as well

> +
> + if (dwc->usb2_generic_phy)
> + phy_power_off(dwc->usb2_generic_phy);
> + if (dwc->usb3_generic_phy)
> + phy_power_off(dwc->usb3_generic_phy);
> }
>
> #define DWC3_ALIGN_MASK (16 - 1)
> @@ -427,6 +438,23 @@ static int dwc3_probe(struct platform_device *pdev)
> dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
> }
>
> + if (of_property_read_bool(node, "phys") || pdata->has_phy) {
> + dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
> + if (IS_ERR(dwc->usb2_generic_phy)) {
> + dev_err(dev, "no usb2 phy configured yet");
> + return PTR_ERR(dwc->usb2_generic_phy);
> + }
> +
> + dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
> + if (IS_ERR(dwc->usb3_generic_phy)) {
> + dev_err(dev, "no usb3 phy configured yet");
> + return PTR_ERR(dwc->usb3_generic_phy);
> + }

better to add
+ /* Don't use USB PHY if generic PHY was found */
+ dwc->usb2_phy = dwc->usb3_phy = NULL;

> + } else {

not required as we've used kzalloc for dwc.

> + dwc->usb2_generic_phy = NULL;
> + dwc->usb3_generic_phy = NULL;
> + }
> +
> /* default to superspeed if no maximum_speed passed */
> if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
> dwc->maximum_speed = USB_SPEED_SUPER;
> @@ -450,6 +478,11 @@ static int dwc3_probe(struct platform_device *pdev)

if (dwc->usb2_phy)

> usb_phy_set_suspend(dwc->usb2_phy, 0);

if (dwc->usb3_phy)

> usb_phy_set_suspend(dwc->usb3_phy, 0);
>
> + if (dwc->usb2_generic_phy)
> + phy_power_on(dwc->usb2_generic_phy);
> + if (dwc->usb3_generic_phy)
> + phy_power_on(dwc->usb3_generic_phy);
> +
> spin_lock_init(&dwc->lock);
> platform_set_drvdata(pdev, dwc);
>
> @@ -576,6 +609,11 @@ static int dwc3_remove(struct platform_device *pdev)

if (dwc->usb2_phy)
> usb_phy_set_suspend(dwc->usb2_phy, 1);

if (dwc->usb3_phy)
> usb_phy_set_suspend(dwc->usb3_phy, 1);
>
> + if (dwc->usb2_generic_phy)
> + phy_power_off(dwc->usb2_generic_phy);
> + if (dwc->usb3_generic_phy)
> + phy_power_off(dwc->usb3_generic_phy);
> +
> pm_runtime_put(&pdev->dev);
> pm_runtime_disable(&pdev->dev);
>
> @@ -673,6 +711,11 @@ static int dwc3_suspend(struct device *dev)

if (dwc->usb3_phy)
> usb_phy_shutdown(dwc->usb3_phy);

if (dwc->usb2_phy)
> usb_phy_shutdown(dwc->usb2_phy);
>
> + if (dwc->usb2_generic_phy)
> + phy_exit(dwc->usb2_generic_phy);
> + if (dwc->usb3_generic_phy)
> + phy_exit(dwc->usb3_generic_phy);
> +
> return 0;
> }
>
> @@ -683,6 +726,12 @@ static int dwc3_resume(struct device *dev)
>

if (dwc->usb3_phy)
> usb_phy_init(dwc->usb3_phy);

if (dwc->usb2_phy)
> usb_phy_init(dwc->usb2_phy);
> +
> + if (dwc->usb2_generic_phy)
> + phy_init(dwc->usb2_generic_phy);
> + if (dwc->usb3_generic_phy)
> + phy_init(dwc->usb3_generic_phy);
> +
> msleep(100);
>
> spin_lock_irqsave(&dwc->lock, flags);
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index f8af8d4..01ec7d7 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -31,6 +31,8 @@
> #include <linux/usb/gadget.h>
> #include <linux/usb/otg.h>
>
> +#include <linux/phy/phy.h>
> +
> /* Global constants */
> #define DWC3_EP0_BOUNCE_SIZE 512
> #define DWC3_ENDPOINTS_NUM 32
> @@ -613,6 +615,8 @@ struct dwc3_scratchpad_array {
> * @dr_mode: requested mode of operation
> * @usb2_phy: pointer to USB2 PHY
> * @usb3_phy: pointer to USB3 PHY
> + * @usb2_generic_phy: pointer to USB2 PHY
> + * @usb3_generic_phy: pointer to USB3 PHY
> * @dcfg: saved contents of DCFG register
> * @gctl: saved contents of GCTL register
> * @is_selfpowered: true when we are selfpowered
> @@ -665,6 +669,9 @@ struct dwc3 {
> struct usb_phy *usb2_phy;
> struct usb_phy *usb3_phy;
>
> + struct phy *usb2_generic_phy;
> + struct phy *usb3_generic_phy;
> +
> void __iomem *regs;
> size_t regs_size;
>
>

cheers,
-roger

2013-10-14 09:20:39

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: Re: [PATCH 3/7] drivers: phy: usb3/pipe3: Adapt pipe3 driver to Generic PHY Framework

Hi Roger,

On Friday 11 October 2013 08:32 PM, Roger Quadros wrote:
> On 09/16/2013 10:37 AM, Roger Quadros wrote:
>> On 09/16/2013 06:01 AM, Kishon Vijay Abraham I wrote:
>>> On Thursday 12 September 2013 04:49 PM, Roger Quadros wrote:
>>>> Hi Kishon,
>>>>
>>>> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>>>>> Adapted omap-usb3 PHY driver to Generic PHY Framework and moved phy-omap-usb3
>>>>> driver in drivers/usb/phy to drivers/phy and also renamed the file to
>>>>> phy-omap-pipe3 since this same driver will be used for SATA PHY and
>>>>> PCIE PHY.
>>>>
>>>> I would suggest to split the renaming and PHY adaptation into 2 separate patches.
>>>
>>> Alright.
>>>>
>>>>>
>>>>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>>>>> ---
>>>>> Documentation/devicetree/bindings/usb/usb-phy.txt | 5 +-
>>>>> drivers/phy/Kconfig | 10 +
>>>>> drivers/phy/Makefile | 1 +
>>>>> .../phy/phy-omap-usb3.c => phy/phy-omap-pipe3.c} | 206 +++++++++++---------
>>>>
>>>> how about naming it to phy-ti-pipe3.c as it is used on OMAP as well as non-OMAP e.g. DRA7.
>>>
>>> hmm.. I thought it would be consistent with other PHY drivers (phy-omap-usb2). Moreover DRA7 is OMAP based platform ;-) Maybe we should reserve that for later?
>>
>> OK. Up to you.
>>
>>>>
>>>>> drivers/usb/phy/Kconfig | 11 --
>>>>> drivers/usb/phy/Makefile | 1 -
>>>>> include/linux/phy/omap_pipe3.h | 52 +++++
>>>>> 7 files changed, 177 insertions(+), 109 deletions(-)
>>>>> rename drivers/{usb/phy/phy-omap-usb3.c => phy/phy-omap-pipe3.c} (57%)
>>>>> create mode 100644 include/linux/phy/omap_pipe3.h
>>>>>
>>>>> diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/usb/usb-phy.txt
>>>>> index c0245c8..36bdb17 100644
>>>>> --- a/Documentation/devicetree/bindings/usb/usb-phy.txt
>>>>> +++ b/Documentation/devicetree/bindings/usb/usb-phy.txt
>>>>> @@ -21,10 +21,11 @@ usb2phy@4a0ad080 {
>>>>> #phy-cells = <0>;
>>>>> };
>>>>>
>>>>> -OMAP USB3 PHY
>>>>> +OMAP PIPE3 PHY
>>>>>
>>>>> Required properties:
>>>>> - - compatible: Should be "ti,omap-usb3"
>>>>> + - compatible: Should be "ti,omap-usb3", "ti,omap-pipe3", "ti,omap-sata"
>>>>> + or "ti,omap-pcie"
>>>>> - reg : Address and length of the register set for the device.
>>>>> - reg-names: The names of the register addresses corresponding to the registers
>>>>> filled in "reg".
>>>>> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
>>>>> index ac239ac..5c2e7a0 100644
>>>>> --- a/drivers/phy/Kconfig
>>>>> +++ b/drivers/phy/Kconfig
>>>>> @@ -27,6 +27,16 @@ config OMAP_USB2
>>>>> The USB OTG controller communicates with the comparator using this
>>>>> driver.
>>>>>
>>>>> +config OMAP_PIPE3
>>>>> + tristate "OMAP PIPE3 PHY Driver"
>>>>> + select GENERIC_PHY
>>>>> + select OMAP_CONTROL_USB
>>>> how about
>>>> depends on OMAP_CONTROL_USB
>>>
>>> From whatever I could make out from comments of Greg in my Generic PHY Framework, it's better to do a select of dependent modules instead of depends on.
>>
>> You can use select, provided the item you are selecting doesn't depend on anything else.
>> As OMAP_CONTROL_USB depends on ARCH_OMAP2PLUS, your configuration will fail if a user enables
>> OMAP_PIPE3 on non OMAP configuration.
>>
>> Further, in this case since it is OMAP related driver, there is no point in showing/building it
>> if OMAP platform is not selected, so you at least need [depends on "ARCH_OMAP2PLUS"] to fix
>> both issue I mentioned.
>>
>>>>
>>>> Also, if this is TI/OMAP it might as well depend on ARCH_OMAP.
>>>>
>>>>> + help
>>>>> + Enable this to support the PIPE3 PHY that is part of SOC. This
>>>>
>>>> worth mentioning TI OMAP/DRA SoCs.
>>>
>>> right.
>>>>
>>>>> + driver takes care of all the PHY functionality apart from comparator.
>>>>> + This driver interacts with the "OMAP Control PHY Driver" to power
>>>>> + on/off the PHY.
>>>>> +
>>>>> config TWL4030_USB
>>>>> tristate "TWL4030 USB Transceiver Driver"
>>>>> depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
>>>>> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
>>>>> index 0dd8a98..48bf9f2 100644
>>>>> --- a/drivers/phy/Makefile
>>>>> +++ b/drivers/phy/Makefile
>>>>> @@ -4,4 +4,5 @@
>>>>>
>>>>> obj-$(CONFIG_GENERIC_PHY) += phy-core.o
>>>>> obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
>>>>> +obj-$(CONFIG_OMAP_PIPE3) += phy-omap-pipe3.o
>>>>> obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
>>>>> diff --git a/drivers/usb/phy/phy-omap-usb3.c b/drivers/phy/phy-omap-pipe3.c
>>>>> similarity index 57%
>>>>> rename from drivers/usb/phy/phy-omap-usb3.c
>>>>> rename to drivers/phy/phy-omap-pipe3.c
>>>>> index 4004f82..ee9a901 100644
>>>>> --- a/drivers/usb/phy/phy-omap-usb3.c
>>>>> +++ b/drivers/phy/phy-omap-pipe3.c
>>>>> @@ -1,5 +1,5 @@
>>>>> /*
>>>>> - * omap-usb3 - USB PHY, talking to dwc3 controller in OMAP.
>>>>> + * omap-pipe3 - PHY driver for SATA, USB and PCIE in OMAP platforms
>>>>> *
>>>>> * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
>>>>> * This program is free software; you can redistribute it and/or modify
>>>>> @@ -19,7 +19,8 @@
>>>>> #include <linux/module.h>
>>>>> #include <linux/platform_device.h>
>>>>> #include <linux/slab.h>
>>>>> -#include <linux/usb/omap_usb.h>
>>>>> +#include <linux/phy/omap_pipe3.h>
>>>>> +#include <linux/phy/phy.h>
>>>>> #include <linux/of.h>
>>>>> #include <linux/clk.h>
>>>>> #include <linux/err.h>
>>>>> @@ -52,17 +53,17 @@
>>>>>
>>>>> /*
>>>>> * This is an Empirical value that works, need to confirm the actual
>>>>> - * value required for the USB3PHY_PLL_CONFIGURATION2.PLL_IDLE status
>>>>> - * to be correctly reflected in the USB3PHY_PLL_STATUS register.
>>>>> + * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status
>>>>> + * to be correctly reflected in the PIPE3PHY_PLL_STATUS register.
>>>>> */
>>>>> # define PLL_IDLE_TIME 100;
>>>>>
>>>>> -struct usb_dpll_map {
>>>>> +struct pipe3_dpll_map {
>>>>> unsigned long rate;
>>>>> - struct usb_dpll_params params;
>>>>> + struct pipe3_dpll_params params;
>>>>> };
>>>>>
>>>>> -static struct usb_dpll_map dpll_map[] = {
>>>>> +static struct pipe3_dpll_map dpll_map[] = {
>>>>> {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */
>>>>> {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */
>>>>> {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */
>>>>> @@ -71,7 +72,7 @@ static struct usb_dpll_map dpll_map[] = {
>>>>> {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */
>>>>> };
>>>>>
>>>>> -static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate)
>>>>> +static struct pipe3_dpll_params *omap_pipe3_get_dpll_params(unsigned long rate)
>>>>> {
>>>>> int i;
>>>>>
>>>>> @@ -83,110 +84,113 @@ static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate)
>>>>> return 0;
>>>>> }
>>>>>
>>>>> -static int omap_usb3_suspend(struct usb_phy *x, int suspend)
>>>>> +static int omap_pipe3_power_off(struct phy *x)
>>>>> {
>>>>> - struct omap_usb *phy = phy_to_omapusb(x);
>>>>> - int val;
>>>>> + struct omap_pipe3 *phy = phy_get_drvdata(x);
>>>>> + int val;
>>>>> int timeout = PLL_IDLE_TIME;
>>>>>
>>>>> - if (suspend && !phy->is_suspended) {
>>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>>>> - val |= PLL_IDLE;
>>>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>>>> -
>>>>> - do {
>>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
>>>>> - if (val & PLL_TICOPWDN)
>>>>> - break;
>>>>> - udelay(1);
>>>>> - } while (--timeout);
>>>>> -
>>>>> - omap_control_usb_phy_power(phy->control_dev, 0);
>>>>> -
>>>>> - phy->is_suspended = 1;
>>>>> - } else if (!suspend && phy->is_suspended) {
>>>>> - phy->is_suspended = 0;
>>>>> -
>>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>>>> - val &= ~PLL_IDLE;
>>>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>>>> -
>>>>> - do {
>>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
>>>>> - if (!(val & PLL_TICOPWDN))
>>>>> - break;
>>>>> - udelay(1);
>>>>> - } while (--timeout);
>>>>> - }
>>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>>>> + val |= PLL_IDLE;
>>>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>>>> +
>>>>> + do {
>>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
>>>>> + if (val & PLL_TICOPWDN)
>>>>> + break;
>>>>> + udelay(1);
>>>>
>>>> Is it better to sleep instead of udelay?
>>>
>>> hmm.. yeah, I guess this function wont be called from interrupt context.
>>>>
>>>>> + } while (--timeout);
>>>>> +
>>>>> + omap_control_usb_phy_power(phy->control_dev, 0);
>>>>> +
>>>>> + return 0;
>>>>> +}
>>>>> +
>>>>> +static int omap_pipe3_power_on(struct phy *x)
>>>>> +{
>>>>> + struct omap_pipe3 *phy = phy_get_drvdata(x);
>>>>> + int val;
>>>>> + int timeout = PLL_IDLE_TIME;
>>>>> +
>>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>>>> + val &= ~PLL_IDLE;
>>>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>>>> +
>>>>> + do {
>>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
>>>>> + if (!(val & PLL_TICOPWDN))
>>>>> + break;
>>>>> + udelay(1);
>>>>
>>>> here too.
>>>
>>> Ok.
>>>>
>>>>> + } while (--timeout);
>>>>>
>>>>> return 0;
>>>>> }
>>>>>
>>>>> -static void omap_usb_dpll_relock(struct omap_usb *phy)
>>>>> +static void omap_pipe3_dpll_relock(struct omap_pipe3 *phy)
>>>>> {
>>>>> u32 val;
>>>>> unsigned long timeout;
>>>>>
>>>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
>>>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
>>>>>
>>>>> timeout = jiffies + msecs_to_jiffies(20);
>>>>> do {
>>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
>>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
>>>>> if (val & PLL_LOCK)
>>>>> break;
>>>>> } while (!WARN_ON(time_after(jiffies, timeout)));
>>>>> }
>>>>>
>>>>> -static int omap_usb_dpll_lock(struct omap_usb *phy)
>>>>> +static int omap_pipe3_dpll_lock(struct omap_pipe3 *phy)
>>>>> {
>>>>> u32 val;
>>>>> unsigned long rate;
>>>>> - struct usb_dpll_params *dpll_params;
>>>>> + struct pipe3_dpll_params *dpll_params;
>>>>>
>>>>> rate = clk_get_rate(phy->sys_clk);
>>>>> - dpll_params = omap_usb3_get_dpll_params(rate);
>>>>> + dpll_params = omap_pipe3_get_dpll_params(rate);
>>>>> if (!dpll_params) {
>>>>> dev_err(phy->dev,
>>>>> "No DPLL configuration for %lu Hz SYS CLK\n", rate);
>>>>> return -EINVAL;
>>>>> }
>>>>>
>>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
>>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
>>>>> val &= ~PLL_REGN_MASK;
>>>>> val |= dpll_params->n << PLL_REGN_SHIFT;
>>>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>>>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>>>>>
>>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
>>>>> val &= ~PLL_SELFREQDCO_MASK;
>>>>> val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
>>>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
>>>>>
>>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
>>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
>>>>> val &= ~PLL_REGM_MASK;
>>>>> val |= dpll_params->m << PLL_REGM_SHIFT;
>>>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>>>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
>>>>>
>>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
>>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
>>>>> val &= ~PLL_REGM_F_MASK;
>>>>> val |= dpll_params->mf << PLL_REGM_F_SHIFT;
>>>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
>>>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
>>>>>
>>>>> - val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
>>>>> + val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
>>>>> val &= ~PLL_SD_MASK;
>>>>> val |= dpll_params->sd << PLL_SD_SHIFT;
>>>>> - omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
>>>>> + omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
>>>>>
>>>>> - omap_usb_dpll_relock(phy);
>>>>> + omap_pipe3_dpll_relock(phy);
>>>>>
>>>>> return 0;
>>>>> }
>>>>>
>>>>> -static int omap_usb3_init(struct usb_phy *x)
>>>>> +static int omap_pipe3_init(struct phy *x)
>>>>> {
>>>>> - struct omap_usb *phy = phy_to_omapusb(x);
>>>>> + struct omap_pipe3 *phy = phy_get_drvdata(x);
>>>>> int ret;
>>>>>
>>>>> - ret = omap_usb_dpll_lock(phy);
>>>>> + ret = omap_pipe3_dpll_lock(phy);
>>>>> if (ret)
>>>>> return ret;
>>>>>
>>>>> @@ -195,9 +199,18 @@ static int omap_usb3_init(struct usb_phy *x)
>>>>> return 0;
>>>>> }
>>>>>
>>>>> -static int omap_usb3_probe(struct platform_device *pdev)
>>>>> +static struct phy_ops ops = {
>>>>> + .init = omap_pipe3_init,
>>>>> + .power_on = omap_pipe3_power_on,
>>>>> + .power_off = omap_pipe3_power_off,
>>>>> + .owner = THIS_MODULE,
>>>>> +};
>>>>> +
>>>>> +static int omap_pipe3_probe(struct platform_device *pdev)
>>>>> {
>>>>> - struct omap_usb *phy;
>>>>> + struct omap_pipe3 *phy;
>>>>> + struct phy *generic_phy;
>>>>> + struct phy_provider *phy_provider;
>>>>> struct resource *res;
>>>>> struct device_node *node = pdev->dev.of_node;
>>>>> struct device_node *control_node;
>>>>> @@ -208,7 +221,7 @@ static int omap_usb3_probe(struct platform_device *pdev)
>>>>>
>>>>> phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
>>>>> if (!phy) {
>>>>> - dev_err(&pdev->dev, "unable to alloc mem for OMAP USB3 PHY\n");
>>>>> + dev_err(&pdev->dev, "unable to alloc mem for OMAP PIPE3 PHY\n");
>>>>> return -ENOMEM;
>>>>> }
>>>>>
>>>>> @@ -219,13 +232,6 @@ static int omap_usb3_probe(struct platform_device *pdev)
>>>>>
>>>>> phy->dev = &pdev->dev;
>>>>>
>>>>> - phy->phy.dev = phy->dev;
>>>>> - phy->phy.label = "omap-usb3";
>>>>> - phy->phy.init = omap_usb3_init;
>>>>> - phy->phy.set_suspend = omap_usb3_suspend;
>>>>> - phy->phy.type = USB_PHY_TYPE_USB3;
>>>>> -
>>>>> - phy->is_suspended = 1;
>>>>> phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
>>>>
>>>> As this is no longer USB specific, we need to make the clock binding generic as well.
>>>
>>> right. Its also needed when we have the same driver work for sata and pcie. Maybe do that in a separate patch?
>>
>> OK. up to you.
>>>>
>>>>> if (IS_ERR(phy->wkupclk)) {
>>>>> dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
>>>>> @@ -251,6 +257,11 @@ static int omap_usb3_probe(struct platform_device *pdev)
>>>>> dev_err(&pdev->dev, "Failed to get control device phandle\n");
>>>>> return -EINVAL;
>>>>> }
>>>>> + phy_provider = devm_of_phy_provider_register(phy->dev,
>>>>> + of_phy_simple_xlate);
>>>>> + if (IS_ERR(phy_provider))
>>>>> + return PTR_ERR(phy_provider);
>>>>> +
>>>>> control_pdev = of_find_device_by_node(control_node);
>>>>> if (!control_pdev) {
>>>>> dev_err(&pdev->dev, "Failed to get control device\n");
>>>>> @@ -260,23 +271,27 @@ static int omap_usb3_probe(struct platform_device *pdev)
>>>>> phy->control_dev = &control_pdev->dev;
>>>>>
>>>>> omap_control_usb_phy_power(phy->control_dev, 0);
>>>>> - usb_add_phy_dev(&phy->phy);
>>>>>
>>>>> platform_set_drvdata(pdev, phy);
>>>>> -
>>>>> pm_runtime_enable(phy->dev);
>>>>> +
>>>>> + generic_phy = devm_phy_create(phy->dev, &ops, NULL);
>>>>> + if (IS_ERR(generic_phy))
>>>>> + return PTR_ERR(generic_phy);
>>>>> +
>>>>> + phy_set_drvdata(generic_phy, phy);
>>>>> +
>>>>> pm_runtime_get(&pdev->dev);
>>>>>
>>>>> return 0;
>>>>> }
>>>>>
>>>>> -static int omap_usb3_remove(struct platform_device *pdev)
>>>>> +static int omap_pipe3_remove(struct platform_device *pdev)
>>>>> {
>>>>> - struct omap_usb *phy = platform_get_drvdata(pdev);
>>>>> + struct omap_pipe3 *phy = platform_get_drvdata(pdev);
>>>>>
>>>>> clk_unprepare(phy->wkupclk);
>>>>> clk_unprepare(phy->optclk);
>>>>> - usb_remove_phy(&phy->phy);
>>>>> if (!pm_runtime_suspended(&pdev->dev))
>>>>> pm_runtime_put(&pdev->dev);
>>>>> pm_runtime_disable(&pdev->dev);
>>>>> @@ -286,10 +301,9 @@ static int omap_usb3_remove(struct platform_device *pdev)
>>>>>
>>>>> #ifdef CONFIG_PM_RUNTIME
>>>>>
>>>>> -static int omap_usb3_runtime_suspend(struct device *dev)
>>>>> +static int omap_pipe3_runtime_suspend(struct device *dev)
>>>>> {
>>>>> - struct platform_device *pdev = to_platform_device(dev);
>>>>> - struct omap_usb *phy = platform_get_drvdata(pdev);
>>>>> + struct omap_pipe3 *phy = dev_get_drvdata(dev);
>>>>>
>>>>> clk_disable(phy->wkupclk);
>>>>> clk_disable(phy->optclk);
>>>>> @@ -297,11 +311,10 @@ static int omap_usb3_runtime_suspend(struct device *dev)
>>>>> return 0;
>>>>> }
>>>>>
>>>>> -static int omap_usb3_runtime_resume(struct device *dev)
>>>>> +static int omap_pipe3_runtime_resume(struct device *dev)
>>>>> {
>>>>> u32 ret = 0;
>>>>> - struct platform_device *pdev = to_platform_device(dev);
>>>>> - struct omap_usb *phy = platform_get_drvdata(pdev);
>>>>> + struct omap_pipe3 *phy = dev_get_drvdata(dev);
>>>>>
>>>>> ret = clk_enable(phy->optclk);
>>>>> if (ret) {
>>>>> @@ -324,38 +337,41 @@ err1:
>>>>> return ret;
>>>>> }
>>>>>
>>>>> -static const struct dev_pm_ops omap_usb3_pm_ops = {
>>>>> - SET_RUNTIME_PM_OPS(omap_usb3_runtime_suspend, omap_usb3_runtime_resume,
>>>>> - NULL)
>>>>> +static const struct dev_pm_ops omap_pipe3_pm_ops = {
>>>>> + SET_RUNTIME_PM_OPS(omap_pipe3_runtime_suspend,
>>>>> + omap_pipe3_runtime_resume, NULL)
>>>>> };
>>>>>
>>>>> -#define DEV_PM_OPS (&omap_usb3_pm_ops)
>>>>> +#define DEV_PM_OPS (&omap_pipe3_pm_ops)
>>>>> #else
>>>>> #define DEV_PM_OPS NULL
>>>>> #endif
>>>>>
>>>>> #ifdef CONFIG_OF
>>>>> -static const struct of_device_id omap_usb3_id_table[] = {
>>>>> +static const struct of_device_id omap_pipe3_id_table[] = {
>>>>> + { .compatible = "ti,omap-pipe3" },
>>>>
>>>> why do you need "omap-pipe3", isn't sata, pcie and usb3 sufficient?
>>>
>>> I thought it would be better if everyone uses omap-pipe3 and added pcie, sata if there are any specific settings (for pcie or sata) that should be done.
>>
>> We can always add specialized options later when needed. AFAIK just the
>> DPLL data is different among the different PHYs.
>>>>
>>>>> + { .compatible = "ti,omap-sata" },
>>>>> + { .compatible = "ti,omap-pcie" },
>>>>> { .compatible = "ti,omap-usb3" },
>>
>> I think compatible strings should be improved to indicate that it is a PHY.
>>
>> e.g. "ti,omap-phy-sata" or just "ti,pipe3-phy-sata"
>>
>
> Please remove "ti,omap-pcie" for now, you can add it later whenever you add
> dpll settings for pcie.
>
> Also, please change the newly added compatible strings to
>
> "ti,phy-pipe3-usb3" and "ti,phy-pipe3-sata"

No, I think we should have omap in the compatible since this PHY is specific to
OMAP.
>
> Also you need to rearrange the patches so that the DT binding document is first
> moded from usb/ to phy/ and then the change is done for pipe3.

Ok.

Thanks
Kishon

2013-10-14 09:27:15

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

Hi Roger,

On Friday 11 October 2013 08:39 PM, Roger Quadros wrote:
> Hi,
>
> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>> Adapted dwc3 core to use the Generic PHY Framework. So for init, exit,
>> power_on and power_off the following APIs are used phy_init(), phy_exit(),
>> phy_power_on() and phy_power_off().
>>
>> However using the old USB phy library wont be removed till the PHYs of all
>> other SoC's using dwc3 core is adapted to the Generic PHY Framework.
>>
>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>> ---
>> Documentation/devicetree/bindings/usb/dwc3.txt | 6 ++-
>> drivers/usb/dwc3/Kconfig | 1 +
>> drivers/usb/dwc3/core.c | 49 ++++++++++++++++++++++++
>> drivers/usb/dwc3/core.h | 7 ++++
>> 4 files changed, 61 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
>> index e807635..471366d 100644
>> --- a/Documentation/devicetree/bindings/usb/dwc3.txt
>> +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
>> @@ -6,11 +6,13 @@ Required properties:
>> - compatible: must be "snps,dwc3"
>> - reg : Address and length of the register set for the device
>> - interrupts: Interrupts used by the dwc3 controller.
>> +
>> +Optional properties:
>> - usb-phy : array of phandle for the PHY device. The first element
>> in the array is expected to be a handle to the USB2/HS PHY and
>> the second element is expected to be a handle to the USB3/SS PHY
>> -
>> -Optional properties:
>> + - phys: from the *Generic PHY* bindings
>> + - phy-names: from the *Generic PHY* bindings
>> - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
>>
>> This is usually a subnode to DWC3 glue to which it is connected.
>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>> index cfc16dd..ad7ce83 100644
>> --- a/drivers/usb/dwc3/Kconfig
>> +++ b/drivers/usb/dwc3/Kconfig
>> @@ -3,6 +3,7 @@ config USB_DWC3
>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
>> depends on EXTCON
>> select USB_PHY
>> + select GENERIC_PHY
>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
>> help
>> Say Y or M here if your system has a Dual Role SuperSpeed
>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>> index 428c29e..485d365 100644
>> --- a/drivers/usb/dwc3/core.c
>> +++ b/drivers/usb/dwc3/core.c
>> @@ -82,6 +82,12 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
>>
>> usb_phy_init(dwc->usb2_phy);
>> usb_phy_init(dwc->usb3_phy);
>
> How about adding
> + if (dwc->usb2_phy)
> + usb_phy_init(dwc->usb2_phy);
> + if (dwc->usb3_phy)
> + usb_phy_init(dwc->usb3_phy);

Thankfully that usb_phy_init will check if phy is NULL.
>
> both usb phy and generic phy shouldn't be present together.

ok.
>
>> +
>> + if (dwc->usb2_generic_phy)
>> + phy_init(dwc->usb2_generic_phy);
>> + if (dwc->usb3_generic_phy)
>> + phy_init(dwc->usb3_generic_phy);
>> +
>> mdelay(100);
>>
>> /* Clear USB3 PHY reset */
>> @@ -343,6 +349,11 @@ static void dwc3_core_exit(struct dwc3 *dwc)
>> {
>> usb_phy_shutdown(dwc->usb2_phy);
>> usb_phy_shutdown(dwc->usb3_phy);
>
> here as well
>
>> +
>> + if (dwc->usb2_generic_phy)
>> + phy_power_off(dwc->usb2_generic_phy);
>> + if (dwc->usb3_generic_phy)
>> + phy_power_off(dwc->usb3_generic_phy);
>> }
>>
>> #define DWC3_ALIGN_MASK (16 - 1)
>> @@ -427,6 +438,23 @@ static int dwc3_probe(struct platform_device *pdev)
>> dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
>> }
>>
>> + if (of_property_read_bool(node, "phys") || pdata->has_phy) {
>> + dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
>> + if (IS_ERR(dwc->usb2_generic_phy)) {
>> + dev_err(dev, "no usb2 phy configured yet");
>> + return PTR_ERR(dwc->usb2_generic_phy);
>> + }
>> +
>> + dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
>> + if (IS_ERR(dwc->usb3_generic_phy)) {
>> + dev_err(dev, "no usb3 phy configured yet");
>> + return PTR_ERR(dwc->usb3_generic_phy);
>> + }
>
> better to add
> + /* Don't use USB PHY if generic PHY was found */
> + dwc->usb2_phy = dwc->usb3_phy = NULL;

ok.
>
>> + } else {
>
> not required as we've used kzalloc for dwc.
>
>> + dwc->usb2_generic_phy = NULL;
>> + dwc->usb3_generic_phy = NULL;
>> + }
>> +
>> /* default to superspeed if no maximum_speed passed */
>> if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
>> dwc->maximum_speed = USB_SPEED_SUPER;
>> @@ -450,6 +478,11 @@ static int dwc3_probe(struct platform_device *pdev)
>
> if (dwc->usb2_phy)
>
>> usb_phy_set_suspend(dwc->usb2_phy, 0);
>
> if (dwc->usb3_phy)
>
>> usb_phy_set_suspend(dwc->usb3_phy, 0);
>>
>> + if (dwc->usb2_generic_phy)
>> + phy_power_on(dwc->usb2_generic_phy);
>> + if (dwc->usb3_generic_phy)
>> + phy_power_on(dwc->usb3_generic_phy);
>> +
>> spin_lock_init(&dwc->lock);
>> platform_set_drvdata(pdev, dwc);
>>
>> @@ -576,6 +609,11 @@ static int dwc3_remove(struct platform_device *pdev)
>
> if (dwc->usb2_phy)
>> usb_phy_set_suspend(dwc->usb2_phy, 1);
>
> if (dwc->usb3_phy)
>> usb_phy_set_suspend(dwc->usb3_phy, 1);
>>
>> + if (dwc->usb2_generic_phy)
>> + phy_power_off(dwc->usb2_generic_phy);
>> + if (dwc->usb3_generic_phy)
>> + phy_power_off(dwc->usb3_generic_phy);
>> +
>> pm_runtime_put(&pdev->dev);
>> pm_runtime_disable(&pdev->dev);
>>
>> @@ -673,6 +711,11 @@ static int dwc3_suspend(struct device *dev)
>
> if (dwc->usb3_phy)
>> usb_phy_shutdown(dwc->usb3_phy);
>
> if (dwc->usb2_phy)
>> usb_phy_shutdown(dwc->usb2_phy);
>>
>> + if (dwc->usb2_generic_phy)
>> + phy_exit(dwc->usb2_generic_phy);
>> + if (dwc->usb3_generic_phy)
>> + phy_exit(dwc->usb3_generic_phy);
>> +
>> return 0;
>> }
>>
>> @@ -683,6 +726,12 @@ static int dwc3_resume(struct device *dev)
>>
>
> if (dwc->usb3_phy)
>> usb_phy_init(dwc->usb3_phy);
>
> if (dwc->usb2_phy)
>> usb_phy_init(dwc->usb2_phy);
>> +
>> + if (dwc->usb2_generic_phy)
>> + phy_init(dwc->usb2_generic_phy);
>> + if (dwc->usb3_generic_phy)
>> + phy_init(dwc->usb3_generic_phy);
>> +
>> msleep(100);
>>
>> spin_lock_irqsave(&dwc->lock, flags);
>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>> index f8af8d4..01ec7d7 100644
>> --- a/drivers/usb/dwc3/core.h
>> +++ b/drivers/usb/dwc3/core.h
>> @@ -31,6 +31,8 @@
>> #include <linux/usb/gadget.h>
>> #include <linux/usb/otg.h>
>>
>> +#include <linux/phy/phy.h>
>> +
>> /* Global constants */
>> #define DWC3_EP0_BOUNCE_SIZE 512
>> #define DWC3_ENDPOINTS_NUM 32
>> @@ -613,6 +615,8 @@ struct dwc3_scratchpad_array {
>> * @dr_mode: requested mode of operation
>> * @usb2_phy: pointer to USB2 PHY
>> * @usb3_phy: pointer to USB3 PHY
>> + * @usb2_generic_phy: pointer to USB2 PHY
>> + * @usb3_generic_phy: pointer to USB3 PHY
>> * @dcfg: saved contents of DCFG register
>> * @gctl: saved contents of GCTL register
>> * @is_selfpowered: true when we are selfpowered
>> @@ -665,6 +669,9 @@ struct dwc3 {
>> struct usb_phy *usb2_phy;
>> struct usb_phy *usb3_phy;
>>
>> + struct phy *usb2_generic_phy;
>> + struct phy *usb3_generic_phy;
>> +
>> void __iomem *regs;
>> size_t regs_size;
>>
>>

Do you have any suggestions on how to get only individual PHYs? like only
usb2phy or usb3phy?

Thanks
Kishon

2013-10-14 09:32:14

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 3/7] drivers: phy: usb3/pipe3: Adapt pipe3 driver to Generic PHY Framework

Kishon,

On 10/14/2013 12:19 PM, Kishon Vijay Abraham I wrote:
> Hi Roger,
>
> On Friday 11 October 2013 08:32 PM, Roger Quadros wrote:
>> On 09/16/2013 10:37 AM, Roger Quadros wrote:
>>> On 09/16/2013 06:01 AM, Kishon Vijay Abraham I wrote:
>>>> On Thursday 12 September 2013 04:49 PM, Roger Quadros wrote:
>>>>> Hi Kishon,
>>>>>
>>>>> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:

>>>>>> #ifdef CONFIG_OF
>>>>>> -static const struct of_device_id omap_usb3_id_table[] = {
>>>>>> +static const struct of_device_id omap_pipe3_id_table[] = {
>>>>>> + { .compatible = "ti,omap-pipe3" },
>>>>>
>>>>> why do you need "omap-pipe3", isn't sata, pcie and usb3 sufficient?
>>>>
>>>> I thought it would be better if everyone uses omap-pipe3 and added pcie, sata if there are any specific settings (for pcie or sata) that should be done.
>>>
>>> We can always add specialized options later when needed. AFAIK just the
>>> DPLL data is different among the different PHYs.
>>>>>
>>>>>> + { .compatible = "ti,omap-sata" },
>>>>>> + { .compatible = "ti,omap-pcie" },
>>>>>> { .compatible = "ti,omap-usb3" },
>>>
>>> I think compatible strings should be improved to indicate that it is a PHY.
>>>
>>> e.g. "ti,omap-phy-sata" or just "ti,pipe3-phy-sata"
>>>
>>
>> Please remove "ti,omap-pcie" for now, you can add it later whenever you add
>> dpll settings for pcie.
>>
>> Also, please change the newly added compatible strings to
>>
>> "ti,phy-pipe3-usb3" and "ti,phy-pipe3-sata"
>
> No, I think we should have omap in the compatible since this PHY is specific to
> OMAP.

DRA7x and an am43x are not OMAP so I was suggesting not to use it for new PHY types.
We still preserve just "ti,omap-usb3" for backward compatibility.

cheers,
-roger

2013-10-14 10:22:26

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

+Vivek

On 10/14/2013 12:26 PM, Kishon Vijay Abraham I wrote:
> Hi Roger,
>
> On Friday 11 October 2013 08:39 PM, Roger Quadros wrote:
>> Hi,
>>
>> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>>> Adapted dwc3 core to use the Generic PHY Framework. So for init, exit,
>>> power_on and power_off the following APIs are used phy_init(), phy_exit(),
>>> phy_power_on() and phy_power_off().
>>>
>>> However using the old USB phy library wont be removed till the PHYs of all
>>> other SoC's using dwc3 core is adapted to the Generic PHY Framework.
>>>
>>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>>> ---
>>> Documentation/devicetree/bindings/usb/dwc3.txt | 6 ++-
>>> drivers/usb/dwc3/Kconfig | 1 +
>>> drivers/usb/dwc3/core.c | 49 ++++++++++++++++++++++++
>>> drivers/usb/dwc3/core.h | 7 ++++
>>> 4 files changed, 61 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
>>> index e807635..471366d 100644
>>> --- a/Documentation/devicetree/bindings/usb/dwc3.txt
>>> +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
>>> @@ -6,11 +6,13 @@ Required properties:
>>> - compatible: must be "snps,dwc3"
>>> - reg : Address and length of the register set for the device
>>> - interrupts: Interrupts used by the dwc3 controller.
>>> +
>>> +Optional properties:
>>> - usb-phy : array of phandle for the PHY device. The first element
>>> in the array is expected to be a handle to the USB2/HS PHY and
>>> the second element is expected to be a handle to the USB3/SS PHY
>>> -
>>> -Optional properties:
>>> + - phys: from the *Generic PHY* bindings
>>> + - phy-names: from the *Generic PHY* bindings
>>> - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
>>>
>>> This is usually a subnode to DWC3 glue to which it is connected.
>>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>>> index cfc16dd..ad7ce83 100644
>>> --- a/drivers/usb/dwc3/Kconfig
>>> +++ b/drivers/usb/dwc3/Kconfig
>>> @@ -3,6 +3,7 @@ config USB_DWC3
>>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
>>> depends on EXTCON
>>> select USB_PHY
>>> + select GENERIC_PHY
>>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
>>> help
>>> Say Y or M here if your system has a Dual Role SuperSpeed
>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>> index 428c29e..485d365 100644
>>> --- a/drivers/usb/dwc3/core.c
>>> +++ b/drivers/usb/dwc3/core.c
>>> @@ -82,6 +82,12 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
>>>
>>> usb_phy_init(dwc->usb2_phy);
>>> usb_phy_init(dwc->usb3_phy);
>>
>> How about adding
>> + if (dwc->usb2_phy)
>> + usb_phy_init(dwc->usb2_phy);
>> + if (dwc->usb3_phy)
>> + usb_phy_init(dwc->usb3_phy);
>
> Thankfully that usb_phy_init will check if phy is NULL.
>>
>> both usb phy and generic phy shouldn't be present together.
>
> ok.
>>
>>> +
>>> + if (dwc->usb2_generic_phy)
>>> + phy_init(dwc->usb2_generic_phy);
>>> + if (dwc->usb3_generic_phy)
>>> + phy_init(dwc->usb3_generic_phy);
>>> +
>>> mdelay(100);
>>>
>>> /* Clear USB3 PHY reset */
>>> @@ -343,6 +349,11 @@ static void dwc3_core_exit(struct dwc3 *dwc)
>>> {
>>> usb_phy_shutdown(dwc->usb2_phy);
>>> usb_phy_shutdown(dwc->usb3_phy);
>>
>> here as well
>>
>>> +
>>> + if (dwc->usb2_generic_phy)
>>> + phy_power_off(dwc->usb2_generic_phy);
>>> + if (dwc->usb3_generic_phy)
>>> + phy_power_off(dwc->usb3_generic_phy);
>>> }
>>>
>>> #define DWC3_ALIGN_MASK (16 - 1)
>>> @@ -427,6 +438,23 @@ static int dwc3_probe(struct platform_device *pdev)
>>> dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
>>> }
>>>
>>> + if (of_property_read_bool(node, "phys") || pdata->has_phy) {
>>> + dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
>>> + if (IS_ERR(dwc->usb2_generic_phy)) {
>>> + dev_err(dev, "no usb2 phy configured yet");
>>> + return PTR_ERR(dwc->usb2_generic_phy);
>>> + }
>>> +
>>> + dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
>>> + if (IS_ERR(dwc->usb3_generic_phy)) {
>>> + dev_err(dev, "no usb3 phy configured yet");
>>> + return PTR_ERR(dwc->usb3_generic_phy);
>>> + }
>>
>> better to add
>> + /* Don't use USB PHY if generic PHY was found */
>> + dwc->usb2_phy = dwc->usb3_phy = NULL;
>
> ok.
>>
>>> + } else {
>>
>> not required as we've used kzalloc for dwc.
>>
>>> + dwc->usb2_generic_phy = NULL;
>>> + dwc->usb3_generic_phy = NULL;
>>> + }
>>> +
>>> /* default to superspeed if no maximum_speed passed */
>>> if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
>>> dwc->maximum_speed = USB_SPEED_SUPER;
>>> @@ -450,6 +478,11 @@ static int dwc3_probe(struct platform_device *pdev)
>>
>> if (dwc->usb2_phy)
>>
>>> usb_phy_set_suspend(dwc->usb2_phy, 0);
>>
>> if (dwc->usb3_phy)
>>
>>> usb_phy_set_suspend(dwc->usb3_phy, 0);
>>>
>>> + if (dwc->usb2_generic_phy)
>>> + phy_power_on(dwc->usb2_generic_phy);
>>> + if (dwc->usb3_generic_phy)
>>> + phy_power_on(dwc->usb3_generic_phy);
>>> +
>>> spin_lock_init(&dwc->lock);
>>> platform_set_drvdata(pdev, dwc);
>>>
>>> @@ -576,6 +609,11 @@ static int dwc3_remove(struct platform_device *pdev)
>>
>> if (dwc->usb2_phy)
>>> usb_phy_set_suspend(dwc->usb2_phy, 1);
>>
>> if (dwc->usb3_phy)
>>> usb_phy_set_suspend(dwc->usb3_phy, 1);
>>>
>>> + if (dwc->usb2_generic_phy)
>>> + phy_power_off(dwc->usb2_generic_phy);
>>> + if (dwc->usb3_generic_phy)
>>> + phy_power_off(dwc->usb3_generic_phy);
>>> +
>>> pm_runtime_put(&pdev->dev);
>>> pm_runtime_disable(&pdev->dev);
>>>
>>> @@ -673,6 +711,11 @@ static int dwc3_suspend(struct device *dev)
>>
>> if (dwc->usb3_phy)
>>> usb_phy_shutdown(dwc->usb3_phy);
>>
>> if (dwc->usb2_phy)
>>> usb_phy_shutdown(dwc->usb2_phy);
>>>
>>> + if (dwc->usb2_generic_phy)
>>> + phy_exit(dwc->usb2_generic_phy);
>>> + if (dwc->usb3_generic_phy)
>>> + phy_exit(dwc->usb3_generic_phy);
>>> +
>>> return 0;
>>> }
>>>
>>> @@ -683,6 +726,12 @@ static int dwc3_resume(struct device *dev)
>>>
>>
>> if (dwc->usb3_phy)
>>> usb_phy_init(dwc->usb3_phy);
>>
>> if (dwc->usb2_phy)
>>> usb_phy_init(dwc->usb2_phy);
>>> +
>>> + if (dwc->usb2_generic_phy)
>>> + phy_init(dwc->usb2_generic_phy);
>>> + if (dwc->usb3_generic_phy)
>>> + phy_init(dwc->usb3_generic_phy);
>>> +
>>> msleep(100);
>>>
>>> spin_lock_irqsave(&dwc->lock, flags);
>>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>>> index f8af8d4..01ec7d7 100644
>>> --- a/drivers/usb/dwc3/core.h
>>> +++ b/drivers/usb/dwc3/core.h
>>> @@ -31,6 +31,8 @@
>>> #include <linux/usb/gadget.h>
>>> #include <linux/usb/otg.h>
>>>
>>> +#include <linux/phy/phy.h>
>>> +
>>> /* Global constants */
>>> #define DWC3_EP0_BOUNCE_SIZE 512
>>> #define DWC3_ENDPOINTS_NUM 32
>>> @@ -613,6 +615,8 @@ struct dwc3_scratchpad_array {
>>> * @dr_mode: requested mode of operation
>>> * @usb2_phy: pointer to USB2 PHY
>>> * @usb3_phy: pointer to USB3 PHY
>>> + * @usb2_generic_phy: pointer to USB2 PHY
>>> + * @usb3_generic_phy: pointer to USB3 PHY
>>> * @dcfg: saved contents of DCFG register
>>> * @gctl: saved contents of GCTL register
>>> * @is_selfpowered: true when we are selfpowered
>>> @@ -665,6 +669,9 @@ struct dwc3 {
>>> struct usb_phy *usb2_phy;
>>> struct usb_phy *usb3_phy;
>>>
>>> + struct phy *usb2_generic_phy;
>>> + struct phy *usb3_generic_phy;
>>> +
>>> void __iomem *regs;
>>> size_t regs_size;
>>>
>>>
>
> Do you have any suggestions on how to get only individual PHYs? like only
> usb2phy or usb3phy?

My earlier understanding was that both PHYs are needed only if .speed is "super-speed"
and only usb2phy is needed for "high-speed". But as per Vivek's email it seems
Samsung's exynos5 SoC doesn't need usb2phy for "super-speed".

So to keeps things flexible, I can propose the following approach
- if speed == 'high-speed' usb2phy must be present. usb3phy will be ignored if supplied.
- if speed == 'super-speed' usb3phy must be present and usb2phy is optional but must be
initialized if supplied.
- if speed is not specified, we default to 'super-speed'.

Felipe, does this address the issue you were facing with OMAP5?

cheers,
-roger

2013-10-15 05:32:23

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

Hi Roger,

On Monday 14 October 2013 03:51 PM, Roger Quadros wrote:
> +Vivek
>
> On 10/14/2013 12:26 PM, Kishon Vijay Abraham I wrote:
>> Hi Roger,
>>
>> On Friday 11 October 2013 08:39 PM, Roger Quadros wrote:
>>> Hi,
>>>
>>> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>>>> Adapted dwc3 core to use the Generic PHY Framework. So for init, exit,
>>>> power_on and power_off the following APIs are used phy_init(), phy_exit(),
>>>> phy_power_on() and phy_power_off().
>>>>
>>>> However using the old USB phy library wont be removed till the PHYs of all
>>>> other SoC's using dwc3 core is adapted to the Generic PHY Framework.
>>>>
>>>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>>>> ---
>>>> Documentation/devicetree/bindings/usb/dwc3.txt | 6 ++-
>>>> drivers/usb/dwc3/Kconfig | 1 +
>>>> drivers/usb/dwc3/core.c | 49 ++++++++++++++++++++++++
>>>> drivers/usb/dwc3/core.h | 7 ++++
>>>> 4 files changed, 61 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
>>>> index e807635..471366d 100644
>>>> --- a/Documentation/devicetree/bindings/usb/dwc3.txt
>>>> +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
>>>> @@ -6,11 +6,13 @@ Required properties:
>>>> - compatible: must be "snps,dwc3"
>>>> - reg : Address and length of the register set for the device
>>>> - interrupts: Interrupts used by the dwc3 controller.
>>>> +
>>>> +Optional properties:
>>>> - usb-phy : array of phandle for the PHY device. The first element
>>>> in the array is expected to be a handle to the USB2/HS PHY and
>>>> the second element is expected to be a handle to the USB3/SS PHY
>>>> -
>>>> -Optional properties:
>>>> + - phys: from the *Generic PHY* bindings
>>>> + - phy-names: from the *Generic PHY* bindings
>>>> - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
>>>>
>>>> This is usually a subnode to DWC3 glue to which it is connected.
>>>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>>>> index cfc16dd..ad7ce83 100644
>>>> --- a/drivers/usb/dwc3/Kconfig
>>>> +++ b/drivers/usb/dwc3/Kconfig
>>>> @@ -3,6 +3,7 @@ config USB_DWC3
>>>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
>>>> depends on EXTCON
>>>> select USB_PHY
>>>> + select GENERIC_PHY
>>>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
>>>> help
>>>> Say Y or M here if your system has a Dual Role SuperSpeed
>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>>> index 428c29e..485d365 100644
>>>> --- a/drivers/usb/dwc3/core.c
>>>> +++ b/drivers/usb/dwc3/core.c
>>>> @@ -82,6 +82,12 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
>>>>
>>>> usb_phy_init(dwc->usb2_phy);
>>>> usb_phy_init(dwc->usb3_phy);
>>>
>>> How about adding
>>> + if (dwc->usb2_phy)
>>> + usb_phy_init(dwc->usb2_phy);
>>> + if (dwc->usb3_phy)
>>> + usb_phy_init(dwc->usb3_phy);
>>
>> Thankfully that usb_phy_init will check if phy is NULL.
>>>
>>> both usb phy and generic phy shouldn't be present together.
>>
>> ok.
>>>
>>>> +
>>>> + if (dwc->usb2_generic_phy)
>>>> + phy_init(dwc->usb2_generic_phy);
>>>> + if (dwc->usb3_generic_phy)
>>>> + phy_init(dwc->usb3_generic_phy);
>>>> +
>>>> mdelay(100);
>>>>
>>>> /* Clear USB3 PHY reset */
>>>> @@ -343,6 +349,11 @@ static void dwc3_core_exit(struct dwc3 *dwc)
>>>> {
>>>> usb_phy_shutdown(dwc->usb2_phy);
>>>> usb_phy_shutdown(dwc->usb3_phy);
>>>
>>> here as well
>>>
>>>> +
>>>> + if (dwc->usb2_generic_phy)
>>>> + phy_power_off(dwc->usb2_generic_phy);
>>>> + if (dwc->usb3_generic_phy)
>>>> + phy_power_off(dwc->usb3_generic_phy);
>>>> }
>>>>
>>>> #define DWC3_ALIGN_MASK (16 - 1)
>>>> @@ -427,6 +438,23 @@ static int dwc3_probe(struct platform_device *pdev)
>>>> dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
>>>> }
>>>>
>>>> + if (of_property_read_bool(node, "phys") || pdata->has_phy) {
>>>> + dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
>>>> + if (IS_ERR(dwc->usb2_generic_phy)) {
>>>> + dev_err(dev, "no usb2 phy configured yet");
>>>> + return PTR_ERR(dwc->usb2_generic_phy);
>>>> + }
>>>> +
>>>> + dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
>>>> + if (IS_ERR(dwc->usb3_generic_phy)) {
>>>> + dev_err(dev, "no usb3 phy configured yet");
>>>> + return PTR_ERR(dwc->usb3_generic_phy);
>>>> + }
>>>
>>> better to add
>>> + /* Don't use USB PHY if generic PHY was found */
>>> + dwc->usb2_phy = dwc->usb3_phy = NULL;
>>
>> ok.
>>>
>>>> + } else {
>>>
>>> not required as we've used kzalloc for dwc.
>>>
>>>> + dwc->usb2_generic_phy = NULL;
>>>> + dwc->usb3_generic_phy = NULL;
>>>> + }
>>>> +
>>>> /* default to superspeed if no maximum_speed passed */
>>>> if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
>>>> dwc->maximum_speed = USB_SPEED_SUPER;
>>>> @@ -450,6 +478,11 @@ static int dwc3_probe(struct platform_device *pdev)
>>>
>>> if (dwc->usb2_phy)
>>>
>>>> usb_phy_set_suspend(dwc->usb2_phy, 0);
>>>
>>> if (dwc->usb3_phy)
>>>
>>>> usb_phy_set_suspend(dwc->usb3_phy, 0);
>>>>
>>>> + if (dwc->usb2_generic_phy)
>>>> + phy_power_on(dwc->usb2_generic_phy);
>>>> + if (dwc->usb3_generic_phy)
>>>> + phy_power_on(dwc->usb3_generic_phy);
>>>> +
>>>> spin_lock_init(&dwc->lock);
>>>> platform_set_drvdata(pdev, dwc);
>>>>
>>>> @@ -576,6 +609,11 @@ static int dwc3_remove(struct platform_device *pdev)
>>>
>>> if (dwc->usb2_phy)
>>>> usb_phy_set_suspend(dwc->usb2_phy, 1);
>>>
>>> if (dwc->usb3_phy)
>>>> usb_phy_set_suspend(dwc->usb3_phy, 1);
>>>>
>>>> + if (dwc->usb2_generic_phy)
>>>> + phy_power_off(dwc->usb2_generic_phy);
>>>> + if (dwc->usb3_generic_phy)
>>>> + phy_power_off(dwc->usb3_generic_phy);
>>>> +
>>>> pm_runtime_put(&pdev->dev);
>>>> pm_runtime_disable(&pdev->dev);
>>>>
>>>> @@ -673,6 +711,11 @@ static int dwc3_suspend(struct device *dev)
>>>
>>> if (dwc->usb3_phy)
>>>> usb_phy_shutdown(dwc->usb3_phy);
>>>
>>> if (dwc->usb2_phy)
>>>> usb_phy_shutdown(dwc->usb2_phy);
>>>>
>>>> + if (dwc->usb2_generic_phy)
>>>> + phy_exit(dwc->usb2_generic_phy);
>>>> + if (dwc->usb3_generic_phy)
>>>> + phy_exit(dwc->usb3_generic_phy);
>>>> +
>>>> return 0;
>>>> }
>>>>
>>>> @@ -683,6 +726,12 @@ static int dwc3_resume(struct device *dev)
>>>>
>>>
>>> if (dwc->usb3_phy)
>>>> usb_phy_init(dwc->usb3_phy);
>>>
>>> if (dwc->usb2_phy)
>>>> usb_phy_init(dwc->usb2_phy);
>>>> +
>>>> + if (dwc->usb2_generic_phy)
>>>> + phy_init(dwc->usb2_generic_phy);
>>>> + if (dwc->usb3_generic_phy)
>>>> + phy_init(dwc->usb3_generic_phy);
>>>> +
>>>> msleep(100);
>>>>
>>>> spin_lock_irqsave(&dwc->lock, flags);
>>>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>>>> index f8af8d4..01ec7d7 100644
>>>> --- a/drivers/usb/dwc3/core.h
>>>> +++ b/drivers/usb/dwc3/core.h
>>>> @@ -31,6 +31,8 @@
>>>> #include <linux/usb/gadget.h>
>>>> #include <linux/usb/otg.h>
>>>>
>>>> +#include <linux/phy/phy.h>
>>>> +
>>>> /* Global constants */
>>>> #define DWC3_EP0_BOUNCE_SIZE 512
>>>> #define DWC3_ENDPOINTS_NUM 32
>>>> @@ -613,6 +615,8 @@ struct dwc3_scratchpad_array {
>>>> * @dr_mode: requested mode of operation
>>>> * @usb2_phy: pointer to USB2 PHY
>>>> * @usb3_phy: pointer to USB3 PHY
>>>> + * @usb2_generic_phy: pointer to USB2 PHY
>>>> + * @usb3_generic_phy: pointer to USB3 PHY
>>>> * @dcfg: saved contents of DCFG register
>>>> * @gctl: saved contents of GCTL register
>>>> * @is_selfpowered: true when we are selfpowered
>>>> @@ -665,6 +669,9 @@ struct dwc3 {
>>>> struct usb_phy *usb2_phy;
>>>> struct usb_phy *usb3_phy;
>>>>
>>>> + struct phy *usb2_generic_phy;
>>>> + struct phy *usb3_generic_phy;
>>>> +
>>>> void __iomem *regs;
>>>> size_t regs_size;
>>>>
>>>>
>>
>> Do you have any suggestions on how to get only individual PHYs? like only
>> usb2phy or usb3phy?
>
> My earlier understanding was that both PHYs are needed only if .speed is "super-speed"
> and only usb2phy is needed for "high-speed". But as per Vivek's email it seems
> Samsung's exynos5 SoC doesn't need usb2phy for "super-speed".
>
> So to keeps things flexible, I can propose the following approach
> - if speed == 'high-speed' usb2phy must be present. usb3phy will be ignored if supplied.
> - if speed == 'super-speed' usb3phy must be present and usb2phy is optional but must be
> initialized if supplied.
> - if speed is not specified, we default to 'super-speed'.
>
> Felipe, does this address the issue you were facing with OMAP5?

IIRC, even if the speed is high speed, you still need to power on the USB3 PHY.
Or else even high speed mode wasn't working in OMAP5.

Thanks
Kishon

2013-10-15 07:58:08

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

On 10/15/2013 08:31 AM, Kishon Vijay Abraham I wrote:
> Hi Roger,
>
> On Monday 14 October 2013 03:51 PM, Roger Quadros wrote:
>> +Vivek
>>
>> On 10/14/2013 12:26 PM, Kishon Vijay Abraham I wrote:
>>> Hi Roger,
>>>
>>> On Friday 11 October 2013 08:39 PM, Roger Quadros wrote:
>>>> Hi,
>>>>
>>>> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>>>>> Adapted dwc3 core to use the Generic PHY Framework. So for init, exit,
>>>>> power_on and power_off the following APIs are used phy_init(), phy_exit(),
>>>>> phy_power_on() and phy_power_off().
>>>>>
>>>>> However using the old USB phy library wont be removed till the PHYs of all
>>>>> other SoC's using dwc3 core is adapted to the Generic PHY Framework.
>>>>>
>>>>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>>>>> ---
>>>>> Documentation/devicetree/bindings/usb/dwc3.txt | 6 ++-
>>>>> drivers/usb/dwc3/Kconfig | 1 +
>>>>> drivers/usb/dwc3/core.c | 49 ++++++++++++++++++++++++
>>>>> drivers/usb/dwc3/core.h | 7 ++++
>>>>> 4 files changed, 61 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
>>>>> index e807635..471366d 100644
>>>>> --- a/Documentation/devicetree/bindings/usb/dwc3.txt
>>>>> +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
>>>>> @@ -6,11 +6,13 @@ Required properties:
>>>>> - compatible: must be "snps,dwc3"
>>>>> - reg : Address and length of the register set for the device
>>>>> - interrupts: Interrupts used by the dwc3 controller.
>>>>> +
>>>>> +Optional properties:
>>>>> - usb-phy : array of phandle for the PHY device. The first element
>>>>> in the array is expected to be a handle to the USB2/HS PHY and
>>>>> the second element is expected to be a handle to the USB3/SS PHY
>>>>> -
>>>>> -Optional properties:
>>>>> + - phys: from the *Generic PHY* bindings
>>>>> + - phy-names: from the *Generic PHY* bindings
>>>>> - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
>>>>>
>>>>> This is usually a subnode to DWC3 glue to which it is connected.
>>>>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>>>>> index cfc16dd..ad7ce83 100644
>>>>> --- a/drivers/usb/dwc3/Kconfig
>>>>> +++ b/drivers/usb/dwc3/Kconfig
>>>>> @@ -3,6 +3,7 @@ config USB_DWC3
>>>>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
>>>>> depends on EXTCON
>>>>> select USB_PHY
>>>>> + select GENERIC_PHY
>>>>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
>>>>> help
>>>>> Say Y or M here if your system has a Dual Role SuperSpeed
>>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>>>> index 428c29e..485d365 100644
>>>>> --- a/drivers/usb/dwc3/core.c
>>>>> +++ b/drivers/usb/dwc3/core.c
>>>>> @@ -82,6 +82,12 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
>>>>>
>>>>> usb_phy_init(dwc->usb2_phy);
>>>>> usb_phy_init(dwc->usb3_phy);
>>>>
>>>> How about adding
>>>> + if (dwc->usb2_phy)
>>>> + usb_phy_init(dwc->usb2_phy);
>>>> + if (dwc->usb3_phy)
>>>> + usb_phy_init(dwc->usb3_phy);
>>>
>>> Thankfully that usb_phy_init will check if phy is NULL.
>>>>
>>>> both usb phy and generic phy shouldn't be present together.
>>>
>>> ok.
>>>>
>>>>> +
>>>>> + if (dwc->usb2_generic_phy)
>>>>> + phy_init(dwc->usb2_generic_phy);
>>>>> + if (dwc->usb3_generic_phy)
>>>>> + phy_init(dwc->usb3_generic_phy);
>>>>> +
>>>>> mdelay(100);
>>>>>
>>>>> /* Clear USB3 PHY reset */
>>>>> @@ -343,6 +349,11 @@ static void dwc3_core_exit(struct dwc3 *dwc)
>>>>> {
>>>>> usb_phy_shutdown(dwc->usb2_phy);
>>>>> usb_phy_shutdown(dwc->usb3_phy);
>>>>
>>>> here as well
>>>>
>>>>> +
>>>>> + if (dwc->usb2_generic_phy)
>>>>> + phy_power_off(dwc->usb2_generic_phy);
>>>>> + if (dwc->usb3_generic_phy)
>>>>> + phy_power_off(dwc->usb3_generic_phy);
>>>>> }
>>>>>
>>>>> #define DWC3_ALIGN_MASK (16 - 1)
>>>>> @@ -427,6 +438,23 @@ static int dwc3_probe(struct platform_device *pdev)
>>>>> dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
>>>>> }
>>>>>
>>>>> + if (of_property_read_bool(node, "phys") || pdata->has_phy) {
>>>>> + dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
>>>>> + if (IS_ERR(dwc->usb2_generic_phy)) {
>>>>> + dev_err(dev, "no usb2 phy configured yet");
>>>>> + return PTR_ERR(dwc->usb2_generic_phy);
>>>>> + }
>>>>> +
>>>>> + dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
>>>>> + if (IS_ERR(dwc->usb3_generic_phy)) {
>>>>> + dev_err(dev, "no usb3 phy configured yet");
>>>>> + return PTR_ERR(dwc->usb3_generic_phy);
>>>>> + }
>>>>
>>>> better to add
>>>> + /* Don't use USB PHY if generic PHY was found */
>>>> + dwc->usb2_phy = dwc->usb3_phy = NULL;
>>>
>>> ok.
>>>>
>>>>> + } else {
>>>>
>>>> not required as we've used kzalloc for dwc.
>>>>
>>>>> + dwc->usb2_generic_phy = NULL;
>>>>> + dwc->usb3_generic_phy = NULL;
>>>>> + }
>>>>> +
>>>>> /* default to superspeed if no maximum_speed passed */
>>>>> if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
>>>>> dwc->maximum_speed = USB_SPEED_SUPER;
>>>>> @@ -450,6 +478,11 @@ static int dwc3_probe(struct platform_device *pdev)
>>>>
>>>> if (dwc->usb2_phy)
>>>>
>>>>> usb_phy_set_suspend(dwc->usb2_phy, 0);
>>>>
>>>> if (dwc->usb3_phy)
>>>>
>>>>> usb_phy_set_suspend(dwc->usb3_phy, 0);
>>>>>
>>>>> + if (dwc->usb2_generic_phy)
>>>>> + phy_power_on(dwc->usb2_generic_phy);
>>>>> + if (dwc->usb3_generic_phy)
>>>>> + phy_power_on(dwc->usb3_generic_phy);
>>>>> +
>>>>> spin_lock_init(&dwc->lock);
>>>>> platform_set_drvdata(pdev, dwc);
>>>>>
>>>>> @@ -576,6 +609,11 @@ static int dwc3_remove(struct platform_device *pdev)
>>>>
>>>> if (dwc->usb2_phy)
>>>>> usb_phy_set_suspend(dwc->usb2_phy, 1);
>>>>
>>>> if (dwc->usb3_phy)
>>>>> usb_phy_set_suspend(dwc->usb3_phy, 1);
>>>>>
>>>>> + if (dwc->usb2_generic_phy)
>>>>> + phy_power_off(dwc->usb2_generic_phy);
>>>>> + if (dwc->usb3_generic_phy)
>>>>> + phy_power_off(dwc->usb3_generic_phy);
>>>>> +
>>>>> pm_runtime_put(&pdev->dev);
>>>>> pm_runtime_disable(&pdev->dev);
>>>>>
>>>>> @@ -673,6 +711,11 @@ static int dwc3_suspend(struct device *dev)
>>>>
>>>> if (dwc->usb3_phy)
>>>>> usb_phy_shutdown(dwc->usb3_phy);
>>>>
>>>> if (dwc->usb2_phy)
>>>>> usb_phy_shutdown(dwc->usb2_phy);
>>>>>
>>>>> + if (dwc->usb2_generic_phy)
>>>>> + phy_exit(dwc->usb2_generic_phy);
>>>>> + if (dwc->usb3_generic_phy)
>>>>> + phy_exit(dwc->usb3_generic_phy);
>>>>> +
>>>>> return 0;
>>>>> }
>>>>>
>>>>> @@ -683,6 +726,12 @@ static int dwc3_resume(struct device *dev)
>>>>>
>>>>
>>>> if (dwc->usb3_phy)
>>>>> usb_phy_init(dwc->usb3_phy);
>>>>
>>>> if (dwc->usb2_phy)
>>>>> usb_phy_init(dwc->usb2_phy);
>>>>> +
>>>>> + if (dwc->usb2_generic_phy)
>>>>> + phy_init(dwc->usb2_generic_phy);
>>>>> + if (dwc->usb3_generic_phy)
>>>>> + phy_init(dwc->usb3_generic_phy);
>>>>> +
>>>>> msleep(100);
>>>>>
>>>>> spin_lock_irqsave(&dwc->lock, flags);
>>>>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>>>>> index f8af8d4..01ec7d7 100644
>>>>> --- a/drivers/usb/dwc3/core.h
>>>>> +++ b/drivers/usb/dwc3/core.h
>>>>> @@ -31,6 +31,8 @@
>>>>> #include <linux/usb/gadget.h>
>>>>> #include <linux/usb/otg.h>
>>>>>
>>>>> +#include <linux/phy/phy.h>
>>>>> +
>>>>> /* Global constants */
>>>>> #define DWC3_EP0_BOUNCE_SIZE 512
>>>>> #define DWC3_ENDPOINTS_NUM 32
>>>>> @@ -613,6 +615,8 @@ struct dwc3_scratchpad_array {
>>>>> * @dr_mode: requested mode of operation
>>>>> * @usb2_phy: pointer to USB2 PHY
>>>>> * @usb3_phy: pointer to USB3 PHY
>>>>> + * @usb2_generic_phy: pointer to USB2 PHY
>>>>> + * @usb3_generic_phy: pointer to USB3 PHY
>>>>> * @dcfg: saved contents of DCFG register
>>>>> * @gctl: saved contents of GCTL register
>>>>> * @is_selfpowered: true when we are selfpowered
>>>>> @@ -665,6 +669,9 @@ struct dwc3 {
>>>>> struct usb_phy *usb2_phy;
>>>>> struct usb_phy *usb3_phy;
>>>>>
>>>>> + struct phy *usb2_generic_phy;
>>>>> + struct phy *usb3_generic_phy;
>>>>> +
>>>>> void __iomem *regs;
>>>>> size_t regs_size;
>>>>>
>>>>>
>>>
>>> Do you have any suggestions on how to get only individual PHYs? like only
>>> usb2phy or usb3phy?
>>
>> My earlier understanding was that both PHYs are needed only if .speed is "super-speed"
>> and only usb2phy is needed for "high-speed". But as per Vivek's email it seems
>> Samsung's exynos5 SoC doesn't need usb2phy for "super-speed".
>>
>> So to keeps things flexible, I can propose the following approach
>> - if speed == 'high-speed' usb2phy must be present. usb3phy will be ignored if supplied.
>> - if speed == 'super-speed' usb3phy must be present and usb2phy is optional but must be
>> initialized if supplied.
>> - if speed is not specified, we default to 'super-speed'.
>>
>> Felipe, does this address the issue you were facing with OMAP5?
>
> IIRC, even if the speed is high speed, you still need to power on the USB3 PHY.
> Or else even high speed mode wasn't working in OMAP5.

Maybe for OMAP5 we can somehow indicate to dwc3 core code that only 'super-speed' mode
is supported by the platform. I'm not aware of any OMAP5 platform using the USB port as 'high-speed'.

So there needs to be some mechanism for dwc3-<platform>.c to indicate to dwc3-core.c the
speeds supported by the platform. e.g. via of_dev_auxdata through of_platform_populate()?

If such data is not supplied, we assume that both speeds are supported.

cheers,
-roger

2013-10-15 11:59:18

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

On Tue, Oct 15, 2013 at 11:01:16AM +0530, Kishon Vijay Abraham I wrote:
> Hi Roger,
>
> On Monday 14 October 2013 03:51 PM, Roger Quadros wrote:
> > +Vivek
> >
> > On 10/14/2013 12:26 PM, Kishon Vijay Abraham I wrote:
> >> Hi Roger,
> >>
> >> On Friday 11 October 2013 08:39 PM, Roger Quadros wrote:
> >>> Hi,
> >>>
> >>> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
> >>>> Adapted dwc3 core to use the Generic PHY Framework. So for init, exit,
> >>>> power_on and power_off the following APIs are used phy_init(), phy_exit(),
> >>>> phy_power_on() and phy_power_off().
> >>>>
> >>>> However using the old USB phy library wont be removed till the PHYs of all
> >>>> other SoC's using dwc3 core is adapted to the Generic PHY Framework.
> >>>>
> >>>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
> >>>> ---
> >>>> Documentation/devicetree/bindings/usb/dwc3.txt | 6 ++-
> >>>> drivers/usb/dwc3/Kconfig | 1 +
> >>>> drivers/usb/dwc3/core.c | 49 ++++++++++++++++++++++++
> >>>> drivers/usb/dwc3/core.h | 7 ++++
> >>>> 4 files changed, 61 insertions(+), 2 deletions(-)
> >>>>
> >>>> diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
> >>>> index e807635..471366d 100644
> >>>> --- a/Documentation/devicetree/bindings/usb/dwc3.txt
> >>>> +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
> >>>> @@ -6,11 +6,13 @@ Required properties:
> >>>> - compatible: must be "snps,dwc3"
> >>>> - reg : Address and length of the register set for the device
> >>>> - interrupts: Interrupts used by the dwc3 controller.
> >>>> +
> >>>> +Optional properties:
> >>>> - usb-phy : array of phandle for the PHY device. The first element
> >>>> in the array is expected to be a handle to the USB2/HS PHY and
> >>>> the second element is expected to be a handle to the USB3/SS PHY
> >>>> -
> >>>> -Optional properties:
> >>>> + - phys: from the *Generic PHY* bindings
> >>>> + - phy-names: from the *Generic PHY* bindings
> >>>> - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
> >>>>
> >>>> This is usually a subnode to DWC3 glue to which it is connected.
> >>>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
> >>>> index cfc16dd..ad7ce83 100644
> >>>> --- a/drivers/usb/dwc3/Kconfig
> >>>> +++ b/drivers/usb/dwc3/Kconfig
> >>>> @@ -3,6 +3,7 @@ config USB_DWC3
> >>>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
> >>>> depends on EXTCON
> >>>> select USB_PHY
> >>>> + select GENERIC_PHY
> >>>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
> >>>> help
> >>>> Say Y or M here if your system has a Dual Role SuperSpeed
> >>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> >>>> index 428c29e..485d365 100644
> >>>> --- a/drivers/usb/dwc3/core.c
> >>>> +++ b/drivers/usb/dwc3/core.c
> >>>> @@ -82,6 +82,12 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
> >>>>
> >>>> usb_phy_init(dwc->usb2_phy);
> >>>> usb_phy_init(dwc->usb3_phy);
> >>>
> >>> How about adding
> >>> + if (dwc->usb2_phy)
> >>> + usb_phy_init(dwc->usb2_phy);
> >>> + if (dwc->usb3_phy)
> >>> + usb_phy_init(dwc->usb3_phy);
> >>
> >> Thankfully that usb_phy_init will check if phy is NULL.
> >>>
> >>> both usb phy and generic phy shouldn't be present together.
> >>
> >> ok.
> >>>
> >>>> +
> >>>> + if (dwc->usb2_generic_phy)
> >>>> + phy_init(dwc->usb2_generic_phy);
> >>>> + if (dwc->usb3_generic_phy)
> >>>> + phy_init(dwc->usb3_generic_phy);
> >>>> +
> >>>> mdelay(100);
> >>>>
> >>>> /* Clear USB3 PHY reset */
> >>>> @@ -343,6 +349,11 @@ static void dwc3_core_exit(struct dwc3 *dwc)
> >>>> {
> >>>> usb_phy_shutdown(dwc->usb2_phy);
> >>>> usb_phy_shutdown(dwc->usb3_phy);
> >>>
> >>> here as well
> >>>
> >>>> +
> >>>> + if (dwc->usb2_generic_phy)
> >>>> + phy_power_off(dwc->usb2_generic_phy);
> >>>> + if (dwc->usb3_generic_phy)
> >>>> + phy_power_off(dwc->usb3_generic_phy);
> >>>> }
> >>>>
> >>>> #define DWC3_ALIGN_MASK (16 - 1)
> >>>> @@ -427,6 +438,23 @@ static int dwc3_probe(struct platform_device *pdev)
> >>>> dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
> >>>> }
> >>>>
> >>>> + if (of_property_read_bool(node, "phys") || pdata->has_phy) {
> >>>> + dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
> >>>> + if (IS_ERR(dwc->usb2_generic_phy)) {
> >>>> + dev_err(dev, "no usb2 phy configured yet");
> >>>> + return PTR_ERR(dwc->usb2_generic_phy);
> >>>> + }
> >>>> +
> >>>> + dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
> >>>> + if (IS_ERR(dwc->usb3_generic_phy)) {
> >>>> + dev_err(dev, "no usb3 phy configured yet");
> >>>> + return PTR_ERR(dwc->usb3_generic_phy);
> >>>> + }
> >>>
> >>> better to add
> >>> + /* Don't use USB PHY if generic PHY was found */
> >>> + dwc->usb2_phy = dwc->usb3_phy = NULL;
> >>
> >> ok.
> >>>
> >>>> + } else {
> >>>
> >>> not required as we've used kzalloc for dwc.
> >>>
> >>>> + dwc->usb2_generic_phy = NULL;
> >>>> + dwc->usb3_generic_phy = NULL;
> >>>> + }
> >>>> +
> >>>> /* default to superspeed if no maximum_speed passed */
> >>>> if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
> >>>> dwc->maximum_speed = USB_SPEED_SUPER;
> >>>> @@ -450,6 +478,11 @@ static int dwc3_probe(struct platform_device *pdev)
> >>>
> >>> if (dwc->usb2_phy)
> >>>
> >>>> usb_phy_set_suspend(dwc->usb2_phy, 0);
> >>>
> >>> if (dwc->usb3_phy)
> >>>
> >>>> usb_phy_set_suspend(dwc->usb3_phy, 0);
> >>>>
> >>>> + if (dwc->usb2_generic_phy)
> >>>> + phy_power_on(dwc->usb2_generic_phy);
> >>>> + if (dwc->usb3_generic_phy)
> >>>> + phy_power_on(dwc->usb3_generic_phy);
> >>>> +
> >>>> spin_lock_init(&dwc->lock);
> >>>> platform_set_drvdata(pdev, dwc);
> >>>>
> >>>> @@ -576,6 +609,11 @@ static int dwc3_remove(struct platform_device *pdev)
> >>>
> >>> if (dwc->usb2_phy)
> >>>> usb_phy_set_suspend(dwc->usb2_phy, 1);
> >>>
> >>> if (dwc->usb3_phy)
> >>>> usb_phy_set_suspend(dwc->usb3_phy, 1);
> >>>>
> >>>> + if (dwc->usb2_generic_phy)
> >>>> + phy_power_off(dwc->usb2_generic_phy);
> >>>> + if (dwc->usb3_generic_phy)
> >>>> + phy_power_off(dwc->usb3_generic_phy);
> >>>> +
> >>>> pm_runtime_put(&pdev->dev);
> >>>> pm_runtime_disable(&pdev->dev);
> >>>>
> >>>> @@ -673,6 +711,11 @@ static int dwc3_suspend(struct device *dev)
> >>>
> >>> if (dwc->usb3_phy)
> >>>> usb_phy_shutdown(dwc->usb3_phy);
> >>>
> >>> if (dwc->usb2_phy)
> >>>> usb_phy_shutdown(dwc->usb2_phy);
> >>>>
> >>>> + if (dwc->usb2_generic_phy)
> >>>> + phy_exit(dwc->usb2_generic_phy);
> >>>> + if (dwc->usb3_generic_phy)
> >>>> + phy_exit(dwc->usb3_generic_phy);
> >>>> +
> >>>> return 0;
> >>>> }
> >>>>
> >>>> @@ -683,6 +726,12 @@ static int dwc3_resume(struct device *dev)
> >>>>
> >>>
> >>> if (dwc->usb3_phy)
> >>>> usb_phy_init(dwc->usb3_phy);
> >>>
> >>> if (dwc->usb2_phy)
> >>>> usb_phy_init(dwc->usb2_phy);
> >>>> +
> >>>> + if (dwc->usb2_generic_phy)
> >>>> + phy_init(dwc->usb2_generic_phy);
> >>>> + if (dwc->usb3_generic_phy)
> >>>> + phy_init(dwc->usb3_generic_phy);
> >>>> +
> >>>> msleep(100);
> >>>>
> >>>> spin_lock_irqsave(&dwc->lock, flags);
> >>>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> >>>> index f8af8d4..01ec7d7 100644
> >>>> --- a/drivers/usb/dwc3/core.h
> >>>> +++ b/drivers/usb/dwc3/core.h
> >>>> @@ -31,6 +31,8 @@
> >>>> #include <linux/usb/gadget.h>
> >>>> #include <linux/usb/otg.h>
> >>>>
> >>>> +#include <linux/phy/phy.h>
> >>>> +
> >>>> /* Global constants */
> >>>> #define DWC3_EP0_BOUNCE_SIZE 512
> >>>> #define DWC3_ENDPOINTS_NUM 32
> >>>> @@ -613,6 +615,8 @@ struct dwc3_scratchpad_array {
> >>>> * @dr_mode: requested mode of operation
> >>>> * @usb2_phy: pointer to USB2 PHY
> >>>> * @usb3_phy: pointer to USB3 PHY
> >>>> + * @usb2_generic_phy: pointer to USB2 PHY
> >>>> + * @usb3_generic_phy: pointer to USB3 PHY
> >>>> * @dcfg: saved contents of DCFG register
> >>>> * @gctl: saved contents of GCTL register
> >>>> * @is_selfpowered: true when we are selfpowered
> >>>> @@ -665,6 +669,9 @@ struct dwc3 {
> >>>> struct usb_phy *usb2_phy;
> >>>> struct usb_phy *usb3_phy;
> >>>>
> >>>> + struct phy *usb2_generic_phy;
> >>>> + struct phy *usb3_generic_phy;
> >>>> +
> >>>> void __iomem *regs;
> >>>> size_t regs_size;
> >>>>
> >>>>
> >>
> >> Do you have any suggestions on how to get only individual PHYs? like only
> >> usb2phy or usb3phy?
> >
> > My earlier understanding was that both PHYs are needed only if .speed is "super-speed"
> > and only usb2phy is needed for "high-speed". But as per Vivek's email it seems
> > Samsung's exynos5 SoC doesn't need usb2phy for "super-speed".
> >
> > So to keeps things flexible, I can propose the following approach
> > - if speed == 'high-speed' usb2phy must be present. usb3phy will be ignored if supplied.
> > - if speed == 'super-speed' usb3phy must be present and usb2phy is optional but must be
> > initialized if supplied.
> > - if speed is not specified, we default to 'super-speed'.
> >
> > Felipe, does this address the issue you were facing with OMAP5?
>
> IIRC, even if the speed is high speed, you still need to power on the USB3 PHY.
> Or else even high speed mode wasn't working in OMAP5.

right

--
balbi


Attachments:
(No filename) (9.13 kB)
signature.asc (836.00 B)
Digital signature
Download all attachments

2013-10-15 11:58:47

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

Hi,

On Mon, Oct 14, 2013 at 01:21:29PM +0300, Roger Quadros wrote:
> +Vivek
>
> On 10/14/2013 12:26 PM, Kishon Vijay Abraham I wrote:
> > Hi Roger,
> >
> > On Friday 11 October 2013 08:39 PM, Roger Quadros wrote:
> >> Hi,
> >>
> >> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
> >>> Adapted dwc3 core to use the Generic PHY Framework. So for init, exit,
> >>> power_on and power_off the following APIs are used phy_init(), phy_exit(),
> >>> phy_power_on() and phy_power_off().
> >>>
> >>> However using the old USB phy library wont be removed till the PHYs of all
> >>> other SoC's using dwc3 core is adapted to the Generic PHY Framework.
> >>>
> >>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
> >>> ---
> >>> Documentation/devicetree/bindings/usb/dwc3.txt | 6 ++-
> >>> drivers/usb/dwc3/Kconfig | 1 +
> >>> drivers/usb/dwc3/core.c | 49 ++++++++++++++++++++++++
> >>> drivers/usb/dwc3/core.h | 7 ++++
> >>> 4 files changed, 61 insertions(+), 2 deletions(-)
> >>>
> >>> diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
> >>> index e807635..471366d 100644
> >>> --- a/Documentation/devicetree/bindings/usb/dwc3.txt
> >>> +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
> >>> @@ -6,11 +6,13 @@ Required properties:
> >>> - compatible: must be "snps,dwc3"
> >>> - reg : Address and length of the register set for the device
> >>> - interrupts: Interrupts used by the dwc3 controller.
> >>> +
> >>> +Optional properties:
> >>> - usb-phy : array of phandle for the PHY device. The first element
> >>> in the array is expected to be a handle to the USB2/HS PHY and
> >>> the second element is expected to be a handle to the USB3/SS PHY
> >>> -
> >>> -Optional properties:
> >>> + - phys: from the *Generic PHY* bindings
> >>> + - phy-names: from the *Generic PHY* bindings
> >>> - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
> >>>
> >>> This is usually a subnode to DWC3 glue to which it is connected.
> >>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
> >>> index cfc16dd..ad7ce83 100644
> >>> --- a/drivers/usb/dwc3/Kconfig
> >>> +++ b/drivers/usb/dwc3/Kconfig
> >>> @@ -3,6 +3,7 @@ config USB_DWC3
> >>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
> >>> depends on EXTCON
> >>> select USB_PHY
> >>> + select GENERIC_PHY
> >>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
> >>> help
> >>> Say Y or M here if your system has a Dual Role SuperSpeed
> >>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> >>> index 428c29e..485d365 100644
> >>> --- a/drivers/usb/dwc3/core.c
> >>> +++ b/drivers/usb/dwc3/core.c
> >>> @@ -82,6 +82,12 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
> >>>
> >>> usb_phy_init(dwc->usb2_phy);
> >>> usb_phy_init(dwc->usb3_phy);
> >>
> >> How about adding
> >> + if (dwc->usb2_phy)
> >> + usb_phy_init(dwc->usb2_phy);
> >> + if (dwc->usb3_phy)
> >> + usb_phy_init(dwc->usb3_phy);
> >
> > Thankfully that usb_phy_init will check if phy is NULL.
> >>
> >> both usb phy and generic phy shouldn't be present together.
> >
> > ok.
> >>
> >>> +
> >>> + if (dwc->usb2_generic_phy)
> >>> + phy_init(dwc->usb2_generic_phy);
> >>> + if (dwc->usb3_generic_phy)
> >>> + phy_init(dwc->usb3_generic_phy);
> >>> +
> >>> mdelay(100);
> >>>
> >>> /* Clear USB3 PHY reset */
> >>> @@ -343,6 +349,11 @@ static void dwc3_core_exit(struct dwc3 *dwc)
> >>> {
> >>> usb_phy_shutdown(dwc->usb2_phy);
> >>> usb_phy_shutdown(dwc->usb3_phy);
> >>
> >> here as well
> >>
> >>> +
> >>> + if (dwc->usb2_generic_phy)
> >>> + phy_power_off(dwc->usb2_generic_phy);
> >>> + if (dwc->usb3_generic_phy)
> >>> + phy_power_off(dwc->usb3_generic_phy);
> >>> }
> >>>
> >>> #define DWC3_ALIGN_MASK (16 - 1)
> >>> @@ -427,6 +438,23 @@ static int dwc3_probe(struct platform_device *pdev)
> >>> dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
> >>> }
> >>>
> >>> + if (of_property_read_bool(node, "phys") || pdata->has_phy) {
> >>> + dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
> >>> + if (IS_ERR(dwc->usb2_generic_phy)) {
> >>> + dev_err(dev, "no usb2 phy configured yet");
> >>> + return PTR_ERR(dwc->usb2_generic_phy);
> >>> + }
> >>> +
> >>> + dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
> >>> + if (IS_ERR(dwc->usb3_generic_phy)) {
> >>> + dev_err(dev, "no usb3 phy configured yet");
> >>> + return PTR_ERR(dwc->usb3_generic_phy);
> >>> + }
> >>
> >> better to add
> >> + /* Don't use USB PHY if generic PHY was found */
> >> + dwc->usb2_phy = dwc->usb3_phy = NULL;
> >
> > ok.
> >>
> >>> + } else {
> >>
> >> not required as we've used kzalloc for dwc.
> >>
> >>> + dwc->usb2_generic_phy = NULL;
> >>> + dwc->usb3_generic_phy = NULL;
> >>> + }
> >>> +
> >>> /* default to superspeed if no maximum_speed passed */
> >>> if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
> >>> dwc->maximum_speed = USB_SPEED_SUPER;
> >>> @@ -450,6 +478,11 @@ static int dwc3_probe(struct platform_device *pdev)
> >>
> >> if (dwc->usb2_phy)
> >>
> >>> usb_phy_set_suspend(dwc->usb2_phy, 0);
> >>
> >> if (dwc->usb3_phy)
> >>
> >>> usb_phy_set_suspend(dwc->usb3_phy, 0);
> >>>
> >>> + if (dwc->usb2_generic_phy)
> >>> + phy_power_on(dwc->usb2_generic_phy);
> >>> + if (dwc->usb3_generic_phy)
> >>> + phy_power_on(dwc->usb3_generic_phy);
> >>> +
> >>> spin_lock_init(&dwc->lock);
> >>> platform_set_drvdata(pdev, dwc);
> >>>
> >>> @@ -576,6 +609,11 @@ static int dwc3_remove(struct platform_device *pdev)
> >>
> >> if (dwc->usb2_phy)
> >>> usb_phy_set_suspend(dwc->usb2_phy, 1);
> >>
> >> if (dwc->usb3_phy)
> >>> usb_phy_set_suspend(dwc->usb3_phy, 1);
> >>>
> >>> + if (dwc->usb2_generic_phy)
> >>> + phy_power_off(dwc->usb2_generic_phy);
> >>> + if (dwc->usb3_generic_phy)
> >>> + phy_power_off(dwc->usb3_generic_phy);
> >>> +
> >>> pm_runtime_put(&pdev->dev);
> >>> pm_runtime_disable(&pdev->dev);
> >>>
> >>> @@ -673,6 +711,11 @@ static int dwc3_suspend(struct device *dev)
> >>
> >> if (dwc->usb3_phy)
> >>> usb_phy_shutdown(dwc->usb3_phy);
> >>
> >> if (dwc->usb2_phy)
> >>> usb_phy_shutdown(dwc->usb2_phy);
> >>>
> >>> + if (dwc->usb2_generic_phy)
> >>> + phy_exit(dwc->usb2_generic_phy);
> >>> + if (dwc->usb3_generic_phy)
> >>> + phy_exit(dwc->usb3_generic_phy);
> >>> +
> >>> return 0;
> >>> }
> >>>
> >>> @@ -683,6 +726,12 @@ static int dwc3_resume(struct device *dev)
> >>>
> >>
> >> if (dwc->usb3_phy)
> >>> usb_phy_init(dwc->usb3_phy);
> >>
> >> if (dwc->usb2_phy)
> >>> usb_phy_init(dwc->usb2_phy);
> >>> +
> >>> + if (dwc->usb2_generic_phy)
> >>> + phy_init(dwc->usb2_generic_phy);
> >>> + if (dwc->usb3_generic_phy)
> >>> + phy_init(dwc->usb3_generic_phy);
> >>> +
> >>> msleep(100);
> >>>
> >>> spin_lock_irqsave(&dwc->lock, flags);
> >>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> >>> index f8af8d4..01ec7d7 100644
> >>> --- a/drivers/usb/dwc3/core.h
> >>> +++ b/drivers/usb/dwc3/core.h
> >>> @@ -31,6 +31,8 @@
> >>> #include <linux/usb/gadget.h>
> >>> #include <linux/usb/otg.h>
> >>>
> >>> +#include <linux/phy/phy.h>
> >>> +
> >>> /* Global constants */
> >>> #define DWC3_EP0_BOUNCE_SIZE 512
> >>> #define DWC3_ENDPOINTS_NUM 32
> >>> @@ -613,6 +615,8 @@ struct dwc3_scratchpad_array {
> >>> * @dr_mode: requested mode of operation
> >>> * @usb2_phy: pointer to USB2 PHY
> >>> * @usb3_phy: pointer to USB3 PHY
> >>> + * @usb2_generic_phy: pointer to USB2 PHY
> >>> + * @usb3_generic_phy: pointer to USB3 PHY
> >>> * @dcfg: saved contents of DCFG register
> >>> * @gctl: saved contents of GCTL register
> >>> * @is_selfpowered: true when we are selfpowered
> >>> @@ -665,6 +669,9 @@ struct dwc3 {
> >>> struct usb_phy *usb2_phy;
> >>> struct usb_phy *usb3_phy;
> >>>
> >>> + struct phy *usb2_generic_phy;
> >>> + struct phy *usb3_generic_phy;
> >>> +
> >>> void __iomem *regs;
> >>> size_t regs_size;
> >>>
> >>>
> >
> > Do you have any suggestions on how to get only individual PHYs? like only
> > usb2phy or usb3phy?
>
> My earlier understanding was that both PHYs are needed only if .speed is "super-speed"
> and only usb2phy is needed for "high-speed". But as per Vivek's email it seems
> Samsung's exynos5 SoC doesn't need usb2phy for "super-speed".
>
> So to keeps things flexible, I can propose the following approach
> - if speed == 'high-speed' usb2phy must be present. usb3phy will be ignored if supplied.
> - if speed == 'super-speed' usb3phy must be present and usb2phy is optional but must be
> initialized if supplied.
> - if speed is not specified, we default to 'super-speed'.
>
> Felipe, does this address the issue you were facing with OMAP5?

on OMAP5 we cannot skip USB3 PHY initialization. But then it becomes a
question of supporting a test feature (in OMAP5 case it would be cool to
force controller to lower speeds for testing) or coping with a broken
DTS.

--
balbi


Attachments:
(No filename) (8.87 kB)
signature.asc (836.00 B)
Digital signature
Download all attachments

2013-10-15 12:01:47

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

On Tue, Oct 15, 2013 at 10:57:16AM +0300, Roger Quadros wrote:
> On 10/15/2013 08:31 AM, Kishon Vijay Abraham I wrote:
> > Hi Roger,
> >
> > On Monday 14 October 2013 03:51 PM, Roger Quadros wrote:
> >> +Vivek
> >>
> >> On 10/14/2013 12:26 PM, Kishon Vijay Abraham I wrote:
> >>> Hi Roger,
> >>>
> >>> On Friday 11 October 2013 08:39 PM, Roger Quadros wrote:
> >>>> Hi,
> >>>>
> >>>> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
> >>>>> Adapted dwc3 core to use the Generic PHY Framework. So for init, exit,
> >>>>> power_on and power_off the following APIs are used phy_init(), phy_exit(),
> >>>>> phy_power_on() and phy_power_off().
> >>>>>
> >>>>> However using the old USB phy library wont be removed till the PHYs of all
> >>>>> other SoC's using dwc3 core is adapted to the Generic PHY Framework.
> >>>>>
> >>>>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
> >>>>> ---
> >>>>> Documentation/devicetree/bindings/usb/dwc3.txt | 6 ++-
> >>>>> drivers/usb/dwc3/Kconfig | 1 +
> >>>>> drivers/usb/dwc3/core.c | 49 ++++++++++++++++++++++++
> >>>>> drivers/usb/dwc3/core.h | 7 ++++
> >>>>> 4 files changed, 61 insertions(+), 2 deletions(-)
> >>>>>
> >>>>> diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
> >>>>> index e807635..471366d 100644
> >>>>> --- a/Documentation/devicetree/bindings/usb/dwc3.txt
> >>>>> +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
> >>>>> @@ -6,11 +6,13 @@ Required properties:
> >>>>> - compatible: must be "snps,dwc3"
> >>>>> - reg : Address and length of the register set for the device
> >>>>> - interrupts: Interrupts used by the dwc3 controller.
> >>>>> +
> >>>>> +Optional properties:
> >>>>> - usb-phy : array of phandle for the PHY device. The first element
> >>>>> in the array is expected to be a handle to the USB2/HS PHY and
> >>>>> the second element is expected to be a handle to the USB3/SS PHY
> >>>>> -
> >>>>> -Optional properties:
> >>>>> + - phys: from the *Generic PHY* bindings
> >>>>> + - phy-names: from the *Generic PHY* bindings
> >>>>> - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
> >>>>>
> >>>>> This is usually a subnode to DWC3 glue to which it is connected.
> >>>>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
> >>>>> index cfc16dd..ad7ce83 100644
> >>>>> --- a/drivers/usb/dwc3/Kconfig
> >>>>> +++ b/drivers/usb/dwc3/Kconfig
> >>>>> @@ -3,6 +3,7 @@ config USB_DWC3
> >>>>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
> >>>>> depends on EXTCON
> >>>>> select USB_PHY
> >>>>> + select GENERIC_PHY
> >>>>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
> >>>>> help
> >>>>> Say Y or M here if your system has a Dual Role SuperSpeed
> >>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> >>>>> index 428c29e..485d365 100644
> >>>>> --- a/drivers/usb/dwc3/core.c
> >>>>> +++ b/drivers/usb/dwc3/core.c
> >>>>> @@ -82,6 +82,12 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
> >>>>>
> >>>>> usb_phy_init(dwc->usb2_phy);
> >>>>> usb_phy_init(dwc->usb3_phy);
> >>>>
> >>>> How about adding
> >>>> + if (dwc->usb2_phy)
> >>>> + usb_phy_init(dwc->usb2_phy);
> >>>> + if (dwc->usb3_phy)
> >>>> + usb_phy_init(dwc->usb3_phy);
> >>>
> >>> Thankfully that usb_phy_init will check if phy is NULL.
> >>>>
> >>>> both usb phy and generic phy shouldn't be present together.
> >>>
> >>> ok.
> >>>>
> >>>>> +
> >>>>> + if (dwc->usb2_generic_phy)
> >>>>> + phy_init(dwc->usb2_generic_phy);
> >>>>> + if (dwc->usb3_generic_phy)
> >>>>> + phy_init(dwc->usb3_generic_phy);
> >>>>> +
> >>>>> mdelay(100);
> >>>>>
> >>>>> /* Clear USB3 PHY reset */
> >>>>> @@ -343,6 +349,11 @@ static void dwc3_core_exit(struct dwc3 *dwc)
> >>>>> {
> >>>>> usb_phy_shutdown(dwc->usb2_phy);
> >>>>> usb_phy_shutdown(dwc->usb3_phy);
> >>>>
> >>>> here as well
> >>>>
> >>>>> +
> >>>>> + if (dwc->usb2_generic_phy)
> >>>>> + phy_power_off(dwc->usb2_generic_phy);
> >>>>> + if (dwc->usb3_generic_phy)
> >>>>> + phy_power_off(dwc->usb3_generic_phy);
> >>>>> }
> >>>>>
> >>>>> #define DWC3_ALIGN_MASK (16 - 1)
> >>>>> @@ -427,6 +438,23 @@ static int dwc3_probe(struct platform_device *pdev)
> >>>>> dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
> >>>>> }
> >>>>>
> >>>>> + if (of_property_read_bool(node, "phys") || pdata->has_phy) {
> >>>>> + dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
> >>>>> + if (IS_ERR(dwc->usb2_generic_phy)) {
> >>>>> + dev_err(dev, "no usb2 phy configured yet");
> >>>>> + return PTR_ERR(dwc->usb2_generic_phy);
> >>>>> + }
> >>>>> +
> >>>>> + dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
> >>>>> + if (IS_ERR(dwc->usb3_generic_phy)) {
> >>>>> + dev_err(dev, "no usb3 phy configured yet");
> >>>>> + return PTR_ERR(dwc->usb3_generic_phy);
> >>>>> + }
> >>>>
> >>>> better to add
> >>>> + /* Don't use USB PHY if generic PHY was found */
> >>>> + dwc->usb2_phy = dwc->usb3_phy = NULL;
> >>>
> >>> ok.
> >>>>
> >>>>> + } else {
> >>>>
> >>>> not required as we've used kzalloc for dwc.
> >>>>
> >>>>> + dwc->usb2_generic_phy = NULL;
> >>>>> + dwc->usb3_generic_phy = NULL;
> >>>>> + }
> >>>>> +
> >>>>> /* default to superspeed if no maximum_speed passed */
> >>>>> if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
> >>>>> dwc->maximum_speed = USB_SPEED_SUPER;
> >>>>> @@ -450,6 +478,11 @@ static int dwc3_probe(struct platform_device *pdev)
> >>>>
> >>>> if (dwc->usb2_phy)
> >>>>
> >>>>> usb_phy_set_suspend(dwc->usb2_phy, 0);
> >>>>
> >>>> if (dwc->usb3_phy)
> >>>>
> >>>>> usb_phy_set_suspend(dwc->usb3_phy, 0);
> >>>>>
> >>>>> + if (dwc->usb2_generic_phy)
> >>>>> + phy_power_on(dwc->usb2_generic_phy);
> >>>>> + if (dwc->usb3_generic_phy)
> >>>>> + phy_power_on(dwc->usb3_generic_phy);
> >>>>> +
> >>>>> spin_lock_init(&dwc->lock);
> >>>>> platform_set_drvdata(pdev, dwc);
> >>>>>
> >>>>> @@ -576,6 +609,11 @@ static int dwc3_remove(struct platform_device *pdev)
> >>>>
> >>>> if (dwc->usb2_phy)
> >>>>> usb_phy_set_suspend(dwc->usb2_phy, 1);
> >>>>
> >>>> if (dwc->usb3_phy)
> >>>>> usb_phy_set_suspend(dwc->usb3_phy, 1);
> >>>>>
> >>>>> + if (dwc->usb2_generic_phy)
> >>>>> + phy_power_off(dwc->usb2_generic_phy);
> >>>>> + if (dwc->usb3_generic_phy)
> >>>>> + phy_power_off(dwc->usb3_generic_phy);
> >>>>> +
> >>>>> pm_runtime_put(&pdev->dev);
> >>>>> pm_runtime_disable(&pdev->dev);
> >>>>>
> >>>>> @@ -673,6 +711,11 @@ static int dwc3_suspend(struct device *dev)
> >>>>
> >>>> if (dwc->usb3_phy)
> >>>>> usb_phy_shutdown(dwc->usb3_phy);
> >>>>
> >>>> if (dwc->usb2_phy)
> >>>>> usb_phy_shutdown(dwc->usb2_phy);
> >>>>>
> >>>>> + if (dwc->usb2_generic_phy)
> >>>>> + phy_exit(dwc->usb2_generic_phy);
> >>>>> + if (dwc->usb3_generic_phy)
> >>>>> + phy_exit(dwc->usb3_generic_phy);
> >>>>> +
> >>>>> return 0;
> >>>>> }
> >>>>>
> >>>>> @@ -683,6 +726,12 @@ static int dwc3_resume(struct device *dev)
> >>>>>
> >>>>
> >>>> if (dwc->usb3_phy)
> >>>>> usb_phy_init(dwc->usb3_phy);
> >>>>
> >>>> if (dwc->usb2_phy)
> >>>>> usb_phy_init(dwc->usb2_phy);
> >>>>> +
> >>>>> + if (dwc->usb2_generic_phy)
> >>>>> + phy_init(dwc->usb2_generic_phy);
> >>>>> + if (dwc->usb3_generic_phy)
> >>>>> + phy_init(dwc->usb3_generic_phy);
> >>>>> +
> >>>>> msleep(100);
> >>>>>
> >>>>> spin_lock_irqsave(&dwc->lock, flags);
> >>>>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> >>>>> index f8af8d4..01ec7d7 100644
> >>>>> --- a/drivers/usb/dwc3/core.h
> >>>>> +++ b/drivers/usb/dwc3/core.h
> >>>>> @@ -31,6 +31,8 @@
> >>>>> #include <linux/usb/gadget.h>
> >>>>> #include <linux/usb/otg.h>
> >>>>>
> >>>>> +#include <linux/phy/phy.h>
> >>>>> +
> >>>>> /* Global constants */
> >>>>> #define DWC3_EP0_BOUNCE_SIZE 512
> >>>>> #define DWC3_ENDPOINTS_NUM 32
> >>>>> @@ -613,6 +615,8 @@ struct dwc3_scratchpad_array {
> >>>>> * @dr_mode: requested mode of operation
> >>>>> * @usb2_phy: pointer to USB2 PHY
> >>>>> * @usb3_phy: pointer to USB3 PHY
> >>>>> + * @usb2_generic_phy: pointer to USB2 PHY
> >>>>> + * @usb3_generic_phy: pointer to USB3 PHY
> >>>>> * @dcfg: saved contents of DCFG register
> >>>>> * @gctl: saved contents of GCTL register
> >>>>> * @is_selfpowered: true when we are selfpowered
> >>>>> @@ -665,6 +669,9 @@ struct dwc3 {
> >>>>> struct usb_phy *usb2_phy;
> >>>>> struct usb_phy *usb3_phy;
> >>>>>
> >>>>> + struct phy *usb2_generic_phy;
> >>>>> + struct phy *usb3_generic_phy;
> >>>>> +
> >>>>> void __iomem *regs;
> >>>>> size_t regs_size;
> >>>>>
> >>>>>
> >>>
> >>> Do you have any suggestions on how to get only individual PHYs? like only
> >>> usb2phy or usb3phy?
> >>
> >> My earlier understanding was that both PHYs are needed only if .speed is "super-speed"
> >> and only usb2phy is needed for "high-speed". But as per Vivek's email it seems
> >> Samsung's exynos5 SoC doesn't need usb2phy for "super-speed".
> >>
> >> So to keeps things flexible, I can propose the following approach
> >> - if speed == 'high-speed' usb2phy must be present. usb3phy will be ignored if supplied.
> >> - if speed == 'super-speed' usb3phy must be present and usb2phy is optional but must be
> >> initialized if supplied.
> >> - if speed is not specified, we default to 'super-speed'.
> >>
> >> Felipe, does this address the issue you were facing with OMAP5?
> >
> > IIRC, even if the speed is high speed, you still need to power on the USB3 PHY.
> > Or else even high speed mode wasn't working in OMAP5.
>
> Maybe for OMAP5 we can somehow indicate to dwc3 core code that only 'super-speed' mode
> is supported by the platform. I'm not aware of any OMAP5 platform using the USB port as 'high-speed'.
>
> So there needs to be some mechanism for dwc3-<platform>.c to indicate
> to dwc3-core.c the speeds supported by the platform. e.g. via
> of_dev_auxdata through of_platform_populate()?

that's not the problem. We can temm dwc3 core that dwc3-omap supports
full, high and super speeds, but nothing prevents the user from passing
speed = highspeed on their DTS right ? Even for OMAP5. Now comes the
question, do we assume that's a broken DTB and don't support it ? Or do
we require nop xceiv for highspeed-only implementations ?

If you think of it, not wiring the superspeed side of a *superspeed*
controller is quite an abomination :-)

cheers

--
balbi


Attachments:
(No filename) (10.24 kB)
signature.asc (836.00 B)
Digital signature
Download all attachments

2013-10-15 12:11:35

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

On 10/15/2013 02:57 PM, Felipe Balbi wrote:
> Hi,
>
> On Mon, Oct 14, 2013 at 01:21:29PM +0300, Roger Quadros wrote:
>> +Vivek
>>
>> On 10/14/2013 12:26 PM, Kishon Vijay Abraham I wrote:
>>> Hi Roger,
>>>
>>> On Friday 11 October 2013 08:39 PM, Roger Quadros wrote:
>>>> Hi,
>>>>
>>>> On 09/02/2013 06:43 PM, Kishon Vijay Abraham I wrote:
>>>>> Adapted dwc3 core to use the Generic PHY Framework. So for init, exit,
>>>>> power_on and power_off the following APIs are used phy_init(), phy_exit(),
>>>>> phy_power_on() and phy_power_off().
>>>>>
>>>>> However using the old USB phy library wont be removed till the PHYs of all
>>>>> other SoC's using dwc3 core is adapted to the Generic PHY Framework.
>>>>>
>>>>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>>>>> ---
>>>>> Documentation/devicetree/bindings/usb/dwc3.txt | 6 ++-
>>>>> drivers/usb/dwc3/Kconfig | 1 +
>>>>> drivers/usb/dwc3/core.c | 49 ++++++++++++++++++++++++
>>>>> drivers/usb/dwc3/core.h | 7 ++++
>>>>> 4 files changed, 61 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
>>>>> index e807635..471366d 100644
>>>>> --- a/Documentation/devicetree/bindings/usb/dwc3.txt
>>>>> +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
>>>>> @@ -6,11 +6,13 @@ Required properties:
>>>>> - compatible: must be "snps,dwc3"
>>>>> - reg : Address and length of the register set for the device
>>>>> - interrupts: Interrupts used by the dwc3 controller.
>>>>> +
>>>>> +Optional properties:
>>>>> - usb-phy : array of phandle for the PHY device. The first element
>>>>> in the array is expected to be a handle to the USB2/HS PHY and
>>>>> the second element is expected to be a handle to the USB3/SS PHY
>>>>> -
>>>>> -Optional properties:
>>>>> + - phys: from the *Generic PHY* bindings
>>>>> + - phy-names: from the *Generic PHY* bindings
>>>>> - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
>>>>>
>>>>> This is usually a subnode to DWC3 glue to which it is connected.
>>>>> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
>>>>> index cfc16dd..ad7ce83 100644
>>>>> --- a/drivers/usb/dwc3/Kconfig
>>>>> +++ b/drivers/usb/dwc3/Kconfig
>>>>> @@ -3,6 +3,7 @@ config USB_DWC3
>>>>> depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
>>>>> depends on EXTCON
>>>>> select USB_PHY
>>>>> + select GENERIC_PHY
>>>>> select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
>>>>> help
>>>>> Say Y or M here if your system has a Dual Role SuperSpeed
>>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>>>> index 428c29e..485d365 100644
>>>>> --- a/drivers/usb/dwc3/core.c
>>>>> +++ b/drivers/usb/dwc3/core.c
>>>>> @@ -82,6 +82,12 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
>>>>>
>>>>> usb_phy_init(dwc->usb2_phy);
>>>>> usb_phy_init(dwc->usb3_phy);
>>>>
>>>> How about adding
>>>> + if (dwc->usb2_phy)
>>>> + usb_phy_init(dwc->usb2_phy);
>>>> + if (dwc->usb3_phy)
>>>> + usb_phy_init(dwc->usb3_phy);
>>>
>>> Thankfully that usb_phy_init will check if phy is NULL.
>>>>
>>>> both usb phy and generic phy shouldn't be present together.
>>>
>>> ok.
>>>>
>>>>> +
>>>>> + if (dwc->usb2_generic_phy)
>>>>> + phy_init(dwc->usb2_generic_phy);
>>>>> + if (dwc->usb3_generic_phy)
>>>>> + phy_init(dwc->usb3_generic_phy);
>>>>> +
>>>>> mdelay(100);
>>>>>
>>>>> /* Clear USB3 PHY reset */
>>>>> @@ -343,6 +349,11 @@ static void dwc3_core_exit(struct dwc3 *dwc)
>>>>> {
>>>>> usb_phy_shutdown(dwc->usb2_phy);
>>>>> usb_phy_shutdown(dwc->usb3_phy);
>>>>
>>>> here as well
>>>>
>>>>> +
>>>>> + if (dwc->usb2_generic_phy)
>>>>> + phy_power_off(dwc->usb2_generic_phy);
>>>>> + if (dwc->usb3_generic_phy)
>>>>> + phy_power_off(dwc->usb3_generic_phy);
>>>>> }
>>>>>
>>>>> #define DWC3_ALIGN_MASK (16 - 1)
>>>>> @@ -427,6 +438,23 @@ static int dwc3_probe(struct platform_device *pdev)
>>>>> dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
>>>>> }
>>>>>
>>>>> + if (of_property_read_bool(node, "phys") || pdata->has_phy) {
>>>>> + dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
>>>>> + if (IS_ERR(dwc->usb2_generic_phy)) {
>>>>> + dev_err(dev, "no usb2 phy configured yet");
>>>>> + return PTR_ERR(dwc->usb2_generic_phy);
>>>>> + }
>>>>> +
>>>>> + dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
>>>>> + if (IS_ERR(dwc->usb3_generic_phy)) {
>>>>> + dev_err(dev, "no usb3 phy configured yet");
>>>>> + return PTR_ERR(dwc->usb3_generic_phy);
>>>>> + }
>>>>
>>>> better to add
>>>> + /* Don't use USB PHY if generic PHY was found */
>>>> + dwc->usb2_phy = dwc->usb3_phy = NULL;
>>>
>>> ok.
>>>>
>>>>> + } else {
>>>>
>>>> not required as we've used kzalloc for dwc.
>>>>
>>>>> + dwc->usb2_generic_phy = NULL;
>>>>> + dwc->usb3_generic_phy = NULL;
>>>>> + }
>>>>> +
>>>>> /* default to superspeed if no maximum_speed passed */
>>>>> if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
>>>>> dwc->maximum_speed = USB_SPEED_SUPER;
>>>>> @@ -450,6 +478,11 @@ static int dwc3_probe(struct platform_device *pdev)
>>>>
>>>> if (dwc->usb2_phy)
>>>>
>>>>> usb_phy_set_suspend(dwc->usb2_phy, 0);
>>>>
>>>> if (dwc->usb3_phy)
>>>>
>>>>> usb_phy_set_suspend(dwc->usb3_phy, 0);
>>>>>
>>>>> + if (dwc->usb2_generic_phy)
>>>>> + phy_power_on(dwc->usb2_generic_phy);
>>>>> + if (dwc->usb3_generic_phy)
>>>>> + phy_power_on(dwc->usb3_generic_phy);
>>>>> +
>>>>> spin_lock_init(&dwc->lock);
>>>>> platform_set_drvdata(pdev, dwc);
>>>>>
>>>>> @@ -576,6 +609,11 @@ static int dwc3_remove(struct platform_device *pdev)
>>>>
>>>> if (dwc->usb2_phy)
>>>>> usb_phy_set_suspend(dwc->usb2_phy, 1);
>>>>
>>>> if (dwc->usb3_phy)
>>>>> usb_phy_set_suspend(dwc->usb3_phy, 1);
>>>>>
>>>>> + if (dwc->usb2_generic_phy)
>>>>> + phy_power_off(dwc->usb2_generic_phy);
>>>>> + if (dwc->usb3_generic_phy)
>>>>> + phy_power_off(dwc->usb3_generic_phy);
>>>>> +
>>>>> pm_runtime_put(&pdev->dev);
>>>>> pm_runtime_disable(&pdev->dev);
>>>>>
>>>>> @@ -673,6 +711,11 @@ static int dwc3_suspend(struct device *dev)
>>>>
>>>> if (dwc->usb3_phy)
>>>>> usb_phy_shutdown(dwc->usb3_phy);
>>>>
>>>> if (dwc->usb2_phy)
>>>>> usb_phy_shutdown(dwc->usb2_phy);
>>>>>
>>>>> + if (dwc->usb2_generic_phy)
>>>>> + phy_exit(dwc->usb2_generic_phy);
>>>>> + if (dwc->usb3_generic_phy)
>>>>> + phy_exit(dwc->usb3_generic_phy);
>>>>> +
>>>>> return 0;
>>>>> }
>>>>>
>>>>> @@ -683,6 +726,12 @@ static int dwc3_resume(struct device *dev)
>>>>>
>>>>
>>>> if (dwc->usb3_phy)
>>>>> usb_phy_init(dwc->usb3_phy);
>>>>
>>>> if (dwc->usb2_phy)
>>>>> usb_phy_init(dwc->usb2_phy);
>>>>> +
>>>>> + if (dwc->usb2_generic_phy)
>>>>> + phy_init(dwc->usb2_generic_phy);
>>>>> + if (dwc->usb3_generic_phy)
>>>>> + phy_init(dwc->usb3_generic_phy);
>>>>> +
>>>>> msleep(100);
>>>>>
>>>>> spin_lock_irqsave(&dwc->lock, flags);
>>>>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>>>>> index f8af8d4..01ec7d7 100644
>>>>> --- a/drivers/usb/dwc3/core.h
>>>>> +++ b/drivers/usb/dwc3/core.h
>>>>> @@ -31,6 +31,8 @@
>>>>> #include <linux/usb/gadget.h>
>>>>> #include <linux/usb/otg.h>
>>>>>
>>>>> +#include <linux/phy/phy.h>
>>>>> +
>>>>> /* Global constants */
>>>>> #define DWC3_EP0_BOUNCE_SIZE 512
>>>>> #define DWC3_ENDPOINTS_NUM 32
>>>>> @@ -613,6 +615,8 @@ struct dwc3_scratchpad_array {
>>>>> * @dr_mode: requested mode of operation
>>>>> * @usb2_phy: pointer to USB2 PHY
>>>>> * @usb3_phy: pointer to USB3 PHY
>>>>> + * @usb2_generic_phy: pointer to USB2 PHY
>>>>> + * @usb3_generic_phy: pointer to USB3 PHY
>>>>> * @dcfg: saved contents of DCFG register
>>>>> * @gctl: saved contents of GCTL register
>>>>> * @is_selfpowered: true when we are selfpowered
>>>>> @@ -665,6 +669,9 @@ struct dwc3 {
>>>>> struct usb_phy *usb2_phy;
>>>>> struct usb_phy *usb3_phy;
>>>>>
>>>>> + struct phy *usb2_generic_phy;
>>>>> + struct phy *usb3_generic_phy;
>>>>> +
>>>>> void __iomem *regs;
>>>>> size_t regs_size;
>>>>>
>>>>>
>>>
>>> Do you have any suggestions on how to get only individual PHYs? like only
>>> usb2phy or usb3phy?
>>
>> My earlier understanding was that both PHYs are needed only if .speed is "super-speed"
>> and only usb2phy is needed for "high-speed". But as per Vivek's email it seems
>> Samsung's exynos5 SoC doesn't need usb2phy for "super-speed".
>>
>> So to keeps things flexible, I can propose the following approach
>> - if speed == 'high-speed' usb2phy must be present. usb3phy will be ignored if supplied.
>> - if speed == 'super-speed' usb3phy must be present and usb2phy is optional but must be
>> initialized if supplied.
>> - if speed is not specified, we default to 'super-speed'.
>>
>> Felipe, does this address the issue you were facing with OMAP5?
>
> on OMAP5 we cannot skip USB3 PHY initialization. But then it becomes a
> question of supporting a test feature (in OMAP5 case it would be cool to
> force controller to lower speeds for testing) or coping with a broken
> DTS.
>

I don't think we can protect ourselves from all possible broken configurations of DTS.
I would vote for simplicity and maximum flexibility.

So IMO we should just depend on DTS to provide the phys that are needed by the platform.
In the driver we initialize whatever PHY is provided and don't complain if any or even all PHYs are missing.

If this is not good enough then could you please suggest an alternative? Thanks.

cheers,
-roger

2013-10-15 13:20:34

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

Hi,

On Tue, Oct 15, 2013 at 03:10:42PM +0300, Roger Quadros wrote:
> >>>>> @@ -665,6 +669,9 @@ struct dwc3 {
> >>>>> struct usb_phy *usb2_phy;
> >>>>> struct usb_phy *usb3_phy;
> >>>>>
> >>>>> + struct phy *usb2_generic_phy;
> >>>>> + struct phy *usb3_generic_phy;
> >>>>> +
> >>>>> void __iomem *regs;
> >>>>> size_t regs_size;
> >>>>>
> >>>>>
> >>>
> >>> Do you have any suggestions on how to get only individual PHYs? like only
> >>> usb2phy or usb3phy?
> >>
> >> My earlier understanding was that both PHYs are needed only if .speed is "super-speed"
> >> and only usb2phy is needed for "high-speed". But as per Vivek's email it seems
> >> Samsung's exynos5 SoC doesn't need usb2phy for "super-speed".
> >>
> >> So to keeps things flexible, I can propose the following approach
> >> - if speed == 'high-speed' usb2phy must be present. usb3phy will be ignored if supplied.
> >> - if speed == 'super-speed' usb3phy must be present and usb2phy is optional but must be
> >> initialized if supplied.
> >> - if speed is not specified, we default to 'super-speed'.
> >>
> >> Felipe, does this address the issue you were facing with OMAP5?
> >
> > on OMAP5 we cannot skip USB3 PHY initialization. But then it becomes a
> > question of supporting a test feature (in OMAP5 case it would be cool to
> > force controller to lower speeds for testing) or coping with a broken
> > DTS.
> >
>
> I don't think we can protect ourselves from all possible broken
> configurations of DTS.
> I would vote for simplicity and maximum flexibility.
>
> So IMO we should just depend on DTS to provide the phys that are
> needed by the platform.
> In the driver we initialize whatever PHY is provided and don't
> complain if any or even all PHYs are missing.

considering that DTS is an ABI, I really think eventually we *will* have
broken DTBs burned into ROM and we will have to find ways to work with
those too. Same thing already happens today with ACPI tables.

> If this is not good enough then could you please suggest an
> alternative? Thanks.

The alternative would be to mandate nop xceiv for the "missing" PHY, but
that doesn't solve anything, really, as DTS authors might still forget
about the NOP xceiv and you can argue that forcing NOP xceiv would be a
SW configuration.

So, perhaps we go with the approach that all PHYs are optional, and
here's my original patch which makes USB3 PHY optional:

commit 979b84f96e4b7559b596b2933ae198aba267f260
Author: Felipe Balbi <[email protected]>
Date: Sun Jun 30 18:39:23 2013 +0300

usb: dwc3: core: make USB3 PHY optional

If we want a port to work at any speed lower
than Superspeed, it makes no sense to even
initialize/power up the USB3 transceiver,
provided it won't be used.

We can use the oportunity to save some power
and leave the superspeed transceiver powered
off.

There is at least one such case which is
Texas Instruments' AM437x which has one
of its USB3 ports without a matching USB3
PHY (that port is hardwired to work on USB2
only).

Signed-off-by: Felipe Balbi <[email protected]>

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 74f9cf0..7a5ab93 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -387,16 +387,34 @@ static int dwc3_probe(struct platform_device *pdev)
if (node) {
dwc->maximum_speed = of_usb_get_maximum_speed(node);

- dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
- dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
+ switch (dwc->maximum_speed) {
+ case USB_SPEED_SUPER:
+ dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
+ dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
+ break;
+ case USB_SPEED_HIGH:
+ case USB_SPEED_FULL:
+ case USB_SPEED_LOW:
+ dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
+ break;
+ }

dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
dwc->dr_mode = of_usb_get_dr_mode(node);
} else if (pdata) {
dwc->maximum_speed = pdata->maximum_speed;

- dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
- dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
+ switch (dwc->maximum_speed) {
+ case USB_SPEED_SUPER:
+ dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+ dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
+ break;
+ case USB_SPEED_HIGH:
+ case USB_SPEED_FULL:
+ case USB_SPEED_LOW:
+ dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+ break;
+ }

dwc->needs_fifo_resize = pdata->tx_fifo_resize;
dwc->dr_mode = pdata->dr_mode;
@@ -424,19 +442,21 @@ static int dwc3_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}

- if (IS_ERR(dwc->usb3_phy)) {
- ret = PTR_ERR(dwc->usb3_phy);
+ if (dwc->maximum_speed == USB_SPEED_SUPER) {
+ if (IS_ERR(dwc->usb3_phy)) {
+ ret = PTR_ERR(dwc->usb3_phy);

- /*
- * if -ENXIO is returned, it means PHY layer wasn't
- * enabled, so it makes no sense to return -EPROBE_DEFER
- * in that case, since no PHY driver will ever probe.
- */
- if (ret == -ENXIO)
- return ret;
+ /*
+ * if -ENXIO is returned, it means PHY layer wasn't
+ * enabled, so it makes no sense to return -EPROBE_DEFER
+ * in that case, since no PHY driver will ever probe.
+ */
+ if (ret == -ENXIO)
+ return ret;

- dev_err(dev, "no usb3 phy configured\n");
- return -EPROBE_DEFER;
+ dev_err(dev, "no usb3 phy configured\n");
+ return -EPROBE_DEFER;
+ }
}

dwc->xhci_resources[0].start = res->start;


what you guys are saying though, is that every PHY should be optional.

Do we have any device which doesn't provide USB2 PHY, only USB3 ? Dude,
that's so non-standard! USB *must* be backwards compatible so I'd expect
USB2 PHY to always be available.

--
balbi


Attachments:
(No filename) (5.72 kB)
signature.asc (836.00 B)
Digital signature
Download all attachments

2013-10-15 13:50:00

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

On 10/15/2013 04:19 PM, Felipe Balbi wrote:
> Hi,
>
> On Tue, Oct 15, 2013 at 03:10:42PM +0300, Roger Quadros wrote:
>>>>>>> @@ -665,6 +669,9 @@ struct dwc3 {
>>>>>>> struct usb_phy *usb2_phy;
>>>>>>> struct usb_phy *usb3_phy;
>>>>>>>
>>>>>>> + struct phy *usb2_generic_phy;
>>>>>>> + struct phy *usb3_generic_phy;
>>>>>>> +
>>>>>>> void __iomem *regs;
>>>>>>> size_t regs_size;
>>>>>>>
>>>>>>>
>>>>>
>>>>> Do you have any suggestions on how to get only individual PHYs? like only
>>>>> usb2phy or usb3phy?
>>>>
>>>> My earlier understanding was that both PHYs are needed only if .speed is "super-speed"
>>>> and only usb2phy is needed for "high-speed". But as per Vivek's email it seems
>>>> Samsung's exynos5 SoC doesn't need usb2phy for "super-speed".
>>>>
>>>> So to keeps things flexible, I can propose the following approach
>>>> - if speed == 'high-speed' usb2phy must be present. usb3phy will be ignored if supplied.
>>>> - if speed == 'super-speed' usb3phy must be present and usb2phy is optional but must be
>>>> initialized if supplied.
>>>> - if speed is not specified, we default to 'super-speed'.
>>>>
>>>> Felipe, does this address the issue you were facing with OMAP5?
>>>
>>> on OMAP5 we cannot skip USB3 PHY initialization. But then it becomes a
>>> question of supporting a test feature (in OMAP5 case it would be cool to
>>> force controller to lower speeds for testing) or coping with a broken
>>> DTS.
>>>
>>
>> I don't think we can protect ourselves from all possible broken
>> configurations of DTS.
>> I would vote for simplicity and maximum flexibility.
>>
>> So IMO we should just depend on DTS to provide the phys that are
>> needed by the platform.
>> In the driver we initialize whatever PHY is provided and don't
>> complain if any or even all PHYs are missing.
>
> considering that DTS is an ABI, I really think eventually we *will* have
> broken DTBs burned into ROM and we will have to find ways to work with
> those too. Same thing already happens today with ACPI tables.
>
>> If this is not good enough then could you please suggest an
>> alternative? Thanks.
>
> The alternative would be to mandate nop xceiv for the "missing" PHY, but
> that doesn't solve anything, really, as DTS authors might still forget
> about the NOP xceiv and you can argue that forcing NOP xceiv would be a
> SW configuration.
>
> So, perhaps we go with the approach that all PHYs are optional, and
> here's my original patch which makes USB3 PHY optional:
>
> commit 979b84f96e4b7559b596b2933ae198aba267f260
> Author: Felipe Balbi <[email protected]>
> Date: Sun Jun 30 18:39:23 2013 +0300
>
> usb: dwc3: core: make USB3 PHY optional
>
> If we want a port to work at any speed lower
> than Superspeed, it makes no sense to even
> initialize/power up the USB3 transceiver,
> provided it won't be used.
>
> We can use the oportunity to save some power
> and leave the superspeed transceiver powered
> off.
>
> There is at least one such case which is
> Texas Instruments' AM437x which has one
> of its USB3 ports without a matching USB3
> PHY (that port is hardwired to work on USB2
> only).
>
> Signed-off-by: Felipe Balbi <[email protected]>
>
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index 74f9cf0..7a5ab93 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -387,16 +387,34 @@ static int dwc3_probe(struct platform_device *pdev)
> if (node) {
> dwc->maximum_speed = of_usb_get_maximum_speed(node);
>
> - dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
> - dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
> + switch (dwc->maximum_speed) {
> + case USB_SPEED_SUPER:
> + dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
> + dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
> + break;
> + case USB_SPEED_HIGH:
> + case USB_SPEED_FULL:
> + case USB_SPEED_LOW:
> + dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
> + break;
> + }
>
> dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
> dwc->dr_mode = of_usb_get_dr_mode(node);
> } else if (pdata) {
> dwc->maximum_speed = pdata->maximum_speed;
>
> - dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
> - dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
> + switch (dwc->maximum_speed) {
> + case USB_SPEED_SUPER:
> + dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
> + dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
> + break;
> + case USB_SPEED_HIGH:
> + case USB_SPEED_FULL:
> + case USB_SPEED_LOW:
> + dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
> + break;
> + }

What if we try to get both PHYs irrespective of 'maximum_speed' but based
on presence of phandle/pdata. That way there is some control in the adaptation code (dts/pdata)
as to which PHYs needs to be initialized for that particular instance.

This is because there doesn't seem to be a consensus between different designs.
e.g. omap5 needs both phys for 'high-speed' whereas exynos5250 needs just the
usb3 phy for 'super-speed'

>
> dwc->needs_fifo_resize = pdata->tx_fifo_resize;
> dwc->dr_mode = pdata->dr_mode;
> @@ -424,19 +442,21 @@ static int dwc3_probe(struct platform_device *pdev)
> return -EPROBE_DEFER;
> }
>
> - if (IS_ERR(dwc->usb3_phy)) {
> - ret = PTR_ERR(dwc->usb3_phy);
> + if (dwc->maximum_speed == USB_SPEED_SUPER) {
> + if (IS_ERR(dwc->usb3_phy)) {
> + ret = PTR_ERR(dwc->usb3_phy);
>
> - /*
> - * if -ENXIO is returned, it means PHY layer wasn't
> - * enabled, so it makes no sense to return -EPROBE_DEFER
> - * in that case, since no PHY driver will ever probe.
> - */
> - if (ret == -ENXIO)
> - return ret;
> + /*
> + * if -ENXIO is returned, it means PHY layer wasn't
> + * enabled, so it makes no sense to return -EPROBE_DEFER
> + * in that case, since no PHY driver will ever probe.
> + */
> + if (ret == -ENXIO)
> + return ret;
>
> - dev_err(dev, "no usb3 phy configured\n");
> - return -EPROBE_DEFER;
> + dev_err(dev, "no usb3 phy configured\n");
> + return -EPROBE_DEFER;
> + }
> }
>
> dwc->xhci_resources[0].start = res->start;
>
>
> what you guys are saying though, is that every PHY should be optional.
>
> Do we have any device which doesn't provide USB2 PHY, only USB3 ? Dude,
> that's so non-standard! USB *must* be backwards compatible so I'd expect
> USB2 PHY to always be available.
>

Maybe the USB2 PHY hardware is there on the Exynos5250 but it just doesn't have discrete power control.
Vivek?

cheers,
-roger

2013-10-15 13:57:59

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

Hi,

On Tue, Oct 15, 2013 at 04:48:51PM +0300, Roger Quadros wrote:
> On 10/15/2013 04:19 PM, Felipe Balbi wrote:
> > Hi,
> >
> > On Tue, Oct 15, 2013 at 03:10:42PM +0300, Roger Quadros wrote:
> >>>>>>> @@ -665,6 +669,9 @@ struct dwc3 {
> >>>>>>> struct usb_phy *usb2_phy;
> >>>>>>> struct usb_phy *usb3_phy;
> >>>>>>>
> >>>>>>> + struct phy *usb2_generic_phy;
> >>>>>>> + struct phy *usb3_generic_phy;
> >>>>>>> +
> >>>>>>> void __iomem *regs;
> >>>>>>> size_t regs_size;
> >>>>>>>
> >>>>>>>
> >>>>>
> >>>>> Do you have any suggestions on how to get only individual PHYs? like only
> >>>>> usb2phy or usb3phy?
> >>>>
> >>>> My earlier understanding was that both PHYs are needed only if .speed is "super-speed"
> >>>> and only usb2phy is needed for "high-speed". But as per Vivek's email it seems
> >>>> Samsung's exynos5 SoC doesn't need usb2phy for "super-speed".
> >>>>
> >>>> So to keeps things flexible, I can propose the following approach
> >>>> - if speed == 'high-speed' usb2phy must be present. usb3phy will be ignored if supplied.
> >>>> - if speed == 'super-speed' usb3phy must be present and usb2phy is optional but must be
> >>>> initialized if supplied.
> >>>> - if speed is not specified, we default to 'super-speed'.
> >>>>
> >>>> Felipe, does this address the issue you were facing with OMAP5?
> >>>
> >>> on OMAP5 we cannot skip USB3 PHY initialization. But then it becomes a
> >>> question of supporting a test feature (in OMAP5 case it would be cool to
> >>> force controller to lower speeds for testing) or coping with a broken
> >>> DTS.
> >>>
> >>
> >> I don't think we can protect ourselves from all possible broken
> >> configurations of DTS.
> >> I would vote for simplicity and maximum flexibility.
> >>
> >> So IMO we should just depend on DTS to provide the phys that are
> >> needed by the platform.
> >> In the driver we initialize whatever PHY is provided and don't
> >> complain if any or even all PHYs are missing.
> >
> > considering that DTS is an ABI, I really think eventually we *will* have
> > broken DTBs burned into ROM and we will have to find ways to work with
> > those too. Same thing already happens today with ACPI tables.
> >
> >> If this is not good enough then could you please suggest an
> >> alternative? Thanks.
> >
> > The alternative would be to mandate nop xceiv for the "missing" PHY, but
> > that doesn't solve anything, really, as DTS authors might still forget
> > about the NOP xceiv and you can argue that forcing NOP xceiv would be a
> > SW configuration.
> >
> > So, perhaps we go with the approach that all PHYs are optional, and
> > here's my original patch which makes USB3 PHY optional:
> >
> > commit 979b84f96e4b7559b596b2933ae198aba267f260
> > Author: Felipe Balbi <[email protected]>
> > Date: Sun Jun 30 18:39:23 2013 +0300
> >
> > usb: dwc3: core: make USB3 PHY optional
> >
> > If we want a port to work at any speed lower
> > than Superspeed, it makes no sense to even
> > initialize/power up the USB3 transceiver,
> > provided it won't be used.
> >
> > We can use the oportunity to save some power
> > and leave the superspeed transceiver powered
> > off.
> >
> > There is at least one such case which is
> > Texas Instruments' AM437x which has one
> > of its USB3 ports without a matching USB3
> > PHY (that port is hardwired to work on USB2
> > only).
> >
> > Signed-off-by: Felipe Balbi <[email protected]>
> >
> > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> > index 74f9cf0..7a5ab93 100644
> > --- a/drivers/usb/dwc3/core.c
> > +++ b/drivers/usb/dwc3/core.c
> > @@ -387,16 +387,34 @@ static int dwc3_probe(struct platform_device *pdev)
> > if (node) {
> > dwc->maximum_speed = of_usb_get_maximum_speed(node);
> >
> > - dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
> > - dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
> > + switch (dwc->maximum_speed) {
> > + case USB_SPEED_SUPER:
> > + dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
> > + dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
> > + break;
> > + case USB_SPEED_HIGH:
> > + case USB_SPEED_FULL:
> > + case USB_SPEED_LOW:
> > + dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
> > + break;
> > + }
> >
> > dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
> > dwc->dr_mode = of_usb_get_dr_mode(node);
> > } else if (pdata) {
> > dwc->maximum_speed = pdata->maximum_speed;
> >
> > - dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
> > - dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
> > + switch (dwc->maximum_speed) {
> > + case USB_SPEED_SUPER:
> > + dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
> > + dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
> > + break;
> > + case USB_SPEED_HIGH:
> > + case USB_SPEED_FULL:
> > + case USB_SPEED_LOW:
> > + dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
> > + break;
> > + }
>
> What if we try to get both PHYs irrespective of 'maximum_speed' but based
> on presence of phandle/pdata. That way there is some control in the adaptation code (dts/pdata)
> as to which PHYs needs to be initialized for that particular instance.
>
> This is because there doesn't seem to be a consensus between different designs.
> e.g. omap5 needs both phys for 'high-speed' whereas exynos5250 needs just the
> usb3 phy for 'super-speed'

sure, can you write such a patch ? If it gets to my inbox in a couple
hours I guess I can still review and take it upstream on v3.13,
otherwise it's only on v3.14 :-(

>
> >
> > dwc->needs_fifo_resize = pdata->tx_fifo_resize;
> > dwc->dr_mode = pdata->dr_mode;
> > @@ -424,19 +442,21 @@ static int dwc3_probe(struct platform_device *pdev)
> > return -EPROBE_DEFER;
> > }
> >
> > - if (IS_ERR(dwc->usb3_phy)) {
> > - ret = PTR_ERR(dwc->usb3_phy);
> > + if (dwc->maximum_speed == USB_SPEED_SUPER) {
> > + if (IS_ERR(dwc->usb3_phy)) {
> > + ret = PTR_ERR(dwc->usb3_phy);
> >
> > - /*
> > - * if -ENXIO is returned, it means PHY layer wasn't
> > - * enabled, so it makes no sense to return -EPROBE_DEFER
> > - * in that case, since no PHY driver will ever probe.
> > - */
> > - if (ret == -ENXIO)
> > - return ret;
> > + /*
> > + * if -ENXIO is returned, it means PHY layer wasn't
> > + * enabled, so it makes no sense to return -EPROBE_DEFER
> > + * in that case, since no PHY driver will ever probe.
> > + */
> > + if (ret == -ENXIO)
> > + return ret;
> >
> > - dev_err(dev, "no usb3 phy configured\n");
> > - return -EPROBE_DEFER;
> > + dev_err(dev, "no usb3 phy configured\n");
> > + return -EPROBE_DEFER;
> > + }
> > }
> >
> > dwc->xhci_resources[0].start = res->start;
> >
> >
> > what you guys are saying though, is that every PHY should be optional.
> >
> > Do we have any device which doesn't provide USB2 PHY, only USB3 ? Dude,
> > that's so non-standard! USB *must* be backwards compatible so I'd expect
> > USB2 PHY to always be available.
> >
>
> Maybe the USB2 PHY hardware is there on the Exynos5250 but it just
> doesn't have discrete power control. Vivek?

I'd really like to hear that answer :-) But patch can come before that,
though.

cheers

--
balbi


Attachments:
(No filename) (7.21 kB)
signature.asc (836.00 B)
Digital signature
Download all attachments

2013-10-15 14:04:55

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

On 10/15/2013 04:56 PM, Felipe Balbi wrote:
> Hi,
>
> On Tue, Oct 15, 2013 at 04:48:51PM +0300, Roger Quadros wrote:
>> On 10/15/2013 04:19 PM, Felipe Balbi wrote:
>>> Hi,
>>>
>>> On Tue, Oct 15, 2013 at 03:10:42PM +0300, Roger Quadros wrote:
>>>>>>>>> @@ -665,6 +669,9 @@ struct dwc3 {
>>>>>>>>> struct usb_phy *usb2_phy;
>>>>>>>>> struct usb_phy *usb3_phy;
>>>>>>>>>
>>>>>>>>> + struct phy *usb2_generic_phy;
>>>>>>>>> + struct phy *usb3_generic_phy;
>>>>>>>>> +
>>>>>>>>> void __iomem *regs;
>>>>>>>>> size_t regs_size;
>>>>>>>>>
>>>>>>>>>
>>>>>>>
>>>>>>> Do you have any suggestions on how to get only individual PHYs? like only
>>>>>>> usb2phy or usb3phy?
>>>>>>
>>>>>> My earlier understanding was that both PHYs are needed only if .speed is "super-speed"
>>>>>> and only usb2phy is needed for "high-speed". But as per Vivek's email it seems
>>>>>> Samsung's exynos5 SoC doesn't need usb2phy for "super-speed".
>>>>>>
>>>>>> So to keeps things flexible, I can propose the following approach
>>>>>> - if speed == 'high-speed' usb2phy must be present. usb3phy will be ignored if supplied.
>>>>>> - if speed == 'super-speed' usb3phy must be present and usb2phy is optional but must be
>>>>>> initialized if supplied.
>>>>>> - if speed is not specified, we default to 'super-speed'.
>>>>>>
>>>>>> Felipe, does this address the issue you were facing with OMAP5?
>>>>>
>>>>> on OMAP5 we cannot skip USB3 PHY initialization. But then it becomes a
>>>>> question of supporting a test feature (in OMAP5 case it would be cool to
>>>>> force controller to lower speeds for testing) or coping with a broken
>>>>> DTS.
>>>>>
>>>>
>>>> I don't think we can protect ourselves from all possible broken
>>>> configurations of DTS.
>>>> I would vote for simplicity and maximum flexibility.
>>>>
>>>> So IMO we should just depend on DTS to provide the phys that are
>>>> needed by the platform.
>>>> In the driver we initialize whatever PHY is provided and don't
>>>> complain if any or even all PHYs are missing.
>>>
>>> considering that DTS is an ABI, I really think eventually we *will* have
>>> broken DTBs burned into ROM and we will have to find ways to work with
>>> those too. Same thing already happens today with ACPI tables.
>>>
>>>> If this is not good enough then could you please suggest an
>>>> alternative? Thanks.
>>>
>>> The alternative would be to mandate nop xceiv for the "missing" PHY, but
>>> that doesn't solve anything, really, as DTS authors might still forget
>>> about the NOP xceiv and you can argue that forcing NOP xceiv would be a
>>> SW configuration.
>>>
>>> So, perhaps we go with the approach that all PHYs are optional, and
>>> here's my original patch which makes USB3 PHY optional:
>>>
>>> commit 979b84f96e4b7559b596b2933ae198aba267f260
>>> Author: Felipe Balbi <[email protected]>
>>> Date: Sun Jun 30 18:39:23 2013 +0300
>>>
>>> usb: dwc3: core: make USB3 PHY optional
>>>
>>> If we want a port to work at any speed lower
>>> than Superspeed, it makes no sense to even
>>> initialize/power up the USB3 transceiver,
>>> provided it won't be used.
>>>
>>> We can use the oportunity to save some power
>>> and leave the superspeed transceiver powered
>>> off.
>>>
>>> There is at least one such case which is
>>> Texas Instruments' AM437x which has one
>>> of its USB3 ports without a matching USB3
>>> PHY (that port is hardwired to work on USB2
>>> only).
>>>
>>> Signed-off-by: Felipe Balbi <[email protected]>
>>>
>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>> index 74f9cf0..7a5ab93 100644
>>> --- a/drivers/usb/dwc3/core.c
>>> +++ b/drivers/usb/dwc3/core.c
>>> @@ -387,16 +387,34 @@ static int dwc3_probe(struct platform_device *pdev)
>>> if (node) {
>>> dwc->maximum_speed = of_usb_get_maximum_speed(node);
>>>
>>> - dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
>>> - dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
>>> + switch (dwc->maximum_speed) {
>>> + case USB_SPEED_SUPER:
>>> + dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
>>> + dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
>>> + break;
>>> + case USB_SPEED_HIGH:
>>> + case USB_SPEED_FULL:
>>> + case USB_SPEED_LOW:
>>> + dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
>>> + break;
>>> + }
>>>
>>> dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
>>> dwc->dr_mode = of_usb_get_dr_mode(node);
>>> } else if (pdata) {
>>> dwc->maximum_speed = pdata->maximum_speed;
>>>
>>> - dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
>>> - dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
>>> + switch (dwc->maximum_speed) {
>>> + case USB_SPEED_SUPER:
>>> + dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
>>> + dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
>>> + break;
>>> + case USB_SPEED_HIGH:
>>> + case USB_SPEED_FULL:
>>> + case USB_SPEED_LOW:
>>> + dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
>>> + break;
>>> + }
>>
>> What if we try to get both PHYs irrespective of 'maximum_speed' but based
>> on presence of phandle/pdata. That way there is some control in the adaptation code (dts/pdata)
>> as to which PHYs needs to be initialized for that particular instance.
>>
>> This is because there doesn't seem to be a consensus between different designs.
>> e.g. omap5 needs both phys for 'high-speed' whereas exynos5250 needs just the
>> usb3 phy for 'super-speed'
>
> sure, can you write such a patch ? If it gets to my inbox in a couple
> hours I guess I can still review and take it upstream on v3.13,
> otherwise it's only on v3.14 :-(

As this patch from Kishon is already touching this area, it would be best if
he can send a v2 with this feature.

cheers,
-roger

2013-10-15 14:13:24

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH 2/7] usb: dwc3: adapt dwc3 core to use Generic PHY Framework

On Tue, Oct 15, 2013 at 05:03:50PM +0300, Roger Quadros wrote:
> On 10/15/2013 04:56 PM, Felipe Balbi wrote:
> > Hi,
> >
> > On Tue, Oct 15, 2013 at 04:48:51PM +0300, Roger Quadros wrote:
> >> On 10/15/2013 04:19 PM, Felipe Balbi wrote:
> >>> Hi,
> >>>
> >>> On Tue, Oct 15, 2013 at 03:10:42PM +0300, Roger Quadros wrote:
> >>>>>>>>> @@ -665,6 +669,9 @@ struct dwc3 {
> >>>>>>>>> struct usb_phy *usb2_phy;
> >>>>>>>>> struct usb_phy *usb3_phy;
> >>>>>>>>>
> >>>>>>>>> + struct phy *usb2_generic_phy;
> >>>>>>>>> + struct phy *usb3_generic_phy;
> >>>>>>>>> +
> >>>>>>>>> void __iomem *regs;
> >>>>>>>>> size_t regs_size;
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>
> >>>>>>> Do you have any suggestions on how to get only individual PHYs? like only
> >>>>>>> usb2phy or usb3phy?
> >>>>>>
> >>>>>> My earlier understanding was that both PHYs are needed only if .speed is "super-speed"
> >>>>>> and only usb2phy is needed for "high-speed". But as per Vivek's email it seems
> >>>>>> Samsung's exynos5 SoC doesn't need usb2phy for "super-speed".
> >>>>>>
> >>>>>> So to keeps things flexible, I can propose the following approach
> >>>>>> - if speed == 'high-speed' usb2phy must be present. usb3phy will be ignored if supplied.
> >>>>>> - if speed == 'super-speed' usb3phy must be present and usb2phy is optional but must be
> >>>>>> initialized if supplied.
> >>>>>> - if speed is not specified, we default to 'super-speed'.
> >>>>>>
> >>>>>> Felipe, does this address the issue you were facing with OMAP5?
> >>>>>
> >>>>> on OMAP5 we cannot skip USB3 PHY initialization. But then it becomes a
> >>>>> question of supporting a test feature (in OMAP5 case it would be cool to
> >>>>> force controller to lower speeds for testing) or coping with a broken
> >>>>> DTS.
> >>>>>
> >>>>
> >>>> I don't think we can protect ourselves from all possible broken
> >>>> configurations of DTS.
> >>>> I would vote for simplicity and maximum flexibility.
> >>>>
> >>>> So IMO we should just depend on DTS to provide the phys that are
> >>>> needed by the platform.
> >>>> In the driver we initialize whatever PHY is provided and don't
> >>>> complain if any or even all PHYs are missing.
> >>>
> >>> considering that DTS is an ABI, I really think eventually we *will* have
> >>> broken DTBs burned into ROM and we will have to find ways to work with
> >>> those too. Same thing already happens today with ACPI tables.
> >>>
> >>>> If this is not good enough then could you please suggest an
> >>>> alternative? Thanks.
> >>>
> >>> The alternative would be to mandate nop xceiv for the "missing" PHY, but
> >>> that doesn't solve anything, really, as DTS authors might still forget
> >>> about the NOP xceiv and you can argue that forcing NOP xceiv would be a
> >>> SW configuration.
> >>>
> >>> So, perhaps we go with the approach that all PHYs are optional, and
> >>> here's my original patch which makes USB3 PHY optional:
> >>>
> >>> commit 979b84f96e4b7559b596b2933ae198aba267f260
> >>> Author: Felipe Balbi <[email protected]>
> >>> Date: Sun Jun 30 18:39:23 2013 +0300
> >>>
> >>> usb: dwc3: core: make USB3 PHY optional
> >>>
> >>> If we want a port to work at any speed lower
> >>> than Superspeed, it makes no sense to even
> >>> initialize/power up the USB3 transceiver,
> >>> provided it won't be used.
> >>>
> >>> We can use the oportunity to save some power
> >>> and leave the superspeed transceiver powered
> >>> off.
> >>>
> >>> There is at least one such case which is
> >>> Texas Instruments' AM437x which has one
> >>> of its USB3 ports without a matching USB3
> >>> PHY (that port is hardwired to work on USB2
> >>> only).
> >>>
> >>> Signed-off-by: Felipe Balbi <[email protected]>
> >>>
> >>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> >>> index 74f9cf0..7a5ab93 100644
> >>> --- a/drivers/usb/dwc3/core.c
> >>> +++ b/drivers/usb/dwc3/core.c
> >>> @@ -387,16 +387,34 @@ static int dwc3_probe(struct platform_device *pdev)
> >>> if (node) {
> >>> dwc->maximum_speed = of_usb_get_maximum_speed(node);
> >>>
> >>> - dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
> >>> - dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
> >>> + switch (dwc->maximum_speed) {
> >>> + case USB_SPEED_SUPER:
> >>> + dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
> >>> + dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
> >>> + break;
> >>> + case USB_SPEED_HIGH:
> >>> + case USB_SPEED_FULL:
> >>> + case USB_SPEED_LOW:
> >>> + dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
> >>> + break;
> >>> + }
> >>>
> >>> dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
> >>> dwc->dr_mode = of_usb_get_dr_mode(node);
> >>> } else if (pdata) {
> >>> dwc->maximum_speed = pdata->maximum_speed;
> >>>
> >>> - dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
> >>> - dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
> >>> + switch (dwc->maximum_speed) {
> >>> + case USB_SPEED_SUPER:
> >>> + dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
> >>> + dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
> >>> + break;
> >>> + case USB_SPEED_HIGH:
> >>> + case USB_SPEED_FULL:
> >>> + case USB_SPEED_LOW:
> >>> + dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
> >>> + break;
> >>> + }
> >>
> >> What if we try to get both PHYs irrespective of 'maximum_speed' but based
> >> on presence of phandle/pdata. That way there is some control in the adaptation code (dts/pdata)
> >> as to which PHYs needs to be initialized for that particular instance.
> >>
> >> This is because there doesn't seem to be a consensus between different designs.
> >> e.g. omap5 needs both phys for 'high-speed' whereas exynos5250 needs just the
> >> usb3 phy for 'super-speed'
> >
> > sure, can you write such a patch ? If it gets to my inbox in a couple
> > hours I guess I can still review and take it upstream on v3.13,
> > otherwise it's only on v3.14 :-(
>
> As this patch from Kishon is already touching this area, it would be best if
> he can send a v2 with this feature.

Alright, and so I'll wait a little longer.

cheers

--
balbi


Attachments:
(No filename) (6.14 kB)
signature.asc (836.00 B)
Digital signature
Download all attachments