Merge tag 'for-v3.8-merged' of git://git.infradead.org/battery-2.6

Pull battery subsystem updates from Anton Vorontsov:
 "Highlights:

   - Two new drivers from Pali Rohár and N900 hackers: rx51_battery and
     bq2415x_charger.  The drivers are a part of a solution to replace
     the proprietary Nokia BME stack

   - Power supply core now registers devices with a thermal cooling
     subsystem, so we can now automatically throttle charging.  Thanks
     to Ramakrishna Pallala!

   - Device tree support for ab8500 and max8925_power drivers

   - Random fixups and enhancements for a bunch of drivers."

* tag 'for-v3.8-merged' of git://git.infradead.org/battery-2.6: (22 commits)
  max8925_power: Add support for device-tree initialization
  ab8500: Add devicetree support for chargalg
  ab8500: Add devicetree support for charger
  ab8500: Add devicetree support for btemp
  ab8500: Add devicetree support for fuelgauge
  twl4030_charger: Change TWL4030_MODULE_* ids to TWL_MODULE_*
  jz4740-battery: Use devm_request_and_ioremap
  jz4740-battery: Use devm_kzalloc
  bq27x00_battery: Fixup nominal available capacity reporting
  bq2415x_charger: Fix style issues
  bq2415x_charger: Add Kconfig/Makefile entries
  power_supply: Add bq2415x charger driver
  power_supply: Add new Nokia RX-51 (N900) power supply battery driver
  max17042_battery: Fix missing verify_model_lock() return value check
  ds2782_battery: Fix signedness bug in ds278x_read_reg16()
  lp8788-charger: Fix ADC channel names
  lp8788-charger: Fix wrong ADC conversion
  lp8788-charger: Use consumer device name on setting IIO channels
  power_supply: Register power supply for thermal cooling device
  power_supply: Add support for CHARGE_CONTROL_* attributes
  ...
This commit is contained in:
Linus Torvalds
2012-12-13 19:26:04 -08:00
31 changed files with 3124 additions and 281 deletions
@@ -24,7 +24,32 @@ ab8500-bm : : : Battery Manager
ab8500-btemp : : : Battery Temperature
ab8500-charger : : : Battery Charger
ab8500-codec : : : Audio Codec
ab8500-fg : : : Fuel Gauge
ab8500-fg : : vddadc : Fuel Gauge
: NCONV_ACCU : : Accumulate N Sample Conversion
: BATT_OVV : : Battery Over Voltage
: LOW_BAT_F : : LOW threshold battery voltage
: CC_INT_CALIB : : Coulomb Counter Internal Calibration
: CCEOC : : Coulomb Counter End of Conversion
ab8500-btemp : : vtvout : Battery Temperature
: BAT_CTRL_INDB : : Battery Removal Indicator
: BTEMP_LOW : : Btemp < BtempLow, if battery temperature is lower than -10°C
: BTEMP_LOW_MEDIUM : : BtempLow < Btemp < BtempMedium,if battery temperature is between -10 and 0°C
: BTEMP_MEDIUM_HIGH : : BtempMedium < Btemp < BtempHigh,if battery temperature is between 0°C and“MaxTemp
: BTEMP_HIGH : : Btemp > BtempHigh, if battery temperature is higher than “MaxTemp
ab8500-charger : : vddadc : Charger interface
: MAIN_CH_UNPLUG_DET : : main charger unplug detection management (not in 8505)
: MAIN_CHARGE_PLUG_DET : : main charger plug detection management (not in 8505)
: MAIN_EXT_CH_NOT_OK : : main charger not OK
: MAIN_CH_TH_PROT_R : : Die temp is above main charger
: MAIN_CH_TH_PROT_F : : Die temp is below main charger
: VBUS_DET_F : : VBUS falling detected
: VBUS_DET_R : : VBUS rising detected
: USB_LINK_STATUS : : USB link status has changed
: USB_CH_TH_PROT_R : : Die temp is above usb charger
: USB_CH_TH_PROT_F : : Die temp is below usb charger
: USB_CHARGER_NOT_OKR : : allowed USB charger not ok detection
: VBUS_OVV : : Overvoltage on Vbus ball detected (USB charge is stopped)
: CH_WD_EXP : : Charger watchdog detected
ab8500-gpadc : HW_CONV_END : vddadc : Analogue to Digital Converter
SW_CONV_END : :
ab8500-gpio : : : GPIO Controller
@@ -0,0 +1,16 @@
=== AB8500 Battery Temperature Monitor Driver ===
The properties below describes the node for btemp driver.
Required Properties:
- compatible = Shall be: "stericsson,ab8500-btemp"
- battery = Shall be battery specific information
Example:
ab8500_btemp {
compatible = "stericsson,ab8500-btemp";
battery = <&ab8500_battery>;
};
For information on battery specific node, Ref:
Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
@@ -0,0 +1,16 @@
=== AB8500 Charging Algorithm Driver ===
The properties below describes the node for chargalg driver.
Required Properties:
- compatible = Shall be: "stericsson,ab8500-chargalg"
- battery = Shall be battery specific information
Example:
ab8500_chargalg {
compatible = "stericsson,ab8500-chargalg";
battery = <&ab8500_battery>;
};
For information on battery specific node, Ref:
Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
@@ -0,0 +1,25 @@
=== AB8500 Charger Driver ===
Required Properties:
- compatible = Shall be "stericsson,ab8500-charger"
- battery = Shall be battery specific information
Example:
ab8500_charger {
compatible = "stericsson,ab8500-charger";
battery = <&ab8500_battery>;
};
- vddadc-supply: Supply for USB and Main charger
Example:
ab8500-charger {
vddadc-supply = <&ab8500_ldo_tvout_reg>;
}
- autopower_cfg:
Boolean value depicting the presence of 'automatic poweron after powerloss'
Example:
ab8500-charger {
autopower_cfg;
};
For information on battery specific node, Ref:
Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
@@ -0,0 +1,58 @@
=== AB8500 Fuel Gauge Driver ===
AB8500 is a mixed signal multimedia and power management
device comprising: power and energy-management-module,
wall-charger, usb-charger, audio codec, general purpose adc,
tvout, clock management and sim card interface.
Fuelgauge support is part of energy-management-modules, other
components of this module are:
main-charger, usb-combo-charger and battery-temperature-monitoring.
The properties below describes the node for fuelgauge driver.
Required Properties:
- compatible = This shall be: "stericsson,ab8500-fg"
- battery = Shall be battery specific information
Example:
ab8500_fg {
compatible = "stericsson,ab8500-fg";
battery = <&ab8500_battery>;
};
dependent node:
ab8500_battery: ab8500_battery {
};
This node will provide information on 'thermistor interface' and
'battery technology type' used.
Properties of this node are:
thermistor-on-batctrl:
A boolean value indicating thermistor interface to battery
Note:
'btemp' and 'batctrl' are the pins interfaced for battery temperature
measurement, 'btemp' signal is used when NTC(negative temperature
coefficient) resister is interfaced external to battery whereas
'batctrl' pin is used when NTC resister is internal to battery.
Example:
ab8500_battery: ab8500_battery {
thermistor-on-batctrl;
};
indicates: NTC resister is internal to battery, 'batctrl' is used
for thermal measurement.
The absence of property 'thermal-on-batctrl' indicates
NTC resister is external to battery and 'btemp' signal is used
for thermal measurement.
battery-type:
This shall be the battery manufacturing technology type,
allowed types are:
"UNKNOWN" "NiMH" "LION" "LIPO" "LiFe" "NiCd" "LiMn"
Example:
ab8500_battery: ab8500_battery {
stericsson,battery-type = "LIPO";
}
@@ -123,6 +123,9 @@ CONSTANT_CHARGE_VOLTAGE - constant charge voltage programmed by charger.
CONSTANT_CHARGE_VOLTAGE_MAX - maximum charge voltage supported by the
power supply object.
CHARGE_CONTROL_LIMIT - current charge control limit setting
CHARGE_CONTROL_LIMIT_MAX - maximum charge control limit setting
ENERGY_FULL, ENERGY_EMPTY - same as above but for energy.
CAPACITY - capacity in percents.
+27 -1
View File
@@ -340,7 +340,33 @@
vddadc-supply = <&ab8500_ldo_tvout_reg>;
};
ab8500-usb {
ab8500_battery: ab8500_battery {
stericsson,battery-type = "LIPO";
thermistor-on-batctrl;
};
ab8500_fg {
compatible = "stericsson,ab8500-fg";
battery = <&ab8500_battery>;
};
ab8500_btemp {
compatible = "stericsson,ab8500-btemp";
battery = <&ab8500_battery>;
};
ab8500_charger {
compatible = "stericsson,ab8500-charger";
battery = <&ab8500_battery>;
vddadc-supply = <&ab8500_ldo_tvout_reg>;
};
ab8500_chargalg {
compatible = "stericsson,ab8500-chargalg";
battery = <&ab8500_battery>;
};
ab8500_usb {
compatible = "stericsson,ab8500-usb";
interrupts = < 90 0x4
96 0x4
+20
View File
@@ -1036,23 +1036,43 @@ static struct mfd_cell abx500_common_devs[] = {
static struct mfd_cell ab8500_bm_devs[] = {
{
.name = "ab8500-charger",
.of_compatible = "stericsson,ab8500-charger",
.num_resources = ARRAY_SIZE(ab8500_charger_resources),
.resources = ab8500_charger_resources,
#ifndef CONFIG_OF
.platform_data = &ab8500_bm_data,
.pdata_size = sizeof(ab8500_bm_data),
#endif
},
{
.name = "ab8500-btemp",
.of_compatible = "stericsson,ab8500-btemp",
.num_resources = ARRAY_SIZE(ab8500_btemp_resources),
.resources = ab8500_btemp_resources,
#ifndef CONFIG_OF
.platform_data = &ab8500_bm_data,
.pdata_size = sizeof(ab8500_bm_data),
#endif
},
{
.name = "ab8500-fg",
.of_compatible = "stericsson,ab8500-fg",
.num_resources = ARRAY_SIZE(ab8500_fg_resources),
.resources = ab8500_fg_resources,
#ifndef CONFIG_OF
.platform_data = &ab8500_bm_data,
.pdata_size = sizeof(ab8500_bm_data),
#endif
},
{
.name = "ab8500-chargalg",
.of_compatible = "stericsson,ab8500-chargalg",
.num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
.resources = ab8500_chargalg_resources,
#ifndef CONFIG_OF
.platform_data = &ab8500_bm_data,
.pdata_size = sizeof(ab8500_bm_data),
#endif
},
};
+17 -7
View File
@@ -245,6 +245,13 @@ config BATTERY_INTEL_MID
Say Y here to enable the battery driver on Intel MID
platforms.
config BATTERY_RX51
tristate "Nokia RX-51 (N900) battery driver"
depends on TWL4030_MADC
help
Say Y here to enable support for battery information on Nokia
RX-51, also known as N900 tablet.
config CHARGER_ISP1704
tristate "ISP1704 USB Charger Detection"
depends on USB_OTG_UTILS
@@ -315,6 +322,16 @@ config CHARGER_MAX8998
Say Y to enable support for the battery charger control sysfs and
platform data of MAX8998/LP3974 PMICs.
config CHARGER_BQ2415X
tristate "TI BQ2415x battery charger driver"
depends on I2C
help
Say Y to enable support for the TI BQ2415x battery charger
PMICs.
You'll need this driver to charge batteries on e.g. Nokia
RX-51/N900.
config CHARGER_SMB347
tristate "Summit Microelectronics SMB347 Battery Charger"
depends on I2C
@@ -329,13 +346,6 @@ config AB8500_BM
help
Say Y to include support for AB8500 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.
source "drivers/power/reset/Kconfig"
endif # POWER_SUPPLY
+3 -1
View File
@@ -37,7 +37,8 @@ obj-$(CONFIG_CHARGER_88PM860X) += 88pm860x_charger.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_BATTERY_RX51) += rx51_battery.o
obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o 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
@@ -47,6 +48,7 @@ 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_BQ2415X) += bq2415x_charger.o
obj-$(CONFIG_POWER_AVS) += avs/
obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o
obj-$(CONFIG_POWER_RESET) += reset/
File diff suppressed because it is too large Load Diff
+40 -37
View File
@@ -20,11 +20,13 @@
#include <linux/power_supply.h>
#include <linux/completion.h>
#include <linux/workqueue.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/jiffies.h>
#include <linux/of.h>
#include <linux/mfd/core.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500/ab8500-bm.h>
#include <linux/mfd/abx500/ab8500-gpadc.h>
#include <linux/jiffies.h>
#define VTVOUT_V 1800
@@ -76,7 +78,6 @@ struct ab8500_btemp_ranges {
* @parent: Pointer to the struct ab8500
* @gpadc: Pointer to the struct gpadc
* @fg: Pointer to the struct fg
* @pdata: Pointer to the abx500_btemp platform data
* @bat: Pointer to the abx500_bm platform data
* @btemp_psy: Structure for BTEMP specific battery properties
* @events: Structure for information about events triggered
@@ -93,7 +94,6 @@ struct ab8500_btemp {
struct ab8500 *parent;
struct ab8500_gpadc *gpadc;
struct ab8500_fg *fg;
struct abx500_btemp_platform_data *pdata;
struct abx500_bm_data *bat;
struct power_supply btemp_psy;
struct ab8500_btemp_events events;
@@ -955,56 +955,57 @@ static int ab8500_btemp_remove(struct platform_device *pdev)
flush_scheduled_work();
power_supply_unregister(&di->btemp_psy);
platform_set_drvdata(pdev, NULL);
kfree(di);
return 0;
}
static char *supply_interface[] = {
"ab8500_chargalg",
"ab8500_fg",
};
static int ab8500_btemp_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct ab8500_btemp *di;
int irq, i, ret = 0;
u8 val;
struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
struct ab8500_btemp *di;
if (!plat_data) {
dev_err(&pdev->dev, "No platform data\n");
return -EINVAL;
}
di = kzalloc(sizeof(*di), GFP_KERNEL);
if (!di)
di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
if (!di) {
dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__);
return -ENOMEM;
}
di->bat = pdev->mfd_cell->platform_data;
if (!di->bat) {
if (np) {
ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
if (ret) {
dev_err(&pdev->dev,
"failed to get battery information\n");
return ret;
}
} else {
dev_err(&pdev->dev, "missing dt node for ab8500_btemp\n");
return -EINVAL;
}
} else {
dev_info(&pdev->dev, "falling back to legacy platform data\n");
}
/* get parent data */
di->dev = &pdev->dev;
di->parent = dev_get_drvdata(pdev->dev.parent);
di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
/* get btemp specific platform data */
di->pdata = plat_data->btemp;
if (!di->pdata) {
dev_err(di->dev, "no btemp platform data supplied\n");
ret = -EINVAL;
goto free_device_info;
}
/* get battery specific platform data */
di->bat = plat_data->battery;
if (!di->bat) {
dev_err(di->dev, "no battery platform data supplied\n");
ret = -EINVAL;
goto free_device_info;
}
/* BTEMP supply */
di->btemp_psy.name = "ab8500_btemp";
di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY;
di->btemp_psy.properties = ab8500_btemp_props;
di->btemp_psy.num_properties = ARRAY_SIZE(ab8500_btemp_props);
di->btemp_psy.get_property = ab8500_btemp_get_property;
di->btemp_psy.supplied_to = di->pdata->supplied_to;
di->btemp_psy.num_supplicants = di->pdata->num_supplicants;
di->btemp_psy.supplied_to = supply_interface;
di->btemp_psy.num_supplicants = ARRAY_SIZE(supply_interface);
di->btemp_psy.external_power_changed =
ab8500_btemp_external_power_changed;
@@ -1014,8 +1015,7 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
create_singlethread_workqueue("ab8500_btemp_wq");
if (di->btemp_wq == NULL) {
dev_err(di->dev, "failed to create work queue\n");
ret = -ENOMEM;
goto free_device_info;
return -ENOMEM;
}
/* Init work for measuring temperature periodically */
@@ -1093,12 +1093,14 @@ free_irq:
}
free_btemp_wq:
destroy_workqueue(di->btemp_wq);
free_device_info:
kfree(di);
return ret;
}
static const struct of_device_id ab8500_btemp_match[] = {
{ .compatible = "stericsson,ab8500-btemp", },
{ },
};
static struct platform_driver ab8500_btemp_driver = {
.probe = ab8500_btemp_probe,
.remove = ab8500_btemp_remove,
@@ -1107,6 +1109,7 @@ static struct platform_driver ab8500_btemp_driver = {
.driver = {
.name = "ab8500-btemp",
.owner = THIS_MODULE,
.of_match_table = ab8500_btemp_match,
},
};
+46 -38
View File
@@ -23,6 +23,8 @@
#include <linux/err.h>
#include <linux/workqueue.h>
#include <linux/kobject.h>
#include <linux/of.h>
#include <linux/mfd/core.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500-bm.h>
@@ -181,9 +183,9 @@ struct ab8500_charger_usb_state {
* @vbat Battery voltage
* @old_vbat Previously measured battery voltage
* @autopower Indicate if we should have automatic pwron after pwrloss
* @autopower_cfg platform specific power config support for "pwron after pwrloss"
* @parent: Pointer to the struct ab8500
* @gpadc: Pointer to the struct gpadc
* @pdata: Pointer to the abx500_charger platform data
* @bat: Pointer to the abx500_bm platform data
* @flags: Structure for information about events triggered
* @usb_state: Structure for usb stack information
@@ -218,9 +220,9 @@ struct ab8500_charger {
int vbat;
int old_vbat;
bool autopower;
bool autopower_cfg;
struct ab8500 *parent;
struct ab8500_gpadc *gpadc;
struct abx500_charger_platform_data *pdata;
struct abx500_bm_data *bat;
struct ab8500_charger_event_flags flags;
struct ab8500_charger_usb_state usb_state;
@@ -322,7 +324,7 @@ static void ab8500_power_loss_handling(struct ab8500_charger *di)
static void ab8500_power_supply_changed(struct ab8500_charger *di,
struct power_supply *psy)
{
if (di->pdata->autopower_cfg) {
if (di->autopower_cfg) {
if (!di->usb.charger_connected &&
!di->ac.charger_connected &&
di->autopower) {
@@ -2526,25 +2528,45 @@ static int ab8500_charger_remove(struct platform_device *pdev)
power_supply_unregister(&di->usb_chg.psy);
power_supply_unregister(&di->ac_chg.psy);
platform_set_drvdata(pdev, NULL);
kfree(di);
return 0;
}
static char *supply_interface[] = {
"ab8500_chargalg",
"ab8500_fg",
"ab8500_btemp",
};
static int ab8500_charger_probe(struct platform_device *pdev)
{
int irq, i, charger_status, ret = 0;
struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
struct device_node *np = pdev->dev.of_node;
struct ab8500_charger *di;
int irq, i, charger_status, ret = 0;
if (!plat_data) {
dev_err(&pdev->dev, "No platform data\n");
return -EINVAL;
}
di = kzalloc(sizeof(*di), GFP_KERNEL);
if (!di)
di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
if (!di) {
dev_err(&pdev->dev, "%s no mem for ab8500_charger\n", __func__);
return -ENOMEM;
}
di->bat = pdev->mfd_cell->platform_data;
if (!di->bat) {
if (np) {
ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
if (ret) {
dev_err(&pdev->dev,
"failed to get battery information\n");
return ret;
}
di->autopower_cfg = of_property_read_bool(np, "autopower_cfg");
} else {
dev_err(&pdev->dev, "missing dt node for ab8500_charger\n");
return -EINVAL;
}
} else {
dev_info(&pdev->dev, "falling back to legacy platform data\n");
di->autopower_cfg = false;
}
/* get parent data */
di->dev = &pdev->dev;
@@ -2554,22 +2576,6 @@ static int ab8500_charger_probe(struct platform_device *pdev)
/* initialize lock */
spin_lock_init(&di->usb_state.usb_lock);
/* get charger specific platform data */
di->pdata = plat_data->charger;
if (!di->pdata) {
dev_err(di->dev, "no charger platform data supplied\n");
ret = -EINVAL;
goto free_device_info;
}
/* get battery specific platform data */
di->bat = plat_data->battery;
if (!di->bat) {
dev_err(di->dev, "no battery platform data supplied\n");
ret = -EINVAL;
goto free_device_info;
}
di->autopower = false;
/* AC supply */
@@ -2579,8 +2585,8 @@ static int ab8500_charger_probe(struct platform_device *pdev)
di->ac_chg.psy.properties = ab8500_charger_ac_props;
di->ac_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_ac_props);
di->ac_chg.psy.get_property = ab8500_charger_ac_get_property;
di->ac_chg.psy.supplied_to = di->pdata->supplied_to;
di->ac_chg.psy.num_supplicants = di->pdata->num_supplicants;
di->ac_chg.psy.supplied_to = supply_interface;
di->ac_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface),
/* ux500_charger sub-class */
di->ac_chg.ops.enable = &ab8500_charger_ac_en;
di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
@@ -2597,8 +2603,8 @@ static int ab8500_charger_probe(struct platform_device *pdev)
di->usb_chg.psy.properties = ab8500_charger_usb_props;
di->usb_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_usb_props);
di->usb_chg.psy.get_property = ab8500_charger_usb_get_property;
di->usb_chg.psy.supplied_to = di->pdata->supplied_to;
di->usb_chg.psy.num_supplicants = di->pdata->num_supplicants;
di->usb_chg.psy.supplied_to = supply_interface;
di->usb_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface),
/* ux500_charger sub-class */
di->usb_chg.ops.enable = &ab8500_charger_usb_en;
di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick;
@@ -2614,8 +2620,7 @@ static int ab8500_charger_probe(struct platform_device *pdev)
create_singlethread_workqueue("ab8500_charger_wq");
if (di->charger_wq == NULL) {
dev_err(di->dev, "failed to create work queue\n");
ret = -ENOMEM;
goto free_device_info;
return -ENOMEM;
}
/* Init work for HW failure check */
@@ -2757,12 +2762,14 @@ free_regulator:
regulator_put(di->regu);
free_charger_wq:
destroy_workqueue(di->charger_wq);
free_device_info:
kfree(di);
return ret;
}
static const struct of_device_id ab8500_charger_match[] = {
{ .compatible = "stericsson,ab8500-charger", },
{ },
};
static struct platform_driver ab8500_charger_driver = {
.probe = ab8500_charger_probe,
.remove = ab8500_charger_remove,
@@ -2771,6 +2778,7 @@ static struct platform_driver ab8500_charger_driver = {
.driver = {
.name = "ab8500-charger",
.owner = THIS_MODULE,
.of_match_table = ab8500_charger_match,
},
};
+42 -40
View File
@@ -22,15 +22,16 @@
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/kobject.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500.h>
#include <linux/slab.h>
#include <linux/mfd/abx500/ab8500-bm.h>
#include <linux/delay.h>
#include <linux/mfd/abx500/ab8500-gpadc.h>
#include <linux/mfd/abx500.h>
#include <linux/time.h>
#include <linux/of.h>
#include <linux/completion.h>
#include <linux/mfd/core.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500/ab8500-bm.h>
#include <linux/mfd/abx500/ab8500-gpadc.h>
#define MILLI_TO_MICRO 1000
#define FG_LSB_IN_MA 1627
@@ -172,7 +173,6 @@ struct inst_curr_result_list {
* @avg_cap: Average capacity filter
* @parent: Pointer to the struct ab8500
* @gpadc: Pointer to the struct gpadc
* @pdata: Pointer to the abx500_fg platform data
* @bat: Pointer to the abx500_bm platform data
* @fg_psy: Structure that holds the FG specific battery properties
* @fg_wq: Work queue for running the FG algorithm
@@ -212,7 +212,6 @@ struct ab8500_fg {
struct ab8500_fg_avg_cap avg_cap;
struct ab8500 *parent;
struct ab8500_gpadc *gpadc;
struct abx500_fg_platform_data *pdata;
struct abx500_bm_data *bat;
struct power_supply fg_psy;
struct workqueue_struct *fg_wq;
@@ -2429,7 +2428,6 @@ static int ab8500_fg_remove(struct platform_device *pdev)
flush_scheduled_work();
power_supply_unregister(&di->fg_psy);
platform_set_drvdata(pdev, NULL);
kfree(di);
return ret;
}
@@ -2442,21 +2440,39 @@ static struct ab8500_fg_interrupts ab8500_fg_irq[] = {
{"CCEOC", ab8500_fg_cc_data_end_handler},
};
static char *supply_interface[] = {
"ab8500_chargalg",
"ab8500_usb",
};
static int ab8500_fg_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct ab8500_fg *di;
int i, irq;
int ret = 0;
struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
struct ab8500_fg *di;
if (!plat_data) {
dev_err(&pdev->dev, "No platform data\n");
return -EINVAL;
}
di = kzalloc(sizeof(*di), GFP_KERNEL);
if (!di)
di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
if (!di) {
dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__);
return -ENOMEM;
}
di->bat = pdev->mfd_cell->platform_data;
if (!di->bat) {
if (np) {
ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
if (ret) {
dev_err(&pdev->dev,
"failed to get battery information\n");
return ret;
}
} else {
dev_err(&pdev->dev, "missing dt node for ab8500_fg\n");
return -EINVAL;
}
} else {
dev_info(&pdev->dev, "falling back to legacy platform data\n");
}
mutex_init(&di->cc_lock);
@@ -2465,29 +2481,13 @@ static int ab8500_fg_probe(struct platform_device *pdev)
di->parent = dev_get_drvdata(pdev->dev.parent);
di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
/* get fg specific platform data */
di->pdata = plat_data->fg;
if (!di->pdata) {
dev_err(di->dev, "no fg platform data supplied\n");
ret = -EINVAL;
goto free_device_info;
}
/* get battery specific platform data */
di->bat = plat_data->battery;
if (!di->bat) {
dev_err(di->dev, "no battery platform data supplied\n");
ret = -EINVAL;
goto free_device_info;
}
di->fg_psy.name = "ab8500_fg";
di->fg_psy.type = POWER_SUPPLY_TYPE_BATTERY;
di->fg_psy.properties = ab8500_fg_props;
di->fg_psy.num_properties = ARRAY_SIZE(ab8500_fg_props);
di->fg_psy.get_property = ab8500_fg_get_property;
di->fg_psy.supplied_to = di->pdata->supplied_to;
di->fg_psy.num_supplicants = di->pdata->num_supplicants;
di->fg_psy.supplied_to = supply_interface;
di->fg_psy.num_supplicants = ARRAY_SIZE(supply_interface),
di->fg_psy.external_power_changed = ab8500_fg_external_power_changed;
di->bat_cap.max_mah_design = MILLI_TO_MICRO *
@@ -2506,8 +2506,7 @@ static int ab8500_fg_probe(struct platform_device *pdev)
di->fg_wq = create_singlethread_workqueue("ab8500_fg_wq");
if (di->fg_wq == NULL) {
dev_err(di->dev, "failed to create work queue\n");
ret = -ENOMEM;
goto free_device_info;
return -ENOMEM;
}
/* Init work for running the fg algorithm instantly */
@@ -2606,12 +2605,14 @@ free_irq:
}
free_inst_curr_wq:
destroy_workqueue(di->fg_wq);
free_device_info:
kfree(di);
return ret;
}
static const struct of_device_id ab8500_fg_match[] = {
{ .compatible = "stericsson,ab8500-fg", },
{ },
};
static struct platform_driver ab8500_fg_driver = {
.probe = ab8500_fg_probe,
.remove = ab8500_fg_remove,
@@ -2620,6 +2621,7 @@ static struct platform_driver ab8500_fg_driver = {
.driver = {
.name = "ab8500-fg",
.owner = THIS_MODULE,
.of_match_table = ab8500_fg_match,
},
};
+38 -18
View File
@@ -21,6 +21,8 @@
#include <linux/completion.h>
#include <linux/workqueue.h>
#include <linux/kobject.h>
#include <linux/of.h>
#include <linux/mfd/core.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ux500_chargalg.h>
#include <linux/mfd/abx500/ab8500-bm.h>
@@ -205,7 +207,6 @@ enum maxim_ret {
* @chg_info: information about connected charger types
* @batt_data: data of the battery
* @susp_status: current charger suspension status
* @pdata: pointer to the abx500_chargalg platform data
* @bat: pointer to the abx500_bm platform data
* @chargalg_psy: structure that holds the battery properties exposed by
* the charging algorithm
@@ -231,7 +232,6 @@ struct abx500_chargalg {
struct abx500_chargalg_charger_info chg_info;
struct abx500_chargalg_battery_data batt_data;
struct abx500_chargalg_suspension_status susp_status;
struct abx500_chargalg_platform_data *pdata;
struct abx500_bm_data *bat;
struct power_supply chargalg_psy;
struct ux500_charger *ac_chg;
@@ -1795,36 +1795,53 @@ static int abx500_chargalg_remove(struct platform_device *pdev)
flush_scheduled_work();
power_supply_unregister(&di->chargalg_psy);
platform_set_drvdata(pdev, NULL);
kfree(di);
return 0;
}
static char *supply_interface[] = {
"ab8500_fg",
};
static int abx500_chargalg_probe(struct platform_device *pdev)
{
struct abx500_bm_plat_data *plat_data;
struct device_node *np = pdev->dev.of_node;
struct abx500_chargalg *di;
int ret = 0;
struct abx500_chargalg *di =
kzalloc(sizeof(struct abx500_chargalg), GFP_KERNEL);
if (!di)
di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
if (!di) {
dev_err(&pdev->dev, "%s no mem for ab8500_chargalg\n", __func__);
return -ENOMEM;
}
di->bat = pdev->mfd_cell->platform_data;
if (!di->bat) {
if (np) {
ret = bmdevs_of_probe(&pdev->dev, np, &di->bat);
if (ret) {
dev_err(&pdev->dev,
"failed to get battery information\n");
return ret;
}
} else {
dev_err(&pdev->dev, "missing dt node for ab8500_chargalg\n");
return -EINVAL;
}
} else {
dev_info(&pdev->dev, "falling back to legacy platform data\n");
}
/* get device struct */
di->dev = &pdev->dev;
plat_data = pdev->dev.platform_data;
di->pdata = plat_data->chargalg;
di->bat = plat_data->battery;
/* chargalg supply */
di->chargalg_psy.name = "abx500_chargalg";
di->chargalg_psy.type = POWER_SUPPLY_TYPE_BATTERY;
di->chargalg_psy.properties = abx500_chargalg_props;
di->chargalg_psy.num_properties = ARRAY_SIZE(abx500_chargalg_props);
di->chargalg_psy.get_property = abx500_chargalg_get_property;
di->chargalg_psy.supplied_to = di->pdata->supplied_to;
di->chargalg_psy.num_supplicants = di->pdata->num_supplicants;
di->chargalg_psy.supplied_to = supply_interface;
di->chargalg_psy.num_supplicants = ARRAY_SIZE(supply_interface),
di->chargalg_psy.external_power_changed =
abx500_chargalg_external_power_changed;
@@ -1844,7 +1861,7 @@ static int abx500_chargalg_probe(struct platform_device *pdev)
create_singlethread_workqueue("abx500_chargalg_wq");
if (di->chargalg_wq == NULL) {
dev_err(di->dev, "failed to create work queue\n");
goto free_device_info;
return -ENOMEM;
}
/* Init work for chargalg */
@@ -1885,20 +1902,23 @@ free_psy:
power_supply_unregister(&di->chargalg_psy);
free_chargalg_wq:
destroy_workqueue(di->chargalg_wq);
free_device_info:
kfree(di);
return ret;
}
static const struct of_device_id ab8500_chargalg_match[] = {
{ .compatible = "stericsson,ab8500-chargalg", },
{ },
};
static struct platform_driver abx500_chargalg_driver = {
.probe = abx500_chargalg_probe,
.remove = abx500_chargalg_remove,
.suspend = abx500_chargalg_suspend,
.resume = abx500_chargalg_resume,
.driver = {
.name = "abx500-chargalg",
.name = "ab8500-chargalg",
.owner = THIS_MODULE,
.of_match_table = ab8500_chargalg_match,
},
};
File diff suppressed because it is too large Load Diff
+8
View File
@@ -230,6 +230,14 @@ static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg)
*/
static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di)
{
int flags;
bool is_bq27500 = di->chip == BQ27500;
bool is_higher = bq27xxx_is_chip_version_higher(di);
flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500);
if (flags >= 0 && !is_higher && (flags & BQ27000_FLAG_CI))
return -ENODATA;
return bq27x00_battery_read_charge(di, BQ27x00_REG_NAC);
}
+2 -2
View File
@@ -80,13 +80,13 @@ static inline int ds278x_read_reg16(struct ds278x_info *info, int reg_msb,
{
int ret;
ret = swab16(i2c_smbus_read_word_data(info->client, reg_msb));
ret = i2c_smbus_read_word_data(info->client, reg_msb);
if (ret < 0) {
dev_err(&info->client->dev, "register read failed\n");
return ret;
}
*val = ret;
*val = swab16(ret);
return 0;
}
+3 -2
View File
@@ -279,7 +279,8 @@ static int gab_probe(struct platform_device *pdev)
}
memcpy(psy->properties, gab_props, sizeof(gab_props));
properties = psy->properties + sizeof(gab_props);
properties = (enum power_supply_property *)
((char *)psy->properties + sizeof(gab_props));
/*
* getting channel from iio and copying the battery properties
@@ -327,7 +328,7 @@ static int gab_probe(struct platform_device *pdev)
ret = request_any_context_irq(irq, gab_charged,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"battery charged", adc_bat);
if (ret)
if (ret < 0)
goto err_gpio;
}
+9 -36
View File
@@ -33,7 +33,6 @@ struct jz_battery {
struct jz_battery_platform_data *pdata;
struct platform_device *pdev;
struct resource *mem;
void __iomem *base;
int irq;
@@ -244,13 +243,14 @@ static int jz_battery_probe(struct platform_device *pdev)
struct jz_battery_platform_data *pdata = pdev->dev.parent->platform_data;
struct jz_battery *jz_battery;
struct power_supply *battery;
struct resource *mem;
if (!pdata) {
dev_err(&pdev->dev, "No platform_data supplied\n");
return -ENXIO;
}
jz_battery = kzalloc(sizeof(*jz_battery), GFP_KERNEL);
jz_battery = devm_kzalloc(&pdev->dev, sizeof(*jz_battery), GFP_KERNEL);
if (!jz_battery) {
dev_err(&pdev->dev, "Failed to allocate driver structure\n");
return -ENOMEM;
@@ -260,33 +260,15 @@ static int jz_battery_probe(struct platform_device *pdev)
jz_battery->irq = platform_get_irq(pdev, 0);
if (jz_battery->irq < 0) {
ret = jz_battery->irq;
dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
goto err_free;
return jz_battery->irq;
}
jz_battery->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!jz_battery->mem) {
ret = -ENOENT;
dev_err(&pdev->dev, "Failed to get platform mmio resource\n");
goto err_free;
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
jz_battery->mem = request_mem_region(jz_battery->mem->start,
resource_size(jz_battery->mem), pdev->name);
if (!jz_battery->mem) {
ret = -EBUSY;
dev_err(&pdev->dev, "Failed to request mmio memory region\n");
goto err_free;
}
jz_battery->base = ioremap_nocache(jz_battery->mem->start,
resource_size(jz_battery->mem));
if (!jz_battery->base) {
ret = -EBUSY;
dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
goto err_release_mem_region;
}
jz_battery->base = devm_request_and_ioremap(&pdev->dev, mem);
if (!jz_battery->base)
return -EBUSY;
battery = &jz_battery->battery;
battery->name = pdata->info.name;
@@ -309,7 +291,7 @@ static int jz_battery_probe(struct platform_device *pdev)
jz_battery);
if (ret) {
dev_err(&pdev->dev, "Failed to request irq %d\n", ret);
goto err_iounmap;
goto err;
}
disable_irq(jz_battery->irq);
@@ -366,13 +348,8 @@ err_free_gpio:
gpio_free(jz_battery->pdata->gpio_charge);
err_free_irq:
free_irq(jz_battery->irq, jz_battery);
err_iounmap:
err:
platform_set_drvdata(pdev, NULL);
iounmap(jz_battery->base);
err_release_mem_region:
release_mem_region(jz_battery->mem->start, resource_size(jz_battery->mem));
err_free:
kfree(jz_battery);
return ret;
}
@@ -392,10 +369,6 @@ static int jz_battery_remove(struct platform_device *pdev)
free_irq(jz_battery->irq, jz_battery);
iounmap(jz_battery->base);
release_mem_region(jz_battery->mem->start, resource_size(jz_battery->mem));
kfree(jz_battery);
return 0;
}

Some files were not shown because too many files have changed in this diff Show More