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