da9150-fg.c (14237B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * DA9150 Fuel-Gauge Driver 4 * 5 * Copyright (c) 2015 Dialog Semiconductor 6 * 7 * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com> 8 */ 9 10#include <linux/kernel.h> 11#include <linux/module.h> 12#include <linux/platform_device.h> 13#include <linux/of.h> 14#include <linux/of_platform.h> 15#include <linux/slab.h> 16#include <linux/interrupt.h> 17#include <linux/delay.h> 18#include <linux/power_supply.h> 19#include <linux/list.h> 20#include <asm/div64.h> 21#include <linux/mfd/da9150/core.h> 22#include <linux/mfd/da9150/registers.h> 23#include <linux/devm-helpers.h> 24 25/* Core2Wire */ 26#define DA9150_QIF_READ (0x0 << 7) 27#define DA9150_QIF_WRITE (0x1 << 7) 28#define DA9150_QIF_CODE_MASK 0x7F 29 30#define DA9150_QIF_BYTE_SIZE 8 31#define DA9150_QIF_BYTE_MASK 0xFF 32#define DA9150_QIF_SHORT_SIZE 2 33#define DA9150_QIF_LONG_SIZE 4 34 35/* QIF Codes */ 36#define DA9150_QIF_UAVG 6 37#define DA9150_QIF_UAVG_SIZE DA9150_QIF_LONG_SIZE 38#define DA9150_QIF_IAVG 8 39#define DA9150_QIF_IAVG_SIZE DA9150_QIF_LONG_SIZE 40#define DA9150_QIF_NTCAVG 12 41#define DA9150_QIF_NTCAVG_SIZE DA9150_QIF_LONG_SIZE 42#define DA9150_QIF_SHUNT_VAL 36 43#define DA9150_QIF_SHUNT_VAL_SIZE DA9150_QIF_SHORT_SIZE 44#define DA9150_QIF_SD_GAIN 38 45#define DA9150_QIF_SD_GAIN_SIZE DA9150_QIF_LONG_SIZE 46#define DA9150_QIF_FCC_MAH 40 47#define DA9150_QIF_FCC_MAH_SIZE DA9150_QIF_SHORT_SIZE 48#define DA9150_QIF_SOC_PCT 43 49#define DA9150_QIF_SOC_PCT_SIZE DA9150_QIF_SHORT_SIZE 50#define DA9150_QIF_CHARGE_LIMIT 44 51#define DA9150_QIF_CHARGE_LIMIT_SIZE DA9150_QIF_SHORT_SIZE 52#define DA9150_QIF_DISCHARGE_LIMIT 45 53#define DA9150_QIF_DISCHARGE_LIMIT_SIZE DA9150_QIF_SHORT_SIZE 54#define DA9150_QIF_FW_MAIN_VER 118 55#define DA9150_QIF_FW_MAIN_VER_SIZE DA9150_QIF_SHORT_SIZE 56#define DA9150_QIF_E_FG_STATUS 126 57#define DA9150_QIF_E_FG_STATUS_SIZE DA9150_QIF_SHORT_SIZE 58#define DA9150_QIF_SYNC 127 59#define DA9150_QIF_SYNC_SIZE DA9150_QIF_SHORT_SIZE 60#define DA9150_QIF_MAX_CODES 128 61 62/* QIF Sync Timeout */ 63#define DA9150_QIF_SYNC_TIMEOUT 1000 64#define DA9150_QIF_SYNC_RETRIES 10 65 66/* QIF E_FG_STATUS */ 67#define DA9150_FG_IRQ_LOW_SOC_MASK (1 << 0) 68#define DA9150_FG_IRQ_HIGH_SOC_MASK (1 << 1) 69#define DA9150_FG_IRQ_SOC_MASK \ 70 (DA9150_FG_IRQ_LOW_SOC_MASK | DA9150_FG_IRQ_HIGH_SOC_MASK) 71 72/* Private data */ 73struct da9150_fg { 74 struct da9150 *da9150; 75 struct device *dev; 76 77 struct mutex io_lock; 78 79 struct power_supply *battery; 80 struct delayed_work work; 81 u32 interval; 82 83 int warn_soc; 84 int crit_soc; 85 int soc; 86}; 87 88/* Battery Properties */ 89static u32 da9150_fg_read_attr(struct da9150_fg *fg, u8 code, u8 size) 90 91{ 92 u8 buf[DA9150_QIF_LONG_SIZE]; 93 u8 read_addr; 94 u32 res = 0; 95 int i; 96 97 /* Set QIF code (READ mode) */ 98 read_addr = (code & DA9150_QIF_CODE_MASK) | DA9150_QIF_READ; 99 100 da9150_read_qif(fg->da9150, read_addr, size, buf); 101 for (i = 0; i < size; ++i) 102 res |= (buf[i] << (i * DA9150_QIF_BYTE_SIZE)); 103 104 return res; 105} 106 107static void da9150_fg_write_attr(struct da9150_fg *fg, u8 code, u8 size, 108 u32 val) 109 110{ 111 u8 buf[DA9150_QIF_LONG_SIZE]; 112 u8 write_addr; 113 int i; 114 115 /* Set QIF code (WRITE mode) */ 116 write_addr = (code & DA9150_QIF_CODE_MASK) | DA9150_QIF_WRITE; 117 118 for (i = 0; i < size; ++i) { 119 buf[i] = (val >> (i * DA9150_QIF_BYTE_SIZE)) & 120 DA9150_QIF_BYTE_MASK; 121 } 122 da9150_write_qif(fg->da9150, write_addr, size, buf); 123} 124 125/* Trigger QIF Sync to update QIF readable data */ 126static void da9150_fg_read_sync_start(struct da9150_fg *fg) 127{ 128 int i = 0; 129 u32 res = 0; 130 131 mutex_lock(&fg->io_lock); 132 133 /* Check if QIF sync already requested, and write to sync if not */ 134 res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC, 135 DA9150_QIF_SYNC_SIZE); 136 if (res > 0) 137 da9150_fg_write_attr(fg, DA9150_QIF_SYNC, 138 DA9150_QIF_SYNC_SIZE, 0); 139 140 /* Wait for sync to complete */ 141 res = 0; 142 while ((res == 0) && (i++ < DA9150_QIF_SYNC_RETRIES)) { 143 usleep_range(DA9150_QIF_SYNC_TIMEOUT, 144 DA9150_QIF_SYNC_TIMEOUT * 2); 145 res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC, 146 DA9150_QIF_SYNC_SIZE); 147 } 148 149 /* Check if sync completed */ 150 if (res == 0) 151 dev_err(fg->dev, "Failed to perform QIF read sync!\n"); 152} 153 154/* 155 * Should always be called after QIF sync read has been performed, and all 156 * attributes required have been accessed. 157 */ 158static inline void da9150_fg_read_sync_end(struct da9150_fg *fg) 159{ 160 mutex_unlock(&fg->io_lock); 161} 162 163/* Sync read of single QIF attribute */ 164static u32 da9150_fg_read_attr_sync(struct da9150_fg *fg, u8 code, u8 size) 165{ 166 u32 val; 167 168 da9150_fg_read_sync_start(fg); 169 val = da9150_fg_read_attr(fg, code, size); 170 da9150_fg_read_sync_end(fg); 171 172 return val; 173} 174 175/* Wait for QIF Sync, write QIF data and wait for ack */ 176static void da9150_fg_write_attr_sync(struct da9150_fg *fg, u8 code, u8 size, 177 u32 val) 178{ 179 int i = 0; 180 u32 res = 0, sync_val; 181 182 mutex_lock(&fg->io_lock); 183 184 /* Check if QIF sync already requested */ 185 res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC, 186 DA9150_QIF_SYNC_SIZE); 187 188 /* Wait for an existing sync to complete */ 189 while ((res == 0) && (i++ < DA9150_QIF_SYNC_RETRIES)) { 190 usleep_range(DA9150_QIF_SYNC_TIMEOUT, 191 DA9150_QIF_SYNC_TIMEOUT * 2); 192 res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC, 193 DA9150_QIF_SYNC_SIZE); 194 } 195 196 if (res == 0) { 197 dev_err(fg->dev, "Timeout waiting for existing QIF sync!\n"); 198 mutex_unlock(&fg->io_lock); 199 return; 200 } 201 202 /* Write value for QIF code */ 203 da9150_fg_write_attr(fg, code, size, val); 204 205 /* Wait for write acknowledgment */ 206 i = 0; 207 sync_val = res; 208 while ((res == sync_val) && (i++ < DA9150_QIF_SYNC_RETRIES)) { 209 usleep_range(DA9150_QIF_SYNC_TIMEOUT, 210 DA9150_QIF_SYNC_TIMEOUT * 2); 211 res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC, 212 DA9150_QIF_SYNC_SIZE); 213 } 214 215 mutex_unlock(&fg->io_lock); 216 217 /* Check write was actually successful */ 218 if (res != (sync_val + 1)) 219 dev_err(fg->dev, "Error performing QIF sync write for code %d\n", 220 code); 221} 222 223/* Power Supply attributes */ 224static int da9150_fg_capacity(struct da9150_fg *fg, 225 union power_supply_propval *val) 226{ 227 val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_SOC_PCT, 228 DA9150_QIF_SOC_PCT_SIZE); 229 230 if (val->intval > 100) 231 val->intval = 100; 232 233 return 0; 234} 235 236static int da9150_fg_current_avg(struct da9150_fg *fg, 237 union power_supply_propval *val) 238{ 239 u32 iavg, sd_gain, shunt_val; 240 u64 div, res; 241 242 da9150_fg_read_sync_start(fg); 243 iavg = da9150_fg_read_attr(fg, DA9150_QIF_IAVG, 244 DA9150_QIF_IAVG_SIZE); 245 shunt_val = da9150_fg_read_attr(fg, DA9150_QIF_SHUNT_VAL, 246 DA9150_QIF_SHUNT_VAL_SIZE); 247 sd_gain = da9150_fg_read_attr(fg, DA9150_QIF_SD_GAIN, 248 DA9150_QIF_SD_GAIN_SIZE); 249 da9150_fg_read_sync_end(fg); 250 251 div = (u64) (sd_gain * shunt_val * 65536ULL); 252 do_div(div, 1000000); 253 res = (u64) (iavg * 1000000ULL); 254 do_div(res, div); 255 256 val->intval = (int) res; 257 258 return 0; 259} 260 261static int da9150_fg_voltage_avg(struct da9150_fg *fg, 262 union power_supply_propval *val) 263{ 264 u64 res; 265 266 val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_UAVG, 267 DA9150_QIF_UAVG_SIZE); 268 269 res = (u64) (val->intval * 186ULL); 270 do_div(res, 10000); 271 val->intval = (int) res; 272 273 return 0; 274} 275 276static int da9150_fg_charge_full(struct da9150_fg *fg, 277 union power_supply_propval *val) 278{ 279 val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_FCC_MAH, 280 DA9150_QIF_FCC_MAH_SIZE); 281 282 val->intval = val->intval * 1000; 283 284 return 0; 285} 286 287/* 288 * Temperature reading from device is only valid if battery/system provides 289 * valid NTC to associated pin of DA9150 chip. 290 */ 291static int da9150_fg_temp(struct da9150_fg *fg, 292 union power_supply_propval *val) 293{ 294 val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_NTCAVG, 295 DA9150_QIF_NTCAVG_SIZE); 296 297 val->intval = (val->intval * 10) / 1048576; 298 299 return 0; 300} 301 302static enum power_supply_property da9150_fg_props[] = { 303 POWER_SUPPLY_PROP_CAPACITY, 304 POWER_SUPPLY_PROP_CURRENT_AVG, 305 POWER_SUPPLY_PROP_VOLTAGE_AVG, 306 POWER_SUPPLY_PROP_CHARGE_FULL, 307 POWER_SUPPLY_PROP_TEMP, 308}; 309 310static int da9150_fg_get_prop(struct power_supply *psy, 311 enum power_supply_property psp, 312 union power_supply_propval *val) 313{ 314 struct da9150_fg *fg = dev_get_drvdata(psy->dev.parent); 315 int ret; 316 317 switch (psp) { 318 case POWER_SUPPLY_PROP_CAPACITY: 319 ret = da9150_fg_capacity(fg, val); 320 break; 321 case POWER_SUPPLY_PROP_CURRENT_AVG: 322 ret = da9150_fg_current_avg(fg, val); 323 break; 324 case POWER_SUPPLY_PROP_VOLTAGE_AVG: 325 ret = da9150_fg_voltage_avg(fg, val); 326 break; 327 case POWER_SUPPLY_PROP_CHARGE_FULL: 328 ret = da9150_fg_charge_full(fg, val); 329 break; 330 case POWER_SUPPLY_PROP_TEMP: 331 ret = da9150_fg_temp(fg, val); 332 break; 333 default: 334 ret = -EINVAL; 335 break; 336 } 337 338 return ret; 339} 340 341/* Repeated SOC check */ 342static bool da9150_fg_soc_changed(struct da9150_fg *fg) 343{ 344 union power_supply_propval val; 345 346 da9150_fg_capacity(fg, &val); 347 if (val.intval != fg->soc) { 348 fg->soc = val.intval; 349 return true; 350 } 351 352 return false; 353} 354 355static void da9150_fg_work(struct work_struct *work) 356{ 357 struct da9150_fg *fg = container_of(work, struct da9150_fg, work.work); 358 359 /* Report if SOC has changed */ 360 if (da9150_fg_soc_changed(fg)) 361 power_supply_changed(fg->battery); 362 363 schedule_delayed_work(&fg->work, msecs_to_jiffies(fg->interval)); 364} 365 366/* SOC level event configuration */ 367static void da9150_fg_soc_event_config(struct da9150_fg *fg) 368{ 369 int soc; 370 371 soc = da9150_fg_read_attr_sync(fg, DA9150_QIF_SOC_PCT, 372 DA9150_QIF_SOC_PCT_SIZE); 373 374 if (soc > fg->warn_soc) { 375 /* If SOC > warn level, set discharge warn level event */ 376 da9150_fg_write_attr_sync(fg, DA9150_QIF_DISCHARGE_LIMIT, 377 DA9150_QIF_DISCHARGE_LIMIT_SIZE, 378 fg->warn_soc + 1); 379 } else if ((soc <= fg->warn_soc) && (soc > fg->crit_soc)) { 380 /* 381 * If SOC <= warn level, set discharge crit level event, 382 * and set charge warn level event. 383 */ 384 da9150_fg_write_attr_sync(fg, DA9150_QIF_DISCHARGE_LIMIT, 385 DA9150_QIF_DISCHARGE_LIMIT_SIZE, 386 fg->crit_soc + 1); 387 388 da9150_fg_write_attr_sync(fg, DA9150_QIF_CHARGE_LIMIT, 389 DA9150_QIF_CHARGE_LIMIT_SIZE, 390 fg->warn_soc); 391 } else if (soc <= fg->crit_soc) { 392 /* If SOC <= crit level, set charge crit level event */ 393 da9150_fg_write_attr_sync(fg, DA9150_QIF_CHARGE_LIMIT, 394 DA9150_QIF_CHARGE_LIMIT_SIZE, 395 fg->crit_soc); 396 } 397} 398 399static irqreturn_t da9150_fg_irq(int irq, void *data) 400{ 401 struct da9150_fg *fg = data; 402 u32 e_fg_status; 403 404 /* Read FG IRQ status info */ 405 e_fg_status = da9150_fg_read_attr(fg, DA9150_QIF_E_FG_STATUS, 406 DA9150_QIF_E_FG_STATUS_SIZE); 407 408 /* Handle warning/critical threhold events */ 409 if (e_fg_status & DA9150_FG_IRQ_SOC_MASK) 410 da9150_fg_soc_event_config(fg); 411 412 /* Clear any FG IRQs */ 413 da9150_fg_write_attr(fg, DA9150_QIF_E_FG_STATUS, 414 DA9150_QIF_E_FG_STATUS_SIZE, e_fg_status); 415 416 return IRQ_HANDLED; 417} 418 419static struct da9150_fg_pdata *da9150_fg_dt_pdata(struct device *dev) 420{ 421 struct device_node *fg_node = dev->of_node; 422 struct da9150_fg_pdata *pdata; 423 424 pdata = devm_kzalloc(dev, sizeof(struct da9150_fg_pdata), GFP_KERNEL); 425 if (!pdata) 426 return NULL; 427 428 of_property_read_u32(fg_node, "dlg,update-interval", 429 &pdata->update_interval); 430 of_property_read_u8(fg_node, "dlg,warn-soc-level", 431 &pdata->warn_soc_lvl); 432 of_property_read_u8(fg_node, "dlg,crit-soc-level", 433 &pdata->crit_soc_lvl); 434 435 return pdata; 436} 437 438static const struct power_supply_desc fg_desc = { 439 .name = "da9150-fg", 440 .type = POWER_SUPPLY_TYPE_BATTERY, 441 .properties = da9150_fg_props, 442 .num_properties = ARRAY_SIZE(da9150_fg_props), 443 .get_property = da9150_fg_get_prop, 444}; 445 446static int da9150_fg_probe(struct platform_device *pdev) 447{ 448 struct device *dev = &pdev->dev; 449 struct da9150 *da9150 = dev_get_drvdata(dev->parent); 450 struct da9150_fg_pdata *fg_pdata = dev_get_platdata(dev); 451 struct da9150_fg *fg; 452 int ver, irq, ret = 0; 453 454 fg = devm_kzalloc(dev, sizeof(*fg), GFP_KERNEL); 455 if (fg == NULL) 456 return -ENOMEM; 457 458 platform_set_drvdata(pdev, fg); 459 fg->da9150 = da9150; 460 fg->dev = dev; 461 462 mutex_init(&fg->io_lock); 463 464 /* Enable QIF */ 465 da9150_set_bits(da9150, DA9150_CORE2WIRE_CTRL_A, DA9150_FG_QIF_EN_MASK, 466 DA9150_FG_QIF_EN_MASK); 467 468 fg->battery = devm_power_supply_register(dev, &fg_desc, NULL); 469 if (IS_ERR(fg->battery)) { 470 ret = PTR_ERR(fg->battery); 471 return ret; 472 } 473 474 ver = da9150_fg_read_attr(fg, DA9150_QIF_FW_MAIN_VER, 475 DA9150_QIF_FW_MAIN_VER_SIZE); 476 dev_info(dev, "Version: 0x%x\n", ver); 477 478 /* Handle DT data if provided */ 479 if (dev->of_node) { 480 fg_pdata = da9150_fg_dt_pdata(dev); 481 dev->platform_data = fg_pdata; 482 } 483 484 /* Handle any pdata provided */ 485 if (fg_pdata) { 486 fg->interval = fg_pdata->update_interval; 487 488 if (fg_pdata->warn_soc_lvl > 100) 489 dev_warn(dev, "Invalid SOC warning level provided, Ignoring"); 490 else 491 fg->warn_soc = fg_pdata->warn_soc_lvl; 492 493 if ((fg_pdata->crit_soc_lvl > 100) || 494 (fg_pdata->crit_soc_lvl >= fg_pdata->warn_soc_lvl)) 495 dev_warn(dev, "Invalid SOC critical level provided, Ignoring"); 496 else 497 fg->crit_soc = fg_pdata->crit_soc_lvl; 498 499 500 } 501 502 /* Configure initial SOC level events */ 503 da9150_fg_soc_event_config(fg); 504 505 /* 506 * If an interval period has been provided then setup repeating 507 * work for reporting data updates. 508 */ 509 if (fg->interval) { 510 ret = devm_delayed_work_autocancel(dev, &fg->work, 511 da9150_fg_work); 512 if (ret) { 513 dev_err(dev, "Failed to init work\n"); 514 return ret; 515 } 516 517 schedule_delayed_work(&fg->work, 518 msecs_to_jiffies(fg->interval)); 519 } 520 521 /* Register IRQ */ 522 irq = platform_get_irq_byname(pdev, "FG"); 523 if (irq < 0) 524 return irq; 525 526 ret = devm_request_threaded_irq(dev, irq, NULL, da9150_fg_irq, 527 IRQF_ONESHOT, "FG", fg); 528 if (ret) { 529 dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret); 530 return ret; 531 } 532 533 return 0; 534} 535 536static int da9150_fg_resume(struct platform_device *pdev) 537{ 538 struct da9150_fg *fg = platform_get_drvdata(pdev); 539 540 /* 541 * Trigger SOC check to happen now so as to indicate any value change 542 * since last check before suspend. 543 */ 544 if (fg->interval) 545 flush_delayed_work(&fg->work); 546 547 return 0; 548} 549 550static struct platform_driver da9150_fg_driver = { 551 .driver = { 552 .name = "da9150-fuel-gauge", 553 }, 554 .probe = da9150_fg_probe, 555 .resume = da9150_fg_resume, 556}; 557 558module_platform_driver(da9150_fg_driver); 559 560MODULE_DESCRIPTION("Fuel-Gauge Driver for DA9150"); 561MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>"); 562MODULE_LICENSE("GPL");