Lines Matching +full:vbus +full:- +full:divider
9 * Copyright (C) 2009-2010 Motorola, Inc.
34 #include <linux/mfd/motorola-cpcap.h>
38 * map to MC13783UG.pdf "Table 5-19. Register 13, Power Control 0"
139 #define CPCAP_NO_BATTERY -400
148 return &ddata->state[state]; in cpcap_battery_get_state()
169 channel = ddata->channels[CPCAP_BATTERY_IIO_BATTDET]; in cpcap_charger_battery_temperature()
172 dev_warn(ddata->dev, "%s failed: %i\n", __func__, error); in cpcap_charger_battery_temperature()
188 channel = ddata->channels[CPCAP_BATTERY_IIO_VOLTAGE]; in cpcap_battery_get_voltage()
191 dev_warn(ddata->dev, "%s failed: %i\n", __func__, error); in cpcap_battery_get_voltage()
204 channel = ddata->channels[CPCAP_BATTERY_IIO_BATT_CURRENT]; in cpcap_battery_get_current()
207 dev_warn(ddata->dev, "%s failed: %i\n", __func__, error); in cpcap_battery_get_current()
216 * cpcap_battery_cc_raw_div - calculate and divide coulomb counter μAms values
221 * @divider: conversion divider
238 s16 offset, u32 divider) in cpcap_battery_cc_raw_div() argument
242 if (!divider) in cpcap_battery_cc_raw_div()
246 acc -= (s64)sample * offset; in cpcap_battery_cc_raw_div()
247 acc *= ddata->cc_lsb; in cpcap_battery_cc_raw_div()
248 acc *= -1; in cpcap_battery_cc_raw_div()
249 acc = div_s64(acc, divider); in cpcap_battery_cc_raw_div()
275 * cpcap_battery_read_accumulated - reads cpcap coulomb counter
296 ccd->sample = 0; in cpcap_battery_read_accumulated()
297 ccd->accumulator = 0; in cpcap_battery_read_accumulated()
298 ccd->offset = 0; in cpcap_battery_read_accumulated()
299 ccd->integrator = 0; in cpcap_battery_read_accumulated()
302 error = regmap_bulk_read(ddata->reg, CPCAP_REG_CCS1, in cpcap_battery_read_accumulated()
308 ccd->sample = (buf[1] & 0x0fff) << 16; in cpcap_battery_read_accumulated()
309 ccd->sample |= buf[0]; in cpcap_battery_read_accumulated()
310 if (ddata->vendor == CPCAP_VENDOR_TI) in cpcap_battery_read_accumulated()
311 ccd->sample = sign_extend32(24, ccd->sample); in cpcap_battery_read_accumulated()
314 ccd->accumulator = ((s16)buf[3]) << 16; in cpcap_battery_read_accumulated()
315 ccd->accumulator |= buf[2]; in cpcap_battery_read_accumulated()
321 ccd->offset = buf[4]; in cpcap_battery_read_accumulated()
322 ccd->offset = sign_extend32(ccd->offset, 9); in cpcap_battery_read_accumulated()
325 if (ddata->vendor == CPCAP_VENDOR_TI) in cpcap_battery_read_accumulated()
326 ccd->integrator = sign_extend32(buf[6], 13); in cpcap_battery_read_accumulated()
328 ccd->integrator = (s16)buf[6]; in cpcap_battery_read_accumulated()
331 ccd->sample, in cpcap_battery_read_accumulated()
332 ccd->accumulator, in cpcap_battery_read_accumulated()
333 ccd->offset); in cpcap_battery_read_accumulated()
337 * cpcap_battery_cc_get_avg_current - read cpcap coulumb counter
347 error = regmap_read(ddata->reg, CPCAP_REG_CCI, &value); in cpcap_battery_cc_get_avg_current()
351 if (ddata->vendor == CPCAP_VENDOR_TI) { in cpcap_battery_cc_get_avg_current()
360 error = regmap_read(ddata->reg, CPCAP_REG_CCM, &value); in cpcap_battery_cc_get_avg_current()
373 if (state->voltage >= in cpcap_battery_full()
374 (ddata->config.bat.constant_charge_voltage_max_uv - 18000)) in cpcap_battery_full()
391 s64 delta_ms = ktime_to_ms(ktime_sub(now, latest->time)); in cpcap_battery_update_status()
453 if (latest->temperature > CPCAP_NO_BATTERY) in cpcap_battery_get_property()
454 val->intval = 1; in cpcap_battery_get_property()
456 val->intval = 0; in cpcap_battery_get_property()
460 val->intval = POWER_SUPPLY_STATUS_FULL; in cpcap_battery_get_property()
464 val->intval = POWER_SUPPLY_STATUS_CHARGING; in cpcap_battery_get_property()
466 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; in cpcap_battery_get_property()
469 val->intval = ddata->config.info.technology; in cpcap_battery_get_property()
472 val->intval = cpcap_battery_get_voltage(ddata); in cpcap_battery_get_property()
475 val->intval = ddata->config.info.voltage_max_design; in cpcap_battery_get_property()
478 val->intval = ddata->config.info.voltage_min_design; in cpcap_battery_get_property()
481 val->intval = ddata->config.bat.constant_charge_voltage_max_uv; in cpcap_battery_get_property()
484 sample = latest->cc.sample - previous->cc.sample; in cpcap_battery_get_property()
486 val->intval = cpcap_battery_cc_get_avg_current(ddata); in cpcap_battery_get_property()
489 accumulator = latest->cc.accumulator - previous->cc.accumulator; in cpcap_battery_get_property()
490 val->intval = cpcap_battery_cc_to_ua(ddata, sample, in cpcap_battery_get_property()
492 latest->cc.offset); in cpcap_battery_get_property()
495 val->intval = latest->current_ua; in cpcap_battery_get_property()
498 val->intval = latest->counter_uah; in cpcap_battery_get_property()
501 tmp = (latest->voltage / 10000) * latest->current_ua; in cpcap_battery_get_property()
502 val->intval = div64_s64(tmp, 100); in cpcap_battery_get_property()
505 sample = latest->cc.sample - previous->cc.sample; in cpcap_battery_get_property()
508 tmp *= (latest->voltage / 10000); in cpcap_battery_get_property()
509 val->intval = div64_s64(tmp, 100); in cpcap_battery_get_property()
512 accumulator = latest->cc.accumulator - previous->cc.accumulator; in cpcap_battery_get_property()
514 latest->cc.offset); in cpcap_battery_get_property()
515 tmp *= ((latest->voltage + previous->voltage) / 20000); in cpcap_battery_get_property()
516 val->intval = div64_s64(tmp, 100); in cpcap_battery_get_property()
520 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL; in cpcap_battery_get_property()
521 else if (latest->voltage >= 3750000) in cpcap_battery_get_property()
522 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_HIGH; in cpcap_battery_get_property()
523 else if (latest->voltage >= 3300000) in cpcap_battery_get_property()
524 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; in cpcap_battery_get_property()
525 else if (latest->voltage > 3100000) in cpcap_battery_get_property()
526 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW; in cpcap_battery_get_property()
527 else if (latest->voltage <= 3100000) in cpcap_battery_get_property()
528 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; in cpcap_battery_get_property()
530 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN; in cpcap_battery_get_property()
533 val->intval = ddata->config.info.charge_full_design; in cpcap_battery_get_property()
536 val->intval = POWER_SUPPLY_SCOPE_SYSTEM; in cpcap_battery_get_property()
539 val->intval = latest->temperature; in cpcap_battery_get_property()
542 return -EINVAL; in cpcap_battery_get_property()
558 return -ENODEV; in cpcap_battery_update_charger()
585 if (val->intval < ddata->config.info.voltage_min_design) in cpcap_battery_set_property()
586 return -EINVAL; in cpcap_battery_set_property()
587 if (val->intval > ddata->config.info.voltage_max_design) in cpcap_battery_set_property()
588 return -EINVAL; in cpcap_battery_set_property()
590 ddata->config.bat.constant_charge_voltage_max_uv = val->intval; in cpcap_battery_set_property()
592 return cpcap_battery_update_charger(ddata, val->intval); in cpcap_battery_set_property()
594 return -EINVAL; in cpcap_battery_set_property()
617 if (!atomic_read(&ddata->active)) in cpcap_battery_irq_thread()
620 list_for_each_entry(d, &ddata->irq_list, node) { in cpcap_battery_irq_thread()
621 if (irq == d->irq) in cpcap_battery_irq_thread()
630 switch (d->action) { in cpcap_battery_irq_thread()
632 dev_info(ddata->dev, "Coulomb counter calibration done\n"); in cpcap_battery_irq_thread()
635 if (latest->current_ua >= 0) in cpcap_battery_irq_thread()
636 dev_warn(ddata->dev, "Battery low at %imV!\n", in cpcap_battery_irq_thread()
637 latest->voltage / 1000); in cpcap_battery_irq_thread()
640 if (latest->current_ua >= 0 && latest->voltage <= 3200000) { in cpcap_battery_irq_thread()
641 dev_emerg(ddata->dev, in cpcap_battery_irq_thread()
643 latest->voltage / 1000); in cpcap_battery_irq_thread()
651 power_supply_changed(ddata->psy); in cpcap_battery_irq_thread()
667 error = devm_request_threaded_irq(ddata->dev, irq, NULL, in cpcap_battery_init_irq()
672 dev_err(ddata->dev, "could not get irq %s: %i\n", in cpcap_battery_init_irq()
678 d = devm_kzalloc(ddata->dev, sizeof(*d), GFP_KERNEL); in cpcap_battery_init_irq()
680 return -ENOMEM; in cpcap_battery_init_irq()
682 d->name = name; in cpcap_battery_init_irq()
683 d->irq = irq; in cpcap_battery_init_irq()
686 d->action = CPCAP_BATTERY_IRQ_ACTION_CC_CAL_DONE; in cpcap_battery_init_irq()
688 d->action = CPCAP_BATTERY_IRQ_ACTION_BATTERY_LOW; in cpcap_battery_init_irq()
690 d->action = CPCAP_BATTERY_IRQ_ACTION_POWEROFF; in cpcap_battery_init_irq()
692 list_add(&d->node, &ddata->irq_list); in cpcap_battery_init_irq()
717 error = regmap_update_bits(ddata->reg, CPCAP_REG_BPEOL, in cpcap_battery_init_interrupts()
734 ddata->channels[i] = devm_iio_channel_get(ddata->dev, in cpcap_battery_init_iio()
736 if (IS_ERR(ddata->channels[i])) { in cpcap_battery_init_iio()
737 error = PTR_ERR(ddata->channels[i]); in cpcap_battery_init_iio()
741 if (!ddata->channels[i]->indio_dev) { in cpcap_battery_init_iio()
742 error = -ENXIO; in cpcap_battery_init_iio()
750 return dev_err_probe(ddata->dev, error, in cpcap_battery_init_iio()
751 "could not initialize VBUS or ID IIO\n"); in cpcap_battery_init_iio()
760 error = regmap_read(ddata->reg, CPCAP_REG_CCC1, &ccc1); in cpcap_battery_calibrate()
767 error = regmap_update_bits(ddata->reg, CPCAP_REG_CCC1, in cpcap_battery_calibrate()
774 error = regmap_read(ddata->reg, CPCAP_REG_CCC1, &value); in cpcap_battery_calibrate()
781 error = regmap_read(ddata->reg, CPCAP_REG_CCM, &value); in cpcap_battery_calibrate()
789 error = regmap_read(ddata->reg, CPCAP_REG_CCM, &value); in cpcap_battery_calibrate()
793 dev_info(ddata->dev, "calibration done: 0x%04x\n", value); in cpcap_battery_calibrate()
797 dev_err(ddata->dev, "%s: error %i\n", __func__, error); in cpcap_battery_calibrate()
799 error = regmap_update_bits(ddata->reg, CPCAP_REG_CCC1, in cpcap_battery_calibrate()
802 dev_err(ddata->dev, "%s: restore error %i\n", in cpcap_battery_calibrate()
830 .compatible = "motorola,cpcap-battery",
847 &pdev->dev); in cpcap_battery_probe()
849 return -EINVAL; in cpcap_battery_probe()
851 if (!match->data) { in cpcap_battery_probe()
852 dev_err(&pdev->dev, "no configuration data found\n"); in cpcap_battery_probe()
854 return -ENODEV; in cpcap_battery_probe()
857 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); in cpcap_battery_probe()
859 return -ENOMEM; in cpcap_battery_probe()
861 INIT_LIST_HEAD(&ddata->irq_list); in cpcap_battery_probe()
862 ddata->dev = &pdev->dev; in cpcap_battery_probe()
863 memcpy(&ddata->config, match->data, sizeof(ddata->config)); in cpcap_battery_probe()
865 ddata->reg = dev_get_regmap(ddata->dev->parent, NULL); in cpcap_battery_probe()
866 if (!ddata->reg) in cpcap_battery_probe()
867 return -ENODEV; in cpcap_battery_probe()
869 error = cpcap_get_vendor(ddata->dev, ddata->reg, &ddata->vendor); in cpcap_battery_probe()
873 switch (ddata->vendor) { in cpcap_battery_probe()
875 ddata->cc_lsb = 95374; /* μAms per LSB */ in cpcap_battery_probe()
878 ddata->cc_lsb = 91501; /* μAms per LSB */ in cpcap_battery_probe()
881 return -EINVAL; in cpcap_battery_probe()
883 ddata->cc_lsb = (ddata->cc_lsb * ddata->config.cd_factor) / 1000; in cpcap_battery_probe()
895 psy_desc = devm_kzalloc(ddata->dev, sizeof(*psy_desc), GFP_KERNEL); in cpcap_battery_probe()
897 return -ENOMEM; in cpcap_battery_probe()
899 psy_desc->name = "battery"; in cpcap_battery_probe()
900 psy_desc->type = POWER_SUPPLY_TYPE_BATTERY; in cpcap_battery_probe()
901 psy_desc->properties = cpcap_battery_props; in cpcap_battery_probe()
902 psy_desc->num_properties = ARRAY_SIZE(cpcap_battery_props); in cpcap_battery_probe()
903 psy_desc->get_property = cpcap_battery_get_property; in cpcap_battery_probe()
904 psy_desc->set_property = cpcap_battery_set_property; in cpcap_battery_probe()
905 psy_desc->property_is_writeable = cpcap_battery_property_is_writeable; in cpcap_battery_probe()
907 psy_cfg.of_node = pdev->dev.of_node; in cpcap_battery_probe()
910 ddata->psy = devm_power_supply_register(ddata->dev, psy_desc, in cpcap_battery_probe()
912 error = PTR_ERR_OR_ZERO(ddata->psy); in cpcap_battery_probe()
914 dev_err(ddata->dev, "failed to register power supply\n"); in cpcap_battery_probe()
918 atomic_set(&ddata->active, 1); in cpcap_battery_probe()
932 atomic_set(&ddata->active, 0); in cpcap_battery_remove()
933 error = regmap_update_bits(ddata->reg, CPCAP_REG_BPEOL, in cpcap_battery_remove()
936 dev_err(&pdev->dev, "could not disable: %i\n", error); in cpcap_battery_remove()