max1721x_battery.c (13070B)
1/* 2 * 1-Wire implementation for Maxim Semiconductor 3 * MAX7211/MAX17215 standalone fuel gauge chip 4 * 5 * Copyright (C) 2017 Radioavionica Corporation 6 * Author: Alex A. Mihaylov <minimumlaw@rambler.ru> 7 * 8 * Use consistent with the GNU GPL is permitted, 9 * provided that this copyright notice is 10 * preserved in its entirety in all copies and derived works. 11 * 12 */ 13 14#include <linux/module.h> 15#include <linux/slab.h> 16#include <linux/w1.h> 17#include <linux/regmap.h> 18#include <linux/power_supply.h> 19 20#define W1_MAX1721X_FAMILY_ID 0x26 21#define DEF_DEV_NAME_MAX17211 "MAX17211" 22#define DEF_DEV_NAME_MAX17215 "MAX17215" 23#define DEF_DEV_NAME_UNKNOWN "UNKNOWN" 24#define DEF_MFG_NAME "MAXIM" 25 26#define PSY_MAX_NAME_LEN 32 27 28/* Number of valid register addresses in W1 mode */ 29#define MAX1721X_MAX_REG_NR 0x1EF 30 31/* Factory settings (nonvolatile registers) (W1 specific) */ 32#define MAX1721X_REG_NRSENSE 0x1CF /* RSense in 10^-5 Ohm */ 33/* Strings */ 34#define MAX1721X_REG_MFG_STR 0x1CC 35#define MAX1721X_REG_MFG_NUMB 3 36#define MAX1721X_REG_DEV_STR 0x1DB 37#define MAX1721X_REG_DEV_NUMB 5 38/* HEX Strings */ 39#define MAX1721X_REG_SER_HEX 0x1D8 40 41/* MAX172XX Output Registers for W1 chips */ 42#define MAX172XX_REG_STATUS 0x000 /* status reg */ 43#define MAX172XX_BAT_PRESENT (1<<4) /* battery connected bit */ 44#define MAX172XX_REG_DEVNAME 0x021 /* chip config */ 45#define MAX172XX_DEV_MASK 0x000F /* chip type mask */ 46#define MAX172X1_DEV 0x0001 47#define MAX172X5_DEV 0x0005 48#define MAX172XX_REG_TEMP 0x008 /* Temperature */ 49#define MAX172XX_REG_BATT 0x0DA /* Battery voltage */ 50#define MAX172XX_REG_CURRENT 0x00A /* Actual current */ 51#define MAX172XX_REG_AVGCURRENT 0x00B /* Average current */ 52#define MAX172XX_REG_REPSOC 0x006 /* Percentage of charge */ 53#define MAX172XX_REG_DESIGNCAP 0x018 /* Design capacity */ 54#define MAX172XX_REG_REPCAP 0x005 /* Average capacity */ 55#define MAX172XX_REG_TTE 0x011 /* Time to empty */ 56#define MAX172XX_REG_TTF 0x020 /* Time to full */ 57 58struct max17211_device_info { 59 char name[PSY_MAX_NAME_LEN]; 60 struct power_supply *bat; 61 struct power_supply_desc bat_desc; 62 struct device *w1_dev; 63 struct regmap *regmap; 64 /* battery design format */ 65 unsigned int rsense; /* in tenths uOhm */ 66 char DeviceName[2 * MAX1721X_REG_DEV_NUMB + 1]; 67 char ManufacturerName[2 * MAX1721X_REG_MFG_NUMB + 1]; 68 char SerialNumber[13]; /* see get_sn_str() later for comment */ 69}; 70 71/* Convert regs value to power_supply units */ 72 73static inline int max172xx_time_to_ps(unsigned int reg) 74{ 75 return reg * 5625 / 1000; /* in sec. */ 76} 77 78static inline int max172xx_percent_to_ps(unsigned int reg) 79{ 80 return reg / 256; /* in percent from 0 to 100 */ 81} 82 83static inline int max172xx_voltage_to_ps(unsigned int reg) 84{ 85 return reg * 1250; /* in uV */ 86} 87 88static inline int max172xx_capacity_to_ps(unsigned int reg) 89{ 90 return reg * 500; /* in uAh */ 91} 92 93/* 94 * Current and temperature is signed values, so unsigned regs 95 * value must be converted to signed type 96 */ 97 98static inline int max172xx_temperature_to_ps(unsigned int reg) 99{ 100 int val = (int16_t)(reg); 101 102 return val * 10 / 256; /* in tenths of deg. C */ 103} 104 105/* 106 * Calculating current registers resolution: 107 * 108 * RSense stored in 10^-5 Ohm, so measurement voltage must be 109 * in 10^-11 Volts for get current in uA. 110 * 16 bit current reg fullscale +/-51.2mV is 102400 uV. 111 * So: 102400 / 65535 * 10^5 = 156252 112 */ 113static inline int max172xx_current_to_voltage(unsigned int reg) 114{ 115 int val = (int16_t)(reg); 116 117 return val * 156252; 118} 119 120 121static inline struct max17211_device_info * 122to_device_info(struct power_supply *psy) 123{ 124 return power_supply_get_drvdata(psy); 125} 126 127static int max1721x_battery_get_property(struct power_supply *psy, 128 enum power_supply_property psp, 129 union power_supply_propval *val) 130{ 131 struct max17211_device_info *info = to_device_info(psy); 132 unsigned int reg = 0; 133 int ret = 0; 134 135 switch (psp) { 136 case POWER_SUPPLY_PROP_PRESENT: 137 /* 138 * POWER_SUPPLY_PROP_PRESENT will always readable via 139 * sysfs interface. Value return 0 if battery not 140 * present or unaccessible via W1. 141 */ 142 val->intval = 143 regmap_read(info->regmap, MAX172XX_REG_STATUS, 144 ®) ? 0 : !(reg & MAX172XX_BAT_PRESENT); 145 break; 146 case POWER_SUPPLY_PROP_CAPACITY: 147 ret = regmap_read(info->regmap, MAX172XX_REG_REPSOC, ®); 148 val->intval = max172xx_percent_to_ps(reg); 149 break; 150 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 151 ret = regmap_read(info->regmap, MAX172XX_REG_BATT, ®); 152 val->intval = max172xx_voltage_to_ps(reg); 153 break; 154 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 155 ret = regmap_read(info->regmap, MAX172XX_REG_DESIGNCAP, ®); 156 val->intval = max172xx_capacity_to_ps(reg); 157 break; 158 case POWER_SUPPLY_PROP_CHARGE_AVG: 159 ret = regmap_read(info->regmap, MAX172XX_REG_REPCAP, ®); 160 val->intval = max172xx_capacity_to_ps(reg); 161 break; 162 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: 163 ret = regmap_read(info->regmap, MAX172XX_REG_TTE, ®); 164 val->intval = max172xx_time_to_ps(reg); 165 break; 166 case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: 167 ret = regmap_read(info->regmap, MAX172XX_REG_TTF, ®); 168 val->intval = max172xx_time_to_ps(reg); 169 break; 170 case POWER_SUPPLY_PROP_TEMP: 171 ret = regmap_read(info->regmap, MAX172XX_REG_TEMP, ®); 172 val->intval = max172xx_temperature_to_ps(reg); 173 break; 174 /* We need signed current, so must cast info->rsense to signed type */ 175 case POWER_SUPPLY_PROP_CURRENT_NOW: 176 ret = regmap_read(info->regmap, MAX172XX_REG_CURRENT, ®); 177 val->intval = 178 max172xx_current_to_voltage(reg) / (int)info->rsense; 179 break; 180 case POWER_SUPPLY_PROP_CURRENT_AVG: 181 ret = regmap_read(info->regmap, MAX172XX_REG_AVGCURRENT, ®); 182 val->intval = 183 max172xx_current_to_voltage(reg) / (int)info->rsense; 184 break; 185 /* 186 * Strings already received and inited by probe. 187 * We do dummy read for check battery still available. 188 */ 189 case POWER_SUPPLY_PROP_MODEL_NAME: 190 ret = regmap_read(info->regmap, MAX1721X_REG_DEV_STR, ®); 191 val->strval = info->DeviceName; 192 break; 193 case POWER_SUPPLY_PROP_MANUFACTURER: 194 ret = regmap_read(info->regmap, MAX1721X_REG_MFG_STR, ®); 195 val->strval = info->ManufacturerName; 196 break; 197 case POWER_SUPPLY_PROP_SERIAL_NUMBER: 198 ret = regmap_read(info->regmap, MAX1721X_REG_SER_HEX, ®); 199 val->strval = info->SerialNumber; 200 break; 201 default: 202 ret = -EINVAL; 203 } 204 205 return ret; 206} 207 208static enum power_supply_property max1721x_battery_props[] = { 209 /* int */ 210 POWER_SUPPLY_PROP_PRESENT, 211 POWER_SUPPLY_PROP_CAPACITY, 212 POWER_SUPPLY_PROP_VOLTAGE_NOW, 213 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 214 POWER_SUPPLY_PROP_CHARGE_AVG, 215 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 216 POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, 217 POWER_SUPPLY_PROP_TEMP, 218 POWER_SUPPLY_PROP_CURRENT_NOW, 219 POWER_SUPPLY_PROP_CURRENT_AVG, 220 /* strings */ 221 POWER_SUPPLY_PROP_MODEL_NAME, 222 POWER_SUPPLY_PROP_MANUFACTURER, 223 POWER_SUPPLY_PROP_SERIAL_NUMBER, 224}; 225 226static int get_string(struct max17211_device_info *info, 227 uint16_t reg, uint8_t nr, char *str) 228{ 229 unsigned int val; 230 231 if (!str || !(reg == MAX1721X_REG_MFG_STR || 232 reg == MAX1721X_REG_DEV_STR)) 233 return -EFAULT; 234 235 while (nr--) { 236 if (regmap_read(info->regmap, reg++, &val)) 237 return -EFAULT; 238 *str++ = val>>8 & 0x00FF; 239 *str++ = val & 0x00FF; 240 } 241 return 0; 242} 243 244/* Maxim say: Serial number is a hex string up to 12 hex characters */ 245static int get_sn_string(struct max17211_device_info *info, char *str) 246{ 247 unsigned int val[3]; 248 249 if (!str) 250 return -EFAULT; 251 252 if (regmap_read(info->regmap, MAX1721X_REG_SER_HEX, &val[0])) 253 return -EFAULT; 254 if (regmap_read(info->regmap, MAX1721X_REG_SER_HEX + 1, &val[1])) 255 return -EFAULT; 256 if (regmap_read(info->regmap, MAX1721X_REG_SER_HEX + 2, &val[2])) 257 return -EFAULT; 258 259 snprintf(str, 13, "%04X%04X%04X", val[0], val[1], val[2]); 260 return 0; 261} 262 263/* 264 * MAX1721x registers description for w1-regmap 265 */ 266static const struct regmap_range max1721x_allow_range[] = { 267 regmap_reg_range(0, 0xDF), /* volatile data */ 268 regmap_reg_range(0x180, 0x1DF), /* non-volatile memory */ 269 regmap_reg_range(0x1E0, 0x1EF), /* non-volatile history (unused) */ 270}; 271 272static const struct regmap_range max1721x_deny_range[] = { 273 /* volatile data unused registers */ 274 regmap_reg_range(0x24, 0x26), 275 regmap_reg_range(0x30, 0x31), 276 regmap_reg_range(0x33, 0x34), 277 regmap_reg_range(0x37, 0x37), 278 regmap_reg_range(0x3B, 0x3C), 279 regmap_reg_range(0x40, 0x41), 280 regmap_reg_range(0x43, 0x44), 281 regmap_reg_range(0x47, 0x49), 282 regmap_reg_range(0x4B, 0x4C), 283 regmap_reg_range(0x4E, 0xAF), 284 regmap_reg_range(0xB1, 0xB3), 285 regmap_reg_range(0xB5, 0xB7), 286 regmap_reg_range(0xBF, 0xD0), 287 regmap_reg_range(0xDB, 0xDB), 288 /* hole between volatile and non-volatile registers */ 289 regmap_reg_range(0xE0, 0x17F), 290}; 291 292static const struct regmap_access_table max1721x_regs = { 293 .yes_ranges = max1721x_allow_range, 294 .n_yes_ranges = ARRAY_SIZE(max1721x_allow_range), 295 .no_ranges = max1721x_deny_range, 296 .n_no_ranges = ARRAY_SIZE(max1721x_deny_range), 297}; 298 299/* 300 * Model Gauge M5 Algorithm output register 301 * Volatile data (must not be cached) 302 */ 303static const struct regmap_range max1721x_volatile_allow[] = { 304 regmap_reg_range(0, 0xDF), 305}; 306 307static const struct regmap_access_table max1721x_volatile_regs = { 308 .yes_ranges = max1721x_volatile_allow, 309 .n_yes_ranges = ARRAY_SIZE(max1721x_volatile_allow), 310}; 311 312/* 313 * W1-regmap config 314 */ 315static const struct regmap_config max1721x_regmap_w1_config = { 316 .reg_bits = 16, 317 .val_bits = 16, 318 .rd_table = &max1721x_regs, 319 .volatile_table = &max1721x_volatile_regs, 320 .max_register = MAX1721X_MAX_REG_NR, 321}; 322 323static int devm_w1_max1721x_add_device(struct w1_slave *sl) 324{ 325 struct power_supply_config psy_cfg = {}; 326 struct max17211_device_info *info; 327 328 info = devm_kzalloc(&sl->dev, sizeof(*info), GFP_KERNEL); 329 if (!info) 330 return -ENOMEM; 331 332 sl->family_data = (void *)info; 333 info->w1_dev = &sl->dev; 334 335 /* 336 * power_supply class battery name translated from W1 slave device 337 * unique ID (look like 26-0123456789AB) to "max1721x-0123456789AB\0" 338 * so, 26 (device family) correspond to max1721x devices. 339 * Device name still unique for any number of connected devices. 340 */ 341 snprintf(info->name, sizeof(info->name), 342 "max1721x-%012X", (unsigned int)sl->reg_num.id); 343 info->bat_desc.name = info->name; 344 345 /* 346 * FixMe: battery device name exceed max len for thermal_zone device 347 * name and translation to thermal_zone must be disabled. 348 */ 349 info->bat_desc.no_thermal = true; 350 info->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY; 351 info->bat_desc.properties = max1721x_battery_props; 352 info->bat_desc.num_properties = ARRAY_SIZE(max1721x_battery_props); 353 info->bat_desc.get_property = max1721x_battery_get_property; 354 psy_cfg.drv_data = info; 355 356 /* regmap init */ 357 info->regmap = devm_regmap_init_w1(info->w1_dev, 358 &max1721x_regmap_w1_config); 359 if (IS_ERR(info->regmap)) { 360 int err = PTR_ERR(info->regmap); 361 362 dev_err(info->w1_dev, "Failed to allocate register map: %d\n", 363 err); 364 return err; 365 } 366 367 /* rsense init */ 368 info->rsense = 0; 369 if (regmap_read(info->regmap, MAX1721X_REG_NRSENSE, &info->rsense)) { 370 dev_err(info->w1_dev, "Can't read RSense. Hardware error.\n"); 371 return -ENODEV; 372 } 373 374 if (!info->rsense) { 375 dev_warn(info->w1_dev, "RSense not calibrated, set 10 mOhms!\n"); 376 info->rsense = 1000; /* in regs in 10^-5 */ 377 } 378 dev_info(info->w1_dev, "RSense: %d mOhms.\n", info->rsense / 100); 379 380 if (get_string(info, MAX1721X_REG_MFG_STR, 381 MAX1721X_REG_MFG_NUMB, info->ManufacturerName)) { 382 dev_err(info->w1_dev, "Can't read manufacturer. Hardware error.\n"); 383 return -ENODEV; 384 } 385 386 if (!info->ManufacturerName[0]) 387 strncpy(info->ManufacturerName, DEF_MFG_NAME, 388 2 * MAX1721X_REG_MFG_NUMB); 389 390 if (get_string(info, MAX1721X_REG_DEV_STR, 391 MAX1721X_REG_DEV_NUMB, info->DeviceName)) { 392 dev_err(info->w1_dev, "Can't read device. Hardware error.\n"); 393 return -ENODEV; 394 } 395 if (!info->DeviceName[0]) { 396 unsigned int dev_name; 397 398 if (regmap_read(info->regmap, 399 MAX172XX_REG_DEVNAME, &dev_name)) { 400 dev_err(info->w1_dev, "Can't read device name reg.\n"); 401 return -ENODEV; 402 } 403 404 switch (dev_name & MAX172XX_DEV_MASK) { 405 case MAX172X1_DEV: 406 strncpy(info->DeviceName, DEF_DEV_NAME_MAX17211, 407 2 * MAX1721X_REG_DEV_NUMB); 408 break; 409 case MAX172X5_DEV: 410 strncpy(info->DeviceName, DEF_DEV_NAME_MAX17215, 411 2 * MAX1721X_REG_DEV_NUMB); 412 break; 413 default: 414 strncpy(info->DeviceName, DEF_DEV_NAME_UNKNOWN, 415 2 * MAX1721X_REG_DEV_NUMB); 416 } 417 } 418 419 if (get_sn_string(info, info->SerialNumber)) { 420 dev_err(info->w1_dev, "Can't read serial. Hardware error.\n"); 421 return -ENODEV; 422 } 423 424 info->bat = devm_power_supply_register(&sl->dev, &info->bat_desc, 425 &psy_cfg); 426 if (IS_ERR(info->bat)) { 427 dev_err(info->w1_dev, "failed to register battery\n"); 428 return PTR_ERR(info->bat); 429 } 430 431 return 0; 432} 433 434static const struct w1_family_ops w1_max1721x_fops = { 435 .add_slave = devm_w1_max1721x_add_device, 436}; 437 438static struct w1_family w1_max1721x_family = { 439 .fid = W1_MAX1721X_FAMILY_ID, 440 .fops = &w1_max1721x_fops, 441}; 442 443module_w1_family(w1_max1721x_family); 444 445MODULE_LICENSE("GPL"); 446MODULE_AUTHOR("Alex A. Mihaylov <minimumlaw@rambler.ru>"); 447MODULE_DESCRIPTION("Maxim MAX17211/MAX17215 Fuel Gauage IC driver"); 448MODULE_ALIAS("w1-family-" __stringify(W1_MAX1721X_FAMILY_ID));