#include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include "musb_core.h"
 
        /* bit positions for mode */
        unsigned        iddig:5;
        /* miscellaneous stuff */
-       u32             musb_core_offset;
        u8              poll_seconds;
-       /* number of musb instances */
-       u8              instances;
 };
 
 /**
  */
 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 */
 };
 
 /**
        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;
        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;
 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)
                                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)
        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;
                         */
                        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) {
                        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);
 
        /* 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);
 
 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));
        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;
 
 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;
 }
 
        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;
 
        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);
                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;
 
        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;
 }
        .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[] = {
 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);