GPIO fixes for the v5.4 series
The fixes pertain to a problem with initializing the Intel GPIO irqchips when adding gpiochips, Andy fixed it up elegantly by adding a hardware initialization callback to the struct gpio_irq_chip so let's use this. Tested and verified on the target hardware. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEElDRnuGcz/wPCXQWMQRCzN7AZXXMFAl2oFDQACgkQQRCzN7AZ XXMqcxAAoFftmi61CZL5EH9oZNMD5ebg8ovBizNbP5KmQ6oAxv7RkX7TJpdAysAF FpzmKIeR/hSiZ6t046xS2M1zBUHya9sb/X7Nlt7n/ZDbEC/aCvbRKaxADEdR7flQ qzB2u/ZZ25yknTuCxu17Yvo1Bg1T1qEXr+36UJhw8tWDAt60UUi893o6qbnixpJ5 qaQc2IBrSsTStxnT4Tfom1nJ86gvCRgN1lKTCua0rlKVOtSO2MXf7ZlKz0eJBGpa CNML7esE+/+4Qe6QM5KY6Rw9V0jO916N7xPoX2lVnF+HWjCc7uNmB7cWHMk55iuZ NmkLfrkEgRwWjWTRXinlqIWTeFNWfrIsDjRbS+dCxZKxRZutPnUgNq8nrA51tD8P qVdc29gk5myGKYCjc9onbDeJT6dgbf4ck/lYmumxp/EVlHIWFL5gCi1OwV0Nn80C 5KFyLvRf2dyKynaZSebTbdqnds4LHK3c49psnmye2eMKv5e7jCPeSzKgsYeCqT/i SAa0gFhIGUd5e8BxiLwYf6rjCjoa6jXDz6fkCmSGDPU6iycp+wh2V4fSuXn6zBD/ wAm67n2QwcKsLWxvSTnCpcbSUt0eykPXHunswAflV+HDMOgmTz40+9F9Ymvcu+B/ H34k89WBDKWPjePDMrFw2su2EeZFo2o6HFJV8JuJzXn7xGHEpA8= =tDS5 -----END PGP SIGNATURE----- Merge tag 'gpio-v5.4-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio Pull GPIO fixes from Linus Walleij: "The fixes pertain to a problem with initializing the Intel GPIO irqchips when adding gpiochips. Andy fixed it up elegantly by adding a hardware initialization callback to the struct gpio_irq_chip so let's use this. Tested and verified on the target hardware" * tag 'gpio-v5.4-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: gpio: lynxpoint: set default handler to be handle_bad_irq() gpio: merrifield: Move hardware initialization to callback gpio: lynxpoint: Move hardware initialization to callback gpio: intel-mid: Move hardware initialization to callback gpiolib: Initialize the hardware with a callback gpio: merrifield: Restore use of irq_base
This commit is contained in:
commit
7801158f83
@ -293,8 +293,9 @@ static void intel_mid_irq_handler(struct irq_desc *desc)
|
||||
chip->irq_eoi(data);
|
||||
}
|
||||
|
||||
static void intel_mid_irq_init_hw(struct intel_mid_gpio *priv)
|
||||
static int intel_mid_irq_init_hw(struct gpio_chip *chip)
|
||||
{
|
||||
struct intel_mid_gpio *priv = gpiochip_get_data(chip);
|
||||
void __iomem *reg;
|
||||
unsigned base;
|
||||
|
||||
@ -309,6 +310,8 @@ static void intel_mid_irq_init_hw(struct intel_mid_gpio *priv)
|
||||
reg = gpio_reg(&priv->chip, base, GEDR);
|
||||
writel(~0, reg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused intel_gpio_runtime_idle(struct device *dev)
|
||||
@ -372,6 +375,7 @@ static int intel_gpio_probe(struct pci_dev *pdev,
|
||||
|
||||
girq = &priv->chip.irq;
|
||||
girq->chip = &intel_mid_irqchip;
|
||||
girq->init_hw = intel_mid_irq_init_hw;
|
||||
girq->parent_handler = intel_mid_irq_handler;
|
||||
girq->num_parents = 1;
|
||||
girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
|
||||
@ -384,9 +388,8 @@ static int intel_gpio_probe(struct pci_dev *pdev,
|
||||
girq->default_type = IRQ_TYPE_NONE;
|
||||
girq->handler = handle_simple_irq;
|
||||
|
||||
intel_mid_irq_init_hw(priv);
|
||||
|
||||
pci_set_drvdata(pdev, priv);
|
||||
|
||||
retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
|
||||
if (retval) {
|
||||
dev_err(&pdev->dev, "gpiochip_add error %d\n", retval);
|
||||
|
@ -294,8 +294,9 @@ static struct irq_chip lp_irqchip = {
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE,
|
||||
};
|
||||
|
||||
static void lp_gpio_irq_init_hw(struct lp_gpio *lg)
|
||||
static int lp_gpio_irq_init_hw(struct gpio_chip *chip)
|
||||
{
|
||||
struct lp_gpio *lg = gpiochip_get_data(chip);
|
||||
unsigned long reg;
|
||||
unsigned base;
|
||||
|
||||
@ -307,6 +308,8 @@ static void lp_gpio_irq_init_hw(struct lp_gpio *lg)
|
||||
reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT);
|
||||
outl(0xffffffff, reg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lp_gpio_probe(struct platform_device *pdev)
|
||||
@ -364,6 +367,7 @@ static int lp_gpio_probe(struct platform_device *pdev)
|
||||
|
||||
girq = &gc->irq;
|
||||
girq->chip = &lp_irqchip;
|
||||
girq->init_hw = lp_gpio_irq_init_hw;
|
||||
girq->parent_handler = lp_gpio_irq_handler;
|
||||
girq->num_parents = 1;
|
||||
girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
|
||||
@ -373,9 +377,7 @@ static int lp_gpio_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
girq->parents[0] = (unsigned)irq_rc->start;
|
||||
girq->default_type = IRQ_TYPE_NONE;
|
||||
girq->handler = handle_simple_irq;
|
||||
|
||||
lp_gpio_irq_init_hw(lg);
|
||||
girq->handler = handle_bad_irq;
|
||||
}
|
||||
|
||||
ret = devm_gpiochip_add_data(dev, gc, lg);
|
||||
|
@ -362,8 +362,9 @@ static void mrfld_irq_handler(struct irq_desc *desc)
|
||||
chained_irq_exit(irqchip, desc);
|
||||
}
|
||||
|
||||
static void mrfld_irq_init_hw(struct mrfld_gpio *priv)
|
||||
static int mrfld_irq_init_hw(struct gpio_chip *chip)
|
||||
{
|
||||
struct mrfld_gpio *priv = gpiochip_get_data(chip);
|
||||
void __iomem *reg;
|
||||
unsigned int base;
|
||||
|
||||
@ -375,6 +376,8 @@ static void mrfld_irq_init_hw(struct mrfld_gpio *priv)
|
||||
reg = gpio_reg(&priv->chip, base, GFER);
|
||||
writel(0, reg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *mrfld_gpio_get_pinctrl_dev_name(struct mrfld_gpio *priv)
|
||||
@ -447,6 +450,7 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
|
||||
|
||||
girq = &priv->chip.irq;
|
||||
girq->chip = &mrfld_irqchip;
|
||||
girq->init_hw = mrfld_irq_init_hw;
|
||||
girq->parent_handler = mrfld_irq_handler;
|
||||
girq->num_parents = 1;
|
||||
girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
|
||||
@ -455,11 +459,10 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
|
||||
if (!girq->parents)
|
||||
return -ENOMEM;
|
||||
girq->parents[0] = pdev->irq;
|
||||
girq->first = irq_base;
|
||||
girq->default_type = IRQ_TYPE_NONE;
|
||||
girq->handler = handle_bad_irq;
|
||||
|
||||
mrfld_irq_init_hw(priv);
|
||||
|
||||
pci_set_drvdata(pdev, priv);
|
||||
retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
|
||||
if (retval) {
|
||||
|
@ -86,6 +86,7 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip,
|
||||
struct lock_class_key *lock_key,
|
||||
struct lock_class_key *request_key);
|
||||
static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip);
|
||||
static int gpiochip_irqchip_init_hw(struct gpio_chip *gpiochip);
|
||||
static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip);
|
||||
static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip);
|
||||
|
||||
@ -1406,6 +1407,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
|
||||
|
||||
machine_gpiochip_add(chip);
|
||||
|
||||
ret = gpiochip_irqchip_init_hw(chip);
|
||||
if (ret)
|
||||
goto err_remove_acpi_chip;
|
||||
|
||||
ret = gpiochip_irqchip_init_valid_mask(chip);
|
||||
if (ret)
|
||||
goto err_remove_acpi_chip;
|
||||
@ -1622,6 +1627,16 @@ static struct gpio_chip *find_chip_by_name(const char *name)
|
||||
* The following is irqchip helper code for gpiochips.
|
||||
*/
|
||||
|
||||
static int gpiochip_irqchip_init_hw(struct gpio_chip *gc)
|
||||
{
|
||||
struct gpio_irq_chip *girq = &gc->irq;
|
||||
|
||||
if (!girq->init_hw)
|
||||
return 0;
|
||||
|
||||
return girq->init_hw(gc);
|
||||
}
|
||||
|
||||
static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gc)
|
||||
{
|
||||
struct gpio_irq_chip *girq = &gc->irq;
|
||||
@ -2446,8 +2461,13 @@ static inline int gpiochip_add_irqchip(struct gpio_chip *gpiochip,
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {}
|
||||
|
||||
static inline int gpiochip_irqchip_init_hw(struct gpio_chip *gpiochip)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip)
|
||||
{
|
||||
return 0;
|
||||
|
@ -201,6 +201,14 @@ struct gpio_irq_chip {
|
||||
*/
|
||||
bool threaded;
|
||||
|
||||
/**
|
||||
* @init_hw: optional routine to initialize hardware before
|
||||
* an IRQ chip will be added. This is quite useful when
|
||||
* a particular driver wants to clear IRQ related registers
|
||||
* in order to avoid undesired events.
|
||||
*/
|
||||
int (*init_hw)(struct gpio_chip *chip);
|
||||
|
||||
/**
|
||||
* @init_valid_mask: optional routine to initialize @valid_mask, to be
|
||||
* used if not all GPIO lines are valid interrupts. Sometimes some
|
||||
|
Loading…
Reference in New Issue
Block a user