diff options
author | Keshava Munegowda <[email protected]> | 2011-05-16 14:24:58 +0530 |
---|---|---|
committer | Samuel Ortiz <[email protected]> | 2011-05-26 19:45:49 +0200 |
commit | 6eb6fbbf3eca6dfba73e72de5ab2eeb52ae41f7a (patch) | |
tree | 471ff9aa1aaf2a30857e69d915807fa9dd803f3c | |
parent | 13ca4f66108188231f9ef0358449f4543a0b84a1 (diff) |
mfd: Fix omap usbhs crash when rmmoding ehci or ohci
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 <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Cc: [email protected]
Signed-off-by: Samuel Ortiz <[email protected]>
-rw-r--r-- | drivers/mfd/omap-usb-host.c | 27 |
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); } |