From 44825e5ead0f3e8dda4bbc1c20175c42942659ab Mon Sep 17 00:00:00 2001 From: Jonathan McDowell Date: Tue, 16 May 2023 18:47:29 +0100 Subject: [PATCH] pinctrl: axp209: Add support for GPIO3 on the AXP209 The AXP209 device has a 4th GPIO which has a slightly different register setup, where the control + status bits are held in a single register rather than sharing AXP20X_GPIO20_SS with GPIOs 0-2. Signed-off-by: Jonathan McDowell Reviewed-by: Jernej Skrabec Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/dde40307f0ebc23b9841c32e702b481ab5193dc4.1684258957.git.noodles@earth.li Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-axp209.c | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/pinctrl/pinctrl-axp209.c b/drivers/pinctrl/pinctrl-axp209.c index 0bc1b381a2b8..b3ba25435c34 100644 --- a/drivers/pinctrl/pinctrl-axp209.c +++ b/drivers/pinctrl/pinctrl-axp209.c @@ -30,6 +30,11 @@ #define AXP20X_GPIO_FUNCTION_OUT_HIGH 1 #define AXP20X_GPIO_FUNCTION_INPUT 2 +#define AXP20X_GPIO3_FUNCTIONS GENMASK(2, 1) +#define AXP20X_GPIO3_FUNCTION_OUT_LOW 0 +#define AXP20X_GPIO3_FUNCTION_OUT_HIGH 2 +#define AXP20X_GPIO3_FUNCTION_INPUT 4 + #define AXP20X_FUNC_GPIO_OUT 0 #define AXP20X_FUNC_GPIO_IN 1 #define AXP20X_FUNC_LDO 2 @@ -73,6 +78,7 @@ static const struct pinctrl_pin_desc axp209_pins[] = { PINCTRL_PIN(0, "GPIO0"), PINCTRL_PIN(1, "GPIO1"), PINCTRL_PIN(2, "GPIO2"), + PINCTRL_PIN(3, "GPIO3"), }; static const struct pinctrl_pin_desc axp22x_pins[] = { @@ -130,6 +136,14 @@ static int axp20x_gpio_get(struct gpio_chip *chip, unsigned int offset) unsigned int val; int ret; + /* AXP209 has GPIO3 status sharing the settings register */ + if (offset == 3) { + ret = regmap_read(pctl->regmap, AXP20X_GPIO3_CTRL, &val); + if (ret) + return ret; + return !!(val & BIT(0)); + } + ret = regmap_read(pctl->regmap, AXP20X_GPIO20_SS, &val); if (ret) return ret; @@ -144,6 +158,17 @@ static int axp20x_gpio_get_direction(struct gpio_chip *chip, unsigned int val; int reg, ret; + /* AXP209 GPIO3 settings have a different layout */ + if (offset == 3) { + ret = regmap_read(pctl->regmap, AXP20X_GPIO3_CTRL, &val); + if (ret) + return ret; + if (val & AXP20X_GPIO3_FUNCTION_INPUT) + return GPIO_LINE_DIRECTION_IN; + + return GPIO_LINE_DIRECTION_OUT; + } + reg = axp20x_gpio_get_reg(offset); if (reg < 0) return reg; @@ -184,6 +209,15 @@ static void axp20x_gpio_set(struct gpio_chip *chip, unsigned int offset, struct axp20x_pctl *pctl = gpiochip_get_data(chip); int reg; + /* AXP209 has GPIO3 status sharing the settings register */ + if (offset == 3) { + regmap_update_bits(pctl->regmap, AXP20X_GPIO3_CTRL, + AXP20X_GPIO3_FUNCTIONS, + value ? AXP20X_GPIO3_FUNCTION_OUT_HIGH : + AXP20X_GPIO3_FUNCTION_OUT_LOW); + return; + } + reg = axp20x_gpio_get_reg(offset); if (reg < 0) return; @@ -200,6 +234,14 @@ static int axp20x_pmx_set(struct pinctrl_dev *pctldev, unsigned int offset, struct axp20x_pctl *pctl = pinctrl_dev_get_drvdata(pctldev); int reg; + /* AXP209 GPIO3 settings have a different layout */ + if (offset == 3) { + return regmap_update_bits(pctl->regmap, AXP20X_GPIO3_CTRL, + AXP20X_GPIO3_FUNCTIONS, + config == AXP20X_MUX_GPIO_OUT ? AXP20X_GPIO3_FUNCTION_OUT_LOW : + AXP20X_GPIO3_FUNCTION_INPUT); + } + reg = axp20x_gpio_get_reg(offset); if (reg < 0) return reg; -- 2.11.0