linux/drivers/regulator/mc13xxx-regulator-core.c
<<
>>
Prefs
   1/*
   2 * Regulator Driver for Freescale MC13xxx PMIC
   3 *
   4 * Copyright 2010 Yong Shen <yong.shen@linaro.org>
   5 *
   6 * Based on mc13783 regulator driver :
   7 * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
   8 * Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13 *
  14 * Regs infos taken from mc13xxx drivers from freescale and mc13xxx.pdf file
  15 * from freescale
  16 */
  17
  18#include <linux/mfd/mc13xxx.h>
  19#include <linux/regulator/machine.h>
  20#include <linux/regulator/driver.h>
  21#include <linux/regulator/of_regulator.h>
  22#include <linux/platform_device.h>
  23#include <linux/kernel.h>
  24#include <linux/slab.h>
  25#include <linux/init.h>
  26#include <linux/err.h>
  27#include <linux/module.h>
  28#include <linux/of.h>
  29#include "mc13xxx.h"
  30
  31static int mc13xxx_regulator_enable(struct regulator_dev *rdev)
  32{
  33        struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
  34        struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
  35        int id = rdev_get_id(rdev);
  36        int ret;
  37
  38        dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
  39
  40        mc13xxx_lock(priv->mc13xxx);
  41        ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg,
  42                        mc13xxx_regulators[id].enable_bit,
  43                        mc13xxx_regulators[id].enable_bit);
  44        mc13xxx_unlock(priv->mc13xxx);
  45
  46        return ret;
  47}
  48
  49static int mc13xxx_regulator_disable(struct regulator_dev *rdev)
  50{
  51        struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
  52        struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
  53        int id = rdev_get_id(rdev);
  54        int ret;
  55
  56        dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
  57
  58        mc13xxx_lock(priv->mc13xxx);
  59        ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg,
  60                        mc13xxx_regulators[id].enable_bit, 0);
  61        mc13xxx_unlock(priv->mc13xxx);
  62
  63        return ret;
  64}
  65
  66static int mc13xxx_regulator_is_enabled(struct regulator_dev *rdev)
  67{
  68        struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
  69        struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
  70        int ret, id = rdev_get_id(rdev);
  71        unsigned int val;
  72
  73        mc13xxx_lock(priv->mc13xxx);
  74        ret = mc13xxx_reg_read(priv->mc13xxx, mc13xxx_regulators[id].reg, &val);
  75        mc13xxx_unlock(priv->mc13xxx);
  76
  77        if (ret)
  78                return ret;
  79
  80        return (val & mc13xxx_regulators[id].enable_bit) != 0;
  81}
  82
  83static int mc13xxx_regulator_set_voltage_sel(struct regulator_dev *rdev,
  84                                             unsigned selector)
  85{
  86        struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
  87        struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
  88        int id = rdev_get_id(rdev);
  89        int ret;
  90
  91        mc13xxx_lock(priv->mc13xxx);
  92        ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].vsel_reg,
  93                        mc13xxx_regulators[id].vsel_mask,
  94                        selector << mc13xxx_regulators[id].vsel_shift);
  95        mc13xxx_unlock(priv->mc13xxx);
  96
  97        return ret;
  98}
  99
 100static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev)
 101{
 102        struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
 103        struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
 104        int ret, id = rdev_get_id(rdev);
 105        unsigned int val;
 106
 107        dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
 108
 109        mc13xxx_lock(priv->mc13xxx);
 110        ret = mc13xxx_reg_read(priv->mc13xxx,
 111                                mc13xxx_regulators[id].vsel_reg, &val);
 112        mc13xxx_unlock(priv->mc13xxx);
 113
 114        if (ret)
 115                return ret;
 116
 117        val = (val & mc13xxx_regulators[id].vsel_mask)
 118                >> mc13xxx_regulators[id].vsel_shift;
 119
 120        dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val);
 121
 122        BUG_ON(val >= mc13xxx_regulators[id].desc.n_voltages);
 123
 124        return rdev->desc->volt_table[val];
 125}
 126
 127struct regulator_ops mc13xxx_regulator_ops = {
 128        .enable = mc13xxx_regulator_enable,
 129        .disable = mc13xxx_regulator_disable,
 130        .is_enabled = mc13xxx_regulator_is_enabled,
 131        .list_voltage = regulator_list_voltage_table,
 132        .set_voltage_sel = mc13xxx_regulator_set_voltage_sel,
 133        .get_voltage = mc13xxx_regulator_get_voltage,
 134};
 135EXPORT_SYMBOL_GPL(mc13xxx_regulator_ops);
 136
 137int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
 138               int max_uV, unsigned *selector)
 139{
 140        int id = rdev_get_id(rdev);
 141
 142        dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
 143                __func__, id, min_uV, max_uV);
 144
 145        if (min_uV <= rdev->desc->volt_table[0] &&
 146            rdev->desc->volt_table[0] <= max_uV) {
 147                *selector = 0;
 148                return 0;
 149        } else {
 150                return -EINVAL;
 151        }
 152}
 153EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_set_voltage);
 154
 155struct regulator_ops mc13xxx_fixed_regulator_ops = {
 156        .enable = mc13xxx_regulator_enable,
 157        .disable = mc13xxx_regulator_disable,
 158        .is_enabled = mc13xxx_regulator_is_enabled,
 159        .list_voltage = regulator_list_voltage_table,
 160        .set_voltage = mc13xxx_fixed_regulator_set_voltage,
 161};
 162EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops);
 163
 164#ifdef CONFIG_OF
 165int mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
 166{
 167        struct device_node *parent, *child;
 168        int num = 0;
 169
 170        of_node_get(pdev->dev.parent->of_node);
 171        parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators");
 172        if (!parent)
 173                return -ENODEV;
 174
 175        for_each_child_of_node(parent, child)
 176                num++;
 177
 178        return num;
 179}
 180EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt);
 181
 182struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
 183        struct platform_device *pdev, struct mc13xxx_regulator *regulators,
 184        int num_regulators)
 185{
 186        struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
 187        struct mc13xxx_regulator_init_data *data, *p;
 188        struct device_node *parent, *child;
 189        int i;
 190
 191        of_node_get(pdev->dev.parent->of_node);
 192        parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators");
 193        if (!parent)
 194                return NULL;
 195
 196        data = devm_kzalloc(&pdev->dev, sizeof(*data) * priv->num_regulators,
 197                            GFP_KERNEL);
 198        if (!data)
 199                return NULL;
 200        p = data;
 201
 202        for_each_child_of_node(parent, child) {
 203                for (i = 0; i < num_regulators; i++) {
 204                        if (!of_node_cmp(child->name,
 205                                         regulators[i].desc.name)) {
 206                                p->id = i;
 207                                p->init_data = of_get_regulator_init_data(
 208                                                        &pdev->dev, child);
 209                                p->node = child;
 210                                p++;
 211                                break;
 212                        }
 213                }
 214        }
 215
 216        return data;
 217}
 218EXPORT_SYMBOL_GPL(mc13xxx_parse_regulators_dt);
 219#endif
 220
 221MODULE_LICENSE("GPL v2");
 222MODULE_AUTHOR("Yong Shen <yong.shen@linaro.org>");
 223MODULE_DESCRIPTION("Regulator Driver for Freescale MC13xxx PMIC");
 224MODULE_ALIAS("mc13xxx-regulator-core");
 225
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.