uboot/drivers/power/regulator/s5m8767.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2015 Google, Inc
   4 */
   5
   6#include <common.h>
   7#include <fdtdec.h>
   8#include <errno.h>
   9#include <dm.h>
  10#include <i2c.h>
  11#include <power/pmic.h>
  12#include <power/regulator.h>
  13#include <power/s5m8767.h>
  14
  15static const struct sec_voltage_desc buck_v1 = {
  16        .max = 2225000,
  17        .min =  650000,
  18        .step =   6250,
  19};
  20
  21static const struct sec_voltage_desc buck_v2 = {
  22        .max = 1600000,
  23        .min =  600000,
  24        .step =   6250,
  25};
  26
  27static const struct sec_voltage_desc buck_v3 = {
  28        .max = 3000000,
  29        .min =  750000,
  30        .step =  12500,
  31};
  32
  33static const struct sec_voltage_desc ldo_v1 = {
  34        .max = 3950000,
  35        .min =  800000,
  36        .step =  50000,
  37};
  38
  39static const struct sec_voltage_desc ldo_v2 = {
  40        .max = 2375000,
  41        .min =  800000,
  42        .step =  25000,
  43};
  44
  45static const struct s5m8767_para buck_param[] = {
  46        /*
  47         *            | voltage ----|  | enable -|   voltage
  48         * regnum       addr  bpos mask  addr  on     desc
  49         */
  50        {S5M8767_BUCK1, 0x33, 0x0, 0xff, 0x32, 0x3, &buck_v1},
  51        {S5M8767_BUCK2, 0x35, 0x0, 0xff, 0x34, 0x1, &buck_v2},
  52        {S5M8767_BUCK3, 0x3e, 0x0, 0xff, 0x3d, 0x1, &buck_v2},
  53        {S5M8767_BUCK4, 0x47, 0x0, 0xff, 0x46, 0x1, &buck_v2},
  54        {S5M8767_BUCK5, 0x50, 0x0, 0xff, 0x4f, 0x3, &buck_v1},
  55        {S5M8767_BUCK6, 0x55, 0x0, 0xff, 0x54, 0x3, &buck_v1},
  56        {S5M8767_BUCK7, 0x57, 0x0, 0xff, 0x56, 0x3, &buck_v3},
  57        {S5M8767_BUCK8, 0x59, 0x0, 0xff, 0x58, 0x3, &buck_v3},
  58        {S5M8767_BUCK9, 0x5b, 0x0, 0xff, 0x5a, 0x3, &buck_v3},
  59};
  60
  61static const struct s5m8767_para ldo_param[] = {
  62        {S5M8767_LDO1,  0x5c, 0x0, 0x3f, 0x5c, 0x3, &ldo_v2},
  63        {S5M8767_LDO2,  0x5d, 0x0, 0x3f, 0x5d, 0x1, &ldo_v2},
  64        {S5M8767_LDO3,  0x61, 0x0, 0x3f, 0x61, 0x3, &ldo_v1},
  65        {S5M8767_LDO4,  0x62, 0x0, 0x3f, 0x62, 0x3, &ldo_v1},
  66        {S5M8767_LDO5,  0x63, 0x0, 0x3f, 0x63, 0x3, &ldo_v1},
  67        {S5M8767_LDO6,  0x64, 0x0, 0x3f, 0x64, 0x1, &ldo_v2},
  68        {S5M8767_LDO7,  0x65, 0x0, 0x3f, 0x65, 0x1, &ldo_v2},
  69        {S5M8767_LDO8,  0x66, 0x0, 0x3f, 0x66, 0x1, &ldo_v2},
  70        {S5M8767_LDO9,  0x67, 0x0, 0x3f, 0x67, 0x3, &ldo_v1},
  71        {S5M8767_LDO10, 0x68, 0x0, 0x3f, 0x68, 0x1, &ldo_v1},
  72        {S5M8767_LDO11, 0x69, 0x0, 0x3f, 0x69, 0x1, &ldo_v1},
  73        {S5M8767_LDO12, 0x6a, 0x0, 0x3f, 0x6a, 0x1, &ldo_v1},
  74        {S5M8767_LDO13, 0x6b, 0x0, 0x3f, 0x6b, 0x3, &ldo_v1},
  75        {S5M8767_LDO14, 0x6c, 0x0, 0x3f, 0x6c, 0x1, &ldo_v1},
  76        {S5M8767_LDO15, 0x6d, 0x0, 0x3f, 0x6d, 0x1, &ldo_v2},
  77        {S5M8767_LDO16, 0x6e, 0x0, 0x3f, 0x6e, 0x1, &ldo_v1},
  78        {S5M8767_LDO17, 0x6f, 0x0, 0x3f, 0x6f, 0x3, &ldo_v1},
  79        {S5M8767_LDO18, 0x70, 0x0, 0x3f, 0x70, 0x3, &ldo_v1},
  80        {S5M8767_LDO19, 0x71, 0x0, 0x3f, 0x71, 0x3, &ldo_v1},
  81        {S5M8767_LDO20, 0x72, 0x0, 0x3f, 0x72, 0x3, &ldo_v1},
  82        {S5M8767_LDO21, 0x73, 0x0, 0x3f, 0x73, 0x3, &ldo_v1},
  83        {S5M8767_LDO22, 0x74, 0x0, 0x3f, 0x74, 0x3, &ldo_v1},
  84        {S5M8767_LDO23, 0x75, 0x0, 0x3f, 0x75, 0x3, &ldo_v1},
  85        {S5M8767_LDO24, 0x76, 0x0, 0x3f, 0x76, 0x3, &ldo_v1},
  86        {S5M8767_LDO25, 0x77, 0x0, 0x3f, 0x77, 0x3, &ldo_v1},
  87        {S5M8767_LDO26, 0x78, 0x0, 0x3f, 0x78, 0x3, &ldo_v1},
  88        {S5M8767_LDO27, 0x79, 0x0, 0x3f, 0x79, 0x3, &ldo_v1},
  89        {S5M8767_LDO28, 0x7a, 0x0, 0x3f, 0x7a, 0x3, &ldo_v1},
  90};
  91
  92enum {
  93        ENABLE_SHIFT    = 6,
  94        ENABLE_MASK     = 3,
  95};
  96
  97static int reg_get_value(struct udevice *dev, const struct s5m8767_para *param)
  98{
  99        const struct sec_voltage_desc *desc;
 100        int ret, uv, val;
 101
 102        ret = pmic_reg_read(dev->parent, param->vol_addr);
 103        if (ret < 0)
 104                return ret;
 105
 106        desc = param->vol;
 107        val = (ret >> param->vol_bitpos) & param->vol_bitmask;
 108        uv = desc->min + val * desc->step;
 109
 110        return uv;
 111}
 112
 113static int reg_set_value(struct udevice *dev, const struct s5m8767_para *param,
 114                         int uv)
 115{
 116        const struct sec_voltage_desc *desc;
 117        int ret, val;
 118
 119        desc = param->vol;
 120        if (uv < desc->min || uv > desc->max)
 121                return -EINVAL;
 122        val = (uv - desc->min) / desc->step;
 123        val = (val & param->vol_bitmask) << param->vol_bitpos;
 124        ret = pmic_clrsetbits(dev->parent, param->vol_addr,
 125                              param->vol_bitmask << param->vol_bitpos,
 126                              val);
 127
 128        return ret;
 129}
 130
 131static int s5m8767_ldo_probe(struct udevice *dev)
 132{
 133        struct dm_regulator_uclass_platdata *uc_pdata;
 134
 135        uc_pdata = dev_get_uclass_platdata(dev);
 136
 137        uc_pdata->type = REGULATOR_TYPE_LDO;
 138        uc_pdata->mode_count = 0;
 139
 140        return 0;
 141}
 142static int ldo_get_value(struct udevice *dev)
 143{
 144        int ldo = dev->driver_data;
 145
 146        return reg_get_value(dev, &ldo_param[ldo]);
 147}
 148
 149static int ldo_set_value(struct udevice *dev, int uv)
 150{
 151        int ldo = dev->driver_data;
 152
 153        return reg_set_value(dev, &ldo_param[ldo], uv);
 154}
 155
 156static int reg_get_enable(struct udevice *dev, const struct s5m8767_para *param)
 157{
 158        bool enable;
 159        int ret;
 160
 161        ret = pmic_reg_read(dev->parent, param->reg_enaddr);
 162        if (ret < 0)
 163                return ret;
 164
 165        enable = (ret >> ENABLE_SHIFT) & ENABLE_MASK;
 166
 167        return enable;
 168}
 169
 170static int reg_set_enable(struct udevice *dev, const struct s5m8767_para *param,
 171                          bool enable)
 172{
 173        int ret;
 174
 175        ret = pmic_reg_read(dev->parent, param->reg_enaddr);
 176        if (ret < 0)
 177                return ret;
 178
 179        ret = pmic_clrsetbits(dev->parent, param->reg_enaddr,
 180                              ENABLE_MASK << ENABLE_SHIFT,
 181                              enable ? param->reg_enbiton << ENABLE_SHIFT : 0);
 182
 183        return ret;
 184}
 185
 186static int ldo_get_enable(struct udevice *dev)
 187{
 188        int ldo = dev->driver_data;
 189
 190        return reg_get_enable(dev, &ldo_param[ldo]);
 191}
 192
 193static int ldo_set_enable(struct udevice *dev, bool enable)
 194{
 195        int ldo = dev->driver_data;
 196
 197        return reg_set_enable(dev, &ldo_param[ldo], enable);
 198}
 199
 200static int s5m8767_buck_probe(struct udevice *dev)
 201{
 202        struct dm_regulator_uclass_platdata *uc_pdata;
 203
 204        uc_pdata = dev_get_uclass_platdata(dev);
 205
 206        uc_pdata->type = REGULATOR_TYPE_BUCK;
 207        uc_pdata->mode_count = 0;
 208
 209        return 0;
 210}
 211
 212static int buck_get_value(struct udevice *dev)
 213{
 214        int buck = dev->driver_data;
 215
 216        return reg_get_value(dev, &buck_param[buck]);
 217}
 218
 219static int buck_set_value(struct udevice *dev, int uv)
 220{
 221        int buck = dev->driver_data;
 222
 223        return reg_set_value(dev, &buck_param[buck], uv);
 224}
 225
 226static int buck_get_enable(struct udevice *dev)
 227{
 228        int buck = dev->driver_data;
 229
 230        return reg_get_enable(dev, &buck_param[buck]);
 231}
 232
 233static int buck_set_enable(struct udevice *dev, bool enable)
 234{
 235        int buck = dev->driver_data;
 236
 237        return reg_set_enable(dev, &buck_param[buck], enable);
 238}
 239
 240static const struct dm_regulator_ops s5m8767_ldo_ops = {
 241        .get_value  = ldo_get_value,
 242        .set_value  = ldo_set_value,
 243        .get_enable = ldo_get_enable,
 244        .set_enable = ldo_set_enable,
 245};
 246
 247U_BOOT_DRIVER(s5m8767_ldo) = {
 248        .name = S5M8767_LDO_DRIVER,
 249        .id = UCLASS_REGULATOR,
 250        .ops = &s5m8767_ldo_ops,
 251        .probe = s5m8767_ldo_probe,
 252};
 253
 254static const struct dm_regulator_ops s5m8767_buck_ops = {
 255        .get_value  = buck_get_value,
 256        .set_value  = buck_set_value,
 257        .get_enable = buck_get_enable,
 258        .set_enable = buck_set_enable,
 259};
 260
 261U_BOOT_DRIVER(s5m8767_buck) = {
 262        .name = S5M8767_BUCK_DRIVER,
 263        .id = UCLASS_REGULATOR,
 264        .ops = &s5m8767_buck_ops,
 265        .probe = s5m8767_buck_probe,
 266};
 267