summaryrefslogtreecommitdiff
path: root/drivers/pinctrl/intel
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/intel')
-rw-r--r--drivers/pinctrl/intel/pinctrl-cherryview.c60
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.c33
-rw-r--r--drivers/pinctrl/intel/pinctrl-merrifield.c2
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;