hrev44168 adds 1 changeset to branch 'master' old head: 08a14068313189d177778a22ce1b85fc5dcc7e60 new head: e9ec7a55ddffa7a4f12eb8d425f43ec10c5ab258 ---------------------------------------------------------------------------- e9ec7a5: Attempt to factor out serial stuff * introduce a DebugUART baseclass, * rework 8250 and PL011 implementations from kallisti5 to inherit DebutUART, * each arch should override the IO methods to access registers. * on ARM registers are 32bit-aligned. * U-Boot still works for the verdex target. * rPi still compiles, needs testing. * Still some more consolidation needed to allow runtime choice of the UART type (as read from FDT blobs for ex.). * serial.cpp should probably mostly be made generic as well. * didn't touch x86 or ppc yet. [ François Revol <revol@xxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev44168 Commit: e9ec7a55ddffa7a4f12eb8d425f43ec10c5ab258 URL: http://cgit.haiku-os.org/haiku/commit/?id=e9ec7a5 Author: François Revol <revol@xxxxxxx> Date: Thu May 17 02:03:16 2012 UTC ---------------------------------------------------------------------------- 12 files changed, 771 insertions(+), 25 deletions(-) headers/private/kernel/arch/arm/arch_uart_pl011.h | 42 ++ headers/private/kernel/arch/generic/debug_uart.h | 56 +++ .../private/kernel/arch/generic/debug_uart_8250.h | 37 ++ src/system/boot/arch/arm/Jamfile | 22 +- src/system/boot/platform/raspberrypi_arm/Jamfile | 2 + .../boot/platform/raspberrypi_arm/serial.cpp | 22 +- src/system/boot/platform/u-boot/Jamfile | 1 + src/system/boot/platform/u-boot/serial.cpp | 18 +- src/system/kernel/arch/arm/arch_uart_8250.cpp | 78 ++++ src/system/kernel/arch/arm/arch_uart_pl011.cpp | 325 ++++++++++++++++ src/system/kernel/arch/generic/debug_uart_8250.cpp | 174 +++++++++ src/system/kernel/arch/ppc/arch_uart_8250.cpp | 19 + ---------------------------------------------------------------------------- diff --git a/headers/private/kernel/arch/arm/arch_uart_pl011.h b/headers/private/kernel/arch/arm/arch_uart_pl011.h new file mode 100644 index 0000000..19a25e2 --- /dev/null +++ b/headers/private/kernel/arch/arm/arch_uart_pl011.h @@ -0,0 +1,42 @@ +/* + * Copyright 2011-2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Alexander von Gluck, kallisti5@xxxxxxxxxxx + */ +#ifndef __DEV_UART_PL011_H +#define __DEV_UART_PL011_H + + +#include <sys/types.h> +#include <SupportDefs.h> +#include <arch/generic/debug_uart.h> + +class ArchUARTPL011 : public DebugUART { +public: + ArchUARTPL011(addr_t base, int64 clock); + ~ArchUARTPL011(); + + void InitEarly(); + void InitPort(uint32 baud); + + void Enable(); + void Disable(); + + int PutChar(char c); + int GetChar(bool wait); + + void FlushTx(); + void FlushRx(); + +private: + void Out32(int reg, uint32 value); + uint32 In32(int reg); + virtual void Barrier(); +}; + + +ArchUARTPL011 *arch_get_uart_pl011(addr_t base, int64 clock); + +#endif diff --git a/headers/private/kernel/arch/generic/debug_uart.h b/headers/private/kernel/arch/generic/debug_uart.h new file mode 100644 index 0000000..4a2cf03 --- /dev/null +++ b/headers/private/kernel/arch/generic/debug_uart.h @@ -0,0 +1,56 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * François Revol, revol@xxxxxxx + */ +#ifndef _KERNEL_ARCH_DEBUG_UART_H +#define _KERNEL_ARCH_DEBUG_UART_H + + +#include <SupportDefs.h> +#include <sys/types.h> + + +class DebugUART { +public: + DebugUART(addr_t base, int64 clock) + : fBase(base), + fClock(clock), + fEnabled(true) {}; + ~DebugUART() {}; + + virtual void InitEarly() {}; + virtual void Init() {}; + virtual void InitPort(uint32 baud) {}; + + virtual void Enable() { fEnabled = true; } + virtual void Disable() { fEnabled = false; } + + virtual int PutChar(char c) = 0; + virtual int GetChar(bool wait) = 0; + + virtual void FlushTx() = 0; + virtual void FlushRx() = 0; + + addr_t Base() const { return fBase; } + int64 Clock() const { return fClock; } + bool Enabled() const { return fEnabled; } + +protected: + // default MMIO + virtual void Out8(int reg, uint8 value) + { *((uint8 *)Base() + reg) = value; } + virtual uint8 In8(int reg) + { return *((uint8 *)Base() + reg); } + virtual void Barrier() {} + +private: + addr_t fBase; + int64 fClock; + bool fEnabled; +}; + + +#endif /* _KERNEL_ARCH_DEBUG_UART_H */ diff --git a/headers/private/kernel/arch/generic/debug_uart_8250.h b/headers/private/kernel/arch/generic/debug_uart_8250.h new file mode 100644 index 0000000..d4887c9 --- /dev/null +++ b/headers/private/kernel/arch/generic/debug_uart_8250.h @@ -0,0 +1,37 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * François Revol, revol@xxxxxxx + */ +#ifndef _KERNEL_ARCH_DEBUG_UART_8250_H +#define _KERNEL_ARCH_DEBUG_UART_8250_H + + +#include <SupportDefs.h> +#include <sys/types.h> + +#include "debug_uart.h" + + +class DebugUART8250 : public DebugUART { +public: + DebugUART8250(addr_t base, int64 clock); + ~DebugUART8250(); + + void InitEarly(); + void Init(); + void InitPort(uint32 baud); + + int PutChar(char c); + int GetChar(bool wait); + + void FlushTx(); + void FlushRx(); +}; + + +extern DebugUART8250 *arch_get_uart_8250(addr_t base, int64 clock); + +#endif /* _KERNEL_ARCH_DEBUG_UART_8250_H */ diff --git a/src/system/boot/arch/arm/Jamfile b/src/system/boot/arch/arm/Jamfile index 9f66dce..0b7e1e3 100644 --- a/src/system/boot/arch/arm/Jamfile +++ b/src/system/boot/arch/arm/Jamfile @@ -1,9 +1,18 @@ SubDir HAIKU_TOP src system boot arch arm ; -DEFINES += _BOOT_MODE ; +#DEFINES += _BOOT_MODE ; +#XXX: should not be needed here UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) board $(TARGET_BOOT_BOARD) ] ; +{ + local defines = _BOOT_MODE ; + + defines = [ FDefines $(defines) ] ; + SubDirCcFlags $(defines) ; + SubDirC++Flags $(defines) -fno-rtti ; +} + # TODO: Is there any reason to recompile arch_string.S here? local librootArchObjects = # <src!system!libroot!posix!string!arch!$(TARGET_ARCH)>arch_string.o @@ -16,9 +25,9 @@ local kernelLibArchObjects = ; KernelMergeObject boot_arch_$(TARGET_ARCH).o : - uart.cpp - uart_8250.cpp - uart_pl011.cpp + debug_uart_8250.cpp + arch_uart_8250.cpp + arch_uart_pl011.cpp arch_elf.cpp arch_video.cpp arch_video_920.cpp @@ -30,8 +39,11 @@ KernelMergeObject boot_arch_$(TARGET_ARCH).o : $(kernelLibArchObjects) ; -SEARCH on [ FGristFiles arch_elf.cpp uart.cpp uart_8250.cpp uart_pl011.cpp ] +SEARCH on [ FGristFiles arch_elf.cpp uart.cpp arch_uart_8250.cpp arch_uart_pl011.cpp ] = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_ARCH) ] ; +SEARCH on [ FGristFiles debug_uart_8250.cpp ] + = [ FDirName $(HAIKU_TOP) src system kernel arch generic ] ; + SEARCH on [ FGristFiles $(librootArchObjects) ] = [ FDirName $(HAIKU_TOP) src system libroot posix string arch $(TARGET_ARCH) ] ; diff --git a/src/system/boot/platform/raspberrypi_arm/Jamfile b/src/system/boot/platform/raspberrypi_arm/Jamfile index 036c5df..179f0d5 100644 --- a/src/system/boot/platform/raspberrypi_arm/Jamfile +++ b/src/system/boot/platform/raspberrypi_arm/Jamfile @@ -7,6 +7,8 @@ UsePrivateHeaders [ FDirName graphics common ] ; UsePrivateHeaders [ FDirName graphics vesa ] ; UsePrivateHeaders [ FDirName storage ] ; +UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) board $(TARGET_BOOT_BOARD) ] ; + { local defines = _BOOT_MODE ; diff --git a/src/system/boot/platform/raspberrypi_arm/serial.cpp b/src/system/boot/platform/raspberrypi_arm/serial.cpp index a85c69d..3d58f87 100644 --- a/src/system/boot/platform/raspberrypi_arm/serial.cpp +++ b/src/system/boot/platform/raspberrypi_arm/serial.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2004-2008, Axel D??rfler, axeld@xxxxxxxxxxxxxxxxx + * Copyright 2004-2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx * Distributed under the terms of the MIT License. * * Copyright 2009 Jonas Sundström, jonas@xxxxxxxxxxx @@ -8,8 +8,9 @@ #include "serial.h" -#include "uart.h" +#include "arch_uart_pl011.h" +#include "board_config.h" #include <boot/platform.h> #include <arch/cpu.h> #include <boot/stage2.h> @@ -17,7 +18,7 @@ #include <string.h> -UartPL011 gLoaderUART(uart_base_debug()); +DebugUART *gUART; static bool sSerialEnabled = false; @@ -26,14 +27,14 @@ static bool sSerialEnabled = false; static void serial_putc(char c) { - gLoaderUART.PutChar(c); + gUART->PutChar(c); } extern "C" int serial_getc(bool wait) { - return gLoaderUART.GetChar(wait); + return gUART->GetChar(wait); } @@ -63,14 +64,14 @@ serial_disable(void) if (sSerialEnabled) serial_cleanup(); - gLoaderUART.Disable(); + gUART->Disable(); } extern "C" void serial_enable(void) { - gLoaderUART.Enable(); + gUART->Enable(); sSerialEnabled = true; } @@ -79,15 +80,16 @@ extern "C" void serial_cleanup(void) { sSerialEnabled = false; - gLoaderUART.FlushTx(); + gUART->FlushTx(); } extern "C" void serial_init(void) { - gLoaderUART.InitEarly(); - gLoaderUART.InitPort(9600); + gUART = arch_get_uart_pl011(BOARD_UART_DEBUG, BOARD_UART_CLOCK); + gUART->InitEarly(); + gUART->InitPort(9600); serial_enable(); diff --git a/src/system/boot/platform/u-boot/Jamfile b/src/system/boot/platform/u-boot/Jamfile index bfc086e..fa025c8 100644 --- a/src/system/boot/platform/u-boot/Jamfile +++ b/src/system/boot/platform/u-boot/Jamfile @@ -8,6 +8,7 @@ UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; UsePrivateHeaders [ FDirName graphics common ] ; UsePrivateHeaders [ FDirName graphics vesa ] ; UsePrivateHeaders [ FDirName storage ] ; +UsePrivateHeaders [ FDirName kernel arch generic ] ; # TODO: move this to arch/arm ! diff --git a/src/system/boot/platform/u-boot/serial.cpp b/src/system/boot/platform/u-boot/serial.cpp index 88300e5..2a8f8f9 100644 --- a/src/system/boot/platform/u-boot/serial.cpp +++ b/src/system/boot/platform/u-boot/serial.cpp @@ -9,7 +9,8 @@ #include "serial.h" -#include "uart.h" +#include <debug_uart_8250.h> +#include <board_config.h> #include <boot/platform.h> #include <arch/cpu.h> #include <boot/stage2.h> @@ -17,7 +18,7 @@ #include <string.h> -Uart8250* gLoaderUART; +DebugUART8250* gUART; static int32 sSerialEnabled = 0; static char sBuffer[16384]; @@ -27,7 +28,7 @@ static uint32 sBufferPosition; static void serial_putc(char c) { - gLoaderUART->PutChar(c); + gUART->PutChar(c); } @@ -68,8 +69,8 @@ serial_enable(void) { /* should already be initialized by U-Boot */ /* - gLoaderUART->InitEarly(); - gLoaderUART->InitPort(9600); + gUART->InitEarly(); + gUART->InitPort(9600); */ sSerialEnabled++; } @@ -92,11 +93,8 @@ serial_cleanup(void) extern "C" void serial_init(void) { - static char sUARTBuffer[sizeof(Uart8250)]; - - // Setup information on uart - gLoaderUART = new(sUARTBuffer) Uart8250(uart_base_debug()); - if (gLoaderUART == 0) + gUART = arch_get_uart_8250(BOARD_UART_DEBUG, BOARD_UART_CLOCK); + if (gUART == 0) return; serial_enable(); diff --git a/src/system/kernel/arch/arm/arch_uart_8250.cpp b/src/system/kernel/arch/arm/arch_uart_8250.cpp new file mode 100644 index 0000000..94d07d3 --- /dev/null +++ b/src/system/kernel/arch/arm/arch_uart_8250.cpp @@ -0,0 +1,78 @@ +/* + * Copyright 2011-2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * François Revol, revol@xxxxxxx + */ + +#include <debug.h> +#include <arch/generic/debug_uart_8250.h> +#include <new> +#include <board_config.h> + + +class ArchUART8250 : public DebugUART8250 { +public: + ArchUART8250(addr_t base, int64 clock); + ~ArchUART8250(); + void InitEarly(); + + // ARM MMIO: on ARM the UART regs are aligned on 32bit + virtual void Out8(int reg, uint8 value); + virtual uint8 In8(int reg); +}; + + +ArchUART8250::ArchUART8250(addr_t base, int64 clock) + : DebugUART8250(base, clock) +{ +} + + +ArchUART8250::~ArchUART8250() +{ +} + +void +ArchUART8250::InitEarly() +{ + // 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 +ArchUART8250::Out8(int reg, uint8 value) +{ + *((uint8 *)Base() + reg * sizeof(uint32)) = value; +} + + +uint8 +ArchUART8250::In8(int reg) +{ + return *((uint8 *)Base() + reg * sizeof(uint32)); +} + + +DebugUART8250 *arch_get_uart_8250(addr_t base, int64 clock) +{ + static char buffer[sizeof(ArchUART8250)]; + ArchUART8250 *uart = new(buffer) ArchUART8250(base, clock); + return uart; +} + diff --git a/src/system/kernel/arch/arm/arch_uart_pl011.cpp b/src/system/kernel/arch/arm/arch_uart_pl011.cpp new file mode 100644 index 0000000..ea2bc66 --- /dev/null +++ b/src/system/kernel/arch/arm/arch_uart_pl011.cpp @@ -0,0 +1,325 @@ +/* + * Copyright 2011-2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Alexander von Gluck, kallisti5@xxxxxxxxxxx + */ + + +#include <debug.h> +#include <arch/arm/reg.h> +#include <arch/generic/debug_uart.h> +#include <arch/arm/arch_uart_pl011.h> +//#include <board_config.h> +#include <new> +//#include <target/debugconfig.h> + + +#define PL01x_DR 0x00 // Data read or written +#define PL01x_RSR 0x04 // Receive status, read +#define PL01x_ECR 0x04 // Error clear, write +#define PL010_LCRH 0x08 // Line control, high +#define PL010_LCRM 0x0C // Line control, middle +#define PL010_LCRL 0x10 // Line control, low +#define PL010_CR 0x14 // Control +#define PL01x_FR 0x18 // Flag (r/o) +#define PL010_IIR 0x1C // Interrupt ID (r) +#define PL010_ICR 0x1C // Interrupt clear (w) +#define PL01x_ILPR 0x20 // IrDA low power +#define PL011_IBRD 0x24 // Interrupt baud rate divisor +#define PL011_FBRD 0x28 // Fractional baud rate divisor +#define PL011_LCRH 0x2C // Line control +#define PL011_CR 0x30 // Control +#define PL011_IFLS 0x34 // Interrupt fifo level +#define PL011_IMSC 0x38 // Interrupt mask +#define PL011_RIS 0x3C // Raw interrupt +#define PL011_MIS 0x40 // Masked interrupt +#define PL011_ICR 0x44 // Interrupt clear +#define PL011_DMACR 0x48 // DMA control register + +#define PL011_DR_OE (1 << 11) +#define PL011_DR_BE (1 << 10) +#define PL011_DR_PE (1 << 9) +#define PL011_DR_FE (1 << 8) + +#define PL01x_RSR_OE 0x08 +#define PL01x_RSR_BE 0x04 +#define PL01x_RSR_PE 0x02 +#define PL01x_RSR_FE 0x01 + +#define PL011_FR_RI 0x100 +#define PL011_FR_TXFE 0x080 +#define PL011_FR_RXFF 0x040 +#define PL01x_FR_TXFF 0x020 +#define PL01x_FR_RXFE 0x010 +#define PL01x_FR_BUSY 0x008 +#define PL01x_FR_DCD 0x004 +#define PL01x_FR_DSR 0x002 +#define PL01x_FR_CTS 0x001 +#define PL01x_FR_TMSK (PL01x_FR_TXFF | PL01x_FR_BUSY) + +#define PL011_CR_CTSEN 0x8000 // CTS flow control +#define PL011_CR_RTSEN 0x4000 // RTS flow control +#define PL011_CR_OUT2 0x2000 // OUT2 +#define PL011_CR_OUT1 0x1000 // OUT1 +#define PL011_CR_RTS 0x0800 // RTS +#define PL011_CR_DTR 0x0400 // DTR +#define PL011_CR_RXE 0x0200 // Receive enable +#define PL011_CR_TXE 0x0100 // Transmit enable +#define PL011_CR_LBE 0x0080 // Loopback enable +#define PL010_CR_RTIE 0x0040 +#define PL010_CR_TIE 0x0020 +#define PL010_CR_RIE 0x0010 +#define PL010_CR_MSIE 0x0008 +#define PL01x_CR_IIRLP 0x0004 // SIR low power mode +#define PL01x_CR_SIREN 0x0002 // SIR enable +#define PL01x_CR_UARTEN 0x0001 // UART enable + +#define PL011_LCRH_SPS 0x80 +#define PL01x_LCRH_WLEN_8 0x60 +#define PL01x_LCRH_WLEN_7 0x40 +#define PL01x_LCRH_WLEN_6 0x20 +#define PL01x_LCRH_WLEN_5 0x00 +#define PL01x_LCRH_FEN 0x10 +#define PL01x_LCRH_STP2 0x08 +#define PL01x_LCRH_EPS 0x04 +#define PL01x_LCRH_PEN 0x02 +#define PL01x_LCRH_BRK 0x01 + +#define PL010_IIR_RTIS 0x08 +#define PL010_IIR_TIS 0x04 +#define PL010_IIR_RIS 0x02 +#define PL010_IIR_MIS 0x01 + +#define PL011_IFLS_RX1_8 (0 << 3) +#define PL011_IFLS_RX2_8 (1 << 3) +#define PL011_IFLS_RX4_8 (2 << 3) +#define PL011_IFLS_RX6_8 (3 << 3) +#define PL011_IFLS_RX7_8 (4 << 3) +#define PL011_IFLS_TX1_8 (0 << 0) +#define PL011_IFLS_TX2_8 (1 << 0) +#define PL011_IFLS_TX4_8 (2 << 0) +#define PL011_IFLS_TX6_8 (3 << 0) +#define PL011_IFLS_TX7_8 (4 << 0) + +#define PL011_IFLS_RX_HALF (5 << 3) // ST vendor only +#define PL011_IFLS_TX_HALF (5 << 0) // ST vendor only + +#define PL011_OEIM (1 << 10) // overrun error interrupt mask +#define PL011_BEIM (1 << 9) // break error interrupt mask +#define PL011_PEIM (1 << 8) // parity error interrupt mask +#define PL011_FEIM (1 << 7) // framing error interrupt mask +#define PL011_RTIM (1 << 6) // receive timeout interrupt mask +#define PL011_TXIM (1 << 5) // transmit interrupt mask +#define PL011_RXIM (1 << 4) // receive interrupt mask +#define PL011_DSRMIM (1 << 3) // DSR interrupt mask +#define PL011_DCDMIM (1 << 2) // DCD interrupt mask +#define PL011_CTSMIM (1 << 1) // CTS interrupt mask +#define PL011_RIMIM (1 << 0) // RI interrupt mask + +#define PL011_OEIS (1 << 10) // overrun error interrupt state +#define PL011_BEIS (1 << 9) // break error interrupt state +#define PL011_PEIS (1 << 8) // parity error interrupt state +#define PL011_FEIS (1 << 7) // framing error interrupt state +#define PL011_RTIS (1 << 6) // receive timeout interrupt state +#define PL011_TXIS (1 << 5) // transmit interrupt state +#define PL011_RXIS (1 << 4) // receive interrupt state +#define PL011_DSRMIS (1 << 3) // DSR interrupt state +#define PL011_DCDMIS (1 << 2) // DCD interrupt state +#define PL011_CTSMIS (1 << 1) // CTS interrupt state +#define PL011_RIMIS (1 << 0) // RI interrupt state + +#define PL011_OEIC (1 << 10) // overrun error interrupt clear +#define PL011_BEIC (1 << 9) // break error interrupt clear +#define PL011_PEIC (1 << 8) // parity error interrupt clear +#define PL011_FEIC (1 << 7) // framing error interrupt clear +#define PL011_RTIC (1 << 6) // receive timeout interrupt clear +#define PL011_TXIC (1 << 5) // transmit interrupt clear +#define PL011_RXIC (1 << 4) // receive interrupt clear +#define PL011_DSRMIC (1 << 3) // DSR interrupt clear +#define PL011_DCDMIC (1 << 2) // DCD interrupt clear +#define PL011_CTSMIC (1 << 1) // CTS interrupt clear +#define PL011_RIMIC (1 << 0) // RI interrupt clear + +#define PL011_DMAONERR (1 << 2) // disable dma on err +#define PL011_TXDMAE (1 << 1) // enable transmit dma +#define PL011_RXDMAE (1 << 0) // enable receive dma + + +ArchUARTPL011::ArchUARTPL011(addr_t base, int64 clock) + : DebugUART(base, clock) +{ + Barrier(); + + // ** Loopback test + uint32 cr = PL01x_CR_UARTEN; + // Enable UART + cr |= PL011_CR_TXE; + // Enable TX + cr |= PL011_CR_LBE; + // Enable Loopback mode + Out32(PL011_CR, cr); + + Out32(PL011_FBRD, 0); + Out32(PL011_IBRD, 1); + Out32(PL011_LCRH, 0); // TODO: ST is different tx, rx lcr + + // Write a 0 to the port and wait for confim.. + Out32(PL01x_DR, 0); + + while (In32(PL01x_FR) & PL01x_FR_BUSY) + Barrier(); + + // ** Disable loopback, enable uart + cr = PL01x_CR_UARTEN | PL011_CR_RXE | PL011_CR_TXE; + Out32(PL011_CR, cr); + + // ** Clear interrupts + Out32(PL011_ICR, PL011_OEIS | PL011_BEIS + | PL011_PEIS | PL011_FEIS); + + // ** Disable interrupts + Out32(PL011_IMSC, 0); +} + + +ArchUARTPL011::~ArchUARTPL011() +{ +} + + +void +ArchUARTPL011::Out32(int reg, uint32 data) +{ + *(volatile uint32*)(Base() + reg) = data; +} + + +uint32 +ArchUARTPL011::In32(int reg) +{ + return *(volatile uint32*)(Base() + reg); +} + + +void +ArchUARTPL011::Barrier() +{ + asm volatile ("" : : : "memory"); +} + + + + +void +ArchUARTPL011::InitPort(uint32 baud) +{ + // Calculate baud divisor + uint32 baudDivisor = Clock() / (16 * baud); + uint32 remainder = Clock() % (16 * baud); + uint32 baudFractional = ((8 * remainder) / baud >> 1) + + ((8 * remainder) / baud & 1); + + // Disable UART + Disable(); + + // Set baud divisor + Out32(PL011_IBRD, baudDivisor); + Out32(PL011_FBRD, baudFractional); + + // Set LCR 8n1, enable fifo + Out32(PL011_LCRH, PL01x_LCRH_WLEN_8 | PL01x_LCRH_FEN); + + // Enable UART + Enable(); +} + + +void +ArchUARTPL011::InitEarly() +{ + // Perform special hardware UART configuration +} + + +void +ArchUARTPL011::Enable() +{ + uint32 cr = PL01x_CR_UARTEN; + // Enable UART + cr |= PL011_CR_TXE | PL011_CR_RXE; + // Enable TX and RX + + Out32(PL011_CR, cr); + + DebugUART::Enable(); +} + + +void +ArchUARTPL011::Disable() +{ + // Disable everything + Out32(PL011_CR, 0); + + DebugUART::Disable(); +} + + +int +ArchUARTPL011::PutChar(char c) +{ + if (Enabled() == true) { + // Wait until there is room in fifo + while ((In32(PL01x_FR) & PL01x_FR_TXFF) != 0) + Barrier(); + + Out32(PL01x_DR, c); + return 0; + } + + return -1; +} + + +int +ArchUARTPL011::GetChar(bool wait) +{ + if (Enabled() == true) { + // Wait until a character is received? + if (wait) { + while ((In32(PL01x_FR) & PL01x_FR_RXFE) != 0) + Barrier(); + } + return In32(PL01x_DR); + } + + return -1; +} + + +void +ArchUARTPL011::FlushTx() +{ + // Wait until transmit fifo empty + while ((In32(PL01x_FR) & PL011_FR_TXFE) == 0) + Barrier(); +} + + +void +ArchUARTPL011::FlushRx() +{ + // Wait until receive fifo empty + while ((In32(PL01x_FR) & PL01x_FR_RXFE) == 0) + Barrier(); +} + + +ArchUARTPL011 *arch_get_uart_pl011(addr_t base, int64 clock) +{ + static char buffer[sizeof(ArchUARTPL011)]; + ArchUARTPL011 *uart = new(buffer) ArchUARTPL011(base, clock); + return uart; +} diff --git a/src/system/kernel/arch/generic/debug_uart_8250.cpp b/src/system/kernel/arch/generic/debug_uart_8250.cpp new file mode 100644 index 0000000..39ac561 --- /dev/null +++ b/src/system/kernel/arch/generic/debug_uart_8250.cpp @@ -0,0 +1,174 @@ +/* + * 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/generic/debug_uart_8250.h> + + +DebugUART8250::DebugUART8250(addr_t base, int64 clock) + : DebugUART(base, clock) +{ +} + + +DebugUART8250::~DebugUART8250() +{ +} + +#define UART_RHR 0 +#define UART_THR 0 +#define UART_DLL 0 +#define UART_IER 1 +#define UART_DLH 1 +#define UART_IIR 2 +#define UART_FCR 2 +#define UART_EFR 2 +#define UART_LCR 3 +#define UART_MCR 4 +#define UART_LSR 5 +#define UART_MSR 6 +#define UART_TCR 6 +#define UART_SPR 7 +#define UART_TLR 7 + +#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 +DebugUART8250::InitPort(uint32 baud) +{ + Disable(); + + uint16 baudDivisor = Clock() / (16 * baud); + + // Write standard uart settings + Out8(UART_LCR, LCR_8N1); + // 8N1 + Out8(UART_IER, 0); + // Disable interrupt + Out8(UART_FCR, 0); + // Disable FIFO + Out8(UART_MCR, MCR_DTR | MCR_RTS); + // DTR / RTS + + // Gain access to, and program baud divisor + unsigned char buffer = In8(UART_LCR); + Out8(UART_LCR, buffer | LCR_BKSE); + Out8(UART_DLL, baudDivisor & 0xff); + Out8(UART_DLH, (baudDivisor >> 8) & 0xff); + Out8(UART_LCR, buffer & ~LCR_BKSE); + +// Out8(UART_MDR1, 0); // UART 16x mode +// Out8(UART_LCR, 0xBF); // config mode B +// Out8(UART_EFR, (1<<7)|(1<<6)); // hw flow control +// Out8(UART_LCR, LCR_8N1); // operational mode + + Enable(); +} + + +void +DebugUART8250::InitEarly() +{ +} + + +void +DebugUART8250::Init() +{ +} + + +int +DebugUART8250::PutChar(char c) +{ + while (!(In8(UART_LSR) & (1<<6))); + // wait for the last char to get out + Out8(UART_THR, c); + return 0; +} + + +/* returns -1 if no data available */ +int +DebugUART8250::GetChar(bool wait) +{ + if (wait) { + while (!(In8(UART_LSR) & (1<<0))); + // wait for data to show up in the rx fifo + } else { + if (!(In8(UART_LSR) & (1<<0))) + return -1; + } + return In8(UART_RHR); +} + + +void +DebugUART8250::FlushTx() +{ + while (!(In8(UART_LSR) & (1<<6))); + // wait for the last char to get out +} + + +void +DebugUART8250::FlushRx() +{ + // empty the rx fifo + while (In8(UART_LSR) & (1<<0)) { + volatile char c = In8(UART_RHR); + (void)c; + } +} diff --git a/src/system/kernel/arch/ppc/arch_uart_8250.cpp b/src/system/kernel/arch/ppc/arch_uart_8250.cpp new file mode 100644 index 0000000..ee990fb --- /dev/null +++ b/src/system/kernel/arch/ppc/arch_uart_8250.cpp @@ -0,0 +1,19 @@ +/* + * Copyright 2012, François Revol, revol@xxxxxxx + * Distributed under the terms of the MIT License. + */ + +#include <debug.h> +#include <arch/generic/debug_uart_8250.h> +//#include <board_config.h> + + +// we shouldn't need special setup, we use plain MMIO. + +DebugUART8250 *arch_get_uart_8250(addr_t base, int64 clock) +{ + static char buffer[sizeof(DebugUART8250)]; + DebugUART8250 *uart = new(buffer) DebugUART8250(base, clock); + return uart; +} +