int main(void) { QM_PUTS("Starting: IRQ lock / unlock"); int key = 0; /* Disable interrupts unconditionally. */ qm_irq_disable(); /* * Lock interrupts and check if the Interrupt Flag bit from EFLAGS * was cleared. */ key = qm_irq_lock(); if (key & X86_FLAGS_IF) { QM_PUTS("Error: IF was set"); return -EIO; } /* Try to unlock, lock again, but check that IF was still cleared. */ qm_irq_unlock(key); key = 0; key = qm_irq_lock(); if (key & X86_FLAGS_IF) { QM_PUTS("Error: IF was set"); return -EIO; } /* Enable interrupts unconditionally. */ qm_irq_enable(); /* Lock them and check if IF was set. */ key = qm_irq_lock(); if (!(key & X86_FLAGS_IF)) { QM_PUTS("Error: IF was cleared"); return -EIO; } /* Try to unlock, lock again, and check that IF is still set. */ qm_irq_unlock(key); key = 0; key = qm_irq_lock(); if (!(key & X86_FLAGS_IF)) { QM_PUTS("Error: IF was cleared"); return -EIO; } QM_PUTS("Finished: IRQ lock / unlock"); return 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; }
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; } }