diff options
Diffstat (limited to 'drivers/usb/musb/omap2430.c')
| -rw-r--r-- | drivers/usb/musb/omap2430.c | 138 |
1 files changed, 97 insertions, 41 deletions
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 1762354fe79..d369bf1f393 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -37,7 +37,8 @@ #include <linux/err.h> #include <linux/delay.h> #include <linux/usb/musb-omap.h> -#include <linux/usb/omap_control_usb.h> +#include <linux/phy/omap_control_phy.h> +#include <linux/of_platform.h> #include "musb_core.h" #include "omap2430.h" @@ -51,7 +52,7 @@ struct omap2430_glue { }; #define glue_to_musb(g) platform_get_drvdata(g->musb) -struct omap2430_glue *_glue; +static struct omap2430_glue *_glue; static struct timer_list musb_idle_timer; @@ -87,7 +88,7 @@ static void musb_do_idle(unsigned long _musb) musb->port1_status &= ~(USB_PORT_STAT_SUSPEND | MUSB_PORT_STAT_RESUME); musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; - usb_hcd_poll_rh_status(musb_to_hcd(musb)); + usb_hcd_poll_rh_status(musb->hcd); /* NOTE: it might really be A_WAIT_BCON ... */ musb->xceiv->state = OTG_STATE_A_HOST; } @@ -117,7 +118,7 @@ static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout) if (musb->is_active || ((musb->a_wait_bcon == 0) && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) { dev_dbg(musb->controller, "%s active, deleting timer\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); del_timer(&musb_idle_timer); last_timer = jiffies; return; @@ -134,7 +135,7 @@ static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout) last_timer = timeout; dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), (unsigned long)jiffies_to_msecs(timeout - jiffies)); mod_timer(&musb_idle_timer, timeout); } @@ -174,8 +175,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) } } - if (otg->set_vbus) - otg_set_vbus(otg, 1); + otg_set_vbus(otg, 1); } else { musb->is_active = 1; otg->default_a = 1; @@ -200,7 +200,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) dev_dbg(musb->controller, "VBUS %s, devctl %02x " /* otg %3x conf %08x prcm %08x */ "\n", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), musb_readb(musb->mregs, MUSB_DEVCTL)); } @@ -237,9 +237,13 @@ void omap_musb_mailbox(enum omap_musb_vbus_id_status status) { struct omap2430_glue *glue = _glue; - if (glue && glue_to_musb(glue)) { - glue->status = status; - } else { + if (!glue) { + pr_err("%s: musb core is not yet initialized\n", __func__); + return; + } + glue->status = status; + + if (!glue_to_musb(glue)) { pr_err("%s: musb core is not yet ready\n", __func__); return; } @@ -252,7 +256,7 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) { struct musb *musb = glue_to_musb(glue); struct device *dev = musb->controller; - struct musb_hdrc_platform_data *pdata = dev->platform_data; + struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev); struct omap_musb_board_data *data = pdata->board_data; struct usb_otg *otg = musb->xceiv->otg; @@ -288,20 +292,23 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) musb->xceiv->last_event = USB_EVENT_NONE; if (musb->gadget_driver) { + omap2430_musb_set_vbus(musb, 0); pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); } - if (data->interface_type == MUSB_INTERFACE_UTMI) { - if (musb->xceiv->otg->set_vbus) - otg_set_vbus(musb->xceiv->otg, 0); - } + if (data->interface_type == MUSB_INTERFACE_UTMI) + otg_set_vbus(musb->xceiv->otg, 0); + omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DISCONNECT); break; default: dev_dbg(dev, "ID float\n"); } + + atomic_notifier_call_chain(&musb->xceiv->notifier, + musb->xceiv->last_event, NULL); } @@ -309,7 +316,13 @@ 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); + struct musb *musb = glue_to_musb(glue); + struct device *dev = musb->controller; + + pm_runtime_get_sync(dev); omap_musb_set_mailbox(glue); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); } static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci) @@ -338,24 +351,43 @@ static int omap2430_musb_init(struct musb *musb) 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 musb_hdrc_platform_data *plat = dev_get_platdata(dev); struct omap_musb_board_data *data = plat->board_data; /* We require some kind of external transceiver, hooked * up through ULPI. TWL4030-family PMICs include one, * which needs a driver, drivers aren't always needed. */ - if (dev->parent->of_node) + if (dev->parent->of_node) { + musb->phy = devm_phy_get(dev->parent, "usb2-phy"); + + /* We can't totally remove musb->xceiv as of now because + * musb core uses xceiv.state and xceiv.otg. Once we have + * a separate state machine to handle otg, these can be moved + * out of xceiv and then we can start using the generic PHY + * framework + */ musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, "usb-phy", 0); - else + } else { musb->xceiv = devm_usb_get_phy_dev(dev, 0); + musb->phy = devm_phy_get(dev, "usb"); + } + + if (IS_ERR(musb->xceiv)) { + status = PTR_ERR(musb->xceiv); + + if (status == -ENXIO) + return status; - if (IS_ERR_OR_NULL(musb->xceiv)) { pr_err("HS USB OTG: no transceiver configured\n"); return -EPROBE_DEFER; } + if (IS_ERR(musb->phy)) { + pr_err("HS USB OTG: no PHY configured\n"); + return PTR_ERR(musb->phy); + } musb->isr = omap2430_musb_interrupt; status = pm_runtime_get_sync(dev); @@ -389,6 +421,9 @@ static int omap2430_musb_init(struct musb *musb) if (glue->status != OMAP_MUSB_UNKNOWN) omap_musb_set_mailbox(glue); + phy_init(musb->phy); + phy_power_on(musb->phy); + pm_runtime_put_noidle(musb->controller); return 0; @@ -402,7 +437,7 @@ static void omap2430_musb_enable(struct musb *musb) 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 musb_hdrc_platform_data *pdata = dev_get_platdata(dev); struct omap_musb_board_data *data = pdata->board_data; switch (glue->status) { @@ -450,6 +485,8 @@ static int omap2430_musb_exit(struct musb *musb) del_timer_sync(&musb_idle_timer); omap2430_low_level_exit(musb); + phy_power_off(musb->phy); + phy_exit(musb->phy); return 0; } @@ -471,7 +508,8 @@ static u64 omap2430_dmamask = DMA_BIT_MASK(32); static int omap2430_probe(struct platform_device *pdev) { - struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; + struct resource musb_resources[3]; + struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); struct omap_musb_board_data *data; struct platform_device *musb; struct omap2430_glue *glue; @@ -498,12 +536,16 @@ static int omap2430_probe(struct platform_device *pdev) glue->dev = &pdev->dev; glue->musb = musb; glue->status = OMAP_MUSB_UNKNOWN; + glue->control_otghs = ERR_PTR(-ENODEV); if (np) { + struct device_node *control_node; + struct platform_device *control_pdev; + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) { dev_err(&pdev->dev, - "failed to allocate musb platfrom data\n"); + "failed to allocate musb platform data\n"); goto err2; } @@ -522,27 +564,26 @@ static int omap2430_probe(struct platform_device *pdev) } of_property_read_u32(np, "mode", (u32 *)&pdata->mode); - of_property_read_u32(np, "interface_type", + of_property_read_u32(np, "interface-type", (u32 *)&data->interface_type); - of_property_read_u32(np, "num_eps", (u32 *)&config->num_eps); - of_property_read_u32(np, "ram_bits", (u32 *)&config->ram_bits); + of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps); + of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits); of_property_read_u32(np, "power", (u32 *)&pdata->power); config->multipoint = of_property_read_bool(np, "multipoint"); - pdata->has_mailbox = of_property_read_bool(np, - "ti,has-mailbox"); pdata->board_data = data; pdata->config = config; - } - if (pdata->has_mailbox) { - glue->control_otghs = omap_get_control_dev(); - if (IS_ERR(glue->control_otghs)) { - dev_vdbg(&pdev->dev, "Failed to get control device\n"); - return -ENODEV; + control_node = of_parse_phandle(np, "ctrl-module", 0); + if (control_node) { + control_pdev = of_find_device_by_node(control_node); + if (!control_pdev) { + dev_err(&pdev->dev, "Failed to get control device\n"); + ret = -EINVAL; + goto err2; + } + glue->control_otghs = &control_pdev->dev; } - } else { - glue->control_otghs = ERR_PTR(-ENODEV); } pdata->platform_ops = &omap2430_ops; @@ -556,8 +597,26 @@ static int omap2430_probe(struct platform_device *pdev) INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work); - ret = platform_device_add_resources(musb, pdev->resource, - pdev->num_resources); + memset(musb_resources, 0x00, sizeof(*musb_resources) * + ARRAY_SIZE(musb_resources)); + + musb_resources[0].name = pdev->resource[0].name; + musb_resources[0].start = pdev->resource[0].start; + musb_resources[0].end = pdev->resource[0].end; + musb_resources[0].flags = pdev->resource[0].flags; + + musb_resources[1].name = pdev->resource[1].name; + musb_resources[1].start = pdev->resource[1].start; + musb_resources[1].end = pdev->resource[1].end; + musb_resources[1].flags = pdev->resource[1].flags; + + musb_resources[2].name = pdev->resource[2].name; + musb_resources[2].start = pdev->resource[2].start; + musb_resources[2].end = pdev->resource[2].end; + musb_resources[2].flags = pdev->resource[2].flags; + + ret = platform_device_add_resources(musb, musb_resources, + ARRAY_SIZE(musb_resources)); if (ret) { dev_err(&pdev->dev, "failed to add resources\n"); goto err2; @@ -608,7 +667,6 @@ static int omap2430_runtime_suspend(struct device *dev) OTG_INTERFSEL); omap2430_low_level_exit(musb); - usb_phy_set_suspend(musb->xceiv, 1); } return 0; @@ -623,8 +681,6 @@ static int omap2430_runtime_resume(struct device *dev) omap2430_low_level_init(musb); musb_writel(musb->mregs, OTG_INTERFSEL, musb->context.otg_interfsel); - - usb_phy_set_suspend(musb->xceiv, 0); } return 0; |
