mfd: Add LM3533 lighting-power core driver
[deliverable/linux.git] / drivers / mfd / lm3533-core.c
CommitLineData
16c5c023
JH
1/*
2 * lm3533-core.c -- LM3533 Core
3 *
4 * Copyright (C) 2011-2012 Texas Instruments
5 *
6 * Author: Johan Hovold <jhovold@gmail.com>
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
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/kernel.h>
17#include <linux/err.h>
18#include <linux/gpio.h>
19#include <linux/i2c.h>
20#include <linux/mfd/core.h>
21#include <linux/regmap.h>
22#include <linux/seq_file.h>
23#include <linux/slab.h>
24#include <linux/uaccess.h>
25
26#include <linux/mfd/lm3533.h>
27
28
29#define LM3533_BOOST_OVP_MAX 0x03
30#define LM3533_BOOST_OVP_MASK 0x06
31#define LM3533_BOOST_OVP_SHIFT 1
32
33#define LM3533_BOOST_FREQ_MAX 0x01
34#define LM3533_BOOST_FREQ_MASK 0x01
35#define LM3533_BOOST_FREQ_SHIFT 0
36
37#define LM3533_BL_ID_MASK 1
38#define LM3533_LED_ID_MASK 3
39#define LM3533_BL_ID_MAX 1
40#define LM3533_LED_ID_MAX 3
41
42#define LM3533_HVLED_ID_MAX 2
43#define LM3533_LVLED_ID_MAX 5
44
45#define LM3533_REG_OUTPUT_CONF1 0x10
46#define LM3533_REG_OUTPUT_CONF2 0x11
47#define LM3533_REG_BOOST_PWM 0x2c
48
49#define LM3533_REG_MAX 0xb2
50
51
52static struct mfd_cell lm3533_als_devs[] = {
53 {
54 .name = "lm3533-als",
55 .id = -1,
56 },
57};
58
59static struct mfd_cell lm3533_bl_devs[] = {
60 {
61 .name = "lm3533-backlight",
62 .id = 0,
63 },
64 {
65 .name = "lm3533-backlight",
66 .id = 1,
67 },
68};
69
70static struct mfd_cell lm3533_led_devs[] = {
71 {
72 .name = "lm3533-leds",
73 .id = 0,
74 },
75 {
76 .name = "lm3533-leds",
77 .id = 1,
78 },
79 {
80 .name = "lm3533-leds",
81 .id = 2,
82 },
83 {
84 .name = "lm3533-leds",
85 .id = 3,
86 },
87};
88
89int lm3533_read(struct lm3533 *lm3533, u8 reg, u8 *val)
90{
91 int tmp;
92 int ret;
93
94 ret = regmap_read(lm3533->regmap, reg, &tmp);
95 if (ret < 0) {
96 dev_err(lm3533->dev, "failed to read register %02x: %d\n",
97 reg, ret);
98 return ret;
99 }
100
101 *val = tmp;
102
103 dev_dbg(lm3533->dev, "read [%02x]: %02x\n", reg, *val);
104
105 return ret;
106}
107EXPORT_SYMBOL_GPL(lm3533_read);
108
109int lm3533_write(struct lm3533 *lm3533, u8 reg, u8 val)
110{
111 int ret;
112
113 dev_dbg(lm3533->dev, "write [%02x]: %02x\n", reg, val);
114
115 ret = regmap_write(lm3533->regmap, reg, val);
116 if (ret < 0) {
117 dev_err(lm3533->dev, "failed to write register %02x: %d\n",
118 reg, ret);
119 }
120
121 return ret;
122}
123EXPORT_SYMBOL_GPL(lm3533_write);
124
125int lm3533_update(struct lm3533 *lm3533, u8 reg, u8 val, u8 mask)
126{
127 int ret;
128
129 dev_dbg(lm3533->dev, "update [%02x]: %02x/%02x\n", reg, val, mask);
130
131 ret = regmap_update_bits(lm3533->regmap, reg, val, mask);
132 if (ret < 0) {
133 dev_err(lm3533->dev, "failed to update register %02x: %d\n",
134 reg, ret);
135 }
136
137 return ret;
138}
139EXPORT_SYMBOL_GPL(lm3533_update);
140
141/*
142 * HVLED output config -- output hvled controlled by backlight bl
143 */
144static int lm3533_set_hvled_config(struct lm3533 *lm3533, u8 hvled, u8 bl)
145{
146 u8 val;
147 u8 mask;
148 int shift;
149 int ret;
150
151 if (hvled == 0 || hvled > LM3533_HVLED_ID_MAX)
152 return -EINVAL;
153
154 if (bl > LM3533_BL_ID_MAX)
155 return -EINVAL;
156
157 shift = hvled - 1;
158 mask = LM3533_BL_ID_MASK << shift;
159 val = bl << shift;
160
161 ret = lm3533_update(lm3533, LM3533_REG_OUTPUT_CONF1, val, mask);
162 if (ret)
163 dev_err(lm3533->dev, "failed to set hvled config\n");
164
165 return ret;
166}
167
168/*
169 * LVLED output config -- output lvled controlled by LED led
170 */
171static int lm3533_set_lvled_config(struct lm3533 *lm3533, u8 lvled, u8 led)
172{
173 u8 reg;
174 u8 val;
175 u8 mask;
176 int shift;
177 int ret;
178
179 if (lvled == 0 || lvled > LM3533_LVLED_ID_MAX)
180 return -EINVAL;
181
182 if (led > LM3533_LED_ID_MAX)
183 return -EINVAL;
184
185 if (lvled < 4) {
186 reg = LM3533_REG_OUTPUT_CONF1;
187 shift = 2 * lvled;
188 } else {
189 reg = LM3533_REG_OUTPUT_CONF2;
190 shift = 2 * (lvled - 4);
191 }
192
193 mask = LM3533_LED_ID_MASK << shift;
194 val = led << shift;
195
196 ret = lm3533_update(lm3533, reg, val, mask);
197 if (ret)
198 dev_err(lm3533->dev, "failed to set lvled config\n");
199
200 return ret;
201}
202
203static void lm3533_enable(struct lm3533 *lm3533)
204{
205 if (gpio_is_valid(lm3533->gpio_hwen))
206 gpio_set_value(lm3533->gpio_hwen, 1);
207}
208
209static void lm3533_disable(struct lm3533 *lm3533)
210{
211 if (gpio_is_valid(lm3533->gpio_hwen))
212 gpio_set_value(lm3533->gpio_hwen, 0);
213}
214
215enum lm3533_attribute_type {
216 LM3533_ATTR_TYPE_BACKLIGHT,
217 LM3533_ATTR_TYPE_LED,
218};
219
220struct lm3533_device_attribute {
221 struct device_attribute dev_attr;
222 enum lm3533_attribute_type type;
223 union {
224 struct {
225 u8 id;
226 } output;
227 struct {
228 u8 reg;
229 u8 shift;
230 u8 mask;
231 u8 max;
232 } generic;
233 } u;
234};
235
236#define to_lm3533_dev_attr(_attr) \
237 container_of(_attr, struct lm3533_device_attribute, dev_attr)
238
239static ssize_t show_lm3533_reg(struct device *dev,
240 struct device_attribute *attr, char *buf)
241{
242 struct lm3533 *lm3533 = dev_get_drvdata(dev);
243 struct lm3533_device_attribute *lattr = to_lm3533_dev_attr(attr);
244 u8 val;
245 int ret;
246
247 ret = lm3533_read(lm3533, lattr->u.generic.reg, &val);
248 if (ret)
249 return ret;
250
251 val = (val & lattr->u.generic.mask) >> lattr->u.generic.shift;
252
253 return scnprintf(buf, PAGE_SIZE, "%u\n", val);
254}
255
256static ssize_t store_lm3533_reg(struct device *dev,
257 struct device_attribute *attr,
258 const char *buf, size_t len)
259{
260 struct lm3533 *lm3533 = dev_get_drvdata(dev);
261 struct lm3533_device_attribute *lattr = to_lm3533_dev_attr(attr);
262 u8 val;
263 int ret;
264
265 if (kstrtou8(buf, 0, &val) || val > lattr->u.generic.max)
266 return -EINVAL;
267
268 val = val << lattr->u.generic.shift;
269 ret = lm3533_update(lm3533, lattr->u.generic.reg, val,
270 lattr->u.generic.mask);
271 if (ret)
272 return ret;
273
274 return len;
275}
276
277#define GENERIC_ATTR(_reg, _max, _mask, _shift) \
278 { .reg = _reg, \
279 .max = _max, \
280 .mask = _mask, \
281 .shift = _shift }
282
283#define LM3533_GENERIC_ATTR(_name, _mode, _show, _store, _type, \
284 _reg, _max, _mask, _shift) \
285 struct lm3533_device_attribute lm3533_dev_attr_##_name = { \
286 .dev_attr = __ATTR(_name, _mode, _show, _store), \
287 .type = _type, \
288 .u.generic = GENERIC_ATTR(_reg, _max, _mask, _shift) }
289
290#define LM3533_GENERIC_ATTR_RW(_name, _type, _reg, _max, _mask, _shift) \
291 LM3533_GENERIC_ATTR(_name, S_IRUGO | S_IWUSR, \
292 show_lm3533_reg, store_lm3533_reg, \
293 _type, _reg, _max, _mask, _shift)
294
295#define LM3533_BOOST_ATTR_RW(_name, _NAME) \
296 LM3533_GENERIC_ATTR_RW(_name, LM3533_ATTR_TYPE_BACKLIGHT, \
297 LM3533_REG_BOOST_PWM, LM3533_##_NAME##_MAX, \
298 LM3533_##_NAME##_MASK, LM3533_##_NAME##_SHIFT)
299/*
300 * Boost Over Voltage Protection Select
301 *
302 * 0 - 16 V (default)
303 * 1 - 24 V
304 * 2 - 32 V
305 * 3 - 40 V
306 */
307static LM3533_BOOST_ATTR_RW(boost_ovp, BOOST_OVP);
308
309/*
310 * Boost Frequency Select
311 *
312 * 0 - 500 kHz (default)
313 * 1 - 1 MHz
314 */
315static LM3533_BOOST_ATTR_RW(boost_freq, BOOST_FREQ);
316
317static ssize_t show_output(struct device *dev,
318 struct device_attribute *attr, char *buf)
319{
320 struct lm3533 *lm3533 = dev_get_drvdata(dev);
321 struct lm3533_device_attribute *lattr = to_lm3533_dev_attr(attr);
322 int id = lattr->u.output.id;
323 u8 reg;
324 u8 val;
325 u8 mask;
326 int shift;
327 int ret;
328
329 if (lattr->type == LM3533_ATTR_TYPE_BACKLIGHT) {
330 reg = LM3533_REG_OUTPUT_CONF1;
331 shift = id - 1;
332 mask = LM3533_BL_ID_MASK << shift;
333 } else {
334 if (id < 4) {
335 reg = LM3533_REG_OUTPUT_CONF1;
336 shift = 2 * id;
337 } else {
338 reg = LM3533_REG_OUTPUT_CONF2;
339 shift = 2 * (id - 4);
340 }
341 mask = LM3533_LED_ID_MASK << shift;
342 }
343
344 ret = lm3533_read(lm3533, reg, &val);
345 if (ret)
346 return ret;
347
348 val = (val & mask) >> shift;
349
350 return scnprintf(buf, PAGE_SIZE, "%u\n", val);
351}
352
353static ssize_t store_output(struct device *dev,
354 struct device_attribute *attr,
355 const char *buf, size_t len)
356{
357 struct lm3533 *lm3533 = dev_get_drvdata(dev);
358 struct lm3533_device_attribute *lattr = to_lm3533_dev_attr(attr);
359 int id = lattr->u.output.id;
360 u8 val;
361 int ret;
362
363 if (kstrtou8(buf, 0, &val))
364 return -EINVAL;
365
366 if (lattr->type == LM3533_ATTR_TYPE_BACKLIGHT)
367 ret = lm3533_set_hvled_config(lm3533, id, val);
368 else
369 ret = lm3533_set_lvled_config(lm3533, id, val);
370
371 if (ret)
372 return ret;
373
374 return len;
375}
376
377#define LM3533_OUTPUT_ATTR(_name, _mode, _show, _store, _type, _id) \
378 struct lm3533_device_attribute lm3533_dev_attr_##_name = \
379 { .dev_attr = __ATTR(_name, _mode, _show, _store), \
380 .type = _type, \
381 .u.output = { .id = _id }, }
382
383#define LM3533_OUTPUT_ATTR_RW(_name, _type, _id) \
384 LM3533_OUTPUT_ATTR(output_##_name, S_IRUGO | S_IWUSR, \
385 show_output, store_output, _type, _id)
386
387#define LM3533_OUTPUT_HVLED_ATTR_RW(_nr) \
388 LM3533_OUTPUT_ATTR_RW(hvled##_nr, LM3533_ATTR_TYPE_BACKLIGHT, _nr)
389#define LM3533_OUTPUT_LVLED_ATTR_RW(_nr) \
390 LM3533_OUTPUT_ATTR_RW(lvled##_nr, LM3533_ATTR_TYPE_LED, _nr)
391/*
392 * Output config:
393 *
394 * output_hvled<nr> 0-1
395 * output_lvled<nr> 0-3
396 */
397static LM3533_OUTPUT_HVLED_ATTR_RW(1);
398static LM3533_OUTPUT_HVLED_ATTR_RW(2);
399static LM3533_OUTPUT_LVLED_ATTR_RW(1);
400static LM3533_OUTPUT_LVLED_ATTR_RW(2);
401static LM3533_OUTPUT_LVLED_ATTR_RW(3);
402static LM3533_OUTPUT_LVLED_ATTR_RW(4);
403static LM3533_OUTPUT_LVLED_ATTR_RW(5);
404
405static struct attribute *lm3533_attributes[] = {
406 &lm3533_dev_attr_boost_freq.dev_attr.attr,
407 &lm3533_dev_attr_boost_ovp.dev_attr.attr,
408 &lm3533_dev_attr_output_hvled1.dev_attr.attr,
409 &lm3533_dev_attr_output_hvled2.dev_attr.attr,
410 &lm3533_dev_attr_output_lvled1.dev_attr.attr,
411 &lm3533_dev_attr_output_lvled2.dev_attr.attr,
412 &lm3533_dev_attr_output_lvled3.dev_attr.attr,
413 &lm3533_dev_attr_output_lvled4.dev_attr.attr,
414 &lm3533_dev_attr_output_lvled5.dev_attr.attr,
415 NULL,
416};
417
418#define to_dev_attr(_attr) \
419 container_of(_attr, struct device_attribute, attr)
420
421static mode_t lm3533_attr_is_visible(struct kobject *kobj,
422 struct attribute *attr, int n)
423{
424 struct device *dev = container_of(kobj, struct device, kobj);
425 struct lm3533 *lm3533 = dev_get_drvdata(dev);
426 struct device_attribute *dattr = to_dev_attr(attr);
427 struct lm3533_device_attribute *lattr = to_lm3533_dev_attr(dattr);
428 enum lm3533_attribute_type type = lattr->type;
429 mode_t mode = attr->mode;
430
431 if (!lm3533->have_backlights && type == LM3533_ATTR_TYPE_BACKLIGHT)
432 mode = 0;
433 else if (!lm3533->have_leds && type == LM3533_ATTR_TYPE_LED)
434 mode = 0;
435
436 return mode;
437};
438
439static struct attribute_group lm3533_attribute_group = {
440 .is_visible = lm3533_attr_is_visible,
441 .attrs = lm3533_attributes
442};
443
444static int __devinit lm3533_device_als_init(struct lm3533 *lm3533)
445{
446 struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
447 int ret;
448
449 if (!pdata->als)
450 return 0;
451
452 lm3533_als_devs[0].platform_data = pdata->als;
453 lm3533_als_devs[0].pdata_size = sizeof(*pdata->als);
454
455 ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL, 0);
456 if (ret) {
457 dev_err(lm3533->dev, "failed to add ALS device\n");
458 return ret;
459 }
460
461 lm3533->have_als = 1;
462
463 return 0;
464}
465
466static int __devinit lm3533_device_bl_init(struct lm3533 *lm3533)
467{
468 struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
469 int i;
470 int ret;
471
472 if (!pdata->backlights || pdata->num_backlights == 0)
473 return 0;
474
475 if (pdata->num_backlights > ARRAY_SIZE(lm3533_bl_devs))
476 pdata->num_backlights = ARRAY_SIZE(lm3533_bl_devs);
477
478 for (i = 0; i < pdata->num_backlights; ++i) {
479 lm3533_bl_devs[i].platform_data = &pdata->backlights[i];
480 lm3533_bl_devs[i].pdata_size = sizeof(pdata->backlights[i]);
481 }
482
483 ret = mfd_add_devices(lm3533->dev, 0, lm3533_bl_devs,
484 pdata->num_backlights, NULL, 0);
485 if (ret) {
486 dev_err(lm3533->dev, "failed to add backlight devices\n");
487 return ret;
488 }
489
490 lm3533->have_backlights = 1;
491
492 return 0;
493}
494
495static int __devinit lm3533_device_led_init(struct lm3533 *lm3533)
496{
497 struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
498 int i;
499 int ret;
500
501 if (!pdata->leds || pdata->num_leds == 0)
502 return 0;
503
504 if (pdata->num_leds > ARRAY_SIZE(lm3533_led_devs))
505 pdata->num_leds = ARRAY_SIZE(lm3533_led_devs);
506
507 for (i = 0; i < pdata->num_leds; ++i) {
508 lm3533_led_devs[i].platform_data = &pdata->leds[i];
509 lm3533_led_devs[i].pdata_size = sizeof(pdata->leds[i]);
510 }
511
512 ret = mfd_add_devices(lm3533->dev, 0, lm3533_led_devs,
513 pdata->num_leds, NULL, 0);
514 if (ret) {
515 dev_err(lm3533->dev, "failed to add LED devices\n");
516 return ret;
517 }
518
519 lm3533->have_leds = 1;
520
521 return 0;
522}
523
524static int __devinit lm3533_device_init(struct lm3533 *lm3533)
525{
526 struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
527 int ret;
528
529 dev_dbg(lm3533->dev, "%s\n", __func__);
530
531 if (!pdata) {
532 dev_err(lm3533->dev, "no platform data\n");
533 return -EINVAL;
534 }
535
536 lm3533->gpio_hwen = pdata->gpio_hwen;
537
538 dev_set_drvdata(lm3533->dev, lm3533);
539
540 if (gpio_is_valid(lm3533->gpio_hwen)) {
541 ret = gpio_request_one(lm3533->gpio_hwen, GPIOF_OUT_INIT_LOW,
542 "lm3533-hwen");
543 if (ret < 0) {
544 dev_err(lm3533->dev,
545 "failed to request HWEN GPIO %d\n",
546 lm3533->gpio_hwen);
547 return ret;
548 }
549 }
550
551 lm3533_enable(lm3533);
552
553 lm3533_device_als_init(lm3533);
554 lm3533_device_bl_init(lm3533);
555 lm3533_device_led_init(lm3533);
556
557 ret = sysfs_create_group(&lm3533->dev->kobj, &lm3533_attribute_group);
558 if (ret < 0) {
559 dev_err(lm3533->dev, "failed to create sysfs attributes\n");
560 goto err_unregister;
561 }
562
563 return 0;
564
565err_unregister:
566 mfd_remove_devices(lm3533->dev);
567 lm3533_disable(lm3533);
568 if (gpio_is_valid(lm3533->gpio_hwen))
569 gpio_free(lm3533->gpio_hwen);
570
571 return ret;
572}
573
574static void __devexit lm3533_device_exit(struct lm3533 *lm3533)
575{
576 dev_dbg(lm3533->dev, "%s\n", __func__);
577
578 sysfs_remove_group(&lm3533->dev->kobj, &lm3533_attribute_group);
579
580 mfd_remove_devices(lm3533->dev);
581 lm3533_disable(lm3533);
582 if (gpio_is_valid(lm3533->gpio_hwen))
583 gpio_free(lm3533->gpio_hwen);
584}
585
586static bool lm3533_readable_register(struct device *dev, unsigned int reg)
587{
588 switch (reg) {
589 case 0x10 ... 0x2c:
590 case 0x30 ... 0x38:
591 case 0x40 ... 0x45:
592 case 0x50 ... 0x57:
593 case 0x60 ... 0x6e:
594 case 0x70 ... 0x75:
595 case 0x80 ... 0x85:
596 case 0x90 ... 0x95:
597 case 0xa0 ... 0xa5:
598 case 0xb0 ... 0xb2:
599 return true;
600 default:
601 return false;
602 }
603}
604
605static bool lm3533_volatile_register(struct device *dev, unsigned int reg)
606{
607 switch (reg) {
608 case 0x34: /* zone */
609 case 0x37 ... 0x38: /* adc */
610 case 0xb0 ... 0xb1: /* fault */
611 return true;
612 default:
613 return false;
614 }
615}
616
617static bool lm3533_precious_register(struct device *dev, unsigned int reg)
618{
619 switch (reg) {
620 case 0x34: /* zone */
621 return true;
622 default:
623 return false;
624 }
625}
626
627static struct regmap_config regmap_config = {
628 .reg_bits = 8,
629 .val_bits = 8,
630 .max_register = LM3533_REG_MAX,
631 .readable_reg = lm3533_readable_register,
632 .volatile_reg = lm3533_volatile_register,
633 .precious_reg = lm3533_precious_register,
634};
635
636static int __devinit lm3533_i2c_probe(struct i2c_client *i2c,
637 const struct i2c_device_id *id)
638{
639 struct lm3533 *lm3533;
640 int ret;
641
642 dev_dbg(&i2c->dev, "%s\n", __func__);
643
644 lm3533 = kzalloc(sizeof(*lm3533), GFP_KERNEL);
645 if (!lm3533)
646 return -ENOMEM;
647
648 i2c_set_clientdata(i2c, lm3533);
649
650 lm3533->regmap = regmap_init_i2c(i2c, &regmap_config);
651 if (IS_ERR(lm3533->regmap)) {
652 ret = PTR_ERR(lm3533->regmap);
653 goto err_regmap;
654 }
655
656 lm3533->dev = &i2c->dev;
657 lm3533->irq = i2c->irq;
658
659 ret = lm3533_device_init(lm3533);
660 if (ret)
661 goto err_dev;
662
663 return 0;
664
665err_dev:
666 regmap_exit(lm3533->regmap);
667err_regmap:
668 kfree(lm3533);
669
670 return ret;
671}
672
673static int __devexit lm3533_i2c_remove(struct i2c_client *i2c)
674{
675 struct lm3533 *lm3533 = i2c_get_clientdata(i2c);
676
677 dev_dbg(&i2c->dev, "%s\n", __func__);
678
679 lm3533_device_exit(lm3533);
680 regmap_exit(lm3533->regmap);
681
682 kfree(lm3533);
683
684 return 0;
685}
686
687static const struct i2c_device_id lm3533_i2c_ids[] = {
688 { "lm3533", 0 },
689 { },
690};
691MODULE_DEVICE_TABLE(i2c, lm3533_i2c_ids);
692
693static struct i2c_driver lm3533_i2c_driver = {
694 .driver = {
695 .name = "lm3533",
696 .owner = THIS_MODULE,
697 },
698 .id_table = lm3533_i2c_ids,
699 .probe = lm3533_i2c_probe,
700 .remove = __devexit_p(lm3533_i2c_remove),
701};
702
703static int __init lm3533_i2c_init(void)
704{
705 return i2c_add_driver(&lm3533_i2c_driver);
706}
707subsys_initcall(lm3533_i2c_init);
708
709static void __exit lm3533_i2c_exit(void)
710{
711 i2c_del_driver(&lm3533_i2c_driver);
712}
713module_exit(lm3533_i2c_exit);
714
715MODULE_AUTHOR("Johan Hovold <jhovold@gmail.com>");
716MODULE_DESCRIPTION("LM3533 Core");
717MODULE_LICENSE("GPL");
This page took 0.054301 seconds and 5 git commands to generate.