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