diff options
Diffstat (limited to 'baseboard/dedede/variant_ec_npcx796fc.c')
-rw-r--r-- | baseboard/dedede/variant_ec_npcx796fc.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/baseboard/dedede/variant_ec_npcx796fc.c b/baseboard/dedede/variant_ec_npcx796fc.c index 4ef55cf682..98ba57b70b 100644 --- a/baseboard/dedede/variant_ec_npcx796fc.c +++ b/baseboard/dedede/variant_ec_npcx796fc.c @@ -7,17 +7,24 @@ #include "adc_chip.h" #include "atomic.h" +#include "chipset.h" #include "common.h" #include "compile_time_macros.h" #include "console.h" #include "gpio.h" #include "hooks.h" #include "i2c.h" +#include "lid_switch.h" #include "power.h" #include "pwm.h" #include "pwm_chip.h" #include "registers.h" #include "task.h" +#include "timer.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) /* ADC channels */ const struct adc_t adc_channels[] = { @@ -95,6 +102,81 @@ static void set_up_adc_irqs(void) } DECLARE_HOOK(HOOK_INIT, set_up_adc_irqs, HOOK_PRIO_INIT_ADC+1); +static void disable_adc_irqs_deferred(void) +{ + CPRINTS("%s", __func__); + npcx_adc_thresh_int_enable(NPCX_ADC_THRESH1, 0); + npcx_adc_thresh_int_enable(NPCX_ADC_THRESH2, 0); + npcx_set_adc_repetitive(adc_channels[ADC_VSNS_PP3300_A].input_ch, 0); + + /* + * If we're already in G3, PP3300_A is already off. Since the ADC + * interrupts were already disabled, this data is stale. Therefore, + * force the PGOOD value to 0 and have the chipset task re-evaluate. + * This should help prevent leakage. + */ + if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) + pp3300_a_pgood = 0; + power_signal_interrupt(GPIO_PG_EC_DSW_PWROK); +} +DECLARE_DEFERRED(disable_adc_irqs_deferred); + +/* + * The ADC interrupts are only needed for booting up. The assumption is that + * the PP3300_A rail will not go down during runtime. Therefore, we'll disable + * the ADC interrupts shortly after booting up and also after shutting down. + */ +static void disable_adc_irqs(void) +{ + int delay = 200 * MSEC; + + /* + * The EC stays in S5 for about 10s after shutting before heading down + * to G3. Therefore, we'll postpone disabling the ADC IRQs until after + * this occurs. + */ + if (chipset_in_or_transitioning_to_state(CHIPSET_STATE_ANY_OFF)) + delay = 15 * SECOND; + hook_call_deferred(&disable_adc_irqs_deferred_data, delay); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, disable_adc_irqs, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_RESUME, disable_adc_irqs, HOOK_PRIO_DEFAULT); + +/* + * We only need the ADC interrupts functional when powering up. Therefore, only + * enable them from our wake sources. These will be the power button, or lid + * open. Below is a summary of the ADC interrupt action per power state and + * wake source. + * + * Powering up to S0: ADC interrupts will be disabled after ~200ms. + * S0ix/S3: No action as ADC interrupts are already disabled if suspending. + * Powering down to S5/G3: ADC interrupts will be disabled after ~15s. + * Powering up from S5/G3: ADC interrupts will be enabled. They will be + * disabled ~200ms after passing thru S3. + * Power button press: If the system is in S5/G3, ADC interrupts will be + * enabled. + * Lid open: ADC interrupts will be enabled. + */ +static void enable_adc_irqs(void) +{ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + CPRINTS("%s", __func__); + hook_call_deferred(&disable_adc_irqs_deferred_data, -1); + npcx_set_adc_repetitive(adc_channels[ADC_VSNS_PP3300_A].input_ch, + 1); + npcx_adc_thresh_int_enable(NPCX_ADC_THRESH1, 1); + npcx_adc_thresh_int_enable(NPCX_ADC_THRESH2, 1); + } +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, enable_adc_irqs, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_POWER_BUTTON_CHANGE, enable_adc_irqs, HOOK_PRIO_DEFAULT); + +static void enable_adc_irqs_via_lid(void) +{ + if (lid_is_open()) + enable_adc_irqs(); +} +DECLARE_HOOK(HOOK_LID_CHANGE, enable_adc_irqs_via_lid, HOOK_PRIO_DEFAULT); /* I2C Ports */ const struct i2c_port_t i2c_ports[] = { |