aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeshava Munegowda <Keshava_mgowda@ti.com>2011-05-16 14:24:58 +0530
committerGreg Kroah-Hartman <gregkh@suse.de>2011-06-03 09:32:31 +0900
commit4e2c4040f3e270dbd66e094a3dff196495d5b765 (patch)
tree5e7c0f3670ac32e543ce11f0482191df60c8282a
parentc8b7f76958e22a88f2fa510ab05aff1ca08358a6 (diff)
mfd: Fix omap usbhs crash when rmmoding ehci or ohci
commit 6eb6fbbf3eca6dfba73e72de5ab2eeb52ae41f7a upstream. The disabling of clocks and freeing GPIO are changed to fix the occurrence of the crash of rmmod of ehci and ohci drivers. The GPIOs should be freed after the spin locks are unlocked. Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com> Acked-by: Felipe Balbi <balbi@ti.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/mfd/omap-usb-host.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 3ab9ffa00aad..55c5d4732f5f 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -994,22 +994,33 @@ static void usbhs_disable(struct device *dev)
dev_dbg(dev, "operation timed out\n");
}
- 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 (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
- gpio_free(pdata->ehci_data->reset_gpio_port[1]);
+ if (is_omap_usbhs_rev2(omap)) {
+ if (is_ehci_tll_mode(pdata->port_mode[0]))
+ clk_enable(omap->usbtll_p1_fck);
+ if (is_ehci_tll_mode(pdata->port_mode[1]))
+ clk_enable(omap->usbtll_p2_fck);
+ clk_disable(omap->utmi_p2_fck);
+ clk_disable(omap->utmi_p1_fck);
}
- clk_disable(omap->utmi_p2_fck);
- clk_disable(omap->utmi_p1_fck);
clk_disable(omap->usbtll_ick);
clk_disable(omap->usbtll_fck);
clk_disable(omap->usbhost_fs_fck);
clk_disable(omap->usbhost_hs_fck);
clk_disable(omap->usbhost_ick);
+ /* The gpio_free migh sleep; so unlock the spinlock */
+ spin_unlock_irqrestore(&omap->lock, flags);
+
+ 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 (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
+ gpio_free(pdata->ehci_data->reset_gpio_port[1]);
+ }
+ return;
+
end_disble:
spin_unlock_irqrestore(&omap->lock, flags);
}