arm uart: Complete redesign of ARM uart code

* Add nested function wrappers to allow usage of other
  uart drivers depending on board. We may want to use this
  on other platforms at some point (haha, maybe)
This commit is contained in:
Alexander von Gluck IV 2012-05-06 16:26:08 -05:00
parent 95aae4ae1e
commit 917e9be1a6
14 changed files with 372 additions and 220 deletions

View File

@ -14,11 +14,13 @@
#include <arch/arm/omap3.h>
// 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)

View File

@ -14,11 +14,13 @@
#include <arch/arm/arm920t.h>
// 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)

View File

@ -14,11 +14,13 @@
#include <arch/arm/omap3.h>
// 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)

View File

@ -16,11 +16,13 @@
#include <arch/arm/bcm2708.h>
// 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 */

View File

@ -14,11 +14,13 @@
#include <arch/arm/pxa270.h>
// 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)

View File

@ -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 <sys/types.h>
#include <sys/types.h>
#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

View File

@ -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 <sys/types.h>
#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

View File

@ -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) ]

View File

@ -17,8 +17,9 @@
#include <string.h>
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');

View File

@ -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 <boot/stage2.h>
#include <string.h>
// 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();
}

View File

@ -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

View File

@ -19,6 +19,9 @@
#include <string.h>
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;
}

View File

@ -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 <debug.h>
#include <arch/arm/reg.h>
#include <arch/arm/uart.h>
#include <board_config.h>
#include <debug.h>
#include <stdlib.h>
//#include <target/debugconfig.h>
#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);
}

View File

@ -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 <debug.h>
#include <arch/arm/reg.h>
#include <arch/arm/uart.h>
#include <board_config.h>
//#include <target/debugconfig.h>
#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;
}
}