Esempio n. 1
0
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);
	}
}
Esempio n. 2
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;
}
Esempio n. 3
0
/**
 * 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();
	}
}
Esempio n. 4
0
/**
 * 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");
}
Esempio n. 5
0
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);
}
Esempio n. 7
0
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");
}
Esempio n. 8
0
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;
}
Esempio n. 9
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;
}
Esempio n. 10
0
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;
}
Esempio n. 11
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);
}
Esempio n. 12
0
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);
}
Esempio n. 13
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);
}
Esempio n. 14
0
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();
}
Esempio n. 15
0
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;
}
Esempio n. 16
0
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;
			}
		}
	}
}
Esempio n. 17
0
/**
 * 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);
	}
}
Esempio n. 18
0
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)
		;
}
Esempio n. 19
0
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;
}
Esempio n. 20
0
/**
 * 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());
}
Esempio n. 22
0
/* 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();
	}
}
Esempio n. 23
0
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);
}
Esempio n. 24
0
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;
}
Esempio n. 25
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;
}
Esempio n. 26
0
/**
 * 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);
}
Esempio n. 27
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;
}
Esempio n. 28
0
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);
}
Esempio n. 29
0
File: pwm.c Progetto: thehobn/ec
/**
 * 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);
	}
}
Esempio n. 30
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!");

}