timer: Add wait_us/wait_ms helper macros to wait for conditions

A very common pattern in drivers is that we need to wait for a condition
to become true (e.g. for a lock bit in a PLL status register to become
set), but we still want to have a maximum timeout before we treat it as
an error. coreboot uses the stopwatch API for this, but it's still a
little verbose for the most simple cases. This patch introduces two new
helper macros that wrap this common application of the stopwatch API in
a single line: wait_ms(XXX, YYY) waits for up to XXX milliseconds to see
if the C condition 'if (YYY)' becomes true. The return value is 0 on
failure (i.e. timeout expires without the condition becoming true) and
the amount of elapsed time on success, so it can be used both in a
boolean context and to log the amount of time waited.

Replace the custom version used in an MTK ADC driver with this new
generic version.

Change-Id: I6de38ee00673c46332ae92b8a11099485de5327a
Signed-off-by: Tristan Shieh <tristan.shieh@mediatek.com>
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://review.coreboot.org/29315
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
Julius Werner
2018-11-02 14:48:24 -07:00
parent 55a972236e
commit 5132570845
2 changed files with 37 additions and 19 deletions

View File

@@ -24,33 +24,17 @@
static struct mtk_auxadc_regs *const mtk_auxadc = (void *)AUXADC_BASE;
/*
* Wait until a condition becomes true or times out
*
* cond : a C expression to wait for
* timeout : msecs
*/
#define wait_ms(cond, timeout) \
({ \
struct stopwatch sw; \
int expired = 0; \
stopwatch_init_msecs_expire(&sw, timeout); \
while (!(cond) && !(expired = stopwatch_expired(&sw))) \
; /* wait */ \
assert(!expired); \
})
static uint32_t auxadc_get_rawdata(int channel)
{
setbits_le32(&mt8183_infracfg->module_sw_cg_1_clr, 1 << 10);
wait_ms(!(read32(&mtk_auxadc->con2) & 0x1), 300);
assert(wait_ms(300, !(read32(&mtk_auxadc->con2) & 0x1)));
clrbits_le32(&mtk_auxadc->con1, 1 << channel);
wait_ms(!(read32(&mtk_auxadc->data[channel]) & (1 << 12)), 300);
assert(wait_ms(300, !(read32(&mtk_auxadc->data[channel]) & (1 << 12))));
setbits_le32(&mtk_auxadc->con1, 1 << channel);
udelay(25);
wait_ms(read32(&mtk_auxadc->data[channel]) & (1 << 12), 300);
assert(wait_ms(300, read32(&mtk_auxadc->data[channel]) & (1 << 12)));
uint32_t value = read32(&mtk_auxadc->data[channel]) & 0x0FFF;