diff options
author | Ramakrishna Pallala <ramakrishna.pallala@intel.com> | 2010-12-09 10:37:48 +0000 |
---|---|---|
committer | Alan Cox <alan@linux.intel.com> | 2010-12-09 10:37:48 +0000 |
commit | f1b855d5148ee7cb7ee78e688ffe8838c7cbf81e (patch) | |
tree | e3c84ce943ce2691679432ad93f36701c6d7439f /drivers/power/intel_mdf_battery.c | |
parent | ebe1c137340dc5f47d2b871e7eb81971d6ef7ec6 (diff) | |
download | mrst-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>
Diffstat (limited to 'drivers/power/intel_mdf_battery.c')
-rw-r--r-- | drivers/power/intel_mdf_battery.c | 103 |
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); |