1 /* 2 * AXP221 and AXP223 driver 3 * 4 * IMPORTANT when making changes to this file check that the registers 5 * used are the same for the axp221 and axp223. 6 * 7 * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com> 8 * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl> 9 * 10 * SPDX-License-Identifier: GPL-2.0+ 11 */ 12 13 #include <common.h> 14 #include <errno.h> 15 #include <asm/arch/p2wi.h> 16 #include <asm/arch/rsb.h> 17 #include <asm/arch/gpio.h> 18 #include <axp221.h> 19 20 /* 21 * The axp221 uses the p2wi bus, the axp223 is identical (for all registers 22 * used sofar) but uses the rsb bus. These functions abstract this. 23 */ 24 static int pmic_bus_init(void) 25 { 26 #ifdef CONFIG_MACH_SUN6I 27 p2wi_init(); 28 return p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR, 29 AXP221_INIT_DATA); 30 #else 31 int ret; 32 33 ret = rsb_init(); 34 if (ret) 35 return ret; 36 37 return rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR); 38 #endif 39 } 40 41 static int pmic_bus_read(const u8 addr, u8 *data) 42 { 43 #ifdef CONFIG_MACH_SUN6I 44 return p2wi_read(addr, data); 45 #else 46 return rsb_read(AXP223_RUNTIME_ADDR, addr, data); 47 #endif 48 } 49 50 static int pmic_bus_write(const u8 addr, u8 data) 51 { 52 #ifdef CONFIG_MACH_SUN6I 53 return p2wi_write(addr, data); 54 #else 55 return rsb_write(AXP223_RUNTIME_ADDR, addr, data); 56 #endif 57 } 58 59 static u8 axp221_mvolt_to_cfg(int mvolt, int min, int max, int div) 60 { 61 if (mvolt < min) 62 mvolt = min; 63 else if (mvolt > max) 64 mvolt = max; 65 66 return (mvolt - min) / div; 67 } 68 69 static int axp221_setbits(u8 reg, u8 bits) 70 { 71 int ret; 72 u8 val; 73 74 ret = pmic_bus_read(reg, &val); 75 if (ret) 76 return ret; 77 78 val |= bits; 79 return pmic_bus_write(reg, val); 80 } 81 82 static int axp221_clrbits(u8 reg, u8 bits) 83 { 84 int ret; 85 u8 val; 86 87 ret = pmic_bus_read(reg, &val); 88 if (ret) 89 return ret; 90 91 val &= ~bits; 92 return pmic_bus_write(reg, val); 93 } 94 95 int axp221_set_dcdc1(unsigned int mvolt) 96 { 97 int ret; 98 u8 cfg = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100); 99 100 if (mvolt == 0) 101 return axp221_clrbits(AXP221_OUTPUT_CTRL1, 102 AXP221_OUTPUT_CTRL1_DCDC1_EN); 103 104 ret = pmic_bus_write(AXP221_DCDC1_CTRL, cfg); 105 if (ret) 106 return ret; 107 108 ret = axp221_setbits(AXP221_OUTPUT_CTRL2, 109 AXP221_OUTPUT_CTRL2_DCDC1SW_EN); 110 if (ret) 111 return ret; 112 113 return axp221_setbits(AXP221_OUTPUT_CTRL1, 114 AXP221_OUTPUT_CTRL1_DCDC1_EN); 115 } 116 117 int axp221_set_dcdc2(unsigned int mvolt) 118 { 119 int ret; 120 u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20); 121 122 if (mvolt == 0) 123 return axp221_clrbits(AXP221_OUTPUT_CTRL1, 124 AXP221_OUTPUT_CTRL1_DCDC2_EN); 125 126 ret = pmic_bus_write(AXP221_DCDC2_CTRL, cfg); 127 if (ret) 128 return ret; 129 130 return axp221_setbits(AXP221_OUTPUT_CTRL1, 131 AXP221_OUTPUT_CTRL1_DCDC2_EN); 132 } 133 134 int axp221_set_dcdc3(unsigned int mvolt) 135 { 136 int ret; 137 u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20); 138 139 if (mvolt == 0) 140 return axp221_clrbits(AXP221_OUTPUT_CTRL1, 141 AXP221_OUTPUT_CTRL1_DCDC3_EN); 142 143 ret = pmic_bus_write(AXP221_DCDC3_CTRL, cfg); 144 if (ret) 145 return ret; 146 147 return axp221_setbits(AXP221_OUTPUT_CTRL1, 148 AXP221_OUTPUT_CTRL1_DCDC3_EN); 149 } 150 151 int axp221_set_dcdc4(unsigned int mvolt) 152 { 153 int ret; 154 u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20); 155 156 if (mvolt == 0) 157 return axp221_clrbits(AXP221_OUTPUT_CTRL1, 158 AXP221_OUTPUT_CTRL1_DCDC4_EN); 159 160 ret = pmic_bus_write(AXP221_DCDC4_CTRL, cfg); 161 if (ret) 162 return ret; 163 164 return axp221_setbits(AXP221_OUTPUT_CTRL1, 165 AXP221_OUTPUT_CTRL1_DCDC4_EN); 166 } 167 168 int axp221_set_dcdc5(unsigned int mvolt) 169 { 170 int ret; 171 u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50); 172 173 if (mvolt == 0) 174 return axp221_clrbits(AXP221_OUTPUT_CTRL1, 175 AXP221_OUTPUT_CTRL1_DCDC5_EN); 176 177 ret = pmic_bus_write(AXP221_DCDC5_CTRL, cfg); 178 if (ret) 179 return ret; 180 181 return axp221_setbits(AXP221_OUTPUT_CTRL1, 182 AXP221_OUTPUT_CTRL1_DCDC5_EN); 183 } 184 185 int axp221_set_dldo1(unsigned int mvolt) 186 { 187 int ret; 188 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 189 190 if (mvolt == 0) 191 return axp221_clrbits(AXP221_OUTPUT_CTRL2, 192 AXP221_OUTPUT_CTRL2_DLDO1_EN); 193 194 ret = pmic_bus_write(AXP221_DLDO1_CTRL, cfg); 195 if (ret) 196 return ret; 197 198 return axp221_setbits(AXP221_OUTPUT_CTRL2, 199 AXP221_OUTPUT_CTRL2_DLDO1_EN); 200 } 201 202 int axp221_set_dldo2(unsigned int mvolt) 203 { 204 int ret; 205 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 206 207 if (mvolt == 0) 208 return axp221_clrbits(AXP221_OUTPUT_CTRL2, 209 AXP221_OUTPUT_CTRL2_DLDO2_EN); 210 211 ret = pmic_bus_write(AXP221_DLDO2_CTRL, cfg); 212 if (ret) 213 return ret; 214 215 return axp221_setbits(AXP221_OUTPUT_CTRL2, 216 AXP221_OUTPUT_CTRL2_DLDO2_EN); 217 } 218 219 int axp221_set_dldo3(unsigned int mvolt) 220 { 221 int ret; 222 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 223 224 if (mvolt == 0) 225 return axp221_clrbits(AXP221_OUTPUT_CTRL2, 226 AXP221_OUTPUT_CTRL2_DLDO3_EN); 227 228 ret = pmic_bus_write(AXP221_DLDO3_CTRL, cfg); 229 if (ret) 230 return ret; 231 232 return axp221_setbits(AXP221_OUTPUT_CTRL2, 233 AXP221_OUTPUT_CTRL2_DLDO3_EN); 234 } 235 236 int axp221_set_dldo4(unsigned int mvolt) 237 { 238 int ret; 239 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 240 241 if (mvolt == 0) 242 return axp221_clrbits(AXP221_OUTPUT_CTRL2, 243 AXP221_OUTPUT_CTRL2_DLDO4_EN); 244 245 ret = pmic_bus_write(AXP221_DLDO4_CTRL, cfg); 246 if (ret) 247 return ret; 248 249 return axp221_setbits(AXP221_OUTPUT_CTRL2, 250 AXP221_OUTPUT_CTRL2_DLDO4_EN); 251 } 252 253 int axp221_set_aldo1(unsigned int mvolt) 254 { 255 int ret; 256 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 257 258 if (mvolt == 0) 259 return axp221_clrbits(AXP221_OUTPUT_CTRL1, 260 AXP221_OUTPUT_CTRL1_ALDO1_EN); 261 262 ret = pmic_bus_write(AXP221_ALDO1_CTRL, cfg); 263 if (ret) 264 return ret; 265 266 return axp221_setbits(AXP221_OUTPUT_CTRL1, 267 AXP221_OUTPUT_CTRL1_ALDO1_EN); 268 } 269 270 int axp221_set_aldo2(unsigned int mvolt) 271 { 272 int ret; 273 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 274 275 if (mvolt == 0) 276 return axp221_clrbits(AXP221_OUTPUT_CTRL1, 277 AXP221_OUTPUT_CTRL1_ALDO2_EN); 278 279 ret = pmic_bus_write(AXP221_ALDO2_CTRL, cfg); 280 if (ret) 281 return ret; 282 283 return axp221_setbits(AXP221_OUTPUT_CTRL1, 284 AXP221_OUTPUT_CTRL1_ALDO2_EN); 285 } 286 287 int axp221_set_aldo3(unsigned int mvolt) 288 { 289 int ret; 290 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 291 292 if (mvolt == 0) 293 return axp221_clrbits(AXP221_OUTPUT_CTRL3, 294 AXP221_OUTPUT_CTRL3_ALDO3_EN); 295 296 ret = pmic_bus_write(AXP221_ALDO3_CTRL, cfg); 297 if (ret) 298 return ret; 299 300 return axp221_setbits(AXP221_OUTPUT_CTRL3, 301 AXP221_OUTPUT_CTRL3_ALDO3_EN); 302 } 303 304 int axp221_set_eldo(int eldo_num, unsigned int mvolt) 305 { 306 int ret; 307 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 308 u8 addr, bits; 309 310 switch (eldo_num) { 311 case 3: 312 addr = AXP221_ELDO3_CTRL; 313 bits = AXP221_OUTPUT_CTRL2_ELDO3_EN; 314 break; 315 case 2: 316 addr = AXP221_ELDO2_CTRL; 317 bits = AXP221_OUTPUT_CTRL2_ELDO2_EN; 318 break; 319 case 1: 320 addr = AXP221_ELDO1_CTRL; 321 bits = AXP221_OUTPUT_CTRL2_ELDO1_EN; 322 break; 323 default: 324 return -EINVAL; 325 } 326 327 if (mvolt == 0) 328 return axp221_clrbits(AXP221_OUTPUT_CTRL2, bits); 329 330 ret = pmic_bus_write(addr, cfg); 331 if (ret) 332 return ret; 333 334 return axp221_setbits(AXP221_OUTPUT_CTRL2, bits); 335 } 336 337 int axp221_init(void) 338 { 339 /* This cannot be 0 because it is used in SPL before BSS is ready */ 340 static int needs_init = 1; 341 u8 axp_chip_id; 342 int ret; 343 344 if (!needs_init) 345 return 0; 346 347 ret = pmic_bus_init(); 348 if (ret) 349 return ret; 350 351 ret = pmic_bus_read(AXP221_CHIP_ID, &axp_chip_id); 352 if (ret) 353 return ret; 354 355 if (!(axp_chip_id == 0x6 || axp_chip_id == 0x7 || axp_chip_id == 0x17)) 356 return -ENODEV; 357 358 needs_init = 0; 359 return 0; 360 } 361 362 int axp221_get_sid(unsigned int *sid) 363 { 364 u8 *dest = (u8 *)sid; 365 int i, ret; 366 367 ret = axp221_init(); 368 if (ret) 369 return ret; 370 371 ret = pmic_bus_write(AXP221_PAGE, 1); 372 if (ret) 373 return ret; 374 375 for (i = 0; i < 16; i++) { 376 ret = pmic_bus_read(AXP221_SID + i, &dest[i]); 377 if (ret) 378 return ret; 379 } 380 381 pmic_bus_write(AXP221_PAGE, 0); 382 383 for (i = 0; i < 4; i++) 384 sid[i] = be32_to_cpu(sid[i]); 385 386 return 0; 387 } 388 389 int axp_gpio_direction_input(unsigned int pin) 390 { 391 switch (pin) { 392 case SUNXI_GPIO_AXP0_VBUS_DETECT: 393 return 0; 394 default: 395 return -EINVAL; 396 } 397 } 398 399 int axp_gpio_direction_output(unsigned int pin, unsigned int val) 400 { 401 int ret; 402 403 switch (pin) { 404 case SUNXI_GPIO_AXP0_VBUS_ENABLE: 405 ret = axp221_clrbits(AXP221_MISC_CTRL, 406 AXP221_MISC_CTRL_N_VBUSEN_FUNC); 407 if (ret) 408 return ret; 409 410 return axp_gpio_set_value(pin, val); 411 default: 412 return -EINVAL; 413 } 414 } 415 416 int axp_gpio_get_value(unsigned int pin) 417 { 418 int ret; 419 u8 val; 420 421 switch (pin) { 422 case SUNXI_GPIO_AXP0_VBUS_DETECT: 423 ret = pmic_bus_read(AXP221_POWER_STATUS, &val); 424 if (ret) 425 return ret; 426 427 return !!(val & AXP221_POWER_STATUS_VBUS_AVAIL); 428 default: 429 return -EINVAL; 430 } 431 } 432 433 int axp_gpio_set_value(unsigned int pin, unsigned int val) 434 { 435 int ret; 436 437 switch (pin) { 438 case SUNXI_GPIO_AXP0_VBUS_ENABLE: 439 if (val) 440 ret = axp221_setbits(AXP221_VBUS_IPSOUT, 441 AXP221_VBUS_IPSOUT_DRIVEBUS); 442 else 443 ret = axp221_clrbits(AXP221_VBUS_IPSOUT, 444 AXP221_VBUS_IPSOUT_DRIVEBUS); 445 446 if (ret) 447 return ret; 448 } 449 450 return 0; 451 } 452