Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
7d9d9b34
Commit
7d9d9b34
authored
Sep 15, 2009
by
Stephen Rothwell
Browse files
Options
Browse Files
Download
Plain Diff
Merge commit 'battery/master'
Conflicts: drivers/power/wm97xx_battery.c
parents
40e07231
3961f7c3
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
1331 additions
and
66 deletions
+1331
-66
Documentation/power/power_supply_class.txt
Documentation/power/power_supply_class.txt
+7
-0
drivers/input/touchscreen/wm97xx-core.c
drivers/input/touchscreen/wm97xx-core.c
+3
-0
drivers/power/Kconfig
drivers/power/Kconfig
+7
-0
drivers/power/Makefile
drivers/power/Makefile
+1
-0
drivers/power/ds2760_battery.c
drivers/power/ds2760_battery.c
+122
-25
drivers/power/olpc_battery.c
drivers/power/olpc_battery.c
+50
-0
drivers/power/power_supply_core.c
drivers/power/power_supply_core.c
+35
-9
drivers/power/power_supply_sysfs.c
drivers/power/power_supply_sysfs.c
+12
-0
drivers/power/wm831x_power.c
drivers/power/wm831x_power.c
+779
-0
drivers/power/wm8350_power.c
drivers/power/wm8350_power.c
+22
-0
drivers/power/wm97xx_battery.c
drivers/power/wm97xx_battery.c
+61
-18
include/linux/mfd/wm831x/pmu.h
include/linux/mfd/wm831x/pmu.h
+189
-0
include/linux/power_supply.h
include/linux/power_supply.h
+21
-0
include/linux/wm97xx.h
include/linux/wm97xx.h
+18
-0
include/linux/wm97xx_batt.h
include/linux/wm97xx_batt.h
+4
-14
No files found.
Documentation/power/power_supply_class.txt
View file @
7d9d9b34
...
...
@@ -76,6 +76,11 @@ STATUS - this attribute represents operating status (charging, full,
discharging (i.e. powering a load), etc.). This corresponds to
BATTERY_STATUS_* values, as defined in battery.h.
CHARGE_TYPE - batteries can typically charge at different rates.
This defines trickle and fast charges. For batteries that
are already charged or discharging, 'n/a' can be displayed (or
'unknown', if the status is not known).
HEALTH - represents health of the battery, values corresponds to
POWER_SUPPLY_HEALTH_*, defined in battery.h.
...
...
@@ -108,6 +113,8 @@ relative, time-based measurements.
ENERGY_FULL, ENERGY_EMPTY - same as above but for energy.
CAPACITY - capacity in percents.
CAPACITY_LEVEL - capacity level. This corresponds to
POWER_SUPPLY_CAPACITY_LEVEL_*.
TEMP - temperature of the power supply.
TEMP_AMBIENT - ambient temperature.
...
...
drivers/input/touchscreen/wm97xx-core.c
View file @
7d9d9b34
...
...
@@ -561,6 +561,7 @@ static void wm97xx_ts_input_close(struct input_dev *idev)
static
int
wm97xx_probe
(
struct
device
*
dev
)
{
struct
wm97xx
*
wm
;
struct
wm97xx_pdata
*
pdata
=
dev
->
platform_data
;
int
ret
=
0
,
id
=
0
;
wm
=
kzalloc
(
sizeof
(
struct
wm97xx
),
GFP_KERNEL
);
...
...
@@ -658,6 +659,7 @@ static int wm97xx_probe(struct device *dev)
}
platform_set_drvdata
(
wm
->
battery_dev
,
wm
);
wm
->
battery_dev
->
dev
.
parent
=
dev
;
wm
->
battery_dev
->
dev
.
platform_data
=
pdata
;
ret
=
platform_device_add
(
wm
->
battery_dev
);
if
(
ret
<
0
)
goto
batt_reg_err
;
...
...
@@ -671,6 +673,7 @@ static int wm97xx_probe(struct device *dev)
}
platform_set_drvdata
(
wm
->
touch_dev
,
wm
);
wm
->
touch_dev
->
dev
.
parent
=
dev
;
wm
->
touch_dev
->
dev
.
platform_data
=
pdata
;
ret
=
platform_device_add
(
wm
->
touch_dev
);
if
(
ret
<
0
)
goto
touch_reg_err
;
...
...
drivers/power/Kconfig
View file @
7d9d9b34
...
...
@@ -29,6 +29,13 @@ config APM_POWER
Say Y here to enable support APM status emulation using
battery class devices.
config WM831X_POWER
tristate "WM831X PMU support"
depends on MFD_WM831X
help
Say Y here to enable support for the power management unit
provided by Wolfson Microelectronics WM831x PMICs.
config WM8350_POWER
tristate "WM8350 PMU support"
depends on MFD_WM8350
...
...
drivers/power/Makefile
View file @
7d9d9b34
...
...
@@ -16,6 +16,7 @@ obj-$(CONFIG_POWER_SUPPLY) += power_supply.o
obj-$(CONFIG_PDA_POWER)
+=
pda_power.o
obj-$(CONFIG_APM_POWER)
+=
apm_power.o
obj-$(CONFIG_WM831X_POWER)
+=
wm831x_power.o
obj-$(CONFIG_WM8350_POWER)
+=
wm8350_power.o
obj-$(CONFIG_BATTERY_DS2760)
+=
ds2760_battery.o
...
...
drivers/power/ds2760_battery.c
View file @
7d9d9b34
...
...
@@ -56,6 +56,7 @@ struct ds2760_device_info {
struct
device
*
w1_dev
;
struct
workqueue_struct
*
monitor_wqueue
;
struct
delayed_work
monitor_work
;
struct
delayed_work
set_charged_work
;
};
static
unsigned
int
cache_time
=
1000
;
...
...
@@ -66,6 +67,14 @@ static unsigned int pmod_enabled;
module_param
(
pmod_enabled
,
bool
,
0644
);
MODULE_PARM_DESC
(
pmod_enabled
,
"PMOD enable bit"
);
static
unsigned
int
rated_capacity
;
module_param
(
rated_capacity
,
uint
,
0644
);
MODULE_PARM_DESC
(
rated_capacity
,
"rated battery capacity, 10*mAh or index"
);
static
unsigned
int
current_accum
;
module_param
(
current_accum
,
uint
,
0644
);
MODULE_PARM_DESC
(
current_accum
,
"current accumulator value"
);
/* Some batteries have their rated capacity stored a N * 10 mAh, while
* others use an index into this table. */
static
int
rated_capacities
[]
=
{
...
...
@@ -168,8 +177,13 @@ static int ds2760_battery_read_status(struct ds2760_device_info *di)
di
->
full_active_uAh
=
di
->
raw
[
DS2760_ACTIVE_FULL
]
<<
8
|
di
->
raw
[
DS2760_ACTIVE_FULL
+
1
];
scale
[
0
]
=
di
->
raw
[
DS2760_ACTIVE_FULL
]
<<
8
|
di
->
raw
[
DS2760_ACTIVE_FULL
+
1
];
/* If the full_active_uAh value is not given, fall back to the rated
* capacity. This is likely to happen when chips are not part of the
* battery pack and is therefore not bootstrapped. */
if
(
di
->
full_active_uAh
==
0
)
di
->
full_active_uAh
=
di
->
rated_capacity
/
1000L
;
scale
[
0
]
=
di
->
full_active_uAh
;
for
(
i
=
1
;
i
<
5
;
i
++
)
scale
[
i
]
=
scale
[
i
-
1
]
+
di
->
raw
[
DS2760_ACTIVE_FULL
+
2
+
i
];
...
...
@@ -197,15 +211,31 @@ static int ds2760_battery_read_status(struct ds2760_device_info *di)
if
(
di
->
rem_capacity
>
100
)
di
->
rem_capacity
=
100
;
if
(
di
->
current_uA
)
di
->
life_sec
=
-
((
di
->
accum_current_uAh
-
di
->
empty_uAh
)
*
3600L
)
/
di
->
current_uA
;
if
(
di
->
current_uA
>=
100L
)
di
->
life_sec
=
-
((
di
->
accum_current_uAh
-
di
->
empty_uAh
)
*
36L
)
/
(
di
->
current_uA
/
100L
)
;
else
di
->
life_sec
=
0
;
return
0
;
}
static
void
ds2760_battery_set_current_accum
(
struct
ds2760_device_info
*
di
,
unsigned
int
acr_val
)
{
unsigned
char
acr
[
2
];
/* acr is in units of 0.25 mAh */
acr_val
*=
4L
;
acr_val
/=
1000
;
acr
[
0
]
=
acr_val
>>
8
;
acr
[
1
]
=
acr_val
&
0xff
;
if
(
w1_ds2760_write
(
di
->
w1_dev
,
acr
,
DS2760_CURRENT_ACCUM_MSB
,
2
)
<
2
)
dev_warn
(
di
->
dev
,
"ACR write failed
\n
"
);
}
static
void
ds2760_battery_update_status
(
struct
ds2760_device_info
*
di
)
{
int
old_charge_status
=
di
->
charge_status
;
...
...
@@ -237,21 +267,9 @@ static void ds2760_battery_update_status(struct ds2760_device_info *di)
if
(
di
->
full_counter
<
2
)
{
di
->
charge_status
=
POWER_SUPPLY_STATUS_CHARGING
;
}
else
{
unsigned
char
acr
[
2
];
int
acr_val
;
/* acr is in units of 0.25 mAh */
acr_val
=
di
->
full_active_uAh
*
4L
/
1000
;
acr
[
0
]
=
acr_val
>>
8
;
acr
[
1
]
=
acr_val
&
0xff
;
if
(
w1_ds2760_write
(
di
->
w1_dev
,
acr
,
DS2760_CURRENT_ACCUM_MSB
,
2
)
<
2
)
dev_warn
(
di
->
dev
,
"ACR reset failed
\n
"
);
di
->
charge_status
=
POWER_SUPPLY_STATUS_FULL
;
ds2760_battery_set_current_accum
(
di
,
di
->
full_active_uAh
);
}
}
}
else
{
...
...
@@ -274,6 +292,17 @@ static void ds2760_battery_write_status(struct ds2760_device_info *di,
w1_ds2760_recall_eeprom
(
di
->
w1_dev
,
DS2760_EEPROM_BLOCK1
);
}
static
void
ds2760_battery_write_rated_capacity
(
struct
ds2760_device_info
*
di
,
unsigned
char
rated_capacity
)
{
if
(
rated_capacity
==
di
->
raw
[
DS2760_RATED_CAPACITY
])
return
;
w1_ds2760_write
(
di
->
w1_dev
,
&
rated_capacity
,
DS2760_RATED_CAPACITY
,
1
);
w1_ds2760_store_eeprom
(
di
->
w1_dev
,
DS2760_EEPROM_BLOCK1
);
w1_ds2760_recall_eeprom
(
di
->
w1_dev
,
DS2760_EEPROM_BLOCK1
);
}
static
void
ds2760_battery_work
(
struct
work_struct
*
work
)
{
struct
ds2760_device_info
*
di
=
container_of
(
work
,
...
...
@@ -299,6 +328,52 @@ static void ds2760_battery_external_power_changed(struct power_supply *psy)
queue_delayed_work
(
di
->
monitor_wqueue
,
&
di
->
monitor_work
,
HZ
/
10
);
}
static
void
ds2760_battery_set_charged_work
(
struct
work_struct
*
work
)
{
char
bias
;
struct
ds2760_device_info
*
di
=
container_of
(
work
,
struct
ds2760_device_info
,
set_charged_work
.
work
);
dev_dbg
(
di
->
dev
,
"%s
\n
"
,
__func__
);
ds2760_battery_read_status
(
di
);
/* When we get notified by external circuitry that the battery is
* considered fully charged now, we know that there is no current
* flow any more. However, the ds2760's internal current meter is
* too inaccurate to rely on - spec say something ~15% failure.
* Hence, we use the current offset bias register to compensate
* that error.
*/
if
(
!
power_supply_am_i_supplied
(
&
di
->
bat
))
return
;
bias
=
(
signed
char
)
di
->
current_raw
+
(
signed
char
)
di
->
raw
[
DS2760_CURRENT_OFFSET_BIAS
];
dev_dbg
(
di
->
dev
,
"%s: bias = %d
\n
"
,
__func__
,
bias
);
w1_ds2760_write
(
di
->
w1_dev
,
&
bias
,
DS2760_CURRENT_OFFSET_BIAS
,
1
);
w1_ds2760_store_eeprom
(
di
->
w1_dev
,
DS2760_EEPROM_BLOCK1
);
w1_ds2760_recall_eeprom
(
di
->
w1_dev
,
DS2760_EEPROM_BLOCK1
);
/* Write to the di->raw[] buffer directly - the CURRENT_OFFSET_BIAS
* value won't be read back by ds2760_battery_read_status() */
di
->
raw
[
DS2760_CURRENT_OFFSET_BIAS
]
=
bias
;
}
static
void
ds2760_battery_set_charged
(
struct
power_supply
*
psy
)
{
struct
ds2760_device_info
*
di
=
to_ds2760_device_info
(
psy
);
/* postpone the actual work by 20 secs. This is for debouncing GPIO
* signals and to let the current value settle. See AN4188. */
cancel_delayed_work
(
&
di
->
set_charged_work
);
queue_delayed_work
(
di
->
monitor_wqueue
,
&
di
->
set_charged_work
,
HZ
*
20
);
}
static
int
ds2760_battery_get_property
(
struct
power_supply
*
psy
,
enum
power_supply_property
psp
,
union
power_supply_propval
*
val
)
...
...
@@ -337,6 +412,12 @@ static int ds2760_battery_get_property(struct power_supply *psy,
case
POWER_SUPPLY_PROP_TEMP
:
val
->
intval
=
di
->
temp_C
;
break
;
case
POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW
:
val
->
intval
=
di
->
life_sec
;
break
;
case
POWER_SUPPLY_PROP_CAPACITY
:
val
->
intval
=
di
->
rem_capacity
;
break
;
default:
return
-
EINVAL
;
}
...
...
@@ -353,6 +434,8 @@ static enum power_supply_property ds2760_battery_props[] = {
POWER_SUPPLY_PROP_CHARGE_EMPTY
,
POWER_SUPPLY_PROP_CHARGE_NOW
,
POWER_SUPPLY_PROP_TEMP
,
POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW
,
POWER_SUPPLY_PROP_CAPACITY
,
};
static
int
ds2760_battery_probe
(
struct
platform_device
*
pdev
)
...
...
@@ -376,17 +459,12 @@ static int ds2760_battery_probe(struct platform_device *pdev)
di
->
bat
.
properties
=
ds2760_battery_props
;
di
->
bat
.
num_properties
=
ARRAY_SIZE
(
ds2760_battery_props
);
di
->
bat
.
get_property
=
ds2760_battery_get_property
;
di
->
bat
.
set_charged
=
ds2760_battery_set_charged
;
di
->
bat
.
external_power_changed
=
ds2760_battery_external_power_changed
;
di
->
charge_status
=
POWER_SUPPLY_STATUS_UNKNOWN
;
retval
=
power_supply_register
(
&
pdev
->
dev
,
&
di
->
bat
);
if
(
retval
)
{
dev_err
(
di
->
dev
,
"failed to register battery
\n
"
);
goto
batt_failed
;
}
/* enable sleep mode feature */
ds2760_battery_read_status
(
di
);
status
=
di
->
raw
[
DS2760_STATUS_REG
];
...
...
@@ -397,7 +475,24 @@ static int ds2760_battery_probe(struct platform_device *pdev)
ds2760_battery_write_status
(
di
,
status
);
/* set rated capacity from module param */
if
(
rated_capacity
)
ds2760_battery_write_rated_capacity
(
di
,
rated_capacity
);
/* set current accumulator if given as parameter.
* this should only be done for bootstrapping the value */
if
(
current_accum
)
ds2760_battery_set_current_accum
(
di
,
current_accum
);
retval
=
power_supply_register
(
&
pdev
->
dev
,
&
di
->
bat
);
if
(
retval
)
{
dev_err
(
di
->
dev
,
"failed to register battery
\n
"
);
goto
batt_failed
;
}
INIT_DELAYED_WORK
(
&
di
->
monitor_work
,
ds2760_battery_work
);
INIT_DELAYED_WORK
(
&
di
->
set_charged_work
,
ds2760_battery_set_charged_work
);
di
->
monitor_wqueue
=
create_singlethread_workqueue
(
dev_name
(
&
pdev
->
dev
));
if
(
!
di
->
monitor_wqueue
)
{
retval
=
-
ESRCH
;
...
...
@@ -422,6 +517,8 @@ static int ds2760_battery_remove(struct platform_device *pdev)
cancel_rearming_delayed_workqueue
(
di
->
monitor_wqueue
,
&
di
->
monitor_work
);
cancel_rearming_delayed_workqueue
(
di
->
monitor_wqueue
,
&
di
->
set_charged_work
);
destroy_workqueue
(
di
->
monitor_wqueue
);
power_supply_unregister
(
&
di
->
bat
);
...
...
drivers/power/olpc_battery.c
View file @
7d9d9b34
...
...
@@ -10,7 +10,9 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/err.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/jiffies.h>
...
...
@@ -231,6 +233,14 @@ static int olpc_bat_get_property(struct power_supply *psy,
if
(
ret
)
return
ret
;
break
;
case
POWER_SUPPLY_PROP_CHARGE_TYPE
:
if
(
ec_byte
&
BAT_STAT_TRICKLE
)
val
->
intval
=
POWER_SUPPLY_CHARGE_TYPE_TRICKLE
;
else
if
(
ec_byte
&
BAT_STAT_CHARGING
)
val
->
intval
=
POWER_SUPPLY_CHARGE_TYPE_FAST
;
else
val
->
intval
=
POWER_SUPPLY_CHARGE_TYPE_NONE
;
break
;
case
POWER_SUPPLY_PROP_PRESENT
:
val
->
intval
=
!!
(
ec_byte
&
(
BAT_STAT_PRESENT
|
BAT_STAT_TRICKLE
));
...
...
@@ -276,6 +286,14 @@ static int olpc_bat_get_property(struct power_supply *psy,
return
ret
;
val
->
intval
=
ec_byte
;
break
;
case
POWER_SUPPLY_PROP_CAPACITY_LEVEL
:
if
(
ec_byte
&
BAT_STAT_FULL
)
val
->
intval
=
POWER_SUPPLY_CAPACITY_LEVEL_FULL
;
else
if
(
ec_byte
&
BAT_STAT_LOW
)
val
->
intval
=
POWER_SUPPLY_CAPACITY_LEVEL_LOW
;
else
val
->
intval
=
POWER_SUPPLY_CAPACITY_LEVEL_NORMAL
;
break
;
case
POWER_SUPPLY_PROP_TEMP
:
ret
=
olpc_ec_cmd
(
EC_BAT_TEMP
,
NULL
,
0
,
(
void
*
)
&
ec_word
,
2
);
if
(
ret
)
...
...
@@ -315,12 +333,14 @@ static int olpc_bat_get_property(struct power_supply *psy,
static
enum
power_supply_property
olpc_bat_props
[]
=
{
POWER_SUPPLY_PROP_STATUS
,
POWER_SUPPLY_PROP_CHARGE_TYPE
,
POWER_SUPPLY_PROP_PRESENT
,
POWER_SUPPLY_PROP_HEALTH
,
POWER_SUPPLY_PROP_TECHNOLOGY
,
POWER_SUPPLY_PROP_VOLTAGE_AVG
,
POWER_SUPPLY_PROP_CURRENT_AVG
,
POWER_SUPPLY_PROP_CAPACITY
,
POWER_SUPPLY_PROP_CAPACITY_LEVEL
,
POWER_SUPPLY_PROP_TEMP
,
POWER_SUPPLY_PROP_TEMP_AMBIENT
,
POWER_SUPPLY_PROP_MANUFACTURER
,
...
...
@@ -370,6 +390,29 @@ static struct bin_attribute olpc_bat_eeprom = {
.
read
=
olpc_bat_eeprom_read
,
};
/* Allow userspace to see the specific error value pulled from the EC */
static
ssize_t
olpc_bat_error_read
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
uint8_t
ec_byte
;
ssize_t
ret
;
ret
=
olpc_ec_cmd
(
EC_BAT_ERRCODE
,
NULL
,
0
,
&
ec_byte
,
1
);
if
(
ret
<
0
)
return
ret
;
return
sprintf
(
buf
,
"%d
\n
"
,
ec_byte
);
}
static
struct
device_attribute
olpc_bat_error
=
{
.
attr
=
{
.
name
=
"error"
,
.
mode
=
S_IRUGO
,
},
.
show
=
olpc_bat_error_read
,
};
/*********************************************************************
* Initialisation
*********************************************************************/
...
...
@@ -433,8 +476,14 @@ static int __init olpc_bat_init(void)
if
(
ret
)
goto
eeprom_failed
;
ret
=
device_create_file
(
olpc_bat
.
dev
,
&
olpc_bat_error
);
if
(
ret
)
goto
error_failed
;
goto
success
;
error_failed:
device_remove_bin_file
(
olpc_bat
.
dev
,
&
olpc_bat_eeprom
);
eeprom_failed:
power_supply_unregister
(
&
olpc_bat
);
battery_failed:
...
...
@@ -447,6 +496,7 @@ success:
static
void
__exit
olpc_bat_exit
(
void
)
{
device_remove_file
(
olpc_bat
.
dev
,
&
olpc_bat_error
);
device_remove_bin_file
(
olpc_bat
.
dev
,
&
olpc_bat_eeprom
);
power_supply_unregister
(
&
olpc_bat
);
power_supply_unregister
(
&
olpc_ac
);
...
...
drivers/power/power_supply_core.c
View file @
7d9d9b34
...
...
@@ -18,7 +18,9 @@
#include <linux/power_supply.h>
#include "power_supply.h"
/* exported for the APM Power driver, APM emulation */
struct
class
*
power_supply_class
;
EXPORT_SYMBOL_GPL
(
power_supply_class
);
static
int
__power_supply_changed_work
(
struct
device
*
dev
,
void
*
data
)
{
...
...
@@ -55,6 +57,7 @@ void power_supply_changed(struct power_supply *psy)
schedule_work
(
&
psy
->
changed_work
);
}
EXPORT_SYMBOL_GPL
(
power_supply_changed
);
static
int
__power_supply_am_i_supplied
(
struct
device
*
dev
,
void
*
data
)
{
...
...
@@ -86,6 +89,7 @@ int power_supply_am_i_supplied(struct power_supply *psy)
return
error
;
}
EXPORT_SYMBOL_GPL
(
power_supply_am_i_supplied
);
static
int
__power_supply_is_system_supplied
(
struct
device
*
dev
,
void
*
data
)
{
...
...
@@ -110,6 +114,35 @@ int power_supply_is_system_supplied(void)
return
error
;
}
EXPORT_SYMBOL_GPL
(
power_supply_is_system_supplied
);
int
power_supply_set_battery_charged
(
struct
power_supply
*
psy
)
{
if
(
psy
->
type
==
POWER_SUPPLY_TYPE_BATTERY
&&
psy
->
set_charged
)
{
psy
->
set_charged
(
psy
);
return
0
;
}
return
-
EINVAL
;
}
EXPORT_SYMBOL_GPL
(
power_supply_set_battery_charged
);
static
int
power_supply_match_device_by_name
(
struct
device
*
dev
,
void
*
data
)
{
const
char
*
name
=
data
;
struct
power_supply
*
psy
=
dev_get_drvdata
(
dev
);
return
strcmp
(
psy
->
name
,
name
)
==
0
;
}
struct
power_supply
*
power_supply_get_by_name
(
char
*
name
)
{
struct
device
*
dev
=
class_find_device
(
power_supply_class
,
NULL
,
name
,
power_supply_match_device_by_name
);
return
dev
?
dev_get_drvdata
(
dev
)
:
NULL
;
}
EXPORT_SYMBOL_GPL
(
power_supply_get_by_name
);
int
power_supply_register
(
struct
device
*
parent
,
struct
power_supply
*
psy
)
{
...
...
@@ -144,6 +177,7 @@ dev_create_failed:
success:
return
rc
;
}
EXPORT_SYMBOL_GPL
(
power_supply_register
);
void
power_supply_unregister
(
struct
power_supply
*
psy
)
{
...
...
@@ -152,6 +186,7 @@ void power_supply_unregister(struct power_supply *psy)
power_supply_remove_attrs
(
psy
);
device_unregister
(
psy
->
dev
);
}
EXPORT_SYMBOL_GPL
(
power_supply_unregister
);
static
int
__init
power_supply_class_init
(
void
)
{
...
...
@@ -170,15 +205,6 @@ static void __exit power_supply_class_exit(void)
class_destroy
(
power_supply_class
);
}
EXPORT_SYMBOL_GPL
(
power_supply_changed
);
EXPORT_SYMBOL_GPL
(
power_supply_am_i_supplied
);
EXPORT_SYMBOL_GPL
(
power_supply_is_system_supplied
);
EXPORT_SYMBOL_GPL
(
power_supply_register
);
EXPORT_SYMBOL_GPL
(
power_supply_unregister
);
/* exported for the APM Power driver, APM emulation */
EXPORT_SYMBOL_GPL
(
power_supply_class
);
subsys_initcall
(
power_supply_class_init
);
module_exit
(
power_supply_class_exit
);
...
...
drivers/power/power_supply_sysfs.c
View file @
7d9d9b34
...
...
@@ -43,6 +43,9 @@ static ssize_t power_supply_show_property(struct device *dev,
static
char
*
status_text
[]
=
{
"Unknown"
,
"Charging"
,
"Discharging"
,
"Not charging"
,
"Full"
};
static
char
*
charge_type
[]
=
{
"Unknown"
,
"N/A"
,
"Trickle"
,
"Fast"
};
static
char
*
health_text
[]
=
{
"Unknown"
,
"Good"
,
"Overheat"
,
"Dead"
,
"Over voltage"
,
"Unspecified failure"
,
"Cold"
,
...
...
@@ -51,6 +54,9 @@ static ssize_t power_supply_show_property(struct device *dev,
"Unknown"
,
"NiMH"
,
"Li-ion"
,
"Li-poly"
,
"LiFe"
,
"NiCd"
,
"LiMn"
};
static
char
*
capacity_level_text
[]
=
{
"Unknown"
,
"Critical"
,
"Low"
,
"Normal"
,
"High"
,
"Full"
};
ssize_t
ret
;
struct
power_supply
*
psy
=
dev_get_drvdata
(
dev
);
const
ptrdiff_t
off
=
attr
-
power_supply_attrs
;
...
...
@@ -67,10 +73,14 @@ static ssize_t power_supply_show_property(struct device *dev,
if
(
off
==
POWER_SUPPLY_PROP_STATUS
)
return
sprintf
(
buf
,
"%s
\n
"
,
status_text
[
value
.
intval
]);
else
if
(
off
==
POWER_SUPPLY_PROP_CHARGE_TYPE
)
return
sprintf
(
buf
,
"%s
\n
"
,
charge_type
[
value
.
intval
]);
else
if
(
off
==
POWER_SUPPLY_PROP_HEALTH
)
return
sprintf
(
buf
,
"%s
\n
"
,
health_text
[
value
.
intval
]);
else
if
(
off
==
POWER_SUPPLY_PROP_TECHNOLOGY
)
return
sprintf
(
buf
,
"%s
\n
"
,
technology_text
[
value
.
intval
]);
else
if
(
off
==
POWER_SUPPLY_PROP_CAPACITY_LEVEL
)
return
sprintf
(
buf
,
"%s
\n
"
,
capacity_level_text
[
value
.
intval
]);
else
if
(
off
>=
POWER_SUPPLY_PROP_MODEL_NAME
)
return
sprintf
(
buf
,
"%s
\n
"
,
value
.
strval
);
...
...
@@ -81,6 +91,7 @@ static ssize_t power_supply_show_property(struct device *dev,
static
struct
device_attribute
power_supply_attrs
[]
=
{
/* Properties of type `int' */
POWER_SUPPLY_ATTR
(
status
),
POWER_SUPPLY_ATTR
(
charge_type
),
POWER_SUPPLY_ATTR
(
health
),
POWER_SUPPLY_ATTR
(
present
),
POWER_SUPPLY_ATTR
(
online
),
...
...
@@ -109,6 +120,7 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR
(
energy_now
),
POWER_SUPPLY_ATTR
(
energy_avg
),
POWER_SUPPLY_ATTR
(
capacity
),
POWER_SUPPLY_ATTR
(
capacity_level
),
POWER_SUPPLY_ATTR
(
temp
),
POWER_SUPPLY_ATTR
(
temp_ambient
),
POWER_SUPPLY_ATTR
(
time_to_empty_now
),
...
...
drivers/power/wm831x_power.c
0 → 100644
View file @
7d9d9b34
/*
* PMU driver for Wolfson Microelectronics wm831x PMICs
*
* Copyright 2009 Wolfson Microelectronics PLC.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/mfd/wm831x/core.h>
#include <linux/mfd/wm831x/auxadc.h>
#include <linux/mfd/wm831x/pmu.h>
#include <linux/mfd/wm831x/pdata.h>
struct
wm831x_power
{
struct
wm831x
*
wm831x
;
struct
power_supply
wall
;
struct
power_supply
backup
;
struct
power_supply
usb
;
struct
power_supply
battery
;
};
static
int
wm831x_power_check_online
(
struct
wm831x
*
wm831x
,
int
supply
,
union
power_supply_propval
*
val
)
{
int
ret
;
ret
=
wm831x_reg_read
(
wm831x
,
WM831X_SYSTEM_STATUS
);
if
(
ret
<
0
)
return
ret
;
if
(
ret
&
supply
)
val
->
intval
=
1
;
else
val
->
intval
=
0
;
return
0
;
}
static
int
wm831x_power_read_voltage
(
struct
wm831x
*
wm831x
,
enum
wm831x_auxadc
src
,
union
power_supply_propval
*
val
)
{
int
ret
;
ret
=
wm831x_auxadc_read_uv
(
wm831x
,
src
);
if
(
ret
>=
0
)
val
->
intval
=
ret
;
return
ret
;
}
/*********************************************************************
* WALL Power
*********************************************************************/
static
int
wm831x_wall_get_prop
(
struct
power_supply
*
psy
,
enum
power_supply_property
psp
,
union
power_supply_propval
*
val
)
{
struct
wm831x_power
*
wm831x_power
=
dev_get_drvdata
(
psy
->
dev
->
parent
);
struct
wm831x
*
wm831x
=
wm831x_power
->
wm831x
;
int
ret
=
0
;
switch
(
psp
)
{
case
POWER_SUPPLY_PROP_ONLINE
:
ret
=
wm831x_power_check_online
(
wm831x
,
WM831X_PWR_WALL
,
val
);
break
;
case
POWER_SUPPLY_PROP_VOLTAGE_NOW
:
ret
=
wm831x_power_read_voltage
(
wm831x
,
WM831X_AUX_WALL
,
val
);
break
;
default:
ret
=
-
EINVAL
;
break
;
}
return
ret
;
}
static
enum
power_supply_property
wm831x_wall_props
[]
=
{
POWER_SUPPLY_PROP_ONLINE
,
POWER_SUPPLY_PROP_VOLTAGE_NOW
,
};
/*********************************************************************
* USB Power
*********************************************************************/
static
int
wm831x_usb_get_prop
(
struct
power_supply
*
psy
,
enum
power_supply_property
psp
,
union
power_supply_propval
*
val
)
{
struct
wm831x_power
*
wm831x_power
=
dev_get_drvdata
(
psy
->
dev
->
parent
);
struct
wm831x
*
wm831x
=
wm831x_power
->
wm831x
;
int
ret
=
0
;
switch
(
psp
)
{
case
POWER_SUPPLY_PROP_ONLINE
:
ret
=
wm831x_power_check_online
(
wm831x
,
WM831X_PWR_USB
,
val
);
break
;
case
POWER_SUPPLY_PROP_VOLTAGE_NOW
:
ret
=
wm831x_power_read_voltage
(
wm831x
,
WM831X_AUX_USB
,
val
);
break
;
default:
ret
=
-
EINVAL
;
break
;
}
return
ret
;
}
static
enum
power_supply_property
wm831x_usb_props
[]
=
{
POWER_SUPPLY_PROP_ONLINE
,
POWER_SUPPLY_PROP_VOLTAGE_NOW
,
};
/*********************************************************************
* Battery properties
*********************************************************************/
struct
chg_map
{
int
val
;
int
reg_val
;
};
static
struct
chg_map
trickle_ilims
[]
=
{
{
50
,
0
<<
WM831X_CHG_TRKL_ILIM_SHIFT
},
{
100
,
1
<<
WM831X_CHG_TRKL_ILIM_SHIFT
},
{
150
,
2
<<
WM831X_CHG_TRKL_ILIM_SHIFT
},
{
200
,
3
<<
WM831X_CHG_TRKL_ILIM_SHIFT
},
};
static
struct
chg_map
vsels
[]
=
{
{
4050
,
0
<<
WM831X_CHG_VSEL_SHIFT
},
{
4100
,
1
<<
WM831X_CHG_VSEL_SHIFT
},
{
4150
,
2
<<
WM831X_CHG_VSEL_SHIFT
},
{
4200
,
3
<<
WM831X_CHG_VSEL_SHIFT
},
};
static
struct
chg_map
fast_ilims
[]
=
{
{
0
,
0
<<
WM831X_CHG_FAST_ILIM_SHIFT
},
{
50
,
1
<<
WM831X_CHG_FAST_ILIM_SHIFT
},
{
100
,
2
<<
WM831X_CHG_FAST_ILIM_SHIFT
},
{
150
,
3
<<
WM831X_CHG_FAST_ILIM_SHIFT
},
{
200
,
4
<<
WM831X_CHG_FAST_ILIM_SHIFT
},
{
250
,
5
<<
WM831X_CHG_FAST_ILIM_SHIFT
},
{
300
,
6
<<
WM831X_CHG_FAST_ILIM_SHIFT
},
{
350
,
7
<<
WM831X_CHG_FAST_ILIM_SHIFT
},
{
400
,
8
<<
WM831X_CHG_FAST_ILIM_SHIFT
},
{
450
,
9
<<
WM831X_CHG_FAST_ILIM_SHIFT
},
{
500
,
10
<<
WM831X_CHG_FAST_ILIM_SHIFT
},
{
600
,
11
<<
WM831X_CHG_FAST_ILIM_SHIFT
},
{
700
,
12
<<
WM831X_CHG_FAST_ILIM_SHIFT
},
{
800
,
13
<<
WM831X_CHG_FAST_ILIM_SHIFT
},
{
900
,
14
<<
WM831X_CHG_FAST_ILIM_SHIFT
},
{
1000
,
15
<<
WM831X_CHG_FAST_ILIM_SHIFT
},
};
static
struct
chg_map
eoc_iterms
[]
=
{
{
20
,
0
<<
WM831X_CHG_ITERM_SHIFT
},
{
30
,
1
<<
WM831X_CHG_ITERM_SHIFT
},
{
40
,
2
<<
WM831X_CHG_ITERM_SHIFT
},
{
50
,
3
<<
WM831X_CHG_ITERM_SHIFT
},
{
60
,
4
<<
WM831X_CHG_ITERM_SHIFT
},
{
70
,
5
<<
WM831X_CHG_ITERM_SHIFT
},
{
80
,
6
<<
WM831X_CHG_ITERM_SHIFT
},
{
90
,
7
<<
WM831X_CHG_ITERM_SHIFT
},
};
static
struct
chg_map
chg_times
[]
=
{
{
60
,
0
<<
WM831X_CHG_TIME_SHIFT
},
{
90
,
1
<<
WM831X_CHG_TIME_SHIFT
},
{
120
,
2
<<
WM831X_CHG_TIME_SHIFT
},
{
150
,
3
<<
WM831X_CHG_TIME_SHIFT
},
{
180
,
4
<<
WM831X_CHG_TIME_SHIFT
},
{
210
,
5
<<
WM831X_CHG_TIME_SHIFT
},
{
240
,
6
<<
WM831X_CHG_TIME_SHIFT
},
{
270
,
7
<<
WM831X_CHG_TIME_SHIFT
},
{
300
,
8
<<
WM831X_CHG_TIME_SHIFT
},
{
330
,
9
<<
WM831X_CHG_TIME_SHIFT
},
{
360
,
10
<<
WM831X_CHG_TIME_SHIFT
},
{
390
,
11
<<
WM831X_CHG_TIME_SHIFT
},
{
420
,
12
<<
WM831X_CHG_TIME_SHIFT
},
{
450
,
13
<<
WM831X_CHG_TIME_SHIFT
},
{
480
,
14
<<
WM831X_CHG_TIME_SHIFT
},
{
510
,
15
<<
WM831X_CHG_TIME_SHIFT
},
};
static
void
wm831x_battey_apply_config
(
struct
wm831x
*
wm831x
,
struct
chg_map
*
map
,
int
count
,
int
val
,
int
*
reg
,
const
char
*
name
,
const
char
*
units
)
{
int
i
;
for
(
i
=
0
;
i
<
count
;
i
++
)
if
(
val
==
map
[
i
].
val
)
break
;
if
(
i
==
count
)
{
dev_err
(
wm831x
->
dev
,
"Invalid %s %d%s
\n
"
,
name
,
val
,
units
);
}
else
{
*
reg
|=
map
[
i
].
reg_val
;
dev_dbg
(
wm831x
->
dev
,
"Set %s of %d%s
\n
"
,
name
,
val
,
units
);
}
}
static
void
wm831x_config_battery
(
struct
wm831x
*
wm831x
)
{
struct
wm831x_pdata
*
wm831x_pdata
=
wm831x
->
dev
->
platform_data
;
struct
wm831x_battery_pdata
*
pdata
;
int
ret
,
reg1
,
reg2
;
if
(
!
wm831x_pdata
||
!
wm831x_pdata
->
battery
)
{
dev_warn
(
wm831x
->
dev
,
"No battery charger configuration
\n
"
);
return
;
}
pdata
=
wm831x_pdata
->
battery
;
reg1
=
0
;
reg2
=
0
;
if
(
!
pdata
->
enable
)
{
dev_info
(
wm831x
->
dev
,
"Battery charger disabled
\n
"
);
return
;
}
reg1
|=
WM831X_CHG_ENA
;
if
(
pdata
->
off_mask
)
reg2
|=
WM831X_CHG_OFF_MSK
;
if
(
pdata
->
fast_enable
)
reg1
|=
WM831X_CHG_FAST
;
wm831x_battey_apply_config
(
wm831x
,
trickle_ilims
,
ARRAY_SIZE
(
trickle_ilims
),
pdata
->
trickle_ilim
,
&
reg2
,
"trickle charge current limit"
,
"mA"
);
wm831x_battey_apply_config
(
wm831x
,
vsels
,
ARRAY_SIZE
(
vsels
),
pdata
->
vsel
,
&
reg2
,
"target voltage"
,
"mV"
);
wm831x_battey_apply_config
(
wm831x
,
fast_ilims
,
ARRAY_SIZE
(
fast_ilims
),
pdata
->
fast_ilim
,
&
reg2
,
"fast charge current limit"
,
"mA"
);
wm831x_battey_apply_config
(
wm831x
,
eoc_iterms
,
ARRAY_SIZE
(
eoc_iterms
),
pdata
->
eoc_iterm
,
&
reg1
,
"end of charge current threshold"
,
"mA"
);
wm831x_battey_apply_config
(
wm831x
,
chg_times
,
ARRAY_SIZE
(
chg_times
),
pdata
->
timeout
,
&
reg2
,
"charger timeout"
,
"min"
);
ret
=
wm831x_reg_unlock
(
wm831x
);
if
(
ret
!=
0
)
{
dev_err
(
wm831x
->
dev
,
"Failed to unlock registers: %d
\n
"
,
ret
);
return
;
}
ret
=
wm831x_set_bits
(
wm831x
,
WM831X_CHARGER_CONTROL_1
,
WM831X_CHG_ENA_MASK
|
WM831X_CHG_FAST_MASK
|
WM831X_CHG_ITERM_MASK
|
WM831X_CHG_ITERM_MASK
,
reg1
);
if
(
ret
!=
0
)
dev_err
(
wm831x
->
dev
,
"Failed to set charger control 1: %d
\n
"
,
ret
);
ret
=
wm831x_set_bits
(
wm831x
,
WM831X_CHARGER_CONTROL_2
,
WM831X_CHG_OFF_MSK
|
WM831X_CHG_TIME_MASK
|
WM831X_CHG_FAST_ILIM_MASK
|
WM831X_CHG_TRKL_ILIM_MASK
|
WM831X_CHG_VSEL_MASK
,
reg2
);
if
(
ret
!=
0
)
dev_err
(
wm831x
->
dev
,
"Failed to set charger control 2: %d
\n
"
,
ret
);
wm831x_reg_lock
(
wm831x
);
}
static
int
wm831x_bat_check_status
(
struct
wm831x
*
wm831x
,
int
*
status
)
{
int
ret
;
ret
=
wm831x_reg_read
(
wm831x
,
WM831X_SYSTEM_STATUS
);
if
(
ret
<
0
)
return
ret
;
if
(
ret
&
WM831X_PWR_SRC_BATT
)
{
*
status
=
POWER_SUPPLY_STATUS_DISCHARGING
;
return
0
;
}
ret
=
wm831x_reg_read
(
wm831x
,
WM831X_CHARGER_STATUS
);
if
(
ret
<
0
)
return
ret
;
switch
(
ret
&
WM831X_CHG_STATE_MASK
)
{
case
WM831X_CHG_STATE_OFF
:
*
status
=
POWER_SUPPLY_STATUS_NOT_CHARGING
;
break
;
case
WM831X_CHG_STATE_TRICKLE
:
case
WM831X_CHG_STATE_FAST
:
*
status
=
POWER_SUPPLY_STATUS_CHARGING
;
break
;
default:
*
status
=
POWER_SUPPLY_STATUS_UNKNOWN
;
break
;
}
return
0
;
}
static
int
wm831x_bat_check_type
(
struct
wm831x
*
wm831x
,
int
*
type
)
{
int
ret
;
ret
=
wm831x_reg_read
(
wm831x
,
WM831X_CHARGER_STATUS
);
if
(
ret
<
0
)
return
ret
;
switch
(
ret
&
WM831X_CHG_STATE_MASK
)
{
case
WM831X_CHG_STATE_TRICKLE
:
case
WM831X_CHG_STATE_TRICKLE_OT
:
*
type
=
POWER_SUPPLY_CHARGE_TYPE_TRICKLE
;
break
;
case
WM831X_CHG_STATE_FAST
:
case
WM831X_CHG_STATE_FAST_OT
:
*
type
=
POWER_SUPPLY_CHARGE_TYPE_FAST
;
break
;
default:
*
type
=
POWER_SUPPLY_CHARGE_TYPE_NONE
;
break
;
}
return
0
;
}
static
int
wm831x_bat_check_health
(
struct
wm831x
*
wm831x
,
int
*
health
)
{
int
ret
;
ret
=
wm831x_reg_read
(
wm831x
,
WM831X_CHARGER_STATUS
);
if
(
ret
<
0
)
return
ret
;
if
(
ret
&
WM831X_BATT_HOT_STS
)
{
*
health
=
POWER_SUPPLY_HEALTH_OVERHEAT
;
return
0
;
}
if
(
ret
&
WM831X_BATT_COLD_STS
)
{
*
health
=
POWER_SUPPLY_HEALTH_COLD
;
return
0
;
}
if
(
ret
&
WM831X_BATT_OV_STS
)
{
*
health
=
POWER_SUPPLY_HEALTH_OVERVOLTAGE
;
return
0
;
}
switch
(
ret
&
WM831X_CHG_STATE_MASK
)
{
case
WM831X_CHG_STATE_TRICKLE_OT
:
case
WM831X_CHG_STATE_FAST_OT
:
*
health
=
POWER_SUPPLY_HEALTH_OVERHEAT
;
break
;
case
WM831X_CHG_STATE_DEFECTIVE
:
*
health
=
POWER_SUPPLY_HEALTH_UNSPEC_FAILURE
;
break
;
default:
*
health
=
POWER_SUPPLY_HEALTH_GOOD
;
break
;
}
return
0
;
}
static
int
wm831x_bat_get_prop
(
struct
power_supply
*
psy
,
enum
power_supply_property
psp
,
union
power_supply_propval
*
val
)
{
struct
wm831x_power
*
wm831x_power
=
dev_get_drvdata
(
psy
->
dev
->
parent
);
struct
wm831x
*
wm831x
=
wm831x_power
->
wm831x
;
int
ret
=
0
;
switch
(
psp
)
{
case
POWER_SUPPLY_PROP_STATUS
:
ret
=
wm831x_bat_check_status
(
wm831x
,
&
val
->
intval
);
break
;
case
POWER_SUPPLY_PROP_ONLINE
:
ret
=
wm831x_power_check_online
(
wm831x
,
WM831X_PWR_SRC_BATT
,
val
);
break
;
case
POWER_SUPPLY_PROP_VOLTAGE_NOW
:
ret
=
wm831x_power_read_voltage
(
wm831x
,
WM831X_AUX_BATT
,
val
);
break
;
case
POWER_SUPPLY_PROP_HEALTH
:
ret
=
wm831x_bat_check_health
(
wm831x
,
&
val
->
intval
);
break
;
case
POWER_SUPPLY_PROP_CHARGE_TYPE
:
ret
=
wm831x_bat_check_type
(
wm831x
,
&
val
->
intval
);
break
;
default:
ret
=
-
EINVAL
;
break
;
}
return
ret
;
}
static
enum
power_supply_property
wm831x_bat_props
[]
=
{
POWER_SUPPLY_PROP_STATUS
,
POWER_SUPPLY_PROP_ONLINE
,
POWER_SUPPLY_PROP_VOLTAGE_NOW
,
POWER_SUPPLY_PROP_HEALTH
,
POWER_SUPPLY_PROP_CHARGE_TYPE
,
};
static
const
char
*
wm831x_bat_irqs
[]
=
{
"BATT HOT"
,
"BATT COLD"
,
"BATT FAIL"
,
"OV"
,
"END"
,
"TO"
,
"MODE"
,
"START"
,
};
static
irqreturn_t
wm831x_bat_irq
(
int
irq
,
void
*
data
)
{
struct
wm831x_power
*
wm831x_power
=
data
;
struct
wm831x
*
wm831x
=
wm831x_power
->
wm831x
;
dev_dbg
(
wm831x
->
dev
,
"Battery status changed: %d
\n
"
,
irq
);
/* The battery charger is autonomous so we don't need to do
* anything except kick user space */
power_supply_changed
(
&
wm831x_power
->
battery
);
return
IRQ_HANDLED
;
}
/*********************************************************************
* Backup supply properties
*********************************************************************/
static
void
wm831x_config_backup
(
struct
wm831x
*
wm831x
)
{
struct
wm831x_pdata
*
wm831x_pdata
=
wm831x
->
dev
->
platform_data
;
struct
wm831x_backup_pdata
*
pdata
;
int
ret
,
reg
;
if
(
!
wm831x_pdata
||
!
wm831x_pdata
->
backup
)
{
dev_warn
(
wm831x
->
dev
,
"No backup battery charger configuration
\n
"
);
return
;
}
pdata
=
wm831x_pdata
->
backup
;
reg
=
0
;
if
(
pdata
->
charger_enable
)
reg
|=
WM831X_BKUP_CHG_ENA
|
WM831X_BKUP_BATT_DET_ENA
;
if
(
pdata
->
no_constant_voltage
)
reg
|=
WM831X_BKUP_CHG_MODE
;
switch
(
pdata
->
vlim
)
{
case
2500
:
break
;
case
3100
:
reg
|=
WM831X_BKUP_CHG_VLIM
;
break
;
default:
dev_err
(
wm831x
->
dev
,
"Invalid backup voltage limit %dmV
\n
"
,
pdata
->
vlim
);
}
switch
(
pdata
->
ilim
)
{
case
100
:
break
;
case
200
:
reg
|=
1
;
break
;
case
300
:
reg
|=
2
;
break
;
case
400
:
reg
|=
3
;
break
;
default:
dev_err
(
wm831x
->
dev
,
"Invalid backup current limit %duA
\n
"
,
pdata
->
ilim
);
}
ret
=
wm831x_reg_unlock
(
wm831x
);
if
(
ret
!=
0
)
{
dev_err
(
wm831x
->
dev
,
"Failed to unlock registers: %d
\n
"
,
ret
);
return
;
}
ret
=
wm831x_set_bits
(
wm831x
,
WM831X_BACKUP_CHARGER_CONTROL
,
WM831X_BKUP_CHG_ENA_MASK
|
WM831X_BKUP_CHG_MODE_MASK
|
WM831X_BKUP_BATT_DET_ENA_MASK
|
WM831X_BKUP_CHG_VLIM_MASK
|
WM831X_BKUP_CHG_ILIM_MASK
,
reg
);
if
(
ret
!=
0
)
dev_err
(
wm831x
->
dev
,
"Failed to set backup charger config: %d
\n
"
,
ret
);
wm831x_reg_lock
(
wm831x
);
}
static
int
wm831x_backup_get_prop
(
struct
power_supply
*
psy
,
enum
power_supply_property
psp
,
union
power_supply_propval
*
val
)
{
struct
wm831x_power
*
wm831x_power
=
dev_get_drvdata
(
psy
->
dev
->
parent
);
struct
wm831x
*
wm831x
=
wm831x_power
->
wm831x
;
int
ret
=
0
;
ret
=
wm831x_reg_read
(
wm831x
,
WM831X_BACKUP_CHARGER_CONTROL
);
if
(
ret
<
0
)
return
ret
;
switch
(
psp
)
{
case
POWER_SUPPLY_PROP_STATUS
:
if
(
ret
&
WM831X_BKUP_CHG_STS
)
val
->
intval
=
POWER_SUPPLY_STATUS_CHARGING
;
else
val
->
intval
=
POWER_SUPPLY_STATUS_NOT_CHARGING
;
break
;
case
POWER_SUPPLY_PROP_VOLTAGE_NOW
:
ret
=
wm831x_power_read_voltage
(
wm831x
,
WM831X_AUX_BKUP_BATT
,
val
);
break
;
case
POWER_SUPPLY_PROP_PRESENT
:
if
(
ret
&
WM831X_BKUP_CHG_STS
)
val
->
intval
=
1
;
else
val
->
intval
=
0
;
break
;
default:
ret
=
-
EINVAL
;
break
;
}
return
ret
;
}
static
enum
power_supply_property
wm831x_backup_props
[]
=
{
POWER_SUPPLY_PROP_STATUS
,
POWER_SUPPLY_PROP_VOLTAGE_NOW
,
POWER_SUPPLY_PROP_PRESENT
,
};
/*********************************************************************
* Initialisation
*********************************************************************/
static
irqreturn_t
wm831x_syslo_irq
(
int
irq
,
void
*
data
)
{
struct
wm831x_power
*
wm831x_power
=
data
;
struct
wm831x
*
wm831x
=
wm831x_power
->
wm831x
;
/* Not much we can actually *do* but tell people for
* posterity, we're probably about to run out of power. */
dev_crit
(
wm831x
->
dev
,
"SYSVDD under voltage
\n
"
);
return
IRQ_HANDLED
;
}
static
irqreturn_t
wm831x_pwr_src_irq
(
int
irq
,
void
*
data
)
{
struct
wm831x_power
*
wm831x_power
=
data
;
struct
wm831x
*
wm831x
=
wm831x_power
->
wm831x
;
dev_dbg
(
wm831x
->
dev
,
"Power source changed
\n
"
);
/* Just notify for everything - little harm in overnotifying.
* The backup battery is not a power source while the system
* is running so skip that.
*/
power_supply_changed
(
&
wm831x_power
->
battery
);
power_supply_changed
(
&
wm831x_power
->
usb
);
power_supply_changed
(
&
wm831x_power
->
wall
);
return
IRQ_HANDLED
;
}
static
__devinit
int
wm831x_power_probe
(
struct
platform_device
*
pdev
)
{
struct
wm831x
*
wm831x
=
dev_get_drvdata
(
pdev
->
dev
.
parent
);
struct
wm831x_power
*
power
;
struct
power_supply
*
usb
;
struct
power_supply
*
battery
;
struct
power_supply
*
wall
;
struct
power_supply
*
backup
;
int
ret
,
irq
,
i
;
power
=
kzalloc
(
sizeof
(
struct
wm831x_power
),
GFP_KERNEL
);
if
(
power
==
NULL
)
return
-
ENOMEM
;
power
->
wm831x
=
wm831x
;
platform_set_drvdata
(
pdev
,
power
);
usb
=
&
power
->
usb
;
battery
=
&
power
->
battery
;
wall
=
&
power
->
wall
;
backup
=
&
power
->
backup
;
/* We ignore configuration failures since we can still read back
* the status without enabling either of the chargers.
*/
wm831x_config_battery
(
wm831x
);
wm831x_config_backup
(
wm831x
);
wall
->
name
=
"wm831x-wall"
;
wall
->
type
=
POWER_SUPPLY_TYPE_MAINS
;
wall
->
properties
=
wm831x_wall_props
;
wall
->
num_properties
=
ARRAY_SIZE
(
wm831x_wall_props
);
wall
->
get_property
=
wm831x_wall_get_prop
;
ret
=
power_supply_register
(
&
pdev
->
dev
,
wall
);
if
(
ret
)
goto
err_kmalloc
;
battery
->
name
=
"wm831x-battery"
;
battery
->
properties
=
wm831x_bat_props
;
battery
->
num_properties
=
ARRAY_SIZE
(
wm831x_bat_props
);
battery
->
get_property
=
wm831x_bat_get_prop
;
battery
->
use_for_apm
=
1
;
ret
=
power_supply_register
(
&
pdev
->
dev
,
battery
);
if
(
ret
)
goto
err_wall
;
usb
->
name
=
"wm831x-usb"
,
usb
->
type
=
POWER_SUPPLY_TYPE_USB
;
usb
->
properties
=
wm831x_usb_props
;
usb
->
num_properties
=
ARRAY_SIZE
(
wm831x_usb_props
);
usb
->
get_property
=
wm831x_usb_get_prop
;
ret
=
power_supply_register
(
&
pdev
->
dev
,
usb
);
if
(
ret
)
goto
err_battery
;
backup
->
name
=
"wm831x-backup"
;
backup
->
type
=
POWER_SUPPLY_TYPE_BATTERY
;
backup
->
properties
=
wm831x_backup_props
;
backup
->
num_properties
=
ARRAY_SIZE
(
wm831x_backup_props
);
backup
->
get_property
=
wm831x_backup_get_prop
;
ret
=
power_supply_register
(
&
pdev
->
dev
,
backup
);
if
(
ret
)
goto
err_usb
;
irq
=
platform_get_irq_byname
(
pdev
,
"SYSLO"
);
ret
=
wm831x_request_irq
(
wm831x
,
irq
,
wm831x_syslo_irq
,
IRQF_TRIGGER_RISING
,
"SYSLO"
,
power
);
if
(
ret
!=
0
)
{
dev_err
(
&
pdev
->
dev
,
"Failed to request SYSLO IRQ %d: %d
\n
"
,
irq
,
ret
);
goto
err_backup
;
}
irq
=
platform_get_irq_byname
(
pdev
,
"PWR SRC"
);
ret
=
wm831x_request_irq
(
wm831x
,
irq
,
wm831x_pwr_src_irq
,
IRQF_TRIGGER_RISING
,
"Power source"
,
power
);
if
(
ret
!=
0
)
{
dev_err
(
&
pdev
->
dev
,
"Failed to request PWR SRC IRQ %d: %d
\n
"
,
irq
,
ret
);
goto
err_syslo
;
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm831x_bat_irqs
);
i
++
)
{
irq
=
platform_get_irq_byname
(
pdev
,
wm831x_bat_irqs
[
i
]);
ret
=
wm831x_request_irq
(
wm831x
,
irq
,
wm831x_bat_irq
,
IRQF_TRIGGER_RISING
,
wm831x_bat_irqs
[
i
],
power
);
if
(
ret
!=
0
)
{
dev_err
(
&
pdev
->
dev
,
"Failed to request %s IRQ %d: %d
\n
"
,
wm831x_bat_irqs
[
i
],
irq
,
ret
);
goto
err_bat_irq
;
}
}
return
ret
;
err_bat_irq:
for
(;
i
>=
0
;
i
--
)
{
irq
=
platform_get_irq_byname
(
pdev
,
wm831x_bat_irqs
[
i
]);
wm831x_free_irq
(
wm831x
,
irq
,
power
);
}
irq
=
platform_get_irq_byname
(
pdev
,
"PWR SRC"
);
wm831x_free_irq
(
wm831x
,
irq
,
power
);
err_syslo:
irq
=
platform_get_irq_byname
(
pdev
,
"SYSLO"
);
wm831x_free_irq
(
wm831x
,
irq
,
power
);
err_backup:
power_supply_unregister
(
backup
);
err_usb:
power_supply_unregister
(
usb
);
err_battery:
power_supply_unregister
(
battery
);
err_wall:
power_supply_unregister
(
wall
);
err_kmalloc:
kfree
(
power
);
return
ret
;
}
static
__devexit
int
wm831x_power_remove
(
struct
platform_device
*
pdev
)
{
struct
wm831x_power
*
wm831x_power
=
platform_get_drvdata
(
pdev
);
struct
wm831x
*
wm831x
=
wm831x_power
->
wm831x
;
int
irq
,
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm831x_bat_irqs
);
i
++
)
{
irq
=
platform_get_irq_byname
(
pdev
,
wm831x_bat_irqs
[
i
]);
wm831x_free_irq
(
wm831x
,
irq
,
wm831x_power
);
}
irq
=
platform_get_irq_byname
(
pdev
,
"PWR SRC"
);
wm831x_free_irq
(
wm831x
,
irq
,
wm831x_power
);
irq
=
platform_get_irq_byname
(
pdev
,
"SYSLO"
);
wm831x_free_irq
(
wm831x
,
irq
,
wm831x_power
);
power_supply_unregister
(
&
wm831x_power
->
backup
);
power_supply_unregister
(
&
wm831x_power
->
battery
);
power_supply_unregister
(
&
wm831x_power
->
wall
);
power_supply_unregister
(
&
wm831x_power
->
usb
);
return
0
;
}
static
struct
platform_driver
wm831x_power_driver
=
{
.
probe
=
wm831x_power_probe
,
.
remove
=
__devexit_p
(
wm831x_power_remove
),
.
driver
=
{
.
name
=
"wm831x-power"
,
},
};
static
int
__init
wm831x_power_init
(
void
)
{
return
platform_driver_register
(
&
wm831x_power_driver
);
}
module_init
(
wm831x_power_init
);
static
void
__exit
wm831x_power_exit
(
void
)
{
platform_driver_unregister
(
&
wm831x_power_driver
);
}
module_exit
(
wm831x_power_exit
);
MODULE_DESCRIPTION
(
"Power supply driver for WM831x PMICs"
);
MODULE_AUTHOR
(
"Mark Brown <broonie@opensource.wolfsonmicro.com>"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_ALIAS
(
"platform:wm831x-power"
);
drivers/power/wm8350_power.c
View file @
7d9d9b34
...
...
@@ -321,6 +321,24 @@ static int wm8350_bat_check_health(struct wm8350 *wm8350)
return
POWER_SUPPLY_HEALTH_GOOD
;
}
static
int
wm8350_bat_get_charge_type
(
struct
wm8350
*
wm8350
)
{
int
state
;
state
=
wm8350_reg_read
(
wm8350
,
WM8350_BATTERY_CHARGER_CONTROL_2
)
&
WM8350_CHG_STS_MASK
;
switch
(
state
)
{
case
WM8350_CHG_STS_OFF
:
return
POWER_SUPPLY_CHARGE_TYPE_NONE
;
case
WM8350_CHG_STS_TRICKLE
:
return
POWER_SUPPLY_CHARGE_TYPE_TRICKLE
;
case
WM8350_CHG_STS_FAST
:
return
POWER_SUPPLY_CHARGE_TYPE_FAST
;
default:
return
POWER_SUPPLY_CHARGE_TYPE_UNKNOWN
;
}
}
static
int
wm8350_bat_get_property
(
struct
power_supply
*
psy
,
enum
power_supply_property
psp
,
union
power_supply_propval
*
val
)
...
...
@@ -342,6 +360,9 @@ static int wm8350_bat_get_property(struct power_supply *psy,
case
POWER_SUPPLY_PROP_HEALTH
:
val
->
intval
=
wm8350_bat_check_health
(
wm8350
);
break
;
case
POWER_SUPPLY_PROP_CHARGE_TYPE
:
val
->
intval
=
wm8350_bat_get_charge_type
(
wm8350
);
break
;
default:
ret
=
-
EINVAL
;
break
;
...
...
@@ -355,6 +376,7 @@ static enum power_supply_property wm8350_bat_props[] = {
POWER_SUPPLY_PROP_ONLINE
,
POWER_SUPPLY_PROP_VOLTAGE_NOW
,
POWER_SUPPLY_PROP_HEALTH
,
POWER_SUPPLY_PROP_CHARGE_TYPE
,
};
/*********************************************************************
...
...
drivers/power/wm97xx_battery.c
View file @
7d9d9b34
...
...
@@ -22,17 +22,20 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/
wm97xx_batt
.h>
#include <linux/
irq
.h>
static
DEFINE_MUTEX
(
bat_lock
);
static
struct
work_struct
bat_work
;
struct
mutex
work_lock
;
static
int
bat_status
=
POWER_SUPPLY_STATUS_UNKNOWN
;
static
struct
wm97xx_batt_info
*
pdata
;
static
struct
wm97xx_batt_info
*
g
pdata
;
static
enum
power_supply_property
*
prop
;
static
unsigned
long
wm97xx_read_bat
(
struct
power_supply
*
bat_ps
)
{
struct
wm97xx_pdata
*
wmdata
=
bat_ps
->
dev
->
parent
->
platform_data
;
struct
wm97xx_batt_pdata
*
pdata
=
wmdata
->
batt_pdata
;
return
wm97xx_read_aux_adc
(
dev_get_drvdata
(
bat_ps
->
dev
->
parent
),
pdata
->
batt_aux
)
*
pdata
->
batt_mult
/
pdata
->
batt_div
;
...
...
@@ -40,6 +43,9 @@ static unsigned long wm97xx_read_bat(struct power_supply *bat_ps)
static
unsigned
long
wm97xx_read_temp
(
struct
power_supply
*
bat_ps
)
{
struct
wm97xx_pdata
*
wmdata
=
bat_ps
->
dev
->
parent
->
platform_data
;
struct
wm97xx_batt_pdata
*
pdata
=
wmdata
->
batt_pdata
;
return
wm97xx_read_aux_adc
(
dev_get_drvdata
(
bat_ps
->
dev
->
parent
),
pdata
->
temp_aux
)
*
pdata
->
temp_mult
/
pdata
->
temp_div
;
...
...
@@ -49,6 +55,9 @@ static int wm97xx_bat_get_property(struct power_supply *bat_ps,
enum
power_supply_property
psp
,
union
power_supply_propval
*
val
)
{
struct
wm97xx_pdata
*
wmdata
=
bat_ps
->
dev
->
parent
->
platform_data
;
struct
wm97xx_batt_pdata
*
pdata
=
wmdata
->
batt_pdata
;
switch
(
psp
)
{
case
POWER_SUPPLY_PROP_STATUS
:
val
->
intval
=
bat_status
;
...
...
@@ -97,6 +106,8 @@ static void wm97xx_bat_external_power_changed(struct power_supply *bat_ps)
static
void
wm97xx_bat_update
(
struct
power_supply
*
bat_ps
)
{
int
old_status
=
bat_status
;
struct
wm97xx_pdata
*
wmdata
=
bat_ps
->
dev
->
parent
->
platform_data
;
struct
wm97xx_batt_pdata
*
pdata
=
wmdata
->
batt_pdata
;
mutex_lock
(
&
work_lock
);
...
...
@@ -127,21 +138,29 @@ static void wm97xx_bat_work(struct work_struct *work)
wm97xx_bat_update
(
&
bat_ps
);
}
static
irqreturn_t
wm97xx_chrg_irq
(
int
irq
,
void
*
data
)
{
schedule_work
(
&
bat_work
);
return
IRQ_HANDLED
;
}
#ifdef CONFIG_PM
static
int
wm97xx_bat_suspend
(
struct
platform_device
*
dev
,
pm_message_t
state
)
static
int
wm97xx_bat_suspend
(
struct
device
*
dev
)
{
flush_scheduled_work
();
return
0
;
}
static
int
wm97xx_bat_resume
(
struct
platform_
device
*
dev
)
static
int
wm97xx_bat_resume
(
struct
device
*
dev
)
{
schedule_work
(
&
bat_work
);
return
0
;
}
#else
#define wm97xx_bat_suspend NULL
#define wm97xx_bat_resume NULL
static
struct
dev_pm_ops
wm97xx_bat_pm_ops
=
{
.
suspend
=
wm97xx_bat_suspend
,
.
resume
=
wm97xx_bat_resume
,
};
#endif
static
int
__devinit
wm97xx_bat_probe
(
struct
platform_device
*
dev
)
...
...
@@ -149,6 +168,15 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev)
int
ret
=
0
;
int
props
=
1
;
/* POWER_SUPPLY_PROP_PRESENT */
int
i
=
0
;
struct
wm97xx_pdata
*
wmdata
=
dev
->
dev
.
platform_data
;
struct
wm97xx_batt_pdata
*
pdata
;
if
(
gpdata
)
{
dev_err
(
&
dev
->
dev
,
"Do not pass platform_data through "
"wm97xx_bat_set_pdata!
\n
"
);
return
-
EINVAL
;
}
else
pdata
=
wmdata
->
batt_pdata
;
if
(
dev
->
id
!=
-
1
)
return
-
EINVAL
;
...
...
@@ -156,15 +184,20 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev)
mutex_init
(
&
work_lock
);
if
(
!
pdata
)
{
dev_err
(
&
dev
->
dev
,
"
Please use wm97xx_bat_set_pdata
\n
"
);
dev_err
(
&
dev
->
dev
,
"
No platform_data supplied
\n
"
);
return
-
EINVAL
;
}
if
(
pdata
->
charge_gpio
>=
0
&&
gpio_is_valid
(
pdata
->
charge_gpio
))
{
if
(
gpio_is_valid
(
pdata
->
charge_gpio
))
{
ret
=
gpio_request
(
pdata
->
charge_gpio
,
"BATT CHRG"
);
if
(
ret
)
goto
err
;
ret
=
gpio_direction_input
(
pdata
->
charge_gpio
);
if
(
ret
)
goto
err2
;
ret
=
request_irq
(
gpio_to_irq
(
pdata
->
charge_gpio
),
wm97xx_chrg_irq
,
IRQF_DISABLED
,
"AC Detect"
,
0
);
if
(
ret
)
goto
err2
;
props
++
;
/* POWER_SUPPLY_PROP_STATUS */
...
...
@@ -183,7 +216,7 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev)
prop
=
kzalloc
(
props
*
sizeof
(
*
prop
),
GFP_KERNEL
);
if
(
!
prop
)
goto
err
2
;
goto
err
3
;
prop
[
i
++
]
=
POWER_SUPPLY_PROP_PRESENT
;
if
(
pdata
->
charge_gpio
>=
0
)
...
...
@@ -216,21 +249,30 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev)
if
(
!
ret
)
schedule_work
(
&
bat_work
);
else
goto
err
3
;
goto
err
4
;
return
0
;
err
3
:
err
4
:
kfree
(
prop
);
err3:
if
(
gpio_is_valid
(
pdata
->
charge_gpio
))
free_irq
(
gpio_to_irq
(
pdata
->
charge_gpio
),
dev
);
err2:
gpio_free
(
pdata
->
charge_gpio
);
if
(
gpio_is_valid
(
pdata
->
charge_gpio
))
gpio_free
(
pdata
->
charge_gpio
);
err:
return
ret
;
}
static
int
__devexit
wm97xx_bat_remove
(
struct
platform_device
*
dev
)
{
if
(
pdata
&&
pdata
->
charge_gpio
&&
pdata
->
charge_gpio
>=
0
)
struct
wm97xx_pdata
*
wmdata
=
dev
->
dev
.
platform_data
;
struct
wm97xx_batt_pdata
*
pdata
=
wmdata
->
batt_pdata
;
if
(
pdata
&&
gpio_is_valid
(
pdata
->
charge_gpio
))
{
free_irq
(
gpio_to_irq
(
pdata
->
charge_gpio
),
dev
);
gpio_free
(
pdata
->
charge_gpio
);
}
flush_scheduled_work
();
power_supply_unregister
(
&
bat_ps
);
kfree
(
prop
);
...
...
@@ -241,11 +283,12 @@ static struct platform_driver wm97xx_bat_driver = {
.
driver
=
{
.
name
=
"wm97xx-battery"
,
.
owner
=
THIS_MODULE
,
#ifdef CONFIG_PM
.
pm
=
&
wm97xx_bat_pm_ops
,
#endif
},
.
probe
=
wm97xx_bat_probe
,
.
remove
=
__devexit_p
(
wm97xx_bat_remove
),
.
suspend
=
wm97xx_bat_suspend
,
.
resume
=
wm97xx_bat_resume
,
};
static
int
__init
wm97xx_bat_init
(
void
)
...
...
@@ -258,9 +301,9 @@ static void __exit wm97xx_bat_exit(void)
platform_driver_unregister
(
&
wm97xx_bat_driver
);
}
void
__init
wm97xx_bat_set_pdata
(
struct
wm97xx_batt_info
*
data
)
void
wm97xx_bat_set_pdata
(
struct
wm97xx_batt_info
*
data
)
{
pdata
=
data
;
g
pdata
=
data
;
}
EXPORT_SYMBOL_GPL
(
wm97xx_bat_set_pdata
);
...
...
include/linux/mfd/wm831x/pmu.h
0 → 100644
View file @
7d9d9b34
/*
* include/linux/mfd/wm831x/pmu.h -- PMU for WM831x
*
* Copyright 2009 Wolfson Microelectronics PLC.
*
* Author: Mark Brown <broonie@opensource.wolfsonmicro.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.
*
*/
#ifndef __MFD_WM831X_PMU_H__
#define __MFD_WM831X_PMU_H__
/*
* R16387 (0x4003) - Power State
*/
#define WM831X_CHIP_ON 0x8000
/* CHIP_ON */
#define WM831X_CHIP_ON_MASK 0x8000
/* CHIP_ON */
#define WM831X_CHIP_ON_SHIFT 15
/* CHIP_ON */
#define WM831X_CHIP_ON_WIDTH 1
/* CHIP_ON */
#define WM831X_CHIP_SLP 0x4000
/* CHIP_SLP */
#define WM831X_CHIP_SLP_MASK 0x4000
/* CHIP_SLP */
#define WM831X_CHIP_SLP_SHIFT 14
/* CHIP_SLP */
#define WM831X_CHIP_SLP_WIDTH 1
/* CHIP_SLP */
#define WM831X_REF_LP 0x1000
/* REF_LP */
#define WM831X_REF_LP_MASK 0x1000
/* REF_LP */
#define WM831X_REF_LP_SHIFT 12
/* REF_LP */
#define WM831X_REF_LP_WIDTH 1
/* REF_LP */
#define WM831X_PWRSTATE_DLY_MASK 0x0C00
/* PWRSTATE_DLY - [11:10] */
#define WM831X_PWRSTATE_DLY_SHIFT 10
/* PWRSTATE_DLY - [11:10] */
#define WM831X_PWRSTATE_DLY_WIDTH 2
/* PWRSTATE_DLY - [11:10] */
#define WM831X_SWRST_DLY 0x0200
/* SWRST_DLY */
#define WM831X_SWRST_DLY_MASK 0x0200
/* SWRST_DLY */
#define WM831X_SWRST_DLY_SHIFT 9
/* SWRST_DLY */
#define WM831X_SWRST_DLY_WIDTH 1
/* SWRST_DLY */
#define WM831X_USB100MA_STARTUP_MASK 0x0030
/* USB100MA_STARTUP - [5:4] */
#define WM831X_USB100MA_STARTUP_SHIFT 4
/* USB100MA_STARTUP - [5:4] */
#define WM831X_USB100MA_STARTUP_WIDTH 2
/* USB100MA_STARTUP - [5:4] */
#define WM831X_USB_CURR_STS 0x0008
/* USB_CURR_STS */
#define WM831X_USB_CURR_STS_MASK 0x0008
/* USB_CURR_STS */
#define WM831X_USB_CURR_STS_SHIFT 3
/* USB_CURR_STS */
#define WM831X_USB_CURR_STS_WIDTH 1
/* USB_CURR_STS */
#define WM831X_USB_ILIM_MASK 0x0007
/* USB_ILIM - [2:0] */
#define WM831X_USB_ILIM_SHIFT 0
/* USB_ILIM - [2:0] */
#define WM831X_USB_ILIM_WIDTH 3
/* USB_ILIM - [2:0] */
/*
* R16397 (0x400D) - System Status
*/
#define WM831X_THW_STS 0x8000
/* THW_STS */
#define WM831X_THW_STS_MASK 0x8000
/* THW_STS */
#define WM831X_THW_STS_SHIFT 15
/* THW_STS */
#define WM831X_THW_STS_WIDTH 1
/* THW_STS */
#define WM831X_PWR_SRC_BATT 0x0400
/* PWR_SRC_BATT */
#define WM831X_PWR_SRC_BATT_MASK 0x0400
/* PWR_SRC_BATT */
#define WM831X_PWR_SRC_BATT_SHIFT 10
/* PWR_SRC_BATT */
#define WM831X_PWR_SRC_BATT_WIDTH 1
/* PWR_SRC_BATT */
#define WM831X_PWR_WALL 0x0200
/* PWR_WALL */
#define WM831X_PWR_WALL_MASK 0x0200
/* PWR_WALL */
#define WM831X_PWR_WALL_SHIFT 9
/* PWR_WALL */
#define WM831X_PWR_WALL_WIDTH 1
/* PWR_WALL */
#define WM831X_PWR_USB 0x0100
/* PWR_USB */
#define WM831X_PWR_USB_MASK 0x0100
/* PWR_USB */
#define WM831X_PWR_USB_SHIFT 8
/* PWR_USB */
#define WM831X_PWR_USB_WIDTH 1
/* PWR_USB */
#define WM831X_MAIN_STATE_MASK 0x001F
/* MAIN_STATE - [4:0] */
#define WM831X_MAIN_STATE_SHIFT 0
/* MAIN_STATE - [4:0] */
#define WM831X_MAIN_STATE_WIDTH 5
/* MAIN_STATE - [4:0] */
/*
* R16456 (0x4048) - Charger Control 1
*/
#define WM831X_CHG_ENA 0x8000
/* CHG_ENA */
#define WM831X_CHG_ENA_MASK 0x8000
/* CHG_ENA */
#define WM831X_CHG_ENA_SHIFT 15
/* CHG_ENA */
#define WM831X_CHG_ENA_WIDTH 1
/* CHG_ENA */
#define WM831X_CHG_FRC 0x4000
/* CHG_FRC */
#define WM831X_CHG_FRC_MASK 0x4000
/* CHG_FRC */
#define WM831X_CHG_FRC_SHIFT 14
/* CHG_FRC */
#define WM831X_CHG_FRC_WIDTH 1
/* CHG_FRC */
#define WM831X_CHG_ITERM_MASK 0x1C00
/* CHG_ITERM - [12:10] */
#define WM831X_CHG_ITERM_SHIFT 10
/* CHG_ITERM - [12:10] */
#define WM831X_CHG_ITERM_WIDTH 3
/* CHG_ITERM - [12:10] */
#define WM831X_CHG_FAST 0x0020
/* CHG_FAST */
#define WM831X_CHG_FAST_MASK 0x0020
/* CHG_FAST */
#define WM831X_CHG_FAST_SHIFT 5
/* CHG_FAST */
#define WM831X_CHG_FAST_WIDTH 1
/* CHG_FAST */
#define WM831X_CHG_IMON_ENA 0x0002
/* CHG_IMON_ENA */
#define WM831X_CHG_IMON_ENA_MASK 0x0002
/* CHG_IMON_ENA */
#define WM831X_CHG_IMON_ENA_SHIFT 1
/* CHG_IMON_ENA */
#define WM831X_CHG_IMON_ENA_WIDTH 1
/* CHG_IMON_ENA */
#define WM831X_CHG_CHIP_TEMP_MON 0x0001
/* CHG_CHIP_TEMP_MON */
#define WM831X_CHG_CHIP_TEMP_MON_MASK 0x0001
/* CHG_CHIP_TEMP_MON */
#define WM831X_CHG_CHIP_TEMP_MON_SHIFT 0
/* CHG_CHIP_TEMP_MON */
#define WM831X_CHG_CHIP_TEMP_MON_WIDTH 1
/* CHG_CHIP_TEMP_MON */
/*
* R16457 (0x4049) - Charger Control 2
*/
#define WM831X_CHG_OFF_MSK 0x4000
/* CHG_OFF_MSK */
#define WM831X_CHG_OFF_MSK_MASK 0x4000
/* CHG_OFF_MSK */
#define WM831X_CHG_OFF_MSK_SHIFT 14
/* CHG_OFF_MSK */
#define WM831X_CHG_OFF_MSK_WIDTH 1
/* CHG_OFF_MSK */
#define WM831X_CHG_TIME_MASK 0x0F00
/* CHG_TIME - [11:8] */
#define WM831X_CHG_TIME_SHIFT 8
/* CHG_TIME - [11:8] */
#define WM831X_CHG_TIME_WIDTH 4
/* CHG_TIME - [11:8] */
#define WM831X_CHG_TRKL_ILIM_MASK 0x00C0
/* CHG_TRKL_ILIM - [7:6] */
#define WM831X_CHG_TRKL_ILIM_SHIFT 6
/* CHG_TRKL_ILIM - [7:6] */
#define WM831X_CHG_TRKL_ILIM_WIDTH 2
/* CHG_TRKL_ILIM - [7:6] */
#define WM831X_CHG_VSEL_MASK 0x0030
/* CHG_VSEL - [5:4] */
#define WM831X_CHG_VSEL_SHIFT 4
/* CHG_VSEL - [5:4] */
#define WM831X_CHG_VSEL_WIDTH 2
/* CHG_VSEL - [5:4] */
#define WM831X_CHG_FAST_ILIM_MASK 0x000F
/* CHG_FAST_ILIM - [3:0] */
#define WM831X_CHG_FAST_ILIM_SHIFT 0
/* CHG_FAST_ILIM - [3:0] */
#define WM831X_CHG_FAST_ILIM_WIDTH 4
/* CHG_FAST_ILIM - [3:0] */
/*
* R16458 (0x404A) - Charger Status
*/
#define WM831X_BATT_OV_STS 0x8000
/* BATT_OV_STS */
#define WM831X_BATT_OV_STS_MASK 0x8000
/* BATT_OV_STS */
#define WM831X_BATT_OV_STS_SHIFT 15
/* BATT_OV_STS */
#define WM831X_BATT_OV_STS_WIDTH 1
/* BATT_OV_STS */
#define WM831X_CHG_STATE_MASK 0x7000
/* CHG_STATE - [14:12] */
#define WM831X_CHG_STATE_SHIFT 12
/* CHG_STATE - [14:12] */
#define WM831X_CHG_STATE_WIDTH 3
/* CHG_STATE - [14:12] */
#define WM831X_BATT_HOT_STS 0x0800
/* BATT_HOT_STS */
#define WM831X_BATT_HOT_STS_MASK 0x0800
/* BATT_HOT_STS */
#define WM831X_BATT_HOT_STS_SHIFT 11
/* BATT_HOT_STS */
#define WM831X_BATT_HOT_STS_WIDTH 1
/* BATT_HOT_STS */
#define WM831X_BATT_COLD_STS 0x0400
/* BATT_COLD_STS */
#define WM831X_BATT_COLD_STS_MASK 0x0400
/* BATT_COLD_STS */
#define WM831X_BATT_COLD_STS_SHIFT 10
/* BATT_COLD_STS */
#define WM831X_BATT_COLD_STS_WIDTH 1
/* BATT_COLD_STS */
#define WM831X_CHG_TOPOFF 0x0200
/* CHG_TOPOFF */
#define WM831X_CHG_TOPOFF_MASK 0x0200
/* CHG_TOPOFF */
#define WM831X_CHG_TOPOFF_SHIFT 9
/* CHG_TOPOFF */
#define WM831X_CHG_TOPOFF_WIDTH 1
/* CHG_TOPOFF */
#define WM831X_CHG_ACTIVE 0x0100
/* CHG_ACTIVE */
#define WM831X_CHG_ACTIVE_MASK 0x0100
/* CHG_ACTIVE */
#define WM831X_CHG_ACTIVE_SHIFT 8
/* CHG_ACTIVE */
#define WM831X_CHG_ACTIVE_WIDTH 1
/* CHG_ACTIVE */
#define WM831X_CHG_TIME_ELAPSED_MASK 0x00FF
/* CHG_TIME_ELAPSED - [7:0] */
#define WM831X_CHG_TIME_ELAPSED_SHIFT 0
/* CHG_TIME_ELAPSED - [7:0] */
#define WM831X_CHG_TIME_ELAPSED_WIDTH 8
/* CHG_TIME_ELAPSED - [7:0] */
#define WM831X_CHG_STATE_OFF (0 << WM831X_CHG_STATE_SHIFT)
#define WM831X_CHG_STATE_TRICKLE (1 << WM831X_CHG_STATE_SHIFT)
#define WM831X_CHG_STATE_FAST (2 << WM831X_CHG_STATE_SHIFT)
#define WM831X_CHG_STATE_TRICKLE_OT (3 << WM831X_CHG_STATE_SHIFT)
#define WM831X_CHG_STATE_FAST_OT (4 << WM831X_CHG_STATE_SHIFT)
#define WM831X_CHG_STATE_DEFECTIVE (5 << WM831X_CHG_STATE_SHIFT)
/*
* R16459 (0x404B) - Backup Charger Control
*/
#define WM831X_BKUP_CHG_ENA 0x8000
/* BKUP_CHG_ENA */
#define WM831X_BKUP_CHG_ENA_MASK 0x8000
/* BKUP_CHG_ENA */
#define WM831X_BKUP_CHG_ENA_SHIFT 15
/* BKUP_CHG_ENA */
#define WM831X_BKUP_CHG_ENA_WIDTH 1
/* BKUP_CHG_ENA */
#define WM831X_BKUP_CHG_STS 0x4000
/* BKUP_CHG_STS */
#define WM831X_BKUP_CHG_STS_MASK 0x4000
/* BKUP_CHG_STS */
#define WM831X_BKUP_CHG_STS_SHIFT 14
/* BKUP_CHG_STS */
#define WM831X_BKUP_CHG_STS_WIDTH 1
/* BKUP_CHG_STS */
#define WM831X_BKUP_CHG_MODE 0x1000
/* BKUP_CHG_MODE */
#define WM831X_BKUP_CHG_MODE_MASK 0x1000
/* BKUP_CHG_MODE */
#define WM831X_BKUP_CHG_MODE_SHIFT 12
/* BKUP_CHG_MODE */
#define WM831X_BKUP_CHG_MODE_WIDTH 1
/* BKUP_CHG_MODE */
#define WM831X_BKUP_BATT_DET_ENA 0x0800
/* BKUP_BATT_DET_ENA */
#define WM831X_BKUP_BATT_DET_ENA_MASK 0x0800
/* BKUP_BATT_DET_ENA */
#define WM831X_BKUP_BATT_DET_ENA_SHIFT 11
/* BKUP_BATT_DET_ENA */
#define WM831X_BKUP_BATT_DET_ENA_WIDTH 1
/* BKUP_BATT_DET_ENA */
#define WM831X_BKUP_BATT_STS 0x0400
/* BKUP_BATT_STS */
#define WM831X_BKUP_BATT_STS_MASK 0x0400
/* BKUP_BATT_STS */
#define WM831X_BKUP_BATT_STS_SHIFT 10
/* BKUP_BATT_STS */
#define WM831X_BKUP_BATT_STS_WIDTH 1
/* BKUP_BATT_STS */
#define WM831X_BKUP_CHG_VLIM 0x0010
/* BKUP_CHG_VLIM */
#define WM831X_BKUP_CHG_VLIM_MASK 0x0010
/* BKUP_CHG_VLIM */
#define WM831X_BKUP_CHG_VLIM_SHIFT 4
/* BKUP_CHG_VLIM */
#define WM831X_BKUP_CHG_VLIM_WIDTH 1
/* BKUP_CHG_VLIM */
#define WM831X_BKUP_CHG_ILIM_MASK 0x0003
/* BKUP_CHG_ILIM - [1:0] */
#define WM831X_BKUP_CHG_ILIM_SHIFT 0
/* BKUP_CHG_ILIM - [1:0] */
#define WM831X_BKUP_CHG_ILIM_WIDTH 2
/* BKUP_CHG_ILIM - [1:0] */
#endif
include/linux/power_supply.h
View file @
7d9d9b34
...
...
@@ -38,6 +38,13 @@ enum {
POWER_SUPPLY_STATUS_FULL
,
};
enum
{
POWER_SUPPLY_CHARGE_TYPE_UNKNOWN
=
0
,
POWER_SUPPLY_CHARGE_TYPE_NONE
,
POWER_SUPPLY_CHARGE_TYPE_TRICKLE
,
POWER_SUPPLY_CHARGE_TYPE_FAST
,
};
enum
{
POWER_SUPPLY_HEALTH_UNKNOWN
=
0
,
POWER_SUPPLY_HEALTH_GOOD
,
...
...
@@ -58,9 +65,19 @@ enum {
POWER_SUPPLY_TECHNOLOGY_LiMn
,
};
enum
{
POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN
=
0
,
POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL
,
POWER_SUPPLY_CAPACITY_LEVEL_LOW
,
POWER_SUPPLY_CAPACITY_LEVEL_NORMAL
,
POWER_SUPPLY_CAPACITY_LEVEL_HIGH
,
POWER_SUPPLY_CAPACITY_LEVEL_FULL
,
};
enum
power_supply_property
{
/* Properties of type `int' */
POWER_SUPPLY_PROP_STATUS
=
0
,
POWER_SUPPLY_PROP_CHARGE_TYPE
,
POWER_SUPPLY_PROP_HEALTH
,
POWER_SUPPLY_PROP_PRESENT
,
POWER_SUPPLY_PROP_ONLINE
,
...
...
@@ -89,6 +106,7 @@ enum power_supply_property {
POWER_SUPPLY_PROP_ENERGY_NOW
,
POWER_SUPPLY_PROP_ENERGY_AVG
,
POWER_SUPPLY_PROP_CAPACITY
,
/* in percents! */
POWER_SUPPLY_PROP_CAPACITY_LEVEL
,
POWER_SUPPLY_PROP_TEMP
,
POWER_SUPPLY_PROP_TEMP_AMBIENT
,
POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW
,
...
...
@@ -126,6 +144,7 @@ struct power_supply {
enum
power_supply_property
psp
,
union
power_supply_propval
*
val
);
void
(
*
external_power_changed
)(
struct
power_supply
*
psy
);
void
(
*
set_charged
)(
struct
power_supply
*
psy
);
/* For APM emulation, think legacy userspace. */
int
use_for_apm
;
...
...
@@ -165,8 +184,10 @@ struct power_supply_info {
int
use_for_apm
;
};
extern
struct
power_supply
*
power_supply_get_by_name
(
char
*
name
);
extern
void
power_supply_changed
(
struct
power_supply
*
psy
);
extern
int
power_supply_am_i_supplied
(
struct
power_supply
*
psy
);
extern
int
power_supply_set_battery_charged
(
struct
power_supply
*
psy
);
#if defined(CONFIG_POWER_SUPPLY) || defined(CONFIG_POWER_SUPPLY_MODULE)
extern
int
power_supply_is_system_supplied
(
void
);
...
...
include/linux/wm97xx.h
View file @
7d9d9b34
...
...
@@ -293,6 +293,24 @@ struct wm97xx {
u16
suspend_mode
;
/* PRP in suspend mode */
};
struct
wm97xx_batt_pdata
{
int
batt_aux
;
int
temp_aux
;
int
charge_gpio
;
int
min_voltage
;
int
max_voltage
;
int
batt_div
;
int
batt_mult
;
int
temp_div
;
int
temp_mult
;
int
batt_tech
;
char
*
batt_name
;
};
struct
wm97xx_pdata
{
struct
wm97xx_batt_pdata
*
batt_pdata
;
/* battery data */
};
/*
* Codec GPIO access (not supported on WM9705)
* This can be used to set/get codec GPIO and Virtual GPIO status.
...
...
include/linux/wm97xx_batt.h
View file @
7d9d9b34
...
...
@@ -3,22 +3,12 @@
#include <linux/wm97xx.h>
struct
wm97xx_batt_info
{
int
batt_aux
;
int
temp_aux
;
int
charge_gpio
;
int
min_voltage
;
int
max_voltage
;
int
batt_div
;
int
batt_mult
;
int
temp_div
;
int
temp_mult
;
int
batt_tech
;
char
*
batt_name
;
};
#warning This file will be removed soon, use wm97xx.h instead!
#define wm97xx_batt_info wm97xx_batt_pdata
#ifdef CONFIG_BATTERY_WM97XX
void
__init
wm97xx_bat_set_pdata
(
struct
wm97xx_batt_info
*
data
);
void
wm97xx_bat_set_pdata
(
struct
wm97xx_batt_info
*
data
);
#else
static
inline
void
wm97xx_bat_set_pdata
(
struct
wm97xx_batt_info
*
data
)
{}
#endif
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment