Merge branch 'for-mfd-and-power' of git://git.linaro.org/people/ljones/linux-3.0-ux500

From Lee Jones <lee.jones@linaro.org>:

"Please find the next instalment of the AB8500 Power drivers upgrade. A lot of
work has taken place on the internal development track, but little effort has
gone into mainlining it. There is a large backlog of patches which are in need
of forward-porting, then upstreaming. This patch-set aims to make a large dent
into them."

Conflicts:
	drivers/mfd/ab8500-gpadc.c
This commit is contained in:
Anton Vorontsov
2013-03-18 19:02:58 -07:00
20 changed files with 4465 additions and 956 deletions
+448 -176
View File
File diff suppressed because it is too large Load Diff
+1597 -144
View File
File diff suppressed because it is too large Load Diff
+457 -104
View File
File diff suppressed because it is too large Load Diff
+87 -11
View File
@@ -15,19 +15,30 @@
#include <linux/mfd/abx500/ab8500.h> #include <linux/mfd/abx500/ab8500.h>
#include <linux/mfd/abx500/ab8500-sysctrl.h> #include <linux/mfd/abx500/ab8500-sysctrl.h>
/* RtcCtrl bits */
#define AB8500_ALARM_MIN_LOW 0x08
#define AB8500_ALARM_MIN_MID 0x09
#define RTC_CTRL 0x0B
#define RTC_ALARM_ENABLE 0x4
static struct device *sysctrl_dev; static struct device *sysctrl_dev;
void ab8500_power_off(void) void ab8500_power_off(void)
{ {
sigset_t old; sigset_t old;
sigset_t all; sigset_t all;
static char *pss[] = {"ab8500_ac", "ab8500_usb"}; static char *pss[] = {"ab8500_ac", "pm2301", "ab8500_usb"};
int i; int i;
bool charger_present = false; bool charger_present = false;
union power_supply_propval val; union power_supply_propval val;
struct power_supply *psy; struct power_supply *psy;
int ret; int ret;
if (sysctrl_dev == NULL) {
pr_err("%s: sysctrl not initialized\n", __func__);
return;
}
/* /*
* If we have a charger connected and we're powering off, * If we have a charger connected and we're powering off,
* reboot into charge-only mode. * reboot into charge-only mode.
@@ -74,6 +85,63 @@ shutdown:
} }
} }
/*
* Use the AB WD to reset the platform. It will perform a hard
* reset instead of a soft reset. Write the reset reason to
* the AB before reset, which can be read upon restart.
*/
void ab8500_restart(char mode, const char *cmd)
{
struct ab8500_platform_data *plat;
struct ab8500_sysctrl_platform_data *pdata;
u16 reason = 0;
u8 val;
if (sysctrl_dev == NULL) {
pr_err("%s: sysctrl not initialized\n", __func__);
return;
}
plat = dev_get_platdata(sysctrl_dev->parent);
pdata = plat->sysctrl;
if (pdata->reboot_reason_code)
reason = pdata->reboot_reason_code(cmd);
else
pr_warn("[%s] No reboot reason set. Default reason %d\n",
__func__, reason);
/*
* Disable RTC alarm, just a precaution so that no alarm
* is running when WD reset is executed.
*/
abx500_get_register_interruptible(sysctrl_dev, AB8500_RTC,
RTC_CTRL , &val);
abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC,
RTC_CTRL , (val & ~RTC_ALARM_ENABLE));
/*
* Android is not using the RTC alarm registers during reboot
* so we borrow them for writing the reason of reset
*/
/* reason[8 LSB] */
val = reason & 0xFF;
abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC,
AB8500_ALARM_MIN_LOW , val);
/* reason[8 MSB] */
val = (reason>>8) & 0xFF;
abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC,
AB8500_ALARM_MIN_MID , val);
/* Setting WD timeout to 0 */
ab8500_sysctrl_write(AB8500_MAINWDOGTIMER, 0xFF, 0x0);
/* Setting the parameters to AB8500 WD*/
ab8500_sysctrl_write(AB8500_MAINWDOGCTRL, 0xFF, (AB8500_ENABLE_WD |
AB8500_WD_RESTART_ON_EXPIRE | AB8500_KICK_WD));
}
static inline bool valid_bank(u8 bank) static inline bool valid_bank(u8 bank)
{ {
return ((bank == AB8500_SYS_CTRL1_BLOCK) || return ((bank == AB8500_SYS_CTRL1_BLOCK) ||
@@ -85,7 +153,7 @@ int ab8500_sysctrl_read(u16 reg, u8 *value)
u8 bank; u8 bank;
if (sysctrl_dev == NULL) if (sysctrl_dev == NULL)
return -EAGAIN; return -EINVAL;
bank = (reg >> 8); bank = (reg >> 8);
if (!valid_bank(bank)) if (!valid_bank(bank))
@@ -101,7 +169,7 @@ int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value)
u8 bank; u8 bank;
if (sysctrl_dev == NULL) if (sysctrl_dev == NULL)
return -EAGAIN; return -EINVAL;
bank = (reg >> 8); bank = (reg >> 8);
if (!valid_bank(bank)) if (!valid_bank(bank))
@@ -114,28 +182,36 @@ EXPORT_SYMBOL(ab8500_sysctrl_write);
static int ab8500_sysctrl_probe(struct platform_device *pdev) static int ab8500_sysctrl_probe(struct platform_device *pdev)
{ {
struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
struct ab8500_platform_data *plat; struct ab8500_platform_data *plat;
struct ab8500_sysctrl_platform_data *pdata; struct ab8500_sysctrl_platform_data *pdata;
sysctrl_dev = &pdev->dev;
plat = dev_get_platdata(pdev->dev.parent); plat = dev_get_platdata(pdev->dev.parent);
if (!(plat && plat->sysctrl))
return -EINVAL;
if (plat->pm_power_off) if (plat->pm_power_off)
pm_power_off = ab8500_power_off; pm_power_off = ab8500_power_off;
pdata = plat->sysctrl; pdata = plat->sysctrl;
if (pdata) { if (pdata) {
int ret, i, j; int last, ret, i, j;
for (i = AB8500_SYSCLKREQ1RFCLKBUF; if (is_ab8505(ab8500))
i <= AB8500_SYSCLKREQ8RFCLKBUF; i++) { last = AB8500_SYSCLKREQ4RFCLKBUF;
else
last = AB8500_SYSCLKREQ8RFCLKBUF;
for (i = AB8500_SYSCLKREQ1RFCLKBUF; i <= last; i++) {
j = i - AB8500_SYSCLKREQ1RFCLKBUF; j = i - AB8500_SYSCLKREQ1RFCLKBUF;
ret = ab8500_sysctrl_write(i, 0xff, ret = ab8500_sysctrl_write(i, 0xff,
pdata->initial_req_buf_config[j]); pdata->initial_req_buf_config[j]);
dev_dbg(&pdev->dev, dev_dbg(&pdev->dev,
"Setting SysClkReq%dRfClkBuf 0x%X\n", "Setting SysClkReq%dRfClkBuf 0x%X\n",
j + 1, j + 1,
pdata->initial_req_buf_config[j]); pdata->initial_req_buf_config[j]);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"unable to set sysClkReq%dRfClkBuf: " "unable to set sysClkReq%dRfClkBuf: "
-7
View File
@@ -353,13 +353,6 @@ config BATTERY_GOLDFISH
Say Y to enable support for the battery and AC power in the Say Y to enable support for the battery and AC power in the
Goldfish emulator. Goldfish emulator.
config CHARGER_PM2301
bool "PM2301 Battery Charger Driver"
depends on AB8500_BM
help
Say Y to include support for PM2301 charger driver.
Depends on AB8500 battery management core.
source "drivers/power/reset/Kconfig" source "drivers/power/reset/Kconfig"
endif # POWER_SUPPLY endif # POWER_SUPPLY
+1 -2
View File
@@ -39,7 +39,7 @@ obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o
obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o
obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o
obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o abx500_chargalg.o obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o abx500_chargalg.o pm2301_charger.o
obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o
obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
@@ -47,7 +47,6 @@ obj-$(CONFIG_CHARGER_LP8727) += lp8727_charger.o
obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o
obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o
obj-$(CONFIG_CHARGER_PM2301) += pm2301_charger.o
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o
+93 -3
View File
@@ -407,15 +407,27 @@ static const struct abx500_fg_parameters fg = {
.battok_raising_th_sel1 = 2860, .battok_raising_th_sel1 = 2860,
.maint_thres = 95, .maint_thres = 95,
.user_cap_limit = 15, .user_cap_limit = 15,
.pcut_enable = 1,
.pcut_max_time = 127,
.pcut_flag_time = 112,
.pcut_max_restart = 15,
.pcut_debounce_time = 2,
}; };
static const struct abx500_maxim_parameters maxi_params = { static const struct abx500_maxim_parameters ab8500_maxi_params = {
.ena_maxi = true, .ena_maxi = true,
.chg_curr = 910, .chg_curr = 910,
.wait_cycles = 10, .wait_cycles = 10,
.charger_curr_step = 100, .charger_curr_step = 100,
}; };
static const struct abx500_maxim_parameters abx540_maxi_params = {
.ena_maxi = true,
.chg_curr = 3000,
.wait_cycles = 10,
.charger_curr_step = 200,
};
static const struct abx500_bm_charger_parameters chg = { static const struct abx500_bm_charger_parameters chg = {
.usb_volt_max = 5500, .usb_volt_max = 5500,
.usb_curr_max = 1500, .usb_curr_max = 1500,
@@ -423,6 +435,46 @@ static const struct abx500_bm_charger_parameters chg = {
.ac_curr_max = 1500, .ac_curr_max = 1500,
}; };
/*
* This array maps the raw hex value to charger output current used by the
* AB8500 values
*/
static int ab8500_charge_output_curr_map[] = {
100, 200, 300, 400, 500, 600, 700, 800,
900, 1000, 1100, 1200, 1300, 1400, 1500, 1500,
};
static int ab8540_charge_output_curr_map[] = {
0, 0, 0, 75, 100, 125, 150, 175,
200, 225, 250, 275, 300, 325, 350, 375,
400, 425, 450, 475, 500, 525, 550, 575,
600, 625, 650, 675, 700, 725, 750, 775,
800, 825, 850, 875, 900, 925, 950, 975,
1000, 1025, 1050, 1075, 1100, 1125, 1150, 1175,
1200, 1225, 1250, 1275, 1300, 1325, 1350, 1375,
1400, 1425, 1450, 1500, 1600, 1700, 1900, 2000,
};
/*
* This array maps the raw hex value to charger input current used by the
* AB8500 values
*/
static int ab8500_charge_input_curr_map[] = {
50, 98, 193, 290, 380, 450, 500, 600,
700, 800, 900, 1000, 1100, 1300, 1400, 1500,
};
static int ab8540_charge_input_curr_map[] = {
25, 50, 75, 100, 125, 150, 175, 200,
225, 250, 275, 300, 325, 350, 375, 400,
425, 450, 475, 500, 525, 550, 575, 600,
625, 650, 675, 700, 725, 750, 775, 800,
825, 850, 875, 900, 925, 950, 975, 1000,
1025, 1050, 1075, 1100, 1125, 1150, 1175, 1200,
1225, 1250, 1275, 1300, 1325, 1350, 1375, 1400,
1425, 1450, 1475, 1500, 1500, 1500, 1500, 1500,
};
struct abx500_bm_data ab8500_bm_data = { struct abx500_bm_data ab8500_bm_data = {
.temp_under = 3, .temp_under = 3,
.temp_low = 8, .temp_low = 8,
@@ -442,15 +494,53 @@ struct abx500_bm_data ab8500_bm_data = {
.fg_res = 100, .fg_res = 100,
.cap_levels = &cap_levels, .cap_levels = &cap_levels,
.bat_type = bat_type_thermistor, .bat_type = bat_type_thermistor,
.n_btypes = 3, .n_btypes = ARRAY_SIZE(bat_type_thermistor),
.batt_id = 0, .batt_id = 0,
.interval_charging = 5, .interval_charging = 5,
.interval_not_charging = 120, .interval_not_charging = 120,
.temp_hysteresis = 3, .temp_hysteresis = 3,
.gnd_lift_resistance = 34, .gnd_lift_resistance = 34,
.maxi = &maxi_params, .chg_output_curr = ab8500_charge_output_curr_map,
.n_chg_out_curr = ARRAY_SIZE(ab8500_charge_output_curr_map),
.maxi = &ab8500_maxi_params,
.chg_params = &chg, .chg_params = &chg,
.fg_params = &fg, .fg_params = &fg,
.chg_input_curr = ab8500_charge_input_curr_map,
.n_chg_in_curr = ARRAY_SIZE(ab8500_charge_input_curr_map),
};
struct abx500_bm_data ab8540_bm_data = {
.temp_under = 3,
.temp_low = 8,
.temp_high = 43,
.temp_over = 48,
.main_safety_tmr_h = 4,
.temp_interval_chg = 20,
.temp_interval_nochg = 120,
.usb_safety_tmr_h = 4,
.bkup_bat_v = BUP_VCH_SEL_2P6V,
.bkup_bat_i = BUP_ICH_SEL_150UA,
.no_maintenance = false,
.capacity_scaling = false,
.adc_therm = ABx500_ADC_THERM_BATCTRL,
.chg_unknown_bat = false,
.enable_overshoot = false,
.fg_res = 100,
.cap_levels = &cap_levels,
.bat_type = bat_type_thermistor,
.n_btypes = ARRAY_SIZE(bat_type_thermistor),
.batt_id = 0,
.interval_charging = 5,
.interval_not_charging = 120,
.temp_hysteresis = 3,
.gnd_lift_resistance = 0,
.maxi = &abx540_maxi_params,
.chg_params = &chg,
.fg_params = &fg,
.chg_output_curr = ab8540_charge_output_curr_map,
.n_chg_out_curr = ARRAY_SIZE(ab8540_charge_output_curr_map),
.chg_input_curr = ab8540_charge_input_curr_map,
.n_chg_in_curr = ARRAY_SIZE(ab8540_charge_input_curr_map),
}; };
int ab8500_bm_of_probe(struct device *dev, int ab8500_bm_of_probe(struct device *dev,
+59 -16
View File
@@ -42,6 +42,9 @@
#define BTEMP_BATCTRL_CURR_SRC_16UA 16 #define BTEMP_BATCTRL_CURR_SRC_16UA 16
#define BTEMP_BATCTRL_CURR_SRC_18UA 18 #define BTEMP_BATCTRL_CURR_SRC_18UA 18
#define BTEMP_BATCTRL_CURR_SRC_60UA 60
#define BTEMP_BATCTRL_CURR_SRC_120UA 120
#define to_ab8500_btemp_device_info(x) container_of((x), \ #define to_ab8500_btemp_device_info(x) container_of((x), \
struct ab8500_btemp, btemp_psy); struct ab8500_btemp, btemp_psy);
@@ -76,8 +79,8 @@ struct ab8500_btemp_ranges {
* @dev: Pointer to the structure device * @dev: Pointer to the structure device
* @node: List of AB8500 BTEMPs, hence prepared for reentrance * @node: List of AB8500 BTEMPs, hence prepared for reentrance
* @curr_source: What current source we use, in uA * @curr_source: What current source we use, in uA
* @bat_temp: Battery temperature in degree Celcius * @bat_temp: Dispatched battery temperature in degree Celcius
* @prev_bat_temp Last dispatched battery temperature * @prev_bat_temp Last measured battery temperature in degree Celcius
* @parent: Pointer to the struct ab8500 * @parent: Pointer to the struct ab8500
* @gpadc: Pointer to the struct gpadc * @gpadc: Pointer to the struct gpadc
* @fg: Pointer to the struct fg * @fg: Pointer to the struct fg
@@ -155,7 +158,7 @@ static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di,
if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL) { if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL) {
/* /*
* If the battery has internal NTC, we use the current * If the battery has internal NTC, we use the current
* source to calculate the resistance, 7uA or 20uA * source to calculate the resistance.
*/ */
rbs = (v_batctrl * 1000 rbs = (v_batctrl * 1000
- di->bm->gnd_lift_resistance * inst_curr) - di->bm->gnd_lift_resistance * inst_curr)
@@ -216,7 +219,12 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
/* Only do this for batteries with internal NTC */ /* Only do this for batteries with internal NTC */
if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) { if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) {
if (is_ab9540(di->parent) || is_ab8505(di->parent)) { if (is_ab8540(di->parent)) {
if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_60UA)
curr = BAT_CTRL_60U_ENA;
else
curr = BAT_CTRL_120U_ENA;
} else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_16UA) if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_16UA)
curr = BAT_CTRL_16U_ENA; curr = BAT_CTRL_16U_ENA;
else else
@@ -257,7 +265,14 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
} else if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) { } else if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) {
dev_dbg(di->dev, "Disable BATCTRL curr source\n"); dev_dbg(di->dev, "Disable BATCTRL curr source\n");
if (is_ab9540(di->parent) || is_ab8505(di->parent)) { if (is_ab8540(di->parent)) {
/* Write 0 to the curr bits */
ret = abx500_mask_and_set_register_interruptible(
di->dev,
AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA,
~(BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA));
} else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
/* Write 0 to the curr bits */ /* Write 0 to the curr bits */
ret = abx500_mask_and_set_register_interruptible( ret = abx500_mask_and_set_register_interruptible(
di->dev, di->dev,
@@ -314,7 +329,13 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
* if we got an error above * if we got an error above
*/ */
disable_curr_source: disable_curr_source:
if (is_ab9540(di->parent) || is_ab8505(di->parent)) { if (is_ab8540(di->parent)) {
/* Write 0 to the curr bits */
ret = abx500_mask_and_set_register_interruptible(di->dev,
AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA,
~(BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA));
} else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
/* Write 0 to the curr bits */ /* Write 0 to the curr bits */
ret = abx500_mask_and_set_register_interruptible(di->dev, ret = abx500_mask_and_set_register_interruptible(di->dev,
AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
@@ -541,7 +562,9 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
{ {
int res; int res;
u8 i; u8 i;
if (is_ab9540(di->parent) || is_ab8505(di->parent)) if (is_ab8540(di->parent))
di->curr_source = BTEMP_BATCTRL_CURR_SRC_60UA;
else if (is_ab9540(di->parent) || is_ab8505(di->parent))
di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA; di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA;
else else
di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA; di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA;
@@ -579,12 +602,17 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
/* /*
* We only have to change current source if the * We only have to change current source if the
* detected type is Type 1, else we use the 7uA source * detected type is Type 1.
*/ */
if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
di->bm->batt_id == 1) { di->bm->batt_id == 1) {
if (is_ab9540(di->parent) || is_ab8505(di->parent)) { if (is_ab8540(di->parent)) {
dev_dbg(di->dev, "Set BATCTRL current source to 16uA\n"); dev_dbg(di->dev,
"Set BATCTRL current source to 60uA\n");
di->curr_source = BTEMP_BATCTRL_CURR_SRC_60UA;
} else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
dev_dbg(di->dev,
"Set BATCTRL current source to 16uA\n");
di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA; di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA;
} else { } else {
dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n"); dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n");
@@ -604,22 +632,37 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
static void ab8500_btemp_periodic_work(struct work_struct *work) static void ab8500_btemp_periodic_work(struct work_struct *work)
{ {
int interval; int interval;
int bat_temp;
struct ab8500_btemp *di = container_of(work, struct ab8500_btemp *di = container_of(work,
struct ab8500_btemp, btemp_periodic_work.work); struct ab8500_btemp, btemp_periodic_work.work);
if (!di->initialized) { if (!di->initialized) {
di->initialized = true;
/* Identify the battery */ /* Identify the battery */
if (ab8500_btemp_id(di) < 0) if (ab8500_btemp_id(di) < 0)
dev_warn(di->dev, "failed to identify the battery\n"); dev_warn(di->dev, "failed to identify the battery\n");
} }
di->bat_temp = ab8500_btemp_measure_temp(di); bat_temp = ab8500_btemp_measure_temp(di);
/*
if (di->bat_temp != di->prev_bat_temp) { * Filter battery temperature.
di->prev_bat_temp = di->bat_temp; * Allow direct updates on temperature only if two samples result in
* same temperature. Else only allow 1 degree change from previous
* reported value in the direction of the new measurement.
*/
if ((bat_temp == di->prev_bat_temp) || !di->initialized) {
if ((di->bat_temp != di->prev_bat_temp) || !di->initialized) {
di->initialized = true;
di->bat_temp = bat_temp;
power_supply_changed(&di->btemp_psy);
}
} else if (bat_temp < di->prev_bat_temp) {
di->bat_temp--;
power_supply_changed(&di->btemp_psy);
} else if (bat_temp > di->prev_bat_temp) {
di->bat_temp++;
power_supply_changed(&di->btemp_psy); power_supply_changed(&di->btemp_psy);
} }
di->prev_bat_temp = bat_temp;
if (di->events.ac_conn || di->events.usb_conn) if (di->events.ac_conn || di->events.usb_conn)
interval = di->bm->temp_interval_chg; interval = di->bm->temp_interval_chg;
File diff suppressed because it is too large Load Diff
+483 -14
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -22
View File
@@ -9,27 +9,6 @@
#ifndef PM2301_CHARGER_H #ifndef PM2301_CHARGER_H
#define PM2301_CHARGER_H #define PM2301_CHARGER_H
#define MAIN_WDOG_ENA 0x01
#define MAIN_WDOG_KICK 0x02
#define MAIN_WDOG_DIS 0x00
#define CHARG_WD_KICK 0x01
#define MAIN_CH_ENA 0x01
#define MAIN_CH_NO_OVERSHOOT_ENA_N 0x02
#define MAIN_CH_DET 0x01
#define MAIN_CH_CV_ON 0x04
#define OTP_ENABLE_WD 0x01
#define MAIN_CH_INPUT_CURR_SHIFT 4
#define LED_INDICATOR_PWM_ENA 0x01
#define LED_INDICATOR_PWM_DIS 0x00
#define LED_IND_CUR_5MA 0x04
#define LED_INDICATOR_PWM_DUTY_252_256 0xBF
/* HW failure constants */
#define MAIN_CH_TH_PROT 0x02
#define MAIN_CH_NOK 0x01
/* Watchdog timeout constant */ /* Watchdog timeout constant */
#define WD_TIMER 0x30 /* 4min */ #define WD_TIMER 0x30 /* 4min */
#define WD_KICK_INTERVAL (30 * HZ) #define WD_KICK_INTERVAL (30 * HZ)
@@ -495,7 +474,6 @@ struct pm2xxx_charger {
int failure_input_ovv; int failure_input_ovv;
unsigned int lpn_pin; unsigned int lpn_pin;
struct pm2xxx_interrupts *pm2_int; struct pm2xxx_interrupts *pm2_int;
struct ab8500_gpadc *gpadc;
struct regulator *regu; struct regulator *regu;
struct pm2xxx_bm_data *bat; struct pm2xxx_bm_data *bat;
struct mutex lock; struct mutex lock;
@@ -506,6 +484,7 @@ struct pm2xxx_charger {
struct delayed_work check_vbat_work; struct delayed_work check_vbat_work;
struct work_struct ac_work; struct work_struct ac_work;
struct work_struct check_main_thermal_prot_work; struct work_struct check_main_thermal_prot_work;
struct delayed_work check_hw_failure_work;
struct ux500_charger ac_chg; struct ux500_charger ac_chg;
struct pm2xxx_charger_event_flags flags; struct pm2xxx_charger_event_flags flags;
}; };
+20 -1
View File
@@ -89,6 +89,11 @@ struct abx500_fg;
* points. * points.
* @maint_thres This is the threshold where we stop reporting * @maint_thres This is the threshold where we stop reporting
* battery full while in maintenance, in per cent * battery full while in maintenance, in per cent
* @pcut_enable: Enable power cut feature in ab8505
* @pcut_max_time: Max time threshold
* @pcut_flag_time: Flagtime threshold
* @pcut_max_restart: Max number of restarts
* @pcut_debounce_time: Sets battery debounce time
*/ */
struct abx500_fg_parameters { struct abx500_fg_parameters {
int recovery_sleep_timer; int recovery_sleep_timer;
@@ -106,6 +111,11 @@ struct abx500_fg_parameters {
int battok_raising_th_sel1; int battok_raising_th_sel1;
int user_cap_limit; int user_cap_limit;
int maint_thres; int maint_thres;
bool pcut_enable;
u8 pcut_max_time;
u8 pcut_flag_time;
u8 pcut_max_restart;
u8 pcut_debounce_time;
}; };
/** /**
@@ -236,7 +246,11 @@ struct abx500_bm_charger_parameters {
* @interval_not_charging charge alg cycle period time when not charging (sec) * @interval_not_charging charge alg cycle period time when not charging (sec)
* @temp_hysteresis temperature hysteresis * @temp_hysteresis temperature hysteresis
* @gnd_lift_resistance Battery ground to phone ground resistance (mOhm) * @gnd_lift_resistance Battery ground to phone ground resistance (mOhm)
* @maxi: maximization parameters * @n_chg_out_curr number of elements in array chg_output_curr
* @n_chg_in_curr number of elements in array chg_input_curr
* @chg_output_curr charger output current level map
* @chg_input_curr charger input current level map
* @maxi maximization parameters
* @cap_levels capacity in percent for the different capacity levels * @cap_levels capacity in percent for the different capacity levels
* @bat_type table of supported battery types * @bat_type table of supported battery types
* @chg_params charger parameters * @chg_params charger parameters
@@ -257,6 +271,7 @@ struct abx500_bm_data {
bool autopower_cfg; bool autopower_cfg;
bool ac_enabled; bool ac_enabled;
bool usb_enabled; bool usb_enabled;
bool usb_power_path;
bool no_maintenance; bool no_maintenance;
bool capacity_scaling; bool capacity_scaling;
bool chg_unknown_bat; bool chg_unknown_bat;
@@ -270,6 +285,10 @@ struct abx500_bm_data {
int interval_not_charging; int interval_not_charging;
int temp_hysteresis; int temp_hysteresis;
int gnd_lift_resistance; int gnd_lift_resistance;
int n_chg_out_curr;
int n_chg_in_curr;
int *chg_output_curr;
int *chg_input_curr;
const struct abx500_maxim_parameters *maxi; const struct abx500_maxim_parameters *maxi;
const struct abx500_bm_capacity_levels *cap_levels; const struct abx500_bm_capacity_levels *cap_levels;
struct abx500_battery_type *bat_type; struct abx500_battery_type *bat_type;
+55 -5
View File
@@ -23,6 +23,7 @@
* Bank : 0x5 * Bank : 0x5
*/ */
#define AB8500_USB_LINE_STAT_REG 0x80 #define AB8500_USB_LINE_STAT_REG 0x80
#define AB8500_USB_LINE_CTRL2_REG 0x82
#define AB8500_USB_LINK1_STAT_REG 0x94 #define AB8500_USB_LINK1_STAT_REG 0x94
/* /*
@@ -33,7 +34,7 @@
#define AB8500_CH_STATUS2_REG 0x01 #define AB8500_CH_STATUS2_REG 0x01
#define AB8500_CH_USBCH_STAT1_REG 0x02 #define AB8500_CH_USBCH_STAT1_REG 0x02
#define AB8500_CH_USBCH_STAT2_REG 0x03 #define AB8500_CH_USBCH_STAT2_REG 0x03
#define AB8500_CH_FSM_STAT_REG 0x04 #define AB8540_CH_USBCH_STAT3_REG 0x04
#define AB8500_CH_STAT_REG 0x05 #define AB8500_CH_STAT_REG 0x05
/* /*
@@ -69,6 +70,8 @@
#define AB8500_USBCH_CTRL1_REG 0xC0 #define AB8500_USBCH_CTRL1_REG 0xC0
#define AB8500_USBCH_CTRL2_REG 0xC1 #define AB8500_USBCH_CTRL2_REG 0xC1
#define AB8500_USBCH_IPT_CRNTLVL_REG 0xC2 #define AB8500_USBCH_IPT_CRNTLVL_REG 0xC2
#define AB8540_USB_PP_MODE_REG 0xC5
#define AB8540_USB_PP_CHR_REG 0xC6
/* /*
* Gas Gauge register offsets * Gas Gauge register offsets
@@ -105,6 +108,7 @@
#define AB8500_RTC_BACKUP_CHG_REG 0x0C #define AB8500_RTC_BACKUP_CHG_REG 0x0C
#define AB8500_RTC_CC_CONF_REG 0x01 #define AB8500_RTC_CC_CONF_REG 0x01
#define AB8500_RTC_CTRL_REG 0x0B #define AB8500_RTC_CTRL_REG 0x0B
#define AB8500_RTC_CTRL1_REG 0x11
/* /*
* OTP register offsets * OTP register offsets
@@ -154,6 +158,7 @@
#define CH_OP_CUR_LVL_1P4 0x0D #define CH_OP_CUR_LVL_1P4 0x0D
#define CH_OP_CUR_LVL_1P5 0x0E #define CH_OP_CUR_LVL_1P5 0x0E
#define CH_OP_CUR_LVL_1P6 0x0F #define CH_OP_CUR_LVL_1P6 0x0F
#define CH_OP_CUR_LVL_2P 0x3F
/* BTEMP High thermal limits */ /* BTEMP High thermal limits */
#define BTEMP_HIGH_TH_57_0 0x00 #define BTEMP_HIGH_TH_57_0 0x00
@@ -179,10 +184,25 @@
#define BUP_ICH_SEL_300UA 0x08 #define BUP_ICH_SEL_300UA 0x08
#define BUP_ICH_SEL_700UA 0x0C #define BUP_ICH_SEL_700UA 0x0C
#define BUP_VCH_SEL_2P5V 0x00 enum bup_vch_sel {
#define BUP_VCH_SEL_2P6V 0x01 BUP_VCH_SEL_2P5V,
#define BUP_VCH_SEL_2P8V 0x02 BUP_VCH_SEL_2P6V,
#define BUP_VCH_SEL_3P1V 0x03 BUP_VCH_SEL_2P8V,
BUP_VCH_SEL_3P1V,
/*
* Note that the following 5 values 2.7v, 2.9v, 3.0v, 3.2v, 3.3v
* are only available on ab8540. You can't choose these 5
* voltage on ab8500/ab8505/ab9540.
*/
BUP_VCH_SEL_2P7V,
BUP_VCH_SEL_2P9V,
BUP_VCH_SEL_3P0V,
BUP_VCH_SEL_3P2V,
BUP_VCH_SEL_3P3V,
};
#define BUP_VCH_RANGE 0x02
#define VBUP33_VRTCN 0x01
/* Battery OVV constants */ /* Battery OVV constants */
#define BATT_OVV_ENA 0x02 #define BATT_OVV_ENA 0x02
@@ -228,6 +248,8 @@
#define BAT_CTRL_20U_ENA 0x02 #define BAT_CTRL_20U_ENA 0x02
#define BAT_CTRL_18U_ENA 0x01 #define BAT_CTRL_18U_ENA 0x01
#define BAT_CTRL_16U_ENA 0x02 #define BAT_CTRL_16U_ENA 0x02
#define BAT_CTRL_60U_ENA 0x01
#define BAT_CTRL_120U_ENA 0x02
#define BAT_CTRL_CMP_ENA 0x04 #define BAT_CTRL_CMP_ENA 0x04
#define FORCE_BAT_CTRL_CMP_HIGH 0x08 #define FORCE_BAT_CTRL_CMP_HIGH 0x08
#define BAT_CTRL_PULL_UP_ENA 0x10 #define BAT_CTRL_PULL_UP_ENA 0x10
@@ -235,6 +257,24 @@
/* Battery type */ /* Battery type */
#define BATTERY_UNKNOWN 00 #define BATTERY_UNKNOWN 00
/* Registers for pcut feature in ab8505 and ab9540 */
#define AB8505_RTC_PCUT_CTL_STATUS_REG 0x12
#define AB8505_RTC_PCUT_TIME_REG 0x13
#define AB8505_RTC_PCUT_MAX_TIME_REG 0x14
#define AB8505_RTC_PCUT_FLAG_TIME_REG 0x15
#define AB8505_RTC_PCUT_RESTART_REG 0x16
#define AB8505_RTC_PCUT_DEBOUNCE_REG 0x17
/* USB Power Path constants for ab8540 */
#define BUS_VSYS_VOL_SELECT_MASK 0x06
#define BUS_VSYS_VOL_SELECT_3P6V 0x00
#define BUS_VSYS_VOL_SELECT_3P325V 0x02
#define BUS_VSYS_VOL_SELECT_3P9V 0x04
#define BUS_VSYS_VOL_SELECT_4P3V 0x06
#define BUS_POWER_PATH_MODE_ENA 0x01
#define BUS_PP_PRECHG_CURRENT_MASK 0x0E
#define BUS_POWER_PATH_PRECHG_ENA 0x01
/** /**
* struct res_to_temp - defines one point in a temp to res curve. To * struct res_to_temp - defines one point in a temp to res curve. To
* be used in battery packs that combines the identification resistor with a * be used in battery packs that combines the identification resistor with a
@@ -283,6 +323,11 @@ struct ab8500_fg;
* points. * points.
* @maint_thres This is the threshold where we stop reporting * @maint_thres This is the threshold where we stop reporting
* battery full while in maintenance, in per cent * battery full while in maintenance, in per cent
* @pcut_enable: Enable power cut feature in ab8505
* @pcut_max_time: Max time threshold
* @pcut_flag_time: Flagtime threshold
* @pcut_max_restart: Max number of restarts
* @pcut_debunce_time: Sets battery debounce time
*/ */
struct ab8500_fg_parameters { struct ab8500_fg_parameters {
int recovery_sleep_timer; int recovery_sleep_timer;
@@ -299,6 +344,11 @@ struct ab8500_fg_parameters {
int battok_raising_th_sel1; int battok_raising_th_sel1;
int user_cap_limit; int user_cap_limit;
int maint_thres; int maint_thres;
bool pcut_enable;
u8 pcut_max_time;
u8 pcut_flag_time;
u8 pcut_max_restart;
u8 pcut_debunce_time;
}; };
/** /**
+57 -17
View File
@@ -4,32 +4,72 @@
* *
* Author: Arun R Murthy <arun.murthy@stericsson.com> * Author: Arun R Murthy <arun.murthy@stericsson.com>
* Author: Daniel Willerud <daniel.willerud@stericsson.com> * Author: Daniel Willerud <daniel.willerud@stericsson.com>
* Author: M'boumba Cedric Madianga <cedric.madianga@stericsson.com>
*/ */
#ifndef _AB8500_GPADC_H #ifndef _AB8500_GPADC_H
#define _AB8500_GPADC_H #define _AB8500_GPADC_H
/* GPADC source: From datasheet(ADCSwSel[4:0] in GPADCCtrl2) */ /* GPADC source: From datasheet(ADCSwSel[4:0] in GPADCCtrl2
#define BAT_CTRL 0x01 * and ADCHwSel[4:0] in GPADCCtrl3 ) */
#define BTEMP_BALL 0x02 #define BAT_CTRL 0x01
#define MAIN_CHARGER_V 0x03 #define BTEMP_BALL 0x02
#define ACC_DETECT1 0x04 #define MAIN_CHARGER_V 0x03
#define ACC_DETECT2 0x05 #define ACC_DETECT1 0x04
#define ADC_AUX1 0x06 #define ACC_DETECT2 0x05
#define ADC_AUX2 0x07 #define ADC_AUX1 0x06
#define MAIN_BAT_V 0x08 #define ADC_AUX2 0x07
#define VBUS_V 0x09 #define MAIN_BAT_V 0x08
#define MAIN_CHARGER_C 0x0A #define VBUS_V 0x09
#define USB_CHARGER_C 0x0B #define MAIN_CHARGER_C 0x0A
#define BK_BAT_V 0x0C #define USB_CHARGER_C 0x0B
#define DIE_TEMP 0x0D #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;
struct ab8500_gpadc *ab8500_gpadc_get(char *name); struct ab8500_gpadc *ab8500_gpadc_get(char *name);
int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 channel); int ab8500_gpadc_sw_hw_convert(struct ab8500_gpadc *gpadc, u8 channel,
int ab8500_gpadc_read_raw(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, int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc,
u8 channel, int ad_value); 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 */ #endif /* _AB8500_GPADC_H */
@@ -12,6 +12,7 @@
int ab8500_sysctrl_read(u16 reg, u8 *value); int ab8500_sysctrl_read(u16 reg, u8 *value);
int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value); int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value);
void ab8500_restart(char mode, const char *cmd);
#else #else
@@ -40,6 +41,7 @@ static inline int ab8500_sysctrl_clear(u16 reg, u8 bits)
/* Configuration data for SysClkReq1RfClkBuf - SysClkReq8RfClkBuf */ /* Configuration data for SysClkReq1RfClkBuf - SysClkReq8RfClkBuf */
struct ab8500_sysctrl_platform_data { struct ab8500_sysctrl_platform_data {
u8 initial_req_buf_config[8]; u8 initial_req_buf_config[8];
u16 (*reboot_reason_code)(const char *cmd);
}; };
/* Registers */ /* Registers */
@@ -299,4 +301,8 @@ struct ab8500_sysctrl_platform_data {
#define AB9540_SYSCLK12BUF4VALID_SYSCLK12BUF4VALID_MASK 0xFF #define AB9540_SYSCLK12BUF4VALID_SYSCLK12BUF4VALID_MASK 0xFF
#define AB9540_SYSCLK12BUF4VALID_SYSCLK12BUF4VALID_SHIFT 0 #define AB9540_SYSCLK12BUF4VALID_SYSCLK12BUF4VALID_SHIFT 0
#define AB8500_ENABLE_WD 0x1
#define AB8500_KICK_WD 0x2
#define AB8500_WD_RESTART_ON_EXPIRE 0x10
#endif /* __AB8500_SYSCTRL_H */ #endif /* __AB8500_SYSCTRL_H */
+3
View File
@@ -362,6 +362,7 @@ struct ab8500 {
u8 *oldmask; u8 *oldmask;
int mask_size; int mask_size;
const int *irq_reg_offset; const int *irq_reg_offset;
int it_latchhier_num;
}; };
struct regulator_reg_init; struct regulator_reg_init;
@@ -512,6 +513,8 @@ static inline int is_ab9540_2p0_or_earlier(struct ab8500 *ab)
return (is_ab9540(ab) && (ab->chip_id < AB8500_CUT2P0)); return (is_ab9540(ab) && (ab->chip_id < AB8500_CUT2P0));
} }
void ab8500_override_turn_on_stat(u8 mask, u8 set);
#ifdef CONFIG_AB8500_DEBUG #ifdef CONFIG_AB8500_DEBUG
void ab8500_dump_all_banks(struct device *dev); void ab8500_dump_all_banks(struct device *dev);
void ab8500_debug_register_interrupt(int line); void ab8500_debug_register_interrupt(int line);
@@ -17,8 +17,11 @@ struct ux500_charger;
struct ux500_charger_ops { struct ux500_charger_ops {
int (*enable) (struct ux500_charger *, int, int, int); int (*enable) (struct ux500_charger *, int, int, int);
int (*check_enable) (struct ux500_charger *, int, int);
int (*kick_wd) (struct ux500_charger *); int (*kick_wd) (struct ux500_charger *);
int (*update_curr) (struct ux500_charger *, int); int (*update_curr) (struct ux500_charger *, int);
int (*pp_enable) (struct ux500_charger *, bool);
int (*pre_chg_enable) (struct ux500_charger *, bool);
}; };
/** /**
@@ -29,6 +32,7 @@ struct ux500_charger_ops {
* @max_out_curr maximum output charger current in mA * @max_out_curr maximum output charger current in mA
* @enabled indicates if this charger is used or not * @enabled indicates if this charger is used or not
* @external external charger unit (pm2xxx) * @external external charger unit (pm2xxx)
* @power_path USB power path support
*/ */
struct ux500_charger { struct ux500_charger {
struct power_supply psy; struct power_supply psy;
@@ -38,6 +42,9 @@ struct ux500_charger {
int wdt_refresh; int wdt_refresh;
bool enabled; bool enabled;
bool external; bool external;
bool power_path;
}; };
extern struct blocking_notifier_head charger_notifier_list;
#endif #endif
+1 -1
View File
@@ -48,7 +48,7 @@ struct pm2xxx_charger_platform_data {
size_t num_supplicants; size_t num_supplicants;
int i2c_bus; int i2c_bus;
const char *label; const char *label;
int irq_number; int gpio_irq_number;
unsigned int lpn_gpio; unsigned int lpn_gpio;
int irq_type; int irq_type;
}; };