linux/drivers/regulator/helpers.c
<<
>>
Prefs
   1/*
   2 * helpers.c  --  Voltage/Current Regulator framework helper functions.
   3 *
   4 * Copyright 2007, 2008 Wolfson Microelectronics PLC.
   5 * Copyright 2008 SlimLogic Ltd.
   6 *
   7 *  This program is free software; you can redistribute  it and/or modify it
   8 *  under  the terms of  the GNU General  Public License as published by the
   9 *  Free Software Foundation;  either version 2 of the  License, or (at your
  10 *  option) any later version.
  11 *
  12 */
  13
  14#include <linux/kernel.h>
  15#include <linux/err.h>
  16#include <linux/delay.h>
  17#include <linux/regmap.h>
  18#include <linux/regulator/consumer.h>
  19#include <linux/regulator/driver.h>
  20#include <linux/module.h>
  21
  22/**
  23 * regulator_is_enabled_regmap - standard is_enabled() for regmap users
  24 *
  25 * @rdev: regulator to operate on
  26 *
  27 * Regulators that use regmap for their register I/O can set the
  28 * enable_reg and enable_mask fields in their descriptor and then use
  29 * this as their is_enabled operation, saving some code.
  30 */
  31int regulator_is_enabled_regmap(struct regulator_dev *rdev)
  32{
  33        unsigned int val;
  34        int ret;
  35
  36        ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
  37        if (ret != 0)
  38                return ret;
  39
  40        if (rdev->desc->enable_is_inverted)
  41                return (val & rdev->desc->enable_mask) == 0;
  42        else
  43                return (val & rdev->desc->enable_mask) != 0;
  44}
  45EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap);
  46
  47/**
  48 * regulator_enable_regmap - standard enable() for regmap users
  49 *
  50 * @rdev: regulator to operate on
  51 *
  52 * Regulators that use regmap for their register I/O can set the
  53 * enable_reg and enable_mask fields in their descriptor and then use
  54 * this as their enable() operation, saving some code.
  55 */
  56int regulator_enable_regmap(struct regulator_dev *rdev)
  57{
  58        unsigned int val;
  59
  60        if (rdev->desc->enable_is_inverted)
  61                val = 0;
  62        else
  63                val = rdev->desc->enable_mask;
  64
  65        return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
  66                                  rdev->desc->enable_mask, val);
  67}
  68EXPORT_SYMBOL_GPL(regulator_enable_regmap);
  69
  70/**
  71 * regulator_disable_regmap - standard disable() for regmap users
  72 *
  73 * @rdev: regulator to operate on
  74 *
  75 * Regulators that use regmap for their register I/O can set the
  76 * enable_reg and enable_mask fields in their descriptor and then use
  77 * this as their disable() operation, saving some code.
  78 */
  79int regulator_disable_regmap(struct regulator_dev *rdev)
  80{
  81        unsigned int val;
  82
  83        if (rdev->desc->enable_is_inverted)
  84                val = rdev->desc->enable_mask;
  85        else
  86                val = 0;
  87
  88        return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
  89                                  rdev->desc->enable_mask, val);
  90}
  91EXPORT_SYMBOL_GPL(regulator_disable_regmap);
  92
  93/**
  94 * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users
  95 *
  96 * @rdev: regulator to operate on
  97 *
  98 * Regulators that use regmap for their register I/O can set the
  99 * vsel_reg and vsel_mask fields in their descriptor and then use this
 100 * as their get_voltage_vsel operation, saving some code.
 101 */
 102int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev)
 103{
 104        unsigned int val;
 105        int ret;
 106
 107        ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
 108        if (ret != 0)
 109                return ret;
 110
 111        val &= rdev->desc->vsel_mask;
 112        val >>= ffs(rdev->desc->vsel_mask) - 1;
 113
 114        return val;
 115}
 116EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap);
 117
 118/**
 119 * regulator_set_voltage_sel_regmap - standard set_voltage_sel for regmap users
 120 *
 121 * @rdev: regulator to operate on
 122 * @sel: Selector to set
 123 *
 124 * Regulators that use regmap for their register I/O can set the
 125 * vsel_reg and vsel_mask fields in their descriptor and then use this
 126 * as their set_voltage_vsel operation, saving some code.
 127 */
 128int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel)
 129{
 130        int ret;
 131
 132        sel <<= ffs(rdev->desc->vsel_mask) - 1;
 133
 134        ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
 135                                  rdev->desc->vsel_mask, sel);
 136        if (ret)
 137                return ret;
 138
 139        if (rdev->desc->apply_bit)
 140                ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg,
 141                                         rdev->desc->apply_bit,
 142                                         rdev->desc->apply_bit);
 143        return ret;
 144}
 145EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap);
 146
 147/**
 148 * regulator_map_voltage_iterate - map_voltage() based on list_voltage()
 149 *
 150 * @rdev: Regulator to operate on
 151 * @min_uV: Lower bound for voltage
 152 * @max_uV: Upper bound for voltage
 153 *
 154 * Drivers implementing set_voltage_sel() and list_voltage() can use
 155 * this as their map_voltage() operation.  It will find a suitable
 156 * voltage by calling list_voltage() until it gets something in bounds
 157 * for the requested voltages.
 158 */
 159int regulator_map_voltage_iterate(struct regulator_dev *rdev,
 160                                  int min_uV, int max_uV)
 161{
 162        int best_val = INT_MAX;
 163        int selector = 0;
 164        int i, ret;
 165
 166        /* Find the smallest voltage that falls within the specified
 167         * range.
 168         */
 169        for (i = 0; i < rdev->desc->n_voltages; i++) {
 170                ret = rdev->desc->ops->list_voltage(rdev, i);
 171                if (ret < 0)
 172                        continue;
 173
 174                if (ret < best_val && ret >= min_uV && ret <= max_uV) {
 175                        best_val = ret;
 176                        selector = i;
 177                }
 178        }
 179
 180        if (best_val != INT_MAX)
 181                return selector;
 182        else
 183                return -EINVAL;
 184}
 185EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate);
 186
 187/**
 188 * regulator_map_voltage_ascend - map_voltage() for ascendant voltage list
 189 *
 190 * @rdev: Regulator to operate on
 191 * @min_uV: Lower bound for voltage
 192 * @max_uV: Upper bound for voltage
 193 *
 194 * Drivers that have ascendant voltage list can use this as their
 195 * map_voltage() operation.
 196 */
 197int regulator_map_voltage_ascend(struct regulator_dev *rdev,
 198                                 int min_uV, int max_uV)
 199{
 200        int i, ret;
 201
 202        for (i = 0; i < rdev->desc->n_voltages; i++) {
 203                ret = rdev->desc->ops->list_voltage(rdev, i);
 204                if (ret < 0)
 205                        continue;
 206
 207                if (ret > max_uV)
 208                        break;
 209
 210                if (ret >= min_uV && ret <= max_uV)
 211                        return i;
 212        }
 213
 214        return -EINVAL;
 215}
 216EXPORT_SYMBOL_GPL(regulator_map_voltage_ascend);
 217
 218/**
 219 * regulator_map_voltage_linear - map_voltage() for simple linear mappings
 220 *
 221 * @rdev: Regulator to operate on
 222 * @min_uV: Lower bound for voltage
 223 * @max_uV: Upper bound for voltage
 224 *
 225 * Drivers providing min_uV and uV_step in their regulator_desc can
 226 * use this as their map_voltage() operation.
 227 */
 228int regulator_map_voltage_linear(struct regulator_dev *rdev,
 229                                 int min_uV, int max_uV)
 230{
 231        int ret, voltage;
 232
 233        /* Allow uV_step to be 0 for fixed voltage */
 234        if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) {
 235                if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV)
 236                        return 0;
 237                else
 238                        return -EINVAL;
 239        }
 240
 241        if (!rdev->desc->uV_step) {
 242                BUG_ON(!rdev->desc->uV_step);
 243                return -EINVAL;
 244        }
 245
 246        if (min_uV < rdev->desc->min_uV)
 247                min_uV = rdev->desc->min_uV;
 248
 249        ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
 250        if (ret < 0)
 251                return ret;
 252
 253        ret += rdev->desc->linear_min_sel;
 254
 255        /* Map back into a voltage to verify we're still in bounds */
 256        voltage = rdev->desc->ops->list_voltage(rdev, ret);
 257        if (voltage < min_uV || voltage > max_uV)
 258                return -EINVAL;
 259
 260        return ret;
 261}
 262EXPORT_SYMBOL_GPL(regulator_map_voltage_linear);
 263
 264/**
 265 * regulator_map_voltage_linear - map_voltage() for multiple linear ranges
 266 *
 267 * @rdev: Regulator to operate on
 268 * @min_uV: Lower bound for voltage
 269 * @max_uV: Upper bound for voltage
 270 *
 271 * Drivers providing linear_ranges in their descriptor can use this as
 272 * their map_voltage() callback.
 273 */
 274int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
 275                                       int min_uV, int max_uV)
 276{
 277        const struct regulator_linear_range *range;
 278        int ret = -EINVAL;
 279        int voltage, i;
 280
 281        if (!rdev->desc->n_linear_ranges) {
 282                BUG_ON(!rdev->desc->n_linear_ranges);
 283                return -EINVAL;
 284        }
 285
 286        for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
 287                range = &rdev->desc->linear_ranges[i];
 288
 289                if (!(min_uV <= range->max_uV && max_uV >= range->min_uV))
 290                        continue;
 291
 292                if (min_uV <= range->min_uV)
 293                        min_uV = range->min_uV;
 294
 295                /* range->uV_step == 0 means fixed voltage range */
 296                if (range->uV_step == 0) {
 297                        ret = 0;
 298                } else {
 299                        ret = DIV_ROUND_UP(min_uV - range->min_uV,
 300                                           range->uV_step);
 301                        if (ret < 0)
 302                                return ret;
 303                }
 304
 305                ret += range->min_sel;
 306
 307                break;
 308        }
 309
 310        if (i == rdev->desc->n_linear_ranges)
 311                return -EINVAL;
 312
 313        /* Map back into a voltage to verify we're still in bounds */
 314        voltage = rdev->desc->ops->list_voltage(rdev, ret);
 315        if (voltage < min_uV || voltage > max_uV)
 316                return -EINVAL;
 317
 318        return ret;
 319}
 320EXPORT_SYMBOL_GPL(regulator_map_voltage_linear_range);
 321
 322/**
 323 * regulator_list_voltage_linear - List voltages with simple calculation
 324 *
 325 * @rdev: Regulator device
 326 * @selector: Selector to convert into a voltage
 327 *
 328 * Regulators with a simple linear mapping between voltages and
 329 * selectors can set min_uV and uV_step in the regulator descriptor
 330 * and then use this function as their list_voltage() operation,
 331 */
 332int regulator_list_voltage_linear(struct regulator_dev *rdev,
 333                                  unsigned int selector)
 334{
 335        if (selector >= rdev->desc->n_voltages)
 336                return -EINVAL;
 337        if (selector < rdev->desc->linear_min_sel)
 338                return 0;
 339
 340        selector -= rdev->desc->linear_min_sel;
 341
 342        return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
 343}
 344EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
 345
 346/**
 347 * regulator_list_voltage_linear_range - List voltages for linear ranges
 348 *
 349 * @rdev: Regulator device
 350 * @selector: Selector to convert into a voltage
 351 *
 352 * Regulators with a series of simple linear mappings between voltages
 353 * and selectors can set linear_ranges in the regulator descriptor and
 354 * then use this function as their list_voltage() operation,
 355 */
 356int regulator_list_voltage_linear_range(struct regulator_dev *rdev,
 357                                        unsigned int selector)
 358{
 359        const struct regulator_linear_range *range;
 360        int i;
 361
 362        if (!rdev->desc->n_linear_ranges) {
 363                BUG_ON(!rdev->desc->n_linear_ranges);
 364                return -EINVAL;
 365        }
 366
 367        for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
 368                range = &rdev->desc->linear_ranges[i];
 369
 370                if (!(selector >= range->min_sel &&
 371                      selector <= range->max_sel))
 372                        continue;
 373
 374                selector -= range->min_sel;
 375
 376                return range->min_uV + (range->uV_step * selector);
 377        }
 378
 379        return -EINVAL;
 380}
 381EXPORT_SYMBOL_GPL(regulator_list_voltage_linear_range);
 382
 383/**
 384 * regulator_list_voltage_table - List voltages with table based mapping
 385 *
 386 * @rdev: Regulator device
 387 * @selector: Selector to convert into a voltage
 388 *
 389 * Regulators with table based mapping between voltages and
 390 * selectors can set volt_table in the regulator descriptor
 391 * and then use this function as their list_voltage() operation.
 392 */
 393int regulator_list_voltage_table(struct regulator_dev *rdev,
 394                                 unsigned int selector)
 395{
 396        if (!rdev->desc->volt_table) {
 397                BUG_ON(!rdev->desc->volt_table);
 398                return -EINVAL;
 399        }
 400
 401        if (selector >= rdev->desc->n_voltages)
 402                return -EINVAL;
 403
 404        return rdev->desc->volt_table[selector];
 405}
 406EXPORT_SYMBOL_GPL(regulator_list_voltage_table);
 407
 408/**
 409 * regulator_set_bypass_regmap - Default set_bypass() using regmap
 410 *
 411 * @rdev: device to operate on.
 412 * @enable: state to set.
 413 */
 414int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable)
 415{
 416        unsigned int val;
 417
 418        if (enable)
 419                val = rdev->desc->bypass_mask;
 420        else
 421                val = 0;
 422
 423        return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg,
 424                                  rdev->desc->bypass_mask, val);
 425}
 426EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap);
 427
 428/**
 429 * regulator_get_bypass_regmap - Default get_bypass() using regmap
 430 *
 431 * @rdev: device to operate on.
 432 * @enable: current state.
 433 */
 434int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable)
 435{
 436        unsigned int val;
 437        int ret;
 438
 439        ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val);
 440        if (ret != 0)
 441                return ret;
 442
 443        *enable = val & rdev->desc->bypass_mask;
 444
 445        return 0;
 446}
 447EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap);
 448
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.