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.
This commit is contained in:
Greg Kroah-Hartman 2012-07-05 15:35:41 -07:00
Родитель 933141509c f8ecf82948
Коммит ff9cce8277
38 изменённых файлов: 538 добавлений и 325 удалений

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -27,6 +27,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/err.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/fsl_devices.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) { if (pdata->operating_mode == FSL_USB2_DR_OTG) {
struct ehci_hcd *ehci = hcd_to_ehci(hcd); 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", dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, phy=0x%p\n",
hcd, ehci, hcd->phy); hcd, ehci, hcd->phy);
if (hcd->phy) { if (!IS_ERR_OR_NULL(hcd->phy)) {
retval = otg_set_host(hcd->phy->otg, retval = otg_set_host(hcd->phy->otg,
&ehci_to_hcd(ehci)->self); &ehci_to_hcd(ehci)->self);
if (retval) { if (retval) {
usb_put_transceiver(hcd->phy); usb_put_phy(hcd->phy);
goto err4; goto err4;
} }
} else { } 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; 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); otg_set_host(hcd->phy->otg, NULL);
usb_put_transceiver(hcd->phy); usb_put_phy(hcd->phy);
} }
usb_remove_hcd(hcd); usb_remove_hcd(hcd);

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -806,7 +806,7 @@ static int fsl_otg_conf(struct platform_device *pdev)
fsl_otg_dev = fsl_otg_tc; fsl_otg_dev = fsl_otg_tc;
/* Store the otg transceiver */ /* 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) { if (status) {
pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n"); pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n");
goto err; goto err;
@ -824,7 +824,7 @@ err:
int usb_otg_start(struct platform_device *pdev) int usb_otg_start(struct platform_device *pdev)
{ {
struct fsl_otg *p_otg; 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; struct otg_fsm *fsm;
int status; int status;
struct resource *res; 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; 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); free_irq(fsl_otg_dev->irq, fsl_otg_dev);
iounmap((void *)usb_dr_regs); iounmap((void *)usb_dr_regs);

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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_host = msm_otg_set_host;
phy->otg->set_peripheral = msm_otg_set_peripheral; 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) { if (ret) {
dev_err(&pdev->dev, "usb_set_transceiver failed\n"); dev_err(&pdev->dev, "usb_add_phy failed\n");
goto free_irq; goto free_irq;
} }
@ -1624,7 +1624,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 0); device_init_wakeup(&pdev->dev, 0);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
usb_set_transceiver(NULL); usb_remove_phy(phy);
free_irq(motg->irq, motg); free_irq(motg->irq, motg);
/* /*

Просмотреть файл

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

Просмотреть файл

@ -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_host = nop_set_host;
nop->phy.otg->set_peripheral = nop_set_peripheral; 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) { if (err) {
dev_err(&pdev->dev, "can't register transceiver, err: %d\n", dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
err); 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); struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
usb_set_transceiver(NULL); usb_remove_phy(&nop->phy);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
kfree(nop->phy.otg); kfree(nop->phy.otg);

Просмотреть файл

@ -11,60 +11,195 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/err.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/slab.h>
#include <linux/usb/otg.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 * Gets the phy using usb_get_phy(), and associates a device with it using
* null if there is no such transceiver. The caller is responsible for * devres. On driver detach, release function is invoked on the devres data,
* calling usb_put_transceiver() to release that count. * then, devres data is freed.
* *
* For use by USB host and peripheral drivers. * 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) struct usb_phy **ptr, *phy;
get_device(phy->dev);
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; return phy;
} }
EXPORT_SYMBOL(usb_get_transceiver); EXPORT_SYMBOL(devm_usb_get_phy);
/** /**
* usb_put_transceiver - release the (single) USB transceiver * usb_get_phy - find the USB PHY
* @x: the transceiver returned by usb_get_transceiver() * @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. * 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) if (x)
put_device(x->dev); put_device(x->dev);
} }
EXPORT_SYMBOL(usb_put_transceiver); EXPORT_SYMBOL(usb_put_phy);
/** /**
* usb_set_transceiver - declare the (single) USB transceiver * usb_add_phy - declare the USB PHY
* @x: the USB transceiver to be used; or NULL * @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 * coordinate the activities of drivers for host and peripheral
* controllers, and in some cases for VBUS current regulation. * 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) int ret = 0;
return -EBUSY; unsigned long flags;
phy = x; struct usb_phy *phy;
return 0;
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) const char *otg_state_string(enum usb_otg_state state)
{ {

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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__ */

Просмотреть файл

@ -43,6 +43,13 @@ enum usb_phy_events {
USB_EVENT_ENUMERATED, /* gadget driver enumerated */ 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; struct usb_phy;
/* for transceivers connected thru an ULPI interface, the user must /* for transceivers connected thru an ULPI interface, the user must
@ -89,6 +96,7 @@ struct usb_phy {
const char *label; const char *label;
unsigned int flags; unsigned int flags;
enum usb_phy_type type;
enum usb_otg_state state; enum usb_otg_state state;
enum usb_phy_events last_event; enum usb_phy_events last_event;
@ -105,6 +113,9 @@ struct usb_phy {
u16 port_status; u16 port_status;
u16 port_change; u16 port_change;
/* to support controllers that have multiple transceivers */
struct list_head head;
/* initialize/shutdown the OTG controller */ /* initialize/shutdown the OTG controller */
int (*init)(struct usb_phy *x); int (*init)(struct usb_phy *x);
void (*shutdown)(struct usb_phy *x); void (*shutdown)(struct usb_phy *x);
@ -121,7 +132,8 @@ struct usb_phy {
/* for board-specific init logic */ /* 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)) #if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE))
/* sometimes transceivers are accessed only through e.g. ULPI */ /* 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 */ /* for usb host and peripheral controller drivers */
#ifdef CONFIG_USB_OTG_UTILS #ifdef CONFIG_USB_OTG_UTILS
extern struct usb_phy *usb_get_transceiver(void); extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
extern void usb_put_transceiver(struct usb_phy *); 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); extern const char *otg_state_string(enum usb_otg_state state);
#else #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; 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) */ /* for OTG controller drivers (and maybe other stuff) */
extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num); 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 */ #endif /* __LINUX_USB_OTG_H */