dev_err(di->dev, "%s mask and set failed\n", __func__);
usb_unregister_notifier(di->usb_phy, &di->nb);
- usb_put_transceiver(di->usb_phy);
+ usb_put_phy(di->usb_phy);
/* Delete the work queue */
destroy_workqueue(di->charger_wq);
goto free_ac;
}
- di->usb_phy = usb_get_transceiver();
- if (!di->usb_phy) {
+ di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(di->usb_phy)) {
dev_err(di->dev, "failed to get usb transceiver\n");
ret = -EINVAL;
goto free_usb;
free_irq(irq, di);
}
put_usb_phy:
- usb_put_transceiver(di->usb_phy);
+ usb_put_phy(di->usb_phy);
free_usb:
power_supply_unregister(&di->usb_chg.psy);
free_ac:
if (!isp)
return -ENOMEM;
- isp->phy = usb_get_transceiver();
- if (!isp->phy)
+ isp->phy = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(isp->phy))
goto fail0;
isp->dev = &pdev->dev;
power_supply_unregister(&isp->psy);
fail1:
isp1704_charger_set_power(isp, 0);
- usb_put_transceiver(isp->phy);
+ usb_put_phy(isp->phy);
fail0:
kfree(isp);
usb_unregister_notifier(isp->phy, &isp->nb);
power_supply_unregister(&isp->psy);
- usb_put_transceiver(isp->phy);
+ usb_put_phy(isp->phy);
isp1704_charger_set_power(isp, 0);
kfree(isp);
}
#ifdef CONFIG_USB_OTG_UTILS
- transceiver = usb_get_transceiver();
- if (transceiver && !pdata->is_usb_online) {
- pdata->is_usb_online = otg_is_usb_online;
- }
- if (transceiver && !pdata->is_ac_online) {
- pdata->is_ac_online = otg_is_ac_online;
+ transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (!IS_ERR_OR_NULL(transceiver)) {
+ if (!pdata->is_usb_online)
+ pdata->is_usb_online = otg_is_usb_online;
+ if (!pdata->is_ac_online)
+ pdata->is_ac_online = otg_is_ac_online;
}
#endif
}
#ifdef CONFIG_USB_OTG_UTILS
- if (transceiver && pdata->use_otg_notifier) {
+ if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) {
otg_nb.notifier_call = otg_handle_notification;
ret = usb_register_notifier(transceiver, &otg_nb);
if (ret) {
if (pdata->is_ac_online && ac_irq)
free_irq(ac_irq->start, &pda_psy_ac);
#ifdef CONFIG_USB_OTG_UTILS
- if (transceiver)
- usb_put_transceiver(transceiver);
+ if (!IS_ERR_OR_NULL(transceiver))
+ usb_put_phy(transceiver);
#endif
ac_irq_failed:
if (pdata->is_ac_online)
if (pdata->is_ac_online)
power_supply_unregister(&pda_psy_ac);
#ifdef CONFIG_USB_OTG_UTILS
- if (transceiver)
- usb_put_transceiver(transceiver);
+ if (!IS_ERR_OR_NULL(transceiver))
+ usb_put_phy(transceiver);
#endif
if (ac_draw) {
regulator_put(ac_draw);
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/i2c/twl.h>
INIT_WORK(&bci->work, twl4030_bci_usb_work);
- bci->transceiver = usb_get_transceiver();
- if (bci->transceiver != NULL) {
+ bci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (!IS_ERR_OR_NULL(bci->transceiver)) {
bci->usb_nb.notifier_call = twl4030_bci_usb_ncb;
usb_register_notifier(bci->transceiver, &bci->usb_nb);
}
return 0;
fail_unmask_interrupts:
- if (bci->transceiver != NULL) {
+ if (!IS_ERR_OR_NULL(bci->transceiver)) {
usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
- usb_put_transceiver(bci->transceiver);
+ usb_put_phy(bci->transceiver);
}
free_irq(bci->irq_bci, bci);
fail_bci_irq:
twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
TWL4030_INTERRUPTS_BCIIMR2A);
- if (bci->transceiver != NULL) {
+ if (!IS_ERR_OR_NULL(bci->transceiver)) {
usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
- usb_put_transceiver(bci->transceiver);
+ usb_put_phy(bci->transceiver);
}
free_irq(bci->irq_bci, bci);
free_irq(bci->irq_chg, bci);
#include <linux/device.h>
#include <linux/dmapool.h>
#include <linux/dma-mapping.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/module.h>
udc->gadget.ep0 = &udc->ep0in->ep;
- udc->transceiver = usb_get_transceiver();
+ udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
if (udc->transceiver == NULL) {
if (retval)
goto unreg_device;
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
retval = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (retval)
return retval;
remove_trans:
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
- usb_put_transceiver(udc->transceiver);
+ usb_put_phy(udc->transceiver);
}
dev_err(dev, "error = %i\n", retval);
unreg_device:
device_unregister(&udc->gadget.dev);
put_transceiver:
- if (udc->transceiver)
- usb_put_transceiver(udc->transceiver);
+ if (!IS_ERR_OR_NULL(udc->transceiver))
+ usb_put_phy(udc->transceiver);
free_pools:
dma_pool_destroy(udc->td_pool);
free_qh_pool:
dma_pool_destroy(udc->td_pool);
dma_pool_destroy(udc->qh_pool);
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
otg_set_peripheral(udc->transceiver->otg, NULL);
- usb_put_transceiver(udc->transceiver);
+ usb_put_phy(udc->transceiver);
}
dbg_remove_files(&udc->gadget.dev);
device_unregister(&udc->gadget.dev);
#include <linux/ioport.h>
#include <linux/types.h>
#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/list.h>
struct fsl_udc *udc;
udc = container_of(gadget, struct fsl_udc, gadget);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return usb_phy_set_power(udc->transceiver, mA);
return -ENOTSUPP;
}
goto out;
}
- if (udc_controller->transceiver) {
+ if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
/* Suspend the controller until OTG enable it */
udc_controller->stopped = 1;
printk(KERN_INFO "Suspend udc for OTG auto detect\n");
/* connect to bus through transceiver */
- if (udc_controller->transceiver) {
+ if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
retval = otg_set_peripheral(
udc_controller->transceiver->otg,
&udc_controller->gadget);
if (!driver || driver != udc_controller->driver || !driver->unbind)
return -EINVAL;
- if (udc_controller->transceiver)
+ if (!IS_ERR_OR_NULL(udc_controller->transceiver))
otg_set_peripheral(udc_controller->transceiver->otg, NULL);
/* stop DR, disable intr */
#ifdef CONFIG_USB_OTG
if (pdata->operating_mode == FSL_USB2_DR_OTG) {
- udc_controller->transceiver = usb_get_transceiver();
- if (!udc_controller->transceiver) {
+ udc_controller->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(udc_controller->transceiver)) {
ERR("Can't find OTG driver!\n");
ret = -ENODEV;
goto err_kfree;
goto err_free_irq;
}
- if (!udc_controller->transceiver) {
+ if (IS_ERR_OR_NULL(udc_controller->transceiver)) {
/* initialize usb hw reg except for regs for EP,
* leave usbintr reg untouched */
dr_controller_setup(udc_controller);
if (ret < 0)
goto err_free_irq;
- if (udc_controller->transceiver)
+ if (!IS_ERR_OR_NULL(udc_controller->transceiver))
udc_controller->gadget.is_otg = 1;
/* setup QH and epctrl for ep0 */
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
return retval;
}
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
retval = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (retval) {
* then vbus irq will not be requested in udc driver.
*/
if (udc->pdata && udc->pdata->vbus
- && udc->clock_gating && udc->transceiver == NULL)
+ && udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver))
free_irq(udc->pdata->vbus->irq, &dev->dev);
/* free memory allocated in probe */
#ifdef CONFIG_USB_OTG_UTILS
if (pdata->mode == MV_USB_MODE_OTG)
- udc->transceiver = usb_get_transceiver();
+ udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
#endif
udc->clknum = pdata->clknum;
eps_init(udc);
/* VBUS detect: we can disable/enable clock on demand.*/
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
udc->clock_gating = 1;
else if (pdata->vbus) {
udc->clock_gating = 1;
err_unregister:
if (udc->pdata && udc->pdata->vbus
- && udc->clock_gating && udc->transceiver == NULL)
+ && udc->clock_gating && IS_ERR_OR_NULL(udc->transceiver))
free_irq(pdata->vbus->irq, &dev->dev);
device_unregister(&udc->gadget.dev);
err_free_irq:
struct mv_udc *udc = the_controller;
/* if OTG is enabled, the following will be done in OTG driver*/
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return 0;
if (udc->pdata->vbus && udc->pdata->vbus->poll)
int retval;
/* if OTG is enabled, the following will be done in OTG driver*/
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return 0;
if (!udc->clock_gating) {
#include <linux/usb/otg.h>
#include <linux/dma-mapping.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/prefetch.h>
#include <linux/io.h>
/* NOTE: non-OTG systems may use SRP TOO... */
} else if (!(udc->devstat & UDC_ATT)) {
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
retval = otg_start_srp(udc->transceiver->otg);
}
spin_unlock_irqrestore(&udc->lock, flags);
struct omap_udc *udc;
udc = container_of(gadget, struct omap_udc, gadget);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return usb_phy_set_power(udc->transceiver, mA);
return -EOPNOTSUPP;
}
if (devstat & UDC_ATT) {
udc->gadget.speed = USB_SPEED_FULL;
VDBG("connect\n");
- if (!udc->transceiver)
+ if (IS_ERR_OR_NULL(udc->transceiver))
pullup_enable(udc);
/* if (driver->connect) call it */
} else if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
udc->gadget.speed = USB_SPEED_UNKNOWN;
- if (!udc->transceiver)
+ if (IS_ERR_OR_NULL(udc->transceiver))
pullup_disable(udc);
DBG("disconnect, gadget %s\n",
udc->driver->driver.name);
udc->driver->suspend(&udc->gadget);
spin_lock(&udc->lock);
}
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
usb_phy_set_suspend(
udc->transceiver, 1);
} else {
VDBG("resume\n");
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
usb_phy_set_suspend(
udc->transceiver, 0);
if (udc->gadget.speed == USB_SPEED_FULL
omap_writew(UDC_IRQ_SRC_MASK, UDC_IRQ_SRC);
/* connect to bus through transceiver */
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
status = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (status < 0) {
if (machine_without_vbus_sense())
omap_vbus_session(&udc->gadget, 0);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
(void) otg_set_peripheral(udc->transceiver->otg, NULL);
else
pullup_disable(udc);
* use it. Except for OTG, we don't _need_ to talk to one;
* but not having one probably means no VBUS detection.
*/
- xceiv = usb_get_transceiver();
- if (xceiv)
+ xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (!IS_ERR_OR_NULL(xceiv))
type = xceiv->label;
else if (config->otg) {
DBG("OTG requires external transceiver!\n");
case 16:
case 19:
case 25:
- if (!xceiv) {
+ if (IS_ERR_OR_NULL(xceiv)) {
DBG("external transceiver not registered!\n");
type = "unknown";
}
udc = NULL;
cleanup0:
- if (xceiv)
- usb_put_transceiver(xceiv);
+ if (!IS_ERR_OR_NULL(xceiv))
+ usb_put_phy(xceiv);
if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
clk_disable(hhc_clk);
udc->done = &done;
pullup_disable(udc);
- if (udc->transceiver) {
- usb_put_transceiver(udc->transceiver);
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
+ usb_put_phy(udc->transceiver);
udc->transceiver = NULL;
}
omap_writew(0, UDC_SYSCON1);
#include <linux/ioport.h>
#include <linux/types.h>
#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
udc = container_of(_gadget, struct pxa25x_udc, gadget);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return usb_phy_set_power(udc->transceiver, mA);
return -EOPNOTSUPP;
}
DMSG("registered gadget driver '%s'\n", driver->driver.name);
/* connect to bus through transceiver */
- if (dev->transceiver) {
+ if (!IS_ERR_OR_NULL(dev->transceiver)) {
retval = otg_set_peripheral(dev->transceiver->otg,
&dev->gadget);
if (retval) {
stop_activity(dev, driver);
local_irq_enable();
- if (dev->transceiver)
+ if (!IS_ERR_OR_NULL(dev->transceiver))
(void) otg_set_peripheral(dev->transceiver->otg, NULL);
driver->unbind(&dev->gadget);
dev->dev = &pdev->dev;
dev->mach = pdev->dev.platform_data;
- dev->transceiver = usb_get_transceiver();
+ dev->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
if (gpio_is_valid(dev->mach->gpio_pullup)) {
if ((retval = gpio_request(dev->mach->gpio_pullup,
if (gpio_is_valid(dev->mach->gpio_pullup))
gpio_free(dev->mach->gpio_pullup);
err_gpio_pullup:
- if (dev->transceiver) {
- usb_put_transceiver(dev->transceiver);
+ if (!IS_ERR_OR_NULL(dev->transceiver)) {
+ usb_put_phy(dev->transceiver);
dev->transceiver = NULL;
}
clk_put(dev->clk);
clk_put(dev->clk);
- if (dev->transceiver) {
- usb_put_transceiver(dev->transceiver);
+ if (!IS_ERR_OR_NULL(dev->transceiver)) {
+ usb_put_phy(dev->transceiver);
dev->transceiver = NULL;
}
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/list.h>
int put_on;
put_on = ((udc->pullup_on) && (udc->driver));
- put_on &= ((udc->vbus_sensed) || (!udc->transceiver));
+ put_on &= ((udc->vbus_sensed) || (IS_ERR_OR_NULL(udc->transceiver)));
return put_on;
}
int put_off;
put_off = ((!udc->pullup_on) || (!udc->driver));
- put_off |= ((!udc->vbus_sensed) && (udc->transceiver));
+ put_off |= ((!udc->vbus_sensed) && (!IS_ERR_OR_NULL(udc->transceiver)));
return put_off;
}
struct pxa_udc *udc;
udc = to_gadget_udc(_gadget);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return usb_phy_set_power(udc->transceiver, mA);
return -EOPNOTSUPP;
}
dev_dbg(udc->dev, "registered gadget driver '%s'\n",
driver->driver.name);
- if (udc->transceiver) {
+ if (!IS_ERR_OR_NULL(udc->transceiver)) {
retval = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (retval) {
dev_info(udc->dev, "unregistered gadget driver '%s'\n",
driver->driver.name);
- if (udc->transceiver)
+ if (!IS_ERR_OR_NULL(udc->transceiver))
return otg_set_peripheral(udc->transceiver->otg, NULL);
return 0;
}
udc->dev = &pdev->dev;
udc->mach = pdev->dev.platform_data;
- udc->transceiver = usb_get_transceiver();
+ udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
gpio = udc->mach->gpio_pullup;
if (gpio_is_valid(gpio)) {
if (gpio_is_valid(gpio))
gpio_free(gpio);
- usb_put_transceiver(udc->transceiver);
+ usb_put_phy(udc->transceiver);
udc->transceiver = NULL;
platform_set_drvdata(_dev, NULL);
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
}
/* connect to bus through transceiver */
- if (hsudc->transceiver) {
+ if (!IS_ERR_OR_NULL(hsudc->transceiver)) {
ret = otg_set_peripheral(hsudc->transceiver->otg,
&hsudc->gadget);
if (ret) {
s3c_hsudc_stop_activity(hsudc);
spin_unlock_irqrestore(&hsudc->lock, flags);
- if (hsudc->transceiver)
+ if (!IS_ERR_OR_NULL(hsudc->transceiver))
(void) otg_set_peripheral(hsudc->transceiver->otg, NULL);
disable_irq(hsudc->irq);
if (!hsudc)
return -ENODEV;
- if (hsudc->transceiver)
+ if (!IS_ERR_OR_NULL(hsudc->transceiver))
return usb_phy_set_power(hsudc->transceiver, mA);
return -EOPNOTSUPP;
hsudc->dev = dev;
hsudc->pd = pdev->dev.platform_data;
- hsudc->transceiver = usb_get_transceiver();
+ hsudc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
for (i = 0; i < ARRAY_SIZE(hsudc->supplies); i++)
hsudc->supplies[i].supply = s3c_hsudc_supply_names[i];
err_remap:
release_mem_region(res->start, resource_size(res));
err_res:
- if (hsudc->transceiver)
- usb_put_transceiver(hsudc->transceiver);
+ if (!IS_ERR_OR_NULL(hsudc->transceiver))
+ usb_put_phy(hsudc->transceiver);
regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
err_supplies:
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/pm.h>
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/fsl_devices.h>
if (pdata->operating_mode == FSL_USB2_DR_OTG) {
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- hcd->phy = usb_get_transceiver();
+ hcd->phy = usb_get_phy(USB_PHY_TYPE_USB2);
dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, phy=0x%p\n",
hcd, ehci, hcd->phy);
- if (hcd->phy) {
+ if (!IS_ERR_OR_NULL(hcd->phy)) {
retval = otg_set_host(hcd->phy->otg,
&ehci_to_hcd(ehci)->self);
if (retval) {
- usb_put_transceiver(hcd->phy);
+ usb_put_phy(hcd->phy);
goto err4;
}
} else {
{
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
- if (hcd->phy) {
+ if (!IS_ERR_OR_NULL(hcd->phy)) {
otg_set_host(hcd->phy->otg, NULL);
- usb_put_transceiver(hcd->phy);
+ usb_put_phy(hcd->phy);
}
usb_remove_hcd(hcd);
* powering up VBUS, mapping of registers address space and power
* management.
*/
- phy = usb_get_transceiver();
- if (!phy) {
+ phy = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(phy)) {
dev_err(&pdev->dev, "unable to find transceiver\n");
ret = -ENODEV;
goto unmap;
return 0;
put_transceiver:
- usb_put_transceiver(phy);
+ usb_put_phy(phy);
unmap:
iounmap(hcd->regs);
put_hcd:
pm_runtime_set_suspended(&pdev->dev);
otg_set_host(phy->otg, NULL);
- usb_put_transceiver(phy);
+ usb_put_phy(phy);
usb_put_hcd(hcd);
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/usb/otg.h>
#include <linux/platform_data/mv_usb.h>
ehci_mv->mode = pdata->mode;
if (ehci_mv->mode == MV_USB_MODE_OTG) {
#ifdef CONFIG_USB_OTG_UTILS
- ehci_mv->otg = usb_get_transceiver();
- if (!ehci_mv->otg) {
+ ehci_mv->otg = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(ehci_mv->otg)) {
dev_err(&pdev->dev,
"unable to find transceiver\n");
retval = -ENODEV;
pdata->set_vbus(0);
#ifdef CONFIG_USB_OTG_UTILS
err_put_transceiver:
- if (ehci_mv->otg)
- usb_put_transceiver(ehci_mv->otg);
+ if (!IS_ERR_OR_NULL(ehci_mv->otg))
+ usb_put_phy(ehci_mv->otg);
#endif
err_disable_clk:
mv_ehci_disable(ehci_mv);
if (hcd->rh_registered)
usb_remove_hcd(hcd);
- if (ehci_mv->otg) {
+ if (!IS_ERR_OR_NULL(ehci_mv->otg)) {
otg_set_host(ehci_mv->otg->otg, NULL);
- usb_put_transceiver(ehci_mv->otg);
+ usb_put_phy(ehci_mv->otg);
}
if (ehci_mv->mode == MV_USB_MODE_HOST) {
*/
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/platform_data/tegra_usb.h>
#include <linux/irq.h>
#ifdef CONFIG_USB_OTG_UTILS
if (pdata->operating_mode == TEGRA_USB_OTG) {
- tegra->transceiver = usb_get_transceiver();
- if (tegra->transceiver)
+ tegra->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (!IS_ERR_OR_NULL(tegra->transceiver))
otg_set_host(tegra->transceiver->otg, &hcd->self);
}
#endif
fail:
#ifdef CONFIG_USB_OTG_UTILS
- if (tegra->transceiver) {
+ if (!IS_ERR_OR_NULL(tegra->transceiver)) {
otg_set_host(tegra->transceiver->otg, NULL);
- usb_put_transceiver(tegra->transceiver);
+ usb_put_phy(tegra->transceiver);
}
#endif
tegra_usb_phy_close(tegra->phy);
pm_runtime_put_noidle(&pdev->dev);
#ifdef CONFIG_USB_OTG_UTILS
- if (tegra->transceiver) {
+ if (!IS_ERR_OR_NULL(tegra->transceiver)) {
otg_set_host(tegra->transceiver->otg, NULL);
- usb_put_transceiver(tegra->transceiver);
+ usb_put_phy(tegra->transceiver);
}
#endif
#include <linux/jiffies.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/gpio.h>
#include <mach/hardware.h>
#ifdef CONFIG_USB_OTG
if (need_transceiver) {
- hcd->phy = usb_get_transceiver();
- if (hcd->phy) {
+ hcd->phy = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (!IS_ERR_OR_NULL(hcd->phy)) {
int status = otg_set_host(hcd->phy->otg,
&ohci_to_hcd(ohci)->self);
dev_dbg(hcd->self.controller, "init %s phy, status %d\n",
hcd->phy->label, status);
if (status) {
- usb_put_transceiver(hcd->phy);
+ usb_put_phy(hcd->phy);
return status;
}
} else {
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
usb_remove_hcd(hcd);
- if (hcd->phy) {
+ if (!IS_ERR_OR_NULL(hcd->phy)) {
(void) otg_set_host(hcd->phy->otg, 0);
- usb_put_transceiver(hcd->phy);
+ usb_put_phy(hcd->phy);
}
if (machine_is_omap_osk())
gpio_free(9);
#include <linux/init.h>
#include <linux/module.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
return -ENODEV;
usb_nop_xceiv_register();
- musb->xceiv = usb_get_transceiver();
- if (!musb->xceiv)
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv))
return -ENODEV;
if (is_host_enabled(musb))
if (data->set_phy_power)
data->set_phy_power(0);
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;
#include <linux/list.h>
#include <linux/gpio.h>
#include <linux/io.h>
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/prefetch.h>
gpio_direction_output(musb->config->gpio_vrsel, 0);
usb_nop_xceiv_register();
- musb->xceiv = usb_get_transceiver();
- if (!musb->xceiv) {
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv)) {
gpio_free(musb->config->gpio_vrsel);
return -ENODEV;
}
{
gpio_free(musb->config->gpio_vrsel);
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;
}
#include <linux/init.h>
#include <linux/module.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
goto fail;
usb_nop_xceiv_register();
- musb->xceiv = usb_get_transceiver();
- if (!musb->xceiv)
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv))
goto fail;
if (is_host_enabled(musb))
phy_off();
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
u32 revision;
usb_nop_xceiv_register();
- musb->xceiv = usb_get_transceiver();
- if (!musb->xceiv)
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv))
goto unregister;
musb->mregs += DAVINCI_BASE_OFFSET;
return 0;
fail:
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
unregister:
usb_nop_xceiv_unregister();
return -ENODEV;
phy_off();
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;
/* The musb_platform_init() call:
* - adjusts musb->mregs and musb->isr if needed,
* - may initialize an integrated tranceiver
- * - initializes musb->xceiv, usually by otg_get_transceiver()
+ * - initializes musb->xceiv, usually by otg_get_phy()
* - stops powering VBUS
*
* There are various transceiver configurations. Blackfin,
irqreturn_t (*isr)(int, void *);
struct work_struct irq_work;
- struct work_struct otg_notifier_work;
u16 hwvers;
/* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
u16 int_tx;
struct usb_phy *xceiv;
- u8 xceiv_event;
int nIrq;
unsigned irq_wake:1;
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
/* NOP driver needs change if supporting dual instance */
usb_nop_xceiv_register();
- musb->xceiv = usb_get_transceiver();
- if (!musb->xceiv)
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv))
return -ENODEV;
/* Returns zero if e.g. not clocked */
return 0;
err0:
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return status;
}
data->set_phy_power(0);
/* NOP driver needs change if supporting dual instance */
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <linux/err.h>
+#include <linux/usb/musb-omap.h>
#include "musb_core.h"
#include "omap2430.h"
struct omap2430_glue {
struct device *dev;
struct platform_device *musb;
+ enum omap_musb_vbus_id_status status;
+ struct work_struct omap_musb_mailbox_work;
};
#define glue_to_musb(g) platform_get_drvdata(g->musb)
+struct omap2430_glue *_glue;
+
static struct timer_list musb_idle_timer;
static void musb_do_idle(unsigned long _musb)
musb_writel(musb->mregs, OTG_FORCESTDBY, l);
}
-static int musb_otg_notifications(struct notifier_block *nb,
- unsigned long event, void *unused)
+void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
{
- struct musb *musb = container_of(nb, struct musb, nb);
+ struct omap2430_glue *glue = _glue;
+ struct musb *musb = glue_to_musb(glue);
- musb->xceiv_event = event;
- schedule_work(&musb->otg_notifier_work);
+ glue->status = status;
+ if (!musb) {
+ dev_err(glue->dev, "musb core is not yet ready\n");
+ return;
+ }
- return NOTIFY_OK;
+ schedule_work(&glue->omap_musb_mailbox_work);
}
+EXPORT_SYMBOL_GPL(omap_musb_mailbox);
-static void musb_otg_notifier_work(struct work_struct *data_notifier_work)
+static void omap_musb_set_mailbox(struct omap2430_glue *glue)
{
- struct musb *musb = container_of(data_notifier_work, struct musb, otg_notifier_work);
+ struct musb *musb = glue_to_musb(glue);
struct device *dev = musb->controller;
struct musb_hdrc_platform_data *pdata = dev->platform_data;
struct omap_musb_board_data *data = pdata->board_data;
+ struct usb_otg *otg = musb->xceiv->otg;
- switch (musb->xceiv_event) {
- case USB_EVENT_ID:
- dev_dbg(musb->controller, "ID GND\n");
+ switch (glue->status) {
+ case OMAP_MUSB_ID_GROUND:
+ dev_dbg(dev, "ID GND\n");
+ otg->default_a = true;
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+ musb->xceiv->last_event = USB_EVENT_ID;
if (!is_otg_enabled(musb) || musb->gadget_driver) {
- pm_runtime_get_sync(musb->controller);
+ pm_runtime_get_sync(dev);
usb_phy_init(musb->xceiv);
omap2430_musb_set_vbus(musb, 1);
}
break;
- case USB_EVENT_VBUS:
- dev_dbg(musb->controller, "VBUS Connect\n");
+ case OMAP_MUSB_VBUS_VALID:
+ dev_dbg(dev, "VBUS Connect\n");
+ otg->default_a = false;
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->last_event = USB_EVENT_VBUS;
if (musb->gadget_driver)
- pm_runtime_get_sync(musb->controller);
+ pm_runtime_get_sync(dev);
usb_phy_init(musb->xceiv);
break;
- case USB_EVENT_NONE:
- dev_dbg(musb->controller, "VBUS Disconnect\n");
+ case OMAP_MUSB_ID_FLOAT:
+ case OMAP_MUSB_VBUS_OFF:
+ dev_dbg(dev, "VBUS Disconnect\n");
+ musb->xceiv->last_event = USB_EVENT_NONE;
if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
if (musb->gadget_driver) {
- pm_runtime_mark_last_busy(musb->controller);
- pm_runtime_put_autosuspend(musb->controller);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
}
if (data->interface_type == MUSB_INTERFACE_UTMI) {
usb_phy_shutdown(musb->xceiv);
break;
default:
- dev_dbg(musb->controller, "ID float\n");
+ dev_dbg(dev, "ID float\n");
}
}
+
+static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
+{
+ struct omap2430_glue *glue = container_of(mailbox_work,
+ struct omap2430_glue, omap_musb_mailbox_work);
+ omap_musb_set_mailbox(glue);
+}
+
static int omap2430_musb_init(struct musb *musb)
{
u32 l;
int status = 0;
struct device *dev = musb->controller;
+ struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
struct musb_hdrc_platform_data *plat = dev->platform_data;
struct omap_musb_board_data *data = plat->board_data;
* up through ULPI. TWL4030-family PMICs include one,
* which needs a driver, drivers aren't always needed.
*/
- musb->xceiv = usb_get_transceiver();
- if (!musb->xceiv) {
+ musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv)) {
pr_err("HS USB OTG: no transceiver configured\n");
return -ENODEV;
}
- INIT_WORK(&musb->otg_notifier_work, musb_otg_notifier_work);
-
status = pm_runtime_get_sync(dev);
if (status < 0) {
dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
musb_readl(musb->mregs, OTG_INTERFSEL),
musb_readl(musb->mregs, OTG_SIMENABLE));
- musb->nb.notifier_call = musb_otg_notifications;
- status = usb_register_notifier(musb->xceiv, &musb->nb);
-
- if (status)
- dev_dbg(musb->controller, "notification register failed\n");
-
setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
+ if (glue->status != OMAP_MUSB_UNKNOWN)
+ omap_musb_set_mailbox(glue);
+
pm_runtime_put_noidle(musb->controller);
return 0;
u8 devctl;
unsigned long timeout = jiffies + msecs_to_jiffies(1000);
struct device *dev = musb->controller;
+ struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
struct musb_hdrc_platform_data *pdata = dev->platform_data;
struct omap_musb_board_data *data = pdata->board_data;
- switch (musb->xceiv->last_event) {
+ switch (glue->status) {
- case USB_EVENT_ID:
+ case OMAP_MUSB_ID_GROUND:
usb_phy_init(musb->xceiv);
if (data->interface_type != MUSB_INTERFACE_UTMI)
break;
}
break;
- case USB_EVENT_VBUS:
+ case OMAP_MUSB_VBUS_VALID:
usb_phy_init(musb->xceiv);
break;
static void omap2430_musb_disable(struct musb *musb)
{
- if (musb->xceiv->last_event)
+ struct device *dev = musb->controller;
+ struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
+
+ if (glue->status != OMAP_MUSB_UNKNOWN)
usb_phy_shutdown(musb->xceiv);
}
static int omap2430_musb_exit(struct musb *musb)
{
del_timer_sync(&musb_idle_timer);
- cancel_work_sync(&musb->otg_notifier_work);
omap2430_low_level_exit(musb);
- usb_put_transceiver(musb->xceiv);
return 0;
}
struct omap2430_glue *glue;
int ret = -ENOMEM;
- glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+ glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
if (!glue) {
dev_err(&pdev->dev, "failed to allocate glue context\n");
goto err0;
musb = platform_device_alloc("musb-hdrc", -1);
if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n");
- goto err1;
+ goto err0;
}
musb->dev.parent = &pdev->dev;
glue->dev = &pdev->dev;
glue->musb = musb;
+ glue->status = OMAP_MUSB_UNKNOWN;
pdata->platform_ops = &omap2430_ops;
platform_set_drvdata(pdev, glue);
+ /*
+ * REVISIT if we ever have two instances of the wrapper, we will be
+ * in big trouble
+ */
+ _glue = glue;
+
+ INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
+
ret = platform_device_add_resources(musb, pdev->resource,
pdev->num_resources);
if (ret) {
dev_err(&pdev->dev, "failed to add resources\n");
- goto err2;
+ goto err1;
}
ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
if (ret) {
dev_err(&pdev->dev, "failed to add platform_data\n");
- goto err2;
+ goto err1;
}
pm_runtime_enable(&pdev->dev);
ret = platform_device_add(musb);
if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n");
- goto err2;
+ goto err1;
}
return 0;
-err2:
- platform_device_put(musb);
-
err1:
- kfree(glue);
+ platform_device_put(musb);
err0:
return ret;
{
struct omap2430_glue *glue = platform_get_drvdata(pdev);
+ cancel_work_sync(&glue->omap_musb_mailbox_work);
platform_device_del(glue->musb);
platform_device_put(glue->musb);
- kfree(glue);
return 0;
}
{
return platform_driver_register(&omap2430_driver);
}
-module_init(omap2430_init);
+subsys_initcall(omap2430_init);
static void __exit omap2430_exit(void)
{
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/prefetch.h>
#include <linux/usb.h>
int ret;
usb_nop_xceiv_register();
- musb->xceiv = usb_get_transceiver();
- if (!musb->xceiv)
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv))
return -ENODEV;
pdev = to_platform_device(musb->controller);
if (sync)
iounmap(sync);
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
}
return ret;
iounmap(musb->sync_va);
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0;
}
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
static int ux500_musb_init(struct musb *musb)
{
- musb->xceiv = usb_get_transceiver();
- if (!musb->xceiv) {
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv)) {
pr_err("HS USB OTG: no transceiver configured\n");
return -ENODEV;
}
static int ux500_musb_exit(struct musb *musb)
{
- usb_put_transceiver(musb->xceiv);
+ usb_put_phy(musb->xceiv);
return 0;
}
if (err < 0)
goto fail0;
- err = usb_set_transceiver(&ab->phy);
+ err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2);
if (err) {
dev_err(&pdev->dev, "Can't register transceiver\n");
goto fail1;
cancel_work_sync(&ab->phy_dis_work);
- usb_set_transceiver(NULL);
+ usb_remove_phy(&ab->phy);
ab8500_usb_host_phy_dis(ab);
ab8500_usb_peri_phy_dis(ab);
fsl_otg_dev = fsl_otg_tc;
/* Store the otg transceiver */
- status = usb_set_transceiver(&fsl_otg_tc->phy);
+ status = usb_add_phy(&fsl_otg_tc->phy, USB_PHY_TYPE_USB2);
if (status) {
pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n");
goto err;
int usb_otg_start(struct platform_device *pdev)
{
struct fsl_otg *p_otg;
- struct usb_phy *otg_trans = usb_get_transceiver();
+ struct usb_phy *otg_trans = usb_get_phy(USB_PHY_TYPE_USB2);
struct otg_fsm *fsm;
int status;
struct resource *res;
{
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
- usb_set_transceiver(NULL);
+ usb_remove_phy(&fsl_otg_dev->phy);
free_irq(fsl_otg_dev->irq, fsl_otg_dev);
iounmap((void *)usb_dr_regs);
}
/* only active when a gadget is registered */
- err = usb_set_transceiver(&gpio_vbus->phy);
+ err = usb_add_phy(&gpio_vbus->phy, USB_PHY_TYPE_USB2);
if (err) {
dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
err);
cancel_delayed_work_sync(&gpio_vbus->work);
regulator_put(gpio_vbus->vbus_draw);
- usb_set_transceiver(NULL);
+ usb_remove_phy(&gpio_vbus->phy);
free_irq(gpio_vbus->irq, pdev);
if (gpio_is_valid(pdata->gpio_pullup))
isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
{
struct isp1301 *isp = container_of(otg->phy, struct isp1301, phy);
-#ifndef CONFIG_USB_OTG
- u32 l;
-#endif
if (!otg || isp != the_transceiver)
return -ENODEV;
otg->gadget = gadget;
// FIXME update its refcount
- l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
- l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS);
- l |= OTG_ID;
- omap_writel(l, OTG_CTRL);
+ {
+ u32 l;
+
+ l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
+ l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS);
+ l |= OTG_ID;
+ omap_writel(l, OTG_CTRL);
+ }
power_up(isp);
isp->phy.state = OTG_STATE_B_IDLE;
dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES);
#endif
- status = usb_set_transceiver(&isp->phy);
+ status = usb_add_phy(&isp->phy, USB_PHY_TYPE_USB2);
if (status < 0)
dev_err(&i2c->dev, "can't register transceiver, %d\n",
status);
static void __exit isp_exit(void)
{
if (the_transceiver)
- usb_set_transceiver(NULL);
+ usb_remove_phy(&the_transceiver->phy);
i2c_del_driver(&isp1301_driver);
}
module_exit(isp_exit);
phy->otg->set_host = msm_otg_set_host;
phy->otg->set_peripheral = msm_otg_set_peripheral;
- ret = usb_set_transceiver(&motg->phy);
+ ret = usb_add_phy(&motg->phy, USB_PHY_TYPE_USB2);
if (ret) {
- dev_err(&pdev->dev, "usb_set_transceiver failed\n");
+ dev_err(&pdev->dev, "usb_add_phy failed\n");
goto free_irq;
}
device_init_wakeup(&pdev->dev, 0);
pm_runtime_disable(&pdev->dev);
- usb_set_transceiver(NULL);
+ usb_remove_phy(phy);
free_irq(motg->irq, motg);
/*
for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++)
clk_put(mvotg->clk[clk_i]);
- usb_set_transceiver(NULL);
+ usb_remove_phy(&mvotg->phy);
platform_set_drvdata(pdev, NULL);
kfree(mvotg->phy.otg);
goto err_disable_clk;
}
- retval = usb_set_transceiver(&mvotg->phy);
+ retval = usb_add_phy(&mvotg->phy, USB_PHY_TYPE_USB2);
if (retval < 0) {
dev_err(&pdev->dev, "can't register transceiver, %d\n",
retval);
return 0;
err_set_transceiver:
- usb_set_transceiver(NULL);
+ usb_remove_phy(&mvotg->phy);
err_free_irq:
free_irq(mvotg->irq, mvotg);
err_disable_clk:
nop->phy.otg->set_host = nop_set_host;
nop->phy.otg->set_peripheral = nop_set_peripheral;
- err = usb_set_transceiver(&nop->phy);
+ err = usb_add_phy(&nop->phy, USB_PHY_TYPE_USB2);
if (err) {
dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
err);
{
struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
- usb_set_transceiver(NULL);
+ usb_remove_phy(&nop->phy);
platform_set_drvdata(pdev, NULL);
kfree(nop->phy.otg);
#include <linux/kernel.h>
#include <linux/export.h>
+#include <linux/err.h>
#include <linux/device.h>
+#include <linux/slab.h>
#include <linux/usb/otg.h>
-static struct usb_phy *phy;
+static LIST_HEAD(phy_list);
+static DEFINE_SPINLOCK(phy_lock);
+
+static struct usb_phy *__usb_find_phy(struct list_head *list,
+ enum usb_phy_type type)
+{
+ struct usb_phy *phy = NULL;
+
+ list_for_each_entry(phy, list, head) {
+ if (phy->type != type)
+ continue;
+
+ return phy;
+ }
+
+ return ERR_PTR(-ENODEV);
+}
+
+static void devm_usb_phy_release(struct device *dev, void *res)
+{
+ struct usb_phy *phy = *(struct usb_phy **)res;
+
+ usb_put_phy(phy);
+}
+
+static int devm_usb_phy_match(struct device *dev, void *res, void *match_data)
+{
+ return res == match_data;
+}
/**
- * usb_get_transceiver - find the (single) USB transceiver
+ * devm_usb_get_phy - find the USB PHY
+ * @dev - device that requests this phy
+ * @type - the type of the phy the controller requires
*
- * Returns the transceiver driver, after getting a refcount to it; or
- * null if there is no such transceiver. The caller is responsible for
- * calling usb_put_transceiver() to release that count.
+ * Gets the phy using usb_get_phy(), and associates a device with it using
+ * devres. On driver detach, release function is invoked on the devres data,
+ * then, devres data is freed.
*
* For use by USB host and peripheral drivers.
*/
-struct usb_phy *usb_get_transceiver(void)
+struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type)
{
- if (phy)
- get_device(phy->dev);
+ struct usb_phy **ptr, *phy;
+
+ ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return NULL;
+
+ phy = usb_get_phy(type);
+ if (!IS_ERR(phy)) {
+ *ptr = phy;
+ devres_add(dev, ptr);
+ } else
+ devres_free(ptr);
+
+ return phy;
+}
+EXPORT_SYMBOL(devm_usb_get_phy);
+
+/**
+ * usb_get_phy - find the USB PHY
+ * @type - the type of the phy the controller requires
+ *
+ * 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.
+ */
+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_transceiver);
+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_transceiver - release the (single) USB transceiver
- * @x: the transceiver returned by usb_get_transceiver()
+ * usb_put_phy - release the USB PHY
+ * @x: the phy returned by usb_get_phy()
*
- * Releases a refcount the caller received from usb_get_transceiver().
+ * Releases a refcount the caller received from usb_get_phy().
*
* For use by USB host and peripheral drivers.
*/
-void usb_put_transceiver(struct usb_phy *x)
+void usb_put_phy(struct usb_phy *x)
{
if (x)
put_device(x->dev);
}
-EXPORT_SYMBOL(usb_put_transceiver);
+EXPORT_SYMBOL(usb_put_phy);
/**
- * usb_set_transceiver - declare the (single) USB transceiver
- * @x: the USB transceiver to be used; or NULL
+ * usb_add_phy - declare the USB PHY
+ * @x: the USB phy to be used; or NULL
+ * @type - the type of this PHY
*
- * This call is exclusively for use by transceiver drivers, which
+ * This call is exclusively for use by phy drivers, which
* coordinate the activities of drivers for host and peripheral
* controllers, and in some cases for VBUS current regulation.
*/
-int usb_set_transceiver(struct usb_phy *x)
+int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
+{
+ int ret = 0;
+ unsigned long flags;
+ struct usb_phy *phy;
+
+ if (x && x->type != USB_PHY_TYPE_UNDEFINED) {
+ dev_err(x->dev, "not accepting initialized PHY %s\n", x->label);
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&phy_lock, flags);
+
+ list_for_each_entry(phy, &phy_list, head) {
+ if (phy->type == type) {
+ ret = -EBUSY;
+ dev_err(x->dev, "transceiver type %s already exists\n",
+ usb_phy_type_string(type));
+ goto out;
+ }
+ }
+
+ x->type = type;
+ list_add_tail(&x->head, &phy_list);
+
+out:
+ spin_unlock_irqrestore(&phy_lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(usb_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)
{
- if (phy && x)
- return -EBUSY;
- phy = x;
- return 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&phy_lock, flags);
+ if (x)
+ list_del(&x->head);
+ spin_unlock_irqrestore(&phy_lock, flags);
}
-EXPORT_SYMBOL(usb_set_transceiver);
+EXPORT_SYMBOL(usb_remove_phy);
const char *otg_state_string(enum usb_otg_state state)
{
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/usb/otg.h>
+#include <linux/usb/musb-omap.h>
#include <linux/usb/ulpi.h>
#include <linux/i2c/twl.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
-#include <linux/notifier.h>
#include <linux/slab.h>
/* Register defines */
enum twl4030_usb_mode usb_mode;
int irq;
- u8 linkstat;
+ enum omap_musb_vbus_id_status linkstat;
bool vbus_supplied;
u8 asleep;
bool irq_enabled;
/*-------------------------------------------------------------------------*/
-static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl)
+static enum omap_musb_vbus_id_status
+ twl4030_usb_linkstat(struct twl4030_usb *twl)
{
int status;
- int linkstat = USB_EVENT_NONE;
- struct usb_otg *otg = twl->phy.otg;
+ enum omap_musb_vbus_id_status linkstat = OMAP_MUSB_UNKNOWN;
twl->vbus_supplied = false;
twl->vbus_supplied = true;
if (status & BIT(2))
- linkstat = USB_EVENT_ID;
+ linkstat = OMAP_MUSB_ID_GROUND;
else
- linkstat = USB_EVENT_VBUS;
- } else
- linkstat = USB_EVENT_NONE;
+ linkstat = OMAP_MUSB_VBUS_VALID;
+ } else {
+ if (twl->linkstat != OMAP_MUSB_UNKNOWN)
+ linkstat = OMAP_MUSB_VBUS_OFF;
+ }
dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
status, status, linkstat);
- twl->phy.last_event = linkstat;
-
/* REVISIT this assumes host and peripheral controllers
* are registered, and that both are active...
*/
spin_lock_irq(&twl->lock);
twl->linkstat = linkstat;
- if (linkstat == USB_EVENT_ID) {
- otg->default_a = true;
- twl->phy.state = OTG_STATE_A_IDLE;
- } else {
- otg->default_a = false;
- twl->phy.state = OTG_STATE_B_IDLE;
- }
spin_unlock_irq(&twl->lock);
return linkstat;
static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
{
struct twl4030_usb *twl = _twl;
- int status;
+ enum omap_musb_vbus_id_status status;
status = twl4030_usb_linkstat(twl);
- if (status >= 0) {
+ if (status > 0) {
/* FIXME add a set_power() method so that B-devices can
* configure the charger appropriately. It's not always
* correct to consume VBUS power, and how much current to
* USB_LINK_VBUS state. musb_hdrc won't care until it
* starts to handle softconnect right.
*/
- if (status == USB_EVENT_NONE)
+ if (status == OMAP_MUSB_VBUS_OFF ||
+ status == OMAP_MUSB_ID_FLOAT)
twl4030_phy_suspend(twl, 0);
else
twl4030_phy_resume(twl);
- atomic_notifier_call_chain(&twl->phy.notifier, status,
- twl->phy.otg->gadget);
+ omap_musb_mailbox(twl->linkstat);
}
sysfs_notify(&twl->dev->kobj, NULL, "vbus");
static void twl4030_usb_phy_init(struct twl4030_usb *twl)
{
- int status;
+ enum omap_musb_vbus_id_status status;
status = twl4030_usb_linkstat(twl);
- if (status >= 0) {
- if (status == USB_EVENT_NONE) {
+ if (status > 0) {
+ if (status == OMAP_MUSB_VBUS_OFF ||
+ status == OMAP_MUSB_ID_FLOAT) {
__twl4030_phy_power(twl, 0);
twl->asleep = 1;
} else {
twl->asleep = 0;
}
- atomic_notifier_call_chain(&twl->phy.notifier, status,
- twl->phy.otg->gadget);
+ omap_musb_mailbox(twl->linkstat);
}
sysfs_notify(&twl->dev->kobj, NULL, "vbus");
}
return -EINVAL;
}
- twl = kzalloc(sizeof *twl, GFP_KERNEL);
+ twl = devm_kzalloc(&pdev->dev, sizeof *twl, GFP_KERNEL);
if (!twl)
return -ENOMEM;
- otg = kzalloc(sizeof *otg, GFP_KERNEL);
- if (!otg) {
- kfree(twl);
+ otg = devm_kzalloc(&pdev->dev, sizeof *otg, GFP_KERNEL);
+ if (!otg)
return -ENOMEM;
- }
twl->dev = &pdev->dev;
twl->irq = platform_get_irq(pdev, 0);
twl->usb_mode = pdata->usb_mode;
twl->vbus_supplied = false;
twl->asleep = 1;
+ twl->linkstat = OMAP_MUSB_UNKNOWN;
twl->phy.dev = twl->dev;
twl->phy.label = "twl4030";
err = twl4030_usb_ldo_init(twl);
if (err) {
dev_err(&pdev->dev, "ldo init failed\n");
- kfree(otg);
- kfree(twl);
return err;
}
- usb_set_transceiver(&twl->phy);
+ usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2);
platform_set_drvdata(pdev, twl);
if (device_create_file(&pdev->dev, &dev_attr_vbus))
dev_warn(&pdev->dev, "could not create sysfs file\n");
- ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
-
/* Our job is to use irqs and status from the power module
* to keep the transceiver disabled when nothing's connected.
*
*/
twl->irq_enabled = true;
status = request_threaded_irq(twl->irq, NULL, twl4030_usb_irq,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
- "twl4030_usb", twl);
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
+ IRQF_ONESHOT, "twl4030_usb", twl);
if (status < 0) {
dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n",
twl->irq, status);
- kfree(otg);
- kfree(twl);
return status;
}
regulator_put(twl->usb1v8);
regulator_put(twl->usb3v1);
- kfree(twl->phy.otg);
- kfree(twl);
-
return 0;
}
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/usb/otg.h>
+#include <linux/usb/musb-omap.h>
#include <linux/i2c/twl.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
-#include <linux/notifier.h>
#include <linux/slab.h>
#include <linux/delay.h>
int irq1;
int irq2;
- u8 linkstat;
+ enum omap_musb_vbus_id_status linkstat;
u8 asleep;
bool irq_enabled;
bool vbus_enable;
dev = twl->dev;
pdata = dev->platform_data;
- if (twl->linkstat == USB_EVENT_ID)
+ if (twl->linkstat == OMAP_MUSB_ID_GROUND)
pdata->phy_power(twl->dev, 1, 1);
else
pdata->phy_power(twl->dev, 0, 1);
spin_lock_irqsave(&twl->lock, flags);
switch (twl->linkstat) {
- case USB_EVENT_VBUS:
+ case OMAP_MUSB_VBUS_VALID:
ret = snprintf(buf, PAGE_SIZE, "vbus\n");
break;
- case USB_EVENT_ID:
+ case OMAP_MUSB_ID_GROUND:
ret = snprintf(buf, PAGE_SIZE, "id\n");
break;
- case USB_EVENT_NONE:
+ case OMAP_MUSB_VBUS_OFF:
ret = snprintf(buf, PAGE_SIZE, "none\n");
break;
default:
static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
{
struct twl6030_usb *twl = _twl;
- struct usb_otg *otg = twl->phy.otg;
- int status;
+ enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
u8 vbus_state, hw_state;
hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
if (vbus_state & VBUS_DET) {
regulator_enable(twl->usb3v3);
twl->asleep = 1;
- status = USB_EVENT_VBUS;
- otg->default_a = false;
- twl->phy.state = OTG_STATE_B_IDLE;
+ status = OMAP_MUSB_VBUS_VALID;
twl->linkstat = status;
- twl->phy.last_event = status;
- atomic_notifier_call_chain(&twl->phy.notifier,
- status, otg->gadget);
+ omap_musb_mailbox(status);
} else {
- status = USB_EVENT_NONE;
- twl->linkstat = status;
- twl->phy.last_event = status;
- atomic_notifier_call_chain(&twl->phy.notifier,
- status, otg->gadget);
- if (twl->asleep) {
- regulator_disable(twl->usb3v3);
- twl->asleep = 0;
+ if (twl->linkstat != OMAP_MUSB_UNKNOWN) {
+ status = OMAP_MUSB_VBUS_OFF;
+ twl->linkstat = status;
+ omap_musb_mailbox(status);
+ if (twl->asleep) {
+ regulator_disable(twl->usb3v3);
+ twl->asleep = 0;
+ }
}
}
}
static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
{
struct twl6030_usb *twl = _twl;
- struct usb_otg *otg = twl->phy.otg;
- int status = USB_EVENT_NONE;
+ enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
u8 hw_state;
hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
twl->asleep = 1;
twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR);
twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
- status = USB_EVENT_ID;
+ status = OMAP_MUSB_ID_GROUND;
otg->default_a = true;
twl->phy.state = OTG_STATE_A_IDLE;
twl->linkstat = status;
- twl->phy.last_event = status;
- atomic_notifier_call_chain(&twl->phy.notifier, status,
- otg->gadget);
+ omap_musb_mailbox(status);
} else {
twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
struct device *dev = &pdev->dev;
pdata = dev->platform_data;
- twl = kzalloc(sizeof *twl, GFP_KERNEL);
+ twl = devm_kzalloc(dev, sizeof *twl, GFP_KERNEL);
if (!twl)
return -ENOMEM;
- otg = kzalloc(sizeof *otg, GFP_KERNEL);
- if (!otg) {
- kfree(twl);
+ otg = devm_kzalloc(dev, sizeof *otg, GFP_KERNEL);
+ if (!otg)
return -ENOMEM;
- }
twl->dev = &pdev->dev;
twl->irq1 = platform_get_irq(pdev, 0);
twl->irq2 = platform_get_irq(pdev, 1);
twl->features = pdata->features;
+ twl->linkstat = OMAP_MUSB_UNKNOWN;
twl->phy.dev = twl->dev;
twl->phy.label = "twl6030";
err = twl6030_usb_ldo_init(twl);
if (err) {
dev_err(&pdev->dev, "ldo init failed\n");
- kfree(otg);
- kfree(twl);
return err;
}
- usb_set_transceiver(&twl->phy);
+ usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2);
platform_set_drvdata(pdev, twl);
if (device_create_file(&pdev->dev, &dev_attr_vbus))
dev_warn(&pdev->dev, "could not create sysfs file\n");
- ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
-
INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
twl->irq_enabled = true;
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
twl->irq1, status);
device_remove_file(twl->dev, &dev_attr_vbus);
- kfree(otg);
- kfree(twl);
return status;
}
twl->irq2, status);
free_irq(twl->irq1, twl);
device_remove_file(twl->dev, &dev_attr_vbus);
- kfree(otg);
- kfree(twl);
return status;
}
pdata->phy_exit(twl->dev);
device_remove_file(twl->dev, &dev_attr_vbus);
cancel_work_sync(&twl->set_vbus_work);
- kfree(twl->phy.otg);
- kfree(twl);
return 0;
}
--- /dev/null
+/*
+ * 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__ */
USB_EVENT_ENUMERATED, /* gadget driver enumerated */
};
+/* associate a type with PHY */
+enum usb_phy_type {
+ USB_PHY_TYPE_UNDEFINED,
+ USB_PHY_TYPE_USB2,
+ USB_PHY_TYPE_USB3,
+};
+
struct usb_phy;
/* for transceivers connected thru an ULPI interface, the user must
const char *label;
unsigned int flags;
+ enum usb_phy_type type;
enum usb_otg_state state;
enum usb_phy_events last_event;
u16 port_status;
u16 port_change;
+ /* to support controllers that have multiple transceivers */
+ struct list_head head;
+
/* initialize/shutdown the OTG controller */
int (*init)(struct usb_phy *x);
void (*shutdown)(struct usb_phy *x);
/* for board-specific init logic */
-extern int usb_set_transceiver(struct usb_phy *);
+extern int usb_add_phy(struct usb_phy *, enum usb_phy_type type);
+extern void usb_remove_phy(struct usb_phy *);
#if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE))
/* sometimes transceivers are accessed only through e.g. ULPI */
/* for usb host and peripheral controller drivers */
#ifdef CONFIG_USB_OTG_UTILS
-extern struct usb_phy *usb_get_transceiver(void);
-extern void usb_put_transceiver(struct usb_phy *);
+extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
+extern struct usb_phy *devm_usb_get_phy(struct device *dev,
+ enum usb_phy_type type);
+extern void usb_put_phy(struct usb_phy *);
+extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x);
extern const char *otg_state_string(enum usb_otg_state state);
#else
-static inline struct usb_phy *usb_get_transceiver(void)
+static inline struct usb_phy *usb_get_phy(enum usb_phy_type type)
+{
+ return NULL;
+}
+
+static inline struct usb_phy *devm_usb_get_phy(struct device *dev,
+ enum usb_phy_type type)
{
return NULL;
}
-static inline void usb_put_transceiver(struct usb_phy *x)
+static inline void usb_put_phy(struct usb_phy *x)
+{
+}
+
+static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x)
{
}
/* for OTG controller drivers (and maybe other stuff) */
extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num);
+static inline const char *usb_phy_type_string(enum usb_phy_type type)
+{
+ switch (type) {
+ case USB_PHY_TYPE_USB2:
+ return "USB2 PHY";
+ case USB_PHY_TYPE_USB3:
+ return "USB3 PHY";
+ default:
+ return "UNKNOWN PHY TYPE";
+ }
+}
#endif /* __LINUX_USB_OTG_H */