1*2fcf033dSHans de Goede /* 2*2fcf033dSHans de Goede * (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com> 3*2fcf033dSHans de Goede * 4*2fcf033dSHans de Goede * X-Powers AXP Power Management ICs gpio driver 5*2fcf033dSHans de Goede * 6*2fcf033dSHans de Goede * SPDX-License-Identifier: GPL-2.0+ 7*2fcf033dSHans de Goede */ 8*2fcf033dSHans de Goede 9*2fcf033dSHans de Goede #include <common.h> 10*2fcf033dSHans de Goede #include <asm/arch/gpio.h> 11*2fcf033dSHans de Goede #include <asm/arch/pmic_bus.h> 12*2fcf033dSHans de Goede #include <errno.h> 13*2fcf033dSHans de Goede 14*2fcf033dSHans de Goede #ifdef CONFIG_AXP152_POWER 15*2fcf033dSHans de Goede #include <axp152.h> 16*2fcf033dSHans de Goede #elif defined CONFIG_AXP209_POWER 17*2fcf033dSHans de Goede #include <axp209.h> 18*2fcf033dSHans de Goede #elif defined CONFIG_AXP221_POWER 19*2fcf033dSHans de Goede #include <axp221.h> 20*2fcf033dSHans de Goede #else 21*2fcf033dSHans de Goede #error Unknown AXP model 22*2fcf033dSHans de Goede #endif 23*2fcf033dSHans de Goede 24*2fcf033dSHans de Goede static u8 axp_get_gpio_ctrl_reg(unsigned pin) 25*2fcf033dSHans de Goede { 26*2fcf033dSHans de Goede switch (pin) { 27*2fcf033dSHans de Goede case 0: return AXP_GPIO0_CTRL; 28*2fcf033dSHans de Goede case 1: return AXP_GPIO1_CTRL; 29*2fcf033dSHans de Goede #ifdef AXP_GPIO2_CTRL 30*2fcf033dSHans de Goede case 2: return AXP_GPIO2_CTRL; 31*2fcf033dSHans de Goede #endif 32*2fcf033dSHans de Goede #ifdef AXP_GPIO3_CTRL 33*2fcf033dSHans de Goede case 3: return AXP_GPIO3_CTRL; 34*2fcf033dSHans de Goede #endif 35*2fcf033dSHans de Goede } 36*2fcf033dSHans de Goede return 0; 37*2fcf033dSHans de Goede } 38*2fcf033dSHans de Goede 39*2fcf033dSHans de Goede int axp_gpio_direction_input(struct udevice *dev, unsigned pin) 40*2fcf033dSHans de Goede { 41*2fcf033dSHans de Goede u8 reg; 42*2fcf033dSHans de Goede 43*2fcf033dSHans de Goede switch (pin) { 44*2fcf033dSHans de Goede #ifndef CONFIG_AXP152_POWER /* NA on axp152 */ 45*2fcf033dSHans de Goede case SUNXI_GPIO_AXP0_VBUS_DETECT: 46*2fcf033dSHans de Goede return 0; 47*2fcf033dSHans de Goede #endif 48*2fcf033dSHans de Goede default: 49*2fcf033dSHans de Goede reg = axp_get_gpio_ctrl_reg(pin); 50*2fcf033dSHans de Goede if (reg == 0) 51*2fcf033dSHans de Goede return -EINVAL; 52*2fcf033dSHans de Goede 53*2fcf033dSHans de Goede return pmic_bus_write(reg, AXP_GPIO_CTRL_INPUT); 54*2fcf033dSHans de Goede } 55*2fcf033dSHans de Goede } 56*2fcf033dSHans de Goede 57*2fcf033dSHans de Goede int axp_gpio_direction_output(struct udevice *dev, unsigned pin, int val) 58*2fcf033dSHans de Goede { 59*2fcf033dSHans de Goede __maybe_unused int ret; 60*2fcf033dSHans de Goede u8 reg; 61*2fcf033dSHans de Goede 62*2fcf033dSHans de Goede switch (pin) { 63*2fcf033dSHans de Goede #ifdef CONFIG_AXP221_POWER /* Only available on axp221/axp223 */ 64*2fcf033dSHans de Goede case SUNXI_GPIO_AXP0_VBUS_ENABLE: 65*2fcf033dSHans de Goede ret = pmic_bus_clrbits(AXP221_MISC_CTRL, 66*2fcf033dSHans de Goede AXP221_MISC_CTRL_N_VBUSEN_FUNC); 67*2fcf033dSHans de Goede if (ret) 68*2fcf033dSHans de Goede return ret; 69*2fcf033dSHans de Goede 70*2fcf033dSHans de Goede return axp_gpio_set_value(dev, pin, val); 71*2fcf033dSHans de Goede #endif 72*2fcf033dSHans de Goede default: 73*2fcf033dSHans de Goede reg = axp_get_gpio_ctrl_reg(pin); 74*2fcf033dSHans de Goede if (reg == 0) 75*2fcf033dSHans de Goede return -EINVAL; 76*2fcf033dSHans de Goede 77*2fcf033dSHans de Goede return pmic_bus_write(reg, val ? AXP_GPIO_CTRL_OUTPUT_HIGH : 78*2fcf033dSHans de Goede AXP_GPIO_CTRL_OUTPUT_LOW); 79*2fcf033dSHans de Goede } 80*2fcf033dSHans de Goede } 81*2fcf033dSHans de Goede 82*2fcf033dSHans de Goede int axp_gpio_get_value(struct udevice *dev, unsigned pin) 83*2fcf033dSHans de Goede { 84*2fcf033dSHans de Goede u8 reg, val, mask; 85*2fcf033dSHans de Goede int ret; 86*2fcf033dSHans de Goede 87*2fcf033dSHans de Goede switch (pin) { 88*2fcf033dSHans de Goede #ifndef CONFIG_AXP152_POWER /* NA on axp152 */ 89*2fcf033dSHans de Goede case SUNXI_GPIO_AXP0_VBUS_DETECT: 90*2fcf033dSHans de Goede ret = pmic_bus_read(AXP_POWER_STATUS, &val); 91*2fcf033dSHans de Goede mask = AXP_POWER_STATUS_VBUS_PRESENT; 92*2fcf033dSHans de Goede break; 93*2fcf033dSHans de Goede #endif 94*2fcf033dSHans de Goede #ifdef CONFIG_AXP221_POWER /* Only available on axp221/axp223 */ 95*2fcf033dSHans de Goede case SUNXI_GPIO_AXP0_VBUS_ENABLE: 96*2fcf033dSHans de Goede ret = pmic_bus_read(AXP221_VBUS_IPSOUT, &val); 97*2fcf033dSHans de Goede mask = AXP221_VBUS_IPSOUT_DRIVEBUS; 98*2fcf033dSHans de Goede break; 99*2fcf033dSHans de Goede #endif 100*2fcf033dSHans de Goede default: 101*2fcf033dSHans de Goede reg = axp_get_gpio_ctrl_reg(pin); 102*2fcf033dSHans de Goede if (reg == 0) 103*2fcf033dSHans de Goede return -EINVAL; 104*2fcf033dSHans de Goede 105*2fcf033dSHans de Goede ret = pmic_bus_read(AXP_GPIO_STATE, &val); 106*2fcf033dSHans de Goede mask = 1 << (pin + AXP_GPIO_STATE_OFFSET); 107*2fcf033dSHans de Goede } 108*2fcf033dSHans de Goede if (ret) 109*2fcf033dSHans de Goede return ret; 110*2fcf033dSHans de Goede 111*2fcf033dSHans de Goede return (val & mask) ? 1 : 0; 112*2fcf033dSHans de Goede } 113*2fcf033dSHans de Goede 114*2fcf033dSHans de Goede int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val) 115*2fcf033dSHans de Goede { 116*2fcf033dSHans de Goede u8 reg; 117*2fcf033dSHans de Goede 118*2fcf033dSHans de Goede switch (pin) { 119*2fcf033dSHans de Goede #ifdef CONFIG_AXP221_POWER /* Only available on axp221/axp223 */ 120*2fcf033dSHans de Goede case SUNXI_GPIO_AXP0_VBUS_ENABLE: 121*2fcf033dSHans de Goede if (val) 122*2fcf033dSHans de Goede return pmic_bus_setbits(AXP221_VBUS_IPSOUT, 123*2fcf033dSHans de Goede AXP221_VBUS_IPSOUT_DRIVEBUS); 124*2fcf033dSHans de Goede else 125*2fcf033dSHans de Goede return pmic_bus_clrbits(AXP221_VBUS_IPSOUT, 126*2fcf033dSHans de Goede AXP221_VBUS_IPSOUT_DRIVEBUS); 127*2fcf033dSHans de Goede #endif 128*2fcf033dSHans de Goede default: 129*2fcf033dSHans de Goede reg = axp_get_gpio_ctrl_reg(pin); 130*2fcf033dSHans de Goede if (reg == 0) 131*2fcf033dSHans de Goede return -EINVAL; 132*2fcf033dSHans de Goede 133*2fcf033dSHans de Goede return pmic_bus_write(reg, val ? AXP_GPIO_CTRL_OUTPUT_HIGH : 134*2fcf033dSHans de Goede AXP_GPIO_CTRL_OUTPUT_LOW); 135*2fcf033dSHans de Goede } 136*2fcf033dSHans de Goede } 137*2fcf033dSHans de Goede 138*2fcf033dSHans de Goede int axp_gpio_init(void) 139*2fcf033dSHans de Goede { 140*2fcf033dSHans de Goede int ret; 141*2fcf033dSHans de Goede 142*2fcf033dSHans de Goede ret = pmic_bus_init(); 143*2fcf033dSHans de Goede if (ret) 144*2fcf033dSHans de Goede return ret; 145*2fcf033dSHans de Goede 146*2fcf033dSHans de Goede return 0; 147*2fcf033dSHans de Goede } 148