pinctrl: samsung: Correct setting of eint wakeup mask on s5pv210
Commita8be2af021
("pinctrl: samsung: Write external wakeup interrupt mask") started writing the eint wakeup mask from the pinctrl driver. Unfortunately, it made the assumption that the private retention data was always a regmap while in the case of s5pv210 it is a raw pointer to the clock base (as the eint wakeup mask not in the PMU as with newer Exynos platforms). Fixes:a8be2af021
("pinctrl: samsung: Write external wakeup interrupt mask") Cc: <stable@vger.kernel.org> Signed-off-by: Jonathan Bakker <xc-racer2@live.ca> Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
This commit is contained in:
parent
8f3d9f3542
commit
b577a27991
|
@ -40,6 +40,8 @@ struct exynos_irq_chip {
|
|||
u32 eint_pend;
|
||||
u32 eint_wake_mask_value;
|
||||
u32 eint_wake_mask_reg;
|
||||
void (*set_eint_wakeup_mask)(struct samsung_pinctrl_drv_data *drvdata,
|
||||
struct exynos_irq_chip *irq_chip);
|
||||
};
|
||||
|
||||
static inline struct exynos_irq_chip *to_exynos_irq_chip(struct irq_chip *chip)
|
||||
|
@ -342,6 +344,47 @@ static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
exynos_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
|
||||
struct exynos_irq_chip *irq_chip)
|
||||
{
|
||||
struct regmap *pmu_regs;
|
||||
|
||||
if (!drvdata->retention_ctrl || !drvdata->retention_ctrl->priv) {
|
||||
dev_warn(drvdata->dev,
|
||||
"No retention data configured bank with external wakeup interrupt. Wake-up mask will not be set.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pmu_regs = drvdata->retention_ctrl->priv;
|
||||
dev_info(drvdata->dev,
|
||||
"Setting external wakeup interrupt mask: 0x%x\n",
|
||||
irq_chip->eint_wake_mask_value);
|
||||
|
||||
regmap_write(pmu_regs, irq_chip->eint_wake_mask_reg,
|
||||
irq_chip->eint_wake_mask_value);
|
||||
}
|
||||
|
||||
static void
|
||||
s5pv210_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
|
||||
struct exynos_irq_chip *irq_chip)
|
||||
|
||||
{
|
||||
void __iomem *clk_base;
|
||||
|
||||
if (!drvdata->retention_ctrl || !drvdata->retention_ctrl->priv) {
|
||||
dev_warn(drvdata->dev,
|
||||
"No retention data configured bank with external wakeup interrupt. Wake-up mask will not be set.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
clk_base = (void __iomem *) drvdata->retention_ctrl->priv;
|
||||
|
||||
__raw_writel(irq_chip->eint_wake_mask_value,
|
||||
clk_base + irq_chip->eint_wake_mask_reg);
|
||||
}
|
||||
|
||||
/*
|
||||
* irq_chip for wakeup interrupts
|
||||
*/
|
||||
|
@ -360,8 +403,9 @@ static const struct exynos_irq_chip s5pv210_wkup_irq_chip __initconst = {
|
|||
.eint_mask = EXYNOS_WKUP_EMASK_OFFSET,
|
||||
.eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
|
||||
.eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED,
|
||||
/* Only difference with exynos4210_wkup_irq_chip: */
|
||||
/* Only differences with exynos4210_wkup_irq_chip: */
|
||||
.eint_wake_mask_reg = S5PV210_EINT_WAKEUP_MASK,
|
||||
.set_eint_wakeup_mask = s5pv210_pinctrl_set_eint_wakeup_mask,
|
||||
};
|
||||
|
||||
static const struct exynos_irq_chip exynos4210_wkup_irq_chip __initconst = {
|
||||
|
@ -380,6 +424,7 @@ static const struct exynos_irq_chip exynos4210_wkup_irq_chip __initconst = {
|
|||
.eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
|
||||
.eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED,
|
||||
.eint_wake_mask_reg = EXYNOS_EINT_WAKEUP_MASK,
|
||||
.set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask,
|
||||
};
|
||||
|
||||
static const struct exynos_irq_chip exynos7_wkup_irq_chip __initconst = {
|
||||
|
@ -398,6 +443,7 @@ static const struct exynos_irq_chip exynos7_wkup_irq_chip __initconst = {
|
|||
.eint_pend = EXYNOS7_WKUP_EPEND_OFFSET,
|
||||
.eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED,
|
||||
.eint_wake_mask_reg = EXYNOS5433_EINT_WAKEUP_MASK,
|
||||
.set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask,
|
||||
};
|
||||
|
||||
/* list of external wakeup controllers supported */
|
||||
|
@ -574,27 +620,6 @@ int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
exynos_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
|
||||
struct exynos_irq_chip *irq_chip)
|
||||
{
|
||||
struct regmap *pmu_regs;
|
||||
|
||||
if (!drvdata->retention_ctrl || !drvdata->retention_ctrl->priv) {
|
||||
dev_warn(drvdata->dev,
|
||||
"No retention data configured bank with external wakeup interrupt. Wake-up mask will not be set.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pmu_regs = drvdata->retention_ctrl->priv;
|
||||
dev_info(drvdata->dev,
|
||||
"Setting external wakeup interrupt mask: 0x%x\n",
|
||||
irq_chip->eint_wake_mask_value);
|
||||
|
||||
regmap_write(pmu_regs, irq_chip->eint_wake_mask_reg,
|
||||
irq_chip->eint_wake_mask_value);
|
||||
}
|
||||
|
||||
static void exynos_pinctrl_suspend_bank(
|
||||
struct samsung_pinctrl_drv_data *drvdata,
|
||||
struct samsung_pin_bank *bank)
|
||||
|
@ -626,8 +651,8 @@ void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
|
|||
else if (bank->eint_type == EINT_TYPE_WKUP) {
|
||||
if (!irq_chip) {
|
||||
irq_chip = bank->irq_chip;
|
||||
exynos_pinctrl_set_eint_wakeup_mask(drvdata,
|
||||
irq_chip);
|
||||
irq_chip->set_eint_wakeup_mask(drvdata,
|
||||
irq_chip);
|
||||
} else if (bank->irq_chip != irq_chip) {
|
||||
dev_warn(drvdata->dev,
|
||||
"More than one external wakeup interrupt chip configured (bank: %s). This is not supported by hardware nor by driver.\n",
|
||||
|
|
Loading…
Reference in New Issue