~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/regulator/mc13xxx-regulator-core.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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/platform_device.h>
 
22
#include <linux/kernel.h>
 
23
#include <linux/slab.h>
 
24
#include <linux/init.h>
 
25
#include <linux/err.h>
 
26
#include <linux/module.h>
 
27
#include "mc13xxx.h"
 
28
 
 
29
static int mc13xxx_regulator_enable(struct regulator_dev *rdev)
 
30
{
 
31
        struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
 
32
        struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
 
33
        int id = rdev_get_id(rdev);
 
34
        int ret;
 
35
 
 
36
        dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
 
37
 
 
38
        mc13xxx_lock(priv->mc13xxx);
 
39
        ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg,
 
40
                        mc13xxx_regulators[id].enable_bit,
 
41
                        mc13xxx_regulators[id].enable_bit);
 
42
        mc13xxx_unlock(priv->mc13xxx);
 
43
 
 
44
        return ret;
 
45
}
 
46
 
 
47
static int mc13xxx_regulator_disable(struct regulator_dev *rdev)
 
48
{
 
49
        struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
 
50
        struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
 
51
        int id = rdev_get_id(rdev);
 
52
        int ret;
 
53
 
 
54
        dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
 
55
 
 
56
        mc13xxx_lock(priv->mc13xxx);
 
57
        ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg,
 
58
                        mc13xxx_regulators[id].enable_bit, 0);
 
59
        mc13xxx_unlock(priv->mc13xxx);
 
60
 
 
61
        return ret;
 
62
}
 
63
 
 
64
static int mc13xxx_regulator_is_enabled(struct regulator_dev *rdev)
 
65
{
 
66
        struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
 
67
        struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
 
68
        int ret, id = rdev_get_id(rdev);
 
69
        unsigned int val;
 
70
 
 
71
        mc13xxx_lock(priv->mc13xxx);
 
72
        ret = mc13xxx_reg_read(priv->mc13xxx, mc13xxx_regulators[id].reg, &val);
 
73
        mc13xxx_unlock(priv->mc13xxx);
 
74
 
 
75
        if (ret)
 
76
                return ret;
 
77
 
 
78
        return (val & mc13xxx_regulators[id].enable_bit) != 0;
 
79
}
 
80
 
 
81
int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev,
 
82
                                                unsigned selector)
 
83
{
 
84
        int id = rdev_get_id(rdev);
 
85
        struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
 
86
        struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
 
87
 
 
88
        if (selector >= mc13xxx_regulators[id].desc.n_voltages)
 
89
                return -EINVAL;
 
90
 
 
91
        return mc13xxx_regulators[id].voltages[selector];
 
92
}
 
93
EXPORT_SYMBOL_GPL(mc13xxx_regulator_list_voltage);
 
94
 
 
95
int mc13xxx_get_best_voltage_index(struct regulator_dev *rdev,
 
96
                                                int min_uV, int max_uV)
 
97
{
 
98
        struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
 
99
        struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
 
100
        int reg_id = rdev_get_id(rdev);
 
101
        int i;
 
102
        int bestmatch;
 
103
        int bestindex;
 
104
 
 
105
        /*
 
106
         * Locate the minimum voltage fitting the criteria on
 
107
         * this regulator. The switchable voltages are not
 
108
         * in strict falling order so we need to check them
 
109
         * all for the best match.
 
110
         */
 
111
        bestmatch = INT_MAX;
 
112
        bestindex = -1;
 
113
        for (i = 0; i < mc13xxx_regulators[reg_id].desc.n_voltages; i++) {
 
114
                if (mc13xxx_regulators[reg_id].voltages[i] >= min_uV &&
 
115
                    mc13xxx_regulators[reg_id].voltages[i] < bestmatch) {
 
116
                        bestmatch = mc13xxx_regulators[reg_id].voltages[i];
 
117
                        bestindex = i;
 
118
                }
 
119
        }
 
120
 
 
121
        if (bestindex < 0 || bestmatch > max_uV) {
 
122
                dev_warn(&rdev->dev, "no possible value for %d<=x<=%d uV\n",
 
123
                                min_uV, max_uV);
 
124
                return -EINVAL;
 
125
        }
 
126
        return bestindex;
 
127
}
 
128
EXPORT_SYMBOL_GPL(mc13xxx_get_best_voltage_index);
 
129
 
 
130
static int mc13xxx_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
 
131
                int max_uV, unsigned *selector)
 
132
{
 
133
        struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
 
134
        struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
 
135
        int value, id = rdev_get_id(rdev);
 
136
        int ret;
 
137
 
 
138
        dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
 
139
                __func__, id, min_uV, max_uV);
 
140
 
 
141
        /* Find the best index */
 
142
        value = mc13xxx_get_best_voltage_index(rdev, min_uV, max_uV);
 
143
        dev_dbg(rdev_get_dev(rdev), "%s best value: %d\n", __func__, value);
 
144
        if (value < 0)
 
145
                return value;
 
146
 
 
147
        mc13xxx_lock(priv->mc13xxx);
 
148
        ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].vsel_reg,
 
149
                        mc13xxx_regulators[id].vsel_mask,
 
150
                        value << mc13xxx_regulators[id].vsel_shift);
 
151
        mc13xxx_unlock(priv->mc13xxx);
 
152
 
 
153
        return ret;
 
154
}
 
155
 
 
156
static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev)
 
157
{
 
158
        struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
 
159
        struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
 
160
        int ret, id = rdev_get_id(rdev);
 
161
        unsigned int val;
 
162
 
 
163
        dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
 
164
 
 
165
        mc13xxx_lock(priv->mc13xxx);
 
166
        ret = mc13xxx_reg_read(priv->mc13xxx,
 
167
                                mc13xxx_regulators[id].vsel_reg, &val);
 
168
        mc13xxx_unlock(priv->mc13xxx);
 
169
 
 
170
        if (ret)
 
171
                return ret;
 
172
 
 
173
        val = (val & mc13xxx_regulators[id].vsel_mask)
 
174
                >> mc13xxx_regulators[id].vsel_shift;
 
175
 
 
176
        dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val);
 
177
 
 
178
        BUG_ON(val >= mc13xxx_regulators[id].desc.n_voltages);
 
179
 
 
180
        return mc13xxx_regulators[id].voltages[val];
 
181
}
 
182
 
 
183
struct regulator_ops mc13xxx_regulator_ops = {
 
184
        .enable = mc13xxx_regulator_enable,
 
185
        .disable = mc13xxx_regulator_disable,
 
186
        .is_enabled = mc13xxx_regulator_is_enabled,
 
187
        .list_voltage = mc13xxx_regulator_list_voltage,
 
188
        .set_voltage = mc13xxx_regulator_set_voltage,
 
189
        .get_voltage = mc13xxx_regulator_get_voltage,
 
190
};
 
191
EXPORT_SYMBOL_GPL(mc13xxx_regulator_ops);
 
192
 
 
193
int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
 
194
               int max_uV, unsigned *selector)
 
195
{
 
196
        struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
 
197
        struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
 
198
        int id = rdev_get_id(rdev);
 
199
 
 
200
        dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
 
201
                __func__, id, min_uV, max_uV);
 
202
 
 
203
        if (min_uV >= mc13xxx_regulators[id].voltages[0] &&
 
204
            max_uV <= mc13xxx_regulators[id].voltages[0])
 
205
                return 0;
 
206
        else
 
207
                return -EINVAL;
 
208
}
 
209
EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_set_voltage);
 
210
 
 
211
int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev)
 
212
{
 
213
        struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
 
214
        struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
 
215
        int id = rdev_get_id(rdev);
 
216
 
 
217
        dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
 
218
 
 
219
        return mc13xxx_regulators[id].voltages[0];
 
220
}
 
221
EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_get_voltage);
 
222
 
 
223
struct regulator_ops mc13xxx_fixed_regulator_ops = {
 
224
        .enable = mc13xxx_regulator_enable,
 
225
        .disable = mc13xxx_regulator_disable,
 
226
        .is_enabled = mc13xxx_regulator_is_enabled,
 
227
        .list_voltage = mc13xxx_regulator_list_voltage,
 
228
        .set_voltage = mc13xxx_fixed_regulator_set_voltage,
 
229
        .get_voltage = mc13xxx_fixed_regulator_get_voltage,
 
230
};
 
231
EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops);
 
232
 
 
233
int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev)
 
234
{
 
235
        return 1;
 
236
}
 
237
EXPORT_SYMBOL_GPL(mc13xxx_sw_regulator_is_enabled);
 
238
 
 
239
MODULE_LICENSE("GPL v2");
 
240
MODULE_AUTHOR("Yong Shen <yong.shen@linaro.org>");
 
241
MODULE_DESCRIPTION("Regulator Driver for Freescale MC13xxx PMIC");
 
242
MODULE_ALIAS("mc13xxx-regulator-core");