Lines Matching +full:current +full:- +full:limit +full:- +full:sense +full:- +full:microvolt

1 // SPDX-License-Identifier: GPL-2.0-only
16 * Curve (1) represents charging current.
20 * a) Trickle-charge with constant current (8).
21 * b) pre-charge with constant current (6)
22 * c) fast-charge, first with constant current (5) phase. After
24 * voltage phase until charging current has dropped to termination
30 *(4)` `.` ` ` ` ` ` ` ` ` ` ` ` ` ` ----------------------------.
32 * . o----+/:/ ` ` ` ` ` ` ` ` ` ` ` ` `.` ` (5)
34 * . + /- -- .
35 * . +`/- + .
36 * . o/- -: .
38 * . .--+ `/ .
40 * . -` + -- .
41 * . (2) ...`` + :- .
42 * . ...`` + -: .
43 *(3)` `.`."" ` ` ` `+-------- ` ` ` ` ` ` `.:` ` ` ` ` ` ` ` ` .` ` (6)
45 * . + -: .
46 * . + -:. .
47 * . + .--. .
49 * -..............` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` + ` ` ` .` ` (8)
50 * . + -
51 * -------------------------------------------------+++++++++-->
71 #include "bd99954-charger.h"
76 u16 ibus_lim_set; /* VBUS input current limitation */
77 u16 icc_lim_set; /* VCC/VACP Input Current Limit Setting */
78 u16 itrich_set; /* Trickle-charge Current Setting */
79 u16 iprech_set; /* Pre-Charge Current Setting */
80 u16 ichg_set; /* Fast-Charge constant current */
82 u16 vprechg_th_set; /* Pre-charge Voltage Threshold Setting */
83 u16 vrechg_set; /* Re-charge Battery Voltage Setting */
85 u16 iterm_set; /* Charging termination current */
179 ret = regmap_field_read(bd->rmap_fields[F_BATTEMP], &tmp); in bd9995x_get_prop_batt_health()
206 ret = regmap_field_read(bd->rmap_fields[F_CHGSTM_STATE], &tmp); in bd9995x_get_prop_charge_type()
229 ret = regmap_field_read(bd->rmap_fields[F_BATTEMP], &tmp); in bd9995x_get_prop_batt_present()
240 ret = regmap_field_read(bd->rmap_fields[F_VBAT_VAL], &tmp); in bd9995x_get_prop_batt_voltage()
253 ret = regmap_field_read(bd->rmap_fields[F_IBATP_VAL], &tmp); in bd9995x_get_prop_batt_current()
266 ret = regmap_field_read(bd->rmap_fields[F_THERM_VAL], &tmp); in bd9995x_get_prop_batt_temp()
270 return (200 - tmp) * 10; in bd9995x_get_prop_batt_temp()
281 mutex_lock(&bd->lock); in bd9995x_power_supply_get_property()
282 state = bd->state; in bd9995x_power_supply_get_property()
283 mutex_unlock(&bd->lock); in bd9995x_power_supply_get_property()
292 val->intval = POWER_SUPPLY_STATUS_CHARGING; in bd9995x_power_supply_get_property()
296 val->intval = POWER_SUPPLY_STATUS_FULL; in bd9995x_power_supply_get_property()
315 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; in bd9995x_power_supply_get_property()
319 val->intval = POWER_SUPPLY_STATUS_UNKNOWN; in bd9995x_power_supply_get_property()
325 val->strval = BD9995X_MANUFACTURER; in bd9995x_power_supply_get_property()
329 val->intval = state.online; in bd9995x_power_supply_get_property()
333 ret = regmap_field_read(bd->rmap_fields[F_IBATP_VAL], &tmp); in bd9995x_power_supply_get_property()
336 val->intval = tmp * 1000; in bd9995x_power_supply_get_property()
340 ret = regmap_field_read(bd->rmap_fields[F_IBATP_AVE_VAL], &tmp); in bd9995x_power_supply_get_property()
343 val->intval = tmp * 1000; in bd9995x_power_supply_get_property()
349 * target current for fast-charging constant current phase. in bd9995x_power_supply_get_property()
350 * I think it is correct in a sense. in bd9995x_power_supply_get_property()
353 * safety limit for combined input currents. This feels in bd9995x_power_supply_get_property()
354 * also correct in a sense. in bd9995x_power_supply_get_property()
359 ret = regmap_field_read(bd->rmap_fields[F_SEL_ILIM_VAL], &tmp); in bd9995x_power_supply_get_property()
362 val->intval = tmp * 1000; in bd9995x_power_supply_get_property()
367 val->intval = 0; in bd9995x_power_supply_get_property()
371 ret = regmap_field_read(bd->rmap_fields[F_VFASTCHG_REG_SET1], in bd9995x_power_supply_get_property()
380 val->intval = clamp_val(tmp << 4, 2560, 19200); in bd9995x_power_supply_get_property()
381 val->intval *= 1000; in bd9995x_power_supply_get_property()
385 ret = regmap_field_read(bd->rmap_fields[F_ITERM_SET], &tmp); in bd9995x_power_supply_get_property()
389 val->intval = tmp << 6; in bd9995x_power_supply_get_property()
390 /* Maximum is 1024 mA - no matter what register says */ in bd9995x_power_supply_get_property()
391 val->intval = min(val->intval, 1024); in bd9995x_power_supply_get_property()
392 val->intval *= 1000; in bd9995x_power_supply_get_property()
397 val->intval = bd9995x_get_prop_batt_present(bd); in bd9995x_power_supply_get_property()
401 val->intval = bd9995x_get_prop_batt_voltage(bd); in bd9995x_power_supply_get_property()
405 val->intval = bd9995x_get_prop_batt_current(bd); in bd9995x_power_supply_get_property()
409 val->intval = bd9995x_get_prop_charge_type(bd); in bd9995x_power_supply_get_property()
413 val->intval = bd9995x_get_prop_batt_health(bd); in bd9995x_power_supply_get_property()
417 val->intval = bd9995x_get_prop_batt_temp(bd); in bd9995x_power_supply_get_property()
421 val->intval = POWER_SUPPLY_TECHNOLOGY_LION; in bd9995x_power_supply_get_property()
425 val->strval = "bd99954"; in bd9995x_power_supply_get_property()
429 return -EINVAL; in bd9995x_power_supply_get_property()
445 bd->rmap_fields[F_CHGSTM_STATE], &state->chgstm_status, in bd9995x_get_chip_state()
447 bd->rmap_fields[F_VBAT_VSYS_STATUS], in bd9995x_get_chip_state()
448 &state->vbat_vsys_status, in bd9995x_get_chip_state()
450 bd->rmap_fields[F_VBUS_VCC_STATUS], in bd9995x_get_chip_state()
451 &state->vbus_vcc_status, in bd9995x_get_chip_state()
464 if (state->vbus_vcc_status & STATUS_VCC_DET || in bd9995x_get_chip_state()
465 state->vbus_vcc_status & STATUS_VBUS_DET) in bd9995x_get_chip_state()
466 state->online = 1; in bd9995x_get_chip_state()
468 state->online = 0; in bd9995x_get_chip_state()
485 * So lets implement really simple and hopefully bullet-proof handler: in bd9995x_irq_handler_thread()
487 * re-read all interesting statuses + give the framework a nudge. in bd9995x_irq_handler_thread()
496 ret = regmap_read(bd->rmap, INT0_STATUS, &status); in bd9995x_irq_handler_thread()
498 dev_err(bd->dev, "Failed to read IRQ status\n"); in bd9995x_irq_handler_thread()
502 ret = regmap_field_read(bd->rmap_fields[F_INT0_SET], &mask); in bd9995x_irq_handler_thread()
504 dev_err(bd->dev, "Failed to read IRQ mask\n"); in bd9995x_irq_handler_thread()
512 /* Lowest bit does not represent any sub-registers */ in bd9995x_irq_handler_thread()
518 ret = regmap_field_write(bd->rmap_fields[F_INT0_SET], 0); in bd9995x_irq_handler_thread()
520 dev_err(bd->dev, "Failed to mask F_INT0\n"); in bd9995x_irq_handler_thread()
524 ret = regmap_write(bd->rmap, INT0_STATUS, status); in bd9995x_irq_handler_thread()
526 dev_err(bd->dev, "Failed to ack F_INT0\n"); in bd9995x_irq_handler_thread()
537 bd->rmap_fields[F_INT1_SET], in bd9995x_irq_handler_thread()
538 bd->rmap_fields[F_INT2_SET], in bd9995x_irq_handler_thread()
539 bd->rmap_fields[F_INT3_SET], in bd9995x_irq_handler_thread()
540 bd->rmap_fields[F_INT4_SET], in bd9995x_irq_handler_thread()
541 bd->rmap_fields[F_INT5_SET], in bd9995x_irq_handler_thread()
542 bd->rmap_fields[F_INT6_SET], in bd9995x_irq_handler_thread()
543 bd->rmap_fields[F_INT7_SET], in bd9995x_irq_handler_thread()
547 ret = regmap_read(bd->rmap, sub_status_reg[i], &sub_status); in bd9995x_irq_handler_thread()
549 dev_err(bd->dev, "Failed to read IRQ sub-status\n"); in bd9995x_irq_handler_thread()
555 dev_err(bd->dev, "Failed to read IRQ sub-mask\n"); in bd9995x_irq_handler_thread()
559 /* Ack active sub-statuses */ in bd9995x_irq_handler_thread()
562 ret = regmap_write(bd->rmap, sub_status_reg[i], sub_status); in bd9995x_irq_handler_thread()
564 dev_err(bd->dev, "Failed to ack sub-IRQ\n"); in bd9995x_irq_handler_thread()
569 ret = regmap_field_write(bd->rmap_fields[F_INT0_SET], mask); in bd9995x_irq_handler_thread()
577 dev_err(bd->dev, "Failed to read chip state\n"); in bd9995x_irq_handler_thread()
579 mutex_lock(&bd->lock); in bd9995x_irq_handler_thread()
580 bd->state = state; in bd9995x_irq_handler_thread()
581 mutex_unlock(&bd->lock); in bd9995x_irq_handler_thread()
583 power_supply_changed(bd->charger); in bd9995x_irq_handler_thread()
589 ret = regmap_field_write(bd->rmap_fields[F_INT0_SET], mask); in bd9995x_irq_handler_thread()
591 dev_err(bd->dev, in bd9995x_irq_handler_thread()
592 "Failed to un-mask F_INT0 - IRQ permanently disabled\n"); in bd9995x_irq_handler_thread()
603 ret = regmap_raw_write(bd->rmap, SYSTEM_CTRL_SET, &tmp, 2); in __bd9995x_chip_reset()
608 ret = regmap_field_read(bd->rmap_fields[F_OTPLD_STATE], &state); in __bd9995x_chip_reset()
613 } while (state == 0 && --rst_check_counter); in __bd9995x_chip_reset()
616 dev_err(bd->dev, "chip reset not completed\n"); in __bd9995x_chip_reset()
617 return -ETIMEDOUT; in __bd9995x_chip_reset()
621 ret = regmap_raw_write(bd->rmap, SYSTEM_CTRL_SET, &tmp, 2); in __bd9995x_chip_reset()
631 struct bd9995x_init_data *id = &bd->init_data; in bd9995x_hw_init()
645 /* Disable automatic limitation of the input current */ in bd9995x_hw_init()
647 /* Select current limitation when SDP charger attached*/ in bd9995x_hw_init()
649 /* Select current limitation when DCP charger attached */ in bd9995x_hw_init()
651 {F_VSYSREG_SET, id->vsysreg_set}, in bd9995x_hw_init()
658 /* Disable Input current Limit setting voltage measurement */ in bd9995x_hw_init()
660 /* Disable input current limiting */ in bd9995x_hw_init()
662 {F_IBUS_LIM_SET, id->ibus_lim_set}, in bd9995x_hw_init()
663 {F_ICC_LIM_SET, id->icc_lim_set}, in bd9995x_hw_init()
664 /* Charge Termination Current Setting to 0*/ in bd9995x_hw_init()
665 {F_ITERM_SET, id->iterm_set}, in bd9995x_hw_init()
666 /* Trickle-charge Current Setting */ in bd9995x_hw_init()
667 {F_ITRICH_SET, id->itrich_set}, in bd9995x_hw_init()
668 /* Pre-charge Current setting */ in bd9995x_hw_init()
669 {F_IPRECH_SET, id->iprech_set}, in bd9995x_hw_init()
670 /* Fast Charge Current for constant current phase */ in bd9995x_hw_init()
671 {F_ICHG_SET, id->ichg_set}, in bd9995x_hw_init()
673 {F_VFASTCHG_REG_SET1, id->vfastchg_reg_set1}, in bd9995x_hw_init()
674 /* Set Pre-charge Voltage Threshold for trickle charging. */ in bd9995x_hw_init()
675 {F_VPRECHG_TH_SET, id->vprechg_th_set}, in bd9995x_hw_init()
676 {F_VRECHG_SET, id->vrechg_set}, in bd9995x_hw_init()
677 {F_VBATOVP_SET, id->vbatovp_set}, in bd9995x_hw_init()
680 /* Disable fast-charging watchdog */ in bd9995x_hw_init()
682 /* Disable pre-charging watchdog */ in bd9995x_hw_init()
706 ret = regmap_field_write(bd->rmap_fields[init_data[i].id], in bd9995x_hw_init()
709 dev_err(bd->dev, "failed to initialize charger (%d)\n", in bd9995x_hw_init()
719 mutex_lock(&bd->lock); in bd9995x_hw_init()
720 bd->state = state; in bd9995x_hw_init()
721 mutex_unlock(&bd->lock); in bd9995x_hw_init()
747 .name = "bd9995x-charger",
755 * Limit configurations for vbus-input-current and vcc-vacp-input-current
756 * Minimum limit is 0 uA. Max is 511 * 32000 uA = 16352000 uA. This is
758 * value equals to 32000 uA limit increment.
760 * Eg, value 0x0 is limit 0, value 0x1 is limit 32000, ...
767 /* Possible trickle, pre-charging and termination current values */
774 * Fast charging voltage regulation, starting re-charging limit
790 /* Possible settings for switching from trickle to pre-charging limits */
797 /* Possible current values for fast-charging constant current phase */
825 struct bd9995x_init_data *init = &bd->init_data; in bd9995x_fw_probe()
828 .name = "trickle-charging current", in bd9995x_fw_probe()
831 .data = &init->itrich_set, in bd9995x_fw_probe()
833 .name = "pre-charging current", in bd9995x_fw_probe()
836 .data = &init->iprech_set, in bd9995x_fw_probe()
838 .name = "pre-to-trickle charge voltage threshold", in bd9995x_fw_probe()
841 .data = &init->vprechg_th_set, in bd9995x_fw_probe()
843 .name = "charging termination current", in bd9995x_fw_probe()
846 .data = &init->iterm_set, in bd9995x_fw_probe()
848 .name = "charging re-start voltage", in bd9995x_fw_probe()
851 .data = &init->vrechg_set, in bd9995x_fw_probe()
853 .name = "battery overvoltage limit", in bd9995x_fw_probe()
856 .data = &init->vbatovp_set, in bd9995x_fw_probe()
858 .name = "fast-charging max current", in bd9995x_fw_probe()
861 .data = &init->ichg_set, in bd9995x_fw_probe()
863 .name = "fast-charging voltage", in bd9995x_fw_probe()
866 .data = &init->vfastchg_reg_set1, in bd9995x_fw_probe()
871 .prop = "rohm,vsys-regulation-microvolt", in bd9995x_fw_probe()
874 .data = &init->vsysreg_set, in bd9995x_fw_probe()
876 .prop = "rohm,vbus-input-current-limit-microamp", in bd9995x_fw_probe()
879 .data = &init->ibus_lim_set, in bd9995x_fw_probe()
881 .prop = "rohm,vcc-input-current-limit-microamp", in bd9995x_fw_probe()
884 .data = &init->icc_lim_set, in bd9995x_fw_probe()
892 ret = power_supply_get_battery_info(bd->charger, &info); in bd9995x_fw_probe()
897 battery_inits[0].info_data = &info->tricklecharge_current_ua; in bd9995x_fw_probe()
898 battery_inits[1].info_data = &info->precharge_current_ua; in bd9995x_fw_probe()
899 battery_inits[2].info_data = &info->precharge_voltage_max_uv; in bd9995x_fw_probe()
900 battery_inits[3].info_data = &info->charge_term_current_ua; in bd9995x_fw_probe()
901 battery_inits[4].info_data = &info->charge_restart_voltage_uv; in bd9995x_fw_probe()
902 battery_inits[5].info_data = &info->overvoltage_limit_uv; in bd9995x_fw_probe()
903 battery_inits[6].info_data = &info->constant_charge_current_max_ua; in bd9995x_fw_probe()
904 battery_inits[7].info_data = &info->constant_charge_voltage_max_uv; in bd9995x_fw_probe()
911 if (val == -EINVAL) in bd9995x_fw_probe()
917 dev_err(bd->dev, "Unsupported value for %s\n", in bd9995x_fw_probe()
920 power_supply_put_battery_info(bd->charger, info); in bd9995x_fw_probe()
921 return -EINVAL; in bd9995x_fw_probe()
924 dev_warn(bd->dev, in bd9995x_fw_probe()
925 "Unsupported value for %s - using smaller\n", in bd9995x_fw_probe()
931 power_supply_put_battery_info(bd->charger, info); in bd9995x_fw_probe()
934 ret = device_property_read_u32(bd->dev, props[i].prop, in bd9995x_fw_probe()
937 dev_err(bd->dev, "failed to read %s", props[i].prop); in bd9995x_fw_probe()
947 dev_err(bd->dev, "Unsupported value for '%s'\n", in bd9995x_fw_probe()
950 return -EINVAL; in bd9995x_fw_probe()
954 dev_warn(bd->dev, in bd9995x_fw_probe()
955 "Unsupported value for '%s' - using smaller\n", in bd9995x_fw_probe()
972 struct device *dev = &client->dev; in bd9995x_probe()
980 return -ENOMEM; in bd9995x_probe()
982 bd->client = client; in bd9995x_probe()
983 bd->dev = dev; in bd9995x_probe()
985 psy_cfg.of_node = dev->of_node; in bd9995x_probe()
987 mutex_init(&bd->lock); in bd9995x_probe()
989 bd->rmap = devm_regmap_init_i2c(client, &bd9995x_regmap_config); in bd9995x_probe()
990 if (IS_ERR(bd->rmap)) { in bd9995x_probe()
992 return PTR_ERR(bd->rmap); in bd9995x_probe()
998 bd->rmap_fields[i] = devm_regmap_field_alloc(dev, bd->rmap, in bd9995x_probe()
1000 if (IS_ERR(bd->rmap_fields[i])) { in bd9995x_probe()
1002 return PTR_ERR(bd->rmap_fields[i]); in bd9995x_probe()
1008 ret = regmap_field_read(bd->rmap_fields[F_CHIP_ID], &bd->chip_id); in bd9995x_probe()
1014 if (bd->chip_id != BD99954_ID) { in bd9995x_probe()
1016 bd->chip_id); in bd9995x_probe()
1017 return -ENODEV; in bd9995x_probe()
1020 ret = regmap_field_read(bd->rmap_fields[F_CHIP_REV], &bd->chip_rev); in bd9995x_probe()
1026 dev_info(bd->dev, "Found BD99954 chip rev %d\n", bd->chip_rev); in bd9995x_probe()
1032 bd->charger = devm_power_supply_register(bd->dev, in bd9995x_probe()
1035 if (IS_ERR(bd->charger)) { in bd9995x_probe()
1037 return PTR_ERR(bd->charger); in bd9995x_probe()
1056 return devm_request_threaded_irq(dev, client->irq, NULL, in bd9995x_probe()
1070 .name = "bd9995x-charger",