From 0c8a1b8d39734eaae692eacbe04894207bb2c6da Mon Sep 17 00:00:00 2001 From: Dino Li Date: Tue, 5 Jan 2016 13:49:57 +0800 Subject: [PATCH] core: nds32: add task_wait_event_mask() function to nds32 core [task] 1. Copy task_wait_event_mask() function of cortex-m0. [system] 2. Include host_command.h for host_command_pd_request_hibernate(). [i2c] 3. Update i2c handler to use task_wait_event_mask. Signed-off-by: Dino Li BRANCH=none BUG=chromium:435611,chromium:435612 TEST=1. console commands: i2cscan, i2cxfer, and battery. Change-Id: If5bb4407460d28c0b021ab133ca4b635ff7bc3c9 Reviewed-on: https://chromium-review.googlesource.com/320440 Commit-Ready: Dino Li Tested-by: Dino Li Reviewed-by: Randall Spangler --- chip/it83xx/i2c.c | 3 ++- chip/it83xx/system.c | 1 + core/nds32/task.c | 32 +++++++++++++++++++++++++++++--- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/chip/it83xx/i2c.c b/chip/it83xx/i2c.c index bc10a5970f..fe516bb41f 100644 --- a/chip/it83xx/i2c.c +++ b/chip/it83xx/i2c.c @@ -410,7 +410,8 @@ int chip_i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size, } /* Start transaction */ i2c_transaction(port); - events = task_wait_event(pd->timeout_us); + /* Wait for transfer complete or timeout */ + events = task_wait_event_mask(TASK_EVENT_I2C_IDLE, pd->timeout_us); /* disable i2c interrupt */ task_disable_irq(i2c_ctrl_regs[port].irq); pd->task_waiting = TASK_ID_INVALID; diff --git a/chip/it83xx/system.c b/chip/it83xx/system.c index 6019c5f41b..90e234ce86 100644 --- a/chip/it83xx/system.c +++ b/chip/it83xx/system.c @@ -9,6 +9,7 @@ #include "cpu.h" #include "ec2i_chip.h" #include "flash.h" +#include "host_command.h" #include "registers.h" #include "system.h" #include "task.h" diff --git a/core/nds32/task.c b/core/nds32/task.c index b34e9e9f50..4be65ac913 100644 --- a/core/nds32/task.c +++ b/core/nds32/task.c @@ -450,6 +450,34 @@ uint32_t task_wait_event(int timeout_us) return __wait_evt(timeout_us, TASK_ID_IDLE); } +uint32_t task_wait_event_mask(uint32_t event_mask, int timeout_us) +{ + uint64_t deadline = get_time().val + timeout_us; + uint32_t events = 0; + int time_remaining_us = timeout_us; + + /* Add the timer event to the mask so we can indicate a timeout */ + event_mask |= TASK_EVENT_TIMER; + + while (!(events & event_mask)) { + /* Collect events to re-post later */ + events |= __wait_evt(time_remaining_us, TASK_ID_IDLE); + + time_remaining_us = deadline - get_time().val; + if (timeout_us > 0 && time_remaining_us <= 0) { + /* Ensure we return a TIMER event if we timeout */ + events |= TASK_EVENT_TIMER; + break; + } + } + + /* Re-post any other events collected */ + if (events & ~event_mask) + atomic_or(¤t_task->events, events & ~event_mask); + + return events & event_mask; +} + uint32_t get_int_mask(void) { uint32_t ret; @@ -577,9 +605,7 @@ void mutex_lock(struct mutex *mtx) /* end of critical section : re-enable interrupts */ interrupt_enable(); /* Sleep waiting for our turn */ - /* TODO(crbug.com/435612, crbug.com/435611) - * This discards any pending events! */ - task_wait_event(0); + task_wait_event_mask(TASK_EVENT_MUTEX, 0); /* re-enter critical section */ interrupt_disable(); }