[PATCH 4/5] USB i.MX chipidea: implement post init support

Sascha Hauer s.hauer at pengutronix.de
Thu Feb 14 04:07:26 EST 2013


Some controllers need an init hook after the USB controller is
started, so implement the post init hook for i.MX.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/usb/imx/chipidea-imx.c |   43 ++++++++++++++++++++++-----
 drivers/usb/imx/imx-usb-misc.c |   63 ++++++++++++++++++++++++++++++++--------
 include/usb/chipidea-imx.h     |    2 ++
 3 files changed, 89 insertions(+), 19 deletions(-)

diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c
index 64bb866..de80c36 100644
--- a/drivers/usb/imx/chipidea-imx.c
+++ b/drivers/usb/imx/chipidea-imx.c
@@ -22,12 +22,41 @@
 
 #define MXC_EHCI_PORTSC_MASK ((0xf << 28) | (1 << 25))
 
+static int imx_chipidea_port_init(void *drvdata)
+{
+	struct device_d *dev = drvdata;
+	struct imxusb_platformdata *pdata = dev->platform_data;
+	int ret;
+
+	ret = imx_usbmisc_port_init(dev->id, pdata->flags);
+	if (ret)
+		dev_err(dev, "misc init failed: %s\n", strerror(-ret));
+
+	if (pdata->init)
+		pdata->init(dev->id);
+
+	return ret;
+}
+
+static int imx_chipidea_port_post_init(void *drvdata)
+{
+	struct device_d *dev = drvdata;
+	struct imxusb_platformdata *pdata = dev->platform_data;
+	int ret;
+
+	ret = imx_usbmisc_port_post_init(dev->id, pdata->flags);
+	if (ret)
+		dev_err(dev, "post misc init failed: %s\n", strerror(-ret));
+
+	return ret;
+}
+
 static int imx_chipidea_probe(struct device_d *dev)
 {
 	struct imxusb_platformdata *pdata = dev->platform_data;
 	int ret;
 	void __iomem *base;
-	struct ehci_data data;
+	struct ehci_data data = {};
 	uint32_t portsc;
 
 	if (!pdata) {
@@ -39,17 +68,17 @@ static int imx_chipidea_probe(struct device_d *dev)
 	if (!base)
 		return -ENODEV;
 
+	data.init = imx_chipidea_port_init;
+	data.post_init = imx_chipidea_port_post_init;
+	data.drvdata = dev;
+
+	imx_chipidea_port_init(dev);
+
 	portsc = readl(base + 0x184);
 	portsc &= ~MXC_EHCI_PORTSC_MASK;
 	portsc |= pdata->flags & MXC_EHCI_PORTSC_MASK;
 	writel(portsc, base + 0x184);
 
-	ret = imx_usbmisc_port_init(dev->id, pdata->flags);
-	if (ret) {
-		dev_err(dev, "failed to init misc regs: %s\n", strerror(-ret));
-		return ret;
-	}
-
 	if ((pdata->flags & MXC_EHCI_PORTSC_MASK) == MXC_EHCI_MODE_ULPI) {
 		dev_dbg(dev, "using ULPI phy\n");
 		if (IS_ENABLED(CONFIG_USB_ULPI)) {
diff --git a/drivers/usb/imx/imx-usb-misc.c b/drivers/usb/imx/imx-usb-misc.c
index 4cdf5ab..d42f4c0 100644
--- a/drivers/usb/imx/imx-usb-misc.c
+++ b/drivers/usb/imx/imx-usb-misc.c
@@ -34,6 +34,11 @@
 #define MX25_H1_USBTE_BIT	(1 << 4)
 #define MX25_H1_OCPOL_BIT	(1 << 2)
 
+struct imx_usb_misc_data {
+	int (*init)(void __iomem *base, int port, unsigned int flags);
+	int (*post_init)(void __iomem *base, int port, unsigned int flags);
+};
+
 static __maybe_unused int mx25_initialize_usb_hw(void __iomem *base, int port, unsigned int flags)
 {
 	unsigned int v;
@@ -93,6 +98,10 @@ static __maybe_unused int mx25_initialize_usb_hw(void __iomem *base, int port, u
 	return 0;
 }
 
+static __maybe_unused struct imx_usb_misc_data mx25_data = {
+	.init = mx25_initialize_usb_hw,
+};
+
 #define MX27_OTG_SIC_SHIFT	29
 #define MX27_OTG_SIC_MASK	(0x3 << MX27_OTG_SIC_SHIFT)
 #define MX27_OTG_PM_BIT		(1 << 24)
@@ -152,6 +161,10 @@ static __maybe_unused int mx27_mx31_initialize_usb_hw(void __iomem *base, int po
 	return 0;
 }
 
+static __maybe_unused struct imx_usb_misc_data mx27_mx31_data = {
+	.init = mx27_mx31_initialize_usb_hw,
+};
+
 #define USBCTRL_OTGBASE_OFFSET	0x600
 
 #define MX35_OTG_SIC_SHIFT	29
@@ -229,6 +242,10 @@ static __maybe_unused int mx35_initialize_usb_hw(void __iomem *base, int port, u
 	return 0;
 }
 
+static __maybe_unused struct imx_usb_misc_data mx35_data = {
+	.init = mx35_initialize_usb_hw,
+};
+
 /* USB_CTRL */
 #define MX5_OTG_UCTRL_OWIE_BIT		(1 << 27)	/* OTG wakeup intr enable */
 #define MX5_OTG_UCTRL_OPM_BIT		(1 << 24)	/* OTG power mask */
@@ -324,53 +341,61 @@ static __maybe_unused int mx5_initialize_usb_hw(void __iomem *base, int port,
 	return 0;
 }
 
+static __maybe_unused struct imx_usb_misc_data mx5_data = {
+	.init = mx5_initialize_usb_hw,
+};
+
 static __maybe_unused int mx6_initialize_usb_hw(void __iomem *base, int port,
 		unsigned int flags)
 {
 	return 0;
 }
 
+static __maybe_unused struct imx_usb_misc_data mx6_data = {
+	.init = mx6_initialize_usb_hw,
+};
+
 static struct platform_device_id imx_usbmisc_ids[] = {
 #ifdef CONFIG_ARCH_IMX25
 	{
 		.name = "imx25-usb-misc",
-		.driver_data = (unsigned long)&mx25_initialize_usb_hw,
+		.driver_data = (unsigned long)&mx25_data,
 	},
 #endif
 #ifdef CONFIG_ARCH_IMX27
 	{
 		.name = "imx27-usb-misc",
-		.driver_data = (unsigned long)&mx27_mx31_initialize_usb_hw,
+		.driver_data = (unsigned long)&mx27_mx31_data,
 	},
 #endif
 #ifdef CONFIG_ARCH_IMX31
 	{
 		.name = "imx31-usb-misc",
-		.driver_data = (unsigned long)&mx27_mx31_initialize_usb_hw,
+		.driver_data = (unsigned long)&mx27_mx31_data,
 	},
 #endif
 #ifdef CONFIG_ARCH_IMX35
 	{
 		.name = "imx35-usb-misc",
-		.driver_data = (unsigned long)&mx35_initialize_usb_hw,
+		.driver_data = (unsigned long)&mx35_data,
 	},
 #endif
 #ifdef CONFIG_ARCH_IMX51
 	{
 		.name = "imx51-usb-misc",
-		.driver_data = (unsigned long)&mx5_initialize_usb_hw,
+		.driver_data = (unsigned long)&mx5_data,
 	},
 #endif
 #ifdef CONFIG_ARCH_IMX53
 	{
 		.name = "imx53-usb-misc",
-		.driver_data = (unsigned long)&mx5_initialize_usb_hw,
+		.driver_data = (unsigned long)&mx5_data,
 	},
 #endif
 #ifdef CONFIG_ARCH_IMX6
 	{
 		.name = "imx6-usb-misc",
-		.driver_data = (unsigned long)&mx6_initialize_usb_hw,
+		.driver_data = (unsigned long)&mx6_data,
 	},
 #endif
 	{
@@ -378,20 +403,34 @@ static struct platform_device_id imx_usbmisc_ids[] = {
 	},
 };
 
-static int (*__imx_usbmisc_port_init)(void __iomem *base, int port, unsigned flags);
+static struct imx_usb_misc_data *imxusbmisc_data;
 static void __iomem *usbmisc_base;
 
 int imx_usbmisc_port_init(int port, unsigned flags)
 {
-	if (!__imx_usbmisc_port_init)
+	if (!imxusbmisc_data)
 		return -ENODEV;
 
-	return __imx_usbmisc_port_init(usbmisc_base, port, flags);
+	if (!imxusbmisc_data->init)
+		return 0;
+
+	return imxusbmisc_data->init(usbmisc_base, port, flags);
+}
+
+int imx_usbmisc_port_post_init(int port, unsigned flags)
+{
+	if (!imxusbmisc_data)
+		return -ENODEV;
+
+	if (!imxusbmisc_data->post_init)
+		return 0;
+
+	return imxusbmisc_data->post_init(usbmisc_base, port, flags);
 }
 
 static int imx_usbmisc_probe(struct device_d *dev)
 {
-	struct imx_serial_devtype_data *devtype;
+	struct imx_usb_misc_data *devtype;
 	int ret;
 
 	ret = dev_get_drvdata(dev, (unsigned long *)&devtype);
@@ -402,7 +441,7 @@ static int imx_usbmisc_probe(struct device_d *dev)
 	if (!usbmisc_base)
 		return -ENOMEM;
 
-	__imx_usbmisc_port_init = (void *)devtype;
+	imxusbmisc_data = devtype;
 
 	return 0;
 }
diff --git a/include/usb/chipidea-imx.h b/include/usb/chipidea-imx.h
index 252d488..3f9f61e 100644
--- a/include/usb/chipidea-imx.h
+++ b/include/usb/chipidea-imx.h
@@ -40,8 +40,10 @@ enum imx_usb_mode {
 struct imxusb_platformdata {
 	unsigned long flags;
 	enum imx_usb_mode mode;
+	int (*init)(int port);
 };
 
 int imx_usbmisc_port_init(int port, unsigned flags);
+int imx_usbmisc_port_post_init(int port, unsigned flags);
 
 #endif /* __USB_CHIPIDEA_IMX_H */
-- 
1.7.10.4




More information about the barebox mailing list