1 /* 2 * AXP818 driver based on AXP221 driver 3 * 4 * 5 * (C) Copyright 2015 Vishnu Patekar <vishnuptekar0510@gmail.com> 6 * 7 * Based on axp221.c 8 * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com> 9 * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl> 10 * 11 * SPDX-License-Identifier: GPL-2.0+ 12 */ 13 14 #include <common.h> 15 #include <errno.h> 16 #include <asm/arch/gpio.h> 17 #include <asm/arch/pmic_bus.h> 18 #include <axp_pmic.h> 19 20 static u8 axp818_mvolt_to_cfg(int mvolt, int min, int max, int div) 21 { 22 if (mvolt < min) 23 mvolt = min; 24 else if (mvolt > max) 25 mvolt = max; 26 27 return (mvolt - min) / div; 28 } 29 30 int axp_set_dcdc1(unsigned int mvolt) 31 { 32 int ret; 33 u8 cfg = axp818_mvolt_to_cfg(mvolt, 1600, 3400, 100); 34 35 if (mvolt == 0) 36 return pmic_bus_clrbits(AXP818_OUTPUT_CTRL1, 37 AXP818_OUTPUT_CTRL1_DCDC1_EN); 38 39 ret = pmic_bus_write(AXP818_DCDC1_CTRL, cfg); 40 if (ret) 41 return ret; 42 43 return pmic_bus_setbits(AXP818_OUTPUT_CTRL1, 44 AXP818_OUTPUT_CTRL1_DCDC1_EN); 45 } 46 47 int axp_set_dcdc2(unsigned int mvolt) 48 { 49 int ret; 50 u8 cfg; 51 52 if (mvolt >= 1220) 53 cfg = 70 + axp818_mvolt_to_cfg(mvolt, 1220, 1300, 20); 54 else 55 cfg = axp818_mvolt_to_cfg(mvolt, 500, 1200, 10); 56 57 if (mvolt == 0) 58 return pmic_bus_clrbits(AXP818_OUTPUT_CTRL1, 59 AXP818_OUTPUT_CTRL1_DCDC2_EN); 60 61 ret = pmic_bus_write(AXP818_DCDC2_CTRL, cfg); 62 if (ret) 63 return ret; 64 65 return pmic_bus_setbits(AXP818_OUTPUT_CTRL1, 66 AXP818_OUTPUT_CTRL1_DCDC2_EN); 67 } 68 69 int axp_set_dcdc3(unsigned int mvolt) 70 { 71 int ret; 72 u8 cfg; 73 74 if (mvolt >= 1220) 75 cfg = 70 + axp818_mvolt_to_cfg(mvolt, 1220, 1300, 20); 76 else 77 cfg = axp818_mvolt_to_cfg(mvolt, 500, 1200, 10); 78 79 if (mvolt == 0) 80 return pmic_bus_clrbits(AXP818_OUTPUT_CTRL1, 81 AXP818_OUTPUT_CTRL1_DCDC3_EN); 82 83 ret = pmic_bus_write(AXP818_DCDC3_CTRL, cfg); 84 if (ret) 85 return ret; 86 87 return pmic_bus_setbits(AXP818_OUTPUT_CTRL1, 88 AXP818_OUTPUT_CTRL1_DCDC3_EN); 89 } 90 91 int axp_set_dcdc5(unsigned int mvolt) 92 { 93 int ret; 94 u8 cfg; 95 96 if (mvolt >= 1140) 97 cfg = 32 + axp818_mvolt_to_cfg(mvolt, 1140, 1840, 20); 98 else 99 cfg = axp818_mvolt_to_cfg(mvolt, 800, 1120, 10); 100 101 if (mvolt == 0) 102 return pmic_bus_clrbits(AXP818_OUTPUT_CTRL1, 103 AXP818_OUTPUT_CTRL1_DCDC5_EN); 104 105 ret = pmic_bus_write(AXP818_DCDC5_CTRL, cfg); 106 if (ret) 107 return ret; 108 109 return pmic_bus_setbits(AXP818_OUTPUT_CTRL1, 110 AXP818_OUTPUT_CTRL1_DCDC5_EN); 111 } 112 113 int axp_set_aldo(int aldo_num, unsigned int mvolt) 114 { 115 int ret; 116 u8 cfg; 117 118 if (aldo_num < 1 || aldo_num > 3) 119 return -EINVAL; 120 121 if (mvolt == 0) 122 return pmic_bus_clrbits(AXP818_OUTPUT_CTRL3, 123 AXP818_OUTPUT_CTRL3_ALDO1_EN << (aldo_num - 1)); 124 125 cfg = axp818_mvolt_to_cfg(mvolt, 700, 3300, 100); 126 ret = pmic_bus_write(AXP818_ALDO1_CTRL + (aldo_num - 1), cfg); 127 if (ret) 128 return ret; 129 130 return pmic_bus_setbits(AXP818_OUTPUT_CTRL3, 131 AXP818_OUTPUT_CTRL3_ALDO1_EN << (aldo_num - 1)); 132 } 133 134 /* TODO: re-work other AXP drivers to consolidate ALDO functions. */ 135 int axp_set_aldo1(unsigned int mvolt) 136 { 137 return axp_set_aldo(1, mvolt); 138 } 139 140 int axp_set_aldo2(unsigned int mvolt) 141 { 142 return axp_set_aldo(2, mvolt); 143 } 144 145 int axp_set_aldo3(unsigned int mvolt) 146 { 147 return axp_set_aldo(3, mvolt); 148 } 149 150 int axp_set_dldo(int dldo_num, unsigned int mvolt) 151 { 152 int ret; 153 u8 cfg; 154 155 if (dldo_num < 1 || dldo_num > 4) 156 return -EINVAL; 157 158 if (mvolt == 0) 159 return pmic_bus_clrbits(AXP818_OUTPUT_CTRL2, 160 AXP818_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1)); 161 162 cfg = axp818_mvolt_to_cfg(mvolt, 700, 3300, 100); 163 if (dldo_num == 2 && mvolt > 3300) 164 cfg += 1 + axp818_mvolt_to_cfg(mvolt, 3400, 4200, 200); 165 ret = pmic_bus_write(AXP818_ELDO1_CTRL + (dldo_num - 1), cfg); 166 if (ret) 167 return ret; 168 169 return pmic_bus_setbits(AXP818_OUTPUT_CTRL2, 170 AXP818_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1)); 171 } 172 173 int axp_set_eldo(int eldo_num, unsigned int mvolt) 174 { 175 int ret; 176 u8 cfg; 177 178 if (eldo_num < 1 || eldo_num > 3) 179 return -EINVAL; 180 181 if (mvolt == 0) 182 return pmic_bus_clrbits(AXP818_OUTPUT_CTRL2, 183 AXP818_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1)); 184 185 cfg = axp818_mvolt_to_cfg(mvolt, 700, 1900, 50); 186 ret = pmic_bus_write(AXP818_ELDO1_CTRL + (eldo_num - 1), cfg); 187 if (ret) 188 return ret; 189 190 return pmic_bus_setbits(AXP818_OUTPUT_CTRL2, 191 AXP818_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1)); 192 } 193 194 int axp_set_fldo(int fldo_num, unsigned int mvolt) 195 { 196 int ret; 197 u8 cfg; 198 199 if (fldo_num < 1 || fldo_num > 3) 200 return -EINVAL; 201 202 if (mvolt == 0) 203 return pmic_bus_clrbits(AXP818_OUTPUT_CTRL3, 204 AXP818_OUTPUT_CTRL3_FLDO1_EN << (fldo_num - 1)); 205 206 if (fldo_num < 3) { 207 cfg = axp818_mvolt_to_cfg(mvolt, 700, 1450, 50); 208 ret = pmic_bus_write(AXP818_FLDO1_CTRL + (fldo_num - 1), cfg); 209 } else { 210 /* 211 * Special case for FLDO3, which is DCDC5 / 2 or FLDOIN / 2 212 * Since FLDOIN is unknown, test against DCDC5. 213 */ 214 if (mvolt * 2 == CONFIG_AXP_DCDC5_VOLT) 215 ret = pmic_bus_clrbits(AXP818_FLDO2_3_CTRL, 216 AXP818_FLDO2_3_CTRL_FLDO3_VOL); 217 else 218 ret = pmic_bus_setbits(AXP818_FLDO2_3_CTRL, 219 AXP818_FLDO2_3_CTRL_FLDO3_VOL); 220 } 221 if (ret) 222 return ret; 223 224 return pmic_bus_setbits(AXP818_OUTPUT_CTRL3, 225 AXP818_OUTPUT_CTRL3_FLDO1_EN << (fldo_num - 1)); 226 } 227 228 int axp_set_sw(bool on) 229 { 230 if (on) 231 return pmic_bus_setbits(AXP818_OUTPUT_CTRL2, 232 AXP818_OUTPUT_CTRL2_SW_EN); 233 234 return pmic_bus_clrbits(AXP818_OUTPUT_CTRL2, 235 AXP818_OUTPUT_CTRL2_SW_EN); 236 } 237 238 int axp_init(void) 239 { 240 u8 axp_chip_id; 241 int ret; 242 243 ret = pmic_bus_init(); 244 if (ret) 245 return ret; 246 247 ret = pmic_bus_read(AXP818_CHIP_ID, &axp_chip_id); 248 if (ret) 249 return ret; 250 251 if (!(axp_chip_id == 0x51)) 252 return -ENODEV; 253 else 254 return ret; 255 256 return 0; 257 } 258 259 int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 260 { 261 pmic_bus_write(AXP818_SHUTDOWN, AXP818_SHUTDOWN_POWEROFF); 262 263 /* infinite loop during shutdown */ 264 while (1) {} 265 266 /* not reached */ 267 return 0; 268 } 269