// SPDX-License-Identifier: GPL-2.0-only
/*
* Awinic AW9523B i2c pin controller driver
* Copyright (c) 2020, AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
*/
#include <linux/bitfield.h>
#include <linux/errno.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.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
* @cached_gpio: stores the previous gpio status for bit comparison
*/
struct aw9523_irq {
struct mutex lock;
u16 cached_gpio;
};
/*
* 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", /* 0-3 */
"gpio4", "gpio5", "gpio6", "gpio7", /* 4-7 */
"gpio8", "gpio9", "gpio10", "gpio11", /* 8-11 */
"gpio12", "gpio13", "gpio14", "gpio15", /* 11-15 */
};
/* Warning: Do NOT reorder this array */
static const struct pinfunction aw9523_pmx[] = {
PINCTRL_PINFUNCTION("pwm", gpio_pwm_groups, ARRAY_SIZE(gpio_pwm_groups)),
PINCTRL_PINFUNCTION("gpio", gpio_pwm_groups, 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 ngroups)
{
*groups = aw9523_pmx[sel].groups;
*ngroups = aw9523_pmx[sel].ngroups;
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