static void charge_shutdown(void) { /* Hibernate immediately if battery level is too low */ if (charge_want_shutdown()) { CPRINTS("charge force EC hibernate after " "shutdown due to low battery"); system_hibernate(0, 0); } }
enum cts_rc test_interrupt_disable(void) { interrupt_disable(); if (!busy_loop()) { CPRINTS("Expected timeout but didn't"); return CTS_RC_FAILURE; } return CTS_RC_SUCCESS; }
/** * Prevent battery from going into deep discharge state */ static void low_battery_shutdown(struct charge_state_context *ctx) { if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { /* AP is off, so shut down the EC now */ CPRINTS("charge force EC hibernate due to low battery"); system_hibernate(0, 0); } else if (!ctx->shutdown_warning_time.val) { /* Warn AP battery level is so low we'll shut down */ CPRINTS("charge warn shutdown due to low battery"); ctx->shutdown_warning_time = get_time(); host_set_single_event(EC_HOST_EVENT_BATTERY_SHUTDOWN); } else if (get_time().val > ctx->shutdown_warning_time.val + LOW_BATTERY_SHUTDOWN_TIMEOUT_US) { /* Timeout waiting for AP to shut down, so kill it */ CPRINTS("charge force shutdown due to low battery"); chipset_force_shutdown(); } }
/** * Set the charge limit based upon desired maximum. * * @param charge_ma Desired charge limit (mA). */ void board_set_charge_limit(int charge_ma) { int rv; charge_current_limit = MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT); rv = charge_set_input_current_limit(charge_current_limit); if (rv < 0) CPRINTS("Failed to set input current limit for PD"); }
void chipset_reset(int is_cold) { if (is_cold) { CPRINTS("EC triggered cold reboot"); power_off(); /* After POWER_GOOD is dropped off, * the system will be on again */ power_request = POWER_REQ_ON; } else { CPRINTS("EC triggered warm reboot"); CPRINTS("assert GPIO_PMIC_WARM_RESET_L for %d ms", PMIC_WARM_RESET_L_HOLD_TIME / MSEC); set_pmic_warm_reset(1); usleep(PMIC_WARM_RESET_L_HOLD_TIME); set_pmic_warm_reset(0); } }
static void dump_i2c_reg(int port, const char *what) { CPRINTS("i2c CR1=%04x CR2=%04x SR1=%04x SR2=%04x %s", STM32_I2C_CR1(port), STM32_I2C_CR2(port), STM32_I2C_SR1(port), STM32_I2C_SR2(port), what); }
void lpcrst_interrupt(enum gpio_signal signal) { if (lpc_get_pltrst_asserted()) /* Store port 80 reset event */ port_80_write(PORT_80_EVENT_RESET); CPRINTS("LPC RESET# %sasserted", lpc_get_pltrst_asserted() ? "" : "de"); }
void usb_disconnect(void) { CPRINTS("%s", __func__); print_later("usb_disconnect()", 0, 0, 0, 0, 0); GR_USB_DCTL |= DCTL_SFTDISCON; device_state = DS_DEFAULT; configuration_value = 0; }
enum power_state power_chipset_init(void) { int init_power_state; uint32_t reset_flags = system_get_reset_flags(); /* * Force the AP shutdown unless we are doing SYSJUMP. Otherwise, * the AP could stay in strange state. */ if (!(reset_flags & RESET_FLAG_SYSJUMP)) { CPRINTS("not sysjump; forcing AP shutdown"); chipset_turn_off_power_rails(); /* * The warm reset triggers AP into the RK recovery mode ( * flash SPI from USB). */ chipset_reset(0); init_power_state = POWER_G3; } else { /* In the SYSJUMP case, we check if the AP is on */ if (power_get_signals() & IN_POWER_GOOD) init_power_state = POWER_S0; else init_power_state = POWER_G3; } /* Leave power off only if requested by reset flags */ if (!(reset_flags & RESET_FLAG_AP_OFF) && !(reset_flags & RESET_FLAG_SYSJUMP)) { CPRINTS("auto_power_on set due to reset_flag 0x%x", system_get_reset_flags()); auto_power_on = 1; } /* * Some batteries use clock stretching feature, which requires * more time to be stable. See http://crosbug.com/p/28289 */ battery_wait_for_stable(); return init_power_state; }
int power_has_signals(uint32_t want) { if ((in_signals & want) == want) return 1; CPRINTS("power lost input; wanted 0x%04x, got 0x%04x", want, in_signals & want); return 0; }
void power_button_pch_pulse(void) { CPRINTS("PB PCH pulse"); chipset_exit_hard_off(); set_pwrbtn_to_pch(0); pwrbtn_state = PWRBTN_STATE_LID_OPEN; tnext_state = get_time().val + PWRBTN_INITIAL_US; task_wake(TASK_ID_POWERBTN); }
void chipset_force_shutdown(void) { CPRINTS("%s()", __func__); /* * Force off. This condition will reset once the state machine * transitions to G3. */ gpio_set_level(GPIO_PCH_DPWROK, 0); }
void usb_mux_init(int port) { const struct usb_mux *mux = &usb_muxes[port]; int res; ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_COUNT); res = mux->driver->init(mux->port_addr); if (res) CPRINTS("Error initializing mux port(%d): %d", port, res); }
static void ipc_init(void) { CPRINTS("ipc_init"); /* Initialize host args and memory map to all zero */ memset(ipc_host_args, 0, sizeof(*ipc_host_args)); memset(lpc_get_memmap_range(), 0, EC_MEMMAP_SIZE); setup_ipc(); }
enum cts_rc test_task_wait_event(void) { uint32_t event; wake_me_up = 1; /* Sleep and wait for interrupt. This shouldn't time out. */ event = task_wait_event(CTS_INTERRUPT_TRIGGER_DELAY_US * 2); if (event != TASK_EVENT_WAKE) { CPRINTS("Woken up by unexpected event: 0x%08x", event); return CTS_RC_FAILURE; } if (!got_interrupt) { CPRINTS("Interrupt context not detected"); return CTS_RC_TIMEOUT; } return CTS_RC_SUCCESS; }
static void i2c_event_handler(int port) { /* save and clear status */ i2c_sr1[port] = STM32_I2C_SR1(port); STM32_I2C_SR1(port) = 0; /* Confirm that you are not in master mode */ if (STM32_I2C_SR2(port) & (1 << 0)) { CPRINTS("slave ISR triggered in master mode, ignoring"); return; } /* transfer matched our slave address */ if (i2c_sr1[port] & (1 << 1)) { /* If it's a receiver slave */ if (!(STM32_I2C_SR2(port) & (1 << 2))) { dma_start_rx(dma_rx_option + port, sizeof(host_buffer), host_buffer); STM32_I2C_CR2(port) |= (1 << 11); rx_pending = 1; } /* cleared by reading SR1 followed by reading SR2 */ STM32_I2C_SR1(port); STM32_I2C_SR2(port); } else if (i2c_sr1[port] & (1 << 4)) { /* If it's a receiver slave */ if (!(STM32_I2C_SR2(port) & (1 << 2))) { /* Disable, and clear the DMA transfer complete flag */ dma_disable(DMAC_SLAVE_RX); dma_clear_isr(DMAC_SLAVE_RX); /* Turn off i2c's DMA flag */ STM32_I2C_CR2(port) &= ~(1 << 11); } /* clear STOPF bit by reading SR1 and then writing CR1 */ STM32_I2C_SR1(port); STM32_I2C_CR1(port) = STM32_I2C_CR1(port); } /* TxE event */ if (i2c_sr1[port] & (1 << 7)) { if (port == I2C2) { /* AP is waiting for EC response */ if (rx_pending) { i2c_process_command(); /* reset host buffer after end of transfer */ rx_pending = 0; } else { /* spurious read : return dummy value */ STM32_I2C_DR(port) = 0xec; } } } }
/** * Start the hang detect timers. */ static void hang_detect_start(const char *why) { /* If already active, don't restart timer */ if (active) return; if (hdparams.host_event_timeout_msec) { CPRINTS("hang detect started on %s (for event)", why); timeout_will_reboot = 0; active = 1; hook_call_deferred(hang_detect_deferred, hdparams.host_event_timeout_msec * MSEC); } else if (hdparams.warm_reboot_timeout_msec) { CPRINTS("hang detect started on %s (for reboot)", why); timeout_will_reboot = 1; active = 1; hook_call_deferred(hang_detect_deferred, hdparams.warm_reboot_timeout_msec * MSEC); } }
void board_hibernate(void) { CPRINTS("Triggering PMIC shutdown."); uart_flush_output(); /* Trigger PMIC shutdown. */ if (i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992, 0x49, 0x01)) { /* * If we can't tell the PMIC to shutdown, instead reset * and don't start the AP. Hopefully we'll be able to * communicate with the PMIC next time. */ CPRINTS("PMIC i2c failed."); system_reset(SYSTEM_RESET_LEAVE_AP_OFF); } /* Await shutdown. */ while (1) ; }
enum cts_rc test_nested_interrupt_low_high(void) { uint32_t event; event = task_wait_event(CTS_INTERRUPT_TRIGGER_DELAY_US * 4); if (event != TASK_EVENT_TIMER) { CPRINTS("Woken up by unexpected event: 0x%08x", event); return CTS_RC_FAILURE; } if (!got_interrupt) { CPRINTS("Interrupt context not detected"); return CTS_RC_TIMEOUT; } if (memcmp(state, "ABCD", sizeof(state))) { CPRINTS("State transition differs from expectation"); return CTS_RC_FAILURE; } return CTS_RC_SUCCESS; }
/** * Abort hash currently in progress, and invalidate any completed hash. */ static void vboot_hash_abort(void) { if (in_progress) { want_abort = 1; } else { CPRINTS("hash abort"); want_abort = 0; data_size = 0; hash = NULL; } }
static void host_command_init(void) { /* Initialize memory map ID area */ host_get_memmap(EC_MEMMAP_ID)[0] = 'E'; host_get_memmap(EC_MEMMAP_ID)[1] = 'C'; *host_get_memmap(EC_MEMMAP_ID_VERSION) = 1; *host_get_memmap(EC_MEMMAP_EVENTS_VERSION) = 1; host_set_single_event(EC_HOST_EVENT_INTERFACE_READY); CPRINTS("hostcmd init 0x%x", host_get_events()); }
/* Put a char to host buffer and send IRQ if specified. */ void lpc_keyboard_put_char(uint8_t chr, int send_irq) { NPCX_HIKDO = chr; CPRINTS("KB put %02x", chr); /* Enable OBE interrupt to detect host read data out */ SET_BIT(NPCX_HICTRL, NPCX_HICTRL_OBECIE); task_enable_irq(NPCX_IRQ_KBC_OBE); if (send_irq) { keyboard_irq_assert(); } }
void usb_mux_flip(int port) { const struct usb_mux *mux = &usb_muxes[port]; int res; mux_state_t mux_state; res = mux->driver->get(mux->port_addr, &mux_state); if (res) { CPRINTS("Error getting mux port(%d): %d", port, res); return; } if (mux_state & MUX_POLARITY_INVERTED) mux_state &= ~MUX_POLARITY_INVERTED; else mux_state |= MUX_POLARITY_INVERTED; res = mux->driver->set(mux->port_addr, mux_state); if (res) CPRINTS("Error setting mux port(%d): %d", port, res); }
static int si114x_revisions(const struct motion_sensor_t *s) { int val; int ret = raw_read8(s->port, s->addr, SI114X_REG_PART_ID, &val); if (ret != EC_SUCCESS) return ret; if (val != CONFIG_ALS_SI114X) { CPRINTS("invalid part"); return EC_ERROR_ACCESS_DENIED; } ret = raw_read8(s->port, s->port, s->addr, SI114X_REG_SEQ_ID, &val); if (ret != EC_SUCCESS) return ret; if (val < SI114X_SEQ_REV_A03) CPRINTS("WARNING: old sequencer revision"); return 0; }
/* When the calibration under runs, it means the fine trim code * has reached 0, but the clock is still too slow. Thus, * software must reduce the coarse trim code by 1 */ static void timer_sof_calibration_underrun_int(void) { unsigned coarseTrimValue = GREG32(XO, CLK_TIMER_RC_COARSE_ATE_TRIM); CPRINTS("%s: 0x%02x", __func__, coarseTrimValue); if (coarseTrimValue > 0x00) GREG32(XO, CLK_TIMER_RC_COARSE_ATE_TRIM) = coarseTrimValue - 1; GREG32(XO, DXO_INT_STATE) = GC_XO_DXO_INT_STATE_SLOW_CALIB_UNDERRUN_MASK; }
/** * Initialize on the specified I2C port. * * @param p the I2c port */ static void i2c_init_port(const struct i2c_port_t *p) { int port = p->port; enum stm32_i2c_clk_src src = I2C_CLK_SRC_48MHZ; enum i2c_freq freq; /* Enable clocks to I2C modules if necessary */ if (!(STM32_RCC_APB1ENR & (1 << (21 + port)))) STM32_RCC_APB1ENR |= 1 << (21 + port); if (port == STM32_I2C1_PORT) { #if defined(CONFIG_HOSTCMD_I2C_SLAVE_ADDR) && \ defined(CONFIG_LOW_POWER_IDLE) && \ (I2C_PORT_EC == STM32_I2C1_PORT) /* * Use HSI (8MHz) for i2c clock. This allows smooth wakeup * from STOP mode since HSI is only clock running immediately * upon exit from STOP mode. */ STM32_RCC_CFGR3 &= ~0x10; src = I2C_CLK_SRC_8MHZ; #else /* Use SYSCLK for i2c clock. */ STM32_RCC_CFGR3 |= 0x10; #endif } /* Configure GPIOs */ gpio_config_module(MODULE_I2C, 1); /* Set clock frequency */ switch (p->kbps) { case 1000: freq = I2C_FREQ_1000KHZ; break; case 400: freq = I2C_FREQ_400KHZ; break; case 100: freq = I2C_FREQ_100KHZ; break; default: /* unknown speed, defaults to 100kBps */ CPRINTS("I2C bad speed %d kBps", p->kbps); freq = I2C_FREQ_100KHZ; } /* Set up initial bus frequencies */ i2c_set_freq_port(p, src, freq); /* Set up default timeout */ i2c_set_timeout(port, 0); }
/** * Wait for the power button to be released * * @param timeout_us Timeout in microseconds, or -1 to wait forever * @return EC_SUCCESS if ok, or * EC_ERROR_TIMEOUT if power button failed to release */ int power_button_wait_for_release(int timeout_us) { timestamp_t deadline; timestamp_t now = get_time(); deadline.val = now.val + timeout_us; while (!power_button_is_stable || power_button_is_pressed()) { now = get_time(); if (timeout_us < 0) { task_wait_event(-1); } else if (timestamp_expired(deadline, &now) || (task_wait_event(deadline.val - now.val) == TASK_EVENT_TIMER)) { CPRINTS("power button not released in time"); return EC_ERROR_TIMEOUT; } } CPRINTS("power button released in time"); return EC_SUCCESS; }
void board_print_tcpc_fw_version(int port) { int rv; int version; if (port) rv = ps8751_tcpc_get_fw_version(port, &version); else rv = anx74xx_tcpc_get_fw_version(port, &version); if (!rv) CPRINTS("TCPC p%d FW VER: 0x%x", port, version); }
/** * Set PWM duty cycle. * * @param ch operation channel * @param percent duty cycle percent * @return none */ void pwm_set_duty(enum pwm_channel ch, int percent) { uint32_t resolution = 0; uint16_t duty_cycle = 0; CPRINTS("pwm0=%d", percent); /* Assume the fan control is active high and invert it ourselves */ if (pwm_channels[ch].flags & PWM_CONFIG_ACTIVE_LOW) SET_BIT(NPCX_PWMCTL(pwm_channels[ch].channel), NPCX_PWMCTL_INVP); else CLEAR_BIT(NPCX_PWMCTL(pwm_channels[ch].channel), NPCX_PWMCTL_INVP); if (percent < 0) percent = 0; /* (Benson_TBD_14) if 100% make mft cannot get TCRB, * it will need to change to 99% */ else if (percent > 100) percent = 100; CPRINTS("pwm1duty=%d", percent); resolution = NPCX_CTR(pwm_channels[ch].channel) + 1; duty_cycle = percent*resolution/100; CPRINTS("freq=0x%x", pwm_channels[ch].freq); CPRINTS("resolution=%d", resolution); CPRINTS("duty_cycle=%d", duty_cycle); /* Set the duty cycle */ /* (Benson_TBD_14) Always enable the fan channel or not */ if (percent) { NPCX_DCR(pwm_channels[ch].channel) = (duty_cycle - 1); pwm_enable(ch, 1); } else { NPCX_DCR(pwm_channels[ch].channel) = 0; pwm_enable(ch, 0); } }
/* For LPC host register initial via SIB module */ void lpc_host_register_init(void) { /* enable ACPI*/ lpc_sib_write_reg(SIO_OFFSET, 0x07, 0x11); lpc_sib_write_reg(SIO_OFFSET, 0x30, 0x01); /* enable KBC*/ lpc_sib_write_reg(SIO_OFFSET, 0x07, 0x05); lpc_sib_write_reg(SIO_OFFSET, 0x30, 0x01); lpc_sib_write_reg(SIO_OFFSET, 0x07, 0x06); lpc_sib_write_reg(SIO_OFFSET, 0x30, 0x01); /* Setting PMC2 */ /* LDN register = 0x12(PMC2) */ lpc_sib_write_reg(SIO_OFFSET, 0x07, 0x12); /* CMD port is 0x200 */ lpc_sib_write_reg(SIO_OFFSET, 0x60, 0x02); lpc_sib_write_reg(SIO_OFFSET, 0x61, 0x00); /* Data port is 0x204 */ lpc_sib_write_reg(SIO_OFFSET, 0x62, 0x02); lpc_sib_write_reg(SIO_OFFSET, 0x63, 0x04); /* enable PMC2 */ lpc_sib_write_reg(SIO_OFFSET, 0x30, 0x01); /* Setting SHM */ /* LDN register = 0x0F(SHM) */ lpc_sib_write_reg(SIO_OFFSET, 0x07, 0x0F); /* WIN1&2 mapping to IO */ lpc_sib_write_reg(SIO_OFFSET, 0xF1, lpc_sib_read_reg(SIO_OFFSET, 0xF1) | 0x30); /* Host Command on the IO:0x0800 */ lpc_sib_write_reg(SIO_OFFSET, 0xF7, 0x00); lpc_sib_write_reg(SIO_OFFSET, 0xF6, 0x00); lpc_sib_write_reg(SIO_OFFSET, 0xF5, 0x08); lpc_sib_write_reg(SIO_OFFSET, 0xF4, 0x00); /* WIN1 as Host Command on the IO:0x0800 */ lpc_sib_write_reg(SIO_OFFSET, 0xFB, 0x00); lpc_sib_write_reg(SIO_OFFSET, 0xFA, 0x00); /* WIN2 as MEMMAP on the IO:0x900 */ lpc_sib_write_reg(SIO_OFFSET, 0xF9, 0x09); lpc_sib_write_reg(SIO_OFFSET, 0xF8, 0x00); /* enable SHM */ lpc_sib_write_reg(SIO_OFFSET, 0x30, 0x01); /* An active LRESET or PLTRST does not generate host domain reset */ SET_BIT(NPCX_RSTCTL, NPCX_RSTCTL_LRESET_PLTRST_MODE); CPRINTS("Host settings are done!"); }