mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2026-01-27 12:35:36 +01:00
LF-10575-3 usb: chipidea: imx: add HSIO blkctl wakup handling
There are two sets (HSIO blkctl and USB non-core) of wakeup setting when HSIO blkctl exists. To support wakup when HSIO domain power is lost, HSIO blkctl wakup handling is a must. This will add the wakup handling for HSIO blkctl cases. Signed-off-by: Xu Yang <xu.yang_2@nxp.com> Reviewed-by: Jun Li <jun.li@nxp.com>
This commit is contained in:
parent
2be33a6a8e
commit
98af898785
|
|
@ -139,6 +139,21 @@
|
|||
#define MX6_USB_OTG_WAKEUP_BITS (MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP | \
|
||||
MX6_BM_ID_WAKEUP | MX6SX_BM_DPDM_WAKEUP_EN)
|
||||
|
||||
/*
|
||||
* HSIO Block Control Register
|
||||
*/
|
||||
|
||||
#define BLKCTL_USB_WAKEUP_CTRL 0x0
|
||||
#define BLKCTL_OTG_WAKE_ENABLE BIT(31)
|
||||
#define BLKCTL_OTG_ID_WAKEUP_EN BIT(2)
|
||||
#define BLKCTL_OTG_VBUS_WAKEUP_EN BIT(1)
|
||||
#define BLKCTL_OTG_DPDM_WAKEUP_EN BIT(0)
|
||||
|
||||
#define BLKCTL_WAKEUP_SOURCE (BLKCTL_OTG_WAKE_ENABLE | \
|
||||
BLKCTL_OTG_ID_WAKEUP_EN | \
|
||||
BLKCTL_OTG_VBUS_WAKEUP_EN | \
|
||||
BLKCTL_OTG_DPDM_WAKEUP_EN)
|
||||
|
||||
struct usbmisc_ops {
|
||||
/* It's called once when probe a usb device */
|
||||
int (*init)(struct imx_usbmisc_data *data);
|
||||
|
|
@ -159,6 +174,7 @@ struct usbmisc_ops {
|
|||
|
||||
struct imx_usbmisc {
|
||||
void __iomem *base;
|
||||
void __iomem *blkctl;
|
||||
spinlock_t lock;
|
||||
const struct usbmisc_ops *ops;
|
||||
};
|
||||
|
|
@ -1016,6 +1032,76 @@ static int usbmisc_imx6sx_power_lost_check(struct imx_usbmisc_data *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u32 usbmisc_blkctl_wakeup_setting(struct imx_usbmisc_data *data)
|
||||
{
|
||||
u32 wakeup_setting = BLKCTL_WAKEUP_SOURCE;
|
||||
|
||||
if (data->ext_id || data->available_role != USB_DR_MODE_OTG)
|
||||
wakeup_setting &= ~BLKCTL_OTG_ID_WAKEUP_EN;
|
||||
|
||||
if (data->ext_vbus || data->available_role == USB_DR_MODE_HOST)
|
||||
wakeup_setting &= ~BLKCTL_OTG_VBUS_WAKEUP_EN;
|
||||
|
||||
|
||||
return wakeup_setting;
|
||||
}
|
||||
|
||||
static int usbmisc_imx95_set_wakeup(struct imx_usbmisc_data *data, bool enabled)
|
||||
{
|
||||
struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&usbmisc->lock, flags);
|
||||
val = readl(usbmisc->blkctl + BLKCTL_USB_WAKEUP_CTRL);
|
||||
val &= ~BLKCTL_WAKEUP_SOURCE;
|
||||
|
||||
if (enabled)
|
||||
val |= usbmisc_blkctl_wakeup_setting(data);
|
||||
|
||||
writel(val, usbmisc->blkctl + BLKCTL_USB_WAKEUP_CTRL);
|
||||
spin_unlock_irqrestore(&usbmisc->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbmisc_imx95_init(struct imx_usbmisc_data *data)
|
||||
{
|
||||
struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
if (data->index >= 1)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&usbmisc->lock, flags);
|
||||
reg = readl(usbmisc->base);
|
||||
if (data->disable_oc) {
|
||||
reg |= MX6_BM_OVER_CUR_DIS;
|
||||
} else {
|
||||
reg &= ~MX6_BM_OVER_CUR_DIS;
|
||||
|
||||
/*
|
||||
* If the polarity is not configured keep it as setup by the
|
||||
* bootloader.
|
||||
*/
|
||||
if (data->oc_pol_configured && data->oc_pol_active_low)
|
||||
reg |= MX6_BM_OVER_CUR_POLARITY;
|
||||
else if (data->oc_pol_configured)
|
||||
reg &= ~MX6_BM_OVER_CUR_POLARITY;
|
||||
}
|
||||
/* If the polarity is not set keep it as setup by the bootlader */
|
||||
if (data->pwr_pol == 1)
|
||||
reg |= MX6_BM_PWR_POLARITY;
|
||||
writel(reg, usbmisc->base);
|
||||
spin_unlock_irqrestore(&usbmisc->lock, flags);
|
||||
|
||||
/* Will use HSIO blkctl wakeup as source, so disable usbmisc wakeup */
|
||||
usbmisc_imx7d_set_wakeup(data, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct usbmisc_ops imx25_usbmisc_ops = {
|
||||
.init = usbmisc_imx25_init,
|
||||
.post = usbmisc_imx25_post,
|
||||
|
|
@ -1068,6 +1154,14 @@ static const struct usbmisc_ops imx7ulp_usbmisc_ops = {
|
|||
.power_lost_check = usbmisc_imx7d_power_lost_check,
|
||||
};
|
||||
|
||||
static const struct usbmisc_ops imx95_usbmisc_ops = {
|
||||
.init = usbmisc_imx95_init,
|
||||
.set_wakeup = usbmisc_imx95_set_wakeup,
|
||||
.charger_detection = imx7d_charger_detection,
|
||||
.power_lost_check = usbmisc_imx7d_power_lost_check,
|
||||
.vbus_comparator_on = usbmisc_imx7d_vbus_comparator_on,
|
||||
};
|
||||
|
||||
static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data)
|
||||
{
|
||||
struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
|
||||
|
|
@ -1285,6 +1379,10 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = {
|
|||
.compatible = "fsl,imx7ulp-usbmisc",
|
||||
.data = &imx7ulp_usbmisc_ops,
|
||||
},
|
||||
{
|
||||
.compatible = "fsl,imx95-usbmisc",
|
||||
.data = &imx95_usbmisc_ops,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
|
||||
|
|
@ -1303,6 +1401,12 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(data->base))
|
||||
return PTR_ERR(data->base);
|
||||
|
||||
if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx95-usbmisc")) {
|
||||
data->blkctl = devm_platform_ioremap_resource(pdev, 1);
|
||||
if (IS_ERR(data->blkctl))
|
||||
return PTR_ERR(data->blkctl);
|
||||
}
|
||||
|
||||
data->ops = of_device_get_match_data(&pdev->dev);
|
||||
platform_set_drvdata(pdev, data);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user