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

« back to all changes in this revision

Viewing changes to drivers/regulator/max8660.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
 * max8660.c  --  Voltage regulation for the Maxim 8660/8661
 
3
 *
 
4
 * based on max1586.c and wm8400-regulator.c
 
5
 *
 
6
 * Copyright (C) 2009 Wolfram Sang, Pengutronix e.K.
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or modify it
 
9
 * under the terms of the GNU General Public License as published by the Free
 
10
 * Software Foundation; version 2 of the License.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful, but WITHOUT
 
13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
14
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 
15
 * more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License along with
 
18
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
19
 * Place, Suite 330, Boston, MA  02111-1307  USA
 
20
 *
 
21
 * Some info:
 
22
 *
 
23
 * Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX8660-MAX8661.pdf
 
24
 *
 
25
 * This chip is a bit nasty because it is a write-only device. Thus, the driver
 
26
 * uses shadow registers to keep track of its values. The main problem appears
 
27
 * to be the initialization: When Linux boots up, we cannot know if the chip is
 
28
 * in the default state or not, so we would have to pass such information in
 
29
 * platform_data. As this adds a bit of complexity to the driver, this is left
 
30
 * out for now until it is really needed.
 
31
 *
 
32
 * [A|S|M]DTV1 registers are currently not used, but [A|S|M]DTV2.
 
33
 *
 
34
 * If the driver is feature complete, it might be worth to check if one set of
 
35
 * functions for V3-V7 is sufficient. For maximum flexibility during
 
36
 * development, they are separated for now.
 
37
 *
 
38
 */
 
39
 
 
40
#include <linux/module.h>
 
41
#include <linux/err.h>
 
42
#include <linux/i2c.h>
 
43
#include <linux/platform_device.h>
 
44
#include <linux/regulator/driver.h>
 
45
#include <linux/slab.h>
 
46
#include <linux/regulator/max8660.h>
 
47
 
 
48
#define MAX8660_DCDC_MIN_UV      725000
 
49
#define MAX8660_DCDC_MAX_UV     1800000
 
50
#define MAX8660_DCDC_STEP         25000
 
51
#define MAX8660_DCDC_MAX_SEL    0x2b
 
52
 
 
53
#define MAX8660_LDO5_MIN_UV     1700000
 
54
#define MAX8660_LDO5_MAX_UV     2000000
 
55
#define MAX8660_LDO5_STEP         25000
 
56
#define MAX8660_LDO5_MAX_SEL    0x0c
 
57
 
 
58
#define MAX8660_LDO67_MIN_UV    1800000
 
59
#define MAX8660_LDO67_MAX_UV    3300000
 
60
#define MAX8660_LDO67_STEP       100000
 
61
#define MAX8660_LDO67_MAX_SEL   0x0f
 
62
 
 
63
enum {
 
64
        MAX8660_OVER1,
 
65
        MAX8660_OVER2,
 
66
        MAX8660_VCC1,
 
67
        MAX8660_ADTV1,
 
68
        MAX8660_ADTV2,
 
69
        MAX8660_SDTV1,
 
70
        MAX8660_SDTV2,
 
71
        MAX8660_MDTV1,
 
72
        MAX8660_MDTV2,
 
73
        MAX8660_L12VCR,
 
74
        MAX8660_FPWM,
 
75
        MAX8660_N_REGS, /* not a real register */
 
76
};
 
77
 
 
78
struct max8660 {
 
79
        struct i2c_client *client;
 
80
        u8 shadow_regs[MAX8660_N_REGS];         /* as chip is write only */
 
81
        struct regulator_dev *rdev[];
 
82
};
 
83
 
 
84
static int max8660_write(struct max8660 *max8660, u8 reg, u8 mask, u8 val)
 
85
{
 
86
        static const u8 max8660_addresses[MAX8660_N_REGS] =
 
87
          { 0x10, 0x12, 0x20, 0x23, 0x24, 0x29, 0x2a, 0x32, 0x33, 0x39, 0x80 };
 
88
 
 
89
        int ret;
 
90
        u8 reg_val = (max8660->shadow_regs[reg] & mask) | val;
 
91
        dev_vdbg(&max8660->client->dev, "Writing reg %02x with %02x\n",
 
92
                        max8660_addresses[reg], reg_val);
 
93
 
 
94
        ret = i2c_smbus_write_byte_data(max8660->client,
 
95
                        max8660_addresses[reg], reg_val);
 
96
        if (ret == 0)
 
97
                max8660->shadow_regs[reg] = reg_val;
 
98
 
 
99
        return ret;
 
100
}
 
101
 
 
102
 
 
103
/*
 
104
 * DCDC functions
 
105
 */
 
106
 
 
107
static int max8660_dcdc_is_enabled(struct regulator_dev *rdev)
 
108
{
 
109
        struct max8660 *max8660 = rdev_get_drvdata(rdev);
 
110
        u8 val = max8660->shadow_regs[MAX8660_OVER1];
 
111
        u8 mask = (rdev_get_id(rdev) == MAX8660_V3) ? 1 : 4;
 
112
        return !!(val & mask);
 
113
}
 
114
 
 
115
static int max8660_dcdc_enable(struct regulator_dev *rdev)
 
116
{
 
117
        struct max8660 *max8660 = rdev_get_drvdata(rdev);
 
118
        u8 bit = (rdev_get_id(rdev) == MAX8660_V3) ? 1 : 4;
 
119
        return max8660_write(max8660, MAX8660_OVER1, 0xff, bit);
 
120
}
 
121
 
 
122
static int max8660_dcdc_disable(struct regulator_dev *rdev)
 
123
{
 
124
        struct max8660 *max8660 = rdev_get_drvdata(rdev);
 
125
        u8 mask = (rdev_get_id(rdev) == MAX8660_V3) ? ~1 : ~4;
 
126
        return max8660_write(max8660, MAX8660_OVER1, mask, 0);
 
127
}
 
128
 
 
129
static int max8660_dcdc_list(struct regulator_dev *rdev, unsigned selector)
 
130
{
 
131
        if (selector > MAX8660_DCDC_MAX_SEL)
 
132
                return -EINVAL;
 
133
        return MAX8660_DCDC_MIN_UV + selector * MAX8660_DCDC_STEP;
 
134
}
 
135
 
 
136
static int max8660_dcdc_get(struct regulator_dev *rdev)
 
137
{
 
138
        struct max8660 *max8660 = rdev_get_drvdata(rdev);
 
139
        u8 reg = (rdev_get_id(rdev) == MAX8660_V3) ? MAX8660_ADTV2 : MAX8660_SDTV2;
 
140
        u8 selector = max8660->shadow_regs[reg];
 
141
        return MAX8660_DCDC_MIN_UV + selector * MAX8660_DCDC_STEP;
 
142
}
 
143
 
 
144
static int max8660_dcdc_set(struct regulator_dev *rdev, int min_uV, int max_uV,
 
145
                            unsigned int *s)
 
146
{
 
147
        struct max8660 *max8660 = rdev_get_drvdata(rdev);
 
148
        u8 reg, selector, bits;
 
149
        int ret;
 
150
 
 
151
        if (min_uV < MAX8660_DCDC_MIN_UV || min_uV > MAX8660_DCDC_MAX_UV)
 
152
                return -EINVAL;
 
153
        if (max_uV < MAX8660_DCDC_MIN_UV || max_uV > MAX8660_DCDC_MAX_UV)
 
154
                return -EINVAL;
 
155
 
 
156
        selector = (min_uV - (MAX8660_DCDC_MIN_UV - MAX8660_DCDC_STEP + 1))
 
157
                        / MAX8660_DCDC_STEP;
 
158
        *s = selector;
 
159
 
 
160
        ret = max8660_dcdc_list(rdev, selector);
 
161
        if (ret < 0 || ret > max_uV)
 
162
                return -EINVAL;
 
163
 
 
164
        reg = (rdev_get_id(rdev) == MAX8660_V3) ? MAX8660_ADTV2 : MAX8660_SDTV2;
 
165
        ret = max8660_write(max8660, reg, 0, selector);
 
166
        if (ret)
 
167
                return ret;
 
168
 
 
169
        /* Select target voltage register and activate regulation */
 
170
        bits = (rdev_get_id(rdev) == MAX8660_V3) ? 0x03 : 0x30;
 
171
        return max8660_write(max8660, MAX8660_VCC1, 0xff, bits);
 
172
}
 
173
 
 
174
static struct regulator_ops max8660_dcdc_ops = {
 
175
        .is_enabled = max8660_dcdc_is_enabled,
 
176
        .list_voltage = max8660_dcdc_list,
 
177
        .set_voltage = max8660_dcdc_set,
 
178
        .get_voltage = max8660_dcdc_get,
 
179
};
 
180
 
 
181
 
 
182
/*
 
183
 * LDO5 functions
 
184
 */
 
185
 
 
186
static int max8660_ldo5_list(struct regulator_dev *rdev, unsigned selector)
 
187
{
 
188
        if (selector > MAX8660_LDO5_MAX_SEL)
 
189
                return -EINVAL;
 
190
        return MAX8660_LDO5_MIN_UV + selector * MAX8660_LDO5_STEP;
 
191
}
 
192
 
 
193
static int max8660_ldo5_get(struct regulator_dev *rdev)
 
194
{
 
195
        struct max8660 *max8660 = rdev_get_drvdata(rdev);
 
196
        u8 selector = max8660->shadow_regs[MAX8660_MDTV2];
 
197
 
 
198
        return MAX8660_LDO5_MIN_UV + selector * MAX8660_LDO5_STEP;
 
199
}
 
200
 
 
201
static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV,
 
202
                            unsigned int *s)
 
203
{
 
204
        struct max8660 *max8660 = rdev_get_drvdata(rdev);
 
205
        u8 selector;
 
206
        int ret;
 
207
 
 
208
        if (min_uV < MAX8660_LDO5_MIN_UV || min_uV > MAX8660_LDO5_MAX_UV)
 
209
                return -EINVAL;
 
210
        if (max_uV < MAX8660_LDO5_MIN_UV || max_uV > MAX8660_LDO5_MAX_UV)
 
211
                return -EINVAL;
 
212
 
 
213
        selector = (min_uV - (MAX8660_LDO5_MIN_UV - MAX8660_LDO5_STEP + 1))
 
214
                        / MAX8660_LDO5_STEP;
 
215
        ret = max8660_ldo5_list(rdev, selector);
 
216
        if (ret < 0 || ret > max_uV)
 
217
                return -EINVAL;
 
218
 
 
219
        *s = selector;
 
220
 
 
221
        ret = max8660_write(max8660, MAX8660_MDTV2, 0, selector);
 
222
        if (ret)
 
223
                return ret;
 
224
 
 
225
        /* Select target voltage register and activate regulation */
 
226
        return max8660_write(max8660, MAX8660_VCC1, 0xff, 0xc0);
 
227
}
 
228
 
 
229
static struct regulator_ops max8660_ldo5_ops = {
 
230
        .list_voltage = max8660_ldo5_list,
 
231
        .set_voltage = max8660_ldo5_set,
 
232
        .get_voltage = max8660_ldo5_get,
 
233
};
 
234
 
 
235
 
 
236
/*
 
237
 * LDO67 functions
 
238
 */
 
239
 
 
240
static int max8660_ldo67_is_enabled(struct regulator_dev *rdev)
 
241
{
 
242
        struct max8660 *max8660 = rdev_get_drvdata(rdev);
 
243
        u8 val = max8660->shadow_regs[MAX8660_OVER2];
 
244
        u8 mask = (rdev_get_id(rdev) == MAX8660_V6) ? 2 : 4;
 
245
        return !!(val & mask);
 
246
}
 
247
 
 
248
static int max8660_ldo67_enable(struct regulator_dev *rdev)
 
249
{
 
250
        struct max8660 *max8660 = rdev_get_drvdata(rdev);
 
251
        u8 bit = (rdev_get_id(rdev) == MAX8660_V6) ? 2 : 4;
 
252
        return max8660_write(max8660, MAX8660_OVER2, 0xff, bit);
 
253
}
 
254
 
 
255
static int max8660_ldo67_disable(struct regulator_dev *rdev)
 
256
{
 
257
        struct max8660 *max8660 = rdev_get_drvdata(rdev);
 
258
        u8 mask = (rdev_get_id(rdev) == MAX8660_V6) ? ~2 : ~4;
 
259
        return max8660_write(max8660, MAX8660_OVER2, mask, 0);
 
260
}
 
261
 
 
262
static int max8660_ldo67_list(struct regulator_dev *rdev, unsigned selector)
 
263
{
 
264
        if (selector > MAX8660_LDO67_MAX_SEL)
 
265
                return -EINVAL;
 
266
        return MAX8660_LDO67_MIN_UV + selector * MAX8660_LDO67_STEP;
 
267
}
 
268
 
 
269
static int max8660_ldo67_get(struct regulator_dev *rdev)
 
270
{
 
271
        struct max8660 *max8660 = rdev_get_drvdata(rdev);
 
272
        u8 shift = (rdev_get_id(rdev) == MAX8660_V6) ? 0 : 4;
 
273
        u8 selector = (max8660->shadow_regs[MAX8660_L12VCR] >> shift) & 0xf;
 
274
 
 
275
        return MAX8660_LDO67_MIN_UV + selector * MAX8660_LDO67_STEP;
 
276
}
 
277
 
 
278
static int max8660_ldo67_set(struct regulator_dev *rdev, int min_uV,
 
279
                             int max_uV, unsigned int *s)
 
280
{
 
281
        struct max8660 *max8660 = rdev_get_drvdata(rdev);
 
282
        u8 selector;
 
283
        int ret;
 
284
 
 
285
        if (min_uV < MAX8660_LDO67_MIN_UV || min_uV > MAX8660_LDO67_MAX_UV)
 
286
                return -EINVAL;
 
287
        if (max_uV < MAX8660_LDO67_MIN_UV || max_uV > MAX8660_LDO67_MAX_UV)
 
288
                return -EINVAL;
 
289
 
 
290
        selector = (min_uV - (MAX8660_LDO67_MIN_UV - MAX8660_LDO67_STEP + 1))
 
291
                        / MAX8660_LDO67_STEP;
 
292
 
 
293
        ret = max8660_ldo67_list(rdev, selector);
 
294
        if (ret < 0 || ret > max_uV)
 
295
                return -EINVAL;
 
296
 
 
297
        *s = selector;
 
298
 
 
299
        if (rdev_get_id(rdev) == MAX8660_V6)
 
300
                return max8660_write(max8660, MAX8660_L12VCR, 0xf0, selector);
 
301
        else
 
302
                return max8660_write(max8660, MAX8660_L12VCR, 0x0f, selector << 4);
 
303
}
 
304
 
 
305
static struct regulator_ops max8660_ldo67_ops = {
 
306
        .is_enabled = max8660_ldo67_is_enabled,
 
307
        .enable = max8660_ldo67_enable,
 
308
        .disable = max8660_ldo67_disable,
 
309
        .list_voltage = max8660_ldo67_list,
 
310
        .get_voltage = max8660_ldo67_get,
 
311
        .set_voltage = max8660_ldo67_set,
 
312
};
 
313
 
 
314
static struct regulator_desc max8660_reg[] = {
 
315
        {
 
316
                .name = "V3(DCDC)",
 
317
                .id = MAX8660_V3,
 
318
                .ops = &max8660_dcdc_ops,
 
319
                .type = REGULATOR_VOLTAGE,
 
320
                .n_voltages = MAX8660_DCDC_MAX_SEL + 1,
 
321
                .owner = THIS_MODULE,
 
322
        },
 
323
        {
 
324
                .name = "V4(DCDC)",
 
325
                .id = MAX8660_V4,
 
326
                .ops = &max8660_dcdc_ops,
 
327
                .type = REGULATOR_VOLTAGE,
 
328
                .n_voltages = MAX8660_DCDC_MAX_SEL + 1,
 
329
                .owner = THIS_MODULE,
 
330
        },
 
331
        {
 
332
                .name = "V5(LDO)",
 
333
                .id = MAX8660_V5,
 
334
                .ops = &max8660_ldo5_ops,
 
335
                .type = REGULATOR_VOLTAGE,
 
336
                .n_voltages = MAX8660_LDO5_MAX_SEL + 1,
 
337
                .owner = THIS_MODULE,
 
338
        },
 
339
        {
 
340
                .name = "V6(LDO)",
 
341
                .id = MAX8660_V6,
 
342
                .ops = &max8660_ldo67_ops,
 
343
                .type = REGULATOR_VOLTAGE,
 
344
                .n_voltages = MAX8660_LDO67_MAX_SEL + 1,
 
345
                .owner = THIS_MODULE,
 
346
        },
 
347
        {
 
348
                .name = "V7(LDO)",
 
349
                .id = MAX8660_V7,
 
350
                .ops = &max8660_ldo67_ops,
 
351
                .type = REGULATOR_VOLTAGE,
 
352
                .n_voltages = MAX8660_LDO67_MAX_SEL + 1,
 
353
                .owner = THIS_MODULE,
 
354
        },
 
355
};
 
356
 
 
357
static int __devinit max8660_probe(struct i2c_client *client,
 
358
                                   const struct i2c_device_id *i2c_id)
 
359
{
 
360
        struct regulator_dev **rdev;
 
361
        struct max8660_platform_data *pdata = client->dev.platform_data;
 
362
        struct max8660 *max8660;
 
363
        int boot_on, i, id, ret = -EINVAL;
 
364
 
 
365
        if (pdata->num_subdevs > MAX8660_V_END) {
 
366
                dev_err(&client->dev, "Too many regulators found!\n");
 
367
                goto out;
 
368
        }
 
369
 
 
370
        max8660 = kzalloc(sizeof(struct max8660) +
 
371
                        sizeof(struct regulator_dev *) * MAX8660_V_END,
 
372
                        GFP_KERNEL);
 
373
        if (!max8660) {
 
374
                ret = -ENOMEM;
 
375
                goto out;
 
376
        }
 
377
 
 
378
        max8660->client = client;
 
379
        rdev = max8660->rdev;
 
380
 
 
381
        if (pdata->en34_is_high) {
 
382
                /* Simulate always on */
 
383
                max8660->shadow_regs[MAX8660_OVER1] = 5;
 
384
        } else {
 
385
                /* Otherwise devices can be toggled via software */
 
386
                max8660_dcdc_ops.enable = max8660_dcdc_enable;
 
387
                max8660_dcdc_ops.disable = max8660_dcdc_disable;
 
388
        }
 
389
 
 
390
        /*
 
391
         * First, set up shadow registers to prevent glitches. As some
 
392
         * registers are shared between regulators, everything must be properly
 
393
         * set up for all regulators in advance.
 
394
         */
 
395
        max8660->shadow_regs[MAX8660_ADTV1] =
 
396
                max8660->shadow_regs[MAX8660_ADTV2] =
 
397
                max8660->shadow_regs[MAX8660_SDTV1] =
 
398
                max8660->shadow_regs[MAX8660_SDTV2] = 0x1b;
 
399
        max8660->shadow_regs[MAX8660_MDTV1] =
 
400
                max8660->shadow_regs[MAX8660_MDTV2] = 0x04;
 
401
 
 
402
        for (i = 0; i < pdata->num_subdevs; i++) {
 
403
 
 
404
                if (!pdata->subdevs[i].platform_data)
 
405
                        goto err_free;
 
406
 
 
407
                boot_on = pdata->subdevs[i].platform_data->constraints.boot_on;
 
408
 
 
409
                switch (pdata->subdevs[i].id) {
 
410
                case MAX8660_V3:
 
411
                        if (boot_on)
 
412
                                max8660->shadow_regs[MAX8660_OVER1] |= 1;
 
413
                        break;
 
414
 
 
415
                case MAX8660_V4:
 
416
                        if (boot_on)
 
417
                                max8660->shadow_regs[MAX8660_OVER1] |= 4;
 
418
                        break;
 
419
 
 
420
                case MAX8660_V5:
 
421
                        break;
 
422
 
 
423
                case MAX8660_V6:
 
424
                        if (boot_on)
 
425
                                max8660->shadow_regs[MAX8660_OVER2] |= 2;
 
426
                        break;
 
427
 
 
428
                case MAX8660_V7:
 
429
                        if (!strcmp(i2c_id->name, "max8661")) {
 
430
                                dev_err(&client->dev, "Regulator not on this chip!\n");
 
431
                                goto err_free;
 
432
                        }
 
433
 
 
434
                        if (boot_on)
 
435
                                max8660->shadow_regs[MAX8660_OVER2] |= 4;
 
436
                        break;
 
437
 
 
438
                default:
 
439
                        dev_err(&client->dev, "invalid regulator %s\n",
 
440
                                 pdata->subdevs[i].name);
 
441
                        goto err_free;
 
442
                }
 
443
        }
 
444
 
 
445
        /* Finally register devices */
 
446
        for (i = 0; i < pdata->num_subdevs; i++) {
 
447
 
 
448
                id = pdata->subdevs[i].id;
 
449
 
 
450
                rdev[i] = regulator_register(&max8660_reg[id], &client->dev,
 
451
                                             pdata->subdevs[i].platform_data,
 
452
                                             max8660);
 
453
                if (IS_ERR(rdev[i])) {
 
454
                        ret = PTR_ERR(rdev[i]);
 
455
                        dev_err(&client->dev, "failed to register %s\n",
 
456
                                max8660_reg[id].name);
 
457
                        goto err_unregister;
 
458
                }
 
459
        }
 
460
 
 
461
        i2c_set_clientdata(client, max8660);
 
462
        dev_info(&client->dev, "Maxim 8660/8661 regulator driver loaded\n");
 
463
        return 0;
 
464
 
 
465
err_unregister:
 
466
        while (--i >= 0)
 
467
                regulator_unregister(rdev[i]);
 
468
err_free:
 
469
        kfree(max8660);
 
470
out:
 
471
        return ret;
 
472
}
 
473
 
 
474
static int __devexit max8660_remove(struct i2c_client *client)
 
475
{
 
476
        struct max8660 *max8660 = i2c_get_clientdata(client);
 
477
        int i;
 
478
 
 
479
        for (i = 0; i < MAX8660_V_END; i++)
 
480
                if (max8660->rdev[i])
 
481
                        regulator_unregister(max8660->rdev[i]);
 
482
        kfree(max8660);
 
483
 
 
484
        return 0;
 
485
}
 
486
 
 
487
static const struct i2c_device_id max8660_id[] = {
 
488
        { "max8660", 0 },
 
489
        { "max8661", 0 },
 
490
        { }
 
491
};
 
492
MODULE_DEVICE_TABLE(i2c, max8660_id);
 
493
 
 
494
static struct i2c_driver max8660_driver = {
 
495
        .probe = max8660_probe,
 
496
        .remove = __devexit_p(max8660_remove),
 
497
        .driver         = {
 
498
                .name   = "max8660",
 
499
                .owner  = THIS_MODULE,
 
500
        },
 
501
        .id_table       = max8660_id,
 
502
};
 
503
 
 
504
static int __init max8660_init(void)
 
505
{
 
506
        return i2c_add_driver(&max8660_driver);
 
507
}
 
508
subsys_initcall(max8660_init);
 
509
 
 
510
static void __exit max8660_exit(void)
 
511
{
 
512
        i2c_del_driver(&max8660_driver);
 
513
}
 
514
module_exit(max8660_exit);
 
515
 
 
516
/* Module information */
 
517
MODULE_DESCRIPTION("MAXIM 8660/8661 voltage regulator driver");
 
518
MODULE_AUTHOR("Wolfram Sang");
 
519
MODULE_LICENSE("GPL v2");