1 /* Power support for Samsung Tuna Board.
3 * Copyright (C) 2011 Google, Inc.
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <linux/err.h>
16 #include <linux/i2c.h>
17 #include <linux/init.h>
18 #include <linux/kernel.h>
19 #include <linux/interrupt.h>
20 #include <linux/gpio.h>
21 #include <linux/max17040_battery.h>
22 #include <linux/moduleparam.h>
23 #include <linux/pda_power.h>
24 #include <linux/platform_device.h>
25 #include <linux/i2c/twl6030-madc.h>
26 #include <linux/delay.h>
29 #include <plat/omap-pm.h>
31 #include "board-tuna.h"
35 /* These will be different on pre-lunchbox, lunchbox, and final */
36 #define GPIO_CHARGING_N 83
37 #define GPIO_TA_NCONNECTED 142
38 #define GPIO_CHARGE_N 13
39 #define GPIO_CHG_CUR_ADJ 102
40 #define GPIO_FUEL_ALERT 44
42 #define TPS62361_GPIO 7
43 #define ADC_NUM_SAMPLES 5
44 #define ADC_LIMIT_ERR_COUNT 5
45 #define ISET_ADC_CHANNEL 3
46 #define TEMP_ADC_CHANNEL 1
48 #define CHARGE_FULL_ADC 150
50 #define HIGH_BLOCK_TEMP_MAGURO 500
51 #define HIGH_RECOVER_TEMP_MAGURO 420
52 #define LOW_BLOCK_TEMP_MAGURO (-50)
53 #define LOW_RECOVER_TEMP_MAGURO 0
55 #define HIGH_BLOCK_TEMP_TORO 490
56 #define HIGH_RECOVER_TEMP_TORO 420
57 #define LOW_BLOCK_TEMP_TORO (-50)
58 #define LOW_RECOVER_TEMP_TORO 0
61 ** temp_adc_table_data
62 ** @adc_value : thermistor adc value
63 ** @temperature : temperature(C) * 10
65 struct temp_adc_table_data
{
70 static DEFINE_SPINLOCK(charge_en_lock
);
71 static int charger_state
;
72 static bool is_charging_mode
;
74 static struct temp_adc_table_data temper_table_maguro
[] = {
75 /* ADC, Temperature (C/10) */
159 static struct temp_adc_table_data temper_table_toro
[] = {
160 /* ADC, Temperature (C/10) */
244 static struct temp_adc_table_data
*temper_table
= temper_table_maguro
;
245 static int temper_table_size
= ARRAY_SIZE(temper_table_maguro
);
247 static bool enable_sr
= true;
248 module_param(enable_sr
, bool, S_IRUSR
| S_IRGRP
| S_IROTH
);
250 static struct gpio charger_gpios
[] = {
251 { .gpio
= GPIO_CHARGING_N
, .flags
= GPIOF_IN
, .label
= "charging_n" },
252 { .gpio
= GPIO_TA_NCONNECTED
, .flags
= GPIOF_IN
, .label
= "charger_n" },
253 { .gpio
= GPIO_CHARGE_N
, .flags
= GPIOF_OUT_INIT_HIGH
, .label
= "charge_n" },
254 { .gpio
= GPIO_CHG_CUR_ADJ
, .flags
= GPIOF_OUT_INIT_LOW
, .label
= "charge_cur_adj" },
257 static int twl6030_get_adc_data(int ch
)
261 int adc_min
= 1 << 11;
265 for (i
= 0; i
< ADC_NUM_SAMPLES
; i
++) {
266 adc_data
= twl6030_get_madc_conversion(ch
);
267 if (adc_data
== -EAGAIN
) {
268 for (j
= 0; j
< ADC_LIMIT_ERR_COUNT
; j
++) {
270 adc_data
= twl6030_get_madc_conversion(ch
);
274 if (j
>= ADC_LIMIT_ERR_COUNT
) {
275 pr_err("%s: Retry count exceeded[ch:%d]\n",
279 } else if (adc_data
< 0) {
280 pr_err("%s: Failed read adc value : %d [ch:%d]\n",
281 __func__
, adc_data
, ch
);
285 if (adc_data
> adc_max
)
287 if (adc_data
< adc_min
)
290 adc_total
+= adc_data
;
292 return (adc_total
- adc_max
- adc_min
) / (ADC_NUM_SAMPLES
- 2);
295 static int iset_adc_value(void)
297 return twl6030_get_adc_data(ISET_ADC_CHANNEL
);
300 static int temp_adc_value(void)
302 return twl6030_get_adc_data(TEMP_ADC_CHANNEL
);
305 static bool check_charge_full(void)
309 ret
= iset_adc_value();
311 pr_err("%s: invalid iset adc value [%d]\n",
315 pr_debug("%s : iset adc value : %d\n", __func__
, ret
);
317 return ret
< CHARGE_FULL_ADC
;
320 static int get_bat_temp_by_adc(int *batt_temp
)
322 int array_size
= temper_table_size
;
323 int temp_adc
= temp_adc_value();
326 int right_side
= array_size
- 1;
330 pr_err("%s : Invalid temperature adc value [%d]\n",
335 while (left_side
<= right_side
) {
336 mid
= (left_side
+ right_side
) / 2;
337 if (mid
== 0 || mid
== array_size
- 1 ||
338 (temper_table
[mid
].adc_value
<= temp_adc
&&
339 temper_table
[mid
+1].adc_value
> temp_adc
)) {
340 temp
= temper_table
[mid
].temperature
;
342 } else if (temp_adc
- temper_table
[mid
].adc_value
> 0) {
345 right_side
= mid
- 1;
349 pr_debug("%s: temp adc : %d, temp : %d\n", __func__
, temp_adc
, temp
);
354 static int charger_init(struct device
*dev
)
356 return gpio_request_array(charger_gpios
, ARRAY_SIZE(charger_gpios
));
359 static void charger_exit(struct device
*dev
)
361 gpio_free_array(charger_gpios
, ARRAY_SIZE(charger_gpios
));
364 static void set_charge_en(int state
)
366 gpio_set_value(GPIO_CHARGE_N
, !state
);
369 static void charger_set_charge(int state
)
373 spin_lock_irqsave(&charge_en_lock
, flags
);
374 gpio_set_value(GPIO_CHG_CUR_ADJ
, !!(state
& PDA_POWER_CHARGE_AC
));
375 charger_state
= state
;
376 set_charge_en(state
);
377 spin_unlock_irqrestore(&charge_en_lock
, flags
);
380 static void charger_set_only_charge(int state
)
384 spin_lock_irqsave(&charge_en_lock
, flags
);
386 set_charge_en(state
);
387 spin_unlock_irqrestore(&charge_en_lock
, flags
);
388 /* CHG_ING_N level changed after set charge_en and 150ms */
392 static int charger_is_online(void)
394 return !gpio_get_value(GPIO_TA_NCONNECTED
);
397 static int charger_is_charging(void)
399 return !gpio_get_value(GPIO_CHARGING_N
);
402 static char *tuna_charger_supplied_to
[] = {
406 static const __initdata
struct pda_power_pdata charger_pdata
= {
407 .init
= charger_init
,
408 .exit
= charger_exit
,
409 .set_charge
= charger_set_charge
,
410 .wait_for_status
= 500,
411 .wait_for_charger
= 500,
412 .supplied_to
= tuna_charger_supplied_to
,
413 .num_supplicants
= ARRAY_SIZE(tuna_charger_supplied_to
),
414 .use_otg_notifier
= true,
417 static struct max17040_platform_data max17043_pdata
= {
418 .charger_online
= charger_is_online
,
419 .charger_enable
= charger_is_charging
,
420 .allow_charging
= charger_set_only_charge
,
423 .is_full_charge
= check_charge_full
,
424 .get_bat_temp
= get_bat_temp_by_adc
,
425 .high_block_temp
= HIGH_BLOCK_TEMP_MAGURO
,
426 .high_recover_temp
= HIGH_RECOVER_TEMP_MAGURO
,
427 .low_block_temp
= LOW_BLOCK_TEMP_MAGURO
,
428 .low_recover_temp
= LOW_RECOVER_TEMP_MAGURO
,
429 .fully_charged_vol
= 4150000,
430 .recharge_vol
= 4140000,
431 .limit_charging_time
= 21600, /* 6 hours */
432 .limit_recharging_time
= 5400, /* 90 min */
435 static const __initdata
struct i2c_board_info max17043_i2c
[] = {
437 I2C_BOARD_INFO("max17040", (0x6C >> 1)),
438 .platform_data
= &max17043_pdata
,
439 .irq
= OMAP_GPIO_IRQ(GPIO_FUEL_ALERT
),
443 static int __init
tuna_charger_mode_setup(char *str
)
445 if (!str
) /* No mode string */
448 is_charging_mode
= !strcmp(str
, "charger");
450 pr_debug("Charge mode string = \"%s\" charger mode = %d\n", str
,
456 __setup("androidboot.mode=", tuna_charger_mode_setup
);
458 void __init
omap4_tuna_power_init(void)
460 struct platform_device
*pdev
;
463 /* Vsel0 = gpio, vsel1 = gnd */
464 status
= omap_tps6236x_board_setup(true, TPS62361_GPIO
, -1,
465 OMAP_PIN_OFF_OUTPUT_HIGH
, -1);
467 pr_err("TPS62361 initialization failed: %d\n", status
);
469 * Some Tuna devices have a 4430 chip on a 4460 board, manually
470 * tweak the power tree to the 4460 style with the TPS regulator.
472 if (cpu_is_omap443x()) {
473 /* Disable 4430 mapping */
474 omap_twl_pmic_update("mpu", CHIP_IS_OMAP443X
, 0x0);
475 omap_twl_pmic_update("core", CHIP_IS_OMAP443X
, 0x0);
476 /* make 4460 map usable for 4430 */
477 omap_twl_pmic_update("core", CHIP_IS_OMAP446X
, CHIP_IS_OMAP443X
);
478 omap_tps6236x_update("mpu", CHIP_IS_OMAP446X
, CHIP_IS_OMAP443X
);
481 /* Update temperature data from board type */
482 if (omap4_tuna_get_type() == TUNA_TYPE_TORO
) {
483 temper_table
= temper_table_toro
;
484 temper_table_size
= ARRAY_SIZE(temper_table_toro
);
486 max17043_pdata
.high_block_temp
= HIGH_BLOCK_TEMP_TORO
;
487 max17043_pdata
.high_recover_temp
= HIGH_RECOVER_TEMP_TORO
;
488 max17043_pdata
.low_block_temp
= LOW_BLOCK_TEMP_TORO
;
489 max17043_pdata
.low_recover_temp
= LOW_RECOVER_TEMP_TORO
;
492 /* Update oscillator information */
493 if (omap4_tuna_get_revision() <= 0x3) {
495 * until sample 4 (Toro and Maguro), we used KC2520B38:
497 * Output Disable time = 100ns
498 * Output enable time = 5ms
499 * tstart = 10ms + 5ms = 15ms.
500 * tshut = 1us (rounded)
502 omap_pm_set_osc_lp_time(15000, 1);
505 * sample 5 onwards (Toro and Maguro), we use SQ200384:
507 * Output Disable time = 100ns
508 * Output enable time = 10ms
509 * tstart = 10ms + 10ms = 20ms.
510 * tshut = 1us (rounded)
512 omap_pm_set_osc_lp_time(20000, 1);
515 omap_mux_init_gpio(charger_gpios
[0].gpio
, OMAP_PIN_INPUT
);
516 omap_mux_init_gpio(charger_gpios
[1].gpio
, OMAP_PIN_INPUT
);
517 omap_mux_init_gpio(charger_gpios
[2].gpio
, OMAP_PIN_OUTPUT
);
518 omap_mux_init_gpio(charger_gpios
[3].gpio
, OMAP_PIN_OUTPUT
);
519 omap_mux_init_gpio(GPIO_FUEL_ALERT
, OMAP_PIN_INPUT
);
521 pdev
= platform_device_register_resndata(NULL
, "pda-power", -1,
522 NULL
, 0, &charger_pdata
, sizeof(charger_pdata
));
523 if (IS_ERR_OR_NULL(pdev
))
524 pr_err("cannot register pda-power\n");
526 max17043_pdata
.use_fuel_alert
= !is_charging_mode
;
527 i2c_register_board_info(4, max17043_i2c
, ARRAY_SIZE(max17043_i2c
));
530 omap_enable_smartreflex_on_init();
532 omap_pm_enable_off_mode();