2016-10-07 16:47:31

by Axel Haslam

[permalink] [raw]
Subject: [PATCH/RFT 00/12] Add DT support for ohci-da8xx

From: Axel Haslam <[email protected]>

The purpose of this patch series is to add DT support to the ohci-da8xx
glue driver without breaking the non-DT boot, which is still used in
unconverted davinci devices.

To Achieve this, the first 8 patches make sure that the non-DT based
enumeration works, and prepares the stage for a DT migration by removing
dependencies on the board files (moving VBUS, and over current
handling to the driver). The last 4 patches actually add the DT
documentation and bindings for the ohci-da8xx driver.

Testing was done on a omap138-lcdk board, using DT, and non-DT boot,
and checking that in both cases the hub, usb mass storage and an input
device are correctly enumerated and working.

Since there have been some recent and ongoing efforts from David Lechner
to clean up davinci-mach code and the ochi-da8xx driver, this series
builds upon that work. Specifically:

* the accepted but soon to be reposted patch to remove mach code form
the ohci driver[1].

* The patch series to add phy nodes, and move usb clocks to a common
file [2].

A git branch based on tag: next-20161004 with the dependencies patches is
available in my github here [3].

The omap138-lcdk does not have gpios to control vbus and get over current
interrupt notifications, hence i was not able to test these and added
the RFT tag. If anyone has a da830-evm based board and could
confirm that ohci is correctly working, i would appreciate it.
(the OHCI option needs to be enabled in menuconfig)

P.D: It seems that the davinci-gpio driver is broken for DT based boot
and any gpio > 32. (luckly none of the DT based boards use gpios yet)
The probelm is that we have 144 gpios in the gpio controller as correctly
declared on the DT (they are not separate gpio controllers as in am3xx),
but the driver creates several gpio chips of 32 pins each, confusing the
"gpio chip to pin" matching logic of gpiolib-of. I think we might need to
fix this by creating a single gpio chip in gpio-davinci.c

[1] [PATCH v6 1/3] usb: ohci-da8xx: Remove code that references mach
http://www.gossamer-threads.com/lists/linux/kernel/2518807
[2] [PATCH v5 0/5] da8xx USB PHY platform devices and clocks (was "da8xx UBS clocks")
http://www.spinics.net/lists/linux-usb/msg140568.html
[3] github branch with all dependante patches
https://github.com/axelhaslamx/linux-axel/commits/ohci-da8xx-dt

Axel Haslam (12):
ARM: davinci: da8xx: Enable the usb20 "per" clk on phy_clk_enable
ARM: davinci: hawk: add full constraints for ohci plat boot
ARM: davinci: rename root_hub to platform_data
USB: ohci-da8xx: Divide power up time in the ohci driver
USB: ohci-da8xx: Fix probe for devices with no vbus/oci gpio
ARM: davinci: hawk: Remove oci and vbus gpios
USB: ohci-da8xx: Request gpios and handle interrupt in the driver
ARM: davinci: register the usb20_phy clock on the SoC file
usb: host: ohci-da8xx: Add devicetree bindings documentation
USB: ohci-da8xx: Add device tree support
ARM: dts: da850: Add the usb ohci device node
ARM: dts: da850-lcdk: enable ohci usb

.../devicetree/bindings/usb/ohci-da8xx.txt | 32 +++++
arch/arm/boot/dts/da850-lcdk.dts | 9 ++
arch/arm/boot/dts/da850.dtsi | 8 ++
arch/arm/mach-davinci/board-da830-evm.c | 75 +---------
arch/arm/mach-davinci/board-omapl138-hawk.c | 105 +-------------
arch/arm/mach-davinci/da850.c | 2 +
arch/arm/mach-davinci/include/mach/da8xx.h | 2 +-
arch/arm/mach-davinci/usb-da8xx.c | 15 +-
drivers/usb/host/ohci-da8xx.c | 158 +++++++++++++++++----
include/linux/platform_data/usb-davinci.h | 22 ++-
10 files changed, 218 insertions(+), 210 deletions(-)
create mode 100644 Documentation/devicetree/bindings/usb/ohci-da8xx.txt

--
2.7.1


2016-10-07 16:43:42

by Axel Haslam

[permalink] [raw]
Subject: [PATCH/RFT 01/12] ARM: davinci: da8xx: Enable the usb20 "per" clk on phy_clk_enable

From: Axel Haslam <[email protected]>

While probing ochi phy with usb20 phy as a parent clock for usb11_phy,
the usb20_phy clock enable would time out. This is because the usb20
module clock needs to enabled while trying to lock the usb20_phy PLL.

Call clk enable and get for the usb20 peripheral before trying to
enable the phy PLL.

Signed-off-by: Axel Haslam <[email protected]>
---
arch/arm/mach-davinci/usb-da8xx.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-davinci/usb-da8xx.c b/arch/arm/mach-davinci/usb-da8xx.c
index 9e41a7f..982e105 100644
--- a/arch/arm/mach-davinci/usb-da8xx.c
+++ b/arch/arm/mach-davinci/usb-da8xx.c
@@ -53,11 +53,19 @@ int __init da8xx_register_usb_refclkin(int rate)

static void usb20_phy_clk_enable(struct clk *clk)
{
+ struct clk *usb20_clk;
u32 val;
u32 timeout = 500000; /* 500 msec */

val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));

+ usb20_clk = clk_get(NULL, "usb20");
+ if (IS_ERR(usb20_clk)) {
+ pr_err("could not get usb20 clk\n");
+ return;
+ }
+
+ clk_prepare_enable(usb20_clk);
/*
* Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
* host may use the PLL clock without USB 2.0 OTG being used.
@@ -70,11 +78,14 @@ static void usb20_phy_clk_enable(struct clk *clk)
while (--timeout) {
val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
if (val & CFGCHIP2_PHYCLKGD)
- return;
+ goto done;
udelay(1);
}

pr_err("Timeout waiting for USB 2.0 PHY clock good.\n");
+done:
+ clk_disable_unprepare(usb20_clk);
+ clk_put(usb20_clk);
}

static void usb20_phy_clk_disable(struct clk *clk)
--
2.7.1

2016-10-07 16:43:52

by Axel Haslam

[permalink] [raw]
Subject: [PATCH/RFT 06/12] ARM: davinci: hawk: Remove oci and vbus gpios

From: Axel Haslam <[email protected]>

The omap138-lcdk and its predecessor the hawk board don't have gpios
connected to control vbus or get the over current notifications for usb.
for example, in the hawk board gpio6-13 is connected to a LED, and
gpio2-4 is not connected at all. In the lcdk board, gpio 2-4 is a push
button, and gpio6-13 is connected to a LED.

Remove the gpio and interrupt registration for these pins.

Signed-off-by: Axel Haslam <[email protected]>
---
arch/arm/mach-davinci/board-omapl138-hawk.c | 78 +----------------------------
1 file changed, 1 insertion(+), 77 deletions(-)

diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
index f9cd388..075be1b 100644
--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
+++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
@@ -28,9 +28,6 @@
#define DA850_HAWK_MMCSD_CD_PIN GPIO_TO_PIN(3, 12)
#define DA850_HAWK_MMCSD_WP_PIN GPIO_TO_PIN(3, 13)

-#define DA850_USB1_VBUS_PIN GPIO_TO_PIN(2, 4)
-#define DA850_USB1_OC_PIN GPIO_TO_PIN(6, 13)
-
static short omapl138_hawk_mii_pins[] __initdata = {
DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3,
DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER,
@@ -181,66 +178,16 @@ static __init void omapl138_hawk_mmc_init(void)
gpio_free(DA850_HAWK_MMCSD_CD_PIN);
}

-static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id);
-static da8xx_ocic_handler_t hawk_usb_ocic_handler;
-
static const short da850_hawk_usb11_pins[] = {
DA850_GPIO2_4, DA850_GPIO6_13,
-1
};

-static int hawk_usb_set_power(unsigned port, int on)
-{
- gpio_set_value(DA850_USB1_VBUS_PIN, on);
- return 0;
-}
-
-static int hawk_usb_get_power(unsigned port)
-{
- return gpio_get_value(DA850_USB1_VBUS_PIN);
-}
-
-static int hawk_usb_get_oci(unsigned port)
-{
- return !gpio_get_value(DA850_USB1_OC_PIN);
-}
-
-static int hawk_usb_ocic_notify(da8xx_ocic_handler_t handler)
-{
- int irq = gpio_to_irq(DA850_USB1_OC_PIN);
- int error = 0;
-
- if (handler != NULL) {
- hawk_usb_ocic_handler = handler;
-
- error = request_irq(irq, omapl138_hawk_usb_ocic_irq,
- IRQF_TRIGGER_RISING |
- IRQF_TRIGGER_FALLING,
- "OHCI over-current indicator", NULL);
- if (error)
- pr_err("%s: could not request IRQ to watch "
- "over-current indicator changes\n", __func__);
- } else {
- free_irq(irq, NULL);
- }
- return error;
-}
-
static struct da8xx_ohci_platform_data omapl138_hawk_usb11_pdata = {
- .set_power = hawk_usb_set_power,
- .get_power = hawk_usb_get_power,
- .get_oci = hawk_usb_get_oci,
- .ocic_notify = hawk_usb_ocic_notify,
/* TPS2087 switch @ 5V */
.potpgt = 3 /* 3 ms max */
};

-static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id)
-{
- hawk_usb_ocic_handler(&omapl138_hawk_usb11_pdata, 1);
- return IRQ_HANDLED;
-}
-
static __init void omapl138_hawk_usb_init(void)
{
int ret;
@@ -266,34 +213,11 @@ static __init void omapl138_hawk_usb_init(void)
pr_warn("%s: USB PHY registration failed: %d\n",
__func__, ret);

- ret = gpio_request_one(DA850_USB1_VBUS_PIN,
- GPIOF_DIR_OUT, "USB1 VBUS");
- if (ret < 0) {
- pr_err("%s: failed to request GPIO for USB 1.1 port "
- "power control: %d\n", __func__, ret);
- return;
- }
-
- ret = gpio_request_one(DA850_USB1_OC_PIN,
- GPIOF_DIR_IN, "USB1 OC");
- if (ret < 0) {
- pr_err("%s: failed to request GPIO for USB 1.1 port "
- "over-current indicator: %d\n", __func__, ret);
- goto usb11_setup_oc_fail;
- }
-
ret = da8xx_register_usb11(&omapl138_hawk_usb11_pdata);
- if (ret) {
+ if (ret)
pr_warn("%s: USB 1.1 registration failed: %d\n", __func__, ret);
- goto usb11_setup_fail;
- }

return;
-
-usb11_setup_fail:
- gpio_free(DA850_USB1_OC_PIN);
-usb11_setup_oc_fail:
- gpio_free(DA850_USB1_VBUS_PIN);
}

static __init void omapl138_hawk_init(void)
--
2.7.1

2016-10-07 16:44:04

by Axel Haslam

[permalink] [raw]
Subject: [PATCH/RFT 04/12] USB: ohci-da8xx: Divide power up time in the ohci driver

From: Axel Haslam <[email protected]>

Instead of requiring platform data to know that the effective time
should be diveded by two, Make that operation in the driver so that
users (platform board files/Device tree) dont have to worry about it.

Signed-off-by: Axel Haslam <[email protected]>
---
arch/arm/mach-davinci/board-da830-evm.c | 2 +-
arch/arm/mach-davinci/board-omapl138-hawk.c | 2 +-
drivers/usb/host/ohci-da8xx.c | 8 ++++++--
3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index 18d2b10..8d126e4 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -94,7 +94,7 @@ static struct da8xx_ohci_platform_data da830_evm_usb11_pdata = {
.ocic_notify = da830_evm_usb_ocic_notify,

/* TPS2065 switch @ 5V */
- .potpgt = (3 + 1) / 2, /* 3 ms max */
+ .potpgt = 3, /* 3 ms max */
};

static irqreturn_t da830_evm_usb_ocic_irq(int irq, void *dev_id)
diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
index a2bf3eb..f9cd388 100644
--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
+++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
@@ -232,7 +232,7 @@ static struct da8xx_ohci_platform_data omapl138_hawk_usb11_pdata = {
.get_oci = hawk_usb_get_oci,
.ocic_notify = hawk_usb_ocic_notify,
/* TPS2087 switch @ 5V */
- .potpgt = (3 + 1) / 2, /* 3 ms max */
+ .potpgt = 3 /* 3 ms max */
};

static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id)
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index 8ed9a52..3c85d6c 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -115,8 +115,12 @@ static int ohci_da8xx_init(struct usb_hcd *hcd)
rh_a &= ~RH_A_NOCP;
rh_a |= RH_A_OCPM;
}
- rh_a &= ~RH_A_POTPGT;
- rh_a |= pdata->potpgt << 24;
+
+ if (pdata->potpgt) {
+ rh_a &= ~RH_A_POTPGT;
+ rh_a |= (DIV_ROUND_UP(pdata->potpgt, 2) << 24);
+ }
+
ohci_writel(ohci, rh_a, &ohci->regs->roothub.a);

return result;
--
2.7.1

2016-10-07 16:44:13

by Axel Haslam

[permalink] [raw]
Subject: [PATCH/RFT 03/12] ARM: davinci: rename root_hub to platform_data

From: Axel Haslam <[email protected]>

To prepare for DT support we will remove the usb callback function
pointers. Since this structure will only pass data to the driver, It
seems better to rename the structure root_hub structure to platform_data

There is no functional change.

Signed-off-by: Axel Haslam <[email protected]>
---
arch/arm/mach-davinci/board-da830-evm.c | 2 +-
arch/arm/mach-davinci/board-omapl138-hawk.c | 2 +-
arch/arm/mach-davinci/include/mach/da8xx.h | 2 +-
arch/arm/mach-davinci/usb-da8xx.c | 2 +-
drivers/usb/host/ohci-da8xx.c | 36 ++++++++++++++---------------
include/linux/platform_data/usb-davinci.h | 6 ++---
6 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index c62766e..18d2b10 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -87,7 +87,7 @@ static int da830_evm_usb_ocic_notify(da8xx_ocic_handler_t handler)
return error;
}

-static struct da8xx_ohci_root_hub da830_evm_usb11_pdata = {
+static struct da8xx_ohci_platform_data da830_evm_usb11_pdata = {
.set_power = da830_evm_usb_set_power,
.get_power = da830_evm_usb_get_power,
.get_oci = da830_evm_usb_get_oci,
diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
index 1dc6112..a2bf3eb 100644
--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
+++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
@@ -226,7 +226,7 @@ static int hawk_usb_ocic_notify(da8xx_ocic_handler_t handler)
return error;
}

-static struct da8xx_ohci_root_hub omapl138_hawk_usb11_pdata = {
+static struct da8xx_ohci_platform_data omapl138_hawk_usb11_pdata = {
.set_power = hawk_usb_set_power,
.get_power = hawk_usb_get_power,
.get_oci = hawk_usb_get_oci,
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index 38d932e..f7d6fd9 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -94,7 +94,7 @@ int da8xx_register_usb20_phy_clk(bool use_usb_refclkin);
int da8xx_register_usb11_phy_clk(bool use_usb_refclkin);
int da8xx_register_usb_phy(void);
int da8xx_register_usb20(unsigned mA, unsigned potpgt);
-int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata);
+int da8xx_register_usb11(struct da8xx_ohci_platform_data *pdata);
int da8xx_register_emac(void);
int da8xx_register_uio_pruss(void);
int da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata);
diff --git a/arch/arm/mach-davinci/usb-da8xx.c b/arch/arm/mach-davinci/usb-da8xx.c
index 982e105..36e3460 100644
--- a/arch/arm/mach-davinci/usb-da8xx.c
+++ b/arch/arm/mach-davinci/usb-da8xx.c
@@ -337,7 +337,7 @@ static struct platform_device da8xx_usb11_device = {
.resource = da8xx_usb11_resources,
};

-int __init da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata)
+int __init da8xx_register_usb11(struct da8xx_ohci_platform_data *pdata)
{
da8xx_usb11_device.dev.platform_data = pdata;
return platform_device_register(&da8xx_usb11_device);
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index 3656d7c..8ed9a52 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -64,20 +64,20 @@ static void ohci_da8xx_disable(void)
/*
* Handle the port over-current indicator change.
*/
-static void ohci_da8xx_ocic_handler(struct da8xx_ohci_root_hub *hub,
+static void ohci_da8xx_ocic_handler(struct da8xx_ohci_platform_data *pdata,
unsigned port)
{
ocic_mask |= 1 << port;

/* Once over-current is detected, the port needs to be powered down */
- if (hub->get_oci(port) > 0)
- hub->set_power(port, 0);
+ if (pdata->get_oci(port) > 0)
+ pdata->set_power(port, 0);
}

static int ohci_da8xx_init(struct usb_hcd *hcd)
{
struct device *dev = hcd->self.controller;
- struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
+ struct da8xx_ohci_platform_data *pdata = dev_get_platdata(dev);
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
int result;
u32 rh_a;
@@ -107,16 +107,16 @@ static int ohci_da8xx_init(struct usb_hcd *hcd)
* the correct hub descriptor...
*/
rh_a = ohci_readl(ohci, &ohci->regs->roothub.a);
- if (hub->set_power) {
+ if (pdata->set_power) {
rh_a &= ~RH_A_NPS;
rh_a |= RH_A_PSM;
}
- if (hub->get_oci) {
+ if (pdata->get_oci) {
rh_a &= ~RH_A_NOCP;
rh_a |= RH_A_OCPM;
}
rh_a &= ~RH_A_POTPGT;
- rh_a |= hub->potpgt << 24;
+ rh_a |= pdata->potpgt << 24;
ohci_writel(ohci, rh_a, &ohci->regs->roothub.a);

return result;
@@ -167,7 +167,7 @@ static int ohci_da8xx_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
u16 wIndex, char *buf, u16 wLength)
{
struct device *dev = hcd->self.controller;
- struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
+ struct da8xx_ohci_platform_data *pdata = dev_get_platdata(dev);
int temp;

switch (typeReq) {
@@ -181,11 +181,11 @@ static int ohci_da8xx_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
temp = roothub_portstatus(hcd_to_ohci(hcd), wIndex - 1);

/* The port power status (PPS) bit defaults to 1 */
- if (hub->get_power && hub->get_power(wIndex) == 0)
+ if (pdata->get_power && pdata->get_power(wIndex) == 0)
temp &= ~RH_PS_PPS;

/* The port over-current indicator (POCI) bit is always 0 */
- if (hub->get_oci && hub->get_oci(wIndex) > 0)
+ if (pdata->get_oci && pdata->get_oci(wIndex) > 0)
temp |= RH_PS_POCI;

/* The over-current indicator change (OCIC) bit is 0 too */
@@ -210,10 +210,10 @@ static int ohci_da8xx_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
dev_dbg(dev, "%sPortFeature(%u): %s\n",
temp ? "Set" : "Clear", wIndex, "POWER");

- if (!hub->set_power)
+ if (!pdata->set_power)
return -EPIPE;

- return hub->set_power(wIndex, temp) ? -EPIPE : 0;
+ return pdata->set_power(wIndex, temp) ? -EPIPE : 0;
case USB_PORT_FEAT_C_OVER_CURRENT:
dev_dbg(dev, "%sPortFeature(%u): %s\n",
temp ? "Set" : "Clear", wIndex,
@@ -288,12 +288,12 @@ static const struct hc_driver ohci_da8xx_hc_driver = {
static int usb_hcd_da8xx_probe(const struct hc_driver *driver,
struct platform_device *pdev)
{
- struct da8xx_ohci_root_hub *hub = dev_get_platdata(&pdev->dev);
+ struct da8xx_ohci_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct usb_hcd *hcd;
struct resource *mem;
int error, irq;

- if (hub == NULL)
+ if (pdata == NULL)
return -ENODEV;

usb11_clk = devm_clk_get(&pdev->dev, "usb11");
@@ -337,8 +337,8 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver,

device_wakeup_enable(hcd->self.controller);

- if (hub->ocic_notify) {
- error = hub->ocic_notify(ohci_da8xx_ocic_handler);
+ if (pdata->ocic_notify) {
+ error = pdata->ocic_notify(ohci_da8xx_ocic_handler);
if (!error)
return 0;
}
@@ -361,9 +361,9 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver,
static inline void
usb_hcd_da8xx_remove(struct usb_hcd *hcd, struct platform_device *pdev)
{
- struct da8xx_ohci_root_hub *hub = dev_get_platdata(&pdev->dev);
+ struct da8xx_ohci_platform_data *pdata = dev_get_platdata(&pdev->dev);

- hub->ocic_notify(NULL);
+ pdata->ocic_notify(NULL);
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
}
diff --git a/include/linux/platform_data/usb-davinci.h b/include/linux/platform_data/usb-davinci.h
index e0bc4ab..dffe3bf 100644
--- a/include/linux/platform_data/usb-davinci.h
+++ b/include/linux/platform_data/usb-davinci.h
@@ -34,13 +34,13 @@
#define CFGCHIP2_REFFREQ_24MHZ (2 << 0)
#define CFGCHIP2_REFFREQ_48MHZ (3 << 0)

-struct da8xx_ohci_root_hub;
+struct da8xx_ohci_platform_data;

-typedef void (*da8xx_ocic_handler_t)(struct da8xx_ohci_root_hub *hub,
+typedef void (*da8xx_ocic_handler_t)(struct da8xx_ohci_platform_data *pdata,
unsigned port);

/* Passed as the platform data to the OHCI driver */
-struct da8xx_ohci_root_hub {
+struct da8xx_ohci_platform_data {
/* Switch the port power on/off */
int (*set_power)(unsigned port, int on);
/* Read the port power status */
--
2.7.1

2016-10-07 16:44:23

by Axel Haslam

[permalink] [raw]
Subject: [PATCH/RFT 02/12] ARM: davinci: hawk: add full constraints for ohci plat boot

From: Axel Haslam <[email protected]>

The phy framework requests an optional "phy" regulator. If it does
not find one, it returns -EPROBE_DEFER. In the case of non-DT based boot
for the omap138-lcdk board, this would prevent the usb11 phy to probe
correctly and ohci would not enumerate.

By calling "regulator_has_full_constraints", An error would be returned
instead of DEFER for the "optional" regulator, and the probe of
the phy driver can continue normally without a regulator.

Signed-off-by: Axel Haslam <[email protected]>
---
arch/arm/mach-davinci/board-omapl138-hawk.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
index c5cb8d9..1dc6112 100644
--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
+++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
@@ -14,6 +14,7 @@
#include <linux/console.h>
#include <linux/gpio.h>
#include <linux/platform_data/gpio-davinci.h>
+#include <linux/regulator/machine.h>

#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -328,6 +329,7 @@ static __init void omapl138_hawk_init(void)
if (ret)
pr_warn("%s: dsp/rproc registration failed: %d\n",
__func__, ret);
+ regulator_has_full_constraints();
}

#ifdef CONFIG_SERIAL_8250_CONSOLE
--
2.7.1

2016-10-07 16:45:12

by Axel Haslam

[permalink] [raw]
Subject: [PATCH/RFT 12/12] ARM: dts: da850-lcdk: enable ohci usb

From: Axel Haslam <[email protected]>

This enables the ohci usb controller for the lcdk board.

Signed-off-by: Axel Haslam <[email protected]>
---
arch/arm/boot/dts/da850-lcdk.dts | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/da850-lcdk.dts b/arch/arm/boot/dts/da850-lcdk.dts
index 7b8ab21..6da9d843 100644
--- a/arch/arm/boot/dts/da850-lcdk.dts
+++ b/arch/arm/boot/dts/da850-lcdk.dts
@@ -86,6 +86,15 @@
};
};

+&usb_phy {
+ status = "okay";
+};
+
+&usb11 {
+ status = "okay";
+ power-on-delay = <3>;
+};
+
&serial2 {
pinctrl-names = "default";
pinctrl-0 = <&serial2_rxtx_pins>;
--
2.7.1

2016-10-07 16:45:20

by Axel Haslam

[permalink] [raw]
Subject: [PATCH/RFT 11/12] ARM: dts: da850: Add the usb ohci device node

From: Axel Haslam <[email protected]>

This adds the device tree node for the usb11 (ohci)
controller present in the da850 family of SoC's.

Signed-off-by: Axel Haslam <[email protected]>
---
arch/arm/boot/dts/da850.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
index 33fcdce..afae565 100644
--- a/arch/arm/boot/dts/da850.dtsi
+++ b/arch/arm/boot/dts/da850.dtsi
@@ -381,6 +381,14 @@
#phy-cells = <1>;
status = "disabled";
};
+ usb11: usb11@0225000 {
+ compatible = "ti,da830-ohci";
+ reg = <0x225000 0x1000>;
+ interrupts = <59>;
+ phys = <&usb_phy 1>;
+ phy-names = "usb-phy";
+ status = "disabled";
+ };
gpio: gpio@226000 {
compatible = "ti,dm6441-gpio";
gpio-controller;
--
2.7.1

2016-10-07 16:45:36

by Axel Haslam

[permalink] [raw]
Subject: [PATCH/RFT 08/12] ARM: davinci: register the usb20_phy clock on the SoC file

From: Axel Haslam <[email protected]>

The usb20_phy clock needs to be registered for the driver to be able
to get and enable a clock. Currently the usb phy clocks are registered
form board files, which will not be called during a device tree based
boot.

To be able to probe correctly usb form a device tree boot, register
the usb phy clocks form the SoC specific init.

Unfourtunatly, davinci does not have proper clock support on device tree
yet, so by registering the clock form de SoC specific file we are
forced to hardcode the parent clock, and cannot select refclkin as
parent for any of the phy clocks of the da850 family.

As none of the current da850 based boards currently in mainline use
refclkin as source. I guess we can live with this limitation until clocks
are correctly represented through CCF/device tree.

Signed-off-by: Axel Haslam <[email protected]>
---
arch/arm/mach-davinci/board-omapl138-hawk.c | 10 ----------
arch/arm/mach-davinci/da850.c | 2 ++
2 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
index 8d72bc1..a78fa16 100644
--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
+++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
@@ -187,16 +187,6 @@ static __init void omapl138_hawk_usb_init(void)
{
int ret;

- /* USB_REFCLKIN is not used. */
- ret = da8xx_register_usb20_phy_clk(false);
- if (ret)
- pr_warn("%s: USB 2.0 PHY CLK registration failed: %d\n",
- __func__, ret);
- ret = da8xx_register_usb11_phy_clk(false);
- if (ret)
- pr_warn("%s: USB 1.1 PHY CLK registration failed: %d\n",
- __func__, ret);
-
ret = da8xx_register_usb_phy();
if (ret)
pr_warn("%s: USB PHY registration failed: %d\n",
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index ed3d0e9..621880d 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -1350,4 +1350,6 @@ void __init da850_init(void)
__raw_writel(v, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));

davinci_clk_init(davinci_soc_info_da850.cpu_clks);
+ da8xx_register_usb20_phy_clk(false);
+ da8xx_register_usb11_phy_clk(false);
}
--
2.7.1

2016-10-07 16:45:34

by Axel Haslam

[permalink] [raw]
Subject: [PATCH/RFT 07/12] USB: ohci-da8xx: Request gpios and handle interrupt in the driver

From: Axel Haslam <[email protected]>

Currently requesting the vbus and overcurrent gpio is handled on
the board specific file. But this does not play well moving to
device tree.

In preparation to migrate to a device tree boot, handle requesting
gpios and overcurrent interrupt on the usb driver itself, thus avoiding
callbacks to arch/mach*

Signed-off-by: Axel Haslam <[email protected]>
---
arch/arm/mach-davinci/board-da830-evm.c | 71 ++---------------------
arch/arm/mach-davinci/board-omapl138-hawk.c | 11 ----
drivers/usb/host/ohci-da8xx.c | 90 +++++++++++++++++++++++------
include/linux/platform_data/usb-davinci.h | 16 +++--
4 files changed, 82 insertions(+), 106 deletions(-)

diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index 8d126e4..cfba9fa 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -47,62 +47,15 @@ static const short da830_evm_usb11_pins[] = {
-1
};

-static da8xx_ocic_handler_t da830_evm_usb_ocic_handler;
-
-static int da830_evm_usb_set_power(unsigned port, int on)
-{
- gpio_set_value(ON_BD_USB_DRV, on);
- return 0;
-}
-
-static int da830_evm_usb_get_power(unsigned port)
-{
- return gpio_get_value(ON_BD_USB_DRV);
-}
-
-static int da830_evm_usb_get_oci(unsigned port)
-{
- return !gpio_get_value(ON_BD_USB_OVC);
-}
-
-static irqreturn_t da830_evm_usb_ocic_irq(int, void *);
-
-static int da830_evm_usb_ocic_notify(da8xx_ocic_handler_t handler)
-{
- int irq = gpio_to_irq(ON_BD_USB_OVC);
- int error = 0;
-
- if (handler != NULL) {
- da830_evm_usb_ocic_handler = handler;
-
- error = request_irq(irq, da830_evm_usb_ocic_irq,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- "OHCI over-current indicator", NULL);
- if (error)
- pr_err("%s: could not request IRQ to watch over-current indicator changes\n",
- __func__);
- } else
- free_irq(irq, NULL);
-
- return error;
-}
-
static struct da8xx_ohci_platform_data da830_evm_usb11_pdata = {
- .set_power = da830_evm_usb_set_power,
- .get_power = da830_evm_usb_get_power,
- .get_oci = da830_evm_usb_get_oci,
- .ocic_notify = da830_evm_usb_ocic_notify,
-
+ .gpio_vbus = ON_BD_USB_DRV,
+ .gpio_overcurrent = ON_BD_USB_OVC,
+ .flags = (DA8XX_OHCI_FLAG_GPIO_VBUS
+ | DA8XX_OHCI_FLAG_GPIO_OCI),
/* TPS2065 switch @ 5V */
.potpgt = 3, /* 3 ms max */
};

-static irqreturn_t da830_evm_usb_ocic_irq(int irq, void *dev_id)
-{
- da830_evm_usb_ocic_handler(&da830_evm_usb11_pdata, 1);
- return IRQ_HANDLED;
-}
-
static __init void da830_evm_usb_init(void)
{
int ret;
@@ -143,22 +96,6 @@ static __init void da830_evm_usb_init(void)
return;
}

- ret = gpio_request(ON_BD_USB_DRV, "ON_BD_USB_DRV");
- if (ret) {
- pr_err("%s: failed to request GPIO for USB 1.1 port power control: %d\n",
- __func__, ret);
- return;
- }
- gpio_direction_output(ON_BD_USB_DRV, 0);
-
- ret = gpio_request(ON_BD_USB_OVC, "ON_BD_USB_OVC");
- if (ret) {
- pr_err("%s: failed to request GPIO for USB 1.1 port over-current indicator: %d\n",
- __func__, ret);
- return;
- }
- gpio_direction_input(ON_BD_USB_OVC);
-
ret = da8xx_register_usb11(&da830_evm_usb11_pdata);
if (ret)
pr_warn("%s: USB 1.1 registration failed: %d\n", __func__, ret);
diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
index 075be1b..8d72bc1 100644
--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
+++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
@@ -178,11 +178,6 @@ static __init void omapl138_hawk_mmc_init(void)
gpio_free(DA850_HAWK_MMCSD_CD_PIN);
}

-static const short da850_hawk_usb11_pins[] = {
- DA850_GPIO2_4, DA850_GPIO6_13,
- -1
-};
-
static struct da8xx_ohci_platform_data omapl138_hawk_usb11_pdata = {
/* TPS2087 switch @ 5V */
.potpgt = 3 /* 3 ms max */
@@ -192,12 +187,6 @@ static __init void omapl138_hawk_usb_init(void)
{
int ret;

- ret = davinci_cfg_reg_list(da850_hawk_usb11_pins);
- if (ret) {
- pr_warn("%s: USB 1.1 PinMux setup failed: %d\n", __func__, ret);
- return;
- }
-
/* USB_REFCLKIN is not used. */
ret = da8xx_register_usb20_phy_clk(false);
if (ret)
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index 9d9f8e3..d7a0f11 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -17,6 +17,7 @@
#include <linux/clk.h>
#include <linux/phy/phy.h>
#include <linux/platform_data/usb-davinci.h>
+#include <linux/gpio.h>

#ifndef CONFIG_ARCH_DAVINCI_DA8XX
#error "This file is DA8xx bus glue. Define CONFIG_ARCH_DAVINCI_DA8XX."
@@ -61,6 +62,24 @@ static void ohci_da8xx_disable(void)
clk_disable_unprepare(usb11_clk);
}

+
+static int ohci_da8xx_set_power(struct da8xx_ohci_platform_data *pdata,
+ int on)
+{
+ gpio_set_value(pdata->gpio_vbus, on);
+ return 0;
+}
+
+static int ohci_da8xx_get_power(struct da8xx_ohci_platform_data *pdata)
+{
+ return gpio_get_value(pdata->gpio_vbus);
+}
+
+static int ohci_da8xx_get_oci(struct da8xx_ohci_platform_data *pdata)
+{
+ return !gpio_get_value(pdata->gpio_overcurrent);
+}
+
/*
* Handle the port over-current indicator change.
*/
@@ -70,8 +89,18 @@ static void ohci_da8xx_ocic_handler(struct da8xx_ohci_platform_data *pdata,
ocic_mask |= 1 << port;

/* Once over-current is detected, the port needs to be powered down */
- if (pdata->get_oci(port) > 0)
- pdata->set_power(port, 0);
+ if (ohci_da8xx_get_oci(pdata) > 0)
+ ohci_da8xx_set_power(pdata, 0);
+}
+
+static irqreturn_t ohci_da8xx_ocic_irq(int irq, void *data)
+{
+ struct platform_device *pdev = (struct platform_device *) data;
+ struct da8xx_ohci_platform_data *pdata = dev_get_platdata(&pdev->dev);
+
+ ohci_da8xx_ocic_handler(pdata, 1);
+
+ return IRQ_HANDLED;
}

static int ohci_da8xx_init(struct usb_hcd *hcd)
@@ -107,11 +136,11 @@ static int ohci_da8xx_init(struct usb_hcd *hcd)
* the correct hub descriptor...
*/
rh_a = ohci_readl(ohci, &ohci->regs->roothub.a);
- if (pdata->set_power) {
+ if (pdata->flags & DA8XX_OHCI_FLAG_GPIO_VBUS) {
rh_a &= ~RH_A_NPS;
rh_a |= RH_A_PSM;
}
- if (pdata->get_oci) {
+ if (pdata->flags & DA8XX_OHCI_FLAG_GPIO_OCI) {
rh_a &= ~RH_A_NOCP;
rh_a |= RH_A_OCPM;
}
@@ -185,11 +214,13 @@ static int ohci_da8xx_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
temp = roothub_portstatus(hcd_to_ohci(hcd), wIndex - 1);

/* The port power status (PPS) bit defaults to 1 */
- if (pdata->get_power && pdata->get_power(wIndex) == 0)
+ if ((pdata->flags & DA8XX_OHCI_FLAG_GPIO_VBUS)
+ && ohci_da8xx_get_power(pdata) == 0)
temp &= ~RH_PS_PPS;

/* The port over-current indicator (POCI) bit is always 0 */
- if (pdata->get_oci && pdata->get_oci(wIndex) > 0)
+ if ((pdata->flags & DA8XX_OHCI_FLAG_GPIO_OCI)
+ && ohci_da8xx_get_oci(pdata) > 0)
temp |= RH_PS_POCI;

/* The over-current indicator change (OCIC) bit is 0 too */
@@ -214,10 +245,10 @@ static int ohci_da8xx_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
dev_dbg(dev, "%sPortFeature(%u): %s\n",
temp ? "Set" : "Clear", wIndex, "POWER");

- if (!pdata->set_power)
+ if (!(pdata->flags & DA8XX_OHCI_FLAG_GPIO_VBUS))
return 0;

- return pdata->set_power(wIndex, temp) ? -EPIPE : 0;
+ return ohci_da8xx_set_power(pdata, temp) ? -EPIPE : 0;
case USB_PORT_FEAT_C_OVER_CURRENT:
dev_dbg(dev, "%sPortFeature(%u): %s\n",
temp ? "Set" : "Clear", wIndex,
@@ -314,6 +345,38 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver,
return PTR_ERR(usb11_phy);
}

+
+ if (pdata->flags & DA8XX_OHCI_FLAG_GPIO_VBUS) {
+ error = devm_gpio_request_one(&pdev->dev,
+ pdata->gpio_vbus,
+ GPIOF_DIR_OUT, "usb11 vbus");
+ if (error) {
+ pr_err("could not request vbus gpio: %d\n", error);
+ return error;
+ }
+ }
+
+ if (pdata->flags & DA8XX_OHCI_FLAG_GPIO_OCI) {
+ error = devm_gpio_request_one(&pdev->dev,
+ pdata->gpio_overcurrent,
+ GPIOF_DIR_IN, "usb11 oci");
+ if (error) {
+ pr_err("could not request oci gpio: %d\n", error);
+ return error;
+ }
+
+ error = devm_request_irq(&pdev->dev,
+ gpio_to_irq(pdata->gpio_overcurrent),
+ ohci_da8xx_ocic_irq,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING,
+ "ohci overcurrent indicator", pdev);
+ if (error) {
+ pr_err("could not request oci irq: %d\n", error);
+ return error;
+ }
+ }
+
hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd)
return -ENOMEM;
@@ -341,15 +404,7 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver,

device_wakeup_enable(hcd->self.controller);

- if (pdata->ocic_notify) {
- error = pdata->ocic_notify(ohci_da8xx_ocic_handler);
- if (error)
- goto err_notify;
- }
-
return 0;
-err_notify:
- usb_remove_hcd(hcd);
err:
usb_put_hcd(hcd);
return error;
@@ -367,9 +422,6 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver,
static inline void
usb_hcd_da8xx_remove(struct usb_hcd *hcd, struct platform_device *pdev)
{
- struct da8xx_ohci_platform_data *pdata = dev_get_platdata(&pdev->dev);
-
- pdata->ocic_notify(NULL);
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
}
diff --git a/include/linux/platform_data/usb-davinci.h b/include/linux/platform_data/usb-davinci.h
index dffe3bf..b72f703 100644
--- a/include/linux/platform_data/usb-davinci.h
+++ b/include/linux/platform_data/usb-davinci.h
@@ -41,17 +41,15 @@ typedef void (*da8xx_ocic_handler_t)(struct da8xx_ohci_platform_data *pdata,

/* Passed as the platform data to the OHCI driver */
struct da8xx_ohci_platform_data {
- /* Switch the port power on/off */
- int (*set_power)(unsigned port, int on);
- /* Read the port power status */
- int (*get_power)(unsigned port);
- /* Read the port over-current indicator */
- int (*get_oci)(unsigned port);
- /* Over-current indicator change notification (pass NULL to disable) */
- int (*ocic_notify)(da8xx_ocic_handler_t handler);
-
/* Time from power on to power good (in 2 ms units) */
u8 potpgt;
+
+ u32 flags;
+#define DA8XX_OHCI_FLAG_GPIO_VBUS (1 << 0)
+#define DA8XX_OHCI_FLAG_GPIO_OCI (1 << 1)
+
+ int gpio_vbus;
+ int gpio_overcurrent;
};

void davinci_setup_usb(unsigned mA, unsigned potpgt_ms);
--
2.7.1

2016-10-07 16:45:32

by Axel Haslam

[permalink] [raw]
Subject: [PATCH/RFT 09/12] usb: host: ohci-da8xx: Add devicetree bindings documentation

From: Axel Haslam <[email protected]>

This patch documents the device tree bindings required for
the ohci controller found in TI da8xx family of SoC's

Signed-off-by: Axel Haslam <[email protected]>
---
.../devicetree/bindings/usb/ohci-da8xx.txt | 32 ++++++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 Documentation/devicetree/bindings/usb/ohci-da8xx.txt

diff --git a/Documentation/devicetree/bindings/usb/ohci-da8xx.txt b/Documentation/devicetree/bindings/usb/ohci-da8xx.txt
new file mode 100644
index 0000000..e954ce5
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ohci-da8xx.txt
@@ -0,0 +1,32 @@
+DA8XX USB OHCI controller
+
+Required properties:
+
+ - compatible: Should be "ti,da830-ohci"
+ - reg: Should contain one register range i.e. start and length
+ - interrupts: Description of the interrupt line
+ - phys: Phandle for the PHY device
+ - phy-names: Should be "usb-phy"
+
+Optional properties:
+ - vbus-gpio: If present, specifies a gpio that needs to be
+ activated for the bus to be powered.
+ - oci-gpio: If present, specifies a gpio that needs to be
+ activated for the overcurrent detection.
+ - power_on_delay: Power On to Power Good time - in ms.
+
+Example for omap138-lck:
+
+usb_phy: usb-phy {
+ compatible = "ti,da830-usb-phy";
+ #phy-cells = <1>;
+ status = "disabled";
+};
+usb11: usb11@0225000 {
+ compatible = "ti,da830-ohci";
+ reg = <0x225000 0x1000>;
+ interrupts = <59>;
+ phys = <&usb_phy 1>;
+ phy-names = "usb-phy";
+ status = "disabled";
+};
--
2.7.1

2016-10-07 16:45:30

by Axel Haslam

[permalink] [raw]
Subject: [PATCH/RFT 10/12] USB: ohci-da8xx: Add device tree support

From: Axel Haslam <[email protected]>

This allows the controller to be specified via device tree.

Signed-off-by: Axel Haslam <[email protected]>
---
drivers/usb/host/ohci-da8xx.c | 52 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 50 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index d7a0f11..10db421 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -18,6 +18,7 @@
#include <linux/phy/phy.h>
#include <linux/platform_data/usb-davinci.h>
#include <linux/gpio.h>
+#include <linux/of_gpio.h>

#ifndef CONFIG_ARCH_DAVINCI_DA8XX
#error "This file is DA8xx bus glue. Define CONFIG_ARCH_DAVINCI_DA8XX."
@@ -311,6 +312,47 @@ static const struct hc_driver ohci_da8xx_hc_driver = {

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

+#ifdef CONFIG_OF
+static const struct of_device_id da8xx_ohci_ids[] = {
+ { .compatible = "ti,da830-ohci" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, da8xx_ohci_ids);
+
+static int ohci_da8xx_of_init(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct da8xx_ohci_platform_data *pdata;
+ u32 tmp;
+
+ if (!np)
+ return 0;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ pdata->gpio_vbus = of_get_named_gpio(np, "vbus-gpio", 0);
+ if (pdata->gpio_vbus >= 0)
+ pdata->flags |= DA8XX_OHCI_FLAG_GPIO_VBUS;
+
+ pdata->gpio_overcurrent = of_get_named_gpio(np, "oci-gpio", 0);
+ if (pdata->gpio_overcurrent >= 0)
+ pdata->flags |= DA8XX_OHCI_FLAG_GPIO_OCI;
+
+ if (!of_property_read_u32(np, "power-on-delay", &tmp))
+ pdata->potpgt = tmp;
+
+ pdev->dev.platform_data = pdata;
+
+ return 0;
+}
+#else
+static int ohci_da8xx_of_init(struct platform_device *pdev)
+{
+ return 0;
+}
+#endif

/**
* usb_hcd_da8xx_probe - initialize DA8xx-based HCDs
@@ -323,12 +365,17 @@ static const struct hc_driver ohci_da8xx_hc_driver = {
static int usb_hcd_da8xx_probe(const struct hc_driver *driver,
struct platform_device *pdev)
{
- struct da8xx_ohci_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct da8xx_ohci_platform_data *pdata;
struct usb_hcd *hcd;
struct resource *mem;
int error, irq;

- if (pdata == NULL)
+ error = ohci_da8xx_of_init(pdev);
+ if (error)
+ pr_err("error initializing platform data: %d\n", error);
+
+ pdata = dev_get_platdata(&pdev->dev);
+ if (!pdata)
return -ENODEV;

usb11_clk = devm_clk_get(&pdev->dev, "usb11");
@@ -498,6 +545,7 @@ static struct platform_driver ohci_hcd_da8xx_driver = {
#endif
.driver = {
.name = "ohci",
+ .of_match_table = da8xx_ohci_ids,
},
};

--
2.7.1

2016-10-07 16:45:27

by Axel Haslam

[permalink] [raw]
Subject: [PATCH/RFT 05/12] USB: ohci-da8xx: Fix probe for devices with no vbus/oci gpio

From: Axel Haslam <[email protected]>

Some boards dont have gpios assigened for vbus or oci.

Allow these boards to enumerate usb without declaring the set_power
and/or the ocic_notify callbacks in platform data.

Signed-off-by: Axel Haslam <[email protected]>
---
drivers/usb/host/ohci-da8xx.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index 3c85d6c..9d9f8e3 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -215,7 +215,7 @@ static int ohci_da8xx_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
temp ? "Set" : "Clear", wIndex, "POWER");

if (!pdata->set_power)
- return -EPIPE;
+ return 0;

return pdata->set_power(wIndex, temp) ? -EPIPE : 0;
case USB_PORT_FEAT_C_OVER_CURRENT:
@@ -343,10 +343,12 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver,

if (pdata->ocic_notify) {
error = pdata->ocic_notify(ohci_da8xx_ocic_handler);
- if (!error)
- return 0;
+ if (error)
+ goto err_notify;
}

+ return 0;
+err_notify:
usb_remove_hcd(hcd);
err:
usb_put_hcd(hcd);
--
2.7.1

2016-10-07 17:11:56

by Sergei Shtylyov

[permalink] [raw]
Subject: Re: [PATCH/RFT 11/12] ARM: dts: da850: Add the usb ohci device node

Hello.

On 10/07/2016 07:42 PM, [email protected] wrote:

> From: Axel Haslam <[email protected]>
>
> This adds the device tree node for the usb11 (ohci)
> controller present in the da850 family of SoC's.
>
> Signed-off-by: Axel Haslam <[email protected]>
> ---
> arch/arm/boot/dts/da850.dtsi | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
> index 33fcdce..afae565 100644
> --- a/arch/arm/boot/dts/da850.dtsi
> +++ b/arch/arm/boot/dts/da850.dtsi
> @@ -381,6 +381,14 @@
> #phy-cells = <1>;
> status = "disabled";
> };
> + usb11: usb11@0225000 {

No, usb@<unit-address> to comply with the DT spec the node names should be
generic.

[...]

MBR, Sergei

2016-10-10 21:35:58

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH/RFT 09/12] usb: host: ohci-da8xx: Add devicetree bindings documentation

On Fri, Oct 07, 2016 at 06:42:54PM +0200, [email protected] wrote:
> From: Axel Haslam <[email protected]>
>
> This patch documents the device tree bindings required for
> the ohci controller found in TI da8xx family of SoC's
>
> Signed-off-by: Axel Haslam <[email protected]>
> ---
> .../devicetree/bindings/usb/ohci-da8xx.txt | 32 ++++++++++++++++++++++
> 1 file changed, 32 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/usb/ohci-da8xx.txt
>
> diff --git a/Documentation/devicetree/bindings/usb/ohci-da8xx.txt b/Documentation/devicetree/bindings/usb/ohci-da8xx.txt
> new file mode 100644
> index 0000000..e954ce5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/usb/ohci-da8xx.txt
> @@ -0,0 +1,32 @@
> +DA8XX USB OHCI controller
> +
> +Required properties:
> +
> + - compatible: Should be "ti,da830-ohci"
> + - reg: Should contain one register range i.e. start and length
> + - interrupts: Description of the interrupt line
> + - phys: Phandle for the PHY device
> + - phy-names: Should be "usb-phy"
> +
> +Optional properties:
> + - vbus-gpio: If present, specifies a gpio that needs to be

vbus-gpios

> + activated for the bus to be powered.
> + - oci-gpio: If present, specifies a gpio that needs to be

oci-gpios

> + activated for the overcurrent detection.
> + - power_on_delay: Power On to Power Good time - in ms.

power-on-delay-ms

> +
> +Example for omap138-lck:
> +
> +usb_phy: usb-phy {
> + compatible = "ti,da830-usb-phy";
> + #phy-cells = <1>;
> + status = "disabled";
> +};
> +usb11: usb11@0225000 {
> + compatible = "ti,da830-ohci";
> + reg = <0x225000 0x1000>;
> + interrupts = <59>;
> + phys = <&usb_phy 1>;
> + phy-names = "usb-phy";
> + status = "disabled";
> +};
> --
> 2.7.1
>

2016-10-10 23:18:28

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH/RFT 07/12] USB: ohci-da8xx: Request gpios and handle interrupt in the driver

On 10/07/2016 11:42 AM, [email protected] wrote:
> From: Axel Haslam <[email protected]>
>
> Currently requesting the vbus and overcurrent gpio is handled on
> the board specific file. But this does not play well moving to
> device tree.
>
> In preparation to migrate to a device tree boot, handle requesting
> gpios and overcurrent interrupt on the usb driver itself, thus avoiding
> callbacks to arch/mach*
>

Instead of using gpios, it seems like it would be better to use a
regulator here. I don't know of any real-life cases, but who is to say
someone will not design a board that uses a regulator controlled by I2C
instead of gpios or something like that.

Then, boards that don't have gpios can just use a fixed regulator (or
you can make the regulator optional). Using a regulator would also allow
users to decide how to respond to overcurrent events (by supplying their
own regulator driver) instead of the behavior being dictated by the ohci
driver.

In my particular area of interest (LEGO MINDSTORMS EV3), the 5V
(hardware) regulator for VBUS does use gpios, but the 5V is also shared
with the LEGO input and output ports. So what I would ultimately like to
be able to do is have userspace notified of an overcurrent event and let
userspace decided when to turn the vbus back on. For example, someone
might plug something into one of the LEGO input or output ports that
causes a short circuit. I would like to display a notification to the
user and wait for them to correct the problem and then press a button to
turn the power back on.

This will require some modifications to the regulator subsystem though.
I actually started work on this a while back, but haven't had the time
to pursue it any farther.

Here are my WIP patches in case there is any interest:
*
https://github.com/dlech/ev3dev-kernel/commit/541a42b3b8ed639e95bbc835df3292f80190c789
*
https://github.com/dlech/ev3dev-kernel/commit/2ba99b1ad6a06c944dd33a073f54044e71b75ae6
*
https://github.com/dlech/ev3dev-kernel/commit/cdb03caa50e64931d4f2836c648739aa4385ed3b
*
https://github.com/dlech/ev3dev-kernel/commit/9d6b50cde34b51309c74d97c26b1430c7ff6aa0f

2016-10-10 23:27:30

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH/RFT 08/12] ARM: davinci: register the usb20_phy clock on the SoC file

On 10/07/2016 11:42 AM, [email protected] wrote:
> From: Axel Haslam <[email protected]>
>
> The usb20_phy clock needs to be registered for the driver to be able
> to get and enable a clock. Currently the usb phy clocks are registered
> form board files, which will not be called during a device tree based
> boot.
>
> To be able to probe correctly usb form a device tree boot, register
> the usb phy clocks form the SoC specific init.
>
> Unfourtunatly, davinci does not have proper clock support on device tree
> yet, so by registering the clock form de SoC specific file we are
> forced to hardcode the parent clock, and cannot select refclkin as
> parent for any of the phy clocks of the da850 family.

FYI, I have started working on the clocks as well if you want to take it
and run with it.

https://github.com/dlech/ev3dev-kernel/compare/9d6b50cde34b51309c74d97c26b1430c7ff6aa0f...d02084598785c369fdb23884171cbbec4fef77b0

(Ignore the ev3dev commit stuck in the middle there.)

>
> As none of the current da850 based boards currently in mainline use
> refclkin as source. I guess we can live with this limitation until clocks
> are correctly represented through CCF/device tree.
>

2016-10-10 23:33:07

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH/RFT 09/12] usb: host: ohci-da8xx: Add devicetree bindings documentation

On 10/07/2016 11:42 AM, [email protected] wrote:
> From: Axel Haslam <[email protected]>
>
> This patch documents the device tree bindings required for
> the ohci controller found in TI da8xx family of SoC's
>
> Signed-off-by: Axel Haslam <[email protected]>
> ---
> .../devicetree/bindings/usb/ohci-da8xx.txt | 32 ++++++++++++++++++++++
> 1 file changed, 32 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/usb/ohci-da8xx.txt
>
> diff --git a/Documentation/devicetree/bindings/usb/ohci-da8xx.txt b/Documentation/devicetree/bindings/usb/ohci-da8xx.txt
> new file mode 100644
> index 0000000..e954ce5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/usb/ohci-da8xx.txt
> @@ -0,0 +1,32 @@
> +DA8XX USB OHCI controller
> +
> +Required properties:
> +
> + - compatible: Should be "ti,da830-ohci"
> + - reg: Should contain one register range i.e. start and length
> + - interrupts: Description of the interrupt line
> + - phys: Phandle for the PHY device
> + - phy-names: Should be "usb-phy"
> +

If these are required, shouldn't they say "Must" instead of "Should"?

> +Optional properties:
> + - vbus-gpio: If present, specifies a gpio that needs to be
> + activated for the bus to be powered.
> + - oci-gpio: If present, specifies a gpio that needs to be
> + activated for the overcurrent detection.
> + - power_on_delay: Power On to Power Good time - in ms.
> +
> +Example for omap138-lck:
> +
> +usb_phy: usb-phy {
> + compatible = "ti,da830-usb-phy";
> + #phy-cells = <1>;
> + status = "disabled";
> +};
> +usb11: usb11@0225000 {
> + compatible = "ti,da830-ohci";
> + reg = <0x225000 0x1000>;
> + interrupts = <59>;
> + phys = <&usb_phy 1>;
> + phy-names = "usb-phy";
> + status = "disabled";
> +};
>

2016-10-12 15:02:41

by Axel Haslam

[permalink] [raw]
Subject: Re: [PATCH/RFT 07/12] USB: ohci-da8xx: Request gpios and handle interrupt in the driver

Hi David

On Tue, Oct 11, 2016 at 1:18 AM, David Lechner <[email protected]> wrote:
> On 10/07/2016 11:42 AM, [email protected] wrote:
>>
>> From: Axel Haslam <[email protected]>
>>
>> Currently requesting the vbus and overcurrent gpio is handled on
>> the board specific file. But this does not play well moving to
>> device tree.
>>
>> In preparation to migrate to a device tree boot, handle requesting
>> gpios and overcurrent interrupt on the usb driver itself, thus avoiding
>> callbacks to arch/mach*
>>
>
> Instead of using gpios, it seems like it would be better to use a regulator
> here. I don't know of any real-life cases, but who is to say someone
> not design a board that uses a regulator controlled by I2C instead of gpios
> or something like that.
>
> Then, boards that don't have gpios can just use a fixed regulator (or you
> can make the regulator optional). Using a regulator would also allow users
> to decide how to respond to overcurrent events (by supplying their own
> regulator driver) instead of the behavior being dictated by the ohci driver.


I agree that we should use a regulator for the vbus power.
i will make that change. However, im not so sure about using the
regulator for the overcurrent handling. There seems to be no other
driver doing this, and as you mention, we would need to change the regulator
framework, which might not be justifiable. I think there is not another way
to handle the over current notification other than powering the port off.

>
> In my particular area of interest (LEGO MINDSTORMS EV3), the 5V (hardware)
> regulator for VBUS does use gpios, but the 5V is also shared with the LEGO
> input and output ports. So what I would ultimately like to be able to do is
> have userspace notified of an overcurrent event and let userspace decided
> when to turn the vbus back on. For example, someone might plug something
> into one of the LEGO input or output ports that causes a short circuit. I
> would like to display a notification to the user and wait for them to
> correct the problem and then press a button to turn the power back on.
>

how about using regulator for vbus, but keeping gpio for overcurrent
notifications?

For the usersapce handling you describe above, maybe we should be able to
listen for an usb overcurrent uevent in userspace? it seems this
question was asked
a couple of years back[1], but im not sure what the conclusion was. In any case,
we could have DT and non-DT based ohci-da8xx working,
And could work on a uevent notification for the scenario you describe
above which
i think is not specific to the ohci-da8xx.

[1]http://linux-usb.vger.kernel.narkive.com/SjcUB5hk/how-best-to-get-over-current-notification-to-user-application


Regards
Axel

> This will require some modifications to the regulator subsystem though. I
> actually started work on this a while back, but haven't had the time to
> pursue it any farther.
>
> Here are my WIP patches in case there is any interest:
> *
> https://github.com/dlech/ev3dev-kernel/commit/541a42b3b8ed639e95bbc835df3292f80190c789
> *
> https://github.com/dlech/ev3dev-kernel/commit/2ba99b1ad6a06c944dd33a073f54044e71b75ae6
> *
> https://github.com/dlech/ev3dev-kernel/commit/cdb03caa50e64931d4f2836c648739aa4385ed3b
> *
> https://github.com/dlech/ev3dev-kernel/commit/9d6b50cde34b51309c74d97c26b1430c7ff6aa0f

2016-10-13 00:49:02

by David Lechner

[permalink] [raw]
Subject: Re: [PATCH/RFT 07/12] USB: ohci-da8xx: Request gpios and handle interrupt in the driver

On 10/12/2016 10:01 AM, Axel Haslam wrote:
> I agree that we should use a regulator for the vbus power.
> i will make that change. However, im not so sure about using the
> regulator for the overcurrent handling. There seems to be no other
> driver doing this, and as you mention, we would need to change the regulator
> framework, which might not be justifiable. I think there is not another way
> to handle the over current notification other than powering the port off.

The regulator framework has REGULATOR_EVENT_OVER_CURRENT already.
Perhaps this could be of some use? For example you could extend the
existing gpio-regulator driver with an optional overcurrent gpio pin.


>
> how about using regulator for vbus, but keeping gpio for overcurrent
> notifications?

See the suggestion above about extending the gpio-regulator driver.


> For the usersapce handling you describe above, maybe we should be able to
> listen for an usb overcurrent uevent in userspace? it seems this
> question was asked
> a couple of years back[1], but im not sure what the conclusion was. In any case,
> we could have DT and non-DT based ohci-da8xx working,
> And could work on a uevent notification for the scenario you describe
> above which
> i think is not specific to the ohci-da8xx.
>
> [1]http://linux-usb.vger.kernel.narkive.com/SjcUB5hk/how-best-to-get-over-current-notification-to-user-application

Thanks for the link. Too bad it seems nothing ever became of this. I
guess it will be up to me to bring up the discussion again if I really
want it.