diff options
Diffstat (limited to 'drivers/usb/musb/musb_dsps.c')
-rw-r--r-- | drivers/usb/musb/musb_dsps.c | 255 |
1 files changed, 98 insertions, 157 deletions
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 74333321cb6..4ffbaace791 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -43,6 +43,7 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/of_address.h> +#include <linux/of_irq.h> #include "musb_core.h" @@ -105,10 +106,7 @@ struct dsps_musb_wrapper { /* bit positions for mode */ unsigned iddig:5; /* miscellaneous stuff */ - u32 musb_core_offset; u8 poll_seconds; - /* number of musb instances */ - u8 instances; }; /** @@ -116,10 +114,10 @@ struct dsps_musb_wrapper { */ struct dsps_glue { struct device *dev; - struct platform_device *musb[2]; /* child musb pdev */ + struct platform_device *musb; /* child musb pdev */ const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ - struct timer_list timer[2]; /* otg_workaround timer */ - unsigned long last_timer[2]; /* last timer data for each instance */ + struct timer_list timer; /* otg_workaround timer */ + unsigned long last_timer; /* last timer data for each instance */ }; /** @@ -168,7 +166,6 @@ static void otg_timer(unsigned long _musb) struct musb *musb = (void *)_musb; void __iomem *mregs = musb->mregs; struct device *dev = musb->controller; - struct platform_device *pdev = to_platform_device(dev); struct dsps_glue *glue = dev_get_drvdata(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; u8 devctl; @@ -205,7 +202,7 @@ static void otg_timer(unsigned long _musb) case OTG_STATE_B_IDLE: devctl = dsps_readb(mregs, MUSB_DEVCTL); if (devctl & MUSB_DEVCTL_BDEVICE) - mod_timer(&glue->timer[pdev->id], + mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ); else musb->xceiv->state = OTG_STATE_A_IDLE; @@ -219,7 +216,6 @@ static void otg_timer(unsigned long _musb) static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout) { struct device *dev = musb->controller; - struct platform_device *pdev = to_platform_device(dev); struct dsps_glue *glue = dev_get_drvdata(dev->parent); if (timeout == 0) @@ -230,23 +226,23 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout) musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { dev_dbg(musb->controller, "%s active, deleting timer\n", usb_otg_state_string(musb->xceiv->state)); - del_timer(&glue->timer[pdev->id]); - glue->last_timer[pdev->id] = jiffies; + del_timer(&glue->timer); + glue->last_timer = jiffies; return; } - if (time_after(glue->last_timer[pdev->id], timeout) && - timer_pending(&glue->timer[pdev->id])) { + if (time_after(glue->last_timer, timeout) && + timer_pending(&glue->timer)) { dev_dbg(musb->controller, "Longer idle timer already pending, ignoring...\n"); return; } - glue->last_timer[pdev->id] = timeout; + glue->last_timer = timeout; dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n", usb_otg_state_string(musb->xceiv->state), jiffies_to_msecs(timeout - jiffies)); - mod_timer(&glue->timer[pdev->id], timeout); + mod_timer(&glue->timer, timeout); } static irqreturn_t dsps_interrupt(int irq, void *hci) @@ -254,7 +250,6 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) struct musb *musb = hci; void __iomem *reg_base = musb->ctrl_base; struct device *dev = musb->controller; - struct platform_device *pdev = to_platform_device(dev); struct dsps_glue *glue = dev_get_drvdata(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; unsigned long flags; @@ -314,7 +309,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) */ musb->int_usb &= ~MUSB_INTR_VBUSERROR; musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; - mod_timer(&glue->timer[pdev->id], + mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ); WARNING("VBUS error workaround (delay coming)\n"); } else if (drvvbus) { @@ -322,7 +317,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) MUSB_HST_MODE(musb); musb->xceiv->otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; - del_timer(&glue->timer[pdev->id]); + del_timer(&glue->timer); } else { musb->is_active = 0; MUSB_DEV_MODE(musb); @@ -344,8 +339,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) /* Poll for ID change */ if (musb->xceiv->state == OTG_STATE_B_IDLE) - mod_timer(&glue->timer[pdev->id], - jiffies + wrp->poll_seconds * HZ); + mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ); out: spin_unlock_irqrestore(&musb->lock, flags); @@ -355,31 +349,34 @@ out: static int dsps_musb_init(struct musb *musb) { struct device *dev = musb->controller; - struct platform_device *pdev = to_platform_device(dev); struct dsps_glue *glue = dev_get_drvdata(dev->parent); + struct platform_device *parent = to_platform_device(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; - void __iomem *reg_base = musb->ctrl_base; + void __iomem *reg_base; + struct resource *r; u32 rev, val; - int status; - /* mentor core register starts at offset of 0x400 from musb base */ - musb->mregs += wrp->musb_core_offset; + r = platform_get_resource_byname(parent, IORESOURCE_MEM, "control"); + if (!r) + return -EINVAL; + + reg_base = devm_ioremap_resource(dev, r); + if (!musb->ctrl_base) + return -EINVAL; + musb->ctrl_base = reg_base; /* NOP driver needs change if supporting dual instance */ - musb->xceiv = devm_usb_get_phy_by_phandle(glue->dev, "phys", 0); - if (IS_ERR_OR_NULL(musb->xceiv)) - return -EPROBE_DEFER; + musb->xceiv = devm_usb_get_phy_by_phandle(dev, "phys", 0); + if (IS_ERR(musb->xceiv)) + return PTR_ERR(musb->xceiv); /* Returns zero if e.g. not clocked */ rev = dsps_readl(reg_base, wrp->revision); - if (!rev) { - status = -ENODEV; - goto err0; - } + if (!rev) + return -ENODEV; usb_phy_init(musb->xceiv); - - setup_timer(&glue->timer[pdev->id], otg_timer, (unsigned long) musb); + setup_timer(&glue->timer, otg_timer, (unsigned long) musb); /* Reset the musb */ dsps_writel(reg_base, wrp->control, (1 << wrp->reset)); @@ -392,17 +389,14 @@ static int dsps_musb_init(struct musb *musb) dsps_writel(musb->ctrl_base, wrp->phy_utmi, val); return 0; -err0: - return status; } static int dsps_musb_exit(struct musb *musb) { struct device *dev = musb->controller; - struct platform_device *pdev = to_platform_device(dev); struct dsps_glue *glue = dev_get_drvdata(dev->parent); - del_timer_sync(&glue->timer[pdev->id]); + del_timer_sync(&glue->timer); usb_phy_shutdown(musb->xceiv); return 0; @@ -420,106 +414,98 @@ static struct musb_platform_ops dsps_ops = { static u64 musb_dmamask = DMA_BIT_MASK(32); -static int dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) +static int get_int_prop(struct device_node *dn, const char *s) { - struct device *dev = glue->dev; - struct platform_device *pdev = to_platform_device(dev); - struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev); - struct device_node *np = pdev->dev.of_node; - struct musb_hdrc_config *config; - struct platform_device *musb; - struct resource *res; + int ret; + u32 val; + + ret = of_property_read_u32(dn, s, &val); + if (ret) + return 0; + return val; +} + +static int dsps_create_musb_pdev(struct dsps_glue *glue, + struct platform_device *parent) +{ + struct musb_hdrc_platform_data pdata; struct resource resources[2]; - char res_name[11]; + struct device *dev = &parent->dev; + struct musb_hdrc_config *config; + struct platform_device *musb; + struct device_node *dn = parent->dev.of_node; + struct device_node *child_node; int ret; - /* first resource is for usbss, so start index from 1 */ - res = platform_get_resource(pdev, IORESOURCE_MEM, id + 1); - if (!res) { - dev_err(dev, "failed to get memory for instance %d\n", id); - ret = -ENODEV; - goto err0; + child_node = of_get_child_by_name(dn, "usb"); + if (!child_node) + return -EINVAL; + + memset(resources, 0, sizeof(resources)); + ret = of_address_to_resource(child_node, 0, &resources[0]); + if (ret) { + dev_err(dev, "failed to get memory.\n"); + return ret; } - res->parent = NULL; - resources[0] = *res; - - /* first resource is for usbss, so start index from 1 */ - res = platform_get_resource(pdev, IORESOURCE_IRQ, id + 1); - if (!res) { - dev_err(dev, "failed to get irq for instance %d\n", id); - ret = -ENODEV; - goto err0; + + ret = of_irq_to_resource(child_node, 0, &resources[1]); + if (ret == 0) { + dev_err(dev, "failed to get irq.\n"); + ret = -EINVAL; + return ret; } - res->parent = NULL; - resources[1] = *res; - resources[1].name = "mc"; /* allocate the child platform device */ musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); if (!musb) { dev_err(dev, "failed to allocate musb device\n"); - ret = -ENOMEM; - goto err0; + return -ENOMEM; } musb->dev.parent = dev; musb->dev.dma_mask = &musb_dmamask; musb->dev.coherent_dma_mask = musb_dmamask; + musb->dev.of_node = of_node_get(child_node); - glue->musb[id] = musb; + glue->musb = musb; - ret = platform_device_add_resources(musb, resources, 2); + ret = platform_device_add_resources(musb, resources, + ARRAY_SIZE(resources)); if (ret) { dev_err(dev, "failed to add resources\n"); - goto err2; + goto err; } - if (np) { - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) { - dev_err(&pdev->dev, - "failed to allocate musb platform data\n"); - ret = -ENOMEM; - goto err2; - } - - config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL); - if (!config) { - dev_err(&pdev->dev, - "failed to allocate musb hdrc config\n"); - ret = -ENOMEM; - goto err2; - } - - of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps); - of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits); - snprintf(res_name, sizeof(res_name), "port%d-mode", id); - of_property_read_u32(np, res_name, (u32 *)&pdata->mode); - of_property_read_u32(np, "power", (u32 *)&pdata->power); - config->multipoint = of_property_read_bool(np, "multipoint"); - - pdata->config = config; + config = devm_kzalloc(&parent->dev, sizeof(*config), GFP_KERNEL); + if (!config) { + dev_err(dev, "failed to allocate musb hdrc config\n"); + ret = -ENOMEM; + goto err; } + pdata.config = config; + pdata.platform_ops = &dsps_ops; - pdata->platform_ops = &dsps_ops; + config->num_eps = get_int_prop(child_node, "num-eps"); + config->ram_bits = get_int_prop(child_node, "ram-bits"); + pdata.mode = get_int_prop(child_node, "port-mode"); + pdata.power = get_int_prop(child_node, "power"); + config->multipoint = of_property_read_bool(child_node, "multipoint"); - ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); + ret = platform_device_add_data(musb, &pdata, sizeof(pdata)); if (ret) { dev_err(dev, "failed to add platform_data\n"); - goto err2; + goto err; } ret = platform_device_add(musb); if (ret) { dev_err(dev, "failed to register musb device\n"); - goto err2; + goto err; } - return 0; -err2: +err: platform_device_put(musb); -err0: return ret; } @@ -528,14 +514,12 @@ static int dsps_probe(struct platform_device *pdev) const struct of_device_id *match; const struct dsps_musb_wrapper *wrp; struct dsps_glue *glue; - struct resource *iomem; - int ret, i; + int ret; match = of_match_node(musb_dsps_of_match, pdev->dev.of_node); if (!match) { dev_err(&pdev->dev, "fail to get matching of_match struct\n"); - ret = -EINVAL; - goto err0; + return -EINVAL; } wrp = match->data; @@ -543,29 +527,13 @@ static int dsps_probe(struct platform_device *pdev) glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { dev_err(&pdev->dev, "unable to allocate glue memory\n"); - ret = -ENOMEM; - goto err0; - } - - /* get memory resource */ - iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iomem) { - dev_err(&pdev->dev, "failed to get usbss mem resourse\n"); - ret = -ENODEV; - goto err1; + return -ENOMEM; } glue->dev = &pdev->dev; + glue->wrp = wrp; - glue->wrp = kmemdup(wrp, sizeof(*wrp), GFP_KERNEL); - if (!glue->wrp) { - dev_err(&pdev->dev, "failed to duplicate wrapper struct memory\n"); - ret = -ENOMEM; - goto err1; - } platform_set_drvdata(pdev, glue); - - /* enable the usbss clocks */ pm_runtime_enable(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev); @@ -574,17 +542,9 @@ static int dsps_probe(struct platform_device *pdev) goto err2; } - /* create the child platform device for all instances of musb */ - for (i = 0; i < wrp->instances ; i++) { - ret = dsps_create_musb_pdev(glue, i); - if (ret != 0) { - dev_err(&pdev->dev, "failed to create child pdev\n"); - /* release resources of previously created instances */ - for (i--; i >= 0 ; i--) - platform_device_unregister(glue->musb[i]); - goto err3; - } - } + ret = dsps_create_musb_pdev(glue, pdev); + if (ret) + goto err3; return 0; @@ -592,26 +552,19 @@ err3: pm_runtime_put(&pdev->dev); err2: pm_runtime_disable(&pdev->dev); - kfree(glue->wrp); -err1: kfree(glue); -err0: return ret; } + static int dsps_remove(struct platform_device *pdev) { struct dsps_glue *glue = platform_get_drvdata(pdev); - const struct dsps_musb_wrapper *wrp = glue->wrp; - int i; - /* delete the child platform device */ - for (i = 0; i < wrp->instances ; i++) - platform_device_unregister(glue->musb[i]); + platform_device_unregister(glue->musb); /* disable usbss clocks */ pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); - kfree(glue->wrp); kfree(glue); return 0; } @@ -641,9 +594,7 @@ static const struct dsps_musb_wrapper am33xx_driver_data = { .rxep_shift = 16, .rxep_mask = 0xfffe, .rxep_bitmap = (0xfffe << 16), - .musb_core_offset = 0x400, .poll_seconds = 2, - .instances = 1, }; static const struct of_device_id musb_dsps_of_match[] = { @@ -667,14 +618,4 @@ MODULE_AUTHOR("Ravi B <ravibabu@ti.com>"); MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>"); MODULE_LICENSE("GPL v2"); -static int __init dsps_init(void) -{ - return platform_driver_register(&dsps_usbss_driver); -} -subsys_initcall(dsps_init); - -static void __exit dsps_exit(void) -{ - platform_driver_unregister(&dsps_usbss_driver); -} -module_exit(dsps_exit); +module_platform_driver(dsps_usbss_driver); |