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

« back to all changes in this revision

Viewing changes to drivers/regulator/pcap-regulator.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
 * PCAP2 Regulator Driver
 
3
 *
 
4
 * Copyright (c) 2009 Daniel Ribeiro <drwyrm@gmail.com>
 
5
 *
 
6
 * This program is free software; you can redistribute  it and/or modify it
 
7
 * under  the terms of  the GNU General  Public License as published by the
 
8
 * Free Software Foundation;  either version 2 of the  License, or (at your
 
9
 * option) any later version.
 
10
 */
 
11
 
 
12
#include <linux/kernel.h>
 
13
#include <linux/module.h>
 
14
#include <linux/init.h>
 
15
#include <linux/err.h>
 
16
#include <linux/platform_device.h>
 
17
#include <linux/regulator/driver.h>
 
18
#include <linux/regulator/machine.h>
 
19
#include <linux/mfd/ezx-pcap.h>
 
20
 
 
21
static const u16 V1_table[] = {
 
22
        2775, 1275, 1600, 1725, 1825, 1925, 2075, 2275,
 
23
};
 
24
 
 
25
static const u16 V2_table[] = {
 
26
        2500, 2775,
 
27
};
 
28
 
 
29
static const u16 V3_table[] = {
 
30
        1075, 1275, 1550, 1725, 1876, 1950, 2075, 2275,
 
31
};
 
32
 
 
33
static const u16 V4_table[] = {
 
34
        1275, 1550, 1725, 1875, 1950, 2075, 2275, 2775,
 
35
};
 
36
 
 
37
static const u16 V5_table[] = {
 
38
        1875, 2275, 2475, 2775,
 
39
};
 
40
 
 
41
static const u16 V6_table[] = {
 
42
        2475, 2775,
 
43
};
 
44
 
 
45
static const u16 V7_table[] = {
 
46
        1875, 2775,
 
47
};
 
48
 
 
49
#define V8_table V4_table
 
50
 
 
51
static const u16 V9_table[] = {
 
52
        1575, 1875, 2475, 2775,
 
53
};
 
54
 
 
55
static const u16 V10_table[] = {
 
56
        5000,
 
57
};
 
58
 
 
59
static const u16 VAUX1_table[] = {
 
60
        1875, 2475, 2775, 3000,
 
61
};
 
62
 
 
63
#define VAUX2_table VAUX1_table
 
64
 
 
65
static const u16 VAUX3_table[] = {
 
66
        1200, 1200, 1200, 1200, 1400, 1600, 1800, 2000,
 
67
        2200, 2400, 2600, 2800, 3000, 3200, 3400, 3600,
 
68
};
 
69
 
 
70
static const u16 VAUX4_table[] = {
 
71
        1800, 1800, 3000, 5000,
 
72
};
 
73
 
 
74
static const u16 VSIM_table[] = {
 
75
        1875, 3000,
 
76
};
 
77
 
 
78
static const u16 VSIM2_table[] = {
 
79
        1875,
 
80
};
 
81
 
 
82
static const u16 VVIB_table[] = {
 
83
        1300, 1800, 2000, 3000,
 
84
};
 
85
 
 
86
static const u16 SW1_table[] = {
 
87
        900, 950, 1000, 1050, 1100, 1150, 1200, 1250,
 
88
        1300, 1350, 1400, 1450, 1500, 1600, 1875, 2250,
 
89
};
 
90
 
 
91
#define SW2_table SW1_table
 
92
 
 
93
static const u16 SW3_table[] = {
 
94
        4000, 4500, 5000, 5500,
 
95
};
 
96
 
 
97
struct pcap_regulator {
 
98
        const u8 reg;
 
99
        const u8 en;
 
100
        const u8 index;
 
101
        const u8 stby;
 
102
        const u8 lowpwr;
 
103
        const u8 n_voltages;
 
104
        const u16 *voltage_table;
 
105
};
 
106
 
 
107
#define NA 0xff
 
108
 
 
109
#define VREG_INFO(_vreg, _reg, _en, _index, _stby, _lowpwr)             \
 
110
        [_vreg] = {                                                     \
 
111
                .reg            = _reg,                                 \
 
112
                .en             = _en,                                  \
 
113
                .index          = _index,                               \
 
114
                .stby           = _stby,                                \
 
115
                .lowpwr         = _lowpwr,                              \
 
116
                .n_voltages     = ARRAY_SIZE(_vreg##_table),            \
 
117
                .voltage_table  = _vreg##_table,                        \
 
118
        }
 
119
 
 
120
static struct pcap_regulator vreg_table[] = {
 
121
        VREG_INFO(V1,    PCAP_REG_VREG1,   1,  2,  18, 0),
 
122
        VREG_INFO(V2,    PCAP_REG_VREG1,   5,  6,  19, 22),
 
123
        VREG_INFO(V3,    PCAP_REG_VREG1,   7,  8,  20, 23),
 
124
        VREG_INFO(V4,    PCAP_REG_VREG1,   11, 12, 21, 24),
 
125
        /* V5 STBY and LOWPWR are on PCAP_REG_VREG2 */
 
126
        VREG_INFO(V5,    PCAP_REG_VREG1,   15, 16, 12, 19),
 
127
 
 
128
        VREG_INFO(V6,    PCAP_REG_VREG2,   1,  2,  14, 20),
 
129
        VREG_INFO(V7,    PCAP_REG_VREG2,   3,  4,  15, 21),
 
130
        VREG_INFO(V8,    PCAP_REG_VREG2,   5,  6,  16, 22),
 
131
        VREG_INFO(V9,    PCAP_REG_VREG2,   9,  10, 17, 23),
 
132
        VREG_INFO(V10,   PCAP_REG_VREG2,   10, NA, 18, 24),
 
133
 
 
134
        VREG_INFO(VAUX1, PCAP_REG_AUXVREG, 1,  2,  22, 23),
 
135
        /* VAUX2 ... VSIM2 STBY and LOWPWR are on PCAP_REG_LOWPWR */
 
136
        VREG_INFO(VAUX2, PCAP_REG_AUXVREG, 4,  5,  0,  1),
 
137
        VREG_INFO(VAUX3, PCAP_REG_AUXVREG, 7,  8,  2,  3),
 
138
        VREG_INFO(VAUX4, PCAP_REG_AUXVREG, 12, 13, 4,  5),
 
139
        VREG_INFO(VSIM,  PCAP_REG_AUXVREG, 17, 18, NA, 6),
 
140
        VREG_INFO(VSIM2, PCAP_REG_AUXVREG, 16, NA, NA, 7),
 
141
        VREG_INFO(VVIB,  PCAP_REG_AUXVREG, 19, 20, NA, NA),
 
142
 
 
143
        VREG_INFO(SW1,   PCAP_REG_SWCTRL,  1,  2,  NA, NA),
 
144
        VREG_INFO(SW2,   PCAP_REG_SWCTRL,  6,  7,  NA, NA),
 
145
        /* SW3 STBY is on PCAP_REG_AUXVREG */
 
146
        VREG_INFO(SW3,   PCAP_REG_SWCTRL,  11, 12, 24, NA),
 
147
 
 
148
        /* SWxS used to control SWx voltage on standby */
 
149
/*      VREG_INFO(SW1S,  PCAP_REG_LOWPWR,  NA, 12, NA, NA),
 
150
        VREG_INFO(SW2S,  PCAP_REG_LOWPWR,  NA, 20, NA, NA), */
 
151
};
 
152
 
 
153
static int pcap_regulator_set_voltage(struct regulator_dev *rdev,
 
154
                                      int min_uV, int max_uV,
 
155
                                      unsigned *selector)
 
156
{
 
157
        struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
 
158
        void *pcap = rdev_get_drvdata(rdev);
 
159
        int uV;
 
160
        u8 i;
 
161
 
 
162
        /* the regulator doesn't support voltage switching */
 
163
        if (vreg->n_voltages == 1)
 
164
                return -EINVAL;
 
165
 
 
166
        for (i = 0; i < vreg->n_voltages; i++) {
 
167
                /* For V1 the first is not the best match */
 
168
                if (i == 0 && rdev_get_id(rdev) == V1)
 
169
                        i = 1;
 
170
                else if (i + 1 == vreg->n_voltages && rdev_get_id(rdev) == V1)
 
171
                        i = 0;
 
172
 
 
173
                uV = vreg->voltage_table[i] * 1000;
 
174
                if (min_uV <= uV && uV <= max_uV) {
 
175
                        *selector = i;
 
176
                        return ezx_pcap_set_bits(pcap, vreg->reg,
 
177
                                        (vreg->n_voltages - 1) << vreg->index,
 
178
                                        i << vreg->index);
 
179
                }
 
180
 
 
181
                if (i == 0 && rdev_get_id(rdev) == V1)
 
182
                        i = vreg->n_voltages - 1;
 
183
        }
 
184
 
 
185
        /* the requested voltage range is not supported by this regulator */
 
186
        return -EINVAL;
 
187
}
 
188
 
 
189
static int pcap_regulator_get_voltage(struct regulator_dev *rdev)
 
190
{
 
191
        struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
 
192
        void *pcap = rdev_get_drvdata(rdev);
 
193
        u32 tmp;
 
194
        int mV;
 
195
 
 
196
        if (vreg->n_voltages == 1)
 
197
                return vreg->voltage_table[0] * 1000;
 
198
 
 
199
        ezx_pcap_read(pcap, vreg->reg, &tmp);
 
200
        tmp = ((tmp >> vreg->index) & (vreg->n_voltages - 1));
 
201
        mV = vreg->voltage_table[tmp];
 
202
 
 
203
        return mV * 1000;
 
204
}
 
205
 
 
206
static int pcap_regulator_enable(struct regulator_dev *rdev)
 
207
{
 
208
        struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
 
209
        void *pcap = rdev_get_drvdata(rdev);
 
210
 
 
211
        if (vreg->en == NA)
 
212
                return -EINVAL;
 
213
 
 
214
        return ezx_pcap_set_bits(pcap, vreg->reg, 1 << vreg->en, 1 << vreg->en);
 
215
}
 
216
 
 
217
static int pcap_regulator_disable(struct regulator_dev *rdev)
 
218
{
 
219
        struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
 
220
        void *pcap = rdev_get_drvdata(rdev);
 
221
 
 
222
        if (vreg->en == NA)
 
223
                return -EINVAL;
 
224
 
 
225
        return ezx_pcap_set_bits(pcap, vreg->reg, 1 << vreg->en, 0);
 
226
}
 
227
 
 
228
static int pcap_regulator_is_enabled(struct regulator_dev *rdev)
 
229
{
 
230
        struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
 
231
        void *pcap = rdev_get_drvdata(rdev);
 
232
        u32 tmp;
 
233
 
 
234
        if (vreg->en == NA)
 
235
                return -EINVAL;
 
236
 
 
237
        ezx_pcap_read(pcap, vreg->reg, &tmp);
 
238
        return (tmp >> vreg->en) & 1;
 
239
}
 
240
 
 
241
static int pcap_regulator_list_voltage(struct regulator_dev *rdev,
 
242
                                                        unsigned int index)
 
243
{
 
244
        struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
 
245
 
 
246
        return vreg->voltage_table[index] * 1000;
 
247
}
 
248
 
 
249
static struct regulator_ops pcap_regulator_ops = {
 
250
        .list_voltage   = pcap_regulator_list_voltage,
 
251
        .set_voltage    = pcap_regulator_set_voltage,
 
252
        .get_voltage    = pcap_regulator_get_voltage,
 
253
        .enable         = pcap_regulator_enable,
 
254
        .disable        = pcap_regulator_disable,
 
255
        .is_enabled     = pcap_regulator_is_enabled,
 
256
};
 
257
 
 
258
#define VREG(_vreg)                                             \
 
259
        [_vreg] = {                                             \
 
260
                .name           = #_vreg,                       \
 
261
                .id             = _vreg,                        \
 
262
                .n_voltages     = ARRAY_SIZE(_vreg##_table),    \
 
263
                .ops            = &pcap_regulator_ops,          \
 
264
                .type           = REGULATOR_VOLTAGE,            \
 
265
                .owner          = THIS_MODULE,                  \
 
266
        }
 
267
 
 
268
static struct regulator_desc pcap_regulators[] = {
 
269
        VREG(V1), VREG(V2), VREG(V3), VREG(V4), VREG(V5), VREG(V6), VREG(V7),
 
270
        VREG(V8), VREG(V9), VREG(V10), VREG(VAUX1), VREG(VAUX2), VREG(VAUX3),
 
271
        VREG(VAUX4), VREG(VSIM), VREG(VSIM2), VREG(VVIB), VREG(SW1), VREG(SW2),
 
272
};
 
273
 
 
274
static int __devinit pcap_regulator_probe(struct platform_device *pdev)
 
275
{
 
276
        struct regulator_dev *rdev;
 
277
        void *pcap = dev_get_drvdata(pdev->dev.parent);
 
278
 
 
279
        rdev = regulator_register(&pcap_regulators[pdev->id], &pdev->dev,
 
280
                                pdev->dev.platform_data, pcap);
 
281
        if (IS_ERR(rdev))
 
282
                return PTR_ERR(rdev);
 
283
 
 
284
        platform_set_drvdata(pdev, rdev);
 
285
 
 
286
        return 0;
 
287
}
 
288
 
 
289
static int __devexit pcap_regulator_remove(struct platform_device *pdev)
 
290
{
 
291
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
292
 
 
293
        regulator_unregister(rdev);
 
294
        platform_set_drvdata(pdev, NULL);
 
295
 
 
296
        return 0;
 
297
}
 
298
 
 
299
static struct platform_driver pcap_regulator_driver = {
 
300
        .driver = {
 
301
                .name   = "pcap-regulator",
 
302
                .owner  = THIS_MODULE,
 
303
        },
 
304
        .probe  = pcap_regulator_probe,
 
305
        .remove = __devexit_p(pcap_regulator_remove),
 
306
};
 
307
 
 
308
static int __init pcap_regulator_init(void)
 
309
{
 
310
        return platform_driver_register(&pcap_regulator_driver);
 
311
}
 
312
 
 
313
static void __exit pcap_regulator_exit(void)
 
314
{
 
315
        platform_driver_unregister(&pcap_regulator_driver);
 
316
}
 
317
 
 
318
subsys_initcall(pcap_regulator_init);
 
319
module_exit(pcap_regulator_exit);
 
320
 
 
321
MODULE_AUTHOR("Daniel Ribeiro <drwyrm@gmail.com>");
 
322
MODULE_DESCRIPTION("PCAP2 Regulator Driver");
 
323
MODULE_LICENSE("GPL");