You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
Merge tag 'for-v3.5' of git://git.infradead.org/battery-2.6
Pull battery updates from Anton Vorontsov: "A bunch of fixes for v3.5, nothing extraordinary." * tag 'for-v3.5' of git://git.infradead.org/battery-2.6: (27 commits) smb347-charger: Include missing <linux/err.h> smb347-charger: Clean up battery attributes max17042_battery: Add support for max17047/50 chip sbs-battery.c: Capacity attr = remaining relative capacity isp1704_charger: Use after free on probe error ds2781_battery: Use DS2781_PARAM_EEPROM_SIZE and DS2781_USER_EEPROM_SIZE power_supply: Fix a typo in BATTERY_DS2781 Kconfig entry charger-manager: Provide cm_notify_event function for in-kernel use charger-manager: Poll battery health in normal state smb347-charger: Convert to regmap API smb347-charger: Move IRQ enabling to the end of probe smb347-charger: Rename few functions to match better what they are doing smb347-charger: Convert to use module_i2c_driver() smb347_charger: Cleanup power supply registration code in probe ab8500: Clean up probe routines ab8500_fg: Harden platform data check ab8500_btemp: Harden platform data check ab8500_charger: Harden platform data check MAINTAINERS: Fix 'F' entry for the power supply class max17042_battery: Handle irq request failure case ...
This commit is contained in:
@@ -44,6 +44,16 @@ Charger Manager supports the following:
|
||||
Normally, the platform will need to resume and suspend some devices
|
||||
that are used by Charger Manager.
|
||||
|
||||
* Support for premature full-battery event handling
|
||||
If the battery voltage drops by "fullbatt_vchkdrop_uV" after
|
||||
"fullbatt_vchkdrop_ms" from the full-battery event, the framework
|
||||
restarts charging. This check is also performed while suspended by
|
||||
setting wakeup time accordingly and using suspend_again.
|
||||
|
||||
* Support for uevent-notify
|
||||
With the charger-related events, the device sends
|
||||
notification to users with UEVENT.
|
||||
|
||||
2. Global Charger-Manager Data related with suspend_again
|
||||
========================================================
|
||||
In order to setup Charger Manager with suspend-again feature
|
||||
@@ -55,7 +65,7 @@ if there are multiple batteries. If there are multiple batteries, the
|
||||
multiple instances of Charger Manager share the same charger_global_desc
|
||||
and it will manage in-suspend monitoring for all instances of Charger Manager.
|
||||
|
||||
The user needs to provide all the two entries properly in order to activate
|
||||
The user needs to provide all the three entries properly in order to activate
|
||||
in-suspend monitoring:
|
||||
|
||||
struct charger_global_desc {
|
||||
@@ -74,6 +84,11 @@ bool (*rtc_only_wakeup)(void);
|
||||
same struct. If there is any other wakeup source triggered the
|
||||
wakeup, it should return false. If the "rtc" is the only wakeup
|
||||
reason, it should return true.
|
||||
|
||||
bool assume_timer_stops_in_suspend;
|
||||
: if true, Charger Manager assumes that
|
||||
the timer (CM uses jiffies as timer) stops during suspend. Then, CM
|
||||
assumes that the suspend-duration is same as the alarm length.
|
||||
};
|
||||
|
||||
3. How to setup suspend_again
|
||||
@@ -111,6 +126,16 @@ enum polling_modes polling_mode;
|
||||
CM_POLL_CHARGING_ONLY: poll this battery if and only if the
|
||||
battery is being charged.
|
||||
|
||||
unsigned int fullbatt_vchkdrop_ms;
|
||||
unsigned int fullbatt_vchkdrop_uV;
|
||||
: If both have non-zero values, Charger Manager will check the
|
||||
battery voltage drop fullbatt_vchkdrop_ms after the battery is fully
|
||||
charged. If the voltage drop is over fullbatt_vchkdrop_uV, Charger
|
||||
Manager will try to recharge the battery by disabling and enabling
|
||||
chargers. Recharge with voltage drop condition only (without delay
|
||||
condition) is needed to be implemented with hardware interrupts from
|
||||
fuel gauges or charger devices/chips.
|
||||
|
||||
unsigned int fullbatt_uV;
|
||||
: If specified with a non-zero value, Charger Manager assumes
|
||||
that the battery is full (capacity = 100) if the battery is not being
|
||||
@@ -122,6 +147,8 @@ unsigned int polling_interval_ms;
|
||||
this battery every polling_interval_ms or more frequently.
|
||||
|
||||
enum data_source battery_present;
|
||||
: CM_BATTERY_PRESENT: assume that the battery exists.
|
||||
CM_NO_BATTERY: assume that the battery does not exists.
|
||||
CM_FUEL_GAUGE: get battery presence information from fuel gauge.
|
||||
CM_CHARGER_STAT: get battery presence from chargers.
|
||||
|
||||
@@ -151,7 +178,17 @@ bool measure_battery_temp;
|
||||
the value of measure_battery_temp.
|
||||
};
|
||||
|
||||
5. Other Considerations
|
||||
5. Notify Charger-Manager of charger events: cm_notify_event()
|
||||
=========================================================
|
||||
If there is an charger event is required to notify
|
||||
Charger Manager, a charger device driver that triggers the event can call
|
||||
cm_notify_event(psy, type, msg) to notify the corresponding Charger Manager.
|
||||
In the function, psy is the charger driver's power_supply pointer, which is
|
||||
associated with Charger-Manager. The parameter "type"
|
||||
is the same as irq's type (enum cm_event_types). The event message "msg" is
|
||||
optional and is effective only if the event type is "UNDESCRIBED" or "OTHERS".
|
||||
|
||||
6. Other Considerations
|
||||
=======================
|
||||
|
||||
At the charger/battery-related events such as battery-pulled-out,
|
||||
|
||||
@@ -84,6 +84,8 @@ are already charged or discharging, 'n/a' can be displayed (or
|
||||
HEALTH - represents health of the battery, values corresponds to
|
||||
POWER_SUPPLY_HEALTH_*, defined in battery.h.
|
||||
|
||||
VOLTAGE_OCV - open circuit voltage of the battery.
|
||||
|
||||
VOLTAGE_MAX_DESIGN, VOLTAGE_MIN_DESIGN - design values for maximal and
|
||||
minimal power supply voltages. Maximal/minimal means values of voltages
|
||||
when battery considered "full"/"empty" at normal conditions. Yes, there is
|
||||
|
||||
@@ -5337,7 +5337,7 @@ M: David Woodhouse <dwmw2@infradead.org>
|
||||
T: git git://git.infradead.org/battery-2.6.git
|
||||
S: Maintained
|
||||
F: include/linux/power_supply.h
|
||||
F: drivers/power/power_supply*
|
||||
F: drivers/power/
|
||||
|
||||
PNP SUPPORT
|
||||
M: Adam Belay <abelay@mit.edu>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
menuconfig POWER_SUPPLY
|
||||
tristate "Power supply class support"
|
||||
bool "Power supply class support"
|
||||
help
|
||||
Say Y here to enable power supply class support. This allows
|
||||
power supply (batteries, AC, USB) monitoring by userspace
|
||||
@@ -77,7 +77,7 @@ config BATTERY_DS2780
|
||||
Say Y here to enable support for batteries with ds2780 chip.
|
||||
|
||||
config BATTERY_DS2781
|
||||
tristate "2781 battery driver"
|
||||
tristate "DS2781 battery driver"
|
||||
depends on HAS_IOMEM
|
||||
select W1
|
||||
select W1_SLAVE_DS2781
|
||||
@@ -181,14 +181,15 @@ config BATTERY_MAX17040
|
||||
to operate with a single lithium cell
|
||||
|
||||
config BATTERY_MAX17042
|
||||
tristate "Maxim MAX17042/8997/8966 Fuel Gauge"
|
||||
tristate "Maxim MAX17042/17047/17050/8997/8966 Fuel Gauge"
|
||||
depends on I2C
|
||||
help
|
||||
MAX17042 is fuel-gauge systems for lithium-ion (Li+) batteries
|
||||
in handheld and portable equipment. The MAX17042 is configured
|
||||
to operate with a single lithium cell. MAX8997 and MAX8966 are
|
||||
multi-function devices that include fuel gauages that are compatible
|
||||
with MAX17042.
|
||||
with MAX17042. This driver also supports max17047/50 chips which are
|
||||
improved version of max17042.
|
||||
|
||||
config BATTERY_Z2
|
||||
tristate "Z2 battery driver"
|
||||
@@ -291,6 +292,7 @@ config CHARGER_MAX8998
|
||||
config CHARGER_SMB347
|
||||
tristate "Summit Microelectronics SMB347 Battery Charger"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
help
|
||||
Say Y to include support for Summit Microelectronics SMB347
|
||||
Battery Charger.
|
||||
|
||||
@@ -964,10 +964,15 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
|
||||
{
|
||||
int irq, i, ret = 0;
|
||||
u8 val;
|
||||
struct abx500_bm_plat_data *plat_data;
|
||||
struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
|
||||
struct ab8500_btemp *di;
|
||||
|
||||
struct ab8500_btemp *di =
|
||||
kzalloc(sizeof(struct ab8500_btemp), GFP_KERNEL);
|
||||
if (!plat_data) {
|
||||
dev_err(&pdev->dev, "No platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
di = kzalloc(sizeof(*di), GFP_KERNEL);
|
||||
if (!di)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -977,7 +982,6 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
|
||||
di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
|
||||
|
||||
/* get btemp specific platform data */
|
||||
plat_data = pdev->dev.platform_data;
|
||||
di->pdata = plat_data->btemp;
|
||||
if (!di->pdata) {
|
||||
dev_err(di->dev, "no btemp platform data supplied\n");
|
||||
|
||||
@@ -2534,10 +2534,15 @@ static int __devexit ab8500_charger_remove(struct platform_device *pdev)
|
||||
static int __devinit ab8500_charger_probe(struct platform_device *pdev)
|
||||
{
|
||||
int irq, i, charger_status, ret = 0;
|
||||
struct abx500_bm_plat_data *plat_data;
|
||||
struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
|
||||
struct ab8500_charger *di;
|
||||
|
||||
struct ab8500_charger *di =
|
||||
kzalloc(sizeof(struct ab8500_charger), GFP_KERNEL);
|
||||
if (!plat_data) {
|
||||
dev_err(&pdev->dev, "No platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
di = kzalloc(sizeof(*di), GFP_KERNEL);
|
||||
if (!di)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -2550,9 +2555,7 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev)
|
||||
spin_lock_init(&di->usb_state.usb_lock);
|
||||
|
||||
/* get charger specific platform data */
|
||||
plat_data = pdev->dev.platform_data;
|
||||
di->pdata = plat_data->charger;
|
||||
|
||||
if (!di->pdata) {
|
||||
dev_err(di->dev, "no charger platform data supplied\n");
|
||||
ret = -EINVAL;
|
||||
|
||||
@@ -2446,10 +2446,15 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev)
|
||||
{
|
||||
int i, irq;
|
||||
int ret = 0;
|
||||
struct abx500_bm_plat_data *plat_data;
|
||||
struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
|
||||
struct ab8500_fg *di;
|
||||
|
||||
struct ab8500_fg *di =
|
||||
kzalloc(sizeof(struct ab8500_fg), GFP_KERNEL);
|
||||
if (!plat_data) {
|
||||
dev_err(&pdev->dev, "No platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
di = kzalloc(sizeof(*di), GFP_KERNEL);
|
||||
if (!di)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -2461,7 +2466,6 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev)
|
||||
di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
|
||||
|
||||
/* get fg specific platform data */
|
||||
plat_data = pdev->dev.platform_data;
|
||||
di->pdata = plat_data->fg;
|
||||
if (!di->pdata) {
|
||||
dev_err(di->dev, "no fg platform data supplied\n");
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -643,9 +643,7 @@ static ssize_t ds2781_read_param_eeprom_bin(struct file *filp,
|
||||
struct power_supply *psy = to_power_supply(dev);
|
||||
struct ds2781_device_info *dev_info = to_ds2781_device_info(psy);
|
||||
|
||||
count = min_t(loff_t, count,
|
||||
DS2781_EEPROM_BLOCK1_END -
|
||||
DS2781_EEPROM_BLOCK1_START + 1 - off);
|
||||
count = min_t(loff_t, count, DS2781_PARAM_EEPROM_SIZE - off);
|
||||
|
||||
return ds2781_read_block(dev_info, buf,
|
||||
DS2781_EEPROM_BLOCK1_START + off, count);
|
||||
@@ -661,9 +659,7 @@ static ssize_t ds2781_write_param_eeprom_bin(struct file *filp,
|
||||
struct ds2781_device_info *dev_info = to_ds2781_device_info(psy);
|
||||
int ret;
|
||||
|
||||
count = min_t(loff_t, count,
|
||||
DS2781_EEPROM_BLOCK1_END -
|
||||
DS2781_EEPROM_BLOCK1_START + 1 - off);
|
||||
count = min_t(loff_t, count, DS2781_PARAM_EEPROM_SIZE - off);
|
||||
|
||||
ret = ds2781_write(dev_info, buf,
|
||||
DS2781_EEPROM_BLOCK1_START + off, count);
|
||||
@@ -682,7 +678,7 @@ static struct bin_attribute ds2781_param_eeprom_bin_attr = {
|
||||
.name = "param_eeprom",
|
||||
.mode = S_IRUGO | S_IWUSR,
|
||||
},
|
||||
.size = DS2781_EEPROM_BLOCK1_END - DS2781_EEPROM_BLOCK1_START + 1,
|
||||
.size = DS2781_PARAM_EEPROM_SIZE,
|
||||
.read = ds2781_read_param_eeprom_bin,
|
||||
.write = ds2781_write_param_eeprom_bin,
|
||||
};
|
||||
@@ -696,9 +692,7 @@ static ssize_t ds2781_read_user_eeprom_bin(struct file *filp,
|
||||
struct power_supply *psy = to_power_supply(dev);
|
||||
struct ds2781_device_info *dev_info = to_ds2781_device_info(psy);
|
||||
|
||||
count = min_t(loff_t, count,
|
||||
DS2781_EEPROM_BLOCK0_END -
|
||||
DS2781_EEPROM_BLOCK0_START + 1 - off);
|
||||
count = min_t(loff_t, count, DS2781_USER_EEPROM_SIZE - off);
|
||||
|
||||
return ds2781_read_block(dev_info, buf,
|
||||
DS2781_EEPROM_BLOCK0_START + off, count);
|
||||
@@ -715,9 +709,7 @@ static ssize_t ds2781_write_user_eeprom_bin(struct file *filp,
|
||||
struct ds2781_device_info *dev_info = to_ds2781_device_info(psy);
|
||||
int ret;
|
||||
|
||||
count = min_t(loff_t, count,
|
||||
DS2781_EEPROM_BLOCK0_END -
|
||||
DS2781_EEPROM_BLOCK0_START + 1 - off);
|
||||
count = min_t(loff_t, count, DS2781_USER_EEPROM_SIZE - off);
|
||||
|
||||
ret = ds2781_write(dev_info, buf,
|
||||
DS2781_EEPROM_BLOCK0_START + off, count);
|
||||
@@ -736,7 +728,7 @@ static struct bin_attribute ds2781_user_eeprom_bin_attr = {
|
||||
.name = "user_eeprom",
|
||||
.mode = S_IRUGO | S_IWUSR,
|
||||
},
|
||||
.size = DS2781_EEPROM_BLOCK0_END - DS2781_EEPROM_BLOCK0_START + 1,
|
||||
.size = DS2781_USER_EEPROM_SIZE,
|
||||
.read = ds2781_read_user_eeprom_bin,
|
||||
.write = ds2781_write_user_eeprom_bin,
|
||||
};
|
||||
|
||||
@@ -474,13 +474,13 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev)
|
||||
fail2:
|
||||
power_supply_unregister(&isp->psy);
|
||||
fail1:
|
||||
isp1704_charger_set_power(isp, 0);
|
||||
usb_put_transceiver(isp->phy);
|
||||
fail0:
|
||||
kfree(isp);
|
||||
|
||||
dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret);
|
||||
|
||||
isp1704_charger_set_power(isp, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/power/max17042_battery.h>
|
||||
@@ -61,9 +62,13 @@
|
||||
#define dP_ACC_100 0x1900
|
||||
#define dP_ACC_200 0x3200
|
||||
|
||||
#define MAX17042_IC_VERSION 0x0092
|
||||
#define MAX17047_IC_VERSION 0x00AC /* same for max17050 */
|
||||
|
||||
struct max17042_chip {
|
||||
struct i2c_client *client;
|
||||
struct power_supply battery;
|
||||
enum max170xx_chip_type chip_type;
|
||||
struct max17042_platform_data *pdata;
|
||||
struct work_struct work;
|
||||
int init_complete;
|
||||
@@ -105,6 +110,7 @@ static enum power_supply_property max17042_battery_props[] = {
|
||||
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_AVG,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_OCV,
|
||||
POWER_SUPPLY_PROP_CAPACITY,
|
||||
POWER_SUPPLY_PROP_CHARGE_FULL,
|
||||
POWER_SUPPLY_PROP_TEMP,
|
||||
@@ -150,7 +156,10 @@ static int max17042_get_property(struct power_supply *psy,
|
||||
val->intval *= 20000; /* Units of LSB = 20mV */
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
|
||||
ret = max17042_read_reg(chip->client, MAX17042_V_empty);
|
||||
if (chip->chip_type == MAX17042)
|
||||
ret = max17042_read_reg(chip->client, MAX17042_V_empty);
|
||||
else
|
||||
ret = max17042_read_reg(chip->client, MAX17047_V_empty);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -169,6 +178,13 @@ static int max17042_get_property(struct power_supply *psy,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val->intval = ret * 625 / 8;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_OCV:
|
||||
ret = max17042_read_reg(chip->client, MAX17042_OCVInternal);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val->intval = ret * 625 / 8;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CAPACITY:
|
||||
@@ -325,11 +341,10 @@ static inline int max17042_model_data_compare(struct max17042_chip *chip,
|
||||
static int max17042_init_model(struct max17042_chip *chip)
|
||||
{
|
||||
int ret;
|
||||
int table_size =
|
||||
sizeof(chip->pdata->config_data->cell_char_tbl)/sizeof(u16);
|
||||
int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl);
|
||||
u16 *temp_data;
|
||||
|
||||
temp_data = kzalloc(table_size, GFP_KERNEL);
|
||||
temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL);
|
||||
if (!temp_data)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -354,12 +369,11 @@ static int max17042_init_model(struct max17042_chip *chip)
|
||||
static int max17042_verify_model_lock(struct max17042_chip *chip)
|
||||
{
|
||||
int i;
|
||||
int table_size =
|
||||
sizeof(chip->pdata->config_data->cell_char_tbl);
|
||||
int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl);
|
||||
u16 *temp_data;
|
||||
int ret = 0;
|
||||
|
||||
temp_data = kzalloc(table_size, GFP_KERNEL);
|
||||
temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL);
|
||||
if (!temp_data)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -382,6 +396,9 @@ static void max17042_write_config_regs(struct max17042_chip *chip)
|
||||
max17042_write_reg(chip->client, MAX17042_FilterCFG,
|
||||
config->filter_cfg);
|
||||
max17042_write_reg(chip->client, MAX17042_RelaxCFG, config->relax_cfg);
|
||||
if (chip->chip_type == MAX17047)
|
||||
max17042_write_reg(chip->client, MAX17047_FullSOCThr,
|
||||
config->full_soc_thresh);
|
||||
}
|
||||
|
||||
static void max17042_write_custom_regs(struct max17042_chip *chip)
|
||||
@@ -392,12 +409,23 @@ static void max17042_write_custom_regs(struct max17042_chip *chip)
|
||||
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);
|
||||
if (chip->chip_type == MAX17042) {
|
||||
max17042_write_reg(chip->client, MAX17042_EmptyTempCo,
|
||||
config->empty_tempco);
|
||||
max17042_write_verify_reg(chip->client, MAX17042_K_empty0,
|
||||
config->kempty0);
|
||||
} else {
|
||||
max17042_write_verify_reg(chip->client, MAX17047_QRTbl00,
|
||||
config->qrtbl00);
|
||||
max17042_write_verify_reg(chip->client, MAX17047_QRTbl10,
|
||||
config->qrtbl10);
|
||||
max17042_write_verify_reg(chip->client, MAX17047_QRTbl20,
|
||||
config->qrtbl20);
|
||||
max17042_write_verify_reg(chip->client, MAX17047_QRTbl30,
|
||||
config->qrtbl30);
|
||||
}
|
||||
}
|
||||
|
||||
static void max17042_update_capacity_regs(struct max17042_chip *chip)
|
||||
@@ -453,6 +481,8 @@ static void max17042_load_new_capacity_params(struct max17042_chip *chip)
|
||||
config->design_cap);
|
||||
max17042_write_verify_reg(chip->client, MAX17042_FullCAPNom,
|
||||
config->fullcapnom);
|
||||
/* Update SOC register with new SOC */
|
||||
max17042_write_reg(chip->client, MAX17042_RepSOC, vfSoc);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -489,20 +519,28 @@ static inline void max17042_override_por_values(struct max17042_chip *chip)
|
||||
|
||||
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);
|
||||
if (chip->chip_type == MAX17042)
|
||||
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);
|
||||
if (chip->chip_type == MAX17042)
|
||||
max17042_override_por(client, MAX17042_V_empty, config->vempty);
|
||||
else
|
||||
max17042_override_por(client, MAX17047_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);
|
||||
if (chip->chip_type) {
|
||||
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)
|
||||
@@ -659,7 +697,19 @@ static int __devinit max17042_probe(struct i2c_client *client,
|
||||
|
||||
i2c_set_clientdata(client, chip);
|
||||
|
||||
chip->battery.name = "max17042_battery";
|
||||
ret = max17042_read_reg(chip->client, MAX17042_DevName);
|
||||
if (ret == MAX17042_IC_VERSION) {
|
||||
dev_dbg(&client->dev, "chip type max17042 detected\n");
|
||||
chip->chip_type = MAX17042;
|
||||
} else if (ret == MAX17047_IC_VERSION) {
|
||||
dev_dbg(&client->dev, "chip type max17047/50 detected\n");
|
||||
chip->chip_type = MAX17047;
|
||||
} else {
|
||||
dev_err(&client->dev, "device version mismatch: %x\n", ret);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
chip->battery.name = "max170xx_battery";
|
||||
chip->battery.type = POWER_SUPPLY_TYPE_BATTERY;
|
||||
chip->battery.get_property = max17042_get_property;
|
||||
chip->battery.properties = max17042_battery_props;
|
||||
@@ -683,6 +733,12 @@ static int __devinit max17042_probe(struct i2c_client *client,
|
||||
max17042_write_reg(client, MAX17042_LearnCFG, 0x0007);
|
||||
}
|
||||
|
||||
ret = power_supply_register(&client->dev, &chip->battery);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "failed: power supply register\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (client->irq) {
|
||||
ret = request_threaded_irq(client->irq, NULL,
|
||||
max17042_thread_handler,
|
||||
@@ -693,13 +749,14 @@ static int __devinit max17042_probe(struct i2c_client *client,
|
||||
reg |= CONFIG_ALRT_BIT_ENBL;
|
||||
max17042_write_reg(client, MAX17042_CONFIG, reg);
|
||||
max17042_set_soc_threshold(chip, 1);
|
||||
} else
|
||||
} else {
|
||||
client->irq = 0;
|
||||
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);
|
||||
@@ -707,23 +764,65 @@ static int __devinit max17042_probe(struct i2c_client *client,
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit max17042_remove(struct i2c_client *client)
|
||||
{
|
||||
struct max17042_chip *chip = i2c_get_clientdata(client);
|
||||
|
||||
if (client->irq)
|
||||
free_irq(client->irq, chip);
|
||||
power_supply_unregister(&chip->battery);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int max17042_suspend(struct device *dev)
|
||||
{
|
||||
struct max17042_chip *chip = dev_get_drvdata(dev);
|
||||
|
||||
/*
|
||||
* disable the irq and enable irq_wake
|
||||
* capability to the interrupt line.
|
||||
*/
|
||||
if (chip->client->irq) {
|
||||
disable_irq(chip->client->irq);
|
||||
enable_irq_wake(chip->client->irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max17042_resume(struct device *dev)
|
||||
{
|
||||
struct max17042_chip *chip = dev_get_drvdata(dev);
|
||||
|
||||
if (chip->client->irq) {
|
||||
disable_irq_wake(chip->client->irq);
|
||||
enable_irq(chip->client->irq);
|
||||
/* re-program the SOC thresholds to 1% change */
|
||||
max17042_set_soc_threshold(chip, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops max17042_pm_ops = {
|
||||
.suspend = max17042_suspend,
|
||||
.resume = max17042_resume,
|
||||
};
|
||||
|
||||
#define MAX17042_PM_OPS (&max17042_pm_ops)
|
||||
#else
|
||||
#define MAX17042_PM_OPS NULL
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id max17042_dt_match[] = {
|
||||
{ .compatible = "maxim,max17042" },
|
||||
{ .compatible = "maxim,max17047" },
|
||||
{ .compatible = "maxim,max17050" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, max17042_dt_match);
|
||||
@@ -731,6 +830,8 @@ MODULE_DEVICE_TABLE(of, max17042_dt_match);
|
||||
|
||||
static const struct i2c_device_id max17042_id[] = {
|
||||
{ "max17042", 0 },
|
||||
{ "max17047", 1 },
|
||||
{ "max17050", 2 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, max17042_id);
|
||||
@@ -739,6 +840,7 @@ static struct i2c_driver max17042_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "max17042",
|
||||
.of_match_table = of_match_ptr(max17042_dt_match),
|
||||
.pm = MAX17042_PM_OPS,
|
||||
},
|
||||
.probe = max17042_probe,
|
||||
.remove = __devexit_p(max17042_remove),
|
||||
|
||||
@@ -146,6 +146,7 @@ static struct device_attribute power_supply_attrs[] = {
|
||||
POWER_SUPPLY_ATTR(voltage_min_design),
|
||||
POWER_SUPPLY_ATTR(voltage_now),
|
||||
POWER_SUPPLY_ATTR(voltage_avg),
|
||||
POWER_SUPPLY_ATTR(voltage_ocv),
|
||||
POWER_SUPPLY_ATTR(current_max),
|
||||
POWER_SUPPLY_ATTR(current_now),
|
||||
POWER_SUPPLY_ATTR(current_avg),
|
||||
|
||||
@@ -89,7 +89,7 @@ static const struct chip_data {
|
||||
[REG_CURRENT] =
|
||||
SBS_DATA(POWER_SUPPLY_PROP_CURRENT_NOW, 0x0A, -32768, 32767),
|
||||
[REG_CAPACITY] =
|
||||
SBS_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0E, 0, 100),
|
||||
SBS_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0D, 0, 100),
|
||||
[REG_REMAINING_CAPACITY] =
|
||||
SBS_DATA(POWER_SUPPLY_PROP_ENERGY_NOW, 0x0F, 0, 65535),
|
||||
[REG_REMAINING_CAPACITY_CHARGE] =
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,8 @@
|
||||
#include <linux/power_supply.h>
|
||||
|
||||
enum data_source {
|
||||
CM_BATTERY_PRESENT,
|
||||
CM_NO_BATTERY,
|
||||
CM_FUEL_GAUGE,
|
||||
CM_CHARGER_STAT,
|
||||
};
|
||||
@@ -29,6 +31,16 @@ enum polling_modes {
|
||||
CM_POLL_CHARGING_ONLY,
|
||||
};
|
||||
|
||||
enum cm_event_types {
|
||||
CM_EVENT_UNKNOWN = 0,
|
||||
CM_EVENT_BATT_FULL,
|
||||
CM_EVENT_BATT_IN,
|
||||
CM_EVENT_BATT_OUT,
|
||||
CM_EVENT_EXT_PWR_IN_OUT,
|
||||
CM_EVENT_CHG_START_STOP,
|
||||
CM_EVENT_OTHERS,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct charger_global_desc
|
||||
* @rtc_name: the name of RTC used to wake up the system from suspend.
|
||||
@@ -38,11 +50,18 @@ enum polling_modes {
|
||||
* rtc_only_wakeup() returning false.
|
||||
* If the RTC given to CM is the only wakeup reason,
|
||||
* rtc_only_wakeup should return true.
|
||||
* @assume_timer_stops_in_suspend:
|
||||
* Assume that the jiffy timer stops in suspend-to-RAM.
|
||||
* When enabled, CM does not rely on jiffies value in
|
||||
* suspend_again and assumes that jiffies value does not
|
||||
* change during suspend.
|
||||
*/
|
||||
struct charger_global_desc {
|
||||
char *rtc_name;
|
||||
|
||||
bool (*rtc_only_wakeup)(void);
|
||||
|
||||
bool assume_timer_stops_in_suspend;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -50,6 +69,11 @@ struct charger_global_desc {
|
||||
* @psy_name: the name of power-supply-class for charger manager
|
||||
* @polling_mode:
|
||||
* Determine which polling mode will be used
|
||||
* @fullbatt_vchkdrop_ms:
|
||||
* @fullbatt_vchkdrop_uV:
|
||||
* Check voltage drop after the battery is fully charged.
|
||||
* If it has dropped more than fullbatt_vchkdrop_uV after
|
||||
* fullbatt_vchkdrop_ms, CM will restart charging.
|
||||
* @fullbatt_uV: voltage in microvolt
|
||||
* If it is not being charged and VBATT >= fullbatt_uV,
|
||||
* it is assumed to be full.
|
||||
@@ -76,6 +100,8 @@ struct charger_desc {
|
||||
enum polling_modes polling_mode;
|
||||
unsigned int polling_interval_ms;
|
||||
|
||||
unsigned int fullbatt_vchkdrop_ms;
|
||||
unsigned int fullbatt_vchkdrop_uV;
|
||||
unsigned int fullbatt_uV;
|
||||
|
||||
enum data_source battery_present;
|
||||
@@ -101,6 +127,11 @@ struct charger_desc {
|
||||
* @fuel_gauge: power_supply for fuel gauge
|
||||
* @charger_stat: array of power_supply for chargers
|
||||
* @charger_enabled: the state of charger
|
||||
* @fullbatt_vchk_jiffies_at:
|
||||
* jiffies at the time full battery check will occur.
|
||||
* @fullbatt_vchk_uV: voltage in microvolt
|
||||
* criteria for full battery
|
||||
* @fullbatt_vchk_work: work queue for full battery check
|
||||
* @emergency_stop:
|
||||
* When setting true, stop charging
|
||||
* @last_temp_mC: the measured temperature in milli-Celsius
|
||||
@@ -121,6 +152,10 @@ struct charger_manager {
|
||||
|
||||
bool charger_enabled;
|
||||
|
||||
unsigned long fullbatt_vchk_jiffies_at;
|
||||
unsigned int fullbatt_vchk_uV;
|
||||
struct delayed_work fullbatt_vchk_work;
|
||||
|
||||
int emergency_stop;
|
||||
int last_temp_mC;
|
||||
|
||||
@@ -134,14 +169,13 @@ struct charger_manager {
|
||||
#ifdef CONFIG_CHARGER_MANAGER
|
||||
extern int setup_charger_manager(struct charger_global_desc *gd);
|
||||
extern bool cm_suspend_again(void);
|
||||
extern void cm_notify_event(struct power_supply *psy,
|
||||
enum cm_event_types type, char *msg);
|
||||
#else
|
||||
static void __maybe_unused setup_charger_manager(struct charger_global_desc *gd)
|
||||
{ }
|
||||
|
||||
static bool __maybe_unused cm_suspend_again(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline int setup_charger_manager(struct charger_global_desc *gd)
|
||||
{ return 0; }
|
||||
static inline bool cm_suspend_again(void) { return false; }
|
||||
static inline void cm_notify_event(struct power_supply *psy,
|
||||
enum cm_event_types type, char *msg) { }
|
||||
#endif
|
||||
|
||||
#endif /* _CHARGER_MANAGER_H */
|
||||
|
||||
@@ -116,6 +116,18 @@ enum max17042_register {
|
||||
MAX17042_VFSOC = 0xFF,
|
||||
};
|
||||
|
||||
/* Registers specific to max17047/50 */
|
||||
enum max17047_register {
|
||||
MAX17047_QRTbl00 = 0x12,
|
||||
MAX17047_FullSOCThr = 0x13,
|
||||
MAX17047_QRTbl10 = 0x22,
|
||||
MAX17047_QRTbl20 = 0x32,
|
||||
MAX17047_V_empty = 0x3A,
|
||||
MAX17047_QRTbl30 = 0x42,
|
||||
};
|
||||
|
||||
enum max170xx_chip_type {MAX17042, MAX17047};
|
||||
|
||||
/*
|
||||
* used for setting a register to a desired value
|
||||
* addr : address for a register
|
||||
@@ -144,6 +156,7 @@ struct max17042_config_data {
|
||||
u16 shdntimer; /* 0x03F */
|
||||
|
||||
/* App data */
|
||||
u16 full_soc_thresh; /* 0x13 */
|
||||
u16 design_cap; /* 0x18 */
|
||||
u16 ichgt_term; /* 0x1E */
|
||||
|
||||
@@ -162,6 +175,10 @@ struct max17042_config_data {
|
||||
u16 lavg_empty; /* 0x36 */
|
||||
u16 dqacc; /* 0x45 */
|
||||
u16 dpacc; /* 0x46 */
|
||||
u16 qrtbl00; /* 0x12 */
|
||||
u16 qrtbl10; /* 0x22 */
|
||||
u16 qrtbl20; /* 0x32 */
|
||||
u16 qrtbl30; /* 0x42 */
|
||||
|
||||
/* Cell technology from power_supply.h */
|
||||
u16 cell_technology;
|
||||
|
||||
@@ -96,6 +96,7 @@ enum power_supply_property {
|
||||
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_AVG,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_OCV,
|
||||
POWER_SUPPLY_PROP_CURRENT_MAX,
|
||||
POWER_SUPPLY_PROP_CURRENT_NOW,
|
||||
POWER_SUPPLY_PROP_CURRENT_AVG,
|
||||
@@ -211,7 +212,7 @@ extern void power_supply_changed(struct power_supply *psy);
|
||||
extern int power_supply_am_i_supplied(struct power_supply *psy);
|
||||
extern int power_supply_set_battery_charged(struct power_supply *psy);
|
||||
|
||||
#if defined(CONFIG_POWER_SUPPLY) || defined(CONFIG_POWER_SUPPLY_MODULE)
|
||||
#ifdef CONFIG_POWER_SUPPLY
|
||||
extern int power_supply_is_system_supplied(void);
|
||||
#else
|
||||
static inline int power_supply_is_system_supplied(void) { return -ENOSYS; }
|
||||
@@ -261,6 +262,7 @@ static inline bool power_supply_is_watt_property(enum power_supply_property psp)
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_AVG:
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_OCV:
|
||||
case POWER_SUPPLY_PROP_POWER_NOW:
|
||||
return 1;
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user