From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49906) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WJBm4-0005j6-Uv for qemu-devel@nongnu.org; Thu, 27 Feb 2014 19:58:06 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WJBlz-0006rC-An for qemu-devel@nongnu.org; Thu, 27 Feb 2014 19:58:00 -0500 Received: from mail-ob0-x22a.google.com ([2607:f8b0:4003:c01::22a]:61934) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WJBlz-0006r8-5j for qemu-devel@nongnu.org; Thu, 27 Feb 2014 19:57:55 -0500 Received: by mail-ob0-f170.google.com with SMTP id uz6so3240501obc.1 for ; Thu, 27 Feb 2014 16:57:54 -0800 (PST) From: Rob Herring Date: Thu, 27 Feb 2014 18:57:32 -0600 Message-Id: <1393549052-26168-1-git-send-email-robherring2@gmail.com> Subject: [Qemu-devel] [PATCH] pl011: reset the fifo when enabled or disabled List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Peter Maydell , Christoffer Dall , Rob Herring From: Rob Herring Intermittent issues have been seen where no serial input occurs. It appears the pl011 gets in a state where the rx interrupt never fires because the rx interrupt only asserts when crossing the fifo trigger level. The fifo state appears to get out of sync when the pl011 is re-configured. This combined with the rx timeout interrupt not being modeled results in no more rx interrupts. Disabling the fifo is the recommended way to clear the fifo in the TRM, but none of the fifo state was getting reset when the fifo was disabled. Ensure all the fifo state is reset when the fifo is enabled or disabled. When setting the fifo trigger level, the rx interrupt needs to be asserted if the current fifo level matches. Also, fix incorrect logic to set the RXFF flag. Signed-off-by: Rob Herring --- hw/char/pl011.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hw/char/pl011.c b/hw/char/pl011.c index 8ced7cd..9260a3d 100644 --- a/hw/char/pl011.c +++ b/hw/char/pl011.c @@ -129,6 +129,9 @@ static void pl011_set_read_trigger(PL011State *s) else #endif s->read_trigger = 1; + + if (s->read_count == s->read_trigger) + s->int_level |= PL011_INT_RX; } static void pl011_write(void *opaque, hwaddr offset, @@ -162,6 +165,10 @@ static void pl011_write(void *opaque, hwaddr offset, s->fbrd = value; break; case 11: /* UARTLCR_H */ + if (!((s->lcr ^ value) & 0x10)) { + s->read_count = 0; + s->read_pos = 0; + } s->lcr = value; pl011_set_read_trigger(s); break; @@ -214,7 +221,7 @@ static void pl011_put_fifo(void *opaque, uint32_t value) s->read_fifo[slot] = value; s->read_count++; s->flags &= ~PL011_FLAG_RXFE; - if (s->cr & 0x10 || s->read_count == 16) { + if (!(s->lcr & 0x10) || s->read_count == 16) { s->flags |= PL011_FLAG_RXFF; } if (s->read_count == s->read_trigger) { -- 1.8.3.2