@@ -502,8 +502,6 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
}
ehci_data.phy_reset = pdata->phy_reset;
ohci_data.es2_compatibility = pdata->es2_compatibility;
- usbhs_data.ehci_data = &ehci_data;
- usbhs_data.ohci_data = &ohci_data;
if (cpu_is_omap34xx()) {
setup_ehci_io_mux(pdata->port_mode);
@@ -24,7 +24,7 @@
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
-#include <linux/gpio.h>
+#include <linux/of_gpio.h>
#include <plat/cpu.h>
#include <linux/platform_device.h>
#include <linux/platform_data/usb-omap.h>
@@ -103,8 +103,6 @@ struct usbhs_hcd_omap {
void __iomem *uhh_base;
- struct usbhs_omap_platform_data platdata;
-
u32 usbhs_rev;
spinlock_t lock;
};
@@ -186,8 +184,6 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct usbhs_hcd_omap *omap;
- struct ehci_hcd_omap_platform_data *ehci_data;
- struct ohci_hcd_omap_platform_data *ohci_data;
struct platform_device *ehci;
struct platform_device *ohci;
struct resource *res;
@@ -195,8 +191,6 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
int ret;
omap = platform_get_drvdata(pdev);
- ehci_data = omap->platdata.ehci_data;
- ohci_data = omap->platdata.ohci_data;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ehci");
if (!res) {
@@ -214,8 +208,8 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
}
resources[1] = *res;
- ehci = omap_usbhs_alloc_child(OMAP_EHCI_DEVICE, resources, 2, ehci_data,
- sizeof(*ehci_data), dev);
+ ehci = omap_usbhs_alloc_child(OMAP_EHCI_DEVICE, resources, 2, NULL,
+ 0, dev);
if (!ehci) {
dev_err(dev, "omap_usbhs_alloc_child failed\n");
@@ -239,8 +233,8 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
}
resources[1] = *res;
- ohci = omap_usbhs_alloc_child(OMAP_OHCI_DEVICE, resources, 2, ohci_data,
- sizeof(*ohci_data), dev);
+ ohci = omap_usbhs_alloc_child(OMAP_OHCI_DEVICE, resources, 2, NULL,
+ 0, dev);
if (!ohci) {
dev_err(dev, "omap_usbhs_alloc_child failed\n");
ret = -ENOMEM;
@@ -279,7 +273,7 @@ static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
static int usbhs_runtime_resume(struct device *dev)
{
struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
- struct usbhs_omap_platform_data *pdata = &omap->platdata;
+ struct usbhs_omap_platform_data *pdata = dev->platform_data;
unsigned long flags;
dev_dbg(dev, "usbhs_runtime_resume\n");
@@ -295,6 +289,7 @@ static int usbhs_runtime_resume(struct device *dev)
if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck))
clk_enable(omap->ehci_logic_fck);
+ clk_enable(pdata->hub_clk);
if (is_ehci_tll_mode(pdata->port_mode[0]))
clk_enable(omap->usbhost_p1_fck);
if (is_ehci_tll_mode(pdata->port_mode[1]))
@@ -311,7 +306,7 @@ static int usbhs_runtime_resume(struct device *dev)
static int usbhs_runtime_suspend(struct device *dev)
{
struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
- struct usbhs_omap_platform_data *pdata = &omap->platdata;
+ struct usbhs_omap_platform_data *pdata = dev->platform_data;
unsigned long flags;
dev_dbg(dev, "usbhs_runtime_suspend\n");
@@ -331,6 +326,7 @@ static int usbhs_runtime_suspend(struct device *dev)
clk_disable(omap->utmi_p2_fck);
clk_disable(omap->utmi_p1_fck);
+ clk_disable(pdata->hub_clk);
if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck))
clk_disable(omap->ehci_logic_fck);
@@ -343,19 +339,29 @@ static int usbhs_runtime_suspend(struct device *dev)
static void omap_usbhs_init(struct device *dev)
{
struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
- struct usbhs_omap_platform_data *pdata = &omap->platdata;
+ struct usbhs_omap_platform_data *pdata = dev->platform_data;
unsigned long flags;
unsigned reg;
dev_dbg(dev, "starting TI HSUSB Controller\n");
- if (pdata->ehci_data->phy_reset) {
- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
- gpio_request_one(pdata->ehci_data->reset_gpio_port[0],
+ if (gpio_is_valid(pdata->hub_power_gpio))
+ gpio_request_one(pdata->hub_power_gpio, GPIOF_OUT_INIT_HIGH,
+ "Hub Power");
+ if (gpio_is_valid(pdata->hub_reset_gpio)) {
+ gpio_request_one(pdata->hub_reset_gpio, GPIOF_OUT_INIT_LOW,
+ "Hub Reset Power");
+ udelay(5);
+ gpio_set_value_cansleep(pdata->hub_reset_gpio, 1);
+ }
+
+ if (pdata->phy_reset) {
+ if (gpio_is_valid(pdata->reset_gpio[0]))
+ gpio_request_one(pdata->reset_gpio[0],
GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
- gpio_request_one(pdata->ehci_data->reset_gpio_port[1],
+ if (gpio_is_valid(pdata->reset_gpio[1]))
+ gpio_request_one(pdata->reset_gpio[1],
GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
/* Hold the PHY in RESET for enough time till DIR is high */
@@ -431,36 +437,85 @@ static void omap_usbhs_init(struct device *dev)
spin_unlock_irqrestore(&omap->lock, flags);
pm_runtime_put_sync(dev);
- if (pdata->ehci_data->phy_reset) {
+ 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->ehci_data->reset_gpio_port[0]))
+ if (gpio_is_valid(pdata->reset_gpio[0]))
gpio_set_value_cansleep
- (pdata->ehci_data->reset_gpio_port[0], 1);
+ (pdata->reset_gpio[0], 1);
- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
+ if (gpio_is_valid(pdata->reset_gpio[1]))
gpio_set_value_cansleep
- (pdata->ehci_data->reset_gpio_port[1], 1);
+ (pdata->reset_gpio[1], 1);
}
}
static void omap_usbhs_deinit(struct device *dev)
{
- struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
- struct usbhs_omap_platform_data *pdata = &omap->platdata;
+ struct usbhs_omap_platform_data *pdata = dev->platform_data;
- if (pdata->ehci_data->phy_reset) {
- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
- gpio_free(pdata->ehci_data->reset_gpio_port[0]);
+ if (pdata->phy_reset) {
+ if (gpio_is_valid(pdata->reset_gpio[0]))
+ gpio_free(pdata->reset_gpio[0]);
- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
- gpio_free(pdata->ehci_data->reset_gpio_port[1]);
+ if (gpio_is_valid(pdata->reset_gpio[1]))
+ gpio_free(pdata->reset_gpio[1]);
}
}
+static struct usbhs_omap_platform_data *of_get_usbhs_pdata(struct device *dev)
+{
+ struct usbhs_omap_platform_data *pdata;
+ struct device_node *np = dev->of_node;
+ struct property *pp;
+ char hubclk[20];
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return NULL; /* out of memory */
+
+ of_property_read_u32(np, "port-0", &pdata->port_mode[0]);
+ of_property_read_u32(np, "port-1", &pdata->port_mode[1]);
+ of_property_read_u32(np, "port-2", &pdata->port_mode[2]);
+ pdata->reset_gpio[0] = of_get_named_gpio(np, "reset-gpio-1", 0);
+ pdata->reset_gpio[1] = of_get_named_gpio(np, "reset-gpio-2", 0);
+ pdata->reset_gpio[2] = of_get_named_gpio(np, "reset-gpio-3", 0);
+
+ if (gpio_is_valid(pdata->reset_gpio[0]) ||
+ gpio_is_valid(pdata->reset_gpio[1]) ||
+ gpio_is_valid(pdata->reset_gpio[2]))
+ pdata->phy_reset = true;
+
+ pp = of_find_property(np, "hub-clk", NULL);
+ if (pp) {
+ strncpy(hubclk, pp->value, 20);
+ pdata->hub_clk = clk_get(NULL, hubclk);
+ if (IS_ERR(pdata->hub_clk)) {
+ dev_err(dev, "hub clk failed error: %ld\n",
+ PTR_ERR(pdata->hub_clk));
+ goto err_end;
+ }
+ } else {
+ pdata->hub_clk = NULL;
+ }
+ if (pdata->hub_clk) {
+ of_property_read_u32(np, "hub-clkrate", &pdata->hub_clkrate);
+ clk_set_rate(pdata->hub_clk, pdata->hub_clkrate);
+ }
+
+ pdata->hub_power_gpio = of_get_named_gpio(np, "hub-power-gpio", 0);
+ pdata->hub_reset_gpio = of_get_named_gpio(np, "hub-reset-gpio", 0);
+
+ return pdata;
+
+err_end:
+ devm_kfree(dev, pdata);
+ return NULL;
+}
+
/**
* usbhs_omap_probe - initialize TI-based HCDs
@@ -470,14 +525,16 @@ static void omap_usbhs_deinit(struct device *dev)
static int __devinit usbhs_omap_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct usbhs_omap_platform_data *pdata = dev->platform_data;
+ struct usbhs_omap_platform_data *pdata;
struct usbhs_hcd_omap *omap;
struct resource *res;
int ret = 0;
int i;
+
+ pdata = of_get_usbhs_pdata(dev);
if (!pdata) {
- dev_err(dev, "Missing platform data\n");
+ dev_err(dev, "function of_get_usbhs_pdata failed\n");
ret = -ENOMEM;
goto end_probe;
}
@@ -486,20 +543,13 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
if (!omap) {
dev_err(dev, "Memory allocation failed\n");
ret = -ENOMEM;
- goto end_probe;
+ goto err_pdata;
}
spin_lock_init(&omap->lock);
- for (i = 0; i < OMAP3_HS_USB_PORTS; i++)
- omap->platdata.port_mode[i] = pdata->port_mode[i];
-
- omap->platdata.ehci_data = pdata->ehci_data;
- omap->platdata.ohci_data = pdata->ohci_data;
-
pm_runtime_enable(dev);
-
for (i = 0; i < OMAP3_HS_USB_PORTS; i++)
if (is_ehci_phy_mode(i) || is_ehci_tll_mode(i) ||
is_ehci_hsic_mode(i)) {
@@ -516,7 +566,7 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
if (IS_ERR(omap->utmi_p1_fck)) {
ret = PTR_ERR(omap->utmi_p1_fck);
dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret);
- goto err_end;
+ goto err_ehci_fck;
}
omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
@@ -605,6 +655,7 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, omap);
+ dev->platform_data = pdata;
omap_usbhs_init(dev);
ret = omap_usbhs_alloc_children(pdev);
@@ -640,11 +691,15 @@ err_xclk60mhsp1_ck:
err_utmi_p1_fck:
clk_put(omap->utmi_p1_fck);
-err_end:
+err_ehci_fck:
clk_put(omap->ehci_logic_fck);
pm_runtime_disable(dev);
kfree(omap);
+err_pdata:
+ clk_put(pdata->hub_clk);
+ devm_kfree(dev, pdata);
+
end_probe:
return ret;
}
@@ -657,9 +712,11 @@ end_probe:
*/
static int __devexit usbhs_omap_remove(struct platform_device *pdev)
{
- struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
+ struct device *dev = &pdev->dev;
+ struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
+ struct usbhs_omap_platform_data *pdata = dev->platform_data;
- omap_usbhs_deinit(&pdev->dev);
+ omap_usbhs_deinit(dev);
iounmap(omap->uhh_base);
clk_put(omap->init_60m_fclk);
clk_put(omap->usbhost_p2_fck);
@@ -669,7 +726,9 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev)
clk_put(omap->xclk60mhsp1_ck);
clk_put(omap->utmi_p1_fck);
clk_put(omap->ehci_logic_fck);
- pm_runtime_disable(&pdev->dev);
+ pm_runtime_disable(dev);
+ clk_put(pdata->hub_clk);
+ devm_kfree(dev, pdata);
kfree(omap);
return 0;
@@ -680,11 +739,23 @@ static const struct dev_pm_ops usbhsomap_dev_pm_ops = {
.runtime_resume = usbhs_runtime_resume,
};
+#ifdef CONFIG_OF
+static const struct of_device_id omap_usbhs_of_match[] = {
+ {
+ .compatible = "ti,usbhs",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, omap_usbhs_of_match);
+
+#endif
+
static struct platform_driver usbhs_omap_driver = {
.driver = {
.name = (char *)usbhs_driver_name,
.owner = THIS_MODULE,
.pm = &usbhsomap_dev_pm_ops,
+ .of_match_table = of_match_ptr(omap_usbhs_of_match),
},
.remove = __exit_p(usbhs_omap_remove),
};
@@ -55,10 +55,23 @@ struct ohci_hcd_omap_platform_data {
};
struct usbhs_omap_platform_data {
- enum usbhs_omap_port_mode port_mode[OMAP3_HS_USB_PORTS];
+ enum usbhs_omap_port_mode port_mode[OMAP3_HS_USB_PORTS];
+ int reset_gpio[OMAP3_HS_USB_PORTS];
+
+ /*
+ * Regulators for USB PHYs.
+ * Each PHY can have a separate regulator.
+ */
+ struct regulator *regulator[OMAP3_HS_USB_PORTS];
- struct ehci_hcd_omap_platform_data *ehci_data;
- struct ohci_hcd_omap_platform_data *ohci_data;
+ unsigned phy_reset:1;
+
+ /* Set this to true for ES2.x silicon */
+ unsigned es2_compatibility:1;
+ struct clk *hub_clk;
+ int hub_clkrate;
+ int hub_power_gpio;
+ int hub_reset_gpio;
};
/*-------------------------------------------------------------------------*/
The USB2 Host device node is extracted and used in the probe of the driver to initialize the usb ports and controller. The platform specific initialization is also performed. Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com> --- arch/arm/mach-omap2/usb-host.c | 2 - drivers/mfd/omap-usb-host.c | 163 +++++++++++++++++++++++--------- include/linux/platform_data/usb-omap.h | 19 +++- 3 files changed, 133 insertions(+), 51 deletions(-)