Skip to content

Commit 2aea029

Browse files
committed
[ot] fix Earlgrey GPIO DIRECT_OUT/DIRECT_OE readback
ot_gpio_eg_read() returned s->regs[reg] for DIRECT_OUT and DIRECT_OE. Those register slots are only updated on a direct write, but firmware that drives outputs through MASKED_OUT_{LOWER,UPPER} / MASKED_OE_{LOWER,UPPER} updates s->data_out / s->data_oe and never the DIRECT_* register slots. As a result a value set via a masked write was not observable through a DIRECT_OUT read, which read back as 0. DIRECT_OUT and the MASKED_OUT registers are alternate views of the same output data register on real hardware (likewise DIRECT_OE and MASKED_OE), so return the live s->data_out / s->data_oe instead. Signed-off-by: Miguel Osorio <miguelosorio@google.com>
1 parent b28bb56 commit 2aea029

1 file changed

Lines changed: 13 additions & 2 deletions

File tree

hw/opentitan/ot_gpio_eg.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,15 +340,26 @@ static uint64_t ot_gpio_eg_read(void *opaque, hwaddr addr, unsigned size)
340340
case R_INTR_STATE:
341341
case R_INTR_ENABLE:
342342
case R_DATA_IN:
343-
case R_DIRECT_OUT:
344-
case R_DIRECT_OE:
345343
case R_INTR_CTRL_EN_RISING:
346344
case R_INTR_CTRL_EN_FALLING:
347345
case R_INTR_CTRL_EN_LVLHIGH:
348346
case R_INTR_CTRL_EN_LVLLOW:
349347
case R_CTRL_EN_INPUT_FILTER:
350348
val32 = s->regs[reg];
351349
break;
350+
case R_DIRECT_OUT:
351+
/*
352+
* DIRECT_OUT and MASKED_OUT_{LOWER,UPPER} are alternate views of the
353+
* same output data register: a masked write must be observable through
354+
* a DIRECT_OUT read. Return the live output value rather than the last
355+
* value written specifically through DIRECT_OUT.
356+
*/
357+
val32 = s->data_out;
358+
break;
359+
case R_DIRECT_OE:
360+
/* Same aliasing applies to the output-enable register. */
361+
val32 = s->data_oe;
362+
break;
352363
case R_MASKED_OUT_LOWER:
353364
val32 = s->data_out & MASKED_VALUE_MASK;
354365
break;

0 commit comments

Comments
 (0)