1 /* Copyright (c) 2014, Sony Mobile Communications Inc.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * This driver is for the multi-block Switch-Mode Battery Charger and Boost
13 * (SMBB) hardware, found in Qualcomm PM8941 PMICs. The charger is an
14 * integrated, single-cell lithium-ion battery charger.
22 * - Boost (not implemented)
27 #include <linux/errno.h>
28 #include <linux/interrupt.h>
29 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/mutex.h>
33 #include <linux/platform_device.h>
34 #include <linux/power_supply.h>
35 #include <linux/regmap.h>
36 #include <linux/slab.h>
38 #define SMBB_CHG_VMAX 0x040
39 #define SMBB_CHG_VSAFE 0x041
40 #define SMBB_CHG_CFG 0x043
41 #define SMBB_CHG_IMAX 0x044
42 #define SMBB_CHG_ISAFE 0x045
43 #define SMBB_CHG_VIN_MIN 0x047
44 #define SMBB_CHG_CTRL 0x049
45 #define CTRL_EN BIT(7)
46 #define SMBB_CHG_VBAT_WEAK 0x052
47 #define SMBB_CHG_IBAT_TERM_CHG 0x05b
48 #define IBAT_TERM_CHG_IEOC BIT(7)
49 #define IBAT_TERM_CHG_IEOC_BMS BIT(7)
50 #define IBAT_TERM_CHG_IEOC_CHG 0
51 #define SMBB_CHG_VBAT_DET 0x05d
52 #define SMBB_CHG_TCHG_MAX_EN 0x060
53 #define TCHG_MAX_EN BIT(7)
54 #define SMBB_CHG_WDOG_TIME 0x062
55 #define SMBB_CHG_WDOG_EN 0x065
56 #define WDOG_EN BIT(7)
58 #define SMBB_BUCK_REG_MODE 0x174
59 #define BUCK_REG_MODE BIT(0)
60 #define BUCK_REG_MODE_VBAT BIT(0)
61 #define BUCK_REG_MODE_VSYS 0
63 #define SMBB_BAT_PRES_STATUS 0x208
64 #define PRES_STATUS_BAT_PRES BIT(7)
65 #define SMBB_BAT_TEMP_STATUS 0x209
66 #define TEMP_STATUS_OK BIT(7)
67 #define TEMP_STATUS_HOT BIT(6)
68 #define SMBB_BAT_BTC_CTRL 0x249
69 #define BTC_CTRL_COMP_EN BIT(7)
70 #define BTC_CTRL_COLD_EXT BIT(1)
71 #define BTC_CTRL_HOT_EXT_N BIT(0)
73 #define SMBB_USB_IMAX 0x344
74 #define SMBB_USB_ENUM_TIMER_STOP 0x34e
75 #define ENUM_TIMER_STOP BIT(0)
76 #define SMBB_USB_SEC_ACCESS 0x3d0
77 #define SEC_ACCESS_MAGIC 0xa5
78 #define SMBB_USB_REV_BST 0x3ed
79 #define REV_BST_CHG_GONE BIT(7)
81 #define SMBB_DC_IMAX 0x444
83 #define SMBB_MISC_REV2 0x601
84 #define SMBB_MISC_BOOT_DONE 0x642
85 #define BOOT_DONE BIT(7)
87 #define STATUS_USBIN_VALID BIT(0) /* USB connection is valid */
88 #define STATUS_DCIN_VALID BIT(1) /* DC connection is valid */
89 #define STATUS_BAT_HOT BIT(2) /* Battery temp 1=Hot, 0=Cold */
90 #define STATUS_BAT_OK BIT(3) /* Battery temp OK */
91 #define STATUS_BAT_PRESENT BIT(4) /* Battery is present */
92 #define STATUS_CHG_DONE BIT(5) /* Charge cycle is complete */
93 #define STATUS_CHG_TRKL BIT(6) /* Trickle charging */
94 #define STATUS_CHG_FAST BIT(7) /* Fast charging */
95 #define STATUS_CHG_GONE BIT(8) /* No charger is connected */
110 struct smbb_charger {
111 unsigned int revision;
117 unsigned long status;
118 struct mutex statlock;
120 unsigned int attr[_ATTR_CNT];
122 struct power_supply *usb_psy;
123 struct power_supply *dc_psy;
124 struct power_supply *bat_psy;
125 struct regmap *regmap;
128 static int smbb_vbat_weak_fn(unsigned int index)
130 return 2100000 + index * 100000;
133 static int smbb_vin_fn(unsigned int index)
136 return 5600000 + (index - 43) * 200000;
137 return 3400000 + index * 50000;
140 static int smbb_vmax_fn(unsigned int index)
142 return 3240000 + index * 10000;
145 static int smbb_vbat_det_fn(unsigned int index)
147 return 3240000 + index * 20000;
150 static int smbb_imax_fn(unsigned int index)
153 return 100000 + index * 50000;
154 return index * 100000;
157 static int smbb_bat_imax_fn(unsigned int index)
159 return index * 50000;
162 static unsigned int smbb_hw_lookup(unsigned int val, int (*fn)(unsigned int))
167 for (widx = sel = 0; (*fn)(widx) <= val; ++widx)
173 static const struct smbb_charger_attr {
176 unsigned int safe_reg;
179 unsigned int fail_ok;
180 int (*hw_fn)(unsigned int);
181 } smbb_charger_attrs[] = {
183 .name = "qcom,fast-charge-safe-current",
184 .reg = SMBB_CHG_ISAFE,
187 .hw_fn = smbb_bat_imax_fn,
191 .name = "qcom,fast-charge-current-limit",
192 .reg = SMBB_CHG_IMAX,
193 .safe_reg = SMBB_CHG_ISAFE,
196 .hw_fn = smbb_bat_imax_fn,
199 .name = "qcom,dc-current-limit",
203 .hw_fn = smbb_imax_fn,
206 .name = "qcom,fast-charge-safe-voltage",
207 .reg = SMBB_CHG_VSAFE,
210 .hw_fn = smbb_vmax_fn,
214 .name = "qcom,fast-charge-high-threshold-voltage",
215 .reg = SMBB_CHG_VMAX,
216 .safe_reg = SMBB_CHG_VSAFE,
219 .hw_fn = smbb_vmax_fn,
222 .name = "qcom,fast-charge-low-threshold-voltage",
223 .reg = SMBB_CHG_VBAT_WEAK,
226 .hw_fn = smbb_vbat_weak_fn,
229 .name = "qcom,auto-recharge-threshold-voltage",
230 .reg = SMBB_CHG_VBAT_DET,
233 .hw_fn = smbb_vbat_det_fn,
236 .name = "qcom,minimum-input-voltage",
237 .reg = SMBB_CHG_VIN_MIN,
240 .hw_fn = smbb_vin_fn,
242 [ATTR_USBIN_IMAX] = {
243 .name = "usb-charge-current-limit",
244 .reg = SMBB_USB_IMAX,
247 .hw_fn = smbb_imax_fn,
251 static int smbb_charger_attr_write(struct smbb_charger *chg,
252 enum smbb_attr which, unsigned int val)
254 const struct smbb_charger_attr *prop;
259 prop = &smbb_charger_attrs[which];
261 if (val > prop->max || val < prop->min) {
262 dev_err(chg->dev, "value out of range for %s [%u:%u]\n",
263 prop->name, prop->min, prop->max);
267 if (prop->safe_reg) {
268 rc = regmap_read(chg->regmap,
269 chg->addr + prop->safe_reg, &wval);
272 "unable to read safe value for '%s'\n",
277 wval = prop->hw_fn(wval);
281 "%s above safe value, clamping at %u\n",
287 wval = smbb_hw_lookup(val, prop->hw_fn);
289 rc = regmap_write(chg->regmap, chg->addr + prop->reg, wval);
291 dev_err(chg->dev, "unable to update %s", prop->name);
294 out = prop->hw_fn(wval);
297 "%s inaccurate, rounded to %u\n",
301 dev_dbg(chg->dev, "%s <= %d\n", prop->name, out);
303 chg->attr[which] = out;
308 static int smbb_charger_attr_read(struct smbb_charger *chg,
309 enum smbb_attr which)
311 const struct smbb_charger_attr *prop;
315 prop = &smbb_charger_attrs[which];
317 rc = regmap_read(chg->regmap, chg->addr + prop->reg, &val);
319 dev_err(chg->dev, "failed to read %s\n", prop->name);
322 val = prop->hw_fn(val);
323 dev_dbg(chg->dev, "%s => %d\n", prop->name, val);
325 chg->attr[which] = val;
330 static int smbb_charger_attr_parse(struct smbb_charger *chg,
331 enum smbb_attr which)
333 const struct smbb_charger_attr *prop;
337 prop = &smbb_charger_attrs[which];
339 rc = of_property_read_u32(chg->dev->of_node, prop->name, &val);
341 rc = smbb_charger_attr_write(chg, which, val);
342 if (!rc || !prop->fail_ok)
345 return smbb_charger_attr_read(chg, which);
348 static void smbb_set_line_flag(struct smbb_charger *chg, int irq, int flag)
353 ret = irq_get_irqchip_state(irq, IRQCHIP_STATE_LINE_LEVEL, &state);
355 dev_err(chg->dev, "failed to read irq line\n");
359 mutex_lock(&chg->statlock);
363 chg->status &= ~flag;
364 mutex_unlock(&chg->statlock);
366 dev_dbg(chg->dev, "status = %03lx\n", chg->status);
369 static irqreturn_t smbb_usb_valid_handler(int irq, void *_data)
371 struct smbb_charger *chg = _data;
373 smbb_set_line_flag(chg, irq, STATUS_USBIN_VALID);
374 power_supply_changed(chg->usb_psy);
379 static irqreturn_t smbb_dc_valid_handler(int irq, void *_data)
381 struct smbb_charger *chg = _data;
383 smbb_set_line_flag(chg, irq, STATUS_DCIN_VALID);
384 if (!chg->dc_disabled)
385 power_supply_changed(chg->dc_psy);
390 static irqreturn_t smbb_bat_temp_handler(int irq, void *_data)
392 struct smbb_charger *chg = _data;
396 rc = regmap_read(chg->regmap, chg->addr + SMBB_BAT_TEMP_STATUS, &val);
400 mutex_lock(&chg->statlock);
401 if (val & TEMP_STATUS_OK) {
402 chg->status |= STATUS_BAT_OK;
404 chg->status &= ~STATUS_BAT_OK;
405 if (val & TEMP_STATUS_HOT)
406 chg->status |= STATUS_BAT_HOT;
408 mutex_unlock(&chg->statlock);
410 power_supply_changed(chg->bat_psy);
414 static irqreturn_t smbb_bat_present_handler(int irq, void *_data)
416 struct smbb_charger *chg = _data;
418 smbb_set_line_flag(chg, irq, STATUS_BAT_PRESENT);
419 power_supply_changed(chg->bat_psy);
424 static irqreturn_t smbb_chg_done_handler(int irq, void *_data)
426 struct smbb_charger *chg = _data;
428 smbb_set_line_flag(chg, irq, STATUS_CHG_DONE);
429 power_supply_changed(chg->bat_psy);
434 static irqreturn_t smbb_chg_gone_handler(int irq, void *_data)
436 struct smbb_charger *chg = _data;
438 smbb_set_line_flag(chg, irq, STATUS_CHG_GONE);
439 power_supply_changed(chg->bat_psy);
440 power_supply_changed(chg->usb_psy);
441 if (!chg->dc_disabled)
442 power_supply_changed(chg->dc_psy);
447 static irqreturn_t smbb_chg_fast_handler(int irq, void *_data)
449 struct smbb_charger *chg = _data;
451 smbb_set_line_flag(chg, irq, STATUS_CHG_FAST);
452 power_supply_changed(chg->bat_psy);
457 static irqreturn_t smbb_chg_trkl_handler(int irq, void *_data)
459 struct smbb_charger *chg = _data;
461 smbb_set_line_flag(chg, irq, STATUS_CHG_TRKL);
462 power_supply_changed(chg->bat_psy);
467 static const struct smbb_irq {
469 irqreturn_t (*handler)(int, void *);
470 } smbb_charger_irqs[] = {
471 { "chg-done", smbb_chg_done_handler },
472 { "chg-fast", smbb_chg_fast_handler },
473 { "chg-trkl", smbb_chg_trkl_handler },
474 { "bat-temp-ok", smbb_bat_temp_handler },
475 { "bat-present", smbb_bat_present_handler },
476 { "chg-gone", smbb_chg_gone_handler },
477 { "usb-valid", smbb_usb_valid_handler },
478 { "dc-valid", smbb_dc_valid_handler },
481 static int smbb_usbin_get_property(struct power_supply *psy,
482 enum power_supply_property psp,
483 union power_supply_propval *val)
485 struct smbb_charger *chg = power_supply_get_drvdata(psy);
489 case POWER_SUPPLY_PROP_ONLINE:
490 mutex_lock(&chg->statlock);
491 val->intval = !(chg->status & STATUS_CHG_GONE) &&
492 (chg->status & STATUS_USBIN_VALID);
493 mutex_unlock(&chg->statlock);
495 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
496 val->intval = chg->attr[ATTR_USBIN_IMAX];
498 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
499 val->intval = 2500000;
509 static int smbb_usbin_set_property(struct power_supply *psy,
510 enum power_supply_property psp,
511 const union power_supply_propval *val)
513 struct smbb_charger *chg = power_supply_get_drvdata(psy);
517 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
518 rc = smbb_charger_attr_write(chg, ATTR_USBIN_IMAX,
529 static int smbb_dcin_get_property(struct power_supply *psy,
530 enum power_supply_property psp,
531 union power_supply_propval *val)
533 struct smbb_charger *chg = power_supply_get_drvdata(psy);
537 case POWER_SUPPLY_PROP_ONLINE:
538 mutex_lock(&chg->statlock);
539 val->intval = !(chg->status & STATUS_CHG_GONE) &&
540 (chg->status & STATUS_DCIN_VALID);
541 mutex_unlock(&chg->statlock);
543 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
544 val->intval = chg->attr[ATTR_DCIN_IMAX];
546 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
547 val->intval = 2500000;
557 static int smbb_dcin_set_property(struct power_supply *psy,
558 enum power_supply_property psp,
559 const union power_supply_propval *val)
561 struct smbb_charger *chg = power_supply_get_drvdata(psy);
565 case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
566 rc = smbb_charger_attr_write(chg, ATTR_DCIN_IMAX,
577 static int smbb_charger_writable_property(struct power_supply *psy,
578 enum power_supply_property psp)
580 return psp == POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT;
583 static int smbb_battery_get_property(struct power_supply *psy,
584 enum power_supply_property psp,
585 union power_supply_propval *val)
587 struct smbb_charger *chg = power_supply_get_drvdata(psy);
588 unsigned long status;
591 mutex_lock(&chg->statlock);
592 status = chg->status;
593 mutex_unlock(&chg->statlock);
596 case POWER_SUPPLY_PROP_STATUS:
597 if (status & STATUS_CHG_GONE)
598 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
599 else if (!(status & (STATUS_DCIN_VALID | STATUS_USBIN_VALID)))
600 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
601 else if (status & STATUS_CHG_DONE)
602 val->intval = POWER_SUPPLY_STATUS_FULL;
603 else if (!(status & STATUS_BAT_OK))
604 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
605 else if (status & (STATUS_CHG_FAST | STATUS_CHG_TRKL))
606 val->intval = POWER_SUPPLY_STATUS_CHARGING;
607 else /* everything is ok for charging, but we are not... */
608 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
610 case POWER_SUPPLY_PROP_HEALTH:
611 if (status & STATUS_BAT_OK)
612 val->intval = POWER_SUPPLY_HEALTH_GOOD;
613 else if (status & STATUS_BAT_HOT)
614 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
616 val->intval = POWER_SUPPLY_HEALTH_COLD;
618 case POWER_SUPPLY_PROP_CHARGE_TYPE:
619 if (status & STATUS_CHG_FAST)
620 val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
621 else if (status & STATUS_CHG_TRKL)
622 val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
624 val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
626 case POWER_SUPPLY_PROP_PRESENT:
627 val->intval = !!(status & STATUS_BAT_PRESENT);
629 case POWER_SUPPLY_PROP_CURRENT_MAX:
630 val->intval = chg->attr[ATTR_BAT_IMAX];
632 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
633 val->intval = chg->attr[ATTR_BAT_VMAX];
635 case POWER_SUPPLY_PROP_TECHNOLOGY:
636 /* this charger is a single-cell lithium-ion battery charger
637 * only. If you hook up some other technology, there will be
640 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
642 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
643 val->intval = 3000000; /* single-cell li-ion low end */
653 static int smbb_battery_set_property(struct power_supply *psy,
654 enum power_supply_property psp,
655 const union power_supply_propval *val)
657 struct smbb_charger *chg = power_supply_get_drvdata(psy);
661 case POWER_SUPPLY_PROP_CURRENT_MAX:
662 rc = smbb_charger_attr_write(chg, ATTR_BAT_IMAX, val->intval);
664 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
665 rc = smbb_charger_attr_write(chg, ATTR_BAT_VMAX, val->intval);
675 static int smbb_battery_writable_property(struct power_supply *psy,
676 enum power_supply_property psp)
679 case POWER_SUPPLY_PROP_CURRENT_MAX:
680 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
687 static enum power_supply_property smbb_charger_properties[] = {
688 POWER_SUPPLY_PROP_ONLINE,
689 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
690 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
693 static enum power_supply_property smbb_battery_properties[] = {
694 POWER_SUPPLY_PROP_STATUS,
695 POWER_SUPPLY_PROP_HEALTH,
696 POWER_SUPPLY_PROP_PRESENT,
697 POWER_SUPPLY_PROP_CHARGE_TYPE,
698 POWER_SUPPLY_PROP_CURRENT_MAX,
699 POWER_SUPPLY_PROP_VOLTAGE_MAX,
700 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
701 POWER_SUPPLY_PROP_TECHNOLOGY,
704 static const struct reg_off_mask_default {
708 unsigned int rev_mask;
709 } smbb_charger_setup[] = {
710 /* The bootloader is supposed to set this... make sure anyway. */
711 { SMBB_MISC_BOOT_DONE, BOOT_DONE, BOOT_DONE },
713 /* Disable software timer */
714 { SMBB_CHG_TCHG_MAX_EN, TCHG_MAX_EN, 0 },
716 /* Clear and disable watchdog */
717 { SMBB_CHG_WDOG_TIME, 0xff, 160 },
718 { SMBB_CHG_WDOG_EN, WDOG_EN, 0 },
720 /* Use charger based EoC detection */
721 { SMBB_CHG_IBAT_TERM_CHG, IBAT_TERM_CHG_IEOC, IBAT_TERM_CHG_IEOC_CHG },
723 /* Disable GSM PA load adjustment.
724 * The PA signal is incorrectly connected on v2.
726 { SMBB_CHG_CFG, 0xff, 0x00, BIT(3) },
728 /* Use VBAT (not VSYS) to compensate for IR drop during fast charging */
729 { SMBB_BUCK_REG_MODE, BUCK_REG_MODE, BUCK_REG_MODE_VBAT },
731 /* Enable battery temperature comparators */
732 { SMBB_BAT_BTC_CTRL, BTC_CTRL_COMP_EN, BTC_CTRL_COMP_EN },
734 /* Stop USB enumeration timer */
735 { SMBB_USB_ENUM_TIMER_STOP, ENUM_TIMER_STOP, ENUM_TIMER_STOP },
737 #if 0 /* FIXME supposedly only to disable hardware ARB termination */
738 { SMBB_USB_SEC_ACCESS, SEC_ACCESS_MAGIC },
739 { SMBB_USB_REV_BST, 0xff, REV_BST_CHG_GONE },
742 /* Stop USB enumeration timer, again */
743 { SMBB_USB_ENUM_TIMER_STOP, ENUM_TIMER_STOP, ENUM_TIMER_STOP },
745 /* Enable charging */
746 { SMBB_CHG_CTRL, CTRL_EN, CTRL_EN },
749 static char *smbb_bif[] = { "smbb-bif" };
751 static const struct power_supply_desc bat_psy_desc = {
753 .type = POWER_SUPPLY_TYPE_BATTERY,
754 .properties = smbb_battery_properties,
755 .num_properties = ARRAY_SIZE(smbb_battery_properties),
756 .get_property = smbb_battery_get_property,
757 .set_property = smbb_battery_set_property,
758 .property_is_writeable = smbb_battery_writable_property,
761 static const struct power_supply_desc usb_psy_desc = {
762 .name = "smbb-usbin",
763 .type = POWER_SUPPLY_TYPE_USB,
764 .properties = smbb_charger_properties,
765 .num_properties = ARRAY_SIZE(smbb_charger_properties),
766 .get_property = smbb_usbin_get_property,
767 .set_property = smbb_usbin_set_property,
768 .property_is_writeable = smbb_charger_writable_property,
771 static const struct power_supply_desc dc_psy_desc = {
773 .type = POWER_SUPPLY_TYPE_MAINS,
774 .properties = smbb_charger_properties,
775 .num_properties = ARRAY_SIZE(smbb_charger_properties),
776 .get_property = smbb_dcin_get_property,
777 .set_property = smbb_dcin_set_property,
778 .property_is_writeable = smbb_charger_writable_property,
781 static int smbb_charger_probe(struct platform_device *pdev)
783 struct power_supply_config bat_cfg = {};
784 struct power_supply_config usb_cfg = {};
785 struct power_supply_config dc_cfg = {};
786 struct smbb_charger *chg;
789 chg = devm_kzalloc(&pdev->dev, sizeof(*chg), GFP_KERNEL);
793 chg->dev = &pdev->dev;
794 mutex_init(&chg->statlock);
796 chg->regmap = dev_get_regmap(pdev->dev.parent, NULL);
798 dev_err(&pdev->dev, "failed to locate regmap\n");
802 rc = of_property_read_u32(pdev->dev.of_node, "reg", &chg->addr);
804 dev_err(&pdev->dev, "missing or invalid 'reg' property\n");
808 rc = regmap_read(chg->regmap, chg->addr + SMBB_MISC_REV2, &chg->revision);
810 dev_err(&pdev->dev, "unable to read revision\n");
815 if (chg->revision != 2 && chg->revision != 3) {
816 dev_err(&pdev->dev, "v1 hardware not supported\n");
819 dev_info(&pdev->dev, "Initializing SMBB rev %u", chg->revision);
821 chg->dc_disabled = of_property_read_bool(pdev->dev.of_node, "qcom,disable-dc");
823 for (i = 0; i < _ATTR_CNT; ++i) {
824 rc = smbb_charger_attr_parse(chg, i);
826 dev_err(&pdev->dev, "failed to parse/apply settings\n");
831 bat_cfg.drv_data = chg;
832 bat_cfg.of_node = pdev->dev.of_node;
833 chg->bat_psy = devm_power_supply_register(&pdev->dev,
836 if (IS_ERR(chg->bat_psy)) {
837 dev_err(&pdev->dev, "failed to register battery\n");
838 return PTR_ERR(chg->bat_psy);
841 usb_cfg.drv_data = chg;
842 usb_cfg.supplied_to = smbb_bif;
843 usb_cfg.num_supplicants = ARRAY_SIZE(smbb_bif);
844 chg->usb_psy = devm_power_supply_register(&pdev->dev,
847 if (IS_ERR(chg->usb_psy)) {
848 dev_err(&pdev->dev, "failed to register USB power supply\n");
849 return PTR_ERR(chg->usb_psy);
852 if (!chg->dc_disabled) {
853 dc_cfg.drv_data = chg;
854 dc_cfg.supplied_to = smbb_bif;
855 dc_cfg.num_supplicants = ARRAY_SIZE(smbb_bif);
856 chg->dc_psy = devm_power_supply_register(&pdev->dev,
859 if (IS_ERR(chg->dc_psy)) {
860 dev_err(&pdev->dev, "failed to register DC power supply\n");
861 return PTR_ERR(chg->dc_psy);
865 for (i = 0; i < ARRAY_SIZE(smbb_charger_irqs); ++i) {
868 irq = platform_get_irq_byname(pdev, smbb_charger_irqs[i].name);
870 dev_err(&pdev->dev, "failed to get irq '%s'\n",
871 smbb_charger_irqs[i].name);
875 smbb_charger_irqs[i].handler(irq, chg);
877 rc = devm_request_threaded_irq(&pdev->dev, irq, NULL,
878 smbb_charger_irqs[i].handler, IRQF_ONESHOT,
879 smbb_charger_irqs[i].name, chg);
881 dev_err(&pdev->dev, "failed to request irq '%s'\n",
882 smbb_charger_irqs[i].name);
887 chg->jeita_ext_temp = of_property_read_bool(pdev->dev.of_node,
888 "qcom,jeita-extended-temp-range");
890 /* Set temperature range to [35%:70%] or [25%:80%] accordingly */
891 rc = regmap_update_bits(chg->regmap, chg->addr + SMBB_BAT_BTC_CTRL,
892 BTC_CTRL_COLD_EXT | BTC_CTRL_HOT_EXT_N,
893 chg->jeita_ext_temp ?
898 "unable to set %s temperature range\n",
899 chg->jeita_ext_temp ? "JEITA extended" : "normal");
903 for (i = 0; i < ARRAY_SIZE(smbb_charger_setup); ++i) {
904 const struct reg_off_mask_default *r = &smbb_charger_setup[i];
906 if (r->rev_mask & BIT(chg->revision))
909 rc = regmap_update_bits(chg->regmap, chg->addr + r->offset,
913 "unable to initializing charging, bailing\n");
918 platform_set_drvdata(pdev, chg);
923 static int smbb_charger_remove(struct platform_device *pdev)
925 struct smbb_charger *chg;
927 chg = platform_get_drvdata(pdev);
929 regmap_update_bits(chg->regmap, chg->addr + SMBB_CHG_CTRL, CTRL_EN, 0);
934 static const struct of_device_id smbb_charger_id_table[] = {
935 { .compatible = "qcom,pm8941-charger" },
938 MODULE_DEVICE_TABLE(of, smbb_charger_id_table);
940 static struct platform_driver smbb_charger_driver = {
941 .probe = smbb_charger_probe,
942 .remove = smbb_charger_remove,
945 .of_match_table = smbb_charger_id_table,
948 module_platform_driver(smbb_charger_driver);
950 MODULE_DESCRIPTION("Qualcomm Switch-Mode Battery Charger and Boost driver");
951 MODULE_LICENSE("GPL v2");