15c7f10fdSOliver Schinagl /* 2bdcdf846SHans de Goede * AXP221 and AXP223 driver 3bdcdf846SHans de Goede * 4bdcdf846SHans de Goede * IMPORTANT when making changes to this file check that the registers 5bdcdf846SHans de Goede * used are the same for the axp221 and axp223. 6bdcdf846SHans de Goede * 7bdcdf846SHans de Goede * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com> 85c7f10fdSOliver Schinagl * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl> 95c7f10fdSOliver Schinagl * 105c7f10fdSOliver Schinagl * SPDX-License-Identifier: GPL-2.0+ 115c7f10fdSOliver Schinagl */ 125c7f10fdSOliver Schinagl 135c7f10fdSOliver Schinagl #include <common.h> 145c7f10fdSOliver Schinagl #include <errno.h> 151d624a4fSHans de Goede #include <asm/arch/pmic_bus.h> 16*6944aff1SHans de Goede #include <axp_pmic.h> 175c7f10fdSOliver Schinagl 185c7f10fdSOliver Schinagl static u8 axp221_mvolt_to_cfg(int mvolt, int min, int max, int div) 195c7f10fdSOliver Schinagl { 205c7f10fdSOliver Schinagl if (mvolt < min) 215c7f10fdSOliver Schinagl mvolt = min; 225c7f10fdSOliver Schinagl else if (mvolt > max) 235c7f10fdSOliver Schinagl mvolt = max; 245c7f10fdSOliver Schinagl 255c7f10fdSOliver Schinagl return (mvolt - min) / div; 265c7f10fdSOliver Schinagl } 275c7f10fdSOliver Schinagl 28*6944aff1SHans de Goede int axp_set_dcdc1(unsigned int mvolt) 295c7f10fdSOliver Schinagl { 305c7f10fdSOliver Schinagl int ret; 315c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100); 325c7f10fdSOliver Schinagl 3350e0d5e6SHans de Goede if (mvolt == 0) 341d624a4fSHans de Goede return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1, 3550e0d5e6SHans de Goede AXP221_OUTPUT_CTRL1_DCDC1_EN); 3650e0d5e6SHans de Goede 37bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_DCDC1_CTRL, cfg); 385c7f10fdSOliver Schinagl if (ret) 395c7f10fdSOliver Schinagl return ret; 405c7f10fdSOliver Schinagl 411d624a4fSHans de Goede ret = pmic_bus_setbits(AXP221_OUTPUT_CTRL2, 4250e0d5e6SHans de Goede AXP221_OUTPUT_CTRL2_DCDC1SW_EN); 4350e0d5e6SHans de Goede if (ret) 4450e0d5e6SHans de Goede return ret; 4550e0d5e6SHans de Goede 461d624a4fSHans de Goede return pmic_bus_setbits(AXP221_OUTPUT_CTRL1, 4750e0d5e6SHans de Goede AXP221_OUTPUT_CTRL1_DCDC1_EN); 485c7f10fdSOliver Schinagl } 495c7f10fdSOliver Schinagl 50*6944aff1SHans de Goede int axp_set_dcdc2(unsigned int mvolt) 515c7f10fdSOliver Schinagl { 5250e0d5e6SHans de Goede int ret; 535c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20); 545c7f10fdSOliver Schinagl 5550e0d5e6SHans de Goede if (mvolt == 0) 561d624a4fSHans de Goede return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1, 5750e0d5e6SHans de Goede AXP221_OUTPUT_CTRL1_DCDC2_EN); 5850e0d5e6SHans de Goede 5950e0d5e6SHans de Goede ret = pmic_bus_write(AXP221_DCDC2_CTRL, cfg); 6050e0d5e6SHans de Goede if (ret) 6150e0d5e6SHans de Goede return ret; 6250e0d5e6SHans de Goede 631d624a4fSHans de Goede return pmic_bus_setbits(AXP221_OUTPUT_CTRL1, 6450e0d5e6SHans de Goede AXP221_OUTPUT_CTRL1_DCDC2_EN); 655c7f10fdSOliver Schinagl } 665c7f10fdSOliver Schinagl 67*6944aff1SHans de Goede int axp_set_dcdc3(unsigned int mvolt) 685c7f10fdSOliver Schinagl { 6950e0d5e6SHans de Goede int ret; 705c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20); 715c7f10fdSOliver Schinagl 7250e0d5e6SHans de Goede if (mvolt == 0) 731d624a4fSHans de Goede return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1, 7450e0d5e6SHans de Goede AXP221_OUTPUT_CTRL1_DCDC3_EN); 7550e0d5e6SHans de Goede 7650e0d5e6SHans de Goede ret = pmic_bus_write(AXP221_DCDC3_CTRL, cfg); 7750e0d5e6SHans de Goede if (ret) 7850e0d5e6SHans de Goede return ret; 7950e0d5e6SHans de Goede 801d624a4fSHans de Goede return pmic_bus_setbits(AXP221_OUTPUT_CTRL1, 8150e0d5e6SHans de Goede AXP221_OUTPUT_CTRL1_DCDC3_EN); 825c7f10fdSOliver Schinagl } 835c7f10fdSOliver Schinagl 84*6944aff1SHans de Goede int axp_set_dcdc4(unsigned int mvolt) 855c7f10fdSOliver Schinagl { 8650e0d5e6SHans de Goede int ret; 875c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20); 885c7f10fdSOliver Schinagl 8950e0d5e6SHans de Goede if (mvolt == 0) 901d624a4fSHans de Goede return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1, 9150e0d5e6SHans de Goede AXP221_OUTPUT_CTRL1_DCDC4_EN); 9250e0d5e6SHans de Goede 9350e0d5e6SHans de Goede ret = pmic_bus_write(AXP221_DCDC4_CTRL, cfg); 9450e0d5e6SHans de Goede if (ret) 9550e0d5e6SHans de Goede return ret; 9650e0d5e6SHans de Goede 971d624a4fSHans de Goede return pmic_bus_setbits(AXP221_OUTPUT_CTRL1, 9850e0d5e6SHans de Goede AXP221_OUTPUT_CTRL1_DCDC4_EN); 995c7f10fdSOliver Schinagl } 1005c7f10fdSOliver Schinagl 101*6944aff1SHans de Goede int axp_set_dcdc5(unsigned int mvolt) 1025c7f10fdSOliver Schinagl { 10350e0d5e6SHans de Goede int ret; 1045c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50); 1055c7f10fdSOliver Schinagl 10650e0d5e6SHans de Goede if (mvolt == 0) 1071d624a4fSHans de Goede return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1, 10850e0d5e6SHans de Goede AXP221_OUTPUT_CTRL1_DCDC5_EN); 10950e0d5e6SHans de Goede 11050e0d5e6SHans de Goede ret = pmic_bus_write(AXP221_DCDC5_CTRL, cfg); 11150e0d5e6SHans de Goede if (ret) 11250e0d5e6SHans de Goede return ret; 11350e0d5e6SHans de Goede 1141d624a4fSHans de Goede return pmic_bus_setbits(AXP221_OUTPUT_CTRL1, 11550e0d5e6SHans de Goede AXP221_OUTPUT_CTRL1_DCDC5_EN); 1165c7f10fdSOliver Schinagl } 1175c7f10fdSOliver Schinagl 118*6944aff1SHans de Goede int axp_set_dldo1(unsigned int mvolt) 1195c7f10fdSOliver Schinagl { 1205c7f10fdSOliver Schinagl int ret; 1215c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 1225c7f10fdSOliver Schinagl 12350e0d5e6SHans de Goede if (mvolt == 0) 1241d624a4fSHans de Goede return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2, 12550e0d5e6SHans de Goede AXP221_OUTPUT_CTRL2_DLDO1_EN); 12650e0d5e6SHans de Goede 127bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_DLDO1_CTRL, cfg); 1285c7f10fdSOliver Schinagl if (ret) 1295c7f10fdSOliver Schinagl return ret; 1305c7f10fdSOliver Schinagl 1311d624a4fSHans de Goede return pmic_bus_setbits(AXP221_OUTPUT_CTRL2, 1325c7f10fdSOliver Schinagl AXP221_OUTPUT_CTRL2_DLDO1_EN); 1335c7f10fdSOliver Schinagl } 1345c7f10fdSOliver Schinagl 135*6944aff1SHans de Goede int axp_set_dldo2(unsigned int mvolt) 1365c7f10fdSOliver Schinagl { 1375c7f10fdSOliver Schinagl int ret; 1385c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 1395c7f10fdSOliver Schinagl 14050e0d5e6SHans de Goede if (mvolt == 0) 1411d624a4fSHans de Goede return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2, 14250e0d5e6SHans de Goede AXP221_OUTPUT_CTRL2_DLDO2_EN); 14350e0d5e6SHans de Goede 144bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_DLDO2_CTRL, cfg); 1455c7f10fdSOliver Schinagl if (ret) 1465c7f10fdSOliver Schinagl return ret; 1475c7f10fdSOliver Schinagl 1481d624a4fSHans de Goede return pmic_bus_setbits(AXP221_OUTPUT_CTRL2, 1495c7f10fdSOliver Schinagl AXP221_OUTPUT_CTRL2_DLDO2_EN); 1505c7f10fdSOliver Schinagl } 1515c7f10fdSOliver Schinagl 152*6944aff1SHans de Goede int axp_set_dldo3(unsigned int mvolt) 1535c7f10fdSOliver Schinagl { 1545c7f10fdSOliver Schinagl int ret; 1555c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 1565c7f10fdSOliver Schinagl 15750e0d5e6SHans de Goede if (mvolt == 0) 1581d624a4fSHans de Goede return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2, 15950e0d5e6SHans de Goede AXP221_OUTPUT_CTRL2_DLDO3_EN); 16050e0d5e6SHans de Goede 161bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_DLDO3_CTRL, cfg); 1625c7f10fdSOliver Schinagl if (ret) 1635c7f10fdSOliver Schinagl return ret; 1645c7f10fdSOliver Schinagl 1651d624a4fSHans de Goede return pmic_bus_setbits(AXP221_OUTPUT_CTRL2, 1665c7f10fdSOliver Schinagl AXP221_OUTPUT_CTRL2_DLDO3_EN); 1675c7f10fdSOliver Schinagl } 1685c7f10fdSOliver Schinagl 169*6944aff1SHans de Goede int axp_set_dldo4(unsigned int mvolt) 1705c7f10fdSOliver Schinagl { 1715c7f10fdSOliver Schinagl int ret; 1725c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 1735c7f10fdSOliver Schinagl 17450e0d5e6SHans de Goede if (mvolt == 0) 1751d624a4fSHans de Goede return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2, 17650e0d5e6SHans de Goede AXP221_OUTPUT_CTRL2_DLDO4_EN); 17750e0d5e6SHans de Goede 178bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_DLDO4_CTRL, cfg); 1795c7f10fdSOliver Schinagl if (ret) 1805c7f10fdSOliver Schinagl return ret; 1815c7f10fdSOliver Schinagl 1821d624a4fSHans de Goede return pmic_bus_setbits(AXP221_OUTPUT_CTRL2, 1835c7f10fdSOliver Schinagl AXP221_OUTPUT_CTRL2_DLDO4_EN); 1845c7f10fdSOliver Schinagl } 1855c7f10fdSOliver Schinagl 186*6944aff1SHans de Goede int axp_set_aldo1(unsigned int mvolt) 1875c7f10fdSOliver Schinagl { 1885c7f10fdSOliver Schinagl int ret; 1895c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 1905c7f10fdSOliver Schinagl 19150e0d5e6SHans de Goede if (mvolt == 0) 1921d624a4fSHans de Goede return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1, 19350e0d5e6SHans de Goede AXP221_OUTPUT_CTRL1_ALDO1_EN); 19450e0d5e6SHans de Goede 195bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_ALDO1_CTRL, cfg); 1965c7f10fdSOliver Schinagl if (ret) 1975c7f10fdSOliver Schinagl return ret; 1985c7f10fdSOliver Schinagl 1991d624a4fSHans de Goede return pmic_bus_setbits(AXP221_OUTPUT_CTRL1, 2005c7f10fdSOliver Schinagl AXP221_OUTPUT_CTRL1_ALDO1_EN); 2015c7f10fdSOliver Schinagl } 2025c7f10fdSOliver Schinagl 203*6944aff1SHans de Goede int axp_set_aldo2(unsigned int mvolt) 2045c7f10fdSOliver Schinagl { 2055c7f10fdSOliver Schinagl int ret; 2065c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 2075c7f10fdSOliver Schinagl 20850e0d5e6SHans de Goede if (mvolt == 0) 2091d624a4fSHans de Goede return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1, 21050e0d5e6SHans de Goede AXP221_OUTPUT_CTRL1_ALDO2_EN); 21150e0d5e6SHans de Goede 212bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_ALDO2_CTRL, cfg); 2135c7f10fdSOliver Schinagl if (ret) 2145c7f10fdSOliver Schinagl return ret; 2155c7f10fdSOliver Schinagl 2161d624a4fSHans de Goede return pmic_bus_setbits(AXP221_OUTPUT_CTRL1, 2175c7f10fdSOliver Schinagl AXP221_OUTPUT_CTRL1_ALDO2_EN); 2185c7f10fdSOliver Schinagl } 2195c7f10fdSOliver Schinagl 220*6944aff1SHans de Goede int axp_set_aldo3(unsigned int mvolt) 2215c7f10fdSOliver Schinagl { 2225c7f10fdSOliver Schinagl int ret; 2235c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 2245c7f10fdSOliver Schinagl 22550e0d5e6SHans de Goede if (mvolt == 0) 2261d624a4fSHans de Goede return pmic_bus_clrbits(AXP221_OUTPUT_CTRL3, 22750e0d5e6SHans de Goede AXP221_OUTPUT_CTRL3_ALDO3_EN); 22850e0d5e6SHans de Goede 229bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_ALDO3_CTRL, cfg); 2305c7f10fdSOliver Schinagl if (ret) 2315c7f10fdSOliver Schinagl return ret; 2325c7f10fdSOliver Schinagl 2331d624a4fSHans de Goede return pmic_bus_setbits(AXP221_OUTPUT_CTRL3, 2345c7f10fdSOliver Schinagl AXP221_OUTPUT_CTRL3_ALDO3_EN); 2355c7f10fdSOliver Schinagl } 2365c7f10fdSOliver Schinagl 237*6944aff1SHans de Goede int axp_set_eldo(int eldo_num, unsigned int mvolt) 2386906df1aSSiarhei Siamashka { 2396906df1aSSiarhei Siamashka int ret; 2406906df1aSSiarhei Siamashka u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 2416906df1aSSiarhei Siamashka u8 addr, bits; 2426906df1aSSiarhei Siamashka 2436906df1aSSiarhei Siamashka switch (eldo_num) { 2446906df1aSSiarhei Siamashka case 3: 2456906df1aSSiarhei Siamashka addr = AXP221_ELDO3_CTRL; 2466906df1aSSiarhei Siamashka bits = AXP221_OUTPUT_CTRL2_ELDO3_EN; 2476906df1aSSiarhei Siamashka break; 2486906df1aSSiarhei Siamashka case 2: 2496906df1aSSiarhei Siamashka addr = AXP221_ELDO2_CTRL; 2506906df1aSSiarhei Siamashka bits = AXP221_OUTPUT_CTRL2_ELDO2_EN; 2516906df1aSSiarhei Siamashka break; 2526906df1aSSiarhei Siamashka case 1: 2536906df1aSSiarhei Siamashka addr = AXP221_ELDO1_CTRL; 2546906df1aSSiarhei Siamashka bits = AXP221_OUTPUT_CTRL2_ELDO1_EN; 2556906df1aSSiarhei Siamashka break; 2566906df1aSSiarhei Siamashka default: 2576906df1aSSiarhei Siamashka return -EINVAL; 2586906df1aSSiarhei Siamashka } 2596906df1aSSiarhei Siamashka 2606906df1aSSiarhei Siamashka if (mvolt == 0) 2611d624a4fSHans de Goede return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2, bits); 2626906df1aSSiarhei Siamashka 2636906df1aSSiarhei Siamashka ret = pmic_bus_write(addr, cfg); 2646906df1aSSiarhei Siamashka if (ret) 2656906df1aSSiarhei Siamashka return ret; 2666906df1aSSiarhei Siamashka 2671d624a4fSHans de Goede return pmic_bus_setbits(AXP221_OUTPUT_CTRL2, bits); 2686906df1aSSiarhei Siamashka } 2696906df1aSSiarhei Siamashka 270*6944aff1SHans de Goede int axp_init(void) 2715c7f10fdSOliver Schinagl { 2723c781190SHans de Goede /* This cannot be 0 because it is used in SPL before BSS is ready */ 2733c781190SHans de Goede static int needs_init = 1; 2745c7f10fdSOliver Schinagl u8 axp_chip_id; 2755c7f10fdSOliver Schinagl int ret; 2765c7f10fdSOliver Schinagl 2773c781190SHans de Goede if (!needs_init) 2783c781190SHans de Goede return 0; 2793c781190SHans de Goede 280bdcdf846SHans de Goede ret = pmic_bus_init(); 2815c7f10fdSOliver Schinagl if (ret) 2825c7f10fdSOliver Schinagl return ret; 2835c7f10fdSOliver Schinagl 284bdcdf846SHans de Goede ret = pmic_bus_read(AXP221_CHIP_ID, &axp_chip_id); 2855c7f10fdSOliver Schinagl if (ret) 2865c7f10fdSOliver Schinagl return ret; 2875c7f10fdSOliver Schinagl 2885c7f10fdSOliver Schinagl if (!(axp_chip_id == 0x6 || axp_chip_id == 0x7 || axp_chip_id == 0x17)) 2895c7f10fdSOliver Schinagl return -ENODEV; 2905c7f10fdSOliver Schinagl 2913c781190SHans de Goede needs_init = 0; 2925c7f10fdSOliver Schinagl return 0; 2935c7f10fdSOliver Schinagl } 294f3fba566SHans de Goede 295*6944aff1SHans de Goede int axp_get_sid(unsigned int *sid) 296f3fba566SHans de Goede { 297f3fba566SHans de Goede u8 *dest = (u8 *)sid; 298f3fba566SHans de Goede int i, ret; 299f3fba566SHans de Goede 300*6944aff1SHans de Goede ret = pmic_bus_init(); 301f3fba566SHans de Goede if (ret) 302f3fba566SHans de Goede return ret; 303f3fba566SHans de Goede 304bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_PAGE, 1); 305f3fba566SHans de Goede if (ret) 306f3fba566SHans de Goede return ret; 307f3fba566SHans de Goede 308f3fba566SHans de Goede for (i = 0; i < 16; i++) { 309bdcdf846SHans de Goede ret = pmic_bus_read(AXP221_SID + i, &dest[i]); 310f3fba566SHans de Goede if (ret) 311f3fba566SHans de Goede return ret; 312f3fba566SHans de Goede } 313f3fba566SHans de Goede 314bdcdf846SHans de Goede pmic_bus_write(AXP221_PAGE, 0); 315f3fba566SHans de Goede 316f3fba566SHans de Goede for (i = 0; i < 4; i++) 317f3fba566SHans de Goede sid[i] = be32_to_cpu(sid[i]); 318f3fba566SHans de Goede 319f3fba566SHans de Goede return 0; 320f3fba566SHans de Goede } 321