Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
16922ffe
Commit
16922ffe
authored
Oct 18, 2019
by
Jonathan Cameron
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'ib-ab8500-5.4-rc1' into HEAD
Immutable branch as considerable overlap with mfd, power and hwmon.
parents
686191a7
a77fc111
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
1495 additions
and
864 deletions
+1495
-864
Documentation/devicetree/bindings/mfd/ab8500.txt
Documentation/devicetree/bindings/mfd/ab8500.txt
+119
-0
MAINTAINERS
MAINTAINERS
+1
-0
drivers/hwmon/Kconfig
drivers/hwmon/Kconfig
+2
-1
drivers/hwmon/ab8500.c
drivers/hwmon/ab8500.c
+41
-24
drivers/iio/adc/Kconfig
drivers/iio/adc/Kconfig
+10
-0
drivers/iio/adc/Makefile
drivers/iio/adc/Makefile
+1
-0
drivers/iio/adc/ab8500-gpadc.c
drivers/iio/adc/ab8500-gpadc.c
+1218
-0
drivers/mfd/Kconfig
drivers/mfd/Kconfig
+0
-7
drivers/mfd/Makefile
drivers/mfd/Makefile
+0
-1
drivers/mfd/ab8500-debugfs.c
drivers/mfd/ab8500-debugfs.c
+0
-715
drivers/power/supply/Kconfig
drivers/power/supply/Kconfig
+1
-1
drivers/power/supply/ab8500_btemp.c
drivers/power/supply/ab8500_btemp.c
+29
-12
drivers/power/supply/ab8500_charger.c
drivers/power/supply/ab8500_charger.c
+58
-20
drivers/power/supply/ab8500_fg.c
drivers/power/supply/ab8500_fg.c
+15
-8
include/linux/mfd/abx500/ab8500-gpadc.h
include/linux/mfd/abx500/ab8500-gpadc.h
+0
-75
No files found.
Documentation/devicetree/bindings/mfd/ab8500.txt
View file @
16922ffe
...
...
@@ -69,6 +69,18 @@ Required child device properties:
- compatible : "stericsson,ab8500-[bm|btemp|charger|fg|gpadc|gpio|ponkey|
pwm|regulator|rtc|sysctrl|usb]";
A few child devices require ADC channels from the GPADC node. Those follow the
standard bindings from iio/iio-bindings.txt and iio/adc/adc.txt
abx500-temp : io-channels "aux1" and "aux2" for measuring external
temperatures.
ab8500-fg : io-channel "main_bat_v" for measuring main battery voltage,
ab8500-btemp : io-channels "btemp_ball" and "bat_ctrl" for measuring the
battery voltage.
ab8500-charger : io-channels "main_charger_v", "main_charger_c", "vbus_v",
"usb_charger_c" for measuring voltage and current of the
different charging supplies.
Optional child device properties:
- interrupts : contains the device IRQ(s) using the 2-cell format (see above)
- interrupt-names : contains names of IRQ resource in the order in which they were
...
...
@@ -102,8 +114,115 @@ ab8500 {
39 0x4>;
interrupt-names = "HW_CONV_END", "SW_CONV_END";
vddadc-supply = <&ab8500_ldo_tvout_reg>;
#address-cells = <1>;
#size-cells = <0>;
#io-channel-cells = <1>;
/* GPADC channels */
bat_ctrl: channel@1 {
reg = <0x01>;
};
btemp_ball: channel@2 {
reg = <0x02>;
};
main_charger_v: channel@3 {
reg = <0x03>;
};
acc_detect1: channel@4 {
reg = <0x04>;
};
acc_detect2: channel@5 {
reg = <0x05>;
};
adc_aux1: channel@6 {
reg = <0x06>;
};
adc_aux2: channel@7 {
reg = <0x07>;
};
main_batt_v: channel@8 {
reg = <0x08>;
};
vbus_v: channel@9 {
reg = <0x09>;
};
main_charger_c: channel@a {
reg = <0x0a>;
};
usb_charger_c: channel@b {
reg = <0x0b>;
};
bk_bat_v: channel@c {
reg = <0x0c>;
};
die_temp: channel@d {
reg = <0x0d>;
};
usb_id: channel@e {
reg = <0x0e>;
};
xtal_temp: channel@12 {
reg = <0x12>;
};
vbat_true_meas: channel@13 {
reg = <0x13>;
};
bat_ctrl_and_ibat: channel@1c {
reg = <0x1c>;
};
vbat_meas_and_ibat: channel@1d {
reg = <0x1d>;
};
vbat_true_meas_and_ibat: channel@1e {
reg = <0x1e>;
};
bat_temp_and_ibat: channel@1f {
reg = <0x1f>;
};
};
ab8500_temp {
compatible = "stericsson,abx500-temp";
io-channels = <&gpadc 0x06>,
<&gpadc 0x07>;
io-channel-name = "aux1", "aux2";
};
ab8500_battery: ab8500_battery {
stericsson,battery-type = "LIPO";
thermistor-on-batctrl;
};
ab8500_fg {
compatible = "stericsson,ab8500-fg";
battery = <&ab8500_battery>;
io-channels = <&gpadc 0x08>;
io-channel-name = "main_bat_v";
};
ab8500_btemp {
compatible = "stericsson,ab8500-btemp";
battery = <&ab8500_battery>;
io-channels = <&gpadc 0x02>,
<&gpadc 0x01>;
io-channel-name = "btemp_ball",
"bat_ctrl";
};
ab8500_charger {
compatible = "stericsson,ab8500-charger";
battery = <&ab8500_battery>;
vddadc-supply = <&ab8500_ldo_tvout_reg>;
io-channels = <&gpadc 0x03>,
<&gpadc 0x0a>,
<&gpadc 0x09>,
<&gpadc 0x0b>;
io-channel-name = "main_charger_v",
"main_charger_c",
"vbus_v",
"usb_charger_c";
};
ab8500-usb {
compatible = "stericsson,ab8500-usb";
interrupts = < 90 0x4
...
...
MAINTAINERS
View file @
16922ffe
...
...
@@ -2005,6 +2005,7 @@ F: drivers/dma/ste_dma40*
F: drivers/hwspinlock/u8500_hsem.c
F: drivers/i2c/busses/i2c-nomadik.c
F: drivers/i2c/busses/i2c-stu300.c
F: drivers/iio/adc/ab8500-gpadc.c
F: drivers/mfd/ab3100*
F: drivers/mfd/ab8500*
F: drivers/mfd/abx500*
...
...
drivers/hwmon/Kconfig
View file @
16922ffe
...
...
@@ -40,7 +40,8 @@ comment "Native drivers"
config SENSORS_AB8500
tristate "AB8500 thermal monitoring"
depends on AB8500_GPADC && AB8500_BM
depends on AB8500_GPADC && AB8500_BM && (IIO = y)
default n
help
If you say yes here you get support for the thermal sensor part
of the AB8500 chip. The driver includes thermal management for
...
...
drivers/hwmon/ab8500.c
View file @
16922ffe
...
...
@@ -17,20 +17,24 @@
#include <linux/hwmon-sysfs.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500-bm.h>
#include <linux/mfd/abx500/ab8500-gpadc.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/power/ab8500.h>
#include <linux/reboot.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/iio/consumer.h>
#include "abx500.h"
#define DEFAULT_POWER_OFF_DELAY (HZ * 10)
#define THERMAL_VCC 1800
#define PULL_UP_RESISTOR 47000
/* Number of monitored sensors should not greater than NUM_SENSORS */
#define NUM_MONITORED_SENSORS 4
#define AB8500_SENSOR_AUX1 0
#define AB8500_SENSOR_AUX2 1
#define AB8500_SENSOR_BTEMP_BALL 2
#define AB8500_SENSOR_BAT_CTRL 3
#define NUM_MONITORED_SENSORS 4
struct
ab8500_gpadc_cfg
{
const
struct
abx500_res_to_temp
*
temp_tbl
;
...
...
@@ -40,7 +44,8 @@ struct ab8500_gpadc_cfg {
};
struct
ab8500_temp
{
struct
ab8500_gpadc
*
gpadc
;
struct
iio_channel
*
aux1
;
struct
iio_channel
*
aux2
;
struct
ab8500_btemp
*
btemp
;
struct
delayed_work
power_off_work
;
struct
ab8500_gpadc_cfg
cfg
;
...
...
@@ -82,15 +87,21 @@ static int ab8500_read_sensor(struct abx500_temp *data, u8 sensor, int *temp)
int
voltage
,
ret
;
struct
ab8500_temp
*
ab8500_data
=
data
->
plat_data
;
if
(
sensor
==
BAT_CTRL
)
{
*
temp
=
ab8500_btemp_get_batctrl_temp
(
ab8500_data
->
btemp
);
}
else
if
(
sensor
==
BTEMP_BALL
)
{
if
(
sensor
==
AB8500_SENSOR_BTEMP_BALL
)
{
*
temp
=
ab8500_btemp_get_temp
(
ab8500_data
->
btemp
);
}
else
{
voltage
=
ab8500_gpadc_convert
(
ab8500_data
->
gpadc
,
sensor
);
if
(
voltage
<
0
)
return
voltage
;
}
else
if
(
sensor
==
AB8500_SENSOR_BAT_CTRL
)
{
*
temp
=
ab8500_btemp_get_batctrl_temp
(
ab8500_data
->
btemp
);
}
else
if
(
sensor
==
AB8500_SENSOR_AUX1
)
{
ret
=
iio_read_channel_processed
(
ab8500_data
->
aux1
,
&
voltage
);
if
(
ret
<
0
)
return
ret
;
ret
=
ab8500_voltage_to_temp
(
&
ab8500_data
->
cfg
,
voltage
,
temp
);
if
(
ret
<
0
)
return
ret
;
}
else
if
(
sensor
==
AB8500_SENSOR_AUX2
)
{
ret
=
iio_read_channel_processed
(
ab8500_data
->
aux2
,
&
voltage
);
if
(
ret
<
0
)
return
ret
;
ret
=
ab8500_voltage_to_temp
(
&
ab8500_data
->
cfg
,
voltage
,
temp
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -164,10 +175,6 @@ int abx500_hwmon_init(struct abx500_temp *data)
if
(
!
ab8500_data
)
return
-
ENOMEM
;
ab8500_data
->
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
if
(
IS_ERR
(
ab8500_data
->
gpadc
))
return
PTR_ERR
(
ab8500_data
->
gpadc
);
ab8500_data
->
btemp
=
ab8500_btemp_get
();
if
(
IS_ERR
(
ab8500_data
->
btemp
))
return
PTR_ERR
(
ab8500_data
->
btemp
);
...
...
@@ -181,15 +188,25 @@ int abx500_hwmon_init(struct abx500_temp *data)
ab8500_data
->
cfg
.
tbl_sz
=
ab8500_temp_tbl_a_size
;
data
->
plat_data
=
ab8500_data
;
ab8500_data
->
aux1
=
devm_iio_channel_get
(
&
data
->
pdev
->
dev
,
"aux1"
);
if
(
IS_ERR
(
ab8500_data
->
aux1
))
{
if
(
PTR_ERR
(
ab8500_data
->
aux1
)
==
-
ENODEV
)
return
-
EPROBE_DEFER
;
dev_err
(
&
data
->
pdev
->
dev
,
"failed to get AUX1 ADC channel
\n
"
);
return
PTR_ERR
(
ab8500_data
->
aux1
);
}
ab8500_data
->
aux2
=
devm_iio_channel_get
(
&
data
->
pdev
->
dev
,
"aux2"
);
if
(
IS_ERR
(
ab8500_data
->
aux2
))
{
if
(
PTR_ERR
(
ab8500_data
->
aux2
)
==
-
ENODEV
)
return
-
EPROBE_DEFER
;
dev_err
(
&
data
->
pdev
->
dev
,
"failed to get AUX2 ADC channel
\n
"
);
return
PTR_ERR
(
ab8500_data
->
aux2
);
}
/*
* ADC_AUX1 and ADC_AUX2, connected to external NTC
* BTEMP_BALL and BAT_CTRL, fixed usage
*/
data
->
gpadc_addr
[
0
]
=
ADC_AUX1
;
data
->
gpadc_addr
[
1
]
=
ADC_AUX2
;
data
->
gpadc_addr
[
2
]
=
BTEMP_BALL
;
data
->
gpadc_addr
[
3
]
=
BAT_CTRL
;
data
->
gpadc_addr
[
0
]
=
AB8500_SENSOR_AUX1
;
data
->
gpadc_addr
[
1
]
=
AB8500_SENSOR_AUX2
;
data
->
gpadc_addr
[
2
]
=
AB8500_SENSOR_BTEMP_BALL
;
data
->
gpadc_addr
[
3
]
=
AB8500_SENSOR_BAT_CTRL
;
data
->
monitored_sensors
=
NUM_MONITORED_SENSORS
;
data
->
ops
.
read_sensor
=
ab8500_read_sensor
;
...
...
drivers/iio/adc/Kconfig
View file @
16922ffe
...
...
@@ -6,6 +6,16 @@
menu "Analog to digital converters"
config AB8500_GPADC
bool "ST-Ericsson AB8500 GPADC driver"
depends on AB8500_CORE && REGULATOR_AB8500
default y
help
AB8500 Analog Baseband, mixed signal integrated circuit GPADC
(General Purpose Analog to Digital Converter) driver used to monitor
internal voltages, convert accessory and battery, AC (charger, mains)
and USB voltages integral to the U8500 platform.
config AD_SIGMA_DELTA
tristate
select IIO_BUFFER
...
...
drivers/iio/adc/Makefile
View file @
16922ffe
...
...
@@ -4,6 +4,7 @@
#
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_AB8500_GPADC)
+=
ab8500-gpadc.o
obj-$(CONFIG_AD_SIGMA_DELTA)
+=
ad_sigma_delta.o
obj-$(CONFIG_AD7124)
+=
ad7124.o
obj-$(CONFIG_AD7266)
+=
ad7266.o
...
...
drivers/
mfd
/ab8500-gpadc.c
→
drivers/
iio/adc
/ab8500-gpadc.c
View file @
16922ffe
...
...
@@ -6,8 +6,26 @@
* Author: Daniel Willerud <daniel.willerud@stericsson.com>
* Author: Johan Palsson <johan.palsson@stericsson.com>
* Author: M'boumba Cedric Madianga
* Author: Linus Walleij <linus.walleij@linaro.org>
*
* AB8500 General Purpose ADC driver. The AB8500 uses reference voltages:
* VinVADC, and VADC relative to GND to do its job. It monitors main and backup
* battery voltages, AC (mains) voltage, USB cable voltage, as well as voltages
* representing the temperature of the chip die and battery, accessory
* detection by resistance measurements using relative voltages and GSM burst
* information.
*
* Some of the voltages are measured on external pins on the IC, such as
* battery temperature or "ADC aux" 1 and 2. Other voltages are internal rails
* from other parts of the ASIC such as main charger voltage, main and battery
* backup voltage or USB VBUS voltage. For this reason drivers for other
* parts of the system are required to obtain handles to the ADC to do work
* for them and the IIO driver provides arbitration among these consumers.
*/
#include <linux/init.h>
#include <linux/bits.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
...
...
@@ -16,22 +34,82 @@
#include <linux/platform_device.h>
#include <linux/completion.h>
#include <linux/regulator/consumer.h>
#include <linux/random.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500/ab8500-gpadc.h>
/*
* GPADC register offsets
* Bank : 0x0A
*/
/* GPADC register offsets and bit definitions */
#define AB8500_GPADC_CTRL1_REG 0x00
/* GPADC control register 1 bits */
#define AB8500_GPADC_CTRL1_DISABLE 0x00
#define AB8500_GPADC_CTRL1_ENABLE BIT(0)
#define AB8500_GPADC_CTRL1_TRIG_ENA BIT(1)
#define AB8500_GPADC_CTRL1_START_SW_CONV BIT(2)
#define AB8500_GPADC_CTRL1_BTEMP_PULL_UP BIT(3)
/* 0 = use rising edge, 1 = use falling edge */
#define AB8500_GPADC_CTRL1_TRIG_EDGE BIT(4)
/* 0 = use VTVOUT, 1 = use VRTC as pull-up supply for battery temp NTC */
#define AB8500_GPADC_CTRL1_PUPSUPSEL BIT(5)
#define AB8500_GPADC_CTRL1_BUF_ENA BIT(6)
#define AB8500_GPADC_CTRL1_ICHAR_ENA BIT(7)
#define AB8500_GPADC_CTRL2_REG 0x01
#define AB8500_GPADC_CTRL3_REG 0x02
/*
* GPADC control register 2 and 3 bits
* the bit layout is the same for SW and HW conversion set-up
*/
#define AB8500_GPADC_CTRL2_AVG_1 0x00
#define AB8500_GPADC_CTRL2_AVG_4 BIT(5)
#define AB8500_GPADC_CTRL2_AVG_8 BIT(6)
#define AB8500_GPADC_CTRL2_AVG_16 (BIT(5) | BIT(6))
enum
ab8500_gpadc_channel
{
AB8500_GPADC_CHAN_UNUSED
=
0x00
,
AB8500_GPADC_CHAN_BAT_CTRL
=
0x01
,
AB8500_GPADC_CHAN_BAT_TEMP
=
0x02
,
/* This is not used on AB8505 */
AB8500_GPADC_CHAN_MAIN_CHARGER
=
0x03
,
AB8500_GPADC_CHAN_ACC_DET_1
=
0x04
,
AB8500_GPADC_CHAN_ACC_DET_2
=
0x05
,
AB8500_GPADC_CHAN_ADC_AUX_1
=
0x06
,
AB8500_GPADC_CHAN_ADC_AUX_2
=
0x07
,
AB8500_GPADC_CHAN_VBAT_A
=
0x08
,
AB8500_GPADC_CHAN_VBUS
=
0x09
,
AB8500_GPADC_CHAN_MAIN_CHARGER_CURRENT
=
0x0a
,
AB8500_GPADC_CHAN_USB_CHARGER_CURRENT
=
0x0b
,
AB8500_GPADC_CHAN_BACKUP_BAT
=
0x0c
,
/* Only on AB8505 */
AB8505_GPADC_CHAN_DIE_TEMP
=
0x0d
,
AB8500_GPADC_CHAN_ID
=
0x0e
,
AB8500_GPADC_CHAN_INTERNAL_TEST_1
=
0x0f
,
AB8500_GPADC_CHAN_INTERNAL_TEST_2
=
0x10
,
AB8500_GPADC_CHAN_INTERNAL_TEST_3
=
0x11
,
/* FIXME: Applicable to all ASIC variants? */
AB8500_GPADC_CHAN_XTAL_TEMP
=
0x12
,
AB8500_GPADC_CHAN_VBAT_TRUE_MEAS
=
0x13
,
/* FIXME: Doesn't seem to work with pure AB8500 */
AB8500_GPADC_CHAN_BAT_CTRL_AND_IBAT
=
0x1c
,
AB8500_GPADC_CHAN_VBAT_MEAS_AND_IBAT
=
0x1d
,
AB8500_GPADC_CHAN_VBAT_TRUE_MEAS_AND_IBAT
=
0x1e
,
AB8500_GPADC_CHAN_BAT_TEMP_AND_IBAT
=
0x1f
,
/*
* Virtual channel used only for ibat conversion to ampere.
* Battery current conversion (ibat) cannot be requested as a
* single conversion but it is always requested in combination
* with other input requests.
*/
AB8500_GPADC_CHAN_IBAT_VIRTUAL
=
0xFF
,
};
#define AB8500_GPADC_AUTO_TIMER_REG 0x03
#define AB8500_GPADC_STAT_REG 0x04
#define AB8500_GPADC_STAT_BUSY BIT(0)
#define AB8500_GPADC_MANDATAL_REG 0x05
#define AB8500_GPADC_MANDATAH_REG 0x06
#define AB8500_GPADC_AUTODATAL_REG 0x07
...
...
@@ -61,309 +139,261 @@
#define AB8540_GPADC_OTP4_REG_6 0x39
#define AB8540_GPADC_OTP4_REG_5 0x3A
/* gpadc constants */
#define EN_VINTCORE12 0x04
#define EN_VTVOUT 0x02
#define EN_GPADC 0x01
#define DIS_GPADC 0x00
#define AVG_1 0x00
#define AVG_4 0x20
#define AVG_8 0x40
#define AVG_16 0x60
#define ADC_SW_CONV 0x04
#define EN_ICHAR 0x80
#define BTEMP_PULL_UP 0x08
#define EN_BUF 0x40
#define DIS_ZERO 0x00
#define GPADC_BUSY 0x01
#define EN_FALLING 0x10
#define EN_TRIG_EDGE 0x02
#define EN_VBIAS_XTAL_TEMP 0x02
#define AB8540_GPADC_DIS_ZERO 0x00
#define AB8540_GPADC_EN_VBIAS_XTAL_TEMP 0x02
/* GPADC constants from AB8500 spec, UM0836 */
#define ADC_RESOLUTION 1024
#define A
DC_CH_BTEMP_MIN
0
#define A
DC_CH_BTEMP_MAX
1350
#define ADC_CH_DIETEMP_MIN 0
#define ADC_CH_DIETEMP_MAX 1350
#define A
DC_CH_CHG_V_MIN
0
#define A
DC_CH_CHG_V_MAX
20030
#define ADC_CH_ACCDET2_MIN 0
#define ADC_CH_ACCDET2_MAX 2500
#define ADC_CH_VBAT_MIN 2300
#define ADC_CH_VBAT_MAX 4800
#define A
DC_CH_CHG_I_MIN
0
#define A
DC_CH_CHG_I_MAX
1500
#define A
DC_CH_BKBAT_MIN
0
#define A
DC_CH_BKBAT_MAX
3200
#define A
B8500_A
DC_RESOLUTION 1024
#define A
B8500_ADC_CH_BTEMP_MIN
0
#define A
B8500_ADC_CH_BTEMP_MAX
1350
#define A
B8500_A
DC_CH_DIETEMP_MIN 0
#define A
B8500_A
DC_CH_DIETEMP_MAX 1350
#define A
B8500_ADC_CH_CHG_V_MIN
0
#define A
B8500_ADC_CH_CHG_V_MAX
20030
#define A
B8500_A
DC_CH_ACCDET2_MIN 0
#define A
B8500_A
DC_CH_ACCDET2_MAX 2500
#define A
B8500_A
DC_CH_VBAT_MIN 2300
#define A
B8500_A
DC_CH_VBAT_MAX 4800
#define A
B8500_ADC_CH_CHG_I_MIN
0
#define A
B8500_ADC_CH_CHG_I_MAX
1500
#define A
B8500_ADC_CH_BKBAT_MIN
0
#define A
B8500_ADC_CH_BKBAT_MAX
3200
/* GPADC constants from AB8540 spec */
#define ADC_CH_IBAT_MIN (-6000)
/* mA range measured by ADC for ibat */
#define ADC_CH_IBAT_MAX 6000
#define ADC_CH_IBAT_MIN_V (-60)
/* mV range measured by ADC for ibat */
#define ADC_CH_IBAT_MAX_V 60
#define
IBAT_VDROP_L
(-56)
/* mV */
#define
IBAT_VDROP_H
56
#define A
B8500_A
DC_CH_IBAT_MIN (-6000)
/* mA range measured by ADC for ibat */
#define A
B8500_A
DC_CH_IBAT_MAX 6000
#define A
B8500_A
DC_CH_IBAT_MIN_V (-60)
/* mV range measured by ADC for ibat */
#define A
B8500_A
DC_CH_IBAT_MAX_V 60
#define
AB8500_GPADC_IBAT_VDROP_L
(-56)
/* mV */
#define
AB8500_GPADC_IBAT_VDROP_H
56
/* This is used to not lose precision when dividing to get gain and offset */
#define
CALIB_SCALE
1000
#define
AB8500_GPADC_CALIB_SCALE
1000
/*
* Number of bits shift used to not lose precision
* when dividing to get ibat gain.
*/
#define CALIB_SHIFT_IBAT 20
#define
AB8500_GPADC_
CALIB_SHIFT_IBAT 20
/* Time in ms before disabling regulator */
#define
GPADC_AUDOSUSPEND_DELAY
1
#define
AB8500_GPADC_AUTOSUSPEND_DELAY
1
#define
CONVERSION_TIME
500
/* ms */
#define
AB8500_GPADC_CONVERSION_TIME
500
/* ms */
enum
cal_channels
{
A
DC_INPUT
_VMAIN
=
0
,
A
DC_INPUT
_BTEMP
,
A
DC_INPUT
_VBAT
,
A
DC_INPUT
_IBAT
,
NBR_CAL_INPUTS
,
enum
ab8500_
cal_channels
{
A
B8500_CAL
_VMAIN
=
0
,
A
B8500_CAL
_BTEMP
,
A
B8500_CAL
_VBAT
,
A
B8500_CAL
_IBAT
,
AB8500_CAL_NR
,
};
/**
* struct adc_cal_data - Table for storing gain and offset for the calibrated
* ADC channels
* @gain: Gain of the ADC channel
* @offset: Offset of the ADC channel
* struct ab8500_adc_cal_data - Table for storing gain and offset for the
* calibrated ADC channels
* @gain: Gain of the ADC channel
* @offset: Offset of the ADC channel
* @otp_calib_hi: Calibration from OTP
* @otp_calib_lo: Calibration from OTP
*/
struct
adc_cal_data
{
struct
a
b8500_a
dc_cal_data
{
s64
gain
;
s64
offset
;
u16
otp_calib_hi
;
u16
otp_calib_lo
;
};
/**
* struct ab8500_gpadc_chan_info - per-channel GPADC info
* @name: name of the channel
* @id: the internal AB8500 ID number for the channel
* @hardware_control: indicate that we want to use hardware ADC control
* on this channel, the default is software ADC control. Hardware control
* is normally only used to test the battery voltage during GSM bursts
* and needs a hardware trigger on the GPADCTrig pin of the ASIC.
* @falling_edge: indicate that we want to trigger on falling edge
* rather than rising edge, rising edge is the default
* @avg_sample: how many samples to average: must be 1, 4, 8 or 16.
* @trig_timer: how long to wait for the trigger, in 32kHz periods:
* 0 .. 255 periods
*/
struct
ab8500_gpadc_chan_info
{
const
char
*
name
;
u8
id
;
bool
hardware_control
;
bool
falling_edge
;
u8
avg_sample
;
u8
trig_timer
;
};
/**
* struct ab8500_gpadc - AB8500 GPADC device information
* @dev: pointer to the struct device
* @node: a list of AB8500 GPADCs, hence prepared for
reentrance
* @parent: pointer to the struct ab8500
* @ab8500_gpadc_complete: pointer to the struct completion, to indicate
* the completion of gpadc conversion
* @ab8500_gpadc_lock: structure of type mutex
* @regu: pointer to the struct regulator
* @irq_sw: interrupt number that is used by gpadc for Sw
* conversion
* @irq_hw: interrupt number that is used by gpadc for Hw
* conversion
* @cal_data array of ADC calibration data structs
* @dev: pointer to the containing device
* @ab8500: pointer to the parent AB8500 device
* @chans: internal per-channel information container
* @nchans: number of channels
* @complete: pointer to the completion that indicates
* the completion of an gpadc conversion cycle
* @vddadc: pointer to the regulator supplying VDDADC
* @irq_sw: interrupt number that is used by gpadc for software ADC conversion
* @irq_hw: interrupt number that is used by gpadc for hardware ADC conversion
* @cal_data: array of ADC calibration data structs
*/
struct
ab8500_gpadc
{
struct
device
*
dev
;
struct
list_head
node
;
struct
ab8500
*
parent
;
struct
completion
ab8500_gpadc_complete
;
struct
mutex
ab8500_gpadc_lock
;
struct
regulator
*
regu
;
struct
ab8500
*
ab8500
;
struct
ab8500
_gpadc_chan_info
*
chans
;
unsigned
int
nchans
;
struct
completion
complete
;
struct
regulator
*
vddadc
;
int
irq_sw
;
int
irq_hw
;
struct
a
dc_cal_data
cal_data
[
NBR_CAL_INPUTS
];
struct
a
b8500_adc_cal_data
cal_data
[
AB8500_CAL_NR
];
};
static
LIST_HEAD
(
ab8500_gpadc_list
);
/**
* ab8500_gpadc_get() - returns a reference to the primary AB8500 GPADC
* (i.e. the first GPADC in the instance list)
*/
struct
ab8500_gpadc
*
ab8500_gpadc_get
(
char
*
name
)
static
struct
ab8500_gpadc_chan_info
*
ab8500_gpadc_get_channel
(
struct
ab8500_gpadc
*
gpadc
,
u8
chan
)
{
struct
ab8500_gpadc
*
gpadc
;
struct
ab8500_gpadc_chan_info
*
ch
;
int
i
;
list_for_each_entry
(
gpadc
,
&
ab8500_gpadc_list
,
node
)
{
if
(
!
strcmp
(
name
,
dev_name
(
gpadc
->
dev
)))
return
gpadc
;
for
(
i
=
0
;
i
<
gpadc
->
nchans
;
i
++
)
{
ch
=
&
gpadc
->
chans
[
i
];
if
(
ch
->
id
==
chan
)
break
;
}
if
(
i
==
gpadc
->
nchans
)
return
NULL
;
return
ERR_PTR
(
-
ENOENT
)
;
return
ch
;
}
EXPORT_SYMBOL
(
ab8500_gpadc_get
);
/**
* ab8500_gpadc_ad_to_voltage() - Convert a raw ADC value to a voltage
* @gpadc: GPADC instance
* @ch: the sampled channel this raw value is coming from
* @ad_value: the raw value
*/
int
ab8500_gpadc_ad_to_voltage
(
struct
ab8500_gpadc
*
gpadc
,
u8
channel
,
int
ad_value
)
static
int
ab8500_gpadc_ad_to_voltage
(
struct
ab8500_gpadc
*
gpadc
,
enum
ab8500_gpadc_channel
ch
,
int
ad_value
)
{
int
res
;
switch
(
ch
annel
)
{
case
MAIN_CHARGER_V
:
/*
For some reason we don't have calibrated data
*/
if
(
!
gpadc
->
cal_data
[
A
DC_INPUT
_VMAIN
].
gain
)
{
res
=
A
DC_CH_CHG_V_MIN
+
(
ADC_CH_CHG_V_MAX
-
ADC_CH_CHG_V_MIN
)
*
ad_value
/
ADC_RESOLUTION
;
switch
(
ch
)
{
case
AB8500_GPADC_CHAN_MAIN_CHARGER
:
/*
No calibration data available: just interpolate
*/
if
(
!
gpadc
->
cal_data
[
A
B8500_CAL
_VMAIN
].
gain
)
{
res
=
A
B8500_ADC_CH_CHG_V_MIN
+
(
AB8500_
ADC_CH_CHG_V_MAX
-
A
B8500_A
DC_CH_CHG_V_MIN
)
*
ad_value
/
A
B8500_A
DC_RESOLUTION
;
break
;
}
/* Here we can use
the calibrated data
*/
res
=
(
int
)
(
ad_value
*
gpadc
->
cal_data
[
A
DC_INPUT
_VMAIN
].
gain
+
gpadc
->
cal_data
[
A
DC_INPUT_VMAIN
].
offset
)
/
CALIB_SCALE
;
/* Here we can use
calibration
*/
res
=
(
int
)
(
ad_value
*
gpadc
->
cal_data
[
A
B8500_CAL
_VMAIN
].
gain
+
gpadc
->
cal_data
[
A
B8500_CAL_VMAIN
].
offset
)
/
AB8500_GPADC_
CALIB_SCALE
;
break
;
case
XTAL_TEMP
:
case
BAT_CTRL
:
case
BTEMP_BALL
:
case
A
CC_DETECT
1
:
case
A
DC_AUX1
:
case
A
DC_AUX2
:
/*
For some reason we don't have calibrated data
*/
if
(
!
gpadc
->
cal_data
[
A
DC_INPUT
_BTEMP
].
gain
)
{
res
=
A
DC_CH_BTEMP_MIN
+
(
ADC_CH_BTEMP_MAX
-
ADC_CH_BTEMP_MIN
)
*
ad_value
/
ADC_RESOLUTION
;
case
AB8500_GPADC_CHAN_BAT_CTRL
:
case
AB8500_GPADC_CHAN_BAT_TEMP
:
case
AB8500_GPADC_CHAN_ACC_DET_1
:
case
A
B8500_GPADC_CHAN_ADC_AUX_
1
:
case
A
B8500_GPADC_CHAN_ADC_AUX_2
:
case
A
B8500_GPADC_CHAN_XTAL_TEMP
:
/*
No calibration data available: just interpolate
*/
if
(
!
gpadc
->
cal_data
[
A
B8500_CAL
_BTEMP
].
gain
)
{
res
=
A
B8500_ADC_CH_BTEMP_MIN
+
(
AB8500_
ADC_CH_BTEMP_MAX
-
A
B8500_A
DC_CH_BTEMP_MIN
)
*
ad_value
/
A
B8500_A
DC_RESOLUTION
;
break
;
}
/* Here we can use
the calibrated data
*/
res
=
(
int
)
(
ad_value
*
gpadc
->
cal_data
[
A
DC_INPUT
_BTEMP
].
gain
+
gpadc
->
cal_data
[
A
DC_INPUT_BTEMP
].
offset
)
/
CALIB_SCALE
;
/* Here we can use
calibration
*/
res
=
(
int
)
(
ad_value
*
gpadc
->
cal_data
[
A
B8500_CAL
_BTEMP
].
gain
+
gpadc
->
cal_data
[
A
B8500_CAL_BTEMP
].
offset
)
/
AB8500_GPADC_
CALIB_SCALE
;
break
;
case
MAIN_BAT_V
:
case
VBAT_TRUE_MEAS
:
/*
For some reason we don't have calibrated data
*/
if
(
!
gpadc
->
cal_data
[
A
DC_INPUT
_VBAT
].
gain
)
{
res
=
A
DC_CH_VBAT_MIN
+
(
ADC_CH_VBAT_MAX
-
ADC_CH_VBAT_MIN
)
*
ad_value
/
ADC_RESOLUTION
;
case
AB8500_GPADC_CHAN_VBAT_A
:
case
AB8500_GPADC_CHAN_
VBAT_TRUE_MEAS
:
/*
No calibration data available: just interpolate
*/
if
(
!
gpadc
->
cal_data
[
A
B8500_CAL
_VBAT
].
gain
)
{
res
=
A
B8500_ADC_CH_VBAT_MIN
+
(
AB8500_
ADC_CH_VBAT_MAX
-
A
B8500_A
DC_CH_VBAT_MIN
)
*
ad_value
/
A
B8500_A
DC_RESOLUTION
;
break
;
}
/* Here we can use
the calibrated data
*/
res
=
(
int
)
(
ad_value
*
gpadc
->
cal_data
[
A
DC_INPUT
_VBAT
].
gain
+
gpadc
->
cal_data
[
A
DC_INPUT_VBAT
].
offset
)
/
CALIB_SCALE
;
/* Here we can use
calibration
*/
res
=
(
int
)
(
ad_value
*
gpadc
->
cal_data
[
A
B8500_CAL
_VBAT
].
gain
+
gpadc
->
cal_data
[
A
B8500_CAL_VBAT
].
offset
)
/
AB8500_GPADC_
CALIB_SCALE
;
break
;
case
DIE_TEMP
:
res
=
ADC_CH_DIETEMP_MIN
+
(
A
DC_CH_DIETEMP_MAX
-
ADC_CH_DIETEMP_MIN
)
*
ad_value
/
ADC_RESOLUTION
;
case
AB8505_GPADC_CHAN_
DIE_TEMP
:
res
=
A
B8500_A
DC_CH_DIETEMP_MIN
+
(
A
B8500_ADC_CH_DIETEMP_MAX
-
AB8500_
ADC_CH_DIETEMP_MIN
)
*
ad_value
/
A
B8500_A
DC_RESOLUTION
;
break
;
case
A
CC_DETECT
2
:
res
=
ADC_CH_ACCDET2_MIN
+
(
A
DC_CH_ACCDET2_MAX
-
ADC_CH_ACCDET2_MIN
)
*
ad_value
/
ADC_RESOLUTION
;
case
A
B8500_GPADC_CHAN_ACC_DET_
2
:
res
=
A
B8500_A
DC_CH_ACCDET2_MIN
+
(
A
B8500_ADC_CH_ACCDET2_MAX
-
AB8500_
ADC_CH_ACCDET2_MIN
)
*
ad_value
/
A
B8500_A
DC_RESOLUTION
;
break
;
case
VBUS_V
:
res
=
ADC_CH_CHG_V_MIN
+
(
A
DC_CH_CHG_V_MAX
-
ADC_CH_CHG_V_MIN
)
*
ad_value
/
ADC_RESOLUTION
;
case
AB8500_GPADC_CHAN_VBUS
:
res
=
A
B8500_A
DC_CH_CHG_V_MIN
+
(
A
B8500_ADC_CH_CHG_V_MAX
-
AB8500_
ADC_CH_CHG_V_MIN
)
*
ad_value
/
A
B8500_A
DC_RESOLUTION
;
break
;
case
MAIN_CHARGER_C
:
case
USB_CHARGER_C
:
res
=
ADC_CH_CHG_I_MIN
+
(
A
DC_CH_CHG_I_MAX
-
ADC_CH_CHG_I_MIN
)
*
ad_value
/
ADC_RESOLUTION
;
case
AB8500_GPADC_CHAN_MAIN_CHARGER_CURRENT
:
case
AB8500_GPADC_CHAN_USB_CHARGER_CURRENT
:
res
=
A
B8500_A
DC_CH_CHG_I_MIN
+
(
A
B8500_ADC_CH_CHG_I_MAX
-
AB8500_
ADC_CH_CHG_I_MIN
)
*
ad_value
/
A
B8500_A
DC_RESOLUTION
;
break
;
case
BK_BAT_V
:
res
=
ADC_CH_BKBAT_MIN
+
(
A
DC_CH_BKBAT_MAX
-
ADC_CH_BKBAT_MIN
)
*
ad_value
/
ADC_RESOLUTION
;
case
AB8500_GPADC_CHAN_BACKUP_BAT
:
res
=
A
B8500_A
DC_CH_BKBAT_MIN
+
(
A
B8500_ADC_CH_BKBAT_MAX
-
AB8500_
ADC_CH_BKBAT_MIN
)
*
ad_value
/
A
B8500_A
DC_RESOLUTION
;
break
;
case
IBAT_VIRTUAL_CHANNE
L
:
/*
For some reason we don't have calibrated data
*/
if
(
!
gpadc
->
cal_data
[
A
DC_INPUT
_IBAT
].
gain
)
{
res
=
A
DC_CH_IBAT_MIN
+
(
ADC_CH_IBAT_MAX
-
ADC_CH_IBAT_MIN
)
*
ad_value
/
ADC_RESOLUTION
;
case
AB8500_GPADC_CHAN_IBAT_VIRTUA
L
:
/*
No calibration data available: just interpolate
*/
if
(
!
gpadc
->
cal_data
[
A
B8500_CAL
_IBAT
].
gain
)
{
res
=
A
B8500_ADC_CH_IBAT_MIN
+
(
AB8500_
ADC_CH_IBAT_MAX
-
A
B8500_A
DC_CH_IBAT_MIN
)
*
ad_value
/
A
B8500_A
DC_RESOLUTION
;
break
;
}
/* Here we can use
the calibrated data
*/
res
=
(
int
)
(
ad_value
*
gpadc
->
cal_data
[
A
DC_INPUT
_IBAT
].
gain
+
gpadc
->
cal_data
[
A
DC_INPUT
_IBAT
].
offset
)
>>
CALIB_SHIFT_IBAT
;
/* Here we can use
calibration
*/
res
=
(
int
)
(
ad_value
*
gpadc
->
cal_data
[
A
B8500_CAL
_IBAT
].
gain
+
gpadc
->
cal_data
[
A
B8500_CAL
_IBAT
].
offset
)
>>
AB8500_GPADC_
CALIB_SHIFT_IBAT
;
break
;
default:
dev_err
(
gpadc
->
dev
,
"unknown channel, not possible to convert
\n
"
);
"unknown channel ID: %d, not possible to convert
\n
"
,
ch
);
res
=
-
EINVAL
;
break
;
}
return
res
;
}
EXPORT_SYMBOL
(
ab8500_gpadc_ad_to_voltage
);
/**
* ab8500_gpadc_sw_hw_convert() - gpadc conversion
* @channel: analog channel to be converted to digital data
* @avg_sample: number of ADC sample to average
* @trig_egde: selected ADC trig edge
* @trig_timer: selected ADC trigger delay timer
* @conv_type: selected conversion type (HW or SW conversion)
*
* This function converts the selected analog i/p to digital
* data.
*/
int
ab8500_gpadc_sw_hw_convert
(
struct
ab8500_gpadc
*
gpadc
,
u8
channel
,
u8
avg_sample
,
u8
trig_edge
,
u8
trig_timer
,
u8
conv_type
)
{
int
ad_value
;
int
voltage
;
ad_value
=
ab8500_gpadc_read_raw
(
gpadc
,
channel
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
/* On failure retry a second time */
if
(
ad_value
<
0
)
ad_value
=
ab8500_gpadc_read_raw
(
gpadc
,
channel
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
if
(
ad_value
<
0
)
{
dev_err
(
gpadc
->
dev
,
"GPADC raw value failed ch: %d
\n
"
,
channel
);
return
ad_value
;
}
voltage
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
channel
,
ad_value
);
if
(
voltage
<
0
)
dev_err
(
gpadc
->
dev
,
"GPADC to voltage conversion failed ch: %d AD: 0x%x
\n
"
,
channel
,
ad_value
);
return
voltage
;
}
EXPORT_SYMBOL
(
ab8500_gpadc_sw_hw_convert
);
/**
* ab8500_gpadc_read_raw() - gpadc read
* @channel: analog channel to be read
* @avg_sample: number of ADC sample to average
* @trig_edge: selected trig edge
* @trig_timer: selected ADC trigger delay timer
* @conv_type: selected conversion type (HW or SW conversion)
*
* This function obtains the raw ADC value for an hardware conversion,
* this then needs to be converted by calling ab8500_gpadc_ad_to_voltage()
*/
int
ab8500_gpadc_read_raw
(
struct
ab8500_gpadc
*
gpadc
,
u8
channel
,
u8
avg_sample
,
u8
trig_edge
,
u8
trig_timer
,
u8
conv_type
)
{
return
ab8500_gpadc_double_read_raw
(
gpadc
,
channel
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
,
NULL
);
return
res
;
}
int
ab8500_gpadc_double_read_raw
(
struct
ab8500_gpadc
*
gpadc
,
u8
channel
,
u8
avg_sample
,
u8
trig_edge
,
u8
trig_timer
,
u8
conv_type
,
int
*
ibat
)
static
int
ab8500_gpadc_read
(
struct
ab8500_gpadc
*
gpadc
,
const
struct
ab8500_gpadc_chan_info
*
ch
,
int
*
ibat
)
{
int
ret
;
int
looplimit
=
0
;
unsigned
long
completion_timeout
;
u8
val
,
low_data
,
high_data
,
low_data2
,
high_data2
;
u8
val_reg1
=
0
;
u8
val
;
u8
low_data
,
high_data
,
low_data2
,
high_data2
;
u8
ctrl1
;
u8
ctrl23
;
unsigned
int
delay_min
=
0
;
unsigned
int
delay_max
=
0
;
u8
data_low_addr
,
data_high_addr
;
...
...
@@ -371,14 +401,13 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
if
(
!
gpadc
)
return
-
ENODEV
;
/* check if conver
t
ion is supported */
if
((
gpadc
->
irq_sw
<
0
)
&&
(
conv_type
==
ADC_SW
)
)
/* check if conver
s
ion is supported */
if
((
gpadc
->
irq_sw
<
=
0
)
&&
!
ch
->
hardware_control
)
return
-
ENOTSUPP
;
if
((
gpadc
->
irq_hw
<
0
)
&&
(
conv_type
==
ADC_HW
)
)
if
((
gpadc
->
irq_hw
<
=
0
)
&&
ch
->
hardware_control
)
return
-
ENOTSUPP
;
mutex_lock
(
&
gpadc
->
ab8500_gpadc_lock
);
/* Enable VTVout LDO this is required for GPADC */
/* Enable vddadc by grabbing PM runtime */
pm_runtime_get_sync
(
gpadc
->
dev
);
/* Check if ADC is not busy, lock and proceed */
...
...
@@ -387,44 +416,45 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
AB8500_GPADC
,
AB8500_GPADC_STAT_REG
,
&
val
);
if
(
ret
<
0
)
goto
out
;
if
(
!
(
val
&
GPADC
_BUSY
))
if
(
!
(
val
&
AB8500_GPADC_STAT
_BUSY
))
break
;
msleep
(
20
);
}
while
(
++
looplimit
<
10
);
if
(
looplimit
>=
10
&&
(
val
&
GPADC
_BUSY
))
{
if
(
looplimit
>=
10
&&
(
val
&
AB8500_GPADC_STAT
_BUSY
))
{
dev_err
(
gpadc
->
dev
,
"gpadc_conversion: GPADC busy"
);
ret
=
-
EINVAL
;
goto
out
;
}
/* Enable GPADC */
val_reg1
|=
EN_GPADC
;
ctrl1
=
AB8500_GPADC_CTRL1_ENABLE
;
/* Select the channel source and set average samples */
switch
(
avg_sample
)
{
case
SAMPLE_
1
:
val
=
channel
|
AVG_1
;
switch
(
ch
->
avg_sample
)
{
case
1
:
ctrl23
=
ch
->
id
|
AB8500_GPADC_CTRL2_
AVG_1
;
break
;
case
SAMPLE_
4
:
val
=
channel
|
AVG_4
;
case
4
:
ctrl23
=
ch
->
id
|
AB8500_GPADC_CTRL2_
AVG_4
;
break
;
case
SAMPLE_
8
:
val
=
channel
|
AVG_8
;
case
8
:
ctrl23
=
ch
->
id
|
AB8500_GPADC_CTRL2_
AVG_8
;
break
;
default:
val
=
channel
|
AVG_16
;
ctrl23
=
ch
->
id
|
AB8500_GPADC_CTRL2_
AVG_16
;
break
;
}
if
(
c
onv_type
==
ADC_HW
)
{
if
(
c
h
->
hardware_control
)
{
ret
=
abx500_set_register_interruptible
(
gpadc
->
dev
,
AB8500_GPADC
,
AB8500_GPADC_CTRL3_REG
,
val
);
val_reg1
|=
EN_TRIG_EDGE
;
if
(
tri
g_edge
)
val_reg1
|=
EN_FALLING
;
}
else
AB8500_GPADC
,
AB8500_GPADC_CTRL3_REG
,
ctrl23
);
ctrl1
|=
AB8500_GPADC_CTRL1_TRIG_ENA
;
if
(
ch
->
fallin
g_edge
)
ctrl1
|=
AB8500_GPADC_CTRL1_TRIG_EDGE
;
}
else
{
ret
=
abx500_set_register_interruptible
(
gpadc
->
dev
,
AB8500_GPADC
,
AB8500_GPADC_CTRL2_REG
,
val
);
AB8500_GPADC
,
AB8500_GPADC_CTRL2_REG
,
ctrl23
);
}
if
(
ret
<
0
)
{
dev_err
(
gpadc
->
dev
,
"gpadc_conversion: set avg samples failed
\n
"
);
...
...
@@ -436,31 +466,33 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
* charging current sense if it needed, ABB 3.0 needs some special
* treatment too.
*/
switch
(
channel
)
{
case
MAIN_CHARGER_C
:
case
USB_CHARGER_C
:
val_reg1
|=
EN_BUF
|
EN_ICHAR
;
switch
(
ch
->
id
)
{
case
AB8500_GPADC_CHAN_MAIN_CHARGER_CURRENT
:
case
AB8500_GPADC_CHAN_USB_CHARGER_CURRENT
:
ctrl1
|=
AB8500_GPADC_CTRL1_BUF_ENA
|
AB8500_GPADC_CTRL1_ICHAR_ENA
;
break
;
case
BTEMP_BALL
:
if
(
!
is_ab8500_2p0_or_earlier
(
gpadc
->
parent
))
{
val_reg1
|=
EN_BUF
|
BTEMP_PULL_UP
;
case
AB8500_GPADC_CHAN_BAT_TEMP
:
if
(
!
is_ab8500_2p0_or_earlier
(
gpadc
->
ab8500
))
{
ctrl1
|=
AB8500_GPADC_CTRL1_BUF_ENA
|
AB8500_GPADC_CTRL1_BTEMP_PULL_UP
;
/*
* Delay might be needed for ABB8500 cut 3.0, if not,
* remove when hardware will be availi
ble
*/
* Delay might be needed for ABB8500 cut 3.0, if not,
* remove when hardware will be availa
ble
*/
delay_min
=
1000
;
/* Delay in micro seconds */
delay_max
=
10000
;
/* large range optimises sleepmode */
break
;
}
/*
Intentional fall
through */
/*
Fall
through */
default:
val_reg1
|=
EN_BUF
;
ctrl1
|=
AB8500_GPADC_CTRL1_BUF_ENA
;
break
;
}
/* Write configuration to
register
*/
/* Write configuration to
control register 1
*/
ret
=
abx500_set_register_interruptible
(
gpadc
->
dev
,
AB8500_GPADC
,
AB8500_GPADC_CTRL1_REG
,
val_reg
1
);
AB8500_GPADC
,
AB8500_GPADC_CTRL1_REG
,
ctrl
1
);
if
(
ret
<
0
)
{
dev_err
(
gpadc
->
dev
,
"gpadc_conversion: set Control register failed
\n
"
);
...
...
@@ -470,10 +502,11 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
if
(
delay_min
!=
0
)
usleep_range
(
delay_min
,
delay_max
);
if
(
c
onv_type
==
ADC_HW
)
{
if
(
c
h
->
hardware_control
)
{
/* Set trigger delay timer */
ret
=
abx500_set_register_interruptible
(
gpadc
->
dev
,
AB8500_GPADC
,
AB8500_GPADC_AUTO_TIMER_REG
,
trig_timer
);
AB8500_GPADC
,
AB8500_GPADC_AUTO_TIMER_REG
,
ch
->
trig_timer
);
if
(
ret
<
0
)
{
dev_err
(
gpadc
->
dev
,
"gpadc_conversion: trig timer failed
\n
"
);
...
...
@@ -486,19 +519,20 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
/* Start SW conversion */
ret
=
abx500_mask_and_set_register_interruptible
(
gpadc
->
dev
,
AB8500_GPADC
,
AB8500_GPADC_CTRL1_REG
,
ADC_SW_CONV
,
ADC_SW_CONV
);
AB8500_GPADC_CTRL1_START_SW_CONV
,
AB8500_GPADC_CTRL1_START_SW_CONV
);
if
(
ret
<
0
)
{
dev_err
(
gpadc
->
dev
,
"gpadc_conversion: start s/w conv failed
\n
"
);
goto
out
;
}
completion_timeout
=
msecs_to_jiffies
(
CONVERSION_TIME
);
completion_timeout
=
msecs_to_jiffies
(
AB8500_GPADC_
CONVERSION_TIME
);
data_low_addr
=
AB8500_GPADC_MANDATAL_REG
;
data_high_addr
=
AB8500_GPADC_MANDATAH_REG
;
}
/*
w
ait for completion of conversion */
if
(
!
wait_for_completion_timeout
(
&
gpadc
->
ab8500_gpadc_
complete
,
/*
W
ait for completion of conversion */
if
(
!
wait_for_completion_timeout
(
&
gpadc
->
complete
,
completion_timeout
))
{
dev_err
(
gpadc
->
dev
,
"timeout didn't receive GPADC conv interrupt
\n
"
);
...
...
@@ -510,24 +544,26 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
ret
=
abx500_get_register_interruptible
(
gpadc
->
dev
,
AB8500_GPADC
,
data_low_addr
,
&
low_data
);
if
(
ret
<
0
)
{
dev_err
(
gpadc
->
dev
,
"gpadc_conversion: read low data failed
\n
"
);
dev_err
(
gpadc
->
dev
,
"gpadc_conversion: read low data failed
\n
"
);
goto
out
;
}
ret
=
abx500_get_register_interruptible
(
gpadc
->
dev
,
AB8500_GPADC
,
data_high_addr
,
&
high_data
);
if
(
ret
<
0
)
{
dev_err
(
gpadc
->
dev
,
"gpadc_conversion: read high data failed
\n
"
);
dev_err
(
gpadc
->
dev
,
"gpadc_conversion: read high data failed
\n
"
);
goto
out
;
}
/* Check if double conver
t
ion is required */
if
((
ch
annel
==
BAT_CTRL_AND_IBAT
)
||
(
channel
==
VBAT_MEAS_AND_IBAT
)
||
(
channel
==
VBAT_TRUE_MEAS_AND_IBAT
)
||
(
channel
==
BAT_TEMP_AND_IBAT
))
{
/* Check if double conver
s
ion is required */
if
((
ch
->
id
==
AB8500_GPADC_CHAN_
BAT_CTRL_AND_IBAT
)
||
(
ch
->
id
==
AB8500_GPADC_CHAN_
VBAT_MEAS_AND_IBAT
)
||
(
ch
->
id
==
AB8500_GPADC_CHAN_
VBAT_TRUE_MEAS_AND_IBAT
)
||
(
ch
->
id
==
AB8500_GPADC_CHAN_
BAT_TEMP_AND_IBAT
))
{
if
(
c
onv_type
==
ADC_HW
)
{
if
(
c
h
->
hardware_control
)
{
/* not supported */
ret
=
-
ENOTSUPP
;
dev_err
(
gpadc
->
dev
,
...
...
@@ -564,18 +600,16 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
/* Disable GPADC */
ret
=
abx500_set_register_interruptible
(
gpadc
->
dev
,
AB8500_GPADC
,
AB8500_GPADC_CTRL1_REG
,
DIS_GPADC
);
AB8500_GPADC_CTRL1_REG
,
AB8500_GPADC_CTRL1_DISABLE
);
if
(
ret
<
0
)
{
dev_err
(
gpadc
->
dev
,
"gpadc_conversion: disable gpadc failed
\n
"
);
goto
out
;
}
/*
Disable VTVout LDO this is required for GPADC
*/
/*
This eventually drops the regulator
*/
pm_runtime_mark_last_busy
(
gpadc
->
dev
);
pm_runtime_put_autosuspend
(
gpadc
->
dev
);
mutex_unlock
(
&
gpadc
->
ab8500_gpadc_lock
);
return
(
high_data
<<
8
)
|
low_data
;
out:
...
...
@@ -586,30 +620,29 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
* seems to timeout when waiting for an interrupt.. Not seen in V2.0
*/
(
void
)
abx500_set_register_interruptible
(
gpadc
->
dev
,
AB8500_GPADC
,
AB8500_GPADC_CTRL1_REG
,
DIS_GPADC
);
AB8500_GPADC_CTRL1_REG
,
AB8500_GPADC_CTRL1_DISABLE
);
pm_runtime_put
(
gpadc
->
dev
);
mutex_unlock
(
&
gpadc
->
ab8500_gpadc_lock
);
dev_err
(
gpadc
->
dev
,
"gpadc_conversion: Failed to AD convert channel %d
\n
"
,
channel
);
"gpadc_conversion: Failed to AD convert channel %d
\n
"
,
ch
->
id
);
return
ret
;
}
EXPORT_SYMBOL
(
ab8500_gpadc_read_raw
);
/**
* ab8500_bm_gpadcconvend_handler() - isr for gpadc conversion completion
* @irq:
irq number
* @data:
pointer to the data passed during request irq
* @irq:
irq number
* @data:
pointer to the data passed during request irq
*
* This is a interrupt service routine for gpadc conversion completion.
* Notifies the gpadc completion is completed and the converted raw value
* can be read from the registers.
* Returns IRQ status(IRQ_HANDLED)
*/
static
irqreturn_t
ab8500_bm_gpadcconvend_handler
(
int
irq
,
void
*
_gpadc
)
static
irqreturn_t
ab8500_bm_gpadcconvend_handler
(
int
irq
,
void
*
data
)
{
struct
ab8500_gpadc
*
gpadc
=
_gpadc
;
struct
ab8500_gpadc
*
gpadc
=
data
;
complete
(
&
gpadc
->
ab8500_gpadc_
complete
);
complete
(
&
gpadc
->
complete
);
return
IRQ_HANDLED
;
}
...
...
@@ -642,17 +675,19 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
int
vbat_high
,
vbat_low
;
int
ibat_high
,
ibat_low
;
s64
V_gain
,
V_offset
,
V2A_gain
,
V2A_offset
;
struct
ab8500
*
ab8500
;
ab8500
=
gpadc
->
parent
;
/* First we read all OTP registers and store the error code */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
otp_cal_regs
);
i
++
)
{
ret
[
i
]
=
abx500_get_register_interruptible
(
gpadc
->
dev
,
AB8500_OTP_EMUL
,
otp_cal_regs
[
i
],
&
gpadc_cal
[
i
]);
if
(
ret
[
i
]
<
0
)
if
(
ret
[
i
]
<
0
)
{
/* Continue anyway: maybe the other registers are OK */
dev_err
(
gpadc
->
dev
,
"%s: read otp reg 0x%02x failed
\n
"
,
__func__
,
otp_cal_regs
[
i
]);
}
else
{
/* Put this in the entropy pool as device-unique */
add_device_randomness
(
&
ret
[
i
],
sizeof
(
ret
[
i
]));
}
}
/*
...
...
@@ -723,25 +758,25 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
* vbat_low: Vin = 2380mV / ADC ideal code = 33
*/
if
(
is_ab8540
(
ab8500
))
{
if
(
is_ab8540
(
gpadc
->
ab8500
))
{
/* Calculate gain and offset for VMAIN if all reads succeeded*/
if
(
!
(
ret
[
1
]
<
0
||
ret
[
2
]
<
0
))
{
vmain_high
=
(((
gpadc_cal
[
1
]
&
0xFF
)
<<
2
)
|
((
gpadc_cal
[
2
]
&
0xC0
)
>>
6
));
vmain_low
=
((
gpadc_cal
[
2
]
&
0x3E
)
>>
1
);
gpadc
->
cal_data
[
A
DC_INPUT
_VMAIN
].
otp_calib_hi
=
gpadc
->
cal_data
[
A
B8500_CAL
_VMAIN
].
otp_calib_hi
=
(
u16
)
vmain_high
;
gpadc
->
cal_data
[
A
DC_INPUT
_VMAIN
].
otp_calib_lo
=
gpadc
->
cal_data
[
A
B8500_CAL
_VMAIN
].
otp_calib_lo
=
(
u16
)
vmain_low
;
gpadc
->
cal_data
[
A
DC_INPUT_VMAIN
].
gain
=
CALIB_SCALE
*
gpadc
->
cal_data
[
A
B8500_CAL_VMAIN
].
gain
=
AB8500_GPADC_
CALIB_SCALE
*
(
19500
-
315
)
/
(
vmain_high
-
vmain_low
);
gpadc
->
cal_data
[
A
DC_INPUT_VMAIN
].
offset
=
CALIB_SCALE
*
19500
-
(
CALIB_SCALE
*
(
19500
-
315
)
/
gpadc
->
cal_data
[
A
B8500_CAL_VMAIN
].
offset
=
AB8500_GPADC_
CALIB_SCALE
*
19500
-
(
AB8500_GPADC_
CALIB_SCALE
*
(
19500
-
315
)
/
(
vmain_high
-
vmain_low
))
*
vmain_high
;
}
else
{
gpadc
->
cal_data
[
ADC_INPUT
_VMAIN
].
gain
=
0
;
gpadc
->
cal_data
[
AB8500_CAL
_VMAIN
].
gain
=
0
;
}
/* Read IBAT calibration Data */
...
...
@@ -762,40 +797,36 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
ibat_low
=
(((
gpadc_otp4
[
1
]
&
0x01
)
<<
5
)
|
((
gpadc_otp4
[
2
]
&
0xF8
)
>>
3
));
gpadc
->
cal_data
[
A
DC_INPUT
_IBAT
].
otp_calib_hi
=
gpadc
->
cal_data
[
A
B8500_CAL
_IBAT
].
otp_calib_hi
=
(
u16
)
ibat_high
;
gpadc
->
cal_data
[
A
DC_INPUT
_IBAT
].
otp_calib_lo
=
gpadc
->
cal_data
[
A
B8500_CAL
_IBAT
].
otp_calib_lo
=
(
u16
)
ibat_low
;
V_gain
=
((
IBAT_VDROP_H
-
IBAT_VDROP_L
)
<<
CALIB_SHIFT_IBAT
)
/
(
ibat_high
-
ibat_low
);
V_gain
=
((
AB8500_GPADC_IBAT_VDROP_H
-
AB8500_GPADC_
IBAT_VDROP_L
)
<<
AB8500_GPADC_
CALIB_SHIFT_IBAT
)
/
(
ibat_high
-
ibat_low
);
V_offset
=
(
IBAT_VDROP_H
<<
CALIB_SHIFT_IBAT
)
-
(((
IBAT_VDROP_H
-
IBAT_VDROP_L
)
<<
CALIB_SHIFT_IBAT
)
/
(
ibat_high
-
ibat_low
))
V_offset
=
(
AB8500_GPADC_IBAT_VDROP_H
<<
AB8500_GPADC_
CALIB_SHIFT_IBAT
)
-
(((
AB8500_GPADC_IBAT_VDROP_H
-
AB8500_GPADC_
IBAT_VDROP_L
)
<<
AB8500_GPADC_
CALIB_SHIFT_IBAT
)
/
(
ibat_high
-
ibat_low
))
*
ibat_high
;
/*
* Result obtained is in mV (at a scale factor),
* we need to calculate gain and offset to get mA
*/
V2A_gain
=
(
A
DC_CH_IBAT_MAX
-
ADC_CH_IBAT_MIN
)
/
(
A
DC_CH_IBAT_MAX_V
-
ADC_CH_IBAT_MIN_V
);
V2A_offset
=
((
A
DC_CH_IBAT_MAX_V
*
ADC_CH_IBAT_MIN
-
A
DC_CH_IBAT_MAX
*
ADC_CH_IBAT_MIN_V
)
<<
CALIB_SHIFT_IBAT
)
/
(
A
DC_CH_IBAT_MAX_V
-
ADC_CH_IBAT_MIN_V
);
gpadc
->
cal_data
[
A
DC_INPUT
_IBAT
].
gain
=
V2A_gain
=
(
A
B8500_ADC_CH_IBAT_MAX
-
AB8500_
ADC_CH_IBAT_MIN
)
/
(
A
B8500_ADC_CH_IBAT_MAX_V
-
AB8500_
ADC_CH_IBAT_MIN_V
);
V2A_offset
=
((
A
B8500_ADC_CH_IBAT_MAX_V
*
AB8500_
ADC_CH_IBAT_MIN
-
A
B8500_ADC_CH_IBAT_MAX
*
AB8500_
ADC_CH_IBAT_MIN_V
)
<<
AB8500_GPADC_
CALIB_SHIFT_IBAT
)
/
(
A
B8500_ADC_CH_IBAT_MAX_V
-
AB8500_
ADC_CH_IBAT_MIN_V
);
gpadc
->
cal_data
[
A
B8500_CAL
_IBAT
].
gain
=
V_gain
*
V2A_gain
;
gpadc
->
cal_data
[
A
DC_INPUT
_IBAT
].
offset
=
gpadc
->
cal_data
[
A
B8500_CAL
_IBAT
].
offset
=
V_offset
*
V2A_gain
+
V2A_offset
;
}
else
{
gpadc
->
cal_data
[
A
DC_INPUT
_IBAT
].
gain
=
0
;
gpadc
->
cal_data
[
A
B8500_CAL
_IBAT
].
gain
=
0
;
}
dev_dbg
(
gpadc
->
dev
,
"IBAT gain %llu offset %llu
\n
"
,
gpadc
->
cal_data
[
ADC_INPUT_IBAT
].
gain
,
gpadc
->
cal_data
[
ADC_INPUT_IBAT
].
offset
);
}
else
{
/* Calculate gain and offset for VMAIN if all reads succeeded */
if
(
!
(
ret
[
0
]
<
0
||
ret
[
1
]
<
0
||
ret
[
2
]
<
0
))
{
...
...
@@ -804,19 +835,19 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
((
gpadc_cal
[
2
]
&
0xC0
)
>>
6
));
vmain_low
=
((
gpadc_cal
[
2
]
&
0x3E
)
>>
1
);
gpadc
->
cal_data
[
A
DC_INPUT
_VMAIN
].
otp_calib_hi
=
gpadc
->
cal_data
[
A
B8500_CAL
_VMAIN
].
otp_calib_hi
=
(
u16
)
vmain_high
;
gpadc
->
cal_data
[
A
DC_INPUT
_VMAIN
].
otp_calib_lo
=
gpadc
->
cal_data
[
A
B8500_CAL
_VMAIN
].
otp_calib_lo
=
(
u16
)
vmain_low
;
gpadc
->
cal_data
[
A
DC_INPUT_VMAIN
].
gain
=
CALIB_SCALE
*
gpadc
->
cal_data
[
A
B8500_CAL_VMAIN
].
gain
=
AB8500_GPADC_
CALIB_SCALE
*
(
19500
-
315
)
/
(
vmain_high
-
vmain_low
);
gpadc
->
cal_data
[
A
DC_INPUT_VMAIN
].
offset
=
CALIB_SCALE
*
19500
-
(
CALIB_SCALE
*
(
19500
-
315
)
/
gpadc
->
cal_data
[
A
B8500_CAL_VMAIN
].
offset
=
AB8500_GPADC_
CALIB_SCALE
*
19500
-
(
AB8500_GPADC_
CALIB_SCALE
*
(
19500
-
315
)
/
(
vmain_high
-
vmain_low
))
*
vmain_high
;
}
else
{
gpadc
->
cal_data
[
A
DC_INPUT
_VMAIN
].
gain
=
0
;
gpadc
->
cal_data
[
A
B8500_CAL
_VMAIN
].
gain
=
0
;
}
}
...
...
@@ -826,16 +857,16 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
(
gpadc_cal
[
3
]
<<
1
)
|
((
gpadc_cal
[
4
]
&
0x80
)
>>
7
));
btemp_low
=
((
gpadc_cal
[
4
]
&
0x7C
)
>>
2
);
gpadc
->
cal_data
[
A
DC_INPUT
_BTEMP
].
otp_calib_hi
=
(
u16
)
btemp_high
;
gpadc
->
cal_data
[
A
DC_INPUT
_BTEMP
].
otp_calib_lo
=
(
u16
)
btemp_low
;
gpadc
->
cal_data
[
A
B8500_CAL
_BTEMP
].
otp_calib_hi
=
(
u16
)
btemp_high
;
gpadc
->
cal_data
[
A
B8500_CAL
_BTEMP
].
otp_calib_lo
=
(
u16
)
btemp_low
;
gpadc
->
cal_data
[
A
DC_INPUT
_BTEMP
].
gain
=
CALIB_SCALE
*
(
1300
-
21
)
/
(
btemp_high
-
btemp_low
);
gpadc
->
cal_data
[
A
DC_INPUT_BTEMP
].
offset
=
CALIB_SCALE
*
1300
-
(
CALIB_SCALE
*
(
1300
-
21
)
/
(
btemp_high
-
btemp_low
))
gpadc
->
cal_data
[
A
B8500_CAL
_BTEMP
].
gain
=
AB8500_GPADC_
CALIB_SCALE
*
(
1300
-
21
)
/
(
btemp_high
-
btemp_low
);
gpadc
->
cal_data
[
A
B8500_CAL_BTEMP
].
offset
=
AB8500_GPADC_
CALIB_SCALE
*
1300
-
(
AB8500_GPADC_
CALIB_SCALE
*
(
1300
-
21
)
/
(
btemp_high
-
btemp_low
))
*
btemp_high
;
}
else
{
gpadc
->
cal_data
[
A
DC_INPUT
_BTEMP
].
gain
=
0
;
gpadc
->
cal_data
[
A
B8500_CAL
_BTEMP
].
gain
=
0
;
}
/* Calculate gain and offset for VBAT if all reads succeeded */
...
...
@@ -843,202 +874,337 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
vbat_high
=
(((
gpadc_cal
[
4
]
&
0x03
)
<<
8
)
|
gpadc_cal
[
5
]);
vbat_low
=
((
gpadc_cal
[
6
]
&
0xFC
)
>>
2
);
gpadc
->
cal_data
[
A
DC_INPUT
_VBAT
].
otp_calib_hi
=
(
u16
)
vbat_high
;
gpadc
->
cal_data
[
A
DC_INPUT
_VBAT
].
otp_calib_lo
=
(
u16
)
vbat_low
;
gpadc
->
cal_data
[
A
B8500_CAL
_VBAT
].
otp_calib_hi
=
(
u16
)
vbat_high
;
gpadc
->
cal_data
[
A
B8500_CAL
_VBAT
].
otp_calib_lo
=
(
u16
)
vbat_low
;
gpadc
->
cal_data
[
A
DC_INPUT_VBAT
].
gain
=
CALIB_SCALE
*
gpadc
->
cal_data
[
A
B8500_CAL_VBAT
].
gain
=
AB8500_GPADC_
CALIB_SCALE
*
(
4700
-
2380
)
/
(
vbat_high
-
vbat_low
);
gpadc
->
cal_data
[
A
DC_INPUT_VBAT
].
offset
=
CALIB_SCALE
*
4700
-
(
CALIB_SCALE
*
(
4700
-
2380
)
/
gpadc
->
cal_data
[
A
B8500_CAL_VBAT
].
offset
=
AB8500_GPADC_
CALIB_SCALE
*
4700
-
(
AB8500_GPADC_
CALIB_SCALE
*
(
4700
-
2380
)
/
(
vbat_high
-
vbat_low
))
*
vbat_high
;
}
else
{
gpadc
->
cal_data
[
A
DC_INPUT
_VBAT
].
gain
=
0
;
gpadc
->
cal_data
[
A
B8500_CAL
_VBAT
].
gain
=
0
;
}
}
dev_dbg
(
gpadc
->
dev
,
"VMAIN gain %llu offset %llu
\n
"
,
gpadc
->
cal_data
[
ADC_INPUT_VMAIN
].
gain
,
gpadc
->
cal_data
[
ADC_INPUT_VMAIN
].
offset
);
static
int
ab8500_gpadc_read_raw
(
struct
iio_dev
*
indio_dev
,
struct
iio_chan_spec
const
*
chan
,
int
*
val
,
int
*
val2
,
long
mask
)
{
struct
ab8500_gpadc
*
gpadc
=
iio_priv
(
indio_dev
);
const
struct
ab8500_gpadc_chan_info
*
ch
;
int
raw_val
;
int
processed
;
ch
=
ab8500_gpadc_get_channel
(
gpadc
,
chan
->
address
);
if
(
!
ch
)
{
dev_err
(
gpadc
->
dev
,
"no such channel %lu
\n
"
,
chan
->
address
);
return
-
EINVAL
;
}
dev_dbg
(
gpadc
->
dev
,
"BTEMP gain %llu offset %llu
\n
"
,
gpadc
->
cal_data
[
ADC_INPUT_BTEMP
].
gain
,
gpadc
->
cal_data
[
ADC_INPUT_BTEMP
].
offset
);
raw_val
=
ab8500_gpadc_read
(
gpadc
,
ch
,
NULL
);
if
(
raw_val
<
0
)
return
raw_val
;
if
(
mask
==
IIO_CHAN_INFO_RAW
)
{
*
val
=
raw_val
;
return
IIO_VAL_INT
;
}
dev_dbg
(
gpadc
->
dev
,
"VBAT gain %llu offset %llu
\n
"
,
gpadc
->
cal_data
[
ADC_INPUT_VBAT
].
gain
,
gpadc
->
cal_data
[
ADC_INPUT_VBAT
].
offset
);
if
(
mask
==
IIO_CHAN_INFO_PROCESSED
)
{
processed
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
ch
->
id
,
raw_val
);
if
(
processed
<
0
)
return
processed
;
/* Return millivolt or milliamps or millicentigrades */
*
val
=
processed
*
1000
;
return
IIO_VAL_INT
;
}
return
-
EINVAL
;
}
static
int
ab8500_gpadc_of_xlate
(
struct
iio_dev
*
indio_dev
,
const
struct
of_phandle_args
*
iiospec
)
{
int
i
;
for
(
i
=
0
;
i
<
indio_dev
->
num_channels
;
i
++
)
if
(
indio_dev
->
channels
[
i
].
channel
==
iiospec
->
args
[
0
])
return
i
;
return
-
EINVAL
;
}
static
const
struct
iio_info
ab8500_gpadc_info
=
{
.
of_xlate
=
ab8500_gpadc_of_xlate
,
.
read_raw
=
ab8500_gpadc_read_raw
,
};
#ifdef CONFIG_PM
static
int
ab8500_gpadc_runtime_suspend
(
struct
device
*
dev
)
{
struct
ab8500_gpadc
*
gpadc
=
dev_get_drvdata
(
dev
);
struct
iio_dev
*
indio_dev
=
dev_get_drvdata
(
dev
);
struct
ab8500_gpadc
*
gpadc
=
iio_priv
(
indio_dev
);
regulator_disable
(
gpadc
->
vddadc
);
regulator_disable
(
gpadc
->
regu
);
return
0
;
}
static
int
ab8500_gpadc_runtime_resume
(
struct
device
*
dev
)
{
struct
ab8500_gpadc
*
gpadc
=
dev_get_drvdata
(
dev
);
struct
iio_dev
*
indio_dev
=
dev_get_drvdata
(
dev
);
struct
ab8500_gpadc
*
gpadc
=
iio_priv
(
indio_dev
);
int
ret
;
ret
=
regulator_enable
(
gpadc
->
regu
);
ret
=
regulator_enable
(
gpadc
->
vddadc
);
if
(
ret
)
dev_err
(
dev
,
"Failed to enable vtvout LDO: %d
\n
"
,
ret
);
dev_err
(
dev
,
"Failed to enable vddadc: %d
\n
"
,
ret
);
return
ret
;
}
#endif
#ifdef CONFIG_PM_SLEEP
static
int
ab8500_gpadc_suspend
(
struct
device
*
dev
)
/**
* ab8500_gpadc_parse_channel() - process devicetree channel configuration
* @dev: pointer to containing device
* @np: device tree node for the channel to configure
* @ch: channel info to fill in
* @iio_chan: IIO channel specification to fill in
*
* The devicetree will set up the channel for use with the specific device,
* and define usage for things like AUX GPADC inputs more precisely.
*/
static
int
ab8500_gpadc_parse_channel
(
struct
device
*
dev
,
struct
device_node
*
np
,
struct
ab8500_gpadc_chan_info
*
ch
,
struct
iio_chan_spec
*
iio_chan
)
{
struct
ab8500_gpadc
*
gpadc
=
dev_get_drvdata
(
dev
);
const
char
*
name
=
np
->
name
;
u32
chan
;
int
ret
;
mutex_lock
(
&
gpadc
->
ab8500_gpadc_lock
);
ret
=
of_property_read_u32
(
np
,
"reg"
,
&
chan
);
if
(
ret
)
{
dev_err
(
dev
,
"invalid channel number %s
\n
"
,
name
);
return
ret
;
}
if
(
chan
>
AB8500_GPADC_CHAN_BAT_TEMP_AND_IBAT
)
{
dev_err
(
dev
,
"%s channel number out of range %d
\n
"
,
name
,
chan
);
return
-
EINVAL
;
}
pm_runtime_get_sync
(
dev
);
iio_chan
->
channel
=
chan
;
iio_chan
->
datasheet_name
=
name
;
iio_chan
->
indexed
=
1
;
iio_chan
->
address
=
chan
;
iio_chan
->
info_mask_separate
=
BIT
(
IIO_CHAN_INFO_RAW
)
|
BIT
(
IIO_CHAN_INFO_PROCESSED
);
/* Most are voltages (also temperatures), some are currents */
if
((
chan
==
AB8500_GPADC_CHAN_MAIN_CHARGER_CURRENT
)
||
(
chan
==
AB8500_GPADC_CHAN_USB_CHARGER_CURRENT
))
iio_chan
->
type
=
IIO_CURRENT
;
else
iio_chan
->
type
=
IIO_VOLTAGE
;
ch
->
id
=
chan
;
/* Sensible defaults */
ch
->
avg_sample
=
16
;
ch
->
hardware_control
=
false
;
ch
->
falling_edge
=
false
;
ch
->
trig_timer
=
0
;
regulator_disable
(
gpadc
->
regu
);
return
0
;
}
static
int
ab8500_gpadc_resume
(
struct
device
*
dev
)
/**
* ab8500_gpadc_parse_channels() - Parse the GPADC channels from DT
* @gpadc: the GPADC to configure the channels for
* @np: device tree node containing the channel configurations
* @chans: the IIO channels we parsed
* @nchans: the number of IIO channels we parsed
*/
static
int
ab8500_gpadc_parse_channels
(
struct
ab8500_gpadc
*
gpadc
,
struct
device_node
*
np
,
struct
iio_chan_spec
**
chans_parsed
,
unsigned
int
*
nchans_parsed
)
{
struct
ab8500_gpadc
*
gpadc
=
dev_get_drvdata
(
dev
);
int
ret
;
struct
device_node
*
child
;
struct
ab8500_gpadc_chan_info
*
ch
;
struct
iio_chan_spec
*
iio_chans
;
unsigned
int
nchans
;
int
i
;
ret
=
regulator_enable
(
gpadc
->
regu
);
if
(
ret
)
dev_err
(
dev
,
"Failed to enable vtvout LDO: %d
\n
"
,
ret
);
nchans
=
of_get_available_child_count
(
np
);
if
(
!
nchans
)
{
dev_err
(
gpadc
->
dev
,
"no channel children
\n
"
);
return
-
ENODEV
;
}
dev_info
(
gpadc
->
dev
,
"found %d ADC channels
\n
"
,
nchans
);
pm_runtime_mark_last_busy
(
gpadc
->
dev
);
pm_runtime_put_autosuspend
(
gpadc
->
dev
);
iio_chans
=
devm_kcalloc
(
gpadc
->
dev
,
nchans
,
sizeof
(
*
iio_chans
),
GFP_KERNEL
);
if
(
!
iio_chans
)
return
-
ENOMEM
;
mutex_unlock
(
&
gpadc
->
ab8500_gpadc_lock
);
return
ret
;
gpadc
->
chans
=
devm_kcalloc
(
gpadc
->
dev
,
nchans
,
sizeof
(
*
gpadc
->
chans
),
GFP_KERNEL
);
if
(
!
gpadc
->
chans
)
return
-
ENOMEM
;
i
=
0
;
for_each_available_child_of_node
(
np
,
child
)
{
struct
iio_chan_spec
*
iio_chan
;
int
ret
;
ch
=
&
gpadc
->
chans
[
i
];
iio_chan
=
&
iio_chans
[
i
];
ret
=
ab8500_gpadc_parse_channel
(
gpadc
->
dev
,
child
,
ch
,
iio_chan
);
if
(
ret
)
{
of_node_put
(
child
);
return
ret
;
}
i
++
;
}
gpadc
->
nchans
=
nchans
;
*
chans_parsed
=
iio_chans
;
*
nchans_parsed
=
nchans
;
return
0
;
}
#endif
static
int
ab8500_gpadc_probe
(
struct
platform_device
*
pdev
)
{
int
ret
=
0
;
struct
ab8500_gpadc
*
gpadc
;
struct
iio_dev
*
indio_dev
;
struct
device
*
dev
=
&
pdev
->
dev
;
struct
device_node
*
np
=
pdev
->
dev
.
of_node
;
struct
iio_chan_spec
*
iio_chans
;
unsigned
int
n_iio_chans
;
int
ret
;
gpadc
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
struct
ab8500_gpadc
),
GFP_KERNEL
);
if
(
!
gpadc
)
indio_dev
=
devm_iio_device_alloc
(
dev
,
sizeof
(
*
gpadc
));
if
(
!
indio_dev
)
return
-
ENOMEM
;
platform_set_drvdata
(
pdev
,
indio_dev
);
gpadc
=
iio_priv
(
indio_dev
);
gpadc
->
dev
=
dev
;
gpadc
->
ab8500
=
dev_get_drvdata
(
dev
->
parent
);
ret
=
ab8500_gpadc_parse_channels
(
gpadc
,
np
,
&
iio_chans
,
&
n_iio_chans
);
if
(
ret
)
return
ret
;
gpadc
->
irq_sw
=
platform_get_irq_byname
(
pdev
,
"SW_CONV_END"
);
if
(
gpadc
->
irq_sw
<
0
)
dev_err
(
gpadc
->
dev
,
"failed to get platform sw_conv_end irq
\n
"
);
if
(
gpadc
->
irq_sw
<
0
)
{
dev_err
(
dev
,
"failed to get platform sw_conv_end irq
\n
"
);
return
gpadc
->
irq_sw
;
}
gpadc
->
irq_hw
=
platform_get_irq_byname
(
pdev
,
"HW_CONV_END"
);
if
(
gpadc
->
irq_hw
<
0
)
dev_err
(
gpadc
->
dev
,
"failed to get platform hw_conv_end irq
\n
"
);
gpadc
->
dev
=
&
pdev
->
dev
;
gpadc
->
parent
=
dev_get_drvdata
(
pdev
->
dev
.
parent
);
mutex_init
(
&
gpadc
->
ab8500_gpadc_lock
);
if
(
gpadc
->
irq_hw
<
0
)
{
dev_err
(
dev
,
"failed to get platform hw_conv_end irq
\n
"
);
return
gpadc
->
irq_hw
;
}
/* Initialize completion used to notify completion of conversion */
init_completion
(
&
gpadc
->
ab8500_gpadc_complete
);
/* Register interrupts */
if
(
gpadc
->
irq_sw
>=
0
)
{
ret
=
request_threaded_irq
(
gpadc
->
irq_sw
,
NULL
,
ab8500_bm_gpadcconvend_handler
,
IRQF_NO_SUSPEND
|
IRQF_SHARED
|
IRQF_ONESHOT
,
"ab8500-gpadc-sw"
,
gpadc
);
if
(
ret
<
0
)
{
dev_err
(
gpadc
->
dev
,
"Failed to register interrupt irq: %d
\n
"
,
gpadc
->
irq_sw
);
goto
fail
;
}
}
init_completion
(
&
gpadc
->
complete
);
if
(
gpadc
->
irq_hw
>=
0
)
{
ret
=
request_threaded_irq
(
gpadc
->
irq_hw
,
NULL
,
ab8500_bm_gpadcconvend_handler
,
IRQF_NO_SUSPEND
|
IRQF_SHARED
|
IRQF_ONESHOT
,
"ab8500-gpadc-hw"
,
gpadc
);
if
(
ret
<
0
)
{
dev_err
(
gpadc
->
dev
,
"Failed to register interrupt irq: %d
\n
"
,
gpadc
->
irq_hw
);
goto
fail_irq
;
}
/* Request interrupts */
ret
=
devm_request_threaded_irq
(
dev
,
gpadc
->
irq_sw
,
NULL
,
ab8500_bm_gpadcconvend_handler
,
IRQF_NO_SUSPEND
|
IRQF_ONESHOT
,
"ab8500-gpadc-sw"
,
gpadc
);
if
(
ret
<
0
)
{
dev_err
(
dev
,
"failed to request sw conversion irq %d
\n
"
,
gpadc
->
irq_sw
);
return
ret
;
}
/* VTVout LDO used to power up ab8500-GPADC */
gpadc
->
regu
=
devm_regulator_get
(
&
pdev
->
dev
,
"vddadc"
);
if
(
IS_ERR
(
gpadc
->
regu
))
{
ret
=
PTR_ERR
(
gpadc
->
regu
);
dev_err
(
gpadc
->
dev
,
"failed to get vtvout LDO
\n
"
);
goto
fail_irq
;
ret
=
devm_request_threaded_irq
(
dev
,
gpadc
->
irq_hw
,
NULL
,
ab8500_bm_gpadcconvend_handler
,
IRQF_NO_SUSPEND
|
IRQF_ONESHOT
,
"ab8500-gpadc-hw"
,
gpadc
);
if
(
ret
<
0
)
{
dev_err
(
dev
,
"Failed to request hw conversion irq: %d
\n
"
,
gpadc
->
irq_hw
);
return
ret
;
}
platform_set_drvdata
(
pdev
,
gpadc
);
/* The VTVout LDO used to power the AB8500 GPADC */
gpadc
->
vddadc
=
devm_regulator_get
(
dev
,
"vddadc"
);
if
(
IS_ERR
(
gpadc
->
vddadc
))
{
ret
=
PTR_ERR
(
gpadc
->
vddadc
);
dev_err
(
dev
,
"failed to get vddadc
\n
"
);
return
ret
;
}
ret
=
regulator_enable
(
gpadc
->
regu
);
ret
=
regulator_enable
(
gpadc
->
vddadc
);
if
(
ret
)
{
dev_err
(
gpadc
->
dev
,
"Failed to enable vtvout LDO
: %d
\n
"
,
ret
);
goto
fail_enable
;
dev_err
(
dev
,
"failed to enable vddadc
: %d
\n
"
,
ret
);
return
ret
;
}
pm_runtime_set_autosuspend_delay
(
gpadc
->
dev
,
GPADC_AUDOSUSPEND_DELAY
);
pm_runtime_use_autosuspend
(
gpadc
->
dev
);
pm_runtime_set_active
(
gpadc
->
dev
);
pm_runtime_enable
(
gpadc
->
dev
);
/* Enable runtime PM */
pm_runtime_get_noresume
(
dev
);
pm_runtime_set_active
(
dev
);
pm_runtime_enable
(
dev
);
pm_runtime_set_autosuspend_delay
(
dev
,
AB8500_GPADC_AUTOSUSPEND_DELAY
);
pm_runtime_use_autosuspend
(
dev
);
ab8500_gpadc_read_calibration_data
(
gpadc
);
list_add_tail
(
&
gpadc
->
node
,
&
ab8500_gpadc_list
);
dev_dbg
(
gpadc
->
dev
,
"probe success
\n
"
);
pm_runtime_put
(
dev
);
indio_dev
->
dev
.
parent
=
dev
;
indio_dev
->
dev
.
of_node
=
np
;
indio_dev
->
name
=
"ab8500-gpadc"
;
indio_dev
->
modes
=
INDIO_DIRECT_MODE
;
indio_dev
->
info
=
&
ab8500_gpadc_info
;
indio_dev
->
channels
=
iio_chans
;
indio_dev
->
num_channels
=
n_iio_chans
;
ret
=
devm_iio_device_register
(
dev
,
indio_dev
);
if
(
ret
)
goto
out_dis_pm
;
return
0
;
fail_enable:
fail_irq:
free_irq
(
gpadc
->
irq_sw
,
gpadc
);
free_irq
(
gpadc
->
irq_hw
,
gpadc
);
fail:
out_dis_pm:
pm_runtime_get_sync
(
dev
);
pm_runtime_put_noidle
(
dev
);
pm_runtime_disable
(
dev
);
regulator_disable
(
gpadc
->
vddadc
);
return
ret
;
}
static
int
ab8500_gpadc_remove
(
struct
platform_device
*
pdev
)
{
struct
ab8500_gpadc
*
gpadc
=
platform_get_drvdata
(
pdev
);
/* remove this gpadc entry from the list */
list_del
(
&
gpadc
->
node
);
/* remove interrupt - completion of Sw ADC conversion */
if
(
gpadc
->
irq_sw
>=
0
)
free_irq
(
gpadc
->
irq_sw
,
gpadc
);
if
(
gpadc
->
irq_hw
>=
0
)
free_irq
(
gpadc
->
irq_hw
,
gpadc
);
struct
iio_dev
*
indio_dev
=
platform_get_drvdata
(
pdev
);
struct
ab8500_gpadc
*
gpadc
=
iio_priv
(
indio_dev
);
pm_runtime_get_sync
(
gpadc
->
dev
);
pm_runtime_disable
(
gpadc
->
dev
);
regulator_disable
(
gpadc
->
regu
);
pm_runtime_set_suspended
(
gpadc
->
dev
);
pm_runtime_put_noidle
(
gpadc
->
dev
);
pm_runtime_disable
(
gpadc
->
dev
);
regulator_disable
(
gpadc
->
vddadc
);
return
0
;
}
static
const
struct
dev_pm_ops
ab8500_gpadc_pm_ops
=
{
SET_SYSTEM_SLEEP_PM_OPS
(
pm_runtime_force_suspend
,
pm_runtime_force_resume
)
SET_RUNTIME_PM_OPS
(
ab8500_gpadc_runtime_suspend
,
ab8500_gpadc_runtime_resume
,
NULL
)
SET_SYSTEM_SLEEP_PM_OPS
(
ab8500_gpadc_suspend
,
ab8500_gpadc_resume
)
};
static
struct
platform_driver
ab8500_gpadc_driver
=
{
...
...
@@ -1049,27 +1215,4 @@ static struct platform_driver ab8500_gpadc_driver = {
.
pm
=
&
ab8500_gpadc_pm_ops
,
},
};
static
int
__init
ab8500_gpadc_init
(
void
)
{
return
platform_driver_register
(
&
ab8500_gpadc_driver
);
}
subsys_initcall_sync
(
ab8500_gpadc_init
);
/**
* ab8540_gpadc_get_otp() - returns OTP values
*
*/
void
ab8540_gpadc_get_otp
(
struct
ab8500_gpadc
*
gpadc
,
u16
*
vmain_l
,
u16
*
vmain_h
,
u16
*
btemp_l
,
u16
*
btemp_h
,
u16
*
vbat_l
,
u16
*
vbat_h
,
u16
*
ibat_l
,
u16
*
ibat_h
)
{
*
vmain_l
=
gpadc
->
cal_data
[
ADC_INPUT_VMAIN
].
otp_calib_lo
;
*
vmain_h
=
gpadc
->
cal_data
[
ADC_INPUT_VMAIN
].
otp_calib_hi
;
*
btemp_l
=
gpadc
->
cal_data
[
ADC_INPUT_BTEMP
].
otp_calib_lo
;
*
btemp_h
=
gpadc
->
cal_data
[
ADC_INPUT_BTEMP
].
otp_calib_hi
;
*
vbat_l
=
gpadc
->
cal_data
[
ADC_INPUT_VBAT
].
otp_calib_lo
;
*
vbat_h
=
gpadc
->
cal_data
[
ADC_INPUT_VBAT
].
otp_calib_hi
;
*
ibat_l
=
gpadc
->
cal_data
[
ADC_INPUT_IBAT
].
otp_calib_lo
;
*
ibat_h
=
gpadc
->
cal_data
[
ADC_INPUT_IBAT
].
otp_calib_hi
;
}
builtin_platform_driver
(
ab8500_gpadc_driver
);
drivers/mfd/Kconfig
View file @
16922ffe
...
...
@@ -1210,13 +1210,6 @@ config AB8500_DEBUG
Select this option if you want debug information using the debug
filesystem, debugfs.
config AB8500_GPADC
bool "ST-Ericsson AB8500 GPADC driver"
depends on AB8500_CORE && REGULATOR_AB8500
default y
help
AB8500 GPADC driver used to convert Acc and battery/ac/usb voltage
config MFD_DB8500_PRCMU
bool "ST-Ericsson DB8500 Power Reset Control Management Unit"
depends on UX500_SOC_DB8500
...
...
drivers/mfd/Makefile
View file @
16922ffe
...
...
@@ -177,7 +177,6 @@ obj-$(CONFIG_ABX500_CORE) += abx500-core.o
obj-$(CONFIG_AB3100_CORE)
+=
ab3100-core.o
obj-$(CONFIG_AB3100_OTP)
+=
ab3100-otp.o
obj-$(CONFIG_AB8500_DEBUG)
+=
ab8500-debugfs.o
obj-$(CONFIG_AB8500_GPADC)
+=
ab8500-gpadc.o
obj-$(CONFIG_MFD_DB8500_PRCMU)
+=
db8500-prcmu.o
# ab8500-core need to come after db8500-prcmu (which provides the channel)
obj-$(CONFIG_AB8500_CORE)
+=
ab8500-core.o ab8500-sysctrl.o
...
...
drivers/mfd/ab8500-debugfs.c
View file @
16922ffe
...
...
@@ -84,7 +84,6 @@
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500/ab8500-gpadc.h>
#ifdef CONFIG_DEBUG_FS
#include <linux/string.h>
...
...
@@ -103,11 +102,6 @@ static int num_irqs;
static
struct
device_attribute
**
dev_attr
;
static
char
**
event_name
;
static
u8
avg_sample
=
SAMPLE_16
;
static
u8
trig_edge
=
RISING_EDGE
;
static
u8
conv_type
=
ADC_SW
;
static
u8
trig_timer
;
/**
* struct ab8500_reg_range
* @first: the first address of the range
...
...
@@ -152,7 +146,6 @@ static struct hwreg_cfg hwreg_cfg = {
};
#define AB8500_NAME_STRING "ab8500"
#define AB8500_ADC_NAME_STRING "gpadc"
#define AB8500_NUM_BANKS AB8500_DEBUG_FIELD_LAST
#define AB8500_REV_REG 0x80
...
...
@@ -1646,633 +1639,6 @@ static int ab8500_modem_show(struct seq_file *s, void *p)
DEFINE_SHOW_ATTRIBUTE
(
ab8500_modem
);
static
int
ab8500_gpadc_bat_ctrl_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
bat_ctrl_raw
;
int
bat_ctrl_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
bat_ctrl_raw
=
ab8500_gpadc_read_raw
(
gpadc
,
BAT_CTRL
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
bat_ctrl_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
BAT_CTRL
,
bat_ctrl_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
,
bat_ctrl_convert
,
bat_ctrl_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8500_gpadc_bat_ctrl
);
static
int
ab8500_gpadc_btemp_ball_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
btemp_ball_raw
;
int
btemp_ball_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
btemp_ball_raw
=
ab8500_gpadc_read_raw
(
gpadc
,
BTEMP_BALL
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
btemp_ball_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
BTEMP_BALL
,
btemp_ball_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
,
btemp_ball_convert
,
btemp_ball_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8500_gpadc_btemp_ball
);
static
int
ab8500_gpadc_main_charger_v_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
main_charger_v_raw
;
int
main_charger_v_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
main_charger_v_raw
=
ab8500_gpadc_read_raw
(
gpadc
,
MAIN_CHARGER_V
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
main_charger_v_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
MAIN_CHARGER_V
,
main_charger_v_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
,
main_charger_v_convert
,
main_charger_v_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8500_gpadc_main_charger_v
);
static
int
ab8500_gpadc_acc_detect1_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
acc_detect1_raw
;
int
acc_detect1_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
acc_detect1_raw
=
ab8500_gpadc_read_raw
(
gpadc
,
ACC_DETECT1
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
acc_detect1_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
ACC_DETECT1
,
acc_detect1_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
,
acc_detect1_convert
,
acc_detect1_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8500_gpadc_acc_detect1
);
static
int
ab8500_gpadc_acc_detect2_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
acc_detect2_raw
;
int
acc_detect2_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
acc_detect2_raw
=
ab8500_gpadc_read_raw
(
gpadc
,
ACC_DETECT2
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
acc_detect2_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
ACC_DETECT2
,
acc_detect2_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
,
acc_detect2_convert
,
acc_detect2_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8500_gpadc_acc_detect2
);
static
int
ab8500_gpadc_aux1_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
aux1_raw
;
int
aux1_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
aux1_raw
=
ab8500_gpadc_read_raw
(
gpadc
,
ADC_AUX1
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
aux1_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
ADC_AUX1
,
aux1_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
,
aux1_convert
,
aux1_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8500_gpadc_aux1
);
static
int
ab8500_gpadc_aux2_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
aux2_raw
;
int
aux2_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
aux2_raw
=
ab8500_gpadc_read_raw
(
gpadc
,
ADC_AUX2
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
aux2_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
ADC_AUX2
,
aux2_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
,
aux2_convert
,
aux2_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8500_gpadc_aux2
);
static
int
ab8500_gpadc_main_bat_v_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
main_bat_v_raw
;
int
main_bat_v_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
main_bat_v_raw
=
ab8500_gpadc_read_raw
(
gpadc
,
MAIN_BAT_V
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
main_bat_v_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
MAIN_BAT_V
,
main_bat_v_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
,
main_bat_v_convert
,
main_bat_v_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8500_gpadc_main_bat_v
);
static
int
ab8500_gpadc_vbus_v_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
vbus_v_raw
;
int
vbus_v_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
vbus_v_raw
=
ab8500_gpadc_read_raw
(
gpadc
,
VBUS_V
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
vbus_v_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
VBUS_V
,
vbus_v_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
,
vbus_v_convert
,
vbus_v_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8500_gpadc_vbus_v
);
static
int
ab8500_gpadc_main_charger_c_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
main_charger_c_raw
;
int
main_charger_c_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
main_charger_c_raw
=
ab8500_gpadc_read_raw
(
gpadc
,
MAIN_CHARGER_C
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
main_charger_c_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
MAIN_CHARGER_C
,
main_charger_c_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
,
main_charger_c_convert
,
main_charger_c_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8500_gpadc_main_charger_c
);
static
int
ab8500_gpadc_usb_charger_c_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
usb_charger_c_raw
;
int
usb_charger_c_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
usb_charger_c_raw
=
ab8500_gpadc_read_raw
(
gpadc
,
USB_CHARGER_C
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
usb_charger_c_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
USB_CHARGER_C
,
usb_charger_c_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
,
usb_charger_c_convert
,
usb_charger_c_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8500_gpadc_usb_charger_c
);
static
int
ab8500_gpadc_bk_bat_v_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
bk_bat_v_raw
;
int
bk_bat_v_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
bk_bat_v_raw
=
ab8500_gpadc_read_raw
(
gpadc
,
BK_BAT_V
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
bk_bat_v_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
BK_BAT_V
,
bk_bat_v_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
,
bk_bat_v_convert
,
bk_bat_v_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8500_gpadc_bk_bat_v
);
static
int
ab8500_gpadc_die_temp_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
die_temp_raw
;
int
die_temp_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
die_temp_raw
=
ab8500_gpadc_read_raw
(
gpadc
,
DIE_TEMP
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
die_temp_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
DIE_TEMP
,
die_temp_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
,
die_temp_convert
,
die_temp_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8500_gpadc_die_temp
);
static
int
ab8500_gpadc_usb_id_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
usb_id_raw
;
int
usb_id_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
usb_id_raw
=
ab8500_gpadc_read_raw
(
gpadc
,
USB_ID
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
usb_id_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
USB_ID
,
usb_id_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
,
usb_id_convert
,
usb_id_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8500_gpadc_usb_id
);
static
int
ab8540_gpadc_xtal_temp_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
xtal_temp_raw
;
int
xtal_temp_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
xtal_temp_raw
=
ab8500_gpadc_read_raw
(
gpadc
,
XTAL_TEMP
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
xtal_temp_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
XTAL_TEMP
,
xtal_temp_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
,
xtal_temp_convert
,
xtal_temp_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8540_gpadc_xtal_temp
);
static
int
ab8540_gpadc_vbat_true_meas_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
vbat_true_meas_raw
;
int
vbat_true_meas_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
vbat_true_meas_raw
=
ab8500_gpadc_read_raw
(
gpadc
,
VBAT_TRUE_MEAS
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
);
vbat_true_meas_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
VBAT_TRUE_MEAS
,
vbat_true_meas_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
,
vbat_true_meas_convert
,
vbat_true_meas_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8540_gpadc_vbat_true_meas
);
static
int
ab8540_gpadc_bat_ctrl_and_ibat_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
bat_ctrl_raw
;
int
bat_ctrl_convert
;
int
ibat_raw
;
int
ibat_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
bat_ctrl_raw
=
ab8500_gpadc_double_read_raw
(
gpadc
,
BAT_CTRL_AND_IBAT
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
,
&
ibat_raw
);
bat_ctrl_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
BAT_CTRL
,
bat_ctrl_raw
);
ibat_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
IBAT_VIRTUAL_CHANNEL
,
ibat_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
"%d,0x%X
\n
"
,
bat_ctrl_convert
,
bat_ctrl_raw
,
ibat_convert
,
ibat_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8540_gpadc_bat_ctrl_and_ibat
);
static
int
ab8540_gpadc_vbat_meas_and_ibat_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
vbat_meas_raw
;
int
vbat_meas_convert
;
int
ibat_raw
;
int
ibat_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
vbat_meas_raw
=
ab8500_gpadc_double_read_raw
(
gpadc
,
VBAT_MEAS_AND_IBAT
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
,
&
ibat_raw
);
vbat_meas_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
MAIN_BAT_V
,
vbat_meas_raw
);
ibat_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
IBAT_VIRTUAL_CHANNEL
,
ibat_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
"%d,0x%X
\n
"
,
vbat_meas_convert
,
vbat_meas_raw
,
ibat_convert
,
ibat_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8540_gpadc_vbat_meas_and_ibat
);
static
int
ab8540_gpadc_vbat_true_meas_and_ibat_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
vbat_true_meas_raw
;
int
vbat_true_meas_convert
;
int
ibat_raw
;
int
ibat_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
vbat_true_meas_raw
=
ab8500_gpadc_double_read_raw
(
gpadc
,
VBAT_TRUE_MEAS_AND_IBAT
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
,
&
ibat_raw
);
vbat_true_meas_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
VBAT_TRUE_MEAS
,
vbat_true_meas_raw
);
ibat_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
IBAT_VIRTUAL_CHANNEL
,
ibat_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
"%d,0x%X
\n
"
,
vbat_true_meas_convert
,
vbat_true_meas_raw
,
ibat_convert
,
ibat_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8540_gpadc_vbat_true_meas_and_ibat
);
static
int
ab8540_gpadc_bat_temp_and_ibat_show
(
struct
seq_file
*
s
,
void
*
p
)
{
int
bat_temp_raw
;
int
bat_temp_convert
;
int
ibat_raw
;
int
ibat_convert
;
struct
ab8500_gpadc
*
gpadc
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
bat_temp_raw
=
ab8500_gpadc_double_read_raw
(
gpadc
,
BAT_TEMP_AND_IBAT
,
avg_sample
,
trig_edge
,
trig_timer
,
conv_type
,
&
ibat_raw
);
bat_temp_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
BTEMP_BALL
,
bat_temp_raw
);
ibat_convert
=
ab8500_gpadc_ad_to_voltage
(
gpadc
,
IBAT_VIRTUAL_CHANNEL
,
ibat_raw
);
seq_printf
(
s
,
"%d,0x%X
\n
"
"%d,0x%X
\n
"
,
bat_temp_convert
,
bat_temp_raw
,
ibat_convert
,
ibat_raw
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8540_gpadc_bat_temp_and_ibat
);
static
int
ab8540_gpadc_otp_calib_show
(
struct
seq_file
*
s
,
void
*
p
)
{
struct
ab8500_gpadc
*
gpadc
;
u16
vmain_l
,
vmain_h
,
btemp_l
,
btemp_h
;
u16
vbat_l
,
vbat_h
,
ibat_l
,
ibat_h
;
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
ab8540_gpadc_get_otp
(
gpadc
,
&
vmain_l
,
&
vmain_h
,
&
btemp_l
,
&
btemp_h
,
&
vbat_l
,
&
vbat_h
,
&
ibat_l
,
&
ibat_h
);
seq_printf
(
s
,
"VMAIN_L:0x%X
\n
"
"VMAIN_H:0x%X
\n
"
"BTEMP_L:0x%X
\n
"
"BTEMP_H:0x%X
\n
"
"VBAT_L:0x%X
\n
"
"VBAT_H:0x%X
\n
"
"IBAT_L:0x%X
\n
"
"IBAT_H:0x%X
\n
"
,
vmain_l
,
vmain_h
,
btemp_l
,
btemp_h
,
vbat_l
,
vbat_h
,
ibat_l
,
ibat_h
);
return
0
;
}
DEFINE_SHOW_ATTRIBUTE
(
ab8540_gpadc_otp_calib
);
static
int
ab8500_gpadc_avg_sample_print
(
struct
seq_file
*
s
,
void
*
p
)
{
seq_printf
(
s
,
"%d
\n
"
,
avg_sample
);
return
0
;
}
static
int
ab8500_gpadc_avg_sample_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
ab8500_gpadc_avg_sample_print
,
inode
->
i_private
);
}
static
ssize_t
ab8500_gpadc_avg_sample_write
(
struct
file
*
file
,
const
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
device
*
dev
=
((
struct
seq_file
*
)(
file
->
private_data
))
->
private
;
unsigned
long
user_avg_sample
;
int
err
;
err
=
kstrtoul_from_user
(
user_buf
,
count
,
0
,
&
user_avg_sample
);
if
(
err
)
return
err
;
if
((
user_avg_sample
==
SAMPLE_1
)
||
(
user_avg_sample
==
SAMPLE_4
)
||
(
user_avg_sample
==
SAMPLE_8
)
||
(
user_avg_sample
==
SAMPLE_16
))
{
avg_sample
=
(
u8
)
user_avg_sample
;
}
else
{
dev_err
(
dev
,
"debugfs err input: should be egal to 1, 4, 8 or 16
\n
"
);
return
-
EINVAL
;
}
return
count
;
}
static
const
struct
file_operations
ab8500_gpadc_avg_sample_fops
=
{
.
open
=
ab8500_gpadc_avg_sample_open
,
.
read
=
seq_read
,
.
write
=
ab8500_gpadc_avg_sample_write
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
.
owner
=
THIS_MODULE
,
};
static
int
ab8500_gpadc_trig_edge_print
(
struct
seq_file
*
s
,
void
*
p
)
{
seq_printf
(
s
,
"%d
\n
"
,
trig_edge
);
return
0
;
}
static
int
ab8500_gpadc_trig_edge_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
ab8500_gpadc_trig_edge_print
,
inode
->
i_private
);
}
static
ssize_t
ab8500_gpadc_trig_edge_write
(
struct
file
*
file
,
const
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
device
*
dev
=
((
struct
seq_file
*
)(
file
->
private_data
))
->
private
;
unsigned
long
user_trig_edge
;
int
err
;
err
=
kstrtoul_from_user
(
user_buf
,
count
,
0
,
&
user_trig_edge
);
if
(
err
)
return
err
;
if
((
user_trig_edge
==
RISING_EDGE
)
||
(
user_trig_edge
==
FALLING_EDGE
))
{
trig_edge
=
(
u8
)
user_trig_edge
;
}
else
{
dev_err
(
dev
,
"Wrong input:
\n
"
"Enter 0. Rising edge
\n
"
"Enter 1. Falling edge
\n
"
);
return
-
EINVAL
;
}
return
count
;
}
static
const
struct
file_operations
ab8500_gpadc_trig_edge_fops
=
{
.
open
=
ab8500_gpadc_trig_edge_open
,
.
read
=
seq_read
,
.
write
=
ab8500_gpadc_trig_edge_write
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
.
owner
=
THIS_MODULE
,
};
static
int
ab8500_gpadc_trig_timer_print
(
struct
seq_file
*
s
,
void
*
p
)
{
seq_printf
(
s
,
"%d
\n
"
,
trig_timer
);
return
0
;
}
static
int
ab8500_gpadc_trig_timer_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
ab8500_gpadc_trig_timer_print
,
inode
->
i_private
);
}
static
ssize_t
ab8500_gpadc_trig_timer_write
(
struct
file
*
file
,
const
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
device
*
dev
=
((
struct
seq_file
*
)(
file
->
private_data
))
->
private
;
unsigned
long
user_trig_timer
;
int
err
;
err
=
kstrtoul_from_user
(
user_buf
,
count
,
0
,
&
user_trig_timer
);
if
(
err
)
return
err
;
if
(
user_trig_timer
&
~
0xFF
)
{
dev_err
(
dev
,
"debugfs error input: should be between 0 to 255
\n
"
);
return
-
EINVAL
;
}
trig_timer
=
(
u8
)
user_trig_timer
;
return
count
;
}
static
const
struct
file_operations
ab8500_gpadc_trig_timer_fops
=
{
.
open
=
ab8500_gpadc_trig_timer_open
,
.
read
=
seq_read
,
.
write
=
ab8500_gpadc_trig_timer_write
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
.
owner
=
THIS_MODULE
,
};
static
int
ab8500_gpadc_conv_type_print
(
struct
seq_file
*
s
,
void
*
p
)
{
seq_printf
(
s
,
"%d
\n
"
,
conv_type
);
return
0
;
}
static
int
ab8500_gpadc_conv_type_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
ab8500_gpadc_conv_type_print
,
inode
->
i_private
);
}
static
ssize_t
ab8500_gpadc_conv_type_write
(
struct
file
*
file
,
const
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
device
*
dev
=
((
struct
seq_file
*
)(
file
->
private_data
))
->
private
;
unsigned
long
user_conv_type
;
int
err
;
err
=
kstrtoul_from_user
(
user_buf
,
count
,
0
,
&
user_conv_type
);
if
(
err
)
return
err
;
if
((
user_conv_type
==
ADC_SW
)
||
(
user_conv_type
==
ADC_HW
))
{
conv_type
=
(
u8
)
user_conv_type
;
}
else
{
dev_err
(
dev
,
"Wrong input:
\n
"
"Enter 0. ADC SW conversion
\n
"
"Enter 1. ADC HW conversion
\n
"
);
return
-
EINVAL
;
}
return
count
;
}
static
const
struct
file_operations
ab8500_gpadc_conv_type_fops
=
{
.
open
=
ab8500_gpadc_conv_type_open
,
.
read
=
seq_read
,
.
write
=
ab8500_gpadc_conv_type_write
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
.
owner
=
THIS_MODULE
,
};
/*
* return length of an ASCII numerical value, 0 is string is not a
* numerical value.
...
...
@@ -2647,7 +2013,6 @@ static const struct file_operations ab8500_hwreg_fops = {
static
int
ab8500_debug_probe
(
struct
platform_device
*
plf
)
{
struct
dentry
*
ab8500_dir
;
struct
dentry
*
ab8500_gpadc_dir
;
struct
ab8500
*
ab8500
;
struct
resource
*
res
;
...
...
@@ -2689,9 +2054,6 @@ static int ab8500_debug_probe(struct platform_device *plf)
ab8500_dir
=
debugfs_create_dir
(
AB8500_NAME_STRING
,
NULL
);
ab8500_gpadc_dir
=
debugfs_create_dir
(
AB8500_ADC_NAME_STRING
,
ab8500_dir
);
debugfs_create_file
(
"all-bank-registers"
,
S_IRUGO
,
ab8500_dir
,
&
plf
->
dev
,
&
ab8500_bank_registers_fops
);
debugfs_create_file
(
"all-banks"
,
S_IRUGO
,
ab8500_dir
,
...
...
@@ -2727,83 +2089,6 @@ static int ab8500_debug_probe(struct platform_device *plf)
&
plf
->
dev
,
&
ab8500_hwreg_fops
);
debugfs_create_file
(
"all-modem-registers"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_dir
,
&
plf
->
dev
,
&
ab8500_modem_fops
);
debugfs_create_file
(
"bat_ctrl"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_bat_ctrl_fops
);
debugfs_create_file
(
"btemp_ball"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_btemp_ball_fops
);
debugfs_create_file
(
"main_charger_v"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_main_charger_v_fops
);
debugfs_create_file
(
"acc_detect1"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_acc_detect1_fops
);
debugfs_create_file
(
"acc_detect2"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_acc_detect2_fops
);
debugfs_create_file
(
"adc_aux1"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_aux1_fops
);
debugfs_create_file
(
"adc_aux2"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_aux2_fops
);
debugfs_create_file
(
"main_bat_v"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_main_bat_v_fops
);
debugfs_create_file
(
"vbus_v"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_vbus_v_fops
);
debugfs_create_file
(
"main_charger_c"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_main_charger_c_fops
);
debugfs_create_file
(
"usb_charger_c"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_usb_charger_c_fops
);
debugfs_create_file
(
"bk_bat_v"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_bk_bat_v_fops
);
debugfs_create_file
(
"die_temp"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_die_temp_fops
);
debugfs_create_file
(
"usb_id"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_usb_id_fops
);
if
(
is_ab8540
(
ab8500
))
{
debugfs_create_file
(
"xtal_temp"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8540_gpadc_xtal_temp_fops
);
debugfs_create_file
(
"vbattruemeas"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8540_gpadc_vbat_true_meas_fops
);
debugfs_create_file
(
"batctrl_and_ibat"
,
(
S_IRUGO
|
S_IWUGO
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8540_gpadc_bat_ctrl_and_ibat_fops
);
debugfs_create_file
(
"vbatmeas_and_ibat"
,
(
S_IRUGO
|
S_IWUGO
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8540_gpadc_vbat_meas_and_ibat_fops
);
debugfs_create_file
(
"vbattruemeas_and_ibat"
,
(
S_IRUGO
|
S_IWUGO
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8540_gpadc_vbat_true_meas_and_ibat_fops
);
debugfs_create_file
(
"battemp_and_ibat"
,
(
S_IRUGO
|
S_IWUGO
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8540_gpadc_bat_temp_and_ibat_fops
);
debugfs_create_file
(
"otp_calib"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8540_gpadc_otp_calib_fops
);
}
debugfs_create_file
(
"avg_sample"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_avg_sample_fops
);
debugfs_create_file
(
"trig_edge"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_trig_edge_fops
);
debugfs_create_file
(
"trig_timer"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_trig_timer_fops
);
debugfs_create_file
(
"conv_type"
,
(
S_IRUGO
|
S_IWUSR
|
S_IWGRP
),
ab8500_gpadc_dir
,
&
plf
->
dev
,
&
ab8500_gpadc_conv_type_fops
);
return
0
;
}
...
...
drivers/power/supply/Kconfig
View file @
16922ffe
...
...
@@ -629,7 +629,7 @@ config BATTERY_GAUGE_LTC2941
config AB8500_BM
bool "AB8500 Battery Management Driver"
depends on AB8500_CORE && AB8500_GPADC
depends on AB8500_CORE && AB8500_GPADC
&& (IIO = y)
help
Say Y to include support for AB8500 battery management.
...
...
drivers/power/supply/ab8500_btemp.c
View file @
16922ffe
...
...
@@ -26,7 +26,7 @@
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500/ab8500-bm.h>
#include <linux/
mfd/abx500/ab8500-gpadc
.h>
#include <linux/
iio/consumer
.h>
#define VTVOUT_V 1800
...
...
@@ -79,7 +79,8 @@ struct ab8500_btemp_ranges {
* @bat_temp: Dispatched battery temperature in degree Celsius
* @prev_bat_temp Last measured battery temperature in degree Celsius
* @parent: Pointer to the struct ab8500
* @gpadc: Pointer to the struct gpadc
* @adc_btemp_ball: ADC channel for the battery ball temperature
* @adc_bat_ctrl: ADC channel for the battery control
* @fg: Pointer to the struct fg
* @bm: Platform specific battery management information
* @btemp_psy: Structure for BTEMP specific battery properties
...
...
@@ -96,7 +97,8 @@ struct ab8500_btemp {
int
bat_temp
;
int
prev_bat_temp
;
struct
ab8500
*
parent
;
struct
ab8500_gpadc
*
gpadc
;
struct
iio_channel
*
btemp_ball
;
struct
iio_channel
*
bat_ctrl
;
struct
ab8500_fg
*
fg
;
struct
abx500_bm_data
*
bm
;
struct
power_supply
*
btemp_psy
;
...
...
@@ -177,13 +179,13 @@ static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di,
*/
static
int
ab8500_btemp_read_batctrl_voltage
(
struct
ab8500_btemp
*
di
)
{
int
vbtemp
;
int
vbtemp
,
ret
;
static
int
prev
;
vbtemp
=
ab8500_gpadc_convert
(
di
->
gpadc
,
BAT_CTRL
);
if
(
vbtemp
<
0
)
{
ret
=
iio_read_channel_processed
(
di
->
bat_ctrl
,
&
vbtemp
);
if
(
ret
<
0
)
{
dev_err
(
di
->
dev
,
"%s
gpadc
conversion failed, using previous value"
,
"%s
ADC
conversion failed, using previous value"
,
__func__
);
return
prev
;
}
...
...
@@ -455,7 +457,7 @@ static int ab8500_btemp_res_to_temp(struct ab8500_btemp *di,
*/
static
int
ab8500_btemp_measure_temp
(
struct
ab8500_btemp
*
di
)
{
int
temp
;
int
temp
,
ret
;
static
int
prev
;
int
rbat
,
rntc
,
vntc
;
u8
id
;
...
...
@@ -480,10 +482,10 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
di
->
bm
->
bat_type
[
id
].
r_to_t_tbl
,
di
->
bm
->
bat_type
[
id
].
n_temp_tbl_elements
,
rbat
);
}
else
{
vntc
=
ab8500_gpadc_convert
(
di
->
gpadc
,
BTEMP_BALL
);
if
(
vntc
<
0
)
{
ret
=
iio_read_channel_processed
(
di
->
btemp_ball
,
&
vntc
);
if
(
ret
<
0
)
{
dev_err
(
di
->
dev
,
"%s
gpadc
conversion failed,"
"%s
ADC
conversion failed,"
" using previous value
\n
"
,
__func__
);
return
prev
;
}
...
...
@@ -1024,7 +1026,22 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
/* get parent data */
di
->
dev
=
&
pdev
->
dev
;
di
->
parent
=
dev_get_drvdata
(
pdev
->
dev
.
parent
);
di
->
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
/* Get ADC channels */
di
->
btemp_ball
=
devm_iio_channel_get
(
&
pdev
->
dev
,
"btemp_ball"
);
if
(
IS_ERR
(
di
->
btemp_ball
))
{
if
(
PTR_ERR
(
di
->
btemp_ball
)
==
-
ENODEV
)
return
-
EPROBE_DEFER
;
dev_err
(
&
pdev
->
dev
,
"failed to get BTEMP BALL ADC channel
\n
"
);
return
PTR_ERR
(
di
->
btemp_ball
);
}
di
->
bat_ctrl
=
devm_iio_channel_get
(
&
pdev
->
dev
,
"bat_ctrl"
);
if
(
IS_ERR
(
di
->
bat_ctrl
))
{
if
(
PTR_ERR
(
di
->
bat_ctrl
)
==
-
ENODEV
)
return
-
EPROBE_DEFER
;
dev_err
(
&
pdev
->
dev
,
"failed to get BAT CTRL ADC channel
\n
"
);
return
PTR_ERR
(
di
->
bat_ctrl
);
}
di
->
initialized
=
false
;
...
...
drivers/power/supply/ab8500_charger.c
View file @
16922ffe
...
...
@@ -29,10 +29,10 @@
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500-bm.h>
#include <linux/mfd/abx500/ab8500-gpadc.h>
#include <linux/mfd/abx500/ux500_chargalg.h>
#include <linux/usb/otg.h>
#include <linux/mutex.h>
#include <linux/iio/consumer.h>
/* Charger constants */
#define NO_PW_CONN 0
...
...
@@ -233,7 +233,10 @@ struct ab8500_charger_max_usb_in_curr {
* @current_stepping_sessions:
* Counter for current stepping sessions
* @parent: Pointer to the struct ab8500
* @gpadc: Pointer to the struct gpadc
* @adc_main_charger_v ADC channel for main charger voltage
* @adc_main_charger_c ADC channel for main charger current
* @adc_vbus_v ADC channel for USB charger voltage
* @adc_usb_charger_c ADC channel for USB charger current
* @bm: Platform specific battery management information
* @flags: Structure for information about events triggered
* @usb_state: Structure for usb stack information
...
...
@@ -283,7 +286,10 @@ struct ab8500_charger {
int
is_aca_rid
;
atomic_t
current_stepping_sessions
;
struct
ab8500
*
parent
;
struct
ab8500_gpadc
*
gpadc
;
struct
iio_channel
*
adc_main_charger_v
;
struct
iio_channel
*
adc_main_charger_c
;
struct
iio_channel
*
adc_vbus_v
;
struct
iio_channel
*
adc_usb_charger_c
;
struct
abx500_bm_data
*
bm
;
struct
ab8500_charger_event_flags
flags
;
struct
ab8500_charger_usb_state
usb_state
;
...
...
@@ -459,13 +465,13 @@ static void ab8500_charger_set_usb_connected(struct ab8500_charger *di,
*/
static
int
ab8500_charger_get_ac_voltage
(
struct
ab8500_charger
*
di
)
{
int
vch
;
int
vch
,
ret
;
/* Only measure voltage if the charger is connected */
if
(
di
->
ac
.
charger_connected
)
{
vch
=
ab8500_gpadc_convert
(
di
->
gpadc
,
MAIN_CHARGER_V
);
if
(
vch
<
0
)
dev_err
(
di
->
dev
,
"%s
gpadc
conv failed,
\n
"
,
__func__
);
ret
=
iio_read_channel_processed
(
di
->
adc_main_charger_v
,
&
vch
);
if
(
ret
<
0
)
dev_err
(
di
->
dev
,
"%s
ADC
conv failed,
\n
"
,
__func__
);
}
else
{
vch
=
0
;
}
...
...
@@ -510,13 +516,13 @@ static int ab8500_charger_ac_cv(struct ab8500_charger *di)
*/
static
int
ab8500_charger_get_vbus_voltage
(
struct
ab8500_charger
*
di
)
{
int
vch
;
int
vch
,
ret
;
/* Only measure voltage if the charger is connected */
if
(
di
->
usb
.
charger_connected
)
{
vch
=
ab8500_gpadc_convert
(
di
->
gpadc
,
VBUS_V
);
if
(
vch
<
0
)
dev_err
(
di
->
dev
,
"%s
gpadc conv failed
\n
"
,
__func__
);
ret
=
iio_read_channel_processed
(
di
->
adc_vbus_v
,
&
vch
);
if
(
ret
<
0
)
dev_err
(
di
->
dev
,
"%s
ADC conv failed,
\n
"
,
__func__
);
}
else
{
vch
=
0
;
}
...
...
@@ -532,13 +538,13 @@ static int ab8500_charger_get_vbus_voltage(struct ab8500_charger *di)
*/
static
int
ab8500_charger_get_usb_current
(
struct
ab8500_charger
*
di
)
{
int
ich
;
int
ich
,
ret
;
/* Only measure current if the charger is online */
if
(
di
->
usb
.
charger_online
)
{
ich
=
ab8500_gpadc_convert
(
di
->
gpadc
,
USB_CHARGER_C
);
if
(
ich
<
0
)
dev_err
(
di
->
dev
,
"%s
gpadc conv failed
\n
"
,
__func__
);
ret
=
iio_read_channel_processed
(
di
->
adc_usb_charger_c
,
&
ich
);
if
(
ret
<
0
)
dev_err
(
di
->
dev
,
"%s
ADC conv failed,
\n
"
,
__func__
);
}
else
{
ich
=
0
;
}
...
...
@@ -554,13 +560,13 @@ static int ab8500_charger_get_usb_current(struct ab8500_charger *di)
*/
static
int
ab8500_charger_get_ac_current
(
struct
ab8500_charger
*
di
)
{
int
ich
;
int
ich
,
ret
;
/* Only measure current if the charger is online */
if
(
di
->
ac
.
charger_online
)
{
ich
=
ab8500_gpadc_convert
(
di
->
gpadc
,
MAIN_CHARGER_C
);
if
(
ich
<
0
)
dev_err
(
di
->
dev
,
"%s
gpadc conv failed
\n
"
,
__func__
);
ret
=
iio_read_channel_processed
(
di
->
adc_main_charger_c
,
&
ich
);
if
(
ret
<
0
)
dev_err
(
di
->
dev
,
"%s
ADC conv failed,
\n
"
,
__func__
);
}
else
{
ich
=
0
;
}
...
...
@@ -3371,7 +3377,39 @@ static int ab8500_charger_probe(struct platform_device *pdev)
/* get parent data */
di
->
dev
=
&
pdev
->
dev
;
di
->
parent
=
dev_get_drvdata
(
pdev
->
dev
.
parent
);
di
->
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
/* Get ADC channels */
di
->
adc_main_charger_v
=
devm_iio_channel_get
(
&
pdev
->
dev
,
"main_charger_v"
);
if
(
IS_ERR
(
di
->
adc_main_charger_v
))
{
if
(
PTR_ERR
(
di
->
adc_main_charger_v
)
==
-
ENODEV
)
return
-
EPROBE_DEFER
;
dev_err
(
&
pdev
->
dev
,
"failed to get ADC main charger voltage
\n
"
);
return
PTR_ERR
(
di
->
adc_main_charger_v
);
}
di
->
adc_main_charger_c
=
devm_iio_channel_get
(
&
pdev
->
dev
,
"main_charger_c"
);
if
(
IS_ERR
(
di
->
adc_main_charger_c
))
{
if
(
PTR_ERR
(
di
->
adc_main_charger_c
)
==
-
ENODEV
)
return
-
EPROBE_DEFER
;
dev_err
(
&
pdev
->
dev
,
"failed to get ADC main charger current
\n
"
);
return
PTR_ERR
(
di
->
adc_main_charger_v
);
}
di
->
adc_vbus_v
=
devm_iio_channel_get
(
&
pdev
->
dev
,
"vbus_v"
);
if
(
IS_ERR
(
di
->
adc_vbus_v
))
{
if
(
PTR_ERR
(
di
->
adc_vbus_v
)
==
-
ENODEV
)
return
-
EPROBE_DEFER
;
dev_err
(
&
pdev
->
dev
,
"failed to get ADC USB charger voltage
\n
"
);
return
PTR_ERR
(
di
->
adc_vbus_v
);
}
di
->
adc_usb_charger_c
=
devm_iio_channel_get
(
&
pdev
->
dev
,
"usb_charger_c"
);
if
(
IS_ERR
(
di
->
adc_usb_charger_c
))
{
if
(
PTR_ERR
(
di
->
adc_usb_charger_c
)
==
-
ENODEV
)
return
-
EPROBE_DEFER
;
dev_err
(
&
pdev
->
dev
,
"failed to get ADC USB charger current
\n
"
);
return
PTR_ERR
(
di
->
adc_usb_charger_c
);
}
/* initialize lock */
spin_lock_init
(
&
di
->
usb_state
.
usb_lock
);
...
...
drivers/power/supply/ab8500_fg.c
View file @
16922ffe
...
...
@@ -32,7 +32,7 @@
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500/ab8500-bm.h>
#include <linux/
mfd/abx500/ab8500-gpadc
.h>
#include <linux/
iio/consumer
.h>
#include <linux/kernel.h>
#define MILLI_TO_MICRO 1000
...
...
@@ -182,7 +182,7 @@ struct inst_curr_result_list {
* @bat_cap: Structure for battery capacity specific parameters
* @avg_cap: Average capacity filter
* @parent: Pointer to the struct ab8500
* @
gpadc: Pointer to the struct gpadc
* @
main_bat_v: ADC channel for the main battery voltage
* @bm: Platform specific battery management information
* @fg_psy: Structure that holds the FG specific battery properties
* @fg_wq: Work queue for running the FG algorithm
...
...
@@ -224,7 +224,7 @@ struct ab8500_fg {
struct
ab8500_fg_battery_capacity
bat_cap
;
struct
ab8500_fg_avg_cap
avg_cap
;
struct
ab8500
*
parent
;
struct
ab8500_gpadc
*
gpadc
;
struct
iio_channel
*
main_bat_v
;
struct
abx500_bm_data
*
bm
;
struct
power_supply
*
fg_psy
;
struct
workqueue_struct
*
fg_wq
;
...
...
@@ -829,13 +829,13 @@ static void ab8500_fg_acc_cur_work(struct work_struct *work)
*/
static
int
ab8500_fg_bat_voltage
(
struct
ab8500_fg
*
di
)
{
int
vbat
;
int
vbat
,
ret
;
static
int
prev
;
vbat
=
ab8500_gpadc_convert
(
di
->
gpadc
,
MAIN_BAT_V
);
if
(
vba
t
<
0
)
{
ret
=
iio_read_channel_processed
(
di
->
main_bat_v
,
&
vbat
);
if
(
re
t
<
0
)
{
dev_err
(
di
->
dev
,
"%s
gpadc
conversion failed, using previous value
\n
"
,
"%s
ADC
conversion failed, using previous value
\n
"
,
__func__
);
return
prev
;
}
...
...
@@ -3066,7 +3066,14 @@ static int ab8500_fg_probe(struct platform_device *pdev)
/* get parent data */
di
->
dev
=
&
pdev
->
dev
;
di
->
parent
=
dev_get_drvdata
(
pdev
->
dev
.
parent
);
di
->
gpadc
=
ab8500_gpadc_get
(
"ab8500-gpadc.0"
);
di
->
main_bat_v
=
devm_iio_channel_get
(
&
pdev
->
dev
,
"main_bat_v"
);
if
(
IS_ERR
(
di
->
main_bat_v
))
{
if
(
PTR_ERR
(
di
->
main_bat_v
)
==
-
ENODEV
)
return
-
EPROBE_DEFER
;
dev_err
(
&
pdev
->
dev
,
"failed to get main battery ADC channel
\n
"
);
return
PTR_ERR
(
di
->
main_bat_v
);
}
psy_cfg
.
supplied_to
=
supply_interface
;
psy_cfg
.
num_supplicants
=
ARRAY_SIZE
(
supply_interface
);
...
...
include/linux/mfd/abx500/ab8500-gpadc.h
deleted
100644 → 0
View file @
686191a7
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2010 ST-Ericsson SA
*
* Author: Arun R Murthy <arun.murthy@stericsson.com>
* Author: Daniel Willerud <daniel.willerud@stericsson.com>
* Author: M'boumba Cedric Madianga <cedric.madianga@stericsson.com>
*/
#ifndef _AB8500_GPADC_H
#define _AB8500_GPADC_H
/* GPADC source: From datasheet(ADCSwSel[4:0] in GPADCCtrl2
* and ADCHwSel[4:0] in GPADCCtrl3 ) */
#define BAT_CTRL 0x01
#define BTEMP_BALL 0x02
#define MAIN_CHARGER_V 0x03
#define ACC_DETECT1 0x04
#define ACC_DETECT2 0x05
#define ADC_AUX1 0x06
#define ADC_AUX2 0x07
#define MAIN_BAT_V 0x08
#define VBUS_V 0x09
#define MAIN_CHARGER_C 0x0A
#define USB_CHARGER_C 0x0B
#define BK_BAT_V 0x0C
#define DIE_TEMP 0x0D
#define USB_ID 0x0E
#define XTAL_TEMP 0x12
#define VBAT_TRUE_MEAS 0x13
#define BAT_CTRL_AND_IBAT 0x1C
#define VBAT_MEAS_AND_IBAT 0x1D
#define VBAT_TRUE_MEAS_AND_IBAT 0x1E
#define BAT_TEMP_AND_IBAT 0x1F
/* Virtual channel used only for ibat convertion to ampere
* Battery current conversion (ibat) cannot be requested as a single conversion
* but it is always in combination with other input requests
*/
#define IBAT_VIRTUAL_CHANNEL 0xFF
#define SAMPLE_1 1
#define SAMPLE_4 4
#define SAMPLE_8 8
#define SAMPLE_16 16
#define RISING_EDGE 0
#define FALLING_EDGE 1
/* Arbitrary ADC conversion type constants */
#define ADC_SW 0
#define ADC_HW 1
struct
ab8500_gpadc
;
struct
ab8500_gpadc
*
ab8500_gpadc_get
(
char
*
name
);
int
ab8500_gpadc_sw_hw_convert
(
struct
ab8500_gpadc
*
gpadc
,
u8
channel
,
u8
avg_sample
,
u8
trig_edge
,
u8
trig_timer
,
u8
conv_type
);
static
inline
int
ab8500_gpadc_convert
(
struct
ab8500_gpadc
*
gpadc
,
u8
channel
)
{
return
ab8500_gpadc_sw_hw_convert
(
gpadc
,
channel
,
SAMPLE_16
,
0
,
0
,
ADC_SW
);
}
int
ab8500_gpadc_read_raw
(
struct
ab8500_gpadc
*
gpadc
,
u8
channel
,
u8
avg_sample
,
u8
trig_edge
,
u8
trig_timer
,
u8
conv_type
);
int
ab8500_gpadc_double_read_raw
(
struct
ab8500_gpadc
*
gpadc
,
u8
channel
,
u8
avg_sample
,
u8
trig_edge
,
u8
trig_timer
,
u8
conv_type
,
int
*
ibat
);
int
ab8500_gpadc_ad_to_voltage
(
struct
ab8500_gpadc
*
gpadc
,
u8
channel
,
int
ad_value
);
void
ab8540_gpadc_get_otp
(
struct
ab8500_gpadc
*
gpadc
,
u16
*
vmain_l
,
u16
*
vmain_h
,
u16
*
btemp_l
,
u16
*
btemp_h
,
u16
*
vbat_l
,
u16
*
vbat_h
,
u16
*
ibat_l
,
u16
*
ibat_h
);
#endif
/* _AB8500_GPADC_H */
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