summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Que <sque@chromium.org>2012-08-09 10:51:39 -0700
committerGerrit <chrome-bot@google.com>2012-08-14 17:04:50 -0700
commit1178484e0e728ab123b8bf3433624c92936b7229 (patch)
tree929bc04c58c5a114877e63efe88a1363cc887dfb
parent6bbddfbfb85ed31b2b821ef1cb3077faf8d1dc44 (diff)
downloadchrome-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.c1
-rw-r--r--board/daisy/board.h1
-rw-r--r--board/snow/board.c3
-rw-r--r--board/snow/board.h1
-rw-r--r--common/gaia_power.c3
-rw-r--r--common/pmu_tps65090.c54
-rw-r--r--common/pmu_tps65090_charger.c46
-rw-r--r--include/pmu_tpschrome.h28
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);