12fcf033dSHans de Goede /* 22fcf033dSHans de Goede * (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com> 32fcf033dSHans de Goede * 42fcf033dSHans de Goede * X-Powers AXP Power Management ICs gpio driver 52fcf033dSHans de Goede * 62fcf033dSHans de Goede * SPDX-License-Identifier: GPL-2.0+ 72fcf033dSHans de Goede */ 82fcf033dSHans de Goede 92fcf033dSHans de Goede #include <common.h> 102fcf033dSHans de Goede #include <asm/arch/gpio.h> 112fcf033dSHans de Goede #include <asm/arch/pmic_bus.h> 12f9b7a04bSHans de Goede #include <asm/gpio.h> 13*6944aff1SHans de Goede #include <axp_pmic.h> 14f9b7a04bSHans de Goede #include <dm.h> 15f9b7a04bSHans de Goede #include <dm/device-internal.h> 16f9b7a04bSHans de Goede #include <dm/lists.h> 17f9b7a04bSHans de Goede #include <dm/root.h> 182fcf033dSHans de Goede #include <errno.h> 192fcf033dSHans de Goede 20421b32b8SHans de Goede static int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val); 21421b32b8SHans de Goede 222fcf033dSHans de Goede static u8 axp_get_gpio_ctrl_reg(unsigned pin) 232fcf033dSHans de Goede { 242fcf033dSHans de Goede switch (pin) { 252fcf033dSHans de Goede case 0: return AXP_GPIO0_CTRL; 262fcf033dSHans de Goede case 1: return AXP_GPIO1_CTRL; 272fcf033dSHans de Goede #ifdef AXP_GPIO2_CTRL 282fcf033dSHans de Goede case 2: return AXP_GPIO2_CTRL; 292fcf033dSHans de Goede #endif 302fcf033dSHans de Goede #ifdef AXP_GPIO3_CTRL 312fcf033dSHans de Goede case 3: return AXP_GPIO3_CTRL; 322fcf033dSHans de Goede #endif 332fcf033dSHans de Goede } 342fcf033dSHans de Goede return 0; 352fcf033dSHans de Goede } 362fcf033dSHans de Goede 37421b32b8SHans de Goede static int axp_gpio_direction_input(struct udevice *dev, unsigned pin) 382fcf033dSHans de Goede { 392fcf033dSHans de Goede u8 reg; 402fcf033dSHans de Goede 412fcf033dSHans de Goede switch (pin) { 422fcf033dSHans de Goede #ifndef CONFIG_AXP152_POWER /* NA on axp152 */ 432fcf033dSHans de Goede case SUNXI_GPIO_AXP0_VBUS_DETECT: 442fcf033dSHans de Goede return 0; 452fcf033dSHans de Goede #endif 462fcf033dSHans de Goede default: 472fcf033dSHans de Goede reg = axp_get_gpio_ctrl_reg(pin); 482fcf033dSHans de Goede if (reg == 0) 492fcf033dSHans de Goede return -EINVAL; 502fcf033dSHans de Goede 512fcf033dSHans de Goede return pmic_bus_write(reg, AXP_GPIO_CTRL_INPUT); 522fcf033dSHans de Goede } 532fcf033dSHans de Goede } 542fcf033dSHans de Goede 55421b32b8SHans de Goede static int axp_gpio_direction_output(struct udevice *dev, unsigned pin, 56421b32b8SHans de Goede int val) 572fcf033dSHans de Goede { 582fcf033dSHans de Goede __maybe_unused int ret; 592fcf033dSHans de Goede u8 reg; 602fcf033dSHans de Goede 612fcf033dSHans de Goede switch (pin) { 622fcf033dSHans de Goede #ifdef CONFIG_AXP221_POWER /* Only available on axp221/axp223 */ 632fcf033dSHans de Goede case SUNXI_GPIO_AXP0_VBUS_ENABLE: 642fcf033dSHans de Goede ret = pmic_bus_clrbits(AXP221_MISC_CTRL, 652fcf033dSHans de Goede AXP221_MISC_CTRL_N_VBUSEN_FUNC); 662fcf033dSHans de Goede if (ret) 672fcf033dSHans de Goede return ret; 682fcf033dSHans de Goede 692fcf033dSHans de Goede return axp_gpio_set_value(dev, pin, val); 702fcf033dSHans de Goede #endif 712fcf033dSHans de Goede default: 722fcf033dSHans de Goede reg = axp_get_gpio_ctrl_reg(pin); 732fcf033dSHans de Goede if (reg == 0) 742fcf033dSHans de Goede return -EINVAL; 752fcf033dSHans de Goede 762fcf033dSHans de Goede return pmic_bus_write(reg, val ? AXP_GPIO_CTRL_OUTPUT_HIGH : 772fcf033dSHans de Goede AXP_GPIO_CTRL_OUTPUT_LOW); 782fcf033dSHans de Goede } 792fcf033dSHans de Goede } 802fcf033dSHans de Goede 81421b32b8SHans de Goede static int axp_gpio_get_value(struct udevice *dev, unsigned pin) 822fcf033dSHans de Goede { 832fcf033dSHans de Goede u8 reg, val, mask; 842fcf033dSHans de Goede int ret; 852fcf033dSHans de Goede 862fcf033dSHans de Goede switch (pin) { 872fcf033dSHans de Goede #ifndef CONFIG_AXP152_POWER /* NA on axp152 */ 882fcf033dSHans de Goede case SUNXI_GPIO_AXP0_VBUS_DETECT: 892fcf033dSHans de Goede ret = pmic_bus_read(AXP_POWER_STATUS, &val); 902fcf033dSHans de Goede mask = AXP_POWER_STATUS_VBUS_PRESENT; 912fcf033dSHans de Goede break; 922fcf033dSHans de Goede #endif 932fcf033dSHans de Goede #ifdef CONFIG_AXP221_POWER /* Only available on axp221/axp223 */ 942fcf033dSHans de Goede case SUNXI_GPIO_AXP0_VBUS_ENABLE: 952fcf033dSHans de Goede ret = pmic_bus_read(AXP221_VBUS_IPSOUT, &val); 962fcf033dSHans de Goede mask = AXP221_VBUS_IPSOUT_DRIVEBUS; 972fcf033dSHans de Goede break; 982fcf033dSHans de Goede #endif 992fcf033dSHans de Goede default: 1002fcf033dSHans de Goede reg = axp_get_gpio_ctrl_reg(pin); 1012fcf033dSHans de Goede if (reg == 0) 1022fcf033dSHans de Goede return -EINVAL; 1032fcf033dSHans de Goede 1042fcf033dSHans de Goede ret = pmic_bus_read(AXP_GPIO_STATE, &val); 1052fcf033dSHans de Goede mask = 1 << (pin + AXP_GPIO_STATE_OFFSET); 1062fcf033dSHans de Goede } 1072fcf033dSHans de Goede if (ret) 1082fcf033dSHans de Goede return ret; 1092fcf033dSHans de Goede 1102fcf033dSHans de Goede return (val & mask) ? 1 : 0; 1112fcf033dSHans de Goede } 1122fcf033dSHans de Goede 113421b32b8SHans de Goede static int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val) 1142fcf033dSHans de Goede { 1152fcf033dSHans de Goede u8 reg; 1162fcf033dSHans de Goede 1172fcf033dSHans de Goede switch (pin) { 1182fcf033dSHans de Goede #ifdef CONFIG_AXP221_POWER /* Only available on axp221/axp223 */ 1192fcf033dSHans de Goede case SUNXI_GPIO_AXP0_VBUS_ENABLE: 1202fcf033dSHans de Goede if (val) 1212fcf033dSHans de Goede return pmic_bus_setbits(AXP221_VBUS_IPSOUT, 1222fcf033dSHans de Goede AXP221_VBUS_IPSOUT_DRIVEBUS); 1232fcf033dSHans de Goede else 1242fcf033dSHans de Goede return pmic_bus_clrbits(AXP221_VBUS_IPSOUT, 1252fcf033dSHans de Goede AXP221_VBUS_IPSOUT_DRIVEBUS); 1262fcf033dSHans de Goede #endif 1272fcf033dSHans de Goede default: 1282fcf033dSHans de Goede reg = axp_get_gpio_ctrl_reg(pin); 1292fcf033dSHans de Goede if (reg == 0) 1302fcf033dSHans de Goede return -EINVAL; 1312fcf033dSHans de Goede 1322fcf033dSHans de Goede return pmic_bus_write(reg, val ? AXP_GPIO_CTRL_OUTPUT_HIGH : 1332fcf033dSHans de Goede AXP_GPIO_CTRL_OUTPUT_LOW); 1342fcf033dSHans de Goede } 1352fcf033dSHans de Goede } 1362fcf033dSHans de Goede 137f9b7a04bSHans de Goede static const struct dm_gpio_ops gpio_axp_ops = { 138f9b7a04bSHans de Goede .direction_input = axp_gpio_direction_input, 139f9b7a04bSHans de Goede .direction_output = axp_gpio_direction_output, 140f9b7a04bSHans de Goede .get_value = axp_gpio_get_value, 141f9b7a04bSHans de Goede .set_value = axp_gpio_set_value, 142f9b7a04bSHans de Goede }; 143f9b7a04bSHans de Goede 144f9b7a04bSHans de Goede static int gpio_axp_probe(struct udevice *dev) 145f9b7a04bSHans de Goede { 146f9b7a04bSHans de Goede struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 147f9b7a04bSHans de Goede 148f9b7a04bSHans de Goede /* Tell the uclass how many GPIOs we have */ 149f9b7a04bSHans de Goede uc_priv->bank_name = strdup(SUNXI_GPIO_AXP0_PREFIX); 150f9b7a04bSHans de Goede uc_priv->gpio_count = SUNXI_GPIO_AXP0_GPIO_COUNT; 151f9b7a04bSHans de Goede 152f9b7a04bSHans de Goede return 0; 153f9b7a04bSHans de Goede } 154f9b7a04bSHans de Goede 155f9b7a04bSHans de Goede U_BOOT_DRIVER(gpio_axp) = { 156f9b7a04bSHans de Goede .name = "gpio_axp", 157f9b7a04bSHans de Goede .id = UCLASS_GPIO, 158f9b7a04bSHans de Goede .ops = &gpio_axp_ops, 159f9b7a04bSHans de Goede .probe = gpio_axp_probe, 160f9b7a04bSHans de Goede }; 161f9b7a04bSHans de Goede 1622fcf033dSHans de Goede int axp_gpio_init(void) 1632fcf033dSHans de Goede { 164421b32b8SHans de Goede struct udevice *dev; 1652fcf033dSHans de Goede int ret; 1662fcf033dSHans de Goede 1672fcf033dSHans de Goede ret = pmic_bus_init(); 1682fcf033dSHans de Goede if (ret) 1692fcf033dSHans de Goede return ret; 1702fcf033dSHans de Goede 171f9b7a04bSHans de Goede /* There is no devicetree support for the axp yet, so bind directly */ 172f9b7a04bSHans de Goede ret = device_bind_driver(dm_root(), "gpio_axp", "AXP-gpio", &dev); 173f9b7a04bSHans de Goede if (ret) 174f9b7a04bSHans de Goede return ret; 175f9b7a04bSHans de Goede 1762fcf033dSHans de Goede return 0; 1772fcf033dSHans de Goede } 178