aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/chipidea
diff options
context:
space:
mode:
authorMichael Grzeschik <m.grzeschik@pengutronix.de>2013-03-30 06:54:01 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-03-30 11:13:58 -0400
commita068533079a0a1be53c78c89e65adfbd3c687591 (patch)
treebe75fdae9ac283f5cf3f5ab7310ba0298578b3e5 /drivers/usb/chipidea
parentf0c910b63cc273c239964776fae1aaa58ed4ad2b (diff)
usb: chipidea: usbmisc: add post handling and errata fix for mx25
This adds a post handling routine which is called after ci13xxx_add_device was called. The first user is the mx25, which has to disable the external-vbus-divider after the udc has started. Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> [Alex: also fixed a signed one-bit bitfield a whitespace error and yet another set of line-too-long and void pointer casting errors] Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/chipidea')
-rw-r--r--drivers/usb/chipidea/ci13xxx_imx.c12
-rw-r--r--drivers/usb/chipidea/ci13xxx_imx.h3
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c36
3 files changed, 51 insertions, 0 deletions
diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c
index 8c291220be7f..8faec9dbbb84 100644
--- a/drivers/usb/chipidea/ci13xxx_imx.c
+++ b/drivers/usb/chipidea/ci13xxx_imx.c
@@ -79,6 +79,9 @@ int usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev)
79 if (of_find_property(np, "disable-over-current", NULL)) 79 if (of_find_property(np, "disable-over-current", NULL))
80 usbdev->disable_oc = 1; 80 usbdev->disable_oc = 1;
81 81
82 if (of_find_property(np, "external-vbus-divider", NULL))
83 usbdev->evdo = 1;
84
82 return 0; 85 return 0;
83} 86}
84EXPORT_SYMBOL_GPL(usbmisc_get_init_data); 87EXPORT_SYMBOL_GPL(usbmisc_get_init_data);
@@ -202,6 +205,15 @@ static int ci13xxx_imx_probe(struct platform_device *pdev)
202 goto err; 205 goto err;
203 } 206 }
204 207
208 if (usbmisc_ops && usbmisc_ops->post) {
209 ret = usbmisc_ops->post(&pdev->dev);
210 if (ret) {
211 dev_err(&pdev->dev,
212 "usbmisc post failed, ret=%d\n", ret);
213 goto put_np;
214 }
215 }
216
205 data->ci_pdev = plat_ci; 217 data->ci_pdev = plat_ci;
206 platform_set_drvdata(pdev, data); 218 platform_set_drvdata(pdev, data);
207 219
diff --git a/drivers/usb/chipidea/ci13xxx_imx.h b/drivers/usb/chipidea/ci13xxx_imx.h
index 9cd2e910b1ca..550bfa457620 100644
--- a/drivers/usb/chipidea/ci13xxx_imx.h
+++ b/drivers/usb/chipidea/ci13xxx_imx.h
@@ -13,6 +13,8 @@
13struct usbmisc_ops { 13struct usbmisc_ops {
14 /* It's called once when probe a usb device */ 14 /* It's called once when probe a usb device */
15 int (*init)(struct device *dev); 15 int (*init)(struct device *dev);
16 /* It's called once after adding a usb device */
17 int (*post)(struct device *dev);
16}; 18};
17 19
18struct usbmisc_usb_device { 20struct usbmisc_usb_device {
@@ -20,6 +22,7 @@ struct usbmisc_usb_device {
20 int index; 22 int index;
21 23
22 unsigned int disable_oc:1; /* over current detect disabled */ 24 unsigned int disable_oc:1; /* over current detect disabled */
25 unsigned int evdo:1; /* set external vbus divider option */
23}; 26};
24 27
25int usbmisc_set_ops(const struct usbmisc_ops *ops); 28int usbmisc_set_ops(const struct usbmisc_ops *ops);
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index 746013d7d391..714a6bd810ed 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -14,11 +14,15 @@
14#include <linux/clk.h> 14#include <linux/clk.h>
15#include <linux/err.h> 15#include <linux/err.h>
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/delay.h>
17 18
18#include "ci13xxx_imx.h" 19#include "ci13xxx_imx.h"
19 20
20#define USB_DEV_MAX 4 21#define USB_DEV_MAX 4
21 22
23#define MX25_USB_PHY_CTRL_OFFSET 0x08
24#define MX25_BM_EXTERNAL_VBUS_DIVIDER BIT(23)
25
22#define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08 26#define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08
23#define MX53_USB_UH2_CTRL_OFFSET 0x14 27#define MX53_USB_UH2_CTRL_OFFSET 0x14
24#define MX53_USB_UH3_CTRL_OFFSET 0x18 28#define MX53_USB_UH3_CTRL_OFFSET 0x18
@@ -59,6 +63,30 @@ static struct usbmisc_usb_device *get_usbdev(struct device *dev)
59 return &usbmisc->usbdev[i]; 63 return &usbmisc->usbdev[i];
60} 64}
61 65
66static int usbmisc_imx25_post(struct device *dev)
67{
68 struct usbmisc_usb_device *usbdev;
69 void __iomem *reg;
70 unsigned long flags;
71 u32 val;
72
73 usbdev = get_usbdev(dev);
74 if (IS_ERR(usbdev))
75 return PTR_ERR(usbdev);
76
77 reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET;
78
79 if (usbdev->evdo) {
80 spin_lock_irqsave(&usbmisc->lock, flags);
81 val = readl(reg);
82 writel(val | MX25_BM_EXTERNAL_VBUS_DIVIDER, reg);
83 spin_unlock_irqrestore(&usbmisc->lock, flags);
84 usleep_range(5000, 10000); /* needed to stabilize voltage */
85 }
86
87 return 0;
88}
89
62static int usbmisc_imx53_init(struct device *dev) 90static int usbmisc_imx53_init(struct device *dev)
63{ 91{
64 struct usbmisc_usb_device *usbdev; 92 struct usbmisc_usb_device *usbdev;
@@ -120,6 +148,10 @@ static int usbmisc_imx6q_init(struct device *dev)
120 return 0; 148 return 0;
121} 149}
122 150
151static const struct usbmisc_ops imx25_usbmisc_ops = {
152 .post = usbmisc_imx25_post,
153};
154
123static const struct usbmisc_ops imx53_usbmisc_ops = { 155static const struct usbmisc_ops imx53_usbmisc_ops = {
124 .init = usbmisc_imx53_init, 156 .init = usbmisc_imx53_init,
125}; 157};
@@ -130,6 +162,10 @@ static const struct usbmisc_ops imx6q_usbmisc_ops = {
130 162
131static const struct of_device_id usbmisc_imx_dt_ids[] = { 163static const struct of_device_id usbmisc_imx_dt_ids[] = {
132 { 164 {
165 .compatible = "fsl,imx25-usbmisc",
166 .data = &imx25_usbmisc_ops,
167 },
168 {
133 .compatible = "fsl,imx53-usbmisc", 169 .compatible = "fsl,imx53-usbmisc",
134 .data = &imx53_usbmisc_ops, 170 .data = &imx53_usbmisc_ops,
135 }, 171 },