Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge git://git.infradead.org/battery-2.6

* git://git.infradead.org/battery-2.6:
da9030_battery: Fix race between event handler and monitor
Add MAX17040 Fuel Gauge driver
w1: ds2760_battery: add support for sleep mode feature
w1: ds2760: add support for EEPROM read and write
ds2760_battery: cleanups in ds2760_battery_probe()

+419 -16
+8
drivers/power/Kconfig
··· 82 82 Say Y here to enable support for batteries charger integrated into 83 83 DA9030 PMIC. 84 84 85 + config BATTERY_MAX17040 86 + tristate "Maxim MAX17040 Fuel Gauge" 87 + depends on I2C 88 + help 89 + MAX17040 is fuel-gauge systems for lithium-ion (Li+) batteries 90 + in handheld and portable equipment. The MAX17040 is configured 91 + to operate with a single lithium cell 92 + 85 93 config CHARGER_PCF50633 86 94 tristate "NXP PCF50633 MBC" 87 95 depends on MFD_PCF50633
+1
drivers/power/Makefile
··· 25 25 obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o 26 26 obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o 27 27 obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o 28 + obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o 28 29 obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
+12 -7
drivers/power/da9030_battery.c
··· 22 22 #include <linux/debugfs.h> 23 23 #include <linux/seq_file.h> 24 24 25 - #define DA9030_STATUS_CHDET (1 << 3) 26 - 27 25 #define DA9030_FAULT_LOG 0x0a 28 26 #define DA9030_FAULT_LOG_OVER_TEMP (1 << 7) 29 27 #define DA9030_FAULT_LOG_VBAT_OVER (1 << 4) ··· 242 244 } 243 245 244 246 da903x_write(charger->master, DA9030_CHARGE_CONTROL, val); 247 + 248 + power_supply_changed(&charger->psy); 245 249 } 246 250 247 251 static void da9030_charger_check_state(struct da9030_charger *charger) ··· 258 258 da9030_set_charge(charger, 1); 259 259 } 260 260 } else { 261 + /* Charger has been pulled out */ 262 + if (!charger->chdet) { 263 + da9030_set_charge(charger, 0); 264 + return; 265 + } 266 + 261 267 if (charger->adc.vbat_res >= 262 268 charger->thresholds.vbat_charge_stop) { 263 269 da9030_set_charge(charger, 0); ··· 401 395 { 402 396 struct da9030_charger *charger = 403 397 container_of(nb, struct da9030_charger, nb); 404 - int status; 405 398 406 399 switch (event) { 407 400 case DA9030_EVENT_CHDET: 408 - status = da903x_query_status(charger->master, 409 - DA9030_STATUS_CHDET); 410 - da9030_set_charge(charger, status); 401 + cancel_delayed_work_sync(&charger->work); 402 + schedule_work(&charger->work.work); 411 403 break; 412 404 case DA9030_EVENT_VBATMON: 413 405 da9030_battery_vbat_event(charger); ··· 569 565 da903x_unregister_notifier(charger->master, &charger->nb, 570 566 DA9030_EVENT_CHDET | DA9030_EVENT_VBATMON | 571 567 DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT); 572 - cancel_delayed_work(&charger->work); 568 + cancel_delayed_work_sync(&charger->work); 569 + da9030_set_charge(charger, 0); 573 570 power_supply_unregister(&charger->psy); 574 571 575 572 kfree(charger);
+33 -9
drivers/power/ds2760_battery.c
··· 62 62 module_param(cache_time, uint, 0644); 63 63 MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); 64 64 65 + static unsigned int pmod_enabled; 66 + module_param(pmod_enabled, bool, 0644); 67 + MODULE_PARM_DESC(pmod_enabled, "PMOD enable bit"); 68 + 65 69 /* Some batteries have their rated capacity stored a N * 10 mAh, while 66 70 * others use an index into this table. */ 67 71 static int rated_capacities[] = { ··· 263 259 power_supply_changed(&di->bat); 264 260 } 265 261 262 + static void ds2760_battery_write_status(struct ds2760_device_info *di, 263 + char status) 264 + { 265 + if (status == di->raw[DS2760_STATUS_REG]) 266 + return; 267 + 268 + w1_ds2760_write(di->w1_dev, &status, DS2760_STATUS_WRITE_REG, 1); 269 + w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1); 270 + w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1); 271 + } 272 + 266 273 static void ds2760_battery_work(struct work_struct *work) 267 274 { 268 275 struct ds2760_device_info *di = container_of(work, ··· 357 342 358 343 static int ds2760_battery_probe(struct platform_device *pdev) 359 344 { 345 + char status; 360 346 int retval = 0; 361 347 struct ds2760_device_info *di; 362 - struct ds2760_platform_data *pdata; 363 348 364 349 di = kzalloc(sizeof(*di), GFP_KERNEL); 365 350 if (!di) { ··· 369 354 370 355 platform_set_drvdata(pdev, di); 371 356 372 - pdata = pdev->dev.platform_data; 373 - di->dev = &pdev->dev; 374 - di->w1_dev = pdev->dev.parent; 375 - di->bat.name = dev_name(&pdev->dev); 376 - di->bat.type = POWER_SUPPLY_TYPE_BATTERY; 377 - di->bat.properties = ds2760_battery_props; 378 - di->bat.num_properties = ARRAY_SIZE(ds2760_battery_props); 379 - di->bat.get_property = ds2760_battery_get_property; 357 + di->dev = &pdev->dev; 358 + di->w1_dev = pdev->dev.parent; 359 + di->bat.name = dev_name(&pdev->dev); 360 + di->bat.type = POWER_SUPPLY_TYPE_BATTERY; 361 + di->bat.properties = ds2760_battery_props; 362 + di->bat.num_properties = ARRAY_SIZE(ds2760_battery_props); 363 + di->bat.get_property = ds2760_battery_get_property; 380 364 di->bat.external_power_changed = 381 365 ds2760_battery_external_power_changed; 382 366 ··· 386 372 dev_err(di->dev, "failed to register battery\n"); 387 373 goto batt_failed; 388 374 } 375 + 376 + /* enable sleep mode feature */ 377 + ds2760_battery_read_status(di); 378 + status = di->raw[DS2760_STATUS_REG]; 379 + if (pmod_enabled) 380 + status |= DS2760_STATUS_PMOD; 381 + else 382 + status &= ~DS2760_STATUS_PMOD; 383 + 384 + ds2760_battery_write_status(di, status); 389 385 390 386 INIT_DELAYED_WORK(&di->monitor_work, ds2760_battery_work); 391 387 di->monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev));
+309
drivers/power/max17040_battery.c
··· 1 + /* 2 + * max17040_battery.c 3 + * fuel-gauge systems for lithium-ion (Li+) batteries 4 + * 5 + * Copyright (C) 2009 Samsung Electronics 6 + * Minkyu Kang <mk7.kang@samsung.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + 13 + #include <linux/module.h> 14 + #include <linux/init.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/mutex.h> 17 + #include <linux/err.h> 18 + #include <linux/i2c.h> 19 + #include <linux/delay.h> 20 + #include <linux/power_supply.h> 21 + #include <linux/max17040_battery.h> 22 + 23 + #define MAX17040_VCELL_MSB 0x02 24 + #define MAX17040_VCELL_LSB 0x03 25 + #define MAX17040_SOC_MSB 0x04 26 + #define MAX17040_SOC_LSB 0x05 27 + #define MAX17040_MODE_MSB 0x06 28 + #define MAX17040_MODE_LSB 0x07 29 + #define MAX17040_VER_MSB 0x08 30 + #define MAX17040_VER_LSB 0x09 31 + #define MAX17040_RCOMP_MSB 0x0C 32 + #define MAX17040_RCOMP_LSB 0x0D 33 + #define MAX17040_CMD_MSB 0xFE 34 + #define MAX17040_CMD_LSB 0xFF 35 + 36 + #define MAX17040_DELAY 1000 37 + #define MAX17040_BATTERY_FULL 95 38 + 39 + struct max17040_chip { 40 + struct i2c_client *client; 41 + struct delayed_work work; 42 + struct power_supply battery; 43 + struct max17040_platform_data *pdata; 44 + 45 + /* State Of Connect */ 46 + int online; 47 + /* battery voltage */ 48 + int vcell; 49 + /* battery capacity */ 50 + int soc; 51 + /* State Of Charge */ 52 + int status; 53 + }; 54 + 55 + static int max17040_get_property(struct power_supply *psy, 56 + enum power_supply_property psp, 57 + union power_supply_propval *val) 58 + { 59 + struct max17040_chip *chip = container_of(psy, 60 + struct max17040_chip, battery); 61 + 62 + switch (psp) { 63 + case POWER_SUPPLY_PROP_STATUS: 64 + val->intval = chip->status; 65 + break; 66 + case POWER_SUPPLY_PROP_ONLINE: 67 + val->intval = chip->online; 68 + break; 69 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 70 + val->intval = chip->vcell; 71 + break; 72 + case POWER_SUPPLY_PROP_CAPACITY: 73 + val->intval = chip->soc; 74 + break; 75 + default: 76 + return -EINVAL; 77 + } 78 + return 0; 79 + } 80 + 81 + static int max17040_write_reg(struct i2c_client *client, int reg, u8 value) 82 + { 83 + int ret; 84 + 85 + ret = i2c_smbus_write_byte_data(client, reg, value); 86 + 87 + if (ret < 0) 88 + dev_err(&client->dev, "%s: err %d\n", __func__, ret); 89 + 90 + return ret; 91 + } 92 + 93 + static int max17040_read_reg(struct i2c_client *client, int reg) 94 + { 95 + int ret; 96 + 97 + ret = i2c_smbus_read_byte_data(client, reg); 98 + 99 + if (ret < 0) 100 + dev_err(&client->dev, "%s: err %d\n", __func__, ret); 101 + 102 + return ret; 103 + } 104 + 105 + static void max17040_reset(struct i2c_client *client) 106 + { 107 + max17040_write_reg(client, MAX17040_CMD_MSB, 0x54); 108 + max17040_write_reg(client, MAX17040_CMD_LSB, 0x00); 109 + } 110 + 111 + static void max17040_get_vcell(struct i2c_client *client) 112 + { 113 + struct max17040_chip *chip = i2c_get_clientdata(client); 114 + u8 msb; 115 + u8 lsb; 116 + 117 + msb = max17040_read_reg(client, MAX17040_VCELL_MSB); 118 + lsb = max17040_read_reg(client, MAX17040_VCELL_LSB); 119 + 120 + chip->vcell = (msb << 4) + (lsb >> 4); 121 + } 122 + 123 + static void max17040_get_soc(struct i2c_client *client) 124 + { 125 + struct max17040_chip *chip = i2c_get_clientdata(client); 126 + u8 msb; 127 + u8 lsb; 128 + 129 + msb = max17040_read_reg(client, MAX17040_SOC_MSB); 130 + lsb = max17040_read_reg(client, MAX17040_SOC_LSB); 131 + 132 + chip->soc = msb; 133 + } 134 + 135 + static void max17040_get_version(struct i2c_client *client) 136 + { 137 + u8 msb; 138 + u8 lsb; 139 + 140 + msb = max17040_read_reg(client, MAX17040_VER_MSB); 141 + lsb = max17040_read_reg(client, MAX17040_VER_LSB); 142 + 143 + dev_info(&client->dev, "MAX17040 Fuel-Gauge Ver %d%d\n", msb, lsb); 144 + } 145 + 146 + static void max17040_get_online(struct i2c_client *client) 147 + { 148 + struct max17040_chip *chip = i2c_get_clientdata(client); 149 + 150 + if (chip->pdata->battery_online) 151 + chip->online = chip->pdata->battery_online(); 152 + else 153 + chip->online = 1; 154 + } 155 + 156 + static void max17040_get_status(struct i2c_client *client) 157 + { 158 + struct max17040_chip *chip = i2c_get_clientdata(client); 159 + 160 + if (!chip->pdata->charger_online || !chip->pdata->charger_enable) { 161 + chip->status = POWER_SUPPLY_STATUS_UNKNOWN; 162 + return; 163 + } 164 + 165 + if (chip->pdata->charger_online()) { 166 + if (chip->pdata->charger_enable()) 167 + chip->status = POWER_SUPPLY_STATUS_CHARGING; 168 + else 169 + chip->status = POWER_SUPPLY_STATUS_NOT_CHARGING; 170 + } else { 171 + chip->status = POWER_SUPPLY_STATUS_DISCHARGING; 172 + } 173 + 174 + if (chip->soc > MAX17040_BATTERY_FULL) 175 + chip->status = POWER_SUPPLY_STATUS_FULL; 176 + } 177 + 178 + static void max17040_work(struct work_struct *work) 179 + { 180 + struct max17040_chip *chip; 181 + 182 + chip = container_of(work, struct max17040_chip, work.work); 183 + 184 + max17040_get_vcell(chip->client); 185 + max17040_get_soc(chip->client); 186 + max17040_get_online(chip->client); 187 + max17040_get_status(chip->client); 188 + 189 + schedule_delayed_work(&chip->work, MAX17040_DELAY); 190 + } 191 + 192 + static enum power_supply_property max17040_battery_props[] = { 193 + POWER_SUPPLY_PROP_STATUS, 194 + POWER_SUPPLY_PROP_ONLINE, 195 + POWER_SUPPLY_PROP_VOLTAGE_NOW, 196 + POWER_SUPPLY_PROP_CAPACITY, 197 + }; 198 + 199 + static int __devinit max17040_probe(struct i2c_client *client, 200 + const struct i2c_device_id *id) 201 + { 202 + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 203 + struct max17040_chip *chip; 204 + int ret; 205 + 206 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) 207 + return -EIO; 208 + 209 + chip = kzalloc(sizeof(*chip), GFP_KERNEL); 210 + if (!chip) 211 + return -ENOMEM; 212 + 213 + chip->client = client; 214 + chip->pdata = client->dev.platform_data; 215 + 216 + i2c_set_clientdata(client, chip); 217 + 218 + chip->battery.name = "battery"; 219 + chip->battery.type = POWER_SUPPLY_TYPE_BATTERY; 220 + chip->battery.get_property = max17040_get_property; 221 + chip->battery.properties = max17040_battery_props; 222 + chip->battery.num_properties = ARRAY_SIZE(max17040_battery_props); 223 + 224 + ret = power_supply_register(&client->dev, &chip->battery); 225 + if (ret) { 226 + dev_err(&client->dev, "failed: power supply register\n"); 227 + i2c_set_clientdata(client, NULL); 228 + kfree(chip); 229 + return ret; 230 + } 231 + 232 + max17040_reset(client); 233 + max17040_get_version(client); 234 + 235 + INIT_DELAYED_WORK_DEFERRABLE(&chip->work, max17040_work); 236 + schedule_delayed_work(&chip->work, MAX17040_DELAY); 237 + 238 + return 0; 239 + } 240 + 241 + static int __devexit max17040_remove(struct i2c_client *client) 242 + { 243 + struct max17040_chip *chip = i2c_get_clientdata(client); 244 + 245 + power_supply_unregister(&chip->battery); 246 + cancel_delayed_work(&chip->work); 247 + i2c_set_clientdata(client, NULL); 248 + kfree(chip); 249 + return 0; 250 + } 251 + 252 + #ifdef CONFIG_PM 253 + 254 + static int max17040_suspend(struct i2c_client *client, 255 + pm_message_t state) 256 + { 257 + struct max17040_chip *chip = i2c_get_clientdata(client); 258 + 259 + cancel_delayed_work(&chip->work); 260 + return 0; 261 + } 262 + 263 + static int max17040_resume(struct i2c_client *client) 264 + { 265 + struct max17040_chip *chip = i2c_get_clientdata(client); 266 + 267 + schedule_delayed_work(&chip->work, MAX17040_DELAY); 268 + return 0; 269 + } 270 + 271 + #else 272 + 273 + #define max17040_suspend NULL 274 + #define max17040_resume NULL 275 + 276 + #endif /* CONFIG_PM */ 277 + 278 + static const struct i2c_device_id max17040_id[] = { 279 + { "max17040", 0 }, 280 + { } 281 + }; 282 + MODULE_DEVICE_TABLE(i2c, max17040_id); 283 + 284 + static struct i2c_driver max17040_i2c_driver = { 285 + .driver = { 286 + .name = "max17040", 287 + }, 288 + .probe = max17040_probe, 289 + .remove = __devexit_p(max17040_remove), 290 + .suspend = max17040_suspend, 291 + .resume = max17040_resume, 292 + .id_table = max17040_id, 293 + }; 294 + 295 + static int __init max17040_init(void) 296 + { 297 + return i2c_add_driver(&max17040_i2c_driver); 298 + } 299 + module_init(max17040_init); 300 + 301 + static void __exit max17040_exit(void) 302 + { 303 + i2c_del_driver(&max17040_i2c_driver); 304 + } 305 + module_exit(max17040_exit); 306 + 307 + MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>"); 308 + MODULE_DESCRIPTION("MAX17040 Fuel Gauge"); 309 + MODULE_LICENSE("GPL");
+30
drivers/w1/slaves/w1_ds2760.c
··· 68 68 return w1_ds2760_io(dev, buf, addr, count, 1); 69 69 } 70 70 71 + static int w1_ds2760_eeprom_cmd(struct device *dev, int addr, int cmd) 72 + { 73 + struct w1_slave *sl = container_of(dev, struct w1_slave, dev); 74 + 75 + if (!dev) 76 + return -EINVAL; 77 + 78 + mutex_lock(&sl->master->mutex); 79 + 80 + if (w1_reset_select_slave(sl) == 0) { 81 + w1_write_8(sl->master, cmd); 82 + w1_write_8(sl->master, addr); 83 + } 84 + 85 + mutex_unlock(&sl->master->mutex); 86 + return 0; 87 + } 88 + 89 + int w1_ds2760_store_eeprom(struct device *dev, int addr) 90 + { 91 + return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_COPY_DATA); 92 + } 93 + 94 + int w1_ds2760_recall_eeprom(struct device *dev, int addr) 95 + { 96 + return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_RECALL_DATA); 97 + } 98 + 71 99 static ssize_t w1_ds2760_read_bin(struct kobject *kobj, 72 100 struct bin_attribute *bin_attr, 73 101 char *buf, loff_t off, size_t count) ··· 228 200 229 201 EXPORT_SYMBOL(w1_ds2760_read); 230 202 EXPORT_SYMBOL(w1_ds2760_write); 203 + EXPORT_SYMBOL(w1_ds2760_store_eeprom); 204 + EXPORT_SYMBOL(w1_ds2760_recall_eeprom); 231 205 232 206 module_init(w1_ds2760_init); 233 207 module_exit(w1_ds2760_exit);
+7
drivers/w1/slaves/w1_ds2760.h
··· 25 25 26 26 #define DS2760_PROTECTION_REG 0x00 27 27 #define DS2760_STATUS_REG 0x01 28 + #define DS2760_STATUS_IE (1 << 2) 29 + #define DS2760_STATUS_SWEN (1 << 3) 30 + #define DS2760_STATUS_RNAOP (1 << 4) 31 + #define DS2760_STATUS_PMOD (1 << 5) 28 32 #define DS2760_EEPROM_REG 0x07 29 33 #define DS2760_SPECIAL_FEATURE_REG 0x08 30 34 #define DS2760_VOLTAGE_MSB 0x0c ··· 42 38 #define DS2760_EEPROM_BLOCK0 0x20 43 39 #define DS2760_ACTIVE_FULL 0x20 44 40 #define DS2760_EEPROM_BLOCK1 0x30 41 + #define DS2760_STATUS_WRITE_REG 0x31 45 42 #define DS2760_RATED_CAPACITY 0x32 46 43 #define DS2760_CURRENT_OFFSET_BIAS 0x33 47 44 #define DS2760_ACTIVE_EMPTY 0x3b ··· 51 46 size_t count); 52 47 extern int w1_ds2760_write(struct device *dev, char *buf, int addr, 53 48 size_t count); 49 + extern int w1_ds2760_store_eeprom(struct device *dev, int addr); 50 + extern int w1_ds2760_recall_eeprom(struct device *dev, int addr); 54 51 55 52 #endif /* !__w1_ds2760_h__ */
+19
include/linux/max17040_battery.h
··· 1 + /* 2 + * Copyright (C) 2009 Samsung Electronics 3 + * Minkyu Kang <mk7.kang@samsung.com> 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 as 7 + * published by the Free Software Foundation. 8 + */ 9 + 10 + #ifndef __MAX17040_BATTERY_H_ 11 + #define __MAX17040_BATTERY_H_ 12 + 13 + struct max17040_platform_data { 14 + int (*battery_online)(void); 15 + int (*charger_online)(void); 16 + int (*charger_enable)(void); 17 + }; 18 + 19 + #endif