power: use orderly shutdown
[GitHub/moto-9609/android_kernel_motorola_exynos9610.git] / drivers / leds / leds-s2mu106.c
1 /*
2 * leds-s2mu106.c - LED class driver for S2MU106 FLASH LEDs.
3 *
4 * Copyright (C) 2018 Samsung Electronics
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 */
11
12 #include <linux/kernel.h>
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/err.h>
16 #include <linux/slab.h>
17 #include <linux/workqueue.h>
18 #include <linux/gpio.h>
19 #include <linux/of_gpio.h>
20 #include <linux/mfd/samsung/s2mu106.h>
21 #include <linux/leds-s2mu106.h>
22 #include <linux/platform_device.h>
23
24 struct s2mu106_fled_data *g_fled_data;
25
26 static char *s2mu106_fled_mode_string[] = {
27 "OFF",
28 "TORCH",
29 "FLASH",
30 };
31
32 static char *s2mu106_fled_operating_mode_string[] = {
33 "AUTO",
34 "BOOST",
35 "TA",
36 "SYS",
37 };
38
39 /* IC current limit */
40 static int s2mu106_fled_torch_curr_max[] = {
41 0, 320, 320, 320
42 };
43
44 /* IC current limit */
45 static int s2mu106_fled_flash_curr_max[] = {
46 0, 1600, 1600, 500
47 };
48
49 #if DEBUG_TEST_READ
50 static void s2mu106_fled_test_read(struct s2mu106_fled_data *fled)
51 {
52 u8 data;
53 char str[1016] = {0,};
54 int i;
55 struct i2c_client *i2c = fled->i2c;
56
57 for (i = 0x0B; i <= 0x0C; i++) {
58 s2mu106_read_reg(i2c, i, &data);
59 sprintf(str+strlen(str), "0x%02x:0x%02x, ", i, data);
60 }
61 for (i = 0x14; i <= 0x15; i++) {
62 s2mu106_read_reg(i2c, i, &data);
63 sprintf(str+strlen(str), "0x%02x:0x%02x, ", i, data);
64 }
65
66 for (i = 0x53; i <= 0x5A; i++) {
67 s2mu106_read_reg(i2c, i, &data);
68 sprintf(str+strlen(str), "0x%02x:0x%02x, ", i, data);
69 }
70
71 s2mu106_read_reg(i2c, 0x5B, &data);
72 pr_err("%s: %s0x5B:0x%02x\n", __func__, str, data);
73
74 memset(str,0,strlen(str));
75
76 for (i = 0x5C; i <= 0x62; i++) {
77 s2mu106_read_reg(i2c, i, &data);
78 sprintf(str+strlen(str), "0x%02x:0x%02x, ", i, data);
79 }
80
81 s2mu106_read_reg(i2c, 0x63, &data);
82 pr_err("%s: %s0x63:0x%02x\n", __func__, str, data);
83 }
84 #endif
85
86 static int s2mu106_fled_get_flash_curr(struct s2mu106_fled_data *fled, int chan)
87 {
88 int curr = -1;
89 u8 data;
90 u8 dest;
91
92 if ((chan < 1) || (chan > S2MU106_CH_MAX)) {
93 pr_info("%s: Wrong channel!!\n", __func__);
94 return -1;
95 }
96
97 switch(chan) {
98 case 1:
99 dest = S2MU106_FLED_CH1_CTRL0;
100 break;
101 case 2:
102 dest = S2MU106_FLED_CH2_CTRL0;
103 break;
104 case 3:
105 dest = S2MU106_FLED_CH3_CTRL0;
106 break;
107 default:
108 return curr;
109 break;
110 }
111
112 s2mu106_read_reg(fled->i2c, dest, &data);
113
114 data = data & S2MU106_CHX_FLASH_IOUT;
115 curr = (data * 50) + 50;
116
117 pr_info("%s: CH%02d flash curr. = %dmA\n", __func__,
118 chan, curr);
119
120 return curr;
121 }
122
123 static int s2mu106_fled_set_flash_curr(struct s2mu106_fled_data *fled,
124 int chan, int curr)
125 {
126 int ret = -1;
127 u8 data;
128 u8 dest;
129 int curr_set;
130
131 if ((chan < 1) || (chan > S2MU106_CH_MAX)) {
132 pr_info("%s: Wrong channel!!\n", __func__);
133 return -1;
134 }
135
136 switch(chan) {
137 case 1:
138 dest = S2MU106_FLED_CH1_CTRL0;
139 break;
140 case 2:
141 dest = S2MU106_FLED_CH2_CTRL0;
142 break;
143 case 3:
144 dest = S2MU106_FLED_CH3_CTRL0;
145 break;
146 default:
147 return ret;
148 break;
149 }
150
151 if (curr < 50)
152 curr = 50;
153 else if (curr > s2mu106_fled_flash_curr_max[chan])
154 curr = s2mu106_fled_flash_curr_max[chan];
155
156 data = (curr - 50)/50;
157
158 s2mu106_update_reg(fled->i2c, dest, data, S2MU106_CHX_FLASH_IOUT);
159
160 curr_set = s2mu106_fled_get_flash_curr(fled, chan);
161
162 pr_info("%s: curr: %d, curr_set: %d\n", __func__,
163 curr, curr_set);
164
165 return ret;
166 }
167
168 static int s2mu106_fled_get_torch_curr(struct s2mu106_fled_data *fled,
169 int chan)
170 {
171 int curr = -1;
172 u8 data;
173 u8 dest;
174
175 if ((chan < 1) || (chan > S2MU106_CH_MAX)) {
176 pr_info("%s: Wrong channel!!\n", __func__);
177 return -1;
178 }
179
180 switch(chan) {
181 case 1:
182 dest = S2MU106_FLED_CH1_CTRL1;
183 break;
184 case 2:
185 dest = S2MU106_FLED_CH2_CTRL1;
186 break;
187 case 3:
188 dest = S2MU106_FLED_CH3_CTRL1;
189 break;
190 default:
191 return curr;
192 break;
193 }
194
195 s2mu106_read_reg(fled->i2c, dest, &data);
196
197 data = data & S2MU106_CHX_TORCH_IOUT;
198 curr = data * 10 + 10;
199
200 pr_info("%s: CH%02d torch curr. = %dmA\n", __func__,
201 chan, curr);
202
203 return curr;
204 }
205
206 static int s2mu106_fled_set_torch_curr(struct s2mu106_fled_data *fled,
207 int chan, int curr)
208 {
209 int ret = -1;
210 u8 data;
211 u8 dest;
212 int curr_set;
213
214 if ((chan < 1) || (chan > S2MU106_CH_MAX)) {
215 pr_info("%s: Wrong channel!!\n", __func__);
216 return -1;
217 }
218
219 switch(chan) {
220 case 1:
221 dest = S2MU106_FLED_CH1_CTRL1;
222 break;
223 case 2:
224 dest = S2MU106_FLED_CH2_CTRL1;
225 break;
226 case 3:
227 dest = S2MU106_FLED_CH3_CTRL1;
228 break;
229 default:
230 return ret;
231 break;
232 }
233
234 if (curr < 10)
235 curr = 10;
236 else if (curr > s2mu106_fled_torch_curr_max[chan])
237 curr = s2mu106_fled_torch_curr_max[chan];
238
239 data = (curr - 10)/10;
240
241 s2mu106_update_reg(fled->i2c, dest, data, S2MU106_CHX_TORCH_IOUT);
242
243 curr_set = s2mu106_fled_get_torch_curr(fled, chan);
244
245 pr_info("%s: curr: %d, curr_set: %d\n", __func__,
246 curr, curr_set);
247
248 ret = 0;
249
250 return ret;
251
252 }
253
254 static void s2mu106_fled_operating_mode(struct s2mu106_fled_data *fled,
255 int mode)
256 {
257 u8 value;
258
259 if (mode < 0 || mode > 3) {
260 pr_info ("%s, wrong mode\n", __func__);
261 mode = AUTO_MODE;
262 }
263
264 pr_info ("%s = %s\n", __func__,
265 s2mu106_fled_operating_mode_string[mode]);
266
267 value = mode << 6;
268 s2mu106_update_reg(fled->i2c, S2MU106_FLED_CTRL0, value, 0xC0);
269 }
270
271 static int s2mu106_fled_get_mode(struct s2mu106_fled_data *fled, int chan)
272 {
273 u8 status;
274 int ret = -1;
275
276 s2mu106_read_reg(fled->i2c, S2MU106_FLED_STATUS1, &status);
277
278 pr_info("%s: S2MU106_FLED_STATUS1: 0x%02x\n", __func__, status);
279
280 if ((chan < 1) || (chan > S2MU106_CH_MAX)) {
281 pr_info("%s: Wrong channel!!\n", __func__);
282 return -1;
283 }
284
285 switch(chan) {
286 case 1:
287 if (status & S2MU106_CH1_FLASH_ON)
288 ret = S2MU106_FLED_MODE_FLASH;
289 else if (status & S2MU106_CH1_TORCH_ON)
290 ret = S2MU106_FLED_MODE_TORCH;
291 else
292 ret = S2MU106_FLED_MODE_OFF;
293 break;
294 case 2:
295 if (status & S2MU106_CH2_FLASH_ON)
296 ret = S2MU106_FLED_MODE_FLASH;
297 else if (status & S2MU106_CH2_TORCH_ON)
298 ret = S2MU106_FLED_MODE_TORCH;
299 else
300 ret = S2MU106_FLED_MODE_OFF;
301 break;
302 case 3:
303 if (status & S2MU106_CH3_FLASH_ON)
304 ret = S2MU106_FLED_MODE_FLASH;
305 else if (status & S2MU106_CH3_TORCH_ON)
306 ret = S2MU106_FLED_MODE_TORCH;
307 else
308 ret = S2MU106_FLED_MODE_OFF;
309 break;
310 default:
311 break;
312 }
313 return ret;
314 }
315
316 static int s2mu106_fled_set_mode(struct s2mu106_fled_data *fled,
317 int chan, int mode)
318 {
319 u8 dest = 0, bit = 0, mask = 0, status = 0;
320
321 if ((chan <= 0) || (chan > S2MU106_CH_MAX) ||
322 (mode < 0) || (mode > S2MU106_FLED_MODE_MAX)) {
323 pr_err("%s: Wrong channel or mode.\n", __func__);
324 return -EFAULT;
325 }
326
327 pr_err("%s: channel: %d, mode: %d\n", __func__, chan, mode);
328
329 /* 0b000: OFF, 0b101: i2c bit control(on) */
330 switch(mode) {
331 case S2MU106_FLED_MODE_OFF:
332 mask = S2MU106_CHX_FLASH_FLED_EN |
333 S2MU106_CHX_TORCH_FLED_EN;
334 bit = 0;
335 break;
336 case S2MU106_FLED_MODE_FLASH:
337 mask = S2MU106_CHX_FLASH_FLED_EN;
338 bit = S2MU106_FLED_EN << 3;
339 break;
340 case S2MU106_FLED_MODE_TORCH:
341 s2mu106_fled_operating_mode(fled, SYS_MODE);
342 mask = S2MU106_CHX_TORCH_FLED_EN;
343 bit = S2MU106_FLED_EN;
344 break;
345 default:
346 return -EFAULT;
347 break;
348 }
349
350 switch(chan) {
351 case 1:
352 dest = S2MU106_FLED_CTRL1;
353 break;
354 case 2:
355 dest = S2MU106_FLED_CTRL2;
356 break;
357 case 3:
358 dest = S2MU106_FLED_CTRL3;
359 break;
360 default:
361 return -EFAULT;
362 break;
363 }
364
365 /* Need to set EN_FLED_PRE bit before mode change */
366 if (mode != S2MU106_FLED_MODE_OFF)
367 s2mu106_update_reg(fled->i2c, S2MU106_FLED_CTRL0,
368 S2MU106_EN_FLED_PRE, S2MU106_EN_FLED_PRE);
369 else {
370 /* If no LED is on, clear EN_FLED_PRE */
371 s2mu106_read_reg(fled->i2c, S2MU106_FLED_STATUS1, &status);
372 if (!(status & S2MU106_FLED_ON_CHECK))
373 s2mu106_update_reg(fled->i2c, S2MU106_FLED_CTRL0,
374 0, S2MU106_EN_FLED_PRE);
375 }
376 s2mu106_update_reg(fled->i2c, dest, bit, mask);
377
378 if (mode == S2MU106_FLED_MODE_OFF)
379 s2mu106_fled_operating_mode(fled, AUTO_MODE);
380
381 return 0;
382 }
383
384 int s2mu106_mode_change_cam_to_leds(enum cam_flash_mode cam_mode)
385 {
386 int mode = -1;
387
388 switch(cam_mode) {
389 case CAM_FLASH_MODE_OFF:
390 mode = S2MU106_FLED_MODE_OFF;
391 break;
392 case CAM_FLASH_MODE_SINGLE:
393 mode = S2MU106_FLED_MODE_FLASH;
394 break;
395 case CAM_FLASH_MODE_TORCH:
396 mode = S2MU106_FLED_MODE_TORCH;
397 break;
398 default:
399 mode = S2MU106_FLED_MODE_OFF;
400 break;
401 }
402
403 return mode;
404 }
405
406 int s2mu106_fled_set_mode_ctrl(int chan, enum cam_flash_mode cam_mode)
407 {
408 struct s2mu106_fled_data *fled = g_fled_data;
409 int mode = -1;
410
411 mode = s2mu106_mode_change_cam_to_leds(cam_mode);
412
413 if ((chan <= 0) || (chan > S2MU106_CH_MAX) ||
414 (mode < 0) || (mode >= S2MU106_FLED_MODE_MAX)) {
415 pr_err("%s: channel: %d, mode: %d\n", __func__, chan, mode);
416 pr_err("%s: Wrong channel or mode.\n", __func__);
417 return -1;
418 }
419
420 s2mu106_fled_set_mode(fled, chan, mode);
421 #if DEBUG_TEST_READ
422 s2mu106_fled_test_read(fled);
423 #endif
424
425 return 0;
426 }
427
428 int s2mu106_fled_set_curr(int chan, enum cam_flash_mode cam_mode, int curr)
429 {
430 struct s2mu106_fled_data *fled = g_fled_data;
431 int mode = -1;
432
433 mode = s2mu106_mode_change_cam_to_leds(cam_mode);
434
435 /* Check channel */
436 if ((chan <= 0) || (chan > S2MU106_CH_MAX)) {
437 pr_err("%s: Wrong channel.\n", __func__);
438 return -EFAULT;
439 }
440
441 switch (mode){
442 case S2MU106_FLED_MODE_TORCH:
443 /* Set curr. */
444 s2mu106_fled_set_torch_curr(fled, chan, curr);
445 break;
446 case S2MU106_FLED_MODE_FLASH:
447 /* Set curr. */
448 s2mu106_fled_set_flash_curr(fled, chan, curr);
449 break;
450 default:
451 return -1;
452 }
453 /* Test read */
454 #if DEBUG_TEST_READ
455 s2mu106_fled_test_read(fled);
456 #endif
457
458 return 0;
459 }
460
461 int s2mu106_fled_get_curr(int chan, enum cam_flash_mode cam_mode)
462 {
463 struct s2mu106_fled_data *fled = g_fled_data;
464 int mode = -1;
465 int curr = 0;
466
467 mode = s2mu106_mode_change_cam_to_leds(cam_mode);
468
469 /* Check channel */
470 if ((chan <= 0) || (chan > S2MU106_CH_MAX)) {
471 pr_err("%s: Wrong channel.\n", __func__);
472 return -EFAULT;
473 }
474
475 switch (mode){
476 case S2MU106_FLED_MODE_TORCH:
477 curr = s2mu106_fled_get_torch_curr(fled, chan);
478 break;
479 case S2MU106_FLED_MODE_FLASH:
480 curr = s2mu106_fled_get_flash_curr(fled, chan);
481 break;
482 default:
483 return -1;
484 }
485 /* Test read */
486 #if DEBUG_TEST_READ
487 s2mu106_fled_test_read(fled);
488 #endif
489
490 return curr;
491 }
492
493 static ssize_t fled_flash_curr_show(struct device *dev,
494 struct device_attribute *attr, char *buf)
495 {
496 struct led_classdev *led_cdev = dev_get_drvdata(dev);
497 struct s2mu106_fled_data *fled =
498 container_of(led_cdev, struct s2mu106_fled_data, cdev);
499 int cnt = 0;
500 int curr = 0;
501 int i;
502 char str[1016] = {0,};
503
504 /* Read curr. */
505 for (i = 1; i <= S2MU106_CH_MAX; i++) {
506 curr = s2mu106_fled_get_flash_curr(fled, i);
507 pr_info("%s: channel: %d, curr: %dmA\n", __func__, i, curr);
508 if (curr >= 0)
509 cnt += sprintf(str+strlen(str), "CH%02d: %dmA, ", i, curr);
510 }
511
512 cnt += sprintf(str+strlen(str), "\n");
513
514 strcpy(buf, str);
515
516 return cnt;
517 }
518
519 static ssize_t fled_flash_curr_store(struct device *dev,
520 struct device_attribute *attr, const char *buf, size_t size)
521 {
522 struct led_classdev *led_cdev = dev_get_drvdata(dev);
523 struct s2mu106_fled_data *fled =
524 container_of(led_cdev, struct s2mu106_fled_data, cdev);
525 int chan = -1;
526 int curr = -1;
527
528 sscanf(buf, "%d %d", &chan, &curr);
529
530 /* Check channel */
531 if ((chan <= 0) || (chan > S2MU106_CH_MAX)) {
532 pr_err("%s: Wrong channel.\n", __func__);
533 return -EFAULT;
534 }
535
536 /* Set curr. */
537 s2mu106_fled_set_flash_curr(fled, chan, curr);
538
539 /* Test read */
540 #if DEBUG_TEST_READ
541 s2mu106_fled_test_read(fled);
542 #endif
543
544 return size;
545 }
546
547
548 static ssize_t fled_torch_curr_show(struct device *dev,
549 struct device_attribute *attr, char *buf)
550 {
551 struct led_classdev *led_cdev = dev_get_drvdata(dev);
552 struct s2mu106_fled_data *fled =
553 container_of(led_cdev, struct s2mu106_fled_data, cdev);
554 int cnt = 0;
555 int curr = 0;
556 int i;
557 char str[1016] = {0,};
558
559 /* Read curr. */
560 for (i = 1; i <= S2MU106_CH_MAX; i++) {
561 curr = s2mu106_fled_get_torch_curr(fled, i);
562 pr_info("%s: channel: %d, curr: %dmA\n", __func__, i, curr);
563 if (curr >= 0)
564 cnt += sprintf(str+strlen(str), "CH%02d: %dmA, ", i, curr);
565 }
566
567 cnt += sprintf(str+strlen(str), "\n");
568
569 strcpy(buf, str);
570
571 return cnt;
572 }
573
574 static ssize_t fled_torch_curr_store(struct device *dev,
575 struct device_attribute *attr, const char *buf, size_t size)
576 {
577 struct led_classdev *led_cdev = dev_get_drvdata(dev);
578 struct s2mu106_fled_data *fled =
579 container_of(led_cdev, struct s2mu106_fled_data, cdev);
580 int chan = -1;
581 int curr = -1;
582
583 sscanf(buf, "%d %d", &chan, &curr);
584
585 /* Check channel */
586 if ((chan <= 0) || (chan > S2MU106_CH_MAX)) {
587 pr_err("%s: Wrong channel.\n", __func__);
588 return -EFAULT;
589 }
590
591 /* Set curr. */
592 s2mu106_fled_set_torch_curr(fled, chan, curr);
593
594 /* Test read */
595 #if DEBUG_TEST_READ
596 s2mu106_fled_test_read(fled);
597 #endif
598
599 return size;
600 }
601
602 static ssize_t fled_mode_show(struct device *dev,
603 struct device_attribute *attr, char *buf)
604 {
605 struct led_classdev *led_cdev = dev_get_drvdata(dev);
606 struct s2mu106_fled_data *fled =
607 container_of(led_cdev, struct s2mu106_fled_data, cdev);
608 int cnt = 0;
609 int mode = 0;
610 int i;
611 char str[1016] = {0,};
612
613 #if DEBUG_TEST_READ
614 s2mu106_fled_test_read(fled);
615 #endif
616
617 for (i = 1; i <= S2MU106_CH_MAX; i++) {
618 mode = s2mu106_fled_get_mode(fled, i);
619 if (mode >= 0)
620 cnt += sprintf(str+strlen(str), "CH%02d: %s, ", i,
621 s2mu106_fled_mode_string[mode]);
622 }
623
624 cnt += sprintf(str+strlen(str), "\n");
625
626 strcpy(buf, str);
627
628 return cnt;
629 }
630
631 static ssize_t fled_mode_store(struct device *dev,
632 struct device_attribute *attr, const char *buf, size_t size)
633 {
634 struct led_classdev *led_cdev = dev_get_drvdata(dev);
635 struct s2mu106_fled_data *fled =
636 container_of(led_cdev, struct s2mu106_fled_data, cdev);
637 int chan = -1;
638 int mode = -1;
639
640 sscanf(buf, "%d %d", &chan, &mode);
641
642 if ((chan <= 0) || (chan > S2MU106_CH_MAX) ||
643 (mode < 0) || (mode >= S2MU106_FLED_MODE_MAX)) {
644 pr_err("%s: channel: %d, mode: %d\n", __func__, chan, mode);
645 pr_err("%s: Wrong channel or mode.\n", __func__);
646 return -EFAULT;
647 }
648
649 s2mu106_fled_set_mode(fled, chan, mode);
650 #if DEBUG_TEST_READ
651 s2mu106_fled_test_read(fled);
652 #endif
653
654 return size;
655 }
656
657 static DEVICE_ATTR(fled_mode, 0644, fled_mode_show, fled_mode_store);
658 static DEVICE_ATTR(fled_flash_curr, 0644, fled_flash_curr_show, fled_flash_curr_store);
659 static DEVICE_ATTR(fled_torch_curr, 0644, fled_torch_curr_show, fled_torch_curr_store);
660
661 static struct attribute *s2mu106_fled_attrs[] = {
662 &dev_attr_fled_mode.attr,
663 &dev_attr_fled_flash_curr.attr,
664 &dev_attr_fled_torch_curr.attr,
665 NULL
666 };
667 ATTRIBUTE_GROUPS(s2mu106_fled);
668
669 static void s2mu106_fled_init(struct s2mu106_fled_data *fled)
670 {
671 int i;
672 struct i2c_client *i2c = fled->i2c;
673 u8 data;
674
675 pr_info("%s: s2mu106_fled init start\n", __func__);
676
677 for (i = 1; i <= S2MU106_CH_MAX; i++) {
678 s2mu106_fled_set_flash_curr(fled, i, fled->pdata->default_current);
679 s2mu106_fled_set_torch_curr(fled, i, fled->pdata->default_current);
680 }
681 s2mu106_write_reg(i2c, 0xDF, 0x28);
682
683 s2mu106_read_reg(i2c, S2MU106_FLED_PMIC_ID, &data);
684 fled->rev_id = data & S2MU106_FLED_REV_NO;
685 pr_info("%s: PMIC_ID = 0x%02x, Rev. No. = %d\n", __func__,
686 data, fled->rev_id);
687
688 if (fled->rev_id >= 1) {
689 /* Set Auto source change for flash mode boosting
690 * VBUS_DET(0x66[5] = 1), T_VBUS_DET_MASK_B(0x67[6] = 1)
691 */
692 s2mu106_update_reg(i2c, 0x66, 1 << 5, 1 << 5);
693 s2mu106_update_reg(i2c, 0x67, 1 << 6, 1 << 6);
694 }
695
696 #if DEBUG_TEST_READ
697 s2mu106_fled_test_read(fled);
698 #endif
699 }
700
701 #if defined(CONFIG_OF)
702 static int s2mu106_led_dt_parse_pdata(struct device *dev,
703 struct s2mu106_fled_platform_data *pdata)
704 {
705 struct device_node *led_np, *np, *c_np;
706 int ret;
707 u32 temp;
708 u32 index;
709
710 led_np = dev->parent->of_node;
711
712 if (!led_np) {
713 pr_err("<%s> could not find led sub-node led_np\n", __func__);
714 return -ENODEV;
715 }
716
717 np = of_find_node_by_name(led_np, "flash_led");
718 if (!np) {
719 pr_err("%s : could not find led sub-node np\n", __func__);
720 return -EINVAL;
721 }
722
723 ret = of_property_read_u32(np, "default_current",
724 &pdata->default_current);
725 if (ret < 0)
726 pr_err("%s : could not find default_current\n", __func__);
727
728 ret = of_property_read_u32(np, "max_current",
729 &pdata->max_current);
730 if (ret < 0)
731 pr_err("%s : could not find max_current\n", __func__);
732
733 ret = of_property_read_u32(np, "default_timer",
734 &pdata->default_timer);
735 if (ret < 0)
736 pr_err("%s : could not find default_timer\n", __func__);
737
738
739 #if FLED_EN
740 ret = pdata->fled-en1-pin = of_get_named_gpio(np, "fled-en1-gpio", 0);
741 if (ret < 0) {
742 pr_err("%s : can't get fled-en1-pin\n", __func__);
743 return ret;
744 }
745
746 ret = pdata->fled-en2-pin = of_get_named_gpio(np, "fled-en2-gpio", 0);
747 if (ret < 0) {
748 pr_err("%s : can't get fled-en2-pin\n", __func__);
749 return ret;
750 }
751
752 ret = pdata->fled-en3-pin = of_get_named_gpio(np, "fled-en3-gpio", 0);
753 if (ret < 0) {
754 pr_err("%s : can't get fled-en3-pin\n", __func__);
755 return ret;
756 }
757
758 ret = pdata->fled-en4-pin = of_get_named_gpio(np, "fled-en4-gpio", 0);
759 if (ret < 0) {
760 pr_err("%s : can't get fled-en4-pin\n", __func__);
761 return ret;
762 }
763 #endif
764
765 pdata->chan_num = of_get_child_count(np);
766
767 if (pdata->chan_num > S2MU106_CH_MAX)
768 pdata->chan_num = S2MU106_CH_MAX;
769
770 pdata->channel = devm_kzalloc(dev,
771 sizeof(struct s2mu106_fled_chan) * pdata->chan_num, GFP_KERNEL);
772
773 for_each_child_of_node(np, c_np) {
774 ret = of_property_read_u32(c_np, "id", &temp);
775 if (ret < 0)
776 goto dt_err;
777 index = temp;
778
779 pr_info("%s: temp = %d, index = %d\n",
780 __func__, temp, index);
781
782 if (index < S2MU106_CH_MAX) {
783 pdata->channel[index].id = index;
784
785 ret = of_property_read_u32_index(np, "current", index,
786 &pdata->channel[index].curr);
787 if (ret < 0) {
788 pr_err("%s : could not find current for channel%d\n",
789 __func__, pdata->channel[index].id);
790 pdata->channel[index].curr = pdata->default_current;
791 }
792
793 ret = of_property_read_u32_index(np, "timer", index,
794 &pdata->channel[index].timer);
795 if (ret < 0) {
796 pr_err("%s : could not find timer for channel%d\n",
797 __func__, pdata->channel[index].id);
798 pdata->channel[index].timer = pdata->default_timer;
799 }
800 }
801 }
802 return 0;
803 dt_err:
804 pr_err("%s: DT parsing finish. ret = %d\n", __func__, ret);
805 return ret;
806 }
807 #endif /* CONFIG_OF */
808
809 static int s2mu106_led_probe(struct platform_device *pdev)
810 {
811 int ret = 0;
812 struct s2mu106_dev *s2mu106 = dev_get_drvdata(pdev->dev.parent);
813 struct s2mu106_fled_data *fled_data;
814 char name[20];
815
816 pr_info("%s: s2mu106_fled start\n", __func__);
817
818 if (!s2mu106) {
819 dev_err(&pdev->dev, "drvdata->dev.parent not supplied\n");
820 return -ENODEV;
821 }
822
823 fled_data = devm_kzalloc(&pdev->dev,
824 sizeof(struct s2mu106_fled_data), GFP_KERNEL);
825 if (!fled_data) {
826 pr_err("%s: failed to allocate driver data\n", __func__);
827 return -ENOMEM;
828 }
829
830 fled_data->dev = &pdev->dev;
831 fled_data->i2c = s2mu106->i2c;
832 fled_data->pdata = devm_kzalloc(&pdev->dev,
833 sizeof(*(fled_data->pdata)), GFP_KERNEL);
834 if (!fled_data->pdata) {
835 pr_err("%s: failed to allocate platform data\n", __func__);
836 return -ENOMEM;
837 }
838
839 if (s2mu106->dev->of_node) {
840 ret = s2mu106_led_dt_parse_pdata(&pdev->dev, fled_data->pdata);
841 if (ret < 0) {
842 pr_err("%s: not found leds dt! ret=%d\n",
843 __func__, ret);
844 return -1;
845 }
846 }
847
848 platform_set_drvdata(pdev, fled_data);
849
850 s2mu106_fled_init(fled_data);
851
852 /* Store fled_data for EXPORT_SYMBOL */
853 g_fled_data = fled_data;
854
855 snprintf(name, sizeof(name), "fled-s2mu106");
856 fled_data->cdev.name = name;
857 fled_data->cdev.groups = s2mu106_fled_groups;
858
859 ret = devm_led_classdev_register(&pdev->dev, &fled_data->cdev);
860 if (ret < 0) {
861 pr_err("%s: unable to register LED class dev\n", __func__);
862 return ret;
863 }
864
865 pr_info("%s: s2mu106_fled loaded\n", __func__);
866 return 0;
867 }
868
869 static int s2mu106_led_remove(struct platform_device *pdev)
870 {
871 return 0;
872 }
873
874 static void s2mu106_led_shutdown(struct platform_device *pdev)
875 {
876 struct s2mu106_fled_data *fled_data =
877 platform_get_drvdata(pdev);
878 int chan;
879
880 if (!fled_data->i2c) {
881 pr_err("%s: no i2c client\n", __func__);
882 return;
883 }
884
885 /* Turn off all leds when power off */
886 pr_info("%s: turn off all leds\n", __func__);
887 for (chan = 1; chan <= S2MU106_CH_MAX; chan++)
888 s2mu106_fled_set_mode(fled_data, chan, S2MU106_FLED_MODE_OFF);
889 }
890
891 static struct platform_driver s2mu106_led_driver = {
892 .driver = {
893 .name = "leds-s2mu106",
894 .owner = THIS_MODULE,
895 },
896 .probe = s2mu106_led_probe,
897 .remove = s2mu106_led_remove,
898 .shutdown = s2mu106_led_shutdown,
899 };
900
901 static int __init s2mu106_led_driver_init(void)
902 {
903 return platform_driver_register(&s2mu106_led_driver);
904 }
905 module_init(s2mu106_led_driver_init);
906
907 static void __exit s2mu106_led_driver_exit(void)
908 {
909 platform_driver_unregister(&s2mu106_led_driver);
910 }
911 module_exit(s2mu106_led_driver_exit);
912
913 MODULE_AUTHOR("Keunho Hwang <keunho.hwang@samsung.com>");
914 MODULE_DESCRIPTION("SAMSUNG s2mu106 flash LED Driver");
915 MODULE_LICENSE("GPL");