uboot/drivers/power/axp818.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * AXP818 driver based on AXP221 driver
   4 *
   5 *
   6 * (C) Copyright 2015 Vishnu Patekar <vishnuptekar0510@gmail.com>
   7 *
   8 * Based on axp221.c
   9 * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
  10 * (C) Copyright 2013 Oliver Schinagl <oliver@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
  19static 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
  29int 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
  46int 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
  68int 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
  90int 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
 112int 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. */
 134int axp_set_aldo1(unsigned int mvolt)
 135{
 136        return axp_set_aldo(1, mvolt);
 137}
 138
 139int axp_set_aldo2(unsigned int mvolt)
 140{
 141        return axp_set_aldo(2, mvolt);
 142}
 143
 144int axp_set_aldo3(unsigned int mvolt)
 145{
 146        return axp_set_aldo(3, mvolt);
 147}
 148
 149int 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
 172int 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
 193int 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
 227int 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
 237int 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
 258int 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