15c7f10fdSOliver Schinagl /* 2*bdcdf846SHans de Goede * AXP221 and AXP223 driver 3*bdcdf846SHans de Goede * 4*bdcdf846SHans de Goede * IMPORTANT when making changes to this file check that the registers 5*bdcdf846SHans de Goede * used are the same for the axp221 and axp223. 6*bdcdf846SHans de Goede * 7*bdcdf846SHans 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> 155c7f10fdSOliver Schinagl #include <asm/arch/p2wi.h> 16*bdcdf846SHans de Goede #include <asm/arch/rsb.h> 175c7f10fdSOliver Schinagl #include <axp221.h> 185c7f10fdSOliver Schinagl 19*bdcdf846SHans de Goede /* 20*bdcdf846SHans de Goede * The axp221 uses the p2wi bus, the axp223 is identical (for all registers 21*bdcdf846SHans de Goede * used sofar) but uses the rsb bus. These functions abstract this. 22*bdcdf846SHans de Goede */ 23*bdcdf846SHans de Goede static int pmic_bus_init(void) 24*bdcdf846SHans de Goede { 25*bdcdf846SHans de Goede #ifdef CONFIG_MACH_SUN6I 26*bdcdf846SHans de Goede p2wi_init(); 27*bdcdf846SHans de Goede return p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR, 28*bdcdf846SHans de Goede AXP221_INIT_DATA); 29*bdcdf846SHans de Goede #else 30*bdcdf846SHans de Goede int ret; 31*bdcdf846SHans de Goede 32*bdcdf846SHans de Goede rsb_init(); 33*bdcdf846SHans de Goede 34*bdcdf846SHans de Goede ret = rsb_set_device_mode(AXP223_DEVICE_MODE_DATA); 35*bdcdf846SHans de Goede if (ret) 36*bdcdf846SHans de Goede return ret; 37*bdcdf846SHans de Goede 38*bdcdf846SHans de Goede return rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR); 39*bdcdf846SHans de Goede #endif 40*bdcdf846SHans de Goede } 41*bdcdf846SHans de Goede 42*bdcdf846SHans de Goede static int pmic_bus_read(const u8 addr, u8 *data) 43*bdcdf846SHans de Goede { 44*bdcdf846SHans de Goede #ifdef CONFIG_MACH_SUN6I 45*bdcdf846SHans de Goede return p2wi_read(addr, data); 46*bdcdf846SHans de Goede #else 47*bdcdf846SHans de Goede return rsb_read(AXP223_RUNTIME_ADDR, addr, data); 48*bdcdf846SHans de Goede #endif 49*bdcdf846SHans de Goede } 50*bdcdf846SHans de Goede 51*bdcdf846SHans de Goede static int pmic_bus_write(const u8 addr, u8 data) 52*bdcdf846SHans de Goede { 53*bdcdf846SHans de Goede #ifdef CONFIG_MACH_SUN6I 54*bdcdf846SHans de Goede return p2wi_write(addr, data); 55*bdcdf846SHans de Goede #else 56*bdcdf846SHans de Goede return rsb_write(AXP223_RUNTIME_ADDR, addr, data); 57*bdcdf846SHans de Goede #endif 58*bdcdf846SHans de Goede } 59*bdcdf846SHans de Goede 605c7f10fdSOliver Schinagl static u8 axp221_mvolt_to_cfg(int mvolt, int min, int max, int div) 615c7f10fdSOliver Schinagl { 625c7f10fdSOliver Schinagl if (mvolt < min) 635c7f10fdSOliver Schinagl mvolt = min; 645c7f10fdSOliver Schinagl else if (mvolt > max) 655c7f10fdSOliver Schinagl mvolt = max; 665c7f10fdSOliver Schinagl 675c7f10fdSOliver Schinagl return (mvolt - min) / div; 685c7f10fdSOliver Schinagl } 695c7f10fdSOliver Schinagl 705c7f10fdSOliver Schinagl static int axp221_setbits(u8 reg, u8 bits) 715c7f10fdSOliver Schinagl { 725c7f10fdSOliver Schinagl int ret; 735c7f10fdSOliver Schinagl u8 val; 745c7f10fdSOliver Schinagl 75*bdcdf846SHans de Goede ret = pmic_bus_read(reg, &val); 765c7f10fdSOliver Schinagl if (ret) 775c7f10fdSOliver Schinagl return ret; 785c7f10fdSOliver Schinagl 795c7f10fdSOliver Schinagl val |= bits; 80*bdcdf846SHans de Goede return pmic_bus_write(reg, val); 815c7f10fdSOliver Schinagl } 825c7f10fdSOliver Schinagl 835c7f10fdSOliver Schinagl int axp221_set_dcdc1(unsigned int mvolt) 845c7f10fdSOliver Schinagl { 855c7f10fdSOliver Schinagl int ret; 865c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100); 875c7f10fdSOliver Schinagl 88*bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_DCDC1_CTRL, cfg); 895c7f10fdSOliver Schinagl if (ret) 905c7f10fdSOliver Schinagl return ret; 915c7f10fdSOliver Schinagl 925c7f10fdSOliver Schinagl return axp221_setbits(AXP221_OUTPUT_CTRL2, 935c7f10fdSOliver Schinagl AXP221_OUTPUT_CTRL2_DCDC1_EN); 945c7f10fdSOliver Schinagl } 955c7f10fdSOliver Schinagl 965c7f10fdSOliver Schinagl int axp221_set_dcdc2(unsigned int mvolt) 975c7f10fdSOliver Schinagl { 985c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20); 995c7f10fdSOliver Schinagl 100*bdcdf846SHans de Goede return pmic_bus_write(AXP221_DCDC2_CTRL, cfg); 1015c7f10fdSOliver Schinagl } 1025c7f10fdSOliver Schinagl 1035c7f10fdSOliver Schinagl int axp221_set_dcdc3(unsigned int mvolt) 1045c7f10fdSOliver Schinagl { 1055c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20); 1065c7f10fdSOliver Schinagl 107*bdcdf846SHans de Goede return pmic_bus_write(AXP221_DCDC3_CTRL, cfg); 1085c7f10fdSOliver Schinagl } 1095c7f10fdSOliver Schinagl 1105c7f10fdSOliver Schinagl int axp221_set_dcdc4(unsigned int mvolt) 1115c7f10fdSOliver Schinagl { 1125c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20); 1135c7f10fdSOliver Schinagl 114*bdcdf846SHans de Goede return pmic_bus_write(AXP221_DCDC4_CTRL, cfg); 1155c7f10fdSOliver Schinagl } 1165c7f10fdSOliver Schinagl 1175c7f10fdSOliver Schinagl int axp221_set_dcdc5(unsigned int mvolt) 1185c7f10fdSOliver Schinagl { 1195c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50); 1205c7f10fdSOliver Schinagl 121*bdcdf846SHans de Goede return pmic_bus_write(AXP221_DCDC5_CTRL, cfg); 1225c7f10fdSOliver Schinagl } 1235c7f10fdSOliver Schinagl 1245c7f10fdSOliver Schinagl int axp221_set_dldo1(unsigned int mvolt) 1255c7f10fdSOliver Schinagl { 1265c7f10fdSOliver Schinagl int ret; 1275c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 1285c7f10fdSOliver Schinagl 129*bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_DLDO1_CTRL, cfg); 1305c7f10fdSOliver Schinagl if (ret) 1315c7f10fdSOliver Schinagl return ret; 1325c7f10fdSOliver Schinagl 1335c7f10fdSOliver Schinagl return axp221_setbits(AXP221_OUTPUT_CTRL2, 1345c7f10fdSOliver Schinagl AXP221_OUTPUT_CTRL2_DLDO1_EN); 1355c7f10fdSOliver Schinagl } 1365c7f10fdSOliver Schinagl 1375c7f10fdSOliver Schinagl int axp221_set_dldo2(unsigned int mvolt) 1385c7f10fdSOliver Schinagl { 1395c7f10fdSOliver Schinagl int ret; 1405c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 1415c7f10fdSOliver Schinagl 142*bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_DLDO2_CTRL, cfg); 1435c7f10fdSOliver Schinagl if (ret) 1445c7f10fdSOliver Schinagl return ret; 1455c7f10fdSOliver Schinagl 1465c7f10fdSOliver Schinagl return axp221_setbits(AXP221_OUTPUT_CTRL2, 1475c7f10fdSOliver Schinagl AXP221_OUTPUT_CTRL2_DLDO2_EN); 1485c7f10fdSOliver Schinagl } 1495c7f10fdSOliver Schinagl 1505c7f10fdSOliver Schinagl int axp221_set_dldo3(unsigned int mvolt) 1515c7f10fdSOliver Schinagl { 1525c7f10fdSOliver Schinagl int ret; 1535c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 1545c7f10fdSOliver Schinagl 155*bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_DLDO3_CTRL, cfg); 1565c7f10fdSOliver Schinagl if (ret) 1575c7f10fdSOliver Schinagl return ret; 1585c7f10fdSOliver Schinagl 1595c7f10fdSOliver Schinagl return axp221_setbits(AXP221_OUTPUT_CTRL2, 1605c7f10fdSOliver Schinagl AXP221_OUTPUT_CTRL2_DLDO3_EN); 1615c7f10fdSOliver Schinagl } 1625c7f10fdSOliver Schinagl 1635c7f10fdSOliver Schinagl int axp221_set_dldo4(unsigned int mvolt) 1645c7f10fdSOliver Schinagl { 1655c7f10fdSOliver Schinagl int ret; 1665c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 1675c7f10fdSOliver Schinagl 168*bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_DLDO4_CTRL, cfg); 1695c7f10fdSOliver Schinagl if (ret) 1705c7f10fdSOliver Schinagl return ret; 1715c7f10fdSOliver Schinagl 1725c7f10fdSOliver Schinagl return axp221_setbits(AXP221_OUTPUT_CTRL2, 1735c7f10fdSOliver Schinagl AXP221_OUTPUT_CTRL2_DLDO4_EN); 1745c7f10fdSOliver Schinagl } 1755c7f10fdSOliver Schinagl 1765c7f10fdSOliver Schinagl int axp221_set_aldo1(unsigned int mvolt) 1775c7f10fdSOliver Schinagl { 1785c7f10fdSOliver Schinagl int ret; 1795c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 1805c7f10fdSOliver Schinagl 181*bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_ALDO1_CTRL, cfg); 1825c7f10fdSOliver Schinagl if (ret) 1835c7f10fdSOliver Schinagl return ret; 1845c7f10fdSOliver Schinagl 1855c7f10fdSOliver Schinagl return axp221_setbits(AXP221_OUTPUT_CTRL1, 1865c7f10fdSOliver Schinagl AXP221_OUTPUT_CTRL1_ALDO1_EN); 1875c7f10fdSOliver Schinagl } 1885c7f10fdSOliver Schinagl 1895c7f10fdSOliver Schinagl int axp221_set_aldo2(unsigned int mvolt) 1905c7f10fdSOliver Schinagl { 1915c7f10fdSOliver Schinagl int ret; 1925c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 1935c7f10fdSOliver Schinagl 194*bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_ALDO2_CTRL, cfg); 1955c7f10fdSOliver Schinagl if (ret) 1965c7f10fdSOliver Schinagl return ret; 1975c7f10fdSOliver Schinagl 1985c7f10fdSOliver Schinagl return axp221_setbits(AXP221_OUTPUT_CTRL1, 1995c7f10fdSOliver Schinagl AXP221_OUTPUT_CTRL1_ALDO2_EN); 2005c7f10fdSOliver Schinagl } 2015c7f10fdSOliver Schinagl 2025c7f10fdSOliver Schinagl int axp221_set_aldo3(unsigned int mvolt) 2035c7f10fdSOliver Schinagl { 2045c7f10fdSOliver Schinagl int ret; 2055c7f10fdSOliver Schinagl u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); 2065c7f10fdSOliver Schinagl 207*bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_ALDO3_CTRL, cfg); 2085c7f10fdSOliver Schinagl if (ret) 2095c7f10fdSOliver Schinagl return ret; 2105c7f10fdSOliver Schinagl 2115c7f10fdSOliver Schinagl return axp221_setbits(AXP221_OUTPUT_CTRL3, 2125c7f10fdSOliver Schinagl AXP221_OUTPUT_CTRL3_ALDO3_EN); 2135c7f10fdSOliver Schinagl } 2145c7f10fdSOliver Schinagl 2155c7f10fdSOliver Schinagl int axp221_init(void) 2165c7f10fdSOliver Schinagl { 2175c7f10fdSOliver Schinagl u8 axp_chip_id; 2185c7f10fdSOliver Schinagl int ret; 2195c7f10fdSOliver Schinagl 220*bdcdf846SHans de Goede ret = pmic_bus_init(); 2215c7f10fdSOliver Schinagl if (ret) 2225c7f10fdSOliver Schinagl return ret; 2235c7f10fdSOliver Schinagl 224*bdcdf846SHans de Goede ret = pmic_bus_read(AXP221_CHIP_ID, &axp_chip_id); 2255c7f10fdSOliver Schinagl if (ret) 2265c7f10fdSOliver Schinagl return ret; 2275c7f10fdSOliver Schinagl 2285c7f10fdSOliver Schinagl if (!(axp_chip_id == 0x6 || axp_chip_id == 0x7 || axp_chip_id == 0x17)) 2295c7f10fdSOliver Schinagl return -ENODEV; 2305c7f10fdSOliver Schinagl 2315c7f10fdSOliver Schinagl return 0; 2325c7f10fdSOliver Schinagl } 233f3fba566SHans de Goede 234f3fba566SHans de Goede int axp221_get_sid(unsigned int *sid) 235f3fba566SHans de Goede { 236f3fba566SHans de Goede u8 *dest = (u8 *)sid; 237f3fba566SHans de Goede int i, ret; 238f3fba566SHans de Goede 239f3fba566SHans de Goede ret = axp221_init(); 240f3fba566SHans de Goede if (ret) 241f3fba566SHans de Goede return ret; 242f3fba566SHans de Goede 243*bdcdf846SHans de Goede ret = pmic_bus_write(AXP221_PAGE, 1); 244f3fba566SHans de Goede if (ret) 245f3fba566SHans de Goede return ret; 246f3fba566SHans de Goede 247f3fba566SHans de Goede for (i = 0; i < 16; i++) { 248*bdcdf846SHans de Goede ret = pmic_bus_read(AXP221_SID + i, &dest[i]); 249f3fba566SHans de Goede if (ret) 250f3fba566SHans de Goede return ret; 251f3fba566SHans de Goede } 252f3fba566SHans de Goede 253*bdcdf846SHans de Goede pmic_bus_write(AXP221_PAGE, 0); 254f3fba566SHans de Goede 255f3fba566SHans de Goede for (i = 0; i < 4; i++) 256f3fba566SHans de Goede sid[i] = be32_to_cpu(sid[i]); 257f3fba566SHans de Goede 258f3fba566SHans de Goede return 0; 259f3fba566SHans de Goede } 260