Message ID | 20140507002421.GA19711@kahuna (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
* Nishanth Menon <nm@ti.com> [140506 17:25]: > Subject: [PATCH] power: twl4030_charger: detect battery presence prior to > enabling charger > > TWL4030's Battery Charger seems to be designed for non-hotpluggable > batteries. > > If battery is not present in the system, BATSTS is always set with the > expectation that software will take actions to move to a required safe > state (could be power down or disable various charger paths). > > It does not seem possible even by manipulating the edge detection > of the event (using BCIEDR2 register) to have a consistent hotplug > handling. This seems to be the result of BATSTS interrupt generated > when the thermistor of the battery pack is disconnected from the > dedicated ADIN1 pin. Clearing the status just results in the status > being regenerated by the monitoring ADC(MADC) and disabling the > edges of event just makes hotplug no longer function. The only > other option is to disable the detection of the MADC by disabling > BCIMFEN4::BATSTSMCHGEN (battery presence detector) - but then, we can > never again detect battery reconnection. > > So, detect battery presence based on precharge(which is hardware > automatic state) or default main charger configuration at the time of > probe and enable charger logic only if battery was present. > > Reported-by: Russell King <linux@arm.linux.org.uk> > Signed-off-by: Nishanth Menon <nm@ti.com> Gets rid of the errors for me if CONFIG_CHARGER_TWL4030=y. Looks like we don't have that enabled by default in omap2plus_defconfig which explain why it's taken so long to notice this one: Tested-by: Tony Lindgren <tony@atomide.com> -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 05/08/2014 08:03 PM, Tony Lindgren wrote: > * Nishanth Menon <nm@ti.com> [140506 17:25]: >> Subject: [PATCH] power: twl4030_charger: detect battery presence prior to >> enabling charger >> >> TWL4030's Battery Charger seems to be designed for non-hotpluggable >> batteries. >> >> If battery is not present in the system, BATSTS is always set with the >> expectation that software will take actions to move to a required safe >> state (could be power down or disable various charger paths). >> >> It does not seem possible even by manipulating the edge detection >> of the event (using BCIEDR2 register) to have a consistent hotplug >> handling. This seems to be the result of BATSTS interrupt generated >> when the thermistor of the battery pack is disconnected from the >> dedicated ADIN1 pin. Clearing the status just results in the status >> being regenerated by the monitoring ADC(MADC) and disabling the >> edges of event just makes hotplug no longer function. The only >> other option is to disable the detection of the MADC by disabling >> BCIMFEN4::BATSTSMCHGEN (battery presence detector) - but then, we can >> never again detect battery reconnection. >> >> So, detect battery presence based on precharge(which is hardware >> automatic state) or default main charger configuration at the time of >> probe and enable charger logic only if battery was present. >> >> Reported-by: Russell King <linux@arm.linux.org.uk> >> Signed-off-by: Nishanth Menon <nm@ti.com> > > Gets rid of the errors for me if CONFIG_CHARGER_TWL4030=y. > Looks like we don't have that enabled by default in > omap2plus_defconfig which explain why it's taken so long to > notice this one: > > Tested-by: Tony Lindgren <tony@atomide.com> > Thanks. I will post this out to the list as formal series.
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index f141088..14ec220 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c @@ -28,10 +28,13 @@ #define TWL4030_BCIICHG 0x08 #define TWL4030_BCIVAC 0x0a #define TWL4030_BCIVBUS 0x0c +#define TWL4030_BCIMFSTS3 0x0F #define TWL4030_BCIMFSTS4 0x10 #define TWL4030_BCICTL1 0x23 #define TWL4030_BB_CFG 0x12 +#define TWL4030_BCIMFSTS1 0x01 + #define TWL4030_BCIAUTOWEN BIT(5) #define TWL4030_CONFIG_DONE BIT(4) #define TWL4030_BCIAUTOUSB BIT(1) @@ -52,6 +55,9 @@ #define TWL4030_BBISEL_500uA 0x02 #define TWL4030_BBISEL_1000uA 0x03 +#define TWL4030_BATSTSPCHG BIT(2) +#define TWL4030_BATSTSMCHG BIT(6) + /* BCI interrupts */ #define TWL4030_WOVF BIT(0) /* Watchdog overflow */ #define TWL4030_TMOVF BIT(1) /* Timer overflow */ @@ -145,6 +151,34 @@ static int twl4030bci_read_adc_val(u8 reg) } /* + * Check if Battery Pack was present + */ +static int twl4030_is_battery_present(struct twl4030_bci *bci) +{ + int ret; + u8 val = 0; + + /* Battery presence in Main charge? */ + ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val, TWL4030_BCIMFSTS3); + if (ret) + return ret; + if (val & TWL4030_BATSTSMCHG) + return 0; + + /* + * OK, It could be that bootloader did not enable main charger, + * pre-charge is h/w auto. So, Battery presence in Pre-charge? + */ + ret = twl_i2c_read_u8(TWL4030_MODULE_PRECHARGE, &val, TWL4030_BCIMFSTS1); + if (ret) + return ret; + if (val & TWL4030_BATSTSPCHG) + return 0; + + return -ENODEV; +} + +/* * Check if VBUS power is present */ static int twl4030_bci_have_vbus(struct twl4030_bci *bci) @@ -541,8 +575,14 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) bci->irq_chg = platform_get_irq(pdev, 0); bci->irq_bci = platform_get_irq(pdev, 1); - platform_set_drvdata(pdev, bci); + /* Only proceed further *IF* battery is physically present */ + ret = twl4030_is_battery_present(bci); + if (ret) { + dev_crit(&pdev->dev, "Battery was not detected:%d\n", ret); + goto fail_no_battery; + } + platform_set_drvdata(pdev, bci); bci->ac.name = "twl4030_ac"; bci->ac.type = POWER_SUPPLY_TYPE_MAINS; bci->ac.properties = twl4030_charger_props; @@ -633,6 +673,7 @@ fail_chg_irq: fail_register_usb: power_supply_unregister(&bci->ac); fail_register_ac: +fail_no_battery: kfree(bci); return ret;