aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator/fan53555-regulator.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/regulator/fan53555-regulator.c
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/regulator/fan53555-regulator.c')
-rw-r--r--drivers/regulator/fan53555-regulator.c567
1 files changed, 567 insertions, 0 deletions
diff --git a/drivers/regulator/fan53555-regulator.c b/drivers/regulator/fan53555-regulator.c
new file mode 100644
index 00000000000..13fa79c4ba3
--- /dev/null
+++ b/drivers/regulator/fan53555-regulator.c
@@ -0,0 +1,567 @@
1/*
2 * driver/regultor/fan53555-regulator.c
3 *
4 * Driver for FAN53555UC00X, FAN53555UC01X, FAN53555UC03X,
5 * FAN53555UC04X, FAN53555UC05X
6 *
7 * Copyright (c) 2011, NVIDIA Corporation.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation version 2.
12 *
13 * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
14 * whether express or implied; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 * 02111-1307, USA
22 */
23
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/err.h>
28#include <linux/platform_device.h>
29#include <linux/regulator/driver.h>
30#include <linux/regulator/machine.h>
31#include <linux/regulator/fan53555-regulator.h>
32#include <linux/i2c.h>
33#include <linux/delay.h>
34#include <linux/slab.h>
35
36/* Register definitions */
37#define FAN53555_REG_VSEL0 0
38#define FAN53555_REG_VSEL1 1
39#define FAN53555_REG_CONTROL 2
40#define FAN53555_REG_ID1 3
41#define FAN53555_REG_ID2 4
42#define FAN53555_REG_MONITOR 5
43
44#define FAN53555_VSEL_BUCK_EN BIT(7)
45#define FAN53555_VSEL_MODE BIT(6)
46#define FAN53555_VSEL_NSEL_SHIFT 0
47#define FAN53555_VSEL_NSEL_MASK 0x3F
48
49#define FAN53555_CONTROL_DISCHARGE BIT(7)
50#define FAN53555_CONTROL_SLEW_SHIFT 4
51#define FAN53555_CONTROL_SLEW_MASK 0x70
52#define FAN53555_CONTROL_RESET BIT(2)
53
54#define FAN53555_ID1_VENDOR_SHIFT 4
55#define FAN53555_ID1_VENDOR_MASK 0xF0
56#define FAN53555_ID1_DIE_ID_SHIFT 0
57#define FAN53555_ID1_DIE_ID_MASK 0x0F
58
59#define FAN53555_ID2_REV_SHIFT 0
60#define FAN53555_ID2_REV_MASK 0x0F
61
62#define FAN53555_MONITOR_ILIM BIT(7)
63#define FAN53555_MONITOR_UVLO BIT(6)
64#define FAN53555_MONITOR_OVP BIT(5)
65#define FAN53555_MONITOR_POS BIT(4)
66#define FAN53555_MONITOR_NEG BIT(3)
67#define FAN53555_MONITOR_RESET_STAT BIT(2)
68#define FAN53555_MONITOR_OT BIT(1)
69#define FAN53555_MONITOR_BUCK_STATUS BIT(0)
70
71#define FAN53555_VSEL0_ID 0
72#define FAN53555_VSEL1_ID 1
73
74#define FAN53555UC00X_ID 0x80
75#define FAN53555UC01X_ID 0x81
76#define FAN53555UC03X_ID 0x83
77#define FAN53555UC04X_ID 0x84
78#define FAN53555UC05X_ID 0x85
79
80#define FAN53555_N_VOLTAGES 64
81
82/* FAN53555 chip information */
83struct fan53555_chip {
84 const char *name;
85 struct device *dev;
86 struct regulator_desc desc;
87 struct i2c_client *client;
88 struct regulator_dev *rdev;
89 struct mutex io_lock;
90 int chip_id;
91 int vsel_id;
92 u8 shadow[6];
93};
94
95#define FAN53555_VOLTAGE(chip_id, vsel) \
96 (((chip_id) == FAN53555UC04X_ID) ? \
97 ((vsel) * 12826 + 600000) : ((vsel) * 10000 + 600000))
98
99static int fan53555_read(struct fan53555_chip *fan, u8 reg)
100{
101 u8 data;
102 u8 val;
103 int ret;
104
105 data = reg;
106
107 ret = i2c_master_send(fan->client, &data, 1);
108 if (ret < 0)
109 goto out;
110
111 ret = i2c_master_recv(fan->client, &val, 1);
112 if (ret < 0)
113 goto out;
114
115 ret = val;
116out:
117 return ret;
118}
119
120static inline int fan53555_write(struct fan53555_chip *fan, u8 reg, u8 val)
121{
122 u8 msg[2];
123 int ret;
124
125 msg[0] = reg;
126 msg[1] = val;
127
128 ret = i2c_master_send(fan->client, msg, 2);
129 if (ret < 0)
130 return ret;
131 if (ret != 2)
132 return -EIO;
133 return 0;
134}
135
136static int fan53555_read_reg(struct fan53555_chip *fan, u8 reg)
137{
138 int data;
139
140 mutex_lock(&fan->io_lock);
141 data = fan53555_read(fan, reg);
142 if (data < 0)
143 dev_err(fan->dev, "Read from reg 0x%x failed\n", reg);
144 mutex_unlock(&fan->io_lock);
145
146 return data;
147}
148
149static int fan53555_set_bits(struct fan53555_chip *fan, u8 reg, u8 mask, u8 val)
150{
151 int err;
152 u8 data;
153
154 mutex_lock(&fan->io_lock);
155 data = fan->shadow[reg];
156 data &= ~mask;
157 val &= mask;
158 data |= val;
159 err = fan53555_write(fan, reg, data);
160 if (err)
161 dev_err(fan->dev, "write for reg 0x%x failed\n", reg);
162 else
163 fan->shadow[reg] = data;
164 mutex_unlock(&fan->io_lock);
165
166 return err;
167}
168
169static int __fan53555_dcdc_set_voltage(struct fan53555_chip *fan,
170 int vsel_id, int min_uV, int max_uV,
171 unsigned *selector)
172{
173 int nsel;
174 int uV;
175 int chip_id;
176 int n_voltages;
177
178 chip_id = fan->chip_id;
179 n_voltages = fan->desc.n_voltages;
180
181 if (max_uV < min_uV) {
182 dev_err(fan->dev, "max_uV(%d) < min_uV(%d)\n", max_uV, min_uV);
183 return -EINVAL;
184 }
185 if (min_uV > FAN53555_VOLTAGE(chip_id, n_voltages - 1)) {
186 dev_err(fan->dev, "min_uV(%d) > %d[uV]\n",
187 min_uV, FAN53555_VOLTAGE(chip_id, n_voltages - 1));
188 return -EINVAL;
189 }
190 if (max_uV < FAN53555_VOLTAGE(chip_id, 0)) {
191 dev_err(fan->dev, "max_uV(%d) < %d[uV]\n",
192 max_uV, FAN53555_VOLTAGE(chip_id, 0));
193 return -EINVAL;
194 }
195 if ((vsel_id != FAN53555_VSEL0_ID) && (vsel_id != FAN53555_VSEL1_ID)) {
196 dev_err(fan->dev,
197 "%d is not valid VSEL register ID\n", vsel_id);
198 return -EINVAL;
199 }
200 for (nsel = 0; nsel < n_voltages; nsel++) {
201 uV = FAN53555_VOLTAGE(chip_id, nsel);
202 if (min_uV <= uV && uV <= max_uV) {
203 if (selector)
204 *selector = nsel;
205 return fan53555_set_bits(fan,
206 FAN53555_REG_VSEL0 + vsel_id,
207 FAN53555_VSEL_NSEL_MASK,
208 nsel <<
209 FAN53555_VSEL_NSEL_SHIFT);
210 }
211 }
212
213 return -EINVAL;
214}
215
216#ifdef CONFIG_DEBUG_FS
217
218#include <linux/debugfs.h>
219#include <linux/seq_file.h>
220
221static int dbg_fan_show(struct seq_file *s, void *unused)
222{
223 struct fan53555_chip *fan = s->private;
224 int val;
225
226 seq_printf(s, "FAN53555 Registers\n");
227 seq_printf(s, "------------------\n");
228
229 val = fan53555_read_reg(fan, FAN53555_REG_VSEL0);
230 if (val >= 0)
231 seq_printf(s, "Reg VSEL0 Value 0x%02x\n", val);
232
233 val = fan53555_read_reg(fan, FAN53555_REG_VSEL1);
234 if (val >= 0)
235 seq_printf(s, "Reg VSEL1 Value 0x%02x\n", val);
236
237 val = fan53555_read_reg(fan, FAN53555_REG_CONTROL);
238 if (val >= 0)
239 seq_printf(s, "Reg CONTROL Value 0x%02x\n", val);
240
241 val = fan53555_read_reg(fan, FAN53555_REG_ID1);
242 if (val >= 0)
243 seq_printf(s, "Reg ID1 Value 0x%02x\n", val);
244
245 val = fan53555_read_reg(fan, FAN53555_REG_ID2);
246 if (val >= 0)
247 seq_printf(s, "Reg ID2 Value 0x%02x\n", val);
248
249 val = fan53555_read_reg(fan, FAN53555_REG_MONITOR);
250 if (val >= 0)
251 seq_printf(s, "Reg MONITOR Value 0x%02x\n", val);
252
253 return 0;
254}
255
256static int dbg_fan_open(struct inode *inode, struct file *file)
257{
258 return single_open(file, dbg_fan_show, inode->i_private);
259}
260
261static const struct file_operations debug_fops = {
262 .open = dbg_fan_open,
263 .read = seq_read,
264 .llseek = seq_lseek,
265 .release = single_release,
266};
267
268static void __init fan53555_debuginit(struct fan53555_chip *fan)
269{
270 (void)debugfs_create_file("fan53555", S_IRUGO, NULL, fan, &debug_fops);
271}
272#else
273static void __init fan53555_debuginit(struct fan53555_chip *fan)
274{
275}
276#endif
277
278static int fan53555_dcdc_init(struct fan53555_chip *fan,
279 struct i2c_client *client,
280 struct fan53555_regulator_platform_data *pdata)
281{
282 int err;
283 int val;
284
285 err = fan53555_read_reg(fan, FAN53555_REG_VSEL0);
286 if (err < 0)
287 return err;
288 fan->shadow[FAN53555_REG_VSEL0] = (u8)err;
289
290 err = fan53555_read_reg(fan, FAN53555_REG_VSEL1);
291 if (err < 0)
292 return err;
293 fan->shadow[FAN53555_REG_VSEL1] = (u8)err;
294
295 err = fan53555_read_reg(fan, FAN53555_REG_CONTROL);
296 if (err < 0)
297 return err;
298 fan->shadow[FAN53555_REG_CONTROL] = (u8)err;
299
300 err = __fan53555_dcdc_set_voltage(fan,
301 FAN53555_VSEL0_ID,
302 pdata->init_vsel0_min_uV,
303 pdata->init_vsel0_max_uV,
304 NULL);
305 if (err < 0)
306 return err;
307
308 val = pdata->vsel0_buck_en ? FAN53555_VSEL_BUCK_EN : 0;
309 val |= pdata->vsel0_mode ? FAN53555_VSEL_MODE : 0;
310 err = fan53555_set_bits(fan,
311 FAN53555_REG_VSEL0,
312 FAN53555_VSEL_BUCK_EN | FAN53555_VSEL_MODE,
313 val);
314 if (err < 0)
315 return err;
316
317 err = __fan53555_dcdc_set_voltage(fan,
318 FAN53555_VSEL1_ID,
319 pdata->init_vsel1_min_uV,
320 pdata->init_vsel1_max_uV,
321 NULL);
322 if (err < 0)
323 return err;
324
325 val = pdata->vsel1_buck_en ? FAN53555_VSEL_BUCK_EN : 0;
326 val |= pdata->vsel1_mode ? FAN53555_VSEL_MODE : 0;
327 err = fan53555_set_bits(fan,
328 FAN53555_REG_VSEL1,
329 FAN53555_VSEL_BUCK_EN | FAN53555_VSEL_MODE,
330 val);
331 if (err < 0)
332 return err;
333
334 val = pdata->slew_rate;
335 val <<= FAN53555_CONTROL_SLEW_SHIFT;
336 val |= pdata->output_discharge ? FAN53555_CONTROL_DISCHARGE : 0;
337 err = fan53555_set_bits(fan,
338 FAN53555_REG_CONTROL,
339 FAN53555_CONTROL_DISCHARGE |
340 FAN53555_CONTROL_SLEW_MASK, val);
341 return err;
342}
343
344static int fan53555_dcdc_list_voltage(struct regulator_dev *dev,
345 unsigned selector)
346{
347 struct fan53555_chip *fan = rdev_get_drvdata(dev);
348
349 if ((selector < 0) || (selector >= fan->desc.n_voltages))
350 return -EINVAL;
351
352 return FAN53555_VOLTAGE(fan->chip_id, selector);
353}
354
355static int fan53555_dcdc_set_voltage(struct regulator_dev *dev,
356 int min_uV, int max_uV,
357 unsigned *selector)
358{
359 struct fan53555_chip *fan = rdev_get_drvdata(dev);
360
361 return __fan53555_dcdc_set_voltage(fan, fan->vsel_id, min_uV, max_uV,
362 selector);
363}
364
365static int fan53555_dcdc_get_voltage(struct regulator_dev *dev)
366{
367 struct fan53555_chip *fan = rdev_get_drvdata(dev);
368 u8 data;
369
370 if ((fan->vsel_id != FAN53555_VSEL0_ID) &&
371 (fan->vsel_id != FAN53555_VSEL1_ID)) {
372 dev_err(fan->dev,
373 "%d is not valid VSEL register ID\n", fan->vsel_id);
374 return -EINVAL;
375 }
376 data = fan->shadow[FAN53555_REG_VSEL0 + fan->vsel_id];
377 data &= FAN53555_VSEL_NSEL_MASK;
378 data >>= FAN53555_VSEL_NSEL_SHIFT;
379
380 return FAN53555_VOLTAGE(fan->chip_id, data);
381}
382
383static int fan53555_dcdc_enable(struct regulator_dev *dev)
384{
385 struct fan53555_chip *fan = rdev_get_drvdata(dev);
386
387 if ((fan->vsel_id != FAN53555_VSEL0_ID) &&
388 (fan->vsel_id != FAN53555_VSEL1_ID)) {
389 dev_err(fan->dev,
390 "%d is not valid VSEL register ID\n", fan->vsel_id);
391 return -EINVAL;
392 }
393
394 return fan53555_set_bits(fan,
395 FAN53555_REG_VSEL0 + fan->vsel_id,
396 FAN53555_VSEL_BUCK_EN, FAN53555_VSEL_BUCK_EN);
397}
398
399static int fan53555_dcdc_disable(struct regulator_dev *dev)
400{
401 struct fan53555_chip *fan = rdev_get_drvdata(dev);
402
403 if ((fan->vsel_id != FAN53555_VSEL0_ID) &&
404 (fan->vsel_id != FAN53555_VSEL1_ID)) {
405 dev_err(fan->dev,
406 "%d is not valid VSEL register ID\n", fan->vsel_id);
407 return -EINVAL;
408 }
409
410 return fan53555_set_bits(fan,
411 FAN53555_REG_VSEL0 + fan->vsel_id,
412 FAN53555_VSEL_BUCK_EN, 0);
413}
414
415static int fan53555_dcdc_is_enabled(struct regulator_dev *dev)
416{
417 struct fan53555_chip *fan = rdev_get_drvdata(dev);
418 u8 data;
419
420 if ((fan->vsel_id != FAN53555_VSEL0_ID) &&
421 (fan->vsel_id != FAN53555_VSEL1_ID)) {
422 dev_err(fan->dev,
423 "%d is not valid VSEL register ID\n", fan->vsel_id);
424 return -EINVAL;
425 }
426 data = fan->shadow[FAN53555_REG_VSEL0 + fan->vsel_id];
427
428 return (data & FAN53555_VSEL_BUCK_EN) ? 1 : 0;
429}
430
431static struct regulator_ops fan53555_dcdc_ops = {
432 .list_voltage = fan53555_dcdc_list_voltage,
433 .set_voltage = fan53555_dcdc_set_voltage,
434 .get_voltage = fan53555_dcdc_get_voltage,
435 .enable = fan53555_dcdc_enable,
436 .disable = fan53555_dcdc_disable,
437 .is_enabled = fan53555_dcdc_is_enabled,
438};
439
440static int __devinit fan53555_probe(struct i2c_client *client,
441 const struct i2c_device_id *id)
442{
443 struct fan53555_regulator_platform_data *pdata;
444 struct regulator_init_data *init_data;
445 struct regulator_dev *rdev;
446 struct fan53555_chip *fan;
447 int chip_id;
448 int err;
449
450 pdata = client->dev.platform_data;
451 if (!pdata) {
452 dev_err(&client->dev, "Err: Platform data not found\n");
453 return -EIO;
454 }
455 init_data = &pdata->reg_init_data;
456 fan = kzalloc(sizeof(*fan), GFP_KERNEL);
457 if (!fan) {
458 dev_err(&client->dev, "Err: Memory allocation fails\n");
459 return -ENOMEM;
460 }
461 mutex_init(&fan->io_lock);
462 fan->client = client;
463 fan->dev = &client->dev;
464 fan->vsel_id = pdata->vsel_id;
465 fan->name = id->name;
466 fan->desc.name = id->name;
467 fan->desc.id = 0;
468 fan->desc.irq = 0;
469 fan->desc.ops = &fan53555_dcdc_ops;
470 fan->desc.type = REGULATOR_VOLTAGE;
471 fan->desc.owner = THIS_MODULE;
472 fan->desc.n_voltages = FAN53555_N_VOLTAGES;
473 i2c_set_clientdata(client, fan);
474
475 chip_id = fan53555_read_reg(fan, FAN53555_REG_ID1);
476 if (chip_id < 0) {
477 err = chip_id;
478 dev_err(fan->dev, "Error in reading device %d\n", err);
479 goto fail;
480 }
481
482 switch (chip_id) {
483 case FAN53555UC00X_ID:
484 case FAN53555UC01X_ID:
485 case FAN53555UC03X_ID:
486 case FAN53555UC04X_ID:
487 case FAN53555UC05X_ID:
488 fan->chip_id = chip_id;
489 break;
490 default:
491 dev_err(fan->dev, "Err: not supported device chip id 0x%x",
492 chip_id);
493 err = -ENODEV;
494 goto fail;
495 }
496
497 err = fan53555_dcdc_init(fan, client, pdata);
498 if (err < 0) {
499 dev_err(fan->dev, "FAN53555 init fails with %d\n", err);
500 goto fail;
501 }
502
503 rdev = regulator_register(&fan->desc, &client->dev, init_data, fan);
504 if (IS_ERR(rdev)) {
505 dev_err(fan->dev, "Failed to register %s\n", id->name);
506 err = PTR_ERR(rdev);
507 goto fail;
508 }
509 fan->rdev = rdev;
510
511 fan53555_debuginit(fan);
512 return 0;
513
514fail:
515 kfree(fan);
516 return err;
517}
518
519/**
520 * fan53555_remove - fan53555 driver i2c remove handler
521 * @client: i2c driver client device structure
522 *
523 * Unregister fan53555 driver as an i2c client device driver
524 */
525static int __devexit fan53555_remove(struct i2c_client *client)
526{
527 struct fan53555_chip *chip = i2c_get_clientdata(client);
528
529 regulator_unregister(chip->rdev);
530 kfree(chip);
531 return 0;
532}
533
534static const struct i2c_device_id fan53555_id[] = {
535 {.name = "fan53555", .driver_data = 0 },
536 {},
537};
538MODULE_DEVICE_TABLE(i2c, fan53555_id);
539
540static struct i2c_driver fan53555_i2c_driver = {
541 .driver = {
542 .name = "fan53555",
543 .owner = THIS_MODULE,
544 },
545 .probe = fan53555_probe,
546 .remove = __devexit_p(fan53555_remove),
547 .id_table = fan53555_id,
548};
549
550/* Module init function */
551static int __init fan53555_init(void)
552{
553 return i2c_add_driver(&fan53555_i2c_driver);
554}
555subsys_initcall_sync(fan53555_init);
556
557/* Module exit function */
558static void __exit fan53555_cleanup(void)
559{
560 i2c_del_driver(&fan53555_i2c_driver);
561}
562module_exit(fan53555_cleanup);
563
564MODULE_LICENSE("GPL");
565MODULE_AUTHOR("Jake Park<jakep@nvidia.com>");
566MODULE_DESCRIPTION("Regulator Driver for Fairchild FAN53555 Regulator");
567MODULE_ALIAS("platform:fan53555-regulator");