max1721x_battery.c 13 KB

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