tegra: usb: otg: factorize host registration code
Alexandre Courbot [Wed, 2 Nov 2011 07:57:31 +0000 (16:57 +0900)]
OTG host register/unregister functions were duplicated identically
across all board files, making the code difficult to maintain (and
actually some boards did not get all some code fixes leading to the same
bug being met again and again). This patch moves this common code into
tegra-otg.c.

Bug 884315
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Change-Id: I99b118664f0481f6c5470411b43f36609e0feb52
Reviewed-on: http://git-master/r/61763
Reviewed-by: Lokesh Pathak <lpathak@nvidia.com>
Tested-by: Lokesh Pathak <lpathak@nvidia.com>

Rebase-Id: Rc52974b7a4656009e9cdade281fe3da13cba74ae

drivers/usb/otg/tegra-otg.c
include/linux/platform_data/tegra_usb.h

index 2545aa7..a063630 100644 (file)
@@ -50,14 +50,12 @@ struct tegra_otg_data {
        void __iomem *regs;
        struct clk *clk;
        int irq;
-       struct platform_device *host;
        struct platform_device *pdev;
        struct work_struct work;
        unsigned int intr_reg_data;
        bool detect_vbus;
        bool clk_enabled;
 };
-
 static struct tegra_otg_data *tegra_clone;
 
 static inline unsigned long otg_readl(struct tegra_otg_data *tegra,
@@ -97,19 +95,68 @@ static const char *tegra_state_name(enum usb_otg_state state)
        return "INVALID";
 }
 
+static struct platform_device *
+tegra_usb_otg_host_register(struct platform_device *ehci_device,
+                           struct tegra_ehci_platform_data *pdata)
+{
+       struct platform_device *pdev;
+       void *platform_data;
+       int val;
+
+       pdev = platform_device_alloc(ehci_device->name, ehci_device->id);
+       if (!pdev)
+               return NULL;
+
+       val = platform_device_add_resources(pdev, ehci_device->resource,
+                                           ehci_device->num_resources);
+       if (val)
+               goto error;
+
+       pdev->dev.dma_mask =  ehci_device->dev.dma_mask;
+       pdev->dev.coherent_dma_mask = ehci_device->dev.coherent_dma_mask;
+
+       platform_data = kmalloc(sizeof(struct tegra_ehci_platform_data),
+               GFP_KERNEL);
+       if (!platform_data)
+               goto error;
+
+       memcpy(platform_data, pdata, sizeof(struct tegra_ehci_platform_data));
+       pdev->dev.platform_data = platform_data;
+
+       val = platform_device_add(pdev);
+       if (val)
+               goto error_add;
+
+       return pdev;
+
+error_add:
+       kfree(platform_data);
+error:
+       pr_err("%s: failed to add the host controller device\n", __func__);
+       platform_device_put(pdev);
+       return NULL;
+}
+
+static void tegra_usb_otg_host_unregister(struct platform_device *pdev)
+{
+       kfree(pdev->dev.platform_data);
+       pdev->dev.platform_data = NULL;
+       platform_device_unregister(pdev);
+}
+
 void tegra_start_host(struct tegra_otg_data *tegra)
 {
        struct tegra_otg_platform_data *pdata = tegra->otg.dev->platform_data;
        if (!tegra->pdev) {
-               tegra->pdev = pdata->host_register();
+               tegra->pdev = tegra_usb_otg_host_register(pdata->ehci_device,
+                                                         pdata->ehci_pdata);
        }
 }
 
 void tegra_stop_host(struct tegra_otg_data *tegra)
 {
-       struct tegra_otg_platform_data *pdata = tegra->otg.dev->platform_data;
        if (tegra->pdev) {
-               pdata->host_unregister(tegra->pdev);
+               tegra_usb_otg_host_unregister(tegra->pdev);
                tegra->pdev = NULL;
        }
 }
index cf75a98..09f32de 100644 (file)
@@ -40,8 +40,8 @@ struct tegra_ehci_platform_data {
 };
 
 struct tegra_otg_platform_data {
-       struct platform_device* (*host_register)(void);
-       void (*host_unregister)(struct platform_device*);
+       struct platform_device *ehci_device;
+       struct tegra_ehci_platform_data *ehci_pdata;
 };
 
 #endif /* _TEGRA_USB_H_ */