uboot/drivers/power/axp221.c
<<
>>
Prefs
   1/*
   2 * AXP221 and AXP223 driver
   3 *
   4 * IMPORTANT when making changes to this file check that the registers
   5 * used are the same for the axp221 and axp223.
   6 *
   7 * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
   8 * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
   9 *
  10 * SPDX-License-Identifier:     GPL-2.0+
  11 */
  12
  13#include <common.h>
  14#include <command.h>
  15#include <errno.h>
  16#include <asm/arch/pmic_bus.h>
  17#include <axp_pmic.h>
  18
  19static u8 axp221_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 = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100);
  33
  34        if (mvolt == 0)
  35                return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
  36                                        AXP221_OUTPUT_CTRL1_DCDC1_EN);
  37
  38        ret = pmic_bus_write(AXP221_DCDC1_CTRL, cfg);
  39        if (ret)
  40                return ret;
  41
  42        ret = pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
  43                               AXP221_OUTPUT_CTRL2_DCDC1SW_EN);
  44        if (ret)
  45                return ret;
  46
  47        return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
  48                                AXP221_OUTPUT_CTRL1_DCDC1_EN);
  49}
  50
  51int axp_set_dcdc2(unsigned int mvolt)
  52{
  53        int ret;
  54        u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
  55
  56        if (mvolt == 0)
  57                return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
  58                                        AXP221_OUTPUT_CTRL1_DCDC2_EN);
  59
  60        ret = pmic_bus_write(AXP221_DCDC2_CTRL, cfg);
  61        if (ret)
  62                return ret;
  63
  64        return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
  65                                AXP221_OUTPUT_CTRL1_DCDC2_EN);
  66}
  67
  68int axp_set_dcdc3(unsigned int mvolt)
  69{
  70        int ret;
  71        u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20);
  72
  73        if (mvolt == 0)
  74                return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
  75                                        AXP221_OUTPUT_CTRL1_DCDC3_EN);
  76
  77        ret = pmic_bus_write(AXP221_DCDC3_CTRL, cfg);
  78        if (ret)
  79                return ret;
  80
  81        return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
  82                                AXP221_OUTPUT_CTRL1_DCDC3_EN);
  83}
  84
  85int axp_set_dcdc4(unsigned int mvolt)
  86{
  87        int ret;
  88        u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
  89
  90        if (mvolt == 0)
  91                return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
  92                                        AXP221_OUTPUT_CTRL1_DCDC4_EN);
  93
  94        ret = pmic_bus_write(AXP221_DCDC4_CTRL, cfg);
  95        if (ret)
  96                return ret;
  97
  98        return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
  99                                AXP221_OUTPUT_CTRL1_DCDC4_EN);
 100}
 101
 102int axp_set_dcdc5(unsigned int mvolt)
 103{
 104        int ret;
 105        u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50);
 106
 107        if (mvolt == 0)
 108                return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
 109                                        AXP221_OUTPUT_CTRL1_DCDC5_EN);
 110
 111        ret = pmic_bus_write(AXP221_DCDC5_CTRL, cfg);
 112        if (ret)
 113                return ret;
 114
 115        return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
 116                                AXP221_OUTPUT_CTRL1_DCDC5_EN);
 117}
 118
 119int axp_set_aldo1(unsigned int mvolt)
 120{
 121        int ret;
 122        u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 123
 124        if (mvolt == 0)
 125                return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
 126                                        AXP221_OUTPUT_CTRL1_ALDO1_EN);
 127
 128        ret = pmic_bus_write(AXP221_ALDO1_CTRL, cfg);
 129        if (ret)
 130                return ret;
 131
 132        return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
 133                                AXP221_OUTPUT_CTRL1_ALDO1_EN);
 134}
 135
 136int axp_set_aldo2(unsigned int mvolt)
 137{
 138        int ret;
 139        u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 140
 141        if (mvolt == 0)
 142                return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
 143                                        AXP221_OUTPUT_CTRL1_ALDO2_EN);
 144
 145        ret = pmic_bus_write(AXP221_ALDO2_CTRL, cfg);
 146        if (ret)
 147                return ret;
 148
 149        return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
 150                                AXP221_OUTPUT_CTRL1_ALDO2_EN);
 151}
 152
 153int axp_set_aldo3(unsigned int mvolt)
 154{
 155        int ret;
 156        u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 157
 158        if (mvolt == 0)
 159                return pmic_bus_clrbits(AXP221_OUTPUT_CTRL3,
 160                                        AXP221_OUTPUT_CTRL3_ALDO3_EN);
 161
 162        ret = pmic_bus_write(AXP221_ALDO3_CTRL, cfg);
 163        if (ret)
 164                return ret;
 165
 166        return pmic_bus_setbits(AXP221_OUTPUT_CTRL3,
 167                                AXP221_OUTPUT_CTRL3_ALDO3_EN);
 168}
 169
 170int axp_set_dldo(int dldo_num, unsigned int mvolt)
 171{
 172        u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 173        int ret;
 174
 175        if (dldo_num < 1 || dldo_num > 4)
 176                return -EINVAL;
 177
 178        if (mvolt == 0)
 179                return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2,
 180                                AXP221_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
 181
 182        ret = pmic_bus_write(AXP221_DLDO1_CTRL + (dldo_num - 1), cfg);
 183        if (ret)
 184                return ret;
 185
 186        return pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
 187                                AXP221_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
 188}
 189
 190int axp_set_eldo(int eldo_num, unsigned int mvolt)
 191{
 192        int ret;
 193        u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 194        u8 addr, bits;
 195
 196        switch (eldo_num) {
 197        case 3:
 198                addr = AXP221_ELDO3_CTRL;
 199                bits = AXP221_OUTPUT_CTRL2_ELDO3_EN;
 200                break;
 201        case 2:
 202                addr = AXP221_ELDO2_CTRL;
 203                bits = AXP221_OUTPUT_CTRL2_ELDO2_EN;
 204                break;
 205        case 1:
 206                addr = AXP221_ELDO1_CTRL;
 207                bits = AXP221_OUTPUT_CTRL2_ELDO1_EN;
 208                break;
 209        default:
 210                return -EINVAL;
 211        }
 212
 213        if (mvolt == 0)
 214                return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2, bits);
 215
 216        ret = pmic_bus_write(addr, cfg);
 217        if (ret)
 218                return ret;
 219
 220        return pmic_bus_setbits(AXP221_OUTPUT_CTRL2, bits);
 221}
 222
 223int axp_init(void)
 224{
 225        u8 axp_chip_id;
 226        int ret;
 227
 228        ret = pmic_bus_init();
 229        if (ret)
 230                return ret;
 231
 232        ret = pmic_bus_read(AXP221_CHIP_ID, &axp_chip_id);
 233        if (ret)
 234                return ret;
 235
 236        if (!(axp_chip_id == 0x6 || axp_chip_id == 0x7 || axp_chip_id == 0x17))
 237                return -ENODEV;
 238
 239        return 0;
 240}
 241
 242int axp_get_sid(unsigned int *sid)
 243{
 244        u8 *dest = (u8 *)sid;
 245        int i, ret;
 246
 247        ret = pmic_bus_init();
 248        if (ret)
 249                return ret;
 250
 251        ret = pmic_bus_write(AXP221_PAGE, 1);
 252        if (ret)
 253                return ret;
 254
 255        for (i = 0; i < 16; i++) {
 256                ret = pmic_bus_read(AXP221_SID + i, &dest[i]);
 257                if (ret)
 258                        return ret;
 259        }
 260
 261        pmic_bus_write(AXP221_PAGE, 0);
 262
 263        for (i = 0; i < 4; i++)
 264                sid[i] = be32_to_cpu(sid[i]);
 265
 266        return 0;
 267}
 268
 269int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 270{
 271        pmic_bus_write(AXP221_SHUTDOWN, AXP221_SHUTDOWN_POWEROFF);
 272
 273        /* infinite loop during shutdown */
 274        while (1) {}
 275
 276        /* not reached */
 277        return 0;
 278}
 279