162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * PCA953x 4/8/16/24/40 bit I/O ports 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> 662306a36Sopenharmony_ci * Copyright (C) 2007 Marvell International Ltd. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Derived from drivers/i2c/chips/pca9539.c 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/acpi.h> 1262306a36Sopenharmony_ci#include <linux/bitmap.h> 1362306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 1462306a36Sopenharmony_ci#include <linux/gpio/driver.h> 1562306a36Sopenharmony_ci#include <linux/i2c.h> 1662306a36Sopenharmony_ci#include <linux/init.h> 1762306a36Sopenharmony_ci#include <linux/interrupt.h> 1862306a36Sopenharmony_ci#include <linux/module.h> 1962306a36Sopenharmony_ci#include <linux/of_platform.h> 2062306a36Sopenharmony_ci#include <linux/platform_data/pca953x.h> 2162306a36Sopenharmony_ci#include <linux/regmap.h> 2262306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 2362306a36Sopenharmony_ci#include <linux/seq_file.h> 2462306a36Sopenharmony_ci#include <linux/slab.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include <asm/unaligned.h> 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define PCA953X_INPUT 0x00 2962306a36Sopenharmony_ci#define PCA953X_OUTPUT 0x01 3062306a36Sopenharmony_ci#define PCA953X_INVERT 0x02 3162306a36Sopenharmony_ci#define PCA953X_DIRECTION 0x03 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#define REG_ADDR_MASK GENMASK(5, 0) 3462306a36Sopenharmony_ci#define REG_ADDR_EXT BIT(6) 3562306a36Sopenharmony_ci#define REG_ADDR_AI BIT(7) 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define PCA957X_IN 0x00 3862306a36Sopenharmony_ci#define PCA957X_INVRT 0x01 3962306a36Sopenharmony_ci#define PCA957X_BKEN 0x02 4062306a36Sopenharmony_ci#define PCA957X_PUPD 0x03 4162306a36Sopenharmony_ci#define PCA957X_CFG 0x04 4262306a36Sopenharmony_ci#define PCA957X_OUT 0x05 4362306a36Sopenharmony_ci#define PCA957X_MSK 0x06 4462306a36Sopenharmony_ci#define PCA957X_INTS 0x07 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define PCAL953X_OUT_STRENGTH 0x20 4762306a36Sopenharmony_ci#define PCAL953X_IN_LATCH 0x22 4862306a36Sopenharmony_ci#define PCAL953X_PULL_EN 0x23 4962306a36Sopenharmony_ci#define PCAL953X_PULL_SEL 0x24 5062306a36Sopenharmony_ci#define PCAL953X_INT_MASK 0x25 5162306a36Sopenharmony_ci#define PCAL953X_INT_STAT 0x26 5262306a36Sopenharmony_ci#define PCAL953X_OUT_CONF 0x27 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#define PCAL6524_INT_EDGE 0x28 5562306a36Sopenharmony_ci#define PCAL6524_INT_CLR 0x2a 5662306a36Sopenharmony_ci#define PCAL6524_IN_STATUS 0x2b 5762306a36Sopenharmony_ci#define PCAL6524_OUT_INDCONF 0x2c 5862306a36Sopenharmony_ci#define PCAL6524_DEBOUNCE 0x2d 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#define PCA_GPIO_MASK GENMASK(7, 0) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define PCAL_GPIO_MASK GENMASK(4, 0) 6362306a36Sopenharmony_ci#define PCAL_PINCTRL_MASK GENMASK(6, 5) 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci#define PCA_INT BIT(8) 6662306a36Sopenharmony_ci#define PCA_PCAL BIT(9) 6762306a36Sopenharmony_ci#define PCA_LATCH_INT (PCA_PCAL | PCA_INT) 6862306a36Sopenharmony_ci#define PCA953X_TYPE BIT(12) 6962306a36Sopenharmony_ci#define PCA957X_TYPE BIT(13) 7062306a36Sopenharmony_ci#define PCAL653X_TYPE BIT(14) 7162306a36Sopenharmony_ci#define PCA_TYPE_MASK GENMASK(15, 12) 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci#define PCA_CHIP_TYPE(x) ((x) & PCA_TYPE_MASK) 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistatic const struct i2c_device_id pca953x_id[] = { 7662306a36Sopenharmony_ci { "pca6408", 8 | PCA953X_TYPE | PCA_INT, }, 7762306a36Sopenharmony_ci { "pca6416", 16 | PCA953X_TYPE | PCA_INT, }, 7862306a36Sopenharmony_ci { "pca9505", 40 | PCA953X_TYPE | PCA_INT, }, 7962306a36Sopenharmony_ci { "pca9506", 40 | PCA953X_TYPE | PCA_INT, }, 8062306a36Sopenharmony_ci { "pca9534", 8 | PCA953X_TYPE | PCA_INT, }, 8162306a36Sopenharmony_ci { "pca9535", 16 | PCA953X_TYPE | PCA_INT, }, 8262306a36Sopenharmony_ci { "pca9536", 4 | PCA953X_TYPE, }, 8362306a36Sopenharmony_ci { "pca9537", 4 | PCA953X_TYPE | PCA_INT, }, 8462306a36Sopenharmony_ci { "pca9538", 8 | PCA953X_TYPE | PCA_INT, }, 8562306a36Sopenharmony_ci { "pca9539", 16 | PCA953X_TYPE | PCA_INT, }, 8662306a36Sopenharmony_ci { "pca9554", 8 | PCA953X_TYPE | PCA_INT, }, 8762306a36Sopenharmony_ci { "pca9555", 16 | PCA953X_TYPE | PCA_INT, }, 8862306a36Sopenharmony_ci { "pca9556", 8 | PCA953X_TYPE, }, 8962306a36Sopenharmony_ci { "pca9557", 8 | PCA953X_TYPE, }, 9062306a36Sopenharmony_ci { "pca9574", 8 | PCA957X_TYPE | PCA_INT, }, 9162306a36Sopenharmony_ci { "pca9575", 16 | PCA957X_TYPE | PCA_INT, }, 9262306a36Sopenharmony_ci { "pca9698", 40 | PCA953X_TYPE, }, 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci { "pcal6408", 8 | PCA953X_TYPE | PCA_LATCH_INT, }, 9562306a36Sopenharmony_ci { "pcal6416", 16 | PCA953X_TYPE | PCA_LATCH_INT, }, 9662306a36Sopenharmony_ci { "pcal6524", 24 | PCA953X_TYPE | PCA_LATCH_INT, }, 9762306a36Sopenharmony_ci { "pcal6534", 34 | PCAL653X_TYPE | PCA_LATCH_INT, }, 9862306a36Sopenharmony_ci { "pcal9535", 16 | PCA953X_TYPE | PCA_LATCH_INT, }, 9962306a36Sopenharmony_ci { "pcal9554b", 8 | PCA953X_TYPE | PCA_LATCH_INT, }, 10062306a36Sopenharmony_ci { "pcal9555a", 16 | PCA953X_TYPE | PCA_LATCH_INT, }, 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci { "max7310", 8 | PCA953X_TYPE, }, 10362306a36Sopenharmony_ci { "max7312", 16 | PCA953X_TYPE | PCA_INT, }, 10462306a36Sopenharmony_ci { "max7313", 16 | PCA953X_TYPE | PCA_INT, }, 10562306a36Sopenharmony_ci { "max7315", 8 | PCA953X_TYPE | PCA_INT, }, 10662306a36Sopenharmony_ci { "max7318", 16 | PCA953X_TYPE | PCA_INT, }, 10762306a36Sopenharmony_ci { "pca6107", 8 | PCA953X_TYPE | PCA_INT, }, 10862306a36Sopenharmony_ci { "tca6408", 8 | PCA953X_TYPE | PCA_INT, }, 10962306a36Sopenharmony_ci { "tca6416", 16 | PCA953X_TYPE | PCA_INT, }, 11062306a36Sopenharmony_ci { "tca6424", 24 | PCA953X_TYPE | PCA_INT, }, 11162306a36Sopenharmony_ci { "tca9538", 8 | PCA953X_TYPE | PCA_INT, }, 11262306a36Sopenharmony_ci { "tca9539", 16 | PCA953X_TYPE | PCA_INT, }, 11362306a36Sopenharmony_ci { "tca9554", 8 | PCA953X_TYPE | PCA_INT, }, 11462306a36Sopenharmony_ci { "xra1202", 8 | PCA953X_TYPE }, 11562306a36Sopenharmony_ci { } 11662306a36Sopenharmony_ci}; 11762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, pca953x_id); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci#ifdef CONFIG_GPIO_PCA953X_IRQ 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci#include <linux/dmi.h> 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistatic const struct acpi_gpio_params pca953x_irq_gpios = { 0, 0, true }; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic const struct acpi_gpio_mapping pca953x_acpi_irq_gpios[] = { 12662306a36Sopenharmony_ci { "irq-gpios", &pca953x_irq_gpios, 1, ACPI_GPIO_QUIRK_ABSOLUTE_NUMBER }, 12762306a36Sopenharmony_ci { } 12862306a36Sopenharmony_ci}; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistatic int pca953x_acpi_get_irq(struct device *dev) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci int ret; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci ret = devm_acpi_dev_add_driver_gpios(dev, pca953x_acpi_irq_gpios); 13562306a36Sopenharmony_ci if (ret) 13662306a36Sopenharmony_ci dev_warn(dev, "can't add GPIO ACPI mapping\n"); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci ret = acpi_dev_gpio_irq_get_by(ACPI_COMPANION(dev), "irq-gpios", 0); 13962306a36Sopenharmony_ci if (ret < 0) 14062306a36Sopenharmony_ci return ret; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci dev_info(dev, "ACPI interrupt quirk (IRQ %d)\n", ret); 14362306a36Sopenharmony_ci return ret; 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic const struct dmi_system_id pca953x_dmi_acpi_irq_info[] = { 14762306a36Sopenharmony_ci { 14862306a36Sopenharmony_ci /* 14962306a36Sopenharmony_ci * On Intel Galileo Gen 2 board the IRQ pin of one of 15062306a36Sopenharmony_ci * the I²C GPIO expanders, which has GpioInt() resource, 15162306a36Sopenharmony_ci * is provided as an absolute number instead of being 15262306a36Sopenharmony_ci * relative. Since first controller (gpio-sch.c) and 15362306a36Sopenharmony_ci * second (gpio-dwapb.c) are at the fixed bases, we may 15462306a36Sopenharmony_ci * safely refer to the number in the global space to get 15562306a36Sopenharmony_ci * an IRQ out of it. 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_ci .matches = { 15862306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "GalileoGen2"), 15962306a36Sopenharmony_ci }, 16062306a36Sopenharmony_ci }, 16162306a36Sopenharmony_ci {} 16262306a36Sopenharmony_ci}; 16362306a36Sopenharmony_ci#endif 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic const struct acpi_device_id pca953x_acpi_ids[] = { 16662306a36Sopenharmony_ci { "INT3491", 16 | PCA953X_TYPE | PCA_LATCH_INT, }, 16762306a36Sopenharmony_ci { } 16862306a36Sopenharmony_ci}; 16962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci#define MAX_BANK 5 17262306a36Sopenharmony_ci#define BANK_SZ 8 17362306a36Sopenharmony_ci#define MAX_LINE (MAX_BANK * BANK_SZ) 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci#define NBANK(chip) DIV_ROUND_UP(chip->gpio_chip.ngpio, BANK_SZ) 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistruct pca953x_reg_config { 17862306a36Sopenharmony_ci int direction; 17962306a36Sopenharmony_ci int output; 18062306a36Sopenharmony_ci int input; 18162306a36Sopenharmony_ci int invert; 18262306a36Sopenharmony_ci}; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistatic const struct pca953x_reg_config pca953x_regs = { 18562306a36Sopenharmony_ci .direction = PCA953X_DIRECTION, 18662306a36Sopenharmony_ci .output = PCA953X_OUTPUT, 18762306a36Sopenharmony_ci .input = PCA953X_INPUT, 18862306a36Sopenharmony_ci .invert = PCA953X_INVERT, 18962306a36Sopenharmony_ci}; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cistatic const struct pca953x_reg_config pca957x_regs = { 19262306a36Sopenharmony_ci .direction = PCA957X_CFG, 19362306a36Sopenharmony_ci .output = PCA957X_OUT, 19462306a36Sopenharmony_ci .input = PCA957X_IN, 19562306a36Sopenharmony_ci .invert = PCA957X_INVRT, 19662306a36Sopenharmony_ci}; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cistruct pca953x_chip { 19962306a36Sopenharmony_ci unsigned gpio_start; 20062306a36Sopenharmony_ci struct mutex i2c_lock; 20162306a36Sopenharmony_ci struct regmap *regmap; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci#ifdef CONFIG_GPIO_PCA953X_IRQ 20462306a36Sopenharmony_ci struct mutex irq_lock; 20562306a36Sopenharmony_ci DECLARE_BITMAP(irq_mask, MAX_LINE); 20662306a36Sopenharmony_ci DECLARE_BITMAP(irq_stat, MAX_LINE); 20762306a36Sopenharmony_ci DECLARE_BITMAP(irq_trig_raise, MAX_LINE); 20862306a36Sopenharmony_ci DECLARE_BITMAP(irq_trig_fall, MAX_LINE); 20962306a36Sopenharmony_ci#endif 21062306a36Sopenharmony_ci atomic_t wakeup_path; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci struct i2c_client *client; 21362306a36Sopenharmony_ci struct gpio_chip gpio_chip; 21462306a36Sopenharmony_ci const char *const *names; 21562306a36Sopenharmony_ci unsigned long driver_data; 21662306a36Sopenharmony_ci struct regulator *regulator; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci const struct pca953x_reg_config *regs; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci u8 (*recalc_addr)(struct pca953x_chip *chip, int reg, int off); 22162306a36Sopenharmony_ci bool (*check_reg)(struct pca953x_chip *chip, unsigned int reg, 22262306a36Sopenharmony_ci u32 checkbank); 22362306a36Sopenharmony_ci}; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cistatic int pca953x_bank_shift(struct pca953x_chip *chip) 22662306a36Sopenharmony_ci{ 22762306a36Sopenharmony_ci return fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); 22862306a36Sopenharmony_ci} 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci#define PCA953x_BANK_INPUT BIT(0) 23162306a36Sopenharmony_ci#define PCA953x_BANK_OUTPUT BIT(1) 23262306a36Sopenharmony_ci#define PCA953x_BANK_POLARITY BIT(2) 23362306a36Sopenharmony_ci#define PCA953x_BANK_CONFIG BIT(3) 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci#define PCA957x_BANK_INPUT BIT(0) 23662306a36Sopenharmony_ci#define PCA957x_BANK_POLARITY BIT(1) 23762306a36Sopenharmony_ci#define PCA957x_BANK_BUSHOLD BIT(2) 23862306a36Sopenharmony_ci#define PCA957x_BANK_CONFIG BIT(4) 23962306a36Sopenharmony_ci#define PCA957x_BANK_OUTPUT BIT(5) 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci#define PCAL9xxx_BANK_IN_LATCH BIT(8 + 2) 24262306a36Sopenharmony_ci#define PCAL9xxx_BANK_PULL_EN BIT(8 + 3) 24362306a36Sopenharmony_ci#define PCAL9xxx_BANK_PULL_SEL BIT(8 + 4) 24462306a36Sopenharmony_ci#define PCAL9xxx_BANK_IRQ_MASK BIT(8 + 5) 24562306a36Sopenharmony_ci#define PCAL9xxx_BANK_IRQ_STAT BIT(8 + 6) 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci/* 24862306a36Sopenharmony_ci * We care about the following registers: 24962306a36Sopenharmony_ci * - Standard set, below 0x40, each port can be replicated up to 8 times 25062306a36Sopenharmony_ci * - PCA953x standard 25162306a36Sopenharmony_ci * Input port 0x00 + 0 * bank_size R 25262306a36Sopenharmony_ci * Output port 0x00 + 1 * bank_size RW 25362306a36Sopenharmony_ci * Polarity Inversion port 0x00 + 2 * bank_size RW 25462306a36Sopenharmony_ci * Configuration port 0x00 + 3 * bank_size RW 25562306a36Sopenharmony_ci * - PCA957x with mixed up registers 25662306a36Sopenharmony_ci * Input port 0x00 + 0 * bank_size R 25762306a36Sopenharmony_ci * Polarity Inversion port 0x00 + 1 * bank_size RW 25862306a36Sopenharmony_ci * Bus hold port 0x00 + 2 * bank_size RW 25962306a36Sopenharmony_ci * Configuration port 0x00 + 4 * bank_size RW 26062306a36Sopenharmony_ci * Output port 0x00 + 5 * bank_size RW 26162306a36Sopenharmony_ci * 26262306a36Sopenharmony_ci * - Extended set, above 0x40, often chip specific. 26362306a36Sopenharmony_ci * - PCAL6524/PCAL9555A with custom PCAL IRQ handling: 26462306a36Sopenharmony_ci * Input latch register 0x40 + 2 * bank_size RW 26562306a36Sopenharmony_ci * Pull-up/pull-down enable reg 0x40 + 3 * bank_size RW 26662306a36Sopenharmony_ci * Pull-up/pull-down select reg 0x40 + 4 * bank_size RW 26762306a36Sopenharmony_ci * Interrupt mask register 0x40 + 5 * bank_size RW 26862306a36Sopenharmony_ci * Interrupt status register 0x40 + 6 * bank_size R 26962306a36Sopenharmony_ci * 27062306a36Sopenharmony_ci * - Registers with bit 0x80 set, the AI bit 27162306a36Sopenharmony_ci * The bit is cleared and the registers fall into one of the 27262306a36Sopenharmony_ci * categories above. 27362306a36Sopenharmony_ci */ 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_cistatic bool pca953x_check_register(struct pca953x_chip *chip, unsigned int reg, 27662306a36Sopenharmony_ci u32 checkbank) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci int bank_shift = pca953x_bank_shift(chip); 27962306a36Sopenharmony_ci int bank = (reg & REG_ADDR_MASK) >> bank_shift; 28062306a36Sopenharmony_ci int offset = reg & (BIT(bank_shift) - 1); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci /* Special PCAL extended register check. */ 28362306a36Sopenharmony_ci if (reg & REG_ADDR_EXT) { 28462306a36Sopenharmony_ci if (!(chip->driver_data & PCA_PCAL)) 28562306a36Sopenharmony_ci return false; 28662306a36Sopenharmony_ci bank += 8; 28762306a36Sopenharmony_ci } 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci /* Register is not in the matching bank. */ 29062306a36Sopenharmony_ci if (!(BIT(bank) & checkbank)) 29162306a36Sopenharmony_ci return false; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci /* Register is not within allowed range of bank. */ 29462306a36Sopenharmony_ci if (offset >= NBANK(chip)) 29562306a36Sopenharmony_ci return false; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci return true; 29862306a36Sopenharmony_ci} 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci/* 30162306a36Sopenharmony_ci * Unfortunately, whilst the PCAL6534 chip (and compatibles) broadly follow the 30262306a36Sopenharmony_ci * same register layout as the PCAL6524, the spacing of the registers has been 30362306a36Sopenharmony_ci * fundamentally altered by compacting them and thus does not obey the same 30462306a36Sopenharmony_ci * rules, including being able to use bit shifting to determine bank. These 30562306a36Sopenharmony_ci * chips hence need special handling here. 30662306a36Sopenharmony_ci */ 30762306a36Sopenharmony_cistatic bool pcal6534_check_register(struct pca953x_chip *chip, unsigned int reg, 30862306a36Sopenharmony_ci u32 checkbank) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci int bank_shift; 31162306a36Sopenharmony_ci int bank; 31262306a36Sopenharmony_ci int offset; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci if (reg >= 0x54) { 31562306a36Sopenharmony_ci /* 31662306a36Sopenharmony_ci * Handle lack of reserved registers after output port 31762306a36Sopenharmony_ci * configuration register to form a bank. 31862306a36Sopenharmony_ci */ 31962306a36Sopenharmony_ci reg -= 0x54; 32062306a36Sopenharmony_ci bank_shift = 16; 32162306a36Sopenharmony_ci } else if (reg >= 0x30) { 32262306a36Sopenharmony_ci /* 32362306a36Sopenharmony_ci * Reserved block between 14h and 2Fh does not align on 32462306a36Sopenharmony_ci * expected bank boundaries like other devices. 32562306a36Sopenharmony_ci */ 32662306a36Sopenharmony_ci reg -= 0x30; 32762306a36Sopenharmony_ci bank_shift = 8; 32862306a36Sopenharmony_ci } else { 32962306a36Sopenharmony_ci bank_shift = 0; 33062306a36Sopenharmony_ci } 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci bank = bank_shift + reg / NBANK(chip); 33362306a36Sopenharmony_ci offset = reg % NBANK(chip); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci /* Register is not in the matching bank. */ 33662306a36Sopenharmony_ci if (!(BIT(bank) & checkbank)) 33762306a36Sopenharmony_ci return false; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci /* Register is not within allowed range of bank. */ 34062306a36Sopenharmony_ci if (offset >= NBANK(chip)) 34162306a36Sopenharmony_ci return false; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci return true; 34462306a36Sopenharmony_ci} 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_cistatic bool pca953x_readable_register(struct device *dev, unsigned int reg) 34762306a36Sopenharmony_ci{ 34862306a36Sopenharmony_ci struct pca953x_chip *chip = dev_get_drvdata(dev); 34962306a36Sopenharmony_ci u32 bank; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci if (PCA_CHIP_TYPE(chip->driver_data) == PCA957X_TYPE) { 35262306a36Sopenharmony_ci bank = PCA957x_BANK_INPUT | PCA957x_BANK_OUTPUT | 35362306a36Sopenharmony_ci PCA957x_BANK_POLARITY | PCA957x_BANK_CONFIG | 35462306a36Sopenharmony_ci PCA957x_BANK_BUSHOLD; 35562306a36Sopenharmony_ci } else { 35662306a36Sopenharmony_ci bank = PCA953x_BANK_INPUT | PCA953x_BANK_OUTPUT | 35762306a36Sopenharmony_ci PCA953x_BANK_POLARITY | PCA953x_BANK_CONFIG; 35862306a36Sopenharmony_ci } 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci if (chip->driver_data & PCA_PCAL) { 36162306a36Sopenharmony_ci bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_PULL_EN | 36262306a36Sopenharmony_ci PCAL9xxx_BANK_PULL_SEL | PCAL9xxx_BANK_IRQ_MASK | 36362306a36Sopenharmony_ci PCAL9xxx_BANK_IRQ_STAT; 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci return chip->check_reg(chip, reg, bank); 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistatic bool pca953x_writeable_register(struct device *dev, unsigned int reg) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci struct pca953x_chip *chip = dev_get_drvdata(dev); 37262306a36Sopenharmony_ci u32 bank; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci if (PCA_CHIP_TYPE(chip->driver_data) == PCA957X_TYPE) { 37562306a36Sopenharmony_ci bank = PCA957x_BANK_OUTPUT | PCA957x_BANK_POLARITY | 37662306a36Sopenharmony_ci PCA957x_BANK_CONFIG | PCA957x_BANK_BUSHOLD; 37762306a36Sopenharmony_ci } else { 37862306a36Sopenharmony_ci bank = PCA953x_BANK_OUTPUT | PCA953x_BANK_POLARITY | 37962306a36Sopenharmony_ci PCA953x_BANK_CONFIG; 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci if (chip->driver_data & PCA_PCAL) 38362306a36Sopenharmony_ci bank |= PCAL9xxx_BANK_IN_LATCH | PCAL9xxx_BANK_PULL_EN | 38462306a36Sopenharmony_ci PCAL9xxx_BANK_PULL_SEL | PCAL9xxx_BANK_IRQ_MASK; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci return chip->check_reg(chip, reg, bank); 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_cistatic bool pca953x_volatile_register(struct device *dev, unsigned int reg) 39062306a36Sopenharmony_ci{ 39162306a36Sopenharmony_ci struct pca953x_chip *chip = dev_get_drvdata(dev); 39262306a36Sopenharmony_ci u32 bank; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci if (PCA_CHIP_TYPE(chip->driver_data) == PCA957X_TYPE) 39562306a36Sopenharmony_ci bank = PCA957x_BANK_INPUT; 39662306a36Sopenharmony_ci else 39762306a36Sopenharmony_ci bank = PCA953x_BANK_INPUT; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci if (chip->driver_data & PCA_PCAL) 40062306a36Sopenharmony_ci bank |= PCAL9xxx_BANK_IRQ_STAT; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci return chip->check_reg(chip, reg, bank); 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cistatic const struct regmap_config pca953x_i2c_regmap = { 40662306a36Sopenharmony_ci .reg_bits = 8, 40762306a36Sopenharmony_ci .val_bits = 8, 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci .use_single_read = true, 41062306a36Sopenharmony_ci .use_single_write = true, 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci .readable_reg = pca953x_readable_register, 41362306a36Sopenharmony_ci .writeable_reg = pca953x_writeable_register, 41462306a36Sopenharmony_ci .volatile_reg = pca953x_volatile_register, 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci .disable_locking = true, 41762306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 41862306a36Sopenharmony_ci .max_register = 0x7f, 41962306a36Sopenharmony_ci}; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_cistatic const struct regmap_config pca953x_ai_i2c_regmap = { 42262306a36Sopenharmony_ci .reg_bits = 8, 42362306a36Sopenharmony_ci .val_bits = 8, 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci .read_flag_mask = REG_ADDR_AI, 42662306a36Sopenharmony_ci .write_flag_mask = REG_ADDR_AI, 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci .readable_reg = pca953x_readable_register, 42962306a36Sopenharmony_ci .writeable_reg = pca953x_writeable_register, 43062306a36Sopenharmony_ci .volatile_reg = pca953x_volatile_register, 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci .disable_locking = true, 43362306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 43462306a36Sopenharmony_ci .max_register = 0x7f, 43562306a36Sopenharmony_ci}; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistatic u8 pca953x_recalc_addr(struct pca953x_chip *chip, int reg, int off) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci int bank_shift = pca953x_bank_shift(chip); 44062306a36Sopenharmony_ci int addr = (reg & PCAL_GPIO_MASK) << bank_shift; 44162306a36Sopenharmony_ci int pinctrl = (reg & PCAL_PINCTRL_MASK) << 1; 44262306a36Sopenharmony_ci u8 regaddr = pinctrl | addr | (off / BANK_SZ); 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci return regaddr; 44562306a36Sopenharmony_ci} 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci/* 44862306a36Sopenharmony_ci * The PCAL6534 and compatible chips have altered bank alignment that doesn't 44962306a36Sopenharmony_ci * fit within the bit shifting scheme used for other devices. 45062306a36Sopenharmony_ci */ 45162306a36Sopenharmony_cistatic u8 pcal6534_recalc_addr(struct pca953x_chip *chip, int reg, int off) 45262306a36Sopenharmony_ci{ 45362306a36Sopenharmony_ci int addr; 45462306a36Sopenharmony_ci int pinctrl; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci addr = (reg & PCAL_GPIO_MASK) * NBANK(chip); 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci switch (reg) { 45962306a36Sopenharmony_ci case PCAL953X_OUT_STRENGTH: 46062306a36Sopenharmony_ci case PCAL953X_IN_LATCH: 46162306a36Sopenharmony_ci case PCAL953X_PULL_EN: 46262306a36Sopenharmony_ci case PCAL953X_PULL_SEL: 46362306a36Sopenharmony_ci case PCAL953X_INT_MASK: 46462306a36Sopenharmony_ci case PCAL953X_INT_STAT: 46562306a36Sopenharmony_ci pinctrl = ((reg & PCAL_PINCTRL_MASK) >> 1) + 0x20; 46662306a36Sopenharmony_ci break; 46762306a36Sopenharmony_ci case PCAL6524_INT_EDGE: 46862306a36Sopenharmony_ci case PCAL6524_INT_CLR: 46962306a36Sopenharmony_ci case PCAL6524_IN_STATUS: 47062306a36Sopenharmony_ci case PCAL6524_OUT_INDCONF: 47162306a36Sopenharmony_ci case PCAL6524_DEBOUNCE: 47262306a36Sopenharmony_ci pinctrl = ((reg & PCAL_PINCTRL_MASK) >> 1) + 0x1c; 47362306a36Sopenharmony_ci break; 47462306a36Sopenharmony_ci default: 47562306a36Sopenharmony_ci pinctrl = 0; 47662306a36Sopenharmony_ci break; 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci return pinctrl + addr + (off / BANK_SZ); 48062306a36Sopenharmony_ci} 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_cistatic int pca953x_write_regs(struct pca953x_chip *chip, int reg, unsigned long *val) 48362306a36Sopenharmony_ci{ 48462306a36Sopenharmony_ci u8 regaddr = chip->recalc_addr(chip, reg, 0); 48562306a36Sopenharmony_ci u8 value[MAX_BANK]; 48662306a36Sopenharmony_ci int i, ret; 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci for (i = 0; i < NBANK(chip); i++) 48962306a36Sopenharmony_ci value[i] = bitmap_get_value8(val, i * BANK_SZ); 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci ret = regmap_bulk_write(chip->regmap, regaddr, value, NBANK(chip)); 49262306a36Sopenharmony_ci if (ret < 0) { 49362306a36Sopenharmony_ci dev_err(&chip->client->dev, "failed writing register\n"); 49462306a36Sopenharmony_ci return ret; 49562306a36Sopenharmony_ci } 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci return 0; 49862306a36Sopenharmony_ci} 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_cistatic int pca953x_read_regs(struct pca953x_chip *chip, int reg, unsigned long *val) 50162306a36Sopenharmony_ci{ 50262306a36Sopenharmony_ci u8 regaddr = chip->recalc_addr(chip, reg, 0); 50362306a36Sopenharmony_ci u8 value[MAX_BANK]; 50462306a36Sopenharmony_ci int i, ret; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci ret = regmap_bulk_read(chip->regmap, regaddr, value, NBANK(chip)); 50762306a36Sopenharmony_ci if (ret < 0) { 50862306a36Sopenharmony_ci dev_err(&chip->client->dev, "failed reading register\n"); 50962306a36Sopenharmony_ci return ret; 51062306a36Sopenharmony_ci } 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci for (i = 0; i < NBANK(chip); i++) 51362306a36Sopenharmony_ci bitmap_set_value8(val, value[i], i * BANK_SZ); 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci return 0; 51662306a36Sopenharmony_ci} 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_cistatic int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) 51962306a36Sopenharmony_ci{ 52062306a36Sopenharmony_ci struct pca953x_chip *chip = gpiochip_get_data(gc); 52162306a36Sopenharmony_ci u8 dirreg = chip->recalc_addr(chip, chip->regs->direction, off); 52262306a36Sopenharmony_ci u8 bit = BIT(off % BANK_SZ); 52362306a36Sopenharmony_ci int ret; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci mutex_lock(&chip->i2c_lock); 52662306a36Sopenharmony_ci ret = regmap_write_bits(chip->regmap, dirreg, bit, bit); 52762306a36Sopenharmony_ci mutex_unlock(&chip->i2c_lock); 52862306a36Sopenharmony_ci return ret; 52962306a36Sopenharmony_ci} 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_cistatic int pca953x_gpio_direction_output(struct gpio_chip *gc, 53262306a36Sopenharmony_ci unsigned off, int val) 53362306a36Sopenharmony_ci{ 53462306a36Sopenharmony_ci struct pca953x_chip *chip = gpiochip_get_data(gc); 53562306a36Sopenharmony_ci u8 dirreg = chip->recalc_addr(chip, chip->regs->direction, off); 53662306a36Sopenharmony_ci u8 outreg = chip->recalc_addr(chip, chip->regs->output, off); 53762306a36Sopenharmony_ci u8 bit = BIT(off % BANK_SZ); 53862306a36Sopenharmony_ci int ret; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci mutex_lock(&chip->i2c_lock); 54162306a36Sopenharmony_ci /* set output level */ 54262306a36Sopenharmony_ci ret = regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0); 54362306a36Sopenharmony_ci if (ret) 54462306a36Sopenharmony_ci goto exit; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci /* then direction */ 54762306a36Sopenharmony_ci ret = regmap_write_bits(chip->regmap, dirreg, bit, 0); 54862306a36Sopenharmony_ciexit: 54962306a36Sopenharmony_ci mutex_unlock(&chip->i2c_lock); 55062306a36Sopenharmony_ci return ret; 55162306a36Sopenharmony_ci} 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_cistatic int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) 55462306a36Sopenharmony_ci{ 55562306a36Sopenharmony_ci struct pca953x_chip *chip = gpiochip_get_data(gc); 55662306a36Sopenharmony_ci u8 inreg = chip->recalc_addr(chip, chip->regs->input, off); 55762306a36Sopenharmony_ci u8 bit = BIT(off % BANK_SZ); 55862306a36Sopenharmony_ci u32 reg_val; 55962306a36Sopenharmony_ci int ret; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci mutex_lock(&chip->i2c_lock); 56262306a36Sopenharmony_ci ret = regmap_read(chip->regmap, inreg, ®_val); 56362306a36Sopenharmony_ci mutex_unlock(&chip->i2c_lock); 56462306a36Sopenharmony_ci if (ret < 0) 56562306a36Sopenharmony_ci return ret; 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci return !!(reg_val & bit); 56862306a36Sopenharmony_ci} 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_cistatic void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) 57162306a36Sopenharmony_ci{ 57262306a36Sopenharmony_ci struct pca953x_chip *chip = gpiochip_get_data(gc); 57362306a36Sopenharmony_ci u8 outreg = chip->recalc_addr(chip, chip->regs->output, off); 57462306a36Sopenharmony_ci u8 bit = BIT(off % BANK_SZ); 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci mutex_lock(&chip->i2c_lock); 57762306a36Sopenharmony_ci regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0); 57862306a36Sopenharmony_ci mutex_unlock(&chip->i2c_lock); 57962306a36Sopenharmony_ci} 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_cistatic int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off) 58262306a36Sopenharmony_ci{ 58362306a36Sopenharmony_ci struct pca953x_chip *chip = gpiochip_get_data(gc); 58462306a36Sopenharmony_ci u8 dirreg = chip->recalc_addr(chip, chip->regs->direction, off); 58562306a36Sopenharmony_ci u8 bit = BIT(off % BANK_SZ); 58662306a36Sopenharmony_ci u32 reg_val; 58762306a36Sopenharmony_ci int ret; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci mutex_lock(&chip->i2c_lock); 59062306a36Sopenharmony_ci ret = regmap_read(chip->regmap, dirreg, ®_val); 59162306a36Sopenharmony_ci mutex_unlock(&chip->i2c_lock); 59262306a36Sopenharmony_ci if (ret < 0) 59362306a36Sopenharmony_ci return ret; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci if (reg_val & bit) 59662306a36Sopenharmony_ci return GPIO_LINE_DIRECTION_IN; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci return GPIO_LINE_DIRECTION_OUT; 59962306a36Sopenharmony_ci} 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_cistatic int pca953x_gpio_get_multiple(struct gpio_chip *gc, 60262306a36Sopenharmony_ci unsigned long *mask, unsigned long *bits) 60362306a36Sopenharmony_ci{ 60462306a36Sopenharmony_ci struct pca953x_chip *chip = gpiochip_get_data(gc); 60562306a36Sopenharmony_ci DECLARE_BITMAP(reg_val, MAX_LINE); 60662306a36Sopenharmony_ci int ret; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci mutex_lock(&chip->i2c_lock); 60962306a36Sopenharmony_ci ret = pca953x_read_regs(chip, chip->regs->input, reg_val); 61062306a36Sopenharmony_ci mutex_unlock(&chip->i2c_lock); 61162306a36Sopenharmony_ci if (ret) 61262306a36Sopenharmony_ci return ret; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci bitmap_replace(bits, bits, reg_val, mask, gc->ngpio); 61562306a36Sopenharmony_ci return 0; 61662306a36Sopenharmony_ci} 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_cistatic void pca953x_gpio_set_multiple(struct gpio_chip *gc, 61962306a36Sopenharmony_ci unsigned long *mask, unsigned long *bits) 62062306a36Sopenharmony_ci{ 62162306a36Sopenharmony_ci struct pca953x_chip *chip = gpiochip_get_data(gc); 62262306a36Sopenharmony_ci DECLARE_BITMAP(reg_val, MAX_LINE); 62362306a36Sopenharmony_ci int ret; 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci mutex_lock(&chip->i2c_lock); 62662306a36Sopenharmony_ci ret = pca953x_read_regs(chip, chip->regs->output, reg_val); 62762306a36Sopenharmony_ci if (ret) 62862306a36Sopenharmony_ci goto exit; 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci bitmap_replace(reg_val, reg_val, bits, mask, gc->ngpio); 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci pca953x_write_regs(chip, chip->regs->output, reg_val); 63362306a36Sopenharmony_ciexit: 63462306a36Sopenharmony_ci mutex_unlock(&chip->i2c_lock); 63562306a36Sopenharmony_ci} 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_cistatic int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip, 63862306a36Sopenharmony_ci unsigned int offset, 63962306a36Sopenharmony_ci unsigned long config) 64062306a36Sopenharmony_ci{ 64162306a36Sopenharmony_ci enum pin_config_param param = pinconf_to_config_param(config); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci u8 pull_en_reg = chip->recalc_addr(chip, PCAL953X_PULL_EN, offset); 64462306a36Sopenharmony_ci u8 pull_sel_reg = chip->recalc_addr(chip, PCAL953X_PULL_SEL, offset); 64562306a36Sopenharmony_ci u8 bit = BIT(offset % BANK_SZ); 64662306a36Sopenharmony_ci int ret; 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci /* 64962306a36Sopenharmony_ci * pull-up/pull-down configuration requires PCAL extended 65062306a36Sopenharmony_ci * registers 65162306a36Sopenharmony_ci */ 65262306a36Sopenharmony_ci if (!(chip->driver_data & PCA_PCAL)) 65362306a36Sopenharmony_ci return -ENOTSUPP; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci mutex_lock(&chip->i2c_lock); 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci /* Configure pull-up/pull-down */ 65862306a36Sopenharmony_ci if (param == PIN_CONFIG_BIAS_PULL_UP) 65962306a36Sopenharmony_ci ret = regmap_write_bits(chip->regmap, pull_sel_reg, bit, bit); 66062306a36Sopenharmony_ci else if (param == PIN_CONFIG_BIAS_PULL_DOWN) 66162306a36Sopenharmony_ci ret = regmap_write_bits(chip->regmap, pull_sel_reg, bit, 0); 66262306a36Sopenharmony_ci else 66362306a36Sopenharmony_ci ret = 0; 66462306a36Sopenharmony_ci if (ret) 66562306a36Sopenharmony_ci goto exit; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci /* Disable/Enable pull-up/pull-down */ 66862306a36Sopenharmony_ci if (param == PIN_CONFIG_BIAS_DISABLE) 66962306a36Sopenharmony_ci ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, 0); 67062306a36Sopenharmony_ci else 67162306a36Sopenharmony_ci ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, bit); 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ciexit: 67462306a36Sopenharmony_ci mutex_unlock(&chip->i2c_lock); 67562306a36Sopenharmony_ci return ret; 67662306a36Sopenharmony_ci} 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_cistatic int pca953x_gpio_set_config(struct gpio_chip *gc, unsigned int offset, 67962306a36Sopenharmony_ci unsigned long config) 68062306a36Sopenharmony_ci{ 68162306a36Sopenharmony_ci struct pca953x_chip *chip = gpiochip_get_data(gc); 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci switch (pinconf_to_config_param(config)) { 68462306a36Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_UP: 68562306a36Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: 68662306a36Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_DOWN: 68762306a36Sopenharmony_ci case PIN_CONFIG_BIAS_DISABLE: 68862306a36Sopenharmony_ci return pca953x_gpio_set_pull_up_down(chip, offset, config); 68962306a36Sopenharmony_ci default: 69062306a36Sopenharmony_ci return -ENOTSUPP; 69162306a36Sopenharmony_ci } 69262306a36Sopenharmony_ci} 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_cistatic void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) 69562306a36Sopenharmony_ci{ 69662306a36Sopenharmony_ci struct gpio_chip *gc; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci gc = &chip->gpio_chip; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci gc->direction_input = pca953x_gpio_direction_input; 70162306a36Sopenharmony_ci gc->direction_output = pca953x_gpio_direction_output; 70262306a36Sopenharmony_ci gc->get = pca953x_gpio_get_value; 70362306a36Sopenharmony_ci gc->set = pca953x_gpio_set_value; 70462306a36Sopenharmony_ci gc->get_direction = pca953x_gpio_get_direction; 70562306a36Sopenharmony_ci gc->get_multiple = pca953x_gpio_get_multiple; 70662306a36Sopenharmony_ci gc->set_multiple = pca953x_gpio_set_multiple; 70762306a36Sopenharmony_ci gc->set_config = pca953x_gpio_set_config; 70862306a36Sopenharmony_ci gc->can_sleep = true; 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci gc->base = chip->gpio_start; 71162306a36Sopenharmony_ci gc->ngpio = gpios; 71262306a36Sopenharmony_ci gc->label = dev_name(&chip->client->dev); 71362306a36Sopenharmony_ci gc->parent = &chip->client->dev; 71462306a36Sopenharmony_ci gc->owner = THIS_MODULE; 71562306a36Sopenharmony_ci gc->names = chip->names; 71662306a36Sopenharmony_ci} 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci#ifdef CONFIG_GPIO_PCA953X_IRQ 71962306a36Sopenharmony_cistatic void pca953x_irq_mask(struct irq_data *d) 72062306a36Sopenharmony_ci{ 72162306a36Sopenharmony_ci struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 72262306a36Sopenharmony_ci struct pca953x_chip *chip = gpiochip_get_data(gc); 72362306a36Sopenharmony_ci irq_hw_number_t hwirq = irqd_to_hwirq(d); 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci clear_bit(hwirq, chip->irq_mask); 72662306a36Sopenharmony_ci gpiochip_disable_irq(gc, hwirq); 72762306a36Sopenharmony_ci} 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_cistatic void pca953x_irq_unmask(struct irq_data *d) 73062306a36Sopenharmony_ci{ 73162306a36Sopenharmony_ci struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 73262306a36Sopenharmony_ci struct pca953x_chip *chip = gpiochip_get_data(gc); 73362306a36Sopenharmony_ci irq_hw_number_t hwirq = irqd_to_hwirq(d); 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci gpiochip_enable_irq(gc, hwirq); 73662306a36Sopenharmony_ci set_bit(hwirq, chip->irq_mask); 73762306a36Sopenharmony_ci} 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_cistatic int pca953x_irq_set_wake(struct irq_data *d, unsigned int on) 74062306a36Sopenharmony_ci{ 74162306a36Sopenharmony_ci struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 74262306a36Sopenharmony_ci struct pca953x_chip *chip = gpiochip_get_data(gc); 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci if (on) 74562306a36Sopenharmony_ci atomic_inc(&chip->wakeup_path); 74662306a36Sopenharmony_ci else 74762306a36Sopenharmony_ci atomic_dec(&chip->wakeup_path); 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci return irq_set_irq_wake(chip->client->irq, on); 75062306a36Sopenharmony_ci} 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_cistatic void pca953x_irq_bus_lock(struct irq_data *d) 75362306a36Sopenharmony_ci{ 75462306a36Sopenharmony_ci struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 75562306a36Sopenharmony_ci struct pca953x_chip *chip = gpiochip_get_data(gc); 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci mutex_lock(&chip->irq_lock); 75862306a36Sopenharmony_ci} 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_cistatic void pca953x_irq_bus_sync_unlock(struct irq_data *d) 76162306a36Sopenharmony_ci{ 76262306a36Sopenharmony_ci struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 76362306a36Sopenharmony_ci struct pca953x_chip *chip = gpiochip_get_data(gc); 76462306a36Sopenharmony_ci DECLARE_BITMAP(irq_mask, MAX_LINE); 76562306a36Sopenharmony_ci DECLARE_BITMAP(reg_direction, MAX_LINE); 76662306a36Sopenharmony_ci int level; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci if (chip->driver_data & PCA_PCAL) { 76962306a36Sopenharmony_ci /* Enable latch on interrupt-enabled inputs */ 77062306a36Sopenharmony_ci pca953x_write_regs(chip, PCAL953X_IN_LATCH, chip->irq_mask); 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci bitmap_complement(irq_mask, chip->irq_mask, gc->ngpio); 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci /* Unmask enabled interrupts */ 77562306a36Sopenharmony_ci pca953x_write_regs(chip, PCAL953X_INT_MASK, irq_mask); 77662306a36Sopenharmony_ci } 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci /* Switch direction to input if needed */ 77962306a36Sopenharmony_ci pca953x_read_regs(chip, chip->regs->direction, reg_direction); 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci bitmap_or(irq_mask, chip->irq_trig_fall, chip->irq_trig_raise, gc->ngpio); 78262306a36Sopenharmony_ci bitmap_complement(reg_direction, reg_direction, gc->ngpio); 78362306a36Sopenharmony_ci bitmap_and(irq_mask, irq_mask, reg_direction, gc->ngpio); 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci /* Look for any newly setup interrupt */ 78662306a36Sopenharmony_ci for_each_set_bit(level, irq_mask, gc->ngpio) 78762306a36Sopenharmony_ci pca953x_gpio_direction_input(&chip->gpio_chip, level); 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci mutex_unlock(&chip->irq_lock); 79062306a36Sopenharmony_ci} 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_cistatic int pca953x_irq_set_type(struct irq_data *d, unsigned int type) 79362306a36Sopenharmony_ci{ 79462306a36Sopenharmony_ci struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 79562306a36Sopenharmony_ci struct pca953x_chip *chip = gpiochip_get_data(gc); 79662306a36Sopenharmony_ci irq_hw_number_t hwirq = irqd_to_hwirq(d); 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci if (!(type & IRQ_TYPE_EDGE_BOTH)) { 79962306a36Sopenharmony_ci dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", 80062306a36Sopenharmony_ci d->irq, type); 80162306a36Sopenharmony_ci return -EINVAL; 80262306a36Sopenharmony_ci } 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci assign_bit(hwirq, chip->irq_trig_fall, type & IRQ_TYPE_EDGE_FALLING); 80562306a36Sopenharmony_ci assign_bit(hwirq, chip->irq_trig_raise, type & IRQ_TYPE_EDGE_RISING); 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci return 0; 80862306a36Sopenharmony_ci} 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_cistatic void pca953x_irq_shutdown(struct irq_data *d) 81162306a36Sopenharmony_ci{ 81262306a36Sopenharmony_ci struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 81362306a36Sopenharmony_ci struct pca953x_chip *chip = gpiochip_get_data(gc); 81462306a36Sopenharmony_ci irq_hw_number_t hwirq = irqd_to_hwirq(d); 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci clear_bit(hwirq, chip->irq_trig_raise); 81762306a36Sopenharmony_ci clear_bit(hwirq, chip->irq_trig_fall); 81862306a36Sopenharmony_ci} 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_cistatic void pca953x_irq_print_chip(struct irq_data *data, struct seq_file *p) 82162306a36Sopenharmony_ci{ 82262306a36Sopenharmony_ci struct gpio_chip *gc = irq_data_get_irq_chip_data(data); 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci seq_printf(p, dev_name(gc->parent)); 82562306a36Sopenharmony_ci} 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_cistatic const struct irq_chip pca953x_irq_chip = { 82862306a36Sopenharmony_ci .irq_mask = pca953x_irq_mask, 82962306a36Sopenharmony_ci .irq_unmask = pca953x_irq_unmask, 83062306a36Sopenharmony_ci .irq_set_wake = pca953x_irq_set_wake, 83162306a36Sopenharmony_ci .irq_bus_lock = pca953x_irq_bus_lock, 83262306a36Sopenharmony_ci .irq_bus_sync_unlock = pca953x_irq_bus_sync_unlock, 83362306a36Sopenharmony_ci .irq_set_type = pca953x_irq_set_type, 83462306a36Sopenharmony_ci .irq_shutdown = pca953x_irq_shutdown, 83562306a36Sopenharmony_ci .irq_print_chip = pca953x_irq_print_chip, 83662306a36Sopenharmony_ci .flags = IRQCHIP_IMMUTABLE, 83762306a36Sopenharmony_ci GPIOCHIP_IRQ_RESOURCE_HELPERS, 83862306a36Sopenharmony_ci}; 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_cistatic bool pca953x_irq_pending(struct pca953x_chip *chip, unsigned long *pending) 84162306a36Sopenharmony_ci{ 84262306a36Sopenharmony_ci struct gpio_chip *gc = &chip->gpio_chip; 84362306a36Sopenharmony_ci DECLARE_BITMAP(reg_direction, MAX_LINE); 84462306a36Sopenharmony_ci DECLARE_BITMAP(old_stat, MAX_LINE); 84562306a36Sopenharmony_ci DECLARE_BITMAP(cur_stat, MAX_LINE); 84662306a36Sopenharmony_ci DECLARE_BITMAP(new_stat, MAX_LINE); 84762306a36Sopenharmony_ci DECLARE_BITMAP(trigger, MAX_LINE); 84862306a36Sopenharmony_ci int ret; 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci if (chip->driver_data & PCA_PCAL) { 85162306a36Sopenharmony_ci /* Read the current interrupt status from the device */ 85262306a36Sopenharmony_ci ret = pca953x_read_regs(chip, PCAL953X_INT_STAT, trigger); 85362306a36Sopenharmony_ci if (ret) 85462306a36Sopenharmony_ci return false; 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci /* Check latched inputs and clear interrupt status */ 85762306a36Sopenharmony_ci ret = pca953x_read_regs(chip, chip->regs->input, cur_stat); 85862306a36Sopenharmony_ci if (ret) 85962306a36Sopenharmony_ci return false; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci /* Apply filter for rising/falling edge selection */ 86262306a36Sopenharmony_ci bitmap_replace(new_stat, chip->irq_trig_fall, chip->irq_trig_raise, cur_stat, gc->ngpio); 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci bitmap_and(pending, new_stat, trigger, gc->ngpio); 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci return !bitmap_empty(pending, gc->ngpio); 86762306a36Sopenharmony_ci } 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci ret = pca953x_read_regs(chip, chip->regs->input, cur_stat); 87062306a36Sopenharmony_ci if (ret) 87162306a36Sopenharmony_ci return false; 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci /* Remove output pins from the equation */ 87462306a36Sopenharmony_ci pca953x_read_regs(chip, chip->regs->direction, reg_direction); 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci bitmap_copy(old_stat, chip->irq_stat, gc->ngpio); 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci bitmap_and(new_stat, cur_stat, reg_direction, gc->ngpio); 87962306a36Sopenharmony_ci bitmap_xor(cur_stat, new_stat, old_stat, gc->ngpio); 88062306a36Sopenharmony_ci bitmap_and(trigger, cur_stat, chip->irq_mask, gc->ngpio); 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci bitmap_copy(chip->irq_stat, new_stat, gc->ngpio); 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci if (bitmap_empty(trigger, gc->ngpio)) 88562306a36Sopenharmony_ci return false; 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci bitmap_and(cur_stat, chip->irq_trig_fall, old_stat, gc->ngpio); 88862306a36Sopenharmony_ci bitmap_and(old_stat, chip->irq_trig_raise, new_stat, gc->ngpio); 88962306a36Sopenharmony_ci bitmap_or(new_stat, old_stat, cur_stat, gc->ngpio); 89062306a36Sopenharmony_ci bitmap_and(pending, new_stat, trigger, gc->ngpio); 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci return !bitmap_empty(pending, gc->ngpio); 89362306a36Sopenharmony_ci} 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_cistatic irqreturn_t pca953x_irq_handler(int irq, void *devid) 89662306a36Sopenharmony_ci{ 89762306a36Sopenharmony_ci struct pca953x_chip *chip = devid; 89862306a36Sopenharmony_ci struct gpio_chip *gc = &chip->gpio_chip; 89962306a36Sopenharmony_ci DECLARE_BITMAP(pending, MAX_LINE); 90062306a36Sopenharmony_ci int level; 90162306a36Sopenharmony_ci bool ret; 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci bitmap_zero(pending, MAX_LINE); 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci mutex_lock(&chip->i2c_lock); 90662306a36Sopenharmony_ci ret = pca953x_irq_pending(chip, pending); 90762306a36Sopenharmony_ci mutex_unlock(&chip->i2c_lock); 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci if (ret) { 91062306a36Sopenharmony_ci ret = 0; 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci for_each_set_bit(level, pending, gc->ngpio) { 91362306a36Sopenharmony_ci int nested_irq = irq_find_mapping(gc->irq.domain, level); 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci if (unlikely(nested_irq <= 0)) { 91662306a36Sopenharmony_ci dev_warn_ratelimited(gc->parent, "unmapped interrupt %d\n", level); 91762306a36Sopenharmony_ci continue; 91862306a36Sopenharmony_ci } 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci handle_nested_irq(nested_irq); 92162306a36Sopenharmony_ci ret = 1; 92262306a36Sopenharmony_ci } 92362306a36Sopenharmony_ci } 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci return IRQ_RETVAL(ret); 92662306a36Sopenharmony_ci} 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_cistatic int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base) 92962306a36Sopenharmony_ci{ 93062306a36Sopenharmony_ci struct i2c_client *client = chip->client; 93162306a36Sopenharmony_ci DECLARE_BITMAP(reg_direction, MAX_LINE); 93262306a36Sopenharmony_ci DECLARE_BITMAP(irq_stat, MAX_LINE); 93362306a36Sopenharmony_ci struct gpio_irq_chip *girq; 93462306a36Sopenharmony_ci int ret; 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci if (dmi_first_match(pca953x_dmi_acpi_irq_info)) { 93762306a36Sopenharmony_ci ret = pca953x_acpi_get_irq(&client->dev); 93862306a36Sopenharmony_ci if (ret > 0) 93962306a36Sopenharmony_ci client->irq = ret; 94062306a36Sopenharmony_ci } 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci if (!client->irq) 94362306a36Sopenharmony_ci return 0; 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci if (irq_base == -1) 94662306a36Sopenharmony_ci return 0; 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci if (!(chip->driver_data & PCA_INT)) 94962306a36Sopenharmony_ci return 0; 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_ci ret = pca953x_read_regs(chip, chip->regs->input, irq_stat); 95262306a36Sopenharmony_ci if (ret) 95362306a36Sopenharmony_ci return ret; 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci /* 95662306a36Sopenharmony_ci * There is no way to know which GPIO line generated the 95762306a36Sopenharmony_ci * interrupt. We have to rely on the previous read for 95862306a36Sopenharmony_ci * this purpose. 95962306a36Sopenharmony_ci */ 96062306a36Sopenharmony_ci pca953x_read_regs(chip, chip->regs->direction, reg_direction); 96162306a36Sopenharmony_ci bitmap_and(chip->irq_stat, irq_stat, reg_direction, chip->gpio_chip.ngpio); 96262306a36Sopenharmony_ci mutex_init(&chip->irq_lock); 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci girq = &chip->gpio_chip.irq; 96562306a36Sopenharmony_ci gpio_irq_chip_set_chip(girq, &pca953x_irq_chip); 96662306a36Sopenharmony_ci /* This will let us handle the parent IRQ in the driver */ 96762306a36Sopenharmony_ci girq->parent_handler = NULL; 96862306a36Sopenharmony_ci girq->num_parents = 0; 96962306a36Sopenharmony_ci girq->parents = NULL; 97062306a36Sopenharmony_ci girq->default_type = IRQ_TYPE_NONE; 97162306a36Sopenharmony_ci girq->handler = handle_simple_irq; 97262306a36Sopenharmony_ci girq->threaded = true; 97362306a36Sopenharmony_ci girq->first = irq_base; /* FIXME: get rid of this */ 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci ret = devm_request_threaded_irq(&client->dev, client->irq, 97662306a36Sopenharmony_ci NULL, pca953x_irq_handler, 97762306a36Sopenharmony_ci IRQF_ONESHOT | IRQF_SHARED, 97862306a36Sopenharmony_ci dev_name(&client->dev), chip); 97962306a36Sopenharmony_ci if (ret) { 98062306a36Sopenharmony_ci dev_err(&client->dev, "failed to request irq %d\n", 98162306a36Sopenharmony_ci client->irq); 98262306a36Sopenharmony_ci return ret; 98362306a36Sopenharmony_ci } 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci return 0; 98662306a36Sopenharmony_ci} 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci#else /* CONFIG_GPIO_PCA953X_IRQ */ 98962306a36Sopenharmony_cistatic int pca953x_irq_setup(struct pca953x_chip *chip, 99062306a36Sopenharmony_ci int irq_base) 99162306a36Sopenharmony_ci{ 99262306a36Sopenharmony_ci struct i2c_client *client = chip->client; 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci if (client->irq && irq_base != -1 && (chip->driver_data & PCA_INT)) 99562306a36Sopenharmony_ci dev_warn(&client->dev, "interrupt support not compiled in\n"); 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci return 0; 99862306a36Sopenharmony_ci} 99962306a36Sopenharmony_ci#endif 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_cistatic int device_pca95xx_init(struct pca953x_chip *chip, u32 invert) 100262306a36Sopenharmony_ci{ 100362306a36Sopenharmony_ci DECLARE_BITMAP(val, MAX_LINE); 100462306a36Sopenharmony_ci u8 regaddr; 100562306a36Sopenharmony_ci int ret; 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci regaddr = chip->recalc_addr(chip, chip->regs->output, 0); 100862306a36Sopenharmony_ci ret = regcache_sync_region(chip->regmap, regaddr, 100962306a36Sopenharmony_ci regaddr + NBANK(chip) - 1); 101062306a36Sopenharmony_ci if (ret) 101162306a36Sopenharmony_ci goto out; 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci regaddr = chip->recalc_addr(chip, chip->regs->direction, 0); 101462306a36Sopenharmony_ci ret = regcache_sync_region(chip->regmap, regaddr, 101562306a36Sopenharmony_ci regaddr + NBANK(chip) - 1); 101662306a36Sopenharmony_ci if (ret) 101762306a36Sopenharmony_ci goto out; 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci /* set platform specific polarity inversion */ 102062306a36Sopenharmony_ci if (invert) 102162306a36Sopenharmony_ci bitmap_fill(val, MAX_LINE); 102262306a36Sopenharmony_ci else 102362306a36Sopenharmony_ci bitmap_zero(val, MAX_LINE); 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci ret = pca953x_write_regs(chip, chip->regs->invert, val); 102662306a36Sopenharmony_ciout: 102762306a36Sopenharmony_ci return ret; 102862306a36Sopenharmony_ci} 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_cistatic int device_pca957x_init(struct pca953x_chip *chip, u32 invert) 103162306a36Sopenharmony_ci{ 103262306a36Sopenharmony_ci DECLARE_BITMAP(val, MAX_LINE); 103362306a36Sopenharmony_ci unsigned int i; 103462306a36Sopenharmony_ci int ret; 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci ret = device_pca95xx_init(chip, invert); 103762306a36Sopenharmony_ci if (ret) 103862306a36Sopenharmony_ci goto out; 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci /* To enable register 6, 7 to control pull up and pull down */ 104162306a36Sopenharmony_ci for (i = 0; i < NBANK(chip); i++) 104262306a36Sopenharmony_ci bitmap_set_value8(val, 0x02, i * BANK_SZ); 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci ret = pca953x_write_regs(chip, PCA957X_BKEN, val); 104562306a36Sopenharmony_ci if (ret) 104662306a36Sopenharmony_ci goto out; 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci return 0; 104962306a36Sopenharmony_ciout: 105062306a36Sopenharmony_ci return ret; 105162306a36Sopenharmony_ci} 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_cistatic int pca953x_probe(struct i2c_client *client) 105462306a36Sopenharmony_ci{ 105562306a36Sopenharmony_ci struct pca953x_platform_data *pdata; 105662306a36Sopenharmony_ci struct pca953x_chip *chip; 105762306a36Sopenharmony_ci int irq_base = 0; 105862306a36Sopenharmony_ci int ret; 105962306a36Sopenharmony_ci u32 invert = 0; 106062306a36Sopenharmony_ci struct regulator *reg; 106162306a36Sopenharmony_ci const struct regmap_config *regmap_config; 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); 106462306a36Sopenharmony_ci if (chip == NULL) 106562306a36Sopenharmony_ci return -ENOMEM; 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci pdata = dev_get_platdata(&client->dev); 106862306a36Sopenharmony_ci if (pdata) { 106962306a36Sopenharmony_ci irq_base = pdata->irq_base; 107062306a36Sopenharmony_ci chip->gpio_start = pdata->gpio_base; 107162306a36Sopenharmony_ci invert = pdata->invert; 107262306a36Sopenharmony_ci chip->names = pdata->names; 107362306a36Sopenharmony_ci } else { 107462306a36Sopenharmony_ci struct gpio_desc *reset_gpio; 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci chip->gpio_start = -1; 107762306a36Sopenharmony_ci irq_base = 0; 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci /* 108062306a36Sopenharmony_ci * See if we need to de-assert a reset pin. 108162306a36Sopenharmony_ci * 108262306a36Sopenharmony_ci * There is no known ACPI-enabled platforms that are 108362306a36Sopenharmony_ci * using "reset" GPIO. Otherwise any of those platform 108462306a36Sopenharmony_ci * must use _DSD method with corresponding property. 108562306a36Sopenharmony_ci */ 108662306a36Sopenharmony_ci reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", 108762306a36Sopenharmony_ci GPIOD_OUT_LOW); 108862306a36Sopenharmony_ci if (IS_ERR(reset_gpio)) 108962306a36Sopenharmony_ci return PTR_ERR(reset_gpio); 109062306a36Sopenharmony_ci } 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci chip->client = client; 109362306a36Sopenharmony_ci chip->driver_data = (uintptr_t)i2c_get_match_data(client); 109462306a36Sopenharmony_ci if (!chip->driver_data) 109562306a36Sopenharmony_ci return -ENODEV; 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci reg = devm_regulator_get(&client->dev, "vcc"); 109862306a36Sopenharmony_ci if (IS_ERR(reg)) 109962306a36Sopenharmony_ci return dev_err_probe(&client->dev, PTR_ERR(reg), "reg get err\n"); 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci ret = regulator_enable(reg); 110262306a36Sopenharmony_ci if (ret) { 110362306a36Sopenharmony_ci dev_err(&client->dev, "reg en err: %d\n", ret); 110462306a36Sopenharmony_ci return ret; 110562306a36Sopenharmony_ci } 110662306a36Sopenharmony_ci chip->regulator = reg; 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci i2c_set_clientdata(client, chip); 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK); 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_ci if (NBANK(chip) > 2 || PCA_CHIP_TYPE(chip->driver_data) == PCA957X_TYPE) { 111362306a36Sopenharmony_ci dev_info(&client->dev, "using AI\n"); 111462306a36Sopenharmony_ci regmap_config = &pca953x_ai_i2c_regmap; 111562306a36Sopenharmony_ci } else { 111662306a36Sopenharmony_ci dev_info(&client->dev, "using no AI\n"); 111762306a36Sopenharmony_ci regmap_config = &pca953x_i2c_regmap; 111862306a36Sopenharmony_ci } 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci if (PCA_CHIP_TYPE(chip->driver_data) == PCAL653X_TYPE) { 112162306a36Sopenharmony_ci chip->recalc_addr = pcal6534_recalc_addr; 112262306a36Sopenharmony_ci chip->check_reg = pcal6534_check_register; 112362306a36Sopenharmony_ci } else { 112462306a36Sopenharmony_ci chip->recalc_addr = pca953x_recalc_addr; 112562306a36Sopenharmony_ci chip->check_reg = pca953x_check_register; 112662306a36Sopenharmony_ci } 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci chip->regmap = devm_regmap_init_i2c(client, regmap_config); 112962306a36Sopenharmony_ci if (IS_ERR(chip->regmap)) { 113062306a36Sopenharmony_ci ret = PTR_ERR(chip->regmap); 113162306a36Sopenharmony_ci goto err_exit; 113262306a36Sopenharmony_ci } 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci regcache_mark_dirty(chip->regmap); 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci mutex_init(&chip->i2c_lock); 113762306a36Sopenharmony_ci /* 113862306a36Sopenharmony_ci * In case we have an i2c-mux controlled by a GPIO provided by an 113962306a36Sopenharmony_ci * expander using the same driver higher on the device tree, read the 114062306a36Sopenharmony_ci * i2c adapter nesting depth and use the retrieved value as lockdep 114162306a36Sopenharmony_ci * subclass for chip->i2c_lock. 114262306a36Sopenharmony_ci * 114362306a36Sopenharmony_ci * REVISIT: This solution is not complete. It protects us from lockdep 114462306a36Sopenharmony_ci * false positives when the expander controlling the i2c-mux is on 114562306a36Sopenharmony_ci * a different level on the device tree, but not when it's on the same 114662306a36Sopenharmony_ci * level on a different branch (in which case the subclass number 114762306a36Sopenharmony_ci * would be the same). 114862306a36Sopenharmony_ci * 114962306a36Sopenharmony_ci * TODO: Once a correct solution is developed, a similar fix should be 115062306a36Sopenharmony_ci * applied to all other i2c-controlled GPIO expanders (and potentially 115162306a36Sopenharmony_ci * regmap-i2c). 115262306a36Sopenharmony_ci */ 115362306a36Sopenharmony_ci lockdep_set_subclass(&chip->i2c_lock, 115462306a36Sopenharmony_ci i2c_adapter_depth(client->adapter)); 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci /* initialize cached registers from their original values. 115762306a36Sopenharmony_ci * we can't share this chip with another i2c master. 115862306a36Sopenharmony_ci */ 115962306a36Sopenharmony_ci if (PCA_CHIP_TYPE(chip->driver_data) == PCA957X_TYPE) { 116062306a36Sopenharmony_ci chip->regs = &pca957x_regs; 116162306a36Sopenharmony_ci ret = device_pca957x_init(chip, invert); 116262306a36Sopenharmony_ci } else { 116362306a36Sopenharmony_ci chip->regs = &pca953x_regs; 116462306a36Sopenharmony_ci ret = device_pca95xx_init(chip, invert); 116562306a36Sopenharmony_ci } 116662306a36Sopenharmony_ci if (ret) 116762306a36Sopenharmony_ci goto err_exit; 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci ret = pca953x_irq_setup(chip, irq_base); 117062306a36Sopenharmony_ci if (ret) 117162306a36Sopenharmony_ci goto err_exit; 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci ret = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip); 117462306a36Sopenharmony_ci if (ret) 117562306a36Sopenharmony_ci goto err_exit; 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_ci if (pdata && pdata->setup) { 117862306a36Sopenharmony_ci ret = pdata->setup(client, chip->gpio_chip.base, 117962306a36Sopenharmony_ci chip->gpio_chip.ngpio, pdata->context); 118062306a36Sopenharmony_ci if (ret < 0) 118162306a36Sopenharmony_ci dev_warn(&client->dev, "setup failed, %d\n", ret); 118262306a36Sopenharmony_ci } 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci return 0; 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_cierr_exit: 118762306a36Sopenharmony_ci regulator_disable(chip->regulator); 118862306a36Sopenharmony_ci return ret; 118962306a36Sopenharmony_ci} 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_cistatic void pca953x_remove(struct i2c_client *client) 119262306a36Sopenharmony_ci{ 119362306a36Sopenharmony_ci struct pca953x_platform_data *pdata = dev_get_platdata(&client->dev); 119462306a36Sopenharmony_ci struct pca953x_chip *chip = i2c_get_clientdata(client); 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci if (pdata && pdata->teardown) { 119762306a36Sopenharmony_ci pdata->teardown(client, chip->gpio_chip.base, 119862306a36Sopenharmony_ci chip->gpio_chip.ngpio, pdata->context); 119962306a36Sopenharmony_ci } 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci regulator_disable(chip->regulator); 120262306a36Sopenharmony_ci} 120362306a36Sopenharmony_ci 120462306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 120562306a36Sopenharmony_cistatic int pca953x_regcache_sync(struct device *dev) 120662306a36Sopenharmony_ci{ 120762306a36Sopenharmony_ci struct pca953x_chip *chip = dev_get_drvdata(dev); 120862306a36Sopenharmony_ci int ret; 120962306a36Sopenharmony_ci u8 regaddr; 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci /* 121262306a36Sopenharmony_ci * The ordering between direction and output is important, 121362306a36Sopenharmony_ci * sync these registers first and only then sync the rest. 121462306a36Sopenharmony_ci */ 121562306a36Sopenharmony_ci regaddr = chip->recalc_addr(chip, chip->regs->direction, 0); 121662306a36Sopenharmony_ci ret = regcache_sync_region(chip->regmap, regaddr, regaddr + NBANK(chip) - 1); 121762306a36Sopenharmony_ci if (ret) { 121862306a36Sopenharmony_ci dev_err(dev, "Failed to sync GPIO dir registers: %d\n", ret); 121962306a36Sopenharmony_ci return ret; 122062306a36Sopenharmony_ci } 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci regaddr = chip->recalc_addr(chip, chip->regs->output, 0); 122362306a36Sopenharmony_ci ret = regcache_sync_region(chip->regmap, regaddr, regaddr + NBANK(chip) - 1); 122462306a36Sopenharmony_ci if (ret) { 122562306a36Sopenharmony_ci dev_err(dev, "Failed to sync GPIO out registers: %d\n", ret); 122662306a36Sopenharmony_ci return ret; 122762306a36Sopenharmony_ci } 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci#ifdef CONFIG_GPIO_PCA953X_IRQ 123062306a36Sopenharmony_ci if (chip->driver_data & PCA_PCAL) { 123162306a36Sopenharmony_ci regaddr = chip->recalc_addr(chip, PCAL953X_IN_LATCH, 0); 123262306a36Sopenharmony_ci ret = regcache_sync_region(chip->regmap, regaddr, 123362306a36Sopenharmony_ci regaddr + NBANK(chip) - 1); 123462306a36Sopenharmony_ci if (ret) { 123562306a36Sopenharmony_ci dev_err(dev, "Failed to sync INT latch registers: %d\n", 123662306a36Sopenharmony_ci ret); 123762306a36Sopenharmony_ci return ret; 123862306a36Sopenharmony_ci } 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci regaddr = chip->recalc_addr(chip, PCAL953X_INT_MASK, 0); 124162306a36Sopenharmony_ci ret = regcache_sync_region(chip->regmap, regaddr, 124262306a36Sopenharmony_ci regaddr + NBANK(chip) - 1); 124362306a36Sopenharmony_ci if (ret) { 124462306a36Sopenharmony_ci dev_err(dev, "Failed to sync INT mask registers: %d\n", 124562306a36Sopenharmony_ci ret); 124662306a36Sopenharmony_ci return ret; 124762306a36Sopenharmony_ci } 124862306a36Sopenharmony_ci } 124962306a36Sopenharmony_ci#endif 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci return 0; 125262306a36Sopenharmony_ci} 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_cistatic int pca953x_suspend(struct device *dev) 125562306a36Sopenharmony_ci{ 125662306a36Sopenharmony_ci struct pca953x_chip *chip = dev_get_drvdata(dev); 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci mutex_lock(&chip->i2c_lock); 125962306a36Sopenharmony_ci regcache_cache_only(chip->regmap, true); 126062306a36Sopenharmony_ci mutex_unlock(&chip->i2c_lock); 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci if (atomic_read(&chip->wakeup_path)) 126362306a36Sopenharmony_ci device_set_wakeup_path(dev); 126462306a36Sopenharmony_ci else 126562306a36Sopenharmony_ci regulator_disable(chip->regulator); 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci return 0; 126862306a36Sopenharmony_ci} 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_cistatic int pca953x_resume(struct device *dev) 127162306a36Sopenharmony_ci{ 127262306a36Sopenharmony_ci struct pca953x_chip *chip = dev_get_drvdata(dev); 127362306a36Sopenharmony_ci int ret; 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_ci if (!atomic_read(&chip->wakeup_path)) { 127662306a36Sopenharmony_ci ret = regulator_enable(chip->regulator); 127762306a36Sopenharmony_ci if (ret) { 127862306a36Sopenharmony_ci dev_err(dev, "Failed to enable regulator: %d\n", ret); 127962306a36Sopenharmony_ci return 0; 128062306a36Sopenharmony_ci } 128162306a36Sopenharmony_ci } 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci mutex_lock(&chip->i2c_lock); 128462306a36Sopenharmony_ci regcache_cache_only(chip->regmap, false); 128562306a36Sopenharmony_ci regcache_mark_dirty(chip->regmap); 128662306a36Sopenharmony_ci ret = pca953x_regcache_sync(dev); 128762306a36Sopenharmony_ci if (ret) { 128862306a36Sopenharmony_ci mutex_unlock(&chip->i2c_lock); 128962306a36Sopenharmony_ci return ret; 129062306a36Sopenharmony_ci } 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_ci ret = regcache_sync(chip->regmap); 129362306a36Sopenharmony_ci mutex_unlock(&chip->i2c_lock); 129462306a36Sopenharmony_ci if (ret) { 129562306a36Sopenharmony_ci dev_err(dev, "Failed to restore register map: %d\n", ret); 129662306a36Sopenharmony_ci return ret; 129762306a36Sopenharmony_ci } 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci return 0; 130062306a36Sopenharmony_ci} 130162306a36Sopenharmony_ci#endif 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci/* convenience to stop overlong match-table lines */ 130462306a36Sopenharmony_ci#define OF_653X(__nrgpio, __int) ((void *)(__nrgpio | PCAL653X_TYPE | __int)) 130562306a36Sopenharmony_ci#define OF_953X(__nrgpio, __int) (void *)(__nrgpio | PCA953X_TYPE | __int) 130662306a36Sopenharmony_ci#define OF_957X(__nrgpio, __int) (void *)(__nrgpio | PCA957X_TYPE | __int) 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_cistatic const struct of_device_id pca953x_dt_ids[] = { 130962306a36Sopenharmony_ci { .compatible = "nxp,pca6408", .data = OF_953X(8, PCA_INT), }, 131062306a36Sopenharmony_ci { .compatible = "nxp,pca6416", .data = OF_953X(16, PCA_INT), }, 131162306a36Sopenharmony_ci { .compatible = "nxp,pca9505", .data = OF_953X(40, PCA_INT), }, 131262306a36Sopenharmony_ci { .compatible = "nxp,pca9506", .data = OF_953X(40, PCA_INT), }, 131362306a36Sopenharmony_ci { .compatible = "nxp,pca9534", .data = OF_953X( 8, PCA_INT), }, 131462306a36Sopenharmony_ci { .compatible = "nxp,pca9535", .data = OF_953X(16, PCA_INT), }, 131562306a36Sopenharmony_ci { .compatible = "nxp,pca9536", .data = OF_953X( 4, 0), }, 131662306a36Sopenharmony_ci { .compatible = "nxp,pca9537", .data = OF_953X( 4, PCA_INT), }, 131762306a36Sopenharmony_ci { .compatible = "nxp,pca9538", .data = OF_953X( 8, PCA_INT), }, 131862306a36Sopenharmony_ci { .compatible = "nxp,pca9539", .data = OF_953X(16, PCA_INT), }, 131962306a36Sopenharmony_ci { .compatible = "nxp,pca9554", .data = OF_953X( 8, PCA_INT), }, 132062306a36Sopenharmony_ci { .compatible = "nxp,pca9555", .data = OF_953X(16, PCA_INT), }, 132162306a36Sopenharmony_ci { .compatible = "nxp,pca9556", .data = OF_953X( 8, 0), }, 132262306a36Sopenharmony_ci { .compatible = "nxp,pca9557", .data = OF_953X( 8, 0), }, 132362306a36Sopenharmony_ci { .compatible = "nxp,pca9574", .data = OF_957X( 8, PCA_INT), }, 132462306a36Sopenharmony_ci { .compatible = "nxp,pca9575", .data = OF_957X(16, PCA_INT), }, 132562306a36Sopenharmony_ci { .compatible = "nxp,pca9698", .data = OF_953X(40, 0), }, 132662306a36Sopenharmony_ci 132762306a36Sopenharmony_ci { .compatible = "nxp,pcal6408", .data = OF_953X(8, PCA_LATCH_INT), }, 132862306a36Sopenharmony_ci { .compatible = "nxp,pcal6416", .data = OF_953X(16, PCA_LATCH_INT), }, 132962306a36Sopenharmony_ci { .compatible = "nxp,pcal6524", .data = OF_953X(24, PCA_LATCH_INT), }, 133062306a36Sopenharmony_ci { .compatible = "nxp,pcal6534", .data = OF_653X(34, PCA_LATCH_INT), }, 133162306a36Sopenharmony_ci { .compatible = "nxp,pcal9535", .data = OF_953X(16, PCA_LATCH_INT), }, 133262306a36Sopenharmony_ci { .compatible = "nxp,pcal9554b", .data = OF_953X( 8, PCA_LATCH_INT), }, 133362306a36Sopenharmony_ci { .compatible = "nxp,pcal9555a", .data = OF_953X(16, PCA_LATCH_INT), }, 133462306a36Sopenharmony_ci 133562306a36Sopenharmony_ci { .compatible = "maxim,max7310", .data = OF_953X( 8, 0), }, 133662306a36Sopenharmony_ci { .compatible = "maxim,max7312", .data = OF_953X(16, PCA_INT), }, 133762306a36Sopenharmony_ci { .compatible = "maxim,max7313", .data = OF_953X(16, PCA_INT), }, 133862306a36Sopenharmony_ci { .compatible = "maxim,max7315", .data = OF_953X( 8, PCA_INT), }, 133962306a36Sopenharmony_ci { .compatible = "maxim,max7318", .data = OF_953X(16, PCA_INT), }, 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci { .compatible = "ti,pca6107", .data = OF_953X( 8, PCA_INT), }, 134262306a36Sopenharmony_ci { .compatible = "ti,pca9536", .data = OF_953X( 4, 0), }, 134362306a36Sopenharmony_ci { .compatible = "ti,tca6408", .data = OF_953X( 8, PCA_INT), }, 134462306a36Sopenharmony_ci { .compatible = "ti,tca6416", .data = OF_953X(16, PCA_INT), }, 134562306a36Sopenharmony_ci { .compatible = "ti,tca6424", .data = OF_953X(24, PCA_INT), }, 134662306a36Sopenharmony_ci { .compatible = "ti,tca9538", .data = OF_953X( 8, PCA_INT), }, 134762306a36Sopenharmony_ci { .compatible = "ti,tca9539", .data = OF_953X(16, PCA_INT), }, 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ci { .compatible = "onnn,cat9554", .data = OF_953X( 8, PCA_INT), }, 135062306a36Sopenharmony_ci { .compatible = "onnn,pca9654", .data = OF_953X( 8, PCA_INT), }, 135162306a36Sopenharmony_ci { .compatible = "onnn,pca9655", .data = OF_953X(16, PCA_INT), }, 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ci { .compatible = "exar,xra1202", .data = OF_953X( 8, 0), }, 135462306a36Sopenharmony_ci { } 135562306a36Sopenharmony_ci}; 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, pca953x_dt_ids); 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(pca953x_pm_ops, pca953x_suspend, pca953x_resume); 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_cistatic struct i2c_driver pca953x_driver = { 136262306a36Sopenharmony_ci .driver = { 136362306a36Sopenharmony_ci .name = "pca953x", 136462306a36Sopenharmony_ci .pm = &pca953x_pm_ops, 136562306a36Sopenharmony_ci .of_match_table = pca953x_dt_ids, 136662306a36Sopenharmony_ci .acpi_match_table = pca953x_acpi_ids, 136762306a36Sopenharmony_ci }, 136862306a36Sopenharmony_ci .probe = pca953x_probe, 136962306a36Sopenharmony_ci .remove = pca953x_remove, 137062306a36Sopenharmony_ci .id_table = pca953x_id, 137162306a36Sopenharmony_ci}; 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_cistatic int __init pca953x_init(void) 137462306a36Sopenharmony_ci{ 137562306a36Sopenharmony_ci return i2c_add_driver(&pca953x_driver); 137662306a36Sopenharmony_ci} 137762306a36Sopenharmony_ci/* register after i2c postcore initcall and before 137862306a36Sopenharmony_ci * subsys initcalls that may rely on these GPIOs 137962306a36Sopenharmony_ci */ 138062306a36Sopenharmony_cisubsys_initcall(pca953x_init); 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_cistatic void __exit pca953x_exit(void) 138362306a36Sopenharmony_ci{ 138462306a36Sopenharmony_ci i2c_del_driver(&pca953x_driver); 138562306a36Sopenharmony_ci} 138662306a36Sopenharmony_cimodule_exit(pca953x_exit); 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ciMODULE_AUTHOR("eric miao <eric.miao@marvell.com>"); 138962306a36Sopenharmony_ciMODULE_DESCRIPTION("GPIO expander driver for PCA953x"); 139062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1391