diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index fe4ce213d7d..09e1868ac8f 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -87,7 +87,6 @@ config ALTERA_PIO config AXP_GPIO bool "X-Powers AXP PMICs GPIO driver" depends on DM_GPIO && PMIC_AXP - depends on AXP_PMIC_BUS help This driver supports the GPIO pins on X-Powers AXP152, AXP2xx, and AXP8xx PMICs. diff --git a/drivers/gpio/axp_gpio.c b/drivers/gpio/axp_gpio.c index a7817e961fe..41897bf6f9d 100644 --- a/drivers/gpio/axp_gpio.c +++ b/drivers/gpio/axp_gpio.c @@ -7,110 +7,117 @@ #include #include -#include #include +#include #include #include #define AXP_GPIO_PREFIX "AXP0-" #define AXP_GPIO_COUNT 4 -static int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val); +#define AXP_GPIO_CTRL_MASK 0x7 +#define AXP_GPIO_CTRL_OUTPUT_LOW 0 +#define AXP_GPIO_CTRL_OUTPUT_HIGH 1 -static u8 axp_get_gpio_ctrl_reg(unsigned pin) -{ - switch (pin) { - case 0: return AXP_GPIO0_CTRL; - case 1: return AXP_GPIO1_CTRL; -#ifdef AXP_GPIO2_CTRL - case 2: return AXP_GPIO2_CTRL; -#endif -#ifdef AXP_GPIO3_CTRL - case 3: return AXP_GPIO3_CTRL; -#endif - } - return 0; -} - -static int axp_gpio_direction_input(struct udevice *dev, unsigned pin) -{ - u8 reg; - - reg = axp_get_gpio_ctrl_reg(pin); - if (reg == 0) - return -EINVAL; - - return pmic_reg_write(dev->parent, reg, AXP_GPIO_CTRL_INPUT); -} - -static int axp_gpio_direction_output(struct udevice *dev, unsigned pin, - int val) -{ - u8 reg; - - reg = axp_get_gpio_ctrl_reg(pin); - if (reg == 0) - return -EINVAL; - - return pmic_reg_write(dev->parent, reg, - val ? AXP_GPIO_CTRL_OUTPUT_HIGH : - AXP_GPIO_CTRL_OUTPUT_LOW); -} +struct axp_gpio_desc { + const u8 *pins; + u8 npins; + u8 status_reg; + u8 status_offset; + u8 input_mux; +}; static int axp_gpio_get_value(struct udevice *dev, unsigned pin) { - u8 reg, mask; + const struct axp_gpio_desc *desc = dev_get_priv(dev); int ret; - reg = axp_get_gpio_ctrl_reg(pin); - if (reg == 0) - return -EINVAL; - - ret = pmic_reg_read(dev->parent, AXP_GPIO_STATE); + ret = pmic_reg_read(dev->parent, desc->status_reg); if (ret < 0) return ret; - mask = 1 << (pin + AXP_GPIO_STATE_OFFSET); - - return (ret & mask) ? 1 : 0; + return !!(ret & BIT(desc->status_offset + pin)); } -static int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val) +static int axp_gpio_set_flags(struct udevice *dev, unsigned pin, ulong flags) { - u8 reg; + const struct axp_gpio_desc *desc = dev_get_priv(dev); + u8 mux; - reg = axp_get_gpio_ctrl_reg(pin); - if (reg == 0) + if (flags & (GPIOD_MASK_DSTYPE | GPIOD_MASK_PULL)) return -EINVAL; - return pmic_reg_write(dev->parent, reg, - val ? AXP_GPIO_CTRL_OUTPUT_HIGH : - AXP_GPIO_CTRL_OUTPUT_LOW); + if (flags & GPIOD_IS_IN) + mux = desc->input_mux; + else if (flags & GPIOD_IS_OUT_ACTIVE) + mux = AXP_GPIO_CTRL_OUTPUT_HIGH; + else + mux = AXP_GPIO_CTRL_OUTPUT_LOW; + + return pmic_clrsetbits(dev->parent, desc->pins[pin], + AXP_GPIO_CTRL_MASK, mux); } static const struct dm_gpio_ops axp_gpio_ops = { - .direction_input = axp_gpio_direction_input, - .direction_output = axp_gpio_direction_output, .get_value = axp_gpio_get_value, - .set_value = axp_gpio_set_value, + .xlate = gpio_xlate_offs_flags, + .set_flags = axp_gpio_set_flags, }; static int axp_gpio_probe(struct udevice *dev) { + struct axp_gpio_desc *desc = (void *)dev_get_driver_data(dev); struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + dev_set_priv(dev, desc); + /* Tell the uclass how many GPIOs we have */ uc_priv->bank_name = AXP_GPIO_PREFIX; - uc_priv->gpio_count = AXP_GPIO_COUNT; + uc_priv->gpio_count = desc->npins; return 0; } +static const u8 axp152_gpio_pins[] = { + 0x90, 0x91, 0x92, 0x93, +}; + +static const struct axp_gpio_desc axp152_gpio_desc = { + .pins = axp152_gpio_pins, + .npins = ARRAY_SIZE(axp152_gpio_pins), + .status_reg = 0x97, + .status_offset = 4, + .input_mux = 3, +}; + +static const u8 axp209_gpio_pins[] = { + 0x90, 0x92, 0x93, +}; + +static const struct axp_gpio_desc axp209_gpio_desc = { + .pins = axp209_gpio_pins, + .npins = ARRAY_SIZE(axp209_gpio_pins), + .status_reg = 0x94, + .status_offset = 4, + .input_mux = 2, +}; + +static const u8 axp221_gpio_pins[] = { + 0x90, 0x92, +}; + +static const struct axp_gpio_desc axp221_gpio_desc = { + .pins = axp221_gpio_pins, + .npins = ARRAY_SIZE(axp221_gpio_pins), + .status_reg = 0x94, + .input_mux = 2, +}; + static const struct udevice_id axp_gpio_ids[] = { - { .compatible = "x-powers,axp152-gpio" }, - { .compatible = "x-powers,axp209-gpio" }, - { .compatible = "x-powers,axp221-gpio" }, - { .compatible = "x-powers,axp813-gpio" }, + { .compatible = "x-powers,axp152-gpio", .data = (ulong)&axp152_gpio_desc }, + { .compatible = "x-powers,axp209-gpio", .data = (ulong)&axp209_gpio_desc }, + { .compatible = "x-powers,axp221-gpio", .data = (ulong)&axp221_gpio_desc }, + { .compatible = "x-powers,axp813-gpio", .data = (ulong)&axp221_gpio_desc }, { } }; diff --git a/drivers/power/axp209.c b/drivers/power/axp209.c index 3447b9f0113..d4a5b1b4ae3 100644 --- a/drivers/power/axp209.c +++ b/drivers/power/axp209.c @@ -215,15 +215,15 @@ int axp_init(void) * Turn off LDOIO regulators / tri-state GPIO pins, when rebooting * from android these are sometimes on. */ - rc = pmic_bus_write(AXP_GPIO0_CTRL, AXP_GPIO_CTRL_INPUT); + rc = pmic_bus_write(AXP209_GPIO0_CTRL, AXP209_GPIO_CTRL_INPUT); if (rc) return rc; - rc = pmic_bus_write(AXP_GPIO1_CTRL, AXP_GPIO_CTRL_INPUT); + rc = pmic_bus_write(AXP209_GPIO1_CTRL, AXP209_GPIO_CTRL_INPUT); if (rc) return rc; - rc = pmic_bus_write(AXP_GPIO2_CTRL, AXP_GPIO_CTRL_INPUT); + rc = pmic_bus_write(AXP209_GPIO2_CTRL, AXP209_GPIO_CTRL_INPUT); if (rc) return rc; diff --git a/drivers/power/axp221.c b/drivers/power/axp221.c index d251c314b98..9308fe98030 100644 --- a/drivers/power/axp221.c +++ b/drivers/power/axp221.c @@ -226,11 +226,11 @@ int axp_init(void) * Turn off LDOIO regulators / tri-state GPIO pins, when rebooting * from android these are sometimes on. */ - ret = pmic_bus_write(AXP_GPIO0_CTRL, AXP_GPIO_CTRL_INPUT); + ret = pmic_bus_write(AXP221_GPIO0_CTRL, AXP221_GPIO_CTRL_INPUT); if (ret) return ret; - ret = pmic_bus_write(AXP_GPIO1_CTRL, AXP_GPIO_CTRL_INPUT); + ret = pmic_bus_write(AXP221_GPIO1_CTRL, AXP221_GPIO_CTRL_INPUT); if (ret) return ret; diff --git a/include/axp152.h b/include/axp152.h index bac6526a362..ed1ae673da3 100644 --- a/include/axp152.h +++ b/include/axp152.h @@ -14,17 +14,7 @@ enum axp152_reg { #define AXP152_POWEROFF (1 << 7) -/* For axp_gpio.c */ #ifdef CONFIG_AXP152_POWER #define AXP_POWER_STATUS 0x00 #define AXP_POWER_STATUS_ALDO_IN BIT(0) -#define AXP_GPIO0_CTRL 0x90 -#define AXP_GPIO1_CTRL 0x91 -#define AXP_GPIO2_CTRL 0x92 -#define AXP_GPIO3_CTRL 0x93 -#define AXP_GPIO_CTRL_OUTPUT_LOW 0x00 /* Drive pin low */ -#define AXP_GPIO_CTRL_OUTPUT_HIGH 0x01 /* Drive pin high */ -#define AXP_GPIO_CTRL_INPUT 0x02 /* Input */ -#define AXP_GPIO_STATE 0x97 -#define AXP_GPIO_STATE_OFFSET 0 #endif diff --git a/include/axp209.h b/include/axp209.h index d8bf44f1fa6..5719704676f 100644 --- a/include/axp209.h +++ b/include/axp209.h @@ -21,6 +21,9 @@ enum axp209_reg { AXP209_IRQ_ENABLE5 = 0x44, AXP209_IRQ_STATUS5 = 0x4c, AXP209_SHUTDOWN = 0x32, + AXP209_GPIO0_CTRL = 0x90, + AXP209_GPIO1_CTRL = 0x92, + AXP209_GPIO2_CTRL = 0x93, }; #define AXP209_POWER_STATUS_ON_BY_DC BIT(0) @@ -73,16 +76,7 @@ enum axp209_reg { #define AXP209_POWEROFF BIT(7) -/* For axp_gpio.c */ #ifdef CONFIG_AXP209_POWER #define AXP_POWER_STATUS 0x00 #define AXP_POWER_STATUS_ALDO_IN BIT(0) -#define AXP_GPIO0_CTRL 0x90 -#define AXP_GPIO1_CTRL 0x92 -#define AXP_GPIO2_CTRL 0x93 -#define AXP_GPIO_CTRL_OUTPUT_LOW 0x00 /* Drive pin low */ -#define AXP_GPIO_CTRL_OUTPUT_HIGH 0x01 /* Drive pin high */ -#define AXP_GPIO_CTRL_INPUT 0x02 /* Input */ -#define AXP_GPIO_STATE 0x94 -#define AXP_GPIO_STATE_OFFSET 4 #endif diff --git a/include/axp221.h b/include/axp221.h index 8a4a3cca82f..7caf604b3b7 100644 --- a/include/axp221.h +++ b/include/axp221.h @@ -44,20 +44,17 @@ #define AXP221_ALDO3_CTRL 0x2a #define AXP221_SHUTDOWN 0x32 #define AXP221_SHUTDOWN_POWEROFF (1 << 7) +#define AXP221_GPIO0_CTRL 0x90 +#define AXP221_GPIO1_CTRL 0x92 +#define AXP221_GPIO_CTRL_OUTPUT_LOW 0x00 +#define AXP221_GPIO_CTRL_OUTPUT_HIGH 0x01 +#define AXP221_GPIO_CTRL_INPUT 0x02 #define AXP221_PAGE 0xff /* Page 1 addresses */ #define AXP221_SID 0x20 -/* For axp_gpio.c */ #ifdef CONFIG_AXP221_POWER #define AXP_POWER_STATUS 0x00 #define AXP_POWER_STATUS_ALDO_IN BIT(0) -#define AXP_GPIO0_CTRL 0x90 -#define AXP_GPIO1_CTRL 0x92 -#define AXP_GPIO_CTRL_OUTPUT_LOW 0x00 /* Drive pin low */ -#define AXP_GPIO_CTRL_OUTPUT_HIGH 0x01 /* Drive pin high */ -#define AXP_GPIO_CTRL_INPUT 0x02 /* Input */ -#define AXP_GPIO_STATE 0x94 -#define AXP_GPIO_STATE_OFFSET 0 #endif diff --git a/include/axp809.h b/include/axp809.h index 3bd71b3d1a3..f8ad7a5d70d 100644 --- a/include/axp809.h +++ b/include/axp809.h @@ -43,15 +43,7 @@ #define AXP809_SHUTDOWN 0x32 #define AXP809_SHUTDOWN_POWEROFF (1 << 7) -/* For axp_gpio.c */ #ifdef CONFIG_AXP809_POWER #define AXP_POWER_STATUS 0x00 #define AXP_POWER_STATUS_ALDO_IN BIT(0) -#define AXP_GPIO0_CTRL 0x90 -#define AXP_GPIO1_CTRL 0x92 -#define AXP_GPIO_CTRL_OUTPUT_LOW 0x00 /* Drive pin low */ -#define AXP_GPIO_CTRL_OUTPUT_HIGH 0x01 /* Drive pin high */ -#define AXP_GPIO_CTRL_INPUT 0x02 /* Input */ -#define AXP_GPIO_STATE 0x94 -#define AXP_GPIO_STATE_OFFSET 0 #endif diff --git a/include/axp818.h b/include/axp818.h index b3a9686e0e5..5d964042359 100644 --- a/include/axp818.h +++ b/include/axp818.h @@ -57,15 +57,7 @@ #define AXP818_SHUTDOWN 0x32 #define AXP818_SHUTDOWN_POWEROFF (1 << 7) -/* For axp_gpio.c */ #ifdef CONFIG_AXP818_POWER #define AXP_POWER_STATUS 0x00 #define AXP_POWER_STATUS_ALDO_IN BIT(0) -#define AXP_GPIO0_CTRL 0x90 -#define AXP_GPIO1_CTRL 0x92 -#define AXP_GPIO_CTRL_OUTPUT_LOW 0x00 /* Drive pin low */ -#define AXP_GPIO_CTRL_OUTPUT_HIGH 0x01 /* Drive pin high */ -#define AXP_GPIO_CTRL_INPUT 0x02 /* Input */ -#define AXP_GPIO_STATE 0x94 -#define AXP_GPIO_STATE_OFFSET 0 #endif