Commit 900915f9 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'pinctrl-v4.19-4' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl

Linus writes:
  "Pin control fixes for v4.19:
   - Fixes to x86 hardware:
   - AMD interrupt debounce issues
   - Faulty Intel cannonlake register offset
   - Revert pin translation IRQ locking"

* tag 'pinctrl-v4.19-4' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl:
  Revert "pinctrl: intel: Do pin translation when lock IRQ"
  pinctrl: cannonlake: Fix HOSTSW_OWN register offset of H variant
  pinctrl/amd: poll InterruptEnable bits in amd_gpio_irq_set_type
parents f151f57b 72923e54
......@@ -15,10 +15,11 @@
#include "pinctrl-intel.h"
#define CNL_PAD_OWN 0x020
#define CNL_PADCFGLOCK 0x080
#define CNL_HOSTSW_OWN 0x0b0
#define CNL_GPI_IE 0x120
#define CNL_PAD_OWN 0x020
#define CNL_PADCFGLOCK 0x080
#define CNL_LP_HOSTSW_OWN 0x0b0
#define CNL_H_HOSTSW_OWN 0x0c0
#define CNL_GPI_IE 0x120
#define CNL_GPP(r, s, e, g) \
{ \
......@@ -30,12 +31,12 @@
#define CNL_NO_GPIO -1
#define CNL_COMMUNITY(b, s, e, g) \
#define CNL_COMMUNITY(b, s, e, o, g) \
{ \
.barno = (b), \
.padown_offset = CNL_PAD_OWN, \
.padcfglock_offset = CNL_PADCFGLOCK, \
.hostown_offset = CNL_HOSTSW_OWN, \
.hostown_offset = (o), \
.ie_offset = CNL_GPI_IE, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
......@@ -43,6 +44,12 @@
.ngpps = ARRAY_SIZE(g), \
}
#define CNLLP_COMMUNITY(b, s, e, g) \
CNL_COMMUNITY(b, s, e, CNL_LP_HOSTSW_OWN, g)
#define CNLH_COMMUNITY(b, s, e, g) \
CNL_COMMUNITY(b, s, e, CNL_H_HOSTSW_OWN, g)
/* Cannon Lake-H */
static const struct pinctrl_pin_desc cnlh_pins[] = {
/* GPP_A */
......@@ -442,10 +449,10 @@ static const struct intel_function cnlh_functions[] = {
};
static const struct intel_community cnlh_communities[] = {
CNL_COMMUNITY(0, 0, 50, cnlh_community0_gpps),
CNL_COMMUNITY(1, 51, 154, cnlh_community1_gpps),
CNL_COMMUNITY(2, 155, 248, cnlh_community3_gpps),
CNL_COMMUNITY(3, 249, 298, cnlh_community4_gpps),
CNLH_COMMUNITY(0, 0, 50, cnlh_community0_gpps),
CNLH_COMMUNITY(1, 51, 154, cnlh_community1_gpps),
CNLH_COMMUNITY(2, 155, 248, cnlh_community3_gpps),
CNLH_COMMUNITY(3, 249, 298, cnlh_community4_gpps),
};
static const struct intel_pinctrl_soc_data cnlh_soc_data = {
......@@ -803,9 +810,9 @@ static const struct intel_padgroup cnllp_community4_gpps[] = {
};
static const struct intel_community cnllp_communities[] = {
CNL_COMMUNITY(0, 0, 67, cnllp_community0_gpps),
CNL_COMMUNITY(1, 68, 180, cnllp_community1_gpps),
CNL_COMMUNITY(2, 181, 243, cnllp_community4_gpps),
CNLLP_COMMUNITY(0, 0, 67, cnllp_community0_gpps),
CNLLP_COMMUNITY(1, 68, 180, cnllp_community1_gpps),
CNLLP_COMMUNITY(2, 181, 243, cnllp_community4_gpps),
};
static const struct intel_pinctrl_soc_data cnllp_soc_data = {
......
......@@ -887,36 +887,6 @@ static const struct gpio_chip intel_gpio_chip = {
.set_config = gpiochip_generic_config,
};
static int intel_gpio_irq_reqres(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
int pin;
int ret;
pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
if (pin >= 0) {
ret = gpiochip_lock_as_irq(gc, pin);
if (ret) {
dev_err(pctrl->dev, "unable to lock HW IRQ %d for IRQ\n",
pin);
return ret;
}
}
return 0;
}
static void intel_gpio_irq_relres(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
int pin;
pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
if (pin >= 0)
gpiochip_unlock_as_irq(gc, pin);
}
static void intel_gpio_irq_ack(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
......@@ -1132,8 +1102,6 @@ static irqreturn_t intel_gpio_irq(int irq, void *data)
static struct irq_chip intel_gpio_irqchip = {
.name = "intel-gpio",
.irq_request_resources = intel_gpio_irq_reqres,
.irq_release_resources = intel_gpio_irq_relres,
.irq_enable = intel_gpio_irq_enable,
.irq_ack = intel_gpio_irq_ack,
.irq_mask = intel_gpio_irq_mask,
......
......@@ -348,21 +348,12 @@ static void amd_gpio_irq_enable(struct irq_data *d)
unsigned long flags;
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
u32 mask = BIT(INTERRUPT_ENABLE_OFF) | BIT(INTERRUPT_MASK_OFF);
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
pin_reg |= BIT(INTERRUPT_ENABLE_OFF);
pin_reg |= BIT(INTERRUPT_MASK_OFF);
writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
/*
* When debounce logic is enabled it takes ~900 us before interrupts
* can be enabled. During this "debounce warm up" period the
* "INTERRUPT_ENABLE" bit will read as 0. Poll the bit here until it
* reads back as 1, signaling that interrupts are now enabled.
*/
while ((readl(gpio_dev->base + (d->hwirq)*4) & mask) != mask)
continue;
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
}
......@@ -426,7 +417,7 @@ static void amd_gpio_irq_eoi(struct irq_data *d)
static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
int ret = 0;
u32 pin_reg;
u32 pin_reg, pin_reg_irq_en, mask;
unsigned long flags, irq_flags;
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
......@@ -495,6 +486,28 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
}
pin_reg |= CLR_INTR_STAT << INTERRUPT_STS_OFF;
/*
* If WAKE_INT_MASTER_REG.MaskStsEn is set, a software write to the
* debounce registers of any GPIO will block wake/interrupt status
* generation for *all* GPIOs for a lenght of time that depends on
* WAKE_INT_MASTER_REG.MaskStsLength[11:0]. During this period the
* INTERRUPT_ENABLE bit will read as 0.
*
* We temporarily enable irq for the GPIO whose configuration is
* changing, and then wait for it to read back as 1 to know when
* debounce has settled and then disable the irq again.
* We do this polling with the spinlock held to ensure other GPIO
* access routines do not read an incorrect value for the irq enable
* bit of other GPIOs. We keep the GPIO masked while polling to avoid
* spurious irqs, and disable the irq again after polling.
*/
mask = BIT(INTERRUPT_ENABLE_OFF);
pin_reg_irq_en = pin_reg;
pin_reg_irq_en |= mask;
pin_reg_irq_en &= ~BIT(INTERRUPT_MASK_OFF);
writel(pin_reg_irq_en, gpio_dev->base + (d->hwirq)*4);
while ((readl(gpio_dev->base + (d->hwirq)*4) & mask) != mask)
continue;
writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment