diff options
Diffstat (limited to 'drivers/pinctrl/intel')
-rw-r--r-- | drivers/pinctrl/intel/pinctrl-cherryview.c | 60 | ||||
-rw-r--r-- | drivers/pinctrl/intel/pinctrl-intel.c | 33 | ||||
-rw-r--r-- | drivers/pinctrl/intel/pinctrl-merrifield.c | 2 |
3 files changed, 44 insertions, 51 deletions
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 5749a4eee746..30389f4ccab4 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -134,6 +134,7 @@ struct chv_gpio_pinrange { * @gpio_ranges: An array of GPIO ranges in this community * @ngpio_ranges: Number of GPIO ranges * @ngpios: Total number of GPIOs in this community + * @nirqs: Total number of IRQs this community can generate */ struct chv_community { const char *uid; @@ -146,6 +147,7 @@ struct chv_community { const struct chv_gpio_pinrange *gpio_ranges; size_t ngpio_ranges; size_t ngpios; + size_t nirqs; }; struct chv_pin_context { @@ -396,6 +398,12 @@ static const struct chv_community southwest_community = { .gpio_ranges = southwest_gpio_ranges, .ngpio_ranges = ARRAY_SIZE(southwest_gpio_ranges), .ngpios = ARRAY_SIZE(southwest_pins), + /* + * Southwest community can benerate GPIO interrupts only for the + * first 8 interrupts. The upper half (8-15) can only be used to + * trigger GPEs. + */ + .nirqs = 8, }; static const struct pinctrl_pin_desc north_pins[] = { @@ -479,6 +487,12 @@ static const struct chv_community north_community = { .gpio_ranges = north_gpio_ranges, .ngpio_ranges = ARRAY_SIZE(north_gpio_ranges), .ngpios = ARRAY_SIZE(north_pins), + /* + * North community can benerate GPIO interrupts only for the first + * 8 interrupts. The upper half (8-15) can only be used to trigger + * GPEs. + */ + .nirqs = 8, }; static const struct pinctrl_pin_desc east_pins[] = { @@ -521,6 +535,7 @@ static const struct chv_community east_community = { .gpio_ranges = east_gpio_ranges, .ngpio_ranges = ARRAY_SIZE(east_gpio_ranges), .ngpios = ARRAY_SIZE(east_pins), + .nirqs = 16, }; static const struct pinctrl_pin_desc southeast_pins[] = { @@ -646,6 +661,7 @@ static const struct chv_community southeast_community = { .gpio_ranges = southeast_gpio_ranges, .ngpio_ranges = ARRAY_SIZE(southeast_gpio_ranges), .ngpios = ARRAY_SIZE(southeast_pins), + .nirqs = 16, }; static const struct chv_community *chv_communities[] = { @@ -1497,7 +1513,7 @@ static void chv_gpio_irq_handler(struct irq_desc *desc) chained_irq_enter(chip, desc); pending = readl(pctrl->regs + CHV_INTSTAT); - for_each_set_bit(intr_line, &pending, 16) { + for_each_set_bit(intr_line, &pending, pctrl->community->nirqs) { unsigned irq, offset; offset = pctrl->intr_lines[intr_line]; @@ -1520,8 +1536,9 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq) chip->label = dev_name(pctrl->dev); chip->parent = pctrl->dev; chip->base = -1; + chip->irq_need_valid_mask = true; - ret = gpiochip_add_data(chip, pctrl); + ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl); if (ret) { dev_err(pctrl->dev, "Failed to register gpiochip\n"); return ret; @@ -1533,31 +1550,40 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq) range->base, range->npins); if (ret) { dev_err(pctrl->dev, "failed to add GPIO pin range\n"); - goto fail; + return ret; } offset += range->npins; } - /* Mask and clear all interrupts */ - chv_writel(0, pctrl->regs + CHV_INTMASK); + /* Do not add GPIOs that can only generate GPEs to the IRQ domain */ + for (i = 0; i < pctrl->community->npins; i++) { + const struct pinctrl_pin_desc *desc; + u32 intsel; + + desc = &pctrl->community->pins[i]; + + intsel = readl(chv_padreg(pctrl, desc->number, CHV_PADCTRL0)); + intsel &= CHV_PADCTRL0_INTSEL_MASK; + intsel >>= CHV_PADCTRL0_INTSEL_SHIFT; + + if (intsel >= pctrl->community->nirqs) + clear_bit(i, chip->irq_valid_mask); + } + + /* Clear all interrupts */ chv_writel(0xffff, pctrl->regs + CHV_INTSTAT); ret = gpiochip_irqchip_add(chip, &chv_gpio_irqchip, 0, - handle_simple_irq, IRQ_TYPE_NONE); + handle_bad_irq, IRQ_TYPE_NONE); if (ret) { dev_err(pctrl->dev, "failed to add IRQ chip\n"); - goto fail; + return ret; } gpiochip_set_chained_irqchip(chip, &chv_gpio_irqchip, irq, chv_gpio_irq_handler); return 0; - -fail: - gpiochip_remove(chip); - - return ret; } static int chv_pinctrl_probe(struct platform_device *pdev) @@ -1625,15 +1651,6 @@ static int chv_pinctrl_probe(struct platform_device *pdev) return 0; } -static int chv_pinctrl_remove(struct platform_device *pdev) -{ - struct chv_pinctrl *pctrl = platform_get_drvdata(pdev); - - gpiochip_remove(&pctrl->chip); - - return 0; -} - #ifdef CONFIG_PM_SLEEP static int chv_pinctrl_suspend(struct device *dev) { @@ -1730,7 +1747,6 @@ MODULE_DEVICE_TABLE(acpi, chv_pinctrl_acpi_match); static struct platform_driver chv_pinctrl_driver = { .probe = chv_pinctrl_probe, - .remove = chv_pinctrl_remove, .driver = { .name = "cherryview-pinctrl", .pm = &chv_pinctrl_pm_ops, diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 257cab129692..63387a40b973 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -86,6 +86,7 @@ struct intel_pinctrl_context { * @communities: All communities in this pin controller * @ncommunities: Number of communities in this pin controller * @context: Configuration saved over system sleep + * @irq: pinctrl/GPIO chip irq number */ struct intel_pinctrl { struct device *dev; @@ -97,6 +98,7 @@ struct intel_pinctrl { struct intel_community *communities; size_t ncommunities; struct intel_pinctrl_context context; + int irq; }; #define pin_to_padno(c, p) ((p) - (c)->pin_base) @@ -793,38 +795,12 @@ static int intel_gpio_irq_wake(struct irq_data *d, unsigned int on) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct intel_pinctrl *pctrl = gpiochip_get_data(gc); - const struct intel_community *community; unsigned pin = irqd_to_hwirq(d); - unsigned padno, gpp, gpp_offset; - unsigned long flags; - u32 gpe_en; - - community = intel_get_community(pctrl, pin); - if (!community) - return -EINVAL; - - raw_spin_lock_irqsave(&pctrl->lock, flags); - padno = pin_to_padno(community, pin); - gpp = padno / community->gpp_size; - gpp_offset = padno % community->gpp_size; - - /* Clear the existing wake status */ - writel(BIT(gpp_offset), community->regs + GPI_GPE_STS + gpp * 4); - - /* - * The controller will generate wake when GPE of the corresponding - * pad is enabled and it is not routed to SCI (GPIROUTSCI is not - * set). - */ - gpe_en = readl(community->regs + GPI_GPE_EN + gpp * 4); if (on) - gpe_en |= BIT(gpp_offset); + enable_irq_wake(pctrl->irq); else - gpe_en &= ~BIT(gpp_offset); - writel(gpe_en, community->regs + GPI_GPE_EN + gpp * 4); - - raw_spin_unlock_irqrestore(&pctrl->lock, flags); + disable_irq_wake(pctrl->irq); dev_dbg(pctrl->dev, "%sable wake for pin %u\n", on ? "en" : "dis", pin); return 0; @@ -905,6 +881,7 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq) pctrl->chip.label = dev_name(pctrl->dev); pctrl->chip.parent = pctrl->dev; pctrl->chip.base = -1; + pctrl->irq = irq; ret = gpiochip_add_data(&pctrl->chip, pctrl); if (ret) { diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c index 7fb765642ee7..7826c7f0cb7c 100644 --- a/drivers/pinctrl/intel/pinctrl-merrifield.c +++ b/drivers/pinctrl/intel/pinctrl-merrifield.c @@ -854,7 +854,7 @@ static int mrfld_pinctrl_probe(struct platform_device *pdev) */ nfamilies = ARRAY_SIZE(mrfld_families), families = devm_kmemdup(&pdev->dev, mrfld_families, - nfamilies * sizeof(mrfld_families), + sizeof(mrfld_families), GFP_KERNEL); if (!families) return -ENOMEM; |