[haiku-commits] haiku: hrev44168 - src/system/kernel/arch/arm src/system/kernel/arch/generic headers/private/kernel/arch/generic src/system headers/private/kernel/arch/arm

  • From: revol@xxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 17 May 2012 04:09:35 +0200 (CEST)

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;
+}
+


Other related posts:

  • » [haiku-commits] haiku: hrev44168 - src/system/kernel/arch/arm src/system/kernel/arch/generic headers/private/kernel/arch/generic src/system headers/private/kernel/arch/arm - revol