From f636cec559c6c01d6a262123446a142e1ae66890 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Wed, 11 Feb 2015 12:44:46 +0800 Subject: [PATCH] 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 Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/ci_hdrc_imx.h | 1 + drivers/usb/chipidea/usbmisc_imx.c | 52 ++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) 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 { int imx_usbmisc_init(struct imx_usbmisc_data *); int imx_usbmisc_init_post(struct imx_usbmisc_data *); +int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *, bool); #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 @@ #define MX53_USB_PLL_DIV_24_MHZ 0x01 #define MX6_BM_OVER_CUR_DIS BIT(7) +#define MX6_BM_WAKEUP_ENABLE BIT(10) +#define MX6_BM_ID_WAKEUP BIT(16) +#define MX6_BM_VBUS_WAKEUP BIT(17) +#define MX6_BM_WAKEUP_INTR BIT(31) #define VF610_OVER_CUR_DIS BIT(7) @@ -63,6 +67,8 @@ struct usbmisc_ops { int (*init)(struct imx_usbmisc_data *data); /* It's called once after adding a usb device */ int (*post)(struct imx_usbmisc_data *data); + /* It's called when we need to enable/disable usb wakeup */ + int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled); }; struct imx_usbmisc { @@ -202,6 +208,35 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data *data) return 0; } +static int usbmisc_imx6q_set_wakeup + (struct imx_usbmisc_data *data, bool enabled) +{ + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); + unsigned long flags; + u32 val; + u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE | + MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP); + int ret = 0; + + if (data->index > 3) + return -EINVAL; + + spin_lock_irqsave(&usbmisc->lock, flags); + val = readl(usbmisc->base + data->index * 4); + if (enabled) { + val |= wakeup_setting; + writel(val, usbmisc->base + data->index * 4); + } else { + if (val & MX6_BM_WAKEUP_INTR) + pr_debug("wakeup int at ci_hdrc.%d\n", data->index); + val &= ~wakeup_setting; + writel(val, usbmisc->base + data->index * 4); + } + spin_unlock_irqrestore(&usbmisc->lock, flags); + + return ret; +} + static int usbmisc_imx6q_init(struct imx_usbmisc_data *data) { struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); @@ -219,6 +254,8 @@ static int usbmisc_imx6q_init(struct imx_usbmisc_data *data) spin_unlock_irqrestore(&usbmisc->lock, flags); } + usbmisc_imx6q_set_wakeup(data, false); + return 0; } @@ -256,6 +293,7 @@ static const struct usbmisc_ops imx53_usbmisc_ops = { }; static const struct usbmisc_ops imx6q_usbmisc_ops = { + .set_wakeup = usbmisc_imx6q_set_wakeup, .init = usbmisc_imx6q_init, }; @@ -291,6 +329,20 @@ int imx_usbmisc_init_post(struct imx_usbmisc_data *data) } EXPORT_SYMBOL_GPL(imx_usbmisc_init_post); +int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled) +{ + struct imx_usbmisc *usbmisc; + + if (!data) + return 0; + + usbmisc = dev_get_drvdata(data->dev); + if (!usbmisc->ops->set_wakeup) + return 0; + return usbmisc->ops->set_wakeup(data, enabled); +} +EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup); + static const struct of_device_id usbmisc_imx_dt_ids[] = { { .compatible = "fsl,imx25-usbmisc",