diff options
author | SON HONG MIN <hongmin.son@samsung.com> | 2011-09-13 12:07:57 -0700 |
---|---|---|
committer | Todd Poynor <toddpoynor@google.com> | 2011-09-13 13:32:07 -0700 |
commit | 111e67f638c4503b5e20cef5d0175b56580dccd8 (patch) | |
tree | f5606659010f3c05748a912ca4cc8d766beae2b5 /arch/arm/mach-omap2/board-tuna-power.c | |
parent | 45a57b0b5a18c4f4c44ed7a981631f4fe06813ce (diff) | |
download | kernel_samsung_tuna-111e67f638c4503b5e20cef5d0175b56580dccd8.zip kernel_samsung_tuna-111e67f638c4503b5e20cef5d0175b56580dccd8.tar.gz kernel_samsung_tuna-111e67f638c4503b5e20cef5d0175b56580dccd8.tar.bz2 |
OMAP4: tuna: Add functions for applying the concept of charge.
- add function to get ISET_ADC value for full charging check.
- add function to get battery temperature ADC value
- add function to set only charge_enable.
- add battery temperature table.
Change-Id: Iac1eee60b156a74d6866be217f874f92b6f9c2f4
Signed-off-by: SON HONG MIN <hongmin.son@samsung.com>
Diffstat (limited to 'arch/arm/mach-omap2/board-tuna-power.c')
-rw-r--r-- | arch/arm/mach-omap2/board-tuna-power.c | 239 |
1 files changed, 235 insertions, 4 deletions
diff --git a/arch/arm/mach-omap2/board-tuna-power.c b/arch/arm/mach-omap2/board-tuna-power.c index e3f5f06..c8ff8cd 100644 --- a/arch/arm/mach-omap2/board-tuna-power.c +++ b/arch/arm/mach-omap2/board-tuna-power.c @@ -22,6 +22,8 @@ #include <linux/moduleparam.h> #include <linux/pda_power.h> #include <linux/platform_device.h> +#include <linux/i2c/twl6030-madc.h> +#include <linux/delay.h> #include <plat/cpu.h> @@ -36,7 +38,111 @@ #define GPIO_CHG_CUR_ADJ 102 #define GPIO_FUEL_ALERT 44 -#define TPS62361_GPIO 7 +#define TPS62361_GPIO 7 +#define ADC_NUM_SAMPLES 5 +#define ADC_LIMIT_ERR_COUNT 5 +#define ISET_ADC_CHANNEL 3 +#define TEMP_ADC_CHANNEL 1 + +#define CHARGE_FULL_ADC 203 + +/** +** temp_adc_table_data +** @adc_value : thermistor adc value +** @temperature : temperature(C) * 10 +**/ +struct temp_adc_table_data { + int adc_value; + int temperature; +}; + +static DEFINE_SPINLOCK(charge_en_lock); +static int charger_state; + +static struct temp_adc_table_data temper_table[] = { + /* ADC, Temperature (C/10) */ + { 75, 700 }, + { 78, 690 }, + { 82, 680 }, + { 84, 670 }, + { 87, 660 }, + { 89, 650 }, + { 92, 640 }, + { 95, 630 }, + { 99, 620 }, + { 102, 610 }, + { 105, 600 }, + { 109, 590 }, + { 113, 580 }, + { 117, 570 }, + { 121, 560 }, + { 124, 550 }, + { 127, 540 }, + { 135, 530 }, + { 139, 520 }, + { 143, 510 }, + { 147, 500 }, + { 153, 490 }, + { 158, 480 }, + { 163, 470 }, + { 169, 460 }, + { 175, 450 }, + { 181, 440 }, + { 187, 430 }, + { 193, 420 }, + { 199, 410 }, + { 205, 400 }, + { 212, 390 }, + { 218, 380 }, + { 227, 370 }, + { 233, 360 }, + { 240, 350 }, + { 249, 340 }, + { 258, 330 }, + { 267, 320 }, + { 276, 310 }, + { 285, 300 }, + { 299, 290 }, + { 308, 280 }, + { 313, 270 }, + { 322, 260 }, + { 331, 250 }, + { 342, 240 }, + { 355, 230 }, + { 363, 220 }, + { 373, 210 }, + { 383, 200 }, + { 394, 190 }, + { 407, 180 }, + { 417, 170 }, + { 427, 160 }, + { 437, 150 }, + { 450, 140 }, + { 465, 130 }, + { 475, 120 }, + { 487, 110 }, + { 500, 100 }, + { 514, 90 }, + { 526, 80 }, + { 540, 70 }, + { 552, 60 }, + { 565, 50 }, + { 577, 40 }, + { 589, 30 }, + { 603, 20 }, + { 614, 10 }, + { 628, 0 }, + { 639, (-10) }, + { 664, (-20) }, + { 689, (-30) }, + { 717, (-40) }, + { 744, (-50) }, + { 754, (-60) }, + { 765, (-70) }, + { 776, (-80) }, + { 787, (-90) }, + { 798, (-100) }, +}; static bool enable_sr = true; module_param(enable_sr, bool, S_IRUSR | S_IRGRP | S_IROTH); @@ -48,6 +154,102 @@ static struct gpio charger_gpios[] = { { .gpio = GPIO_CHG_CUR_ADJ, .flags = GPIOF_OUT_INIT_LOW, .label = "charge_cur_adj" }, }; +static int twl6030_get_adc_data(int ch) +{ + int adc_data; + int adc_max = -1; + int adc_min = 1 << 11; + int adc_total = 0; + int i, j; + + for (i = 0; i < ADC_NUM_SAMPLES; i++) { + adc_data = twl6030_get_madc_conversion(ch); + if (adc_data == -EAGAIN) { + for (j = 0; j < ADC_LIMIT_ERR_COUNT; j++) { + msleep(20); + adc_data = twl6030_get_madc_conversion(ch); + if (adc_data > 0) + break; + } + if (j >= ADC_LIMIT_ERR_COUNT) { + pr_err("%s: Retry count exceeded[ch:%d]\n", + __func__, ch); + return adc_data; + } + } else if (adc_data < 0) { + pr_err("%s: Failed read adc value : %d [ch:%d]\n", + __func__, adc_data, ch); + return adc_data; + } + + if (adc_data > adc_max) + adc_max = adc_data; + if (adc_data < adc_min) + adc_min = adc_data; + + adc_total += adc_data; + } + return (adc_total - adc_max - adc_min) / (ADC_NUM_SAMPLES - 2); +} + +static int iset_adc_value(void) +{ + return twl6030_get_adc_data(ISET_ADC_CHANNEL); +} + +static int temp_adc_value(void) +{ + return twl6030_get_adc_data(TEMP_ADC_CHANNEL); +} + +static bool check_charge_full(void) +{ + int ret; + + ret = iset_adc_value(); + if (ret < 0) { + pr_err("%s: invalid iset adc value [%d]\n", + __func__, ret); + return false; + } + pr_debug("%s : iset adc value : %d\n", __func__, ret); + + return ret < CHARGE_FULL_ADC; +} + +static int get_bat_temp_by_adc(void) +{ + int array_size = ARRAY_SIZE(temper_table); + int temp_adc = temp_adc_value(); + int mid; + int left_side = 0; + int right_side = array_size - 1; + int temp = 0; + + if (temp_adc < 0) { + pr_err("%s : Invalid temperature adc value [%d]\n", + __func__, temp_adc); + return temp_adc; + } + + while (left_side <= right_side) { + mid = (left_side + right_side) / 2; + if (mid == 0 || mid == array_size - 1 || + (temper_table[mid].adc_value <= temp_adc && + temper_table[mid+1].adc_value > temp_adc)) { + temp = temper_table[mid].temperature; + break; + } else if (temp_adc - temper_table[mid].adc_value > 0) { + left_side = mid + 1; + } else { + right_side = mid - 1; + } + } + + pr_debug("%s: temp adc : %d, temp : %d\n", __func__, temp_adc, temp); + return temp; +} + static int charger_init(struct device *dev) { return gpio_request_array(charger_gpios, ARRAY_SIZE(charger_gpios)); @@ -58,10 +260,28 @@ static void charger_exit(struct device *dev) gpio_free_array(charger_gpios, ARRAY_SIZE(charger_gpios)); } +static void set_charge_en(int state) +{ + gpio_set_value(GPIO_CHARGE_N, !state); +} + static void charger_set_charge(int state) { gpio_set_value(GPIO_CHG_CUR_ADJ, !!(state & PDA_POWER_CHARGE_AC)); - gpio_set_value(GPIO_CHARGE_N, !state); + spin_lock(&charge_en_lock); + charger_state = state; + set_charge_en(state); + spin_unlock(&charge_en_lock); +} + +static void charger_set_only_charge(int state) +{ + spin_lock(&charge_en_lock); + if (charger_state) + set_charge_en(state); + spin_unlock(&charge_en_lock); + /* CHG_ING_N level changed after set charge_en and 150ms */ + msleep(150); } static int charger_is_online(void) @@ -92,8 +312,19 @@ static const __initdata struct pda_power_pdata charger_pdata = { static struct max17040_platform_data max17043_pdata = { .charger_online = charger_is_online, .charger_enable = charger_is_charging, - .skip_reset = true, - .min_capacity = 3, + .allow_charging = charger_set_only_charge, + .skip_reset = true, + .min_capacity = 3, + .is_full_charge = check_charge_full, + .get_bat_temp = get_bat_temp_by_adc, + .high_block_temp = 500, + .high_recover_temp = 420, + .low_block_temp = (-50), + .low_recover_temp = 0, + .fully_charged_vol = 4150000, + .recharge_vol = 4140000, + .limit_charging_time = 21600, /* 6 hours */ + .limit_recharging_time = 5400, /* 90 min */ }; static const __initdata struct i2c_board_info max17043_i2c[] = { |