电池电量转换参考

http://blog.csdn.net/yunfly163/article/details/9232031

[cpp]  view plain copy print ?
  1. "code" class="cpp">"code" class="cpp">/** 
  2.  * Driver for batteries with DS2760 chips inside. 
  3.  * 
  4.  * Copyright © 2007 Anton Vorontsov 
  5.  *         2004-2007 Matt Reimer 
  6.  *         2004 Szabolcs Gyurko 
  7.  * 
  8.  * Use consistent with the GNU GPL is permitted, 
  9.  * provided that this copyright notice is 
  10.  * preserved in its entirety in all copies and derived works. 
  11.  * 
  12.  * Author:  Anton Vorontsov  
  13.  *      February 2007 
  14.  * 
  15.  *      Matt Reimer  
  16.  *      April 2004, 2005, 2007 
  17.  * 
  18.  *      Szabolcs Gyurko  
  19.  *      September 2004 
  20.  */  
  21.   
  22. #include   
  23. #include   
  24. #include   
  25. #include   
  26. #include   
  27. #include   
  28. #include   
  29. #include   
  30.   
  31. #include "../w1/w1.h"  
  32. #include "../w1/slaves/w1_ds2760.h"  
  33.   
  34. struct ds2760_device_info {  
  35.     struct device *dev;  
  36.   
  37.     /** DS2760 data, valid after calling ds2760_battery_read_status() */  
  38.     unsigned long update_time;  /** jiffies when data read */  
  39.     char raw[DS2760_DATA_SIZE]; /** raw DS2760 data */  
  40.     int voltage_raw;        /** units of 4.88 mV */  
  41.     int voltage_uV;         /** units of µV */  
  42.     int current_raw;        /** units of 0.625 mA */  
  43.     int current_uA;         /** units of µA */  
  44.     int accum_current_raw;      /** units of 0.25 mAh */  
  45.     int accum_current_uAh;      /** units of µAh */  
  46.     int temp_raw;           /** units of 0.125 °C */  
  47.     int temp_C;         /** units of 0.1 °C */  
  48.     int rated_capacity;     /** units of µAh */  
  49.     int rem_capacity;       /** percentage */  
  50.     int full_active_uAh;        /** units of µAh */  
  51.     int empty_uAh;          /** units of µAh */  
  52.     int life_sec;           /** units of seconds */  
  53.     int charge_status;      /** POWER_SUPPLY_STATUS_* */  
  54.   
  55.     int full_counter;  
  56.     struct power_supply bat;  
  57.     struct device *w1_dev;  
  58.     struct workqueue_struct *monitor_wqueue;  
  59.     struct delayed_work monitor_work;  
  60.     struct delayed_work set_charged_work;  
  61. };  
  62.   
  63. static unsigned int cache_time = 1000;  
  64. module_param(cache_time, uint, 0644);  
  65. MODULE_PARM_DESC(cache_time, "cache time in milliseconds");  
  66.   
  67. static unsigned int pmod_enabled;  
  68. module_param(pmod_enabled, bool, 0644);  
  69. MODULE_PARM_DESC(pmod_enabled, "PMOD enable bit");  
  70.   
  71. static unsigned int rated_capacity;  
  72. module_param(rated_capacity, uint, 0644);  
  73. MODULE_PARM_DESC(rated_capacity, "rated battery capacity, 10*mAh or index");  
  74.   
  75. static unsigned int current_accum;  
  76. module_param(current_accum, uint, 0644);  
  77. MODULE_PARM_DESC(current_accum, "current accumulator value");  
  78.   
  79. /** Some batteries have their rated capacity stored a N * 10 mAh, while 
  80.  * others use an index into this table. */  
  81. static int rated_capacities[] = {  
  82.     0,  
  83.     920,    /** Samsung */  
  84.     920,    /** BYD */  
  85.     920,    /** Lishen */  
  86.     920,    /** NEC */  
  87.     1440,   /** Samsung */  
  88.     1440,   /** BYD */  
  89.     1440,   /** Lishen */  
  90.     1440,   /** NEC */  
  91.     2880,   /** Samsung */  
  92.     2880,   /** BYD */  
  93.     2880,   /** Lishen */  
  94.     2880    /** NEC */  
  95. };  
  96.   
  97. /** array is level at temps 0°C, 10°C, 20°C, 30°C, 40°C 
  98.  * temp is in Celsius */  
  99. static int battery_interpolate(int array[], int temp)  
  100. {  
  101.     int index, dt;  
  102.   
  103.     if (temp <= 0)  
  104.         return array[0];  
  105.     if (temp >= 40)  
  106.         return array[4];  
  107.   
  108.     index = temp / 10;  
  109.     dt    = temp % 10;  
  110.   
  111.     return array[index] + (((array[index + 1] - array[index]) * dt) / 10);  
  112. }  
  113.   
  114. static int ds2760_battery_read_status(struct ds2760_device_info *di)  
  115. {  
  116.     int ret, i, start, count, scale[5];  
  117.   
  118.     if (di->update_time && time_before(jiffies, di->update_time +  
  119.                        msecs_to_jiffies(cache_time)))  
  120.         return 0;  
  121.   
  122.     /** The first time we read the entire contents of SRAM/EEPROM, 
  123.      * but after that we just read the interesting bits that change. */  
  124.     if (di->update_time == 0) {  
  125.         start = 0;  
  126.         count = DS2760_DATA_SIZE;  
  127.     } else {  
  128.         start = DS2760_VOLTAGE_MSB;  
  129.         count = DS2760_TEMP_LSB - start + 1;  
  130.     }  
  131.   
  132.     ret = w1_ds2760_read(di->w1_dev, di->raw + start, start, count);  
  133.     if (ret != count) {  
  134.         dev_warn(di->dev, "call to w1_ds2760_read failed (0x%p)\n",  
  135.              di->w1_dev);  
  136.         return 1;  
  137.     }  
  138.   
  139.     di->update_time = jiffies;  
  140.   
  141.     /** DS2760 reports voltage in units of 4.88mV, but the battery class 
  142.      * reports in units of uV, so convert by multiplying by 4880. */  
  143.     di->voltage_raw = (di->raw[DS2760_VOLTAGE_MSB] << 3) |  
  144.               (di->raw[DS2760_VOLTAGE_LSB] >> 5);  
  145.     di->voltage_uV = di->voltage_raw * 4880;  
  146.   
  147.     /** DS2760 reports current in signed units of 0.625mA, but the battery 
  148.      * class reports in units of µA, so convert by multiplying by 625. */  
  149.     di->current_raw =  
  150.         (((signed char)di->raw[DS2760_CURRENT_MSB]) << 5) |  
  151.               (di->raw[DS2760_CURRENT_LSB] >> 3);  
  152.     di->current_uA = di->current_raw * 625;  
  153.   
  154.     /** DS2760 reports accumulated current in signed units of 0.25mAh. */  
  155.     di->accum_current_raw =  
  156.         (((signed char)di->raw[DS2760_CURRENT_ACCUM_MSB]) << 8) |  
  157.                di->raw[DS2760_CURRENT_ACCUM_LSB];  
  158.     di->accum_current_uAh = di->accum_current_raw * 250;  
  159.   
  160.     /** DS2760 reports temperature in signed units of 0.125°C, but the 
  161.      * battery class reports in units of 1/10 °C, so we convert by 
  162.      * multiplying by .125 * 10 = 1.25. */  
  163.     di->temp_raw = (((signed char)di->raw[DS2760_TEMP_MSB]) << 3) |  
  164.                      (di->raw[DS2760_TEMP_LSB] >> 5);  
  165.     di->temp_C = di->temp_raw + (di->temp_raw / 4);  
  166.   
  167.     /** At least some battery monitors (e.g. HP iPAQ) store the battery's 
  168.      * maximum rated capacity. */  
  169.     if (di->raw[DS2760_RATED_CAPACITY] < ARRAY_SIZE(rated_capacities))  
  170.         di->rated_capacity = rated_capacities[  
  171.             (unsigned int)di->raw[DS2760_RATED_CAPACITY]];  
  172.     else  
  173.         di->rated_capacity = di->raw[DS2760_RATED_CAPACITY] * 10;  
  174.   
  175.     di->rated_capacity *= 1000; /** convert to µAh */  
  176.   
  177.     /** Calculate the full level at the present temperature. */  
  178.     di->full_active_uAh = di->raw[DS2760_ACTIVE_FULL] << 8 |  
  179.                   di->raw[DS2760_ACTIVE_FULL + 1];  
  180.   
  181.     /** If the full_active_uAh value is not given, fall back to the rated 
  182.      * capacity. This is likely to happen when chips are not part of the 
  183.      * battery pack and is therefore not bootstrapped. */  
  184.     if (di->full_active_uAh == 0)  
  185.         di->full_active_uAh = di->rated_capacity / 1000L;  
  186.   
  187.     scale[0] = di->full_active_uAh;  
  188.     for (i = 1; i < 5; i++)  
  189.         scale[i] = scale[i - 1] + di->raw[DS2760_ACTIVE_FULL + 2 + i];  
  190.   
  191.     di->full_active_uAh = battery_interpolate(scale, di->temp_C / 10);  
  192.     di->full_active_uAh *= 1000; /** convert to µAh */  
  193.   
  194.     /** Calculate the empty level at the present temperature. */  
  195.     scale[4] = di->raw[DS2760_ACTIVE_EMPTY + 4];  
  196.     for (i = 3; i >= 0; i--)  
  197.         scale[i] = scale[i + 1] + di->raw[DS2760_ACTIVE_EMPTY + i];  
  198.   
  199.     di->empty_uAh = battery_interpolate(scale, di->temp_C / 10);  
  200.     di->empty_uAh *= 1000; /** convert to µAh */  
  201.   
  202.     if (di->full_active_uAh == di->empty_uAh)  
  203.         di->rem_capacity = 0;  
  204.     else  
  205.         /** From Maxim Application Note 131: remaining capacity = 
  206.          * ((ICA - Empty Value) / (Full Value - Empty Value)) x 100% */  
  207.         di->rem_capacity = ((di->accum_current_uAh - di->empty_uAh) * 100L) /  
  208.                     (di->full_active_uAh - di->empty_uAh);  
  209.   
  210.     if (di->rem_capacity < 0)  
  211.         di->rem_capacity = 0;  
  212.     if (di->rem_capacity > 100)  
  213.         di->rem_capacity = 100;  
  214.   
  215.     if (di->current_uA >= 100L)  
  216.         di->life_sec = -((di->accum_current_uAh - di->empty_uAh) * 36L)  
  217.                     / (di->current_uA / 100L);  
  218.     else  
  219.         di->life_sec = 0;  
  220.   
  221.     return 0;  
  222. }  
  223.   
  224. static void ds2760_battery_set_current_accum(struct ds2760_device_info *di,  
  225.                          unsigned int acr_val)  
  226. {  
  227.     unsigned char acr[2];  
  228.   
  229.     /** acr is in units of 0.25 mAh */  
  230.     acr_val *= 4L;  
  231.     acr_val /= 1000;  
  232.   
  233.     acr[0] = acr_val >> 8;  
  234.     acr[1] = acr_val & 0xff;  
  235.   
  236.     if (w1_ds2760_write(di->w1_dev, acr, DS2760_CURRENT_ACCUM_MSB, 2) < 2)  
  237.         dev_warn(di->dev, "ACR write failed\n");  
  238. }  
  239.   
  240. static void ds2760_battery_update_status(struct ds2760_device_info *di)  
  241. {  
  242.     int old_charge_status = di->charge_status;  
  243.   
  244.     ds2760_battery_read_status(di);  
  245.   
  246.     if (di->charge_status == POWER_SUPPLY_STATUS_UNKNOWN)  
  247.         di->full_counter = 0;  
  248.   
  249.     if (power_supply_am_i_supplied(&di->bat)) {  
  250.         if (di->current_uA > 10000) {  
  251.             di->charge_status = POWER_SUPPLY_STATUS_CHARGING;  
  252.             di->full_counter = 0;  
  253.         } else if (di->current_uA < -5000) {  
  254.             if (di->charge_status != POWER_SUPPLY_STATUS_NOT_CHARGING)  
  255.                 dev_notice(di->dev, "not enough power to "  
  256.                        "charge\n");  
  257.             di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;  
  258.             di->full_counter = 0;  
  259.         } else if (di->current_uA < 10000 &&  
  260.                 di->charge_status != POWER_SUPPLY_STATUS_FULL) {  
  261.   
  262.             /** Don't consider the battery to be full unless 
  263.              * we've seen the current < 10 mA at least two 
  264.              * consecutive times. */  
  265.   
  266.             di->full_counter++;  
  267.   
  268.             if (di->full_counter < 2) {  
  269.                 di->charge_status = POWER_SUPPLY_STATUS_CHARGING;  
  270.             } else {  
  271.                 di->charge_status = POWER_SUPPLY_STATUS_FULL;  
  272.                 ds2760_battery_set_current_accum(di,  
  273.                         di->full_active_uAh);  
  274.             }  
  275.         }  
  276.     } else {  
  277.         di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;  
  278.         di->full_counter = 0;  
  279.     }  
  280.   
  281.     if (di->charge_status != old_charge_status)  
  282.         power_supply_changed(&di->bat);  
  283. }  
  284.   
  285. static void ds2760_battery_write_status(struct ds2760_device_info *di,  
  286.                     char status)  
  287. {  
  288.     if (status == di->raw[DS2760_STATUS_REG])  
  289.         return;  
  290.   
  291.     w1_ds2760_write(di->w1_dev, &status, DS2760_STATUS_WRITE_REG, 1);  
  292.     w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);  
  293.     w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);  
  294. }  
  295.   
  296. static void ds2760_battery_write_rated_capacity(struct ds2760_device_info *di,  
  297.                         unsigned char rated_capacity)  
  298. {  
  299.     if (rated_capacity == di->raw[DS2760_RATED_CAPACITY])  
  300.         return;  
  301.   
  302.     w1_ds2760_write(di->w1_dev, &rated_capacity, DS2760_RATED_CAPACITY, 1);  
  303.     w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);  
  304.     w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);  
  305. }  
  306.   
  307. static void ds2760_battery_write_active_full(struct ds2760_device_info *di,  
  308.                          int active_full)  
  309. {  
  310.     unsigned char tmp[2] = {  
  311.         active_full >> 8,  
  312.         active_full & 0xff  
  313.     };  
  314.   
  315.     if (tmp[0] == di->raw[DS2760_ACTIVE_FULL] &&  
  316.         tmp[1] == di->raw[DS2760_ACTIVE_FULL + 1])  
  317.         return;  
  318.   
  319.     w1_ds2760_write(di->w1_dev, tmp, DS2760_ACTIVE_FULL, sizeof(tmp));  
  320.     w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK0);  
  321.     w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK0);  
  322.   
  323.     /** Write to the di->raw[] buffer directly - the DS2760_ACTIVE_FULL 
  324.      * values won't be read back by ds2760_battery_read_status() */  
  325.     di->raw[DS2760_ACTIVE_FULL] = tmp[0];  
  326.     di->raw[DS2760_ACTIVE_FULL + 1] = tmp[1];  
  327. }  
  328.   
  329. static void ds2760_battery_work(struct work_struct *work)  
  330. {  
  331.     struct ds2760_device_info *di = container_of(work,  
  332.         struct ds2760_device_info, monitor_work.work);  
  333.     const int interval = HZ * 60;  
  334.   
  335.     dev_dbg(di->dev, "%s\n", __func__);  
  336.   
  337.     ds2760_battery_update_status(di);  
  338.     queue_delayed_work(di->monitor_wqueue, &di->monitor_work, interval);  
  339. }  
  340.   
  341. #define to_ds2760_device_info(x) container_of((x), struct ds2760_device_info, \  
  342.                           bat);  
  343.   
  344. static void ds2760_battery_external_power_changed(struct power_supply *psy)  
  345. {  
  346.     struct ds2760_device_info *di = to_ds2760_device_info(psy);  
  347.   
  348.     dev_dbg(di->dev, "%s\n", __func__);  
  349.   
  350.     cancel_delayed_work(&di->monitor_work);  
  351.     queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ/10);  
  352. }  
  353.   
  354.   
  355. static void ds2760_battery_set_charged_work(struct work_struct *work)  
  356. {  
  357.     char bias;  
  358.     struct ds2760_device_info *di = container_of(work,  
  359.         struct ds2760_device_info, set_charged_work.work);  
  360.   
  361.     dev_dbg(di->dev, "%s\n", __func__);  
  362.   
  363.     ds2760_battery_read_status(di);  
  364.   
  365.     /** When we get notified by external circuitry that the battery is 
  366.      * considered fully charged now, we know that there is no current 
  367.      * flow any more. However, the ds2760's internal current meter is 
  368.      * too inaccurate to rely on - spec say something ~15% failure. 
  369.      * Hence, we use the current offset bias register to compensate 
  370.      * that error. 
  371.      */  
  372.   
  373.     if (!power_supply_am_i_supplied(&di->bat))  
  374.         return;  
  375.   
  376.     bias = (signed char) di->current_raw +  
  377.         (signed char) di->raw[DS2760_CURRENT_OFFSET_BIAS];  
  378.   
  379.     dev_dbg(di->dev, "%s: bias = %d\n", __func__, bias);  
  380.   
  381.     w1_ds2760_write(di->w1_dev, &bias, DS2760_CURRENT_OFFSET_BIAS, 1);  
  382.     w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);  
  383.     w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);  
  384.   
  385.     /** Write to the di->raw[] buffer directly - the CURRENT_OFFSET_BIAS 
  386.      * value won't be read back by ds2760_battery_read_status() */  
  387.     di->raw[DS2760_CURRENT_OFFSET_BIAS] = bias;  
  388. }  
  389.   
  390. static void ds2760_battery_set_charged(struct power_supply *psy)  
  391. {  
  392.     struct ds2760_device_info *di = to_ds2760_device_info(psy);  
  393.   
  394.     /** postpone the actual work by 20 secs. This is for debouncing GPIO 
  395.      * signals and to let the current value settle. See AN4188. */  
  396.     cancel_delayed_work(&di->set_charged_work);  
  397.     queue_delayed_work(di->monitor_wqueue, &di->set_charged_work, HZ * 20);  
  398. }  
  399.   
  400. static int ds2760_battery_get_property(struct power_supply *psy,  
  401.                        enum power_supply_property psp,  
  402.                        union power_supply_propval *val)  
  403. {  
  404.     struct ds2760_device_info *di = to_ds2760_device_info(psy);  
  405.   
  406.     switch (psp) {  
  407.     case POWER_SUPPLY_PROP_STATUS:  
  408.         val->intval = di->charge_status;  
  409.         return 0;  
  410.     default:  
  411.         break;  
  412.     }  
  413.   
  414.     ds2760_battery_read_status(di);  
  415.   
  416.     switch (psp) {  
  417.     case POWER_SUPPLY_PROP_VOLTAGE_NOW:  
  418.         val->intval = di->voltage_uV;  
  419.         break;  
  420.     case POWER_SUPPLY_PROP_CURRENT_NOW:  
  421.         val->intval = di->current_uA;  
  422.         break;  
  423.     case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:  
  424.         val->intval = di->rated_capacity;  
  425.         break;  
  426.     case POWER_SUPPLY_PROP_CHARGE_FULL:  
  427.         val->intval = di->full_active_uAh;  
  428.         break;  
  429.     case POWER_SUPPLY_PROP_CHARGE_EMPTY:  
  430.         val->intval = di->empty_uAh;  
  431.         break;  
  432.     case POWER_SUPPLY_PROP_CHARGE_NOW:  
  433.         val->intval = di->accum_current_uAh;  
  434.         break;  
  435.     case POWER_SUPPLY_PROP_TEMP:  
  436.         val->intval = di->temp_C;  
  437.         break;  
  438.     case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:  
  439.         val->intval = di->life_sec;  
  440.         break;  
  441.     case POWER_SUPPLY_PROP_CAPACITY:  
  442.         val->intval = di->rem_capacity;  
  443.         break;  
  444.     default:  
  445.         return -EINVAL;  
  446.     }  
  447.   
  448.     return 0;  
  449. }  
  450.   
  451. static int ds2760_battery_set_property(struct power_supply *psy,  
  452.                        enum power_supply_property psp,  
  453.                        const union power_supply_propval *val)  
  454. {  
  455.     struct ds2760_device_info *di = to_ds2760_device_info(psy);  
  456.   
  457.     switch (psp) {  
  458.     case POWER_SUPPLY_PROP_CHARGE_FULL:  
  459.         /** the interface counts in uAh, convert the value */  
  460.         ds2760_battery_write_active_full(di, val->intval / 1000L);  
  461.         break;  
  462.   
  463.     case POWER_SUPPLY_PROP_CHARGE_NOW:  
  464.         /** ds2760_battery_set_current_accum() does the conversion */  
  465.         ds2760_battery_set_current_accum(di, val->intval);  
  466.         break;  
  467.   
  468.     default:  
  469.         return -EPERM;  
  470.     }  
  471.   
  472.     return 0;  
  473. }  
  474.   
  475. static int ds2760_battery_property_is_writeable(struct power_supply *psy,  
  476.                         enum power_supply_property psp)  
  477. {  
  478.     switch (psp) {  
  479.     case POWER_SUPPLY_PROP_CHARGE_FULL:  
  480.     case POWER_SUPPLY_PROP_CHARGE_NOW:  
  481.         return 1;  
  482.   
  483.     default:  
  484.         break;  
  485.     }  
  486.   
  487.     return 0;  
  488. }  
  489.   
  490. static enum power_supply_property ds2760_battery_props[] = {  
  491.     POWER_SUPPLY_PROP_STATUS,  
  492.     POWER_SUPPLY_PROP_VOLTAGE_NOW,  
  493.     POWER_SUPPLY_PROP_CURRENT_NOW,  
  494.     POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,  
  495.     POWER_SUPPLY_PROP_CHARGE_FULL,  
  496.     POWER_SUPPLY_PROP_CHARGE_EMPTY,  
  497.     POWER_SUPPLY_PROP_CHARGE_NOW,  
  498.     POWER_SUPPLY_PROP_TEMP,  
  499.     POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,  
  500.     POWER_SUPPLY_PROP_CAPACITY,  
  501. };  
  502.   
  503. static int ds2760_battery_probe(struct platform_device *pdev)  
  504. {  
  505.     char status;  
  506.     int retval = 0;  
  507.     struct ds2760_device_info *di;  
  508.   
  509.     di = kzalloc(sizeof(*di), GFP_KERNEL);  
  510.     if (!di) {  
  511.         retval = -ENOMEM;  
  512.         goto di_alloc_failed;  
  513.     }  
  514.   
  515.     platform_set_drvdata(pdev, di);  
  516.   
  517.     di->dev          = &pdev->dev;  
  518.     di->w1_dev       = pdev->dev.parent;  
  519.     di->bat.name     = dev_name(&pdev->dev);  
  520.     di->bat.type     = POWER_SUPPLY_TYPE_BATTERY;  
  521.     di->bat.properties   = ds2760_battery_props;  
  522.     di->bat.num_properties   = ARRAY_SIZE(ds2760_battery_props);  
  523.     di->bat.get_property = ds2760_battery_get_property;  
  524.     di->bat.set_property = ds2760_battery_set_property;  
  525.     di->bat.property_is_writeable =  
  526.                   ds2760_battery_property_is_writeable;  
  527.     di->bat.set_charged  = ds2760_battery_set_charged;  
  528.     di->bat.external_power_changed =  
  529.                   ds2760_battery_external_power_changed;  
  530.   
  531.     di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;  
  532.   
  533.     /** enable sleep mode feature */  
  534.     ds2760_battery_read_status(di);  
  535.     status = di->raw[DS2760_STATUS_REG];  
  536.     if (pmod_enabled)  
  537.         status |= DS2760_STATUS_PMOD;  
  538.     else  
  539.         status &= ~DS2760_STATUS_PMOD;  
  540.   
  541.     ds2760_battery_write_status(di, status);  
  542.   
  543.     /** set rated capacity from module param */  
  544.     if (rated_capacity)  
  545.         ds2760_battery_write_rated_capacity(di, rated_capacity);  
  546.   
  547.     /** set current accumulator if given as parameter. 
  548.      * this should only be done for bootstrapping the value */  
  549.     if (current_accum)  
  550.         ds2760_battery_set_current_accum(di, current_accum);  
  551.   
  552.     retval = power_supply_register(&pdev->dev, &di->bat);  
  553.     if (retval) {  
  554.         dev_err(di->dev, "failed to register battery\n");  
  555.         goto batt_failed;  
  556.     }  
  557.   
  558.     INIT_DELAYED_WORK(&di->monitor_work, ds2760_battery_work);  
  559.     INIT_DELAYED_WORK(&di->set_charged_work,  
  560.               ds2760_battery_set_charged_work);  
  561.     di->monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev));  
  562.     if (!di->monitor_wqueue) {  
  563.         retval = -ESRCH;  
  564.         goto workqueue_failed;  
  565.     }  
  566.     queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 1);  
  567.   
  568.     goto success;  
  569.   
  570. workqueue_failed:  
  571.     power_supply_unregister(&di->bat);  
  572. batt_failed:  
  573.     kfree(di);  
  574. di_alloc_failed:  
  575. success:  
  576.     return retval;  
  577. }  
  578.   
  579. static int ds2760_battery_remove(struct platform_device *pdev)  
  580. {  
  581.     struct ds2760_device_info *di = platform_get_drvdata(pdev);  
  582.   
  583.     cancel_rearming_delayed_workqueue(di->monitor_wqueue,  
  584.                       &di->monitor_work);  
  585.     cancel_rearming_delayed_workqueue(di->monitor_wqueue,  
  586.                       &di->set_charged_work);  
  587.     destroy_workqueue(di->monitor_wqueue);  
  588.     power_supply_unregister(&di->bat);  
  589.     kfree(di);  
  590.   
  591.     return 0;  
  592. }  
  593.   
  594. #ifdef CONFIG_PM  
  595.   
  596. static int ds2760_battery_suspend(struct platform_device *pdev,  
  597.                   pm_message_t state)  
  598. {  
  599.     struct ds2760_device_info *di = platform_get_drvdata(pdev);  
  600.   
  601.     di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;  
  602.   
  603.     return 0;  
  604. }  
  605.   
  606. static int ds2760_battery_resume(struct platform_device *pdev)  
  607. {  
  608.     struct ds2760_device_info *di = platform_get_drvdata(pdev);  
  609.   
  610.     di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;  
  611.     power_supply_changed(&di->bat);  
  612.   
  613.     cancel_delayed_work(&di->monitor_work);  
  614.     queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ);  
  615.   
  616.     return 0;  
  617. }  
  618.   
  619. #else  
  620.   
  621. #define ds2760_battery_suspend NULL  
  622. #define ds2760_battery_resume NULL  
  623.   
  624. #endif /** CONFIG_PM */  
  625.   
  626. MODULE_ALIAS("platform:ds2760-battery");  
  627.   
  628. static struct platform_driver ds2760_battery_driver = {  
  629.     .driver = {  
  630.         .name = "ds2760-battery",  
  631.     },  
  632.     .probe    = ds2760_battery_probe,  
  633.     .remove   = ds2760_battery_remove,  
  634.     .suspend  = ds2760_battery_suspend,  
  635.     .resume   = ds2760_battery_resume,  
  636. };  
  637.   
  638. static int __init ds2760_battery_init(void)  
  639. {  
  640.     return platform_driver_register(&ds2760_battery_driver);  
  641. }  
  642.   
  643. static void __exit ds2760_battery_exit(void)  
  644. {  
  645.     platform_driver_unregister(&ds2760_battery_driver);  
  646. }  
  647.   
  648. module_init(ds2760_battery_init);  
  649. module_exit(ds2760_battery_exit);  
  650.   
  651. MODULE_LICENSE("GPL");  
  652. MODULE_AUTHOR("Szabolcs Gyurko , "  
  653.           "Matt Reimer , "  
  654.           "Anton Vorontsov ");  
  655. MODULE_DESCRIPTION("ds2760 battery driver");  

  656.   

  657.   
  658.   
  659.   
  660.   
  661.   
  662.   

你可能感兴趣的:(Q_BATTERY)