diff options
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/Kconfig | 14 | ||||
-rw-r--r-- | drivers/power/Makefile | 2 | ||||
-rw-r--r-- | drivers/power/max17042_fuelgauge_px.c | 348 | ||||
-rw-r--r-- | drivers/power/max17042_fuelgauge_u1.c | 15 | ||||
-rw-r--r-- | drivers/power/max8922_charger_s2plus.c | 320 | ||||
-rw-r--r-- | drivers/power/power_supply_sysfs.c | 3 | ||||
-rw-r--r-- | drivers/power/sec_battery_px.c | 206 | ||||
-rw-r--r-- | drivers/power/sec_battery_u1.c | 93 | ||||
-rw-r--r--[-rwxr-xr-x] | drivers/power/smb347_charger.c | 0 |
9 files changed, 583 insertions, 418 deletions
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 9474894..5715075 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -241,12 +241,6 @@ config BATTERY_SAMSUNG help Say Y to enable support for batteries with samsung chip. -config BATTERY_SAMSUNG_S2PLUS - tristate "Fake battery driver for samsung s2plus boards" - depends on PLAT_SAMSUNG - help - Say Y to enable support for batteries with s2plus board. - config CHARGER_MAX8997 tristate "Maxim MAX8997/MAX8966 PMIC battery charger driver" depends on MFD_MAX8997 && REGULATOR_MAX8997 @@ -282,14 +276,6 @@ config CHARGER_MAX8922_U1 Say Y here to enable support for the battery charger in the Maxim MAX8922 Charger IC. -config CHARGER_MAX8922_S2PLUS - tristate "MAX8922 battery charger support for Samsung Galaxy S2 ICS upgrade" - depends on PLAT_SAMSUNG - default n - help - Say Y here to enable support for the battery charger in the Maxim - MAX8922 Charger IC. - config BATTERY_MAX17042_FUELGAUGE_U1 tristate "Maxim MAX17042/8997/8966 Fuel Gauge for Samsung Galaxy S2 ICS upgrade" depends on I2C diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 9be94fd..b33da76 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -37,11 +37,9 @@ obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o obj-$(CONFIG_BATTERY_SAMSUNG) += samsung_fake_battery.o -obj-$(CONFIG_BATTERY_SAMSUNG_S2PLUS) += samsung_fake_battery.o obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o obj-$(CONFIG_CHARGER_MAX8997_U1) += max8997_charger_u1.o obj-$(CONFIG_CHARGER_MAX8922_U1) += max8922_charger_u1.o -obj-$(CONFIG_CHARGER_MAX8922_S2PLUS) += max8922_charger_s2plus.o obj-$(CONFIG_CHARGER_MAX8997_PX) += max8997_charger_px.o ifeq ($(CONFIG_TARGET_LOCALE_KOR),y) obj-$(CONFIG_BATTERY_SEC_U1) += sec_battery_u1_kor.o diff --git a/drivers/power/max17042_fuelgauge_px.c b/drivers/power/max17042_fuelgauge_px.c index 6244f2b..b8f02cb 100644 --- a/drivers/power/max17042_fuelgauge_px.c +++ b/drivers/power/max17042_fuelgauge_px.c @@ -28,6 +28,9 @@ #include <linux/workqueue.h> #include <linux/rtc.h> #include <mach/gpio.h> +#if defined(CONFIG_TARGET_LOCALE_KOR) +#include <linux/power_supply.h> +#endif /* CONFIG_TARGET_LOCALE_KOR */ #include <linux/power/sec_battery_px.h> #include <linux/power/max17042_fuelgauge_px.h> @@ -136,11 +139,11 @@ void fg_write_and_verify_register(u8 addr, u16 w_data) } } -static void fg_test_print(void) +static void fg_debug_print(void) { struct i2c_client *client = fg_i2c_client; u8 data[2]; - u32 average_vcell; + u32 avg_v; u16 w_data; u32 temp; u32 temp2; @@ -154,19 +157,19 @@ static void fg_test_print(void) w_data = (data[1]<<8) | data[0]; temp = (w_data & 0xFFF) * 78125; - average_vcell = temp / 1000000; + avg_v = temp / 1000000; temp = ((w_data & 0xF000) >> 4) * 78125; temp2 = temp / 1000000; - average_vcell += (temp2 << 4); + avg_v += (temp2 << 4); fullcap = fg_read_register(FULLCAP_REG); remcap = fg_read_register(REMCAP_REP_REG); mixcap = fg_read_register(REMCAP_MIX_REG); avcap = fg_read_register(REMCAP_AV_REG); - pr_info("avg_vcell(%d), fullcap(%d), remcap(%d), mixcap(%d), avcap(%d)\n", - average_vcell, fullcap/2, remcap/2, mixcap/2, avcap/2); + pr_info("avg_v(%d), fullcap(%d), remcap(%d), mixcap(%d), avcap(%d)\n", + avg_v, (fullcap / 2), (remcap / 2), (mixcap / 2), (avcap / 2)); msleep(20); } @@ -221,8 +224,8 @@ static int fg_read_vcell(void) vcell += (temp2 << 4); if (!(chip->info.pr_cnt % PRINT_COUNT)) - pr_info("%s: VCELL(%d), data(0x%04x)\n", - __func__, vcell, (data[1]<<8) | data[0]); + pr_info("%s: vcell(%d, 0x%04x)\n", __func__, + vcell, (data[1]<<8) | data[0]); return vcell; } @@ -339,44 +342,49 @@ static int fg_read_temp(void) temper = 20000; if (!(chip->info.pr_cnt % PRINT_COUNT)) - pr_info("%s: TEMPERATURE(%d), data(0x%04x)\n", __func__, + pr_info("%s: temper(%d, 0x%04x)\n", __func__, temper, (data[1]<<8) | data[0]); return temper; } -static int fg_read_soc(void) +static int fg_read_vfsoc(void) { struct i2c_client *client = fg_i2c_client; - struct max17042_chip *chip = i2c_get_clientdata(client); u8 data[2]; - u32 soc = 0; - if (fg_i2c_read(client, SOCREP_REG, data, 2) < 0) { - pr_err("%s: Failed to read SOCREP\n", __func__); + if (fg_i2c_read(client, VFSOC_REG, data, 2) < 0) { + pr_err("%s: Failed to read VFSOC\n", __func__); return -1; } - soc = data[1]; - - if (!(chip->info.pr_cnt % PRINT_COUNT)) - pr_info("%s: SOC(%d), data(0x%04x)\n", __func__, - soc, (data[1]<<8) | data[0]); - - return soc; + return (int)data[1]; } -static int fg_read_vfsoc(void) +static int fg_read_soc(void) { struct i2c_client *client = fg_i2c_client; + struct max17042_chip *chip = i2c_get_clientdata(client); u8 data[2]; + u32 soc = 0; + u32 soc_lsb = 0; + int psoc = 0; - if (fg_i2c_read(client, VFSOC_REG, data, 2) < 0) { - pr_err("%s: Failed to read VFSOC\n", __func__); + if (fg_i2c_read(client, SOCREP_REG, data, 2) < 0) { + pr_err("%s: Failed to read SOCREP\n", __func__); return -1; } - return (int)data[1]; + soc_lsb = (data[0] * 100) / 256; + psoc = (data[1] * 100) + soc_lsb; + soc = psoc / 99; + chip->info.psoc = psoc; + + if (!(chip->info.pr_cnt % PRINT_COUNT)) + pr_info("%s: soc(%d), psoc(%d), vfsoc(%d)\n", __func__, + soc, psoc, fg_read_vfsoc()); + + return soc; } static int fg_read_current(void) @@ -421,10 +429,11 @@ static int fg_read_current(void) avg_current *= -1; if (!(chip->info.pr_cnt++ % PRINT_COUNT)) { - fg_test_print(); - pr_info("%s: CURRENT(%dmA), AVG_CURRENT(%dmA)\n", __func__, + pr_info("%s: curr(%d), avg_curr(%dmA)\n", __func__, i_current, avg_current); chip->info.pr_cnt = 1; + + fg_debug_print(); /* Read max17042's all registers every 5 minute. */ fg_periodic_read(); } @@ -590,8 +599,9 @@ void fg_low_batt_compensation(u32 level) void fg_periodic_read(void) { + u8 reg; int i; - u16 data[0x10]; + int data[0x10]; struct timespec ts; struct rtc_time tm; @@ -599,21 +609,21 @@ void fg_periodic_read(void) rtc_time_to_tm(ts.tv_sec, &tm); pr_info("[MAX17042] %d/%d/%d %02d:%02d,", - tm.tm_mday, tm.tm_mon + 1, tm.tm_year + 1900, tm.tm_hour, - tm.tm_min); + tm.tm_mday, tm.tm_mon + 1, tm.tm_year + 1900, + tm.tm_hour, tm.tm_min); for (i = 0; i < 16; i++) { - fg_read_16register(i, data); + for (reg = 0; reg < 0x10; reg++) + data[reg] = fg_read_register(reg + i * 0x10); - pr_info("%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,", + pr_info("%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,\n" + "%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,", data[0x00], data[0x01], data[0x02], data[0x03], - data[0x04], data[0x05], data[0x06], data[0x07]); - pr_info("%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,%04xh,", + data[0x04], data[0x05], data[0x06], data[0x07], data[0x08], data[0x09], data[0x0a], data[0x0b], data[0x0c], data[0x0d], data[0x0e], data[0x0f]); if (i == 4) i = 13; - msleep(20); } pr_info("\n"); @@ -1048,6 +1058,8 @@ static void display_low_batt_comp_cnt(void) sprintf(type_str, "SDI"); else if (fg_get_battery_type() == ATL_BATTERY_TYPE) sprintf(type_str, "ATL"); + else if (fg_get_battery_type() == BYD_BATTERY_TYPE) + sprintf(type_str, "BYD"); else sprintf(type_str, "Unknown"); @@ -1109,7 +1121,7 @@ void prevent_early_late_poweroff(int vcell, int *fg_soc) return; avg_vcell = fg_read_avg_vcell(); - pr_info("%s: soc=%d%%(0x%04x), vcell=%d avg_vcell=%d\n", + pr_info("%s: soc(%d%%(0x%04x)), v(%d), avg_v(%d)\n", __func__, repsoc, repsoc_data, vcell, avg_vcell); if (vcell > POWER_OFF_VOLTAGE_HIGH_MARGIN) { @@ -1118,8 +1130,8 @@ void prevent_early_late_poweroff(int vcell, int *fg_soc) fg_write_register(REMCAP_REP_REG, (u16)(read_val * 13 / 1000)); msleep(200); *fg_soc = fg_read_soc(); - pr_info("%s: new soc=%d, vcell=%d, avg_vcell=%d\n", - __func__, *fg_soc, vcell, avg_vcell); + pr_info("%s: 1.3%% case: new soc(%d), v(%d), avg_v(%d)\n", + __func__, *fg_soc, vcell, avg_vcell); } else if ((vcell < POWER_OFF_VOLTAGE_NOW_LOW_MARGIN) && (avg_vcell < POWER_OFF_VOLTAGE_AVG_LOW_MARGIN)) { read_val = fg_read_register(FULLCAP_REG); @@ -1127,8 +1139,8 @@ void prevent_early_late_poweroff(int vcell, int *fg_soc) fg_write_register(REMCAP_REP_REG, (u16)(read_val * 9 / 1000)); msleep(200); *fg_soc = fg_read_soc(); - pr_info("%s: new soc=%d, vcell=%d, avg_vcell=%d\n", - __func__, *fg_soc, vcell, avg_vcell); + pr_info("%s: 0%% case: new soc(%d), v(%d), avg_v(%d)\n", + __func__, *fg_soc, vcell, avg_vcell); } } @@ -1263,10 +1275,87 @@ static int get_low_batt_threshold(int range, int level, int nCurrent) break; } } +#if defined(CONFIG_MACH_P4NOTE) + else if (fg_get_battery_type() == BYD_BATTERY_TYPE) { + switch (range) { + case 5: + if (level == 1) + ret = BYD_Range5_1_Offset + \ + ((nCurrent * BYD_Range5_1_Slope) / 1000); + else if (level == 3) + ret = BYD_Range5_3_Offset + \ + ((nCurrent * BYD_Range5_3_Slope) / 1000); + break; + case 4: + if (level == 1) + ret = BYD_Range4_1_Offset + \ + ((nCurrent * BYD_Range4_1_Slope) / 1000); + else if (level == 3) + ret = BYD_Range4_3_Offset + \ + ((nCurrent * BYD_Range4_3_Slope) / 1000); + break; + + case 3: + if (level == 1) + ret = BYD_Range3_1_Offset + \ + ((nCurrent * BYD_Range3_1_Slope) / 1000); + else if (level == 3) + ret = BYD_Range3_3_Offset + \ + ((nCurrent * BYD_Range3_3_Slope) / 1000); + break; + + case 2: + if (level == 1) + ret = BYD_Range2_1_Offset + \ + ((nCurrent * BYD_Range2_1_Slope) / 1000); + else if (level == 3) + ret = BYD_Range2_3_Offset + \ + ((nCurrent * BYD_Range2_3_Slope) / 1000); + break; + case 1: + if (level == 1) + ret = BYD_Range1_1_Offset + \ + ((nCurrent * BYD_Range1_1_Slope) / 1000); + else if (level == 3) + ret = BYD_Range1_3_Offset + \ + ((nCurrent * BYD_Range1_3_Slope) / 1000); + break; + + default: + break; + } + } +#endif return ret; } +void fg_reset_fullcap_in_fullcharge(void) +{ + u32 fullCap = fg_read_register(FULLCAP_REG); + u32 remCapRep = fg_read_register(REMCAP_REP_REG); + if (!fullCap || !remCapRep) { + pr_err("%s: Possible i2c failure !!!\n", __func__); + return; + } + + pr_info("%s: FullCap(%d), RemCapRep(%d)\n", + __func__, + fullCap, + remCapRep); + + if (remCapRep < fullCap) { + /* Usually we need a delay of 100ms here for the + * RemCapRep to adjust to the new FullCap but + * here this call is being made in an interrupt where + * we already follow this call with a delay + * of 300ms, hence avoided. + */ + fg_write_register(FULLCAP_REG, remCapRep); + } + return; +} + int low_batt_compensation(int fg_soc, int fg_vcell, int fg_current) { struct i2c_client *client = fg_i2c_client; @@ -1411,6 +1500,9 @@ static void fg_set_battery_type(void) else if ((data == chip->pdata->atl_vfcapacity) || \ (data == chip->pdata->atl_vfcapacity-1)) chip->info.battery_type = ATL_BATTERY_TYPE; + else if ((data == chip->pdata->byd_vfcapacity) || \ + (data == chip->pdata->byd_vfcapacity-1)) + chip->info.battery_type = BYD_BATTERY_TYPE; else { pr_info("%s: Unknown battery is set to SDI type.\n", __func__); chip->info.battery_type = SDI_BATTERY_TYPE; @@ -1420,6 +1512,8 @@ static void fg_set_battery_type(void) sprintf(type_str, "SDI"); else if (chip->info.battery_type == ATL_BATTERY_TYPE) sprintf(type_str, "ATL"); + else if (chip->info.battery_type == BYD_BATTERY_TYPE) + sprintf(type_str, "BYD"); else sprintf(type_str, "Unknown"); @@ -1431,7 +1525,10 @@ static void fg_set_battery_type(void) chip->info.capacity = chip->pdata->atl_capacity; chip->info.vfcapacity = chip->pdata->atl_vfcapacity; break; - + case BYD_BATTERY_TYPE: + chip->info.capacity = chip->pdata->byd_capacity; + chip->info.vfcapacity = chip->pdata->byd_vfcapacity; + break; case SDI_BATTERY_TYPE: default: chip->info.capacity = chip->pdata->sdi_capacity; @@ -1447,6 +1544,9 @@ static void fg_set_battery_type(void) else if (chip->info.battery_type == ATL_BATTERY_TYPE) chip->info.check_start_vol = \ chip->pdata->atl_low_bat_comp_start_vol; + else if (chip->info.battery_type == BYD_BATTERY_TYPE) + chip->info.check_start_vol = \ + chip->pdata->byd_low_bat_comp_start_vol; } } @@ -1537,10 +1637,159 @@ static int fg_i2c_remove(struct i2c_client *client) return 0; } +#if defined(CONFIG_TARGET_LOCALE_KOR) +static int max17042_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; + break; + case POWER_SUPPLY_PROP_ONLINE: + val->intval = 1; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = get_fuelgauge_value(FG_VOLTAGE); + break; + case POWER_SUPPLY_PROP_CAPACITY: + val->intval = get_fuelgauge_value(FG_LEVEL); + break; + default: + return -EINVAL; + } + return 0; +} + +static enum power_supply_property max17042_battery_props[] = { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_CAPACITY, +}; + +static ssize_t max17042_show_property(struct device *dev, + struct device_attribute *attr, + char *buf); + +static ssize_t max17042_store_property(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); + +#define SEC_MAX17042_ATTR(_name) \ +{ \ + .attr = { .name = #_name, .mode = S_IRUGO | (S_IWUSR | S_IWGRP) }, \ + .show = max17042_show_property, \ + .store = max17042_store_property, \ +} + +static struct device_attribute sec_max17042_attrs[] = { + SEC_MAX17042_ATTR(fg_vfsoc), + SEC_MAX17042_ATTR(fg_vfocv), + SEC_MAX17042_ATTR(fg_filtercfg), + SEC_MAX17042_ATTR(fg_cgain), +}; + +enum { + MAX17042_VFSOC = 0, + MAX17042_VFOCV, + MAX17042_FILTERCFG, + MAX17042_CGAIN, +}; + +static ssize_t max17042_show_property(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct power_supply *psy = dev_get_drvdata(dev); + struct max17042_chip *chip = container_of(psy, + struct max17042_chip, + battery); + int i = 0; + const ptrdiff_t off = attr - sec_max17042_attrs; + int val; + + switch (off) { + case MAX17042_VFSOC: + val = fg_read_register(VFSOC_REG); + val = val >> 8; /* % */ + if (val >= 0) + i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", val); + else + i = -EINVAL; + break; + case MAX17042_VFOCV: + val = fg_read_register(VFOCV_REG); + val = ((val >> 3) * 625) / 1000; /* mV */ + if (val >= 0) + i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", val); + else + i = -EINVAL; + break; + case MAX17042_FILTERCFG: + val = fg_read_register(FILTERCFG_REG); + if (val >= 0) + i += scnprintf(buf + i, PAGE_SIZE - i, "0x%x\n", val); + else + i = -EINVAL; + break; + case MAX17042_CGAIN: + val = fg_read_register(CGAIN_REG); + if (val >= 0) + i += scnprintf(buf + i, PAGE_SIZE - i, + "0x%x, PSOC: %d\n", val, chip->info.psoc); + else + i = -EINVAL; + break; + default: + i = -EINVAL; + break; + } + + return i; +} + +static ssize_t max17042_store_property(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret = 0; + const ptrdiff_t off = attr - sec_max17042_attrs; + + switch (off) { + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int max17042_create_attrs(struct device *dev) +{ + int i, rc; + + for (i = 0; i < ARRAY_SIZE(sec_max17042_attrs); i++) { + rc = device_create_file(dev, &sec_max17042_attrs[i]); + if (rc) + goto max17042_attrs_failed; + } + goto succeed; + +max17042_attrs_failed: + while (i--) + device_remove_file(dev, &sec_max17042_attrs[i]); +succeed: + return rc; +} +#endif /* CONFIG_TARGET_LOCALE_KOR */ + static int fg_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct max17042_chip *chip; +#if defined(CONFIG_TARGET_LOCALE_KOR) + int ret = 0; +#endif /* CONFIG_TARGET_LOCALE_KOR */ if (!client->dev.platform_data) { pr_err("%s: No platform data\n", __func__); @@ -1585,6 +1834,23 @@ fg_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) fg_alert_init(); fg_read_model_data(); fg_periodic_read(); + +#if defined(CONFIG_TARGET_LOCALE_KOR) + chip->battery.name = "fuelgauge"; + chip->battery.type = POWER_SUPPLY_TYPE_BATTERY; + chip->battery.get_property = max17042_get_property; + chip->battery.properties = max17042_battery_props; + chip->battery.num_properties = ARRAY_SIZE(max17042_battery_props); + ret = power_supply_register(&client->dev, &chip->battery); + if (ret) { + pr_err("%s : failed to regist fuel_gauge(ret = %d)\n", + __func__, ret); + kfree(chip); + return ret; + } + + max17042_create_attrs(chip->battery.dev); +#endif /* CONFIG_TARGET_LOCALE_KOR */ return 0; } diff --git a/drivers/power/max17042_fuelgauge_u1.c b/drivers/power/max17042_fuelgauge_u1.c index 1434c72..39b931c 100644 --- a/drivers/power/max17042_fuelgauge_u1.c +++ b/drivers/power/max17042_fuelgauge_u1.c @@ -337,9 +337,10 @@ static void max17042_get_soc(struct i2c_client *client) if (chip->is_enable) { if (max17042_read_reg(client, MAX17042_REG_SOC_VF, data) < 0) return; +#ifndef PRODUCT_SHIP dev_info(&chip->client->dev, "%s : soc(%02x%02x)\n", __func__, data[1], data[0]); - +#endif soc = (data[1] * 100) + (data[0] * 100 / 256); chip->raw_soc = min(soc / 100, 100); @@ -398,7 +399,7 @@ static void max17042_get_soc(struct i2c_client *client) /*raw 1.6% ~ 97.6% */ soc = (soc > 100) ? ((soc - 60) * 100 / 9700) : 0; /*raw 1.5% ~ 95% */ - /*soc = (soc < 150) ? 0 : ((soc - 150) * 100 / 9350) + 1; */ + /*soc = (soc < 150) ? 0 : ((soc - 150) * 100 / 9350) + 1; */ } #else /* adjusted soc by adding 0.45 */ @@ -412,8 +413,10 @@ static void max17042_get_soc(struct i2c_client *client) chip->soc = soc; +#ifndef PRODUCT_SHIP dev_info(&client->dev, "%s : use raw (%d), soc (%d)\n", __func__, chip->raw_soc, soc); +#endif } static void max17042_get_temperature(struct i2c_client *client) @@ -423,7 +426,8 @@ static void max17042_get_temperature(struct i2c_client *client) s32 temper = 0; if (chip->is_enable) { - if (max17042_read_reg(client, MAX17042_REG_TEMPERATURE, data) < 0) + if (max17042_read_reg(client, + MAX17042_REG_TEMPERATURE, data) < 0) return; /* data[] store 2's compliment format number */ @@ -513,7 +517,7 @@ static void max17042_work(struct work_struct *work) dev_info(&chip->client->dev, "fuel alert already activated (raw:%d)\n", chip->raw_soc); - } else if (chip->raw_soc == chip->fuel_alert_soc) { + } else if (chip->raw_soc >= chip->fuel_alert_soc) { if (chip->is_fuel_alerted) { wake_unlock(&chip->fuel_alert_wake_lock); chip->is_fuel_alerted = false; @@ -629,7 +633,8 @@ static ssize_t sec_fg_store(struct device *dev, union power_supply_propval value; if (!psy) { - pr_err("%s: fail to get battery ps\n", __func__); + pr_err("%s: fail to get battery ps\n", + __func__); return -ENODEV; } diff --git a/drivers/power/max8922_charger_s2plus.c b/drivers/power/max8922_charger_s2plus.c deleted file mode 100644 index 86b8af7..0000000 --- a/drivers/power/max8922_charger_s2plus.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * max8922-charger.c - * MAXIM 8922 charger interface driver - * - * Copyright (C) 2011 Samsung Electronics - * - * <ms925.kim@samsung.com> - * - * Copyright (C) 2012 Samsung Electronics - * Jaecheol kim <jc22.kim@samsung.com> - * - * modify S2PLUS usb charger based on max8922_charger_u1.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/err.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/delay.h> -#include <linux/power_supply.h> -#include <linux/power/max8922_charger_u1.h> -#include <linux/battery/samsung_battery.h> - -struct max8922_info { - struct device *dev; - struct power_supply psy_bat; - struct max8922_platform_data *pdata; - bool is_usb_cable; - int irq_chg_ing; -}; - -static enum power_supply_property max8922_battery_props[] = { - POWER_SUPPLY_PROP_STATUS, - POWER_SUPPLY_PROP_ONLINE, -}; - -static inline int max8922_is_charging(struct max8922_info *info) -{ - int ta_nconnected = gpio_get_value(info->pdata->gpio_ta_nconnected); - int chg_ing = gpio_get_value(info->pdata->gpio_chg_ing); - - dev_info(info->dev, "%s: charging state = 0x%x\n", __func__, - (ta_nconnected << 1) | chg_ing); - - /*return (ta_nconnected == 0 && chg_ing == 0); */ - return (ta_nconnected << 1) | chg_ing; -} - -static int max8922_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct max8922_info *info = - container_of(psy, struct max8922_info, psy_bat); - - switch (psp) { - case POWER_SUPPLY_PROP_STATUS: - switch (max8922_is_charging(info)) { - case 0: - val->intval = POWER_SUPPLY_STATUS_CHARGING; - break; - case 1: - val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; - break; - default: - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; - break; - } - break; - case POWER_SUPPLY_PROP_ONLINE: - /* battery is always online */ - val->intval = 1; - break; - default: - return -EINVAL; - } - return 0; -} - -static int max8922_enable_charging(struct max8922_info *info, bool enable) -{ - int gpio_chg_en = info->pdata->gpio_chg_en; - unsigned long flags; - - dev_info(info->dev, "%s: %s charging,%s\n", __func__, - enable ? "enable" : "disable", - info->is_usb_cable ? "USB" : "TA"); - - if (enable) { - if (info->is_usb_cable) { - /* Charging by USB cable */ - gpio_direction_output(gpio_chg_en, GPIO_LEVEL_HIGH); - } else { - /* Charging by TA cable */ - gpio_direction_output(gpio_chg_en, GPIO_LEVEL_HIGH); - mdelay(5); - - local_irq_save(flags); - gpio_direction_output(gpio_chg_en, GPIO_LEVEL_LOW); - udelay(300); - gpio_direction_output(gpio_chg_en, GPIO_LEVEL_HIGH); - local_irq_restore(flags); - } - } else - gpio_direction_output(gpio_chg_en, GPIO_LEVEL_LOW); - - msleep(300); - return max8922_is_charging(info); -} - -static int max8922_set_property(struct power_supply *psy, - enum power_supply_property psp, - const union power_supply_propval *val) -{ - struct max8922_info *info = - container_of(psy, struct max8922_info, psy_bat); - bool enable; - - switch (psp) { - case POWER_SUPPLY_PROP_CURRENT_NOW: /* Set charging current */ - info->is_usb_cable = (val->intval <= CHARGER_USB_CURRENT); - break; - case POWER_SUPPLY_PROP_STATUS: /* Enable/Disable charging */ - enable = (val->intval == POWER_SUPPLY_STATUS_CHARGING); - max8922_enable_charging(info, enable); - break; - default: - return -EINVAL; - } - return 0; -} - -static irqreturn_t max8922_chg_ing_irq(int irq, void *data) -{ - struct max8922_info *info = data; - int ret = 0; - - dev_info(info->dev, "chg_ing IRQ occurred!\n"); - - if (gpio_get_value(info->pdata->gpio_ta_nconnected)) - return IRQ_HANDLED; - - if (info->pdata->topoff_cb) - ret = info->pdata->topoff_cb(); - - if (ret) { - dev_err(info->dev, "%s: error from topoff_cb(%d)\n", __func__, - ret); - return IRQ_HANDLED; - } - - return IRQ_HANDLED; -} - -static __devinit int max8922_probe(struct platform_device *pdev) -{ - struct max8922_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct max8922_info *info; - int ret; - - dev_info(&pdev->dev, "%s : MAX8922 Charger Driver Loading\n", __func__); - - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - platform_set_drvdata(pdev, info); - - info->dev = &pdev->dev; - info->pdata = pdata; - - info->psy_bat.name = "max8922-charger", - info->psy_bat.type = POWER_SUPPLY_TYPE_BATTERY, - info->psy_bat.properties = max8922_battery_props, - info->psy_bat.num_properties = ARRAY_SIZE(max8922_battery_props), - info->psy_bat.get_property = max8922_get_property, - info->psy_bat.set_property = max8922_set_property, - ret = power_supply_register(&pdev->dev, &info->psy_bat); - if (ret) { - dev_err(info->dev, "Failed to register psy_bat\n"); - goto err_kfree; - } - - if (pdata->cfg_gpio) { - ret = pdata->cfg_gpio(); - if (ret) { - dev_err(info->dev, "failed to configure GPIO\n"); - goto err_kfree; - } - } - - if (gpio_is_valid(pdata->gpio_chg_en)) { - if (!pdata->gpio_chg_en) { - dev_err(info->dev, "gpio_chg_en defined as 0\n"); - WARN_ON(!pdata->gpio_chg_en); - ret = -EIO; - goto err_kfree; - } - gpio_request(pdata->gpio_chg_en, "MAX8922 CHG_EN"); - } - - if (gpio_is_valid(pdata->gpio_chg_ing)) { - if (!pdata->gpio_chg_ing) { - dev_err(info->dev, "gpio_chg_ing defined as 0\n"); - WARN_ON(!pdata->gpio_chg_ing); - ret = -EIO; - goto err_kfree; - } - gpio_request(pdata->gpio_chg_ing, "MAX8922 CHG_ING"); - } - - if (gpio_is_valid(pdata->gpio_ta_nconnected)) { - if (!pdata->gpio_ta_nconnected) { - dev_err(info->dev, "gpio_ta_nconnected defined as 0\n"); - WARN_ON(!pdata->gpio_ta_nconnected); - ret = -EIO; - goto err_kfree; - } - gpio_request(pdata->gpio_ta_nconnected, - "MAX8922 TA_nCONNECTED"); - } -#if 0 - info->irq_chg_ing = gpio_to_irq(pdata->gpio_chg_ing); - - ret = request_threaded_irq(info->irq_chg_ing, NULL, - max8922_chg_ing_irq, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - "chg_ing", info); - if (ret) - dev_err(&pdev->dev, "%s: fail to request chg_ing IRQ:" - " %d: %d\n", __func__, info->irq_chg_ing, ret); -#endif - - return 0; -err_kfree: - power_supply_unregister(&info->psy_bat); - platform_set_drvdata(pdev, NULL); - kfree(info); - return ret; -} - -static int __devexit max8922_remove(struct platform_device *pdev) -{ - struct max8922_info *info = platform_get_drvdata(pdev); - - power_supply_unregister(&info->psy_bat); - - gpio_free(info->pdata->gpio_chg_en); - gpio_free(info->pdata->gpio_chg_ing); - gpio_free(info->pdata->gpio_ta_nconnected); - - kfree(info); - - return 0; -} - -#ifdef CONFIG_PM -static int max8922_suspend(struct device *dev) -{ - struct max8922_info *info = dev_get_drvdata(dev); - - if (info && info->irq_chg_ing) - disable_irq(info->irq_chg_ing); - - return 0; -} - -static int max8922_resume(struct device *dev) -{ - struct max8922_info *info = dev_get_drvdata(dev); - - if (info && info->irq_chg_ing) - enable_irq(info->irq_chg_ing); - - return 0; -} -#else -#define max8922_charger_suspend NULL -#define max8922_charger_resume NULL -#endif - -static const struct dev_pm_ops max8922_pm_ops = { - .suspend = max8922_suspend, - .resume = max8922_resume, -}; - -static struct platform_driver max8922_driver = { - .driver = { - .name = "max8922-charger", - .owner = THIS_MODULE, - .pm = &max8922_pm_ops, - }, - .probe = max8922_probe, - .remove = __devexit_p(max8922_remove), -}; - -static int __init max8922_init(void) -{ - return platform_driver_register(&max8922_driver); -} - -static void __exit max8922_exit(void) -{ - platform_driver_register(&max8922_driver); -} - -module_init(max8922_init); -module_exit(max8922_exit); - -MODULE_DESCRIPTION("MAXIM 8922 charger control driver"); -MODULE_AUTHOR("<ms925.kim@samsung.com>"); -MODULE_LICENSE("GPL"); diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 605514a..009e905 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -158,6 +158,9 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(energy_now), POWER_SUPPLY_ATTR(energy_avg), POWER_SUPPLY_ATTR(capacity), +#ifdef CONFIG_SLP + POWER_SUPPLY_ATTR(capacity_raw), +#endif POWER_SUPPLY_ATTR(capacity_level), POWER_SUPPLY_ATTR(temp), POWER_SUPPLY_ATTR(temp_ambient), diff --git a/drivers/power/sec_battery_px.c b/drivers/power/sec_battery_px.c index 0b5d8d4..4787c9d 100644 --- a/drivers/power/sec_battery_px.c +++ b/drivers/power/sec_battery_px.c @@ -33,13 +33,18 @@ #include <linux/power/sec_battery_px.h> #include <linux/power/max17042_fuelgauge_px.h> #include <linux/mfd/max8997.h> - +#if defined(CONFIG_TARGET_LOCALE_KOR) +#include <linux/proc_fs.h> +#endif /* CONFIG_TARGET_LOCALE_KOR */ #include <plat/adc.h> #include <mach/usb_switch.h> #define FAST_POLL 40 /* 40 sec */ #define SLOW_POLL (30*60) /* 30 min */ +/* cut off voltage */ +#define MAX_CUT_OFF_VOL 3500 + /* SIOP */ #define CHARGING_CURRENT_HIGH_LOW_STANDARD 450 #define CHARGING_CURRENT_USB 500 @@ -67,11 +72,16 @@ static char *supply_list[] = { "battery", }; +/* Get LP charging mode state */ +unsigned int lpcharge; + static enum power_supply_property sec_battery_properties[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CURRENT_AVG, POWER_SUPPLY_PROP_CAPACITY, }; @@ -95,6 +105,11 @@ struct battery_info { u32 batt_improper_ta; /* 1: improper ta */ u32 abstimer_is_active; /* 0 : Not active 1: Active */ u32 siop_activated; /* 0 : Not active 1: Active */ +#if defined(CONFIG_TARGET_LOCALE_KOR) + u32 batt_vfsoc; + u32 batt_soc; +#endif /* CONFIG_TARGET_LOCALE_KOR */ + u32 batt_current_avg; }; struct battery_data { @@ -123,6 +138,9 @@ struct battery_data { #ifdef __TEST_DEVICE_DRIVER__ struct wake_lock wake_lock_for_dev; #endif /* __TEST_DEVICE_DRIVER__ */ +#if defined(CONFIG_TARGET_LOCALE_KOR) + struct proc_dir_entry *entry; +#endif /* CONFIG_TARGET_LOCALE_KOR */ enum charger_type current_cable_status; enum charger_type previous_cable_status; int present; @@ -146,6 +164,7 @@ struct battery_data { /* 0:Default, 1:Only charger, 2:Only PMIC */ int cable_detect_source; int pmic_cable_state; + int dock_type; bool is_low_batt_alarm; }; @@ -174,6 +193,7 @@ static int bat_temp_force_state; static bool check_UV_charging_case(void); static void sec_bat_status_update(struct power_supply *bat_ps); +static void fullcharge_discharge_comp(struct battery_data *battery); static int get_cached_charging_status(struct battery_data *battery) { @@ -226,7 +246,7 @@ static int check_ta_conn(struct battery_data *battery) #ifdef CONFIG_SAMSUNG_LPM_MODE static void lpm_mode_check(struct battery_data *battery) { - battery->charging_mode_booting = \ + battery->charging_mode_booting = lpcharge = battery->pdata->check_lp_charging_boot(); pr_info("%s : charging_mode_booting(%d)\n", __func__, battery->charging_mode_booting); @@ -292,7 +312,7 @@ enum charger_type sec_get_dedicted_charger_type(struct battery_data *battery) mutex_lock(&battery->work_lock); /* ADC check margin (300~500ms) */ - msleep(150); + msleep(300); usb_switch_lock(); usb_switch_set_path(USB_PATH_ADCCHECK); @@ -318,10 +338,13 @@ enum charger_type sec_get_dedicted_charger_type(struct battery_data *battery) battery->pdata->charger.accessory_line); pr_info("%s: accessory line(%d)\n", __func__, accessory_line); - if (accessory_line == 0) /* HDMI dock cable connected*/ + if (battery->dock_type == DOCK_DESK) { + pr_info("%s: deskdock(%d) charging\n", + __func__, battery->dock_type); result = CHARGER_DOCK; - else + } else { result = CHARGER_AC; + } #else result = CHARGER_AC; /* TA connected. */ #endif @@ -369,6 +392,9 @@ static void sec_TA_work_handler(struct work_struct *work) /* Prevent unstable VBUS signal from PC */ ta_state = check_ta_conn(battery); if (ta_state == 0) { + /* Check for immediate discharge after fullcharge */ + fullcharge_discharge_comp(battery); + msleep(TA_DISCONNECT_RECHECK_TIME); if (ta_state != check_ta_conn(battery)) { pr_info("%s: unstable ta_state(%d), ignore it.\n", @@ -456,6 +482,29 @@ static int is_over_abs_time(struct battery_data *battery) return 0; } +/* fullcharge_discharge_comp: During the small window between + * Full Charge and Recharge if the cable is connected , we always show + * 100% SOC to the UI , evven though in background its discharging. + * If the user pulls out the TA in between this small window he should + * see a sudden drop from 100% to a disacharged state of 95% - 98%. + * We fake the SOC on Fulll cap and let FG manage the differences on + * long run. + * Also during the start of recharging phase if the TA is disconnected SOC + * can sudden;y drop down to a lower value. In that case also the user + * expects to see a 100% so we update Full Cap again. +*/ +static void fullcharge_discharge_comp(struct battery_data *battery) +{ + int fg_vcell = get_fuelgauge_value(FG_VOLTAGE); + + if (battery->info.batt_is_full) { + pr_info("%s: Resetting FULLCAP !!\n", __func__); + fg_reset_fullcap_in_fullcharge(); + } + + return; +} + static int sec_get_bat_level(struct power_supply *bat_ps) { struct battery_data *battery = container_of(bat_ps, @@ -476,6 +525,9 @@ static int sec_get_bat_level(struct power_supply *bat_ps) } fg_soc = get_fuelgauge_value(FG_LEVEL); +#if defined(CONFIG_TARGET_LOCALE_KOR) + battery->info.batt_soc = fg_soc; +#endif /* CONFIG_TARGET_LOCALE_KOR */ if (fg_soc < 0) { pr_info("Can't read soc!!!"); fg_soc = battery->info.level; @@ -523,6 +575,10 @@ static int sec_get_bat_level(struct power_supply *bat_ps) battery->info.batt_current = fg_current; avg_current = get_fuelgauge_value(FG_CURRENT_AVG); fg_vfsoc = get_fuelgauge_value(FG_VF_SOC); +#if defined(CONFIG_TARGET_LOCALE_KOR) + battery->info.batt_vfsoc = fg_vfsoc; +#endif /* CONFIG_TARGET_LOCALE_KOR */ + battery->info.batt_current_avg = avg_current; /* P4-Creative does not set full flag by force */ #if !defined(CONFIG_MACH_P4NOTE) @@ -992,8 +1048,7 @@ static int sec_bat_get_charging_status(struct battery_data *battery) case CHARGER_AC: case CHARGER_MISC: case CHARGER_DOCK: - if (battery->info.batt_is_full || - battery->info.level == 100) + if (battery->info.batt_is_full) return POWER_SUPPLY_STATUS_FULL; else if (battery->info.batt_improper_ta) return POWER_SUPPLY_STATUS_DISCHARGING; @@ -1015,6 +1070,15 @@ static int sec_bat_set_property(struct power_supply *ps, switch (psp) { case POWER_SUPPLY_PROP_ONLINE: +#if defined(CONFIG_MACH_P4NOTE) + battery->dock_type = val->intval; + pr_info("dock type(%d)\n", battery->dock_type); + /* if need current update state, set */ + if (battery->dock_type == DOCK_DESK) { + sec_get_cable_status(battery); + sec_cable_changed(battery); + } +#else battery->pmic_cable_state = val->intval; pr_info("PMIC cable state: %d\n", battery->pmic_cable_state); if (battery->cable_detect_source == 2) { @@ -1024,6 +1088,7 @@ static int sec_bat_set_property(struct power_supply *ps, sec_cable_changed(battery); } battery->cable_detect_source = 0; +#endif break; default: return -EINVAL; @@ -1052,8 +1117,25 @@ static int sec_bat_get_property(struct power_supply *bat_ps, case POWER_SUPPLY_PROP_TECHNOLOGY: val->intval = POWER_SUPPLY_TECHNOLOGY_LION; break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + val->intval = battery->info.batt_current; + break; + case POWER_SUPPLY_PROP_CURRENT_AVG: + val->intval = battery->info.batt_current_avg; + break; case POWER_SUPPLY_PROP_CAPACITY: +#if defined(CONFIG_MACH_P4NOTE) + if ((battery->info.level == 0) && + (battery->info.batt_vol > MAX_CUT_OFF_VOL)) { + pr_info("%s: mismatch power off soc(%d) and vol(%d)\n", + __func__, battery->info.level, battery->info.batt_vol); + val->intval = battery->info.level = 1; + } else { + val->intval = battery->info.level; + } +#else val->intval = battery->info.level; +#endif pr_info("level = %d\n", val->intval); break; case POWER_SUPPLY_PROP_TEMP: @@ -1143,6 +1225,13 @@ static struct device_attribute sec_battery_attrs[] = { #endif SEC_BATTERY_ATTR(jig_on), SEC_BATTERY_ATTR(fg_capacity), + SEC_BATTERY_ATTR(update), +#if defined(CONFIG_TARGET_LOCALE_KOR) + SEC_BATTERY_ATTR(batt_sysrev), + SEC_BATTERY_ATTR(batt_temp_adc_spec), + SEC_BATTERY_ATTR(batt_current_adc), + SEC_BATTERY_ATTR(batt_current_avg), +#endif /* CONFIG_TARGET_LOCALE_KOR */ }; enum { @@ -1167,6 +1256,13 @@ enum { #endif JIG_ON, FG_CAPACITY, + UPDATE, +#if defined(CONFIG_TARGET_LOCALE_KOR) + BATT_SYSTEM_REVISION, + BATT_TEMP_ADC_SPEC, + BATT_CURRENT_ADC, + BATT_CURRENT_AVG, +#endif /* CONFIG_TARGET_LOCALE_KOR */ }; static int sec_bat_create_attrs(struct device *dev) @@ -1268,6 +1364,28 @@ static ssize_t sec_bat_show_property(struct device *dev, get_fuelgauge_capacity(CAPACITY_TYPE_AV), get_fuelgauge_capacity(CAPACITY_TYPE_REP)); break; +#if defined(CONFIG_TARGET_LOCALE_KOR) + case BATT_SYSTEM_REVISION: + i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", + system_rev); + break; + case BATT_TEMP_ADC_SPEC: + i += scnprintf(buf + i, PAGE_SIZE - i, + "(HIGH: %d / %d,\tLOW: %d / %d)\n", + debug_batterydata->pdata->temp_high_threshold / 100, + debug_batterydata->pdata->temp_high_recovery / 100, + debug_batterydata->pdata->temp_low_threshold / 100, + debug_batterydata->pdata->temp_low_recovery / 100); + break; + case BATT_CURRENT_ADC: + i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", + get_fuelgauge_value(FG_CURRENT)); + break; + case BATT_CURRENT_AVG: + i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", + get_fuelgauge_value(FG_CURRENT_AVG)); + break; +#endif /* CONFIG_TARGET_LOCALE_KOR */ default: i = -EINVAL; } @@ -1334,6 +1452,12 @@ static ssize_t sec_bat_store(struct device *dev, } pr_info("%s: SIOP_ACTIVATED :%d\n", __func__, x); break; + case UPDATE: + pr_info("%s: battery update\n", __func__); + wake_lock(&debug_batterydata->work_wake_lock); + schedule_work(&debug_batterydata->battery_work); + ret = count; + break; #ifdef CONFIG_SAMSUNG_LPM_MODE case BATT_LP_CHARGING: if (sscanf(buf, "%d\n", &x) == 1) { @@ -1503,8 +1627,6 @@ static int sec_cable_status_update(struct battery_data *battery, int status) wake_lock(&battery->work_wake_lock); schedule_work(&battery->battery_work); - pr_debug("call power_supply_changed "); - return ret; } @@ -1543,10 +1665,12 @@ static void sec_bat_status_update(struct power_supply *bat_ps) power_supply_changed(bat_ps); pr_debug("call power_supply_changed"); - pr_info("BAT : soc(%d), vcell(%dmV), curr(%dmA), temp(%d.%d), chg(%d)", + pr_info("BAT : soc(%d), vcell(%dmV), curr(%dmA), " + "avg curr(%dmA), temp(%d.%d), chg(%d)", battery->info.level, battery->info.batt_vol, battery->info.batt_current, + battery->info.batt_current_avg, battery->info.batt_temp/10, battery->info.batt_temp%10, battery->info.charging_enabled); @@ -1723,17 +1847,15 @@ void fuelgauge_recovery_handler(struct work_struct *work) if (battery->info.level > 0) { pr_err("%s: Reduce the Reported SOC by 1 unit, wait for 30s\n", - __func__); + __func__); if (!battery->info.charging_enabled) wake_lock_timeout(&battery->vbus_wake_lock, HZ); current_soc = get_fuelgauge_value(FG_LEVEL); if (current_soc) { pr_info("%s: Returning to Normal discharge path.\n", __func__); - pr_info(" Actual SOC(%d) non-zero.\n", - current_soc); + pr_info(" Actual SOC(%d) non-zero.\n", current_soc); battery->is_low_batt_alarm = false; - return; } else { battery->info.level--; pr_err("%s: New Reduced Reported SOC (%d).\n", @@ -1745,12 +1867,22 @@ void fuelgauge_recovery_handler(struct work_struct *work) } } else { if (!get_charger_status(battery)) { - pr_err("Set battery level as 0, power off.\n"); + pr_err("%s: 0%% wo/ charging, will be power off\n", + __func__); battery->info.level = 0; wake_lock_timeout(&battery->vbus_wake_lock, HZ); power_supply_changed(&battery->psy_battery); + } else { + pr_info("%s: 0%% w/ charging, exit low bat alarm\n", + __func__); + /* finish low battery alarm state */ + battery->is_low_batt_alarm = false; } } + + pr_info("%s: low batt alarm(%d)\n", __func__, + battery->is_low_batt_alarm); + return; } #define STABLE_LOW_BATTERY_DIFF 3 @@ -1759,6 +1891,7 @@ int _low_battery_alarm_(struct battery_data *battery) { int overcurrent_limit_in_soc; int current_soc = get_fuelgauge_value(FG_LEVEL); + pr_info("%s\n", __func__); if (battery->info.level <= STABLE_LOW_BATTERY_DIFF) overcurrent_limit_in_soc = STABLE_LOW_BATTERY_DIFF_LOWBATT; @@ -1881,6 +2014,39 @@ static void fullcharging_work_handler(struct work_struct *work) enable_irq(battery->charging_irq); } +#if defined(CONFIG_TARGET_LOCALE_KOR) +static int sec_bat_read_proc(char *buf, char **start, + off_t offset, int count, int *eof, void *data) +{ + struct battery_data *battery = data; + struct timespec cur_time; + ktime_t ktime; + int len = 0; + + ktime = alarm_get_elapsed_realtime(); + cur_time = ktime_to_timespec(ktime); + + len = sprintf(buf, + "%lu\t%u\t%u\t%u\t%u\t%u\t%u\t%d\t%d\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t0x%04x\t0x%04x\n", + cur_time.tv_sec, + battery->info.batt_vol, battery->info.level, + battery->info.batt_soc, battery->info.batt_vfsoc, + max17042_chip_data->info.psoc, + battery->info.batt_temp, + battery->info.batt_current, battery->info.batt_current_avg, + battery->info.charging_source, battery->info.batt_improper_ta, + battery->info.charging_enabled, battery->info.charging_current, + sec_bat_get_charging_status(battery), battery->info.batt_health, + battery->info.batt_is_full, battery->info.batt_is_recharging, + battery->info.abstimer_is_active, battery->info.siop_activated, + get_fuelgauge_capacity(CAPACITY_TYPE_FULL), + get_fuelgauge_capacity(CAPACITY_TYPE_REP) + ); + + return len; +} +#endif /* CONFIG_TARGET_LOCALE_KOR */ + static int __devinit sec_bat_probe(struct platform_device *pdev) { struct sec_battery_platform_data *pdata = dev_get_platdata(&pdev->dev); @@ -2063,6 +2229,16 @@ static int __devinit sec_bat_probe(struct platform_device *pdev) lpm_mode_check(battery); #endif +#if defined(CONFIG_TARGET_LOCALE_KOR) + battery->entry = create_proc_entry("batt_info_proc", S_IRUGO, NULL); + if (!battery->entry) { + pr_err("%s : failed to create proc_entry!\n", __func__); + } else { + battery->entry->read_proc = sec_bat_read_proc; + battery->entry->data = battery; + } +#endif /* CONFIG_TARGET_LOCALE_KOR */ + return 0; err_charger_irq: diff --git a/drivers/power/sec_battery_u1.c b/drivers/power/sec_battery_u1.c index a442251..3dcd150 100644 --- a/drivers/power/sec_battery_u1.c +++ b/drivers/power/sec_battery_u1.c @@ -39,8 +39,13 @@ #if defined(CONFIG_TARGET_LOCALE_NAATT) #define VF_CHECK_INTERVAL (5 * 1000) +#if defined(CONFIG_MACH_U1_NA_SPR) || defined(CONFIG_MACH_U1_NA_USCC) +#define MAX_VF 1500 +#define MIN_VF 1350 +#else #define MAX_VF 1800 #define MIN_VF 1100 +#endif #define VF_COUNT 1 #elif defined(CONFIG_MACH_Q1_BD) #define VF_CHECK_INTERVAL (5 * 1000) @@ -126,6 +131,17 @@ #define LOW_BLOCK_TEMP_ADC_LPM 521 #define HIGH_RECOVER_TEMP_ADC_LPM 714 #define LOW_RECOVER_TEMP_ADC_LPM 522 +#elif defined(CONFIG_MACH_U1_NA_USCC) +#define EVENT_BLOCK_TEMP_ADC 770 +#define HIGH_BLOCK_TEMP_ADC 770 +#define LOW_BLOCK_TEMP_ADC 502 +#define HIGH_RECOVER_TEMP_ADC 699 +#define LOW_RECOVER_TEMP_ADC 516 + +#define HIGH_BLOCK_TEMP_ADC_LPM 710 +#define LOW_BLOCK_TEMP_ADC_LPM 506 +#define HIGH_RECOVER_TEMP_ADC_LPM 702 +#define LOW_RECOVER_TEMP_ADC_LPM 512 #else #define EVENT_BLOCK_TEMP_ADC 777 #define HIGH_BLOCK_TEMP_ADC 729 @@ -367,6 +383,10 @@ static enum power_supply_property sec_battery_props[] = { POWER_SUPPLY_PROP_TECHNOLOGY, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CAPACITY, +#ifdef CONFIG_SLP + POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_CHARGE_FULL, +#endif POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_CURRENT_AVG, }; @@ -492,6 +512,20 @@ static int sec_bat_get_property(struct power_supply *ps, if (val->intval == -1) return -EINVAL; break; +#ifdef CONFIG_SLP + case POWER_SUPPLY_PROP_CHARGE_FULL: + if (info->charging_status == POWER_SUPPLY_STATUS_FULL) + val->intval = true; + else + val->intval = false; + break; + case POWER_SUPPLY_PROP_CHARGE_NOW: + if (info->charging_status == POWER_SUPPLY_STATUS_CHARGING) + val->intval = true; + else + val->intval = false; + break; +#endif case POWER_SUPPLY_PROP_CAPACITY: #ifdef CONFIG_TARGET_LOCALE_NA if (info->charging_status != POWER_SUPPLY_STATUS_FULL @@ -513,7 +547,7 @@ static int sec_bat_get_property(struct power_supply *ps, val->intval = POWER_SUPPLY_TECHNOLOGY_LION; break; case POWER_SUPPLY_PROP_CURRENT_AVG: - val->intval = -1; + val->intval = 1; break; default: return -EINVAL; @@ -783,12 +817,16 @@ static int is_event_end_timer_running(struct sec_bat_info *info) if (time_after(passed_time, (unsigned long)EVENT_OVER_TIME)) { info->event_end_time = 0xFFFFFFFF; + #ifndef PRODUCT_SHIP dev_info(info->dev, "%s: Event timer is over 10 min\n", __func__); + #endif return false; } else { + #ifndef PRODUCT_SHIP dev_info(info->dev, "%s: Event timer is running(%u s)\n", __func__, jiffies_to_msecs(passed_time) / 1000); + #endif return true; } @@ -816,13 +854,17 @@ static int is_event_end_timer_running(struct sec_bat_info *info) if (time_after(passed_time, (unsigned long)BAT_USE_TIMER_EXPIRE)) { info->event_expired_time = 0xFFFFFFFF; + #ifndef PRODUCT_SHIP dev_info(info->dev, "[SPR_NA] %s: Event timer is over 10 min\n", __func__); + #endif return false; } else { +#ifndef PRODUCT_SHIP dev_info(info->dev, "[SPR_NA] %s: Event timer is running(%u s)\n", __func__, jiffies_to_msecs(passed_time) / 1000); +#endif return true; } @@ -932,9 +974,11 @@ static int sec_bat_check_temper(struct sec_bat_info *info) } else { if ((info->batt_event_status) || (is_event_end_timer_running(info))) { +#ifndef PRODUCT_SHIP dev_info(info->dev, - "[NA_SPR] Changed Put off Current", + "%s: [NA_SPR] Changed Put off Current", __func__); +#endif if (temp_radc >= EVENT_BLOCK_TEMP_ADC) { if (health != POWER_SUPPLY_HEALTH_OVERHEAT @@ -943,7 +987,7 @@ static int sec_bat_check_temper(struct sec_bat_info *info) if (info->batt_temp_high_cnt < TEMP_BLOCK_COUNT) info-> - batt_temp_high_cnt++; + batt_temp_high_cnt++; dev_info(info->dev, "%s: high count = %d\n", __func__, @@ -962,7 +1006,7 @@ static int sec_bat_check_temper(struct sec_bat_info *info) batt_temp_recover_cnt < TEMP_BLOCK_COUNT) info-> - batt_temp_recover_cnt++; + batt_temp_recover_cnt++; dev_info(info->dev, "%s: recovery count = %d\n", __func__, @@ -995,7 +1039,7 @@ static int sec_bat_check_temper(struct sec_bat_info *info) if (info->batt_temp_high_cnt < TEMP_BLOCK_COUNT) info-> - batt_temp_high_cnt++; + batt_temp_high_cnt++; dev_info(info->dev, "%s: high count = %d\n", __func__, @@ -1015,7 +1059,7 @@ static int sec_bat_check_temper(struct sec_bat_info *info) batt_temp_recover_cnt < TEMP_BLOCK_COUNT) info-> - batt_temp_recover_cnt++; + batt_temp_recover_cnt++; dev_info(info->dev, "%s: recovery count = %d\n", __func__, @@ -1073,9 +1117,9 @@ static int sec_bat_check_temper(struct sec_bat_info *info) __func__, ret); } } - +#ifndef PRODUCT_SHIP dev_info(info->dev, "%s: temp=%d, adc=%d\n", __func__, temp, temp_adc); - +#endif return temp; } @@ -1263,8 +1307,9 @@ static int sec_bat_check_temper(struct sec_bat_info *info) __func__, ret); } } - +#ifndef PRODUCT_SHIP dev_info(info->dev, "%s: temp=%d, adc=%d\n", __func__, temp, temp_adc); +#endif return temp; } @@ -1350,9 +1395,9 @@ static int sec_bat_check_temper(struct sec_bat_info *info) __func__, ret); } } - +#ifndef PRODUCT_SHIP dev_info(info->dev, "%s: temp=%d, adc=%d\n", __func__, temp, temp_adc); - +#endif return temp; } #endif @@ -1729,9 +1774,10 @@ static bool sec_bat_charging_time_management(struct sec_bat_info *info) dev_info(info->dev, "%s: Undefine Battery Status\n", __func__); return false; } - +#ifndef PRODUCT_SHIP dev_info(info->dev, "Time past : %u secs\n", jiffies_to_msecs(info->charging_passed_time) / 1000); +#endif return false; } @@ -1953,9 +1999,9 @@ static bool sec_bat_check_ing_level_trigger(struct sec_bat_info *info) charging_int_full_count >= FULL_CHG_COND_COUNT) { info-> - charging_int_full_count + charging_int_full_count = 0; - sec_bat_handle_charger_topoff + sec_bat_handle_charger_topoff (info); return true; } @@ -1963,7 +2009,7 @@ static bool sec_bat_check_ing_level_trigger(struct sec_bat_info *info) "%s : full interrupt cnt = %d\n", __func__, info-> - charging_int_full_count); + charging_int_full_count); } else { info->charging_int_full_count = 0; @@ -2042,9 +2088,9 @@ static bool sec_bat_check_ing_level_trigger(struct sec_bat_info *info) charging_int_full_count >= FULL_CHG_COND_COUNT) { info-> - charging_int_full_count + charging_int_full_count = 0; - sec_bat_handle_charger_topoff + sec_bat_handle_charger_topoff (info); return true; } @@ -2052,13 +2098,14 @@ static bool sec_bat_check_ing_level_trigger(struct sec_bat_info *info) "%s : full interrupt cnt = %d\n", __func__, info-> - charging_int_full_count); + charging_int_full_count); } else { info->charging_int_full_count = 0; /*reactivate charging in */ /*next monitor work */ - /*for abnormal full-charged status */ + /*for abnormal + full-charged status */ info->charging_next_time = info->charging_passed_time + HZ; @@ -2230,12 +2277,14 @@ static void sec_bat_monitor_work(struct work_struct *work) info->batt_temp / 10, info->charging_status, info->batt_health, info->batt_vf_adc); #else +#ifndef PRODUCT_SHIP dev_info(info->dev, "soc(%d), vfocv(%d), vcell(%d), temp(%d), charging(%d), health(%d), chg_adc(%d)\n", info->batt_soc, info->batt_vfocv, info->batt_vcell / 1000, info->batt_temp / 10, info->charging_status, info->batt_health, info->batt_current_adc); #endif +#endif power_supply_changed(&info->psy_bat); @@ -2449,10 +2498,10 @@ static void sec_bat_check_event_status(struct sec_bat_info *info, int mode, if (info->batt_event_status & offset) info->batt_event_status &= ~offset; } - +#ifndef PRODUCT_SHIP printk(KERN_DEBUG "[%s] current batt_event_status = 0x%x\n", __func__, info->batt_event_status); - +#endif if ((info->batt_event_status == 0) && (is_event_running == 1)) info->event_expired_time = jiffies; @@ -2463,6 +2512,7 @@ int sec_bat_use_wimax(int onoff) { struct sec_bat_info *info = pchg; sec_bat_check_event_status(info, onoff, USE_WIMAX); + return 0; } EXPORT_SYMBOL(sec_bat_use_wimax); #endif @@ -2916,6 +2966,7 @@ static ssize_t sec_bat_store(struct device *dev, case BATT_CAMERA: /* TODO */ if (sscanf(buf, "%d\n", &x) == 1) { + info->use_camera = x; dev_info(info->dev, "[NA_SPR]%s: CAMERA(%d)\n", __func__, x); ret = count; diff --git a/drivers/power/smb347_charger.c b/drivers/power/smb347_charger.c index a339776..a339776 100755..100644 --- a/drivers/power/smb347_charger.c +++ b/drivers/power/smb347_charger.c |