Pin control fixes for v4.19:
- Fixes to x86 hardware: - AMD interrupt debounce issues - Faulty Intel cannonlake register offset - Revert pin translation IRQ locking -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJbrdCVAAoJEEEQszewGV1z0LkP/RqChMOkmgsYKhTosA2Fy5gY bi/h4wqpiyLazAaDduX1vyuTPclDOjwsv+6xLNvHOeqThxydwHm0fyG+DYSBSI+r /DNGhKmaGb8XDzwioee2MaACdXa4Bdz1fawKFjHlLMbeFcROxO+frtAAet+Bq/aX tlx7ClAP90wI7/UTMmsoMtH7S/7/x4NjzyL5ZTKWUVxRdZI/REVSs3tFzWliO5Y+ e7tqtwaq4ZR5TCqmUlv9rk4C02ZUQtTqH3pjsb9BM/wkfZWQ/YbEDNd9eR66EsEC /rFpdXHDN8qB9cXDyH5pGieNYs2Et/QMaOlz2GJXkokGC1cLheM2oLw4RO5Oaekq RjJg2qAsgpLOkWBrydt/e1UBj34XPrOcabaxNxud+h58lNINb2T9PD+4WNMlST4a AyZH1r29T27UERGZ5x627WVXtqTjYETx7zCjWpDjsqRY/5qicr+nbMc4k0z8uOiz XxrqzQtUJGjZ2HVcfepN6EEeNceriRSymbsaDS7MNN000DyAWTrP7Sao4splznhd qeafXiZf2oI3Ticz0yF/qFlpi6XY5BNjmVtHHWvvWi2JyS5VJt/waGHJUpCAiz9Y i0hp0QZqnL1lWiLBqqeyu/VCuzXTa0udWnQjq+Gn0TugyfZrAqSUTrZVLeGcxTlb ezBwpDaY5vzNVwcZWArw =/o9Q -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
900915f903
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue