@@ -8,6 +8,8 @@ Optional properties :
- maxim,rsns-microohm : Resistance of rsns resistor in micro Ohms
(datasheet-recommended value is 10000).
Defining this property enables current-sense functionality.
+ - maxim,thermometer-exist : Represent thermistor directly conneted.
+ (NOTE) Without this flag, max17042 never checks battery temperature.
Example:
@@ -15,4 +17,5 @@ Example:
compatible = "maxim,max17042";
reg = <0x36>;
maxim,rsns-microohm = <10000>;
+ maxim,thermometer-exist;
};
@@ -45,7 +45,15 @@ struct max17042_chip {
int init_complete;
};
-static enum power_supply_property max17042_battery_props[] = {
+/*
+ * Max17042/7 fuel-gauge optional properties :
+ * POWER_SUPPLY_PROP_CURRENT_NOW,
+ * POWER_SUPPLY_PROP_CURRENT_AVG,
+ * POWER_SUPPLY_PROP_CHARGE_FULL,
+ * POWER_SUPPLY_PROP_CHARGE_COUNTER,
+ * POWER_SUPPLY_PROP_TEMP,
+ */
+static enum power_supply_property max17042_default_props[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_CYCLE_COUNT,
POWER_SUPPLY_PROP_VOLTAGE_MAX,
@@ -54,12 +62,8 @@ static enum power_supply_property max17042_battery_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_AVG,
POWER_SUPPLY_PROP_VOLTAGE_OCV,
POWER_SUPPLY_PROP_CAPACITY,
- POWER_SUPPLY_PROP_CHARGE_FULL,
- POWER_SUPPLY_PROP_CHARGE_COUNTER,
- POWER_SUPPLY_PROP_TEMP,
- POWER_SUPPLY_PROP_CURRENT_NOW,
- POWER_SUPPLY_PROP_CURRENT_AVG,
};
+#define NUM_ADDITIONAL_PROPS 5
static int max17042_get_property(struct power_supply *psy,
enum power_supply_property psp,
@@ -140,6 +144,8 @@ static int max17042_get_property(struct power_supply *psy,
val->intval = data >> 8;
break;
case POWER_SUPPLY_PROP_CHARGE_FULL:
+ if (!chip->pdata->enable_current_sense)
+ return -EINVAL;
ret = regmap_read(map, MAX17042_FULLCAP, &data);
if (ret < 0)
return ret;
@@ -147,6 +153,8 @@ static int max17042_get_property(struct power_supply *psy,
val->intval = data * 1000 / 2;
break;
case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+ if (!chip->pdata->enable_current_sense)
+ return -EINVAL;
ret = regmap_read(map, MAX17042_QH, &data);
if (ret < 0)
return ret;
@@ -154,6 +162,8 @@ static int max17042_get_property(struct power_supply *psy,
val->intval = data * 1000 / 2;
break;
case POWER_SUPPLY_PROP_TEMP:
+ if (!chip->pdata->enable_temperature_sense)
+ return -EINVAL;
ret = regmap_read(map, MAX17042_TEMP, &data);
if (ret < 0)
return ret;
@@ -169,40 +179,36 @@ static int max17042_get_property(struct power_supply *psy,
val->intval = val->intval * 10 / 256;
break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
- if (chip->pdata->enable_current_sense) {
- ret = regmap_read(map, MAX17042_CURRENT, &data);
- if (ret < 0)
- return ret;
-
- val->intval = data;
- if (val->intval & 0x8000) {
- /* Negative */
- val->intval = ~val->intval & 0x7fff;
- val->intval++;
- val->intval *= -1;
- }
- val->intval *= 1562500 / chip->pdata->r_sns;
- } else {
+ if (!chip->pdata->enable_current_sense)
return -EINVAL;
+ ret = regmap_read(map, MAX17042_CURRENT, &data);
+ if (ret < 0)
+ return ret;
+
+ val->intval = data;
+ if (val->intval & 0x8000) {
+ /* Negative */
+ val->intval = ~val->intval & 0x7fff;
+ val->intval++;
+ val->intval *= -1;
}
+ val->intval *= 1562500 / chip->pdata->r_sns;
break;
case POWER_SUPPLY_PROP_CURRENT_AVG:
- if (chip->pdata->enable_current_sense) {
- ret = regmap_read(map, MAX17042_AVGCURRENT, &data);
- if (ret < 0)
- return ret;
-
- val->intval = data;
- if (val->intval & 0x8000) {
- /* Negative */
- val->intval = ~val->intval & 0x7fff;
- val->intval++;
- val->intval *= -1;
- }
- val->intval *= 1562500 / chip->pdata->r_sns;
- } else {
+ if (!chip->pdata->enable_current_sense)
return -EINVAL;
+ ret = regmap_read(map, MAX17042_AVGCURRENT, &data);
+ if (ret < 0)
+ return ret;
+
+ val->intval = data;
+ if (val->intval & 0x8000) {
+ /* Negative */
+ val->intval = ~val->intval & 0x7fff;
+ val->intval++;
+ val->intval *= -1;
}
+ val->intval *= 1562500 / chip->pdata->r_sns;
break;
default:
return -EINVAL;
@@ -617,6 +623,9 @@ max17042_get_pdata(struct device *dev)
pdata->enable_current_sense = true;
}
+ if (of_get_property(np, "maxim,thermometer-exist", NULL))
+ pdata->enable_temperature_sense = true;
+
return pdata;
}
#else
@@ -633,6 +642,57 @@ static struct regmap_config max17042_regmap_config = {
.val_format_endian = REGMAP_ENDIAN_NATIVE,
};
+static int max17042_init_properties(struct max17042_chip *chip)
+{
+ enum power_supply_property additional_props[NUM_ADDITIONAL_PROPS];
+ enum power_supply_property *properties;
+ int i, _base, added = 0;
+
+ _base = ARRAY_SIZE(max17042_default_props);
+
+ if (chip->pdata->enable_current_sense) {
+ additional_props[added++] = POWER_SUPPLY_PROP_CURRENT_NOW;
+ additional_props[added++] = POWER_SUPPLY_PROP_CURRENT_AVG;
+ additional_props[added++] = POWER_SUPPLY_PROP_CHARGE_FULL;
+ additional_props[added++] = POWER_SUPPLY_PROP_CHARGE_COUNTER;
+ if (chip->pdata->r_sns == 0)
+ chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;
+ } else {
+ /* ModelGauge v1 - Without current sense */
+ regmap_write(chip->regmap, MAX17042_CGAIN, 0x0000);
+ regmap_write(chip->regmap, MAX17042_MISCCFG, 0x0003);
+ regmap_write(chip->regmap, MAX17042_LEARNCFG, 0x0007);
+ }
+
+ if (chip->pdata->enable_temperature_sense)
+ additional_props[added++] = POWER_SUPPLY_PROP_TEMP;
+ else
+ /* Off thermistor - temperature will be externally given */
+ regmap_update_bits(chip->regmap, MAX17042_CONFIG,
+ CONFIG_ETHERM_BIT | CONFIG_TEX_BIT | CONFIG_TEN_BIT,
+ CONFIG_TEX_BIT);
+
+ if (added) {
+ properties = devm_kzalloc(&chip->client->dev,
+ (_base + added) * sizeof(*properties), GFP_KERNEL);
+ if (!properties)
+ return -ENOMEM;
+
+ memcpy(properties, max17042_default_props,
+ sizeof(max17042_default_props));
+ for (i = 0; i < added; i++)
+ properties[_base + i] = additional_props[i];
+
+ chip->battery.properties = properties;
+ chip->battery.num_properties = _base + added;
+ } else {
+ chip->battery.properties = max17042_default_props;
+ chip->battery.num_properties = _base;
+ }
+
+ return 0;
+}
+
static int max17042_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -679,16 +739,10 @@ static int max17042_probe(struct i2c_client *client,
chip->battery.name = "max170xx_battery";
chip->battery.type = POWER_SUPPLY_TYPE_BATTERY;
chip->battery.get_property = max17042_get_property;
- chip->battery.properties = max17042_battery_props;
- chip->battery.num_properties = ARRAY_SIZE(max17042_battery_props);
- /* When current is not measured,
- * CURRENT_NOW and CURRENT_AVG properties should be invisible. */
- 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 = max17042_init_properties(chip);
+ if (ret)
+ return ret;
if (chip->pdata->init_data)
for (i = 0; i < chip->pdata->num_init_data; i++)
@@ -37,6 +37,9 @@
/* Config register bits */
#define CONFIG_ALRT_BIT_ENBL (1 << 2)
+#define CONFIG_ETHERM_BIT (1 << 4)
+#define CONFIG_TEX_BIT (1 << 8)
+#define CONFIG_TEN_BIT (1 << 9)
#define MAX17042_BATTERY_FULL (100)
#define MAX17042_DEFAULT_SNS_RESISTOR (10000)
@@ -223,6 +226,7 @@ struct max17042_platform_data {
struct max17042_config_data *config_data;
int num_init_data; /* Number of enties in init_data array */
bool enable_current_sense;
+ bool enable_temperature_sense;
bool enable_por_init; /* Use POR init from Maxim appnote */
/*