Various small bugfixes and enhancements, plus two new drivers:
- A quite complex ab8500 charger driver, submitted by Arun Murthy @ ST-Ericsson; - Summit Microelectronics SMB347 Battery Charger, submitted by Bruce E. Robertson and Alan Cox @ Intel. And that's all. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.18 (GNU/Linux) iQIcBAABAgAGBQJPdhj7AAoJEGgI9fZJve1bSKEQAKzKXPwqpBREXzS888YWzb34 0r3Bly+F8eSRTjclbEEvEOVVCjxKOFpow5lN+eAkRNAMLDBcMamfBTR+rpoYb822 d7R4Hy/stVnmD5nul0WMezZ0OZf6qRy8kHazmvb63Jk37ykof52TqoEInKdHL/ww afUNfCnAFAbZkjxEr/9MwpM+nzYKdlGIoQlu9CJLARJiT9CyICjgHG48MGmyxOws 1LPha40jXuKLoyE+6nvG1Ji71NzZlFaVuFpzk75kjsWoB78zkRsMSv+zboHRz3QP PI+uS54auIkGhqeIeEuuSzPZx+1K2Fr2/qyut3tqM8AejBE4kETiBAy0b0BREBSd NqA4/Yw24c8xglIFP6OlNjHnLgCsExfHATzqzML2El/dXG8P2ggEayZzDh9bmsuU ZNKOmHZYgEj2eEorJcmlfZ23rJwlxuspl1m2nH2WEnqw6Z6TnskK4N1JSNlpGRPU j+iHbTPA04hultQkzNHCdPRR/jK1IC5eGdwc612QgxOhZPkvhmW92e8EOVz/3E3X TqKXfBiKxKtkIncLPYFh7oeZINKnlqZrXsYrHhxhlm9UstGOqfEIqbCGqlf0Q4P1 WOhIQe1cP/JpB9T58e3mLF2dQIGScTqzQCRSW6/m+3HmDwZb8JyUQRw5188s3yJr umrBS5hqS+z3bISWrcGi =Y8fe -----END PGP SIGNATURE----- Merge tag 'for-v3.4-rc1' of git://git.infradead.org/battery-2.6 Pull battery updates from Anton Vorontsov: "Various small bugfixes and enhancements, plus two new drivers: - A quite complex ab8500 charger driver, submitted by Arun Murthy @ ST-Ericsson; - Summit Microelectronics SMB347 Battery Charger, submitted by Bruce E Robertson and Alan Cox @ Intel. And that's all." * tag 'for-v3.4-rc1' of git://git.infradead.org/battery-2.6: (36 commits) max17042_battery: Clean up interrupt handling Revert "max8998_charger: Include linux/module.h just once" ab8500_fg: Fix some build warnings on x86_64 max17042_battery: Fix CHARGE_FULL representation. max8998_charger: Include linux/module.h just once power_supply: Convert i2c drivers to module_i2c_driver lp8727_charger: Add MODULE_DEVICE_TABLE charger-manager: Simplify charger_get_property(), get rid of a warning charger-manager: Clean up for better readability da9052-battery: Convert to use module_platform_driver da9052-battery: Fix a memory leak when unload the module da9052-battery: Add missing platform_set_drvdata ab8500: Turn unneeded global symbols into local ones ab8500_fg: Fix copy-paste error ab8500_fg: Get rid of 'struct battery_type' ab8500_fg: Get rid of 'struct v_to_cap' ab8500_btemp: Get rid of 'enum adc_therm' ab8500_charger: Convert to the new USB OTG calls ab8500-btemp: AB8500 battery temperature driver ab8500-fg: A8500 fuel gauge driver ...
This commit is contained in:
Коммит
919c840167
|
@ -0,0 +1,18 @@
|
|||
max17042_battery
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
Required properties :
|
||||
- compatible : "maxim,max17042"
|
||||
|
||||
Optional properties :
|
||||
- maxim,rsns-microohm : Resistance of rsns resistor in micro Ohms
|
||||
(datasheet-recommended value is 10000).
|
||||
Defining this property enables current-sense functionality.
|
||||
|
||||
Example:
|
||||
|
||||
battery-charger@36 {
|
||||
compatible = "maxim,max17042";
|
||||
reg = <0x36>;
|
||||
maxim,rsns-microohm = <10000>;
|
||||
};
|
|
@ -249,7 +249,7 @@ config CHARGER_TWL4030
|
|||
Say Y here to enable support for TWL4030 Battery Charge Interface.
|
||||
|
||||
config CHARGER_LP8727
|
||||
tristate "National Semiconductor LP8727 charger driver"
|
||||
tristate "TI/National Semiconductor LP8727 charger driver"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here to enable support for LP8727 Charger Driver.
|
||||
|
@ -288,4 +288,23 @@ config CHARGER_MAX8998
|
|||
Say Y to enable support for the battery charger control sysfs and
|
||||
platform data of MAX8998/LP3974 PMICs.
|
||||
|
||||
config CHARGER_SMB347
|
||||
tristate "Summit Microelectronics SMB347 Battery Charger"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y to include support for Summit Microelectronics SMB347
|
||||
Battery Charger.
|
||||
|
||||
config AB8500_BM
|
||||
bool "AB8500 Battery Management Driver"
|
||||
depends on AB8500_CORE && AB8500_GPADC
|
||||
help
|
||||
Say Y to include support for AB5500 battery management.
|
||||
|
||||
config AB8500_BATTERY_THERM_ON_BATCTRL
|
||||
bool "Thermistor connected on BATCTRL ADC"
|
||||
depends on AB8500_BM
|
||||
help
|
||||
Say Y to enable battery temperature measurements using
|
||||
thermistor connected on BATCTRL ADC.
|
||||
endif # POWER_SUPPLY
|
||||
|
|
|
@ -34,6 +34,7 @@ obj-$(CONFIG_BATTERY_S3C_ADC) += s3c_adc_battery.o
|
|||
obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
|
||||
obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o
|
||||
obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o
|
||||
obj-$(CONFIG_AB8500_BM) += ab8500_charger.o ab8500_btemp.o ab8500_fg.o abx500_chargalg.o
|
||||
obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
|
||||
obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o
|
||||
obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
|
||||
|
@ -42,3 +43,4 @@ obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
|
|||
obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o
|
||||
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
|
||||
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
|
||||
obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -134,12 +134,11 @@ static int get_batt_uV(struct charger_manager *cm, int *uV)
|
|||
union power_supply_propval val;
|
||||
int ret;
|
||||
|
||||
if (cm->fuel_gauge)
|
||||
ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW, &val);
|
||||
else
|
||||
if (!cm->fuel_gauge)
|
||||
return -ENODEV;
|
||||
|
||||
ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -245,9 +244,7 @@ static int try_charger_enable(struct charger_manager *cm, bool enable)
|
|||
struct charger_desc *desc = cm->desc;
|
||||
|
||||
/* Ignore if it's redundent command */
|
||||
if (enable && cm->charger_enabled)
|
||||
return 0;
|
||||
if (!enable && !cm->charger_enabled)
|
||||
if (enable == cm->charger_enabled)
|
||||
return 0;
|
||||
|
||||
if (enable) {
|
||||
|
@ -309,9 +306,7 @@ static void uevent_notify(struct charger_manager *cm, const char *event)
|
|||
|
||||
if (!strncmp(env_str_save, event, UEVENT_BUF_SIZE))
|
||||
return; /* Duplicated. */
|
||||
else
|
||||
strncpy(env_str_save, event, UEVENT_BUF_SIZE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -387,8 +382,10 @@ static bool cm_monitor(void)
|
|||
|
||||
mutex_lock(&cm_list_mtx);
|
||||
|
||||
list_for_each_entry(cm, &cm_list, entry)
|
||||
stop = stop || _cm_monitor(cm);
|
||||
list_for_each_entry(cm, &cm_list, entry) {
|
||||
if (_cm_monitor(cm))
|
||||
stop = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&cm_list_mtx);
|
||||
|
||||
|
@ -402,7 +399,8 @@ static int charger_get_property(struct power_supply *psy,
|
|||
struct charger_manager *cm = container_of(psy,
|
||||
struct charger_manager, charger_psy);
|
||||
struct charger_desc *desc = cm->desc;
|
||||
int i, ret = 0, uV;
|
||||
int ret = 0;
|
||||
int uV;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
|
@ -428,8 +426,7 @@ static int charger_get_property(struct power_supply *psy,
|
|||
val->intval = 0;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
ret = get_batt_uV(cm, &i);
|
||||
val->intval = i;
|
||||
ret = get_batt_uV(cm, &val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CURRENT_NOW:
|
||||
ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
|
||||
|
@ -697,8 +694,10 @@ bool cm_suspend_again(void)
|
|||
mutex_lock(&cm_list_mtx);
|
||||
list_for_each_entry(cm, &cm_list, entry) {
|
||||
if (cm->status_save_ext_pwr_inserted != is_ext_pwr_online(cm) ||
|
||||
cm->status_save_batt != is_batt_present(cm))
|
||||
cm->status_save_batt != is_batt_present(cm)) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&cm_list_mtx);
|
||||
|
||||
|
@ -855,11 +854,10 @@ static int charger_manager_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, cm);
|
||||
|
||||
memcpy(&cm->charger_psy, &psy_default,
|
||||
sizeof(psy_default));
|
||||
memcpy(&cm->charger_psy, &psy_default, sizeof(psy_default));
|
||||
|
||||
if (!desc->psy_name) {
|
||||
strncpy(cm->psy_name_buf, psy_default.name,
|
||||
PSY_NAME_MAX);
|
||||
strncpy(cm->psy_name_buf, psy_default.name, PSY_NAME_MAX);
|
||||
} else {
|
||||
strncpy(cm->psy_name_buf, desc->psy_name, PSY_NAME_MAX);
|
||||
}
|
||||
|
@ -894,15 +892,15 @@ static int charger_manager_probe(struct platform_device *pdev)
|
|||
POWER_SUPPLY_PROP_CURRENT_NOW;
|
||||
cm->charger_psy.num_properties++;
|
||||
}
|
||||
if (!desc->measure_battery_temp) {
|
||||
cm->charger_psy.properties[cm->charger_psy.num_properties] =
|
||||
POWER_SUPPLY_PROP_TEMP_AMBIENT;
|
||||
cm->charger_psy.num_properties++;
|
||||
}
|
||||
|
||||
if (desc->measure_battery_temp) {
|
||||
cm->charger_psy.properties[cm->charger_psy.num_properties] =
|
||||
POWER_SUPPLY_PROP_TEMP;
|
||||
cm->charger_psy.num_properties++;
|
||||
} else {
|
||||
cm->charger_psy.properties[cm->charger_psy.num_properties] =
|
||||
POWER_SUPPLY_PROP_TEMP_AMBIENT;
|
||||
cm->charger_psy.num_properties++;
|
||||
}
|
||||
|
||||
ret = power_supply_register(NULL, &cm->charger_psy);
|
||||
|
@ -933,7 +931,6 @@ static int charger_manager_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
err_chg_enable:
|
||||
if (desc->charger_regulators)
|
||||
regulator_bulk_free(desc->num_charger_regulators,
|
||||
desc->charger_regulators);
|
||||
err_bulk_get:
|
||||
|
@ -961,10 +958,8 @@ static int __devexit charger_manager_remove(struct platform_device *pdev)
|
|||
list_del(&cm->entry);
|
||||
mutex_unlock(&cm_list_mtx);
|
||||
|
||||
if (desc->charger_regulators)
|
||||
regulator_bulk_free(desc->num_charger_regulators,
|
||||
desc->charger_regulators);
|
||||
|
||||
power_supply_unregister(&cm->charger_psy);
|
||||
kfree(cm->charger_psy.properties);
|
||||
kfree(cm->charger_stat);
|
||||
|
@ -982,9 +977,7 @@ MODULE_DEVICE_TABLE(platform, charger_manager_id);
|
|||
|
||||
static int cm_suspend_prepare(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = container_of(dev, struct platform_device,
|
||||
dev);
|
||||
struct charger_manager *cm = platform_get_drvdata(pdev);
|
||||
struct charger_manager *cm = dev_get_drvdata(dev);
|
||||
|
||||
if (!cm_suspended) {
|
||||
if (rtc_dev) {
|
||||
|
@ -1020,9 +1013,7 @@ static int cm_suspend_prepare(struct device *dev)
|
|||
|
||||
static void cm_suspend_complete(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = container_of(dev, struct platform_device,
|
||||
dev);
|
||||
struct charger_manager *cm = platform_get_drvdata(pdev);
|
||||
struct charger_manager *cm = dev_get_drvdata(dev);
|
||||
|
||||
if (cm_suspended) {
|
||||
if (rtc_dev) {
|
||||
|
|
|
@ -612,6 +612,7 @@ static s32 __devinit da9052_bat_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto err;
|
||||
|
||||
platform_set_drvdata(pdev, bat);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
@ -633,6 +634,7 @@ static int __devexit da9052_bat_remove(struct platform_device *pdev)
|
|||
free_irq(bat->da9052->irq_base + irq, bat);
|
||||
}
|
||||
power_supply_unregister(&bat->psy);
|
||||
kfree(bat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -645,18 +647,7 @@ static struct platform_driver da9052_bat_driver = {
|
|||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init da9052_bat_init(void)
|
||||
{
|
||||
return platform_driver_register(&da9052_bat_driver);
|
||||
}
|
||||
module_init(da9052_bat_init);
|
||||
|
||||
static void __exit da9052_bat_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&da9052_bat_driver);
|
||||
}
|
||||
module_exit(da9052_bat_exit);
|
||||
module_platform_driver(da9052_bat_driver);
|
||||
|
||||
MODULE_DESCRIPTION("DA9052 BAT Device Driver");
|
||||
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
|
||||
|
|
|
@ -403,18 +403,7 @@ static struct i2c_driver ds278x_battery_driver = {
|
|||
.remove = ds278x_battery_remove,
|
||||
.id_table = ds278x_id,
|
||||
};
|
||||
|
||||
static int __init ds278x_init(void)
|
||||
{
|
||||
return i2c_add_driver(&ds278x_battery_driver);
|
||||
}
|
||||
module_init(ds278x_init);
|
||||
|
||||
static void __exit ds278x_exit(void)
|
||||
{
|
||||
i2c_del_driver(&ds278x_battery_driver);
|
||||
}
|
||||
module_exit(ds278x_exit);
|
||||
module_i2c_driver(ds278x_battery_driver);
|
||||
|
||||
MODULE_AUTHOR("Ryan Mallon");
|
||||
MODULE_DESCRIPTION("Maxim/Dallas DS2782 Stand-Alone Fuel Gauage IC driver");
|
||||
|
|
|
@ -480,6 +480,7 @@ fail0:
|
|||
|
||||
dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret);
|
||||
|
||||
isp1704_charger_set_power(isp, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Driver for LP8727 Micro/Mini USB IC with intergrated charger
|
||||
* Driver for LP8727 Micro/Mini USB IC with integrated charger
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments
|
||||
* Copyright (C) 2011 National Semiconductor
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -91,7 +92,7 @@ struct lp8727_chg {
|
|||
enum lp8727_dev_id devid;
|
||||
};
|
||||
|
||||
static int lp8727_i2c_read(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len)
|
||||
static int lp8727_read_bytes(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len)
|
||||
{
|
||||
s32 ret;
|
||||
|
||||
|
@ -102,29 +103,22 @@ static int lp8727_i2c_read(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len)
|
|||
return (ret != len) ? -EIO : 0;
|
||||
}
|
||||
|
||||
static int lp8727_i2c_write(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len)
|
||||
static inline int lp8727_read_byte(struct lp8727_chg *pchg, u8 reg, u8 *data)
|
||||
{
|
||||
s32 ret;
|
||||
return lp8727_read_bytes(pchg, reg, data, 1);
|
||||
}
|
||||
|
||||
static int lp8727_write_byte(struct lp8727_chg *pchg, u8 reg, u8 data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&pchg->xfer_lock);
|
||||
ret = i2c_smbus_write_i2c_block_data(pchg->client, reg, len, data);
|
||||
ret = i2c_smbus_write_byte_data(pchg->client, reg, data);
|
||||
mutex_unlock(&pchg->xfer_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int lp8727_i2c_read_byte(struct lp8727_chg *pchg, u8 reg,
|
||||
u8 *data)
|
||||
{
|
||||
return lp8727_i2c_read(pchg, reg, data, 1);
|
||||
}
|
||||
|
||||
static inline int lp8727_i2c_write_byte(struct lp8727_chg *pchg, u8 reg,
|
||||
u8 *data)
|
||||
{
|
||||
return lp8727_i2c_write(pchg, reg, data, 1);
|
||||
}
|
||||
|
||||
static int lp8727_is_charger_attached(const char *name, int id)
|
||||
{
|
||||
if (name) {
|
||||
|
@ -137,37 +131,41 @@ static int lp8727_is_charger_attached(const char *name, int id)
|
|||
return (id >= ID_TA && id <= ID_USB_CHG) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void lp8727_init_device(struct lp8727_chg *pchg)
|
||||
static int lp8727_init_device(struct lp8727_chg *pchg)
|
||||
{
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
val = ID200_EN | ADC_EN | CP_EN;
|
||||
if (lp8727_i2c_write_byte(pchg, CTRL1, &val))
|
||||
dev_err(pchg->dev, "i2c write err : addr=0x%.2x\n", CTRL1);
|
||||
ret = lp8727_write_byte(pchg, CTRL1, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = INT_EN | CHGDET_EN;
|
||||
if (lp8727_i2c_write_byte(pchg, CTRL2, &val))
|
||||
dev_err(pchg->dev, "i2c write err : addr=0x%.2x\n", CTRL2);
|
||||
ret = lp8727_write_byte(pchg, CTRL2, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lp8727_is_dedicated_charger(struct lp8727_chg *pchg)
|
||||
{
|
||||
u8 val;
|
||||
lp8727_i2c_read_byte(pchg, STATUS1, &val);
|
||||
return (val & DCPORT);
|
||||
lp8727_read_byte(pchg, STATUS1, &val);
|
||||
return val & DCPORT;
|
||||
}
|
||||
|
||||
static int lp8727_is_usb_charger(struct lp8727_chg *pchg)
|
||||
{
|
||||
u8 val;
|
||||
lp8727_i2c_read_byte(pchg, STATUS1, &val);
|
||||
return (val & CHPORT);
|
||||
lp8727_read_byte(pchg, STATUS1, &val);
|
||||
return val & CHPORT;
|
||||
}
|
||||
|
||||
static void lp8727_ctrl_switch(struct lp8727_chg *pchg, u8 sw)
|
||||
{
|
||||
u8 val = sw;
|
||||
lp8727_i2c_write_byte(pchg, SWCTRL, &val);
|
||||
lp8727_write_byte(pchg, SWCTRL, sw);
|
||||
}
|
||||
|
||||
static void lp8727_id_detection(struct lp8727_chg *pchg, u8 id, int vbusin)
|
||||
|
@ -207,9 +205,9 @@ static void lp8727_enable_chgdet(struct lp8727_chg *pchg)
|
|||
{
|
||||
u8 val;
|
||||
|
||||
lp8727_i2c_read_byte(pchg, CTRL2, &val);
|
||||
lp8727_read_byte(pchg, CTRL2, &val);
|
||||
val |= CHGDET_EN;
|
||||
lp8727_i2c_write_byte(pchg, CTRL2, &val);
|
||||
lp8727_write_byte(pchg, CTRL2, val);
|
||||
}
|
||||
|
||||
static void lp8727_delayed_func(struct work_struct *_work)
|
||||
|
@ -218,7 +216,7 @@ static void lp8727_delayed_func(struct work_struct *_work)
|
|||
struct lp8727_chg *pchg =
|
||||
container_of(_work, struct lp8727_chg, work.work);
|
||||
|
||||
if (lp8727_i2c_read(pchg, INT1, intstat, 2)) {
|
||||
if (lp8727_read_bytes(pchg, INT1, intstat, 2)) {
|
||||
dev_err(pchg->dev, "can not read INT registers\n");
|
||||
return;
|
||||
}
|
||||
|
@ -244,20 +242,22 @@ static irqreturn_t lp8727_isr_func(int irq, void *ptr)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void lp8727_intr_config(struct lp8727_chg *pchg)
|
||||
static int lp8727_intr_config(struct lp8727_chg *pchg)
|
||||
{
|
||||
INIT_DELAYED_WORK(&pchg->work, lp8727_delayed_func);
|
||||
|
||||
pchg->irqthread = create_singlethread_workqueue("lp8727-irqthd");
|
||||
if (!pchg->irqthread)
|
||||
if (!pchg->irqthread) {
|
||||
dev_err(pchg->dev, "can not create thread for lp8727\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (request_threaded_irq(pchg->client->irq,
|
||||
return request_threaded_irq(pchg->client->irq,
|
||||
NULL,
|
||||
lp8727_isr_func,
|
||||
IRQF_TRIGGER_FALLING, "lp8727_irq", pchg)) {
|
||||
dev_err(pchg->dev, "lp8727 irq can not be registered\n");
|
||||
}
|
||||
IRQF_TRIGGER_FALLING,
|
||||
"lp8727_irq",
|
||||
pchg);
|
||||
}
|
||||
|
||||
static enum power_supply_property lp8727_charger_prop[] = {
|
||||
|
@ -300,7 +300,7 @@ static int lp8727_battery_get_property(struct power_supply *psy,
|
|||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
if (lp8727_is_charger_attached(psy->name, pchg->devid)) {
|
||||
lp8727_i2c_read_byte(pchg, STATUS1, &read);
|
||||
lp8727_read_byte(pchg, STATUS1, &read);
|
||||
if (((read & CHGSTAT) >> 4) == EOC)
|
||||
val->intval = POWER_SUPPLY_STATUS_FULL;
|
||||
else
|
||||
|
@ -310,7 +310,7 @@ static int lp8727_battery_get_property(struct power_supply *psy,
|
|||
}
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_HEALTH:
|
||||
lp8727_i2c_read_byte(pchg, STATUS2, &read);
|
||||
lp8727_read_byte(pchg, STATUS2, &read);
|
||||
read = (read & TEMP_STAT) >> 5;
|
||||
if (read >= 0x1 && read <= 0x3)
|
||||
val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
|
||||
|
@ -351,7 +351,7 @@ static void lp8727_charger_changed(struct power_supply *psy)
|
|||
eoc_level = pchg->chg_parm->eoc_level;
|
||||
ichg = pchg->chg_parm->ichg;
|
||||
val = (ichg << 4) | eoc_level;
|
||||
lp8727_i2c_write_byte(pchg, CHGCTRL2, &val);
|
||||
lp8727_write_byte(pchg, CHGCTRL2, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -439,15 +439,29 @@ static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
|
|||
|
||||
mutex_init(&pchg->xfer_lock);
|
||||
|
||||
lp8727_init_device(pchg);
|
||||
lp8727_intr_config(pchg);
|
||||
ret = lp8727_init_device(pchg);
|
||||
if (ret) {
|
||||
dev_err(pchg->dev, "i2c communication err: %d", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = lp8727_intr_config(pchg);
|
||||
if (ret) {
|
||||
dev_err(pchg->dev, "irq handler err: %d", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = lp8727_register_psy(pchg);
|
||||
if (ret)
|
||||
dev_err(pchg->dev,
|
||||
"can not register power supplies. err=%d", ret);
|
||||
if (ret) {
|
||||
dev_err(pchg->dev, "power supplies register err: %d", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
kfree(pchg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit lp8727_remove(struct i2c_client *cl)
|
||||
|
@ -466,6 +480,7 @@ static const struct i2c_device_id lp8727_ids[] = {
|
|||
{"lp8727", 0},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, lp8727_ids);
|
||||
|
||||
static struct i2c_driver lp8727_driver = {
|
||||
.driver = {
|
||||
|
@ -475,21 +490,9 @@ static struct i2c_driver lp8727_driver = {
|
|||
.remove = __devexit_p(lp8727_remove),
|
||||
.id_table = lp8727_ids,
|
||||
};
|
||||
module_i2c_driver(lp8727_driver);
|
||||
|
||||
static int __init lp8727_init(void)
|
||||
{
|
||||
return i2c_add_driver(&lp8727_driver);
|
||||
}
|
||||
|
||||
static void __exit lp8727_exit(void)
|
||||
{
|
||||
i2c_del_driver(&lp8727_driver);
|
||||
}
|
||||
|
||||
module_init(lp8727_init);
|
||||
module_exit(lp8727_exit);
|
||||
|
||||
MODULE_DESCRIPTION("National Semiconductor LP8727 charger driver");
|
||||
MODULE_AUTHOR
|
||||
("Woogyom Kim <milo.kim@ti.com>, Daniel Jeong <daniel.jeong@ti.com>");
|
||||
MODULE_DESCRIPTION("TI/National Semiconductor LP8727 charger driver");
|
||||
MODULE_AUTHOR("Woogyom Kim <milo.kim@ti.com>, "
|
||||
"Daniel Jeong <daniel.jeong@ti.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -290,18 +290,7 @@ static struct i2c_driver max17040_i2c_driver = {
|
|||
.resume = max17040_resume,
|
||||
.id_table = max17040_id,
|
||||
};
|
||||
|
||||
static int __init max17040_init(void)
|
||||
{
|
||||
return i2c_add_driver(&max17040_i2c_driver);
|
||||
}
|
||||
module_init(max17040_init);
|
||||
|
||||
static void __exit max17040_exit(void)
|
||||
{
|
||||
i2c_del_driver(&max17040_i2c_driver);
|
||||
}
|
||||
module_exit(max17040_exit);
|
||||
module_i2c_driver(max17040_i2c_driver);
|
||||
|
||||
MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>");
|
||||
MODULE_DESCRIPTION("MAX17040 Fuel Gauge");
|
||||
|
|
|
@ -26,14 +26,47 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/power/max17042_battery.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
/* Status register bits */
|
||||
#define STATUS_POR_BIT (1 << 1)
|
||||
#define STATUS_BST_BIT (1 << 3)
|
||||
#define STATUS_VMN_BIT (1 << 8)
|
||||
#define STATUS_TMN_BIT (1 << 9)
|
||||
#define STATUS_SMN_BIT (1 << 10)
|
||||
#define STATUS_BI_BIT (1 << 11)
|
||||
#define STATUS_VMX_BIT (1 << 12)
|
||||
#define STATUS_TMX_BIT (1 << 13)
|
||||
#define STATUS_SMX_BIT (1 << 14)
|
||||
#define STATUS_BR_BIT (1 << 15)
|
||||
|
||||
/* Interrupt mask bits */
|
||||
#define CONFIG_ALRT_BIT_ENBL (1 << 2)
|
||||
#define STATUS_INTR_SOCMIN_BIT (1 << 10)
|
||||
#define STATUS_INTR_SOCMAX_BIT (1 << 14)
|
||||
|
||||
#define VFSOC0_LOCK 0x0000
|
||||
#define VFSOC0_UNLOCK 0x0080
|
||||
#define MODEL_UNLOCK1 0X0059
|
||||
#define MODEL_UNLOCK2 0X00C4
|
||||
#define MODEL_LOCK1 0X0000
|
||||
#define MODEL_LOCK2 0X0000
|
||||
|
||||
#define dQ_ACC_DIV 0x4
|
||||
#define dP_ACC_100 0x1900
|
||||
#define dP_ACC_200 0x3200
|
||||
|
||||
struct max17042_chip {
|
||||
struct i2c_client *client;
|
||||
struct power_supply battery;
|
||||
struct max17042_platform_data *pdata;
|
||||
struct work_struct work;
|
||||
int init_complete;
|
||||
};
|
||||
|
||||
static int max17042_write_reg(struct i2c_client *client, u8 reg, u16 value)
|
||||
|
@ -87,6 +120,9 @@ static int max17042_get_property(struct power_supply *psy,
|
|||
struct max17042_chip, battery);
|
||||
int ret;
|
||||
|
||||
if (!chip->init_complete)
|
||||
return -EAGAIN;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
ret = max17042_read_reg(chip->client, MAX17042_STATUS);
|
||||
|
@ -136,21 +172,18 @@ static int max17042_get_property(struct power_supply *psy,
|
|||
val->intval = ret * 625 / 8;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CAPACITY:
|
||||
ret = max17042_read_reg(chip->client, MAX17042_SOC);
|
||||
ret = max17042_read_reg(chip->client, MAX17042_RepSOC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val->intval = ret >> 8;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CHARGE_FULL:
|
||||
ret = max17042_read_reg(chip->client, MAX17042_RepSOC);
|
||||
ret = max17042_read_reg(chip->client, MAX17042_FullCAP);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if ((ret >> 8) >= MAX17042_BATTERY_FULL)
|
||||
val->intval = 1;
|
||||
else if (ret >= 0)
|
||||
val->intval = 0;
|
||||
val->intval = ret * 1000 / 2;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TEMP:
|
||||
ret = max17042_read_reg(chip->client, MAX17042_TEMP);
|
||||
|
@ -210,22 +243,419 @@ static int max17042_get_property(struct power_supply *psy,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int max17042_write_verify_reg(struct i2c_client *client,
|
||||
u8 reg, u16 value)
|
||||
{
|
||||
int retries = 8;
|
||||
int ret;
|
||||
u16 read_value;
|
||||
|
||||
do {
|
||||
ret = i2c_smbus_write_word_data(client, reg, value);
|
||||
read_value = max17042_read_reg(client, reg);
|
||||
if (read_value != value) {
|
||||
ret = -EIO;
|
||||
retries--;
|
||||
}
|
||||
} while (retries && read_value != value);
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(&client->dev, "%s: err %d\n", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void max17042_override_por(
|
||||
struct i2c_client *client, u8 reg, u16 value)
|
||||
{
|
||||
if (value)
|
||||
max17042_write_reg(client, reg, value);
|
||||
}
|
||||
|
||||
static inline void max10742_unlock_model(struct max17042_chip *chip)
|
||||
{
|
||||
struct i2c_client *client = chip->client;
|
||||
max17042_write_reg(client, MAX17042_MLOCKReg1, MODEL_UNLOCK1);
|
||||
max17042_write_reg(client, MAX17042_MLOCKReg2, MODEL_UNLOCK2);
|
||||
}
|
||||
|
||||
static inline void max10742_lock_model(struct max17042_chip *chip)
|
||||
{
|
||||
struct i2c_client *client = chip->client;
|
||||
max17042_write_reg(client, MAX17042_MLOCKReg1, MODEL_LOCK1);
|
||||
max17042_write_reg(client, MAX17042_MLOCKReg2, MODEL_LOCK2);
|
||||
}
|
||||
|
||||
static inline void max17042_write_model_data(struct max17042_chip *chip,
|
||||
u8 addr, int size)
|
||||
{
|
||||
struct i2c_client *client = chip->client;
|
||||
int i;
|
||||
for (i = 0; i < size; i++)
|
||||
max17042_write_reg(client, addr + i,
|
||||
chip->pdata->config_data->cell_char_tbl[i]);
|
||||
}
|
||||
|
||||
static inline void max17042_read_model_data(struct max17042_chip *chip,
|
||||
u8 addr, u16 *data, int size)
|
||||
{
|
||||
struct i2c_client *client = chip->client;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
data[i] = max17042_read_reg(client, addr + i);
|
||||
}
|
||||
|
||||
static inline int max17042_model_data_compare(struct max17042_chip *chip,
|
||||
u16 *data1, u16 *data2, int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (memcmp(data1, data2, size)) {
|
||||
dev_err(&chip->client->dev, "%s compare failed\n", __func__);
|
||||
for (i = 0; i < size; i++)
|
||||
dev_info(&chip->client->dev, "0x%x, 0x%x",
|
||||
data1[i], data2[i]);
|
||||
dev_info(&chip->client->dev, "\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max17042_init_model(struct max17042_chip *chip)
|
||||
{
|
||||
int ret;
|
||||
int table_size =
|
||||
sizeof(chip->pdata->config_data->cell_char_tbl)/sizeof(u16);
|
||||
u16 *temp_data;
|
||||
|
||||
temp_data = kzalloc(table_size, GFP_KERNEL);
|
||||
if (!temp_data)
|
||||
return -ENOMEM;
|
||||
|
||||
max10742_unlock_model(chip);
|
||||
max17042_write_model_data(chip, MAX17042_MODELChrTbl,
|
||||
table_size);
|
||||
max17042_read_model_data(chip, MAX17042_MODELChrTbl, temp_data,
|
||||
table_size);
|
||||
|
||||
ret = max17042_model_data_compare(
|
||||
chip,
|
||||
chip->pdata->config_data->cell_char_tbl,
|
||||
temp_data,
|
||||
table_size);
|
||||
|
||||
max10742_lock_model(chip);
|
||||
kfree(temp_data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max17042_verify_model_lock(struct max17042_chip *chip)
|
||||
{
|
||||
int i;
|
||||
int table_size =
|
||||
sizeof(chip->pdata->config_data->cell_char_tbl);
|
||||
u16 *temp_data;
|
||||
int ret = 0;
|
||||
|
||||
temp_data = kzalloc(table_size, GFP_KERNEL);
|
||||
if (!temp_data)
|
||||
return -ENOMEM;
|
||||
|
||||
max17042_read_model_data(chip, MAX17042_MODELChrTbl, temp_data,
|
||||
table_size);
|
||||
for (i = 0; i < table_size; i++)
|
||||
if (temp_data[i])
|
||||
ret = -EINVAL;
|
||||
|
||||
kfree(temp_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void max17042_write_config_regs(struct max17042_chip *chip)
|
||||
{
|
||||
struct max17042_config_data *config = chip->pdata->config_data;
|
||||
|
||||
max17042_write_reg(chip->client, MAX17042_CONFIG, config->config);
|
||||
max17042_write_reg(chip->client, MAX17042_LearnCFG, config->learn_cfg);
|
||||
max17042_write_reg(chip->client, MAX17042_FilterCFG,
|
||||
config->filter_cfg);
|
||||
max17042_write_reg(chip->client, MAX17042_RelaxCFG, config->relax_cfg);
|
||||
}
|
||||
|
||||
static void max17042_write_custom_regs(struct max17042_chip *chip)
|
||||
{
|
||||
struct max17042_config_data *config = chip->pdata->config_data;
|
||||
|
||||
max17042_write_verify_reg(chip->client, MAX17042_RCOMP0,
|
||||
config->rcomp0);
|
||||
max17042_write_verify_reg(chip->client, MAX17042_TempCo,
|
||||
config->tcompc0);
|
||||
max17042_write_reg(chip->client, MAX17042_EmptyTempCo,
|
||||
config->empty_tempco);
|
||||
max17042_write_verify_reg(chip->client, MAX17042_K_empty0,
|
||||
config->kempty0);
|
||||
max17042_write_verify_reg(chip->client, MAX17042_ICHGTerm,
|
||||
config->ichgt_term);
|
||||
}
|
||||
|
||||
static void max17042_update_capacity_regs(struct max17042_chip *chip)
|
||||
{
|
||||
struct max17042_config_data *config = chip->pdata->config_data;
|
||||
|
||||
max17042_write_verify_reg(chip->client, MAX17042_FullCAP,
|
||||
config->fullcap);
|
||||
max17042_write_reg(chip->client, MAX17042_DesignCap,
|
||||
config->design_cap);
|
||||
max17042_write_verify_reg(chip->client, MAX17042_FullCAPNom,
|
||||
config->fullcapnom);
|
||||
}
|
||||
|
||||
static void max17042_reset_vfsoc0_reg(struct max17042_chip *chip)
|
||||
{
|
||||
u16 vfSoc;
|
||||
|
||||
vfSoc = max17042_read_reg(chip->client, MAX17042_VFSOC);
|
||||
max17042_write_reg(chip->client, MAX17042_VFSOC0Enable, VFSOC0_UNLOCK);
|
||||
max17042_write_verify_reg(chip->client, MAX17042_VFSOC0, vfSoc);
|
||||
max17042_write_reg(chip->client, MAX17042_VFSOC0Enable, VFSOC0_LOCK);
|
||||
}
|
||||
|
||||
static void max17042_load_new_capacity_params(struct max17042_chip *chip)
|
||||
{
|
||||
u16 full_cap0, rep_cap, dq_acc, vfSoc;
|
||||
u32 rem_cap;
|
||||
|
||||
struct max17042_config_data *config = chip->pdata->config_data;
|
||||
|
||||
full_cap0 = max17042_read_reg(chip->client, MAX17042_FullCAP0);
|
||||
vfSoc = max17042_read_reg(chip->client, MAX17042_VFSOC);
|
||||
|
||||
/* fg_vfSoc needs to shifted by 8 bits to get the
|
||||
* perc in 1% accuracy, to get the right rem_cap multiply
|
||||
* full_cap0, fg_vfSoc and devide by 100
|
||||
*/
|
||||
rem_cap = ((vfSoc >> 8) * full_cap0) / 100;
|
||||
max17042_write_verify_reg(chip->client, MAX17042_RemCap, (u16)rem_cap);
|
||||
|
||||
rep_cap = (u16)rem_cap;
|
||||
max17042_write_verify_reg(chip->client, MAX17042_RepCap, rep_cap);
|
||||
|
||||
/* Write dQ_acc to 200% of Capacity and dP_acc to 200% */
|
||||
dq_acc = config->fullcap / dQ_ACC_DIV;
|
||||
max17042_write_verify_reg(chip->client, MAX17042_dQacc, dq_acc);
|
||||
max17042_write_verify_reg(chip->client, MAX17042_dPacc, dP_ACC_200);
|
||||
|
||||
max17042_write_verify_reg(chip->client, MAX17042_FullCAP,
|
||||
config->fullcap);
|
||||
max17042_write_reg(chip->client, MAX17042_DesignCap,
|
||||
config->design_cap);
|
||||
max17042_write_verify_reg(chip->client, MAX17042_FullCAPNom,
|
||||
config->fullcapnom);
|
||||
}
|
||||
|
||||
/*
|
||||
* Block write all the override values coming from platform data.
|
||||
* This function MUST be called before the POR initialization proceedure
|
||||
* specified by maxim.
|
||||
*/
|
||||
static inline void max17042_override_por_values(struct max17042_chip *chip)
|
||||
{
|
||||
struct i2c_client *client = chip->client;
|
||||
struct max17042_config_data *config = chip->pdata->config_data;
|
||||
|
||||
max17042_override_por(client, MAX17042_TGAIN, config->tgain);
|
||||
max17042_override_por(client, MAx17042_TOFF, config->toff);
|
||||
max17042_override_por(client, MAX17042_CGAIN, config->cgain);
|
||||
max17042_override_por(client, MAX17042_COFF, config->coff);
|
||||
|
||||
max17042_override_por(client, MAX17042_VALRT_Th, config->valrt_thresh);
|
||||
max17042_override_por(client, MAX17042_TALRT_Th, config->talrt_thresh);
|
||||
max17042_override_por(client, MAX17042_SALRT_Th,
|
||||
config->soc_alrt_thresh);
|
||||
max17042_override_por(client, MAX17042_CONFIG, config->config);
|
||||
max17042_override_por(client, MAX17042_SHDNTIMER, config->shdntimer);
|
||||
|
||||
max17042_override_por(client, MAX17042_DesignCap, config->design_cap);
|
||||
max17042_override_por(client, MAX17042_ICHGTerm, config->ichgt_term);
|
||||
|
||||
max17042_override_por(client, MAX17042_AtRate, config->at_rate);
|
||||
max17042_override_por(client, MAX17042_LearnCFG, config->learn_cfg);
|
||||
max17042_override_por(client, MAX17042_FilterCFG, config->filter_cfg);
|
||||
max17042_override_por(client, MAX17042_RelaxCFG, config->relax_cfg);
|
||||
max17042_override_por(client, MAX17042_MiscCFG, config->misc_cfg);
|
||||
max17042_override_por(client, MAX17042_MaskSOC, config->masksoc);
|
||||
|
||||
max17042_override_por(client, MAX17042_FullCAP, config->fullcap);
|
||||
max17042_override_por(client, MAX17042_FullCAPNom, config->fullcapnom);
|
||||
max17042_override_por(client, MAX17042_SOC_empty, config->socempty);
|
||||
max17042_override_por(client, MAX17042_LAvg_empty, config->lavg_empty);
|
||||
max17042_override_por(client, MAX17042_dQacc, config->dqacc);
|
||||
max17042_override_por(client, MAX17042_dPacc, config->dpacc);
|
||||
|
||||
max17042_override_por(client, MAX17042_V_empty, config->vempty);
|
||||
max17042_override_por(client, MAX17042_TempNom, config->temp_nom);
|
||||
max17042_override_por(client, MAX17042_TempLim, config->temp_lim);
|
||||
max17042_override_por(client, MAX17042_FCTC, config->fctc);
|
||||
max17042_override_por(client, MAX17042_RCOMP0, config->rcomp0);
|
||||
max17042_override_por(client, MAX17042_TempCo, config->tcompc0);
|
||||
max17042_override_por(client, MAX17042_EmptyTempCo,
|
||||
config->empty_tempco);
|
||||
max17042_override_por(client, MAX17042_K_empty0, config->kempty0);
|
||||
}
|
||||
|
||||
static int max17042_init_chip(struct max17042_chip *chip)
|
||||
{
|
||||
int ret;
|
||||
int val;
|
||||
|
||||
max17042_override_por_values(chip);
|
||||
/* After Power up, the MAX17042 requires 500mS in order
|
||||
* to perform signal debouncing and initial SOC reporting
|
||||
*/
|
||||
msleep(500);
|
||||
|
||||
/* Initialize configaration */
|
||||
max17042_write_config_regs(chip);
|
||||
|
||||
/* write cell characterization data */
|
||||
ret = max17042_init_model(chip);
|
||||
if (ret) {
|
||||
dev_err(&chip->client->dev, "%s init failed\n",
|
||||
__func__);
|
||||
return -EIO;
|
||||
}
|
||||
max17042_verify_model_lock(chip);
|
||||
if (ret) {
|
||||
dev_err(&chip->client->dev, "%s lock verify failed\n",
|
||||
__func__);
|
||||
return -EIO;
|
||||
}
|
||||
/* write custom parameters */
|
||||
max17042_write_custom_regs(chip);
|
||||
|
||||
/* update capacity params */
|
||||
max17042_update_capacity_regs(chip);
|
||||
|
||||
/* delay must be atleast 350mS to allow VFSOC
|
||||
* to be calculated from the new configuration
|
||||
*/
|
||||
msleep(350);
|
||||
|
||||
/* reset vfsoc0 reg */
|
||||
max17042_reset_vfsoc0_reg(chip);
|
||||
|
||||
/* load new capacity params */
|
||||
max17042_load_new_capacity_params(chip);
|
||||
|
||||
/* Init complete, Clear the POR bit */
|
||||
val = max17042_read_reg(chip->client, MAX17042_STATUS);
|
||||
max17042_write_reg(chip->client, MAX17042_STATUS,
|
||||
val & (~STATUS_POR_BIT));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off)
|
||||
{
|
||||
u16 soc, soc_tr;
|
||||
|
||||
/* program interrupt thesholds such that we should
|
||||
* get interrupt for every 'off' perc change in the soc
|
||||
*/
|
||||
soc = max17042_read_reg(chip->client, MAX17042_RepSOC) >> 8;
|
||||
soc_tr = (soc + off) << 8;
|
||||
soc_tr |= (soc - off);
|
||||
max17042_write_reg(chip->client, MAX17042_SALRT_Th, soc_tr);
|
||||
}
|
||||
|
||||
static irqreturn_t max17042_thread_handler(int id, void *dev)
|
||||
{
|
||||
struct max17042_chip *chip = dev;
|
||||
u16 val;
|
||||
|
||||
val = max17042_read_reg(chip->client, MAX17042_STATUS);
|
||||
if ((val & STATUS_INTR_SOCMIN_BIT) ||
|
||||
(val & STATUS_INTR_SOCMAX_BIT)) {
|
||||
dev_info(&chip->client->dev, "SOC threshold INTR\n");
|
||||
max17042_set_soc_threshold(chip, 1);
|
||||
}
|
||||
|
||||
power_supply_changed(&chip->battery);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void max17042_init_worker(struct work_struct *work)
|
||||
{
|
||||
struct max17042_chip *chip = container_of(work,
|
||||
struct max17042_chip, work);
|
||||
int ret;
|
||||
|
||||
/* Initialize registers according to values from the platform data */
|
||||
if (chip->pdata->enable_por_init && chip->pdata->config_data) {
|
||||
ret = max17042_init_chip(chip);
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
|
||||
chip->init_complete = 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct max17042_platform_data *
|
||||
max17042_get_pdata(struct device *dev)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
u32 prop;
|
||||
struct max17042_platform_data *pdata;
|
||||
|
||||
if (!np)
|
||||
return dev->platform_data;
|
||||
|
||||
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Require current sense resistor value to be specified for
|
||||
* current-sense functionality to be enabled at all.
|
||||
*/
|
||||
if (of_property_read_u32(np, "maxim,rsns-microohm", &prop) == 0) {
|
||||
pdata->r_sns = prop;
|
||||
pdata->enable_current_sense = true;
|
||||
}
|
||||
|
||||
return pdata;
|
||||
}
|
||||
#else
|
||||
static struct max17042_platform_data *
|
||||
max17042_get_pdata(struct device *dev)
|
||||
{
|
||||
return dev->platform_data;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __devinit max17042_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
|
||||
struct max17042_chip *chip;
|
||||
int ret;
|
||||
int reg;
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
|
||||
return -EIO;
|
||||
|
||||
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
|
||||
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->client = client;
|
||||
chip->pdata = client->dev.platform_data;
|
||||
chip->pdata = max17042_get_pdata(&client->dev);
|
||||
if (!chip->pdata) {
|
||||
dev_err(&client->dev, "no platform data provided\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, chip);
|
||||
|
||||
|
@ -243,14 +673,6 @@ static int __devinit max17042_probe(struct i2c_client *client,
|
|||
if (chip->pdata->r_sns == 0)
|
||||
chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;
|
||||
|
||||
ret = power_supply_register(&client->dev, &chip->battery);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "failed: power supply register\n");
|
||||
kfree(chip);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize registers according to values from the platform data */
|
||||
if (chip->pdata->init_data)
|
||||
max17042_set_reg(client, chip->pdata->init_data,
|
||||
chip->pdata->num_init_data);
|
||||
|
@ -261,7 +683,34 @@ static int __devinit max17042_probe(struct i2c_client *client,
|
|||
max17042_write_reg(client, MAX17042_LearnCFG, 0x0007);
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (client->irq) {
|
||||
ret = request_threaded_irq(client->irq, NULL,
|
||||
max17042_thread_handler,
|
||||
IRQF_TRIGGER_FALLING,
|
||||
chip->battery.name, chip);
|
||||
if (!ret) {
|
||||
reg = max17042_read_reg(client, MAX17042_CONFIG);
|
||||
reg |= CONFIG_ALRT_BIT_ENBL;
|
||||
max17042_write_reg(client, MAX17042_CONFIG, reg);
|
||||
max17042_set_soc_threshold(chip, 1);
|
||||
} else
|
||||
dev_err(&client->dev, "%s(): cannot get IRQ\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
reg = max17042_read_reg(chip->client, MAX17042_STATUS);
|
||||
|
||||
if (reg & STATUS_POR_BIT) {
|
||||
INIT_WORK(&chip->work, max17042_init_worker);
|
||||
schedule_work(&chip->work);
|
||||
} else {
|
||||
chip->init_complete = 1;
|
||||
}
|
||||
|
||||
ret = power_supply_register(&client->dev, &chip->battery);
|
||||
if (ret)
|
||||
dev_err(&client->dev, "failed: power supply register\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit max17042_remove(struct i2c_client *client)
|
||||
|
@ -269,10 +718,17 @@ static int __devexit max17042_remove(struct i2c_client *client)
|
|||
struct max17042_chip *chip = i2c_get_clientdata(client);
|
||||
|
||||
power_supply_unregister(&chip->battery);
|
||||
kfree(chip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id max17042_dt_match[] = {
|
||||
{ .compatible = "maxim,max17042" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, max17042_dt_match);
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id max17042_id[] = {
|
||||
{ "max17042", 0 },
|
||||
{ }
|
||||
|
@ -282,23 +738,13 @@ MODULE_DEVICE_TABLE(i2c, max17042_id);
|
|||
static struct i2c_driver max17042_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "max17042",
|
||||
.of_match_table = of_match_ptr(max17042_dt_match),
|
||||
},
|
||||
.probe = max17042_probe,
|
||||
.remove = __devexit_p(max17042_remove),
|
||||
.id_table = max17042_id,
|
||||
};
|
||||
|
||||
static int __init max17042_init(void)
|
||||
{
|
||||
return i2c_add_driver(&max17042_i2c_driver);
|
||||
}
|
||||
module_init(max17042_init);
|
||||
|
||||
static void __exit max17042_exit(void)
|
||||
{
|
||||
i2c_del_driver(&max17042_i2c_driver);
|
||||
}
|
||||
module_exit(max17042_exit);
|
||||
module_i2c_driver(max17042_i2c_driver);
|
||||
|
||||
MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
|
||||
MODULE_DESCRIPTION("MAX17042 Fuel Gauge");
|
||||
|
|
|
@ -852,18 +852,7 @@ static struct i2c_driver sbs_battery_driver = {
|
|||
.of_match_table = sbs_dt_ids,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init sbs_battery_init(void)
|
||||
{
|
||||
return i2c_add_driver(&sbs_battery_driver);
|
||||
}
|
||||
module_init(sbs_battery_init);
|
||||
|
||||
static void __exit sbs_battery_exit(void)
|
||||
{
|
||||
i2c_del_driver(&sbs_battery_driver);
|
||||
}
|
||||
module_exit(sbs_battery_exit);
|
||||
module_i2c_driver(sbs_battery_driver);
|
||||
|
||||
MODULE_DESCRIPTION("SBS battery monitor driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -316,19 +316,7 @@ static struct i2c_driver z2_batt_driver = {
|
|||
.remove = __devexit_p(z2_batt_remove),
|
||||
.id_table = z2_batt_id,
|
||||
};
|
||||
|
||||
static int __init z2_batt_init(void)
|
||||
{
|
||||
return i2c_add_driver(&z2_batt_driver);
|
||||
}
|
||||
|
||||
static void __exit z2_batt_exit(void)
|
||||
{
|
||||
i2c_del_driver(&z2_batt_driver);
|
||||
}
|
||||
|
||||
module_init(z2_batt_init);
|
||||
module_exit(z2_batt_exit);
|
||||
module_i2c_driver(z2_batt_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Peter Edwards <sweetlilmre@gmail.com>");
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
/*
|
||||
* LP8727 Micro/Mini USB IC with integrated charger
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments
|
||||
* Copyright (C) 2011 National Semiconductor
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -32,13 +35,24 @@ enum lp8727_ichg {
|
|||
ICHG_1000mA,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct lp8727_chg_param
|
||||
* @eoc_level : end of charge level setting
|
||||
* @ichg : charging current
|
||||
*/
|
||||
struct lp8727_chg_param {
|
||||
/* end of charge level setting */
|
||||
enum lp8727_eoc_level eoc_level;
|
||||
/* charging current */
|
||||
enum lp8727_ichg ichg;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct lp8727_platform_data
|
||||
* @get_batt_present : check battery status - exists or not
|
||||
* @get_batt_level : get battery voltage (mV)
|
||||
* @get_batt_capacity : get battery capacity (%)
|
||||
* @get_batt_temp : get battery temperature
|
||||
* @ac, @usb : charging parameters each charger type
|
||||
*/
|
||||
struct lp8727_platform_data {
|
||||
u8 (*get_batt_present)(void);
|
||||
u16 (*get_batt_level)(void);
|
||||
|
|
|
@ -146,6 +146,279 @@ struct abx500_init_settings {
|
|||
u8 setting;
|
||||
};
|
||||
|
||||
/* Battery driver related data */
|
||||
/*
|
||||
* ADC for the battery thermistor.
|
||||
* When using the ABx500_ADC_THERM_BATCTRL the battery ID resistor is combined
|
||||
* with a NTC resistor to both identify the battery and to measure its
|
||||
* temperature. Different phone manufactures uses different techniques to both
|
||||
* identify the battery and to read its temperature.
|
||||
*/
|
||||
enum abx500_adc_therm {
|
||||
ABx500_ADC_THERM_BATCTRL,
|
||||
ABx500_ADC_THERM_BATTEMP,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct abx500_res_to_temp - defines one point in a temp to res curve. To
|
||||
* be used in battery packs that combines the identification resistor with a
|
||||
* NTC resistor.
|
||||
* @temp: battery pack temperature in Celcius
|
||||
* @resist: NTC resistor net total resistance
|
||||
*/
|
||||
struct abx500_res_to_temp {
|
||||
int temp;
|
||||
int resist;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct abx500_v_to_cap - Table for translating voltage to capacity
|
||||
* @voltage: Voltage in mV
|
||||
* @capacity: Capacity in percent
|
||||
*/
|
||||
struct abx500_v_to_cap {
|
||||
int voltage;
|
||||
int capacity;
|
||||
};
|
||||
|
||||
/* Forward declaration */
|
||||
struct abx500_fg;
|
||||
|
||||
/**
|
||||
* struct abx500_fg_parameters - Fuel gauge algorithm parameters, in seconds
|
||||
* if not specified
|
||||
* @recovery_sleep_timer: Time between measurements while recovering
|
||||
* @recovery_total_time: Total recovery time
|
||||
* @init_timer: Measurement interval during startup
|
||||
* @init_discard_time: Time we discard voltage measurement at startup
|
||||
* @init_total_time: Total init time during startup
|
||||
* @high_curr_time: Time current has to be high to go to recovery
|
||||
* @accu_charging: FG accumulation time while charging
|
||||
* @accu_high_curr: FG accumulation time in high current mode
|
||||
* @high_curr_threshold: High current threshold, in mA
|
||||
* @lowbat_threshold: Low battery threshold, in mV
|
||||
* @overbat_threshold: Over battery threshold, in mV
|
||||
* @battok_falling_th_sel0 Threshold in mV for battOk signal sel0
|
||||
* Resolution in 50 mV step.
|
||||
* @battok_raising_th_sel1 Threshold in mV for battOk signal sel1
|
||||
* Resolution in 50 mV step.
|
||||
* @user_cap_limit Capacity reported from user must be within this
|
||||
* limit to be considered as sane, in percentage
|
||||
* points.
|
||||
* @maint_thres This is the threshold where we stop reporting
|
||||
* battery full while in maintenance, in per cent
|
||||
*/
|
||||
struct abx500_fg_parameters {
|
||||
int recovery_sleep_timer;
|
||||
int recovery_total_time;
|
||||
int init_timer;
|
||||
int init_discard_time;
|
||||
int init_total_time;
|
||||
int high_curr_time;
|
||||
int accu_charging;
|
||||
int accu_high_curr;
|
||||
int high_curr_threshold;
|
||||
int lowbat_threshold;
|
||||
int overbat_threshold;
|
||||
int battok_falling_th_sel0;
|
||||
int battok_raising_th_sel1;
|
||||
int user_cap_limit;
|
||||
int maint_thres;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct abx500_charger_maximization - struct used by the board config.
|
||||
* @use_maxi: Enable maximization for this battery type
|
||||
* @maxi_chg_curr: Maximum charger current allowed
|
||||
* @maxi_wait_cycles: cycles to wait before setting charger current
|
||||
* @charger_curr_step delta between two charger current settings (mA)
|
||||
*/
|
||||
struct abx500_maxim_parameters {
|
||||
bool ena_maxi;
|
||||
int chg_curr;
|
||||
int wait_cycles;
|
||||
int charger_curr_step;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct abx500_battery_type - different batteries supported
|
||||
* @name: battery technology
|
||||
* @resis_high: battery upper resistance limit
|
||||
* @resis_low: battery lower resistance limit
|
||||
* @charge_full_design: Maximum battery capacity in mAh
|
||||
* @nominal_voltage: Nominal voltage of the battery in mV
|
||||
* @termination_vol: max voltage upto which battery can be charged
|
||||
* @termination_curr battery charging termination current in mA
|
||||
* @recharge_vol battery voltage limit that will trigger a new
|
||||
* full charging cycle in the case where maintenan-
|
||||
* -ce charging has been disabled
|
||||
* @normal_cur_lvl: charger current in normal state in mA
|
||||
* @normal_vol_lvl: charger voltage in normal state in mV
|
||||
* @maint_a_cur_lvl: charger current in maintenance A state in mA
|
||||
* @maint_a_vol_lvl: charger voltage in maintenance A state in mV
|
||||
* @maint_a_chg_timer_h: charge time in maintenance A state
|
||||
* @maint_b_cur_lvl: charger current in maintenance B state in mA
|
||||
* @maint_b_vol_lvl: charger voltage in maintenance B state in mV
|
||||
* @maint_b_chg_timer_h: charge time in maintenance B state
|
||||
* @low_high_cur_lvl: charger current in temp low/high state in mA
|
||||
* @low_high_vol_lvl: charger voltage in temp low/high state in mV'
|
||||
* @battery_resistance: battery inner resistance in mOhm.
|
||||
* @n_r_t_tbl_elements: number of elements in r_to_t_tbl
|
||||
* @r_to_t_tbl: table containing resistance to temp points
|
||||
* @n_v_cap_tbl_elements: number of elements in v_to_cap_tbl
|
||||
* @v_to_cap_tbl: Voltage to capacity (in %) table
|
||||
* @n_batres_tbl_elements number of elements in the batres_tbl
|
||||
* @batres_tbl battery internal resistance vs temperature table
|
||||
*/
|
||||
struct abx500_battery_type {
|
||||
int name;
|
||||
int resis_high;
|
||||
int resis_low;
|
||||
int charge_full_design;
|
||||
int nominal_voltage;
|
||||
int termination_vol;
|
||||
int termination_curr;
|
||||
int recharge_vol;
|
||||
int normal_cur_lvl;
|
||||
int normal_vol_lvl;
|
||||
int maint_a_cur_lvl;
|
||||
int maint_a_vol_lvl;
|
||||
int maint_a_chg_timer_h;
|
||||
int maint_b_cur_lvl;
|
||||
int maint_b_vol_lvl;
|
||||
int maint_b_chg_timer_h;
|
||||
int low_high_cur_lvl;
|
||||
int low_high_vol_lvl;
|
||||
int battery_resistance;
|
||||
int n_temp_tbl_elements;
|
||||
struct abx500_res_to_temp *r_to_t_tbl;
|
||||
int n_v_cap_tbl_elements;
|
||||
struct abx500_v_to_cap *v_to_cap_tbl;
|
||||
int n_batres_tbl_elements;
|
||||
struct batres_vs_temp *batres_tbl;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct abx500_bm_capacity_levels - abx500 capacity level data
|
||||
* @critical: critical capacity level in percent
|
||||
* @low: low capacity level in percent
|
||||
* @normal: normal capacity level in percent
|
||||
* @high: high capacity level in percent
|
||||
* @full: full capacity level in percent
|
||||
*/
|
||||
struct abx500_bm_capacity_levels {
|
||||
int critical;
|
||||
int low;
|
||||
int normal;
|
||||
int high;
|
||||
int full;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct abx500_bm_charger_parameters - Charger specific parameters
|
||||
* @usb_volt_max: maximum allowed USB charger voltage in mV
|
||||
* @usb_curr_max: maximum allowed USB charger current in mA
|
||||
* @ac_volt_max: maximum allowed AC charger voltage in mV
|
||||
* @ac_curr_max: maximum allowed AC charger current in mA
|
||||
*/
|
||||
struct abx500_bm_charger_parameters {
|
||||
int usb_volt_max;
|
||||
int usb_curr_max;
|
||||
int ac_volt_max;
|
||||
int ac_curr_max;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct abx500_bm_data - abx500 battery management data
|
||||
* @temp_under under this temp, charging is stopped
|
||||
* @temp_low between this temp and temp_under charging is reduced
|
||||
* @temp_high between this temp and temp_over charging is reduced
|
||||
* @temp_over over this temp, charging is stopped
|
||||
* @temp_now present battery temperature
|
||||
* @temp_interval_chg temperature measurement interval in s when charging
|
||||
* @temp_interval_nochg temperature measurement interval in s when not charging
|
||||
* @main_safety_tmr_h safety timer for main charger
|
||||
* @usb_safety_tmr_h safety timer for usb charger
|
||||
* @bkup_bat_v voltage which we charge the backup battery with
|
||||
* @bkup_bat_i current which we charge the backup battery with
|
||||
* @no_maintenance indicates that maintenance charging is disabled
|
||||
* @abx500_adc_therm placement of thermistor, batctrl or battemp adc
|
||||
* @chg_unknown_bat flag to enable charging of unknown batteries
|
||||
* @enable_overshoot flag to enable VBAT overshoot control
|
||||
* @auto_trig flag to enable auto adc trigger
|
||||
* @fg_res resistance of FG resistor in 0.1mOhm
|
||||
* @n_btypes number of elements in array bat_type
|
||||
* @batt_id index of the identified battery in array bat_type
|
||||
* @interval_charging charge alg cycle period time when charging (sec)
|
||||
* @interval_not_charging charge alg cycle period time when not charging (sec)
|
||||
* @temp_hysteresis temperature hysteresis
|
||||
* @gnd_lift_resistance Battery ground to phone ground resistance (mOhm)
|
||||
* @maxi: maximization parameters
|
||||
* @cap_levels capacity in percent for the different capacity levels
|
||||
* @bat_type table of supported battery types
|
||||
* @chg_params charger parameters
|
||||
* @fg_params fuel gauge parameters
|
||||
*/
|
||||
struct abx500_bm_data {
|
||||
int temp_under;
|
||||
int temp_low;
|
||||
int temp_high;
|
||||
int temp_over;
|
||||
int temp_now;
|
||||
int temp_interval_chg;
|
||||
int temp_interval_nochg;
|
||||
int main_safety_tmr_h;
|
||||
int usb_safety_tmr_h;
|
||||
int bkup_bat_v;
|
||||
int bkup_bat_i;
|
||||
bool no_maintenance;
|
||||
bool chg_unknown_bat;
|
||||
bool enable_overshoot;
|
||||
bool auto_trig;
|
||||
enum abx500_adc_therm adc_therm;
|
||||
int fg_res;
|
||||
int n_btypes;
|
||||
int batt_id;
|
||||
int interval_charging;
|
||||
int interval_not_charging;
|
||||
int temp_hysteresis;
|
||||
int gnd_lift_resistance;
|
||||
const struct abx500_maxim_parameters *maxi;
|
||||
const struct abx500_bm_capacity_levels *cap_levels;
|
||||
const struct abx500_battery_type *bat_type;
|
||||
const struct abx500_bm_charger_parameters *chg_params;
|
||||
const struct abx500_fg_parameters *fg_params;
|
||||
};
|
||||
|
||||
struct abx500_chargalg_platform_data {
|
||||
char **supplied_to;
|
||||
size_t num_supplicants;
|
||||
};
|
||||
|
||||
struct abx500_charger_platform_data {
|
||||
char **supplied_to;
|
||||
size_t num_supplicants;
|
||||
bool autopower_cfg;
|
||||
};
|
||||
|
||||
struct abx500_btemp_platform_data {
|
||||
char **supplied_to;
|
||||
size_t num_supplicants;
|
||||
};
|
||||
|
||||
struct abx500_fg_platform_data {
|
||||
char **supplied_to;
|
||||
size_t num_supplicants;
|
||||
};
|
||||
|
||||
struct abx500_bm_plat_data {
|
||||
struct abx500_bm_data *battery;
|
||||
struct abx500_charger_platform_data *charger;
|
||||
struct abx500_btemp_platform_data *btemp;
|
||||
struct abx500_fg_platform_data *fg;
|
||||
struct abx500_chargalg_platform_data *chargalg;
|
||||
};
|
||||
|
||||
int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
|
||||
u8 value);
|
||||
int abx500_get_register_interruptible(struct device *dev, u8 bank, u8 reg,
|
||||
|
|
|
@ -0,0 +1,474 @@
|
|||
/*
|
||||
* Copyright ST-Ericsson 2012.
|
||||
*
|
||||
* Author: Arun Murthy <arun.murthy@stericsson.com>
|
||||
* Licensed under GPLv2.
|
||||
*/
|
||||
|
||||
#ifndef _AB8500_BM_H
|
||||
#define _AB8500_BM_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/abx500.h>
|
||||
|
||||
/*
|
||||
* System control 2 register offsets.
|
||||
* bank = 0x02
|
||||
*/
|
||||
#define AB8500_MAIN_WDOG_CTRL_REG 0x01
|
||||
#define AB8500_LOW_BAT_REG 0x03
|
||||
#define AB8500_BATT_OK_REG 0x04
|
||||
/*
|
||||
* USB/ULPI register offsets
|
||||
* Bank : 0x5
|
||||
*/
|
||||
#define AB8500_USB_LINE_STAT_REG 0x80
|
||||
|
||||
/*
|
||||
* Charger / status register offfsets
|
||||
* Bank : 0x0B
|
||||
*/
|
||||
#define AB8500_CH_STATUS1_REG 0x00
|
||||
#define AB8500_CH_STATUS2_REG 0x01
|
||||
#define AB8500_CH_USBCH_STAT1_REG 0x02
|
||||
#define AB8500_CH_USBCH_STAT2_REG 0x03
|
||||
#define AB8500_CH_FSM_STAT_REG 0x04
|
||||
#define AB8500_CH_STAT_REG 0x05
|
||||
|
||||
/*
|
||||
* Charger / control register offfsets
|
||||
* Bank : 0x0B
|
||||
*/
|
||||
#define AB8500_CH_VOLT_LVL_REG 0x40
|
||||
#define AB8500_CH_VOLT_LVL_MAX_REG 0x41 /*Only in Cut2.0*/
|
||||
#define AB8500_CH_OPT_CRNTLVL_REG 0x42
|
||||
#define AB8500_CH_OPT_CRNTLVL_MAX_REG 0x43 /*Only in Cut2.0*/
|
||||
#define AB8500_CH_WD_TIMER_REG 0x50
|
||||
#define AB8500_CHARG_WD_CTRL 0x51
|
||||
#define AB8500_BTEMP_HIGH_TH 0x52
|
||||
#define AB8500_LED_INDICATOR_PWM_CTRL 0x53
|
||||
#define AB8500_LED_INDICATOR_PWM_DUTY 0x54
|
||||
#define AB8500_BATT_OVV 0x55
|
||||
#define AB8500_CHARGER_CTRL 0x56
|
||||
#define AB8500_BAT_CTRL_CURRENT_SOURCE 0x60 /*Only in Cut2.0*/
|
||||
|
||||
/*
|
||||
* Charger / main control register offsets
|
||||
* Bank : 0x0B
|
||||
*/
|
||||
#define AB8500_MCH_CTRL1 0x80
|
||||
#define AB8500_MCH_CTRL2 0x81
|
||||
#define AB8500_MCH_IPT_CURLVL_REG 0x82
|
||||
#define AB8500_CH_WD_REG 0x83
|
||||
|
||||
/*
|
||||
* Charger / USB control register offsets
|
||||
* Bank : 0x0B
|
||||
*/
|
||||
#define AB8500_USBCH_CTRL1_REG 0xC0
|
||||
#define AB8500_USBCH_CTRL2_REG 0xC1
|
||||
#define AB8500_USBCH_IPT_CRNTLVL_REG 0xC2
|
||||
|
||||
/*
|
||||
* Gas Gauge register offsets
|
||||
* Bank : 0x0C
|
||||
*/
|
||||
#define AB8500_GASG_CC_CTRL_REG 0x00
|
||||
#define AB8500_GASG_CC_ACCU1_REG 0x01
|
||||
#define AB8500_GASG_CC_ACCU2_REG 0x02
|
||||
#define AB8500_GASG_CC_ACCU3_REG 0x03
|
||||
#define AB8500_GASG_CC_ACCU4_REG 0x04
|
||||
#define AB8500_GASG_CC_SMPL_CNTRL_REG 0x05
|
||||
#define AB8500_GASG_CC_SMPL_CNTRH_REG 0x06
|
||||
#define AB8500_GASG_CC_SMPL_CNVL_REG 0x07
|
||||
#define AB8500_GASG_CC_SMPL_CNVH_REG 0x08
|
||||
#define AB8500_GASG_CC_CNTR_AVGOFF_REG 0x09
|
||||
#define AB8500_GASG_CC_OFFSET_REG 0x0A
|
||||
#define AB8500_GASG_CC_NCOV_ACCU 0x10
|
||||
#define AB8500_GASG_CC_NCOV_ACCU_CTRL 0x11
|
||||
#define AB8500_GASG_CC_NCOV_ACCU_LOW 0x12
|
||||
#define AB8500_GASG_CC_NCOV_ACCU_MED 0x13
|
||||
#define AB8500_GASG_CC_NCOV_ACCU_HIGH 0x14
|
||||
|
||||
/*
|
||||
* Interrupt register offsets
|
||||
* Bank : 0x0E
|
||||
*/
|
||||
#define AB8500_IT_SOURCE2_REG 0x01
|
||||
#define AB8500_IT_SOURCE21_REG 0x14
|
||||
|
||||
/*
|
||||
* RTC register offsets
|
||||
* Bank: 0x0F
|
||||
*/
|
||||
#define AB8500_RTC_BACKUP_CHG_REG 0x0C
|
||||
#define AB8500_RTC_CC_CONF_REG 0x01
|
||||
#define AB8500_RTC_CTRL_REG 0x0B
|
||||
|
||||
/*
|
||||
* OTP register offsets
|
||||
* Bank : 0x15
|
||||
*/
|
||||
#define AB8500_OTP_CONF_15 0x0E
|
||||
|
||||
/* GPADC constants from AB8500 spec, UM0836 */
|
||||
#define ADC_RESOLUTION 1024
|
||||
#define ADC_CH_MAIN_MIN 0
|
||||
#define ADC_CH_MAIN_MAX 20030
|
||||
#define ADC_CH_VBUS_MIN 0
|
||||
#define ADC_CH_VBUS_MAX 20030
|
||||
#define ADC_CH_VBAT_MIN 2300
|
||||
#define ADC_CH_VBAT_MAX 4800
|
||||
#define ADC_CH_BKBAT_MIN 0
|
||||
#define ADC_CH_BKBAT_MAX 3200
|
||||
|
||||
/* Main charge i/p current */
|
||||
#define MAIN_CH_IP_CUR_0P9A 0x80
|
||||
#define MAIN_CH_IP_CUR_1P0A 0x90
|
||||
#define MAIN_CH_IP_CUR_1P1A 0xA0
|
||||
#define MAIN_CH_IP_CUR_1P2A 0xB0
|
||||
#define MAIN_CH_IP_CUR_1P3A 0xC0
|
||||
#define MAIN_CH_IP_CUR_1P4A 0xD0
|
||||
#define MAIN_CH_IP_CUR_1P5A 0xE0
|
||||
|
||||
/* ChVoltLevel */
|
||||
#define CH_VOL_LVL_3P5 0x00
|
||||
#define CH_VOL_LVL_4P0 0x14
|
||||
#define CH_VOL_LVL_4P05 0x16
|
||||
#define CH_VOL_LVL_4P1 0x1B
|
||||
#define CH_VOL_LVL_4P15 0x20
|
||||
#define CH_VOL_LVL_4P2 0x25
|
||||
#define CH_VOL_LVL_4P6 0x4D
|
||||
|
||||
/* ChOutputCurrentLevel */
|
||||
#define CH_OP_CUR_LVL_0P1 0x00
|
||||
#define CH_OP_CUR_LVL_0P2 0x01
|
||||
#define CH_OP_CUR_LVL_0P3 0x02
|
||||
#define CH_OP_CUR_LVL_0P4 0x03
|
||||
#define CH_OP_CUR_LVL_0P5 0x04
|
||||
#define CH_OP_CUR_LVL_0P6 0x05
|
||||
#define CH_OP_CUR_LVL_0P7 0x06
|
||||
#define CH_OP_CUR_LVL_0P8 0x07
|
||||
#define CH_OP_CUR_LVL_0P9 0x08
|
||||
#define CH_OP_CUR_LVL_1P4 0x0D
|
||||
#define CH_OP_CUR_LVL_1P5 0x0E
|
||||
#define CH_OP_CUR_LVL_1P6 0x0F
|
||||
|
||||
/* BTEMP High thermal limits */
|
||||
#define BTEMP_HIGH_TH_57_0 0x00
|
||||
#define BTEMP_HIGH_TH_52 0x01
|
||||
#define BTEMP_HIGH_TH_57_1 0x02
|
||||
#define BTEMP_HIGH_TH_62 0x03
|
||||
|
||||
/* current is mA */
|
||||
#define USB_0P1A 100
|
||||
#define USB_0P2A 200
|
||||
#define USB_0P3A 300
|
||||
#define USB_0P4A 400
|
||||
#define USB_0P5A 500
|
||||
|
||||
#define LOW_BAT_3P1V 0x20
|
||||
#define LOW_BAT_2P3V 0x00
|
||||
#define LOW_BAT_RESET 0x01
|
||||
#define LOW_BAT_ENABLE 0x01
|
||||
|
||||
/* Backup battery constants */
|
||||
#define BUP_ICH_SEL_50UA 0x00
|
||||
#define BUP_ICH_SEL_150UA 0x04
|
||||
#define BUP_ICH_SEL_300UA 0x08
|
||||
#define BUP_ICH_SEL_700UA 0x0C
|
||||
|
||||
#define BUP_VCH_SEL_2P5V 0x00
|
||||
#define BUP_VCH_SEL_2P6V 0x01
|
||||
#define BUP_VCH_SEL_2P8V 0x02
|
||||
#define BUP_VCH_SEL_3P1V 0x03
|
||||
|
||||
/* Battery OVV constants */
|
||||
#define BATT_OVV_ENA 0x02
|
||||
#define BATT_OVV_TH_3P7 0x00
|
||||
#define BATT_OVV_TH_4P75 0x01
|
||||
|
||||
/* A value to indicate over voltage */
|
||||
#define BATT_OVV_VALUE 4750
|
||||
|
||||
/* VBUS OVV constants */
|
||||
#define VBUS_OVV_SELECT_MASK 0x78
|
||||
#define VBUS_OVV_SELECT_5P6V 0x00
|
||||
#define VBUS_OVV_SELECT_5P7V 0x08
|
||||
#define VBUS_OVV_SELECT_5P8V 0x10
|
||||
#define VBUS_OVV_SELECT_5P9V 0x18
|
||||
#define VBUS_OVV_SELECT_6P0V 0x20
|
||||
#define VBUS_OVV_SELECT_6P1V 0x28
|
||||
#define VBUS_OVV_SELECT_6P2V 0x30
|
||||
#define VBUS_OVV_SELECT_6P3V 0x38
|
||||
|
||||
#define VBUS_AUTO_IN_CURR_LIM_ENA 0x04
|
||||
|
||||
/* Fuel Gauge constants */
|
||||
#define RESET_ACCU 0x02
|
||||
#define READ_REQ 0x01
|
||||
#define CC_DEEP_SLEEP_ENA 0x02
|
||||
#define CC_PWR_UP_ENA 0x01
|
||||
#define CC_SAMPLES_40 0x28
|
||||
#define RD_NCONV_ACCU_REQ 0x01
|
||||
#define CC_CALIB 0x08
|
||||
#define CC_INTAVGOFFSET_ENA 0x10
|
||||
#define CC_MUXOFFSET 0x80
|
||||
#define CC_INT_CAL_N_AVG_MASK 0x60
|
||||
#define CC_INT_CAL_SAMPLES_16 0x40
|
||||
#define CC_INT_CAL_SAMPLES_8 0x20
|
||||
#define CC_INT_CAL_SAMPLES_4 0x00
|
||||
|
||||
/* RTC constants */
|
||||
#define RTC_BUP_CH_ENA 0x10
|
||||
|
||||
/* BatCtrl Current Source Constants */
|
||||
#define BAT_CTRL_7U_ENA 0x01
|
||||
#define BAT_CTRL_20U_ENA 0x02
|
||||
#define BAT_CTRL_CMP_ENA 0x04
|
||||
#define FORCE_BAT_CTRL_CMP_HIGH 0x08
|
||||
#define BAT_CTRL_PULL_UP_ENA 0x10
|
||||
|
||||
/* Battery type */
|
||||
#define BATTERY_UNKNOWN 00
|
||||
|
||||
/**
|
||||
* struct res_to_temp - defines one point in a temp to res curve. To
|
||||
* be used in battery packs that combines the identification resistor with a
|
||||
* NTC resistor.
|
||||
* @temp: battery pack temperature in Celcius
|
||||
* @resist: NTC resistor net total resistance
|
||||
*/
|
||||
struct res_to_temp {
|
||||
int temp;
|
||||
int resist;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct batres_vs_temp - defines one point in a temp vs battery internal
|
||||
* resistance curve.
|
||||
* @temp: battery pack temperature in Celcius
|
||||
* @resist: battery internal reistance in mOhm
|
||||
*/
|
||||
struct batres_vs_temp {
|
||||
int temp;
|
||||
int resist;
|
||||
};
|
||||
|
||||
/* Forward declaration */
|
||||
struct ab8500_fg;
|
||||
|
||||
/**
|
||||
* struct ab8500_fg_parameters - Fuel gauge algorithm parameters, in seconds
|
||||
* if not specified
|
||||
* @recovery_sleep_timer: Time between measurements while recovering
|
||||
* @recovery_total_time: Total recovery time
|
||||
* @init_timer: Measurement interval during startup
|
||||
* @init_discard_time: Time we discard voltage measurement at startup
|
||||
* @init_total_time: Total init time during startup
|
||||
* @high_curr_time: Time current has to be high to go to recovery
|
||||
* @accu_charging: FG accumulation time while charging
|
||||
* @accu_high_curr: FG accumulation time in high current mode
|
||||
* @high_curr_threshold: High current threshold, in mA
|
||||
* @lowbat_threshold: Low battery threshold, in mV
|
||||
* @battok_falling_th_sel0 Threshold in mV for battOk signal sel0
|
||||
* Resolution in 50 mV step.
|
||||
* @battok_raising_th_sel1 Threshold in mV for battOk signal sel1
|
||||
* Resolution in 50 mV step.
|
||||
* @user_cap_limit Capacity reported from user must be within this
|
||||
* limit to be considered as sane, in percentage
|
||||
* points.
|
||||
* @maint_thres This is the threshold where we stop reporting
|
||||
* battery full while in maintenance, in per cent
|
||||
*/
|
||||
struct ab8500_fg_parameters {
|
||||
int recovery_sleep_timer;
|
||||
int recovery_total_time;
|
||||
int init_timer;
|
||||
int init_discard_time;
|
||||
int init_total_time;
|
||||
int high_curr_time;
|
||||
int accu_charging;
|
||||
int accu_high_curr;
|
||||
int high_curr_threshold;
|
||||
int lowbat_threshold;
|
||||
int battok_falling_th_sel0;
|
||||
int battok_raising_th_sel1;
|
||||
int user_cap_limit;
|
||||
int maint_thres;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ab8500_charger_maximization - struct used by the board config.
|
||||
* @use_maxi: Enable maximization for this battery type
|
||||
* @maxi_chg_curr: Maximum charger current allowed
|
||||
* @maxi_wait_cycles: cycles to wait before setting charger current
|
||||
* @charger_curr_step delta between two charger current settings (mA)
|
||||
*/
|
||||
struct ab8500_maxim_parameters {
|
||||
bool ena_maxi;
|
||||
int chg_curr;
|
||||
int wait_cycles;
|
||||
int charger_curr_step;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ab8500_bm_capacity_levels - ab8500 capacity level data
|
||||
* @critical: critical capacity level in percent
|
||||
* @low: low capacity level in percent
|
||||
* @normal: normal capacity level in percent
|
||||
* @high: high capacity level in percent
|
||||
* @full: full capacity level in percent
|
||||
*/
|
||||
struct ab8500_bm_capacity_levels {
|
||||
int critical;
|
||||
int low;
|
||||
int normal;
|
||||
int high;
|
||||
int full;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ab8500_bm_charger_parameters - Charger specific parameters
|
||||
* @usb_volt_max: maximum allowed USB charger voltage in mV
|
||||
* @usb_curr_max: maximum allowed USB charger current in mA
|
||||
* @ac_volt_max: maximum allowed AC charger voltage in mV
|
||||
* @ac_curr_max: maximum allowed AC charger current in mA
|
||||
*/
|
||||
struct ab8500_bm_charger_parameters {
|
||||
int usb_volt_max;
|
||||
int usb_curr_max;
|
||||
int ac_volt_max;
|
||||
int ac_curr_max;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ab8500_bm_data - ab8500 battery management data
|
||||
* @temp_under under this temp, charging is stopped
|
||||
* @temp_low between this temp and temp_under charging is reduced
|
||||
* @temp_high between this temp and temp_over charging is reduced
|
||||
* @temp_over over this temp, charging is stopped
|
||||
* @temp_interval_chg temperature measurement interval in s when charging
|
||||
* @temp_interval_nochg temperature measurement interval in s when not charging
|
||||
* @main_safety_tmr_h safety timer for main charger
|
||||
* @usb_safety_tmr_h safety timer for usb charger
|
||||
* @bkup_bat_v voltage which we charge the backup battery with
|
||||
* @bkup_bat_i current which we charge the backup battery with
|
||||
* @no_maintenance indicates that maintenance charging is disabled
|
||||
* @adc_therm placement of thermistor, batctrl or battemp adc
|
||||
* @chg_unknown_bat flag to enable charging of unknown batteries
|
||||
* @enable_overshoot flag to enable VBAT overshoot control
|
||||
* @fg_res resistance of FG resistor in 0.1mOhm
|
||||
* @n_btypes number of elements in array bat_type
|
||||
* @batt_id index of the identified battery in array bat_type
|
||||
* @interval_charging charge alg cycle period time when charging (sec)
|
||||
* @interval_not_charging charge alg cycle period time when not charging (sec)
|
||||
* @temp_hysteresis temperature hysteresis
|
||||
* @gnd_lift_resistance Battery ground to phone ground resistance (mOhm)
|
||||
* @maxi: maximization parameters
|
||||
* @cap_levels capacity in percent for the different capacity levels
|
||||
* @bat_type table of supported battery types
|
||||
* @chg_params charger parameters
|
||||
* @fg_params fuel gauge parameters
|
||||
*/
|
||||
struct ab8500_bm_data {
|
||||
int temp_under;
|
||||
int temp_low;
|
||||
int temp_high;
|
||||
int temp_over;
|
||||
int temp_interval_chg;
|
||||
int temp_interval_nochg;
|
||||
int main_safety_tmr_h;
|
||||
int usb_safety_tmr_h;
|
||||
int bkup_bat_v;
|
||||
int bkup_bat_i;
|
||||
bool no_maintenance;
|
||||
bool chg_unknown_bat;
|
||||
bool enable_overshoot;
|
||||
enum abx500_adc_therm adc_therm;
|
||||
int fg_res;
|
||||
int n_btypes;
|
||||
int batt_id;
|
||||
int interval_charging;
|
||||
int interval_not_charging;
|
||||
int temp_hysteresis;
|
||||
int gnd_lift_resistance;
|
||||
const struct ab8500_maxim_parameters *maxi;
|
||||
const struct ab8500_bm_capacity_levels *cap_levels;
|
||||
const struct ab8500_bm_charger_parameters *chg_params;
|
||||
const struct ab8500_fg_parameters *fg_params;
|
||||
};
|
||||
|
||||
struct ab8500_charger_platform_data {
|
||||
char **supplied_to;
|
||||
size_t num_supplicants;
|
||||
bool autopower_cfg;
|
||||
};
|
||||
|
||||
struct ab8500_btemp_platform_data {
|
||||
char **supplied_to;
|
||||
size_t num_supplicants;
|
||||
};
|
||||
|
||||
struct ab8500_fg_platform_data {
|
||||
char **supplied_to;
|
||||
size_t num_supplicants;
|
||||
};
|
||||
|
||||
struct ab8500_chargalg_platform_data {
|
||||
char **supplied_to;
|
||||
size_t num_supplicants;
|
||||
};
|
||||
struct ab8500_btemp;
|
||||
struct ab8500_gpadc;
|
||||
struct ab8500_fg;
|
||||
#ifdef CONFIG_AB8500_BM
|
||||
void ab8500_fg_reinit(void);
|
||||
void ab8500_charger_usb_state_changed(u8 bm_usb_state, u16 mA);
|
||||
struct ab8500_btemp *ab8500_btemp_get(void);
|
||||
int ab8500_btemp_get_batctrl_temp(struct ab8500_btemp *btemp);
|
||||
struct ab8500_fg *ab8500_fg_get(void);
|
||||
int ab8500_fg_inst_curr_blocking(struct ab8500_fg *dev);
|
||||
int ab8500_fg_inst_curr_start(struct ab8500_fg *di);
|
||||
int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res);
|
||||
int ab8500_fg_inst_curr_done(struct ab8500_fg *di);
|
||||
|
||||
#else
|
||||
int ab8500_fg_inst_curr_done(struct ab8500_fg *di)
|
||||
{
|
||||
}
|
||||
static void ab8500_fg_reinit(void)
|
||||
{
|
||||
}
|
||||
static void ab8500_charger_usb_state_changed(u8 bm_usb_state, u16 mA)
|
||||
{
|
||||
}
|
||||
static struct ab8500_btemp *ab8500_btemp_get(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static int ab8500_btemp_get_batctrl_temp(struct ab8500_btemp *btemp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
struct ab8500_fg *ab8500_fg_get(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static int ab8500_fg_inst_curr_blocking(struct ab8500_fg *dev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int ab8500_fg_inst_curr_start(struct ab8500_fg *di)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* _AB8500_BM_H */
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (C) ST-Ericsson SA 2012
|
||||
* Author: Johan Gardsmark <johan.gardsmark@stericsson.com> for ST-Ericsson.
|
||||
* License terms: GNU General Public License (GPL), version 2
|
||||
*/
|
||||
|
||||
#ifndef _UX500_CHARGALG_H
|
||||
#define _UX500_CHARGALG_H
|
||||
|
||||
#include <linux/power_supply.h>
|
||||
|
||||
#define psy_to_ux500_charger(x) container_of((x), \
|
||||
struct ux500_charger, psy)
|
||||
|
||||
/* Forward declaration */
|
||||
struct ux500_charger;
|
||||
|
||||
struct ux500_charger_ops {
|
||||
int (*enable) (struct ux500_charger *, int, int, int);
|
||||
int (*kick_wd) (struct ux500_charger *);
|
||||
int (*update_curr) (struct ux500_charger *, int);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ux500_charger - power supply ux500 charger sub class
|
||||
* @psy power supply base class
|
||||
* @ops ux500 charger operations
|
||||
* @max_out_volt maximum output charger voltage in mV
|
||||
* @max_out_curr maximum output charger current in mA
|
||||
*/
|
||||
struct ux500_charger {
|
||||
struct power_supply psy;
|
||||
struct ux500_charger_ops ops;
|
||||
int max_out_volt;
|
||||
int max_out_curr;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -27,6 +27,8 @@
|
|||
#define MAX17042_BATTERY_FULL (100)
|
||||
#define MAX17042_DEFAULT_SNS_RESISTOR (10000)
|
||||
|
||||
#define MAX17042_CHARACTERIZATION_DATA_SIZE 48
|
||||
|
||||
enum max17042_register {
|
||||
MAX17042_STATUS = 0x00,
|
||||
MAX17042_VALRT_Th = 0x01,
|
||||
|
@ -40,11 +42,11 @@ enum max17042_register {
|
|||
MAX17042_VCELL = 0x09,
|
||||
MAX17042_Current = 0x0A,
|
||||
MAX17042_AvgCurrent = 0x0B,
|
||||
MAX17042_Qresidual = 0x0C,
|
||||
|
||||
MAX17042_SOC = 0x0D,
|
||||
MAX17042_AvSOC = 0x0E,
|
||||
MAX17042_RemCap = 0x0F,
|
||||
MAX17402_FullCAP = 0x10,
|
||||
MAX17042_FullCAP = 0x10,
|
||||
MAX17042_TTE = 0x11,
|
||||
MAX17042_V_empty = 0x12,
|
||||
|
||||
|
@ -62,14 +64,14 @@ enum max17042_register {
|
|||
MAX17042_AvCap = 0x1F,
|
||||
MAX17042_ManName = 0x20,
|
||||
MAX17042_DevName = 0x21,
|
||||
MAX17042_DevChem = 0x22,
|
||||
|
||||
MAX17042_FullCAPNom = 0x23,
|
||||
MAX17042_TempNom = 0x24,
|
||||
MAX17042_TempCold = 0x25,
|
||||
MAX17042_TempLim = 0x25,
|
||||
MAX17042_TempHot = 0x26,
|
||||
MAX17042_AIN = 0x27,
|
||||
MAX17042_LearnCFG = 0x28,
|
||||
MAX17042_SHFTCFG = 0x29,
|
||||
MAX17042_FilterCFG = 0x29,
|
||||
MAX17042_RelaxCFG = 0x2A,
|
||||
MAX17042_MiscCFG = 0x2B,
|
||||
MAX17042_TGAIN = 0x2C,
|
||||
|
@ -77,22 +79,41 @@ enum max17042_register {
|
|||
MAX17042_CGAIN = 0x2E,
|
||||
MAX17042_COFF = 0x2F,
|
||||
|
||||
MAX17042_Q_empty = 0x33,
|
||||
MAX17042_MaskSOC = 0x32,
|
||||
MAX17042_SOC_empty = 0x33,
|
||||
MAX17042_T_empty = 0x34,
|
||||
|
||||
MAX17042_FullCAP0 = 0x35,
|
||||
MAX17042_LAvg_empty = 0x36,
|
||||
MAX17042_FCTC = 0x37,
|
||||
MAX17042_RCOMP0 = 0x38,
|
||||
MAX17042_TempCo = 0x39,
|
||||
MAX17042_Rx = 0x3A,
|
||||
MAX17042_T_empty0 = 0x3B,
|
||||
MAX17042_EmptyTempCo = 0x3A,
|
||||
MAX17042_K_empty0 = 0x3B,
|
||||
MAX17042_TaskPeriod = 0x3C,
|
||||
MAX17042_FSTAT = 0x3D,
|
||||
|
||||
MAX17042_SHDNTIMER = 0x3F,
|
||||
|
||||
MAX17042_VFRemCap = 0x4A,
|
||||
MAX17042_dQacc = 0x45,
|
||||
MAX17042_dPacc = 0x46,
|
||||
|
||||
MAX17042_VFSOC0 = 0x48,
|
||||
|
||||
MAX17042_QH = 0x4D,
|
||||
MAX17042_QL = 0x4E,
|
||||
|
||||
MAX17042_VFSOC0Enable = 0x60,
|
||||
MAX17042_MLOCKReg1 = 0x62,
|
||||
MAX17042_MLOCKReg2 = 0x63,
|
||||
|
||||
MAX17042_MODELChrTbl = 0x80,
|
||||
|
||||
MAX17042_OCV = 0xEE,
|
||||
|
||||
MAX17042_OCVInternal = 0xFB,
|
||||
|
||||
MAX17042_VFSOC = 0xFF,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -105,10 +126,64 @@ struct max17042_reg_data {
|
|||
u16 data;
|
||||
};
|
||||
|
||||
struct max17042_config_data {
|
||||
/* External current sense resistor value in milli-ohms */
|
||||
u32 cur_sense_val;
|
||||
|
||||
/* A/D measurement */
|
||||
u16 tgain; /* 0x2C */
|
||||
u16 toff; /* 0x2D */
|
||||
u16 cgain; /* 0x2E */
|
||||
u16 coff; /* 0x2F */
|
||||
|
||||
/* Alert / Status */
|
||||
u16 valrt_thresh; /* 0x01 */
|
||||
u16 talrt_thresh; /* 0x02 */
|
||||
u16 soc_alrt_thresh; /* 0x03 */
|
||||
u16 config; /* 0x01D */
|
||||
u16 shdntimer; /* 0x03F */
|
||||
|
||||
/* App data */
|
||||
u16 design_cap; /* 0x18 */
|
||||
u16 ichgt_term; /* 0x1E */
|
||||
|
||||
/* MG3 config */
|
||||
u16 at_rate; /* 0x04 */
|
||||
u16 learn_cfg; /* 0x28 */
|
||||
u16 filter_cfg; /* 0x29 */
|
||||
u16 relax_cfg; /* 0x2A */
|
||||
u16 misc_cfg; /* 0x2B */
|
||||
u16 masksoc; /* 0x32 */
|
||||
|
||||
/* MG3 save and restore */
|
||||
u16 fullcap; /* 0x10 */
|
||||
u16 fullcapnom; /* 0x23 */
|
||||
u16 socempty; /* 0x33 */
|
||||
u16 lavg_empty; /* 0x36 */
|
||||
u16 dqacc; /* 0x45 */
|
||||
u16 dpacc; /* 0x46 */
|
||||
|
||||
/* Cell technology from power_supply.h */
|
||||
u16 cell_technology;
|
||||
|
||||
/* Cell Data */
|
||||
u16 vempty; /* 0x12 */
|
||||
u16 temp_nom; /* 0x24 */
|
||||
u16 temp_lim; /* 0x25 */
|
||||
u16 fctc; /* 0x37 */
|
||||
u16 rcomp0; /* 0x38 */
|
||||
u16 tcompc0; /* 0x39 */
|
||||
u16 empty_tempco; /* 0x3A */
|
||||
u16 kempty0; /* 0x3B */
|
||||
u16 cell_char_tbl[MAX17042_CHARACTERIZATION_DATA_SIZE];
|
||||
} __packed;
|
||||
|
||||
struct max17042_platform_data {
|
||||
struct max17042_reg_data *init_data;
|
||||
struct max17042_config_data *config_data;
|
||||
int num_init_data; /* Number of enties in init_data array */
|
||||
bool enable_current_sense;
|
||||
bool enable_por_init; /* Use POR init from Maxim appnote */
|
||||
|
||||
/*
|
||||
* R_sns in micro-ohms.
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Summit Microelectronics SMB347 Battery Charger Driver
|
||||
*
|
||||
* Copyright (C) 2011, Intel Corporation
|
||||
*
|
||||
* Authors: Bruce E. Robertson <bruce.e.robertson@intel.com>
|
||||
* Mika Westerberg <mika.westerberg@linux.intel.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef SMB347_CHARGER_H
|
||||
#define SMB347_CHARGER_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/power_supply.h>
|
||||
|
||||
enum {
|
||||
/* use the default compensation method */
|
||||
SMB347_SOFT_TEMP_COMPENSATE_DEFAULT = -1,
|
||||
|
||||
SMB347_SOFT_TEMP_COMPENSATE_NONE,
|
||||
SMB347_SOFT_TEMP_COMPENSATE_CURRENT,
|
||||
SMB347_SOFT_TEMP_COMPENSATE_VOLTAGE,
|
||||
};
|
||||
|
||||
/* Use default factory programmed value for hard/soft temperature limit */
|
||||
#define SMB347_TEMP_USE_DEFAULT -273
|
||||
|
||||
/*
|
||||
* Charging enable can be controlled by software (via i2c) by
|
||||
* smb347-charger driver or by EN pin (active low/high).
|
||||
*/
|
||||
enum smb347_chg_enable {
|
||||
SMB347_CHG_ENABLE_SW,
|
||||
SMB347_CHG_ENABLE_PIN_ACTIVE_LOW,
|
||||
SMB347_CHG_ENABLE_PIN_ACTIVE_HIGH,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct smb347_charger_platform_data - platform data for SMB347 charger
|
||||
* @battery_info: Information about the battery
|
||||
* @max_charge_current: maximum current (in uA) the battery can be charged
|
||||
* @max_charge_voltage: maximum voltage (in uV) the battery can be charged
|
||||
* @pre_charge_current: current (in uA) to use in pre-charging phase
|
||||
* @termination_current: current (in uA) used to determine when the
|
||||
* charging cycle terminates
|
||||
* @pre_to_fast_voltage: voltage (in uV) treshold used for transitioning to
|
||||
* pre-charge to fast charge mode
|
||||
* @mains_current_limit: maximum input current drawn from AC/DC input (in uA)
|
||||
* @usb_hc_current_limit: maximum input high current (in uA) drawn from USB
|
||||
* input
|
||||
* @chip_temp_threshold: die temperature where device starts limiting charge
|
||||
* current [%100 - %130] (in degree C)
|
||||
* @soft_cold_temp_limit: soft cold temperature limit [%0 - %15] (in degree C),
|
||||
* granularity is 5 deg C.
|
||||
* @soft_hot_temp_limit: soft hot temperature limit [%40 - %55] (in degree C),
|
||||
* granularity is 5 deg C.
|
||||
* @hard_cold_temp_limit: hard cold temperature limit [%-5 - %10] (in degree C),
|
||||
* granularity is 5 deg C.
|
||||
* @hard_hot_temp_limit: hard hot temperature limit [%50 - %65] (in degree C),
|
||||
* granularity is 5 deg C.
|
||||
* @suspend_on_hard_temp_limit: suspend charging when hard limit is hit
|
||||
* @soft_temp_limit_compensation: compensation method when soft temperature
|
||||
* limit is hit
|
||||
* @charge_current_compensation: current (in uA) for charging compensation
|
||||
* current when temperature hits soft limits
|
||||
* @use_mains: AC/DC input can be used
|
||||
* @use_usb: USB input can be used
|
||||
* @use_usb_otg: USB OTG output can be used (not implemented yet)
|
||||
* @irq_gpio: GPIO number used for interrupts (%-1 if not used)
|
||||
* @enable_control: how charging enable/disable is controlled
|
||||
* (driver/pin controls)
|
||||
*
|
||||
* @use_main, @use_usb, and @use_usb_otg are means to enable/disable
|
||||
* hardware support for these. This is useful when we want to have for
|
||||
* example OTG charging controlled via OTG transceiver driver and not by
|
||||
* the SMB347 hardware.
|
||||
*
|
||||
* Hard and soft temperature limit values are given as described in the
|
||||
* device data sheet and assuming NTC beta value is %3750. Even if this is
|
||||
* not the case, these values should be used. They can be mapped to the
|
||||
* corresponding NTC beta values with the help of table %2 in the data
|
||||
* sheet. So for example if NTC beta is %3375 and we want to program hard
|
||||
* hot limit to be %53 deg C, @hard_hot_temp_limit should be set to %50.
|
||||
*
|
||||
* If zero value is given in any of the current and voltage values, the
|
||||
* factory programmed default will be used. For soft/hard temperature
|
||||
* values, pass in %SMB347_TEMP_USE_DEFAULT instead.
|
||||
*/
|
||||
struct smb347_charger_platform_data {
|
||||
struct power_supply_info battery_info;
|
||||
unsigned int max_charge_current;
|
||||
unsigned int max_charge_voltage;
|
||||
unsigned int pre_charge_current;
|
||||
unsigned int termination_current;
|
||||
unsigned int pre_to_fast_voltage;
|
||||
unsigned int mains_current_limit;
|
||||
unsigned int usb_hc_current_limit;
|
||||
unsigned int chip_temp_threshold;
|
||||
int soft_cold_temp_limit;
|
||||
int soft_hot_temp_limit;
|
||||
int hard_cold_temp_limit;
|
||||
int hard_hot_temp_limit;
|
||||
bool suspend_on_hard_temp_limit;
|
||||
unsigned int soft_temp_limit_compensation;
|
||||
unsigned int charge_current_compensation;
|
||||
bool use_mains;
|
||||
bool use_usb;
|
||||
bool use_usb_otg;
|
||||
int irq_gpio;
|
||||
enum smb347_chg_enable enable_control;
|
||||
};
|
||||
|
||||
#endif /* SMB347_CHARGER_H */
|
Загрузка…
Ссылка в новой задаче