Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f636cec5 authored by Peter Chen's avatar Peter Chen Committed by Greg Kroah-Hartman
Browse files

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: default avatarPeter Chen <peter.chen@freescale.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 1f874edc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 */
+52 −0
Original line number Diff line number Diff line
@@ -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",