[RFC PATCH 3/3] gpio: pca953x: Redesign register address calculation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The driver supports 8 chip types, 6 of which have extended registers
with various functions, e.g. pull-up and pull-down bias for the gpio
lines or interrupt masking. To allow supporting these functions, the
driver has to be able to calculate the addresses of these registers.

Replace the address calculation scheme with new reg_addr() and check_reg()
functions, one for each register layout. The new functions can work with
all of the extended registers. The functions have been tested with the
register layout of each compatible chip.

Signed-off-by: Levente Révész <levente.revesz@xxxxxxxxxx>
---
 drivers/gpio/gpio-pca953x.c | 551 ++++++++++++++++++++++++++++--------
 1 file changed, 434 insertions(+), 117 deletions(-)

diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 3d4c3efeaf35..34326abf8f63 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -26,26 +26,8 @@
 #include <asm/unaligned.h>
 
 #define REG_ADDR_MASK		GENMASK(5, 0)
-#define REG_ADDR_EXT		BIT(6)
 #define REG_ADDR_AI		BIT(7)
 
-#define PCAL953X_OUT_STRENGTH	0x20
-#define PCAL953X_IN_LATCH	0x22
-#define PCAL953X_PULL_EN	0x23
-#define PCAL953X_PULL_SEL	0x24
-#define PCAL953X_INT_MASK	0x25
-#define PCAL953X_INT_STAT	0x26
-#define PCAL953X_OUT_CONF	0x27
-
-#define PCAL6524_INT_EDGE	0x28
-#define PCAL6524_INT_CLR	0x2a
-#define PCAL6524_IN_STATUS	0x2b
-#define PCAL6524_OUT_INDCONF	0x2c
-#define PCAL6524_DEBOUNCE	0x2d
-
-#define PCAL_GPIO_MASK		GENMASK(4, 0)
-#define PCAL_PINCTRL_MASK	GENMASK(6, 5)
-
 /*
  * driver_data
  *
@@ -348,9 +330,10 @@ struct pca953x_chip {
 	enum pca953x_chip_type type;
 	const struct pca953x_reg_config *regs;
 
-	u8 (*recalc_addr)(struct pca953x_chip *chip, int reg, int off);
-	bool (*check_reg)(struct pca953x_chip *chip, unsigned int reg,
-			  u32 checkbank);
+	u8 (*reg_addr)(struct pca953x_chip *chip, unsigned int reg,
+		       unsigned int offset);
+	bool (*check_reg)(struct pca953x_chip *chip, u8 reg_addr,
+			  u32 registers);
 };
 
 static bool pca953x_has_int(struct pca953x_chip *chip)
@@ -398,25 +381,33 @@ static int pca953x_bank_shift(struct pca953x_chip *chip)
  *   categories above.
  */
 
-static bool pca953x_check_register(struct pca953x_chip *chip, unsigned int reg,
-				   u32 checkbank)
+/*
+ * Register types:
+ *   - Single register: 1 byte for each GPIO port.
+ *   - Double register: 2 bytes for each GPIO port.
+ *   - One-byte register: Only a single byte.
+ */
+
+/* Check if register address belongs to any of the registers in a set. */
+static bool pca953x_check_reg(struct pca953x_chip *chip, u8 reg_addr,
+			      u32 registers)
 {
 	int bank_shift = pca953x_bank_shift(chip);
-	int bank = (reg & REG_ADDR_MASK) >> bank_shift;
-	int offset = reg & (BIT(bank_shift) - 1);
+	int reg;
+	int offset;
 
-	/* Special PCAL extended register check. */
-	if (reg & REG_ADDR_EXT) {
-		if (!pca953x_is_pcal_type(chip))
-			return false;
-		bank += 8;
-	}
+	reg_addr &= REG_ADDR_MASK;
+
+	reg = reg_addr >> bank_shift;
+
+	/* Which byte this is in a register bank. */
+	offset = reg_addr & (BIT(bank_shift) - 1);
 
-	/* Register is not in the matching bank. */
-	if (!(BIT(bank) & checkbank))
+	/* Address does not belong to any of the registers. */
+	if (!(BIT(reg) & registers))
 		return false;
 
-	/* Register is not within allowed range of bank. */
+	/* Offset is not within allowed range of the register. */
 	if (offset >= NBANK(chip))
 		return false;
 
@@ -424,46 +415,287 @@ static bool pca953x_check_register(struct pca953x_chip *chip, unsigned int reg,
 }
 
 /*
- * Unfortunately, whilst the PCAL6534 chip (and compatibles) broadly follow the
- * same register layout as the PCAL6524, the spacing of the registers has been
- * fundamentally altered by compacting them and thus does not obey the same
- * rules, including being able to use bit shifting to determine bank. These
- * chips hence need special handling here.
+ * Convert register address to register enum value.
+ * Returns -1 if reg_addr is invalid.
  */
-static bool pcal6534_check_register(struct pca953x_chip *chip, unsigned int reg,
-				    u32 checkbank)
+static int pcal953x_reg_addr_to_reg(int bank_shift, u8 reg_addr)
 {
-	int bank_shift;
-	int bank;
+	int reg;
+
+	if (reg_addr < (4U << bank_shift)) {
+		/* Basic registers. */
+		reg = reg_addr >> bank_shift;
+	} else if (reg_addr < 0x40) {
+		reg = -1;
+	} else if (reg_addr < 0x4F) {
+		/* Extended registers */
+		reg = ((reg_addr - 0x40) >> bank_shift) +
+			PCAL953X_REG_DRIVE_STRENGTH;
+
+		/* Compensate skipped reg numbers due to double registers. */
+		if (reg > PCAL953X_REG_DRIVE_STRENGTH)
+			reg -= 1;
+
+	} else if (reg_addr == 0x4F) {
+		/* Drive Mode register. Always 1 byte. */
+		reg = PCAL953X_REG_DRIVE_MODE;
+	} else {
+		reg = -1;
+	}
+
+	return reg;
+}
+
+static int pcal953x_calculate_reg_offset(int bank_offset, u8 reg_addr,
+					 enum pcal953x_reg reg)
+{
+	/*
+	 * Single registers and one-byte registers always start on a bank
+	 * border, the offset is the distance from reg_addr to the bank border.
+	 *
+	 * Double registers span over two banks, so the offset can be larger
+	 * than a bank. The offset is the distance from reg_addr to either an
+	 * odd or an even bank border, depending on the base address of the
+	 * register.
+	 */
+
+	u8 ext_addr;
+
+	if (reg <= PCAL953X_REG_DIRECTION)
+		return reg_addr % bank_offset;
+
+	/* Count banks from the base address of the extended regs. */
+	ext_addr = reg_addr - 0x40;
+
+	/* Double register in bank (N,N+1), N is even. */
+	if (reg == PCAL953X_REG_DRIVE_STRENGTH)
+		return ext_addr % (bank_offset * 2);
+	/* Drive Mode has no offsets. */
+	else if (reg == PCAL953X_REG_DRIVE_MODE)
+		return 0;
+	else
+		return ext_addr % bank_offset;
+}
+
+/* Check if offset is valid for register reg. */
+static bool pcal953x_check_reg_offset(int bank_size, enum pcal953x_reg reg,
+				      unsigned int offset)
+{
+	int maxoffset = bank_size - 1;
+
+	/* Double register */
+	if (reg == PCAL953X_REG_DRIVE_STRENGTH)
+		maxoffset = 2 * bank_size - 1;
+
+	/* One byte register */
+	if (reg == PCAL953X_REG_DRIVE_MODE)
+		maxoffset = 0;
+
+	/* Offset is not within allowed range of the register. */
+	if (offset > maxoffset)
+		return false;
+
+	return true;
+}
+
+/* Check if register address belongs to any of the registers in a set. */
+static bool pcal953x_check_reg(struct pca953x_chip *chip, u8 reg_addr,
+			       u32 registers)
+{
+	int bank_shift = pca953x_bank_shift(chip);
+	int bank_offset = BIT(bank_shift);
+	int reg;
 	int offset;
 
-	if (reg >= 0x54) {
-		/*
-		 * Handle lack of reserved registers after output port
-		 * configuration register to form a bank.
-		 */
-		reg -= 0x54;
-		bank_shift = 16;
-	} else if (reg >= 0x30) {
-		/*
-		 * Reserved block between 14h and 2Fh does not align on
-		 * expected bank boundaries like other devices.
-		 */
-		reg -= 0x30;
-		bank_shift = 8;
+	reg_addr &= REG_ADDR_MASK;
+
+	reg = pcal953x_reg_addr_to_reg(bank_shift, reg_addr);
+
+	/* Address does not belong to any of the registers. */
+	if (!(BIT(reg) & registers))
+		return false;
+
+	offset = pcal953x_calculate_reg_offset(bank_offset, reg_addr, reg);
+
+	if (!pcal953x_check_reg_offset(NBANK(chip), reg, offset))
+		return false;
+
+	return true;
+}
+
+/*
+ * Convert register address to register enum value.
+ * Returns -1 if reg_addr is invalid.
+ */
+static int pcal65xx_reg_addr_to_reg(int bank_offset, u8 ext_base_addr,
+				    u8 reg_addr)
+{
+	int reg;
+
+	if (reg_addr < 4 * bank_offset) {
+		/* Basic registers. */
+		reg = reg_addr / bank_offset;
+	} else if (reg_addr < ext_base_addr) {
+		reg = -1;
+	} else if (reg_addr < ext_base_addr + 15 * bank_offset) {
+		/* Extended registers */
+		reg = ((reg_addr - ext_base_addr) / bank_offset) +
+			PCAL65XX_REG_DRIVE_STRENGTH;
+
+		/* Compensate for skipped reg numbers after double registers. */
+		if (reg > PCAL65XX_REG_DRIVE_STRENGTH)
+			reg -= 1;
+
+		if (reg > PCAL65XX_REG_INT_EDGE)
+			reg -= 1;
 	} else {
-		bank_shift = 0;
+		reg = -1;
 	}
 
-	bank = bank_shift + reg / NBANK(chip);
-	offset = reg % NBANK(chip);
+	return reg;
+}
+
+static int pcal65xx_calculate_reg_offset(int bank_offset, u8 ext_base_addr,
+					 u8 reg_addr, enum pcal65xx_reg reg)
+{
+	/*
+	 * Single registers and one-byte registers always start on a bank
+	 * border, the offset is the distance from reg_addr to the bank border.
+	 *
+	 * Double registers span over two banks, so the offset can be larger
+	 * than a bank. The offset is the distance from reg_addr to either an
+	 * odd or an even bank border, depending on the base address of the
+	 * register.
+	 */
 
-	/* Register is not in the matching bank. */
-	if (!(BIT(bank) & checkbank))
+	u8 ext_addr;
+
+	if (reg <= PCAL65XX_REG_DIRECTION)
+		return reg_addr % bank_offset;
+
+	/* Count banks in relation to the base address of the extended regs. */
+	ext_addr = reg_addr - ext_base_addr;
+
+	/* Double register in bank (N,N+1), N is even. */
+	if (reg == PCAL65XX_REG_DRIVE_STRENGTH || reg == PCAL65XX_REG_INT_EDGE)
+		return ext_addr % (bank_offset * 2);
+	else
+		return ext_addr % bank_offset;
+}
+
+/* Check if offset is valid for register reg. */
+static bool pcal65xx_check_reg_offset(int bank_size, enum pcal65xx_reg reg,
+				      unsigned int offset)
+{
+	int maxoffset = bank_size - 1;
+	int num_debounce_ports = min(bank_size, PCAL65XX_MAX_NUM_DEBOUNCE_PORTS);
+
+	/* Double registers */
+	if (reg == PCAL65XX_REG_DRIVE_STRENGTH || reg == PCAL65XX_REG_INT_EDGE)
+		maxoffset = 2 * bank_size - 1;
+
+	/* One byte registers */
+	if (reg == PCAL65XX_REG_DRIVE_MODE || reg == PCAL65XX_REG_DEBOUNCE_COUNT)
+		maxoffset = 0;
+
+	if (reg == PCAL65XX_REG_DEBOUNCE_EN)
+		maxoffset = num_debounce_ports;
+
+	/* Offset is not within allowed range of the register. */
+	if (offset > maxoffset)
 		return false;
 
-	/* Register is not within allowed range of bank. */
-	if (offset >= NBANK(chip))
+	return true;
+}
+
+/* Check if register address belongs to any of the registers in a set. */
+static bool pcal652x_check_reg(struct pca953x_chip *chip, u8 reg_addr,
+			       u32 registers)
+{
+	int bank_shift = pca953x_bank_shift(chip);
+	int bank_offset = BIT(bank_shift);
+	int ext_base_addr = 0x40;
+	int num_debounce_ports = min(NBANK(chip), PCAL65XX_MAX_NUM_DEBOUNCE_PORTS);
+	int max_addr;
+	int reg;
+	int offset;
+
+	reg_addr &= REG_ADDR_MASK;
+
+	max_addr = ext_base_addr + (13U << bank_shift) + num_debounce_ports;
+	if (reg_addr > max_addr)
+		return false;
+
+	/*
+	 * The debounce count register is not aligned to bank offset.
+	 * Add enough offset to reg_address to form a bank.
+	 */
+	if (reg_addr == ext_base_addr + (13U << bank_shift) + num_debounce_ports)
+		reg_addr += bank_offset - num_debounce_ports;
+
+
+	reg = pcal65xx_reg_addr_to_reg(bank_offset, ext_base_addr, reg_addr);
+	if (reg < 0)
+		return false;
+
+	/* Address does not belong to any of the registers. */
+	if (!(BIT(reg) & registers))
+		return false;
+
+	offset = pcal65xx_calculate_reg_offset(bank_offset, ext_base_addr,
+					       reg_addr, reg);
+
+	if (!pcal65xx_check_reg_offset(NBANK(chip), reg, offset))
+		return false;
+
+	return true;
+}
+
+/* Check if register address belongs to any of the registers in a set. */
+static bool pcal653x_check_reg(struct pca953x_chip *chip, u8 reg_addr,
+			       u32 registers)
+{
+	/* PCAL653X has no padding (reserved registers) between banks. */
+
+	int bank_offset = NBANK(chip);
+	int ext_base_addr = 0x30;
+	int num_debounce_ports = min(NBANK(chip), PCAL65XX_MAX_NUM_DEBOUNCE_PORTS);
+	int max_addr;
+	int reg;
+	int offset;
+
+	reg_addr &= REG_ADDR_MASK;
+
+	max_addr = ext_base_addr + 13 * bank_offset + num_debounce_ports;
+	if (reg_addr > max_addr)
+		return false;
+
+	/*
+	 * The drive mode register is only 1 byte long with no padding after it.
+	 * Add enough offset to reg_addr to form a bank.
+	 */
+	if (reg_addr > ext_base_addr + 7 * bank_offset)
+		reg_addr += bank_offset - 1;
+
+	/*
+	 * The debounce count register is not aligned to bank offset. Add enough
+	 * offset to reg_address to form a bank.
+	 */
+	if (reg_addr == ext_base_addr + 13 * bank_offset + num_debounce_ports)
+		reg_addr += bank_offset - num_debounce_ports;
+
+	reg = pcal65xx_reg_addr_to_reg(bank_offset, 0x30, reg_addr);
+	if (reg < 0)
+		return false;
+
+	/* Address does not belong to any of the registers. */
+	if (!(BIT(reg) & registers))
+		return false;
+
+	offset = pcal65xx_calculate_reg_offset(bank_offset, ext_base_addr,
+					       reg_addr, reg);
+
+	if (!pcal65xx_check_reg_offset(NBANK(chip), reg, offset))
 		return false;
 
 	return true;
@@ -686,51 +918,125 @@ static const struct regmap_config pca953x_ai_i2c_regmap = {
 	.max_register = 0x7f,
 };
 
-static u8 pca953x_recalc_addr(struct pca953x_chip *chip, int reg, int off)
+/* Get the i2c address of register reg for line at offset. */
+static u8 pca953x_reg_addr(struct pca953x_chip *chip, unsigned int reg,
+			   unsigned int offset)
 {
 	int bank_shift = pca953x_bank_shift(chip);
-	int addr = (reg & PCAL_GPIO_MASK) << bank_shift;
-	int pinctrl = (reg & PCAL_PINCTRL_MASK) << 1;
-	u8 regaddr = pinctrl | addr | (off / BANK_SZ);
+	u8 reg_addr = (reg << bank_shift) + offset / BANK_SZ;
 
-	return regaddr;
+	return reg_addr;
+}
+
+/* Get the i2c address of register reg for line at offset. */
+static u8 pcal953x_reg_addr(struct pca953x_chip *chip, unsigned int reg,
+			    unsigned int offset)
+{
+	int bank_shift = pca953x_bank_shift(chip);
+	u8 reg_addr;
+
+	if (reg == PCAL953X_REG_DRIVE_MODE) {
+		/* One byte register on a fixed address. */
+		return 0x4F;
+	}
+
+	if (reg < PCAL953X_REG_DRIVE_STRENGTH)
+		reg_addr = reg << bank_shift;
+	else
+		reg_addr = 0x40 + ((reg - 4) << bank_shift);
+
+	/* Compensate for double register. */
+	if (reg > PCAL953X_REG_DRIVE_STRENGTH)
+		reg_addr += BIT(bank_shift);
+
+	if (reg == PCAL953X_REG_DRIVE_STRENGTH)
+		/*
+		 * Double register. Return the specific byte for given offset.
+		 * e.g. offset=0 -> byte 0, offset=4 -> byte 1.
+		 */
+		reg_addr += 2 * offset / BANK_SZ;
+	else
+		reg_addr += offset / BANK_SZ;
+
+	return reg_addr;
+}
+
+static u8 pcal65xx_reg_addr_common(int bank_offset,
+				   unsigned int ext_base_addr,
+				   enum pcal65xx_reg reg,
+				   int offset)
+{
+	u8 reg_addr;
+
+	if (reg < PCAL65XX_REG_DRIVE_STRENGTH)
+		reg_addr = reg * bank_offset;
+	else
+		reg_addr = ext_base_addr + (reg - 4) * bank_offset;
+
+	/* Compensate for double register. */
+	if (reg > PCAL65XX_REG_DRIVE_STRENGTH)
+		reg_addr += bank_offset;
+
+	if (reg > PCAL65XX_REG_INT_EDGE)
+		reg_addr += bank_offset;
+
+	if (reg == PCAL65XX_REG_DRIVE_STRENGTH || reg == PCAL65XX_REG_INT_EDGE)
+		/*
+		 * Double register. Return the specific byte for given offset.
+		 * e.g. offset=0 -> byte 0, offset=4 -> byte 1.
+		 */
+		reg_addr += 2 * offset / BANK_SZ;
+	else if (reg == PCAL65XX_REG_DRIVE_MODE || reg == PCAL65XX_REG_DEBOUNCE_COUNT)
+		/* One byte register. Do not add offset. */
+		;
+	else
+		reg_addr += offset / BANK_SZ;
+
+	return reg_addr;
+}
+
+/* Get the i2c address of register reg for line at offset. */
+static u8 pcal652x_reg_addr(struct pca953x_chip *chip, unsigned int reg,
+			    unsigned int offset)
+{
+	int bank_offset = BIT(pca953x_bank_shift(chip));
+	u8 reg_addr = pcal65xx_reg_addr_common(bank_offset, 0x40, reg, offset);
+	int num_debounce_ports = min(NBANK(chip), PCAL65XX_MAX_NUM_DEBOUNCE_PORTS);
+
+	/* The reserved registers before the Debounce Count register are missing. */
+	if (reg == PCAL65XX_REG_DEBOUNCE_COUNT)
+		reg_addr -= bank_offset - num_debounce_ports;
+
+	return reg_addr;
 }
 
 /*
- * The PCAL6534 and compatible chips have altered bank alignment that doesn't
- * fit within the bit shifting scheme used for other devices.
+ * Get the i2c address of register reg for line at offset.
+ *
+ * PCAL653X does not have padding between the register banks, unlike other chip
+ * types.
  */
-static u8 pcal6534_recalc_addr(struct pca953x_chip *chip, int reg, int off)
+static u8 pcal653x_reg_addr(struct pca953x_chip *chip, unsigned int reg,
+			    unsigned int offset)
 {
-	int addr;
-	int pinctrl;
-
-	addr = (reg & PCAL_GPIO_MASK) * NBANK(chip);
-
-	switch (reg) {
-	case PCAL953X_OUT_STRENGTH:
-	case PCAL953X_IN_LATCH:
-	case PCAL953X_PULL_EN:
-	case PCAL953X_PULL_SEL:
-	case PCAL953X_INT_MASK:
-	case PCAL953X_INT_STAT:
-		pinctrl = ((reg & PCAL_PINCTRL_MASK) >> 1) + 0x20;
-		break;
-	case PCAL6524_INT_EDGE:
-	case PCAL6524_INT_CLR:
-	case PCAL6524_IN_STATUS:
-	case PCAL6524_OUT_INDCONF:
-	case PCAL6524_DEBOUNCE:
-		pinctrl = ((reg & PCAL_PINCTRL_MASK) >> 1) + 0x1c;
-		break;
-	}
+	int bank_offset = NBANK(chip);
+	u8 reg_addr = pcal65xx_reg_addr_common(bank_offset, 0x30, reg, offset);
+	int num_debounce_ports = min(NBANK(chip), PCAL65XX_MAX_NUM_DEBOUNCE_PORTS);
+
+	/* Drive Mode is only one byte, not a full bank. */
+	if (reg > PCAL65XX_REG_DRIVE_MODE)
+		reg_addr -= (bank_offset - 1);
+
+	/* Debounce Count is only num_debounce_ports bytes long, not a full bank. */
+	if (reg == PCAL65XX_REG_DEBOUNCE_COUNT)
+		reg_addr -= bank_offset - num_debounce_ports;
 
-	return pinctrl + addr + (off / BANK_SZ);
+	return reg_addr;
 }
 
 static int pca953x_write_regs(struct pca953x_chip *chip, int reg, unsigned long *val)
 {
-	u8 regaddr = chip->recalc_addr(chip, reg, 0);
+	u8 regaddr = chip->reg_addr(chip, reg, 0);
 	u8 value[MAX_BANK];
 	int i, ret;
 
@@ -748,7 +1054,7 @@ static int pca953x_write_regs(struct pca953x_chip *chip, int reg, unsigned long
 
 static int pca953x_read_regs(struct pca953x_chip *chip, int reg, unsigned long *val)
 {
-	u8 regaddr = chip->recalc_addr(chip, reg, 0);
+	u8 regaddr = chip->reg_addr(chip, reg, 0);
 	u8 value[MAX_BANK];
 	int i, ret;
 
@@ -767,7 +1073,7 @@ static int pca953x_read_regs(struct pca953x_chip *chip, int reg, unsigned long *
 static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
 {
 	struct pca953x_chip *chip = gpiochip_get_data(gc);
-	u8 dirreg = chip->recalc_addr(chip, chip->regs->direction, off);
+	u8 dirreg = chip->reg_addr(chip, chip->regs->direction, off);
 	u8 bit = BIT(off % BANK_SZ);
 	int ret;
 
@@ -781,8 +1087,8 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
 		unsigned off, int val)
 {
 	struct pca953x_chip *chip = gpiochip_get_data(gc);
-	u8 dirreg = chip->recalc_addr(chip, chip->regs->direction, off);
-	u8 outreg = chip->recalc_addr(chip, chip->regs->output, off);
+	u8 dirreg = chip->reg_addr(chip, chip->regs->direction, off);
+	u8 outreg = chip->reg_addr(chip, chip->regs->output, off);
 	u8 bit = BIT(off % BANK_SZ);
 	int ret;
 
@@ -802,7 +1108,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
 static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
 {
 	struct pca953x_chip *chip = gpiochip_get_data(gc);
-	u8 inreg = chip->recalc_addr(chip, chip->regs->input, off);
+	u8 inreg = chip->reg_addr(chip, chip->regs->input, off);
 	u8 bit = BIT(off % BANK_SZ);
 	u32 reg_val;
 	int ret;
@@ -819,7 +1125,7 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
 static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
 {
 	struct pca953x_chip *chip = gpiochip_get_data(gc);
-	u8 outreg = chip->recalc_addr(chip, chip->regs->output, off);
+	u8 outreg = chip->reg_addr(chip, chip->regs->output, off);
 	u8 bit = BIT(off % BANK_SZ);
 
 	mutex_lock(&chip->i2c_lock);
@@ -830,7 +1136,7 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
 static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off)
 {
 	struct pca953x_chip *chip = gpiochip_get_data(gc);
-	u8 dirreg = chip->recalc_addr(chip, chip->regs->direction, off);
+	u8 dirreg = chip->reg_addr(chip, chip->regs->direction, off);
 	u8 bit = BIT(off % BANK_SZ);
 	u32 reg_val;
 	int ret;
@@ -889,8 +1195,8 @@ static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip,
 {
 	enum pin_config_param param = pinconf_to_config_param(config);
 
-	u8 pull_en_reg = chip->recalc_addr(chip, chip->regs->pull_en, offset);
-	u8 pull_sel_reg = chip->recalc_addr(chip, chip->regs->pull_sel, offset);
+	u8 pull_en_reg = chip->reg_addr(chip, chip->regs->pull_en, offset);
+	u8 pull_sel_reg = chip->reg_addr(chip, chip->regs->pull_sel, offset);
 	u8 bit = BIT(offset % BANK_SZ);
 	int ret;
 
@@ -1253,13 +1559,13 @@ static int device_pca95xx_init(struct pca953x_chip *chip, u32 invert)
 	u8 regaddr;
 	int ret;
 
-	regaddr = chip->recalc_addr(chip, chip->regs->output, 0);
+	regaddr = chip->reg_addr(chip, chip->regs->output, 0);
 	ret = regcache_sync_region(chip->regmap, regaddr,
 				   regaddr + NBANK(chip) - 1);
 	if (ret)
 		goto out;
 
-	regaddr = chip->recalc_addr(chip, chip->regs->direction, 0);
+	regaddr = chip->reg_addr(chip, chip->regs->direction, 0);
 	ret = regcache_sync_region(chip->regmap, regaddr,
 				   regaddr + NBANK(chip) - 1);
 	if (ret)
@@ -1404,12 +1710,23 @@ static int pca953x_probe(struct i2c_client *client)
 		break;
 	}
 
-	if (chip->type == TYPE_PCAL653X) {
-		chip->recalc_addr = pcal6534_recalc_addr;
-		chip->check_reg = pcal6534_check_register;
-	} else {
-		chip->recalc_addr = pca953x_recalc_addr;
-		chip->check_reg = pca953x_check_register;
+	switch (chip->type) {
+	case TYPE_PCAL953X:
+		chip->reg_addr = pcal953x_reg_addr;
+		chip->check_reg = pcal953x_check_reg;
+		break;
+	case TYPE_PCAL652X:
+		chip->reg_addr = pcal652x_reg_addr;
+		chip->check_reg = pcal652x_check_reg;
+		break;
+	case TYPE_PCAL653X:
+		chip->reg_addr = pcal653x_reg_addr;
+		chip->check_reg = pcal653x_check_reg;
+		break;
+	default:
+		chip->reg_addr = pca953x_reg_addr;
+		chip->check_reg = pca953x_check_reg;
+		break;
 	}
 
 	chip->regmap = devm_regmap_init_i2c(client, regmap_config);
@@ -1497,14 +1814,14 @@ static int pca953x_regcache_sync(struct device *dev)
 	 * The ordering between direction and output is important,
 	 * sync these registers first and only then sync the rest.
 	 */
-	regaddr = chip->recalc_addr(chip, chip->regs->direction, 0);
+	regaddr = chip->reg_addr(chip, chip->regs->direction, 0);
 	ret = regcache_sync_region(chip->regmap, regaddr, regaddr + NBANK(chip) - 1);
 	if (ret) {
 		dev_err(dev, "Failed to sync GPIO dir registers: %d\n", ret);
 		return ret;
 	}
 
-	regaddr = chip->recalc_addr(chip, chip->regs->output, 0);
+	regaddr = chip->reg_addr(chip, chip->regs->output, 0);
 	ret = regcache_sync_region(chip->regmap, regaddr, regaddr + NBANK(chip) - 1);
 	if (ret) {
 		dev_err(dev, "Failed to sync GPIO out registers: %d\n", ret);
@@ -1513,7 +1830,7 @@ static int pca953x_regcache_sync(struct device *dev)
 
 #ifdef CONFIG_GPIO_PCA953X_IRQ
 	if (pca953x_is_pcal_type(chip)) {
-		regaddr = chip->recalc_addr(chip, chip->regs->input_latch, 0);
+		regaddr = chip->reg_addr(chip, chip->regs->input_latch, 0);
 		ret = regcache_sync_region(chip->regmap, regaddr,
 					   regaddr + NBANK(chip) - 1);
 		if (ret) {
@@ -1522,7 +1839,7 @@ static int pca953x_regcache_sync(struct device *dev)
 			return ret;
 		}
 
-		regaddr = chip->recalc_addr(chip, chip->regs->int_mask, 0);
+		regaddr = chip->reg_addr(chip, chip->regs->int_mask, 0);
 		ret = regcache_sync_region(chip->regmap, regaddr,
 					   regaddr + NBANK(chip) - 1);
 		if (ret) {
-- 
2.38.1





[Index of Archives]     [Linux SPI]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux