diff --git a/headers/private/kernel/arch/arm/board/beagle/board_config.h b/headers/private/kernel/arch/arm/board/beagle/board_config.h index 3c6c97a37d..77bc5f237e 100644 --- a/headers/private/kernel/arch/arm/board/beagle/board_config.h +++ b/headers/private/kernel/arch/arm/board/beagle/board_config.h @@ -14,11 +14,13 @@ #include // UART Settings +#define BOARD_UART_8250 1 + #define BOARD_UART1_BASE OMAP_UART1_BASE #define BOARD_UART2_BASE OMAP_UART2_BASE #define BOARD_UART3_BASE OMAP_UART3_BASE -#define BOARD_DEBUG_UART 2 +#define BOARD_UART_DEBUG BOARD_UART3_BASE #define BOARD_UART_CLOCK 48000000 // 48MHz (APLL96/2) diff --git a/headers/private/kernel/arch/arm/board/neo_freerunner/board_config.h b/headers/private/kernel/arch/arm/board/neo_freerunner/board_config.h index eda0ab49fd..baf244123f 100644 --- a/headers/private/kernel/arch/arm/board/neo_freerunner/board_config.h +++ b/headers/private/kernel/arch/arm/board/neo_freerunner/board_config.h @@ -14,11 +14,13 @@ #include // UART Settings +#define BOARD_UART_8250 1 + #define BOARD_UART1_BASE UART0_BASE #define BOARD_UART2_BASE UART1_BASE #define BOARD_UART3_BASE UART2_BASE -#define BOARD_DEBUG_UART 2 +#define BOARD_UART_DEBUG BOARD_UART3_BASE #define BOARD_UART_CLOCK 48000000 // 48MHz (APLL96/2) diff --git a/headers/private/kernel/arch/arm/board/overo/board_config.h b/headers/private/kernel/arch/arm/board/overo/board_config.h index 2816fe6198..12f471d28b 100644 --- a/headers/private/kernel/arch/arm/board/overo/board_config.h +++ b/headers/private/kernel/arch/arm/board/overo/board_config.h @@ -14,11 +14,13 @@ #include // UART Settings +#define BOARD_UART_8250 1 + #define BOARD_UART1_BASE OMAP_UART1_BASE #define BOARD_UART2_BASE OMAP_UART2_BASE #define BOARD_UART3_BASE OMAP_UART3_BASE -#define BOARD_DEBUG_UART 2 +#define BOARD_UART_DEBUG BOARD_UART3_BASE #define BOARD_UART_CLOCK 48000000 // 48MHz (APLL96/2) diff --git a/headers/private/kernel/arch/arm/board/raspberry_pi/board_config.h b/headers/private/kernel/arch/arm/board/raspberry_pi/board_config.h index 33b72ed77b..e1d11a5ebc 100644 --- a/headers/private/kernel/arch/arm/board/raspberry_pi/board_config.h +++ b/headers/private/kernel/arch/arm/board/raspberry_pi/board_config.h @@ -16,11 +16,13 @@ #include // UART Settings +#define BOARD_UART_8250 1 + #define BOARD_UART1_BASE UART0_BASE #define BOARD_UART2_BASE UART1_BASE #define BOARD_UART3_BASE 0 -#define BOARD_DEBUG_UART 0 +#define BOARD_UART_DEBUG BOARD_UART2_BASE #define BOARD_UART_CLOCK 125000000 /* 125Mhz, strange */ diff --git a/headers/private/kernel/arch/arm/board/verdex/board_config.h b/headers/private/kernel/arch/arm/board/verdex/board_config.h index dfc83d580b..4a9942e6d1 100644 --- a/headers/private/kernel/arch/arm/board/verdex/board_config.h +++ b/headers/private/kernel/arch/arm/board/verdex/board_config.h @@ -14,11 +14,13 @@ #include // UART Settings +#define BOARD_UART_8250 1 + #define BOARD_UART1_BASE FFUART_BASE #define BOARD_UART2_BASE BTUART_BASE #define BOARD_UART3_BASE STUART_BASE -#define BOARD_DEBUG_UART 0 +#define BOARD_UART_DEBUG BOARD_UART1_BASE #define BOARD_UART_CLOCK 48000000 // 48MHz (APLL96/2) diff --git a/headers/private/kernel/arch/arm/uart.h b/headers/private/kernel/arch/arm/uart.h index 3c3826649e..25685ed808 100644 --- a/headers/private/kernel/arch/arm/uart.h +++ b/headers/private/kernel/arch/arm/uart.h @@ -1,47 +1,45 @@ /* - * Copyright (c) 2008 Travis Geiselbrecht + * Copyright 2011-2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * Authors: + * Alexander von Gluck, kallisti5@unixzen.com */ #ifndef __DEV_UART_H #define __DEV_UART_H -//#include + +#include + +#include "uart_8250.h" + + #ifdef __cplusplus extern "C" { #endif -void uart_init(void); -void uart_init_early(void); -int uart_debug_port(void); +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 (*putc)(addr_t base, char c); + int (*getc)(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); -int uart_putc(int port, char c); -int uart_getc(int port, bool wait); -void uart_flush_tx(int port); -void uart_flush_rx(int port); -void uart_init_port(int port, uint baud); #ifdef __cplusplus } #endif - #endif - diff --git a/headers/private/kernel/arch/arm/uart_8250.h b/headers/private/kernel/arch/arm/uart_8250.h new file mode 100644 index 0000000000..97d6ae330d --- /dev/null +++ b/headers/private/kernel/arch/arm/uart_8250.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2008 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef __DEV_UART_8250_H +#define __DEV_UART_8250_H + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +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_putc(addr_t base, char c); +int uart_8250_getc(addr_t base, bool wait); +void uart_8250_flush_tx(addr_t base); +void uart_8250_flush_rx(addr_t base); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/system/boot/arch/arm/Jamfile b/src/system/boot/arch/arm/Jamfile index c6c30769dc..dc172cb19e 100644 --- a/src/system/boot/arch/arm/Jamfile +++ b/src/system/boot/arch/arm/Jamfile @@ -17,6 +17,8 @@ local kernelLibArchObjects = KernelMergeObject boot_arch_$(TARGET_ARCH).o : uart.cpp + uart_8250.cpp +# uart_amba101.cpp arch_elf.cpp arch_video.cpp arch_video_920.cpp @@ -28,7 +30,7 @@ KernelMergeObject boot_arch_$(TARGET_ARCH).o : $(kernelLibArchObjects) ; -SEARCH on [ FGristFiles arch_elf.cpp uart.cpp ] +SEARCH on [ FGristFiles arch_elf.cpp uart.cpp uart_8250.cpp ] = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_ARCH) ] ; SEARCH on [ FGristFiles $(librootArchObjects) ] diff --git a/src/system/boot/platform/raspberrypi_arm/serial.cpp b/src/system/boot/platform/raspberrypi_arm/serial.cpp index 85efbc01d9..39d39fcf31 100644 --- a/src/system/boot/platform/raspberrypi_arm/serial.cpp +++ b/src/system/boot/platform/raspberrypi_arm/serial.cpp @@ -17,8 +17,9 @@ #include -static int32 sSerialEnabled = 0; +struct uart_info* gUARTInfo; +static int32 sSerialEnabled = 0; static char sBuffer[16384]; static uint32 sBufferPosition; @@ -26,7 +27,8 @@ static uint32 sBufferPosition; static void serial_putc(char c) { - uart_putc(uart_debug_port(), c); + if (gUARTInfo != NULL) + gUARTInfo->putc(gUARTInfo->base, c); } @@ -65,8 +67,6 @@ serial_disable(void) extern "C" void serial_enable(void) { - uart_init_early(); - uart_init(); sSerialEnabled++; } @@ -81,6 +81,16 @@ serial_cleanup(void) extern "C" void serial_init(void) { + gUARTInfo = uart_create(); + + if (gUARTInfo == NULL) { + // TODO: Notify user somehow. + return; + } + + gUARTInfo->init_early(); + gUARTInfo->init(gUARTInfo->base); + serial_enable(); serial_putc('S'); diff --git a/src/system/boot/platform/u-boot/serial.cpp b/src/system/boot/platform/u-boot/serial.cpp index afe84e890f..49c86d751f 100644 --- a/src/system/boot/platform/u-boot/serial.cpp +++ b/src/system/boot/platform/u-boot/serial.cpp @@ -1,6 +1,9 @@ /* * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. + * + * Copyright 2012, Alexander von Gluck, kallisti5@unixzen.com + * Distributed under the terms of the MIT License. */ @@ -12,12 +15,10 @@ #include #include -// serial output should always be enabled on u-boot platforms.. -#define ENABLE_SERIAL +struct uart_info* gUARTInfo; static int32 sSerialEnabled = 0; - static char sBuffer[16384]; static uint32 sBufferPosition; @@ -25,7 +26,7 @@ static uint32 sBufferPosition; static void serial_putc(char c) { - uart_putc(uart_debug_port(),c); + gUARTInfo->putc(gUARTInfo->base, c); } @@ -54,25 +55,21 @@ serial_puts(const char* string, size_t size) } -extern "C" void +extern "C" void serial_disable(void) { -#ifdef ENABLE_SERIAL sSerialEnabled = 0; -#else - sSerialEnabled--; -#endif } -extern "C" void +extern "C" void serial_enable(void) { /* should already be initialized by U-Boot */ /* - uart_init_early(); - uart_init();//todo - uart_init_port(uart_debug_port(),9600); + gUARTInfo->init_early(); + gUARTInfo->init(gUARTInfo->base); + gUARTInfo->init_port(gUARTInfo->base, 9600); */ sSerialEnabled++; } @@ -95,8 +92,13 @@ serial_cleanup(void) extern "C" void serial_init(void) { -#ifdef ENABLE_SERIAL - serial_enable(); -#endif -} + // Setup information on uart + gUARTInfo = uart_create(); + if (gUARTInfo == NULL) { + // TODO: Notify user somehow. + return; + } + + serial_enable(); +} diff --git a/src/system/kernel/arch/arm/Jamfile b/src/system/kernel/arch/arm/Jamfile index 63700e4a66..af0832f0bb 100644 --- a/src/system/kernel/arch/arm/Jamfile +++ b/src/system/kernel/arch/arm/Jamfile @@ -29,6 +29,7 @@ KernelMergeObject kernel_arch_arm.o : arch_vm_translation_map.cpp arch_asm.S uart.cpp + uart_8250.cpp # paging arm_physical_page_mapper.cpp diff --git a/src/system/kernel/arch/arm/arch_debug_console.cpp b/src/system/kernel/arch/arm/arch_debug_console.cpp index 8ae632a1b9..f1933ea466 100644 --- a/src/system/kernel/arch/arm/arch_debug_console.cpp +++ b/src/system/kernel/arch/arm/arch_debug_console.cpp @@ -19,6 +19,9 @@ #include +struct uart_info* gUART; + + void arch_debug_remove_interrupt_handler(uint32 line) { @@ -57,14 +60,18 @@ arch_debug_serial_try_getchar(void) char arch_debug_serial_getchar(void) { - return uart_getc(uart_debug_port(), FALSE); + if (gUART->getc != NULL) + return gUART->getc(gUART->base, false); + + return 0; } void arch_debug_serial_putchar(const char c) { - uart_putc(uart_debug_port(), c); + if (gUART->putc != NULL) + gUART->putc(gUART->base, c); } @@ -89,7 +96,12 @@ arch_debug_serial_early_boot_message(const char *string) status_t arch_debug_console_init(kernel_args *args) { - uart_init_early(); + gUART = uart_create(); + + if (gUART == NULL) + return B_ERROR; + + gUART->init_early(); return B_OK; } diff --git a/src/system/kernel/arch/arm/uart.cpp b/src/system/kernel/arch/arm/uart.cpp index 8d4ec4dd06..480b7c070c 100644 --- a/src/system/kernel/arch/arm/uart.cpp +++ b/src/system/kernel/arch/arm/uart.cpp @@ -1,193 +1,82 @@ /* - * Copyright (c) 2008 Travis Geiselbrecht + * Copyright 2011-2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * Authors: + * Alexander von Gluck, kallisti5@unixzen.com */ -#include #include #include #include +#include +#include + //#include -#define DEBUG_UART BOARD_DEBUG_UART +#define DEBUG_UART BOARD_UART_DEBUG -struct uart_stat { - addr_t base; - uint shift; -}; - - -static struct uart_stat uart[3] = { - { BOARD_UART1_BASE, 2 }, - { BOARD_UART2_BASE, 2 }, - { BOARD_UART3_BASE, 2 }, -}; - - -static inline void write_uart_reg(int port, uint reg, unsigned char data) -{ - *(volatile unsigned char *)(uart[port].base + (reg << uart[port].shift)) - = data; -} - - -static inline unsigned char read_uart_reg(int port, uint reg) -{ - return *(volatile unsigned char *)(uart[port].base - + (reg << uart[port].shift)); -} - - -#define LCR_8N1 0x03 - -#define FCR_FIFO_EN 0x01 /* Fifo enable */ -#define FCR_RXSR 0x02 /* Receiver soft reset */ -#define FCR_TXSR 0x04 /* Transmitter soft reset */ - -#define MCR_DTR 0x01 -#define MCR_RTS 0x02 -#define MCR_DMA_EN 0x04 -#define MCR_TX_DFR 0x08 - -#define LCR_WLS_MSK 0x03 /* character length select mask */ -#define LCR_WLS_5 0x00 /* 5 bit character length */ -#define LCR_WLS_6 0x01 /* 6 bit character length */ -#define LCR_WLS_7 0x02 /* 7 bit character length */ -#define LCR_WLS_8 0x03 /* 8 bit character length */ -#define LCR_STB 0x04 /* Number of stop Bits, off = 1, on = 1.5 or 2) */ -#define LCR_PEN 0x08 /* Parity eneble */ -#define LCR_EPS 0x10 /* Even Parity Select */ -#define LCR_STKP 0x20 /* Stick Parity */ -#define LCR_SBRK 0x40 /* Set Break */ -#define LCR_BKSE 0x80 /* Bank select enable */ - -#define LSR_DR 0x01 /* Data ready */ -#define LSR_OE 0x02 /* Overrun */ -#define LSR_PE 0x04 /* Parity error */ -#define LSR_FE 0x08 /* Framing error */ -#define LSR_BI 0x10 /* Break */ -#define LSR_THRE 0x20 /* Xmit holding register empty */ -#define LSR_TEMT 0x40 /* Xmitter empty */ -#define LSR_ERR 0x80 /* Error */ - - -int uart_debug_port(void) +addr_t +uart_base_debug(void) { return DEBUG_UART; } -void uart_init_port(int port, uint baud) +addr_t +uart_base_port(int port) { - uint16 baudDivisor = BOARD_UART_CLOCK / (16 * baud); + switch (port) { + case 1: + return BOARD_UART1_BASE; + case 2: + return BOARD_UART2_BASE; + case 3: + return BOARD_UART3_BASE; + } - // Write standard uart settings - write_uart_reg(port, UART_LCR, LCR_8N1); - // 8N1 - write_uart_reg(port, UART_IER, 0); - // Disable interrupt - write_uart_reg(port, UART_FCR, 0); - // Disable FIFO - write_uart_reg(port, UART_MCR, MCR_DTR | MCR_RTS); - // DTR / RTS - - // Gain access to, and program baud divisor - unsigned char buffer = read_uart_reg(port, UART_LCR); - write_uart_reg(port, UART_LCR, buffer | LCR_BKSE); - write_uart_reg(port, UART_DLL, baudDivisor & 0xff); - write_uart_reg(port, UART_DLH, (baudDivisor >> 8) & 0xff); - write_uart_reg(port, UART_LCR, buffer & ~LCR_BKSE); - -// write_uart_reg(port, UART_MDR1, 0); // UART 16x mode -// write_uart_reg(port, UART_LCR, 0xBF); // config mode B -// write_uart_reg(port, UART_EFR, (1<<7)|(1<<6)); // hw flow control -// write_uart_reg(port, UART_LCR, LCR_8N1); // operational mode + return uart_base_debug(); } -void uart_init_early(void) +uart_info* +uart_create(void) { - // Perform special hardware UART configuration + struct uart_info* uart; - #if BOARD_CPU_OMAP3 - /* UART1 */ - RMWREG32(CM_FCLKEN1_CORE, 13, 1, 1); - RMWREG32(CM_ICLKEN1_CORE, 13, 1, 1); + uart = (uart_info*)malloc(sizeof(uart_info)); + uart->base = uart_base_debug(); - /* UART2 */ - RMWREG32(CM_FCLKEN1_CORE, 14, 1, 1); - RMWREG32(CM_ICLKEN1_CORE, 14, 1, 1); - - /* UART3 */ - RMWREG32(CM_FCLKEN_PER, 11, 1, 1); - RMWREG32(CM_ICLKEN_PER, 11, 1, 1); + #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->putc = uart_8250_putc; + uart->getc = uart_8250_getc; + uart->flush_tx = uart_8250_flush_tx; + uart->flush_rx = uart_8250_flush_rx; + #elif defined(BOARD_UART_AMBA) + #error BOARD_UART_AMBA is Incomplete! + uart->init = uart_amba_init; + uart->init_early = uart_amba_init_early; + uart->init_port = uart_amba_init_port; + uart->putc = uart_amba_putc; + uart->getc = uart_amba_getc; + uart->flush_tx = uart_amba_flush_tx; + uart->flush_rx = uart_amba_flush_rx; #else - #warning INTITIALIZE UART!!!!! + #error Unknown UART Type (or no UART provided) #endif + + return uart; } -void uart_init(void) +void +uart_destroy(uart_info* uart) { - uart_init_port(uart_debug_port(), 115200); -} - - -int uart_putc(int port, char c ) -{ - while (!(read_uart_reg(port, UART_LSR) & (1<<6))); - // wait for the last char to get out - write_uart_reg(port, UART_THR, c); - return 0; -} - - -int uart_getc(int port, bool wait) /* returns -1 if no data available */ -{ - if (wait) { - while (!(read_uart_reg(port, UART_LSR) & (1<<0))); - // wait for data to show up in the rx fifo - } else { - if (!(read_uart_reg(port, UART_LSR) & (1<<0))) - return -1; - } - return read_uart_reg(port, UART_RHR); -} - - -void uart_flush_tx(int port) -{ - while (!(read_uart_reg(port, UART_LSR) & (1<<6))); - // wait for the last char to get out -} - - -void uart_flush_rx(int port) -{ - // empty the rx fifo - while (read_uart_reg(port, UART_LSR) & (1<<0)) { - volatile char c = read_uart_reg(port, UART_RHR); - (void)c; - } + free(uart); } diff --git a/src/system/kernel/arch/arm/uart_8250.cpp b/src/system/kernel/arch/arm/uart_8250.cpp new file mode 100644 index 0000000000..f04166cd01 --- /dev/null +++ b/src/system/kernel/arch/arm/uart_8250.cpp @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2008 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include +#include +#include +#include +//#include + + +#define UART_SHIFT 2 + + +static inline void write_8250(addr_t base, uint reg, unsigned char data) +{ + *(volatile unsigned char *)(base + (reg << UART_SHIFT)) + = data; +} + + +static inline unsigned char read_8250(addr_t base, uint reg) +{ + return *(volatile unsigned char *)(base + (reg << UART_SHIFT)); +} + + +#define LCR_8N1 0x03 + +#define FCR_FIFO_EN 0x01 /* Fifo enable */ +#define FCR_RXSR 0x02 /* Receiver soft reset */ +#define FCR_TXSR 0x04 /* Transmitter soft reset */ + +#define MCR_DTR 0x01 +#define MCR_RTS 0x02 +#define MCR_DMA_EN 0x04 +#define MCR_TX_DFR 0x08 + +#define LCR_WLS_MSK 0x03 /* character length select mask */ +#define LCR_WLS_5 0x00 /* 5 bit character length */ +#define LCR_WLS_6 0x01 /* 6 bit character length */ +#define LCR_WLS_7 0x02 /* 7 bit character length */ +#define LCR_WLS_8 0x03 /* 8 bit character length */ +#define LCR_STB 0x04 /* Number of stop Bits, off = 1, on = 1.5 or 2) */ +#define LCR_PEN 0x08 /* Parity eneble */ +#define LCR_EPS 0x10 /* Even Parity Select */ +#define LCR_STKP 0x20 /* Stick Parity */ +#define LCR_SBRK 0x40 /* Set Break */ +#define LCR_BKSE 0x80 /* Bank select enable */ + +#define LSR_DR 0x01 /* Data ready */ +#define LSR_OE 0x02 /* Overrun */ +#define LSR_PE 0x04 /* Parity error */ +#define LSR_FE 0x08 /* Framing error */ +#define LSR_BI 0x10 /* Break */ +#define LSR_THRE 0x20 /* Xmit holding register empty */ +#define LSR_TEMT 0x40 /* Xmitter empty */ +#define LSR_ERR 0x80 /* Error */ + + +void +uart_8250_init_port(addr_t base, uint baud) +{ + uint16 baudDivisor = BOARD_UART_CLOCK / (16 * baud); + + // Write standard uart settings + write_8250(base, UART_LCR, LCR_8N1); + // 8N1 + write_8250(base, UART_IER, 0); + // Disable interrupt + write_8250(base, UART_FCR, 0); + // Disable FIFO + write_8250(base, 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 +} + + +void +uart_8250_init_early(void) +{ + // Perform special hardware UART configuration + + #if BOARD_CPU_OMAP3 + /* UART1 */ + RMWREG32(CM_FCLKEN1_CORE, 13, 1, 1); + RMWREG32(CM_ICLKEN1_CORE, 13, 1, 1); + + /* UART2 */ + RMWREG32(CM_FCLKEN1_CORE, 14, 1, 1); + RMWREG32(CM_ICLKEN1_CORE, 14, 1, 1); + + /* UART3 */ + RMWREG32(CM_FCLKEN_PER, 11, 1, 1); + RMWREG32(CM_ICLKEN_PER, 11, 1, 1); + #else + #warning INTITIALIZE UART!!!!! + #endif +} + + +void +uart_8250_init(addr_t base) +{ + uart_8250_init_port(base, 115200); +} + + +int +uart_8250_putc(addr_t base, char c ) +{ + while (!(read_8250(base, UART_LSR) & (1<<6))); + // wait for the last char to get out + write_8250(base, UART_THR, c); + return 0; +} + + +/* returns -1 if no data available */ +int +uart_8250_getc(addr_t base, bool wait) +{ + if (wait) { + while (!(read_8250(base, UART_LSR) & (1<<0))); + // wait for data to show up in the rx fifo + } else { + if (!(read_8250(base, UART_LSR) & (1<<0))) + return -1; + } + return read_8250(base, UART_RHR); +} + + +void +uart_8250_flush_tx(addr_t base) +{ + while (!(read_8250(base, UART_LSR) & (1<<6))); + // wait for the last char to get out +} + + +void +uart_8250_flush_rx(addr_t base) +{ + // empty the rx fifo + while (read_8250(base, UART_LSR) & (1<<0)) { + volatile char c = read_8250(base, UART_RHR); + (void)c; + } +}