aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Chen <peter.chen@freescale.com>2015-02-10 23:44:46 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-03-18 11:19:09 -0400
commitf636cec559c6c01d6a262123446a142e1ae66890 (patch)
tree464ca8463152e13f0ce9101722bf40deec87916a
parent1f874edcb7318c5dd71025df9f3849715b4e4f71 (diff)
usb: chipidea: usbmisc_imx: add .set_wakeup interface
This API is used to enable/disable usb wakeup, only imx6 series are added, since I don't have other imx hardware on hand. Other imx users can add their API according to reference manual after testing. Signed-off-by: Peter Chen <peter.chen@freescale.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.h1
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c52
2 files changed, 53 insertions, 0 deletions
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h b/drivers/usb/chipidea/ci_hdrc_imx.h
index 4ed828f75a1e..635717e9354a 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.h
+++ b/drivers/usb/chipidea/ci_hdrc_imx.h
@@ -22,5 +22,6 @@ struct imx_usbmisc_data {
22 22
23int imx_usbmisc_init(struct imx_usbmisc_data *); 23int imx_usbmisc_init(struct imx_usbmisc_data *);
24int imx_usbmisc_init_post(struct imx_usbmisc_data *); 24int imx_usbmisc_init_post(struct imx_usbmisc_data *);
25int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *, bool);
25 26
26#endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */ 27#endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index eb77e3285c8a..90b7d7f3c81b 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -55,6 +55,10 @@
55#define MX53_USB_PLL_DIV_24_MHZ 0x01 55#define MX53_USB_PLL_DIV_24_MHZ 0x01
56 56
57#define MX6_BM_OVER_CUR_DIS BIT(7) 57#define MX6_BM_OVER_CUR_DIS BIT(7)
58#define MX6_BM_WAKEUP_ENABLE BIT(10)
59#define MX6_BM_ID_WAKEUP BIT(16)
60#define MX6_BM_VBUS_WAKEUP BIT(17)
61#define MX6_BM_WAKEUP_INTR BIT(31)
58 62
59#define VF610_OVER_CUR_DIS BIT(7) 63#define VF610_OVER_CUR_DIS BIT(7)
60 64
@@ -63,6 +67,8 @@ struct usbmisc_ops {
63 int (*init)(struct imx_usbmisc_data *data); 67 int (*init)(struct imx_usbmisc_data *data);
64 /* It's called once after adding a usb device */ 68 /* It's called once after adding a usb device */
65 int (*post)(struct imx_usbmisc_data *data); 69 int (*post)(struct imx_usbmisc_data *data);
70 /* It's called when we need to enable/disable usb wakeup */
71 int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled);
66}; 72};
67 73
68struct imx_usbmisc { 74struct imx_usbmisc {
@@ -202,6 +208,35 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
202 return 0; 208 return 0;
203} 209}
204 210
211static int usbmisc_imx6q_set_wakeup
212 (struct imx_usbmisc_data *data, bool enabled)
213{
214 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
215 unsigned long flags;
216 u32 val;
217 u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE |
218 MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP);
219 int ret = 0;
220
221 if (data->index > 3)
222 return -EINVAL;
223
224 spin_lock_irqsave(&usbmisc->lock, flags);
225 val = readl(usbmisc->base + data->index * 4);
226 if (enabled) {
227 val |= wakeup_setting;
228 writel(val, usbmisc->base + data->index * 4);
229 } else {
230 if (val & MX6_BM_WAKEUP_INTR)
231 pr_debug("wakeup int at ci_hdrc.%d\n", data->index);
232 val &= ~wakeup_setting;
233 writel(val, usbmisc->base + data->index * 4);
234 }
235 spin_unlock_irqrestore(&usbmisc->lock, flags);
236
237 return ret;
238}
239
205static int usbmisc_imx6q_init(struct imx_usbmisc_data *data) 240static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
206{ 241{
207 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 242 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
@@ -219,6 +254,8 @@ static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
219 spin_unlock_irqrestore(&usbmisc->lock, flags); 254 spin_unlock_irqrestore(&usbmisc->lock, flags);
220 } 255 }
221 256
257 usbmisc_imx6q_set_wakeup(data, false);
258
222 return 0; 259 return 0;
223} 260}
224 261
@@ -256,6 +293,7 @@ static const struct usbmisc_ops imx53_usbmisc_ops = {
256}; 293};
257 294
258static const struct usbmisc_ops imx6q_usbmisc_ops = { 295static const struct usbmisc_ops imx6q_usbmisc_ops = {
296 .set_wakeup = usbmisc_imx6q_set_wakeup,
259 .init = usbmisc_imx6q_init, 297 .init = usbmisc_imx6q_init,
260}; 298};
261 299
@@ -291,6 +329,20 @@ int imx_usbmisc_init_post(struct imx_usbmisc_data *data)
291} 329}
292EXPORT_SYMBOL_GPL(imx_usbmisc_init_post); 330EXPORT_SYMBOL_GPL(imx_usbmisc_init_post);
293 331
332int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled)
333{
334 struct imx_usbmisc *usbmisc;
335
336 if (!data)
337 return 0;
338
339 usbmisc = dev_get_drvdata(data->dev);
340 if (!usbmisc->ops->set_wakeup)
341 return 0;
342 return usbmisc->ops->set_wakeup(data, enabled);
343}
344EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup);
345
294static const struct of_device_id usbmisc_imx_dt_ids[] = { 346static const struct of_device_id usbmisc_imx_dt_ids[] = {
295 { 347 {
296 .compatible = "fsl,imx25-usbmisc", 348 .compatible = "fsl,imx25-usbmisc",