Home | History | Annotate | Download | only in power
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * AXP818 driver based on AXP221 driver
      4  *
      5  *
      6  * (C) Copyright 2015 Vishnu Patekar <vishnuptekar0510 (at) gmail.com>
      7  *
      8  * Based on axp221.c
      9  * (C) Copyright 2014 Hans de Goede <hdegoede (at) redhat.com>
     10  * (C) Copyright 2013 Oliver Schinagl <oliver (at) schinagl.nl>
     11  */
     12 
     13 #include <common.h>
     14 #include <errno.h>
     15 #include <asm/arch/gpio.h>
     16 #include <asm/arch/pmic_bus.h>
     17 #include <axp_pmic.h>
     18 
     19 static u8 axp818_mvolt_to_cfg(int mvolt, int min, int max, int div)
     20 {
     21 	if (mvolt < min)
     22 		mvolt = min;
     23 	else if (mvolt > max)
     24 		mvolt = max;
     25 
     26 	return  (mvolt - min) / div;
     27 }
     28 
     29 int axp_set_dcdc1(unsigned int mvolt)
     30 {
     31 	int ret;
     32 	u8 cfg = axp818_mvolt_to_cfg(mvolt, 1600, 3400, 100);
     33 
     34 	if (mvolt == 0)
     35 		return pmic_bus_clrbits(AXP818_OUTPUT_CTRL1,
     36 					AXP818_OUTPUT_CTRL1_DCDC1_EN);
     37 
     38 	ret = pmic_bus_write(AXP818_DCDC1_CTRL, cfg);
     39 	if (ret)
     40 		return ret;
     41 
     42 	return pmic_bus_setbits(AXP818_OUTPUT_CTRL1,
     43 				AXP818_OUTPUT_CTRL1_DCDC1_EN);
     44 }
     45 
     46 int axp_set_dcdc2(unsigned int mvolt)
     47 {
     48 	int ret;
     49 	u8 cfg;
     50 
     51 	if (mvolt >= 1220)
     52 		cfg = 70 + axp818_mvolt_to_cfg(mvolt, 1220, 1300, 20);
     53 	else
     54 		cfg = axp818_mvolt_to_cfg(mvolt, 500, 1200, 10);
     55 
     56 	if (mvolt == 0)
     57 		return pmic_bus_clrbits(AXP818_OUTPUT_CTRL1,
     58 					AXP818_OUTPUT_CTRL1_DCDC2_EN);
     59 
     60 	ret = pmic_bus_write(AXP818_DCDC2_CTRL, cfg);
     61 	if (ret)
     62 		return ret;
     63 
     64 	return pmic_bus_setbits(AXP818_OUTPUT_CTRL1,
     65 				AXP818_OUTPUT_CTRL1_DCDC2_EN);
     66 }
     67 
     68 int axp_set_dcdc3(unsigned int mvolt)
     69 {
     70 	int ret;
     71 	u8 cfg;
     72 
     73 	if (mvolt >= 1220)
     74 		cfg = 70 + axp818_mvolt_to_cfg(mvolt, 1220, 1300, 20);
     75 	else
     76 		cfg = axp818_mvolt_to_cfg(mvolt, 500, 1200, 10);
     77 
     78 	if (mvolt == 0)
     79 		return pmic_bus_clrbits(AXP818_OUTPUT_CTRL1,
     80 					AXP818_OUTPUT_CTRL1_DCDC3_EN);
     81 
     82 	ret = pmic_bus_write(AXP818_DCDC3_CTRL, cfg);
     83 	if (ret)
     84 		return ret;
     85 
     86 	return pmic_bus_setbits(AXP818_OUTPUT_CTRL1,
     87 				AXP818_OUTPUT_CTRL1_DCDC3_EN);
     88 }
     89 
     90 int axp_set_dcdc5(unsigned int mvolt)
     91 {
     92 	int ret;
     93 	u8 cfg;
     94 
     95 	if (mvolt >= 1140)
     96 		cfg = 32 + axp818_mvolt_to_cfg(mvolt, 1140, 1840, 20);
     97 	else
     98 		cfg = axp818_mvolt_to_cfg(mvolt, 800, 1120, 10);
     99 
    100 	if (mvolt == 0)
    101 		return pmic_bus_clrbits(AXP818_OUTPUT_CTRL1,
    102 					AXP818_OUTPUT_CTRL1_DCDC5_EN);
    103 
    104 	ret = pmic_bus_write(AXP818_DCDC5_CTRL, cfg);
    105 	if (ret)
    106 		return ret;
    107 
    108 	return pmic_bus_setbits(AXP818_OUTPUT_CTRL1,
    109 				AXP818_OUTPUT_CTRL1_DCDC5_EN);
    110 }
    111 
    112 int axp_set_aldo(int aldo_num, unsigned int mvolt)
    113 {
    114 	int ret;
    115 	u8 cfg;
    116 
    117 	if (aldo_num < 1 || aldo_num > 3)
    118 		return -EINVAL;
    119 
    120 	if (mvolt == 0)
    121 		return pmic_bus_clrbits(AXP818_OUTPUT_CTRL3,
    122 				AXP818_OUTPUT_CTRL3_ALDO1_EN << (aldo_num - 1));
    123 
    124 	cfg = axp818_mvolt_to_cfg(mvolt, 700, 3300, 100);
    125 	ret = pmic_bus_write(AXP818_ALDO1_CTRL + (aldo_num - 1), cfg);
    126 	if (ret)
    127 		return ret;
    128 
    129 	return pmic_bus_setbits(AXP818_OUTPUT_CTRL3,
    130 				AXP818_OUTPUT_CTRL3_ALDO1_EN << (aldo_num - 1));
    131 }
    132 
    133 /* TODO: re-work other AXP drivers to consolidate ALDO functions. */
    134 int axp_set_aldo1(unsigned int mvolt)
    135 {
    136 	return axp_set_aldo(1, mvolt);
    137 }
    138 
    139 int axp_set_aldo2(unsigned int mvolt)
    140 {
    141 	return axp_set_aldo(2, mvolt);
    142 }
    143 
    144 int axp_set_aldo3(unsigned int mvolt)
    145 {
    146 	return axp_set_aldo(3, mvolt);
    147 }
    148 
    149 int axp_set_dldo(int dldo_num, unsigned int mvolt)
    150 {
    151 	int ret;
    152 	u8 cfg;
    153 
    154 	if (dldo_num < 1 || dldo_num > 4)
    155 		return -EINVAL;
    156 
    157 	if (mvolt == 0)
    158 		return pmic_bus_clrbits(AXP818_OUTPUT_CTRL2,
    159 				AXP818_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
    160 
    161 	cfg = axp818_mvolt_to_cfg(mvolt, 700, 3300, 100);
    162 	if (dldo_num == 2 && mvolt > 3300)
    163 		cfg += 1 + axp818_mvolt_to_cfg(mvolt, 3400, 4200, 200);
    164 	ret = pmic_bus_write(AXP818_ELDO1_CTRL + (dldo_num - 1), cfg);
    165 	if (ret)
    166 		return ret;
    167 
    168 	return pmic_bus_setbits(AXP818_OUTPUT_CTRL2,
    169 				AXP818_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
    170 }
    171 
    172 int axp_set_eldo(int eldo_num, unsigned int mvolt)
    173 {
    174 	int ret;
    175 	u8 cfg;
    176 
    177 	if (eldo_num < 1 || eldo_num > 3)
    178 		return -EINVAL;
    179 
    180 	if (mvolt == 0)
    181 		return pmic_bus_clrbits(AXP818_OUTPUT_CTRL2,
    182 				AXP818_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
    183 
    184 	cfg = axp818_mvolt_to_cfg(mvolt, 700, 1900, 50);
    185 	ret = pmic_bus_write(AXP818_ELDO1_CTRL + (eldo_num - 1), cfg);
    186 	if (ret)
    187 		return ret;
    188 
    189 	return pmic_bus_setbits(AXP818_OUTPUT_CTRL2,
    190 				AXP818_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
    191 }
    192 
    193 int axp_set_fldo(int fldo_num, unsigned int mvolt)
    194 {
    195 	int ret;
    196 	u8 cfg;
    197 
    198 	if (fldo_num < 1 || fldo_num > 3)
    199 		return -EINVAL;
    200 
    201 	if (mvolt == 0)
    202 		return pmic_bus_clrbits(AXP818_OUTPUT_CTRL3,
    203 				AXP818_OUTPUT_CTRL3_FLDO1_EN << (fldo_num - 1));
    204 
    205 	if (fldo_num < 3) {
    206 		cfg = axp818_mvolt_to_cfg(mvolt, 700, 1450, 50);
    207 		ret = pmic_bus_write(AXP818_FLDO1_CTRL + (fldo_num - 1), cfg);
    208 	} else {
    209 		/*
    210 		 * Special case for FLDO3, which is DCDC5 / 2 or FLDOIN / 2
    211 		 * Since FLDOIN is unknown, test against DCDC5.
    212 		 */
    213 		if (mvolt * 2 == CONFIG_AXP_DCDC5_VOLT)
    214 			ret = pmic_bus_clrbits(AXP818_FLDO2_3_CTRL,
    215 					       AXP818_FLDO2_3_CTRL_FLDO3_VOL);
    216 		else
    217 			ret = pmic_bus_setbits(AXP818_FLDO2_3_CTRL,
    218 					       AXP818_FLDO2_3_CTRL_FLDO3_VOL);
    219 	}
    220 	if (ret)
    221 		return ret;
    222 
    223 	return pmic_bus_setbits(AXP818_OUTPUT_CTRL3,
    224 				AXP818_OUTPUT_CTRL3_FLDO1_EN << (fldo_num - 1));
    225 }
    226 
    227 int axp_set_sw(bool on)
    228 {
    229 	if (on)
    230 		return pmic_bus_setbits(AXP818_OUTPUT_CTRL2,
    231 					AXP818_OUTPUT_CTRL2_SW_EN);
    232 
    233 	return pmic_bus_clrbits(AXP818_OUTPUT_CTRL2,
    234 				AXP818_OUTPUT_CTRL2_SW_EN);
    235 }
    236 
    237 int axp_init(void)
    238 {
    239 	u8 axp_chip_id;
    240 	int ret;
    241 
    242 	ret = pmic_bus_init();
    243 	if (ret)
    244 		return ret;
    245 
    246 	ret = pmic_bus_read(AXP818_CHIP_ID, &axp_chip_id);
    247 	if (ret)
    248 		return ret;
    249 
    250 	if (!(axp_chip_id == 0x51))
    251 		return -ENODEV;
    252 	else
    253 		return ret;
    254 
    255 	return 0;
    256 }
    257 
    258 int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
    259 {
    260 	pmic_bus_write(AXP818_SHUTDOWN, AXP818_SHUTDOWN_POWEROFF);
    261 
    262 	/* infinite loop during shutdown */
    263 	while (1) {}
    264 
    265 	/* not reached */
    266 	return 0;
    267 }
    268