2013-03-12 10:45:06

by Roger Quadros

[permalink] [raw]
Subject: [PATCH 00/12] USB: ehci-omap: Device tree support for 3.10

Hi Greg,

These patches implement device tree support for the OMAP's
EHCI host controller. The corresponding MFD/SoC patches will be sent
separately and this set has no dependeny with them.

NOTE: Last 2 patches are new and still need and Ack from Alan Stern.
Please accept this set after he has acked them. Thanks.

cheers,
-roger

The following changes since commit f6161aa153581da4a3867a2d1a7caf4be19b6ec9:

Linux 3.9-rc2 (2013-03-10 16:54:19 -0700)

are available in the git repository at:
git://github.com/rogerq/linux.git usbhost-usb-next

Alan Stern (1):
USB: EHCI: split ehci-omap out to a separate driver

Roger Quadros (11):
USB: ehci-omap: Use devm_ioremap_resource()
USB: ehci-omap: Use PHY APIs to get the PHY device and put it out of
suspend
USB: ehci-omap: Remove PHY reset handling code
USB: ehci-omap: Remove PHY regulator handling code
USB: ehci-omap: Select NOP USB transceiver driver
USB: ehci-omap: Get platform resources by index rather than by name
USB: ohci-omap3: Get platform resources by index rather than by name
USB: ohci-omap3: Add device tree support and binding information
USB: ehci-omap: Add device tree support and binding information
USB: ehci-omap: Try to get PHY even if not in PHY mode
USB: ehci-omap: Fix detection in HSIC mode

.../devicetree/bindings/usb/ehci-omap.txt | 32 ++
.../devicetree/bindings/usb/ohci-omap3.txt | 15 +
drivers/usb/host/Kconfig | 3 +-
drivers/usb/host/Makefile | 1 +
drivers/usb/host/ehci-hcd.c | 6 +-
drivers/usb/host/ehci-omap.c | 312 +++++++++-----------
drivers/usb/host/ohci-omap3.c | 24 ++-
7 files changed, 214 insertions(+), 179 deletions(-)
create mode 100644 Documentation/devicetree/bindings/usb/ehci-omap.txt
create mode 100644 Documentation/devicetree/bindings/usb/ohci-omap3.txt

--
1.7.4.1


2013-03-12 10:45:13

by Roger Quadros

[permalink] [raw]
Subject: [PATCH 02/12] USB: ehci-omap: Use devm_ioremap_resource()

Make use of devm_ioremap_resource() and correct comment.

Signed-off-by: Roger Quadros <[email protected]>
Acked-by: Alan Stern <[email protected]>
---
drivers/usb/host/ehci-omap.c | 21 +++++----------------
1 files changed, 5 insertions(+), 16 deletions(-)

diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index fa66757..70e8e6f 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -216,23 +216,15 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)

res = platform_get_resource_byname(pdev,
IORESOURCE_MEM, "ehci");
- if (!res) {
- dev_err(dev, "UHH EHCI get resource failed\n");
- return -ENODEV;
- }
-
- regs = ioremap(res->start, resource_size(res));
- if (!regs) {
- dev_err(dev, "UHH EHCI ioremap failed\n");
- return -ENOMEM;
- }
+ regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);

hcd = usb_create_hcd(&ehci_omap_hc_driver, dev,
dev_name(dev));
if (!hcd) {
- dev_err(dev, "failed to create hcd with err %d\n", ret);
- ret = -ENOMEM;
- goto err_io;
+ dev_err(dev, "Failed to create HCD\n");
+ return -ENOMEM;
}

hcd->rsrc_start = res->start;
@@ -285,8 +277,6 @@ err_pm_runtime:
pm_runtime_put_sync(dev);
usb_put_hcd(hcd);

-err_io:
- iounmap(regs);
return ret;
}

@@ -306,7 +296,6 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)

usb_remove_hcd(hcd);
disable_put_regulator(dev->platform_data);
- iounmap(hcd->regs);
usb_put_hcd(hcd);

pm_runtime_put_sync(dev);
--
1.7.4.1

2013-03-12 10:45:19

by Roger Quadros

[permalink] [raw]
Subject: [PATCH 04/12] USB: ehci-omap: Remove PHY reset handling code

Reset GPIO handling for the PHY must be done in the PHY
driver. We use the PHY helpers instead to reset the PHY.

Signed-off-by: Roger Quadros <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Acked-by: Alan Stern <[email protected]>
---
drivers/usb/host/ehci-omap.c | 72 ++++++------------------------------------
1 files changed, 10 insertions(+), 62 deletions(-)

diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 6b8b7e5..0bbfdc1 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -86,79 +86,27 @@ static inline u32 ehci_read(void __iomem *base, u32 reg)
return __raw_readl(base + reg);
}

-
-static void omap_ehci_soft_phy_reset(struct usb_hcd *hcd, u8 port)
-{
- unsigned long timeout = jiffies + msecs_to_jiffies(1000);
- unsigned reg = 0;
-
- reg = ULPI_FUNC_CTRL_RESET
- /* FUNCTION_CTRL_SET register */
- | (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT)
- /* Write */
- | (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT)
- /* PORTn */
- | ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT)
- /* start ULPI access*/
- | (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT);
-
- ehci_write(hcd->regs, EHCI_INSNREG05_ULPI, reg);
-
- /* Wait for ULPI access completion */
- while ((ehci_read(hcd->regs, EHCI_INSNREG05_ULPI)
- & (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) {
- cpu_relax();
-
- if (time_after(jiffies, timeout)) {
- dev_dbg(hcd->self.controller,
- "phy reset operation timed out\n");
- break;
- }
- }
-}
-
static int omap_ehci_init(struct usb_hcd *hcd)
{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int rc;
- struct usbhs_omap_platform_data *pdata;
-
- pdata = hcd->self.controller->platform_data;
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ struct omap_hcd *omap = (struct omap_hcd *)ehci->priv;
+ int rc, i;

/* Hold PHYs in reset while initializing EHCI controller */
- if (pdata->phy_reset) {
- if (gpio_is_valid(pdata->reset_gpio_port[0]))
- gpio_set_value_cansleep(pdata->reset_gpio_port[0], 0);
-
- if (gpio_is_valid(pdata->reset_gpio_port[1]))
- gpio_set_value_cansleep(pdata->reset_gpio_port[1], 0);
-
- /* Hold the PHY in RESET for enough time till DIR is high */
- udelay(10);
+ for (i = 0; i < omap->nports; i++) {
+ if (omap->phy[i])
+ usb_phy_shutdown(omap->phy[i]);
}

- /* Soft reset the PHY using PHY reset command over ULPI */
- if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY)
- omap_ehci_soft_phy_reset(hcd, 0);
- if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY)
- omap_ehci_soft_phy_reset(hcd, 1);
-
/* we know this is the memory we want, no need to ioremap again */
ehci->caps = hcd->regs;

rc = ehci_setup(hcd);

- if (pdata->phy_reset) {
- /* Hold the PHY in RESET for enough time till
- * PHY is settled and ready
- */
- udelay(10);
-
- if (gpio_is_valid(pdata->reset_gpio_port[0]))
- gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1);
-
- if (gpio_is_valid(pdata->reset_gpio_port[1]))
- gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
+ /* Bring PHYs out of reset */
+ for (i = 0; i < omap->nports; i++) {
+ if (omap->phy[i])
+ usb_phy_init(omap->phy[i]);
}

return rc;
--
1.7.4.1

2013-03-12 10:45:21

by Roger Quadros

[permalink] [raw]
Subject: [PATCH 05/12] USB: ehci-omap: Remove PHY regulator handling code

PHY regulator handling must be done in the PHY driver

Signed-off-by: Roger Quadros <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Acked-by: Alan Stern <[email protected]>
---
drivers/usb/host/ehci-omap.c | 34 ----------------------------------
1 files changed, 0 insertions(+), 34 deletions(-)

diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 0bbfdc1..57fe985 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -43,7 +43,6 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/usb/ulpi.h>
-#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/gpio.h>
#include <linux/clk.h>
@@ -112,19 +111,6 @@ static int omap_ehci_init(struct usb_hcd *hcd)
return rc;
}

-static void disable_put_regulator(
- struct usbhs_omap_platform_data *pdata)
-{
- int i;
-
- for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
- if (pdata->regulator[i]) {
- regulator_disable(pdata->regulator[i]);
- regulator_put(pdata->regulator[i]);
- }
- }
-}
-
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */

@@ -152,7 +138,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
int ret = -ENODEV;
int irq;
int i;
- char supply[7];
struct omap_hcd *omap;

if (usb_disabled())
@@ -213,23 +198,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
usb_phy_set_suspend(omap->phy[i], 0);
}

- /* get ehci regulator and enable */
- for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
- if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) {
- pdata->regulator[i] = NULL;
- continue;
- }
- snprintf(supply, sizeof(supply), "hsusb%d", i);
- pdata->regulator[i] = regulator_get(dev, supply);
- if (IS_ERR(pdata->regulator[i])) {
- pdata->regulator[i] = NULL;
- dev_dbg(dev,
- "failed to get ehci port%d regulator\n", i);
- } else {
- regulator_enable(pdata->regulator[i]);
- }
- }
-
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);

@@ -255,7 +223,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
return 0;

err_pm_runtime:
- disable_put_regulator(pdata);
pm_runtime_put_sync(dev);

err_phy:
@@ -286,7 +253,6 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)
int i;

usb_remove_hcd(hcd);
- disable_put_regulator(dev->platform_data);

for (i = 0; i < omap->nports; i++) {
if (omap->phy[i])
--
1.7.4.1

2013-03-12 10:45:34

by Roger Quadros

[permalink] [raw]
Subject: [PATCH 09/12] USB: ohci-omap3: Add device tree support and binding information

Allows the OHCI controller found in OMAP3 and later chips to
be specified via device tree.

Signed-off-by: Roger Quadros <[email protected]>
Reviewed-by: Mark Rutland <[email protected]>
Acked-by: Alan Stern <[email protected]>
---
.../devicetree/bindings/usb/ohci-omap3.txt | 15 +++++++++++++++
drivers/usb/host/ohci-omap3.c | 19 +++++++++++++++++++
2 files changed, 34 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/usb/ohci-omap3.txt

diff --git a/Documentation/devicetree/bindings/usb/ohci-omap3.txt b/Documentation/devicetree/bindings/usb/ohci-omap3.txt
new file mode 100644
index 0000000..14ab428
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ohci-omap3.txt
@@ -0,0 +1,15 @@
+OMAP HS USB OHCI controller (OMAP3 and later)
+
+Required properties:
+
+- compatible: should be "ti,ohci-omap3"
+- reg: should contain one register range i.e. start and length
+- interrupts: description of the interrupt line
+
+Example for OMAP4:
+
+usbhsohci: ohci@4a064800 {
+ compatible = "ti,ohci-omap3", "usb-ohci";
+ reg = <0x4a064800 0x400>;
+ interrupts = <0 76 0x4>;
+};
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
index 5ed28c5..ddfc314 100644
--- a/drivers/usb/host/ohci-omap3.c
+++ b/drivers/usb/host/ohci-omap3.c
@@ -31,6 +31,8 @@

#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/dma-mapping.h>

/*-------------------------------------------------------------------------*/

@@ -112,6 +114,8 @@ static const struct hc_driver ohci_omap3_hc_driver = {

/*-------------------------------------------------------------------------*/

+static u64 omap_ohci_dma_mask = DMA_BIT_MASK(32);
+
/*
* configure so an HC device and id are always provided
* always called with process context; sleeping is OK
@@ -159,6 +163,13 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)
return -ENOMEM;
}

+ /*
+ * Right now device-tree probed devices don't get dma_mask set.
+ * Since shared usb code relies on it, set it here for now.
+ * Once we have dma capability bindings this can go away.
+ */
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &omap_ohci_dma_mask;

hcd = usb_create_hcd(&ohci_omap3_hc_driver, dev,
dev_name(dev));
@@ -228,12 +239,20 @@ static void ohci_hcd_omap3_shutdown(struct platform_device *pdev)
hcd->driver->shutdown(hcd);
}

+static const struct of_device_id omap_ohci_dt_ids[] = {
+ { .compatible = "ti,ohci-omap3" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, omap_ohci_dt_ids);
+
static struct platform_driver ohci_hcd_omap3_driver = {
.probe = ohci_hcd_omap3_probe,
.remove = ohci_hcd_omap3_remove,
.shutdown = ohci_hcd_omap3_shutdown,
.driver = {
.name = "ohci-omap3",
+ .of_match_table = of_match_ptr(omap_ohci_dt_ids),
},
};

--
1.7.4.1

2013-03-12 10:45:45

by Roger Quadros

[permalink] [raw]
Subject: [PATCH 12/12] USB: ehci-omap: Fix detection in HSIC mode

The HSIC devices need to be kept in reset while the EHCI controller
is being initialized and only brought out of reset after the
initialization is complete, else HSIC devices will not be detected.

Signed-off-by: Roger Quadros <[email protected]>
CC: Alan Stern <[email protected]>
---
drivers/usb/host/ehci-omap.c | 28 +++++++++++-----------------
1 files changed, 11 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 1ba1df8..52a2d46 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -50,6 +50,7 @@
#include <linux/usb/hcd.h>
#include <linux/of.h>
#include <linux/dma-mapping.h>
+#include <linux/delay.h>

#include "ehci.h"

@@ -90,26 +91,13 @@ static inline u32 ehci_read(void __iomem *base, u32 reg)
static int omap_ehci_init(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- struct omap_hcd *omap = (struct omap_hcd *)ehci->priv;
- int rc, i;
-
- /* Hold PHYs in reset while initializing EHCI controller */
- for (i = 0; i < omap->nports; i++) {
- if (omap->phy[i])
- usb_phy_shutdown(omap->phy[i]);
- }
+ int rc;

/* we know this is the memory we want, no need to ioremap again */
ehci->caps = hcd->regs;

rc = ehci_setup(hcd);

- /* Bring PHYs out of reset */
- for (i = 0; i < omap->nports; i++) {
- if (omap->phy[i])
- usb_phy_init(omap->phy[i]);
- }
-
return rc;
}

@@ -219,9 +207,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
}

omap->phy[i] = phy;
- usb_phy_init(omap->phy[i]);
- /* bring PHY out of suspend */
- usb_phy_set_suspend(omap->phy[i], 0);
}

pm_runtime_enable(dev);
@@ -245,6 +230,15 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
goto err_pm_runtime;
}

+ /* Bring PHYs out of reset */
+ for (i = 0; i < omap->nports; i++) {
+ if (!omap->phy[i])
+ continue;
+
+ usb_phy_init(omap->phy[i]);
+ /* bring PHY out of suspend */
+ usb_phy_set_suspend(omap->phy[i], 0);
+ }

return 0;

--
1.7.4.1

2013-03-12 10:46:32

by Roger Quadros

[permalink] [raw]
Subject: [PATCH 11/12] USB: ehci-omap: Try to get PHY even if not in PHY mode

Even when not in PHY mode, the USB device on the port (e.g. HUB)
might need resources like RESET which can be modelled as a PHY
device. So try to get the PHY device in any case.

Signed-off-by: Roger Quadros <[email protected]>
CC: Alan Stern <[email protected]>
---
drivers/usb/host/ehci-omap.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 45cd01e..1ba1df8 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -202,15 +202,16 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
for (i = 0 ; i < omap->nports ; i++) {
struct usb_phy *phy;

- if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY)
- continue;
-
/* get the PHY device */
if (dev->of_node)
phy = devm_usb_get_phy_by_phandle(dev, "phys", i);
else
phy = devm_usb_get_phy_dev(dev, i);
if (IS_ERR(phy) || !phy) {
+ /* Don't bail out if PHY is not absolutely necessary */
+ if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY)
+ continue;
+
ret = IS_ERR(phy) ? PTR_ERR(phy) : -ENODEV;
dev_err(dev, "Can't get PHY device for port %d: %d\n",
i, ret);
--
1.7.4.1

2013-03-12 10:45:32

by Roger Quadros

[permalink] [raw]
Subject: [PATCH 10/12] USB: ehci-omap: Add device tree support and binding information

Allows the OMAP EHCI controller to be specified via device tree.

Signed-off-by: Roger Quadros <[email protected]>
Reviewed-by: Mark Rutland <[email protected]>
Acked-by: Alan Stern <[email protected]>
---
.../devicetree/bindings/usb/ehci-omap.txt | 32 +++++++++++++++++
drivers/usb/host/ehci-omap.c | 37 +++++++++++++++++++-
2 files changed, 68 insertions(+), 1 deletions(-)
create mode 100644 Documentation/devicetree/bindings/usb/ehci-omap.txt

diff --git a/Documentation/devicetree/bindings/usb/ehci-omap.txt b/Documentation/devicetree/bindings/usb/ehci-omap.txt
new file mode 100644
index 0000000..485a9a1
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ehci-omap.txt
@@ -0,0 +1,32 @@
+OMAP HS USB EHCI controller
+
+This device is usually the child of the omap-usb-host
+Documentation/devicetree/bindings/mfd/omap-usb-host.txt
+
+Required properties:
+
+- compatible: should be "ti,ehci-omap"
+- reg: should contain one register range i.e. start and length
+- interrupts: description of the interrupt line
+
+Optional properties:
+
+- phys: list of phandles to PHY nodes.
+ This property is required if at least one of the ports are in
+ PHY mode i.e. OMAP_EHCI_PORT_MODE_PHY
+
+To specify the port mode, see
+Documentation/devicetree/bindings/mfd/omap-usb-host.txt
+
+Example for OMAP4:
+
+usbhsehci: ehci@4a064c00 {
+ compatible = "ti,ehci-omap", "usb-ehci";
+ reg = <0x4a064c00 0x400>;
+ interrupts = <0 77 0x4>;
+};
+
+&usbhsehci {
+ phys = <&hsusb1_phy 0 &hsusb3_phy>;
+};
+
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 7d05cce..45cd01e 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -48,6 +48,8 @@
#include <linux/clk.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
+#include <linux/of.h>
+#include <linux/dma-mapping.h>

#include "ehci.h"

@@ -121,6 +123,8 @@ static const struct ehci_driver_overrides ehci_omap_overrides __initdata = {
.extra_priv_size = sizeof(struct omap_hcd),
};

+static u64 omap_ehci_dma_mask = DMA_BIT_MASK(32);
+
/**
* ehci_hcd_omap_probe - initialize TI-based HCDs
*
@@ -148,6 +152,17 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
return -ENODEV;
}

+ /* For DT boot, get platform data from parent. i.e. usbhshost */
+ if (dev->of_node) {
+ pdata = dev->parent->platform_data;
+ dev->platform_data = pdata;
+ }
+
+ if (!pdata) {
+ dev_err(dev, "Missing platform data\n");
+ return -ENODEV;
+ }
+
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "EHCI irq failed\n");
@@ -159,6 +174,14 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
if (IS_ERR(regs))
return PTR_ERR(regs);

+ /*
+ * Right now device-tree probed devices don't get dma_mask set.
+ * Since shared usb code relies on it, set it here for now.
+ * Once we have dma capability bindings this can go away.
+ */
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &omap_ehci_dma_mask;
+
hcd = usb_create_hcd(&ehci_omap_hc_driver, dev,
dev_name(dev));
if (!hcd) {
@@ -183,7 +206,10 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
continue;

/* get the PHY device */
- phy = devm_usb_get_phy_dev(dev, i);
+ if (dev->of_node)
+ phy = devm_usb_get_phy_by_phandle(dev, "phys", i);
+ else
+ phy = devm_usb_get_phy_dev(dev, i);
if (IS_ERR(phy) || !phy) {
ret = IS_ERR(phy) ? PTR_ERR(phy) : -ENODEV;
dev_err(dev, "Can't get PHY device for port %d: %d\n",
@@ -273,6 +299,13 @@ static void ehci_hcd_omap_shutdown(struct platform_device *pdev)
hcd->driver->shutdown(hcd);
}

+static const struct of_device_id omap_ehci_dt_ids[] = {
+ { .compatible = "ti,ehci-omap" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, omap_ehci_dt_ids);
+
static struct platform_driver ehci_hcd_omap_driver = {
.probe = ehci_hcd_omap_probe,
.remove = ehci_hcd_omap_remove,
@@ -281,6 +314,7 @@ static struct platform_driver ehci_hcd_omap_driver = {
/*.resume = ehci_hcd_omap_resume, */
.driver = {
.name = hcd_name,
+ .of_match_table = of_match_ptr(omap_ehci_dt_ids),
}
};

@@ -307,6 +341,7 @@ module_exit(ehci_omap_cleanup);
MODULE_ALIAS("platform:ehci-omap");
MODULE_AUTHOR("Texas Instruments, Inc.");
MODULE_AUTHOR("Felipe Balbi <[email protected]>");
+MODULE_AUTHOR("Roger Quadros <[email protected]>");

MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
--
1.7.4.1

2013-03-12 10:45:28

by Roger Quadros

[permalink] [raw]
Subject: [PATCH 08/12] USB: ohci-omap3: Get platform resources by index rather than by name

Since there is only one resource per type we don't really need
to use resource name to obtain it. This also also makes it easier
for device tree adaptation.

Signed-off-by: Roger Quadros <[email protected]>
Acked-by: Alan Stern <[email protected]>
---
drivers/usb/host/ohci-omap3.c | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
index eb35d96..5ed28c5 100644
--- a/drivers/usb/host/ohci-omap3.c
+++ b/drivers/usb/host/ohci-omap3.c
@@ -141,14 +141,13 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)
return -ENODEV;
}

- irq = platform_get_irq_byname(pdev, "ohci-irq");
+ irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "OHCI irq failed\n");
return -ENODEV;
}

- res = platform_get_resource_byname(pdev,
- IORESOURCE_MEM, "ohci");
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "UHH OHCI get resource failed\n");
return -ENOMEM;
--
1.7.4.1

2013-03-12 10:47:37

by Roger Quadros

[permalink] [raw]
Subject: [PATCH 07/12] USB: ehci-omap: Get platform resources by index rather than by name

Since there is only one resource per type we don't really need
to use resource name to obtain it. This also also makes it easier
for device tree adaptation.

Signed-off-by: Roger Quadros <[email protected]>
Acked-by: Alan Stern <[email protected]>
---
drivers/usb/host/ehci-omap.c | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 57fe985..7d05cce 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -148,14 +148,13 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
return -ENODEV;
}

- irq = platform_get_irq_byname(pdev, "ehci-irq");
+ irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "EHCI irq failed\n");
return -ENODEV;
}

- res = platform_get_resource_byname(pdev,
- IORESOURCE_MEM, "ehci");
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(dev, res);
if (IS_ERR(regs))
return PTR_ERR(regs);
--
1.7.4.1

2013-03-12 10:48:09

by Roger Quadros

[permalink] [raw]
Subject: [PATCH 06/12] USB: ehci-omap: Select NOP USB transceiver driver

In PHY mode we need to have the nop-usb-xceiv transceiver
driver to operate, so select it in Kconfig.

Signed-off-by: Roger Quadros <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Acked-by: Alan Stern <[email protected]>
---
drivers/usb/host/Kconfig | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 62f4e9a..2f68221 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -157,6 +157,7 @@ config USB_EHCI_MXC
config USB_EHCI_HCD_OMAP
tristate "EHCI support for OMAP3 and later chips"
depends on USB_EHCI_HCD && ARCH_OMAP
+ select NOP_USB_XCEIV
default y
---help---
Enables support for the on-chip EHCI controller on
--
1.7.4.1

2013-03-12 10:48:41

by Roger Quadros

[permalink] [raw]
Subject: [PATCH 03/12] USB: ehci-omap: Use PHY APIs to get the PHY device and put it out of suspend

For each port that is in PHY mode we obtain a PHY device using the USB PHY
library and put it out of suspend.

It is up to platform code to associate the PHY to the controller's
port and it is up to the PHY driver to manage the PHY's resources.

Also remove weird spacing around declarations we come across.

Signed-off-by: Roger Quadros <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Acked-by: Alan Stern <[email protected]>
---
drivers/usb/host/ehci-omap.c | 76 ++++++++++++++++++++++++++++++++++--------
1 files changed, 62 insertions(+), 14 deletions(-)

diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 70e8e6f..6b8b7e5 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -4,10 +4,11 @@
* Bus Glue for the EHCI controllers in OMAP3/4
* Tested on several OMAP3 boards, and OMAP4 Pandaboard
*
- * Copyright (C) 2007-2011 Texas Instruments, Inc.
+ * Copyright (C) 2007-2013 Texas Instruments, Inc.
* Author: Vikram Pandita <[email protected]>
* Author: Anand Gadiyar <[email protected]>
* Author: Keshava Munegowda <[email protected]>
+ * Author: Roger Quadros <[email protected]>
*
* Copyright (C) 2009 Nokia Corporation
* Contact: Felipe Balbi <[email protected]>
@@ -70,6 +71,10 @@ static const char hcd_name[] = "ehci-omap";

/*-------------------------------------------------------------------------*/

+struct omap_hcd {
+ struct usb_phy *phy[OMAP3_HS_USB_PORTS]; /* one PHY for each port */
+ int nports;
+};

static inline void ehci_write(void __iomem *base, u32 reg, u32 val)
{
@@ -178,7 +183,8 @@ static void disable_put_regulator(
static struct hc_driver __read_mostly ehci_omap_hc_driver;

static const struct ehci_driver_overrides ehci_omap_overrides __initdata = {
- .reset = omap_ehci_init,
+ .reset = omap_ehci_init,
+ .extra_priv_size = sizeof(struct omap_hcd),
};

/**
@@ -190,15 +196,16 @@ static const struct ehci_driver_overrides ehci_omap_overrides __initdata = {
*/
static int ehci_hcd_omap_probe(struct platform_device *pdev)
{
- struct device *dev = &pdev->dev;
- struct usbhs_omap_platform_data *pdata = dev->platform_data;
- struct resource *res;
- struct usb_hcd *hcd;
- void __iomem *regs;
- int ret = -ENODEV;
- int irq;
- int i;
- char supply[7];
+ struct device *dev = &pdev->dev;
+ struct usbhs_omap_platform_data *pdata = dev->platform_data;
+ struct resource *res;
+ struct usb_hcd *hcd;
+ void __iomem *regs;
+ int ret = -ENODEV;
+ int irq;
+ int i;
+ char supply[7];
+ struct omap_hcd *omap;

if (usb_disabled())
return -ENODEV;
@@ -231,6 +238,33 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
hcd->rsrc_len = resource_size(res);
hcd->regs = regs;

+ omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv;
+ omap->nports = pdata->nports;
+
+ platform_set_drvdata(pdev, hcd);
+
+ /* get the PHY devices if needed */
+ for (i = 0 ; i < omap->nports ; i++) {
+ struct usb_phy *phy;
+
+ if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY)
+ continue;
+
+ /* get the PHY device */
+ phy = devm_usb_get_phy_dev(dev, i);
+ if (IS_ERR(phy) || !phy) {
+ ret = IS_ERR(phy) ? PTR_ERR(phy) : -ENODEV;
+ dev_err(dev, "Can't get PHY device for port %d: %d\n",
+ i, ret);
+ goto err_phy;
+ }
+
+ omap->phy[i] = phy;
+ usb_phy_init(omap->phy[i]);
+ /* bring PHY out of suspend */
+ usb_phy_set_suspend(omap->phy[i], 0);
+ }
+
/* get ehci regulator and enable */
for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) {
@@ -275,6 +309,13 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
err_pm_runtime:
disable_put_regulator(pdata);
pm_runtime_put_sync(dev);
+
+err_phy:
+ for (i = 0; i < omap->nports; i++) {
+ if (omap->phy[i])
+ usb_phy_shutdown(omap->phy[i]);
+ }
+
usb_put_hcd(hcd);

return ret;
@@ -291,13 +332,20 @@ err_pm_runtime:
*/
static int ehci_hcd_omap_remove(struct platform_device *pdev)
{
- struct device *dev = &pdev->dev;
- struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct device *dev = &pdev->dev;
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct omap_hcd *omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv;
+ int i;

usb_remove_hcd(hcd);
disable_put_regulator(dev->platform_data);
- usb_put_hcd(hcd);

+ for (i = 0; i < omap->nports; i++) {
+ if (omap->phy[i])
+ usb_phy_shutdown(omap->phy[i]);
+ }
+
+ usb_put_hcd(hcd);
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);

--
1.7.4.1

2013-03-12 10:48:43

by Roger Quadros

[permalink] [raw]
Subject: [PATCH 01/12] USB: EHCI: split ehci-omap out to a separate driver

From: Alan Stern <[email protected]>

This patch (as1645) converts ehci-omap over to the new "ehci-hcd is a
library" approach, so that it can coexist peacefully with other EHCI
platform drivers and can make use of the private area allocated at
the end of struct ehci_hcd.

Signed-off-by: Alan Stern <[email protected]>
---
drivers/usb/host/Kconfig | 2 +-
drivers/usb/host/Makefile | 1 +
drivers/usb/host/ehci-hcd.c | 6 +---
drivers/usb/host/ehci-omap.c | 76 +++++++++++++++++++-----------------------
4 files changed, 37 insertions(+), 48 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index c59a112..62f4e9a 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -155,7 +155,7 @@ config USB_EHCI_MXC
Variation of ARC USB block used in some Freescale chips.

config USB_EHCI_HCD_OMAP
- bool "EHCI support for OMAP3 and later chips"
+ tristate "EHCI support for OMAP3 and later chips"
depends on USB_EHCI_HCD && ARCH_OMAP
default y
---help---
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 001fbff..56de410 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o
obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o
+obj-$(CONFIG_USB_EHCI_HCD_OMAP) += ehci-omap.o

obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index b416a3f..303b022 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1252,11 +1252,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_hcd_sh_driver
#endif

-#ifdef CONFIG_USB_EHCI_HCD_OMAP
-#include "ehci-omap.c"
-#define PLATFORM_DRIVER ehci_hcd_omap_driver
-#endif
-
#ifdef CONFIG_PPC_PS3
#include "ehci-ps3.c"
#define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver
@@ -1346,6 +1341,7 @@ MODULE_LICENSE ("GPL");
!IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
!IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \
!IS_ENABLED(CONFIG_USB_EHCI_MXC) && \
+ !IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \
!defined(PLATFORM_DRIVER) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && \
!defined(OF_PLATFORM_DRIVER) && \
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 0555ee4..fa66757 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -36,6 +36,9 @@
* - convert to use hwmod and runtime PM
*/

+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/usb/ulpi.h>
@@ -43,6 +46,10 @@
#include <linux/pm_runtime.h>
#include <linux/gpio.h>
#include <linux/clk.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ehci.h"

#include <linux/platform_data/usb-omap.h>

@@ -57,9 +64,11 @@
#define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8
#define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0

-/*-------------------------------------------------------------------------*/
+#define DRIVER_DESC "OMAP-EHCI Host Controller driver"

-static const struct hc_driver ehci_omap_hc_driver;
+static const char hcd_name[] = "ehci-omap";
+
+/*-------------------------------------------------------------------------*/


static inline void ehci_write(void __iomem *base, u32 reg, u32 val)
@@ -166,6 +175,12 @@ static void disable_put_regulator(
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */

+static struct hc_driver __read_mostly ehci_omap_hc_driver;
+
+static const struct ehci_driver_overrides ehci_omap_overrides __initdata = {
+ .reset = omap_ehci_init,
+};
+
/**
* ehci_hcd_omap_probe - initialize TI-based HCDs
*
@@ -315,56 +330,33 @@ static struct platform_driver ehci_hcd_omap_driver = {
/*.suspend = ehci_hcd_omap_suspend, */
/*.resume = ehci_hcd_omap_resume, */
.driver = {
- .name = "ehci-omap",
+ .name = hcd_name,
}
};

/*-------------------------------------------------------------------------*/

-static const struct hc_driver ehci_omap_hc_driver = {
- .description = hcd_name,
- .product_desc = "OMAP-EHCI Host Controller",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /*
- * basic lifecycle operations
- */
- .reset = omap_ehci_init,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
+static int __init ehci_omap_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;

- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);

- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
+ ehci_init_driver(&ehci_omap_hc_driver, &ehci_omap_overrides);
+ return platform_driver_register(&ehci_hcd_omap_driver);
+}
+module_init(ehci_omap_init);

- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
+static void __exit ehci_omap_cleanup(void)
+{
+ platform_driver_unregister(&ehci_hcd_omap_driver);
+}
+module_exit(ehci_omap_cleanup);

MODULE_ALIAS("platform:ehci-omap");
MODULE_AUTHOR("Texas Instruments, Inc.");
MODULE_AUTHOR("Felipe Balbi <[email protected]>");

+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
--
1.7.4.1

2013-03-12 10:51:26

by Kishon Vijay Abraham I

[permalink] [raw]
Subject: Re: [PATCH 12/12] USB: ehci-omap: Fix detection in HSIC mode

Hi,

On Tuesday 12 March 2013 04:14 PM, Roger Quadros wrote:
> The HSIC devices need to be kept in reset while the EHCI controller
> is being initialized and only brought out of reset after the
> initialization is complete, else HSIC devices will not be detected.
>
> Signed-off-by: Roger Quadros <[email protected]>
> CC: Alan Stern <[email protected]>
> ---
> drivers/usb/host/ehci-omap.c | 28 +++++++++++-----------------
> 1 files changed, 11 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
> index 1ba1df8..52a2d46 100644
> --- a/drivers/usb/host/ehci-omap.c
> +++ b/drivers/usb/host/ehci-omap.c
> @@ -50,6 +50,7 @@
> #include <linux/usb/hcd.h>
> #include <linux/of.h>
> #include <linux/dma-mapping.h>
> +#include <linux/delay.h>

not needed here I guess.
>
> #include "ehci.h"
>
> @@ -90,26 +91,13 @@ static inline u32 ehci_read(void __iomem *base, u32 reg)
> static int omap_ehci_init(struct usb_hcd *hcd)
> {
> struct ehci_hcd *ehci = hcd_to_ehci(hcd);
> - struct omap_hcd *omap = (struct omap_hcd *)ehci->priv;
> - int rc, i;
> -
> - /* Hold PHYs in reset while initializing EHCI controller */
> - for (i = 0; i < omap->nports; i++) {
> - if (omap->phy[i])
> - usb_phy_shutdown(omap->phy[i]);
> - }
> + int rc;
>
> /* we know this is the memory we want, no need to ioremap again */
> ehci->caps = hcd->regs;
>
> rc = ehci_setup(hcd);
>
> - /* Bring PHYs out of reset */
> - for (i = 0; i < omap->nports; i++) {
> - if (omap->phy[i])
> - usb_phy_init(omap->phy[i]);
> - }
> -
> return rc;
> }
>
> @@ -219,9 +207,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
> }
>
> omap->phy[i] = phy;
> - usb_phy_init(omap->phy[i]);
> - /* bring PHY out of suspend */
> - usb_phy_set_suspend(omap->phy[i], 0);
> }
>
> pm_runtime_enable(dev);
> @@ -245,6 +230,15 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
> goto err_pm_runtime;
> }
>
> + /* Bring PHYs out of reset */
> + for (i = 0; i < omap->nports; i++) {
> + if (!omap->phy[i])
> + continue;
> +
> + usb_phy_init(omap->phy[i]);
> + /* bring PHY out of suspend */
> + usb_phy_set_suspend(omap->phy[i], 0);
> + }

But isn't HSIC supposed to be PHYless devices. Maybe a comment
explaining it might be helpful.

Thanks
Kishon

2013-03-12 10:54:12

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH 12/12] USB: ehci-omap: Fix detection in HSIC mode

On 03/12/2013 12:51 PM, kishon wrote:
> Hi,
>
> On Tuesday 12 March 2013 04:14 PM, Roger Quadros wrote:
>> The HSIC devices need to be kept in reset while the EHCI controller
>> is being initialized and only brought out of reset after the
>> initialization is complete, else HSIC devices will not be detected.
>>
>> Signed-off-by: Roger Quadros <[email protected]>
>> CC: Alan Stern <[email protected]>
>> ---
>> drivers/usb/host/ehci-omap.c | 28 +++++++++++-----------------
>> 1 files changed, 11 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
>> index 1ba1df8..52a2d46 100644
>> --- a/drivers/usb/host/ehci-omap.c
>> +++ b/drivers/usb/host/ehci-omap.c
>> @@ -50,6 +50,7 @@
>> #include <linux/usb/hcd.h>
>> #include <linux/of.h>
>> #include <linux/dma-mapping.h>
>> +#include <linux/delay.h>
>
> not needed here I guess.

Right. will remove.

>>
>> #include "ehci.h"
>>
>> @@ -90,26 +91,13 @@ static inline u32 ehci_read(void __iomem *base, u32 reg)
>> static int omap_ehci_init(struct usb_hcd *hcd)
>> {
>> struct ehci_hcd *ehci = hcd_to_ehci(hcd);
>> - struct omap_hcd *omap = (struct omap_hcd *)ehci->priv;
>> - int rc, i;
>> -
>> - /* Hold PHYs in reset while initializing EHCI controller */
>> - for (i = 0; i < omap->nports; i++) {
>> - if (omap->phy[i])
>> - usb_phy_shutdown(omap->phy[i]);
>> - }
>> + int rc;
>>
>> /* we know this is the memory we want, no need to ioremap again */
>> ehci->caps = hcd->regs;
>>
>> rc = ehci_setup(hcd);
>>
>> - /* Bring PHYs out of reset */
>> - for (i = 0; i < omap->nports; i++) {
>> - if (omap->phy[i])
>> - usb_phy_init(omap->phy[i]);
>> - }
>> -
>> return rc;
>> }
>>
>> @@ -219,9 +207,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
>> }
>>
>> omap->phy[i] = phy;
>> - usb_phy_init(omap->phy[i]);
>> - /* bring PHY out of suspend */
>> - usb_phy_set_suspend(omap->phy[i], 0);
>> }
>>
>> pm_runtime_enable(dev);
>> @@ -245,6 +230,15 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
>> goto err_pm_runtime;
>> }
>>
>> + /* Bring PHYs out of reset */
>> + for (i = 0; i < omap->nports; i++) {
>> + if (!omap->phy[i])
>> + continue;
>> +
>> + usb_phy_init(omap->phy[i]);
>> + /* bring PHY out of suspend */
>> + usb_phy_set_suspend(omap->phy[i], 0);
>> + }
>
> But isn't HSIC supposed to be PHYless devices. Maybe a comment explaining it might be helpful.
>

Yes HSIC is PHYless but they do have reset line between the chips.
I'll put a comment.

cheers,
-roger

2013-03-12 11:09:14

by Roger Quadros

[permalink] [raw]
Subject: [PATCH v2 12/12] USB: ehci-omap: Fix detection in HSIC mode

The HSIC devices need to be kept in reset while the EHCI controller
is being initialized and only brought out of reset after the
initialization is complete, else HSIC devices will not be detected.

Also remove outdated TODO list from header.

Signed-off-by: Roger Quadros <[email protected]>
CC: Alan Stern <[email protected]>
---
drivers/usb/host/ehci-omap.c | 38 +++++++++++++++-----------------------
1 files changed, 15 insertions(+), 23 deletions(-)

diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 1ba1df8..dc2de47 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -29,12 +29,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * TODO (last updated Feb 27, 2010):
- * - add kernel-doc
- * - enable AUTOIDLE
- * - add suspend/resume
- * - add HSIC and TLL support
- * - convert to use hwmod and runtime PM
*/

#include <linux/kernel.h>
@@ -90,26 +84,13 @@ static inline u32 ehci_read(void __iomem *base, u32 reg)
static int omap_ehci_init(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- struct omap_hcd *omap = (struct omap_hcd *)ehci->priv;
- int rc, i;
-
- /* Hold PHYs in reset while initializing EHCI controller */
- for (i = 0; i < omap->nports; i++) {
- if (omap->phy[i])
- usb_phy_shutdown(omap->phy[i]);
- }
+ int rc;

/* we know this is the memory we want, no need to ioremap again */
ehci->caps = hcd->regs;

rc = ehci_setup(hcd);

- /* Bring PHYs out of reset */
- for (i = 0; i < omap->nports; i++) {
- if (omap->phy[i])
- usb_phy_init(omap->phy[i]);
- }
-
return rc;
}

@@ -219,9 +200,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
}

omap->phy[i] = phy;
- usb_phy_init(omap->phy[i]);
- /* bring PHY out of suspend */
- usb_phy_set_suspend(omap->phy[i], 0);
}

pm_runtime_enable(dev);
@@ -245,6 +223,20 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
goto err_pm_runtime;
}

+ /*
+ * Bring PHYs out of reset.
+ * Even though HSIC mode is a PHY-less mode, the reset
+ * line exists between the chips and can be modelled
+ * as a PHY device for reset control.
+ */
+ for (i = 0; i < omap->nports; i++) {
+ if (!omap->phy[i])
+ continue;
+
+ usb_phy_init(omap->phy[i]);
+ /* bring PHY out of suspend */
+ usb_phy_set_suspend(omap->phy[i], 0);
+ }

return 0;

--
1.7.4.1

2013-03-12 15:57:58

by Alan Stern

[permalink] [raw]
Subject: Re: [PATCH 11/12] USB: ehci-omap: Try to get PHY even if not in PHY mode

On Tue, 12 Mar 2013, Roger Quadros wrote:

> Even when not in PHY mode, the USB device on the port (e.g. HUB)
> might need resources like RESET which can be modelled as a PHY
> device. So try to get the PHY device in any case.
>
> Signed-off-by: Roger Quadros <[email protected]>
> CC: Alan Stern <[email protected]>

Acked-by: Alan Stern <[email protected]>

> /* get the PHY device */
> if (dev->of_node)
> phy = devm_usb_get_phy_by_phandle(dev, "phys", i);
> else
> phy = devm_usb_get_phy_dev(dev, i);
> if (IS_ERR(phy) || !phy) {
> + /* Don't bail out if PHY is not absolutely necessary */
> + if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY)
> + continue;
> +
> ret = IS_ERR(phy) ? PTR_ERR(phy) : -ENODEV;
> dev_err(dev, "Can't get PHY device for port %d: %d\n",
> i, ret);

Felipe, this is a strange interface. Why do we sometimes get an
error-pointer and sometimes get just NULL? Why not always an
error-pointer?

Alan Stern

2013-03-12 16:07:05

by Alan Stern

[permalink] [raw]
Subject: Re: [PATCH v2 12/12] USB: ehci-omap: Fix detection in HSIC mode

On Tue, 12 Mar 2013, Roger Quadros wrote:

> The HSIC devices need to be kept in reset while the EHCI controller
> is being initialized and only brought out of reset after the
> initialization is complete, else HSIC devices will not be detected.

This is not a great description of what the patch does. You should say
that it moves PHY initialization until after EHCI initialization is
complete, instead of initializing the PHYs first, shutting them down
again, and then initializing them a second time.

> Also remove outdated TODO list from header.
>
> Signed-off-by: Roger Quadros <[email protected]>
> CC: Alan Stern <[email protected]>
> ---
> drivers/usb/host/ehci-omap.c | 38 +++++++++++++++-----------------------
> 1 files changed, 15 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
> index 1ba1df8..dc2de47 100644
> --- a/drivers/usb/host/ehci-omap.c
> +++ b/drivers/usb/host/ehci-omap.c
> @@ -29,12 +29,6 @@
> * along with this program; if not, write to the Free Software
> * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> *
> - * TODO (last updated Feb 27, 2010):
> - * - add kernel-doc
> - * - enable AUTOIDLE
> - * - add suspend/resume
> - * - add HSIC and TLL support
> - * - convert to use hwmod and runtime PM
> */
>
> #include <linux/kernel.h>
> @@ -90,26 +84,13 @@ static inline u32 ehci_read(void __iomem *base, u32 reg)
> static int omap_ehci_init(struct usb_hcd *hcd)
> {
> struct ehci_hcd *ehci = hcd_to_ehci(hcd);
> - struct omap_hcd *omap = (struct omap_hcd *)ehci->priv;
> - int rc, i;
> -
> - /* Hold PHYs in reset while initializing EHCI controller */
> - for (i = 0; i < omap->nports; i++) {
> - if (omap->phy[i])
> - usb_phy_shutdown(omap->phy[i]);
> - }
> + int rc;
>
> /* we know this is the memory we want, no need to ioremap again */
> ehci->caps = hcd->regs;
>
> rc = ehci_setup(hcd);
>
> - /* Bring PHYs out of reset */
> - for (i = 0; i < omap->nports; i++) {
> - if (omap->phy[i])
> - usb_phy_init(omap->phy[i]);
> - }
> -
> return rc;
> }

Now that there's almost nothing left of this function, you can get rid
of it completely. Move the assignment to ehci->caps into
ehci_hcd_omap_probe() and remove the init entry in the overrides
structure.

Alan Stern

2013-03-13 11:48:25

by Roger Quadros

[permalink] [raw]
Subject: Re: [PATCH v2 12/12] USB: ehci-omap: Fix detection in HSIC mode

On 03/12/2013 06:07 PM, Alan Stern wrote:
> On Tue, 12 Mar 2013, Roger Quadros wrote:
>
>> The HSIC devices need to be kept in reset while the EHCI controller
>> is being initialized and only brought out of reset after the
>> initialization is complete, else HSIC devices will not be detected.
>
> This is not a great description of what the patch does. You should say
> that it moves PHY initialization until after EHCI initialization is
> complete, instead of initializing the PHYs first, shutting them down
> again, and then initializing them a second time.
>

Okay will update the description.

>> Also remove outdated TODO list from header.
>>
>> Signed-off-by: Roger Quadros <[email protected]>
>> CC: Alan Stern <[email protected]>
>> ---
>> drivers/usb/host/ehci-omap.c | 38 +++++++++++++++-----------------------
>> 1 files changed, 15 insertions(+), 23 deletions(-)
>>
>> diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
>> index 1ba1df8..dc2de47 100644
>> --- a/drivers/usb/host/ehci-omap.c
>> +++ b/drivers/usb/host/ehci-omap.c
>> @@ -29,12 +29,6 @@
>> * along with this program; if not, write to the Free Software
>> * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
>> *
>> - * TODO (last updated Feb 27, 2010):
>> - * - add kernel-doc
>> - * - enable AUTOIDLE
>> - * - add suspend/resume
>> - * - add HSIC and TLL support
>> - * - convert to use hwmod and runtime PM
>> */
>>
>> #include <linux/kernel.h>
>> @@ -90,26 +84,13 @@ static inline u32 ehci_read(void __iomem *base, u32 reg)
>> static int omap_ehci_init(struct usb_hcd *hcd)
>> {
>> struct ehci_hcd *ehci = hcd_to_ehci(hcd);
>> - struct omap_hcd *omap = (struct omap_hcd *)ehci->priv;
>> - int rc, i;
>> -
>> - /* Hold PHYs in reset while initializing EHCI controller */
>> - for (i = 0; i < omap->nports; i++) {
>> - if (omap->phy[i])
>> - usb_phy_shutdown(omap->phy[i]);
>> - }
>> + int rc;
>>
>> /* we know this is the memory we want, no need to ioremap again */
>> ehci->caps = hcd->regs;
>>
>> rc = ehci_setup(hcd);
>>
>> - /* Bring PHYs out of reset */
>> - for (i = 0; i < omap->nports; i++) {
>> - if (omap->phy[i])
>> - usb_phy_init(omap->phy[i]);
>> - }
>> -
>> return rc;
>> }
>
> Now that there's almost nothing left of this function, you can get rid
> of it completely. Move the assignment to ehci->caps into
> ehci_hcd_omap_probe() and remove the init entry in the overrides
> structure.

Right. Sounds good.

cheers,
-roger

2013-03-13 13:14:54

by Roger Quadros

[permalink] [raw]
Subject: [PATCH v3 12/13] USB: ehci-omap: Fix detection in HSIC mode

Move PHY initialization until after EHCI initialization is
complete, instead of initializing the PHYs first, shutting
them down again, and then initializing them a second time.

This fixes HSIC device detection.

Signed-off-by: Roger Quadros <[email protected]>
CC: Alan Stern <[email protected]>
---
drivers/usb/host/ehci-omap.c | 32 +++++++++++++++-----------------
1 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 1ba1df8..755b428 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -90,26 +90,13 @@ static inline u32 ehci_read(void __iomem *base, u32 reg)
static int omap_ehci_init(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- struct omap_hcd *omap = (struct omap_hcd *)ehci->priv;
- int rc, i;
-
- /* Hold PHYs in reset while initializing EHCI controller */
- for (i = 0; i < omap->nports; i++) {
- if (omap->phy[i])
- usb_phy_shutdown(omap->phy[i]);
- }
+ int rc;

/* we know this is the memory we want, no need to ioremap again */
ehci->caps = hcd->regs;

rc = ehci_setup(hcd);

- /* Bring PHYs out of reset */
- for (i = 0; i < omap->nports; i++) {
- if (omap->phy[i])
- usb_phy_init(omap->phy[i]);
- }
-
return rc;
}

@@ -219,9 +206,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
}

omap->phy[i] = phy;
- usb_phy_init(omap->phy[i]);
- /* bring PHY out of suspend */
- usb_phy_set_suspend(omap->phy[i], 0);
}

pm_runtime_enable(dev);
@@ -245,6 +229,20 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
goto err_pm_runtime;
}

+ /*
+ * Bring PHYs out of reset.
+ * Even though HSIC mode is a PHY-less mode, the reset
+ * line exists between the chips and can be modelled
+ * as a PHY device for reset control.
+ */
+ for (i = 0; i < omap->nports; i++) {
+ if (!omap->phy[i])
+ continue;
+
+ usb_phy_init(omap->phy[i]);
+ /* bring PHY out of suspend */
+ usb_phy_set_suspend(omap->phy[i], 0);
+ }

return 0;

--
1.7.4.1

2013-03-13 13:16:13

by Roger Quadros

[permalink] [raw]
Subject: [PATCH 13/13] USB: ehci-omap: Get rid of omap_ehci_init()

As it does almost nothing, get rid of omap_ehci_init()
and move the ehci->caps initialization part into probe().

Also remove the outdated TODO list from header.

Signed-off-by: Roger Quadros <[email protected]>
CC: Alan Stern <[email protected]>
---
drivers/usb/host/ehci-omap.c | 21 +--------------------
1 files changed, 1 insertions(+), 20 deletions(-)

diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 755b428..5de3e43 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -29,12 +29,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * TODO (last updated Feb 27, 2010):
- * - add kernel-doc
- * - enable AUTOIDLE
- * - add suspend/resume
- * - add HSIC and TLL support
- * - convert to use hwmod and runtime PM
*/

#include <linux/kernel.h>
@@ -87,26 +81,12 @@ static inline u32 ehci_read(void __iomem *base, u32 reg)
return __raw_readl(base + reg);
}

-static int omap_ehci_init(struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int rc;
-
- /* we know this is the memory we want, no need to ioremap again */
- ehci->caps = hcd->regs;
-
- rc = ehci_setup(hcd);
-
- return rc;
-}
-
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */

static struct hc_driver __read_mostly ehci_omap_hc_driver;

static const struct ehci_driver_overrides ehci_omap_overrides __initdata = {
- .reset = omap_ehci_init,
.extra_priv_size = sizeof(struct omap_hcd),
};

@@ -179,6 +159,7 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res);
hcd->regs = regs;
+ hcd_to_ehci(hcd)->caps = regs;

omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv;
omap->nports = pdata->nports;
--
1.7.4.1

2013-03-13 14:30:18

by Alan Stern

[permalink] [raw]
Subject: Re: [PATCH v3 12/13] USB: ehci-omap: Fix detection in HSIC mode

On Wed, 13 Mar 2013, Roger Quadros wrote:

> Move PHY initialization until after EHCI initialization is
> complete, instead of initializing the PHYs first, shutting
> them down again, and then initializing them a second time.
>
> This fixes HSIC device detection.
>
> Signed-off-by: Roger Quadros <[email protected]>
> CC: Alan Stern <[email protected]>

Acked-by: Alan Stern <[email protected]>

2013-03-13 14:32:18

by Alan Stern

[permalink] [raw]
Subject: Re: [PATCH 13/13] USB: ehci-omap: Get rid of omap_ehci_init()

On Wed, 13 Mar 2013, Roger Quadros wrote:

> As it does almost nothing, get rid of omap_ehci_init()
> and move the ehci->caps initialization part into probe().
>
> Also remove the outdated TODO list from header.
>
> Signed-off-by: Roger Quadros <[email protected]>
> CC: Alan Stern <[email protected]>

Acked-by: Alan Stern <[email protected]>

2013-03-14 14:08:48

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH 11/12] USB: ehci-omap: Try to get PHY even if not in PHY mode

On Tue, Mar 12, 2013 at 11:57:56AM -0400, Alan Stern wrote:
> On Tue, 12 Mar 2013, Roger Quadros wrote:
>
> > Even when not in PHY mode, the USB device on the port (e.g. HUB)
> > might need resources like RESET which can be modelled as a PHY
> > device. So try to get the PHY device in any case.
> >
> > Signed-off-by: Roger Quadros <[email protected]>
> > CC: Alan Stern <[email protected]>
>
> Acked-by: Alan Stern <[email protected]>
>
> > /* get the PHY device */
> > if (dev->of_node)
> > phy = devm_usb_get_phy_by_phandle(dev, "phys", i);
> > else
> > phy = devm_usb_get_phy_dev(dev, i);
> > if (IS_ERR(phy) || !phy) {
> > + /* Don't bail out if PHY is not absolutely necessary */
> > + if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY)
> > + continue;
> > +
> > ret = IS_ERR(phy) ? PTR_ERR(phy) : -ENODEV;
> > dev_err(dev, "Can't get PHY device for port %d: %d\n",
> > i, ret);
>
> Felipe, this is a strange interface. Why do we sometimes get an
> error-pointer and sometimes get just NULL? Why not always an
> error-pointer?

looks like we get NULL when PHY layer is disabled. Sounds like an
oversight to me. Do you want to send a patch, or do I cook one and put
yourself as Reported-by ?

--
balbi


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

2013-03-14 15:08:54

by Alan Stern

[permalink] [raw]
Subject: Re: [PATCH 11/12] USB: ehci-omap: Try to get PHY even if not in PHY mode

On Thu, 14 Mar 2013, Felipe Balbi wrote:

> > > if (IS_ERR(phy) || !phy) {
> > > + /* Don't bail out if PHY is not absolutely necessary */
> > > + if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY)
> > > + continue;
> > > +
> > > ret = IS_ERR(phy) ? PTR_ERR(phy) : -ENODEV;
> > > dev_err(dev, "Can't get PHY device for port %d: %d\n",
> > > i, ret);
> >
> > Felipe, this is a strange interface. Why do we sometimes get an
> > error-pointer and sometimes get just NULL? Why not always an
> > error-pointer?
>
> looks like we get NULL when PHY layer is disabled. Sounds like an
> oversight to me. Do you want to send a patch, or do I cook one and put
> yourself as Reported-by ?

You're more familiar with that code. "Reported-by" is good enough for
me. :-)

Alan Stern