struct device *dev;
struct power_supply bat;
struct device *w1_dev;
+ struct task_struct *mutex_holder;
};
enum current_types {
static const char model[] = "DS2780";
static const char manufacturer[] = "Maxim/Dallas";
- static inline struct ds2780_device_info *to_ds2780_device_info(
- struct power_supply *psy)
+ static inline struct ds2780_device_info *
+ to_ds2780_device_info(struct power_supply *psy)
{
return container_of(psy, struct ds2780_device_info, bat);
}
return dev_get_drvdata(dev);
}
- static inline int ds2780_read8(struct device *dev, u8 *val, int addr)
+ static inline int ds2780_battery_io(struct ds2780_device_info *dev_info,
+ char *buf, int addr, size_t count, int io)
{
- return w1_ds2780_io(dev, val, addr, sizeof(u8), 0);
+ if (dev_info->mutex_holder == current)
+ return w1_ds2780_io_nolock(dev_info->w1_dev, buf, addr, count, io);
+ else
+ return w1_ds2780_io(dev_info->w1_dev, buf, addr, count, io);
+ }
+
+ static inline int ds2780_read8(struct ds2780_device_info *dev_info, u8 *val,
+ int addr)
+ {
+ return ds2780_battery_io(dev_info, val, addr, sizeof(u8), 0);
}
- static int ds2780_read16(struct device *dev, s16 *val, int addr)
+ static int ds2780_read16(struct ds2780_device_info *dev_info, s16 *val,
+ int addr)
{
int ret;
u8 raw[2];
- ret = w1_ds2780_io(dev, raw, addr, sizeof(u8) * 2, 0);
+ ret = ds2780_battery_io(dev_info, raw, addr, sizeof(raw), 0);
if (ret < 0)
return ret;
return 0;
}
- static inline int ds2780_read_block(struct device *dev, u8 *val, int addr,
- size_t count)
+ static inline int ds2780_read_block(struct ds2780_device_info *dev_info,
+ u8 *val, int addr, size_t count)
{
- return w1_ds2780_io(dev, val, addr, count, 0);
+ return ds2780_battery_io(dev_info, val, addr, count, 0);
}
- static inline int ds2780_write(struct device *dev, u8 *val, int addr,
- size_t count)
+ static inline int ds2780_write(struct ds2780_device_info *dev_info, u8 *val,
+ int addr, size_t count)
{
- return w1_ds2780_io(dev, val, addr, count, 1);
+ return ds2780_battery_io(dev_info, val, addr, count, 1);
}
static inline int ds2780_store_eeprom(struct device *dev, int addr)
{
int ret;
- ret = ds2780_write(dev_info->w1_dev, &conductance,
+ ret = ds2780_write(dev_info, &conductance,
DS2780_RSNSP_REG, sizeof(u8));
if (ret < 0)
return ret;
static int ds2780_get_rsgain_register(struct ds2780_device_info *dev_info,
u16 *rsgain)
{
- return ds2780_read16(dev_info->w1_dev, rsgain, DS2780_RSGAIN_MSB_REG);
+ return ds2780_read16(dev_info, rsgain, DS2780_RSGAIN_MSB_REG);
}
/* Set RSGAIN value from 0 to 1.999 in steps of 0.001 */
int ret;
u8 raw[] = {rsgain >> 8, rsgain & 0xFF};
- ret = ds2780_write(dev_info->w1_dev, raw,
- DS2780_RSGAIN_MSB_REG, sizeof(u8) * 2);
+ ret = ds2780_write(dev_info, raw,
+ DS2780_RSGAIN_MSB_REG, sizeof(raw));
if (ret < 0)
return ret;
* Bits 2 - 0 of the voltage value are in bits 7 - 5 of the
* voltage LSB register
*/
- ret = ds2780_read16(dev_info->w1_dev, &voltage_raw,
+ ret = ds2780_read16(dev_info, &voltage_raw,
DS2780_VOLT_MSB_REG);
if (ret < 0)
return ret;
* Bits 2 - 0 of the temperature value are in bits 7 - 5 of the
* temperature LSB register
*/
- ret = ds2780_read16(dev_info->w1_dev, &temperature_raw,
+ ret = ds2780_read16(dev_info, &temperature_raw,
DS2780_TEMP_MSB_REG);
if (ret < 0)
return ret;
* The units of measurement for current are dependent on the value of
* the sense resistor.
*/
- ret = ds2780_read8(dev_info->w1_dev, &sense_res_raw, DS2780_RSNSP_REG);
+ ret = ds2780_read8(dev_info, &sense_res_raw, DS2780_RSNSP_REG);
if (ret < 0)
return ret;
if (sense_res_raw == 0) {
dev_err(dev_info->dev, "sense resistor value is 0\n");
- return -ENXIO;
+ return -EINVAL;
}
sense_res = 1000 / sense_res_raw;
* Bits 7 - 0 of the current value are in bits 7 - 0 of the current
* LSB register
*/
- ret = ds2780_read16(dev_info->w1_dev, ¤t_raw, reg_msb);
+ ret = ds2780_read16(dev_info, ¤t_raw, reg_msb);
if (ret < 0)
return ret;
* The units of measurement for accumulated current are dependent on
* the value of the sense resistor.
*/
- ret = ds2780_read8(dev_info->w1_dev, &sense_res_raw, DS2780_RSNSP_REG);
+ ret = ds2780_read8(dev_info, &sense_res_raw, DS2780_RSNSP_REG);
if (ret < 0)
return ret;
* Bits 7 - 0 of the ACR value are in bits 7 - 0 of the ACR
* LSB register
*/
- ret = ds2780_read16(dev_info->w1_dev, ¤t_raw, DS2780_ACR_MSB_REG);
+ ret = ds2780_read16(dev_info, ¤t_raw, DS2780_ACR_MSB_REG);
if (ret < 0)
return ret;
int ret;
u8 raw;
- ret = ds2780_read8(dev_info->w1_dev, &raw, DS2780_RARC_REG);
+ ret = ds2780_read8(dev_info, &raw, DS2780_RARC_REG);
if (ret < 0)
return ret;
* Bits 7 - 0 of the RAAC value are in bits 7 - 0 of the RAAC
* LSB register
*/
- ret = ds2780_read16(dev_info->w1_dev, &charge_raw, DS2780_RAAC_MSB_REG);
+ ret = ds2780_read16(dev_info, &charge_raw, DS2780_RAAC_MSB_REG);
if (ret < 0)
return ret;
static int ds2780_get_control_register(struct ds2780_device_info *dev_info,
u8 *control_reg)
{
- return ds2780_read8(dev_info->w1_dev, control_reg, DS2780_CONTROL_REG);
+ return ds2780_read8(dev_info, control_reg, DS2780_CONTROL_REG);
}
static int ds2780_set_control_register(struct ds2780_device_info *dev_info,
{
int ret;
- ret = ds2780_write(dev_info->w1_dev, &control_reg,
+ ret = ds2780_write(dev_info, &control_reg,
DS2780_CONTROL_REG, sizeof(u8));
if (ret < 0)
return ret;
struct power_supply *psy = to_power_supply(dev);
struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
- ret = ds2780_read8(dev_info->w1_dev, &sense_resistor, DS2780_RSNSP_REG);
+ ret = ds2780_read8(dev_info, &sense_resistor, DS2780_RSNSP_REG);
if (ret < 0)
return ret;
struct power_supply *psy = to_power_supply(dev);
struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
- ret = ds2780_read8(dev_info->w1_dev, &sfr, DS2780_SFR_REG);
+ ret = ds2780_read8(dev_info, &sfr, DS2780_SFR_REG);
if (ret < 0)
return ret;
return -EINVAL;
}
- ret = ds2780_write(dev_info->w1_dev, &new_setting,
+ ret = ds2780_write(dev_info, &new_setting,
DS2780_SFR_REG, sizeof(u8));
if (ret < 0)
return ret;
DS2780_EEPROM_BLOCK1_END -
DS2780_EEPROM_BLOCK1_START + 1 - off);
- return ds2780_read_block(dev_info->w1_dev, buf,
+ return ds2780_read_block(dev_info, buf,
DS2780_EEPROM_BLOCK1_START + off, count);
}
DS2780_EEPROM_BLOCK1_END -
DS2780_EEPROM_BLOCK1_START + 1 - off);
- ret = ds2780_write(dev_info->w1_dev, buf,
+ ret = ds2780_write(dev_info, buf,
DS2780_EEPROM_BLOCK1_START + off, count);
if (ret < 0)
return ret;
DS2780_EEPROM_BLOCK0_END -
DS2780_EEPROM_BLOCK0_START + 1 - off);
- return ds2780_read_block(dev_info->w1_dev, buf,
+ return ds2780_read_block(dev_info, buf,
DS2780_EEPROM_BLOCK0_START + off, count);
-
}
static ssize_t ds2780_write_user_eeprom_bin(struct file *filp,
DS2780_EEPROM_BLOCK0_END -
DS2780_EEPROM_BLOCK0_START + 1 - off);
- ret = ds2780_write(dev_info->w1_dev, buf,
+ ret = ds2780_write(dev_info, buf,
DS2780_EEPROM_BLOCK0_START + off, count);
if (ret < 0)
return ret;
dev_info->bat.properties = ds2780_battery_props;
dev_info->bat.num_properties = ARRAY_SIZE(ds2780_battery_props);
dev_info->bat.get_property = ds2780_battery_get_property;
+ dev_info->mutex_holder = current;
ret = power_supply_register(&pdev->dev, &dev_info->bat);
if (ret) {
goto fail_remove_bin_file;
}
+ dev_info->mutex_holder = NULL;
+
return 0;
fail_remove_bin_file:
{
struct ds2780_device_info *dev_info = platform_get_drvdata(pdev);
+ dev_info->mutex_holder = current;
+
/* remove attributes */
sysfs_remove_group(&dev_info->bat.dev->kobj, &ds2780_attr_group);
.name = "ds2780-battery",
},
.probe = ds2780_battery_probe,
- .remove = ds2780_battery_remove,
+ .remove = __devexit_p(ds2780_battery_remove),
};
static int __init ds2780_battery_init(void)
*/
#include <linux/init.h>
+ #include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/mod_devicetable.h>
{
struct max17042_chip *chip = container_of(psy,
struct max17042_chip, battery);
+ int ret;
switch (psp) {
case POWER_SUPPLY_PROP_PRESENT:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_STATUS);
- if (val->intval & MAX17042_STATUS_BattAbsent)
+ ret = max17042_read_reg(chip->client, MAX17042_STATUS);
+ if (ret < 0)
+ return ret;
+
+ if (ret & MAX17042_STATUS_BattAbsent)
val->intval = 0;
else
val->intval = 1;
break;
case POWER_SUPPLY_PROP_CYCLE_COUNT:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_Cycles);
+ ret = max17042_read_reg(chip->client, MAX17042_Cycles);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_MinMaxVolt);
- val->intval >>= 8;
+ ret = max17042_read_reg(chip->client, MAX17042_MinMaxVolt);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret >> 8;
val->intval *= 20000; /* Units of LSB = 20mV */
break;
case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_V_empty);
- val->intval >>= 7;
+ ret = max17042_read_reg(chip->client, MAX17042_V_empty);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret >> 7;
val->intval *= 10000; /* Units of LSB = 10mV */
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_VCELL) * 83; /* 1000 / 12 = 83 */
+ ret = max17042_read_reg(chip->client, MAX17042_VCELL);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret * 625 / 8;
break;
case POWER_SUPPLY_PROP_VOLTAGE_AVG:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_AvgVCELL) * 83;
+ ret = max17042_read_reg(chip->client, MAX17042_AvgVCELL);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret * 625 / 8;
break;
case POWER_SUPPLY_PROP_CAPACITY:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_SOC) / 256;
+ ret = max17042_read_reg(chip->client, MAX17042_SOC);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret >> 8;
break;
case POWER_SUPPLY_PROP_CHARGE_FULL:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_RepSOC);
- if ((val->intval / 256) >= MAX17042_BATTERY_FULL)
+ ret = max17042_read_reg(chip->client, MAX17042_RepSOC);
+ if (ret < 0)
+ return ret;
+
+ if ((ret >> 8) >= MAX17042_BATTERY_FULL)
val->intval = 1;
- else if (val->intval >= 0)
+ else if (ret >= 0)
val->intval = 0;
break;
case POWER_SUPPLY_PROP_TEMP:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_TEMP);
+ ret = max17042_read_reg(chip->client, MAX17042_TEMP);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
/* The value is signed. */
if (val->intval & 0x8000) {
val->intval = (0x7fff & ~val->intval) + 1;
break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
if (chip->pdata->enable_current_sense) {
- val->intval = max17042_read_reg(chip->client,
- MAX17042_Current);
+ ret = max17042_read_reg(chip->client, MAX17042_Current);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
if (val->intval & 0x8000) {
/* Negative */
val->intval = ~val->intval & 0x7fff;
val->intval++;
val->intval *= -1;
}
- val->intval >>= 4;
- val->intval *= 1000000 * 25 / chip->pdata->r_sns;
+ val->intval *= 1562500 / chip->pdata->r_sns;
} else {
return -EINVAL;
}
break;
case POWER_SUPPLY_PROP_CURRENT_AVG:
if (chip->pdata->enable_current_sense) {
- val->intval = max17042_read_reg(chip->client,
- MAX17042_AvgCurrent);
+ ret = max17042_read_reg(chip->client,
+ MAX17042_AvgCurrent);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
if (val->intval & 0x8000) {
/* Negative */
val->intval = ~val->intval & 0x7fff;
if (!chip->pdata->enable_current_sense)
chip->battery.num_properties -= 2;
+ if (chip->pdata->r_sns == 0)
+ chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;
+
ret = power_supply_register(&client->dev, &chip->battery);
if (ret) {
dev_err(&client->dev, "failed: power supply register\n");
max17042_write_reg(client, MAX17042_CGAIN, 0x0000);
max17042_write_reg(client, MAX17042_MiscCFG, 0x0003);
max17042_write_reg(client, MAX17042_LearnCFG, 0x0007);
- } else {
- if (chip->pdata->r_sns == 0)
- chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;
}
return 0;
#include <linux/ctype.h>
#include <linux/power_supply.h>
#include <linux/slab.h>
+ #include <linux/stat.h>
#include "power_supply.h"
struct device_attribute *attr,
char *buf) {
static char *type_text[] = {
- "Battery", "UPS", "Mains", "USB",
+ "Unknown", "Battery", "UPS", "Mains", "USB",
"USB_DCP", "USB_CDP", "USB_ACA"
};
static char *status_text[] = {
static char *capacity_level_text[] = {
"Unknown", "Critical", "Low", "Normal", "High", "Full"
};
+ static char *scope_text[] = {
+ "Unknown", "System", "Device"
+ };
ssize_t ret = 0;
struct power_supply *psy = dev_get_drvdata(dev);
const ptrdiff_t off = attr - power_supply_attrs;
dev_dbg(dev, "driver has no data for `%s' property\n",
attr->attr.name);
else if (ret != -ENODEV)
- dev_err(dev, "driver failed to report `%s' property\n",
- attr->attr.name);
+ dev_err(dev, "driver failed to report `%s' property: %zd\n",
+ attr->attr.name, ret);
return ret;
}
return sprintf(buf, "%s\n", capacity_level_text[value.intval]);
else if (off == POWER_SUPPLY_PROP_TYPE)
return sprintf(buf, "%s\n", type_text[value.intval]);
+ else if (off == POWER_SUPPLY_PROP_SCOPE)
+ return sprintf(buf, "%s\n", scope_text[value.intval]);
else if (off >= POWER_SUPPLY_PROP_MODEL_NAME)
return sprintf(buf, "%s\n", value.strval);
POWER_SUPPLY_ATTR(time_to_full_now),
POWER_SUPPLY_ATTR(time_to_full_avg),
POWER_SUPPLY_ATTR(type),
+ POWER_SUPPLY_ATTR(scope),
/* Properties of type `const char *' */
POWER_SUPPLY_ATTR(model_name),
POWER_SUPPLY_ATTR(manufacturer),