diff --git a/drivers/pinctrl/airoha/airoha-common.h b/drivers/pinctrl/airoha/airoha-common.h index c1acbfb7426e..16f7abcdfb83 100644 --- a/drivers/pinctrl/airoha/airoha-common.h +++ b/drivers/pinctrl/airoha/airoha-common.h @@ -127,6 +127,7 @@ struct airoha_pinctrl { struct gpio_chip gpiochip; struct airoha_gpiochip_regs *gpio_regs; + unsigned int num_irq_pins; }; struct airoha_pinctrl_match_data { @@ -140,6 +141,8 @@ struct airoha_pinctrl_match_data { const struct airoha_pinctrl_func *funcs; const unsigned int num_funcs; const struct airoha_pinctrl_confs_info confs_info[AIROHA_PINCTRL_CONFS_MAX]; + /* number of GPIOs wired to the interrupt controller */ + const unsigned int num_irq_pins; }; int airoha_pinctrl_probe(struct platform_device *pdev); diff --git a/drivers/pinctrl/airoha/pinctrl-airoha.c b/drivers/pinctrl/airoha/pinctrl-airoha.c index f505a3f69c5d..52a768c859b7 100644 --- a/drivers/pinctrl/airoha/pinctrl-airoha.c +++ b/drivers/pinctrl/airoha/pinctrl-airoha.c @@ -213,7 +213,7 @@ static void airoha_irq_unmask(struct irq_data *data) u32 mask = GENMASK(2 * offset + 1, 2 * offset); u32 val = BIT(2 * offset); - if (WARN_ON_ONCE(data->hwirq >= AIROHA_NUM_PINS)) + if (WARN_ON_ONCE(data->hwirq >= pinctrl->num_irq_pins)) return; gpiochip_enable_irq(gc, irqd_to_hwirq(data)); @@ -249,7 +249,7 @@ static void airoha_irq_mask(struct irq_data *data) u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_PIN; u32 mask = GENMASK(2 * offset + 1, 2 * offset); - if (data->hwirq >= AIROHA_NUM_PINS) + if (data->hwirq >= pinctrl->num_irq_pins) return; regmap_clear_bits(pinctrl->regmap, gpio_regs->level[index], mask); @@ -265,7 +265,7 @@ static void airoha_irq_ack(struct irq_data *data) u8 offset = data->hwirq % AIROHA_PIN_BANK_SIZE; u8 index = data->hwirq / AIROHA_PIN_BANK_SIZE; - if (data->hwirq >= AIROHA_NUM_PINS) + if (data->hwirq >= pinctrl->num_irq_pins) return; regmap_write(pinctrl->regmap, gpio_regs->status[index], BIT(offset)); @@ -273,7 +273,10 @@ static void airoha_irq_ack(struct irq_data *data) static int airoha_irq_type(struct irq_data *data, unsigned int type) { - if (data->hwirq >= AIROHA_NUM_PINS) + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct airoha_pinctrl *pinctrl = gpiochip_get_data(gc); + + if (data->hwirq >= pinctrl->num_irq_pins) return -EINVAL; if (type == IRQ_TYPE_NONE) { @@ -304,9 +307,11 @@ static irqreturn_t airoha_irq_handler(int irq, void *data) { struct airoha_pinctrl *pinctrl = data; bool handled = false; + unsigned int nbanks; int i; - for (i = 0; i < ARRAY_SIZE(irq_status_regs); i++) { + nbanks = DIV_ROUND_UP(pinctrl->num_irq_pins, AIROHA_PIN_BANK_SIZE); + for (i = 0; i < nbanks; i++) { struct gpio_irq_chip *girq = &pinctrl->gpiochip.irq; u32 regmap; unsigned long status; @@ -340,6 +345,22 @@ static const struct irq_chip airoha_gpio_irq_chip = { GPIOCHIP_IRQ_RESOURCE_HELPERS, }; +/* + * Mark the GPIOs that are not wired to the interrupt controller as not + * valid, so that gpiod_to_irq() fails for them with -ENXIO instead of + * handing out an interrupt that can never fire. + */ +static void airoha_gpio_init_valid_mask(struct gpio_chip *gc, + unsigned long *valid_mask, + unsigned int ngpios) +{ + struct airoha_pinctrl *pinctrl = gpiochip_get_data(gc); + unsigned int num_irq_pins = pinctrl->num_irq_pins; + + if (num_irq_pins < ngpios) + bitmap_clear(valid_mask, num_irq_pins, ngpios - num_irq_pins); +} + static int airoha_pinctrl_add_gpiochip(struct airoha_pinctrl *pinctrl, struct platform_device *pdev) { @@ -362,6 +383,7 @@ static int airoha_pinctrl_add_gpiochip(struct airoha_pinctrl *pinctrl, girq->default_type = IRQ_TYPE_NONE; girq->handler = handle_bad_irq; + girq->init_valid_mask = airoha_gpio_init_valid_mask; gpio_irq_chip_set_chip(girq, &airoha_gpio_irq_chip); irq = platform_get_irq(pdev, 0); @@ -848,6 +870,7 @@ int airoha_pinctrl_probe(struct platform_device *pdev) pinctrl->grps = data->grps; pinctrl->funcs = data->funcs; pinctrl->confs_info = data->confs_info; + pinctrl->num_irq_pins = data->num_irq_pins; err = pinctrl_enable(pinctrl->ctrl); if (err) diff --git a/drivers/pinctrl/airoha/pinctrl-an7563.c b/drivers/pinctrl/airoha/pinctrl-an7563.c index 40cbbe90cc46..f011c6c9ccce 100644 --- a/drivers/pinctrl/airoha/pinctrl-an7563.c +++ b/drivers/pinctrl/airoha/pinctrl-an7563.c @@ -1069,6 +1069,7 @@ static const struct airoha_pinctrl_match_data pinctrl_match_data = { .num_grps = ARRAY_SIZE(pinctrl_groups), .funcs = pinctrl_funcs, .num_funcs = ARRAY_SIZE(pinctrl_funcs), + .num_irq_pins = AIROHA_NUM_PINS, .confs_info = { [AIROHA_PINCTRL_CONFS_PULLUP] = { .confs = pinctrl_pullup_conf, diff --git a/drivers/pinctrl/airoha/pinctrl-an7581.c b/drivers/pinctrl/airoha/pinctrl-an7581.c index 2fcf88106e11..bfb777594811 100644 --- a/drivers/pinctrl/airoha/pinctrl-an7581.c +++ b/drivers/pinctrl/airoha/pinctrl-an7581.c @@ -1441,6 +1441,7 @@ static const struct airoha_pinctrl_match_data pinctrl_match_data = { .num_grps = ARRAY_SIZE(pinctrl_groups), .funcs = pinctrl_funcs, .num_funcs = ARRAY_SIZE(pinctrl_funcs), + .num_irq_pins = AIROHA_NUM_PINS, .confs_info = { [AIROHA_PINCTRL_CONFS_PULLUP] = { .confs = pinctrl_pullup_conf, diff --git a/drivers/pinctrl/airoha/pinctrl-an7583.c b/drivers/pinctrl/airoha/pinctrl-an7583.c index 2c3a75c35915..1cd0f442ddc1 100644 --- a/drivers/pinctrl/airoha/pinctrl-an7583.c +++ b/drivers/pinctrl/airoha/pinctrl-an7583.c @@ -1471,6 +1471,7 @@ static const struct airoha_pinctrl_match_data pinctrl_match_data = { .num_grps = ARRAY_SIZE(pinctrl_groups), .funcs = pinctrl_funcs, .num_funcs = ARRAY_SIZE(pinctrl_funcs), + .num_irq_pins = AIROHA_NUM_PINS, .confs_info = { [AIROHA_PINCTRL_CONFS_PULLUP] = { .confs = pinctrl_pullup_conf, diff --git a/drivers/pinctrl/airoha/pinctrl-en7523.c b/drivers/pinctrl/airoha/pinctrl-en7523.c index 5aa39bacf460..b0c5e60f0aeb 100644 --- a/drivers/pinctrl/airoha/pinctrl-en7523.c +++ b/drivers/pinctrl/airoha/pinctrl-en7523.c @@ -1113,6 +1113,7 @@ static const struct airoha_pinctrl_match_data pinctrl_match_data = { .num_grps = ARRAY_SIZE(pinctrl_groups), .funcs = pinctrl_funcs, .num_funcs = ARRAY_SIZE(pinctrl_funcs), + .num_irq_pins = AIROHA_NUM_PINS, .confs_info = { [AIROHA_PINCTRL_CONFS_PULLUP] = { .confs = pinctrl_pullup_conf,