Skip to content

Instantly share code, notes, and snippets.

@leventerevesz
Created September 22, 2022 11:03
Show Gist options
  • Save leventerevesz/60d53b9ef2ae5500c9754bf4763bbecf to your computer and use it in GitHub Desktop.
Save leventerevesz/60d53b9ef2ae5500c9754bf4763bbecf to your computer and use it in GitHub Desktop.
Add pca9505 mask interrupt support to gpio-pca953x.c
From 277f00fe0486c3eba4743937afe2090cffe925da Mon Sep 17 00:00:00 2001
From: Levente <levente.revesz@eilabs.com>
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