diff options
author | Simon Que <sque@chromium.org> | 2012-08-09 10:51:39 -0700 |
---|---|---|
committer | Gerrit <chrome-bot@google.com> | 2012-08-14 17:04:50 -0700 |
commit | 1178484e0e728ab123b8bf3433624c92936b7229 (patch) | |
tree | 929bc04c58c5a114877e63efe88a1363cc887dfb | |
parent | 6bbddfbfb85ed31b2b821ef1cb3077faf8d1dc44 (diff) | |
download | chrome-ec-1178484e0e728ab123b8bf3433624c92936b7229.tar.gz |
Handle IRQ from TPS65090, pass AC status to AP
Changes made by this patch:
1. Create IRQ handler for the TPS65090 IRQ. IRQ wakes up charger task.
2. Charger task sets the AC_STATUS GPIO based on the AC status.
3. Initialize PMU at power-on.
BRANCH=snow
BUG=chrome-os-partner:11739
TEST=Power on the system, with servo v2 connected to EC console. Plug
and unplug AC. The IRQ handler should be triggered.
Change-Id: Ice23411c275111fdb56d2c47ba28c3c44dee4d71
Signed-off-by: Simon Que <sque@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/29914
Commit-Ready: Rong Chang <rongchang@chromium.org>
Reviewed-by: Rong Chang <rongchang@chromium.org>
Tested-by: Rong Chang <rongchang@chromium.org>
-rw-r--r-- | board/daisy/board.c | 1 | ||||
-rw-r--r-- | board/daisy/board.h | 1 | ||||
-rw-r--r-- | board/snow/board.c | 3 | ||||
-rw-r--r-- | board/snow/board.h | 1 | ||||
-rw-r--r-- | common/gaia_power.c | 3 | ||||
-rw-r--r-- | common/pmu_tps65090.c | 54 | ||||
-rw-r--r-- | common/pmu_tps65090_charger.c | 46 | ||||
-rw-r--r-- | include/pmu_tpschrome.h | 28 |
8 files changed, 90 insertions, 47 deletions
diff --git a/board/daisy/board.c b/board/daisy/board.c index fa1d17af7d..7a2a0083f2 100644 --- a/board/daisy/board.c +++ b/board/daisy/board.c @@ -66,6 +66,7 @@ const struct gpio_info gpio_list[GPIO_COUNT] = { {"SPI1_NSS", GPIO_A, (1<<4), GPIO_PULL_UP, NULL}, /* Outputs */ + {"AC_STATUS", GPIO_A, (1<<5), GPIO_OUT_HIGH, NULL}, {"SPI1_MISO", GPIO_A, (1<<6), GPIO_OUT_HIGH, NULL}, {"EN_PP1350", GPIO_A, (1<<2), GPIO_OUT_LOW, NULL}, {"EN_PP5000", GPIO_A, (1<<11), GPIO_OUT_LOW, NULL}, diff --git a/board/daisy/board.h b/board/daisy/board.h index a866466d0f..c7a2587d5e 100644 --- a/board/daisy/board.h +++ b/board/daisy/board.h @@ -73,6 +73,7 @@ enum gpio_signal { GPIO_AC_PWRBTN_L, GPIO_SPI1_NSS, /* Outputs */ + GPIO_AC_STATUS, GPIO_SPI1_MISO, GPIO_EN_PP1350, /* DDR 1.35v rail enable */ GPIO_EN_PP5000, /* 5.0v rail enable */ diff --git a/board/snow/board.c b/board/snow/board.c index 8359f25c7e..bf9aa71c98 100644 --- a/board/snow/board.c +++ b/board/snow/board.c @@ -40,7 +40,7 @@ const struct gpio_info gpio_list[GPIO_COUNT] = { {"KB_PWR_ON_L", GPIO_B, (1<<5), GPIO_INT_BOTH, gaia_power_event}, {"PP1800_LDO2", GPIO_A, (1<<1), GPIO_INT_BOTH, gaia_power_event}, {"XPSHOLD", GPIO_A, (1<<3), GPIO_INT_RISING, gaia_power_event}, - {"CHARGER_INT", GPIO_C, (1<<4), GPIO_INT_RISING, NULL}, + {"CHARGER_INT", GPIO_C, (1<<4), GPIO_INT_FALLING, pmu_irq_handler}, {"LID_OPEN", GPIO_C, (1<<13), GPIO_INT_RISING, gaia_lid_event}, {"SUSPEND_L", GPIO_A, (1<<7), GPIO_INT_BOTH, gaia_suspend_event}, {"WP_L", GPIO_B, (1<<4), GPIO_INPUT, NULL}, @@ -57,6 +57,7 @@ const struct gpio_info gpio_list[GPIO_COUNT] = { {"SPI1_NSS", GPIO_A, (1<<4), GPIO_PULL_UP, NULL}, /* Outputs */ + {"AC_STATUS", GPIO_A, (1<<5), GPIO_OUT_HIGH, NULL}, {"SPI1_MISO", GPIO_A, (1<<6), GPIO_OUT_HIGH, NULL}, {"EN_PP1350", GPIO_A, (1<<2), GPIO_OUT_LOW, NULL}, {"EN_PP5000", GPIO_A, (1<<11), GPIO_OUT_LOW, NULL}, diff --git a/board/snow/board.h b/board/snow/board.h index 2e72250b34..c7ecae04e7 100644 --- a/board/snow/board.h +++ b/board/snow/board.h @@ -77,6 +77,7 @@ enum gpio_signal { GPIO_AC_PWRBTN_L, GPIO_SPI1_NSS, /* Outputs */ + GPIO_AC_STATUS, GPIO_SPI1_MISO, GPIO_EN_PP1350, /* DDR 1.35v rail enable */ GPIO_EN_PP5000, /* 5.0v rail enable */ diff --git a/common/gaia_power.c b/common/gaia_power.c index d440ff5929..ee266de2eb 100644 --- a/common/gaia_power.c +++ b/common/gaia_power.c @@ -388,6 +388,9 @@ static int power_on(void) /* Call hooks now that AP is running */ hook_notify(HOOK_CHIPSET_STARTUP, 0); + /* Enable charger interrupt. */ + gpio_enable_interrupt(GPIO_CHARGER_INT); + CPRINTF("[%T AP running ...]\n"); return 0; } diff --git a/common/pmu_tps65090.c b/common/pmu_tps65090.c index ba75d82235..1d121b6a4e 100644 --- a/common/pmu_tps65090.c +++ b/common/pmu_tps65090.c @@ -8,8 +8,10 @@ #include "board.h" #include "console.h" #include "common.h" +#include "hooks.h" #include "i2c.h" #include "pmu_tpschrome.h" +#include "task.h" #include "timer.h" #include "util.h" @@ -49,12 +51,6 @@ /* Charger alarm */ #define CHARGER_ALARM 3 -/* Clear tps65090 irq */ -static inline int pmu_clear_irq(void) -{ - return pmu_write(IRQ1_REG, 0); -} - /* Read all tps65090 interrupt events */ static int pmu_get_event(int *event) { @@ -81,6 +77,12 @@ static int pmu_get_event(int *event) return EC_SUCCESS; } +/* Clear tps65090 irq */ +int pmu_clear_irq(void) +{ + return pmu_write(IRQ1_REG, 0); +} + /* Read/write tps65090 register */ int pmu_read(int reg, int *value) { @@ -215,6 +217,35 @@ int pmu_low_current_charging(int enable) return pmu_write(CG_CTRL5, reg_val); } +void pmu_irq_handler(enum gpio_signal signal) +{ + CPRINTF("Charger IRQ received.\n"); + gpio_set_level(GPIO_AC_STATUS, pmu_get_ac()); + task_wake(TASK_ID_PMU_TPS65090_CHARGER); +} + +int pmu_get_ac(void) +{ + /* + * Detect AC state using combined gpio pins + * + * On daisy and snow, there's no single gpio signal to detect AC. + * GPIO_AC_PWRBTN_L provides AC on and PWRBTN release. + * GPIO_KB_PWR_ON_L provides PWRBTN release. + * Hence the ac state can be logical OR of these two signal line. + * + * One drawback of this detection is, when press-and-hold power + * button. AC state will be unknown. The implementation below treats + * that condition as AC off. + * + * TODO(rongchang): move board related function to board/ and common + * interface to system_get_ac() + */ + + return gpio_get_level(GPIO_AC_PWRBTN_L) && + gpio_get_level(GPIO_KB_PWR_ON_L); +} + void pmu_init(void) { #ifdef CONFIG_PMU_BOARD_INIT @@ -233,11 +264,20 @@ void pmu_init(void) */ pmu_write(CG_CTRL3, 0xbb); #endif - /* Enable interrupt mask */ + /* Enable interrupts */ + pmu_clear_irq(); pmu_write(IRQ1MASK, 0xff); pmu_write(IRQ2MASK, 0xff); +} +/* Initializes PMU when power is turned on. This is necessary because the TPS' + * 3.3V rail is not powered until the power is turned on. */ +static int pmu_chipset_startup(void) +{ + pmu_init(); + return 0; } +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, pmu_chipset_startup, HOOK_PRIO_DEFAULT); #ifdef CONFIG_CMD_PMU static int print_pmu_info(void) diff --git a/common/pmu_tps65090_charger.c b/common/pmu_tps65090_charger.c index 62c84bb342..29f6dda19c 100644 --- a/common/pmu_tps65090_charger.c +++ b/common/pmu_tps65090_charger.c @@ -57,38 +57,6 @@ static void enable_charging(int enable) gpio_set_level(GPIO_CHARGER_EN, enable); } - -/** - * Get AC state through GPIO - * - * @return 0 AC off - * @return 1 AC on - * - * TODO: This is a board specific function, should be moved to - * system_common.c or board.c - */ -static int get_ac(void) -{ - /* - * Detect AC state using combined gpio pins - * - * On daisy and snow, there's no single gpio signal to detect AC. - * GPIO_AC_PWRBTN_L provides AC on and PWRBTN release. - * GPIO_KB_PWR_ON_L provides PWRBTN release. - * Hence the ac state can be logical OR of these two signal line. - * - * One drawback of this detection is, when press-and-hold power - * button. AC state will be unknown. The implementation below treats - * that condition as AC off. - * - * TODO(rongchang): move board related function to board/ and common - * interface to system_get_ac() - */ - - return gpio_get_level(GPIO_AC_PWRBTN_L) && - gpio_get_level(GPIO_KB_PWR_ON_L); -} - /* * TODO(rongchang): move battery vendor specific functions to battery pack * module @@ -182,7 +150,7 @@ static int calc_next_state(int state) case ST_IDLE: /* Check AC and chiset state */ - if (!get_ac()) { + if (!pmu_get_ac()) { if (chipset_in_state(CHIPSET_STATE_ON)) return ST_DISCHARGING; @@ -224,7 +192,7 @@ static int calc_next_state(int state) return wait_t1_idle(); case ST_PRE_CHARGING: - if (!get_ac()) + if (!pmu_get_ac()) return wait_t1_idle(); /* If the battery goes online after enable the charger, @@ -238,7 +206,7 @@ static int calc_next_state(int state) case ST_CHARGING: /* Go back to idle state when AC is unplugged */ - if (!get_ac()) + if (!pmu_get_ac()) break; /* @@ -284,7 +252,7 @@ static int calc_next_state(int state) case ST_DISCHARGING: /* Go back to idle state when AC is plugged */ - if (get_ac()) + if (pmu_get_ac()) return wait_t1_idle(); /* Check battery discharging temperature range */ @@ -319,9 +287,9 @@ void pmu_charger_task(void) int state = ST_IDLE; int next_state; - pmu_init(); - while (1) { + pmu_clear_irq(); + next_state = calc_next_state(state); if (next_state != state) { CPRINTF("[batt] state %s -> %s\n", @@ -331,6 +299,6 @@ void pmu_charger_task(void) } /* TODO(sjg@chromium.org): root cause crosbug.com/p/11285 */ - usleep(5000 * 1000); + task_wait_event(5000 * 1000); } } diff --git a/include/pmu_tpschrome.h b/include/pmu_tpschrome.h index eb4eb71b0c..0c014a864a 100644 --- a/include/pmu_tpschrome.h +++ b/include/pmu_tpschrome.h @@ -8,6 +8,8 @@ #ifndef __CROS_EC_TPSCHROME_H #define __CROS_EC_TPSCHROME_H +#include "gpio.h" + enum TPS_TEMPERATURE_RANGE { RANGE_T01, RANGE_T12, /* low charging temperature range */ @@ -39,6 +41,14 @@ enum TPS_TERMINATION_CURRENT { #define FET_BACKLIGHT 1 #define FET_LCD_PANEL 6 + +/** + * Clear tps65090 IRQ register + * + * @return return EC_SUCCESS on success, err code otherwise + */ +int pmu_clear_irq(void); + /** * Read pmu register * @@ -127,6 +137,24 @@ int pmu_set_term_voltage(enum TPS_TEMPERATURE_RANGE range, int pmu_low_current_charging(int enable); /** + * Handles interrupts from tpschrome + * + * @param signal Indicates signal type. + */ +void pmu_irq_handler(enum gpio_signal signal); + +/** + * Get AC state through GPIO + * + * @return 0 AC off + * @return 1 AC on + * + * TODO: This is a board specific function, should be moved to + * system_common.c or board.c + */ +int pmu_get_ac(void); + +/** * * Initialize pmu * */ void pmu_init(void); |