mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-29 07:34:06 +08:00
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);
|
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;
|
void __iomem *reg;
|
||||||
unsigned base;
|
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);
|
reg = gpio_reg(&priv->chip, base, GEDR);
|
||||||
writel(~0, reg);
|
writel(~0, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __maybe_unused intel_gpio_runtime_idle(struct device *dev)
|
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 = &priv->chip.irq;
|
||||||
girq->chip = &intel_mid_irqchip;
|
girq->chip = &intel_mid_irqchip;
|
||||||
|
girq->init_hw = intel_mid_irq_init_hw;
|
||||||
girq->parent_handler = intel_mid_irq_handler;
|
girq->parent_handler = intel_mid_irq_handler;
|
||||||
girq->num_parents = 1;
|
girq->num_parents = 1;
|
||||||
girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
|
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->default_type = IRQ_TYPE_NONE;
|
||||||
girq->handler = handle_simple_irq;
|
girq->handler = handle_simple_irq;
|
||||||
|
|
||||||
intel_mid_irq_init_hw(priv);
|
|
||||||
|
|
||||||
pci_set_drvdata(pdev, priv);
|
pci_set_drvdata(pdev, priv);
|
||||||
|
|
||||||
retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
|
retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
dev_err(&pdev->dev, "gpiochip_add error %d\n", 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,
|
.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 long reg;
|
||||||
unsigned base;
|
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);
|
reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT);
|
||||||
outl(0xffffffff, reg);
|
outl(0xffffffff, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lp_gpio_probe(struct platform_device *pdev)
|
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 = &gc->irq;
|
||||||
girq->chip = &lp_irqchip;
|
girq->chip = &lp_irqchip;
|
||||||
|
girq->init_hw = lp_gpio_irq_init_hw;
|
||||||
girq->parent_handler = lp_gpio_irq_handler;
|
girq->parent_handler = lp_gpio_irq_handler;
|
||||||
girq->num_parents = 1;
|
girq->num_parents = 1;
|
||||||
girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
|
girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
|
||||||
@ -373,9 +377,7 @@ static int lp_gpio_probe(struct platform_device *pdev)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
girq->parents[0] = (unsigned)irq_rc->start;
|
girq->parents[0] = (unsigned)irq_rc->start;
|
||||||
girq->default_type = IRQ_TYPE_NONE;
|
girq->default_type = IRQ_TYPE_NONE;
|
||||||
girq->handler = handle_simple_irq;
|
girq->handler = handle_bad_irq;
|
||||||
|
|
||||||
lp_gpio_irq_init_hw(lg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = devm_gpiochip_add_data(dev, gc, lg);
|
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);
|
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;
|
void __iomem *reg;
|
||||||
unsigned int base;
|
unsigned int base;
|
||||||
|
|
||||||
@ -375,6 +376,8 @@ static void mrfld_irq_init_hw(struct mrfld_gpio *priv)
|
|||||||
reg = gpio_reg(&priv->chip, base, GFER);
|
reg = gpio_reg(&priv->chip, base, GFER);
|
||||||
writel(0, reg);
|
writel(0, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *mrfld_gpio_get_pinctrl_dev_name(struct mrfld_gpio *priv)
|
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 = &priv->chip.irq;
|
||||||
girq->chip = &mrfld_irqchip;
|
girq->chip = &mrfld_irqchip;
|
||||||
|
girq->init_hw = mrfld_irq_init_hw;
|
||||||
girq->parent_handler = mrfld_irq_handler;
|
girq->parent_handler = mrfld_irq_handler;
|
||||||
girq->num_parents = 1;
|
girq->num_parents = 1;
|
||||||
girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
|
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)
|
if (!girq->parents)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
girq->parents[0] = pdev->irq;
|
girq->parents[0] = pdev->irq;
|
||||||
|
girq->first = irq_base;
|
||||||
girq->default_type = IRQ_TYPE_NONE;
|
girq->default_type = IRQ_TYPE_NONE;
|
||||||
girq->handler = handle_bad_irq;
|
girq->handler = handle_bad_irq;
|
||||||
|
|
||||||
mrfld_irq_init_hw(priv);
|
|
||||||
|
|
||||||
pci_set_drvdata(pdev, priv);
|
pci_set_drvdata(pdev, priv);
|
||||||
retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
|
retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
|
||||||
if (retval) {
|
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 *lock_key,
|
||||||
struct lock_class_key *request_key);
|
struct lock_class_key *request_key);
|
||||||
static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip);
|
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 int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip);
|
||||||
static void gpiochip_irqchip_free_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);
|
machine_gpiochip_add(chip);
|
||||||
|
|
||||||
|
ret = gpiochip_irqchip_init_hw(chip);
|
||||||
|
if (ret)
|
||||||
|
goto err_remove_acpi_chip;
|
||||||
|
|
||||||
ret = gpiochip_irqchip_init_valid_mask(chip);
|
ret = gpiochip_irqchip_init_valid_mask(chip);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_remove_acpi_chip;
|
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.
|
* 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)
|
static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gc)
|
||||||
{
|
{
|
||||||
struct gpio_irq_chip *girq = &gc->irq;
|
struct gpio_irq_chip *girq = &gc->irq;
|
||||||
@ -2446,8 +2461,13 @@ static inline int gpiochip_add_irqchip(struct gpio_chip *gpiochip,
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {}
|
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)
|
static inline int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -201,6 +201,14 @@ struct gpio_irq_chip {
|
|||||||
*/
|
*/
|
||||||
bool threaded;
|
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
|
* @init_valid_mask: optional routine to initialize @valid_mask, to be
|
||||||
* used if not all GPIO lines are valid interrupts. Sometimes some
|
* used if not all GPIO lines are valid interrupts. Sometimes some
|
||||||
|
Loading…
Reference in New Issue
Block a user