[RFC PATCH] remove platform device from dwc3.ko module

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Felipe,

Here is my "more-invasive" approach to making the dwc3 driver support
hibernation on our HAPS platform.

This gets rid of the fake platform device that is constructed by the
bus glue for the dwc3.ko module, and turns it into a library-like
module that can be called from the bus glue code.

This will allow the HAPS PCI glue to get a pointer to the dwc3 context,
so it can easily do the things it needs for hibernation. It gets rid
of the (I think) strange need to have pm-runtime calls in both the
dwc3 module and the bus glue module. Why should we have two sets of
those for a single piece of hardware anyway? Or two platform devices
for a single piece of hardware for that matter?

And, it results in a nice reduction in the lines of code.

If someone really needs a separate platform device for the dwc3.ko
module, they can write a small piece of code to do that, much like
Sebastian did for the xhci driver. But I don't see why that should
be necessary.

Note that I didn't add the hibernation code itself to this patch.
This patch just changes the API between the dwc3.ko module and the
PCI and OMAP glue modules.

Is there a reason why this approach won't work, or why it is
inferior to what you have now?

- Paul

---
 drivers/usb/dwc3/core.c      |   98 ++++++++++++++++--------------------------
 drivers/usb/dwc3/core.h      |    7 ++-
 drivers/usb/dwc3/dwc3-omap.c |   67 +++++++++++-----------------
 drivers/usb/dwc3/dwc3-pci.c  |   87 +++++++++----------------------------
 drivers/usb/dwc3/ep0.c       |    1 -
 drivers/usb/dwc3/gadget.c    |   15 +-----
 6 files changed, 93 insertions(+), 182 deletions(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index fd6917b..7647c87 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -40,7 +40,6 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
@@ -69,7 +68,7 @@ MODULE_PARM_DESC(maximum_speed, "Maximum supported speed.");
 
 static DECLARE_BITMAP(dwc3_devs, DWC3_DEVS_POSSIBLE);
 
-int dwc3_get_device_id(void)
+static int dwc3_get_device_id(void)
 {
 	int		id;
 
@@ -88,9 +87,8 @@ again:
 
 	return id;
 }
-EXPORT_SYMBOL_GPL(dwc3_get_device_id);
 
-void dwc3_put_device_id(int id)
+static void dwc3_put_device_id(int id)
 {
 	int			ret;
 
@@ -101,7 +99,6 @@ void dwc3_put_device_id(int id)
 	WARN(!ret, "dwc3: ID %d not in use\n", id);
 	clear_bit(id, dwc3_devs);
 }
-EXPORT_SYMBOL_GPL(dwc3_put_device_id);
 
 void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
 {
@@ -402,63 +399,50 @@ static void dwc3_core_exit(struct dwc3 *dwc)
 
 #define DWC3_ALIGN_MASK		(16 - 1)
 
-static int __devinit dwc3_probe(struct platform_device *pdev)
+struct dwc3 * __devinit dwc3_init(struct device *dev, struct resource *res,
+		int irq, int irqf)
 {
-	struct device_node	*node = pdev->dev.of_node;
-	struct resource		*res;
+	struct device_node	*node = dev->of_node;
 	struct dwc3		*dwc;
-	struct device		*dev = &pdev->dev;
-
-	int			ret = -ENOMEM;
-	int			irq;
 
 	void __iomem		*regs;
 	void			*mem;
 
+	int			devid;
+	int			ret = -ENOMEM;
+
 	u8			mode;
 
 	mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
 	if (!mem) {
 		dev_err(dev, "not enough memory\n");
-		return -ENOMEM;
+		goto err0;
 	}
 	dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
 	dwc->mem = mem;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "missing resource\n");
-		return -ENODEV;
-	}
-
-	dwc->res = res;
-
-	res = devm_request_mem_region(dev, res->start, resource_size(res),
-			dev_name(dev));
-	if (!res) {
-		dev_err(dev, "can't request mem region\n");
-		return -ENOMEM;
+	devid = dwc3_get_device_id();
+	if (devid < 0) {
+		ret = devid;
+		goto err0;
 	}
+	dwc->devid = devid;
 
 	regs = devm_ioremap(dev, res->start, resource_size(res));
 	if (!regs) {
 		dev_err(dev, "ioremap failed\n");
-		return -ENOMEM;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(dev, "missing IRQ\n");
-		return -ENODEV;
+		ret = -EINVAL;
+		goto err0;
 	}
 
 	spin_lock_init(&dwc->lock);
-	platform_set_drvdata(pdev, dwc);
 
+	dwc->res	= res;
 	dwc->regs	= regs;
 	dwc->regs_size	= resource_size(res);
 	dwc->dev	= dev;
 	dwc->irq	= irq;
+	dwc->irqf	= irqf;
 
 	if (!strncmp("super", maximum_speed, 5))
 		dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
@@ -481,7 +465,7 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
 	ret = dwc3_core_init(dwc);
 	if (ret) {
 		dev_err(dev, "failed to initialize core\n");
-		return ret;
+		goto err0;
 	}
 
 	mode = DWC3_MODE(dwc->hwparams.hwparams0);
@@ -531,7 +515,7 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
 
 	pm_runtime_allow(dev);
 
-	return 0;
+	return dwc;
 
 err2:
 	switch (mode) {
@@ -553,18 +537,17 @@ err2:
 err1:
 	dwc3_core_exit(dwc);
 
-	return ret;
+err0:
+	return ERR_PTR(ret);
 }
+EXPORT_SYMBOL_GPL(dwc3_init);
 
-static int __devexit dwc3_remove(struct platform_device *pdev)
+void __devexit dwc3_exit(struct dwc3 *dwc)
 {
-	struct dwc3	*dwc = platform_get_drvdata(pdev);
-	struct resource	*res;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	struct device	*dev = dwc->dev;
 
-	pm_runtime_put(&pdev->dev);
-	pm_runtime_disable(&pdev->dev);
+	pm_runtime_put(dev);
+	pm_runtime_disable(dev);
 
 	dwc3_debugfs_exit(dwc);
 
@@ -585,31 +568,24 @@ static int __devexit dwc3_remove(struct platform_device *pdev)
 	}
 
 	dwc3_core_exit(dwc);
-
-	return 0;
+	dwc3_put_device_id(dwc->devid);
 }
+EXPORT_SYMBOL_GPL(dwc3_exit);
 
-static struct platform_driver dwc3_driver = {
-	.probe		= dwc3_probe,
-	.remove		= __devexit_p(dwc3_remove),
-	.driver		= {
-		.name	= "dwc3",
-	},
-};
-
-MODULE_ALIAS("platform:dwc3");
+MODULE_ALIAS("dwc3");
 MODULE_AUTHOR("Felipe Balbi <balbi@xxxxxx>");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
 
-static int __devinit dwc3_init(void)
+static int __devinit dwc3_module_init(void)
 {
-	return platform_driver_register(&dwc3_driver);
+	/* all init is done in dwc3_init(), called from bus glue module */
+	return 0;
 }
-module_init(dwc3_init);
+module_init(dwc3_module_init);
 
-static void __exit dwc3_exit(void)
+static void __exit dwc3_module_exit(void)
 {
-	platform_driver_unregister(&dwc3_driver);
+	/* all teardown is done in dwc3_exit(), called from bus glue module */
 }
-module_exit(dwc3_exit);
+module_exit(dwc3_module_exit);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 6c7945b..1979c94 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -595,6 +595,8 @@ struct dwc3 {
 	size_t			regs_size;
 
 	int			irq;
+	int			irqf;
+	int			devid;
 
 	u32			num_event_buffers;
 	u32			u1u2;
@@ -778,7 +780,8 @@ void dwc3_host_exit(struct dwc3 *dwc);
 int dwc3_gadget_init(struct dwc3 *dwc);
 void dwc3_gadget_exit(struct dwc3 *dwc);
 
-extern int dwc3_get_device_id(void);
-extern void dwc3_put_device_id(int id);
+extern struct dwc3 * __devinit dwc3_init(struct device *dev,
+		struct resource *res, int irq, int irqf);
+extern void __devexit dwc3_exit(struct dwc3 *dwc);
 
 #endif /* __DRIVERS_USB_DWC3_CORE_H */
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index d7d9c0e..8a1d47e 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -131,7 +131,7 @@ struct dwc3_omap {
 	/* device lock */
 	spinlock_t		lock;
 
-	struct platform_device	*dwc3;
+	struct dwc3		*dwc;
 	struct device		*dev;
 
 	int			irq;
@@ -199,12 +199,11 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
 	struct dwc3_omap_data	*pdata = pdev->dev.platform_data;
 	struct device_node	*node = pdev->dev.of_node;
 
-	struct platform_device	*dwc3;
+	struct dwc3		*dwc;
 	struct dwc3_omap	*omap;
 	struct resource		*res;
 	struct device		*dev = &pdev->dev;
 
-	int			devid;
 	int			size;
 	int			ret = -ENOMEM;
 	int			irq;
@@ -225,13 +224,13 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
 
 	irq = platform_get_irq(pdev, 1);
 	if (irq < 0) {
-		dev_err(dev, "missing IRQ resource\n");
+		dev_err(dev, "missing IRQ resource 1\n");
 		return -EINVAL;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	if (!res) {
-		dev_err(dev, "missing memory base resource\n");
+		dev_err(dev, "missing memory base resource 1\n");
 		return -EINVAL;
 	}
 
@@ -241,34 +240,19 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	devid = dwc3_get_device_id();
-	if (devid < 0)
-		return -ENODEV;
-
-	dwc3 = platform_device_alloc("dwc3", devid);
-	if (!dwc3) {
-		dev_err(dev, "couldn't allocate dwc3 device\n");
-		goto err1;
-	}
-
 	context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL);
 	if (!context) {
 		dev_err(dev, "couldn't allocate dwc3 context memory\n");
-		goto err2;
+		return -ENOMEM;
 	}
 
 	spin_lock_init(&omap->lock);
-	dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask);
 
-	dwc3->dev.parent = dev;
-	dwc3->dev.dma_mask = dev->dma_mask;
-	dwc3->dev.dma_parms = dev->dma_parms;
 	omap->resource_size = resource_size(res);
 	omap->context	= context;
 	omap->dev	= dev;
 	omap->irq	= irq;
 	omap->base	= base;
-	omap->dwc3	= dwc3;
 
 	reg = dwc3_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
 
@@ -300,8 +284,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
 	omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE);
 
 	/* Set No-Idle and No-Standby */
-	reg &= ~(USBOTGSS_STANDBYMODE_MASK
-			| USBOTGSS_IDLEMODE_MASK);
+	reg &= ~(USBOTGSS_STANDBYMODE_MASK | USBOTGSS_IDLEMODE_MASK);
 
 	reg |= (USBOTGSS_SYSCONFIG_STANDBYMODE(USBOTGSS_STANDBYMODE_NO_STANDBY)
 		| USBOTGSS_SYSCONFIG_IDLEMODE(USBOTGSS_IDLEMODE_NO_IDLE));
@@ -313,7 +296,7 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
 	if (ret) {
 		dev_err(dev, "failed to request IRQ #%d --> %d\n",
 				omap->irq, ret);
-		goto err2;
+		goto err1;
 	}
 
 	/* enable all IRQs */
@@ -332,27 +315,31 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
 
 	dwc3_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
 
-	ret = platform_device_add_resources(dwc3, pdev->resource,
-			pdev->num_resources);
-	if (ret) {
-		dev_err(dev, "couldn't add resources to dwc3 device\n");
-		goto err2;
+	ret = -EINVAL;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(dev, "missing IRQ resource 0\n");
+		goto err1;
 	}
 
-	ret = platform_device_add(dwc3);
-	if (ret) {
-		dev_err(dev, "failed to register dwc3 device\n");
-		goto err2;
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "missing memory base resource 0\n");
+		goto err1;
 	}
 
-	return 0;
+	dwc = dwc3_init(dev, res, irq, 0);
+	if (PTR_ERR(dwc)) {
+		dev_err(dev, "dwc3_init() failed\n");
+		ret = PTR_ERR(dwc);
+		goto err1;
+	}
+	omap->dwc = dwc;
 
-err2:
-	platform_device_put(dwc3);
+	return 0;
 
 err1:
-	dwc3_put_device_id(devid);
-
 	return ret;
 }
 
@@ -360,9 +347,7 @@ static int __devexit dwc3_omap_remove(struct platform_device *pdev)
 {
 	struct dwc3_omap	*omap = platform_get_drvdata(pdev);
 
-	platform_device_unregister(omap->dwc3);
-
-	dwc3_put_device_id(omap->dwc3->id);
+	dwc3_exit(omap->dwc);
 
 	return 0;
 }
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index a81b30e..898019c 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -40,7 +40,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
-#include <linux/platform_device.h>
+#include <linux/interrupt.h>
 
 #include "core.h"
 
@@ -48,91 +48,49 @@
 #define PCI_VENDOR_ID_SYNOPSYS		0x16c3
 #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3	0xabcd
 
-struct dwc3_pci {
-	struct device		*dev;
-	struct platform_device	*dwc3;
-};
-
 static int __devinit dwc3_pci_probe(struct pci_dev *pci,
 		const struct pci_device_id *id)
 {
-	struct resource		res[2];
-	struct platform_device	*dwc3;
-	struct dwc3_pci		*glue;
-	int			ret = -ENOMEM;
-	int			devid;
+	struct resource		*res;
+	struct dwc3		*dwc;
 	struct device		*dev = &pci->dev;
 
-	glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
-	if (!glue) {
-		dev_err(dev, "not enough memory\n");
-		return -ENOMEM;
-	}
-
-	glue->dev = dev;
+	int			ret;
 
 	ret = pci_enable_device(pci);
 	if (ret) {
 		dev_err(dev, "failed to enable pci device\n");
-		return -ENODEV;
+		return ret;
 	}
 
 	pci_set_power_state(pci, PCI_D0);
 	pci_set_master(pci);
 
-	ret = -ENOMEM;
-
-	devid = dwc3_get_device_id();
-	if (devid < 0)
+	res = devm_request_mem_region(dev, pci_resource_start(pci, 0),
+			pci_resource_len(pci, 0), dev_name(dev));
+	if (!res) {
+		dev_err(dev, "can't request mem region\n");
+		ret = -EBUSY;
 		goto err1;
+	}
 
-	dwc3 = platform_device_alloc("dwc3", devid);
-	if (!dwc3) {
-		dev_err(dev, "couldn't allocate dwc3 device\n");
+	if (!pci->irq) {
+		dev_err(dev, "no IRQ for PCI device\n");
+		ret = -ENODEV;
 		goto err1;
 	}
 
-	memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
-
-	res[0].start	= pci_resource_start(pci, 0);
-	res[0].end	= pci_resource_end(pci, 0);
-	res[0].name	= "dwc_usb3";
-	res[0].flags	= IORESOURCE_MEM;
-
-	res[1].start	= pci->irq;
-	res[1].name	= "dwc_usb3";
-	res[1].flags	= IORESOURCE_IRQ;
-
-	ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res));
-	if (ret) {
-		dev_err(dev, "couldn't add resources to dwc3 device\n");
-		goto err2;
+	dwc = dwc3_init(dev, res, pci->irq, IRQF_SHARED);
+	if (PTR_ERR(dwc)) {
+		dev_err(dev, "dwc3_init() failed\n");
+		ret = PTR_ERR(dwc);
+		goto err1;
 	}
 
-	pci_set_drvdata(pci, glue);
-
-	dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask);
-
-	dwc3->dev.dma_mask = dev->dma_mask;
-	dwc3->dev.dma_parms = dev->dma_parms;
-	dwc3->dev.parent = dev;
-	glue->dwc3 = dwc3;
-
-	ret = platform_device_add(dwc3);
-	if (ret) {
-		dev_err(dev, "failed to register dwc3 device\n");
-		goto err3;
-	}
+	pci_set_drvdata(pci, dwc);
 
 	return 0;
 
-err3:
-	pci_set_drvdata(pci, NULL);
-	platform_device_put(dwc3);
-
-err2:
-	dwc3_put_device_id(devid);
-
 err1:
 	pci_disable_device(pci);
 
@@ -141,10 +99,9 @@ err1:
 
 static void __devexit dwc3_pci_remove(struct pci_dev *pci)
 {
-	struct dwc3_pci	*glue = pci_get_drvdata(pci);
+	struct dwc3	*dwc = pci_get_drvdata(pci);
 
-	dwc3_put_device_id(glue->dwc3->id);
-	platform_device_unregister(glue->dwc3);
+	dwc3_exit(dwc);
 	pci_set_drvdata(pci, NULL);
 	pci_disable_device(pci);
 }
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 25910e2..fc17110 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -39,7 +39,6 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 3430dbb..5ef3213 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -40,7 +40,6 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -2249,7 +2248,6 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
 {
 	u32					reg;
 	int					ret;
-	int					irq;
 
 	dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
 			&dwc->ctrl_req_addr, GFP_KERNEL);
@@ -2307,13 +2305,11 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
 	if (ret)
 		goto err4;
 
-	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-
-	ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED,
-			"dwc3", dwc);
+	ret = devm_request_irq(dwc->dev, dwc->irq, dwc3_interrupt, dwc->irqf,
+				"dwc3", dwc);
 	if (ret) {
 		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
-				irq, ret);
+				dwc->irq, ret);
 		goto err5;
 	}
 
@@ -2349,7 +2345,6 @@ err7:
 
 err6:
 	dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
-	free_irq(irq, dwc);
 
 err5:
 	dwc3_gadget_free_endpoints(dwc);
@@ -2375,13 +2370,9 @@ err0:
 
 void dwc3_gadget_exit(struct dwc3 *dwc)
 {
-	int			irq;
-
 	usb_del_gadget_udc(&dwc->gadget);
-	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
 
 	dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
-	free_irq(irq, dwc);
 
 	dwc3_gadget_free_endpoints(dwc);
 
-- 
1.7.4.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux