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