hrev44136 adds 1 changeset to branch 'master' old head: 605041242ab32c7e66388c0f34c25ec4750e60a1 new head: 57a2ea0d548205653ca3ae7dc4a649a4b1ae61b4 ---------------------------------------------------------------------------- 57a2ea0: uart: Replace Init calls with Enable/Disable * Enable/Disable makes more sense and matches platform loader serial functions. * Rework PL011 code after finding a PDF covering the details of it. * Rename UART global defines in loader to be more exact about location [ Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev44136 Commit: 57a2ea0d548205653ca3ae7dc4a649a4b1ae61b4 URL: http://cgit.haiku-os.org/haiku/commit/?id=57a2ea0 Author: Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> Date: Wed May 9 17:46:35 2012 UTC ---------------------------------------------------------------------------- 6 files changed, 70 insertions(+), 44 deletions(-) headers/private/kernel/arch/arm/uart_8250.h | 4 + headers/private/kernel/arch/arm/uart_pl011.h | 5 +- .../boot/platform/raspberrypi_arm/serial.cpp | 13 ++-- src/system/boot/platform/u-boot/serial.cpp | 13 ++-- src/system/kernel/arch/arm/uart_8250.cpp | 16 +++- src/system/kernel/arch/arm/uart_pl011.cpp | 63 +++++++++------- ---------------------------------------------------------------------------- diff --git a/headers/private/kernel/arch/arm/uart_8250.h b/headers/private/kernel/arch/arm/uart_8250.h index 92adf14..137d5d1 100644 --- a/headers/private/kernel/arch/arm/uart_8250.h +++ b/headers/private/kernel/arch/arm/uart_8250.h @@ -37,6 +37,9 @@ public: void Init(); void InitPort(uint32 baud); + void Enable(); + void Disable(); + int PutChar(char c); int GetChar(bool wait); @@ -47,6 +50,7 @@ private: void WriteUart(uint32 reg, unsigned char data); unsigned char ReadUart(uint32 reg); + bool fUARTEnabled; addr_t fUARTBase; }; diff --git a/headers/private/kernel/arch/arm/uart_pl011.h b/headers/private/kernel/arch/arm/uart_pl011.h index 7db010a..4c86118 100644 --- a/headers/private/kernel/arch/arm/uart_pl011.h +++ b/headers/private/kernel/arch/arm/uart_pl011.h @@ -93,9 +93,11 @@ public: ~UartPL011(); void InitEarly(); - void Init(); void InitPort(uint32 baud); + void Enable(); + void Disable(); + int PutChar(char c); int GetChar(bool wait); @@ -106,6 +108,7 @@ private: void WriteUart(uint32 reg, unsigned char data); unsigned char ReadUart(uint32 reg); + bool fUARTEnabled; addr_t fUARTBase; }; diff --git a/src/system/boot/platform/raspberrypi_arm/serial.cpp b/src/system/boot/platform/raspberrypi_arm/serial.cpp index 29995d0..f6e786c 100644 --- a/src/system/boot/platform/raspberrypi_arm/serial.cpp +++ b/src/system/boot/platform/raspberrypi_arm/serial.cpp @@ -17,7 +17,7 @@ #include <string.h> -UartPL011* gUART; +UartPL011* gLoaderUART; static int32 sSerialEnabled = 0; static char sBuffer[16384]; @@ -27,7 +27,7 @@ static uint32 sBufferPosition; static void serial_putc(char c) { - gUART->PutChar(c); + gLoaderUART->PutChar(c); } @@ -80,13 +80,12 @@ serial_cleanup(void) extern "C" void serial_init(void) { - gUART = new(nothrow) UartPL011(uart_base_debug()); - if (gUART == 0) + gLoaderUART = new(nothrow) UartPL011(uart_base_debug()); + if (gLoaderUART == 0) return; - gUART->InitEarly(); - gUART->Init(); - gUART->InitPort(9600); + gLoaderUART->InitEarly(); + gLoaderUART->InitPort(9600); serial_enable(); diff --git a/src/system/boot/platform/u-boot/serial.cpp b/src/system/boot/platform/u-boot/serial.cpp index 308942c..28f8406 100644 --- a/src/system/boot/platform/u-boot/serial.cpp +++ b/src/system/boot/platform/u-boot/serial.cpp @@ -16,7 +16,7 @@ #include <string.h> -gUart8250* gUART; +Uart8250* gLoaderUART; static int32 sSerialEnabled = 0; static char sBuffer[16384]; @@ -26,7 +26,7 @@ static uint32 sBufferPosition; static void serial_putc(char c) { - gUART->PutChar(c); + gLoaderUART->PutChar(c); } @@ -67,9 +67,8 @@ serial_enable(void) { /* should already be initialized by U-Boot */ /* - gUART->InitEarly(); - gUART->Init(); - gUART->InitPort(9600); + gLoaderUART->InitEarly(); + gLoaderUART->InitPort(9600); */ sSerialEnabled++; } @@ -93,7 +92,9 @@ extern "C" void serial_init(void) { // Setup information on uart - gUART = new Uart8250(uart_base_debug()); + gLoaderUART = new(nothrow) Uart8250(uart_base_debug()); + if (gLoaderUART == 0) + return; serial_enable(); } diff --git a/src/system/kernel/arch/arm/uart_8250.cpp b/src/system/kernel/arch/arm/uart_8250.cpp index 769c295..f8c3dcb 100644 --- a/src/system/kernel/arch/arm/uart_8250.cpp +++ b/src/system/kernel/arch/arm/uart_8250.cpp @@ -34,6 +34,7 @@ Uart8250::Uart8250(addr_t base) : + fUARTEnabled(true), fUARTBase(base) { } @@ -95,6 +96,8 @@ Uart8250::ReadUart(uint32 reg) void Uart8250::InitPort(uint32 baud) { + Disable(); + uint16 baudDivisor = BOARD_UART_CLOCK / (16 * baud); // Write standard uart settings @@ -118,6 +121,8 @@ Uart8250::InitPort(uint32 baud) // WriteUart(UART_LCR, 0xBF); // config mode B // WriteUart(UART_EFR, (1<<7)|(1<<6)); // hw flow control // WriteUart(UART_LCR, LCR_8N1); // operational mode + + Enable(); } @@ -145,9 +150,16 @@ Uart8250::InitEarly() void -Uart8250::Init() +Uart8250::Enable() +{ + fUARTEnabled = true; +} + + +void +Uart8250::Disable() { - InitPort(115200); + fUARTEnabled = false; } diff --git a/src/system/kernel/arch/arm/uart_pl011.cpp b/src/system/kernel/arch/arm/uart_pl011.cpp index 33a2092..6dc1e07 100644 --- a/src/system/kernel/arch/arm/uart_pl011.cpp +++ b/src/system/kernel/arch/arm/uart_pl011.cpp @@ -16,6 +16,7 @@ UartPL011::UartPL011(addr_t base) : + fUARTEnabled(true), fUARTBase(base) { } @@ -43,28 +44,22 @@ UartPL011::ReadUart(uint32 reg) void UartPL011::InitPort(uint32 baud) { - uint16 clockDiv - = (baud > BOARD_UART_CLOCK / 16) ? 8 : 4; - uint16 baudDivisor = BOARD_UART_CLOCK * clockDiv / baud; - // TODO: Round to closest baud divisor - uint16 lcr = PL01x_LCRH_WLEN_8; + // Disable UART + Disable(); - // Disable everything - unsigned char originalCR - = ReadUart(PL011_CR); - WriteUart(PL011_CR, 0); + // Calculate baud divisor + uint16 baudDivisor = BOARD_UART_CLOCK / (16 * baud); + uint16 baudFractional = BOARD_UART_CLOCK % (16 * baud); // Set baud divisor - WriteUart(PL011_FBRD, baudDivisor & 0x3f); - WriteUart(PL011_IBRD, baudDivisor >> 6); + WriteUart(PL011_IBRD, baudDivisor); + WriteUart(PL011_FBRD, baudFractional); // Set LCR - WriteUart(PL011_LCRH, lcr); + WriteUart(PL011_LCRH, PL01x_LCRH_WLEN_8); - // Disable auto RTS / CTS in original CR - originalCR &= ~(PL011_CR_CTSEN | PL011_CR_RTSEN); - - WriteUart(PL011_CR, originalCR); + // Enable UART + Enable(); } @@ -77,36 +72,48 @@ UartPL011::InitEarly() void -UartPL011::Init() +UartPL011::Enable() { // TODO: Enable clock producer? - // TODO: Clear pending error and receive interrupts - // Provoke TX FIFO into asserting - uint32 cr = PL011_CR_UARTEN | PL011_CR_TXE | PL011_IFLS; + unsigned char cr = PL011_CR_UARTEN; + // Enable UART + cr |= PL011_CR_TXE; // | PL011_CR_RXE; + // Enable TX and RX WriteUart(PL011_CR, cr); - WriteUart(PL011_FBRD, 0); - WriteUart(PL011_IBRD, 1); // TODO: For arm vendor, st different rx vs tx - WriteUart(PL011_LCRH, 0); + // WriteUart(PL011_LCRH, 0); WriteUart(PL01x_DR, 0); while (ReadUart(PL01x_FR) & PL01x_FR_BUSY); // Wait for xmit + + fUARTEnabled = true; +} + + +void +UartPL011::Disable() +{ + // Disable everything + WriteUart(PL011_CR, 0); + fUARTEnabled = false; } int UartPL011::PutChar(char c) { - WriteUart(PL01x_DR, (unsigned int)c); + if (fUARTEnabled == true) { + WriteUart(PL01x_DR, (unsigned int)c); + while (ReadUart(PL01x_FR) & PL01x_FR_TXFF); + // wait for the last char to get out + return 0; + } - while (ReadUart(PL01x_FR) & PL01x_FR_TXFF); - // wait for the last char to get out - - return 0; + return -1; }