1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * I2C client/driver for the Linear Technology LTC2941, LTC2942, LTC2943 4 * and LTC2944 Battery Gas Gauge IC 5 * 6 * Copyright (C) 2014 Topic Embedded Systems 7 * 8 * Author: Auryn Verwegen 9 * Author: Mike Looijmans 10 */ 11 #include <linux/devm-helpers.h> 12 #include <linux/kernel.h> 13 #include <linux/module.h> 14 #include <linux/of_device.h> 15 #include <linux/types.h> 16 #include <linux/errno.h> 17 #include <linux/swab.h> 18 #include <linux/i2c.h> 19 #include <linux/delay.h> 20 #include <linux/power_supply.h> 21 #include <linux/slab.h> 22 23 #define I16_MSB(x) ((x >> 8) & 0xFF) 24 #define I16_LSB(x) (x & 0xFF) 25 26 #define LTC294X_WORK_DELAY 10 /* Update delay in seconds */ 27 28 #define LTC294X_MAX_VALUE 0xFFFF 29 #define LTC294X_MID_SUPPLY 0x7FFF 30 31 #define LTC2941_MAX_PRESCALER_EXP 7 32 #define LTC2943_MAX_PRESCALER_EXP 6 33 34 enum ltc294x_reg { 35 LTC294X_REG_STATUS = 0x00, 36 LTC294X_REG_CONTROL = 0x01, 37 LTC294X_REG_ACC_CHARGE_MSB = 0x02, 38 LTC294X_REG_ACC_CHARGE_LSB = 0x03, 39 LTC294X_REG_CHARGE_THR_HIGH_MSB = 0x04, 40 LTC294X_REG_CHARGE_THR_HIGH_LSB = 0x05, 41 LTC294X_REG_CHARGE_THR_LOW_MSB = 0x06, 42 LTC294X_REG_CHARGE_THR_LOW_LSB = 0x07, 43 LTC294X_REG_VOLTAGE_MSB = 0x08, 44 LTC294X_REG_VOLTAGE_LSB = 0x09, 45 LTC2942_REG_TEMPERATURE_MSB = 0x0C, 46 LTC2942_REG_TEMPERATURE_LSB = 0x0D, 47 LTC2943_REG_CURRENT_MSB = 0x0E, 48 LTC2943_REG_CURRENT_LSB = 0x0F, 49 LTC2943_REG_TEMPERATURE_MSB = 0x14, 50 LTC2943_REG_TEMPERATURE_LSB = 0x15, 51 }; 52 53 enum ltc294x_id { 54 LTC2941_ID, 55 LTC2942_ID, 56 LTC2943_ID, 57 LTC2944_ID, 58 }; 59 60 #define LTC2941_REG_STATUS_CHIP_ID BIT(7) 61 62 #define LTC2942_REG_CONTROL_MODE_SCAN (BIT(7) | BIT(6)) 63 #define LTC2943_REG_CONTROL_MODE_SCAN BIT(7) 64 #define LTC294X_REG_CONTROL_PRESCALER_MASK (BIT(5) | BIT(4) | BIT(3)) 65 #define LTC294X_REG_CONTROL_SHUTDOWN_MASK (BIT(0)) 66 #define LTC294X_REG_CONTROL_PRESCALER_SET(x) \ 67 ((x << 3) & LTC294X_REG_CONTROL_PRESCALER_MASK) 68 #define LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED 0 69 #define LTC294X_REG_CONTROL_ADC_DISABLE(x) ((x) & ~(BIT(7) | BIT(6))) 70 71 struct ltc294x_info { 72 struct i2c_client *client; /* I2C Client pointer */ 73 struct power_supply *supply; /* Supply pointer */ 74 struct power_supply_desc supply_desc; /* Supply description */ 75 struct delayed_work work; /* Work scheduler */ 76 enum ltc294x_id id; /* Chip type */ 77 int charge; /* Last charge register content */ 78 int r_sense; /* mOhm */ 79 int Qlsb; /* nAh */ 80 }; 81 82 static inline int convert_bin_to_uAh( 83 const struct ltc294x_info *info, int Q) 84 { 85 return ((Q * (info->Qlsb / 10))) / 100; 86 } 87 88 static inline int convert_uAh_to_bin( 89 const struct ltc294x_info *info, int uAh) 90 { 91 int Q; 92 93 Q = (uAh * 100) / (info->Qlsb/10); 94 return (Q < LTC294X_MAX_VALUE) ? Q : LTC294X_MAX_VALUE; 95 } 96 97 static int ltc294x_read_regs(struct i2c_client *client, 98 enum ltc294x_reg reg, u8 *buf, int num_regs) 99 { 100 int ret; 101 struct i2c_msg msgs[2] = { }; 102 u8 reg_start = reg; 103 104 msgs[0].addr = client->addr; 105 msgs[0].len = 1; 106 msgs[0].buf = ®_start; 107 108 msgs[1].addr = client->addr; 109 msgs[1].len = num_regs; 110 msgs[1].buf = buf; 111 msgs[1].flags = I2C_M_RD; 112 113 ret = i2c_transfer(client->adapter, &msgs[0], 2); 114 if (ret < 0) { 115 dev_err(&client->dev, "ltc2941 read_reg failed!\n"); 116 return ret; 117 } 118 119 dev_dbg(&client->dev, "%s (%#x, %d) -> %#x\n", 120 __func__, reg, num_regs, *buf); 121 122 return 0; 123 } 124 125 static int ltc294x_write_regs(struct i2c_client *client, 126 enum ltc294x_reg reg, const u8 *buf, int num_regs) 127 { 128 int ret; 129 u8 reg_start = reg; 130 131 ret = i2c_smbus_write_i2c_block_data(client, reg_start, num_regs, buf); 132 if (ret < 0) { 133 dev_err(&client->dev, "ltc2941 write_reg failed!\n"); 134 return ret; 135 } 136 137 dev_dbg(&client->dev, "%s (%#x, %d) -> %#x\n", 138 __func__, reg, num_regs, *buf); 139 140 return 0; 141 } 142 143 static int ltc294x_reset(const struct ltc294x_info *info, int prescaler_exp) 144 { 145 int ret; 146 u8 value; 147 u8 control; 148 149 /* Read status and control registers */ 150 ret = ltc294x_read_regs(info->client, LTC294X_REG_CONTROL, &value, 1); 151 if (ret < 0) { 152 dev_err(&info->client->dev, 153 "Could not read registers from device\n"); 154 goto error_exit; 155 } 156 157 control = LTC294X_REG_CONTROL_PRESCALER_SET(prescaler_exp) | 158 LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED; 159 /* Put device into "monitor" mode */ 160 switch (info->id) { 161 case LTC2942_ID: /* 2942 measures every 2 sec */ 162 control |= LTC2942_REG_CONTROL_MODE_SCAN; 163 break; 164 case LTC2943_ID: 165 case LTC2944_ID: /* 2943 and 2944 measure every 10 sec */ 166 control |= LTC2943_REG_CONTROL_MODE_SCAN; 167 break; 168 default: 169 break; 170 } 171 172 if (value != control) { 173 ret = ltc294x_write_regs(info->client, 174 LTC294X_REG_CONTROL, &control, 1); 175 if (ret < 0) { 176 dev_err(&info->client->dev, 177 "Could not write register\n"); 178 goto error_exit; 179 } 180 } 181 182 return 0; 183 184 error_exit: 185 return ret; 186 } 187 188 static int ltc294x_read_charge_register(const struct ltc294x_info *info, 189 enum ltc294x_reg reg) 190 { 191 int ret; 192 u8 datar[2]; 193 194 ret = ltc294x_read_regs(info->client, reg, &datar[0], 2); 195 if (ret < 0) 196 return ret; 197 return (datar[0] << 8) + datar[1]; 198 } 199 200 static int ltc294x_get_charge(const struct ltc294x_info *info, 201 enum ltc294x_reg reg, int *val) 202 { 203 int value = ltc294x_read_charge_register(info, reg); 204 205 if (value < 0) 206 return value; 207 /* When r_sense < 0, this counts up when the battery discharges */ 208 if (info->Qlsb < 0) 209 value -= 0xFFFF; 210 *val = convert_bin_to_uAh(info, value); 211 return 0; 212 } 213 214 static int ltc294x_set_charge_now(const struct ltc294x_info *info, int val) 215 { 216 int ret; 217 u8 dataw[2]; 218 u8 ctrl_reg; 219 s32 value; 220 221 value = convert_uAh_to_bin(info, val); 222 /* Direction depends on how sense+/- were connected */ 223 if (info->Qlsb < 0) 224 value += 0xFFFF; 225 if ((value < 0) || (value > 0xFFFF)) /* input validation */ 226 return -EINVAL; 227 228 /* Read control register */ 229 ret = ltc294x_read_regs(info->client, 230 LTC294X_REG_CONTROL, &ctrl_reg, 1); 231 if (ret < 0) 232 return ret; 233 /* Disable analog section */ 234 ctrl_reg |= LTC294X_REG_CONTROL_SHUTDOWN_MASK; 235 ret = ltc294x_write_regs(info->client, 236 LTC294X_REG_CONTROL, &ctrl_reg, 1); 237 if (ret < 0) 238 return ret; 239 /* Set new charge value */ 240 dataw[0] = I16_MSB(value); 241 dataw[1] = I16_LSB(value); 242 ret = ltc294x_write_regs(info->client, 243 LTC294X_REG_ACC_CHARGE_MSB, &dataw[0], 2); 244 if (ret < 0) 245 goto error_exit; 246 /* Enable analog section */ 247 error_exit: 248 ctrl_reg &= ~LTC294X_REG_CONTROL_SHUTDOWN_MASK; 249 ret = ltc294x_write_regs(info->client, 250 LTC294X_REG_CONTROL, &ctrl_reg, 1); 251 252 return ret < 0 ? ret : 0; 253 } 254 255 static int ltc294x_set_charge_thr(const struct ltc294x_info *info, 256 enum ltc294x_reg reg, int val) 257 { 258 u8 dataw[2]; 259 s32 value; 260 261 value = convert_uAh_to_bin(info, val); 262 /* Direction depends on how sense+/- were connected */ 263 if (info->Qlsb < 0) 264 value += 0xFFFF; 265 if ((value < 0) || (value > 0xFFFF)) /* input validation */ 266 return -EINVAL; 267 268 /* Set new charge value */ 269 dataw[0] = I16_MSB(value); 270 dataw[1] = I16_LSB(value); 271 return ltc294x_write_regs(info->client, reg, &dataw[0], 2); 272 } 273 274 static int ltc294x_get_charge_counter( 275 const struct ltc294x_info *info, int *val) 276 { 277 int value = ltc294x_read_charge_register(info, LTC294X_REG_ACC_CHARGE_MSB); 278 279 if (value < 0) 280 return value; 281 value -= LTC294X_MID_SUPPLY; 282 *val = convert_bin_to_uAh(info, value); 283 return 0; 284 } 285 286 static int ltc294x_get_voltage(const struct ltc294x_info *info, int *val) 287 { 288 int ret; 289 u8 datar[2]; 290 u32 value; 291 292 ret = ltc294x_read_regs(info->client, 293 LTC294X_REG_VOLTAGE_MSB, &datar[0], 2); 294 value = (datar[0] << 8) | datar[1]; 295 switch (info->id) { 296 case LTC2943_ID: 297 value *= 23600 * 2; 298 value /= 0xFFFF; 299 value *= 1000 / 2; 300 break; 301 case LTC2944_ID: 302 value *= 70800 / 5*4; 303 value /= 0xFFFF; 304 value *= 1000 * 5/4; 305 break; 306 default: 307 value *= 6000 * 10; 308 value /= 0xFFFF; 309 value *= 1000 / 10; 310 break; 311 } 312 *val = value; 313 return ret; 314 } 315 316 static int ltc294x_get_current(const struct ltc294x_info *info, int *val) 317 { 318 int ret; 319 u8 datar[2]; 320 s32 value; 321 322 ret = ltc294x_read_regs(info->client, 323 LTC2943_REG_CURRENT_MSB, &datar[0], 2); 324 value = (datar[0] << 8) | datar[1]; 325 value -= 0x7FFF; 326 if (info->id == LTC2944_ID) 327 value *= 64000; 328 else 329 value *= 60000; 330 /* Value is in range -32k..+32k, r_sense is usually 10..50 mOhm, 331 * the formula below keeps everything in s32 range while preserving 332 * enough digits */ 333 *val = 1000 * (value / (info->r_sense * 0x7FFF)); /* in uA */ 334 return ret; 335 } 336 337 static int ltc294x_get_temperature(const struct ltc294x_info *info, int *val) 338 { 339 enum ltc294x_reg reg; 340 int ret; 341 u8 datar[2]; 342 u32 value; 343 344 if (info->id == LTC2942_ID) { 345 reg = LTC2942_REG_TEMPERATURE_MSB; 346 value = 6000; /* Full-scale is 600 Kelvin */ 347 } else { 348 reg = LTC2943_REG_TEMPERATURE_MSB; 349 value = 5100; /* Full-scale is 510 Kelvin */ 350 } 351 ret = ltc294x_read_regs(info->client, reg, &datar[0], 2); 352 value *= (datar[0] << 8) | datar[1]; 353 /* Convert to tenths of degree Celsius */ 354 *val = value / 0xFFFF - 2722; 355 return ret; 356 } 357 358 static int ltc294x_get_property(struct power_supply *psy, 359 enum power_supply_property prop, 360 union power_supply_propval *val) 361 { 362 struct ltc294x_info *info = power_supply_get_drvdata(psy); 363 364 switch (prop) { 365 case POWER_SUPPLY_PROP_CHARGE_FULL: 366 return ltc294x_get_charge(info, LTC294X_REG_CHARGE_THR_HIGH_MSB, 367 &val->intval); 368 case POWER_SUPPLY_PROP_CHARGE_EMPTY: 369 return ltc294x_get_charge(info, LTC294X_REG_CHARGE_THR_LOW_MSB, 370 &val->intval); 371 case POWER_SUPPLY_PROP_CHARGE_NOW: 372 return ltc294x_get_charge(info, LTC294X_REG_ACC_CHARGE_MSB, 373 &val->intval); 374 case POWER_SUPPLY_PROP_CHARGE_COUNTER: 375 return ltc294x_get_charge_counter(info, &val->intval); 376 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 377 return ltc294x_get_voltage(info, &val->intval); 378 case POWER_SUPPLY_PROP_CURRENT_NOW: 379 return ltc294x_get_current(info, &val->intval); 380 case POWER_SUPPLY_PROP_TEMP: 381 return ltc294x_get_temperature(info, &val->intval); 382 default: 383 return -EINVAL; 384 } 385 } 386 387 static int ltc294x_set_property(struct power_supply *psy, 388 enum power_supply_property psp, 389 const union power_supply_propval *val) 390 { 391 struct ltc294x_info *info = power_supply_get_drvdata(psy); 392 393 switch (psp) { 394 case POWER_SUPPLY_PROP_CHARGE_FULL: 395 return ltc294x_set_charge_thr(info, 396 LTC294X_REG_CHARGE_THR_HIGH_MSB, val->intval); 397 case POWER_SUPPLY_PROP_CHARGE_EMPTY: 398 return ltc294x_set_charge_thr(info, 399 LTC294X_REG_CHARGE_THR_LOW_MSB, val->intval); 400 case POWER_SUPPLY_PROP_CHARGE_NOW: 401 return ltc294x_set_charge_now(info, val->intval); 402 default: 403 return -EPERM; 404 } 405 } 406 407 static int ltc294x_property_is_writeable( 408 struct power_supply *psy, enum power_supply_property psp) 409 { 410 switch (psp) { 411 case POWER_SUPPLY_PROP_CHARGE_FULL: 412 case POWER_SUPPLY_PROP_CHARGE_EMPTY: 413 case POWER_SUPPLY_PROP_CHARGE_NOW: 414 return 1; 415 default: 416 return 0; 417 } 418 } 419 420 static void ltc294x_update(struct ltc294x_info *info) 421 { 422 int charge = ltc294x_read_charge_register(info, LTC294X_REG_ACC_CHARGE_MSB); 423 424 if (charge != info->charge) { 425 info->charge = charge; 426 power_supply_changed(info->supply); 427 } 428 } 429 430 static void ltc294x_work(struct work_struct *work) 431 { 432 struct ltc294x_info *info; 433 434 info = container_of(work, struct ltc294x_info, work.work); 435 ltc294x_update(info); 436 schedule_delayed_work(&info->work, LTC294X_WORK_DELAY * HZ); 437 } 438 439 static enum power_supply_property ltc294x_properties[] = { 440 POWER_SUPPLY_PROP_CHARGE_COUNTER, 441 POWER_SUPPLY_PROP_CHARGE_FULL, 442 POWER_SUPPLY_PROP_CHARGE_EMPTY, 443 POWER_SUPPLY_PROP_CHARGE_NOW, 444 POWER_SUPPLY_PROP_VOLTAGE_NOW, 445 POWER_SUPPLY_PROP_TEMP, 446 POWER_SUPPLY_PROP_CURRENT_NOW, 447 }; 448 449 static int ltc294x_i2c_probe(struct i2c_client *client, 450 const struct i2c_device_id *id) 451 { 452 struct power_supply_config psy_cfg = {}; 453 struct ltc294x_info *info; 454 struct device_node *np; 455 int ret; 456 u32 prescaler_exp; 457 s32 r_sense; 458 u8 status; 459 460 info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL); 461 if (info == NULL) 462 return -ENOMEM; 463 464 i2c_set_clientdata(client, info); 465 466 np = of_node_get(client->dev.of_node); 467 468 info->id = (enum ltc294x_id) (uintptr_t) of_device_get_match_data( 469 &client->dev); 470 info->supply_desc.name = np->name; 471 472 /* r_sense can be negative, when sense+ is connected to the battery 473 * instead of the sense-. This results in reversed measurements. */ 474 ret = of_property_read_u32(np, "lltc,resistor-sense", &r_sense); 475 if (ret < 0) { 476 dev_err(&client->dev, 477 "Could not find lltc,resistor-sense in devicetree\n"); 478 return ret; 479 } 480 info->r_sense = r_sense; 481 482 ret = of_property_read_u32(np, "lltc,prescaler-exponent", 483 &prescaler_exp); 484 if (ret < 0) { 485 dev_warn(&client->dev, 486 "lltc,prescaler-exponent not in devicetree\n"); 487 prescaler_exp = LTC2941_MAX_PRESCALER_EXP; 488 } 489 490 if (info->id == LTC2943_ID) { 491 if (prescaler_exp > LTC2943_MAX_PRESCALER_EXP) 492 prescaler_exp = LTC2943_MAX_PRESCALER_EXP; 493 info->Qlsb = ((340 * 50000) / r_sense) / 494 (4096 / (1 << (2*prescaler_exp))); 495 } else { 496 if (prescaler_exp > LTC2941_MAX_PRESCALER_EXP) 497 prescaler_exp = LTC2941_MAX_PRESCALER_EXP; 498 info->Qlsb = ((85 * 50000) / r_sense) / 499 (128 / (1 << prescaler_exp)); 500 } 501 502 /* Read status register to check for LTC2942 */ 503 if (info->id == LTC2941_ID || info->id == LTC2942_ID) { 504 ret = ltc294x_read_regs(client, LTC294X_REG_STATUS, &status, 1); 505 if (ret < 0) { 506 dev_err(&client->dev, 507 "Could not read status register\n"); 508 return ret; 509 } 510 if (status & LTC2941_REG_STATUS_CHIP_ID) 511 info->id = LTC2941_ID; 512 else 513 info->id = LTC2942_ID; 514 } 515 516 info->client = client; 517 info->supply_desc.type = POWER_SUPPLY_TYPE_BATTERY; 518 info->supply_desc.properties = ltc294x_properties; 519 switch (info->id) { 520 case LTC2944_ID: 521 case LTC2943_ID: 522 info->supply_desc.num_properties = 523 ARRAY_SIZE(ltc294x_properties); 524 break; 525 case LTC2942_ID: 526 info->supply_desc.num_properties = 527 ARRAY_SIZE(ltc294x_properties) - 1; 528 break; 529 case LTC2941_ID: 530 default: 531 info->supply_desc.num_properties = 532 ARRAY_SIZE(ltc294x_properties) - 3; 533 break; 534 } 535 info->supply_desc.get_property = ltc294x_get_property; 536 info->supply_desc.set_property = ltc294x_set_property; 537 info->supply_desc.property_is_writeable = ltc294x_property_is_writeable; 538 info->supply_desc.external_power_changed = NULL; 539 540 psy_cfg.drv_data = info; 541 542 ret = devm_delayed_work_autocancel(&client->dev, &info->work, 543 ltc294x_work); 544 if (ret) 545 return ret; 546 547 ret = ltc294x_reset(info, prescaler_exp); 548 if (ret < 0) { 549 dev_err(&client->dev, "Communication with chip failed\n"); 550 return ret; 551 } 552 553 info->supply = devm_power_supply_register(&client->dev, 554 &info->supply_desc, &psy_cfg); 555 if (IS_ERR(info->supply)) { 556 dev_err(&client->dev, "failed to register ltc2941\n"); 557 return PTR_ERR(info->supply); 558 } else { 559 schedule_delayed_work(&info->work, LTC294X_WORK_DELAY * HZ); 560 } 561 562 return 0; 563 } 564 565 static void ltc294x_i2c_shutdown(struct i2c_client *client) 566 { 567 struct ltc294x_info *info = i2c_get_clientdata(client); 568 int ret; 569 u8 value; 570 u8 control; 571 572 /* The LTC2941 does not need any special handling */ 573 if (info->id == LTC2941_ID) 574 return; 575 576 /* Read control register */ 577 ret = ltc294x_read_regs(info->client, LTC294X_REG_CONTROL, &value, 1); 578 if (ret < 0) 579 return; 580 581 /* Disable continuous ADC conversion as this drains the battery */ 582 control = LTC294X_REG_CONTROL_ADC_DISABLE(value); 583 if (control != value) 584 ltc294x_write_regs(info->client, LTC294X_REG_CONTROL, 585 &control, 1); 586 } 587 588 #ifdef CONFIG_PM_SLEEP 589 590 static int ltc294x_suspend(struct device *dev) 591 { 592 struct i2c_client *client = to_i2c_client(dev); 593 struct ltc294x_info *info = i2c_get_clientdata(client); 594 595 cancel_delayed_work(&info->work); 596 return 0; 597 } 598 599 static int ltc294x_resume(struct device *dev) 600 { 601 struct i2c_client *client = to_i2c_client(dev); 602 struct ltc294x_info *info = i2c_get_clientdata(client); 603 604 schedule_delayed_work(&info->work, LTC294X_WORK_DELAY * HZ); 605 return 0; 606 } 607 608 static SIMPLE_DEV_PM_OPS(ltc294x_pm_ops, ltc294x_suspend, ltc294x_resume); 609 #define LTC294X_PM_OPS (<c294x_pm_ops) 610 611 #else 612 #define LTC294X_PM_OPS NULL 613 #endif /* CONFIG_PM_SLEEP */ 614 615 616 static const struct i2c_device_id ltc294x_i2c_id[] = { 617 { "ltc2941", LTC2941_ID, }, 618 { "ltc2942", LTC2942_ID, }, 619 { "ltc2943", LTC2943_ID, }, 620 { "ltc2944", LTC2944_ID, }, 621 { }, 622 }; 623 MODULE_DEVICE_TABLE(i2c, ltc294x_i2c_id); 624 625 static const struct of_device_id ltc294x_i2c_of_match[] = { 626 { 627 .compatible = "lltc,ltc2941", 628 .data = (void *)LTC2941_ID, 629 }, 630 { 631 .compatible = "lltc,ltc2942", 632 .data = (void *)LTC2942_ID, 633 }, 634 { 635 .compatible = "lltc,ltc2943", 636 .data = (void *)LTC2943_ID, 637 }, 638 { 639 .compatible = "lltc,ltc2944", 640 .data = (void *)LTC2944_ID, 641 }, 642 { }, 643 }; 644 MODULE_DEVICE_TABLE(of, ltc294x_i2c_of_match); 645 646 static struct i2c_driver ltc294x_driver = { 647 .driver = { 648 .name = "LTC2941", 649 .of_match_table = ltc294x_i2c_of_match, 650 .pm = LTC294X_PM_OPS, 651 }, 652 .probe = ltc294x_i2c_probe, 653 .shutdown = ltc294x_i2c_shutdown, 654 .id_table = ltc294x_i2c_id, 655 }; 656 module_i2c_driver(ltc294x_driver); 657 658 MODULE_AUTHOR("Auryn Verwegen, Topic Embedded Systems"); 659 MODULE_AUTHOR("Mike Looijmans, Topic Embedded Products"); 660 MODULE_DESCRIPTION("LTC2941/LTC2942/LTC2943/LTC2944 Battery Gas Gauge IC driver"); 661 MODULE_LICENSE("GPL"); 662