Update from product codes
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / battery / sm5701_charger.c
1 /*
2  *  SM5701_charger.c
3  *  SiliconMitus SM5701 Charger Driver
4  *
5  *  Copyright (C) 2014 SiliconMitus
6  *
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  */
18 #include <linux/module.h>
19 #include <linux/moduleparam.h>
20 #include <linux/bug.h>
21 #include <linux/delay.h>
22 #include <linux/err.h>
23 #include <linux/gpio.h>
24 #include <linux/slab.h>
25 #include <linux/platform_device.h>
26 #include <linux/i2c.h>
27 #include <linux/mfd/sm5701_core.h>
28 #include <linux/battery/sec_charger.h>
29 #include <linux/interrupt.h>
30 #include <linux/irq.h>
31
32 #include <linux/seq_file.h>
33 #include <linux/debugfs.h>
34 #include <linux/seq_file.h>
35
36 #include <linux/gpio-pxa.h>
37 #include <linux/of_device.h>
38 #include <linux/of_gpio.h>
39 #include <linux/of_irq.h>
40
41 extern int sec_chg_dt_init(struct device_node *np,
42                          struct device *dev,
43                          sec_battery_platform_data_t *pdata);
44 extern led_state_charger;
45
46 static enum power_supply_property sec_charger_props[] = {
47         POWER_SUPPLY_PROP_STATUS,
48         POWER_SUPPLY_PROP_CHARGE_TYPE,
49         POWER_SUPPLY_PROP_HEALTH,
50         POWER_SUPPLY_PROP_PRESENT,
51         POWER_SUPPLY_PROP_ONLINE,
52                 POWER_SUPPLY_PROP_VOLTAGE_MAX,
53         POWER_SUPPLY_PROP_CURRENT_MAX,
54         POWER_SUPPLY_PROP_CURRENT_AVG,
55         POWER_SUPPLY_PROP_CURRENT_NOW,
56 };
57
58 static void SM5701_charger_initialize(struct SM5701_charger_data *charger);
59
60 static int SM5701_get_battery_present(struct SM5701_charger_data *charger)
61 {
62         u8 data;
63
64         SM5701_reg_read(charger->SM5701->i2c, SM5701_STATUS1, &data);
65
66         pr_info("%s: SM5701_STATUS1 (0x%02x)\n", __func__, data);
67
68         data = ((data & SM5701_STATUS1_NOBAT) >> SM5701_STATUS1_NOBAT_SHIFT);
69
70         return !data;
71 }
72
73 static int SM5701_get_charging_status(struct SM5701_charger_data *charger)
74 {
75         int status = POWER_SUPPLY_STATUS_UNKNOWN;
76         int nCHG;
77         u8 stat2, chg_en, cln;
78
79         SM5701_reg_read(charger->SM5701->i2c, SM5701_STATUS2, &stat2);
80         pr_info("%s : SM5701_STATUS2 : 0x%02x\n", __func__, stat2);
81
82 //      Clear interrupt register 2
83         SM5701_reg_read(charger->SM5701->i2c, SM5701_INT2, &cln);
84
85         SM5701_reg_read(charger->SM5701->i2c, SM5701_CNTL, &chg_en);
86         chg_en &= SM5701_CNTL_OPERATIONMODE;
87
88         nCHG = gpio_get_value(charger->pdata->chg_gpio_en);
89
90         if((stat2 & SM5701_STATUS2_DONE) || (stat2 & SM5701_STATUS2_TOPOFF)) {
91                 status = POWER_SUPPLY_STATUS_FULL;
92                 charger->is_fullcharged = true;
93                 pr_info("%s : Status, Power Supply Full \n", __func__);
94         } else {
95                 if (nCHG)
96                         status = POWER_SUPPLY_STATUS_DISCHARGING;
97                 else
98                         status = POWER_SUPPLY_STATUS_CHARGING;
99         }
100
101         return (int)status;
102 }
103
104 static int SM5701_get_charging_health(struct SM5701_charger_data *charger)
105 {
106         static int health = POWER_SUPPLY_HEALTH_GOOD;
107         u8 stat1, cln;
108
109         SM5701_reg_read(charger->SM5701->i2c, SM5701_STATUS1, &stat1);
110
111         //      Clear interrupt register 1
112         SM5701_reg_read(charger->SM5701->i2c, SM5701_INT1, &cln);
113
114         pr_info("%s : Health, SM5701_STATUS1 : 0x%02x\n", __func__, stat1);
115
116         if (stat1 & SM5701_STATUS1_VBUSOVP) {
117                 health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
118         } else if (stat1 & SM5701_STATUS1_VBUSUVLO) {
119                 if (charger->cable_type != POWER_SUPPLY_TYPE_BATTERY) {
120                         health = POWER_SUPPLY_HEALTH_UNDERVOLTAGE;
121                 }
122         } else if (stat1 & SM5701_INT1_VBUSOK) {
123                 health = POWER_SUPPLY_HEALTH_GOOD;
124         }
125
126         return (int)health;
127 }
128
129 static u8 SM5701_set_batreg_voltage(
130                 struct SM5701_charger_data *charger, int batreg_voltage)
131 {
132         u8 data = 0;
133
134         SM5701_reg_read(charger->SM5701->i2c, SM5701_CHGCNTL3, &data);
135
136         data &= ~BATREG_MASK;
137
138         if (charger->dev_id < 3) {
139                 if ((batreg_voltage*10) < 40125)
140                         data = 0x00;
141                 else if ((batreg_voltage*10) > 44000)
142                         batreg_voltage = 4400;
143                 else
144                         data = ((batreg_voltage*10 - 40125) / 125);
145         } else {
146                 if (batreg_voltage <= 3725)
147                         data = 0x0;
148                 else if (batreg_voltage >= 4400)
149                         data = 0x1F;
150                 else if (batreg_voltage <= 4300)
151                         data = (batreg_voltage - 3725) / 25;
152                 else
153                         data = (batreg_voltage - 4300) * 10 / 125 + 23;
154         }
155
156         SM5701_reg_write(charger->SM5701->i2c, SM5701_CHGCNTL3, data);
157
158         SM5701_reg_read(charger->SM5701->i2c, SM5701_CHGCNTL3, &data);
159         pr_info("%s : SM5701_CHGCNTL3 (Battery regulation voltage) : 0x%02x\n",
160                 __func__, data);
161
162         return data;
163 }
164
165 static u8 SM5701_set_vbuslimit_current(
166                 struct SM5701_charger_data *charger, int input_current)
167 {
168         u8 data = 0, temp = 0;
169         SM5701_reg_read(charger->SM5701->i2c, SM5701_VBUSCNTL, &data);
170         data &= ~SM5701_VBUSCNTL_VBUSLIMIT;
171
172         if (input_current >= 1200)
173                 input_current = 1200;
174
175         if (charger->voltage_max != 4200) {
176                 if (charger->cable_type != POWER_SUPPLY_TYPE_BATTERY) {
177                         data &= ~SM5701_VBUSCNTL_VBUSLIMIT;
178                         SM5701_reg_write(charger->SM5701->i2c, SM5701_VBUSCNTL, data);
179                         pr_info("%s : SM5701_VBUSCNTL (Input current limit) : 0x%02x\n",
180                                 __func__, data);
181                 }
182         }
183         if(input_current <= 100)
184                 data &= ~SM5701_VBUSCNTL_VBUSLIMIT;
185         else if(input_current <= 500)
186                 data |= 0x01;
187         else {
188                 temp = (input_current/100)-5;
189                 data |= temp;
190         }
191
192         msleep(500);
193
194         SM5701_reg_write(charger->SM5701->i2c, SM5701_VBUSCNTL, data);
195
196         SM5701_reg_read(charger->SM5701->i2c, SM5701_VBUSCNTL, &data);
197         pr_info("%s : SM5701_VBUSCNTL (Input current limit) : 0x%02x\n",
198                 __func__, data);
199
200         return data;
201 }
202
203 static u8 SM5701_set_topoff(
204                 struct SM5701_charger_data *charger, int topoff_current)
205 {
206         u8 data = 0;
207
208         SM5701_reg_read(charger->SM5701->i2c, SM5701_CHGCNTL1, &data);
209
210         data &= ~SM5701_CHGCNTL1_TOPOFF;
211
212         if(topoff_current < 100)
213                 topoff_current = 100;
214         else if (topoff_current > 475)
215                 topoff_current = 475;
216
217         data |= (topoff_current - 100) / 25;
218
219         SM5701_reg_write(charger->SM5701->i2c, SM5701_CHGCNTL1, data);
220
221         SM5701_reg_read(charger->SM5701->i2c, SM5701_CHGCNTL1, &data);
222         pr_info("%s : SM5701_CHGCNTL1 (Top-off current threshold) : 0x%02x\n",
223                 __func__, data);
224
225         return data;
226 }
227
228 static u8 SM5701_set_fastchg_current(
229                 struct SM5701_charger_data *charger, int fast_charging_current)
230 {
231         u8 data = 0;
232
233         if(fast_charging_current < 100)
234                 fast_charging_current = 100;
235         else if (fast_charging_current > 1600)
236                 fast_charging_current = 1600;
237
238         data = (fast_charging_current - 100) / 25;
239
240         SM5701_reg_write(charger->SM5701->i2c, SM5701_CHGCNTL2, data);
241
242         SM5701_reg_read(charger->SM5701->i2c, SM5701_CHGCNTL2, &data);
243         pr_info("%s : SM5701_CHGCNTL2 (fastchg current) : 0x%02x\n",
244                 __func__, data);
245
246         return data;
247 }
248
249 static int SM5701_get_charging_current(
250         struct SM5701_charger_data *charger)
251 {
252         u8 data = 0;
253         int get_current = 0;
254
255         if (charger->charging_current) {
256                 SM5701_reg_read(charger->SM5701->i2c, SM5701_CHGCNTL2, &data);
257                 data &= SM5701_CHGCNTL2_FASTCHG;
258                 charger->charging_curr_step = 25;
259                 get_current = (100 + (data * charger->charging_curr_step));
260                 if (get_current <= 1600)
261                         get_current = (100 + (data * charger->charging_curr_step));
262         } else {
263                 get_current = 100;
264         }
265
266         get_current = (100 + (data * charger->charging_curr_step));
267
268         pr_debug("%s : Charging current : %dmA\n", __func__, get_current);
269         return get_current;
270 }
271
272 static u8 SM5701_toggle_charger(struct SM5701_charger_data *charger, int enable)
273 {
274         u8 chg_en = 0, mask = 0;
275
276         SM5701_reg_read(charger->SM5701->i2c, SM5701_CNTL, &chg_en);
277
278         mask = charger->dev_id < 3 ? OP_MODE_CHG_ON : OP_MODE_CHG_ON_REV3;
279         chg_en &= ~mask;
280
281         if ((led_state_charger == LED_DISABLE) || (charger->dev_id != 4)) {
282                 if (enable)
283                         chg_en |= mask;
284
285                 SM5701_reg_write(charger->SM5701->i2c, SM5701_CNTL, chg_en);
286                 gpio_direction_output((charger->pdata->chg_gpio_en), !enable);
287
288                 pr_info("%s: SM5701 Charger toggled!! \n", __func__);
289
290                 SM5701_reg_read(charger->SM5701->i2c, SM5701_CNTL, &chg_en);
291                 pr_info("%s : CNTL register (0x09) : 0x%02x\n", __func__, chg_en);
292
293         } else {
294                  SM5701_set_operationmode(SM5701_OPERATIONMODE_FLASH_ON);
295                 pr_info("%s: SM5701 Charger toggled!! - flash on!! \n", __func__);
296                 gpio_direction_output((charger->pdata->chg_gpio_en), !enable);
297         }
298
299         return chg_en;
300 }
301
302 static void SM5701_isr_work(struct work_struct *work)
303 {
304         union power_supply_propval val, value;
305         struct SM5701_charger_data *charger =
306                 container_of(work, struct SM5701_charger_data, isr_work.work);;
307         int full_check_type;
308
309         u8 cln = 0, topoff_data = 0, status = 0;
310
311         psy_do_property("battery", get,
312                 POWER_SUPPLY_PROP_CHARGE_NOW, val);
313         if (val.intval == SEC_BATTERY_CHARGING_1ST)
314                 full_check_type = charger->pdata->full_check_type;
315         else
316                 full_check_type = charger->pdata->full_check_type_2nd;
317
318         if (full_check_type == SEC_BATTERY_FULLCHARGED_CHGINT) {
319                 val.intval = SM5701_get_charging_status(charger);
320
321                 switch (val.intval) {
322                 case POWER_SUPPLY_STATUS_FULL:
323                         pr_err("%s: Interrupted by Full\n", __func__);
324                         psy_do_property("battery", set,
325                                 POWER_SUPPLY_PROP_STATUS, val);
326                         break;
327                 }
328         }
329
330         pr_info("=============================================================\n");
331         SM5701_reg_read(charger->SM5701->i2c, SM5701_CHGCNTL1, &topoff_data);
332         pr_info("%s : SM5701_CHGCNTL1 (Top-off current threshold) : 0x%02x\n",__func__, topoff_data);
333         SM5701_reg_read(charger->SM5701->i2c, SM5701_STATUS2, &status);
334         pr_info("%s: STATUS2 : %d\n", __func__, status); //SM : test
335         pr_info("=============================================================\n");
336
337         if (charger->pdata->ovp_uvlo_check_type ==
338                 SEC_BATTERY_OVP_UVLO_CHGINT) {
339                 val.intval = SM5701_get_charging_health(charger);
340
341                 switch (val.intval) {
342                 case POWER_SUPPLY_HEALTH_OVERVOLTAGE:
343                 /* case POWER_SUPPLY_HEALTH_UNDERVOLTAGE: */
344                         pr_info("%s: Interrupted by OVP/UVLO\n", __func__);
345                         psy_do_property("battery", set,
346                                 POWER_SUPPLY_PROP_HEALTH, val);
347                         break;
348                 case POWER_SUPPLY_HEALTH_UNDERVOLTAGE:
349                 /* case POWER_SUPPLY_HEALTH_UNDERVOLTAGE: */
350                         psy_do_property("battery", get,
351                                 POWER_SUPPLY_PROP_ONLINE, value);
352
353                         if (value.intval != POWER_SUPPLY_TYPE_BATTERY) {
354                                 pr_info("%s: Interrupted by OVP/UVLO\n", __func__);
355                                 psy_do_property("battery", set,
356                                         POWER_SUPPLY_PROP_HEALTH, val);
357                         }
358                         break;
359                 case POWER_SUPPLY_HEALTH_GOOD:
360                         pr_err("%s: Interrupted but Good\n", __func__);
361                         psy_do_property("battery", set,
362                                 POWER_SUPPLY_PROP_HEALTH, val);
363                         break;
364                 default:
365                         pr_err("%s: Invalid Charger Health\n", __func__);
366                         break;
367                 }
368         }
369
370         val.intval = SM5701_get_battery_present(charger);
371         pr_info("%s: battery status : %d\n", __func__, val.intval);
372         if (!val.intval)
373                 psy_do_property("battery", set,
374                         POWER_SUPPLY_PROP_PRESENT, val);
375 }
376
377 static irqreturn_t SM5701_irq_thread(int irq, void *irq_data)
378 {
379         struct SM5701_charger_data *charger = irq_data;
380         pr_info("*** %s ***\n", __func__);
381         // Temporary delay of the interrupt to prevent MUIC interrupt running after it
382         schedule_delayed_work(&charger->isr_work, HZ * 0.25);
383         return IRQ_HANDLED;
384 }
385
386 static int SM5701_debugfs_show(struct seq_file *s, void *data)
387 {
388         struct SM5701_charger_data *charger = s->private;
389         u8 reg;
390         u8 reg_data;
391
392         seq_printf(s, "SM5701 CHARGER IC :\n");
393         seq_printf(s, "===================\n");
394         for (reg = SM5701_INTMASK1; reg <= SM5701_FLEDCNTL6; reg++) {
395                 SM5701_reg_read(charger->SM5701->i2c, reg, &reg_data);
396                 seq_printf(s, "0x%02x:\t0x%02x\n", reg, reg_data);
397         }
398
399         seq_printf(s, "\n");
400         return 0;
401 }
402
403 static int SM5701_debugfs_open(struct inode *inode, struct file *file)
404 {
405         return single_open(file, SM5701_debugfs_show, inode->i_private);
406 }
407
408 static const struct file_operations SM5701_debugfs_fops = {
409         .open           = SM5701_debugfs_open,
410         .read           = seq_read,
411         .llseek         = seq_lseek,
412         .release        = single_release,
413 };
414
415 static void SM5701_charger_initialize(struct SM5701_charger_data *charger)
416 {
417         u8 reg_data = 0, status1 = 0;
418
419         SM5701_reg_read(charger->SM5701->i2c,
420                         SM5701_DEVICE_ID, &charger->dev_id);
421         pr_info("%s: SM5701 Charger init, CHIP REV : %2d !! \n",
422                         __func__, charger->dev_id);
423         charger->is_fullcharged = false;
424
425         SM5701_reg_read(charger->SM5701->i2c, SM5701_VBUSCNTL, &reg_data);
426         reg_data &= ~SM5701_VBUSCNTL_AICLEN;
427         SM5701_reg_write(charger->SM5701->i2c, SM5701_VBUSCNTL, reg_data);
428
429         SM5701_reg_read(charger->SM5701->i2c, SM5701_STATUS1, &status1);
430         pr_info("%s : SM5701_STATUS1 : 0x%02x\n", __func__, status1);
431
432 /* NOBAT, Enable OVP, UVLO, VBUSOK interrupts */
433         reg_data = 0x63;
434         SM5701_reg_write(charger->SM5701->i2c, SM5701_INTMASK1, reg_data);
435
436 /* Mask CHGON, FASTTMROFFM */
437         reg_data = 0xFF;
438         SM5701_reg_write(charger->SM5701->i2c, SM5701_INTMASK2, reg_data);
439
440 /* Set OVPSEL to 6.35V
441         SM5701_reg_read(charger->SM5701->i2c, SM5701_CNTL, &reg_data);
442         reg_data |= 0x1A;
443         SM5701_reg_write(charger->SM5701->i2c, SM5701_CNTL, reg_data);
444 */
445
446         /* Operating Frequency in PWM BUCK mode : 2.4KHz */
447         SM5701_reg_read(charger->SM5701->i2c, SM5701_CNTL, &reg_data);
448         reg_data &= ~0xC0;
449         reg_data |= (FREQ_24 | 0x4);
450         SM5701_reg_write(charger->SM5701->i2c, SM5701_CNTL, reg_data);
451
452         /* Disable AUTOSTOP */
453         SM5701_reg_read(charger->SM5701->i2c, SM5701_CHGCNTL1, &reg_data);
454         reg_data &= ~SM5701_CHGCNTL1_AUTOSTOP;
455         SM5701_reg_write(charger->SM5701->i2c, SM5701_CHGCNTL1, reg_data);
456
457         (void) debugfs_create_file("SM5701_regs",
458                 S_IRUGO, NULL, (void *)charger, &SM5701_debugfs_fops);
459
460         SM5701_test_read(charger->SM5701->i2c);
461 }
462
463 static int sec_chg_get_property(struct power_supply *psy,
464                               enum power_supply_property psp,
465                               union power_supply_propval *val)
466 {
467         struct SM5701_charger_data *charger =
468                 container_of(psy, struct SM5701_charger_data, psy_chg);
469
470         switch (psp) {
471         case POWER_SUPPLY_PROP_ONLINE:
472                 printk("[%s] got val->intval:%d\n",__func__, val->intval);
473                 break;
474         case POWER_SUPPLY_PROP_STATUS:
475                 if (charger->is_fullcharged)
476                         val->intval = POWER_SUPPLY_STATUS_FULL;
477                 else
478                         val->intval = SM5701_get_charging_status(charger);
479                 break;
480         case POWER_SUPPLY_PROP_HEALTH:
481                 val->intval = SM5701_get_charging_health(charger);
482                 break;
483         case POWER_SUPPLY_PROP_PRESENT:
484                 val->intval = SM5701_get_battery_present(charger);
485                 break;
486         case POWER_SUPPLY_PROP_CURRENT_MAX:
487                 val->intval = charger->charging_current_max;
488                 break;
489         case POWER_SUPPLY_PROP_CURRENT_AVG:
490                 val->intval = charger->charging_current;
491                 break;
492         case POWER_SUPPLY_PROP_CHARGE_NOW:
493                 break;
494         case POWER_SUPPLY_PROP_CURRENT_NOW:
495                 val->intval = SM5701_get_charging_current(charger);
496                 break;
497         case POWER_SUPPLY_PROP_CHARGE_TYPE:
498                 if (!charger->is_charging)
499                         val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
500                 else if (charger->aicl_on)
501                 {
502                         val->intval = POWER_SUPPLY_CHARGE_TYPE_SLOW;
503                         pr_info("%s: slow-charging mode\n", __func__);
504                 }
505                 else
506                         val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
507                 break;
508         case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
509                 break;
510         default:
511                 return -EINVAL;
512         }
513         return 0;
514 }
515
516 static int sec_chg_set_property(struct power_supply *psy,
517                               enum power_supply_property psp,
518                               const union power_supply_propval *val)
519 {
520         struct SM5701_charger_data *charger =
521                 container_of(psy, struct SM5701_charger_data, psy_chg);
522         union power_supply_propval value;
523         int charging_current;
524 //      int set_charging_current, set_charging_current_max;
525 //      const int usb_charging_current = charger->pdata->charging_current[
526 //              POWER_SUPPLY_TYPE_USB].fast_charging_current;
527         u8 topoff_data = 0, stauts = 0;
528
529         switch (psp) {
530         case POWER_SUPPLY_PROP_STATUS:
531                 charger->status = val->intval;
532                 break;
533         case POWER_SUPPLY_PROP_ONLINE:
534                 charger->cable_type = val->intval;
535                 psy_do_property("battery", get,
536                                 POWER_SUPPLY_PROP_HEALTH, value);
537                 if (val->intval == POWER_SUPPLY_TYPE_BATTERY) {
538                         /* Disable Charger */
539                         charger->is_charging = false;
540                         charger->nchgen = true;
541                         charger->aicl_on = false;
542                         pr_info("%s : Disable Charger, Battery Supply!\n", __func__);
543                         // nCHG_EN is logic low so set 1 to disable charger
544                         charger->is_fullcharged = false;
545                 } else if(val->intval == POWER_SUPPLY_TYPE_OTG){
546                         charger->is_charging = false;
547                         charger->nchgen = true;
548                         charger->aicl_on = false;
549                         charger->is_fullcharged = false;
550                         charger->status = POWER_SUPPLY_STATUS_NOT_CHARGING;
551                         SM5701_set_bstout(SM5701_BSTOUT_5P0);
552                         SM5701_set_operationmode(SM5701_OPERATIONMODE_OTG_ON_FLASH_ON);
553                         SM5701_test_read(charger->SM5701->i2c); 
554
555                 } else {
556                         charger->is_charging = true;
557                         charger->nchgen = false;
558                         charger->charging_current_max =
559                                         charger->pdata->charging_current
560                                         [charger->cable_type].input_current_limit;
561                         charger->charging_current =
562                                         charger->pdata->charging_current
563                                         [charger->cable_type].fast_charging_current;
564                 }
565
566                 SM5701_operation_mode_function_control();
567                 pr_info("%s : STATUS OF CHARGER ON(0)/OFF(1): %d\n", __func__, charger->nchgen);
568                 SM5701_toggle_charger(charger, charger->is_charging);
569
570                 /* if battery full, only disable charging  */
571                 if ((charger->status == POWER_SUPPLY_STATUS_CHARGING) ||
572                         (charger->status == POWER_SUPPLY_STATUS_DISCHARGING) ||
573                         (charger->status == POWER_SUPPLY_STATUS_FULL) ||
574                         (value.intval == POWER_SUPPLY_HEALTH_UNSPEC_FAILURE) ||
575                         (value.intval == POWER_SUPPLY_HEALTH_OVERHEATLIMIT)) {
576
577                         /* Set float voltage */
578                         pr_info("%s : float voltage (%dmV)\n",
579                                 __func__, charger->pdata->chg_float_voltage);
580                         if (charger->pdata->chg_float_voltage > charger->voltage_max) {
581                                 SM5701_set_batreg_voltage(
582                                         charger, charger->voltage_max);
583                                 pr_info("%s : set float voltage to voltage_max (%dmV)\n",
584                                         __func__, charger->voltage_max);
585                         } else {
586                                 SM5701_set_batreg_voltage(
587                                         charger, charger->pdata->chg_float_voltage);
588                         }
589
590                         /* if battery is removed, put vbus current limit to minimum */
591                         if ((value.intval == POWER_SUPPLY_HEALTH_UNSPEC_FAILURE) ||
592                             (value.intval == POWER_SUPPLY_HEALTH_OVERHEATLIMIT))
593                                 SM5701_set_vbuslimit_current(charger, 100);
594                         else {
595                                 /* Set input current limit */
596                                 pr_info("%s : vbus current limit (%dmA)\n",
597                                         __func__, charger->pdata->charging_current
598                                         [charger->cable_type].input_current_limit);
599
600                                 SM5701_set_vbuslimit_current(
601                                         charger, charger->pdata->charging_current
602                                         [charger->cable_type].input_current_limit);
603                         }
604
605                         /* Set topoff current */
606                         pr_info("%s : topoff current (%dmA)\n",
607                                 __func__, charger->pdata->charging_current[
608                                 charger->cable_type].full_check_current_1st);
609                         if (charger->voltage_max == 4200)
610                                 SM5701_set_topoff(charger, 100);
611                         else
612                                 SM5701_set_topoff(
613                                         charger, charger->pdata->charging_current[
614                                         charger->cable_type].full_check_current_1st);
615
616                         /* Set fast charge current */
617                         pr_info("%s : fast charging current (%dmA), siop_level=%d\n",
618                                 __func__, charger->charging_current, charger->siop_level);
619                         charging_current = 
620                                 charger->charging_current * charger->siop_level / 100;
621                         SM5701_set_fastchg_current(
622                                 charger, charging_current);
623                 }
624                 break;
625         /* val->intval : float voltage */
626         case POWER_SUPPLY_PROP_VOLTAGE_MAX:
627                 charger->voltage_max = val->intval;
628                 SM5701_set_batreg_voltage(
629                                 charger, charger->voltage_max);
630                 pr_info("POWER_SUPPLY_PROP_VOLTAGE_MAX[%d]\n", charger->voltage_max);
631                 if (charger->voltage_max == 4200)
632                         SM5701_set_topoff(charger, 100);
633                 else if (charger->voltage_max == 4350)
634                         SM5701_set_topoff(charger, charger->pdata->charging_current[
635                                         charger->cable_type].full_check_current_1st);
636                 break;
637         /* val->intval : input charging current */
638         case POWER_SUPPLY_PROP_CURRENT_MAX:
639                 charger->charging_current_max = val->intval;
640                 break;
641         /*  val->intval : charging current */
642         case POWER_SUPPLY_PROP_CURRENT_AVG:
643                 charger->charging_current = val->intval;
644                 break;
645         case POWER_SUPPLY_PROP_CURRENT_NOW:
646                 SM5701_set_fastchg_current(charger,
647                                 val->intval);
648                 SM5701_set_vbuslimit_current(charger,
649                                 val->intval);
650                 break;
651         case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
652                 charger->siop_level = val->intval;
653                 /* Set fast charge current */
654                 pr_info("%s : fast charging current (%dmA), siop_level=%d\n",
655                         __func__, charger->charging_current, charger->siop_level);
656                 charging_current = 
657                         charger->charging_current * charger->siop_level / 100;
658                 SM5701_set_fastchg_current(
659                         charger, charging_current);
660                 break;
661         default:
662                 return -EINVAL;
663         }
664         return 0;
665 }
666
667 #ifdef CONFIG_OF
668 static struct of_device_id SM5701_charger_match_table[] = {
669         { .compatible = "sm,sm5701-charger",},
670         {},
671 };
672 #else
673 #define SM5701_charger_match_table NULL
674 #endif /* CONFIG_OF */
675
676 static int SM5701_charger_probe(struct platform_device *pdev)
677 {
678         struct SM5701_dev *iodev = dev_get_drvdata(pdev->dev.parent);
679         struct SM5701_platform_data *pdata = dev_get_platdata(iodev->dev);
680         struct SM5701_charger_data *charger;
681         int ret = 0;
682
683         pr_info("%s: SM5701 Charger Probe Start\n", __func__);
684
685         charger = kzalloc(sizeof(*charger), GFP_KERNEL);
686         if (!charger)
687                 return -ENOMEM;
688
689         if (pdev->dev.parent->of_node) {
690                 pdev->dev.of_node = of_find_compatible_node(
691                         of_node_get(pdev->dev.parent->of_node), NULL,
692                         SM5701_charger_match_table[0].compatible);
693     }
694
695         charger->SM5701 = iodev;
696         charger->SM5701->dev = &pdev->dev;
697
698     if (pdev->dev.of_node) {
699                 charger->pdata = devm_kzalloc(&pdev->dev, sizeof(*(charger->pdata)),
700                         GFP_KERNEL);
701                 if (!charger->pdata) {
702                         dev_err(&pdev->dev, "Failed to allocate memory\n");
703                         ret = -ENOMEM;
704                         goto err_parse_dt_nomem;
705                 }
706                 ret = sec_chg_dt_init(pdev->dev.of_node, &pdev->dev, charger->pdata);
707                 if (ret < 0)
708                         goto err_parse_dt;
709         } else
710                 charger->pdata = pdata->charger_data;
711
712         charger->voltage_max = charger->pdata->chg_float_voltage;
713
714         platform_set_drvdata(pdev, charger);
715
716     if (charger->pdata->charger_name == NULL)
717             charger->pdata->charger_name = "sec-charger";
718
719         charger->psy_chg.name           = charger->pdata->charger_name;
720         charger->psy_chg.type           = POWER_SUPPLY_TYPE_UNKNOWN;
721         charger->psy_chg.get_property   = sec_chg_get_property;
722         charger->psy_chg.set_property   = sec_chg_set_property;
723         charger->psy_chg.properties     = sec_charger_props;
724         charger->psy_chg.num_properties = ARRAY_SIZE(sec_charger_props);
725
726         charger->siop_level = 100;
727         SM5701_charger_initialize(charger);
728
729         charger->input_curr_limit_step = 500;
730         charger->charging_curr_step= 25;
731     ret = power_supply_register(&pdev->dev, &charger->psy_chg);
732     if (ret) {
733             pr_err("%s: Failed to Register psy_chg\n", __func__);
734             goto err_power_supply_register;
735     }
736
737     SM5701_set_charger_data(charger);
738         if (charger->pdata->chg_irq) {
739                 INIT_DELAYED_WORK(&charger->isr_work, SM5701_isr_work);
740
741                 ret = request_threaded_irq(charger->pdata->chg_irq,
742                                 NULL, SM5701_irq_thread,
743                                 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
744                                 /* charger->pdata->chg_irq_attr, */
745                                 "charger-irq", charger);
746                 if (ret) {
747                         dev_err(&pdev->dev,
748                                         "%s: Failed to Reqeust IRQ\n", __func__);
749                         goto err_request_irq;
750                 }
751
752                 ret = enable_irq_wake(charger->pdata->chg_irq);
753                 if (ret < 0)
754                         dev_err(&pdev->dev,
755                                         "%s: Failed to Enable Wakeup Source(%d)\n",
756                                         __func__, ret);
757         }
758         pr_info("%s: SM5701 Charger Probe Loaded\n", __func__);
759         return 0;
760
761 err_request_irq:
762         power_supply_unregister(&charger->psy_chg);
763 err_power_supply_register:
764         pr_info("%s: err_power_supply_register error \n", __func__);
765 err_parse_dt:
766         pr_info("%s: err_parse_dt error \n", __func__);
767 err_parse_dt_nomem:
768         pr_info("%s: err_parse_dt_nomem error \n", __func__);
769         kfree(charger);
770         return ret;
771 }
772
773 static int SM5701_charger_remove(struct platform_device *pdev)
774 {
775         struct SM5701_charger_data *charger =
776                                 platform_get_drvdata(pdev);
777         power_supply_unregister(&charger->psy_chg);
778         kfree(charger);
779
780         return 0;
781 }
782
783 bool SM5701_charger_suspend(struct SM5701_charger_data *charger)
784 {
785         pr_info("%s: CHARGER - SM5701(suspend mode)!!\n", __func__);
786         return true;
787 }
788
789 bool SM5701_charger_resume(struct SM5701_charger_data *charger)
790 {
791         pr_info("%s: CHARGER - SM5701(resume mode)!!\n", __func__);
792         return true;
793 }
794
795 static void SM5701_charger_shutdown(struct device *dev)
796 {
797         struct SM5701_charger_data *charger =
798                                 dev_get_drvdata(dev);
799
800         pr_info("%s: SM5701 Charger driver shutdown\n", __func__);
801         if (!charger->SM5701->i2c) {
802                 pr_err("%s: no SM5701 i2c client\n", __func__);
803                 return;
804         }
805 }
806
807 static const struct platform_device_id SM5701_charger_id[] = {
808         { "sm5701-charger", 0},
809         { },
810 };
811 MODULE_DEVICE_TABLE(platform, SM5701_charger_id);
812
813 static struct platform_driver SM5701_charger_driver = {
814         .driver = {
815                 .name = "sm5701-charger",
816                 .owner = THIS_MODULE,
817                 .of_match_table = SM5701_charger_match_table,
818                 .shutdown = SM5701_charger_shutdown,
819         },
820         .probe = SM5701_charger_probe,
821         .remove = SM5701_charger_remove,
822         .id_table = SM5701_charger_id,
823 };
824
825 static int __init SM5701_charger_init(void)
826 {
827         pr_info("%s\n", __func__);
828         return platform_driver_register(&SM5701_charger_driver);
829 }
830
831 subsys_initcall(SM5701_charger_init);
832
833 static void __exit SM5701_charger_exit(void)
834 {
835         platform_driver_unregister(&SM5701_charger_driver);
836 }
837
838 module_exit(SM5701_charger_exit);
839
840 MODULE_DESCRIPTION("SILICONMITUS SM5701 Charger Driver");
841 MODULE_AUTHOR("Samsung Electronics");
842 MODULE_LICENSE("GPL");
843 MODULE_ALIAS("platform:SM5701_charger");
844