1 /* drivers/power/rk2818_battery.c
3 * battery detect driver for the rk2818
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 #include <linux/module.h>
17 #include <linux/err.h>
18 #include <linux/platform_device.h>
19 #include <linux/power_supply.h>
20 #include <linux/types.h>
21 #include <linux/pci.h>
22 #include <linux/interrupt.h>
24 #include <asm/mach-types.h>
25 #include <asm/mach/arch.h>
26 #include <asm/mach/map.h>
27 #include <mach/gpio.h>
29 #include <mach/iomux.h>
32 #define DBG(x...) printk(x)
37 /*******************ÒÔϲÎÊý¿ÉÒÔÐÞ¸Ä******************************/
38 #define TIMER_MS_COUNTS 50 //¶¨Ê±Æ÷µÄ³¤¶Èms
39 #define SLOPE_SECOND_COUNTS 120 //ͳ¼ÆµçѹбÂʵÄʱ¼ä¼ä¸ôs
40 #define TIME_UPDATE_STATUS 5000 //¸üеç³Ø״̬µÄʱ¼ä¼ä¸ôms
41 #define BATT_MAX_VOL_VALUE 4180 //ÂúµçʱµÄµç³Øµçѹ FOR A7
42 #define BATT_ZERO_VOL_VALUE 3400 //¹Ø»úʱµÄµç³Øµçѹ
43 #define BATT_NOMAL_VOL_VALUE 3800
44 #define THRESHOLD_VOLTAGE_LEVEL0 4050
45 #define THRESHOLD_VOLTAGE_LEVEL1 3950
46 #define THRESHOLD_VOLTAGE_LEVEL2 3850
47 #define THRESHOLD_VOLTAGE_LEVEL3 BATT_ZERO_VOL_VALUE
48 #define THRESHOLD_SLOPE_HIGH 10 //бÂÊÖµ = µçѹ½µµÍµÄËÙ¶È
49 #define THRESHOLD_SLOPE_MID 5 //< THRESHOLD_SLOPE_HIGH
50 #define THRESHOLD_SLOPE_LOW 0 //< THRESHOLD_SLOPE_MID
52 /*************************************************************/
55 #define BATT_LEVEL_EMPTY 0
56 #define BATT_PRESENT_TRUE 1
57 #define BATT_PRESENT_FALSE 0
58 #define BAT_1V2_VALUE 1330
59 #define CHARGEOK_PIN RK2818_PIN_PB1
61 #define BAT_LOADER_STATUS 0 //Óõç״̬
62 #define BAT_CHANGE_STATUS 1 //²¨¶¯×´Ì¬
63 #define BAT_CHARGE_STATUS 2 //³äµç״̬
64 #define BAT_RELEASE_STATUS 3 //µç³ØºÄ¾¡×´Ì¬
66 #define SLOPE_HIGH_LEVEL 0 //µçѹ±ä»¯Ð±Âʵȼ¶
67 #define SLOPE_MID_LEVEL 1
68 #define SLOPE_LOW_LEVEL 2
70 #define VOLTAGE_HIGH_LEVEL 0 //µçѹ¸ßµÍµÈ¼¶
71 #define VOLTAGE_MID_LEVEL 1
72 #define VOLTAGE_LOW_LEVEL 2
73 #define VOLTAGE_RELEASE_LEVEL 3
75 #define NUM_VOLTAGE_SAMPLE ((1000*SLOPE_SECOND_COUNTS) / TIMER_MS_COUNTS) //´æ´¢µÄ²ÉÑùµã¸öÊý
77 int gBatLastStatus = 0;
78 int gBatStatus = POWER_SUPPLY_STATUS_UNKNOWN;
79 int gBatHealth = POWER_SUPPLY_HEALTH_GOOD;
80 int gBatLastPresent = 0;
81 int gBatPresent = BATT_PRESENT_TRUE;
82 int gBatLastVoltage = 0;
83 int gBatVoltage = BATT_NOMAL_VOL_VALUE;
84 int gBatLastCapacity = 0;
85 int gBatCapacity = ((BATT_NOMAL_VOL_VALUE-BATT_ZERO_VOL_VALUE)*100/(BATT_MAX_VOL_VALUE-BATT_ZERO_VOL_VALUE));
87 int gBatVoltageSamples[NUM_VOLTAGE_SAMPLE];
88 int gBatSlopeValue = 0;
89 int gBatVoltageValue[2]={0,0};
90 int *pSamples = &gBatVoltageSamples[0]; //²ÉÑùµãÖ¸Õë
91 int gFlagLoop = 0; //²ÉÑù×ã¹»±êÖ¾
98 int gBatSlopeLevel = SLOPE_LOW_LEVEL;
99 int gBatVoltageLevel = VOLTAGE_MID_LEVEL;
100 int gBatUseStatus = BAT_LOADER_STATUS;
104 extern int dwc_vbus_status(void);
105 extern int get_msc_connect_flag(void);
107 struct rk2818_battery_data {
110 struct work_struct timer_work;
111 struct timer_list timer;
112 struct power_supply battery;
113 struct power_supply usb;
114 struct power_supply ac;
122 /* temporary variable used between rk2818_battery_probe() and rk2818_battery_open() */
123 static struct rk2818_battery_data *gBatteryData;
129 BATTERY_CAPACITY = 3,
130 BATTERY_AC_ONLINE = 4,
131 BATTERY_STATUS_CHANGED = 5,
132 AC_STATUS_CHANGED = 6,
133 BATTERY_INT_STATUS = 7,
134 BATTERY_INT_ENABLE = 8,
143 static int rk2818_get_charge_status(void)
145 //DBG("gAdcValue[CHN_USB_ADC]=%d\n",gAdcValue[CHN_USB_ADC]);
146 if(gAdcValue[CHN_USB_ADC] > 250) //about 0.5V
148 else if((1 == dwc_vbus_status())&& (0 == get_msc_connect_flag()))
154 static void rk2818_get_bat_status(struct rk2818_battery_data *bat)
156 if(rk2818_get_charge_status() == 1)
158 if(gpio_get_value (CHARGEOK_PIN) == 1) //CHG_OK ==0
160 gBatStatus = POWER_SUPPLY_STATUS_FULL;
161 DBG("Battery is Full!\n");
164 gBatStatus = POWER_SUPPLY_STATUS_CHARGING;
167 gBatStatus = POWER_SUPPLY_STATUS_NOT_CHARGING;
170 static void rk2818_get_bat_health(struct rk2818_battery_data *bat)
172 gBatHealth = POWER_SUPPLY_HEALTH_GOOD;
175 static void rk2818_get_bat_present(struct rk2818_battery_data *bat)
177 if(gBatVoltage < bat->bat_min)
183 static void rk2818_get_bat_voltage(struct rk2818_battery_data *bat)
186 int i,*pSamp,*pStart = &gBatVoltageSamples[0],num = 0;
188 value = gAdcValue[CHN_BAT_ADC];
189 if(0 != gAdcValue[3])
190 gBatVoltage = (value * BAT_1V2_VALUE * 2)/gAdcValue[3]; // channel 3 is about 1.42v,need modified
192 if(gBatVoltage >= BATT_MAX_VOL_VALUE + 10)
193 gBatVoltage = BATT_MAX_VOL_VALUE + 10;
194 else if(gBatVoltage <= BATT_ZERO_VOL_VALUE - 10)
195 gBatVoltage = BATT_ZERO_VOL_VALUE - 10;
197 *pSamples = gBatVoltage;
198 num = ++pSamples - pStart;
199 if(num > NUM_VOLTAGE_SAMPLE)
205 if(gFlagLoop != 1) //δ²É¼¯µ½ NUM_VOLTAGE_SAMPLE¸öµçѹֵ
207 for(i=(num>>1); i<num; i++)
209 temp[0] += gBatVoltageSamples[i];
214 gBatVoltage = temp[0] / ((num+1)>>1);
215 gBatCapacity = ((gBatVoltage - bat->bat_min) * 100) / (bat->bat_max - bat->bat_min);
216 if(gBatCapacity >= 100)
218 else if(gBatCapacity < 0)
221 //DBG("gBatVoltage=%d,gBatCapacity=%d,num=%d\n",gBatVoltage,gBatCapacity,num);
225 //compute the average voltage after samples-count is larger than NUM_VOLTAGE_SAMPLE
227 for(i=0; i<(NUM_VOLTAGE_SAMPLE >> 1); i++)
230 if((++pSamp - pStart) > NUM_VOLTAGE_SAMPLE)
234 gBatVoltageValue[0] = temp[0] / (NUM_VOLTAGE_SAMPLE >> 1);
235 for(i=0; i<(NUM_VOLTAGE_SAMPLE >> 1); i++)
238 if((++pSamp - pStart) > NUM_VOLTAGE_SAMPLE)
242 gBatVoltageValue[1] = temp[1] / (NUM_VOLTAGE_SAMPLE >> 1);
244 gBatVoltage = gBatVoltageValue[1];
246 gBatSlopeValue = gBatVoltageValue[0] - gBatVoltageValue[1];
247 //DBG("gBatSlopeValue=%d,gBatVoltageValue[1]=%d\n",gBatSlopeValue,gBatVoltageValue[1]);
249 if(gBatVoltageValue[1] < BATT_ZERO_VOL_VALUE)
251 gBatUseStatus = BAT_RELEASE_STATUS; //µç³ØºÄ¾¡×´Ì¬
255 if(gBatSlopeValue < 0)
259 //Á¬Ðø¶à´Îµçѹ½µµÍÂÊΪ¸º±íʾ³äµç״̬
260 if(gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_LEVEL0)
262 else if(gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_LEVEL1)
264 else if(gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_LEVEL2)
266 else if(gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_LEVEL3)
268 if((++gNumCharge >= gMaxCharge) && (gBatStatus != POWER_SUPPLY_STATUS_NOT_CHARGING))
270 gBatUseStatus = BAT_CHARGE_STATUS; //³äµç״̬
271 gNumCharge = gMaxCharge ;
275 gBatUseStatus = BAT_CHANGE_STATUS; //²¨¶¯×´Ì¬
282 //Á¬Ðø¶à´Îµçѹ½µµÍÂÊΪÕý±íʾÓõç״̬
283 if(gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_LEVEL0)
285 else if(gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_LEVEL1)
287 else if(gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_LEVEL2)
289 else if(gBatVoltageValue[1] >= THRESHOLD_VOLTAGE_LEVEL3)
292 if((++gNumLoader >= gMaxLoader) && (gBatStatus == POWER_SUPPLY_STATUS_NOT_CHARGING))
294 gBatUseStatus = BAT_LOADER_STATUS;
295 gNumLoader = gMaxLoader;
299 gBatUseStatus = BAT_CHANGE_STATUS; //²¨¶¯×´Ì¬
309 static void rk2818_get_bat_capacity(struct rk2818_battery_data *bat)
313 if(gBatUseStatus == BAT_LOADER_STATUS)
315 //Óõç״̬ϳöÏÖ¸ºÔرäСÈÝÁ¿±ä´óʱ£¬²»¸üÐÂÈÝÁ¿Öµ
316 if((gBatLastVoltage == 0) || (gBatVoltage <= gBatLastVoltage))
318 gBatCapacity = ((gBatVoltage - bat->bat_min) * 100) / (bat->bat_max - bat->bat_min);
319 if(gBatCapacity >= 100)
321 else if(gBatCapacity < 0)
323 gBatLastVoltage = gBatVoltage;
327 else if(gBatUseStatus == BAT_CHARGE_STATUS)
329 //³äµç״̬ÏÂÈÝÁ¿½µµÍʱ£¬²»¸üÐÂÈÝÁ¿Öµ
330 if((gBatLastVoltage == 0) || (gBatVoltage >= gBatLastVoltage))
332 gBatCapacity = ((gBatVoltage - bat->bat_min) * 100) / (bat->bat_max - bat->bat_min);
333 if(gBatCapacity >= 100)
335 else if(gBatCapacity < 0)
337 gBatLastVoltage = gBatVoltage;
338 //DBG("BAT_CHARGE_STATUS\n");
344 //DBG("BAT_CHANGE_STATUS\n");
348 gBatCapacity = ((gBatVoltage - bat->bat_min) * 100) / (bat->bat_max - bat->bat_min);
349 if(gBatCapacity >= 100)
351 else if(gBatCapacity < 0)
357 static void rk2818_battery_timer_work(struct work_struct *work)
359 rk2818_get_bat_status(gBatteryData);
360 rk2818_get_bat_health(gBatteryData);
361 rk2818_get_bat_present(gBatteryData);
362 rk2818_get_bat_voltage(gBatteryData);
363 rk2818_get_bat_capacity(gBatteryData);
365 /*update battery parameter after adc and capacity has been changed*/
366 if((gBatStatus != gBatLastStatus) || (gBatPresent != gBatLastPresent) || (gBatCapacity != gBatLastCapacity))
369 gBatLastStatus = gBatStatus;
370 gBatLastPresent = gBatPresent;
371 gBatLastCapacity = gBatCapacity;
373 if(!( strstr(saved_command_line,"nfsroot=") ) )
375 power_supply_changed(&gBatteryData->battery);
379 DBG("voltage has changed\n");
380 DBG("gBatStatus=%d,gBatHealth=%d,gBatPresent=%d\n",gBatStatus,gBatHealth,gBatPresent);
381 if(gBatVoltageValue[1] == 0)
382 DBG("gBatVoltage=%d\n",gBatVoltage);
384 DBG("gBatVoltage=%d\n",gBatVoltageValue[1]);
385 DBG("gBatCapacity=%d%%\n",gBatCapacity);
393 static void rk2818_batscan_timer(unsigned long data)
395 gBatteryData->timer.expires = jiffies + msecs_to_jiffies(TIMER_MS_COUNTS);
396 add_timer(&gBatteryData->timer);
397 schedule_work(&gBatteryData->timer_work);
401 static int rk2818_usb_get_property(struct power_supply *psy,
402 enum power_supply_property psp,
403 union power_supply_propval *val)
405 charger_type_t charger;
406 charger = CHARGER_USB;
409 case POWER_SUPPLY_PROP_ONLINE:
410 if (psy->type == POWER_SUPPLY_TYPE_USB)
411 val->intval = dwc_vbus_status();
412 DBG("%s:%d\n",__FUNCTION__,val->intval);
424 static int rk2818_ac_get_property(struct power_supply *psy,
425 enum power_supply_property psp,
426 union power_supply_propval *val)
428 // struct rk2818_battery_data *data = container_of(psy,
429 // struct rk2818_battery_data, ac);
431 charger_type_t charger;
432 charger = CHARGER_USB;
434 case POWER_SUPPLY_PROP_ONLINE:
435 if (psy->type == POWER_SUPPLY_TYPE_MAINS)
437 if(gAdcValue[CHN_USB_ADC] > 250)
442 DBG("%s:%d\n",__FUNCTION__,val->intval);
452 static int rk2818_battery_get_property(struct power_supply *psy,
453 enum power_supply_property psp,
454 union power_supply_propval *val)
456 struct rk2818_battery_data *data = container_of(psy,
457 struct rk2818_battery_data, battery);
461 case POWER_SUPPLY_PROP_STATUS:
462 val->intval = gBatStatus;
463 DBG("gBatStatus=%d\n",val->intval);
465 case POWER_SUPPLY_PROP_HEALTH:
466 val->intval = gBatHealth;
467 DBG("gBatHealth=%d\n",val->intval);
469 case POWER_SUPPLY_PROP_PRESENT:
470 val->intval = gBatPresent;
471 DBG("gBatPresent=%d\n",val->intval);
473 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
474 if(gBatVoltageValue[1] == 0)
475 val ->intval = gBatVoltage;
477 val ->intval = gBatVoltageValue[1];
478 DBG("gBatVoltage=%d\n",val->intval);
480 case POWER_SUPPLY_PROP_TECHNOLOGY:
481 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
483 case POWER_SUPPLY_PROP_CAPACITY:
484 val->intval = gBatCapacity;
485 DBG("gBatCapacity=%d%%\n",val->intval);
487 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
488 val->intval = data->bat_max;
490 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
491 val->intval = data->bat_min;
501 static enum power_supply_property rk2818_battery_props[] = {
502 POWER_SUPPLY_PROP_STATUS,
503 POWER_SUPPLY_PROP_HEALTH,
504 POWER_SUPPLY_PROP_PRESENT,
505 POWER_SUPPLY_PROP_VOLTAGE_NOW,
506 POWER_SUPPLY_PROP_TECHNOLOGY,
507 POWER_SUPPLY_PROP_CAPACITY,
508 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
509 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
512 static enum power_supply_property rk2818_usb_props[] = {
513 POWER_SUPPLY_PROP_ONLINE,
517 static enum power_supply_property rk2818_ac_props[] = {
518 POWER_SUPPLY_PROP_ONLINE,
523 static int rk2818_battery_suspend(struct platform_device *dev, pm_message_t state)
525 /* flush all pending status updates */
526 flush_scheduled_work();
530 static int rk2818_battery_resume(struct platform_device *dev)
532 /* things may have changed while we were away */
533 schedule_work(&gBatteryData->timer_work);
537 #define tosa_bat_suspend NULL
538 #define tosa_bat_resume NULL
542 static int rk2818_battery_probe(struct platform_device *pdev)
545 struct rk2818_battery_data *data;
547 ret = gpio_request(CHARGEOK_PIN, NULL);
549 printk("failed to request charge_ok gpio\n");
553 gpio_pull_updown(CHARGEOK_PIN, GPIOPullUp);//important
554 ret = gpio_direction_input(CHARGEOK_PIN);
556 printk("failed to set gpio charge_ok input\n");
560 data = kzalloc(sizeof(*data), GFP_KERNEL);
563 goto err_data_alloc_failed;
565 spin_lock_init(&data->lock);
567 memset(gBatVoltageSamples, 0, sizeof(gBatVoltageSamples));
569 data->battery.properties = rk2818_battery_props;
570 data->battery.num_properties = ARRAY_SIZE(rk2818_battery_props);
571 data->battery.get_property = rk2818_battery_get_property;
572 data->battery.name = "battery";
573 data->battery.type = POWER_SUPPLY_TYPE_BATTERY;
574 data->adc_bat_divider = 414;
575 data->bat_max = BATT_MAX_VOL_VALUE;
576 data->bat_min = BATT_ZERO_VOL_VALUE;
577 DBG("bat_min = %d\n",data->bat_min);
579 data->usb.properties = rk2818_usb_props;
580 data->usb.num_properties = ARRAY_SIZE(rk2818_ac_props);
581 data->usb.get_property = rk2818_usb_get_property;
582 data->usb.name = "usb";
583 data->usb.type = POWER_SUPPLY_TYPE_USB;
585 data->ac.properties = rk2818_ac_props;
586 data->ac.num_properties = ARRAY_SIZE(rk2818_ac_props);
587 data->ac.get_property = rk2818_ac_get_property;
588 data->ac.name = "ac";
589 data->ac.type = POWER_SUPPLY_TYPE_MAINS;
591 ret = power_supply_register(&pdev->dev, &data->ac);
594 printk(KERN_INFO "fail to power_supply_register\n");
598 ret = power_supply_register(&pdev->dev, &data->usb);
601 printk(KERN_INFO "fail to power_supply_register\n");
605 ret = power_supply_register(&pdev->dev, &data->battery);
608 printk(KERN_INFO "fail to power_supply_register\n");
609 goto err_battery_failed;
611 platform_set_drvdata(pdev, data);
613 INIT_WORK(&data->timer_work, rk2818_battery_timer_work);
616 setup_timer(&data->timer, rk2818_batscan_timer, (unsigned long)data);
617 data->timer.expires = jiffies+100;
618 add_timer(&data->timer);
619 printk(KERN_INFO "rk2818_battery: driver initialized\n");
624 power_supply_unregister(&data->usb);
626 power_supply_unregister(&data->ac);
629 err_data_alloc_failed:
632 gpio_free(CHARGEOK_PIN);
636 static int rk2818_battery_remove(struct platform_device *pdev)
638 struct rk2818_battery_data *data = platform_get_drvdata(pdev);
640 power_supply_unregister(&data->battery);
641 power_supply_unregister(&data->usb);
642 power_supply_unregister(&data->ac);
643 gpio_free(CHARGEOK_PIN);
644 free_irq(data->irq, data);
650 static struct platform_driver rk2818_battery_device = {
651 .probe = rk2818_battery_probe,
652 .remove = rk2818_battery_remove,
653 .suspend = rk2818_battery_suspend,
654 .resume = rk2818_battery_resume,
656 .name = "rk2818-battery",
657 .owner = THIS_MODULE,
661 static int __init rk2818_battery_init(void)
663 return platform_driver_register(&rk2818_battery_device);
666 static void __exit rk2818_battery_exit(void)
668 platform_driver_unregister(&rk2818_battery_device);
671 module_init(rk2818_battery_init);
672 module_exit(rk2818_battery_exit);
674 MODULE_DESCRIPTION("Battery detect driver for the rk2818");
675 MODULE_AUTHOR("luowei lw@rock-chips.com");
676 MODULE_LICENSE("GPL");