Esempio n. 1
0
void soc_sleep_requested(bool ready_to_sleep)
{
	unsigned int key;

	QM_PUTS("SoC sleep requested");

	if (!ready_to_sleep) {
		QM_PUTS("Sleep NAK'd");
		send_msg(SLEEP_NAK);
	} else {
		key = qm_irq_lock();
		send_msg(SLEEP_ACK);
		soc_sleep(CORE_SLEEP);
		qm_irq_unlock(key);
	}

	return;
}
Esempio n. 2
0
void request_soc_sleep(void)
{
	unsigned int key;
	qm_mbox_ch_status_t stat;

	QM_PUTS("Request SoC sleep");

	key = qm_irq_lock();

	/* Send sleep request. */
	send_msg(SLEEP_REQ);

	/* Wait for the answer from other core. */
	do {
		if (qm_mbox_ch_get_status(mbox_rx, &stat) != 0) {
			QM_PUTS("Unable to get mailbox status");
		}
	} while (stat == QM_MBOX_CH_IDLE);

	qm_mbox_ch_read(mbox_rx, &rx_data);

	switch (rx_data.ctrl) {
	case SLEEP_NAK:
		QM_PUTS("MBox NAK");
		qm_irq_unlock(key);

		CORE_HALT();
		break;

	case SLEEP_REQ:
		QM_PUTS("MBox REQ");
/*
 * There is a race condition where both cores want to go to
 * sleep. The policy is to make the x86 perform the SoC sleep
 * transition. Sensor will go to core sleep.
 */
#if QM_SENSOR
		soc_sleep(CORE_SLEEP);
		qm_irq_unlock(key);
#else
		/* Wait for other core to be ready. */
		while (!other_core_sleep_flag()) {
		}
		soc_sleep(SOC_SLEEP);
		qm_irq_unlock(key);
#endif
		break;

	case SLEEP_ACK:
		QM_PUTS("MBox ACK");

		/* Wait for other core to be actually ready for sleep mode. */
		while (!other_core_sleep_flag()) {
		}

		soc_sleep(SOC_SLEEP);
		qm_irq_unlock(key);
		break;

	default:
		QM_PUTS("Wrong message received");
		break;
	}
}
Esempio n. 3
0
File: main.c Progetto: CurieBSP/qmsi
/* Low power app example */
int main(void)
{
	/* Setup the RTC to get out of sleep mode. deep sleep will require an */
	/* analog comparator interrupt to wake up the system. */
	/*  Variables */
	uint32_t pmux_sel_save[2], pmux_in_en_save, pmux_pullup_save;
	qm_ac_config_t ac_cfg;
	qm_rtc_config_t rtc_cfg;

	QM_PUTS("Low power mode example.");

	clk_periph_enable(CLK_PERIPH_RTC_REGISTER | CLK_PERIPH_CLK);

	/*  Initialise RTC configuration. */
	rtc_cfg.init_val = 0;
	rtc_cfg.alarm_en = 1;
	rtc_cfg.alarm_val = QM_RTC_ALARM_SECOND;
	rtc_cfg.callback = rtc_example_callback;
	qm_rtc_set_config(QM_RTC_0, &rtc_cfg);

	qm_irq_request(QM_IRQ_RTC_0, qm_rtc_isr_0);

	QM_PUTS("CPU Halt.");
	/* Halt the CPU, RTC alarm will wake me up. */
	cpu_halt();
	QM_PUTS("CPU Halt wakeup.");

	/* Set another alarm one minute from now. */
	qm_rtc_set_alarm(QM_RTC_0,
			 QM_RTC[QM_RTC_0].rtc_ccvr + QM_RTC_ALARM_SECOND);
	QM_PUTS("Go to sleep.");
	/* Go to sleep, RTC will wake me up. */
	soc_sleep();
	QM_PUTS("Wake up from sleep.");

	/* Physical step at this stage to raise the V on the comparator pin. */
	/* Go to deep sleep, a comparator should wake me up. */
	QM_PUTS("Go to deep sleep.");

	ac_cfg.reference =
	    BIT(WAKEUP_COMPARATOR_PIN); /* Ref internal voltage */
	ac_cfg.polarity = 0x0; /* Fire if greater than ref (high level) */
	ac_cfg.power = BIT(WAKEUP_COMPARATOR_PIN);  /* Normal operation mode */
	ac_cfg.int_en = BIT(WAKEUP_COMPARATOR_PIN); /* Enable comparator */
	ac_cfg.callback = ac_example_callback;
	qm_ac_set_config(&ac_cfg);

	qm_irq_request(QM_IRQ_AC, qm_ac_isr);

	/*
	 * Comparator pin will fire an interrupt when the input voltage is
	 * greater than the reference voltage (0.95V).
	 */

	/*
	 * In order to minimise power, pmux_sel must be set to 0, input enable
	 * must be cleared for any pins not expecting to be used to wake the
	 * SoC from deep sleep mode, in this example we are using AC 6.
	 */
	pmux_sel_save[0] = QM_SCSS_PMUX->pmux_sel[0];
	pmux_sel_save[1] = QM_SCSS_PMUX->pmux_sel[1];
	pmux_in_en_save = QM_SCSS_PMUX->pmux_in_en[0];

	pmux_pullup_save = QM_SCSS_PMUX->pmux_pullup[0];

	QM_SCSS_PMUX->pmux_sel[0] = QM_SCSS_PMUX->pmux_sel[1] = 0;
	QM_SCSS_PMUX->pmux_in_en[0] = BIT(WAKEUP_COMPARATOR_PIN);
	QM_SCSS_PMUX->pmux_pullup[0] = 0;

	/* Mux out comparator */
	qm_pmux_select(QM_PIN_ID_6, QM_PMUX_FN_1);
	qm_pmux_input_en(QM_PIN_ID_6, true);

	soc_deep_sleep();

	/* Restore previous pinmuxing settings. */
	QM_SCSS_PMUX->pmux_sel[0] = pmux_sel_save[0];
	QM_SCSS_PMUX->pmux_sel[1] = pmux_sel_save[1];
	QM_SCSS_PMUX->pmux_in_en[0] = pmux_in_en_save;
	QM_SCSS_PMUX->pmux_pullup[0] = pmux_pullup_save;

	QM_PUTS("Wake up from deep sleep.");
	return 0;
}