hrev44132 adds 1 changeset to branch 'master' old head: 58f3387d560449ab352cd9cfdfe5eac6214ada6a new head: 78004f1677f78808556a184a5bac9e112fe0165b ---------------------------------------------------------------------------- 78004f1: arm uart: Convert new uart code to classes * This makes things a little more flexible and the interface to use the uarts cleaner. * May want to make a generic Uart wrapper class in uart.h / uart.cpp and call drivers as needed from there. [ Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev44132 Commit: 78004f1677f78808556a184a5bac9e112fe0165b URL: http://cgit.haiku-os.org/haiku/commit/?id=78004f1 Author: Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> Date: Wed May 9 03:16:19 2012 UTC ---------------------------------------------------------------------------- 9 files changed, 156 insertions(+), 192 deletions(-) headers/private/kernel/arch/arm/uart.h | 26 +---- headers/private/kernel/arch/arm/uart_8250.h | 33 +++--- headers/private/kernel/arch/arm/uart_pl011.h | 33 +++--- .../boot/platform/raspberrypi_arm/serial.cpp | 18 ++-- src/system/boot/platform/u-boot/serial.cpp | 17 ++-- src/system/kernel/arch/arm/arch_debug_console.cpp | 25 ++--- src/system/kernel/arch/arm/uart.cpp | 42 +------- src/system/kernel/arch/arm/uart_8250.cpp | 84 +++++++++------- src/system/kernel/arch/arm/uart_pl011.cpp | 70 +++++++------ ---------------------------------------------------------------------------- diff --git a/headers/private/kernel/arch/arm/uart.h b/headers/private/kernel/arch/arm/uart.h index 4a4691b..7d34067 100644 --- a/headers/private/kernel/arch/arm/uart.h +++ b/headers/private/kernel/arch/arm/uart.h @@ -15,32 +15,8 @@ #include "uart_pl011.h" -#ifdef __cplusplus -extern "C" { -#endif - - -struct uart_info { - addr_t base; - - // Pointers to functions based on port type - void (*init)(addr_t base); - void (*init_early)(void); - void (*init_port)(addr_t base, uint baud); - int (*putchar)(addr_t base, char c); - int (*getchar)(addr_t base, bool wait); - void (*flush_tx)(addr_t base); - void (*flush_rx)(addr_t base); -}; - - -uart_info* uart_create(void); -void uart_destroy(); addr_t uart_base_port(int port); -addr_t uart_debug_port(void); +addr_t uart_base_debug(); -#ifdef __cplusplus -} -#endif #endif diff --git a/headers/private/kernel/arch/arm/uart_8250.h b/headers/private/kernel/arch/arm/uart_8250.h index be557e7..92adf14 100644 --- a/headers/private/kernel/arch/arm/uart_8250.h +++ b/headers/private/kernel/arch/arm/uart_8250.h @@ -24,24 +24,31 @@ #define __DEV_UART_8250_H +#include <SupportDefs.h> #include <sys/types.h> -#ifdef __cplusplus -extern "C" { -#endif +class Uart8250 { +public: + Uart8250(addr_t base); + ~Uart8250(); + void InitEarly(); + void Init(); + void InitPort(uint32 baud); -void uart_8250_init_port(addr_t base, uint baud); -void uart_8250_init_early(void); -void uart_8250_init(addr_t base); -int uart_8250_putchar(addr_t base, char c); -int uart_8250_getchar(addr_t base, bool wait); -void uart_8250_flush_tx(addr_t base); -void uart_8250_flush_rx(addr_t base); + int PutChar(char c); + int GetChar(bool wait); + + void FlushTx(); + void FlushRx(); + +private: + void WriteUart(uint32 reg, unsigned char data); + unsigned char ReadUart(uint32 reg); + + addr_t fUARTBase; +}; -#ifdef __cplusplus -} -#endif #endif diff --git a/headers/private/kernel/arch/arm/uart_pl011.h b/headers/private/kernel/arch/arm/uart_pl011.h index 5510dbc..7db010a 100644 --- a/headers/private/kernel/arch/arm/uart_pl011.h +++ b/headers/private/kernel/arch/arm/uart_pl011.h @@ -10,6 +10,7 @@ #include <sys/types.h> +#include <SupportDefs.h> #define PL01x_DR 0x00 // Data read or written @@ -86,21 +87,27 @@ // TODO: Other PL01x registers + values? -#ifdef __cplusplus -extern "C" { -#endif +class UartPL011 { +public: + UartPL011(addr_t base); + ~UartPL011(); + void InitEarly(); + void Init(); + void InitPort(uint32 baud); -void uart_pl011_init_port(addr_t base, uint baud); -void uart_pl011_init_early(void); -void uart_pl011_init(addr_t base); -int uart_pl011_putchar(addr_t base, char c); -int uart_pl011_getchar(addr_t base, bool wait); -void uart_pl011_flush_tx(addr_t base); -void uart_pl011_flush_rx(addr_t base); + int PutChar(char c); + int GetChar(bool wait); + + void FlushTx(); + void FlushRx(); + +private: + void WriteUart(uint32 reg, unsigned char data); + unsigned char ReadUart(uint32 reg); + + addr_t fUARTBase; +}; -#ifdef __cplusplus -} -#endif #endif diff --git a/src/system/boot/platform/raspberrypi_arm/serial.cpp b/src/system/boot/platform/raspberrypi_arm/serial.cpp index 4c2e77f..1fb320d 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> -struct uart_info* gUARTInfo; +UartPL011* gUART; static int32 sSerialEnabled = 0; static char sBuffer[16384]; @@ -27,8 +27,7 @@ static uint32 sBufferPosition; static void serial_putc(char c) { - if (gUARTInfo != NULL) - gUARTInfo->putchar(gUARTInfo->base, c); + gUART->PutChar(c); } @@ -81,16 +80,11 @@ serial_cleanup(void) extern "C" void serial_init(void) { - gUARTInfo = uart_create(); + gUART = new UartPL011(uart_base_debug()); - if (gUARTInfo == NULL) { - // TODO: Notify user somehow. - return; - } - - gUARTInfo->init_early(); - gUARTInfo->init_port(gUARTInfo->base, 9600); - //gUARTInfo->init(gUARTInfo->base); + gUART->InitEarly(); + gUART->Init(); + gUART->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 2fa59c2..308942c 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> -struct uart_info* gUARTInfo; +gUart8250* gUART; static int32 sSerialEnabled = 0; static char sBuffer[16384]; @@ -26,7 +26,7 @@ static uint32 sBufferPosition; static void serial_putc(char c) { - gUARTInfo->putchar(gUARTInfo->base, c); + gUART->PutChar(c); } @@ -67,9 +67,9 @@ serial_enable(void) { /* should already be initialized by U-Boot */ /* - gUARTInfo->init_early(); - gUARTInfo->init(gUARTInfo->base); - gUARTInfo->init_port(gUARTInfo->base, 9600); + gUART->InitEarly(); + gUART->Init(); + gUART->InitPort(9600); */ sSerialEnabled++; } @@ -93,12 +93,7 @@ extern "C" void serial_init(void) { // Setup information on uart - gUARTInfo = uart_create(); - - if (gUARTInfo == NULL) { - // TODO: Notify user somehow. - return; - } + gUART = new Uart8250(uart_base_debug()); serial_enable(); } diff --git a/src/system/kernel/arch/arm/arch_debug_console.cpp b/src/system/kernel/arch/arm/arch_debug_console.cpp index 7e02347..5e6d421 100644 --- a/src/system/kernel/arch/arm/arch_debug_console.cpp +++ b/src/system/kernel/arch/arm/arch_debug_console.cpp @@ -19,7 +19,11 @@ #include <string.h> -struct uart_info* gUART; +#if defined(BOARD_UART_AMBA_PL011) +UartPL011* gArchDebugUART; +#else +Uart8250* gArchDebugUART; +#endif void @@ -60,18 +64,14 @@ arch_debug_serial_try_getchar(void) char arch_debug_serial_getchar(void) { - if (gUART->getchar != NULL) - return gUART->getchar(gUART->base, false); - - return 0; + return gArchDebugUART->GetChar(false); } void arch_debug_serial_putchar(const char c) { - if (gUART->putchar != NULL) - gUART->putchar(gUART->base, c); + gArchDebugUART->PutChar(c); } @@ -96,12 +96,13 @@ arch_debug_serial_early_boot_message(const char *string) status_t arch_debug_console_init(kernel_args *args) { - gUART = uart_create(); - - if (gUART == NULL) - return B_ERROR; + #if defined(BOARD_UART_AMBA_PL011) + gArchDebugUART = new UartPL011(uart_base_debug()); + #else + gArchDebugUART = new Uart8250(uart_base_debug()); + #endif - gUART->init_early(); + gArchDebugUART->InitEarly(); return B_OK; } diff --git a/src/system/kernel/arch/arm/uart.cpp b/src/system/kernel/arch/arm/uart.cpp index 5269a97..bba93b8 100644 --- a/src/system/kernel/arch/arm/uart.cpp +++ b/src/system/kernel/arch/arm/uart.cpp @@ -12,7 +12,6 @@ #include <board_config.h> #include <debug.h> #include <stdlib.h> - //#include <target/debugconfig.h> @@ -20,7 +19,7 @@ addr_t -uart_base_debug(void) +uart_base_debug() { return DEBUG_UART; } @@ -40,42 +39,3 @@ uart_base_port(int port) return uart_base_debug(); } - - -uart_info* -uart_create(void) -{ - struct uart_info* uart; - - uart = (uart_info*)malloc(sizeof(uart_info)); - uart->base = uart_base_debug(); - - #if defined(BOARD_UART_8250) - uart->init = uart_8250_init; - uart->init_early = uart_8250_init_early; - uart->init_port = uart_8250_init_port; - uart->putchar = uart_8250_putchar; - uart->getchar = uart_8250_getchar; - uart->flush_tx = uart_8250_flush_tx; - uart->flush_rx = uart_8250_flush_rx; - #elif defined(BOARD_UART_AMBA_PL011) - uart->init = uart_pl011_init; - uart->init_early = uart_pl011_init_early; - uart->init_port = uart_pl011_init_port; - uart->putchar = uart_pl011_putchar; - uart->getchar = uart_pl011_getchar; - uart->flush_tx = uart_pl011_flush_tx; - uart->flush_rx = uart_pl011_flush_rx; - #else - #error Unknown UART Type (or no UART provided) - #endif - - return uart; -} - - -void -uart_destroy(uart_info* uart) -{ - free(uart); -} diff --git a/src/system/kernel/arch/arm/uart_8250.cpp b/src/system/kernel/arch/arm/uart_8250.cpp index f17c020..769c295 100644 --- a/src/system/kernel/arch/arm/uart_8250.cpp +++ b/src/system/kernel/arch/arm/uart_8250.cpp @@ -32,18 +32,30 @@ #define UART_SHIFT 2 -static inline void -write_8250(addr_t base, uint reg, unsigned char data) +Uart8250::Uart8250(addr_t base) + : + fUARTBase(base) { - *(volatile unsigned char *)(base + (reg << UART_SHIFT)) +} + + +Uart8250::~Uart8250() +{ +} + + +void +Uart8250::WriteUart(uint32 reg, unsigned char data) +{ + *(volatile unsigned char *)(fUARTBase + (reg << UART_SHIFT)) = data; } -static inline unsigned char -read_8250(addr_t base, uint reg) +unsigned char +Uart8250::ReadUart(uint32 reg) { - return *(volatile unsigned char *)(base + (reg << UART_SHIFT)); + return *(volatile unsigned char *)(fUARTBase + (reg << UART_SHIFT)); } @@ -81,36 +93,36 @@ read_8250(addr_t base, uint reg) void -uart_8250_init_port(addr_t base, uint baud) +Uart8250::InitPort(uint32 baud) { uint16 baudDivisor = BOARD_UART_CLOCK / (16 * baud); // Write standard uart settings - write_8250(base, UART_LCR, LCR_8N1); + WriteUart(UART_LCR, LCR_8N1); // 8N1 - write_8250(base, UART_IER, 0); + WriteUart(UART_IER, 0); // Disable interrupt - write_8250(base, UART_FCR, 0); + WriteUart(UART_FCR, 0); // Disable FIFO - write_8250(base, UART_MCR, MCR_DTR | MCR_RTS); + WriteUart(UART_MCR, MCR_DTR | MCR_RTS); // DTR / RTS // Gain access to, and program baud divisor - unsigned char buffer = read_8250(base, UART_LCR); - write_8250(base, UART_LCR, buffer | LCR_BKSE); - write_8250(base, UART_DLL, baudDivisor & 0xff); - write_8250(base, UART_DLH, (baudDivisor >> 8) & 0xff); - write_8250(base, UART_LCR, buffer & ~LCR_BKSE); - -// write_8250(base, UART_MDR1, 0); // UART 16x mode -// write_8250(base, UART_LCR, 0xBF); // config mode B -// write_8250(base, UART_EFR, (1<<7)|(1<<6)); // hw flow control -// write_8250(base, UART_LCR, LCR_8N1); // operational mode + unsigned char buffer = ReadUart(UART_LCR); + WriteUart(UART_LCR, buffer | LCR_BKSE); + WriteUart(UART_DLL, baudDivisor & 0xff); + WriteUart(UART_DLH, (baudDivisor >> 8) & 0xff); + WriteUart(UART_LCR, buffer & ~LCR_BKSE); + +// WriteUart(UART_MDR1, 0); // UART 16x mode +// WriteUart(UART_LCR, 0xBF); // config mode B +// WriteUart(UART_EFR, (1<<7)|(1<<6)); // hw flow control +// WriteUart(UART_LCR, LCR_8N1); // operational mode } void -uart_8250_init_early(void) +Uart8250::InitEarly() { // Perform special hardware UART configuration @@ -133,51 +145,51 @@ uart_8250_init_early(void) void -uart_8250_init(addr_t base) +Uart8250::Init() { - uart_8250_init_port(base, 115200); + InitPort(115200); } int -uart_8250_putchar(addr_t base, char c) +Uart8250::PutChar(char c) { - while (!(read_8250(base, UART_LSR) & (1<<6))); + while (!(ReadUart(UART_LSR) & (1<<6))); // wait for the last char to get out - write_8250(base, UART_THR, c); + WriteUart(UART_THR, c); return 0; } /* returns -1 if no data available */ int -uart_8250_getchar(addr_t base, bool wait) +Uart8250::GetChar(bool wait) { if (wait) { - while (!(read_8250(base, UART_LSR) & (1<<0))); + while (!(ReadUart(UART_LSR) & (1<<0))); // wait for data to show up in the rx fifo } else { - if (!(read_8250(base, UART_LSR) & (1<<0))) + if (!(ReadUart(UART_LSR) & (1<<0))) return -1; } - return read_8250(base, UART_RHR); + return ReadUart(UART_RHR); } void -uart_8250_flush_tx(addr_t base) +Uart8250::FlushTx() { - while (!(read_8250(base, UART_LSR) & (1<<6))); + while (!(ReadUart(UART_LSR) & (1<<6))); // wait for the last char to get out } void -uart_8250_flush_rx(addr_t base) +Uart8250::FlushRx() { // empty the rx fifo - while (read_8250(base, UART_LSR) & (1<<0)) { - volatile char c = read_8250(base, UART_RHR); + while (ReadUart(UART_LSR) & (1<<0)) { + volatile char c = ReadUart(UART_RHR); (void)c; } } diff --git a/src/system/kernel/arch/arm/uart_pl011.cpp b/src/system/kernel/arch/arm/uart_pl011.cpp index 468934c..33a2092 100644 --- a/src/system/kernel/arch/arm/uart_pl011.cpp +++ b/src/system/kernel/arch/arm/uart_pl011.cpp @@ -14,22 +14,34 @@ //#include <target/debugconfig.h> -static inline void -write_pl011(addr_t base, uint reg, unsigned char data) +UartPL011::UartPL011(addr_t base) + : + fUARTBase(base) { - *(volatile unsigned char *)(base + reg) = data; } -static inline unsigned char -read_pl011(addr_t base, uint reg) +UartPL011::~UartPL011() { - return *(volatile unsigned char *)(base + reg); } void -uart_pl011_init_port(addr_t base, uint baud) +UartPL011::WriteUart(uint32 reg, unsigned char data) +{ + *(volatile unsigned char *)(fUARTBase + reg) = data; +} + + +unsigned char +UartPL011::ReadUart(uint32 reg) +{ + return *(volatile unsigned char *)(fUARTBase + reg); +} + + +void +UartPL011::InitPort(uint32 baud) { uint16 clockDiv = (baud > BOARD_UART_CLOCK / 16) ? 8 : 4; @@ -39,25 +51,25 @@ uart_pl011_init_port(addr_t base, uint baud) // Disable everything unsigned char originalCR - = read_pl011(base, PL011_CR); - write_pl011(base, PL011_CR, 0); + = ReadUart(PL011_CR); + WriteUart(PL011_CR, 0); // Set baud divisor - write_pl011(base, PL011_FBRD, baudDivisor & 0x3f); - write_pl011(base, PL011_IBRD, baudDivisor >> 6); + WriteUart(PL011_FBRD, baudDivisor & 0x3f); + WriteUart(PL011_IBRD, baudDivisor >> 6); // Set LCR - write_pl011(base, PL011_LCRH, lcr); + WriteUart(PL011_LCRH, lcr); // Disable auto RTS / CTS in original CR originalCR &= ~(PL011_CR_CTSEN | PL011_CR_RTSEN); - write_pl011(base, PL011_CR, originalCR); + WriteUart(PL011_CR, originalCR); } void -uart_pl011_init_early(void) +UartPL011::InitEarly() { // Perform special hardware UART configuration // Raspberry Pi: Early setup handled by gpio_init in platform code @@ -65,33 +77,33 @@ uart_pl011_init_early(void) void -uart_pl011_init(addr_t base) +UartPL011::Init() { // TODO: Enable clock producer? // TODO: Clear pending error and receive interrupts // Provoke TX FIFO into asserting - unsigned char cr = PL011_CR_UARTEN | PL011_CR_TXE | PL011_IFLS; - write_pl011(base, PL011_CR, cr); - write_pl011(base, PL011_FBRD, 0); - write_pl011(base, PL011_IBRD, 1); + uint32 cr = PL011_CR_UARTEN | PL011_CR_TXE | PL011_IFLS; + WriteUart(PL011_CR, cr); + WriteUart(PL011_FBRD, 0); + WriteUart(PL011_IBRD, 1); // TODO: For arm vendor, st different rx vs tx - write_pl011(base, PL011_LCRH, 0); + WriteUart(PL011_LCRH, 0); - write_pl011(base, PL01x_DR, 0); + WriteUart(PL01x_DR, 0); - while (read_pl011(base, PL01x_FR) & PL01x_FR_BUSY); + while (ReadUart(PL01x_FR) & PL01x_FR_BUSY); // Wait for xmit } int -uart_pl011_putchar(addr_t base, char c) +UartPL011::PutChar(char c) { - write_pl011(base, PL01x_DR, (unsigned int)c); + WriteUart(PL01x_DR, (unsigned int)c); - while (read_pl011(base, PL01x_FR) & PL01x_FR_TXFF); + while (ReadUart(PL01x_FR) & PL01x_FR_TXFF); // wait for the last char to get out return 0; @@ -100,7 +112,7 @@ uart_pl011_putchar(addr_t base, char c) /* returns -1 if no data available */ int -uart_pl011_getchar(addr_t base, bool wait) +UartPL011::GetChar(bool wait) { #warning ARM Amba PL011 UART incomplete return -1; @@ -108,15 +120,15 @@ uart_pl011_getchar(addr_t base, bool wait) void -uart_pl011_flush_tx(addr_t base) +UartPL011::FlushTx() { - while (read_pl011(base, PL01x_FR) & PL01x_FR_TXFF); + while (ReadUart(PL01x_FR) & PL01x_FR_TXFF); // wait for the last char to get out } void -uart_pl011_flush_rx(addr_t base) +UartPL011::FlushRx() { #warning ARM Amba PL011 UART incomplete }