1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2012 4 * Henrik Nordstrom <henrik@henriknordstrom.net> 5 */ 6 7 #include <common.h> 8 #include <command.h> 9 #include <asm/arch/pmic_bus.h> 10 #include <axp_pmic.h> 11 12 static u8 axp209_mvolt_to_cfg(int mvolt, int min, int max, int div) 13 { 14 if (mvolt < min) 15 mvolt = min; 16 else if (mvolt > max) 17 mvolt = max; 18 19 return (mvolt - min) / div; 20 } 21 22 int axp_set_dcdc2(unsigned int mvolt) 23 { 24 int rc; 25 u8 cfg, current; 26 27 if (mvolt == 0) 28 return pmic_bus_clrbits(AXP209_OUTPUT_CTRL, 29 AXP209_OUTPUT_CTRL_DCDC2); 30 31 rc = pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_DCDC2); 32 if (rc) 33 return rc; 34 35 cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25); 36 37 /* Do we really need to be this gentle? It has built-in voltage slope */ 38 while ((rc = pmic_bus_read(AXP209_DCDC2_VOLTAGE, ¤t)) == 0 && 39 current != cfg) { 40 if (current < cfg) 41 current++; 42 else 43 current--; 44 45 rc = pmic_bus_write(AXP209_DCDC2_VOLTAGE, current); 46 if (rc) 47 break; 48 } 49 50 return rc; 51 } 52 53 int axp_set_dcdc3(unsigned int mvolt) 54 { 55 u8 cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25); 56 int rc; 57 58 if (mvolt == 0) 59 return pmic_bus_clrbits(AXP209_OUTPUT_CTRL, 60 AXP209_OUTPUT_CTRL_DCDC3); 61 62 rc = pmic_bus_write(AXP209_DCDC3_VOLTAGE, cfg); 63 if (rc) 64 return rc; 65 66 return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_DCDC3); 67 } 68 69 int axp_set_aldo2(unsigned int mvolt) 70 { 71 int rc; 72 u8 cfg, reg; 73 74 if (mvolt == 0) 75 return pmic_bus_clrbits(AXP209_OUTPUT_CTRL, 76 AXP209_OUTPUT_CTRL_LDO2); 77 78 cfg = axp209_mvolt_to_cfg(mvolt, 1800, 3300, 100); 79 80 rc = pmic_bus_read(AXP209_LDO24_VOLTAGE, ®); 81 if (rc) 82 return rc; 83 84 /* LDO2 configuration is in upper 4 bits */ 85 reg = (reg & 0x0f) | (cfg << 4); 86 rc = pmic_bus_write(AXP209_LDO24_VOLTAGE, reg); 87 if (rc) 88 return rc; 89 90 return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_LDO2); 91 } 92 93 int axp_set_aldo3(unsigned int mvolt) 94 { 95 u8 cfg; 96 int rc; 97 98 if (mvolt == 0) 99 return pmic_bus_clrbits(AXP209_OUTPUT_CTRL, 100 AXP209_OUTPUT_CTRL_LDO3); 101 102 if (mvolt == -1) 103 cfg = 0x80; /* determined by LDO3IN pin */ 104 else 105 cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25); 106 107 rc = pmic_bus_write(AXP209_LDO3_VOLTAGE, cfg); 108 if (rc) 109 return rc; 110 111 return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_LDO3); 112 } 113 114 int axp_set_aldo4(unsigned int mvolt) 115 { 116 int rc; 117 static const unsigned int vindex[] = { 118 1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2500, 119 2700, 2800, 3000, 3100, 3200, 3300 120 }; 121 u8 cfg, reg; 122 123 if (mvolt == 0) 124 return pmic_bus_clrbits(AXP209_OUTPUT_CTRL, 125 AXP209_OUTPUT_CTRL_LDO4); 126 127 /* Translate mvolt to register cfg value, requested <= selected */ 128 for (cfg = 15; vindex[cfg] > mvolt && cfg > 0; cfg--); 129 130 rc = pmic_bus_read(AXP209_LDO24_VOLTAGE, ®); 131 if (rc) 132 return rc; 133 134 /* LDO4 configuration is in lower 4 bits */ 135 reg = (reg & 0xf0) | (cfg << 0); 136 rc = pmic_bus_write(AXP209_LDO24_VOLTAGE, reg); 137 if (rc) 138 return rc; 139 140 return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_LDO4); 141 } 142 143 int axp_init(void) 144 { 145 u8 ver; 146 int i, rc; 147 148 rc = pmic_bus_init(); 149 if (rc) 150 return rc; 151 152 rc = pmic_bus_read(AXP209_CHIP_VERSION, &ver); 153 if (rc) 154 return rc; 155 156 /* Low 4 bits is chip version */ 157 ver &= 0x0f; 158 159 if (ver != 0x1) 160 return -EINVAL; 161 162 /* Mask all interrupts */ 163 for (i = AXP209_IRQ_ENABLE1; i <= AXP209_IRQ_ENABLE5; i++) { 164 rc = pmic_bus_write(i, 0); 165 if (rc) 166 return rc; 167 } 168 169 /* 170 * Turn off LDOIO regulators / tri-state GPIO pins, when rebooting 171 * from android these are sometimes on. 172 */ 173 rc = pmic_bus_write(AXP_GPIO0_CTRL, AXP_GPIO_CTRL_INPUT); 174 if (rc) 175 return rc; 176 177 rc = pmic_bus_write(AXP_GPIO1_CTRL, AXP_GPIO_CTRL_INPUT); 178 if (rc) 179 return rc; 180 181 rc = pmic_bus_write(AXP_GPIO2_CTRL, AXP_GPIO_CTRL_INPUT); 182 if (rc) 183 return rc; 184 185 return 0; 186 } 187 188 int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 189 { 190 pmic_bus_write(AXP209_SHUTDOWN, AXP209_POWEROFF); 191 192 /* infinite loop during shutdown */ 193 while (1) {} 194 195 /* not reached */ 196 return 0; 197 } 198