1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Awinic AW9523B i2c pin controller driver
- * Copyright (c) 2020, AngeloGioacchino Del Regno
- * <[email protected]>
- */
- #include <linux/bitfield.h>
- #include <linux/regmap.h>
- #include <linux/i2c.h>
- #include <linux/init.h>
- #include <linux/interrupt.h>
- #include <linux/irq.h>
- #include <linux/mutex.h>
- #include <linux/module.h>
- #include <linux/slab.h>
- #include <linux/of.h>
- #include <linux/of_device.h>
- #include <linux/version.h>
- #include <linux/gpio/consumer.h>
- #include <linux/gpio/driver.h>
- #include <linux/pinctrl/pinconf.h>
- #include <linux/pinctrl/pinctrl.h>
- #include <linux/pinctrl/pinmux.h>
- #include <linux/pinctrl/pinconf-generic.h>
- #include <linux/regulator/consumer.h>
- #include "core.h"
- #include "pinconf.h"
- #include "pinctrl-utils.h"
- #define AW9523_MAX_FUNCS 2
- #define AW9523_NUM_PORTS 2
- #define AW9523_PINS_PER_PORT 8
- /*
- * HW needs at least 20uS for reset and at least 1-2uS to recover from
- * reset, but we have to account for eventual board quirks, if any:
- * for this reason, keep reset asserted for 50uS and wait for 20uS
- * to recover from the reset.
- */
- #define AW9523_HW_RESET_US 50
- #define AW9523_HW_RESET_RECOVERY_US 20
- /* Port 0: P0_0...P0_7 - Port 1: P1_0...P1_7 */
- #define AW9523_PIN_TO_PORT(pin) (pin >> 3)
- #define AW9523_REG_IN_STATE(pin) (0x00 + AW9523_PIN_TO_PORT(pin))
- #define AW9523_REG_OUT_STATE(pin) (0x02 + AW9523_PIN_TO_PORT(pin))
- #define AW9523_REG_CONF_STATE(pin) (0x04 + AW9523_PIN_TO_PORT(pin))
- #define AW9523_REG_INTR_DIS(pin) (0x06 + AW9523_PIN_TO_PORT(pin))
- #define AW9523_REG_CHIPID 0x10
- #define AW9523_VAL_EXPECTED_CHIPID 0x23
- #define AW9523_REG_GCR 0x11
- #define AW9523_GCR_ISEL_MASK GENMASK(0, 1)
- #define AW9523_GCR_GPOMD_MASK BIT(4)
- #define AW9523_REG_PORT_MODE(pin) (0x12 + AW9523_PIN_TO_PORT(pin))
- #define AW9523_REG_SOFT_RESET 0x7f
- #define AW9523_VAL_RESET 0x00
- /*
- * struct aw9523_irq - Interrupt controller structure
- * @lock: mutex locking for the irq bus
- * @irqchip: structure holding irqchip params
- * @cached_gpio: stores the previous gpio status for bit comparison
- */
- struct aw9523_irq {
- struct mutex lock;
- struct irq_chip *irqchip;
- u16 cached_gpio;
- };
- /*
- * struct aw9523_pinmux - Pin mux params
- * @name: Name of the mux
- * @grps: Groups of the mux
- * @num_grps: Number of groups (sizeof array grps)
- */
- struct aw9523_pinmux {
- const char *name;
- const char * const *grps;
- const u8 num_grps;
- };
- /*
- * struct aw9523 - Main driver structure
- * @dev: device handle
- * @regmap: regmap handle for current device
- * @i2c_lock: Mutex lock for i2c operations
- * @reset_gpio: Hardware reset (RSTN) signal GPIO
- * @vio_vreg: VCC regulator (Optional)
- * @pctl: pinctrl handle for current device
- * @gpio: structure holding gpiochip params
- * @irq: Interrupt controller structure
- */
- struct aw9523 {
- struct device *dev;
- struct regmap *regmap;
- struct mutex i2c_lock;
- struct gpio_desc *reset_gpio;
- struct regulator *vio_vreg;
- struct pinctrl_dev *pctl;
- struct gpio_chip gpio;
- struct aw9523_irq *irq;
- };
- static const struct pinctrl_pin_desc aw9523_pins[] = {
- /* Port 0 */
- PINCTRL_PIN(0, "gpio0"),
- PINCTRL_PIN(1, "gpio1"),
- PINCTRL_PIN(2, "gpio2"),
- PINCTRL_PIN(3, "gpio3"),
- PINCTRL_PIN(4, "gpio4"),
- PINCTRL_PIN(5, "gpio5"),
- PINCTRL_PIN(6, "gpio6"),
- PINCTRL_PIN(7, "gpio7"),
- /* Port 1 */
- PINCTRL_PIN(8, "gpio8"),
- PINCTRL_PIN(9, "gpio9"),
- PINCTRL_PIN(10, "gpio10"),
- PINCTRL_PIN(11, "gpio11"),
- PINCTRL_PIN(12, "gpio12"),
- PINCTRL_PIN(13, "gpio13"),
- PINCTRL_PIN(14, "gpio14"),
- PINCTRL_PIN(15, "gpio15"),
- };
- static int aw9523_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
- {
- return ARRAY_SIZE(aw9523_pins);
- }
- static const char *aw9523_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
- unsigned int selector)
- {
- return aw9523_pins[selector].name;
- }
- static int aw9523_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
- unsigned int selector,
- const unsigned int **pins,
- unsigned int *num_pins)
- {
- *pins = &aw9523_pins[selector].number;
- *num_pins = 1;
- return 0;
- }
- static const struct pinctrl_ops aw9523_pinctrl_ops = {
- .get_groups_count = aw9523_pinctrl_get_groups_count,
- .get_group_pins = aw9523_pinctrl_get_group_pins,
- .get_group_name = aw9523_pinctrl_get_group_name,
- .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
- .dt_free_map = pinconf_generic_dt_free_map,
- };
- static const char * const gpio_pwm_groups[] = {
- "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5",
- "gpio6", "gpio7", "gpio8", "gpio9", "gpio10", "gpio11",
- "gpio12", "gpio13", "gpio14", "gpio15"
- };
- /* Warning: Do NOT reorder this array */
- static const struct aw9523_pinmux aw9523_pmx[] = {
- {
- .name = "pwm",
- .grps = gpio_pwm_groups,
- .num_grps = ARRAY_SIZE(gpio_pwm_groups),
- },
- {
- .name = "gpio",
- .grps = gpio_pwm_groups,
- .num_grps = ARRAY_SIZE(gpio_pwm_groups),
- },
- };
- static int aw9523_pmx_get_funcs_count(struct pinctrl_dev *pctl)
- {
- return ARRAY_SIZE(aw9523_pmx);
- }
- static const char *aw9523_pmx_get_fname(struct pinctrl_dev *pctl,
- unsigned int sel)
- {
- return aw9523_pmx[sel].name;
- }
- static int aw9523_pmx_get_groups(struct pinctrl_dev *pctl, unsigned int sel,
- const char * const **groups,
- unsigned int * const num_groups)
- {
- *groups = aw9523_pmx[sel].grps;
- *num_groups = aw9523_pmx[sel].num_grps;
- return 0;
- }
- static int aw9523_pmx_set_mux(struct pinctrl_dev *pctl, unsigned int fsel,
- unsigned int grp)
- {
- struct aw9523 *awi = pinctrl_dev_get_drvdata(pctl);
- int ret, pin = aw9523_pins[grp].number % AW9523_PINS_PER_PORT;
- if (fsel >= ARRAY_SIZE(aw9523_pmx))
- return -EINVAL;
- /*
- * This maps directly to the aw9523_pmx array: programming a
- * high bit means "gpio" and a low bit means "pwm".
- */
- mutex_lock(&awi->i2c_lock);
- ret = regmap_update_bits(awi->regmap, AW9523_REG_PORT_MODE(pin),
- BIT(pin), (fsel ? BIT(pin) : 0));
- mutex_unlock(&awi->i2c_lock);
- return ret;
- }
- static const struct pinmux_ops aw9523_pinmux_ops = {
- .get_functions_count = aw9523_pmx_get_funcs_count,
- .get_function_name = aw9523_pmx_get_fname,
- .get_function_groups = aw9523_pmx_get_groups,
- .set_mux = aw9523_pmx_set_mux,
- };
- static int aw9523_pcfg_param_to_reg(enum pin_config_param pcp, int pin, u8 *r)
- {
- u8 reg;
- switch (pcp) {
- case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
- case PIN_CONFIG_BIAS_PULL_DOWN:
- case PIN_CONFIG_BIAS_PULL_UP:
- reg = AW9523_REG_IN_STATE(pin);
- break;
- case PIN_CONFIG_DRIVE_OPEN_DRAIN:
- case PIN_CONFIG_DRIVE_PUSH_PULL:
- reg = AW9523_REG_GCR;
- break;
- case PIN_CONFIG_INPUT_ENABLE:
- case PIN_CONFIG_OUTPUT_ENABLE:
- reg = AW9523_REG_CONF_STATE(pin);
- break;
- case PIN_CONFIG_OUTPUT:
- reg = AW9523_REG_OUT_STATE(pin);
- break;
- default:
- return -ENOTSUPP;
- }
- *r = reg;
- return 0;
- }
- static int aw9523_pconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
- unsigned long *config)
- {
- struct aw9523 *awi = pinctrl_dev_get_drvdata(pctldev);
- enum pin_config_param param = pinconf_to_config_param(*config);
- int regbit = pin % AW9523_PINS_PER_PORT;
- unsigned int val;
- u8 reg;
- int rc;
- rc = aw9523_pcfg_param_to_reg(param, pin, ®);
- if (rc)
- return rc;
- mutex_lock(&awi->i2c_lock);
- rc = regmap_read(awi->regmap, reg, &val);
- mutex_unlock(&awi->i2c_lock);
- if (rc)
- return rc;
- switch (param) {
- case PIN_CONFIG_BIAS_PULL_UP:
- case PIN_CONFIG_INPUT_ENABLE:
- case PIN_CONFIG_OUTPUT:
- val &= BIT(regbit);
- break;
- case PIN_CONFIG_BIAS_PULL_DOWN:
- case PIN_CONFIG_OUTPUT_ENABLE:
- val &= BIT(regbit);
- val = !val;
- break;
- case PIN_CONFIG_DRIVE_OPEN_DRAIN:
- if (pin >= AW9523_PINS_PER_PORT)
- val = 0;
- else
- val = !FIELD_GET(AW9523_GCR_GPOMD_MASK, val);
- break;
- case PIN_CONFIG_DRIVE_PUSH_PULL:
- if (pin >= AW9523_PINS_PER_PORT)
- val = 1;
- else
- val = FIELD_GET(AW9523_GCR_GPOMD_MASK, val);
- break;
- default:
- return -ENOTSUPP;
- }
- if (val < 1)
- return -EINVAL;
- *config = pinconf_to_config_packed(param, !!val);
- return rc;
- }
- static int aw9523_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
- unsigned long *configs, unsigned int num_configs)
- {
- struct aw9523 *awi = pinctrl_dev_get_drvdata(pctldev);
- enum pin_config_param param;
- int regbit = pin % AW9523_PINS_PER_PORT;
- u32 arg;
- u8 reg;
- unsigned int mask, val;
- int i, rc;
- mutex_lock(&awi->i2c_lock);
- for (i = 0; i < num_configs; i++) {
- param = pinconf_to_config_param(configs[i]);
- arg = pinconf_to_config_argument(configs[i]);
- rc = aw9523_pcfg_param_to_reg(param, pin, ®);
- if (rc)
- goto end;
- switch (param) {
- case PIN_CONFIG_OUTPUT:
- /* First, enable pin output */
- rc = regmap_update_bits(awi->regmap,
- AW9523_REG_CONF_STATE(pin),
- BIT(regbit), 0);
- if (rc)
- goto end;
- /* Then, fall through to config output level */
- fallthrough;
- case PIN_CONFIG_OUTPUT_ENABLE:
- arg = !arg;
- fallthrough;
- case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
- case PIN_CONFIG_BIAS_PULL_DOWN:
- case PIN_CONFIG_BIAS_PULL_UP:
- case PIN_CONFIG_INPUT_ENABLE:
- mask = BIT(regbit);
- val = arg ? BIT(regbit) : 0;
- break;
- case PIN_CONFIG_DRIVE_OPEN_DRAIN:
- /* Open-Drain is supported only on port 0 */
- if (pin >= AW9523_PINS_PER_PORT) {
- rc = -ENOTSUPP;
- goto end;
- }
- mask = AW9523_GCR_GPOMD_MASK;
- val = 0;
- break;
- case PIN_CONFIG_DRIVE_PUSH_PULL:
- /* Port 1 is always Push-Pull */
- if (pin >= AW9523_PINS_PER_PORT) {
- mask = 0;
- val = 0;
- continue;
- }
- mask = AW9523_GCR_GPOMD_MASK;
- val = AW9523_GCR_GPOMD_MASK;
- break;
- default:
- rc = -ENOTSUPP;
- goto end;
- }
- rc = regmap_update_bits(awi->regmap, reg, mask, val);
- if (rc)
- goto end;
- }
- end:
- mutex_unlock(&awi->i2c_lock);
- return rc;
- }
- static const struct pinconf_ops aw9523_pinconf_ops = {
- .pin_config_get = aw9523_pconf_get,
- .pin_config_set = aw9523_pconf_set,
- .is_generic = true,
- };
- /*
- * aw9523_get_pin_direction - Get pin direction
- * @regmap: Regmap structure
- * @pin: gpiolib pin number
- * @n: pin index in port register
- *
- * Return: Pin direction for success or negative number for error
- */
- static int aw9523_get_pin_direction(struct regmap *regmap, u8 pin, u8 n)
- {
- int val, ret;
- ret = regmap_read(regmap, AW9523_REG_CONF_STATE(pin), &val);
- if (ret < 0)
- return ret;
- return (val & BIT(n)) == BIT(n);
- }
- /*
- * aw9523_get_port_state - Get input or output state for entire port
- * @regmap: Regmap structure
- * @pin: gpiolib pin number
- * @regbit: hw pin index, used to retrieve port number
- * @state: returned port state
- *
- * Return: Zero for success or negative number for error
- */
- static int aw9523_get_port_state(struct regmap *regmap, u8 pin,
- u8 regbit, unsigned int *state)
- {
- u8 reg;
- int dir;
- dir = aw9523_get_pin_direction(regmap, pin, regbit);
- if (dir < 0)
- return dir;
- if (dir == GPIO_LINE_DIRECTION_IN)
- reg = AW9523_REG_IN_STATE(pin);
- else
- reg = AW9523_REG_OUT_STATE(pin);
- return regmap_read(regmap, reg, state);
- }
- static int aw9523_gpio_irq_type(struct irq_data *d, unsigned int type)
- {
- switch (type) {
- case IRQ_TYPE_NONE:
- case IRQ_TYPE_EDGE_BOTH:
- return 0;
- default:
- return -EINVAL;
- };
- }
- /*
- * aw9523_irq_mask - Mask interrupt
- * @d: irq data
- *
- * Sets which interrupt to mask in the bitmap;
- * The interrupt will be masked when unlocking the irq bus.
- */
- static void aw9523_irq_mask(struct irq_data *d)
- {
- struct aw9523 *awi = gpiochip_get_data(irq_data_get_irq_chip_data(d));
- unsigned int n = d->hwirq % AW9523_PINS_PER_PORT;
- regmap_update_bits(awi->regmap,
- AW9523_REG_INTR_DIS(d->hwirq),
- BIT(n), BIT(n));
- }
- /*
- * aw9523_irq_unmask - Unmask interrupt
- * @d: irq data
- *
- * Sets which interrupt to unmask in the bitmap;
- * The interrupt will be masked when unlocking the irq bus.
- */
- static void aw9523_irq_unmask(struct irq_data *d)
- {
- struct aw9523 *awi = gpiochip_get_data(irq_data_get_irq_chip_data(d));
- unsigned int n = d->hwirq % AW9523_PINS_PER_PORT;
- regmap_update_bits(awi->regmap,
- AW9523_REG_INTR_DIS(d->hwirq),
- BIT(n), 0);
- }
- static irqreturn_t aw9523_irq_thread_func(int irq, void *dev_id)
- {
- struct aw9523 *awi = (struct aw9523 *)dev_id;
- unsigned long n, val = 0;
- unsigned long changed_gpio;
- unsigned int tmp, port_pin, i, ret;
- for (i = 0; i < AW9523_NUM_PORTS; i++) {
- port_pin = i * AW9523_PINS_PER_PORT;
- ret = regmap_read(awi->regmap,
- AW9523_REG_IN_STATE(port_pin),
- &tmp);
- if (ret)
- return ret;
- val |= (u8)tmp << (i * 8);
- }
- /* Handle GPIO input release interrupt as well */
- changed_gpio = awi->irq->cached_gpio ^ val;
- awi->irq->cached_gpio = val;
- /*
- * To avoid up to four *slow* i2c reads from any driver hooked
- * up to our interrupts, just check for the irq_find_mapping
- * result: if the interrupt is not mapped, then we don't want
- * to care about it.
- */
- for_each_set_bit(n, &changed_gpio, awi->gpio.ngpio) {
- tmp = irq_find_mapping(awi->gpio.irq.domain, n);
- if (tmp <= 0)
- continue;
- handle_nested_irq(tmp);
- }
- return IRQ_HANDLED;
- }
- /*
- * aw9523_irq_bus_lock - Grab lock for interrupt operation
- * @d: irq data
- */
- static void aw9523_irq_bus_lock(struct irq_data *d)
- {
- struct aw9523 *awi = gpiochip_get_data(irq_data_get_irq_chip_data(d));
- mutex_lock(&awi->irq->lock);
- regcache_cache_only(awi->regmap, true);
- }
- /*
- * aw9523_irq_bus_sync_unlock - Synchronize state and unlock
- * @d: irq data
- *
- * Writes the interrupt mask bits (found in the bit map) to the
- * hardware, then unlocks the bus.
- */
- static void aw9523_irq_bus_sync_unlock(struct irq_data *d)
- {
- struct aw9523 *awi = gpiochip_get_data(irq_data_get_irq_chip_data(d));
- regcache_cache_only(awi->regmap, false);
- regcache_sync(awi->regmap);
- mutex_unlock(&awi->irq->lock);
- }
- static int aw9523_gpio_get_direction(struct gpio_chip *chip,
- unsigned int offset)
- {
- struct aw9523 *awi = gpiochip_get_data(chip);
- u8 regbit = offset % AW9523_PINS_PER_PORT;
- int ret;
- mutex_lock(&awi->i2c_lock);
- ret = aw9523_get_pin_direction(awi->regmap, offset, regbit);
- mutex_unlock(&awi->i2c_lock);
- return ret;
- }
- static int aw9523_gpio_get(struct gpio_chip *chip, unsigned int offset)
- {
- struct aw9523 *awi = gpiochip_get_data(chip);
- u8 regbit = offset % AW9523_PINS_PER_PORT;
- unsigned int val;
- int ret;
- mutex_lock(&awi->i2c_lock);
- ret = aw9523_get_port_state(awi->regmap, offset, regbit, &val);
- mutex_unlock(&awi->i2c_lock);
- if (ret)
- return ret;
- return !!(val & BIT(regbit));
- }
- /**
- * _aw9523_gpio_get_multiple - Get I/O state for an entire port
- * @regmap: Regmap structure
- * @pin: gpiolib pin number
- * @regbit: hw pin index, used to retrieve port number
- * @state: returned port I/O state
- *
- * Return: Zero for success or negative number for error
- */
- static int _aw9523_gpio_get_multiple(struct aw9523 *awi, u8 regbit,
- u8 *state, u8 mask)
- {
- u32 dir_in, val;
- u8 m;
- int ret;
- /* Registers are 8-bits wide */
- ret = regmap_read(awi->regmap, AW9523_REG_CONF_STATE(regbit), &dir_in);
- if (ret)
- return ret;
- *state = 0;
- m = mask & dir_in;
- if (m) {
- ret = regmap_read(awi->regmap, AW9523_REG_IN_STATE(regbit),
- &val);
- if (ret)
- return ret;
- *state |= (u8)val & m;
- }
- m = mask & ~dir_in;
- if (m) {
- ret = regmap_read(awi->regmap, AW9523_REG_OUT_STATE(regbit),
- &val);
- if (ret)
- return ret;
- *state |= (u8)val & m;
- }
- return 0;
- }
- static int aw9523_gpio_get_multiple(struct gpio_chip *chip,
- unsigned long *mask,
- unsigned long *bits)
- {
- struct aw9523 *awi = gpiochip_get_data(chip);
- u8 m, state = 0;
- int ret;
- mutex_lock(&awi->i2c_lock);
- /* Port 0 (gpio 0-7) */
- m = *mask & U8_MAX;
- if (m) {
- ret = _aw9523_gpio_get_multiple(awi, 0, &state, m);
- if (ret)
- goto out;
- }
- *bits = state;
- /* Port 1 (gpio 8-15) */
- m = (*mask >> 8) & U8_MAX;
- if (m) {
- ret = _aw9523_gpio_get_multiple(awi, AW9523_PINS_PER_PORT,
- &state, m);
- if (ret)
- goto out;
- *bits |= (state << 8);
- }
- out:
- mutex_unlock(&awi->i2c_lock);
- return ret;
- }
- static void aw9523_gpio_set_multiple(struct gpio_chip *chip,
- unsigned long *mask,
- unsigned long *bits)
- {
- struct aw9523 *awi = gpiochip_get_data(chip);
- u8 mask_lo, mask_hi, bits_lo, bits_hi;
- unsigned int reg;
- int ret = 0;
- mask_lo = *mask & U8_MAX;
- mask_hi = (*mask >> 8) & U8_MAX;
- mutex_lock(&awi->i2c_lock);
- if (mask_hi) {
- reg = AW9523_REG_OUT_STATE(AW9523_PINS_PER_PORT);
- bits_hi = (*bits >> 8) & U8_MAX;
- ret = regmap_write_bits(awi->regmap, reg, mask_hi, bits_hi);
- if (ret) {
- dev_warn(awi->dev, "Cannot write port1 out level\n");
- goto out;
- }
- }
- if (mask_lo) {
- reg = AW9523_REG_OUT_STATE(0);
- bits_lo = *bits & U8_MAX;
- ret = regmap_write_bits(awi->regmap, reg, mask_lo, bits_lo);
- if (ret)
- dev_warn(awi->dev, "Cannot write port0 out level\n");
- }
- out:
- mutex_unlock(&awi->i2c_lock);
- }
- static void aw9523_gpio_set(struct gpio_chip *chip,
- unsigned int offset, int value)
- {
- struct aw9523 *awi = gpiochip_get_data(chip);
- u8 regbit = offset % AW9523_PINS_PER_PORT;
- mutex_lock(&awi->i2c_lock);
- regmap_update_bits(awi->regmap, AW9523_REG_OUT_STATE(offset),
- BIT(regbit), value ? BIT(regbit) : 0);
- mutex_unlock(&awi->i2c_lock);
- }
- static int aw9523_direction_input(struct gpio_chip *chip, unsigned int offset)
- {
- struct aw9523 *awi = gpiochip_get_data(chip);
- u8 regbit = offset % AW9523_PINS_PER_PORT;
- int ret;
- mutex_lock(&awi->i2c_lock);
- ret = regmap_update_bits(awi->regmap, AW9523_REG_CONF_STATE(offset),
- BIT(regbit), BIT(regbit));
- mutex_unlock(&awi->i2c_lock);
- return ret;
- }
- static int aw9523_direction_output(struct gpio_chip *chip,
- unsigned int offset, int value)
- {
- struct aw9523 *awi = gpiochip_get_data(chip);
- u8 regbit = offset % AW9523_PINS_PER_PORT;
- int ret;
- mutex_lock(&awi->i2c_lock);
- ret = regmap_update_bits(awi->regmap, AW9523_REG_OUT_STATE(offset),
- BIT(regbit), value ? BIT(regbit) : 0);
- if (ret)
- goto end;
- ret = regmap_update_bits(awi->regmap, AW9523_REG_CONF_STATE(offset),
- BIT(regbit), 0);
- end:
- mutex_unlock(&awi->i2c_lock);
- return ret;
- }
- static int aw9523_drive_reset_gpio(struct aw9523 *awi)
- {
- unsigned int chip_id;
- int ret;
- /*
- * If the chip is already configured for any reason, then we
- * will probably succeed in sending the soft reset signal to
- * the hardware through I2C: this operation takes less time
- * compared to a full HW reset and it gives the same results.
- */
- ret = regmap_write(awi->regmap, AW9523_REG_SOFT_RESET, 0);
- if (ret == 0)
- goto done;
- dev_dbg(awi->dev, "Cannot execute soft reset: trying hard reset\n");
- ret = gpiod_direction_output(awi->reset_gpio, 0);
- if (ret)
- return ret;
- /* The reset pulse has to be longer than 20uS due to deglitch */
- usleep_range(AW9523_HW_RESET_US, AW9523_HW_RESET_US + 1);
- ret = gpiod_direction_output(awi->reset_gpio, 1);
- if (ret)
- return ret;
- done:
- /* The HW needs at least 1uS to reliably recover after reset */
- usleep_range(AW9523_HW_RESET_RECOVERY_US,
- AW9523_HW_RESET_RECOVERY_US + 1);
- /* Check the ChipID */
- ret = regmap_read(awi->regmap, AW9523_REG_CHIPID, &chip_id);
- if (ret) {
- dev_err(awi->dev, "Cannot read Chip ID: %d\n", ret);
- return ret;
- }
- if (chip_id != AW9523_VAL_EXPECTED_CHIPID) {
- dev_err(awi->dev, "Bad ChipID; read 0x%x, expected 0x%x\n",
- chip_id, AW9523_VAL_EXPECTED_CHIPID);
- return -EINVAL;
- }
- return 0;
- }
- static int aw9523_hw_reset(struct aw9523 *awi)
- {
- int ret, max_retries = 2;
- /* Sometimes the chip needs more than one reset cycle */
- do {
- ret = aw9523_drive_reset_gpio(awi);
- if (ret == 0)
- break;
- max_retries--;
- } while (max_retries);
- return ret;
- }
- static int aw9523_init_gpiochip(struct aw9523 *awi, unsigned int npins)
- {
- struct device *dev = awi->dev;
- struct gpio_chip *gpiochip = &awi->gpio;
- gpiochip->label = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
- if (!gpiochip->label)
- return -ENOMEM;
- gpiochip->base = -1;
- gpiochip->ngpio = npins;
- gpiochip->get_direction = aw9523_gpio_get_direction;
- gpiochip->direction_input = aw9523_direction_input;
- gpiochip->direction_output = aw9523_direction_output;
- gpiochip->get = aw9523_gpio_get;
- gpiochip->get_multiple = aw9523_gpio_get_multiple;
- gpiochip->set = aw9523_gpio_set;
- gpiochip->set_multiple = aw9523_gpio_set_multiple;
- gpiochip->set_config = gpiochip_generic_config;
- gpiochip->parent = dev;
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
- gpiochip->fwnode = dev->fwnode;
- #else
- gpiochip->of_node = dev->of_node;
- #endif
- gpiochip->owner = THIS_MODULE;
- gpiochip->can_sleep = true;
- return 0;
- }
- static int aw9523_init_irq(struct aw9523 *awi, int irq)
- {
- struct device *dev = awi->dev;
- struct gpio_irq_chip *gpioirq;
- struct irq_chip *irqchip;
- int ret;
- if (!device_property_read_bool(dev, "interrupt-controller"))
- return 0;
- irqchip = devm_kzalloc(dev, sizeof(*irqchip), GFP_KERNEL);
- if (!irqchip)
- return -ENOMEM;
- awi->irq = devm_kzalloc(dev, sizeof(*awi->irq), GFP_KERNEL);
- if (!awi->irq)
- return -ENOMEM;
- irqchip->name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
- if (!irqchip->name)
- return -ENOMEM;
- irqchip->irq_mask = aw9523_irq_mask;
- irqchip->irq_unmask = aw9523_irq_unmask;
- irqchip->irq_bus_lock = aw9523_irq_bus_lock;
- irqchip->irq_bus_sync_unlock = aw9523_irq_bus_sync_unlock;
- irqchip->irq_set_type = aw9523_gpio_irq_type;
- awi->irq->irqchip = irqchip;
- mutex_init(&awi->irq->lock);
- ret = devm_request_threaded_irq(dev, irq, NULL, aw9523_irq_thread_func,
- IRQF_ONESHOT, dev_name(dev), awi);
- if (ret) {
- dev_err(dev, "Failed to request irq %d\n", irq);
- return ret;
- }
- gpioirq = &awi->gpio.irq;
- gpioirq->chip = irqchip;
- gpioirq->parent_handler = NULL;
- gpioirq->num_parents = 0;
- gpioirq->parents = NULL;
- gpioirq->default_type = IRQ_TYPE_LEVEL_MASK;
- gpioirq->handler = handle_simple_irq;
- gpioirq->threaded = true;
- gpioirq->first = 0;
- return 0;
- }
- static bool aw9523_is_reg_hole(unsigned int reg)
- {
- return (reg > AW9523_REG_PORT_MODE(AW9523_PINS_PER_PORT) &&
- reg < AW9523_REG_SOFT_RESET) ||
- (reg > AW9523_REG_INTR_DIS(AW9523_PINS_PER_PORT) &&
- reg < AW9523_REG_CHIPID);
- }
- static bool aw9523_readable_reg(struct device *dev, unsigned int reg)
- {
- /* All available registers (minus holes) can be read */
- return !aw9523_is_reg_hole(reg);
- }
- static bool aw9523_volatile_reg(struct device *dev, unsigned int reg)
- {
- return aw9523_is_reg_hole(reg) ||
- reg == AW9523_REG_IN_STATE(0) ||
- reg == AW9523_REG_IN_STATE(AW9523_PINS_PER_PORT) ||
- reg == AW9523_REG_CHIPID ||
- reg == AW9523_REG_SOFT_RESET;
- }
- static bool aw9523_writeable_reg(struct device *dev, unsigned int reg)
- {
- return !aw9523_is_reg_hole(reg) && reg != AW9523_REG_CHIPID;
- }
- static bool aw9523_precious_reg(struct device *dev, unsigned int reg)
- {
- /* Reading AW9523_REG_IN_STATE clears interrupt status */
- return aw9523_is_reg_hole(reg) ||
- reg == AW9523_REG_IN_STATE(0) ||
- reg == AW9523_REG_IN_STATE(AW9523_PINS_PER_PORT);
- }
- static const struct regmap_config aw9523_regmap = {
- .reg_bits = 8,
- .val_bits = 8,
- .reg_stride = 1,
- .precious_reg = aw9523_precious_reg,
- .readable_reg = aw9523_readable_reg,
- .volatile_reg = aw9523_volatile_reg,
- .writeable_reg = aw9523_writeable_reg,
- .cache_type = REGCACHE_FLAT,
- .disable_locking = true,
- .num_reg_defaults_raw = AW9523_REG_SOFT_RESET,
- };
- static int aw9523_hw_init(struct aw9523 *awi)
- {
- u8 p1_pin = AW9523_PINS_PER_PORT;
- unsigned int val;
- int ret;
- /* No register caching during initialization */
- regcache_cache_bypass(awi->regmap, true);
- /* Bring up the chip */
- ret = aw9523_hw_reset(awi);
- if (ret) {
- dev_err(awi->dev, "HW Reset failed: %d\n", ret);
- return ret;
- }
- /*
- * This is the expected chip and it is running: it's time to
- * set a safe default configuration in case the user doesn't
- * configure (all of the available) pins in this chip.
- * P.S.: The writes order doesn't matter.
- */
- /* Set all pins as GPIO */
- ret = regmap_write(awi->regmap, AW9523_REG_PORT_MODE(0), U8_MAX);
- if (ret)
- return ret;
- ret = regmap_write(awi->regmap, AW9523_REG_PORT_MODE(p1_pin), U8_MAX);
- if (ret)
- return ret;
- /* Set Open-Drain mode on Port 0 (Port 1 is always P-P) */
- ret = regmap_write(awi->regmap, AW9523_REG_GCR, 0);
- if (ret)
- return ret;
- /* Set all pins as inputs */
- ret = regmap_write(awi->regmap, AW9523_REG_CONF_STATE(0), U8_MAX);
- if (ret)
- return ret;
- ret = regmap_write(awi->regmap, AW9523_REG_CONF_STATE(p1_pin), U8_MAX);
- if (ret)
- return ret;
- /* Disable all interrupts to avoid unreasoned wakeups */
- ret = regmap_write(awi->regmap, AW9523_REG_INTR_DIS(0), U8_MAX);
- if (ret)
- return ret;
- ret = regmap_write(awi->regmap, AW9523_REG_INTR_DIS(p1_pin), U8_MAX);
- if (ret)
- return ret;
- /* Clear setup-generated interrupts by performing a port state read */
- ret = aw9523_get_port_state(awi->regmap, 0, 0, &val);
- if (ret)
- return ret;
- ret = aw9523_get_port_state(awi->regmap, p1_pin, 0, &val);
- if (ret)
- return ret;
- /* Everything went fine: activate and reinitialize register cache */
- regcache_cache_bypass(awi->regmap, false);
- return regmap_reinit_cache(awi->regmap, &aw9523_regmap);
- }
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
- static int aw9523_probe(struct i2c_client *client)
- #else
- static int aw9523_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
- #endif
- {
- struct device *dev = &client->dev;
- struct pinctrl_desc *pdesc;
- struct aw9523 *awi;
- int ret;
- awi = devm_kzalloc(dev, sizeof(*awi), GFP_KERNEL);
- if (!awi)
- return -ENOMEM;
- i2c_set_clientdata(client, awi);
- awi->dev = dev;
- awi->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
- if (IS_ERR(awi->reset_gpio))
- return PTR_ERR(awi->reset_gpio);
- gpiod_set_consumer_name(awi->reset_gpio, "aw9523 reset");
- awi->regmap = devm_regmap_init_i2c(client, &aw9523_regmap);
- if (IS_ERR(awi->regmap))
- return PTR_ERR(awi->regmap);
- awi->vio_vreg = devm_regulator_get_optional(dev, "vio");
- if (IS_ERR(awi->vio_vreg)) {
- if (PTR_ERR(awi->vio_vreg) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- awi->vio_vreg = NULL;
- } else {
- ret = regulator_enable(awi->vio_vreg);
- if (ret)
- return ret;
- }
- mutex_init(&awi->i2c_lock);
- lockdep_set_subclass(&awi->i2c_lock,
- i2c_adapter_depth(client->adapter));
- pdesc = devm_kzalloc(dev, sizeof(*pdesc), GFP_KERNEL);
- if (!pdesc)
- return -ENOMEM;
- ret = aw9523_hw_init(awi);
- if (ret)
- goto err_disable_vregs;
- pdesc->name = dev_name(dev);
- pdesc->owner = THIS_MODULE;
- pdesc->pctlops = &aw9523_pinctrl_ops;
- pdesc->pmxops = &aw9523_pinmux_ops;
- pdesc->confops = &aw9523_pinconf_ops;
- pdesc->pins = aw9523_pins;
- pdesc->npins = ARRAY_SIZE(aw9523_pins);
- ret = aw9523_init_gpiochip(awi, pdesc->npins);
- if (ret)
- goto err_disable_vregs;
- if (client->irq) {
- ret = aw9523_init_irq(awi, client->irq);
- if (ret)
- goto err_disable_vregs;
- }
- awi->pctl = devm_pinctrl_register(dev, pdesc, awi);
- if (IS_ERR(awi->pctl)) {
- ret = PTR_ERR(awi->pctl);
- dev_err(dev, "Cannot register pinctrl: %d", ret);
- goto err_disable_vregs;
- }
- ret = devm_gpiochip_add_data(dev, &awi->gpio, awi);
- if (ret)
- goto err_disable_vregs;
- return ret;
- err_disable_vregs:
- if (awi->vio_vreg)
- regulator_disable(awi->vio_vreg);
- mutex_destroy(&awi->i2c_lock);
- return ret;
- }
- static int aw9523_remove(struct i2c_client *client)
- {
- struct aw9523 *awi = i2c_get_clientdata(client);
- int ret;
- if (!awi)
- return 0;
- /*
- * If the chip VIO is connected to a regulator that we can turn
- * off, life is easy... otherwise, reinitialize the chip and
- * set the pins to hardware defaults before removing the driver
- * to leave it in a clean, safe and predictable state.
- */
- if (awi->vio_vreg) {
- regulator_disable(awi->vio_vreg);
- } else {
- mutex_lock(&awi->i2c_lock);
- ret = aw9523_hw_init(awi);
- mutex_unlock(&awi->i2c_lock);
- if (ret)
- return ret;
- }
- mutex_destroy(&awi->i2c_lock);
- return 0;
- }
- static void aw9523_remove_void(struct i2c_client *client)
- {
- aw9523_remove(client);
- }
- static const struct i2c_device_id aw9523_i2c_id_table[] = {
- { "aw9523_i2c", 0 },
- { }
- };
- MODULE_DEVICE_TABLE(i2c, aw9523_i2c_id_table);
- static const struct of_device_id of_aw9523_i2c_match[] = {
- { .compatible = "awinic,aw9523-pinctrl", },
- };
- MODULE_DEVICE_TABLE(of, of_aw9523_i2c_match);
- static struct i2c_driver aw9523_driver = {
- .driver = {
- .name = "aw9523-pinctrl",
- .of_match_table = of_aw9523_i2c_match,
- },
- .probe = aw9523_probe,
- .remove = aw9523_remove_void,
- .id_table = aw9523_i2c_id_table,
- };
- module_i2c_driver(aw9523_driver);
- MODULE_DESCRIPTION("Awinic AW9523 I2C GPIO Expander driver");
- MODULE_AUTHOR("AngeloGioacchino Del Regno <[email protected]>");
- MODULE_LICENSE("GPL v2");
- MODULE_ALIAS("platform:aw9523");
|