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.
This commit is contained in:
Alexander von Gluck IV
2012-05-08 22:17:03 -05:00
parent 58f3387d56
commit 78004f1677
9 changed files with 163 additions and 199 deletions
+1 -25
View File
@@ -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
+24 -17
View File
@@ -24,24 +24,31 @@
#define __DEV_UART_8250_H
#include <SupportDefs.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_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);
#ifdef __cplusplus
}
#endif
class Uart8250 {
public:
Uart8250(addr_t base);
~Uart8250();
void InitEarly();
void Init();
void InitPort(uint32 baud);
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;
};
#endif
+24 -17
View File
@@ -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
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);
#ifdef __cplusplus
}
#endif
class UartPL011 {
public:
UartPL011(addr_t base);
~UartPL011();
void InitEarly();
void Init();
void InitPort(uint32 baud);
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;
};
#endif
@@ -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();
+6 -11
View File
@@ -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();
}
@@ -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 defined(BOARD_UART_AMBA_PL011)
gArchDebugUART = new UartPL011(uart_base_debug());
#else
gArchDebugUART = new Uart8250(uart_base_debug());
#endif
if (gUART == NULL)
return B_ERROR;
gUART->init_early();
gArchDebugUART->InitEarly();
return B_OK;
}
+1 -41
View File
@@ -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);
}
+47 -35
View File
@@ -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);
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);
// 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
// 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;
}
}
+41 -29
View File
@@ -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
}