1 /* 2 * AXP809 driver based on AXP221 driver 3 * 4 * 5 * (C) Copyright 2016 Chen-Yu Tsai <wens@csie.org> 6 * 7 * Based on axp221.c 8 * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com> 9 * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl> 10 * 11 * SPDX-License-Identifier: GPL-2.0+ 12 */ 13 14 #include <common.h> 15 #include <errno.h> 16 #include <asm/arch/gpio.h> 17 #include <asm/arch/pmic_bus.h> 18 #include <axp_pmic.h> 19 20 static u8 axp809_mvolt_to_cfg(int mvolt, int min, int max, int div) 21 { 22 if (mvolt < min) 23 mvolt = min; 24 else if (mvolt > max) 25 mvolt = max; 26 27 return (mvolt - min) / div; 28 } 29 30 int axp_set_dcdc1(unsigned int mvolt) 31 { 32 int ret; 33 u8 cfg = axp809_mvolt_to_cfg(mvolt, 1600, 3400, 100); 34 35 if (mvolt == 0) 36 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1, 37 AXP809_OUTPUT_CTRL1_DCDC1_EN); 38 39 ret = pmic_bus_write(AXP809_DCDC1_CTRL, cfg); 40 if (ret) 41 return ret; 42 43 ret = pmic_bus_setbits(AXP809_OUTPUT_CTRL2, 44 AXP809_OUTPUT_CTRL2_DC1SW_EN); 45 if (ret) 46 return ret; 47 48 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1, 49 AXP809_OUTPUT_CTRL1_DCDC1_EN); 50 } 51 52 int axp_set_dcdc2(unsigned int mvolt) 53 { 54 int ret; 55 u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1540, 20); 56 57 if (mvolt == 0) 58 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1, 59 AXP809_OUTPUT_CTRL1_DCDC2_EN); 60 61 ret = pmic_bus_write(AXP809_DCDC2_CTRL, cfg); 62 if (ret) 63 return ret; 64 65 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1, 66 AXP809_OUTPUT_CTRL1_DCDC2_EN); 67 } 68 69 int axp_set_dcdc3(unsigned int mvolt) 70 { 71 int ret; 72 u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1860, 20); 73 74 if (mvolt == 0) 75 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1, 76 AXP809_OUTPUT_CTRL1_DCDC3_EN); 77 78 ret = pmic_bus_write(AXP809_DCDC3_CTRL, cfg); 79 if (ret) 80 return ret; 81 82 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1, 83 AXP809_OUTPUT_CTRL1_DCDC3_EN); 84 } 85 86 int axp_set_dcdc4(unsigned int mvolt) 87 { 88 int ret; 89 u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1540, 20); 90 91 if (mvolt >= 1540) 92 cfg = 0x30 + axp809_mvolt_to_cfg(mvolt, 1800, 2600, 100); 93 94 if (mvolt == 0) 95 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1, 96 AXP809_OUTPUT_CTRL1_DCDC4_EN); 97 98 ret = pmic_bus_write(AXP809_DCDC5_CTRL, cfg); 99 if (ret) 100 return ret; 101 102 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1, 103 AXP809_OUTPUT_CTRL1_DCDC4_EN); 104 } 105 106 int axp_set_dcdc5(unsigned int mvolt) 107 { 108 int ret; 109 u8 cfg = axp809_mvolt_to_cfg(mvolt, 1000, 2550, 50); 110 111 if (mvolt == 0) 112 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1, 113 AXP809_OUTPUT_CTRL1_DCDC5_EN); 114 115 ret = pmic_bus_write(AXP809_DCDC5_CTRL, cfg); 116 if (ret) 117 return ret; 118 119 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1, 120 AXP809_OUTPUT_CTRL1_DCDC5_EN); 121 } 122 123 int axp_set_aldo(int aldo_num, unsigned int mvolt) 124 { 125 int ret; 126 u8 cfg; 127 128 if (aldo_num < 1 || aldo_num > 3) 129 return -EINVAL; 130 131 if (mvolt == 0 && aldo_num == 3) 132 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2, 133 AXP809_OUTPUT_CTRL2_ALDO3_EN); 134 if (mvolt == 0) 135 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1, 136 AXP809_OUTPUT_CTRL1_ALDO1_EN << (aldo_num - 1)); 137 138 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100); 139 ret = pmic_bus_write(AXP809_ALDO1_CTRL + (aldo_num - 1), cfg); 140 if (ret) 141 return ret; 142 143 if (aldo_num == 3) 144 return pmic_bus_setbits(AXP809_OUTPUT_CTRL2, 145 AXP809_OUTPUT_CTRL2_ALDO3_EN); 146 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1, 147 AXP809_OUTPUT_CTRL1_ALDO1_EN << (aldo_num - 1)); 148 } 149 150 /* TODO: re-work other AXP drivers to consolidate ALDO functions. */ 151 int axp_set_aldo1(unsigned int mvolt) 152 { 153 return axp_set_aldo(1, mvolt); 154 } 155 156 int axp_set_aldo2(unsigned int mvolt) 157 { 158 return axp_set_aldo(2, mvolt); 159 } 160 161 int axp_set_aldo3(unsigned int mvolt) 162 { 163 return axp_set_aldo(3, mvolt); 164 } 165 166 int axp_set_dldo(int dldo_num, unsigned int mvolt) 167 { 168 u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100); 169 int ret; 170 171 if (dldo_num < 1 || dldo_num > 2) 172 return -EINVAL; 173 174 if (mvolt == 0) 175 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2, 176 AXP809_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1)); 177 178 if (dldo_num == 1 && mvolt > 3300) 179 cfg += 1 + axp809_mvolt_to_cfg(mvolt, 3400, 4200, 200); 180 ret = pmic_bus_write(AXP809_DLDO1_CTRL + (dldo_num - 1), cfg); 181 if (ret) 182 return ret; 183 184 return pmic_bus_setbits(AXP809_OUTPUT_CTRL2, 185 AXP809_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1)); 186 } 187 188 int axp_set_eldo(int eldo_num, unsigned int mvolt) 189 { 190 int ret; 191 u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100); 192 193 if (eldo_num < 1 || eldo_num > 3) 194 return -EINVAL; 195 196 if (mvolt == 0) 197 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2, 198 AXP809_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1)); 199 200 ret = pmic_bus_write(AXP809_ELDO1_CTRL + (eldo_num - 1), cfg); 201 if (ret) 202 return ret; 203 204 return pmic_bus_setbits(AXP809_OUTPUT_CTRL2, 205 AXP809_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1)); 206 } 207 208 int axp_set_sw(bool on) 209 { 210 if (on) 211 return pmic_bus_setbits(AXP809_OUTPUT_CTRL2, 212 AXP809_OUTPUT_CTRL2_SWOUT_EN); 213 214 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2, 215 AXP809_OUTPUT_CTRL2_SWOUT_EN); 216 } 217 218 int axp_init(void) 219 { 220 int ret; 221 222 ret = pmic_bus_init(); 223 if (ret) 224 return ret; 225 226 return 0; 227 } 228 229 int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 230 { 231 pmic_bus_write(AXP809_SHUTDOWN, AXP809_SHUTDOWN_POWEROFF); 232 233 /* infinite loop during shutdown */ 234 while (1) {} 235 236 /* not reached */ 237 return 0; 238 } 239