pl011 uart: Fix fifo states

* Lets wait for space *before* writing to the fifo
  instead of after.
* Flush functions now really flush the fifo waiting
  for them to enter an empty state.
* Simple memory barriers added (may need revised)
  We don't have access to the kernel barriers here.
This commit is contained in:
Alexander von Gluck IV
2012-05-16 04:47:24 -05:00
parent a5453f6dd8
commit 91161d1d6f
+23 -14
View File
@@ -14,13 +14,20 @@
//#include <target/debugconfig.h> //#include <target/debugconfig.h>
static void
barrier()
{
asm volatile ("" : : : "memory");
}
UartPL011::UartPL011(addr_t base) UartPL011::UartPL011(addr_t base)
: :
fUARTEnabled(true), fUARTEnabled(true),
fUARTBase(base) fUARTBase(base)
{ {
// TODO: Nice, but not required barrier();
#if 0
// ** Loopback test // ** Loopback test
uint32 cr = PL01x_CR_UARTEN; uint32 cr = PL01x_CR_UARTEN;
// Enable UART // Enable UART
@@ -37,23 +44,19 @@ UartPL011::UartPL011(addr_t base)
// Write a 0 to the port and wait for confim.. // Write a 0 to the port and wait for confim..
WriteUart(PL01x_DR, 0); WriteUart(PL01x_DR, 0);
while (ReadUart(PL01x_FR) & PL01x_FR_BUSY); while (ReadUart(PL01x_FR) & PL01x_FR_BUSY)
// Wait for xmit on loopback barrier();
// ** Disable loopback, enable uart // ** Disable loopback, enable uart
cr = PL01x_CR_UARTEN | PL011_CR_RXE | PL011_CR_TXE; cr = PL01x_CR_UARTEN | PL011_CR_RXE | PL011_CR_TXE;
WriteUart(PL011_CR, cr); WriteUart(PL011_CR, cr);
// Enable DMA to received request outputs
WriteUart(PL011_DMACR, PL011_DMAONERR);
// ** Clear interrupts // ** Clear interrupts
WriteUart(PL011_ICR, PL011_OEIS | PL011_BEIS WriteUart(PL011_ICR, PL011_OEIS | PL011_BEIS
| PL011_PEIS | PL011_FEIS); | PL011_PEIS | PL011_FEIS);
// Set Rx timeout interrupt mask and Rx interrput mask // ** Disable interrupts
WriteUart(PL011_IMSC, PL011_RTIM | PL011_RXIM); WriteUart(PL011_IMSC, 0);
#endif
} }
@@ -134,9 +137,11 @@ int
UartPL011::PutChar(char c) UartPL011::PutChar(char c)
{ {
if (fUARTEnabled == true) { if (fUARTEnabled == true) {
// Wait until there is room in fifo
while ((ReadUart(PL01x_FR) & PL01x_FR_TXFF) != 0)
barrier();
WriteUart(PL01x_DR, c); WriteUart(PL01x_DR, c);
// Empty the transmit buffer
FlushTx();
return 0; return 0;
} }
@@ -155,12 +160,16 @@ UartPL011::GetChar(bool wait)
void void
UartPL011::FlushTx() UartPL011::FlushTx()
{ {
while (ReadUart(PL01x_FR) & PL01x_FR_TXFF); // Wait until transmit fifo empty
while ((ReadUart(PL01x_FR) & PL011_FR_TXFE) == 0)
barrier();
} }
void void
UartPL011::FlushRx() UartPL011::FlushRx()
{ {
#warning ARM Amba PL011 UART incomplete // Wait until receive fifo empty
while ((ReadUart(PL01x_FR) & PL01x_FR_RXFE) == 0)
barrier();
} }