Created
September 22, 2022 11:03
-
-
Save leventerevesz/60d53b9ef2ae5500c9754bf4763bbecf to your computer and use it in GitHub Desktop.
Add pca9505 mask interrupt support to gpio-pca953x.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 277f00fe0486c3eba4743937afe2090cffe925da Mon Sep 17 00:00:00 2001 | |
From: Levente <[email protected]> | |
Date: Thu, 22 Sep 2022 10:30:30 +0200 | |
Subject: [PATCH] Add support for interrupt mask register in pca9505 | |
--- | |
drivers/gpio/gpio-pca953x.c | 36 ++++++++++++++++++++++++++++++++++-- | |
1 file changed, 34 insertions(+), 2 deletions(-) | |
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c | |
index c81d73d5e015..6c7d2e102189 100644 | |
--- a/drivers/gpio/gpio-pca953x.c | |
+++ b/drivers/gpio/gpio-pca953x.c | |
@@ -28,6 +28,7 @@ | |
#define PCA953X_OUTPUT 0x01 | |
#define PCA953X_INVERT 0x02 | |
#define PCA953X_DIRECTION 0x03 | |
+#define PCA953X_IRQ_MASK 0x04 | |
#define REG_ADDR_MASK GENMASK(5, 0) | |
#define REG_ADDR_EXT BIT(6) | |
@@ -63,7 +64,9 @@ | |
#define PCA_INT BIT(8) | |
#define PCA_PCAL BIT(9) | |
+#define PCA_HAS_INT_MASK BIT(10) | |
#define PCA_LATCH_INT (PCA_PCAL | PCA_INT) | |
+#define PCA_MASKABLE_INT (PCA_HAS_INT_MASK | PCA_INT) | |
#define PCA953X_TYPE BIT(12) | |
#define PCA957X_TYPE BIT(13) | |
#define PCA_TYPE_MASK GENMASK(15, 12) | |
@@ -72,7 +75,7 @@ | |
static const struct i2c_device_id pca953x_id[] = { | |
{ "pca6416", 16 | PCA953X_TYPE | PCA_INT, }, | |
- { "pca9505", 40 | PCA953X_TYPE | PCA_INT, }, | |
+ { "pca9505", 40 | PCA953X_TYPE | PCA_MASKABLE_INT, }, | |
{ "pca9534", 8 | PCA953X_TYPE | PCA_INT, }, | |
{ "pca9535", 16 | PCA953X_TYPE | PCA_INT, }, | |
{ "pca9536", 4 | PCA953X_TYPE, }, | |
@@ -201,6 +204,7 @@ struct pca953x_reg_config { | |
int output; | |
int input; | |
int invert; | |
+ int irq_mask; | |
}; | |
static const struct pca953x_reg_config pca953x_regs = { | |
@@ -208,6 +212,7 @@ static const struct pca953x_reg_config pca953x_regs = { | |
.output = PCA953X_OUTPUT, | |
.input = PCA953X_INPUT, | |
.invert = PCA953X_INVERT, | |
+ .irq_mask = PCA953X_IRQ_MASK, | |
}; | |
static const struct pca953x_reg_config pca957x_regs = { | |
@@ -250,6 +255,7 @@ static int pca953x_bank_shift(struct pca953x_chip *chip) | |
#define PCA953x_BANK_OUTPUT BIT(1) | |
#define PCA953x_BANK_POLARITY BIT(2) | |
#define PCA953x_BANK_CONFIG BIT(3) | |
+#define PCA953x_BANK_IRQ_MASK BIT(4) | |
#define PCA957x_BANK_INPUT BIT(0) | |
#define PCA957x_BANK_POLARITY BIT(1) | |
@@ -330,6 +336,10 @@ static bool pca953x_readable_register(struct device *dev, unsigned int reg) | |
PCA957x_BANK_BUSHOLD; | |
} | |
+ if (chip->driver_data & PCA_HAS_INT_MASK) { | |
+ bank |= PCA953x_BANK_IRQ_MASK; | |
+ } | |
+ | |
if (chip->driver_data & PCA_PCAL) { | |
bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_PULL_EN | | |
PCAL9xxx_BANK_PULL_SEL | PCAL9xxx_BANK_IRQ_MASK | | |
@@ -352,6 +362,10 @@ static bool pca953x_writeable_register(struct device *dev, unsigned int reg) | |
PCA957x_BANK_CONFIG | PCA957x_BANK_BUSHOLD; | |
} | |
+ if (chip->driver_data & PCA_HAS_INT_MASK) { | |
+ bank |= PCA953x_BANK_IRQ_MASK; | |
+ } | |
+ | |
if (chip->driver_data & PCA_PCAL) | |
bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_PULL_EN | | |
PCAL9xxx_BANK_PULL_SEL | PCAL9xxx_BANK_IRQ_MASK; | |
@@ -695,6 +709,14 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) | |
pca953x_read_regs(chip, chip->regs->direction, reg_direction); | |
+ if (chip->driver_data & PCA_HAS_INT_MASK) { | |
+ for (i = 0; i < NBANK(chip); i++) | |
+ invert_irq_mask[i] = ~chip->irq_mask[i]; | |
+ | |
+ /* Unmask enabled interrupts */ | |
+ pca953x_write_regs(chip, chip->regs->irq_mask, invert_irq_mask); | |
+ } | |
+ | |
if (chip->driver_data & PCA_PCAL) { | |
/* Enable latch on interrupt-enabled inputs */ | |
pca953x_write_regs(chip, PCAL953X_IN_LATCH, chip->irq_mask); | |
@@ -1172,6 +1194,16 @@ static int pca953x_regcache_sync(struct device *dev) | |
} | |
#ifdef CONFIG_GPIO_PCA953X_IRQ | |
+ if (chip->driver_data & PCA_HAS_INT_MASK) { | |
+ ret = regcache_sync_region(chip->regmap, chip->regs->irq_mask, | |
+ chip->regs->irq_mask + NBANK(chip)); | |
+ if (ret) { | |
+ dev_err(dev, "Failed to sync INT mask registers: %d\n", | |
+ ret); | |
+ return ret; | |
+ } | |
+ } | |
+ | |
if (chip->driver_data & PCA_PCAL) { | |
ret = regcache_sync_region(chip->regmap, PCAL953X_IN_LATCH, | |
PCAL953X_IN_LATCH + NBANK(chip)); | |
@@ -1249,7 +1281,7 @@ static int pca953x_resume(struct device *dev) | |
static const struct of_device_id pca953x_dt_ids[] = { | |
{ .compatible = "nxp,pca6416", .data = OF_953X(16, PCA_INT), }, | |
- { .compatible = "nxp,pca9505", .data = OF_953X(40, PCA_INT), }, | |
+ { .compatible = "nxp,pca9505", .data = OF_953X(40, PCA_MASKABLE_INT), }, | |
{ .compatible = "nxp,pca9534", .data = OF_953X( 8, PCA_INT), }, | |
{ .compatible = "nxp,pca9535", .data = OF_953X(16, PCA_INT), }, | |
{ .compatible = "nxp,pca9536", .data = OF_953X( 4, 0), }, | |
-- | |
2.37.3 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment