Exemple #1
0
/* Initialize board. */
static void board_init(void)
{
	/* Enable PD MCU interrupt */
	gpio_enable_interrupt(GPIO_PD_MCU_INT);

	/* Enable VBUS interrupt */
	gpio_enable_interrupt(GPIO_USB_C0_VBUS_WAKE_L);
	gpio_enable_interrupt(GPIO_USB_C1_VBUS_WAKE_L);

	/* Enable pericom BC1.2 interrupts */
	gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L);
	gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L);

	/* Provide AC status to the PCH */
	gpio_set_level(GPIO_PCH_ACOK, extpower_is_present());

	/* Proto board workarounds */
	if (system_get_board_version() == 0) {
		/* Disable interrupt for SLP_S0 */
		gpio_set_flags(GPIO_PCH_SLP_S0_L,
			       GPIO_INPUT | GPIO_PULL_DOWN);

		/* Add internal pullup on PLATFORM_EC_PROCHOT */
		gpio_set_flags(GPIO_PLATFORM_EC_PROCHOT,
			       GPIO_INPUT | GPIO_PULL_UP);
	}
}
Exemple #2
0
int board_get_version(void)
{
	static int version = BOARD_VERSION_UNKNOWN;
	int mv, i;

	if (version != BOARD_VERSION_UNKNOWN)
		return version;

	/* FIXME(dhendrix): enable ADC */
	gpio_set_flags(GPIO_EC_BRD_ID_EN_ODL, GPIO_ODR_HIGH);
	gpio_set_level(GPIO_EC_BRD_ID_EN_ODL, 0);
	/* Wait to allow cap charge */
	msleep(1);
	mv = adc_read_channel(ADC_BOARD_ID);
	/* FIXME(dhendrix): disable ADC */
	gpio_set_level(GPIO_EC_BRD_ID_EN_ODL, 1);
	gpio_set_flags(GPIO_EC_BRD_ID_EN_ODL, GPIO_INPUT);

	if (mv == ADC_READ_ERROR) {
		version = BOARD_VERSION_UNKNOWN;
		return version;
	}

	for (i = 0; i < BOARD_VERSION_COUNT; i++) {
		if (mv < reef_board_versions[i].thresh_mv) {
			version = reef_board_versions[i].version;
			break;
		}
	}

	CPRINTS("Board version: %d\n", version);
	return version;
}
Exemple #3
0
static int cmd_btn_press(int argc, char **argv)
{
	enum gpio_signal gpio;
	char *e;
	int v;

	if (argc < 2)
		return EC_ERROR_PARAM_COUNT;

	if (!strcasecmp(argv[1], "volup"))
		gpio = GPIO_BTN_VOLU_L;
	else if (!strcasecmp(argv[1], "voldown"))
		gpio = GPIO_BTN_VOLD_L;
	else
		return EC_ERROR_PARAM1;

	if (argc < 3) {
		/* Just reading */
		ccprintf("Button %s pressed = %d\n", argv[1],
						     !gpio_get_level(gpio));
		return EC_SUCCESS;
	}

	v = strtoi(argv[2], &e, 0);
	if (*e)
		return EC_ERROR_PARAM2;

	if (v)
		gpio_set_flags(gpio, GPIO_OUT_LOW);
	else
		gpio_set_flags(gpio, GPIO_INPUT | GPIO_PULL_UP);

	return EC_SUCCESS;
}
Exemple #4
0
/**
 * Power off the AP
 */
static void power_off(void)
{
	unsigned int power_off_timeout = 100; /* ms */

	/* Call hooks before we drop power rails */
	hook_notify(HOOK_CHIPSET_SHUTDOWN);
	/* switch off all rails */
	chipset_turn_off_power_rails();
	/* Change SUSPEND_L and EC_INT pin to high-Z to reduce power draw. */
	gpio_set_flags(GPIO_SUSPEND_L, GPIO_INPUT);
	gpio_set_flags(GPIO_EC_INT_L, GPIO_INPUT);

	/* Wait till we actually turn off to not mess up the state machine. */
	while (power_get_signals() & IN_POWER_GOOD) {
		msleep(1);
		power_off_timeout--;
		ASSERT(power_off_timeout);
	}

	lid_opened = 0;
	enable_sleep(SLEEP_MASK_AP_RUN);
	powerled_set_state(POWERLED_STATE_OFF);

	CPRINTS("power shutdown complete");
}
Exemple #5
0
/**
 * Enable and disable SPI for case closed debugging.  This forces the AP into
 * reset while SPI is enabled, thus preventing contention on the SPI interface.
 */
void usb_spi_board_enable(struct usb_spi_config const *config)
{
	/* Place AP into reset */
	gpio_set_level(GPIO_PMIC_WARM_RESET_L, 0);

	/* Configure SPI GPIOs */
	gpio_config_module(MODULE_SPI_FLASH, 1);
	gpio_set_flags(SPI_FLASH_DEVICE->gpio_cs, GPIO_OUT_HIGH);

	/* Set all four SPI pins to high speed */
	/* pins B10/B14/B15 and B9 */
	STM32_GPIO_OSPEEDR(GPIO_B) |= 0xf03c0000;

	/* Enable clocks to SPI2 module */
	STM32_RCC_APB1ENR |= STM32_RCC_PB1_SPI2;

	/* Reset SPI2 */
	STM32_RCC_APB1RSTR |= STM32_RCC_PB1_SPI2;
	STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2;

	/* Enable SPI LDO to power the flash chip */
	gpio_set_level(GPIO_VDDSPI_EN, 1);

	spi_enable(CONFIG_SPI_FLASH_PORT, 1);
}
Exemple #6
0
void board_hibernate_late(void)
{
	int i;
	const uint32_t hibernate_pins[][2] = {
		/* Turn off LEDs in hibernate */
		{GPIO_BAT_LED_BLUE, GPIO_INPUT | GPIO_PULL_UP},
		{GPIO_BAT_LED_AMBER, GPIO_INPUT | GPIO_PULL_UP},
		{GPIO_LID_OPEN, GPIO_INT_RISING | GPIO_PULL_DOWN},

		/*
		 * BD99956 handles charge input automatically. We'll disable
		 * charge output in hibernate. Charger will assert ACOK_OD
		 * when VBUS or VCC are plugged in.
		 */
		{GPIO_USB_C0_5V_EN,       GPIO_INPUT  | GPIO_PULL_DOWN},
		{GPIO_USB_C1_5V_EN,       GPIO_INPUT  | GPIO_PULL_DOWN},
	};

	/* Change GPIOs' state in hibernate for better power consumption */
	for (i = 0; i < ARRAY_SIZE(hibernate_pins); ++i)
		gpio_set_flags(hibernate_pins[i][0], hibernate_pins[i][1]);

	gpio_config_module(MODULE_KEYBOARD_SCAN, 0);

	/*
	 * Calling gpio_config_module sets disabled alternate function pins to
	 * GPIO_INPUT.  But to prevent keypresses causing leakage currents
	 * while hibernating we want to enable GPIO_PULL_UP as well.
	 */
	gpio_set_flags_by_mask(0x2, 0x03, GPIO_INPUT | GPIO_PULL_UP);
	gpio_set_flags_by_mask(0x1, 0xFF, GPIO_INPUT | GPIO_PULL_UP);
	gpio_set_flags_by_mask(0x0, 0xE0, GPIO_INPUT | GPIO_PULL_UP);
}
Exemple #7
0
enum cts_rc read_low_test(void)
{
	gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_LOW);
	gpio_set_level(GPIO_OUTPUT_TEST, 0);
	msleep(READ_WAIT_TIME_MS*2);
	return CTS_RC_SUCCESS;
}
Exemple #8
0
/**
 * Power off the AP
 */
static void power_off(void)
{
	/* Call hooks before we drop power rails */
	hook_notify(HOOK_CHIPSET_SHUTDOWN);
	/* switch off all rails */
	chipset_turn_off_power_rails();
	/* Change SUSPEND_L and EC_INT pin to high-Z to reduce power draw. */
	gpio_set_flags(GPIO_SUSPEND_L, GPIO_INPUT);
	gpio_set_flags(GPIO_EC_INT, GPIO_INPUT);

	lid_opened = 0;
	enable_sleep(SLEEP_MASK_AP_RUN);
	powerled_set_state(POWERLED_STATE_OFF);

	CPRINTS("power shutdown complete");
}
Exemple #9
0
static void board_handle_reboot(void)
{
	int flags;

	if (system_jumped_to_this_image())
		return;

	if (system_get_board_version() < BOARD_MIN_ID_LOD_EN)
		return;

	/* Interrogate current reset flags from previous reboot. */
	flags = system_get_reset_flags();

	if (!(flags & PMIC_RESET_FLAGS))
		return;

	/* Preserve AP off request. */
	if (flags & RESET_FLAG_AP_OFF)
		chip_save_reset_flags(RESET_FLAG_AP_OFF);

	ccprintf("Restarting system with PMIC.\n");
	/* Flush console */
	cflush();

	/* Bring down all rails but RTC rail (including EC power). */
	gpio_set_flags(GPIO_BATLOW_L_PMIC_LDO_EN, GPIO_OUT_HIGH);
	while (1)
		; /* wait here */
}
Exemple #10
0
static int command_gpio_set(int argc, char **argv)
{
#ifdef CONFIG_CMD_GPIO_EXTENDED
	int gpio;
	int flags = 0;
	int af = -1;
	char *e;

	if (argc < 3)
		return EC_ERROR_PARAM_COUNT;

	gpio = find_signal_by_name(argv[1]);
	if (gpio == GPIO_COUNT)
		return EC_ERROR_PARAM1;

	if (strcasecmp(argv[2], "IN") == 0)
		flags = GPIO_INPUT;
	else if (strcasecmp(argv[2], "1") == 0)
		flags = GPIO_OUT_HIGH;
	else if (strcasecmp(argv[2], "0") == 0)
		flags = GPIO_OUT_LOW;
	else if (strcasecmp(argv[2], "A") == 0)
		flags = GPIO_ANALOG;
	else if (strcasecmp(argv[2], "ALT") == 0) {
		if (argc >= 4) {
			af = strtoi(argv[3], &e, 0);
			if (*e || af < 0 || af > 5)
				return EC_ERROR_PARAM2;
		}
		flags = GPIO_ALTERNATE;
	} else
		return EC_ERROR_PARAM2;

	/* Update alt function if requested. */
	if (af >= 0) {
		const struct gpio_info *g = gpio_list + gpio;

		gpio_set_alternate_function(g->port, g->mask, af);
	}
	/* Update GPIO flags. */
	gpio_set_flags(gpio, flags);
#else
	char *e;
	int v;

	if (argc < 3)
		return EC_ERROR_PARAM_COUNT;

	v = strtoi(argv[2], &e, 0);
	if (*e)
		return EC_ERROR_PARAM2;

	if (set(argv[1], v) != EC_SUCCESS)
		return EC_ERROR_PARAM1;
#endif
	return EC_SUCCESS;
}
Exemple #11
0
static enum cts_rc timer_calibration_test(void)
{
	gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_HIGH);

	sync();
	usleep(SECOND);
	gpio_set_level(GPIO_OUTPUT_TEST, 0);

	return CTS_RC_SUCCESS;
}
Exemple #12
0
static void spi_chipset_shutdown(void)
{
	enabled = 0;
	state = SPI_STATE_DISABLED;

	/* Disable pullup and interrupts on NSS */
	gpio_set_flags(GPIO_SPI1_NSS, GPIO_INPUT);

	/* Set SPI pins to inputs so we don't leak power when AP is off */
	gpio_config_module(MODULE_SPI, 0);
}
Exemple #13
0
enum cts_rc set_low_test(void)
{
	int level;

	gpio_set_flags(GPIO_INPUT_TEST, GPIO_INPUT | GPIO_PULL_UP);
	msleep(READ_WAIT_TIME_MS);
	level = gpio_get_level(GPIO_INPUT_TEST);
	if (!level)
		return CTS_RC_SUCCESS;
	else
		return CTS_RC_FAILURE;
}
Exemple #14
0
/**
 * Set SPI enabled.
 *
 * @spi_port port to act on. Only one port supported, one gpio.
 * @param   enable enabled flag
 * @return  success
 */
int spi_enable(int port, int enable)
{
	int i;
	enum gpio_signal gpio;

	if (enable) {
		/* Enabling spi module for gpio configuration */
		gpio_config_module(MODULE_SPI, 1);
		/* GPIO No SPI Select */
		CLEAR_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_GPIO_NO_SPIP);

		for (i = 0; i < spi_devices_used; i++) {
			if (spi_devices[i].port != port)
				continue;
			gpio = spi_devices[i].gpio_cs;
			/* Make sure CS# is a GPIO output mode. */
			gpio_set_flags(gpio, GPIO_OUTPUT);
			/* Make sure CS# is deselected */
			gpio_set_level(gpio, 1);
		}
		/* Enabling spi module */
		SET_BIT(NPCX_SPI_CTL1, NPCX_SPI_CTL1_SPIEN);
	} else {
		/* Disabling spi module */
		CLEAR_BIT(NPCX_SPI_CTL1, NPCX_SPI_CTL1_SPIEN);
		for (i = 0; i < spi_devices_used; i++) {
			if (spi_devices[i].port != port)
				continue;
			gpio = spi_devices[i].gpio_cs;
			/* Make sure CS# is deselected */
			gpio_set_level(gpio, 1);
			gpio_set_flags(gpio, GPIO_ODR_HIGH);
		}
		/* Disabling spi module for gpio configuration */
		gpio_config_module(MODULE_SPI, 0);
		/* GPIO No SPI Select */
		SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_GPIO_NO_SPIP);
	}
	return EC_SUCCESS;
}
Exemple #15
0
int board_get_version(void)
{
	static int ver;

	if (!ver) {
		/*
		 * read the board EC ID on the tristate strappings
		 * using ternary encoding: 0 = 0, 1 = 1, Hi-Z = 2
		 */
		uint8_t id0 = 0, id1 = 0;
		gpio_set_flags(GPIO_BOARD_ID0, GPIO_PULL_DOWN | GPIO_INPUT);
		gpio_set_flags(GPIO_BOARD_ID1, GPIO_PULL_DOWN | GPIO_INPUT);
		usleep(100);
		id0 = gpio_get_level(GPIO_BOARD_ID0);
		id1 = gpio_get_level(GPIO_BOARD_ID1);
		gpio_set_flags(GPIO_BOARD_ID0, GPIO_PULL_UP | GPIO_INPUT);
		gpio_set_flags(GPIO_BOARD_ID1, GPIO_PULL_UP | GPIO_INPUT);
		usleep(100);
		id0 = gpio_get_level(GPIO_BOARD_ID0) && !id0 ? 2 : id0;
		id1 = gpio_get_level(GPIO_BOARD_ID1) && !id1 ? 2 : id1;
		gpio_set_flags(GPIO_BOARD_ID0, GPIO_INPUT);
		gpio_set_flags(GPIO_BOARD_ID1, GPIO_INPUT);
		ver = id1 * 3 + id0;
		CPRINTS("Board ID = %d", ver);
	}

	return ver;
}
Exemple #16
0
/**
 * Flush an SPI transaction and receive data from slave.
 *
 * @param   spi_device  device to talk to
 * @param   txdata  transfer data
 * @param   txlen   transfer length
 * @param   rxdata  receive data
 * @param   rxlen   receive length
 * @return  success
 * @notes   set master transaction mode in npcx chip
 */
int spi_transaction(const struct spi_device_t *spi_device,
		const uint8_t *txdata, int txlen,
		uint8_t *rxdata, int rxlen)
{
	int i = 0;
	enum gpio_signal gpio = spi_device->gpio_cs;

	/* Make sure CS# is a GPIO output mode. */
	gpio_set_flags(gpio, GPIO_OUTPUT);
	/* Make sure CS# is deselected */
	gpio_set_level(gpio, 1);
	/* Cleaning junk data in the buffer */
	clear_databuf();
	/* Assert CS# to start transaction */
	gpio_set_level(gpio, 0);
	CPRINTS("NPCX_SPI_DATA=%x", NPCX_SPI_DATA);
	CPRINTS("NPCX_SPI_CTL1=%x", NPCX_SPI_CTL1);
	CPRINTS("NPCX_SPI_STAT=%x", NPCX_SPI_STAT);
	/* Writing the data */
	for (i = 0; i < txlen; ++i) {
		/* Making sure we can write */
		while (IS_BIT_SET(NPCX_SPI_STAT, NPCX_SPI_STAT_BSY))
			;
		/* Write the data */
		NPCX_SPI_DATA =  txdata[i];
		CPRINTS("txdata[i]=%x", txdata[i]);
		/* Waiting till reading is finished */
		while (!IS_BIT_SET(NPCX_SPI_STAT, NPCX_SPI_STAT_RBF))
			;
		/* Reading the (dummy) data */
		clear_databuf();
	}
	CPRINTS("write end");
	/* Reading the data */
	for (i = 0; i < rxlen; ++i) {
		/* Making sure we can write */
		while (IS_BIT_SET(NPCX_SPI_STAT, NPCX_SPI_STAT_BSY))
			;
		/* Write the (dummy) data */
		NPCX_SPI_DATA =  0;
		/* Wait till reading is finished */
		while (!IS_BIT_SET(NPCX_SPI_STAT, NPCX_SPI_STAT_RBF))
			;
		/* Reading the data */
		rxdata[i] = (uint8_t)NPCX_SPI_DATA;
		CPRINTS("rxdata[i]=%x", rxdata[i]);
	}
	/* Deassert CS# (high) to end transaction */
	gpio_set_level(gpio, 1);

	return EC_SUCCESS;
}
Exemple #17
0
static void spi_chipset_startup(void)
{
	/* Enable pullup and interrupts on NSS */
	gpio_set_flags(GPIO_SPI1_NSS, GPIO_INT_BOTH | GPIO_PULL_UP);

	/* Set SPI pins to alternate function */
	gpio_config_module(MODULE_SPI, 1);

	/* Set up for next transaction */
	setup_for_transaction();

	enabled = 1;
}
Exemple #18
0
/*
 *  This is for NOT having enough hibernate (more precisely, the stand-by mode)
 *  wake-up source pin. STM32L100 supports 3 wake-up source pins:
 *
 *     WKUP1 (PA0)  -- used for ACOK_PMU
 *     WKUP2 (PC13) -- used for LID_OPEN
 *     WKUP3 (PE6)  -- cannot be used due to IC package.
 *
 *  However, we need the power button as a wake-up source as well and there is
 *  no available pin for us (we don't want to move the ACOK_PMU pin).
 *
 *  Fortunately, the STM32L is low-power enough so that we don't need the
 *  super-low-power mode. So, we fake this hibernate mode and accept the
 *  following wake-up source.
 *
 *     RTC alarm  (faked as well).
 *     Power button
 *     Lid open
 *     AC detected
 *
 *  The original issue is here: crosbug.com/p/25435.
 */
void __enter_hibernate(uint32_t seconds, uint32_t microseconds)
{
	int i;
	fake_hibernate = 1;

#ifdef CONFIG_POWER_COMMON
	/*
	 * A quick hack to stop annoying messages from charger task.
	 *
	 * When the battery is under 3%, the power task would call
	 * power_off() to shutdown AP. However, the power_off() would
	 * notify the HOOK_CHIPSET_SHUTDOWN, where the last hook is
	 * charge_shutdown() and it hibernates the power task (infinite
	 * loop -- not real CPU hibernate mode). Unfortunately, the
	 * charger task is still running. It keeps generating annoying
	 * log message.
	 *
	 * Thus, the hack is to set the power state machine (before we
	 * enter infinite loop) so that the charger task thinks the AP
	 * is off and stops generating messages.
	 */
	power_set_state(POWER_G3);
#endif

	/*
	 * Change keyboard outputs to high-Z to reduce power draw.
	 * We don't need corresponding code to change them back,
	 * because fake hibernate is always exited with a reboot.
	 *
	 * A little hacky to do this here.
	 */
	for (i = GPIO_KB_OUT00; i < GPIO_KB_OUT00 + KEYBOARD_COLS; i++)
		gpio_set_flags(i, GPIO_INPUT);

	ccprints("fake hibernate. waits for power button/lid/RTC/AC");
	cflush();

	if (seconds || microseconds) {
		if (seconds)
			sleep(seconds);
		if (microseconds)
			usleep(microseconds);
	} else {
		while (1)
			task_wait_event(-1);
	}

	ccprints("fake RTC alarm fires. resets EC");
	cflush();
	system_reset(SYSTEM_RESET_HARD);
}
Exemple #19
0
static void board_vbus_update_source_current(int port)
{
	enum gpio_signal gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN;
	int flags = (vbus_rp[port] == TYPEC_RP_1A5 && vbus_en[port]) ?
		(GPIO_INPUT | GPIO_PULL_UP) : (GPIO_OUTPUT | GPIO_PULL_UP);

	/*
	 * Driving USB_Cx_5V_EN high, actually put a 16.5k resistance
	 * (2x 33k in parallel) on the NX5P3290 load switch ILIM pin,
	 * setting a minimum OCP current of 3186 mA.
	 * Putting an internal pull-up on USB_Cx_5V_EN, effectively put a 33k
	 * resistor on ILIM, setting a minimum OCP current of 1505 mA.
	 */
	gpio_set_level(gpio, vbus_en[port]);
	gpio_set_flags(gpio, flags);
}
Exemple #20
0
void usb_spi_board_disable(struct usb_spi_config const *config)
{
	spi_enable(CONFIG_SPI_FLASH_PORT, 0);

	/* Disable SPI LDO */
	gpio_set_level(GPIO_VDDSPI_EN, 0);

	/* Disable clocks to SPI2 module */
	STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2;

	/* Release SPI GPIOs */
	gpio_config_module(MODULE_SPI_FLASH, 0);
	gpio_set_flags(SPI_FLASH_DEVICE->gpio_cs, GPIO_INPUT);

	/* Release AP from reset */
	gpio_set_level(GPIO_PMIC_WARM_RESET_L, 1);
}
Exemple #21
0
void cts_task(void)
{
	enum cts_rc rc;
	int i;

	gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_HIGH);

	for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
		gpio_set_level(GPIO_OUTPUT_TEST, 1);
		gpio_set_level(GPIO_CTS_IRQ2, 1);
		sync();
		rc = tests[i].run();
		CPRINTF("\n%s %d\n", tests[i].name, rc);
		cflush();
	}

	CPRINTS("Interrupt test suite finished");
	cflush();

	while (1) {
		watchdog_reload();
		sleep(1);
	}
}
Exemple #22
0
void system_hibernate(uint32_t seconds, uint32_t microseconds)
{
	int i;

#ifdef CONFIG_HOSTCMD_PD
	/* Inform the PD MCU that we are going to hibernate. */
	host_command_pd_request_hibernate();
	/* Wait to ensure exchange with PD before hibernating. */
	msleep(100);
#endif

	cflush();

	if (board_hibernate)
		board_hibernate();

	/* Disable interrupts */
	interrupt_disable();
	for (i = 0; i <= 92; ++i) {
		task_disable_irq(i);
		task_clear_pending_irq(i);
	}

	for (i = 8; i <= 23; ++i)
		MEC1322_INT_DISABLE(i) = 0xffffffff;

	MEC1322_INT_BLK_DIS |= 0xffff00;

	/* Power down ADC VREF */
	MEC1322_EC_ADC_VREF_PD |= 1;

	/* Assert nSIO_RESET */
	MEC1322_PCR_PWR_RST_CTL |= 1;

	/* Disable UART */
	MEC1322_UART_ACT &= ~0x1;
	MEC1322_LPC_ACT &= ~0x1;

	/* Disable JTAG */
	MEC1322_EC_JTAG_EN &= ~1;

	/* Disable 32KHz clock */
	MEC1322_VBAT_CE &= ~0x2;

	/* Stop watchdog */
	MEC1322_WDG_CTL &= ~1;

	/* Stop timers */
	MEC1322_TMR32_CTL(0) &= ~1;
	MEC1322_TMR32_CTL(1) &= ~1;
	MEC1322_TMR16_CTL(0) &= ~1;

	/* Power down ADC */
	MEC1322_ADC_CTRL &= ~1;

	/* Disable blocks */
	MEC1322_PCR_CHIP_SLP_EN |= 0x3;
	MEC1322_PCR_EC_SLP_EN |= MEC1322_PCR_EC_SLP_EN_SLEEP;
	MEC1322_PCR_HOST_SLP_EN |= MEC1322_PCR_HOST_SLP_EN_SLEEP;
	MEC1322_PCR_EC_SLP_EN2 |= MEC1322_PCR_EC_SLP_EN2_SLEEP;
	MEC1322_PCR_SLOW_CLK_CTL &= 0xfffffc00;

	/* Set sleep state */
	MEC1322_PCR_SYS_SLP_CTL = (MEC1322_PCR_SYS_SLP_CTL & ~0x7) | 0x2;
	CPU_SCB_SYSCTRL |= 0x4;

	/* Setup GPIOs for hibernate */
	if (board_hibernate_late)
		board_hibernate_late();

#ifdef CONFIG_USB_PD_PORT_COUNT
	/*
	 * Leave USB-C charging enabled in hibernate, in order to
	 * allow wake-on-plug. 5V enable must be pulled low.
	 */
#if CONFIG_USB_PD_PORT_COUNT > 0
	gpio_set_flags(GPIO_USB_C0_5V_EN, GPIO_PULL_DOWN | GPIO_INPUT);
	gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 0);
#endif
#if CONFIG_USB_PD_PORT_COUNT > 1
	gpio_set_flags(GPIO_USB_C1_5V_EN, GPIO_PULL_DOWN | GPIO_INPUT);
	gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, 0);
#endif
#endif /* CONFIG_USB_PD_PORT_COUNT */

	if (hibernate_wake_pins_used > 0) {
		for (i = 0; i < hibernate_wake_pins_used; ++i) {
			const enum gpio_signal pin = hibernate_wake_pins[i];

			gpio_reset(pin);
			gpio_enable_interrupt(pin);
		}

		interrupt_enable();
		task_enable_irq(MEC1322_IRQ_GIRQ8);
		task_enable_irq(MEC1322_IRQ_GIRQ9);
		task_enable_irq(MEC1322_IRQ_GIRQ10);
		task_enable_irq(MEC1322_IRQ_GIRQ11);
		task_enable_irq(MEC1322_IRQ_GIRQ20);
	}

	if (seconds || microseconds) {
		MEC1322_INT_BLK_EN |= 1 << 17;
		MEC1322_INT_ENABLE(17) |= 1 << 20;
		interrupt_enable();
		task_enable_irq(MEC1322_IRQ_HTIMER);
		if (seconds > 2) {
			ASSERT(seconds <= 0xffff / 8);
			MEC1322_HTIMER_CONTROL = 1;
			MEC1322_HTIMER_PRELOAD =
				(seconds * 8 + microseconds / 125000);
		} else {
			MEC1322_HTIMER_CONTROL = 0;
			MEC1322_HTIMER_PRELOAD =
				(seconds * 1000000 + microseconds) * 2 / 71;
		}
	}

	asm("wfi");

	/* Use 48MHz clock to speed through wake-up */
	MEC1322_PCR_PROC_CLK_CTL = 1;

	/* Reboot */
	_system_reset(0, 1);

	/* We should never get here. */
	while (1)
		;
}
Exemple #23
0
enum power_state power_handle_state(enum power_state state)
{
	int value;
	static int boot_from_g3;

	switch (state) {
	case POWER_G3:
		boot_from_g3 = check_for_power_on_event();
		if (boot_from_g3)
			return POWER_G3S5;
		break;

	case POWER_G3S5:
		return POWER_S5;

	case POWER_S5:
		if (boot_from_g3) {
			value = boot_from_g3;
			boot_from_g3 = 0;
		} else {
			value = check_for_power_on_event();
		}

		if (value) {
			CPRINTS("power on %d", value);
			return POWER_S5S3;
		}
		return state;

	case POWER_S5S3:
		hook_notify(HOOK_CHIPSET_PRE_INIT);

		power_on();

		disable_sleep(SLEEP_MASK_AP_RUN);
		powerled_set_state(POWERLED_STATE_ON);

		if (power_wait_signals(IN_POWER_GOOD) == EC_SUCCESS) {
			CPRINTS("POWER_GOOD seen");
			if (power_button_wait_for_release(
					DELAY_SHUTDOWN_ON_POWER_HOLD) ==
					EC_SUCCESS) {
				power_button_was_pressed = 0;
				set_pmic_pwron(0);

				/* setup misc gpio for S3/S0 functionality */
				gpio_set_flags(GPIO_SUSPEND_L, GPIO_INPUT
					| GPIO_INT_BOTH | GPIO_PULL_DOWN);
				gpio_set_flags(GPIO_EC_INT_L, GPIO_OUTPUT
						| GPIO_OUT_HIGH);

				/* Call hooks now that AP is running */
				hook_notify(HOOK_CHIPSET_STARTUP);

				return POWER_S3;
			} else {
				CPRINTS("long-press button, shutdown");
				power_off();
				/*
				 * Since the AP may be up already, return S0S3
				 * state to go through the suspend hook.
				 */
				return POWER_S0S3;
			}
		} else {
			CPRINTS("POWER_GOOD not seen in time");
		}

		chipset_turn_off_power_rails();
		return POWER_S5;

	case POWER_S3:
		if (!(power_get_signals() & IN_POWER_GOOD))
			return POWER_S3S5;
		else if (!(power_get_signals() & IN_SUSPEND))
			return POWER_S3S0;
		return state;

	case POWER_S3S0:
		powerled_set_state(POWERLED_STATE_ON);
		hook_notify(HOOK_CHIPSET_RESUME);
		return POWER_S0;

	case POWER_S0:
		value = check_for_power_off_event();
		if (value) {
			CPRINTS("power off %d", value);
			power_off();
			return POWER_S0S3;
		} else if (power_get_signals() & IN_SUSPEND)
			return POWER_S0S3;
		return state;

	case POWER_S0S3:
		if (lid_is_open())
			powerled_set_state(POWERLED_STATE_SUSPEND);
		else
			powerled_set_state(POWERLED_STATE_OFF);
		/* Call hooks here since we don't know it prior to AP suspend */
		hook_notify(HOOK_CHIPSET_SUSPEND);
		return POWER_S3;

	case POWER_S3S5:
		power_button_wait_for_release(-1);
		power_button_was_pressed = 0;
		return POWER_S5;

	case POWER_S5G3:
		return POWER_G3;
	}

	return state;
}
Exemple #24
0
enum cts_rc od_read_high_test(void)
{
	gpio_set_flags(GPIO_INPUT_TEST, GPIO_OUTPUT | GPIO_ODR_LOW);
	msleep(READ_WAIT_TIME_MS*2);
	return CTS_RC_SUCCESS;
}