forked from Minki/linux
pinctrl: samsung: Use bank name as irqchip name
Use the bank name as the irqchip name. This name is later visible in /proc/interrupts, what makes it possible to easily identify each GPIO interrupt. /proc/interrupts before this patch: 143: 0 exynos4210_wkup_irq_chip 7 Edge hdmi 144: 0 exynos4210_wkup_irq_chip 6 Level wm8994 145: 1 exynos4210_wkup_irq_chip 7 Edge max77686-pmic, max77686-rtc 146: 1 exynos_gpio_irq_chip 3 Edge 3-0048 /proc/interrupts after this patch: 143: 0 gpx3 7 Edge hdmi 144: 0 gpx3 6 Level wm8994 145: 1 gpx0 7 Edge max77686-pmic, max77686-rtc 146: 1 gpm2 3 Edge 3-0048 Handling of the eint_wake_mask_value has been reworked, because each bank has now its own exynos_irq_chip structure allocated. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org> Link: https://lore.kernel.org/r/20200720145412.24221-1-krzk@kernel.org Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
f1b206cf7c
commit
85745c870a
@ -38,7 +38,7 @@ struct exynos_irq_chip {
|
||||
u32 eint_con;
|
||||
u32 eint_mask;
|
||||
u32 eint_pend;
|
||||
u32 eint_wake_mask_value;
|
||||
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);
|
||||
@ -207,7 +207,7 @@ static void exynos_irq_release_resources(struct irq_data *irqd)
|
||||
/*
|
||||
* irq_chip for gpio interrupts.
|
||||
*/
|
||||
static struct exynos_irq_chip exynos_gpio_irq_chip = {
|
||||
static const struct exynos_irq_chip exynos_gpio_irq_chip __initconst = {
|
||||
.chip = {
|
||||
.name = "exynos_gpio_irq_chip",
|
||||
.irq_unmask = exynos_irq_unmask,
|
||||
@ -274,7 +274,7 @@ struct exynos_eint_gpio_save {
|
||||
* exynos_eint_gpio_init() - setup handling of external gpio interrupts.
|
||||
* @d: driver data of samsung pinctrl driver.
|
||||
*/
|
||||
int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
|
||||
__init int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
|
||||
{
|
||||
struct samsung_pin_bank *bank;
|
||||
struct device *dev = d->dev;
|
||||
@ -297,6 +297,15 @@ int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
|
||||
for (i = 0; i < d->nr_banks; ++i, ++bank) {
|
||||
if (bank->eint_type != EINT_TYPE_GPIO)
|
||||
continue;
|
||||
|
||||
bank->irq_chip = devm_kmemdup(dev, &exynos_gpio_irq_chip,
|
||||
sizeof(*bank->irq_chip), GFP_KERNEL);
|
||||
if (!bank->irq_chip) {
|
||||
ret = -ENOMEM;
|
||||
goto err_domains;
|
||||
}
|
||||
bank->irq_chip->chip.name = bank->name;
|
||||
|
||||
bank->irq_domain = irq_domain_add_linear(bank->of_node,
|
||||
bank->nr_pins, &exynos_eint_irqd_ops, bank);
|
||||
if (!bank->irq_domain) {
|
||||
@ -313,7 +322,6 @@ int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
|
||||
goto err_domains;
|
||||
}
|
||||
|
||||
bank->irq_chip = &exynos_gpio_irq_chip;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -338,9 +346,9 @@ static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on)
|
||||
pr_info("wake %s for irq %d\n", on ? "enabled" : "disabled", irqd->irq);
|
||||
|
||||
if (!on)
|
||||
our_chip->eint_wake_mask_value |= bit;
|
||||
*our_chip->eint_wake_mask_value |= bit;
|
||||
else
|
||||
our_chip->eint_wake_mask_value &= ~bit;
|
||||
*our_chip->eint_wake_mask_value &= ~bit;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -360,10 +368,10 @@ exynos_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
|
||||
pmu_regs = drvdata->retention_ctrl->priv;
|
||||
dev_info(drvdata->dev,
|
||||
"Setting external wakeup interrupt mask: 0x%x\n",
|
||||
irq_chip->eint_wake_mask_value);
|
||||
*irq_chip->eint_wake_mask_value);
|
||||
|
||||
regmap_write(pmu_regs, irq_chip->eint_wake_mask_reg,
|
||||
irq_chip->eint_wake_mask_value);
|
||||
*irq_chip->eint_wake_mask_value);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -382,10 +390,11 @@ s5pv210_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
|
||||
|
||||
clk_base = (void __iomem *) drvdata->retention_ctrl->priv;
|
||||
|
||||
__raw_writel(irq_chip->eint_wake_mask_value,
|
||||
__raw_writel(*irq_chip->eint_wake_mask_value,
|
||||
clk_base + irq_chip->eint_wake_mask_reg);
|
||||
}
|
||||
|
||||
static u32 eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED;
|
||||
/*
|
||||
* irq_chip for wakeup interrupts
|
||||
*/
|
||||
@ -403,7 +412,7 @@ static const struct exynos_irq_chip s5pv210_wkup_irq_chip __initconst = {
|
||||
.eint_con = EXYNOS_WKUP_ECON_OFFSET,
|
||||
.eint_mask = EXYNOS_WKUP_EMASK_OFFSET,
|
||||
.eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
|
||||
.eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED,
|
||||
.eint_wake_mask_value = &eint_wake_mask_value,
|
||||
/* 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,
|
||||
@ -423,7 +432,7 @@ static const struct exynos_irq_chip exynos4210_wkup_irq_chip __initconst = {
|
||||
.eint_con = EXYNOS_WKUP_ECON_OFFSET,
|
||||
.eint_mask = EXYNOS_WKUP_EMASK_OFFSET,
|
||||
.eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
|
||||
.eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED,
|
||||
.eint_wake_mask_value = &eint_wake_mask_value,
|
||||
.eint_wake_mask_reg = EXYNOS_EINT_WAKEUP_MASK,
|
||||
.set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask,
|
||||
};
|
||||
@ -442,7 +451,7 @@ static const struct exynos_irq_chip exynos7_wkup_irq_chip __initconst = {
|
||||
.eint_con = EXYNOS7_WKUP_ECON_OFFSET,
|
||||
.eint_mask = EXYNOS7_WKUP_EMASK_OFFSET,
|
||||
.eint_pend = EXYNOS7_WKUP_EPEND_OFFSET,
|
||||
.eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED,
|
||||
.eint_wake_mask_value = &eint_wake_mask_value,
|
||||
.eint_wake_mask_reg = EXYNOS5433_EINT_WAKEUP_MASK,
|
||||
.set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask,
|
||||
};
|
||||
@ -513,7 +522,7 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc)
|
||||
* exynos_eint_wkup_init() - setup handling of external wakeup interrupts.
|
||||
* @d: driver data of samsung pinctrl driver.
|
||||
*/
|
||||
int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
|
||||
__init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
|
||||
{
|
||||
struct device *dev = d->dev;
|
||||
struct device_node *wkup_np = NULL;
|
||||
@ -521,7 +530,7 @@ int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
|
||||
struct samsung_pin_bank *bank;
|
||||
struct exynos_weint_data *weint_data;
|
||||
struct exynos_muxed_weint_data *muxed_data;
|
||||
struct exynos_irq_chip *irq_chip;
|
||||
const struct exynos_irq_chip *irq_chip;
|
||||
unsigned int muxed_banks = 0;
|
||||
unsigned int i;
|
||||
int idx, irq;
|
||||
@ -531,12 +540,7 @@ int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
|
||||
|
||||
match = of_match_node(exynos_wkup_irq_ids, np);
|
||||
if (match) {
|
||||
irq_chip = kmemdup(match->data,
|
||||
sizeof(*irq_chip), GFP_KERNEL);
|
||||
if (!irq_chip) {
|
||||
of_node_put(np);
|
||||
return -ENOMEM;
|
||||
}
|
||||
irq_chip = match->data;
|
||||
wkup_np = np;
|
||||
break;
|
||||
}
|
||||
@ -549,6 +553,14 @@ int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
|
||||
if (bank->eint_type != EINT_TYPE_WKUP)
|
||||
continue;
|
||||
|
||||
bank->irq_chip = devm_kmemdup(dev, irq_chip, sizeof(*irq_chip),
|
||||
GFP_KERNEL);
|
||||
if (!bank->irq_chip) {
|
||||
of_node_put(wkup_np);
|
||||
return -ENOMEM;
|
||||
}
|
||||
bank->irq_chip->chip.name = bank->name;
|
||||
|
||||
bank->irq_domain = irq_domain_add_linear(bank->of_node,
|
||||
bank->nr_pins, &exynos_eint_irqd_ops, bank);
|
||||
if (!bank->irq_domain) {
|
||||
@ -557,8 +569,6 @@ int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
bank->irq_chip = irq_chip;
|
||||
|
||||
if (!of_find_property(bank->of_node, "interrupts", NULL)) {
|
||||
bank->eint_type = EINT_TYPE_WKUP_MUX;
|
||||
++muxed_banks;
|
||||
@ -657,10 +667,6 @@ void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
|
||||
irq_chip = bank->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",
|
||||
bank->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user