Changeset 19505


Ignore:
Timestamp:
2010-02-03T17:08:01+01:00 (6 years ago)
Author:
lars
Message:

[xburst] Cleanup battery driver

Location:
trunk/target/linux/xburst/files-2.6.32
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/xburst/files-2.6.32/drivers/power/jz4740-battery.c

    r19504 r19505  
    11/* 
    22 * Battery measurement code for Ingenic JZ SOC. 
     3 * 
     4 * Copyright (C) 2009 Jiejing Zhang <kzjeef@gmail.com> 
     5 * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> 
    36 * 
    47 * based on tosa_battery.c 
    58 * 
    69 * Copyright (C) 2008 Marek Vasut <marek.vasut@gmail.com> 
    7  * Copyright (C) 2009 Jiejing Zhang <kzjeef@gmail.com> 
    8  * 
     10* 
    911 * This program is free software; you can redistribute it and/or modify 
    1012 * it under the terms of the GNU General Public License version 2 as 
     
    2022#include <linux/platform_device.h> 
    2123#include <linux/gpio.h> 
     24#include <linux/interrupt.h> 
    2225 
    2326#include <linux/power/jz4740-battery.h> 
    2427#include <linux/jz4740-adc.h> 
    2528 
    26 struct jz_battery_info { 
    27         struct power_supply bat; 
    28         int bat_status; 
    29         struct jz_batt_info *pdata; 
    30         struct mutex work_lock; 
    31         struct workqueue_struct *monitor_wqueue; 
    32         struct delayed_work bat_work; 
     29struct jz_battery { 
     30        struct jz_battery_platform_data *pdata; 
     31 
     32        int charge_irq; 
     33 
     34        int status; 
     35        long voltage; 
     36 
     37        struct power_supply battery; 
     38        struct delayed_work work; 
    3339}; 
    3440 
    35 #define ps_to_jz_battery(x) container_of((x), struct jz_battery_info, bat); 
    36  
    37 /********************************************************************* 
    38  *              Battery properties 
    39  *********************************************************************/ 
    40  
    41 static long jz_read_bat(struct power_supply *psy) 
    42 { 
    43         struct jz_battery_info *bat_info = ps_to_jz_battery(psy); 
     41static inline struct jz_battery *psy_to_jz_battery(struct power_supply *psy) 
     42{ 
     43        return container_of(psy, struct jz_battery, battery); 
     44} 
     45 
     46static long jz_battery_read_voltage(struct jz_battery *jz_battery) 
     47{ 
     48        struct device *adc = jz_battery->battery.dev->parent->parent; 
    4449        enum jz_adc_battery_scale scale; 
    4550 
    46         if (bat_info->pdata->max_voltag > 2500000) 
     51        if (jz_battery->pdata->info.voltage_max_design > 2500000) 
    4752                scale = JZ_ADC_BATTERY_SCALE_7V5; 
    4853        else 
    4954                scale = JZ_ADC_BATTERY_SCALE_2V5; 
    5055 
    51         return jz4740_adc_read_battery_voltage(psy->dev->parent->parent, scale); 
    52 } 
    53  
    54 static int jz_bat_get_capacity(struct power_supply *psy) 
    55 { 
     56        return jz4740_adc_read_battery_voltage(adc, scale); 
     57} 
     58 
     59static int jz_battery_get_capacity(struct power_supply *psy) 
     60{ 
     61        struct jz_battery *jz_battery = psy_to_jz_battery(psy); 
     62        struct power_supply_info *info = &jz_battery->pdata->info; 
     63        long voltage; 
    5664        int ret; 
    57         struct jz_battery_info *bat_info = ps_to_jz_battery(psy); 
    58  
    59         ret = jz_read_bat(psy); 
    60  
    61         if (ret < 0) 
    62                 return ret; 
    63  
    64         ret = (ret - bat_info->pdata->min_voltag) * 100 
    65                 / (bat_info->pdata->max_voltag - bat_info->pdata->min_voltag); 
     65        int voltage_span; 
     66 
     67        voltage = jz_battery_read_voltage(jz_battery); 
     68 
     69        if (voltage < 0) 
     70                return voltage; 
     71 
     72        voltage_span = info->voltage_max_design - info->voltage_min_design; 
     73        ret = ((voltage - info->voltage_min_design) * 100) / voltage_span; 
    6674 
    6775        if (ret > 100) 
     
    7381} 
    7482 
    75 static int jz_bat_get_property(struct power_supply *psy, 
     83static int jz_battery_get_property(struct power_supply *psy, 
    7684                                enum power_supply_property psp, 
    7785                                union power_supply_propval *val) 
    7886{ 
    79         struct jz_battery_info *bat_info = ps_to_jz_battery(psy) 
    80          
     87        struct jz_battery *jz_battery = psy_to_jz_battery(psy); 
     88        struct power_supply_info *info = &jz_battery->pdata->info; 
     89        long voltage; 
     90 
    8191        switch (psp) { 
    8292        case POWER_SUPPLY_PROP_STATUS: 
    83                 val->intval = bat_info->bat_status; 
     93                val->intval = jz_battery->status; 
    8494                break; 
    8595        case POWER_SUPPLY_PROP_TECHNOLOGY: 
    86                 val->intval = bat_info->pdata->batt_tech; 
     96                val->intval = jz_battery->pdata->info.technology; 
    8797                break; 
    8898        case POWER_SUPPLY_PROP_HEALTH: 
    89                 if(jz_read_bat(psy) < bat_info->pdata->min_voltag) { 
    90                         dev_dbg(psy->dev, "%s: battery is dead," 
    91                                 "voltage too low!\n", __func__); 
     99                voltage = jz_battery_read_voltage(jz_battery); 
     100                if (voltage < info->voltage_min_design) 
    92101                        val->intval = POWER_SUPPLY_HEALTH_DEAD; 
    93                 } else { 
    94                         dev_dbg(psy->dev, "%s: battery is good," 
    95                                 "voltage normal.\n", __func__); 
     102                else 
    96103                        val->intval = POWER_SUPPLY_HEALTH_GOOD; 
    97                 } 
    98104                break; 
    99105        case POWER_SUPPLY_PROP_CAPACITY: 
    100                 val->intval = jz_bat_get_capacity(psy); 
    101                 dev_dbg(psy->dev, "%s: battery_capacity = %d\n", 
    102                         __func__, val->intval); 
     106                val->intval = jz_battery_get_capacity(psy); 
    103107                break; 
    104108        case POWER_SUPPLY_PROP_VOLTAGE_NOW: 
    105                 val->intval = jz_read_bat(psy); 
     109                val->intval = jz_battery_read_voltage(jz_battery); 
    106110                if (val->intval < 0) 
    107111                        return val->intval; 
    108112                break; 
    109         case POWER_SUPPLY_PROP_VOLTAGE_MAX: 
    110113        case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 
    111                 val->intval = bat_info->pdata->max_voltag; 
     114                val->intval = info->voltage_max_design; 
    112115                break; 
    113116        case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 
    114                 val->intval = bat_info->pdata->min_voltag; 
     117                val->intval = info->voltage_min_design; 
    115118                break; 
    116119        case POWER_SUPPLY_PROP_PRESENT: 
     
    123126} 
    124127 
    125 static void jz_bat_external_power_changed(struct power_supply *psy) 
    126 { 
    127         struct jz_battery_info *bat_info = ps_to_jz_battery(psy); 
    128          
    129         cancel_delayed_work(&bat_info->bat_work); 
    130         queue_delayed_work(bat_info->monitor_wqueue, &bat_info->bat_work, HZ / 8); 
    131 } 
    132  
    133 static char *status_text[] = { 
    134         [POWER_SUPPLY_STATUS_UNKNOWN] =         "Unknown", 
    135         [POWER_SUPPLY_STATUS_CHARGING] =        "Charging", 
    136         [POWER_SUPPLY_STATUS_DISCHARGING] =     "Discharging", 
    137         [POWER_SUPPLY_STATUS_NOT_CHARGING] =    "Not charging", 
    138 }; 
    139  
    140 static void jz_bat_update(struct power_supply *psy) 
    141 { 
    142         struct jz_battery_info *bat_info = ps_to_jz_battery(psy); 
    143                  
    144         int old_status = bat_info->bat_status; 
    145         static unsigned long old_batt_vol = 0; 
    146         unsigned long batt_vol = jz_read_bat(psy); 
    147          
    148         mutex_lock(&bat_info->work_lock); 
    149  
    150         if (gpio_is_valid(bat_info->pdata->charg_stat_gpio)) { 
    151                 if(!gpio_get_value(bat_info->pdata->charg_stat_gpio)) 
    152                         bat_info->bat_status = POWER_SUPPLY_STATUS_CHARGING; 
     128static void jz_battery_external_power_changed(struct power_supply *psy) 
     129{ 
     130        struct jz_battery *jz_battery = psy_to_jz_battery(psy); 
     131 
     132        cancel_delayed_work(&jz_battery->work); 
     133        schedule_delayed_work(&jz_battery->work, 0); 
     134} 
     135 
     136static irqreturn_t jz_battery_charge_irq(int irq, void *data) 
     137{ 
     138        struct jz_battery *jz_battery = data; 
     139 
     140        cancel_delayed_work(&jz_battery->work); 
     141        schedule_delayed_work(&jz_battery->work, 0); 
     142 
     143        return IRQ_HANDLED; 
     144} 
     145 
     146static void jz_battery_update(struct jz_battery *jz_battery) 
     147{ 
     148        int status; 
     149        long voltage; 
     150        long voltage_difference; 
     151        bool has_changed = 0; 
     152 
     153        if (gpio_is_valid(jz_battery->pdata->gpio_charge)) { 
     154                int is_charging; 
     155 
     156                is_charging = gpio_get_value(jz_battery->pdata->gpio_charge); 
     157                is_charging ^= jz_battery->pdata->gpio_charge_active_low; 
     158                if (is_charging) 
     159                        status = POWER_SUPPLY_STATUS_CHARGING; 
    153160                else 
    154                         bat_info->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING; 
    155                 dev_dbg(psy->dev, "%s: battery status=%s\n", 
    156                         __func__, status_text[bat_info->bat_status]); 
    157                  
    158                 if (old_status != bat_info->bat_status) { 
    159                         dev_dbg(psy->dev, "%s %s -> %s\n", 
    160                                 psy->name, 
    161                                 status_text[old_status], 
    162                                 status_text[bat_info->bat_status]); 
    163  
    164                         power_supply_changed(psy); 
     161                        status = POWER_SUPPLY_STATUS_NOT_CHARGING; 
     162 
     163                if (status != jz_battery->status) { 
     164                        jz_battery->status = status; 
     165                        has_changed = 1; 
    165166                } 
    166167        } 
    167168 
    168         if (old_batt_vol - batt_vol > 50000) { 
    169                 dev_dbg(psy->dev, "voltage change : %ld -> %ld\n", 
    170                         old_batt_vol, batt_vol); 
    171                 power_supply_changed(psy); 
    172                 old_batt_vol = batt_vol; 
    173         } 
    174  
    175         mutex_unlock(&bat_info->work_lock); 
    176 } 
    177  
    178 static enum power_supply_property jz_bat_main_props[] = { 
     169        voltage = jz_battery_read_voltage(jz_battery); 
     170        voltage_difference = voltage - jz_battery->voltage; 
     171        if (voltage_difference > 50000 || voltage_difference < 50000) { 
     172                jz_battery->voltage = voltage; 
     173                has_changed = 1; 
     174        } 
     175        if (has_changed) 
     176                power_supply_changed(&jz_battery->battery); 
     177} 
     178 
     179static enum power_supply_property jz_battery_properties[] = { 
    179180        POWER_SUPPLY_PROP_STATUS, 
    180181        POWER_SUPPLY_PROP_TECHNOLOGY, 
    181182        POWER_SUPPLY_PROP_HEALTH, 
    182         POWER_SUPPLY_PROP_CAPACITY, /* in percents! */ 
     183        POWER_SUPPLY_PROP_CAPACITY, 
    183184        POWER_SUPPLY_PROP_VOLTAGE_NOW, 
    184         POWER_SUPPLY_PROP_VOLTAGE_MAX, 
     185        POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 
    185186        POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 
    186187        POWER_SUPPLY_PROP_PRESENT, 
    187188}; 
    188189 
    189 struct power_supply bat_ps = { 
    190         .name                   = "battery", 
    191         .type                   = POWER_SUPPLY_TYPE_BATTERY, 
    192         .properties             = jz_bat_main_props, 
    193         .num_properties         = ARRAY_SIZE(jz_bat_main_props), 
    194         .get_property           = jz_bat_get_property, 
    195         .external_power_changed = jz_bat_external_power_changed, 
    196         .use_for_apm            = 1, 
    197 }; 
    198  
    199 static void jz_bat_work(struct work_struct *work) 
    200 { 
    201         /* query interval too small will increase system workload*/ 
     190static void jz_battery_work(struct work_struct *work) 
     191{ 
     192        /* Too small interval will increase system workload */ 
    202193        const int interval = HZ * 30; 
    203         struct jz_battery_info *bat_info = container_of(work,struct jz_battery_info, bat_work.work); 
    204  
    205         jz_bat_update(&bat_info->bat); 
    206         queue_delayed_work(bat_info->monitor_wqueue, 
    207                            &bat_info->bat_work, interval); 
    208 } 
    209  
    210 #ifdef CONFIG_PM 
    211 static int jz_bat_suspend(struct platform_device *pdev, pm_message_t state) 
    212 { 
    213         struct jz_battery_info *bat_info = platform_get_drvdata(pdev); 
    214          
    215         bat_info->bat_status =  POWER_SUPPLY_STATUS_UNKNOWN; 
    216  
    217         return 0; 
    218 } 
    219  
    220 static int jz_bat_resume(struct platform_device *pdev) 
    221 { 
    222         struct jz_battery_info *bat_info = platform_get_drvdata(pdev); 
    223  
    224         bat_info->bat_status =  POWER_SUPPLY_STATUS_UNKNOWN; 
    225  
    226         cancel_delayed_work(&bat_info->bat_work); 
    227         queue_delayed_work(bat_info->monitor_wqueue, &bat_info->bat_work, HZ/10); 
    228  
    229         return 0; 
    230 } 
    231 #else 
    232 #define jz_bat_suspend NULL 
    233 #define jz_bat_resume NULL 
    234 #endif 
    235  
    236 static int jz_bat_probe(struct platform_device *pdev) 
     194        struct jz_battery *jz_battery = container_of(work, struct jz_battery, 
     195                                            work.work); 
     196 
     197        jz_battery_update(jz_battery); 
     198        schedule_delayed_work(&jz_battery->work, interval); 
     199} 
     200 
     201static int jz_battery_probe(struct platform_device *pdev) 
    237202{ 
    238203        int ret = 0; 
    239         struct jz_battery_info *bat_info; 
     204        struct jz_battery_platform_data *pdata = pdev->dev.platform_data; 
     205        struct jz_battery *jz_battery; 
     206        struct power_supply *battery; 
    240207 
    241208        if (!pdev->dev.platform_data) { 
    242                 dev_err(&pdev->dev, "Please set battery info\n"); 
     209                dev_err(&pdev->dev, "No platform data\n"); 
    243210                return -EINVAL; 
    244211        } 
    245212 
    246         bat_info = kzalloc(sizeof(struct jz_battery_info), GFP_KERNEL); 
    247  
    248         if (!bat_info) { 
     213        jz_battery = kzalloc(sizeof(*jz_battery), GFP_KERNEL); 
     214 
     215        if (!jz_battery) { 
     216                dev_err(&pdev->dev, "Failed to allocate driver structure\n"); 
    249217                return -ENOMEM; 
    250218        } 
    251219 
    252         platform_set_drvdata(pdev, bat_info); 
    253         bat_info->pdata = pdev->dev.platform_data; 
    254         bat_info->bat = bat_ps; 
    255         mutex_init(&bat_info->work_lock); 
    256         INIT_DELAYED_WORK(&bat_info->bat_work, jz_bat_work); 
    257  
    258         if (gpio_is_valid(bat_info->pdata->charg_stat_gpio)) { 
    259                 ret = gpio_request(bat_info->pdata->charg_stat_gpio, "CHARG STAT"); 
     220        battery = &jz_battery->battery; 
     221        battery->name = pdata->info.name; 
     222        battery->type = POWER_SUPPLY_TYPE_BATTERY; 
     223        battery->properties     = jz_battery_properties; 
     224        battery->num_properties = ARRAY_SIZE(jz_battery_properties); 
     225        battery->get_property = jz_battery_get_property; 
     226        battery->external_power_changed = jz_battery_external_power_changed; 
     227        battery->use_for_apm = 1; 
     228 
     229        jz_battery->pdata = pdata; 
     230 
     231        INIT_DELAYED_WORK(&jz_battery->work, jz_battery_work); 
     232 
     233        if (gpio_is_valid(pdata->gpio_charge)) { 
     234                ret = gpio_request(pdata->gpio_charge, dev_name(&pdev->dev)); 
    260235                if (ret) { 
    261236                        dev_err(&pdev->dev, "charger state gpio request failed.\n"); 
    262                         goto err_charg_gpio_request; 
     237                        goto err_free; 
    263238                } 
    264                 ret = gpio_direction_input(bat_info->pdata->charg_stat_gpio); 
     239                ret = gpio_direction_input(pdata->gpio_charge); 
    265240                if (ret) { 
    266241                        dev_err(&pdev->dev, "charger state gpio set direction failed.\n"); 
    267                         goto err_charg_gpio_direction; 
     242                        goto err_free_gpio; 
    268243                } 
    269244 
    270                 ret = power_supply_register(&pdev->dev, &bat_info->bat); 
    271                 if (ret) { 
    272                         dev_err(&pdev->dev, "power supply battery register failed.\n"); 
    273                         goto err_power_register_bat; 
    274                 } else { 
    275                         bat_info->monitor_wqueue = create_singlethread_workqueue("jz_battery"); 
    276                         if (!bat_info->monitor_wqueue) { 
    277                                 return -ESRCH; 
     245                jz_battery->charge_irq = gpio_to_irq(pdata->gpio_charge); 
     246 
     247                if (jz_battery->charge_irq >= 0) { 
     248                        ret = request_irq(jz_battery->charge_irq, 
     249                                    jz_battery_charge_irq, 
     250                                    IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 
     251                                    dev_name(&pdev->dev), jz_battery); 
     252                        if (ret) { 
     253                                dev_err(&pdev->dev, "Failed to request charge irq: %d\n", ret); 
     254                                goto err_free_gpio; 
    278255                        } 
    279                         queue_delayed_work(bat_info->monitor_wqueue, &bat_info->bat_work, HZ * 1); 
    280256                } 
    281         } 
    282         printk(KERN_INFO "jz_bat init success.\n"); 
     257        } else { 
     258                jz_battery->charge_irq = -1; 
     259        } 
     260 
     261 
     262        ret = power_supply_register(&pdev->dev, &jz_battery->battery); 
     263        if (ret) { 
     264                dev_err(&pdev->dev, "power supply battery register failed.\n"); 
     265                goto err_free_irq; 
     266        } 
     267 
     268        platform_set_drvdata(pdev, jz_battery); 
     269        schedule_delayed_work(&jz_battery->work, 0); 
     270 
     271        return 0; 
     272 
     273err_free_irq: 
     274        if (jz_battery->charge_irq >= 0) 
     275                free_irq(jz_battery->charge_irq, jz_battery); 
     276err_free_gpio: 
     277        if (gpio_is_valid(pdata->gpio_charge)) 
     278                gpio_free(jz_battery->pdata->gpio_charge); 
     279err_free: 
     280        kfree(jz_battery); 
    283281        return ret; 
    284  
    285 err_power_register_bat: 
    286 err_charg_gpio_direction: 
    287         gpio_free(bat_info->pdata->charg_stat_gpio); 
    288 err_charg_gpio_request: 
    289         kfree(bat_info); 
    290         return ret; 
    291 } 
    292  
    293 static int jz_bat_remove(struct platform_device *pdev) 
    294 { 
    295         struct jz_battery_info *bat_info = platform_get_drvdata(pdev); 
    296  
    297         if (bat_info->pdata) { 
    298                 if (gpio_is_valid(bat_info->pdata->charg_stat_gpio)) 
    299                         gpio_free(bat_info->pdata->charg_stat_gpio); 
    300         } 
    301  
    302         power_supply_unregister(&bat_ps); 
    303  
    304         return 0; 
    305 } 
    306  
    307 static struct platform_driver jz_bat_driver = { 
    308         .probe          = jz_bat_probe, 
    309         .remove         = __devexit_p(jz_bat_remove), 
    310         .suspend        = jz_bat_suspend, 
    311         .resume         = jz_bat_resume, 
     282} 
     283 
     284static int jz_battery_remove(struct platform_device *pdev) 
     285{ 
     286        struct jz_battery *jz_battery = platform_get_drvdata(pdev); 
     287 
     288        cancel_delayed_work_sync(&jz_battery->work); 
     289 
     290        if (gpio_is_valid(jz_battery->pdata->gpio_charge)) { 
     291                if (jz_battery->charge_irq >= 0) 
     292                        free_irq(jz_battery->charge_irq, jz_battery); 
     293                gpio_free(jz_battery->pdata->gpio_charge); 
     294        } 
     295 
     296        power_supply_unregister(&jz_battery->battery); 
     297 
     298        return 0; 
     299} 
     300 
     301#ifdef CONFIG_PM 
     302static int jz_battery_suspend(struct platform_device *pdev, pm_message_t state) 
     303{ 
     304        struct jz_battery *jz_battery = platform_get_drvdata(pdev); 
     305 
     306        cancel_delayed_work_sync(&jz_battery->work); 
     307        jz_battery->status =  POWER_SUPPLY_STATUS_UNKNOWN; 
     308 
     309        return 0; 
     310} 
     311 
     312static int jz_battery_resume(struct platform_device *pdev) 
     313{ 
     314        struct jz_battery *jz_battery = platform_get_drvdata(pdev); 
     315 
     316        schedule_delayed_work(&jz_battery->work, 0); 
     317 
     318        return 0; 
     319} 
     320#else 
     321#define jz_battery_suspend NULL 
     322#define jz_battery_resume NULL 
     323#endif 
     324 
     325static struct platform_driver jz_battery_driver = { 
     326        .probe          = jz_battery_probe, 
     327        .remove         = __devexit_p(jz_battery_remove), 
     328        .suspend        = jz_battery_suspend, 
     329        .resume         = jz_battery_resume, 
    312330        .driver = { 
    313331                .name = "jz4740-battery", 
     
    316334}; 
    317335 
    318 static int __init jz_bat_init(void) 
    319 { 
    320         return platform_driver_register(&jz_bat_driver); 
    321 } 
    322 module_init(jz_bat_init); 
    323  
    324 static void __exit jz_bat_exit(void) 
    325 { 
    326         platform_driver_unregister(&jz_bat_driver); 
    327 } 
    328 module_exit(jz_bat_exit); 
     336static int __init jz_battery_init(void) 
     337{ 
     338        return platform_driver_register(&jz_battery_driver); 
     339} 
     340module_init(jz_battery_init); 
     341 
     342static void __exit jz_battery_exit(void) 
     343{ 
     344        platform_driver_unregister(&jz_battery_driver); 
     345} 
     346module_exit(jz_battery_exit); 
    329347 
    330348MODULE_LICENSE("GPL"); 
  • trunk/target/linux/xburst/files-2.6.32/include/linux/power/jz4740-battery.h

    r19504 r19505  
    1616#define __JZ4740_BATTERY_H 
    1717 
    18 struct jz_batt_info { 
    19         int charg_stat_gpio;    /* GPIO port of Charger state */ 
    20  
    21         int min_voltag;         /* Mininal battery voltage in uV */ 
    22         int max_voltag;         /* Maximum battery voltage in uV */ 
    23         int batt_tech;          /* Battery technology */ 
     18struct jz_battery_platform_data { 
     19        struct power_supply_info info; 
     20        int gpio_charge;        /* GPIO port of Charger state */ 
     21        int gpio_charge_active_low; 
    2422}; 
    2523 
Note: See TracChangeset for help on using the changeset viewer.