aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/board-tuna-power.c
diff options
context:
space:
mode:
authorSON HONG MIN <hongmin.son@samsung.com>2011-09-13 12:07:57 -0700
committerTodd Poynor <toddpoynor@google.com>2011-09-13 13:32:07 -0700
commit111e67f638c4503b5e20cef5d0175b56580dccd8 (patch)
treef5606659010f3c05748a912ca4cc8d766beae2b5 /arch/arm/mach-omap2/board-tuna-power.c
parent45a57b0b5a18c4f4c44ed7a981631f4fe06813ce (diff)
downloadkernel_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.c239
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[] = {