aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRamakrishna Pallala <ramakrishna.pallala@intel.com>2010-12-09 10:37:48 +0000
committerAlan Cox <alan@linux.intel.com>2010-12-09 10:37:48 +0000
commitf1b855d5148ee7cb7ee78e688ffe8838c7cbf81e (patch)
treee3c84ce943ce2691679432ad93f36701c6d7439f
parentebe1c137340dc5f47d2b871e7eb81971d6ef7ec6 (diff)
downloadmrst-s0i3-test-f1b855d5148ee7cb7ee78e688ffe8838c7cbf81e.tar.gz
mrst-s0i3-test-f1b855d5148ee7cb7ee78e688ffe8838c7cbf81e.tar.xz
mrst-s0i3-test-f1b855d5148ee7cb7ee78e688ffe8838c7cbf81e.zip
Added support for Emergency call Charging
Added a sysfs interface for enabling/disabling Emergency call support. During the charge cycle depending on the temperature and emergency charge enablement parameters we set the current limit value accordingly. Signed-off-by: Ramakrishna Pallala <ramakrishna.pallala@intel.com> Signed-off-by: Alan Cox <alan@linux.intel.com>
-rw-r--r--drivers/power/intel_mdf_battery.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/drivers/power/intel_mdf_battery.c b/drivers/power/intel_mdf_battery.c
index 5a58b0c527f..426cb841e4e 100644
--- a/drivers/power/intel_mdf_battery.c
+++ b/drivers/power/intel_mdf_battery.c
@@ -400,6 +400,7 @@ struct msic_power_module_info {
spinlock_t event_lock;
int batt_event;
int charging_mode;
+ int emrg_chrg_enbl; /* Emergency call charge enable */
/* lock to avoid concurrent access to HW Registers.
* As some chargeer control and parameter registers
@@ -409,6 +410,15 @@ struct msic_power_module_info {
struct mutex ipc_rw_lock;
};
+
+static ssize_t set_emrg_chrg(struct device *device,
+ struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t get_emrg_chrg(struct device *device,
+ struct device_attribute *attr, char *buf);
+/* Sysfs Entry for enable or disable Emergency Charging */
+static DEVICE_ATTR(emrg_charge_enable, S_IWUGO | S_IRUGO,
+ get_emrg_chrg, set_emrg_chrg);
+
/*
* msic usb properties
*/
@@ -980,6 +990,42 @@ static int msic_battery_get_property(struct power_supply *psy,
return 0;
}
+static ssize_t set_emrg_chrg(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct platform_device *pdev = container_of(dev,
+ struct platform_device, dev);
+ struct msic_power_module_info *mbi = platform_get_drvdata(pdev);
+ unsigned long value;
+
+ if (strict_strtoul(buf, 10, &value))
+ return -EINVAL;
+
+ spin_lock(&mbi->event_lock);
+ if (value)
+ mbi->emrg_chrg_enbl = true;
+ else
+ mbi->emrg_chrg_enbl = false;
+ spin_unlock(&mbi->event_lock);
+
+ return count;
+}
+static ssize_t get_emrg_chrg(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct platform_device *pdev = container_of(dev,
+ struct platform_device, dev);
+ struct msic_power_module_info *mbi = platform_get_drvdata(pdev);
+ unsigned int val;
+
+ spin_lock(&mbi->event_lock);
+ val = mbi->emrg_chrg_enbl;
+ spin_unlock(&mbi->event_lock);
+
+ return sprintf(buf, "%d\n", val);
+}
+
+
/**
* msic_log_exception_event - log battery events
* @event: msic event to be logged
@@ -1126,6 +1172,40 @@ static int msic_write_multi(struct msic_power_module_info *mbi,
return retval;
}
+static int ipc_read_modify_chr_param_reg(struct msic_power_module_info *mbi,
+ uint16_t addr, uint8_t val, int set)
+{
+ int ret = 0;
+ static u16 address[2] = {
+ MSIC_BATT_CHR_WDTWRITE_ADDR, 0
+ };
+ static u8 data[2] = {
+ WDTWRITE_UNLOCK_VALUE, 0
+ };
+
+ address[1] = addr;
+
+ /* Unlock Charge parameter registers before reading */
+ ret = intel_scu_ipc_iowrite8(address[0], data[0]);
+ if (ret) {
+ dev_warn(msic_dev, "%s:ipc write failed\n", __func__);
+ return ret;
+ }
+
+ ret = intel_scu_ipc_ioread8(address[1], &data[1]);
+ if (ret) {
+ dev_warn(msic_dev, "%s:ipc read failed\n", __func__);
+ return ret;
+ }
+
+ if (set)
+ data[1] |= val;
+ else
+ data[1] &= (~val);
+
+ return msic_write_multi(mbi, address, data, 2);
+}
+
static int msic_batt_stop_charging(struct msic_power_module_info *mbi)
{
static const u16 address[] = {
@@ -1400,6 +1480,22 @@ static void msic_batt_temp_charging(struct work_struct *work)
dev_dbg(msic_dev, "params vol: %x cur:%x vinilmt:%x\n",
charge_param.cvol, charge_param.ccur, charge_param.vinilmt);
+ /*
+ * Check if emergency charging is not enabled and temperarure is < 0
+ * limit the charging current to LOW CHARGE (325 mA) else
+ * allow the charging as set in charge current register
+ */
+ spin_lock(&mbi->event_lock);
+ if (!mbi->emrg_chrg_enbl && (i == sfi_table->temp_mon_ranges)) {
+ dev_dbg(msic_dev, "Emeregency Charging Enabled\n");
+ ipc_read_modify_chr_param_reg(mbi, MSIC_BATT_CHR_SPCHARGER_ADDR,
+ CHR_SPCHRGER_LOWCHR_ENABLE, BIT_SET);
+ } else {
+ dev_dbg(msic_dev, "Emeregency Charging Not Enabled\n");
+ ipc_read_modify_chr_param_reg(mbi, MSIC_BATT_CHR_SPCHARGER_ADDR,
+ CHR_SPCHRGER_LOWCHR_ENABLE, BIT_RESET);
+ }
+ spin_unlock(&mbi->event_lock);
/* enable charging here */
ret = msic_batt_do_charging(mbi, &charge_param);
@@ -1941,6 +2037,10 @@ static int msic_battery_probe(struct platform_device *pdev)
goto power_reg_failed_usb;
}
+ retval = device_create_file(&pdev->dev, &dev_attr_emrg_charge_enable);
+ if (retval)
+ goto sysfs_create_faied;
+
/* Register with OTG */
otg_handle = penwell_otg_register_bc_callback(msic_charger_callback,
(void *)mbi);
@@ -1976,6 +2076,8 @@ requestirq_failed:
penwell_otg_unregister_bc_callback(otg_handle);
ipc_read_failed:
otg_failed:
+ device_remove_file(&pdev->dev, &dev_attr_emrg_charge_enable);
+sysfs_create_faied:
power_supply_unregister(&mbi->usb);
power_reg_failed_usb:
power_supply_unregister(&mbi->batt);
@@ -2009,6 +2111,7 @@ static int msic_battery_remove(struct platform_device *pdev)
free_irq(mbi->irq, mbi);
if (mbi->msic_regs_iomap != NULL)
iounmap(mbi->msic_regs_iomap);
+ device_remove_file(&pdev->dev, &dev_attr_emrg_charge_enable);
power_supply_unregister(&mbi->usb);
power_supply_unregister(&mbi->batt);