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