Highlights:
- Power supply notifier - Several drivers gained DT support - Added Maxim 14577 driver - Change of maintainer -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJS3bUsAAoJEBTbcu2+gGW4uC8QAJFPpPqnEjz9NnFjbngyTswc +Wq5kusHpdgIXCqx9+H26pm2NTyIm4uAcVn2XjYIvdKZbDvygNzMr8gPYpwWapJz 1K6ED1sZROhbvSKx0ADuGHz05Kwl78Kx6Qa+YtesGaKMaTxbJySWqh81zmYvN5Sq SoSqWC866bJwL4BVFIi7qZzHuD4czMP+iI8nrDKm1OFpj94y6DzC+BNxruYRCieI k+EEjTR6sKfQ0XFNxhyWSxxZtcxexVNvck7wsMleUUGysWHFjIu8HF01o9v58mt9 o/Tr8ZAHx8h0vPVtFF4ugnc+LZHwodqlcoFj1Q+5w3AsGYZUVMOIv2wY7gQZnRTj UcDXC06fG1ODMuBc1IUZy4j1ABAk+xoNW7zylMdtpgNDTpYdF5Mfy/yuD1eu5wzT SZyRpuCfoXEP1MDt+lcgBwakb4nh4HFgnzxbKWNwzKSsbJ/ZOHja5k4xe+aQ8yQX VmifBL8WUSYj97UQVy44/9DxSI7hE4GN7oXBKN2G/an5inqceePNDl89dymywBi1 NpWGX7a2NcQpdP+EpwLPuMU/J8SC5rzPWgMttpablrFSY0NQYJhmL3AdEcROP5gf cclLaT+UKgSTxOdAN4b8PIlMmffhJjvfBdxMsBaxe8PtLkRaXyXRcBkH/eDEsk7S Jj+gZOgLoThqJSK/IbB3 =QMHd -----END PGP SIGNATURE----- Merge tag 'for-v3.14' of git://git.infradead.org/battery-2.6 Pull battery updates from Dmitry Eremin-Solenikov: "I'm picking up power supply maintainership from Anton Vorontov. Could you please pull battery-2.6 git tree changes prepared for the v3.14 release. Highlights: - Power supply notifier - Several drivers gained DT support - Added Maxim 14577 driver - Change of maintainer" * tag 'for-v3.14' of git://git.infradead.org/battery-2.6: MAINTAINERS: Pick up power supply maintainership max17042_battery: Add IRQF_ONESHOT flag to use default irq handler gpio-charger: Support wakeup events power_supply: Add charger support for Maxim 14577 dt: Binding documentation for isp1704 charger isp1704_charger: Add DT support charger-manager: of_cm_parse_desc() should be static bq2415x_charger: Add DT support power_supply: Add power_supply_get_by_phandle bq2415x_charger: Use power_supply notifier for automode power: reset: Add as3722 power-off driver mfd: AS3722: Add dt node properties for system power controller charger-manager: Support deivce tree in charger manager driver charger-manager: Modify the way of checking battery's temperature power_supply: Add power_supply notifier
This commit is contained in:
commit
03d11a0e45
|
@ -112,6 +112,15 @@ Following are properties of regulator subnode.
|
||||||
ams,enable-tracking: Enable tracking with SD1, only supported
|
ams,enable-tracking: Enable tracking with SD1, only supported
|
||||||
by LDO3.
|
by LDO3.
|
||||||
|
|
||||||
|
Power-off:
|
||||||
|
=========
|
||||||
|
AS3722 supports the system power off by turning off all its rail. This
|
||||||
|
is provided through pm_power_off.
|
||||||
|
The device node should have the following properties to enable this
|
||||||
|
functionality
|
||||||
|
ams,system-power-controller: Boolean, to enable the power off functionality
|
||||||
|
through this device.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
--------
|
--------
|
||||||
#include <dt-bindings/mfd/as3722.h>
|
#include <dt-bindings/mfd/as3722.h>
|
||||||
|
@ -120,6 +129,8 @@ ams3722 {
|
||||||
compatible = "ams,as3722";
|
compatible = "ams,as3722";
|
||||||
reg = <0x48>;
|
reg = <0x48>;
|
||||||
|
|
||||||
|
ams,system-power-controller;
|
||||||
|
|
||||||
interrupt-parent = <&intc>;
|
interrupt-parent = <&intc>;
|
||||||
interrupt-controller;
|
interrupt-controller;
|
||||||
#interrupt-cells = <2>;
|
#interrupt-cells = <2>;
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
Binding for NXP ISP1704 USB Charger Detection
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible: Should contain one of the following:
|
||||||
|
* "nxp,isp1704"
|
||||||
|
- nxp,enable-gpio: Should contain a phandle + gpio-specifier
|
||||||
|
to the GPIO pin connected to the chip's enable pin.
|
||||||
|
- usb-phy: Should contain a phandle to the USB PHY
|
||||||
|
the ISP1704 is connected to.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
isp1704 {
|
||||||
|
compatible = "nxp,isp1704";
|
||||||
|
nxp,enable-gpio = <&gpio3 3 GPIO_ACTIVE_LOW>;
|
||||||
|
usb-phy = <&usb2_phy>;
|
||||||
|
};
|
|
@ -0,0 +1,81 @@
|
||||||
|
charger-manager bindings
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Required properties :
|
||||||
|
- compatible : "charger-manager"
|
||||||
|
- <>-supply : for regulator consumer
|
||||||
|
- cm-num-chargers : number of chargers
|
||||||
|
- cm-chargers : name of chargers
|
||||||
|
- cm-fuel-gauge : name of battery fuel gauge
|
||||||
|
- subnode <regulator> :
|
||||||
|
- cm-regulator-name : name of charger regulator
|
||||||
|
- subnode <cable> :
|
||||||
|
- cm-cable-name : name of charger cable
|
||||||
|
- cm-cable-extcon : name of extcon dev
|
||||||
|
(optional) - cm-cable-min : minimum current of cable
|
||||||
|
(optional) - cm-cable-max : maximum current of cable
|
||||||
|
|
||||||
|
Optional properties :
|
||||||
|
- cm-name : charger manager's name (default : "battery")
|
||||||
|
- cm-poll-mode : polling mode (enum polling_modes)
|
||||||
|
- cm-poll-interval : polling interval
|
||||||
|
- cm-battery-stat : battery status (enum data_source)
|
||||||
|
- cm-fullbatt-* : data for full battery checking
|
||||||
|
- cm-thermal-zone : name of external thermometer's thermal zone
|
||||||
|
- cm-battery-* : threshold battery temperature for charging
|
||||||
|
-cold : critical cold temperature of battery for charging
|
||||||
|
-cold-in-minus : flag that cold temerature is in minus degree
|
||||||
|
-hot : critical hot temperature of battery for charging
|
||||||
|
-temp-diff : temperature difference to allow recharging
|
||||||
|
- cm-dis/charging-max = limits of charging duration
|
||||||
|
|
||||||
|
Example :
|
||||||
|
charger-manager@0 {
|
||||||
|
compatible = "charger-manager";
|
||||||
|
chg-reg-supply = <&charger_regulator>;
|
||||||
|
|
||||||
|
cm-name = "battery";
|
||||||
|
/* Always polling ON : 30s */
|
||||||
|
cm-poll-mode = <1>;
|
||||||
|
cm-poll-interval = <30000>;
|
||||||
|
|
||||||
|
cm-fullbatt-vchkdrop-ms = <30000>;
|
||||||
|
cm-fullbatt-vchkdrop-volt = <150000>;
|
||||||
|
cm-fullbatt-soc = <100>;
|
||||||
|
|
||||||
|
cm-battery-stat = <3>;
|
||||||
|
|
||||||
|
cm-num-chargers = <3>;
|
||||||
|
cm-chargers = "charger0", "charger1", "charger2";
|
||||||
|
|
||||||
|
cm-fuel-gauge = "fuelgauge0";
|
||||||
|
|
||||||
|
cm-thermal-zone = "thermal_zone.1"
|
||||||
|
/* in deci centigrade */
|
||||||
|
cm-battery-cold = <50>;
|
||||||
|
cm-battery-cold-in-minus;
|
||||||
|
cm-battery-hot = <800>;
|
||||||
|
cm-battery-temp-diff = <100>;
|
||||||
|
|
||||||
|
/* Allow charging for 5hr */
|
||||||
|
cm-charging-max = <18000000>;
|
||||||
|
/* Allow discharging for 2hr */
|
||||||
|
cm-discharging-max = <7200000>;
|
||||||
|
|
||||||
|
regulator@0 {
|
||||||
|
cm-regulator-name = "chg-reg";
|
||||||
|
cable@0 {
|
||||||
|
cm-cable-name = "USB";
|
||||||
|
cm-cable-extcon = "extcon-dev.0";
|
||||||
|
cm-cable-min = <475000>;
|
||||||
|
cm-cable-max = <500000>;
|
||||||
|
};
|
||||||
|
cable@1 {
|
||||||
|
cm-cable-name = "TA";
|
||||||
|
cm-cable-extcon = "extcon-dev.0";
|
||||||
|
cm-cable-min = <650000>;
|
||||||
|
cm-cable-max = <675000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
|
@ -6712,7 +6712,7 @@ F: include/linux/timer*
|
||||||
F: kernel/*timer*
|
F: kernel/*timer*
|
||||||
|
|
||||||
POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS
|
POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS
|
||||||
M: Anton Vorontsov <anton@enomsg.org>
|
M: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
|
||||||
M: David Woodhouse <dwmw2@infradead.org>
|
M: David Woodhouse <dwmw2@infradead.org>
|
||||||
T: git git://git.infradead.org/battery-2.6.git
|
T: git git://git.infradead.org/battery-2.6.git
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
|
@ -317,6 +317,13 @@ config CHARGER_MANAGER
|
||||||
runtime and in suspend-to-RAM by waking up the system periodically
|
runtime and in suspend-to-RAM by waking up the system periodically
|
||||||
with help of suspend_again support.
|
with help of suspend_again support.
|
||||||
|
|
||||||
|
config CHARGER_MAX14577
|
||||||
|
tristate "Maxim MAX14577 MUIC battery charger driver"
|
||||||
|
depends on MFD_MAX14577
|
||||||
|
help
|
||||||
|
Say Y to enable support for the battery charger control sysfs and
|
||||||
|
platform data of MAX14577 MUICs.
|
||||||
|
|
||||||
config CHARGER_MAX8997
|
config CHARGER_MAX8997
|
||||||
tristate "Maxim MAX8997/MAX8966 PMIC battery charger driver"
|
tristate "Maxim MAX8997/MAX8966 PMIC battery charger driver"
|
||||||
depends on MFD_MAX8997 && REGULATOR_MAX8997
|
depends on MFD_MAX8997 && REGULATOR_MAX8997
|
||||||
|
|
|
@ -48,6 +48,7 @@ obj-$(CONFIG_CHARGER_LP8727) += lp8727_charger.o
|
||||||
obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o
|
obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o
|
||||||
obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
|
obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
|
||||||
obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o
|
obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o
|
||||||
|
obj-$(CONFIG_CHARGER_MAX14577) += max14577_charger.o
|
||||||
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
|
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
|
||||||
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
|
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
|
||||||
obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o
|
obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* bq2415x charger driver
|
* bq2415x charger driver
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
|
* Copyright (C) 2011-2013 Pali Rohár <pali.rohar@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -170,6 +170,8 @@ struct bq2415x_device {
|
||||||
struct bq2415x_platform_data init_data;
|
struct bq2415x_platform_data init_data;
|
||||||
struct power_supply charger;
|
struct power_supply charger;
|
||||||
struct delayed_work work;
|
struct delayed_work work;
|
||||||
|
struct power_supply *notify_psy;
|
||||||
|
struct notifier_block nb;
|
||||||
enum bq2415x_mode reported_mode;/* mode reported by hook function */
|
enum bq2415x_mode reported_mode;/* mode reported by hook function */
|
||||||
enum bq2415x_mode mode; /* current configured mode */
|
enum bq2415x_mode mode; /* current configured mode */
|
||||||
enum bq2415x_chip chip;
|
enum bq2415x_chip chip;
|
||||||
|
@ -795,24 +797,53 @@ static int bq2415x_set_mode(struct bq2415x_device *bq, enum bq2415x_mode mode)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hook function called by other driver which set reported mode */
|
static int bq2415x_notifier_call(struct notifier_block *nb,
|
||||||
static void bq2415x_hook_function(enum bq2415x_mode mode, void *data)
|
unsigned long val, void *v)
|
||||||
{
|
{
|
||||||
struct bq2415x_device *bq = data;
|
struct bq2415x_device *bq =
|
||||||
|
container_of(nb, struct bq2415x_device, nb);
|
||||||
|
struct power_supply *psy = v;
|
||||||
|
enum bq2415x_mode mode;
|
||||||
|
union power_supply_propval prop;
|
||||||
|
int ret;
|
||||||
|
int mA;
|
||||||
|
|
||||||
if (!bq)
|
if (val != PSY_EVENT_PROP_CHANGED)
|
||||||
return;
|
return NOTIFY_OK;
|
||||||
|
|
||||||
|
if (psy != bq->notify_psy)
|
||||||
|
return NOTIFY_OK;
|
||||||
|
|
||||||
|
dev_dbg(bq->dev, "notifier call was called\n");
|
||||||
|
|
||||||
|
ret = psy->get_property(psy, POWER_SUPPLY_PROP_CURRENT_MAX, &prop);
|
||||||
|
if (ret != 0)
|
||||||
|
return NOTIFY_OK;
|
||||||
|
|
||||||
|
mA = prop.intval;
|
||||||
|
|
||||||
|
if (mA == 0)
|
||||||
|
mode = BQ2415X_MODE_OFF;
|
||||||
|
else if (mA < 500)
|
||||||
|
mode = BQ2415X_MODE_NONE;
|
||||||
|
else if (mA < 1800)
|
||||||
|
mode = BQ2415X_MODE_HOST_CHARGER;
|
||||||
|
else
|
||||||
|
mode = BQ2415X_MODE_DEDICATED_CHARGER;
|
||||||
|
|
||||||
|
if (bq->reported_mode == mode)
|
||||||
|
return NOTIFY_OK;
|
||||||
|
|
||||||
dev_dbg(bq->dev, "hook function was called\n");
|
|
||||||
bq->reported_mode = mode;
|
bq->reported_mode = mode;
|
||||||
|
|
||||||
/* if automode is not enabled do not tell about reported_mode */
|
/* if automode is not enabled do not tell about reported_mode */
|
||||||
if (bq->automode < 1)
|
if (bq->automode < 1)
|
||||||
return;
|
return NOTIFY_OK;
|
||||||
|
|
||||||
sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode");
|
sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode");
|
||||||
bq2415x_set_mode(bq, bq->reported_mode);
|
bq2415x_set_mode(bq, bq->reported_mode);
|
||||||
|
|
||||||
|
return NOTIFY_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**** timer functions ****/
|
/**** timer functions ****/
|
||||||
|
@ -1512,9 +1543,11 @@ static int bq2415x_probe(struct i2c_client *client,
|
||||||
int num;
|
int num;
|
||||||
char *name;
|
char *name;
|
||||||
struct bq2415x_device *bq;
|
struct bq2415x_device *bq;
|
||||||
|
struct device_node *np = client->dev.of_node;
|
||||||
|
struct bq2415x_platform_data *pdata = client->dev.platform_data;
|
||||||
|
|
||||||
if (!client->dev.platform_data) {
|
if (!np && !pdata) {
|
||||||
dev_err(&client->dev, "platform data not set\n");
|
dev_err(&client->dev, "platform data missing\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1539,6 +1572,17 @@ static int bq2415x_probe(struct i2c_client *client,
|
||||||
goto error_2;
|
goto error_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (np) {
|
||||||
|
bq->notify_psy = power_supply_get_by_phandle(np, "ti,usb-charger-detection");
|
||||||
|
|
||||||
|
if (!bq->notify_psy)
|
||||||
|
return -EPROBE_DEFER;
|
||||||
|
}
|
||||||
|
else if (pdata->notify_device)
|
||||||
|
bq->notify_psy = power_supply_get_by_name(pdata->notify_device);
|
||||||
|
else
|
||||||
|
bq->notify_psy = NULL;
|
||||||
|
|
||||||
i2c_set_clientdata(client, bq);
|
i2c_set_clientdata(client, bq);
|
||||||
|
|
||||||
bq->id = num;
|
bq->id = num;
|
||||||
|
@ -1550,8 +1594,34 @@ static int bq2415x_probe(struct i2c_client *client,
|
||||||
bq->autotimer = 0;
|
bq->autotimer = 0;
|
||||||
bq->automode = 0;
|
bq->automode = 0;
|
||||||
|
|
||||||
memcpy(&bq->init_data, client->dev.platform_data,
|
if (np) {
|
||||||
sizeof(bq->init_data));
|
ret = of_property_read_u32(np, "ti,current-limit",
|
||||||
|
&bq->init_data.current_limit);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
ret = of_property_read_u32(np, "ti,weak-battery-voltage",
|
||||||
|
&bq->init_data.weak_battery_voltage);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
ret = of_property_read_u32(np, "ti,battery-regulation-voltage",
|
||||||
|
&bq->init_data.battery_regulation_voltage);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
ret = of_property_read_u32(np, "ti,charge-current",
|
||||||
|
&bq->init_data.charge_current);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
ret = of_property_read_u32(np, "ti,termination-current",
|
||||||
|
&bq->init_data.termination_current);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
ret = of_property_read_u32(np, "ti,resistor-sense",
|
||||||
|
&bq->init_data.resistor_sense);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
memcpy(&bq->init_data, pdata, sizeof(bq->init_data));
|
||||||
|
}
|
||||||
|
|
||||||
bq2415x_reset_chip(bq);
|
bq2415x_reset_chip(bq);
|
||||||
|
|
||||||
|
@ -1573,16 +1643,20 @@ static int bq2415x_probe(struct i2c_client *client,
|
||||||
goto error_4;
|
goto error_4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bq->init_data.set_mode_hook) {
|
if (bq->notify_psy) {
|
||||||
if (bq->init_data.set_mode_hook(
|
bq->nb.notifier_call = bq2415x_notifier_call;
|
||||||
bq2415x_hook_function, bq)) {
|
ret = power_supply_reg_notifier(&bq->nb);
|
||||||
bq->automode = 1;
|
if (ret) {
|
||||||
bq2415x_set_mode(bq, bq->reported_mode);
|
dev_err(bq->dev, "failed to reg notifier: %d\n", ret);
|
||||||
dev_info(bq->dev, "automode enabled\n");
|
goto error_5;
|
||||||
} else {
|
|
||||||
bq->automode = -1;
|
|
||||||
dev_info(bq->dev, "automode failed\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Query for initial reported_mode and set it */
|
||||||
|
bq2415x_notifier_call(&bq->nb, PSY_EVENT_PROP_CHANGED, bq->notify_psy);
|
||||||
|
bq2415x_set_mode(bq, bq->reported_mode);
|
||||||
|
|
||||||
|
bq->automode = 1;
|
||||||
|
dev_info(bq->dev, "automode enabled\n");
|
||||||
} else {
|
} else {
|
||||||
bq->automode = -1;
|
bq->automode = -1;
|
||||||
dev_info(bq->dev, "automode not supported\n");
|
dev_info(bq->dev, "automode not supported\n");
|
||||||
|
@ -1594,6 +1668,7 @@ static int bq2415x_probe(struct i2c_client *client,
|
||||||
dev_info(bq->dev, "driver registered\n");
|
dev_info(bq->dev, "driver registered\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error_5:
|
||||||
error_4:
|
error_4:
|
||||||
bq2415x_sysfs_exit(bq);
|
bq2415x_sysfs_exit(bq);
|
||||||
error_3:
|
error_3:
|
||||||
|
@ -1614,8 +1689,8 @@ static int bq2415x_remove(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct bq2415x_device *bq = i2c_get_clientdata(client);
|
struct bq2415x_device *bq = i2c_get_clientdata(client);
|
||||||
|
|
||||||
if (bq->init_data.set_mode_hook)
|
if (bq->notify_psy)
|
||||||
bq->init_data.set_mode_hook(NULL, NULL);
|
power_supply_unreg_notifier(&bq->nb);
|
||||||
|
|
||||||
bq2415x_sysfs_exit(bq);
|
bq2415x_sysfs_exit(bq);
|
||||||
bq2415x_power_supply_exit(bq);
|
bq2415x_power_supply_exit(bq);
|
||||||
|
|
|
@ -25,12 +25,23 @@
|
||||||
#include <linux/power/charger-manager.h>
|
#include <linux/power/charger-manager.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
#include <linux/sysfs.h>
|
#include <linux/sysfs.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/thermal.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default termperature threshold for charging.
|
||||||
|
* Every temperature units are in tenth of centigrade.
|
||||||
|
*/
|
||||||
|
#define CM_DEFAULT_RECHARGE_TEMP_DIFF 50
|
||||||
|
#define CM_DEFAULT_CHARGE_TEMP_MAX 500
|
||||||
|
|
||||||
static const char * const default_event_names[] = {
|
static const char * const default_event_names[] = {
|
||||||
[CM_EVENT_UNKNOWN] = "Unknown",
|
[CM_EVENT_UNKNOWN] = "Unknown",
|
||||||
[CM_EVENT_BATT_FULL] = "Battery Full",
|
[CM_EVENT_BATT_FULL] = "Battery Full",
|
||||||
[CM_EVENT_BATT_IN] = "Battery Inserted",
|
[CM_EVENT_BATT_IN] = "Battery Inserted",
|
||||||
[CM_EVENT_BATT_OUT] = "Battery Pulled Out",
|
[CM_EVENT_BATT_OUT] = "Battery Pulled Out",
|
||||||
|
[CM_EVENT_BATT_OVERHEAT] = "Battery Overheat",
|
||||||
|
[CM_EVENT_BATT_COLD] = "Battery Cold",
|
||||||
[CM_EVENT_EXT_PWR_IN_OUT] = "External Power Attach/Detach",
|
[CM_EVENT_EXT_PWR_IN_OUT] = "External Power Attach/Detach",
|
||||||
[CM_EVENT_CHG_START_STOP] = "Charging Start/Stop",
|
[CM_EVENT_CHG_START_STOP] = "Charging Start/Stop",
|
||||||
[CM_EVENT_OTHERS] = "Other battery events"
|
[CM_EVENT_OTHERS] = "Other battery events"
|
||||||
|
@ -518,7 +529,7 @@ static int check_charging_duration(struct charger_manager *cm)
|
||||||
duration = curr - cm->charging_start_time;
|
duration = curr - cm->charging_start_time;
|
||||||
|
|
||||||
if (duration > desc->charging_max_duration_ms) {
|
if (duration > desc->charging_max_duration_ms) {
|
||||||
dev_info(cm->dev, "Charging duration exceed %lldms\n",
|
dev_info(cm->dev, "Charging duration exceed %ums\n",
|
||||||
desc->charging_max_duration_ms);
|
desc->charging_max_duration_ms);
|
||||||
uevent_notify(cm, "Discharging");
|
uevent_notify(cm, "Discharging");
|
||||||
try_charger_enable(cm, false);
|
try_charger_enable(cm, false);
|
||||||
|
@ -529,7 +540,7 @@ static int check_charging_duration(struct charger_manager *cm)
|
||||||
|
|
||||||
if (duration > desc->charging_max_duration_ms &&
|
if (duration > desc->charging_max_duration_ms &&
|
||||||
is_ext_pwr_online(cm)) {
|
is_ext_pwr_online(cm)) {
|
||||||
dev_info(cm->dev, "Discharging duration exceed %lldms\n",
|
dev_info(cm->dev, "Discharging duration exceed %ums\n",
|
||||||
desc->discharging_max_duration_ms);
|
desc->discharging_max_duration_ms);
|
||||||
uevent_notify(cm, "Recharging");
|
uevent_notify(cm, "Recharging");
|
||||||
try_charger_enable(cm, true);
|
try_charger_enable(cm, true);
|
||||||
|
@ -540,6 +551,60 @@ static int check_charging_duration(struct charger_manager *cm)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cm_get_battery_temperature(struct charger_manager *cm,
|
||||||
|
int *temp)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!cm->desc->measure_battery_temp)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
#ifdef CONFIG_THERMAL
|
||||||
|
ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long *)temp);
|
||||||
|
if (!ret)
|
||||||
|
/* Calibrate temperature unit */
|
||||||
|
*temp /= 100;
|
||||||
|
#else
|
||||||
|
ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
|
||||||
|
POWER_SUPPLY_PROP_TEMP,
|
||||||
|
(union power_supply_propval *)temp);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cm_check_thermal_status(struct charger_manager *cm)
|
||||||
|
{
|
||||||
|
struct charger_desc *desc = cm->desc;
|
||||||
|
int temp, upper_limit, lower_limit;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = cm_get_battery_temperature(cm, &temp);
|
||||||
|
if (ret) {
|
||||||
|
/* FIXME:
|
||||||
|
* No information of battery temperature might
|
||||||
|
* occur hazadous result. We have to handle it
|
||||||
|
* depending on battery type.
|
||||||
|
*/
|
||||||
|
dev_err(cm->dev, "Failed to get battery temperature\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
upper_limit = desc->temp_max;
|
||||||
|
lower_limit = desc->temp_min;
|
||||||
|
|
||||||
|
if (cm->emergency_stop) {
|
||||||
|
upper_limit -= desc->temp_diff;
|
||||||
|
lower_limit += desc->temp_diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temp > upper_limit)
|
||||||
|
ret = CM_EVENT_BATT_OVERHEAT;
|
||||||
|
else if (temp < lower_limit)
|
||||||
|
ret = CM_EVENT_BATT_COLD;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _cm_monitor - Monitor the temperature and return true for exceptions.
|
* _cm_monitor - Monitor the temperature and return true for exceptions.
|
||||||
* @cm: the Charger Manager representing the battery.
|
* @cm: the Charger Manager representing the battery.
|
||||||
|
@ -549,28 +614,22 @@ static int check_charging_duration(struct charger_manager *cm)
|
||||||
*/
|
*/
|
||||||
static bool _cm_monitor(struct charger_manager *cm)
|
static bool _cm_monitor(struct charger_manager *cm)
|
||||||
{
|
{
|
||||||
struct charger_desc *desc = cm->desc;
|
int temp_alrt;
|
||||||
int temp = desc->temperature_out_of_range(&cm->last_temp_mC);
|
|
||||||
|
|
||||||
dev_dbg(cm->dev, "monitoring (%2.2d.%3.3dC)\n",
|
temp_alrt = cm_check_thermal_status(cm);
|
||||||
cm->last_temp_mC / 1000, cm->last_temp_mC % 1000);
|
|
||||||
|
|
||||||
/* It has been stopped already */
|
/* It has been stopped already */
|
||||||
if (temp && cm->emergency_stop)
|
if (temp_alrt && cm->emergency_stop)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check temperature whether overheat or cold.
|
* Check temperature whether overheat or cold.
|
||||||
* If temperature is out of range normal state, stop charging.
|
* If temperature is out of range normal state, stop charging.
|
||||||
*/
|
*/
|
||||||
if (temp) {
|
if (temp_alrt) {
|
||||||
cm->emergency_stop = temp;
|
cm->emergency_stop = temp_alrt;
|
||||||
if (!try_charger_enable(cm, false)) {
|
if (!try_charger_enable(cm, false))
|
||||||
if (temp > 0)
|
uevent_notify(cm, default_event_names[temp_alrt]);
|
||||||
uevent_notify(cm, "OVERHEAT");
|
|
||||||
else
|
|
||||||
uevent_notify(cm, "COLD");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check whole charging duration and discharing duration
|
* Check whole charging duration and discharing duration
|
||||||
|
@ -802,21 +861,8 @@ static int charger_get_property(struct power_supply *psy,
|
||||||
POWER_SUPPLY_PROP_CURRENT_NOW, val);
|
POWER_SUPPLY_PROP_CURRENT_NOW, val);
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_TEMP:
|
case POWER_SUPPLY_PROP_TEMP:
|
||||||
/* in thenth of centigrade */
|
|
||||||
if (cm->last_temp_mC == INT_MIN)
|
|
||||||
desc->temperature_out_of_range(&cm->last_temp_mC);
|
|
||||||
val->intval = cm->last_temp_mC / 100;
|
|
||||||
if (!desc->measure_battery_temp)
|
|
||||||
ret = -ENODEV;
|
|
||||||
break;
|
|
||||||
case POWER_SUPPLY_PROP_TEMP_AMBIENT:
|
case POWER_SUPPLY_PROP_TEMP_AMBIENT:
|
||||||
/* in thenth of centigrade */
|
return cm_get_battery_temperature(cm, &val->intval);
|
||||||
if (cm->last_temp_mC == INT_MIN)
|
|
||||||
desc->temperature_out_of_range(&cm->last_temp_mC);
|
|
||||||
val->intval = cm->last_temp_mC / 100;
|
|
||||||
if (desc->measure_battery_temp)
|
|
||||||
ret = -ENODEV;
|
|
||||||
break;
|
|
||||||
case POWER_SUPPLY_PROP_CAPACITY:
|
case POWER_SUPPLY_PROP_CAPACITY:
|
||||||
if (!cm->fuel_gauge) {
|
if (!cm->fuel_gauge) {
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
|
@ -1439,9 +1485,183 @@ err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cm_init_thermal_data(struct charger_manager *cm)
|
||||||
|
{
|
||||||
|
struct charger_desc *desc = cm->desc;
|
||||||
|
union power_supply_propval val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Verify whether fuel gauge provides battery temperature */
|
||||||
|
ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
|
||||||
|
POWER_SUPPLY_PROP_TEMP, &val);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
cm->charger_psy.properties[cm->charger_psy.num_properties] =
|
||||||
|
POWER_SUPPLY_PROP_TEMP;
|
||||||
|
cm->charger_psy.num_properties++;
|
||||||
|
cm->desc->measure_battery_temp = true;
|
||||||
|
}
|
||||||
|
#ifdef CONFIG_THERMAL
|
||||||
|
cm->tzd_batt = cm->fuel_gauge->tzd;
|
||||||
|
|
||||||
|
if (ret && desc->thermal_zone) {
|
||||||
|
cm->tzd_batt =
|
||||||
|
thermal_zone_get_zone_by_name(desc->thermal_zone);
|
||||||
|
if (IS_ERR(cm->tzd_batt))
|
||||||
|
return PTR_ERR(cm->tzd_batt);
|
||||||
|
|
||||||
|
/* Use external thermometer */
|
||||||
|
cm->charger_psy.properties[cm->charger_psy.num_properties] =
|
||||||
|
POWER_SUPPLY_PROP_TEMP_AMBIENT;
|
||||||
|
cm->charger_psy.num_properties++;
|
||||||
|
cm->desc->measure_battery_temp = true;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (cm->desc->measure_battery_temp) {
|
||||||
|
/* NOTICE : Default allowable minimum charge temperature is 0 */
|
||||||
|
if (!desc->temp_max)
|
||||||
|
desc->temp_max = CM_DEFAULT_CHARGE_TEMP_MAX;
|
||||||
|
if (!desc->temp_diff)
|
||||||
|
desc->temp_diff = CM_DEFAULT_RECHARGE_TEMP_DIFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct of_device_id charger_manager_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "charger-manager",
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct charger_desc *of_cm_parse_desc(struct device *dev)
|
||||||
|
{
|
||||||
|
struct charger_desc *desc;
|
||||||
|
struct device_node *np = dev->of_node;
|
||||||
|
u32 poll_mode = CM_POLL_DISABLE;
|
||||||
|
u32 battery_stat = CM_NO_BATTERY;
|
||||||
|
int num_chgs = 0;
|
||||||
|
|
||||||
|
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
|
||||||
|
if (!desc)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
of_property_read_string(np, "cm-name", &desc->psy_name);
|
||||||
|
|
||||||
|
of_property_read_u32(np, "cm-poll-mode", &poll_mode);
|
||||||
|
desc->polling_mode = poll_mode;
|
||||||
|
|
||||||
|
of_property_read_u32(np, "cm-poll-interval",
|
||||||
|
&desc->polling_interval_ms);
|
||||||
|
|
||||||
|
of_property_read_u32(np, "cm-fullbatt-vchkdrop-ms",
|
||||||
|
&desc->fullbatt_vchkdrop_ms);
|
||||||
|
of_property_read_u32(np, "cm-fullbatt-vchkdrop-volt",
|
||||||
|
&desc->fullbatt_vchkdrop_uV);
|
||||||
|
of_property_read_u32(np, "cm-fullbatt-voltage", &desc->fullbatt_uV);
|
||||||
|
of_property_read_u32(np, "cm-fullbatt-soc", &desc->fullbatt_soc);
|
||||||
|
of_property_read_u32(np, "cm-fullbatt-capacity",
|
||||||
|
&desc->fullbatt_full_capacity);
|
||||||
|
|
||||||
|
of_property_read_u32(np, "cm-battery-stat", &battery_stat);
|
||||||
|
desc->battery_present = battery_stat;
|
||||||
|
|
||||||
|
/* chargers */
|
||||||
|
of_property_read_u32(np, "cm-num-chargers", &num_chgs);
|
||||||
|
if (num_chgs) {
|
||||||
|
/* Allocate empty bin at the tail of array */
|
||||||
|
desc->psy_charger_stat = devm_kzalloc(dev, sizeof(char *)
|
||||||
|
* (num_chgs + 1), GFP_KERNEL);
|
||||||
|
if (desc->psy_charger_stat) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < num_chgs; i++)
|
||||||
|
of_property_read_string_index(np, "cm-chargers",
|
||||||
|
i, &desc->psy_charger_stat[i]);
|
||||||
|
} else {
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
of_property_read_string(np, "cm-fuel-gauge", &desc->psy_fuel_gauge);
|
||||||
|
|
||||||
|
of_property_read_string(np, "cm-thermal-zone", &desc->thermal_zone);
|
||||||
|
|
||||||
|
of_property_read_u32(np, "cm-battery-cold", &desc->temp_min);
|
||||||
|
if (of_get_property(np, "cm-battery-cold-in-minus", NULL))
|
||||||
|
desc->temp_min *= -1;
|
||||||
|
of_property_read_u32(np, "cm-battery-hot", &desc->temp_max);
|
||||||
|
of_property_read_u32(np, "cm-battery-temp-diff", &desc->temp_diff);
|
||||||
|
|
||||||
|
of_property_read_u32(np, "cm-charging-max",
|
||||||
|
&desc->charging_max_duration_ms);
|
||||||
|
of_property_read_u32(np, "cm-discharging-max",
|
||||||
|
&desc->discharging_max_duration_ms);
|
||||||
|
|
||||||
|
/* battery charger regualtors */
|
||||||
|
desc->num_charger_regulators = of_get_child_count(np);
|
||||||
|
if (desc->num_charger_regulators) {
|
||||||
|
struct charger_regulator *chg_regs;
|
||||||
|
struct device_node *child;
|
||||||
|
|
||||||
|
chg_regs = devm_kzalloc(dev, sizeof(*chg_regs)
|
||||||
|
* desc->num_charger_regulators,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!chg_regs)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
desc->charger_regulators = chg_regs;
|
||||||
|
|
||||||
|
for_each_child_of_node(np, child) {
|
||||||
|
struct charger_cable *cables;
|
||||||
|
struct device_node *_child;
|
||||||
|
|
||||||
|
of_property_read_string(child, "cm-regulator-name",
|
||||||
|
&chg_regs->regulator_name);
|
||||||
|
|
||||||
|
/* charger cables */
|
||||||
|
chg_regs->num_cables = of_get_child_count(child);
|
||||||
|
if (chg_regs->num_cables) {
|
||||||
|
cables = devm_kzalloc(dev, sizeof(*cables)
|
||||||
|
* chg_regs->num_cables,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!cables)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
chg_regs->cables = cables;
|
||||||
|
|
||||||
|
for_each_child_of_node(child, _child) {
|
||||||
|
of_property_read_string(_child,
|
||||||
|
"cm-cable-name", &cables->name);
|
||||||
|
of_property_read_string(_child,
|
||||||
|
"cm-cable-extcon",
|
||||||
|
&cables->extcon_name);
|
||||||
|
of_property_read_u32(_child,
|
||||||
|
"cm-cable-min",
|
||||||
|
&cables->min_uA);
|
||||||
|
of_property_read_u32(_child,
|
||||||
|
"cm-cable-max",
|
||||||
|
&cables->max_uA);
|
||||||
|
cables++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chg_regs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct charger_desc *cm_get_drv_data(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
if (pdev->dev.of_node)
|
||||||
|
return of_cm_parse_desc(&pdev->dev);
|
||||||
|
return (struct charger_desc *)dev_get_platdata(&pdev->dev);
|
||||||
|
}
|
||||||
|
|
||||||
static int charger_manager_probe(struct platform_device *pdev)
|
static int charger_manager_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct charger_desc *desc = dev_get_platdata(&pdev->dev);
|
struct charger_desc *desc = cm_get_drv_data(pdev);
|
||||||
struct charger_manager *cm;
|
struct charger_manager *cm;
|
||||||
int ret = 0, i = 0;
|
int ret = 0, i = 0;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
|
@ -1470,7 +1690,6 @@ static int charger_manager_probe(struct platform_device *pdev)
|
||||||
/* Basic Values. Unspecified are Null or 0 */
|
/* Basic Values. Unspecified are Null or 0 */
|
||||||
cm->dev = &pdev->dev;
|
cm->dev = &pdev->dev;
|
||||||
cm->desc = desc;
|
cm->desc = desc;
|
||||||
cm->last_temp_mC = INT_MIN; /* denotes "unmeasured, yet" */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following two do not need to be errors.
|
* The following two do not need to be errors.
|
||||||
|
@ -1533,11 +1752,6 @@ static int charger_manager_probe(struct platform_device *pdev)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!desc->temperature_out_of_range) {
|
|
||||||
dev_err(&pdev->dev, "there is no temperature_out_of_range\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!desc->charging_max_duration_ms ||
|
if (!desc->charging_max_duration_ms ||
|
||||||
!desc->discharging_max_duration_ms) {
|
!desc->discharging_max_duration_ms) {
|
||||||
dev_info(&pdev->dev, "Cannot limit charging duration checking mechanism to prevent overcharge/overheat and control discharging duration\n");
|
dev_info(&pdev->dev, "Cannot limit charging duration checking mechanism to prevent overcharge/overheat and control discharging duration\n");
|
||||||
|
@ -1583,14 +1797,10 @@ static int charger_manager_probe(struct platform_device *pdev)
|
||||||
cm->charger_psy.num_properties++;
|
cm->charger_psy.num_properties++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (desc->measure_battery_temp) {
|
ret = cm_init_thermal_data(cm);
|
||||||
cm->charger_psy.properties[cm->charger_psy.num_properties] =
|
if (ret) {
|
||||||
POWER_SUPPLY_PROP_TEMP;
|
dev_err(&pdev->dev, "Failed to initialize thermal data\n");
|
||||||
cm->charger_psy.num_properties++;
|
cm->desc->measure_battery_temp = false;
|
||||||
} else {
|
|
||||||
cm->charger_psy.properties[cm->charger_psy.num_properties] =
|
|
||||||
POWER_SUPPLY_PROP_TEMP_AMBIENT;
|
|
||||||
cm->charger_psy.num_properties++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INIT_DELAYED_WORK(&cm->fullbatt_vchk_work, fullbatt_vchk);
|
INIT_DELAYED_WORK(&cm->fullbatt_vchk_work, fullbatt_vchk);
|
||||||
|
@ -1808,6 +2018,7 @@ static struct platform_driver charger_manager_driver = {
|
||||||
.name = "charger-manager",
|
.name = "charger-manager",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.pm = &charger_manager_pm,
|
.pm = &charger_manager_pm,
|
||||||
|
.of_match_table = charger_manager_match,
|
||||||
},
|
},
|
||||||
.probe = charger_manager_probe,
|
.probe = charger_manager_probe,
|
||||||
.remove = charger_manager_remove,
|
.remove = charger_manager_remove,
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
struct gpio_charger {
|
struct gpio_charger {
|
||||||
const struct gpio_charger_platform_data *pdata;
|
const struct gpio_charger_platform_data *pdata;
|
||||||
unsigned int irq;
|
unsigned int irq;
|
||||||
|
bool wakeup_enabled;
|
||||||
|
|
||||||
struct power_supply charger;
|
struct power_supply charger;
|
||||||
};
|
};
|
||||||
|
@ -136,6 +137,8 @@ static int gpio_charger_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
platform_set_drvdata(pdev, gpio_charger);
|
platform_set_drvdata(pdev, gpio_charger);
|
||||||
|
|
||||||
|
device_init_wakeup(&pdev->dev, 1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_gpio_free:
|
err_gpio_free:
|
||||||
|
@ -159,18 +162,32 @@ static int gpio_charger_remove(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
static int gpio_charger_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct gpio_charger *gpio_charger = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (device_may_wakeup(dev))
|
||||||
|
gpio_charger->wakeup_enabled =
|
||||||
|
enable_irq_wake(gpio_charger->irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int gpio_charger_resume(struct device *dev)
|
static int gpio_charger_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
struct gpio_charger *gpio_charger = platform_get_drvdata(pdev);
|
struct gpio_charger *gpio_charger = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
if (gpio_charger->wakeup_enabled)
|
||||||
|
disable_irq_wake(gpio_charger->irq);
|
||||||
power_supply_changed(&gpio_charger->charger);
|
power_supply_changed(&gpio_charger->charger);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, NULL, gpio_charger_resume);
|
static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops,
|
||||||
|
gpio_charger_suspend, gpio_charger_resume);
|
||||||
|
|
||||||
static struct platform_driver gpio_charger_driver = {
|
static struct platform_driver gpio_charger_driver = {
|
||||||
.probe = gpio_charger_probe,
|
.probe = gpio_charger_probe,
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/power_supply.h>
|
#include <linux/power_supply.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_gpio.h>
|
||||||
|
|
||||||
#include <linux/usb/otg.h>
|
#include <linux/usb/otg.h>
|
||||||
#include <linux/usb/ulpi.h>
|
#include <linux/usb/ulpi.h>
|
||||||
|
@ -88,6 +90,8 @@ static void isp1704_charger_set_power(struct isp1704_charger *isp, bool on)
|
||||||
|
|
||||||
if (board && board->set_power)
|
if (board && board->set_power)
|
||||||
board->set_power(on);
|
board->set_power(on);
|
||||||
|
else if (board)
|
||||||
|
gpio_set_value(board->enable_gpio, on);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -400,12 +404,47 @@ static int isp1704_charger_probe(struct platform_device *pdev)
|
||||||
struct isp1704_charger *isp;
|
struct isp1704_charger *isp;
|
||||||
int ret = -ENODEV;
|
int ret = -ENODEV;
|
||||||
|
|
||||||
|
struct isp1704_charger_data *pdata = dev_get_platdata(&pdev->dev);
|
||||||
|
struct device_node *np = pdev->dev.of_node;
|
||||||
|
|
||||||
|
if (np) {
|
||||||
|
int gpio = of_get_named_gpio(np, "nxp,enable-gpio", 0);
|
||||||
|
|
||||||
|
if (gpio < 0)
|
||||||
|
return gpio;
|
||||||
|
|
||||||
|
pdata = devm_kzalloc(&pdev->dev,
|
||||||
|
sizeof(struct isp1704_charger_data), GFP_KERNEL);
|
||||||
|
pdata->enable_gpio = gpio;
|
||||||
|
|
||||||
|
dev_info(&pdev->dev, "init gpio %d\n", pdata->enable_gpio);
|
||||||
|
|
||||||
|
ret = devm_gpio_request_one(&pdev->dev, pdata->enable_gpio,
|
||||||
|
GPIOF_OUT_INIT_HIGH, "isp1704_reset");
|
||||||
|
if (ret)
|
||||||
|
goto fail0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pdata) {
|
||||||
|
dev_err(&pdev->dev, "missing platform data!\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL);
|
isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL);
|
||||||
if (!isp)
|
if (!isp)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
isp->phy = usb_get_phy(USB_PHY_TYPE_USB2);
|
if (np)
|
||||||
if (IS_ERR_OR_NULL(isp->phy))
|
isp->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
|
||||||
|
else
|
||||||
|
isp->phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
|
||||||
|
|
||||||
|
if (IS_ERR(isp->phy)) {
|
||||||
|
ret = PTR_ERR(isp->phy);
|
||||||
|
goto fail0;
|
||||||
|
}
|
||||||
|
if (!isp->phy)
|
||||||
goto fail0;
|
goto fail0;
|
||||||
|
|
||||||
isp->dev = &pdev->dev;
|
isp->dev = &pdev->dev;
|
||||||
|
@ -464,7 +503,6 @@ fail2:
|
||||||
power_supply_unregister(&isp->psy);
|
power_supply_unregister(&isp->psy);
|
||||||
fail1:
|
fail1:
|
||||||
isp1704_charger_set_power(isp, 0);
|
isp1704_charger_set_power(isp, 0);
|
||||||
usb_put_phy(isp->phy);
|
|
||||||
fail0:
|
fail0:
|
||||||
dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret);
|
dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret);
|
||||||
|
|
||||||
|
@ -477,15 +515,23 @@ static int isp1704_charger_remove(struct platform_device *pdev)
|
||||||
|
|
||||||
usb_unregister_notifier(isp->phy, &isp->nb);
|
usb_unregister_notifier(isp->phy, &isp->nb);
|
||||||
power_supply_unregister(&isp->psy);
|
power_supply_unregister(&isp->psy);
|
||||||
usb_put_phy(isp->phy);
|
|
||||||
isp1704_charger_set_power(isp, 0);
|
isp1704_charger_set_power(isp, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
static const struct of_device_id omap_isp1704_of_match[] = {
|
||||||
|
{ .compatible = "nxp,isp1704", },
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, omap_isp1704_of_match);
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct platform_driver isp1704_charger_driver = {
|
static struct platform_driver isp1704_charger_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "isp1704_charger",
|
.name = "isp1704_charger",
|
||||||
|
.of_match_table = of_match_ptr(omap_isp1704_of_match),
|
||||||
},
|
},
|
||||||
.probe = isp1704_charger_probe,
|
.probe = isp1704_charger_probe,
|
||||||
.remove = isp1704_charger_remove,
|
.remove = isp1704_charger_remove,
|
||||||
|
|
|
@ -0,0 +1,311 @@
|
||||||
|
/*
|
||||||
|
* Battery charger driver for the Maxim 14577
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Samsung Electronics
|
||||||
|
* Krzysztof Kozlowski <k.kozlowski@samsung.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/power_supply.h>
|
||||||
|
#include <linux/mfd/max14577-private.h>
|
||||||
|
|
||||||
|
struct max14577_charger {
|
||||||
|
struct device *dev;
|
||||||
|
struct max14577 *max14577;
|
||||||
|
struct power_supply charger;
|
||||||
|
|
||||||
|
unsigned int charging_state;
|
||||||
|
unsigned int battery_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int max14577_get_charger_state(struct max14577_charger *chg)
|
||||||
|
{
|
||||||
|
struct regmap *rmap = chg->max14577->regmap;
|
||||||
|
int state = POWER_SUPPLY_STATUS_DISCHARGING;
|
||||||
|
u8 reg_data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Charging occurs only if:
|
||||||
|
* - CHGCTRL2/MBCHOSTEN == 1
|
||||||
|
* - STATUS2/CGMBC == 1
|
||||||
|
*
|
||||||
|
* TODO:
|
||||||
|
* - handle FULL after Top-off timer (EOC register may be off
|
||||||
|
* and the charger won't be charging although MBCHOSTEN is on)
|
||||||
|
* - handle properly dead-battery charging (respect timer)
|
||||||
|
* - handle timers (fast-charge and prequal) /MBCCHGERR/
|
||||||
|
*/
|
||||||
|
max14577_read_reg(rmap, MAX14577_CHG_REG_CHG_CTRL2, ®_data);
|
||||||
|
if ((reg_data & CHGCTRL2_MBCHOSTEN_MASK) == 0)
|
||||||
|
goto state_set;
|
||||||
|
|
||||||
|
max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, ®_data);
|
||||||
|
if (reg_data & STATUS3_CGMBC_MASK) {
|
||||||
|
/* Charger or USB-cable is connected */
|
||||||
|
if (reg_data & STATUS3_EOC_MASK)
|
||||||
|
state = POWER_SUPPLY_STATUS_FULL;
|
||||||
|
else
|
||||||
|
state = POWER_SUPPLY_STATUS_CHARGING;
|
||||||
|
goto state_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
state_set:
|
||||||
|
chg->charging_state = state;
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Supported charge types:
|
||||||
|
* - POWER_SUPPLY_CHARGE_TYPE_NONE
|
||||||
|
* - POWER_SUPPLY_CHARGE_TYPE_FAST
|
||||||
|
*/
|
||||||
|
static int max14577_get_charge_type(struct max14577_charger *chg)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* TODO: CHARGE_TYPE_TRICKLE (VCHGR_RC or EOC)?
|
||||||
|
* As spec says:
|
||||||
|
* [after reaching EOC interrupt]
|
||||||
|
* "When the battery is fully charged, the 30-minute (typ)
|
||||||
|
* top-off timer starts. The device continues to trickle
|
||||||
|
* charge the battery until the top-off timer runs out."
|
||||||
|
*/
|
||||||
|
if (max14577_get_charger_state(chg) == POWER_SUPPLY_STATUS_CHARGING)
|
||||||
|
return POWER_SUPPLY_CHARGE_TYPE_FAST;
|
||||||
|
return POWER_SUPPLY_CHARGE_TYPE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int max14577_get_online(struct max14577_charger *chg)
|
||||||
|
{
|
||||||
|
struct regmap *rmap = chg->max14577->regmap;
|
||||||
|
u8 reg_data;
|
||||||
|
|
||||||
|
max14577_read_reg(rmap, MAX14577_MUIC_REG_STATUS2, ®_data);
|
||||||
|
reg_data = ((reg_data & STATUS2_CHGTYP_MASK) >> STATUS2_CHGTYP_SHIFT);
|
||||||
|
switch (reg_data) {
|
||||||
|
case MAX14577_CHARGER_TYPE_USB:
|
||||||
|
case MAX14577_CHARGER_TYPE_DEDICATED_CHG:
|
||||||
|
case MAX14577_CHARGER_TYPE_SPECIAL_500MA:
|
||||||
|
case MAX14577_CHARGER_TYPE_SPECIAL_1A:
|
||||||
|
case MAX14577_CHARGER_TYPE_DEAD_BATTERY:
|
||||||
|
return 1;
|
||||||
|
case MAX14577_CHARGER_TYPE_NONE:
|
||||||
|
case MAX14577_CHARGER_TYPE_DOWNSTREAM_PORT:
|
||||||
|
case MAX14577_CHARGER_TYPE_RESERVED:
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Supported health statuses:
|
||||||
|
* - POWER_SUPPLY_HEALTH_DEAD
|
||||||
|
* - POWER_SUPPLY_HEALTH_OVERVOLTAGE
|
||||||
|
* - POWER_SUPPLY_HEALTH_GOOD
|
||||||
|
*/
|
||||||
|
static int max14577_get_battery_health(struct max14577_charger *chg)
|
||||||
|
{
|
||||||
|
struct regmap *rmap = chg->max14577->regmap;
|
||||||
|
int state = POWER_SUPPLY_HEALTH_GOOD;
|
||||||
|
u8 reg_data;
|
||||||
|
|
||||||
|
max14577_read_reg(rmap, MAX14577_MUIC_REG_STATUS2, ®_data);
|
||||||
|
reg_data = ((reg_data & STATUS2_CHGTYP_MASK) >> STATUS2_CHGTYP_SHIFT);
|
||||||
|
if (reg_data == MAX14577_CHARGER_TYPE_DEAD_BATTERY) {
|
||||||
|
state = POWER_SUPPLY_HEALTH_DEAD;
|
||||||
|
goto state_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, ®_data);
|
||||||
|
if (reg_data & STATUS3_OVP_MASK) {
|
||||||
|
state = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
|
||||||
|
goto state_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
state_set:
|
||||||
|
chg->battery_state = state;
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Always returns 1.
|
||||||
|
* The max14577 chip doesn't report any status of battery presence.
|
||||||
|
* Lets assume that it will always be used with some battery.
|
||||||
|
*/
|
||||||
|
static int max14577_get_present(struct max14577_charger *chg)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets charger registers to proper and safe default values.
|
||||||
|
* Some of these values are equal to defaults in MAX14577E
|
||||||
|
* data sheet but there are minor differences.
|
||||||
|
*/
|
||||||
|
static void max14577_charger_reg_init(struct max14577_charger *chg)
|
||||||
|
{
|
||||||
|
struct regmap *rmap = chg->max14577->regmap;
|
||||||
|
u8 reg_data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Charger-Type Manual Detection, default off (set CHGTYPMAN to 0)
|
||||||
|
* Charger-Detection Enable, default on (set CHGDETEN to 1)
|
||||||
|
* Combined mask of CHGDETEN and CHGTYPMAN will zero the CHGTYPMAN bit
|
||||||
|
*/
|
||||||
|
reg_data = 0x1 << CDETCTRL1_CHGDETEN_SHIFT;
|
||||||
|
max14577_update_reg(rmap, MAX14577_REG_CDETCTRL1,
|
||||||
|
CDETCTRL1_CHGDETEN_MASK | CDETCTRL1_CHGTYPMAN_MASK,
|
||||||
|
reg_data);
|
||||||
|
|
||||||
|
/* Battery Fast-Charge Timer, from SM-V700: 6hrs */
|
||||||
|
reg_data = 0x3 << CHGCTRL1_TCHW_SHIFT;
|
||||||
|
max14577_write_reg(rmap, MAX14577_REG_CHGCTRL1, reg_data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wall-Adapter Rapid Charge, default on
|
||||||
|
* Battery-Charger, default on
|
||||||
|
*/
|
||||||
|
reg_data = 0x1 << CHGCTRL2_VCHGR_RC_SHIFT;
|
||||||
|
reg_data |= 0x1 << CHGCTRL2_MBCHOSTEN_SHIFT;
|
||||||
|
max14577_write_reg(rmap, MAX14577_REG_CHGCTRL2, reg_data);
|
||||||
|
|
||||||
|
/* Battery-Charger Constant Voltage (CV) Mode, from SM-V700: 4.35V */
|
||||||
|
reg_data = 0xf << CHGCTRL3_MBCCVWRC_SHIFT;
|
||||||
|
max14577_write_reg(rmap, MAX14577_REG_CHGCTRL3, reg_data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fast Battery-Charge Current Low, default 200-950mA
|
||||||
|
* Fast Battery-Charge Current High, from SM-V700: 450mA
|
||||||
|
*/
|
||||||
|
reg_data = 0x1 << CHGCTRL4_MBCICHWRCL_SHIFT;
|
||||||
|
reg_data |= 0x5 << CHGCTRL4_MBCICHWRCH_SHIFT;
|
||||||
|
max14577_write_reg(rmap, MAX14577_REG_CHGCTRL4, reg_data);
|
||||||
|
|
||||||
|
/* End-of-Charge Current, from SM-V700: 50mA */
|
||||||
|
reg_data = 0x0 << CHGCTRL5_EOCS_SHIFT;
|
||||||
|
max14577_write_reg(rmap, MAX14577_REG_CHGCTRL5, reg_data);
|
||||||
|
|
||||||
|
/* Auto Charging Stop, default off */
|
||||||
|
reg_data = 0x0 << CHGCTRL6_AUTOSTOP_SHIFT;
|
||||||
|
max14577_write_reg(rmap, MAX14577_REG_CHGCTRL6, reg_data);
|
||||||
|
|
||||||
|
/* Overvoltage-Protection Threshold, from SM-V700: 6.5V */
|
||||||
|
reg_data = 0x2 << CHGCTRL7_OTPCGHCVS_SHIFT;
|
||||||
|
max14577_write_reg(rmap, MAX14577_REG_CHGCTRL7, reg_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Support property from charger */
|
||||||
|
static enum power_supply_property max14577_charger_props[] = {
|
||||||
|
POWER_SUPPLY_PROP_STATUS,
|
||||||
|
POWER_SUPPLY_PROP_CHARGE_TYPE,
|
||||||
|
POWER_SUPPLY_PROP_HEALTH,
|
||||||
|
POWER_SUPPLY_PROP_PRESENT,
|
||||||
|
POWER_SUPPLY_PROP_ONLINE,
|
||||||
|
POWER_SUPPLY_PROP_MODEL_NAME,
|
||||||
|
POWER_SUPPLY_PROP_MANUFACTURER,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *model_name = "MAX14577";
|
||||||
|
static const char *manufacturer = "Maxim Integrated";
|
||||||
|
|
||||||
|
static int max14577_charger_get_property(struct power_supply *psy,
|
||||||
|
enum power_supply_property psp,
|
||||||
|
union power_supply_propval *val)
|
||||||
|
{
|
||||||
|
struct max14577_charger *chg = container_of(psy,
|
||||||
|
struct max14577_charger,
|
||||||
|
charger);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
switch (psp) {
|
||||||
|
case POWER_SUPPLY_PROP_STATUS:
|
||||||
|
val->intval = max14577_get_charger_state(chg);
|
||||||
|
break;
|
||||||
|
case POWER_SUPPLY_PROP_CHARGE_TYPE:
|
||||||
|
val->intval = max14577_get_charge_type(chg);
|
||||||
|
break;
|
||||||
|
case POWER_SUPPLY_PROP_HEALTH:
|
||||||
|
val->intval = max14577_get_battery_health(chg);
|
||||||
|
break;
|
||||||
|
case POWER_SUPPLY_PROP_PRESENT:
|
||||||
|
val->intval = max14577_get_present(chg);
|
||||||
|
break;
|
||||||
|
case POWER_SUPPLY_PROP_ONLINE:
|
||||||
|
val->intval = max14577_get_online(chg);
|
||||||
|
break;
|
||||||
|
case POWER_SUPPLY_PROP_MODEL_NAME:
|
||||||
|
val->strval = model_name;
|
||||||
|
break;
|
||||||
|
case POWER_SUPPLY_PROP_MANUFACTURER:
|
||||||
|
val->strval = manufacturer;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int max14577_charger_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct max14577_charger *chg;
|
||||||
|
struct max14577 *max14577 = dev_get_drvdata(pdev->dev.parent);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
chg = devm_kzalloc(&pdev->dev, sizeof(*chg), GFP_KERNEL);
|
||||||
|
if (!chg)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, chg);
|
||||||
|
chg->dev = &pdev->dev;
|
||||||
|
chg->max14577 = max14577;
|
||||||
|
|
||||||
|
max14577_charger_reg_init(chg);
|
||||||
|
|
||||||
|
chg->charger.name = "max14577-charger",
|
||||||
|
chg->charger.type = POWER_SUPPLY_TYPE_BATTERY,
|
||||||
|
chg->charger.properties = max14577_charger_props,
|
||||||
|
chg->charger.num_properties = ARRAY_SIZE(max14577_charger_props),
|
||||||
|
chg->charger.get_property = max14577_charger_get_property,
|
||||||
|
|
||||||
|
ret = power_supply_register(&pdev->dev, &chg->charger);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&pdev->dev, "failed: power supply register\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int max14577_charger_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct max14577_charger *chg = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
power_supply_unregister(&chg->charger);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver max14577_charger_driver = {
|
||||||
|
.driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "max14577-charger",
|
||||||
|
},
|
||||||
|
.probe = max14577_charger_probe,
|
||||||
|
.remove = max14577_charger_remove,
|
||||||
|
};
|
||||||
|
module_platform_driver(max14577_charger_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Krzysztof Kozlowski <k.kozlowski@samsung.com>");
|
||||||
|
MODULE_DESCRIPTION("MAXIM 14577 charger driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
|
@ -741,9 +741,9 @@ static int max17042_probe(struct i2c_client *client,
|
||||||
|
|
||||||
if (client->irq) {
|
if (client->irq) {
|
||||||
ret = request_threaded_irq(client->irq, NULL,
|
ret = request_threaded_irq(client->irq, NULL,
|
||||||
max17042_thread_handler,
|
max17042_thread_handler,
|
||||||
IRQF_TRIGGER_FALLING,
|
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||||
chip->battery.name, chip);
|
chip->battery.name, chip);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
regmap_read(chip->regmap, MAX17042_CONFIG, &val);
|
regmap_read(chip->regmap, MAX17042_CONFIG, &val);
|
||||||
val |= CONFIG_ALRT_BIT_ENBL;
|
val |= CONFIG_ALRT_BIT_ENBL;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
#include <linux/notifier.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/power_supply.h>
|
#include <linux/power_supply.h>
|
||||||
#include <linux/thermal.h>
|
#include <linux/thermal.h>
|
||||||
|
@ -24,6 +25,9 @@
|
||||||
struct class *power_supply_class;
|
struct class *power_supply_class;
|
||||||
EXPORT_SYMBOL_GPL(power_supply_class);
|
EXPORT_SYMBOL_GPL(power_supply_class);
|
||||||
|
|
||||||
|
ATOMIC_NOTIFIER_HEAD(power_supply_notifier);
|
||||||
|
EXPORT_SYMBOL_GPL(power_supply_notifier);
|
||||||
|
|
||||||
static struct device_type power_supply_dev_type;
|
static struct device_type power_supply_dev_type;
|
||||||
|
|
||||||
static bool __power_supply_is_supplied_by(struct power_supply *supplier,
|
static bool __power_supply_is_supplied_by(struct power_supply *supplier,
|
||||||
|
@ -80,6 +84,8 @@ static void power_supply_changed_work(struct work_struct *work)
|
||||||
class_for_each_device(power_supply_class, NULL, psy,
|
class_for_each_device(power_supply_class, NULL, psy,
|
||||||
__power_supply_changed_work);
|
__power_supply_changed_work);
|
||||||
power_supply_update_leds(psy);
|
power_supply_update_leds(psy);
|
||||||
|
atomic_notifier_call_chain(&power_supply_notifier,
|
||||||
|
PSY_EVENT_PROP_CHANGED, psy);
|
||||||
kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE);
|
kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE);
|
||||||
spin_lock_irqsave(&psy->changed_lock, flags);
|
spin_lock_irqsave(&psy->changed_lock, flags);
|
||||||
}
|
}
|
||||||
|
@ -335,6 +341,32 @@ struct power_supply *power_supply_get_by_name(const char *name)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(power_supply_get_by_name);
|
EXPORT_SYMBOL_GPL(power_supply_get_by_name);
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
static int power_supply_match_device_node(struct device *dev, const void *data)
|
||||||
|
{
|
||||||
|
return dev->parent && dev->parent->of_node == data;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct power_supply *power_supply_get_by_phandle(struct device_node *np,
|
||||||
|
const char *property)
|
||||||
|
{
|
||||||
|
struct device_node *power_supply_np;
|
||||||
|
struct device *dev;
|
||||||
|
|
||||||
|
power_supply_np = of_parse_phandle(np, property, 0);
|
||||||
|
if (!power_supply_np)
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
|
dev = class_find_device(power_supply_class, NULL, power_supply_np,
|
||||||
|
power_supply_match_device_node);
|
||||||
|
|
||||||
|
of_node_put(power_supply_np);
|
||||||
|
|
||||||
|
return dev ? dev_get_drvdata(dev) : NULL;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(power_supply_get_by_phandle);
|
||||||
|
#endif /* CONFIG_OF */
|
||||||
|
|
||||||
int power_supply_powers(struct power_supply *psy, struct device *dev)
|
int power_supply_powers(struct power_supply *psy, struct device *dev)
|
||||||
{
|
{
|
||||||
return sysfs_create_link(&psy->dev->kobj, &dev->kobj, "powers");
|
return sysfs_create_link(&psy->dev->kobj, &dev->kobj, "powers");
|
||||||
|
@ -347,6 +379,18 @@ static void power_supply_dev_release(struct device *dev)
|
||||||
kfree(dev);
|
kfree(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int power_supply_reg_notifier(struct notifier_block *nb)
|
||||||
|
{
|
||||||
|
return atomic_notifier_chain_register(&power_supply_notifier, nb);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(power_supply_reg_notifier);
|
||||||
|
|
||||||
|
void power_supply_unreg_notifier(struct notifier_block *nb)
|
||||||
|
{
|
||||||
|
atomic_notifier_chain_unregister(&power_supply_notifier, nb);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(power_supply_unreg_notifier);
|
||||||
|
|
||||||
#ifdef CONFIG_THERMAL
|
#ifdef CONFIG_THERMAL
|
||||||
static int power_supply_read_temp(struct thermal_zone_device *tzd,
|
static int power_supply_read_temp(struct thermal_zone_device *tzd,
|
||||||
unsigned long *temp)
|
unsigned long *temp)
|
||||||
|
|
|
@ -6,6 +6,12 @@ menuconfig POWER_RESET
|
||||||
|
|
||||||
Say Y here to enable board reset and power off
|
Say Y here to enable board reset and power off
|
||||||
|
|
||||||
|
config POWER_RESET_AS3722
|
||||||
|
bool "ams AS3722 power-off driver"
|
||||||
|
depends on MFD_AS3722 && POWER_RESET
|
||||||
|
help
|
||||||
|
This driver supports turning off board via a ams AS3722 power-off.
|
||||||
|
|
||||||
config POWER_RESET_GPIO
|
config POWER_RESET_GPIO
|
||||||
bool "GPIO power-off driver"
|
bool "GPIO power-off driver"
|
||||||
depends on OF_GPIO && POWER_RESET
|
depends on OF_GPIO && POWER_RESET
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
|
||||||
obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
|
obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
|
||||||
obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
|
obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
|
||||||
obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
|
obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* Power off driver for ams AS3722 device.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
|
||||||
|
*
|
||||||
|
* Author: Laxman Dewangan <ldewangan@nvidia.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/mfd/as3722.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
struct as3722_poweroff {
|
||||||
|
struct device *dev;
|
||||||
|
struct as3722 *as3722;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct as3722_poweroff *as3722_pm_poweroff;
|
||||||
|
|
||||||
|
static void as3722_pm_power_off(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!as3722_pm_poweroff) {
|
||||||
|
pr_err("AS3722 poweroff is not initialised\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = as3722_update_bits(as3722_pm_poweroff->as3722,
|
||||||
|
AS3722_RESET_CONTROL_REG, AS3722_POWER_OFF, AS3722_POWER_OFF);
|
||||||
|
if (ret < 0)
|
||||||
|
dev_err(as3722_pm_poweroff->dev,
|
||||||
|
"RESET_CONTROL_REG update failed, %d\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int as3722_poweroff_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct as3722_poweroff *as3722_poweroff;
|
||||||
|
struct device_node *np = pdev->dev.parent->of_node;
|
||||||
|
|
||||||
|
if (!np)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!of_property_read_bool(np, "ams,system-power-controller"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
as3722_poweroff = devm_kzalloc(&pdev->dev, sizeof(*as3722_poweroff),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!as3722_poweroff)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
as3722_poweroff->as3722 = dev_get_drvdata(pdev->dev.parent);
|
||||||
|
as3722_poweroff->dev = &pdev->dev;
|
||||||
|
as3722_pm_poweroff = as3722_poweroff;
|
||||||
|
if (!pm_power_off)
|
||||||
|
pm_power_off = as3722_pm_power_off;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int as3722_poweroff_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
if (pm_power_off == as3722_pm_power_off)
|
||||||
|
pm_power_off = NULL;
|
||||||
|
as3722_pm_poweroff = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver as3722_poweroff_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "as3722-power-off",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
},
|
||||||
|
.probe = as3722_poweroff_probe,
|
||||||
|
.remove = as3722_poweroff_remove,
|
||||||
|
};
|
||||||
|
|
||||||
|
module_platform_driver(as3722_poweroff_driver);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Power off driver for ams AS3722 PMIC Device");
|
||||||
|
MODULE_ALIAS("platform:as3722-power-off");
|
||||||
|
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* bq2415x charger driver
|
* bq2415x charger driver
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
|
* Copyright (C) 2011-2013 Pali Rohár <pali.rohar@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -31,46 +31,9 @@
|
||||||
* termination current. It it is less or equal to zero, configuring charge
|
* termination current. It it is less or equal to zero, configuring charge
|
||||||
* and termination current will not be possible.
|
* and termination current will not be possible.
|
||||||
*
|
*
|
||||||
* Function set_mode_hook is needed for automode (setting correct current
|
* For automode support is needed to provide name of power supply device
|
||||||
* limit when charger is connected/disconnected or setting boost mode).
|
* in value notify_device. Device driver must immediately report property
|
||||||
* When is NULL, automode function is disabled. When is not NULL, it must
|
* POWER_SUPPLY_PROP_CURRENT_MAX when current changed.
|
||||||
* have this prototype:
|
|
||||||
*
|
|
||||||
* int (*set_mode_hook)(
|
|
||||||
* void (*hook)(enum bq2415x_mode mode, void *data),
|
|
||||||
* void *data)
|
|
||||||
*
|
|
||||||
* hook is hook function (see below) and data is pointer to driver private
|
|
||||||
* data
|
|
||||||
*
|
|
||||||
* bq2415x driver will call it as:
|
|
||||||
*
|
|
||||||
* platform_data->set_mode_hook(bq2415x_hook_function, bq2415x_device);
|
|
||||||
*
|
|
||||||
* Board/platform function set_mode_hook return non zero value when hook
|
|
||||||
* function was successful registered. Platform code should call that hook
|
|
||||||
* function (which get from pointer, with data) every time when charger
|
|
||||||
* was connected/disconnected or require to enable boost mode. bq2415x
|
|
||||||
* driver then will set correct current limit, enable/disable charger or
|
|
||||||
* boost mode.
|
|
||||||
*
|
|
||||||
* Hook function has this prototype:
|
|
||||||
*
|
|
||||||
* void hook(enum bq2415x_mode mode, void *data);
|
|
||||||
*
|
|
||||||
* mode is bq2415x mode (charger or boost)
|
|
||||||
* data is pointer to driver private data (which get from
|
|
||||||
* set_charger_type_hook)
|
|
||||||
*
|
|
||||||
* When bq driver is being unloaded, it call function:
|
|
||||||
*
|
|
||||||
* platform_data->set_mode_hook(NULL, NULL);
|
|
||||||
*
|
|
||||||
* (hook function and driver private data are NULL)
|
|
||||||
*
|
|
||||||
* After that board/platform code must not call driver hook function! It
|
|
||||||
* is possible that pointer to hook function will not be valid and calling
|
|
||||||
* will cause undefined result.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Supported modes with maximal current limit */
|
/* Supported modes with maximal current limit */
|
||||||
|
@ -89,8 +52,7 @@ struct bq2415x_platform_data {
|
||||||
int charge_current; /* mA */
|
int charge_current; /* mA */
|
||||||
int termination_current; /* mA */
|
int termination_current; /* mA */
|
||||||
int resistor_sense; /* m ohm */
|
int resistor_sense; /* m ohm */
|
||||||
int (*set_mode_hook)(void (*hook)(enum bq2415x_mode mode, void *data),
|
const char *notify_device; /* name */
|
||||||
void *data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -37,6 +37,8 @@ enum cm_event_types {
|
||||||
CM_EVENT_BATT_FULL,
|
CM_EVENT_BATT_FULL,
|
||||||
CM_EVENT_BATT_IN,
|
CM_EVENT_BATT_IN,
|
||||||
CM_EVENT_BATT_OUT,
|
CM_EVENT_BATT_OUT,
|
||||||
|
CM_EVENT_BATT_OVERHEAT,
|
||||||
|
CM_EVENT_BATT_COLD,
|
||||||
CM_EVENT_EXT_PWR_IN_OUT,
|
CM_EVENT_EXT_PWR_IN_OUT,
|
||||||
CM_EVENT_CHG_START_STOP,
|
CM_EVENT_CHG_START_STOP,
|
||||||
CM_EVENT_OTHERS,
|
CM_EVENT_OTHERS,
|
||||||
|
@ -173,11 +175,10 @@ struct charger_regulator {
|
||||||
* @num_charger_regulator: the number of entries in charger_regulators
|
* @num_charger_regulator: the number of entries in charger_regulators
|
||||||
* @charger_regulators: array of charger regulators
|
* @charger_regulators: array of charger regulators
|
||||||
* @psy_fuel_gauge: the name of power-supply for fuel gauge
|
* @psy_fuel_gauge: the name of power-supply for fuel gauge
|
||||||
* @temperature_out_of_range:
|
* @thermal_zone : the name of thermal zone for battery
|
||||||
* Determine whether the status is overheat or cold or normal.
|
* @temp_min : Minimum battery temperature for charging.
|
||||||
* return_value > 0: overheat
|
* @temp_max : Maximum battery temperature for charging.
|
||||||
* return_value == 0: normal
|
* @temp_diff : Temperature diffential to restart charging.
|
||||||
* return_value < 0: cold
|
|
||||||
* @measure_battery_temp:
|
* @measure_battery_temp:
|
||||||
* true: measure battery temperature
|
* true: measure battery temperature
|
||||||
* false: measure ambient temperature
|
* false: measure ambient temperature
|
||||||
|
@ -190,7 +191,7 @@ struct charger_regulator {
|
||||||
* max_duration_ms', cm start charging.
|
* max_duration_ms', cm start charging.
|
||||||
*/
|
*/
|
||||||
struct charger_desc {
|
struct charger_desc {
|
||||||
char *psy_name;
|
const char *psy_name;
|
||||||
|
|
||||||
enum polling_modes polling_mode;
|
enum polling_modes polling_mode;
|
||||||
unsigned int polling_interval_ms;
|
unsigned int polling_interval_ms;
|
||||||
|
@ -203,18 +204,23 @@ struct charger_desc {
|
||||||
|
|
||||||
enum data_source battery_present;
|
enum data_source battery_present;
|
||||||
|
|
||||||
char **psy_charger_stat;
|
const char **psy_charger_stat;
|
||||||
|
|
||||||
int num_charger_regulators;
|
int num_charger_regulators;
|
||||||
struct charger_regulator *charger_regulators;
|
struct charger_regulator *charger_regulators;
|
||||||
|
|
||||||
char *psy_fuel_gauge;
|
const char *psy_fuel_gauge;
|
||||||
|
|
||||||
|
const char *thermal_zone;
|
||||||
|
|
||||||
|
int temp_min;
|
||||||
|
int temp_max;
|
||||||
|
int temp_diff;
|
||||||
|
|
||||||
int (*temperature_out_of_range)(int *mC);
|
|
||||||
bool measure_battery_temp;
|
bool measure_battery_temp;
|
||||||
|
|
||||||
u64 charging_max_duration_ms;
|
u32 charging_max_duration_ms;
|
||||||
u64 discharging_max_duration_ms;
|
u32 discharging_max_duration_ms;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PSY_NAME_MAX 30
|
#define PSY_NAME_MAX 30
|
||||||
|
@ -226,13 +232,13 @@ struct charger_desc {
|
||||||
* @desc: instance of charger_desc
|
* @desc: instance of charger_desc
|
||||||
* @fuel_gauge: power_supply for fuel gauge
|
* @fuel_gauge: power_supply for fuel gauge
|
||||||
* @charger_stat: array of power_supply for chargers
|
* @charger_stat: array of power_supply for chargers
|
||||||
|
* @tzd_batt : thermal zone device for battery
|
||||||
* @charger_enabled: the state of charger
|
* @charger_enabled: the state of charger
|
||||||
* @fullbatt_vchk_jiffies_at:
|
* @fullbatt_vchk_jiffies_at:
|
||||||
* jiffies at the time full battery check will occur.
|
* jiffies at the time full battery check will occur.
|
||||||
* @fullbatt_vchk_work: work queue for full battery check
|
* @fullbatt_vchk_work: work queue for full battery check
|
||||||
* @emergency_stop:
|
* @emergency_stop:
|
||||||
* When setting true, stop charging
|
* When setting true, stop charging
|
||||||
* @last_temp_mC: the measured temperature in milli-Celsius
|
|
||||||
* @psy_name_buf: the name of power-supply-class for charger manager
|
* @psy_name_buf: the name of power-supply-class for charger manager
|
||||||
* @charger_psy: power_supply for charger manager
|
* @charger_psy: power_supply for charger manager
|
||||||
* @status_save_ext_pwr_inserted:
|
* @status_save_ext_pwr_inserted:
|
||||||
|
@ -250,13 +256,15 @@ struct charger_manager {
|
||||||
struct power_supply *fuel_gauge;
|
struct power_supply *fuel_gauge;
|
||||||
struct power_supply **charger_stat;
|
struct power_supply **charger_stat;
|
||||||
|
|
||||||
|
#ifdef CONFIG_THERMAL
|
||||||
|
struct thermal_zone_device *tzd_batt;
|
||||||
|
#endif
|
||||||
bool charger_enabled;
|
bool charger_enabled;
|
||||||
|
|
||||||
unsigned long fullbatt_vchk_jiffies_at;
|
unsigned long fullbatt_vchk_jiffies_at;
|
||||||
struct delayed_work fullbatt_vchk_work;
|
struct delayed_work fullbatt_vchk_work;
|
||||||
|
|
||||||
int emergency_stop;
|
int emergency_stop;
|
||||||
int last_temp_mC;
|
|
||||||
|
|
||||||
char psy_name_buf[PSY_NAME_MAX + 1];
|
char psy_name_buf[PSY_NAME_MAX + 1];
|
||||||
struct power_supply charger_psy;
|
struct power_supply charger_psy;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
struct isp1704_charger_data {
|
struct isp1704_charger_data {
|
||||||
void (*set_power)(bool on);
|
void (*set_power)(bool on);
|
||||||
|
int enable_gpio;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/leds.h>
|
#include <linux/leds.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/notifier.h>
|
||||||
|
|
||||||
struct device;
|
struct device;
|
||||||
|
|
||||||
|
@ -158,6 +159,10 @@ enum power_supply_type {
|
||||||
POWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */
|
POWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum power_supply_notifier_events {
|
||||||
|
PSY_EVENT_PROP_CHANGED,
|
||||||
|
};
|
||||||
|
|
||||||
union power_supply_propval {
|
union power_supply_propval {
|
||||||
int intval;
|
int intval;
|
||||||
const char *strval;
|
const char *strval;
|
||||||
|
@ -235,7 +240,18 @@ struct power_supply_info {
|
||||||
int use_for_apm;
|
int use_for_apm;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern struct atomic_notifier_head power_supply_notifier;
|
||||||
|
extern int power_supply_reg_notifier(struct notifier_block *nb);
|
||||||
|
extern void power_supply_unreg_notifier(struct notifier_block *nb);
|
||||||
extern struct power_supply *power_supply_get_by_name(const char *name);
|
extern struct power_supply *power_supply_get_by_name(const char *name);
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
extern struct power_supply *power_supply_get_by_phandle(struct device_node *np,
|
||||||
|
const char *property);
|
||||||
|
#else /* !CONFIG_OF */
|
||||||
|
static inline struct power_supply *
|
||||||
|
power_supply_get_by_phandle(struct device_node *np, const char *property)
|
||||||
|
{ return NULL; }
|
||||||
|
#endif /* CONFIG_OF */
|
||||||
extern void power_supply_changed(struct power_supply *psy);
|
extern void power_supply_changed(struct power_supply *psy);
|
||||||
extern int power_supply_am_i_supplied(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);
|
extern int power_supply_set_battery_charged(struct power_supply *psy);
|
||||||
|
|
Loading…
Reference in New Issue