Lines Matching +full:i2c +full:- +full:lt +full:- +full:enable

1 // SPDX-License-Identifier: GPL-2.0-or-later
9 #include <linux/i2c.h>
90 u8 ilim_en; /* enable ILIM pin */
113 char name[28]; /* "bq25890-charger-%d" */
272 * Most of the val -> idx conversions can be computed, given the minimum,
322 0, -10, -20, -30, -40, -60, -70, -80,
323 -90, -10, -120, -140, -150, -170, -190, -210,
341 struct bq25890_lookup lt; member
356 [TBL_TREG] = { .lt = {bq25890_treg_tbl, BQ25890_TREG_TBL_SIZE} },
357 [TBL_BOOSTI] = { .lt = {bq25890_boosti_tbl, BQ25890_BOOSTI_TBL_SIZE} },
358 [TBL_TSPCT] = { .lt = {bq25890_tspct_tbl, BQ25890_TSPCT_TBL_SIZE} }
367 ret = regmap_field_read(bq->rmap_fields[field_id], &val); in bq25890_field_read()
377 return regmap_field_write(bq->rmap_fields[field_id], val); in bq25890_field_write()
385 const u32 *tbl = bq25890_tables[id].lt.tbl; in bq25890_find_idx()
386 u32 tbl_size = bq25890_tables[id].lt.size; in bq25890_find_idx()
394 rtbl_size = (rtbl->max - rtbl->min) / rtbl->step + 1; in bq25890_find_idx()
397 idx < rtbl_size && (idx * rtbl->step + rtbl->min <= value); in bq25890_find_idx()
402 return idx - 1; in bq25890_find_idx()
411 return bq25890_tables[id].lt.tbl[idx]; in bq25890_find_val()
416 return (rtbl->min + idx * rtbl->step); in bq25890_find_val()
474 mutex_lock(&bq->lock); in bq25890_update_state()
477 *state = bq->state; in bq25890_update_state()
478 do_adc_conv = (!state->online || state->hiz) && bq25890_is_adc_property(psp); in bq25890_update_state()
481 mutex_unlock(&bq->lock); in bq25890_update_state()
484 regmap_field_read_poll_timeout(bq->rmap_fields[F_CONV_START], in bq25890_update_state()
501 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; in bq25890_power_supply_get_property()
503 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; in bq25890_power_supply_get_property()
506 val->intval = POWER_SUPPLY_STATUS_CHARGING; in bq25890_power_supply_get_property()
508 val->intval = POWER_SUPPLY_STATUS_FULL; in bq25890_power_supply_get_property()
510 val->intval = POWER_SUPPLY_STATUS_UNKNOWN; in bq25890_power_supply_get_property()
518 val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; in bq25890_power_supply_get_property()
520 val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD; in bq25890_power_supply_get_property()
522 val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; in bq25890_power_supply_get_property()
524 val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN; in bq25890_power_supply_get_property()
528 val->strval = BQ25890_MANUFACTURER; in bq25890_power_supply_get_property()
532 val->strval = bq25890_chip_name[bq->chip_version]; in bq25890_power_supply_get_property()
536 val->intval = state.online && !state.hiz; in bq25890_power_supply_get_property()
541 val->intval = POWER_SUPPLY_HEALTH_GOOD; in bq25890_power_supply_get_property()
543 val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; in bq25890_power_supply_get_property()
545 val->intval = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; in bq25890_power_supply_get_property()
547 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; in bq25890_power_supply_get_property()
549 val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; in bq25890_power_supply_get_property()
553 val->intval = bq25890_find_val(bq->init_data.iprechg, TBL_ITERM); in bq25890_power_supply_get_property()
557 val->intval = bq25890_find_val(bq->init_data.iterm, TBL_ITERM); in bq25890_power_supply_get_property()
565 val->intval = bq25890_find_val(ret, TBL_IINLIM); in bq25890_power_supply_get_property()
570 * This is ADC-sampled immediate charge current supplied in bq25890_power_supply_get_property()
573 * Documentation/ABI/testing/sysfs-class-power in bq25890_power_supply_get_property()
581 val->intval = ret * -50000; in bq25890_power_supply_get_property()
586 * This is user-configured constant charge current supplied in bq25890_power_supply_get_property()
598 val->intval = bq25890_find_val(ret, TBL_ICHG); in bq25890_power_supply_get_property()
601 if (bq->state.ntc_fault == NTC_FAULT_COOL) { in bq25890_power_supply_get_property()
607 val->intval /= 5; in bq25890_power_supply_get_property()
609 val->intval /= 2; in bq25890_power_supply_get_property()
621 val->intval = bq25890_find_val(bq->init_data.ichg, TBL_ICHG); in bq25890_power_supply_get_property()
626 * This is ADC-sampled immediate charge voltage supplied in bq25890_power_supply_get_property()
629 * Documentation/ABI/testing/sysfs-class-power in bq25890_power_supply_get_property()
637 val->intval = 2304000 + ret * 20000; in bq25890_power_supply_get_property()
642 * This is user-configured constant charge voltage supplied in bq25890_power_supply_get_property()
655 val->intval = bq25890_find_val(ret, TBL_VREG); in bq25890_power_supply_get_property()
666 val->intval = bq25890_find_val(bq->init_data.vreg, TBL_VREG); in bq25890_power_supply_get_property()
675 val->intval = bq25890_find_val(ret, TBL_TSPCT); in bq25890_power_supply_get_property()
679 return -EINVAL; in bq25890_power_supply_get_property()
696 maxval = bq25890_find_val(bq->init_data.ichg, TBL_ICHG); in bq25890_power_supply_set_property()
697 lval = bq25890_find_idx(min(val->intval, maxval), TBL_ICHG); in bq25890_power_supply_set_property()
700 maxval = bq25890_find_val(bq->init_data.vreg, TBL_VREG); in bq25890_power_supply_set_property()
701 lval = bq25890_find_idx(min(val->intval, maxval), TBL_VREG); in bq25890_power_supply_set_property()
704 lval = bq25890_find_idx(val->intval, TBL_IINLIM); in bq25890_power_supply_set_property()
707 ret = bq25890_field_write(bq, F_EN_HIZ, !val->intval); in bq25890_power_supply_set_property()
709 bq->force_hiz = !val->intval; in bq25890_power_supply_set_property()
713 return -EINVAL; in bq25890_power_supply_set_property()
732 * If there are multiple chargers the maximum current the external power-supply
734 * to the bq->iinlim_percentage setting.
739 iinlim_ua = iinlim_ua * bq->iinlim_percentage / 100; in bq25890_charger_get_scaled_iinlim_regval()
743 /* On the BQ25892 try to get charger-type info from our supplier */
750 if (bq->chip_version != BQ25892) in bq25890_charger_external_power_changed()
762 if (bq->pump_express_vbus_max) { in bq25890_charger_external_power_changed()
764 &bq->pump_express_work, in bq25890_charger_external_power_changed()
790 {F_CHG_STAT, &state->chrg_status}, in bq25890_get_chip_state()
791 {F_PG_STAT, &state->online}, in bq25890_get_chip_state()
792 {F_EN_HIZ, &state->hiz}, in bq25890_get_chip_state()
793 {F_VSYS_STAT, &state->vsys_status}, in bq25890_get_chip_state()
794 {F_BOOST_FAULT, &state->boost_fault}, in bq25890_get_chip_state()
795 {F_BAT_FAULT, &state->bat_fault}, in bq25890_get_chip_state()
796 {F_CHG_FAULT, &state->chrg_fault}, in bq25890_get_chip_state()
797 {F_NTC_FAULT, &state->ntc_fault} in bq25890_get_chip_state()
808 dev_dbg(bq->dev, "S:CHG/PG/HIZ/VSYS=%d/%d/%d/%d, F:CHG/BOOST/BAT/NTC=%d/%d/%d/%d\n", in bq25890_get_chip_state()
809 state->chrg_status, state->online, in bq25890_get_chip_state()
810 state->hiz, state->vsys_status, in bq25890_get_chip_state()
811 state->chrg_fault, state->boost_fault, in bq25890_get_chip_state()
812 state->bat_fault, state->ntc_fault); in bq25890_get_chip_state()
827 if (!memcmp(&bq->state, &new_state, sizeof(new_state))) in __bq25890_handle_irq()
834 if (new_state.online && !bq->state.online && bq->force_hiz) { in __bq25890_handle_irq()
835 ret = bq25890_field_write(bq, F_EN_HIZ, bq->force_hiz); in __bq25890_handle_irq()
842 adc_conv_rate = bq->state.online && !bq->state.hiz; in __bq25890_handle_irq()
851 bq->state = new_state; in __bq25890_handle_irq()
852 power_supply_changed(bq->charger); in __bq25890_handle_irq()
856 dev_err(bq->dev, "Error communicating with the chip: %pe\n", in __bq25890_handle_irq()
866 mutex_lock(&bq->lock); in bq25890_irq_handler_thread()
868 mutex_unlock(&bq->lock); in bq25890_irq_handler_thread()
888 } while (ret == 1 && --rst_check_counter); in bq25890_chip_reset()
891 return -ETIMEDOUT; in bq25890_chip_reset()
898 bool write = !bq->read_back_init_data; in bq25890_rw_init_data()
906 {F_ICHG, &bq->init_data.ichg}, in bq25890_rw_init_data()
907 {F_VREG, &bq->init_data.vreg}, in bq25890_rw_init_data()
908 {F_ITERM, &bq->init_data.iterm}, in bq25890_rw_init_data()
909 {F_IPRECHG, &bq->init_data.iprechg}, in bq25890_rw_init_data()
910 {F_SYSVMIN, &bq->init_data.sysvmin}, in bq25890_rw_init_data()
911 {F_BOOSTV, &bq->init_data.boostv}, in bq25890_rw_init_data()
912 {F_BOOSTI, &bq->init_data.boosti}, in bq25890_rw_init_data()
913 {F_BOOSTF, &bq->init_data.boostf}, in bq25890_rw_init_data()
914 {F_EN_ILIM, &bq->init_data.ilim_en}, in bq25890_rw_init_data()
915 {F_TREG, &bq->init_data.treg}, in bq25890_rw_init_data()
916 {F_BATCMP, &bq->init_data.rbatcomp}, in bq25890_rw_init_data()
917 {F_VCLAMP, &bq->init_data.vclamp}, in bq25890_rw_init_data()
930 dev_dbg(bq->dev, "Accessing init data failed %d\n", ret); in bq25890_rw_init_data()
942 if (!bq->skip_reset) { in bq25890_hw_init()
945 dev_dbg(bq->dev, "Reset failed %d\n", ret); in bq25890_hw_init()
956 dev_dbg(bq->dev, "Enabling charging failed %d\n", ret); in bq25890_hw_init()
964 dev_dbg(bq->dev, "Disabling watchdog failed %d\n", ret); in bq25890_hw_init()
973 ret = bq25890_get_chip_state(bq, &bq->state); in bq25890_hw_init()
975 dev_dbg(bq->dev, "Get state failed %d\n", ret); in bq25890_hw_init()
980 ret = bq25890_field_write(bq, F_CONV_RATE, bq->state.online && !bq->state.hiz); in bq25890_hw_init()
982 dev_dbg(bq->dev, "Config ADC failed %d\n", ret); in bq25890_hw_init()
1009 "main-battery",
1028 bq->id = idr_alloc(&bq25890_id, bq, 0, 0, GFP_KERNEL); in bq25890_power_supply_init()
1030 if (bq->id < 0) in bq25890_power_supply_init()
1031 return bq->id; in bq25890_power_supply_init()
1033 snprintf(bq->name, sizeof(bq->name), "bq25890-charger-%d", bq->id); in bq25890_power_supply_init()
1034 bq->desc = bq25890_power_supply_desc; in bq25890_power_supply_init()
1035 bq->desc.name = bq->name; in bq25890_power_supply_init()
1040 bq->charger = devm_power_supply_register(bq->dev, &bq->desc, &psy_cfg); in bq25890_power_supply_init()
1042 return PTR_ERR_OR_ZERO(bq->charger); in bq25890_power_supply_init()
1051 dev_err(bq->dev, "Error switching to boost/charger mode: %d\n", ret); in bq25890_set_otg_cfg()
1063 dev_dbg(bq->dev, "Start to request input voltage increasing\n"); in bq25890_pump_express_work()
1065 /* If there is a second charger put in Hi-Z mode */ in bq25890_pump_express_work()
1066 if (bq->secondary_chrg) { in bq25890_pump_express_work()
1068 power_supply_set_property(bq->secondary_chrg, POWER_SUPPLY_PROP_ONLINE, &value); in bq25890_pump_express_work()
1071 /* Enable current pulse voltage control protocol */ in bq25890_pump_express_work()
1080 dev_dbg(bq->dev, "input voltage = %d uV\n", voltage); in bq25890_pump_express_work()
1083 bq->pump_express_vbus_max) in bq25890_pump_express_work()
1090 /* Note a single PUMPX up pulse-sequence takes 2.1s */ in bq25890_pump_express_work()
1091 ret = regmap_field_read_poll_timeout(bq->rmap_fields[F_PUMPX_UP], in bq25890_pump_express_work()
1102 if (bq->secondary_chrg) { in bq25890_pump_express_work()
1104 power_supply_set_property(bq->secondary_chrg, POWER_SUPPLY_PROP_ONLINE, &value); in bq25890_pump_express_work()
1107 dev_info(bq->dev, "Hi-voltage charging requested, input voltage is %d mV\n", in bq25890_pump_express_work()
1110 power_supply_changed(bq->charger); in bq25890_pump_express_work()
1115 dev_err(bq->dev, "Failed to request hi-voltage charging\n"); in bq25890_pump_express_work()
1124 switch (bq->usb_event) { in bq25890_usb_work()
1126 /* Enable boost mode */ in bq25890_usb_work()
1134 power_supply_changed(bq->charger); in bq25890_usb_work()
1145 bq->usb_event = val; in bq25890_usb_notifier()
1146 queue_work(system_power_efficient_wq, &bq->usb_work); in bq25890_usb_notifier()
1161 * charger in Hi-Z mode to avoid it trying to charge the secondary in bq25890_vbus_enable()
1164 if (bq->secondary_chrg) in bq25890_vbus_enable()
1165 power_supply_set_property(bq->secondary_chrg, POWER_SUPPLY_PROP_ONLINE, &val); in bq25890_vbus_enable()
1182 if (bq->secondary_chrg) in bq25890_vbus_disable()
1183 power_supply_set_property(bq->secondary_chrg, POWER_SUPPLY_PROP_ONLINE, &val); in bq25890_vbus_disable()
1217 .enable = bq25890_vbus_enable,
1225 .of_match = "usb-otg-vbus",
1245 struct bq25890_platform_data *pdata = dev_get_platdata(bq->dev); in bq25890_register_regulator()
1247 .dev = bq->dev, in bq25890_register_regulator()
1253 cfg.init_data = pdata->regulator_init_data; in bq25890_register_regulator()
1255 reg = devm_regulator_register(bq->dev, &bq25890_vbus_desc, &cfg); in bq25890_register_regulator()
1257 return dev_err_probe(bq->dev, PTR_ERR(reg), in bq25890_register_regulator()
1261 /* pdata->regulator_init_data is for vbus only */ in bq25890_register_regulator()
1263 reg = devm_regulator_register(bq->dev, &bq25890_vsys_desc, &cfg); in bq25890_register_regulator()
1265 return dev_err_probe(bq->dev, PTR_ERR(reg), in bq25890_register_regulator()
1285 dev_err(bq->dev, "Cannot read chip ID: %d\n", id); in bq25890_get_chip_version()
1291 dev_err(bq->dev, "Cannot read chip revision: %d\n", rev); in bq25890_get_chip_version()
1297 bq->chip_version = BQ25890; in bq25890_get_chip_version()
1304 bq->chip_version = BQ25896; in bq25890_get_chip_version()
1307 bq->chip_version = BQ25892; in bq25890_get_chip_version()
1310 dev_err(bq->dev, in bq25890_get_chip_version()
1313 bq->chip_version = BQ25892; in bq25890_get_chip_version()
1318 bq->chip_version = BQ25895; in bq25890_get_chip_version()
1322 dev_err(bq->dev, "Unknown chip ID %d\n", id); in bq25890_get_chip_version()
1323 return -ENODEV; in bq25890_get_chip_version()
1333 irq = devm_gpiod_get(bq->dev, BQ25890_IRQ_PIN, GPIOD_IN); in bq25890_irq_probe()
1335 return dev_err_probe(bq->dev, PTR_ERR(irq), in bq25890_irq_probe()
1346 struct bq25890_init_data *init = &bq->init_data; in bq25890_fw_read_u32_props()
1354 {"ti,charge-current", false, TBL_ICHG, &init->ichg}, in bq25890_fw_read_u32_props()
1355 {"ti,battery-regulation-voltage", false, TBL_VREG, &init->vreg}, in bq25890_fw_read_u32_props()
1356 {"ti,termination-current", false, TBL_ITERM, &init->iterm}, in bq25890_fw_read_u32_props()
1357 {"ti,precharge-current", false, TBL_ITERM, &init->iprechg}, in bq25890_fw_read_u32_props()
1358 {"ti,minimum-sys-voltage", false, TBL_SYSVMIN, &init->sysvmin}, in bq25890_fw_read_u32_props()
1359 {"ti,boost-voltage", false, TBL_BOOSTV, &init->boostv}, in bq25890_fw_read_u32_props()
1360 {"ti,boost-max-current", false, TBL_BOOSTI, &init->boosti}, in bq25890_fw_read_u32_props()
1363 {"ti,thermal-regulation-threshold", true, TBL_TREG, &init->treg}, in bq25890_fw_read_u32_props()
1364 {"ti,ibatcomp-micro-ohms", true, TBL_RBATCOMP, &init->rbatcomp}, in bq25890_fw_read_u32_props()
1365 {"ti,ibatcomp-clamp-microvolt", true, TBL_VBATCOMP, &init->vclamp}, in bq25890_fw_read_u32_props()
1369 init->treg = 3; /* 120 degrees Celsius */ in bq25890_fw_read_u32_props()
1370 init->rbatcomp = init->vclamp = 0; /* IBAT compensation disabled */ in bq25890_fw_read_u32_props()
1373 ret = device_property_read_u32(bq->dev, props[i].name, in bq25890_fw_read_u32_props()
1379 dev_err(bq->dev, "Unable to read property %d %s\n", ret, in bq25890_fw_read_u32_props()
1395 struct bq25890_init_data *init = &bq->init_data; in bq25890_fw_probe()
1399 ret = device_property_read_string(bq->dev, "linux,secondary-charger-name", &str); in bq25890_fw_probe()
1401 bq->secondary_chrg = power_supply_get_by_name(str); in bq25890_fw_probe()
1402 if (!bq->secondary_chrg) in bq25890_fw_probe()
1403 return -EPROBE_DEFER; in bq25890_fw_probe()
1407 device_property_read_u32(bq->dev, "linux,pump-express-vbus-max", in bq25890_fw_probe()
1408 &bq->pump_express_vbus_max); in bq25890_fw_probe()
1410 ret = device_property_read_u32(bq->dev, "linux,iinlim-percentage", &val); in bq25890_fw_probe()
1413 dev_err(bq->dev, "Error linux,iinlim-percentage %u > 100\n", val); in bq25890_fw_probe()
1414 return -EINVAL; in bq25890_fw_probe()
1416 bq->iinlim_percentage = val; in bq25890_fw_probe()
1418 bq->iinlim_percentage = 100; in bq25890_fw_probe()
1421 bq->skip_reset = device_property_read_bool(bq->dev, "linux,skip-reset"); in bq25890_fw_probe()
1422 bq->read_back_init_data = device_property_read_bool(bq->dev, in bq25890_fw_probe()
1423 "linux,read-back-settings"); in bq25890_fw_probe()
1424 if (bq->read_back_init_data) in bq25890_fw_probe()
1431 init->ilim_en = device_property_read_bool(bq->dev, "ti,use-ilim-pin"); in bq25890_fw_probe()
1432 init->boostf = device_property_read_bool(bq->dev, "ti,boost-low-freq"); in bq25890_fw_probe()
1441 cancel_delayed_work_sync(&bq->pump_express_work); in bq25890_non_devm_cleanup()
1443 if (bq->id >= 0) { in bq25890_non_devm_cleanup()
1445 idr_remove(&bq25890_id, bq->id); in bq25890_non_devm_cleanup()
1452 struct device *dev = &client->dev; in bq25890_probe()
1458 return -ENOMEM; in bq25890_probe()
1460 bq->client = client; in bq25890_probe()
1461 bq->dev = dev; in bq25890_probe()
1462 bq->id = -1; in bq25890_probe()
1464 mutex_init(&bq->lock); in bq25890_probe()
1465 INIT_DELAYED_WORK(&bq->pump_express_work, bq25890_pump_express_work); in bq25890_probe()
1467 bq->rmap = devm_regmap_init_i2c(client, &bq25890_regmap_config); in bq25890_probe()
1468 if (IS_ERR(bq->rmap)) in bq25890_probe()
1469 return dev_err_probe(dev, PTR_ERR(bq->rmap), in bq25890_probe()
1472 ret = devm_regmap_field_bulk_alloc(dev, bq->rmap, bq->rmap_fields, in bq25890_probe()
1495 if (client->irq <= 0) in bq25890_probe()
1496 client->irq = bq25890_irq_probe(bq); in bq25890_probe()
1498 if (client->irq < 0) { in bq25890_probe()
1500 return client->irq; in bq25890_probe()
1504 bq->usb_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); in bq25890_probe()
1522 ret = devm_request_threaded_irq(dev, client->irq, NULL, in bq25890_probe()
1529 if (!IS_ERR_OR_NULL(bq->usb_phy)) { in bq25890_probe()
1530 INIT_WORK(&bq->usb_work, bq25890_usb_work); in bq25890_probe()
1531 bq->usb_nb.notifier_call = bq25890_usb_notifier; in bq25890_probe()
1532 usb_register_notifier(bq->usb_phy, &bq->usb_nb); in bq25890_probe()
1542 if (!IS_ERR_OR_NULL(bq->usb_phy)) { in bq25890_remove()
1543 usb_unregister_notifier(bq->usb_phy, &bq->usb_nb); in bq25890_remove()
1544 cancel_work_sync(&bq->usb_work); in bq25890_remove()
1547 if (!bq->skip_reset) { in bq25890_remove()
1559 * introduce a function change for boards using the usb-phy framework. in bq25890_shutdown()
1562 if (!IS_ERR_OR_NULL(bq->usb_phy)) in bq25890_shutdown()
1567 * Micro-USB or Type-C USB port. Leaving this on drains power and in bq25890_shutdown()
1568 * this avoids the PMIC on some device-models seeing this as Vbus in bq25890_shutdown()
1570 * power-up again. in bq25890_shutdown()
1592 mutex_lock(&bq->lock); in bq25890_resume()
1594 ret = bq25890_get_chip_state(bq, &bq->state); in bq25890_resume()
1598 /* Re-enable ADC only if charger is plugged in. */ in bq25890_resume()
1599 if (bq->state.online) { in bq25890_resume()
1606 power_supply_changed(bq->charger); in bq25890_resume()
1609 mutex_unlock(&bq->lock); in bq25890_resume()
1626 MODULE_DEVICE_TABLE(i2c, bq25890_i2c_ids);
1647 .name = "bq25890-charger",