/* * 1-Wire implementation for Maxim Semiconductor * MAX7211/MAX17215 standalone fuel gauge chip * * Copyright (C) 2017 Radioavionica Corporation * Author: Alex A. Mihaylov <minimumlaw@rambler.ru> * * Use consistent with the GNU GPL is permitted, * provided that this copyright notice is * preserved in its entirety in all copies and derived works. *
*/
/* * Current and temperature is signed values, so unsigned regs * value must be converted to signed type
*/
staticinlineint max172xx_temperature_to_ps(unsignedint reg)
{ int val = (int16_t)(reg);
return val * 10 / 256; /* in tenths of deg. C */
}
/* * Calculating current registers resolution: * * RSense stored in 10^-5 Ohm, so measurement voltage must be * in 10^-11 Volts for get current in uA. * 16 bit current reg fullscale +/-51.2mV is 102400 uV. * So: 102400 / 65535 * 10^5 = 156252
*/ staticinlineint max172xx_current_to_voltage(unsignedint reg)
{ int val = (int16_t)(reg);
staticint max1721x_battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val)
{ struct max17211_device_info *info = to_device_info(psy); unsignedint reg = 0; int ret = 0;
switch (psp) { case POWER_SUPPLY_PROP_PRESENT: /* * POWER_SUPPLY_PROP_PRESENT will always readable via * sysfs interface. Value return 0 if battery not * present or unaccessible via W1.
*/
val->intval =
regmap_read(info->regmap, MAX172XX_REG_STATUS,
®) ? 0 : !(reg & MAX172XX_BAT_PRESENT); break; case POWER_SUPPLY_PROP_CAPACITY:
ret = regmap_read(info->regmap, MAX172XX_REG_REPSOC, ®);
val->intval = max172xx_percent_to_ps(reg); break; case POWER_SUPPLY_PROP_VOLTAGE_NOW:
ret = regmap_read(info->regmap, MAX172XX_REG_BATT, ®);
val->intval = max172xx_voltage_to_ps(reg); break; case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
ret = regmap_read(info->regmap, MAX172XX_REG_DESIGNCAP, ®);
val->intval = max172xx_capacity_to_ps(reg); break; case POWER_SUPPLY_PROP_CHARGE_AVG:
ret = regmap_read(info->regmap, MAX172XX_REG_REPCAP, ®);
val->intval = max172xx_capacity_to_ps(reg); break; case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
ret = regmap_read(info->regmap, MAX172XX_REG_TTE, ®);
val->intval = max172xx_time_to_ps(reg); break; case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
ret = regmap_read(info->regmap, MAX172XX_REG_TTF, ®);
val->intval = max172xx_time_to_ps(reg); break; case POWER_SUPPLY_PROP_TEMP:
ret = regmap_read(info->regmap, MAX172XX_REG_TEMP, ®);
val->intval = max172xx_temperature_to_ps(reg); break; /* We need signed current, so must cast info->rsense to signed type */ case POWER_SUPPLY_PROP_CURRENT_NOW:
ret = regmap_read(info->regmap, MAX172XX_REG_CURRENT, ®);
val->intval =
max172xx_current_to_voltage(reg) / (int)info->rsense; break; case POWER_SUPPLY_PROP_CURRENT_AVG:
ret = regmap_read(info->regmap, MAX172XX_REG_AVGCURRENT, ®);
val->intval =
max172xx_current_to_voltage(reg) / (int)info->rsense; break; /* * Strings already received and inited by probe. * We do dummy read for check battery still available.
*/ case POWER_SUPPLY_PROP_MODEL_NAME:
ret = regmap_read(info->regmap, MAX1721X_REG_DEV_STR, ®);
val->strval = info->DeviceName; break; case POWER_SUPPLY_PROP_MANUFACTURER:
ret = regmap_read(info->regmap, MAX1721X_REG_MFG_STR, ®);
val->strval = info->ManufacturerName; break; case POWER_SUPPLY_PROP_SERIAL_NUMBER:
ret = regmap_read(info->regmap, MAX1721X_REG_SER_HEX, ®);
val->strval = info->SerialNumber; break; default:
ret = -EINVAL;
}
while (nr--) { if (regmap_read(info->regmap, reg++, &val)) return -EFAULT;
*str++ = val>>8 & 0x00FF;
*str++ = val & 0x00FF;
} return 0;
}
/* Maxim say: Serial number is a hex string up to 12 hex characters */ staticint get_sn_string(struct max17211_device_info *info, char *str)
{ unsignedint val[3];
if (!str) return -EFAULT;
if (regmap_read(info->regmap, MAX1721X_REG_SER_HEX, &val[0])) return -EFAULT; if (regmap_read(info->regmap, MAX1721X_REG_SER_HEX + 1, &val[1])) return -EFAULT; if (regmap_read(info->regmap, MAX1721X_REG_SER_HEX + 2, &val[2])) return -EFAULT;
/* * power_supply class battery name translated from W1 slave device * unique ID (look like 26-0123456789AB) to "max1721x-0123456789AB\0" * so, 26 (device family) correspond to max1721x devices. * Device name still unique for any number of connected devices.
*/
snprintf(info->name, sizeof(info->name), "max1721x-%012X", (unsignedint)sl->reg_num.id);
info->bat_desc.name = info->name;
/* * FixMe: battery device name exceed max len for thermal_zone device * name and translation to thermal_zone must be disabled.
*/
info->bat_desc.no_thermal = true;
info->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
info->bat_desc.properties = max1721x_battery_props;
info->bat_desc.num_properties = ARRAY_SIZE(max1721x_battery_props);
info->bat_desc.get_property = max1721x_battery_get_property;
psy_cfg.drv_data = info;
/* regmap init */
info->regmap = devm_regmap_init_w1(info->w1_dev,
&max1721x_regmap_w1_config); if (IS_ERR(info->regmap)) { int err = PTR_ERR(info->regmap);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.