1
0
Fork 0

usb: phy: patches for v3.6 merge window

We are starting to support multiple USB phys as
 we should thanks for Kishon's work. DeviceTree support
 for USB PHYs won't come until discussion with DeviceTree
 maintainer is finished.
 
 Together with that series, we have one fix for twl4030
 which missed a IRQF_ONESHOT annotation when requesting
 a threaded IRQ without a top half handler, and removal
 of an unused variable compilation warning to isp1301_omap.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iQIcBAABAgAGBQJP8VcOAAoJEIaOsuA1yqREeNYQAIxHOteF78nx5gMwB20agndf
 vYCOB3Jymc67vcLuEf60lqoVBuQ7bxGsJyx+HlNkKrVQQfF8enL9UBhUDwvmKytm
 Z1FBVmuA33PxS2aGSODkgafODO6wfnp5USzzYjEG+Hu6Q9Zt4rJ3NYakYFXdbrM3
 kT3uZ2uwuOd/B1Pzt8oiMSbiF16kLeX0a6m6C4KEFViX0uGHAe/KqN4b9eSbO41q
 16fvfthbAaqqSpEoMusI+kCFLku7ib3CXl5d4kgik7C7+wY08JTDWhWBMIl6wiFz
 LeDIXfoX0MgEcB3vDszGCf2pgtCNR8rfl/pzuLvr6F6p+Cj6CqtgsfV8HCe43Dzr
 RI7Fewl1xdz6MztKRBgr75RxqZ6VA91gLWT21nDI72DEBwyBJ1pk882CxkxSLK+b
 VNtI/La9JZkUqb0PXioD0a4JUVpzw5nLatpw1PXZoLUgSozVXmhDE6Wjhl/jvl4y
 ZVQVRQn2ZcyNzYY9bG2X08zyDRRvurXFfQ20CfAeBpgvvfccN9e5vGdWVbohwZro
 Vn1x+fSyb6KqVOeYlzpAKf+UGXE9UM53YKpjFnmrstqUjbL5ByW2pZn5fYgJP08v
 9im3SXwvs3Iz2mzwenRFUpI6PDuaTnIWgB7qquFDY1QwFyAKoPJuVN81/iPCisUM
 bIYQILhqgTNNjsnPmpCr
 =HwsA
 -----END PGP SIGNATURE-----

Merge tag 'xceiv-for-v3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next

usb: phy: patches for v3.6 merge window

We are starting to support multiple USB phys as
we should thanks for Kishon's work. DeviceTree support
for USB PHYs won't come until discussion with DeviceTree
maintainer is finished.

Together with that series, we have one fix for twl4030
which missed a IRQF_ONESHOT annotation when requesting
a threaded IRQ without a top half handler, and removal
of an unused variable compilation warning to isp1301_omap.
hifive-unleashed-5.1
Greg Kroah-Hartman 2012-07-05 15:35:41 -07:00
commit ff9cce8277
38 changed files with 538 additions and 325 deletions

View File

@ -2517,7 +2517,7 @@ static int __devexit ab8500_charger_remove(struct platform_device *pdev)
dev_err(di->dev, "%s mask and set failed\n", __func__);
usb_unregister_notifier(di->usb_phy, &di->nb);
usb_put_transceiver(di->usb_phy);
usb_put_phy(di->usb_phy);
/* Delete the work queue */
destroy_workqueue(di->charger_wq);
@ -2688,8 +2688,8 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev)
goto free_ac;
}
di->usb_phy = usb_get_transceiver();
if (!di->usb_phy) {
di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(di->usb_phy)) {
dev_err(di->dev, "failed to get usb transceiver\n");
ret = -EINVAL;
goto free_usb;
@ -2747,7 +2747,7 @@ free_irq:
free_irq(irq, di);
}
put_usb_phy:
usb_put_transceiver(di->usb_phy);
usb_put_phy(di->usb_phy);
free_usb:
power_supply_unregister(&di->usb_chg.psy);
free_ac:

View File

@ -415,8 +415,8 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev)
if (!isp)
return -ENOMEM;
isp->phy = usb_get_transceiver();
if (!isp->phy)
isp->phy = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(isp->phy))
goto fail0;
isp->dev = &pdev->dev;
@ -475,7 +475,7 @@ fail2:
power_supply_unregister(&isp->psy);
fail1:
isp1704_charger_set_power(isp, 0);
usb_put_transceiver(isp->phy);
usb_put_phy(isp->phy);
fail0:
kfree(isp);
@ -490,7 +490,7 @@ static int __devexit isp1704_charger_remove(struct platform_device *pdev)
usb_unregister_notifier(isp->phy, &isp->nb);
power_supply_unregister(&isp->psy);
usb_put_transceiver(isp->phy);
usb_put_phy(isp->phy);
isp1704_charger_set_power(isp, 0);
kfree(isp);

View File

@ -321,12 +321,12 @@ static int pda_power_probe(struct platform_device *pdev)
}
#ifdef CONFIG_USB_OTG_UTILS
transceiver = usb_get_transceiver();
if (transceiver && !pdata->is_usb_online) {
pdata->is_usb_online = otg_is_usb_online;
}
if (transceiver && !pdata->is_ac_online) {
pdata->is_ac_online = otg_is_ac_online;
transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
if (!IS_ERR_OR_NULL(transceiver)) {
if (!pdata->is_usb_online)
pdata->is_usb_online = otg_is_usb_online;
if (!pdata->is_ac_online)
pdata->is_ac_online = otg_is_ac_online;
}
#endif
@ -373,7 +373,7 @@ static int pda_power_probe(struct platform_device *pdev)
}
#ifdef CONFIG_USB_OTG_UTILS
if (transceiver && pdata->use_otg_notifier) {
if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) {
otg_nb.notifier_call = otg_handle_notification;
ret = usb_register_notifier(transceiver, &otg_nb);
if (ret) {
@ -408,8 +408,8 @@ usb_supply_failed:
if (pdata->is_ac_online && ac_irq)
free_irq(ac_irq->start, &pda_psy_ac);
#ifdef CONFIG_USB_OTG_UTILS
if (transceiver)
usb_put_transceiver(transceiver);
if (!IS_ERR_OR_NULL(transceiver))
usb_put_phy(transceiver);
#endif
ac_irq_failed:
if (pdata->is_ac_online)
@ -443,8 +443,8 @@ static int pda_power_remove(struct platform_device *pdev)
if (pdata->is_ac_online)
power_supply_unregister(&pda_psy_ac);
#ifdef CONFIG_USB_OTG_UTILS
if (transceiver)
usb_put_transceiver(transceiver);
if (!IS_ERR_OR_NULL(transceiver))
usb_put_phy(transceiver);
#endif
if (ac_draw) {
regulator_put(ac_draw);

View File

@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/i2c/twl.h>
@ -479,8 +480,8 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
INIT_WORK(&bci->work, twl4030_bci_usb_work);
bci->transceiver = usb_get_transceiver();
if (bci->transceiver != NULL) {
bci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
if (!IS_ERR_OR_NULL(bci->transceiver)) {
bci->usb_nb.notifier_call = twl4030_bci_usb_ncb;
usb_register_notifier(bci->transceiver, &bci->usb_nb);
}
@ -507,9 +508,9 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
return 0;
fail_unmask_interrupts:
if (bci->transceiver != NULL) {
if (!IS_ERR_OR_NULL(bci->transceiver)) {
usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
usb_put_transceiver(bci->transceiver);
usb_put_phy(bci->transceiver);
}
free_irq(bci->irq_bci, bci);
fail_bci_irq:
@ -538,9 +539,9 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev)
twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
TWL4030_INTERRUPTS_BCIIMR2A);
if (bci->transceiver != NULL) {
if (!IS_ERR_OR_NULL(bci->transceiver)) {
usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
usb_put_transceiver(bci->transceiver);
usb_put_phy(bci->transceiver);
}
free_irq(bci->irq_bci, bci);
free_irq(bci->irq_chg, bci);

View File

@ -14,6 +14,7 @@
#include <linux/device.h>
#include <linux/dmapool.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/module.h>
@ -1687,7 +1688,7 @@ static int udc_start(struct ci13xxx *udc)
udc->gadget.ep0 = &udc->ep0in->ep;
udc->transceiver = usb_get_transceiver();
udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
if (udc->transceiver == NULL) {
@ -1712,7 +1713,7 @@ static int udc_start(struct ci13xxx *udc)
if (retval)
goto unreg_device;
if (udc->transceiver) {
if (!IS_ERR_OR_NULL(udc->transceiver)) {
retval = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (retval)
@ -1729,9 +1730,9 @@ static int udc_start(struct ci13xxx *udc)
return retval;
remove_trans:
if (udc->transceiver) {
if (!IS_ERR_OR_NULL(udc->transceiver)) {
otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
usb_put_transceiver(udc->transceiver);
usb_put_phy(udc->transceiver);
}
dev_err(dev, "error = %i\n", retval);
@ -1740,8 +1741,8 @@ remove_dbg:
unreg_device:
device_unregister(&udc->gadget.dev);
put_transceiver:
if (udc->transceiver)
usb_put_transceiver(udc->transceiver);
if (!IS_ERR_OR_NULL(udc->transceiver))
usb_put_phy(udc->transceiver);
free_pools:
dma_pool_destroy(udc->td_pool);
free_qh_pool:
@ -1772,9 +1773,9 @@ static void udc_stop(struct ci13xxx *udc)
dma_pool_destroy(udc->td_pool);
dma_pool_destroy(udc->qh_pool);
if (udc->transceiver) {
if (!IS_ERR_OR_NULL(udc->transceiver)) {
otg_set_peripheral(udc->transceiver->otg, NULL);
usb_put_transceiver(udc->transceiver);
usb_put_phy(udc->transceiver);
}
dbg_remove_files(&udc->gadget.dev);
device_unregister(&udc->gadget.dev);

View File

@ -24,6 +24,7 @@
#include <linux/ioport.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/list.h>
@ -1229,7 +1230,7 @@ static int fsl_vbus_draw(struct usb_gadget *gadget, unsigned mA)
struct fsl_udc *udc;
udc = container_of(gadget, struct fsl_udc, gadget);
if (udc->transceiver)
if (!IS_ERR_OR_NULL(udc->transceiver))
return usb_phy_set_power(udc->transceiver, mA);
return -ENOTSUPP;
}
@ -1983,13 +1984,13 @@ static int fsl_start(struct usb_gadget_driver *driver,
goto out;
}
if (udc_controller->transceiver) {
if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
/* Suspend the controller until OTG enable it */
udc_controller->stopped = 1;
printk(KERN_INFO "Suspend udc for OTG auto detect\n");
/* connect to bus through transceiver */
if (udc_controller->transceiver) {
if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
retval = otg_set_peripheral(
udc_controller->transceiver->otg,
&udc_controller->gadget);
@ -2030,7 +2031,7 @@ static int fsl_stop(struct usb_gadget_driver *driver)
if (!driver || driver != udc_controller->driver || !driver->unbind)
return -EINVAL;
if (udc_controller->transceiver)
if (!IS_ERR_OR_NULL(udc_controller->transceiver))
otg_set_peripheral(udc_controller->transceiver->otg, NULL);
/* stop DR, disable intr */
@ -2455,8 +2456,8 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
#ifdef CONFIG_USB_OTG
if (pdata->operating_mode == FSL_USB2_DR_OTG) {
udc_controller->transceiver = usb_get_transceiver();
if (!udc_controller->transceiver) {
udc_controller->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(udc_controller->transceiver)) {
ERR("Can't find OTG driver!\n");
ret = -ENODEV;
goto err_kfree;
@ -2540,7 +2541,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
goto err_free_irq;
}
if (!udc_controller->transceiver) {
if (IS_ERR_OR_NULL(udc_controller->transceiver)) {
/* initialize usb hw reg except for regs for EP,
* leave usbintr reg untouched */
dr_controller_setup(udc_controller);
@ -2565,7 +2566,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
if (ret < 0)
goto err_free_irq;
if (udc_controller->transceiver)
if (!IS_ERR_OR_NULL(udc_controller->transceiver))
udc_controller->gadget.is_otg = 1;
/* setup QH and epctrl for ep0 */

View File

@ -19,6 +19,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
@ -1381,7 +1382,7 @@ static int mv_udc_start(struct usb_gadget_driver *driver,
return retval;
}
if (udc->transceiver) {
if (!IS_ERR_OR_NULL(udc->transceiver)) {
retval = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (retval) {
@ -2107,7 +2108,7 @@ static int __devexit mv_udc_remove(struct platform_device *dev)
* then vbus irq will not be requested in udc driver.
*/
if (udc->pdata && udc->pdata->vbus
&& udc->clock_gating && udc->transceiver == NULL)
&& udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver))
free_irq(udc->pdata->vbus->irq, &dev->dev);
/* free memory allocated in probe */
@ -2180,7 +2181,7 @@ static int __devinit mv_udc_probe(struct platform_device *dev)
#ifdef CONFIG_USB_OTG_UTILS
if (pdata->mode == MV_USB_MODE_OTG)
udc->transceiver = usb_get_transceiver();
udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
#endif
udc->clknum = pdata->clknum;
@ -2325,7 +2326,7 @@ static int __devinit mv_udc_probe(struct platform_device *dev)
eps_init(udc);
/* VBUS detect: we can disable/enable clock on demand.*/
if (udc->transceiver)
if (!IS_ERR_OR_NULL(udc->transceiver))
udc->clock_gating = 1;
else if (pdata->vbus) {
udc->clock_gating = 1;
@ -2369,7 +2370,7 @@ static int __devinit mv_udc_probe(struct platform_device *dev)
err_unregister:
if (udc->pdata && udc->pdata->vbus
&& udc->clock_gating && udc->transceiver == NULL)
&& udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver))
free_irq(pdata->vbus->irq, &dev->dev);
device_unregister(&udc->gadget.dev);
err_free_irq:
@ -2404,7 +2405,7 @@ static int mv_udc_suspend(struct device *_dev)
struct mv_udc *udc = the_controller;
/* if OTG is enabled, the following will be done in OTG driver*/
if (udc->transceiver)
if (!IS_ERR_OR_NULL(udc->transceiver))
return 0;
if (udc->pdata->vbus && udc->pdata->vbus->poll)
@ -2437,7 +2438,7 @@ static int mv_udc_resume(struct device *_dev)
int retval;
/* if OTG is enabled, the following will be done in OTG driver*/
if (udc->transceiver)
if (!IS_ERR_OR_NULL(udc->transceiver))
return 0;
if (!udc->clock_gating) {

View File

@ -35,6 +35,7 @@
#include <linux/usb/otg.h>
#include <linux/dma-mapping.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/prefetch.h>
#include <linux/io.h>
@ -1152,7 +1153,7 @@ static int omap_wakeup(struct usb_gadget *gadget)
/* NOTE: non-OTG systems may use SRP TOO... */
} else if (!(udc->devstat & UDC_ATT)) {
if (udc->transceiver)
if (!IS_ERR_OR_NULL(udc->transceiver))
retval = otg_start_srp(udc->transceiver->otg);
}
spin_unlock_irqrestore(&udc->lock, flags);
@ -1284,7 +1285,7 @@ static int omap_vbus_draw(struct usb_gadget *gadget, unsigned mA)
struct omap_udc *udc;
udc = container_of(gadget, struct omap_udc, gadget);
if (udc->transceiver)
if (!IS_ERR_OR_NULL(udc->transceiver))
return usb_phy_set_power(udc->transceiver, mA);
return -EOPNOTSUPP;
}
@ -1734,12 +1735,12 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src)
if (devstat & UDC_ATT) {
udc->gadget.speed = USB_SPEED_FULL;
VDBG("connect\n");
if (!udc->transceiver)
if (IS_ERR_OR_NULL(udc->transceiver))
pullup_enable(udc);
/* if (driver->connect) call it */
} else if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
udc->gadget.speed = USB_SPEED_UNKNOWN;
if (!udc->transceiver)
if (IS_ERR_OR_NULL(udc->transceiver))
pullup_disable(udc);
DBG("disconnect, gadget %s\n",
udc->driver->driver.name);
@ -1779,12 +1780,12 @@ static void devstate_irq(struct omap_udc *udc, u16 irq_src)
udc->driver->suspend(&udc->gadget);
spin_lock(&udc->lock);
}
if (udc->transceiver)
if (!IS_ERR_OR_NULL(udc->transceiver))
usb_phy_set_suspend(
udc->transceiver, 1);
} else {
VDBG("resume\n");
if (udc->transceiver)
if (!IS_ERR_OR_NULL(udc->transceiver))
usb_phy_set_suspend(
udc->transceiver, 0);
if (udc->gadget.speed == USB_SPEED_FULL
@ -2092,7 +2093,7 @@ static int omap_udc_start(struct usb_gadget_driver *driver,
omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC);
/* connect to bus through transceiver */
if (udc->transceiver) {
if (!IS_ERR_OR_NULL(udc->transceiver)) {
status = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (status < 0) {
@ -2139,7 +2140,7 @@ static int omap_udc_stop(struct usb_gadget_driver *driver)
if (machine_without_vbus_sense())
omap_vbus_session(&udc->gadget, 0);
if (udc->transceiver)
if (!IS_ERR_OR_NULL(udc->transceiver))
(void) otg_set_peripheral(udc->transceiver->otg, NULL);
else
pullup_disable(udc);
@ -2829,8 +2830,8 @@ static int __devinit omap_udc_probe(struct platform_device *pdev)
* use it. Except for OTG, we don't _need_ to talk to one;
* but not having one probably means no VBUS detection.
*/
xceiv = usb_get_transceiver();
if (xceiv)
xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (!IS_ERR_OR_NULL(xceiv))
type = xceiv->label;
else if (config->otg) {
DBG("OTG requires external transceiver!\n");
@ -2854,7 +2855,7 @@ static int __devinit omap_udc_probe(struct platform_device *pdev)
case 16:
case 19:
case 25:
if (!xceiv) {
if (IS_ERR_OR_NULL(xceiv)) {
DBG("external transceiver not registered!\n");
type = "unknown";
}
@ -2956,8 +2957,8 @@ cleanup1:
udc = NULL;
cleanup0:
if (xceiv)
usb_put_transceiver(xceiv);
if (!IS_ERR_OR_NULL(xceiv))
usb_put_phy(xceiv);
if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
clk_disable(hhc_clk);
@ -2986,8 +2987,8 @@ static int __devexit omap_udc_remove(struct platform_device *pdev)
udc->done = &done;
pullup_disable(udc);
if (udc->transceiver) {
usb_put_transceiver(udc->transceiver);
if (!IS_ERR_OR_NULL(udc->transceiver)) {
usb_put_phy(udc->transceiver);
udc->transceiver = NULL;
}
omap_writew(0, UDC_SYSCON1);

View File

@ -21,6 +21,7 @@
#include <linux/ioport.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
@ -993,7 +994,7 @@ static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
udc = container_of(_gadget, struct pxa25x_udc, gadget);
if (udc->transceiver)
if (!IS_ERR_OR_NULL(udc->transceiver))
return usb_phy_set_power(udc->transceiver, mA);
return -EOPNOTSUPP;
}
@ -1299,7 +1300,7 @@ fail:
DMSG("registered gadget driver '%s'\n", driver->driver.name);
/* connect to bus through transceiver */
if (dev->transceiver) {
if (!IS_ERR_OR_NULL(dev->transceiver)) {
retval = otg_set_peripheral(dev->transceiver->otg,
&dev->gadget);
if (retval) {
@ -1359,7 +1360,7 @@ static int pxa25x_stop(struct usb_gadget_driver *driver)
stop_activity(dev, driver);
local_irq_enable();
if (dev->transceiver)
if (!IS_ERR_OR_NULL(dev->transceiver))
(void) otg_set_peripheral(dev->transceiver->otg, NULL);
driver->unbind(&dev->gadget);
@ -2159,7 +2160,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
dev->dev = &pdev->dev;
dev->mach = pdev->dev.platform_data;
dev->transceiver = usb_get_transceiver();
dev->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
if (gpio_is_valid(dev->mach->gpio_pullup)) {
if ((retval = gpio_request(dev->mach->gpio_pullup,
@ -2237,8 +2238,8 @@ lubbock_fail0:
if (gpio_is_valid(dev->mach->gpio_pullup))
gpio_free(dev->mach->gpio_pullup);
err_gpio_pullup:
if (dev->transceiver) {
usb_put_transceiver(dev->transceiver);
if (!IS_ERR_OR_NULL(dev->transceiver)) {
usb_put_phy(dev->transceiver);
dev->transceiver = NULL;
}
clk_put(dev->clk);
@ -2279,8 +2280,8 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
clk_put(dev->clk);
if (dev->transceiver) {
usb_put_transceiver(dev->transceiver);
if (!IS_ERR_OR_NULL(dev->transceiver)) {
usb_put_phy(dev->transceiver);
dev->transceiver = NULL;
}

View File

@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/list.h>
@ -1573,7 +1574,7 @@ static int should_enable_udc(struct pxa_udc *udc)
int put_on;
put_on = ((udc->pullup_on) && (udc->driver));
put_on &= ((udc->vbus_sensed) || (!udc->transceiver));
put_on &= ((udc->vbus_sensed) || (IS_ERR_OR_NULL(udc->transceiver)));
return put_on;
}
@ -1594,7 +1595,7 @@ static int should_disable_udc(struct pxa_udc *udc)
int put_off;
put_off = ((!udc->pullup_on) || (!udc->driver));
put_off |= ((!udc->vbus_sensed) && (udc->transceiver));
put_off |= ((!udc->vbus_sensed) && (!IS_ERR_OR_NULL(udc->transceiver)));
return put_off;
}
@ -1665,7 +1666,7 @@ static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
struct pxa_udc *udc;
udc = to_gadget_udc(_gadget);
if (udc->transceiver)
if (!IS_ERR_OR_NULL(udc->transceiver))
return usb_phy_set_power(udc->transceiver, mA);
return -EOPNOTSUPP;
}
@ -1834,7 +1835,7 @@ static int pxa27x_udc_start(struct usb_gadget_driver *driver,
dev_dbg(udc->dev, "registered gadget driver '%s'\n",
driver->driver.name);
if (udc->transceiver) {
if (!IS_ERR_OR_NULL(udc->transceiver)) {
retval = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (retval) {
@ -1908,7 +1909,7 @@ static int pxa27x_udc_stop(struct usb_gadget_driver *driver)
dev_info(udc->dev, "unregistered gadget driver '%s'\n",
driver->driver.name);
if (udc->transceiver)
if (!IS_ERR_OR_NULL(udc->transceiver))
return otg_set_peripheral(udc->transceiver->otg, NULL);
return 0;
}
@ -2464,7 +2465,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
udc->dev = &pdev->dev;
udc->mach = pdev->dev.platform_data;
udc->transceiver = usb_get_transceiver();
udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
gpio = udc->mach->gpio_pullup;
if (gpio_is_valid(gpio)) {
@ -2543,7 +2544,7 @@ static int __exit pxa_udc_remove(struct platform_device *_dev)
if (gpio_is_valid(gpio))
gpio_free(gpio);
usb_put_transceiver(udc->transceiver);
usb_put_phy(udc->transceiver);
udc->transceiver = NULL;
platform_set_drvdata(_dev, NULL);

View File

@ -24,6 +24,7 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
@ -1165,7 +1166,7 @@ static int s3c_hsudc_start(struct usb_gadget *gadget,
}
/* connect to bus through transceiver */
if (hsudc->transceiver) {
if (!IS_ERR_OR_NULL(hsudc->transceiver)) {
ret = otg_set_peripheral(hsudc->transceiver->otg,
&hsudc->gadget);
if (ret) {
@ -1220,7 +1221,7 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget,
s3c_hsudc_stop_activity(hsudc);
spin_unlock_irqrestore(&hsudc->lock, flags);
if (hsudc->transceiver)
if (!IS_ERR_OR_NULL(hsudc->transceiver))
(void) otg_set_peripheral(hsudc->transceiver->otg, NULL);
disable_irq(hsudc->irq);
@ -1249,7 +1250,7 @@ static int s3c_hsudc_vbus_draw(struct usb_gadget *gadget, unsigned mA)
if (!hsudc)
return -ENODEV;
if (hsudc->transceiver)
if (!IS_ERR_OR_NULL(hsudc->transceiver))
return usb_phy_set_power(hsudc->transceiver, mA);
return -EOPNOTSUPP;
@ -1282,7 +1283,7 @@ static int __devinit s3c_hsudc_probe(struct platform_device *pdev)
hsudc->dev = dev;
hsudc->pd = pdev->dev.platform_data;
hsudc->transceiver = usb_get_transceiver();
hsudc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
for (i = 0; i < ARRAY_SIZE(hsudc->supplies); i++)
hsudc->supplies[i].supply = s3c_hsudc_supply_names[i];
@ -1385,8 +1386,8 @@ err_irq:
err_remap:
release_mem_region(res->start, resource_size(res));
err_res:
if (hsudc->transceiver)
usb_put_transceiver(hsudc->transceiver);
if (!IS_ERR_OR_NULL(hsudc->transceiver))
usb_put_phy(hsudc->transceiver);
regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
err_supplies:

View File

@ -27,6 +27,7 @@
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/fsl_devices.h>
@ -142,15 +143,15 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
if (pdata->operating_mode == FSL_USB2_DR_OTG) {
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
hcd->phy = usb_get_transceiver();
hcd->phy = usb_get_phy(USB_PHY_TYPE_USB2);
dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, phy=0x%p\n",
hcd, ehci, hcd->phy);
if (hcd->phy) {
if (!IS_ERR_OR_NULL(hcd->phy)) {
retval = otg_set_host(hcd->phy->otg,
&ehci_to_hcd(ehci)->self);
if (retval) {
usb_put_transceiver(hcd->phy);
usb_put_phy(hcd->phy);
goto err4;
}
} else {
@ -191,9 +192,9 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
{
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
if (hcd->phy) {
if (!IS_ERR_OR_NULL(hcd->phy)) {
otg_set_host(hcd->phy->otg, NULL);
usb_put_transceiver(hcd->phy);
usb_put_phy(hcd->phy);
}
usb_remove_hcd(hcd);

View File

@ -145,8 +145,8 @@ static int ehci_msm_probe(struct platform_device *pdev)
* powering up VBUS, mapping of registers address space and power
* management.
*/
phy = usb_get_transceiver();
if (!phy) {
phy = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(phy)) {
dev_err(&pdev->dev, "unable to find transceiver\n");
ret = -ENODEV;
goto unmap;
@ -169,7 +169,7 @@ static int ehci_msm_probe(struct platform_device *pdev)
return 0;
put_transceiver:
usb_put_transceiver(phy);
usb_put_phy(phy);
unmap:
iounmap(hcd->regs);
put_hcd:
@ -187,7 +187,7 @@ static int __devexit ehci_msm_remove(struct platform_device *pdev)
pm_runtime_set_suspended(&pdev->dev);
otg_set_host(phy->otg, NULL);
usb_put_transceiver(phy);
usb_put_phy(phy);
usb_put_hcd(hcd);

View File

@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/usb/otg.h>
#include <linux/platform_data/mv_usb.h>
@ -253,8 +254,8 @@ static int mv_ehci_probe(struct platform_device *pdev)
ehci_mv->mode = pdata->mode;
if (ehci_mv->mode == MV_USB_MODE_OTG) {
#ifdef CONFIG_USB_OTG_UTILS
ehci_mv->otg = usb_get_transceiver();
if (!ehci_mv->otg) {
ehci_mv->otg = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(ehci_mv->otg)) {
dev_err(&pdev->dev,
"unable to find transceiver\n");
retval = -ENODEV;
@ -302,8 +303,8 @@ err_set_vbus:
pdata->set_vbus(0);
#ifdef CONFIG_USB_OTG_UTILS
err_put_transceiver:
if (ehci_mv->otg)
usb_put_transceiver(ehci_mv->otg);
if (!IS_ERR_OR_NULL(ehci_mv->otg))
usb_put_phy(ehci_mv->otg);
#endif
err_disable_clk:
mv_ehci_disable(ehci_mv);
@ -331,9 +332,9 @@ static int mv_ehci_remove(struct platform_device *pdev)
if (hcd->rh_registered)
usb_remove_hcd(hcd);
if (ehci_mv->otg) {
if (!IS_ERR_OR_NULL(ehci_mv->otg)) {
otg_set_host(ehci_mv->otg->otg, NULL);
usb_put_transceiver(ehci_mv->otg);
usb_put_phy(ehci_mv->otg);
}
if (ehci_mv->mode == MV_USB_MODE_HOST) {

View File

@ -17,6 +17,7 @@
*/
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/platform_data/tegra_usb.h>
#include <linux/irq.h>
@ -749,8 +750,8 @@ static int tegra_ehci_probe(struct platform_device *pdev)
#ifdef CONFIG_USB_OTG_UTILS
if (pdata->operating_mode == TEGRA_USB_OTG) {
tegra->transceiver = usb_get_transceiver();
if (tegra->transceiver)
tegra->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
if (!IS_ERR_OR_NULL(tegra->transceiver))
otg_set_host(tegra->transceiver->otg, &hcd->self);
}
#endif
@ -773,9 +774,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)
fail:
#ifdef CONFIG_USB_OTG_UTILS
if (tegra->transceiver) {
if (!IS_ERR_OR_NULL(tegra->transceiver)) {
otg_set_host(tegra->transceiver->otg, NULL);
usb_put_transceiver(tegra->transceiver);
usb_put_phy(tegra->transceiver);
}
#endif
tegra_usb_phy_close(tegra->phy);
@ -808,9 +809,9 @@ static int tegra_ehci_remove(struct platform_device *pdev)
pm_runtime_put_noidle(&pdev->dev);
#ifdef CONFIG_USB_OTG_UTILS
if (tegra->transceiver) {
if (!IS_ERR_OR_NULL(tegra->transceiver)) {
otg_set_host(tegra->transceiver->otg, NULL);
usb_put_transceiver(tegra->transceiver);
usb_put_phy(tegra->transceiver);
}
#endif

View File

@ -18,6 +18,7 @@
#include <linux/jiffies.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <mach/hardware.h>
@ -212,14 +213,14 @@ static int ohci_omap_init(struct usb_hcd *hcd)
#ifdef CONFIG_USB_OTG
if (need_transceiver) {
hcd->phy = usb_get_transceiver();
if (hcd->phy) {
hcd->phy = usb_get_phy(USB_PHY_TYPE_USB2);
if (!IS_ERR_OR_NULL(hcd->phy)) {
int status = otg_set_host(hcd->phy->otg,
&ohci_to_hcd(ohci)->self);
dev_dbg(hcd->self.controller, "init %s phy, status %d\n",
hcd->phy->label, status);
if (status) {
usb_put_transceiver(hcd->phy);
usb_put_phy(hcd->phy);
return status;
}
} else {
@ -404,9 +405,9 @@ usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
usb_remove_hcd(hcd);
if (hcd->phy) {
if (!IS_ERR_OR_NULL(hcd->phy)) {
(void) otg_set_host(hcd->phy->otg, 0);
usb_put_transceiver(hcd->phy);
usb_put_phy(hcd->phy);
}
if (machine_is_omap_osk())
gpio_free(9);

View File

@ -29,6 +29,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
@ -364,8 +365,8 @@ static int am35x_musb_init(struct musb *musb)
return -ENODEV;
usb_nop_xceiv_register();
musb->xceiv = usb_get_transceiver();
if (!musb->xceiv)
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(musb->xceiv))
return -ENODEV;
if (is_host_enabled(musb))
@ -406,7 +407,7 @@ static int am35x_musb_exit(struct musb *musb)
if (data->set_phy_power)
data->set_phy_power(0);
usb_put_transceiver(musb->xceiv);
usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;

View File

@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/prefetch.h>
@ -415,8 +416,8 @@ static int bfin_musb_init(struct musb *musb)
gpio_direction_output(musb->config->gpio_vrsel, 0);
usb_nop_xceiv_register();
musb->xceiv = usb_get_transceiver();
if (!musb->xceiv) {
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(musb->xceiv)) {
gpio_free(musb->config->gpio_vrsel);
return -ENODEV;
}
@ -440,7 +441,7 @@ static int bfin_musb_exit(struct musb *musb)
{
gpio_free(musb->config->gpio_vrsel);
usb_put_transceiver(musb->xceiv);
usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;
}

View File

@ -29,6 +29,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
@ -425,8 +426,8 @@ static int da8xx_musb_init(struct musb *musb)
goto fail;
usb_nop_xceiv_register();
musb->xceiv = usb_get_transceiver();
if (!musb->xceiv)
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(musb->xceiv))
goto fail;
if (is_host_enabled(musb))
@ -458,7 +459,7 @@ static int da8xx_musb_exit(struct musb *musb)
phy_off();
usb_put_transceiver(musb->xceiv);
usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;

View File

@ -28,6 +28,7 @@
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
@ -385,8 +386,8 @@ static int davinci_musb_init(struct musb *musb)
u32 revision;
usb_nop_xceiv_register();
musb->xceiv = usb_get_transceiver();
if (!musb->xceiv)
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(musb->xceiv))
goto unregister;
musb->mregs += DAVINCI_BASE_OFFSET;
@ -444,7 +445,7 @@ static int davinci_musb_init(struct musb *musb)
return 0;
fail:
usb_put_transceiver(musb->xceiv);
usb_put_phy(musb->xceiv);
unregister:
usb_nop_xceiv_unregister();
return -ENODEV;
@ -494,7 +495,7 @@ static int davinci_musb_exit(struct musb *musb)
phy_off();
usb_put_transceiver(musb->xceiv);
usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;

View File

@ -1909,7 +1909,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
/* The musb_platform_init() call:
* - adjusts musb->mregs and musb->isr if needed,
* - may initialize an integrated tranceiver
* - initializes musb->xceiv, usually by otg_get_transceiver()
* - initializes musb->xceiv, usually by otg_get_phy()
* - stops powering VBUS
*
* There are various transceiver configurations. Blackfin,

View File

@ -327,7 +327,6 @@ struct musb {
irqreturn_t (*isr)(int, void *);
struct work_struct irq_work;
struct work_struct otg_notifier_work;
u16 hwvers;
/* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
@ -373,7 +372,6 @@ struct musb {
u16 int_tx;
struct usb_phy *xceiv;
u8 xceiv_event;
int nIrq;
unsigned irq_wake:1;

View File

@ -31,6 +31,7 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
@ -376,8 +377,8 @@ static int dsps_musb_init(struct musb *musb)
/* NOP driver needs change if supporting dual instance */
usb_nop_xceiv_register();
musb->xceiv = usb_get_transceiver();
if (!musb->xceiv)
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(musb->xceiv))
return -ENODEV;
/* Returns zero if e.g. not clocked */
@ -409,7 +410,7 @@ static int dsps_musb_init(struct musb *musb)
return 0;
err0:
usb_put_transceiver(musb->xceiv);
usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return status;
}
@ -430,7 +431,7 @@ static int dsps_musb_exit(struct musb *musb)
data->set_phy_power(0);
/* NOP driver needs change if supporting dual instance */
usb_put_transceiver(musb->xceiv);
usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;

View File

@ -34,6 +34,7 @@
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <linux/err.h>
#include <linux/usb/musb-omap.h>
#include "musb_core.h"
#include "omap2430.h"
@ -41,9 +42,13 @@
struct omap2430_glue {
struct device *dev;
struct platform_device *musb;
enum omap_musb_vbus_id_status status;
struct work_struct omap_musb_mailbox_work;
};
#define glue_to_musb(g) platform_get_drvdata(g->musb)
struct omap2430_glue *_glue;
static struct timer_list musb_idle_timer;
static void musb_do_idle(unsigned long _musb)
@ -223,50 +228,63 @@ static inline void omap2430_low_level_init(struct musb *musb)
musb_writel(musb->mregs, OTG_FORCESTDBY, l);
}
static int musb_otg_notifications(struct notifier_block *nb,
unsigned long event, void *unused)
void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
{
struct musb *musb = container_of(nb, struct musb, nb);
struct omap2430_glue *glue = _glue;
struct musb *musb = glue_to_musb(glue);
musb->xceiv_event = event;
schedule_work(&musb->otg_notifier_work);
glue->status = status;
if (!musb) {
dev_err(glue->dev, "musb core is not yet ready\n");
return;
}
return NOTIFY_OK;
schedule_work(&glue->omap_musb_mailbox_work);
}
EXPORT_SYMBOL_GPL(omap_musb_mailbox);
static void musb_otg_notifier_work(struct work_struct *data_notifier_work)
static void omap_musb_set_mailbox(struct omap2430_glue *glue)
{
struct musb *musb = container_of(data_notifier_work, struct musb, otg_notifier_work);
struct musb *musb = glue_to_musb(glue);
struct device *dev = musb->controller;
struct musb_hdrc_platform_data *pdata = dev->platform_data;
struct omap_musb_board_data *data = pdata->board_data;
struct usb_otg *otg = musb->xceiv->otg;
switch (musb->xceiv_event) {
case USB_EVENT_ID:
dev_dbg(musb->controller, "ID GND\n");
switch (glue->status) {
case OMAP_MUSB_ID_GROUND:
dev_dbg(dev, "ID GND\n");
otg->default_a = true;
musb->xceiv->state = OTG_STATE_A_IDLE;
musb->xceiv->last_event = USB_EVENT_ID;
if (!is_otg_enabled(musb) || musb->gadget_driver) {
pm_runtime_get_sync(musb->controller);
pm_runtime_get_sync(dev);
usb_phy_init(musb->xceiv);
omap2430_musb_set_vbus(musb, 1);
}
break;
case USB_EVENT_VBUS:
dev_dbg(musb->controller, "VBUS Connect\n");
case OMAP_MUSB_VBUS_VALID:
dev_dbg(dev, "VBUS Connect\n");
otg->default_a = false;
musb->xceiv->state = OTG_STATE_B_IDLE;
musb->xceiv->last_event = USB_EVENT_VBUS;
if (musb->gadget_driver)
pm_runtime_get_sync(musb->controller);
pm_runtime_get_sync(dev);
usb_phy_init(musb->xceiv);
break;
case USB_EVENT_NONE:
dev_dbg(musb->controller, "VBUS Disconnect\n");
case OMAP_MUSB_ID_FLOAT:
case OMAP_MUSB_VBUS_OFF:
dev_dbg(dev, "VBUS Disconnect\n");
musb->xceiv->last_event = USB_EVENT_NONE;
if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
if (musb->gadget_driver) {
pm_runtime_mark_last_busy(musb->controller);
pm_runtime_put_autosuspend(musb->controller);
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
}
if (data->interface_type == MUSB_INTERFACE_UTMI) {
@ -276,15 +294,24 @@ static void musb_otg_notifier_work(struct work_struct *data_notifier_work)
usb_phy_shutdown(musb->xceiv);
break;
default:
dev_dbg(musb->controller, "ID float\n");
dev_dbg(dev, "ID float\n");
}
}
static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
{
struct omap2430_glue *glue = container_of(mailbox_work,
struct omap2430_glue, omap_musb_mailbox_work);
omap_musb_set_mailbox(glue);
}
static int omap2430_musb_init(struct musb *musb)
{
u32 l;
int status = 0;
struct device *dev = musb->controller;
struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
struct musb_hdrc_platform_data *plat = dev->platform_data;
struct omap_musb_board_data *data = plat->board_data;
@ -292,14 +319,12 @@ static int omap2430_musb_init(struct musb *musb)
* up through ULPI. TWL4030-family PMICs include one,
* which needs a driver, drivers aren't always needed.
*/
musb->xceiv = usb_get_transceiver();
if (!musb->xceiv) {
musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(musb->xceiv)) {
pr_err("HS USB OTG: no transceiver configured\n");
return -ENODEV;
}
INIT_WORK(&musb->otg_notifier_work, musb_otg_notifier_work);
status = pm_runtime_get_sync(dev);
if (status < 0) {
dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
@ -326,14 +351,11 @@ static int omap2430_musb_init(struct musb *musb)
musb_readl(musb->mregs, OTG_INTERFSEL),
musb_readl(musb->mregs, OTG_SIMENABLE));
musb->nb.notifier_call = musb_otg_notifications;
status = usb_register_notifier(musb->xceiv, &musb->nb);
if (status)
dev_dbg(musb->controller, "notification register failed\n");
setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
if (glue->status != OMAP_MUSB_UNKNOWN)
omap_musb_set_mailbox(glue);
pm_runtime_put_noidle(musb->controller);
return 0;
@ -346,12 +368,13 @@ static void omap2430_musb_enable(struct musb *musb)
u8 devctl;
unsigned long timeout = jiffies + msecs_to_jiffies(1000);
struct device *dev = musb->controller;
struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
struct musb_hdrc_platform_data *pdata = dev->platform_data;
struct omap_musb_board_data *data = pdata->board_data;
switch (musb->xceiv->last_event) {
switch (glue->status) {
case USB_EVENT_ID:
case OMAP_MUSB_ID_GROUND:
usb_phy_init(musb->xceiv);
if (data->interface_type != MUSB_INTERFACE_UTMI)
break;
@ -370,7 +393,7 @@ static void omap2430_musb_enable(struct musb *musb)
}
break;
case USB_EVENT_VBUS:
case OMAP_MUSB_VBUS_VALID:
usb_phy_init(musb->xceiv);
break;
@ -381,17 +404,18 @@ static void omap2430_musb_enable(struct musb *musb)
static void omap2430_musb_disable(struct musb *musb)
{
if (musb->xceiv->last_event)
struct device *dev = musb->controller;
struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
if (glue->status != OMAP_MUSB_UNKNOWN)
usb_phy_shutdown(musb->xceiv);
}
static int omap2430_musb_exit(struct musb *musb)
{
del_timer_sync(&musb_idle_timer);
cancel_work_sync(&musb->otg_notifier_work);
omap2430_low_level_exit(musb);
usb_put_transceiver(musb->xceiv);
return 0;
}
@ -418,7 +442,7 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
struct omap2430_glue *glue;
int ret = -ENOMEM;
glue = kzalloc(sizeof(*glue), GFP_KERNEL);
glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
if (!glue) {
dev_err(&pdev->dev, "failed to allocate glue context\n");
goto err0;
@ -427,7 +451,7 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
musb = platform_device_alloc("musb-hdrc", -1);
if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n");
goto err1;
goto err0;
}
musb->dev.parent = &pdev->dev;
@ -436,22 +460,31 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
glue->dev = &pdev->dev;
glue->musb = musb;
glue->status = OMAP_MUSB_UNKNOWN;
pdata->platform_ops = &omap2430_ops;
platform_set_drvdata(pdev, glue);
/*
* REVISIT if we ever have two instances of the wrapper, we will be
* in big trouble
*/
_glue = glue;
INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
ret = platform_device_add_resources(musb, pdev->resource,
pdev->num_resources);
if (ret) {
dev_err(&pdev->dev, "failed to add resources\n");
goto err2;
goto err1;
}
ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
if (ret) {
dev_err(&pdev->dev, "failed to add platform_data\n");
goto err2;
goto err1;
}
pm_runtime_enable(&pdev->dev);
@ -459,16 +492,13 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
ret = platform_device_add(musb);
if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n");
goto err2;
goto err1;
}
return 0;
err2:
platform_device_put(musb);
err1:
kfree(glue);
platform_device_put(musb);
err0:
return ret;
@ -478,9 +508,9 @@ static int __devexit omap2430_remove(struct platform_device *pdev)
{
struct omap2430_glue *glue = platform_get_drvdata(pdev);
cancel_work_sync(&glue->omap_musb_mailbox_work);
platform_device_del(glue->musb);
platform_device_put(glue->musb);
kfree(glue);
return 0;
}
@ -546,7 +576,7 @@ static int __init omap2430_init(void)
{
return platform_driver_register(&omap2430_driver);
}
module_init(omap2430_init);
subsys_initcall(omap2430_init);
static void __exit omap2430_exit(void)
{

View File

@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/prefetch.h>
#include <linux/usb.h>
@ -1078,8 +1079,8 @@ static int tusb_musb_init(struct musb *musb)
int ret;
usb_nop_xceiv_register();
musb->xceiv = usb_get_transceiver();
if (!musb->xceiv)
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(musb->xceiv))
return -ENODEV;
pdev = to_platform_device(musb->controller);
@ -1130,7 +1131,7 @@ done:
if (sync)
iounmap(sync);
usb_put_transceiver(musb->xceiv);
usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
}
return ret;
@ -1146,7 +1147,7 @@ static int tusb_musb_exit(struct musb *musb)
iounmap(musb->sync_va);
usb_put_transceiver(musb->xceiv);
usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;
}

View File

@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
@ -37,8 +38,8 @@ struct ux500_glue {
static int ux500_musb_init(struct musb *musb)
{
musb->xceiv = usb_get_transceiver();
if (!musb->xceiv) {
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(musb->xceiv)) {
pr_err("HS USB OTG: no transceiver configured\n");
return -ENODEV;
}
@ -48,7 +49,7 @@ static int ux500_musb_init(struct musb *musb)
static int ux500_musb_exit(struct musb *musb)
{
usb_put_transceiver(musb->xceiv);
usb_put_phy(musb->xceiv);
return 0;
}

View File

@ -529,7 +529,7 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev)
if (err < 0)
goto fail0;
err = usb_set_transceiver(&ab->phy);
err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2);
if (err) {
dev_err(&pdev->dev, "Can't register transceiver\n");
goto fail1;
@ -556,7 +556,7 @@ static int __devexit ab8500_usb_remove(struct platform_device *pdev)
cancel_work_sync(&ab->phy_dis_work);
usb_set_transceiver(NULL);
usb_remove_phy(&ab->phy);
ab8500_usb_host_phy_dis(ab);
ab8500_usb_peri_phy_dis(ab);

View File

@ -806,7 +806,7 @@ static int fsl_otg_conf(struct platform_device *pdev)
fsl_otg_dev = fsl_otg_tc;
/* Store the otg transceiver */
status = usb_set_transceiver(&fsl_otg_tc->phy);
status = usb_add_phy(&fsl_otg_tc->phy, USB_PHY_TYPE_USB2);
if (status) {
pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n");
goto err;
@ -824,7 +824,7 @@ err:
int usb_otg_start(struct platform_device *pdev)
{
struct fsl_otg *p_otg;
struct usb_phy *otg_trans = usb_get_transceiver();
struct usb_phy *otg_trans = usb_get_phy(USB_PHY_TYPE_USB2);
struct otg_fsm *fsm;
int status;
struct resource *res;
@ -1134,7 +1134,7 @@ static int __devexit fsl_otg_remove(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
usb_set_transceiver(NULL);
usb_remove_phy(&fsl_otg_dev->phy);
free_irq(fsl_otg_dev->irq, fsl_otg_dev);
iounmap((void *)usb_dr_regs);

View File

@ -320,7 +320,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev)
}
/* only active when a gadget is registered */
err = usb_set_transceiver(&gpio_vbus->phy);
err = usb_add_phy(&gpio_vbus->phy, USB_PHY_TYPE_USB2);
if (err) {
dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
err);
@ -354,7 +354,7 @@ static int __exit gpio_vbus_remove(struct platform_device *pdev)
cancel_delayed_work_sync(&gpio_vbus->work);
regulator_put(gpio_vbus->vbus_draw);
usb_set_transceiver(NULL);
usb_remove_phy(&gpio_vbus->phy);
free_irq(gpio_vbus->irq, pdev);
if (gpio_is_valid(pdata->gpio_pullup))

View File

@ -1336,9 +1336,6 @@ static int
isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
{
struct isp1301 *isp = container_of(otg->phy, struct isp1301, phy);
#ifndef CONFIG_USB_OTG
u32 l;
#endif
if (!otg || isp != the_transceiver)
return -ENODEV;
@ -1365,10 +1362,14 @@ isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
otg->gadget = gadget;
// FIXME update its refcount
l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS);
l |= OTG_ID;
omap_writel(l, OTG_CTRL);
{
u32 l;
l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS);
l |= OTG_ID;
omap_writel(l, OTG_CTRL);
}
power_up(isp);
isp->phy.state = OTG_STATE_B_IDLE;
@ -1610,7 +1611,7 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES);
#endif
status = usb_set_transceiver(&isp->phy);
status = usb_add_phy(&isp->phy, USB_PHY_TYPE_USB2);
if (status < 0)
dev_err(&i2c->dev, "can't register transceiver, %d\n",
status);
@ -1649,7 +1650,7 @@ subsys_initcall(isp_init);
static void __exit isp_exit(void)
{
if (the_transceiver)
usb_set_transceiver(NULL);
usb_remove_phy(&the_transceiver->phy);
i2c_del_driver(&isp1301_driver);
}
module_exit(isp_exit);

View File

@ -1555,9 +1555,9 @@ static int __init msm_otg_probe(struct platform_device *pdev)
phy->otg->set_host = msm_otg_set_host;
phy->otg->set_peripheral = msm_otg_set_peripheral;
ret = usb_set_transceiver(&motg->phy);
ret = usb_add_phy(&motg->phy, USB_PHY_TYPE_USB2);
if (ret) {
dev_err(&pdev->dev, "usb_set_transceiver failed\n");
dev_err(&pdev->dev, "usb_add_phy failed\n");
goto free_irq;
}
@ -1624,7 +1624,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 0);
pm_runtime_disable(&pdev->dev);
usb_set_transceiver(NULL);
usb_remove_phy(phy);
free_irq(motg->irq, motg);
/*

View File

@ -690,7 +690,7 @@ int mv_otg_remove(struct platform_device *pdev)
for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++)
clk_put(mvotg->clk[clk_i]);
usb_set_transceiver(NULL);
usb_remove_phy(&mvotg->phy);
platform_set_drvdata(pdev, NULL);
kfree(mvotg->phy.otg);
@ -853,7 +853,7 @@ static int mv_otg_probe(struct platform_device *pdev)
goto err_disable_clk;
}
retval = usb_set_transceiver(&mvotg->phy);
retval = usb_add_phy(&mvotg->phy, USB_PHY_TYPE_USB2);
if (retval < 0) {
dev_err(&pdev->dev, "can't register transceiver, %d\n",
retval);
@ -880,7 +880,7 @@ static int mv_otg_probe(struct platform_device *pdev)
return 0;
err_set_transceiver:
usb_set_transceiver(NULL);
usb_remove_phy(&mvotg->phy);
err_free_irq:
free_irq(mvotg->irq, mvotg);
err_disable_clk:

View File

@ -117,7 +117,7 @@ static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev)
nop->phy.otg->set_host = nop_set_host;
nop->phy.otg->set_peripheral = nop_set_peripheral;
err = usb_set_transceiver(&nop->phy);
err = usb_add_phy(&nop->phy, USB_PHY_TYPE_USB2);
if (err) {
dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
err);
@ -139,7 +139,7 @@ static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev)
{
struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
usb_set_transceiver(NULL);
usb_remove_phy(&nop->phy);
platform_set_drvdata(pdev, NULL);
kfree(nop->phy.otg);

View File

@ -11,60 +11,195 @@
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/err.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/usb/otg.h>
static struct usb_phy *phy;
static LIST_HEAD(phy_list);
static DEFINE_SPINLOCK(phy_lock);
static struct usb_phy *__usb_find_phy(struct list_head *list,
enum usb_phy_type type)
{
struct usb_phy *phy = NULL;
list_for_each_entry(phy, list, head) {
if (phy->type != type)
continue;
return phy;
}
return ERR_PTR(-ENODEV);
}
static void devm_usb_phy_release(struct device *dev, void *res)
{
struct usb_phy *phy = *(struct usb_phy **)res;
usb_put_phy(phy);
}
static int devm_usb_phy_match(struct device *dev, void *res, void *match_data)
{
return res == match_data;
}
/**
* usb_get_transceiver - find the (single) USB transceiver
* devm_usb_get_phy - find the USB PHY
* @dev - device that requests this phy
* @type - the type of the phy the controller requires
*
* Returns the transceiver driver, after getting a refcount to it; or
* null if there is no such transceiver. The caller is responsible for
* calling usb_put_transceiver() to release that count.
* Gets the phy using usb_get_phy(), and associates a device with it using
* devres. On driver detach, release function is invoked on the devres data,
* then, devres data is freed.
*
* For use by USB host and peripheral drivers.
*/
struct usb_phy *usb_get_transceiver(void)
struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type)
{
if (phy)
get_device(phy->dev);
struct usb_phy **ptr, *phy;
ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return NULL;
phy = usb_get_phy(type);
if (!IS_ERR(phy)) {
*ptr = phy;
devres_add(dev, ptr);
} else
devres_free(ptr);
return phy;
}
EXPORT_SYMBOL(usb_get_transceiver);
EXPORT_SYMBOL(devm_usb_get_phy);
/**
* usb_put_transceiver - release the (single) USB transceiver
* @x: the transceiver returned by usb_get_transceiver()
* usb_get_phy - find the USB PHY
* @type - the type of the phy the controller requires
*
* Releases a refcount the caller received from usb_get_transceiver().
* Returns the phy driver, after getting a refcount to it; or
* -ENODEV if there is no such phy. The caller is responsible for
* calling usb_put_phy() to release that count.
*
* For use by USB host and peripheral drivers.
*/
void usb_put_transceiver(struct usb_phy *x)
struct usb_phy *usb_get_phy(enum usb_phy_type type)
{
struct usb_phy *phy = NULL;
unsigned long flags;
spin_lock_irqsave(&phy_lock, flags);
phy = __usb_find_phy(&phy_list, type);
if (IS_ERR(phy)) {
pr_err("unable to find transceiver of type %s\n",
usb_phy_type_string(type));
goto err0;
}
get_device(phy->dev);
err0:
spin_unlock_irqrestore(&phy_lock, flags);
return phy;
}
EXPORT_SYMBOL(usb_get_phy);
/**
* devm_usb_put_phy - release the USB PHY
* @dev - device that wants to release this phy
* @phy - the phy returned by devm_usb_get_phy()
*
* destroys the devres associated with this phy and invokes usb_put_phy
* to release the phy.
*
* For use by USB host and peripheral drivers.
*/
void devm_usb_put_phy(struct device *dev, struct usb_phy *phy)
{
int r;
r = devres_destroy(dev, devm_usb_phy_release, devm_usb_phy_match, phy);
dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
}
EXPORT_SYMBOL(devm_usb_put_phy);
/**
* usb_put_phy - release the USB PHY
* @x: the phy returned by usb_get_phy()
*
* Releases a refcount the caller received from usb_get_phy().
*
* For use by USB host and peripheral drivers.
*/
void usb_put_phy(struct usb_phy *x)
{
if (x)
put_device(x->dev);
}
EXPORT_SYMBOL(usb_put_transceiver);
EXPORT_SYMBOL(usb_put_phy);
/**
* usb_set_transceiver - declare the (single) USB transceiver
* @x: the USB transceiver to be used; or NULL
* usb_add_phy - declare the USB PHY
* @x: the USB phy to be used; or NULL
* @type - the type of this PHY
*
* This call is exclusively for use by transceiver drivers, which
* This call is exclusively for use by phy drivers, which
* coordinate the activities of drivers for host and peripheral
* controllers, and in some cases for VBUS current regulation.
*/
int usb_set_transceiver(struct usb_phy *x)
int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
{
if (phy && x)
return -EBUSY;
phy = x;
return 0;
int ret = 0;
unsigned long flags;
struct usb_phy *phy;
if (x && x->type != USB_PHY_TYPE_UNDEFINED) {
dev_err(x->dev, "not accepting initialized PHY %s\n", x->label);
return -EINVAL;
}
spin_lock_irqsave(&phy_lock, flags);
list_for_each_entry(phy, &phy_list, head) {
if (phy->type == type) {
ret = -EBUSY;
dev_err(x->dev, "transceiver type %s already exists\n",
usb_phy_type_string(type));
goto out;
}
}
x->type = type;
list_add_tail(&x->head, &phy_list);
out:
spin_unlock_irqrestore(&phy_lock, flags);
return ret;
}
EXPORT_SYMBOL(usb_set_transceiver);
EXPORT_SYMBOL(usb_add_phy);
/**
* usb_remove_phy - remove the OTG PHY
* @x: the USB OTG PHY to be removed;
*
* This reverts the effects of usb_add_phy
*/
void usb_remove_phy(struct usb_phy *x)
{
unsigned long flags;
spin_lock_irqsave(&phy_lock, flags);
if (x)
list_del(&x->head);
spin_unlock_irqrestore(&phy_lock, flags);
}
EXPORT_SYMBOL(usb_remove_phy);
const char *otg_state_string(enum usb_otg_state state)
{

View File

@ -33,11 +33,11 @@
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/usb/otg.h>
#include <linux/usb/musb-omap.h>
#include <linux/usb/ulpi.h>
#include <linux/i2c/twl.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
#include <linux/notifier.h>
#include <linux/slab.h>
/* Register defines */
@ -159,7 +159,7 @@ struct twl4030_usb {
enum twl4030_usb_mode usb_mode;
int irq;
u8 linkstat;
enum omap_musb_vbus_id_status linkstat;
bool vbus_supplied;
u8 asleep;
bool irq_enabled;
@ -246,11 +246,11 @@ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
/*-------------------------------------------------------------------------*/
static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl)
static enum omap_musb_vbus_id_status
twl4030_usb_linkstat(struct twl4030_usb *twl)
{
int status;
int linkstat = USB_EVENT_NONE;
struct usb_otg *otg = twl->phy.otg;
enum omap_musb_vbus_id_status linkstat = OMAP_MUSB_UNKNOWN;
twl->vbus_supplied = false;
@ -273,30 +273,23 @@ static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl)
twl->vbus_supplied = true;
if (status & BIT(2))
linkstat = USB_EVENT_ID;
linkstat = OMAP_MUSB_ID_GROUND;
else
linkstat = USB_EVENT_VBUS;
} else
linkstat = USB_EVENT_NONE;
linkstat = OMAP_MUSB_VBUS_VALID;
} else {
if (twl->linkstat != OMAP_MUSB_UNKNOWN)
linkstat = OMAP_MUSB_VBUS_OFF;
}
dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
status, status, linkstat);
twl->phy.last_event = linkstat;
/* REVISIT this assumes host and peripheral controllers
* are registered, and that both are active...
*/
spin_lock_irq(&twl->lock);
twl->linkstat = linkstat;
if (linkstat == USB_EVENT_ID) {
otg->default_a = true;
twl->phy.state = OTG_STATE_A_IDLE;
} else {
otg->default_a = false;
twl->phy.state = OTG_STATE_B_IDLE;
}
spin_unlock_irq(&twl->lock);
return linkstat;
@ -501,10 +494,10 @@ static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL);
static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
{
struct twl4030_usb *twl = _twl;
int status;
enum omap_musb_vbus_id_status status;
status = twl4030_usb_linkstat(twl);
if (status >= 0) {
if (status > 0) {
/* FIXME add a set_power() method so that B-devices can
* configure the charger appropriately. It's not always
* correct to consume VBUS power, and how much current to
@ -516,13 +509,13 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
* USB_LINK_VBUS state. musb_hdrc won't care until it
* starts to handle softconnect right.
*/
if (status == USB_EVENT_NONE)
if (status == OMAP_MUSB_VBUS_OFF ||
status == OMAP_MUSB_ID_FLOAT)
twl4030_phy_suspend(twl, 0);
else
twl4030_phy_resume(twl);
atomic_notifier_call_chain(&twl->phy.notifier, status,
twl->phy.otg->gadget);
omap_musb_mailbox(twl->linkstat);
}
sysfs_notify(&twl->dev->kobj, NULL, "vbus");
@ -531,11 +524,12 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
static void twl4030_usb_phy_init(struct twl4030_usb *twl)
{
int status;
enum omap_musb_vbus_id_status status;
status = twl4030_usb_linkstat(twl);
if (status >= 0) {
if (status == USB_EVENT_NONE) {
if (status > 0) {
if (status == OMAP_MUSB_VBUS_OFF ||
status == OMAP_MUSB_ID_FLOAT) {
__twl4030_phy_power(twl, 0);
twl->asleep = 1;
} else {
@ -543,8 +537,7 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl)
twl->asleep = 0;
}
atomic_notifier_call_chain(&twl->phy.notifier, status,
twl->phy.otg->gadget);
omap_musb_mailbox(twl->linkstat);
}
sysfs_notify(&twl->dev->kobj, NULL, "vbus");
}
@ -598,21 +591,20 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
return -EINVAL;
}
twl = kzalloc(sizeof *twl, GFP_KERNEL);
twl = devm_kzalloc(&pdev->dev, sizeof *twl, GFP_KERNEL);
if (!twl)
return -ENOMEM;
otg = kzalloc(sizeof *otg, GFP_KERNEL);
if (!otg) {
kfree(twl);
otg = devm_kzalloc(&pdev->dev, sizeof *otg, GFP_KERNEL);
if (!otg)
return -ENOMEM;
}
twl->dev = &pdev->dev;
twl->irq = platform_get_irq(pdev, 0);
twl->usb_mode = pdata->usb_mode;
twl->vbus_supplied = false;
twl->asleep = 1;
twl->linkstat = OMAP_MUSB_UNKNOWN;
twl->phy.dev = twl->dev;
twl->phy.label = "twl4030";
@ -629,18 +621,14 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
err = twl4030_usb_ldo_init(twl);
if (err) {
dev_err(&pdev->dev, "ldo init failed\n");
kfree(otg);
kfree(twl);
return err;
}
usb_set_transceiver(&twl->phy);
usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2);
platform_set_drvdata(pdev, twl);
if (device_create_file(&pdev->dev, &dev_attr_vbus))
dev_warn(&pdev->dev, "could not create sysfs file\n");
ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
/* Our job is to use irqs and status from the power module
* to keep the transceiver disabled when nothing's connected.
*
@ -651,13 +639,11 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
*/
twl->irq_enabled = true;
status = request_threaded_irq(twl->irq, NULL, twl4030_usb_irq,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
"twl4030_usb", twl);
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
IRQF_ONESHOT, "twl4030_usb", twl);
if (status < 0) {
dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n",
twl->irq, status);
kfree(otg);
kfree(twl);
return status;
}
@ -701,9 +687,6 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev)
regulator_put(twl->usb1v8);
regulator_put(twl->usb3v1);
kfree(twl->phy.otg);
kfree(twl);
return 0;
}

View File

@ -26,10 +26,10 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/usb/otg.h>
#include <linux/usb/musb-omap.h>
#include <linux/i2c/twl.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
#include <linux/notifier.h>
#include <linux/slab.h>
#include <linux/delay.h>
@ -100,7 +100,7 @@ struct twl6030_usb {
int irq1;
int irq2;
u8 linkstat;
enum omap_musb_vbus_id_status linkstat;
u8 asleep;
bool irq_enabled;
bool vbus_enable;
@ -147,7 +147,7 @@ static int twl6030_phy_init(struct usb_phy *x)
dev = twl->dev;
pdata = dev->platform_data;
if (twl->linkstat == USB_EVENT_ID)
if (twl->linkstat == OMAP_MUSB_ID_GROUND)
pdata->phy_power(twl->dev, 1, 1);
else
pdata->phy_power(twl->dev, 0, 1);
@ -235,13 +235,13 @@ static ssize_t twl6030_usb_vbus_show(struct device *dev,
spin_lock_irqsave(&twl->lock, flags);
switch (twl->linkstat) {
case USB_EVENT_VBUS:
case OMAP_MUSB_VBUS_VALID:
ret = snprintf(buf, PAGE_SIZE, "vbus\n");
break;
case USB_EVENT_ID:
case OMAP_MUSB_ID_GROUND:
ret = snprintf(buf, PAGE_SIZE, "id\n");
break;
case USB_EVENT_NONE:
case OMAP_MUSB_VBUS_OFF:
ret = snprintf(buf, PAGE_SIZE, "none\n");
break;
default:
@ -256,8 +256,7 @@ static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL);
static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
{
struct twl6030_usb *twl = _twl;
struct usb_otg *otg = twl->phy.otg;
int status;
enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
u8 vbus_state, hw_state;
hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
@ -268,22 +267,18 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
if (vbus_state & VBUS_DET) {
regulator_enable(twl->usb3v3);
twl->asleep = 1;
status = USB_EVENT_VBUS;
otg->default_a = false;
twl->phy.state = OTG_STATE_B_IDLE;
status = OMAP_MUSB_VBUS_VALID;
twl->linkstat = status;
twl->phy.last_event = status;
atomic_notifier_call_chain(&twl->phy.notifier,
status, otg->gadget);
omap_musb_mailbox(status);
} else {
status = USB_EVENT_NONE;
twl->linkstat = status;
twl->phy.last_event = status;
atomic_notifier_call_chain(&twl->phy.notifier,
status, otg->gadget);
if (twl->asleep) {
regulator_disable(twl->usb3v3);
twl->asleep = 0;
if (twl->linkstat != OMAP_MUSB_UNKNOWN) {
status = OMAP_MUSB_VBUS_OFF;
twl->linkstat = status;
omap_musb_mailbox(status);
if (twl->asleep) {
regulator_disable(twl->usb3v3);
twl->asleep = 0;
}
}
}
}
@ -295,8 +290,7 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
{
struct twl6030_usb *twl = _twl;
struct usb_otg *otg = twl->phy.otg;
int status = USB_EVENT_NONE;
enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
u8 hw_state;
hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
@ -307,13 +301,11 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
twl->asleep = 1;
twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR);
twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
status = USB_EVENT_ID;
status = OMAP_MUSB_ID_GROUND;
otg->default_a = true;
twl->phy.state = OTG_STATE_A_IDLE;
twl->linkstat = status;
twl->phy.last_event = status;
atomic_notifier_call_chain(&twl->phy.notifier, status,
otg->gadget);
omap_musb_mailbox(status);
} else {
twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
@ -402,20 +394,19 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
pdata = dev->platform_data;
twl = kzalloc(sizeof *twl, GFP_KERNEL);
twl = devm_kzalloc(dev, sizeof *twl, GFP_KERNEL);
if (!twl)
return -ENOMEM;
otg = kzalloc(sizeof *otg, GFP_KERNEL);
if (!otg) {
kfree(twl);
otg = devm_kzalloc(dev, sizeof *otg, GFP_KERNEL);
if (!otg)
return -ENOMEM;
}
twl->dev = &pdev->dev;
twl->irq1 = platform_get_irq(pdev, 0);
twl->irq2 = platform_get_irq(pdev, 1);
twl->features = pdata->features;
twl->linkstat = OMAP_MUSB_UNKNOWN;
twl->phy.dev = twl->dev;
twl->phy.label = "twl6030";
@ -436,18 +427,14 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
err = twl6030_usb_ldo_init(twl);
if (err) {
dev_err(&pdev->dev, "ldo init failed\n");
kfree(otg);
kfree(twl);
return err;
}
usb_set_transceiver(&twl->phy);
usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2);
platform_set_drvdata(pdev, twl);
if (device_create_file(&pdev->dev, &dev_attr_vbus))
dev_warn(&pdev->dev, "could not create sysfs file\n");
ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
twl->irq_enabled = true;
@ -458,8 +445,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
twl->irq1, status);
device_remove_file(twl->dev, &dev_attr_vbus);
kfree(otg);
kfree(twl);
return status;
}
@ -471,8 +456,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
twl->irq2, status);
free_irq(twl->irq1, twl);
device_remove_file(twl->dev, &dev_attr_vbus);
kfree(otg);
kfree(twl);
return status;
}
@ -503,8 +486,6 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev)
pdata->phy_exit(twl->dev);
device_remove_file(twl->dev, &dev_attr_vbus);
cancel_work_sync(&twl->set_vbus_work);
kfree(twl->phy.otg);
kfree(twl);
return 0;
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2011-2012 by Texas Instruments
*
* The Inventra Controller Driver for Linux is free software; you
* can redistribute it and/or modify it under the terms of the GNU
* General Public License version 2 as published by the Free Software
* Foundation.
*/
#ifndef __MUSB_OMAP_H__
#define __MUSB_OMAP_H__
enum omap_musb_vbus_id_status {
OMAP_MUSB_UNKNOWN = 0,
OMAP_MUSB_ID_GROUND,
OMAP_MUSB_ID_FLOAT,
OMAP_MUSB_VBUS_VALID,
OMAP_MUSB_VBUS_OFF,
};
#if (defined(CONFIG_USB_MUSB_OMAP2PLUS) || \
defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE))
void omap_musb_mailbox(enum omap_musb_vbus_id_status status);
#else
static inline void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
{
}
#endif
#endif /* __MUSB_OMAP_H__ */

View File

@ -43,6 +43,13 @@ enum usb_phy_events {
USB_EVENT_ENUMERATED, /* gadget driver enumerated */
};
/* associate a type with PHY */
enum usb_phy_type {
USB_PHY_TYPE_UNDEFINED,
USB_PHY_TYPE_USB2,
USB_PHY_TYPE_USB3,
};
struct usb_phy;
/* for transceivers connected thru an ULPI interface, the user must
@ -89,6 +96,7 @@ struct usb_phy {
const char *label;
unsigned int flags;
enum usb_phy_type type;
enum usb_otg_state state;
enum usb_phy_events last_event;
@ -105,6 +113,9 @@ struct usb_phy {
u16 port_status;
u16 port_change;
/* to support controllers that have multiple transceivers */
struct list_head head;
/* initialize/shutdown the OTG controller */
int (*init)(struct usb_phy *x);
void (*shutdown)(struct usb_phy *x);
@ -121,7 +132,8 @@ struct usb_phy {
/* for board-specific init logic */
extern int usb_set_transceiver(struct usb_phy *);
extern int usb_add_phy(struct usb_phy *, enum usb_phy_type type);
extern void usb_remove_phy(struct usb_phy *);
#if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE))
/* sometimes transceivers are accessed only through e.g. ULPI */
@ -172,16 +184,29 @@ usb_phy_shutdown(struct usb_phy *x)
/* for usb host and peripheral controller drivers */
#ifdef CONFIG_USB_OTG_UTILS
extern struct usb_phy *usb_get_transceiver(void);
extern void usb_put_transceiver(struct usb_phy *);
extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
extern struct usb_phy *devm_usb_get_phy(struct device *dev,
enum usb_phy_type type);
extern void usb_put_phy(struct usb_phy *);
extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x);
extern const char *otg_state_string(enum usb_otg_state state);
#else
static inline struct usb_phy *usb_get_transceiver(void)
static inline struct usb_phy *usb_get_phy(enum usb_phy_type type)
{
return NULL;
}
static inline void usb_put_transceiver(struct usb_phy *x)
static inline struct usb_phy *devm_usb_get_phy(struct device *dev,
enum usb_phy_type type)
{
return NULL;
}
static inline void usb_put_phy(struct usb_phy *x)
{
}
static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x)
{
}
@ -276,4 +301,15 @@ usb_unregister_notifier(struct usb_phy *x, struct notifier_block *nb)
/* for OTG controller drivers (and maybe other stuff) */
extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num);
static inline const char *usb_phy_type_string(enum usb_phy_type type)
{
switch (type) {
case USB_PHY_TYPE_USB2:
return "USB2 PHY";
case USB_PHY_TYPE_USB3:
return "USB3 PHY";
default:
return "UNKNOWN PHY TYPE";
}
}
#endif /* __LINUX_USB_OTG_H */