Index: HelenOS.config
===================================================================
--- HelenOS.config	(revision 119b46e45d903caf31b28eb1f2046fe108aa20c4)
+++ HelenOS.config	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -66,4 +66,5 @@
 @ "beagleboardxm" BeagleBoard-xM
 @ "beaglebone" BeagleBone
+@ "raspberrypi" Raspberry Pi
 ! [PLATFORM=arm32] MACHINE (choice)
 
@@ -99,4 +100,7 @@
 ! [PLATFORM=arm32&MACHINE=integratorcp] PROCESSOR (choice)
 
+% CPU type
+@ "arm1176" ARM1176
+! [PLATFORM=arm32&MACHINE=raspberrypi] PROCESSOR (choice)
 
 # Add more ARMv4 CPUs
@@ -109,4 +113,9 @@
 @ "armv5" ARMv5
 ! [PLATFORM=arm32&(PROCESSOR=arm926ej_s)] PROCESSOR_ARCH (choice)
+
+# Add more ARMv6 CPUs
+% CPU arch
+@ "armv6" ARMv6
+! [PLATFORM=arm32&(PROCESSOR=arm1176)] PROCESSOR_ARCH (choice)
 
 # Add more ARMv7-A CPUs
@@ -447,5 +456,5 @@
 % Output device class
 @ "generic" Monitor or serial line
-! [PLATFORM=arm32&(MACHINE=gta02|MACHINE=integratorcp|MACHINE=beagleboardxm|MACHINE=beaglebone)] CONFIG_HID_OUT (choice)
+! [PLATFORM=arm32&(MACHINE=gta02|MACHINE=integratorcp|MACHINE=beagleboardxm|MACHINE=beaglebone|MACHINE=raspberrypi)] CONFIG_HID_OUT (choice)
 
 % Output device class
@@ -481,4 +490,7 @@
 ! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&PLATFORM=arm32&MACHINE=integratorcp] CONFIG_ARM926_UART (y/n)
 
+% Support for BCM2835 on-chip UART
+! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&PLATFORM=arm32&MACHINE=raspberrypi] CONFIG_BCM2835_UART (y/n)
+
 % Support for Samsung S3C24XX on-chip UART
 ! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&PLATFORM=arm32&MACHINE=gta02] CONFIG_S3C24XX_UART (y/n)
@@ -515,5 +527,5 @@
 
 % Serial line input module
-! [CONFIG_DSRLNIN=y|(PLATFORM=arm32&MACHINE=gta02)|(PLATFORM=arm32&MACHINE=integratorcp&CONFIG_ARM926_UART=y)|(PLATFORM=arm32&MACHINE=beaglebone&CONFIG_AM335X_UART=y)|(PLATFORM=arm32&MACHINE=beagleboardxm&CONFIG_AMDM37X_UART=y)|(PLATFORM=ia64&MACHINE=i460GX&CONFIG_NS16550=y)|(PLATFORM=ia64&MACHINE=ski)|(PLATFORM=sparc64&PROCESSOR=sun4v)] CONFIG_SRLN (y)
+! [CONFIG_DSRLNIN=y|(PLATFORM=arm32&MACHINE=gta02)|(PLATFORM=arm32&MACHINE=integratorcp&CONFIG_ARM926_UART=y)|(PLATFORM=arm32&MACHINE=beaglebone&CONFIG_AM335X_UART=y)|(PLATFORM=arm32&MACHINE=beagleboardxm&CONFIG_AMDM37X_UART=y)|(PLATFORM=ia64&MACHINE=i460GX&CONFIG_NS16550=y)|(PLATFORM=ia64&MACHINE=ski)|(PLATFORM=sparc64&PROCESSOR=sun4v)|(PLATFORM=arm32&MACHINE=raspberrypi&CONFIG_BCM2835_UART=y)] CONFIG_SRLN (y)
 
 % EGA support
Index: boot/arch/arm32/Makefile.inc
===================================================================
--- boot/arch/arm32/Makefile.inc	(revision 119b46e45d903caf31b28eb1f2046fe108aa20c4)
+++ boot/arch/arm32/Makefile.inc	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -43,4 +43,12 @@
 endif
 
+ifeq ($(MACHINE), raspberrypi)
+	BOOT_OUTPUT = image.boot
+	POST_OUTPUT = $(ROOT_PATH)/uImage.bin	
+	LADDR = 0x00008000
+	SADDR = 0x00008000
+	POSTBUILD = Makefile.uboot	     
+endif
+
 BFD_NAME = elf32-littlearm
 BFD_OUTPUT = $(BFD_NAME)
Index: boot/arch/arm32/include/arch.h
===================================================================
--- boot/arch/arm32/include/arch.h	(revision 119b46e45d903caf31b28eb1f2046fe108aa20c4)
+++ boot/arch/arm32/include/arch.h	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -46,4 +46,6 @@
 #elif defined MACHINE_beaglebone
 #define BOOT_BASE       0x80000000
+#elif defined MACHINE_raspberrypi
+#define BOOT_BASE	0x00008000
 #else
 #define BOOT_BASE	0x00000000
Index: boot/arch/arm32/include/main.h
===================================================================
--- boot/arch/arm32/include/main.h	(revision 119b46e45d903caf31b28eb1f2046fe108aa20c4)
+++ boot/arch/arm32/include/main.h	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -75,4 +75,24 @@
 #define ICP_SCONS_ADDR		0x16000000
 
+/** Raspberry PI serial console registers */
+#define BCM2835_UART0_BASE	0x20201000
+#define BCM2835_UART0_DR	(BCM2835_UART0_BASE + 0x00)
+#define BCM2835_UART0_FR	(BCM2835_UART0_BASE + 0x18)
+#define BCM2835_UART0_ILPR	(BCM2835_UART0_BASE + 0x20)
+#define BCM2835_UART0_IBRD	(BCM2835_UART0_BASE + 0x24)
+#define BCM2835_UART0_FBRD	(BCM2835_UART0_BASE + 0x28)
+#define BCM2835_UART0_LCRH	(BCM2835_UART0_BASE + 0x2C)
+#define BCM2835_UART0_CR	(BCM2835_UART0_BASE + 0x30)
+#define BCM2835_UART0_ICR	(BCM2835_UART0_BASE + 0x44)
+
+#define BCM2835_UART0_FR_TXFF	(1 << 5)
+#define BCM2835_UART0_LCRH_FEN	(1 << 4)
+#define BCM2835_UART0_LCRH_WL8	((1 << 5) | (1 << 6))
+#define BCM2835_UART0_CR_UARTEN	(1 << 0)
+#define BCM2835_UART0_CR_TXE	(1 << 8)
+#define BCM2835_UART0_CR_RXE	(1 << 9)
+
+
+
 extern void bootstrap(void);
 
Index: boot/arch/arm32/include/mm.h
===================================================================
--- boot/arch/arm32/include/mm.h	(revision 119b46e45d903caf31b28eb1f2046fe108aa20c4)
+++ boot/arch/arm32/include/mm.h	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -68,4 +68,8 @@
 #define AM335x_RAM_END     0xC0000000
 
+/** Start of ram memory on BCM2835 */
+#define BCM2835_RAM_START   0
+/** End of ram memory on BCM2835 */
+#define BCM2835_RAM_END     0x20000000
 
 /* Page table level 0 entry - "section" format is used
Index: boot/arch/arm32/src/mm.c
===================================================================
--- boot/arch/arm32/src/mm.c	(revision 119b46e45d903caf31b28eb1f2046fe108aa20c4)
+++ boot/arch/arm32/src/mm.c	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -75,4 +75,8 @@
 	if (address >= AM335x_RAM_START && address < AM335x_RAM_END)
 		return 1;
+#elif defined MACHINE_raspberrypi
+	const unsigned long address = section << PTE_SECTION_SHIFT;
+	if (address < BCM2835_RAM_END)
+		return 1;
 #endif
 	return 0;
@@ -113,10 +117,19 @@
 static void init_boot_pt(void)
 {
+#if defined MACHINE_raspberrypi
+	const pfn_t split_page = 2048;
+#else
 	const pfn_t split_page = PTL0_ENTRIES;
+#endif
+
 	/* Create 1:1 virtual-physical mapping (in lower 2 GB). */
 	pfn_t page;
 	for (page = 0; page < split_page; page++)
 		init_ptl0_section(&boot_pt[page], page);
-	
+
+#if defined MACHINE_raspberrypi
+	for (; page < PTL0_ENTRIES; page++)
+		init_ptl0_section(&boot_pt[page], page - split_page);
+#endif	
 	asm volatile (
 		"mcr p15, 0, %[pt], c2, c0, 0\n"
Index: boot/arch/arm32/src/putchar.c
===================================================================
--- boot/arch/arm32/src/putchar.c	(revision 119b46e45d903caf31b28eb1f2046fe108aa20c4)
+++ boot/arch/arm32/src/putchar.c	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -122,4 +122,46 @@
 #endif
 
+#ifdef MACHINE_raspberrypi
+
+static int raspi_init;
+
+static inline void write32(uint32_t addr, uint32_t data)
+{
+	*(volatile uint32_t *)(addr) = data;
+}
+
+static inline uint32_t read32(uint32_t addr)
+{
+	return *(volatile uint32_t *)(addr);
+}
+
+static void scons_init_raspi(void)
+{
+	write32(BCM2835_UART0_CR, 0x0);		/* Disable UART */
+	write32(BCM2835_UART0_ICR, 0x7f);	/* Clear interrupts */
+	write32(BCM2835_UART0_IBRD, 1);		/* Set integer baud rate */
+	write32(BCM2835_UART0_FBRD, 40);	/* Set fractional baud rate */
+	write32(BCM2835_UART0_LCRH,
+		BCM2835_UART0_LCRH_FEN |	/* Enable FIFOs */
+		BCM2835_UART0_LCRH_WL8);	/* Word length: 8 */
+	write32(BCM2835_UART0_CR,
+		BCM2835_UART0_CR_UARTEN |	/* Enable UART */
+		BCM2835_UART0_CR_TXE |		/* Enable TX */
+		BCM2835_UART0_CR_RXE);		/* Enable RX */
+}
+
+static void scons_sendb_raspi(uint8_t byte)
+{
+	if (!raspi_init) {
+		scons_init_raspi();
+		raspi_init = 1;
+	}
+
+	while (read32(BCM2835_UART0_FR) & BCM2835_UART0_FR_TXFF);
+
+	write32(BCM2835_UART0_DR, byte);
+}
+#endif
+
 /** Send a byte to the serial console.
  *
@@ -139,4 +181,7 @@
 #ifdef MACHINE_integratorcp
 	scons_sendb_icp(byte);
+#endif
+#ifdef MACHINE_raspberrypi
+	scons_sendb_raspi(byte);
 #endif
 }
Index: kernel/arch/arm32/Makefile.inc
===================================================================
--- kernel/arch/arm32/Makefile.inc	(revision 119b46e45d903caf31b28eb1f2046fe108aa20c4)
+++ kernel/arch/arm32/Makefile.inc	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -89,4 +89,8 @@
 endif
 
+ifeq ($(MACHINE),raspberrypi)
+	ARCH_SOURCES += arch/$(KARCH)/src/mach/raspberrypi/raspberrypi.c
+endif
+
 ifeq ($(CONFIG_PL050),y)
 	ARCH_SOURCES += genarch/src/drivers/pl050/pl050.c
Index: kernel/arch/arm32/_link.ld.in
===================================================================
--- kernel/arch/arm32/_link.ld.in	(revision 119b46e45d903caf31b28eb1f2046fe108aa20c4)
+++ kernel/arch/arm32/_link.ld.in	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -13,4 +13,6 @@
 #elif defined MACHINE_beaglebone
 #define KERNEL_LOAD_ADDRESS 0x80a00000
+#elif defined MACHINE_raspberrypi
+#define KERNEL_LOAD_ADDRESS 0x80a08000
 #else
 #define KERNEL_LOAD_ADDRESS 0x80a00000
Index: kernel/arch/arm32/include/arch/cp15.h
===================================================================
--- kernel/arch/arm32/include/arch/cp15.h	(revision 119b46e45d903caf31b28eb1f2046fe108aa20c4)
+++ kernel/arch/arm32/include/arch/cp15.h	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -223,4 +223,5 @@
 	SCTLR_FAST_IRQ_EN_FLAG       = 1 << 21, /* Disable impl. specific feat*/
 	SCTLR_UNALIGNED_EN_FLAG      = 1 << 22, /* Must be 1 on armv7 */
+	SCTLR_EXTENDED_PT_EN_FLAG    = 1 << 23,
 	SCTLR_IRQ_VECTORS_EN_FLAG    = 1 << 24,
 	SCTLR_BIG_ENDIAN_EXC_FLAG    = 1 << 25,
Index: kernel/arch/arm32/include/arch/mach/raspberrypi/raspberrypi.h
===================================================================
--- kernel/arch/arm32/include/arch/mach/raspberrypi/raspberrypi.h	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
+++ kernel/arch/arm32/include/arch/mach/raspberrypi/raspberrypi.h	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013 Beniamino Galvani
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup arm32raspberrypi raspberrypi
+ *  @brief Raspberry Pi platform.
+ *  @ingroup arm32
+ * @{
+ */
+/** @file
+ *  @brief Raspberry Pi platform driver.
+ */
+
+#ifndef KERN_arm32_raspberrypi_H_
+#define KERN_arm32_raspberrypi_H_
+
+#include <arch/machine_func.h>
+
+extern struct arm_machine_ops raspberrypi_machine_ops;
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/arm32/include/arch/mm/frame.h
===================================================================
--- kernel/arch/arm32/include/arch/mm/frame.h	(revision 119b46e45d903caf31b28eb1f2046fe108aa20c4)
+++ kernel/arch/arm32/include/arch/mm/frame.h	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -61,4 +61,9 @@
 #define BOOT_PAGE_TABLE_ADDRESS  0x80008000
 
+#elif defined MACHINE_raspberrypi
+
+#define PHYSMEM_START_ADDR       0x00000000
+#define BOOT_PAGE_TABLE_ADDRESS  0x00010000
+
 #else
 
Index: kernel/arch/arm32/src/mach/raspberrypi/raspberrypi.c
===================================================================
--- kernel/arch/arm32/src/mach/raspberrypi/raspberrypi.c	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
+++ kernel/arch/arm32/src/mach/raspberrypi/raspberrypi.c	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2013 Beniamino Galvani
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup arm32raspberrypi
+ * @{
+ */
+/** @file
+ *  @brief Raspberry PI platform driver.
+ */
+
+#include <arch/exception.h>
+#include <arch/mach/raspberrypi/raspberrypi.h>
+#include <genarch/drivers/bcm2835/pl011_uart.h>
+#include <genarch/drivers/bcm2835/irc.h>
+#include <genarch/drivers/bcm2835/timer.h>
+#include <arch/mm/page.h>
+#include <mm/page.h>
+#include <mm/km.h>
+#include <genarch/fb/fb.h>
+#include <abi/fb/visuals.h>
+#include <genarch/srln/srln.h>
+#include <sysinfo/sysinfo.h>
+#include <interrupt.h>
+#include <ddi/ddi.h>
+#include <ddi/device.h>
+
+#define RPI_MEMORY_START 0
+/*
+ * TODO: size of available memory depends on hw model and
+ * bootloader configuration, we should detect it somehow.
+ * 128MB should be a safe value for now.
+ * */
+#define RPI_MEMORY_SIZE  0x08000000
+#define RPI_MEMORY_SKIP  0x8000
+
+static void raspberrypi_init(void);
+static void raspberrypi_timer_irq_start(void);
+static void raspberrypi_cpu_halt(void);
+static void raspberrypi_get_memory_extents(uintptr_t *start, size_t *size);
+static void raspberrypi_irq_exception(unsigned int exc_no, istate_t *istate);
+static void raspberrypi_frame_init(void);
+static void raspberrypi_output_init(void);
+static void raspberrypi_input_init(void);
+static size_t raspberrypi_get_irq_count(void);
+static const char *raspberrypi_get_platform_name(void);
+
+static struct {
+	pl011_uart_t	uart;
+	bcm2835_irc_t	*irc;
+	bcm2835_timer_t	*timer;
+} raspi;
+
+struct arm_machine_ops raspberrypi_machine_ops = {
+	raspberrypi_init,
+	raspberrypi_timer_irq_start,
+	raspberrypi_cpu_halt,
+	raspberrypi_get_memory_extents,
+	raspberrypi_irq_exception,
+	raspberrypi_frame_init,
+	raspberrypi_output_init,
+	raspberrypi_input_init,
+	raspberrypi_get_irq_count,
+	raspberrypi_get_platform_name
+};
+
+static irq_ownership_t raspberrypi_timer_irq_claim(irq_t *irq)
+{
+	return IRQ_ACCEPT;
+}
+
+static void raspberrypi_timer_irq_handler(irq_t *irq)
+{
+	bcm2835_timer_irq_ack(raspi.timer);
+	spinlock_unlock(&irq->lock);
+	clock();
+	spinlock_lock(&irq->lock);
+}
+
+static void raspberrypi_init(void)
+{
+	/* Initialize interrupt controller */
+	raspi.irc = (void *) km_map(BCM2835_IRC_ADDR, sizeof(bcm2835_irc_t),
+				    PAGE_NOT_CACHEABLE);
+	ASSERT(raspi.irc);
+	bcm2835_irc_init(raspi.irc);
+
+	/* Initialize system timer */
+	raspi.timer = (void *) km_map(BCM2835_TIMER_ADDR,
+				      sizeof(bcm2835_timer_t),
+				      PAGE_NOT_CACHEABLE);
+}
+
+static void raspberrypi_timer_irq_start(void)
+{
+	/* Initialize timer IRQ */
+	static irq_t timer_irq;
+	irq_initialize(&timer_irq);
+	timer_irq.devno = device_assign_devno();
+	timer_irq.inr = BCM2835_TIMER1_IRQ;
+	timer_irq.claim = raspberrypi_timer_irq_claim;
+	timer_irq.handler = raspberrypi_timer_irq_handler;
+	irq_register(&timer_irq);
+
+	bcm2835_irc_enable(raspi.irc, BCM2835_TIMER1_IRQ);
+	bcm2835_timer_start(raspi.timer);
+}
+
+static void raspberrypi_cpu_halt(void)
+{
+	while (1) ;
+}
+
+/** Get extents of available memory.
+ *
+ * @param start		Place to store memory start address (physical).
+ * @param size		Place to store memory size.
+ */
+static void raspberrypi_get_memory_extents(uintptr_t *start, size_t *size)
+{
+	*start = RPI_MEMORY_START + RPI_MEMORY_SKIP;
+	*size  = RPI_MEMORY_SIZE - RPI_MEMORY_SKIP;
+}
+
+static void raspberrypi_irq_exception(unsigned int exc_no, istate_t *istate)
+{
+	const unsigned inum = bcm2835_irc_inum_get(raspi.irc);
+
+	irq_t *irq = irq_dispatch_and_lock(inum);
+	if (irq) {
+		/* The IRQ handler was found. */
+		irq->handler(irq);
+		spinlock_unlock(&irq->lock);
+	} else {
+		/* Spurious interrupt.*/
+		printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, inum);
+		bcm2835_irc_disable(raspi.irc, inum);
+	}
+}
+
+static void raspberrypi_frame_init(void)
+{
+}
+
+static void raspberrypi_output_init(void)
+{
+#ifdef CONFIG_BCM2835_UART
+	if (pl011_uart_init(&raspi.uart, BCM2835_UART_IRQ,
+			    PL011_UART0_BASE_ADDRESS,
+			    sizeof(pl011_uart_regs_t)))
+		stdout_wire(&raspi.uart.outdev);
+#endif
+}
+
+static void raspberrypi_input_init(void)
+{
+	srln_instance_t *srln_instance = srln_init();
+	if (srln_instance) {
+		indev_t *sink = stdin_wire();
+		indev_t *srln = srln_wire(srln_instance, sink);
+
+		pl011_uart_input_wire(&raspi.uart, srln);
+		bcm2835_irc_enable(raspi.irc, BCM2835_UART_IRQ);
+	}
+}
+
+size_t raspberrypi_get_irq_count(void)
+{
+	return BCM2835_IRQ_COUNT;
+}
+
+const char *raspberrypi_get_platform_name(void)
+{
+	return "raspberrypi";
+}
+
+/** @}
+ */
Index: kernel/arch/arm32/src/machine_func.c
===================================================================
--- kernel/arch/arm32/src/machine_func.c	(revision 119b46e45d903caf31b28eb1f2046fe108aa20c4)
+++ kernel/arch/arm32/src/machine_func.c	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -43,4 +43,5 @@
 #include <arch/mach/beagleboardxm/beagleboardxm.h>
 #include <arch/mach/beaglebone/beaglebone.h>
+#include <arch/mach/raspberrypi/raspberrypi.h>
 
 /** Pointer to machine_ops structure being used. */
@@ -58,4 +59,6 @@
 #elif defined(MACHINE_beaglebone)
 	machine_ops = &bbone_machine_ops;
+#elif defined(MACHINE_raspberrypi)
+	machine_ops = &raspberrypi_machine_ops;
 #else
 #error Machine type not defined.
Index: kernel/arch/arm32/src/mm/page.c
===================================================================
--- kernel/arch/arm32/src/mm/page.c	(revision 119b46e45d903caf31b28eb1f2046fe108aa20c4)
+++ kernel/arch/arm32/src/mm/page.c	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -55,4 +55,8 @@
 	page_mapping_operations = &pt_mapping_operations;
 
+#ifdef PROCESSOR_ARCH_armv6
+	/* Select ARMv6 and ARMv7 memory model */
+	SCTLR_write(SCTLR_read() | SCTLR_EXTENDED_PT_EN_FLAG);
+#endif
 	page_table_lock(AS_KERNEL, true);
 	
Index: kernel/genarch/Makefile.inc
===================================================================
--- kernel/genarch/Makefile.inc	(revision 119b46e45d903caf31b28eb1f2046fe108aa20c4)
+++ kernel/genarch/Makefile.inc	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -96,4 +96,9 @@
 endif
 
+ifeq ($(CONFIG_BCM2835_UART),y)
+	GENARCH_SOURCES += \
+		genarch/src/drivers/bcm2835/pl011_uart.c
+endif
+
 ifeq ($(CONFIG_S3C24XX_IRQC),y)
 	GENARCH_SOURCES += \
Index: kernel/genarch/include/genarch/drivers/bcm2835/irc.h
===================================================================
--- kernel/genarch/include/genarch/drivers/bcm2835/irc.h	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
+++ kernel/genarch/include/genarch/drivers/bcm2835/irc.h	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2012 Jan Vesely
+ * Copyright (c) 2013 Beniamino Galvani
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup genarch
+ * @{
+ */
+/**
+ * @file
+ * @brief Broadcom BCM2835 on-chip interrupt controller driver.
+ */
+
+#ifndef KERN_BCM2835_IRQC_H_
+#define KERN_BCM2835_IRQC_H_
+
+#include <typedefs.h>
+
+#define BANK_GPU0	0
+#define BANK_GPU1	1
+#define BANK_ARM	2
+
+#define IRQ_TO_BANK(x)	((x) >> 5)
+#define IRQ_TO_NUM(x)	((x) & 0x1f)
+
+#define MAKE_IRQ(b,n)	(((b) << 5) | ((n) & 0x1f))
+
+#define BCM2835_UART_IRQ	MAKE_IRQ(BANK_GPU1, 25)
+#define BCM2835_TIMER1_IRQ	MAKE_IRQ(BANK_GPU0,  1)
+
+typedef struct {
+	ioport32_t	irq_basic_pending;
+	ioport32_t	irq_pending1;
+	ioport32_t	irq_pending2;
+
+	ioport32_t	fiq_control;
+
+	ioport32_t	irq_enable[3];
+	ioport32_t	irq_disable[3];
+} bcm2835_irc_t;
+
+#define BCM2835_IRC_ADDR 0x2000b200
+#define BCM2835_IRQ_COUNT 96
+
+static inline void bcm2835_irc_dump(bcm2835_irc_t *regs)
+{
+#define DUMP_REG(name) \
+	printf("%s : %08x\n", #name, regs->name);
+
+	DUMP_REG(irq_basic_pending);
+	DUMP_REG(irq_pending1);
+	DUMP_REG(irq_pending2);
+	DUMP_REG(fiq_control);
+
+	for (int i = 0; i < 3; ++i) {
+		DUMP_REG(irq_enable[i]);
+		DUMP_REG(irq_disable[i]);
+	}
+#undef DUMP_REG
+}
+
+static inline void bcm2835_irc_init(bcm2835_irc_t *regs)
+{
+	/* Disable all interrupts */
+	regs->irq_disable[BANK_GPU0] = 0xffffffff;
+	regs->irq_disable[BANK_GPU1] = 0xffffffff;
+	regs->irq_disable[BANK_ARM]  = 0xffffffff;
+
+	/* Disable FIQ generation */
+	regs->fiq_control = 0;
+}
+
+static inline int ffs(unsigned int x)
+{
+	int ret;
+
+	asm volatile (
+		"clz r0, %[x]\n"
+		"rsb %[ret], r0, #32\n"
+		: [ret] "=r" (ret)
+		: [x] "r" (x)
+		: "r0" );
+
+	return ret;
+}
+
+static inline unsigned bcm2835_irc_inum_get(bcm2835_irc_t *regs)
+{
+	uint32_t pending;
+
+	/* TODO: use 'shortcut' bits in basic pending register */
+
+	pending = regs->irq_basic_pending;
+	if (pending & 0xff)
+		return MAKE_IRQ(BANK_ARM, ffs(pending & 0xFF) - 1);
+
+	pending = regs->irq_pending1;
+	if (pending)
+		return MAKE_IRQ(BANK_GPU0, ffs(pending) - 1);
+
+	pending = regs->irq_pending2;
+	if (pending)
+		return MAKE_IRQ(BANK_GPU1, ffs(pending) - 1);
+
+	printf("Spurious interrupt!\n");
+	bcm2835_irc_dump(regs);
+	return 0;
+}
+
+static inline void bcm2835_irc_enable(bcm2835_irc_t *regs, unsigned inum)
+{
+	ASSERT(inum < BCM2835_IRQ_COUNT);
+	regs->irq_enable[IRQ_TO_BANK(inum)] |= (1 << IRQ_TO_NUM(inum));
+}
+
+static inline void bcm2835_irc_disable(bcm2835_irc_t *regs, unsigned inum)
+{
+	ASSERT(inum < BCM2835_IRQ_COUNT);
+	regs->irq_disable[IRQ_TO_BANK(inum)] |= (1 << IRQ_TO_NUM(inum));
+}
+
+#endif /* KERN_BCM2835_IRQC_H_ */
+
+/**
+ * @}
+ */
Index: kernel/genarch/include/genarch/drivers/bcm2835/pl011_uart.h
===================================================================
--- kernel/genarch/include/genarch/drivers/bcm2835/pl011_uart.h	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
+++ kernel/genarch/include/genarch/drivers/bcm2835/pl011_uart.h	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2012 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genarch
+ * @{
+ */
+/**
+ * @file
+ * @brief PL011 on-chip UART (PrimeCell UART, PL011) driver.
+ */
+
+#ifndef KERN_PL011_UART_H_
+#define KERN_PL011_UART_H_
+
+#include <ddi/irq.h>
+#include <console/chardev.h>
+#include <typedefs.h>
+
+#define PL011_UART0_BASE_ADDRESS   0x20201000
+
+/** PrimeCell UART TRM ch. 3.3 (p. 49 in the pdf) */
+typedef struct {
+	/** UART data register */
+	ioport32_t data;
+#define PL011_UART_DATA_DATA_MASK   0xff
+#define PL011_UART_DATA_FE_FLAG   (1 <<  7)
+#define PL011_UART_DATA_PE_FLAG   (1 <<  9)
+#define PL011_UART_DATA_BE_FLAG   (1 << 10)
+#define PL011_UART_DATA_OE_FLAG   (1 << 11)
+
+	union {
+		/* Same values that are in upper bits of data register*/
+		const ioport32_t status;
+#define PL011_UART_STATUS_FE_FLAG   (1 << 0)
+#define PL011_UART_STATUS_PE_FLAG   (1 << 1)
+#define PL011_UART_STATUS_BE_FLAG   (1 << 2)
+#define PL011_UART_STATUS_OE_FLAG   (1 << 3)
+		/* Writing anything clears all errors */
+		ioport32_t error_clear;
+	};
+	uint32_t padd0_[4];
+
+	const ioport32_t flag;
+#define PL011_UART_FLAG_CTS_FLAG    (1 << 0)
+#define PL011_UART_FLAG_DSR_FLAG    (1 << 1)
+#define PL011_UART_FLAG_DCD_FLAG    (1 << 2)
+#define PL011_UART_FLAG_BUSY_FLAG   (1 << 3)
+#define PL011_UART_FLAG_RXFE_FLAG   (1 << 4)
+#define PL011_UART_FLAG_TXFF_FLAG   (1 << 5)
+#define PL011_UART_FLAG_RXFF_FLAG   (1 << 6)
+#define PL011_UART_FLAG_TXFE_FLAG   (1 << 7)
+#define PL011_UART_FLAG_RI_FLAG     (1 << 8)
+	uint32_t padd1_;
+
+	ioport32_t irda_low_power;
+#define PL011_UART_IRDA_LOW_POWER_MASK   0xff
+
+	ioport32_t int_baud_divisor;
+#define PL011_UART_INT_BAUD_DIVISOR_MASK   0xffff
+
+	ioport32_t fract_baud_divisor;
+#define PL011_UART_FRACT_BAUD_DIVISOR_MASK   0x1f
+
+	ioport32_t line_control_high;
+#define PL011_UART_CONTROLHI_BRK_FLAG    (1 << 0)
+#define PL011_UART_CONTROLHI_PEN_FLAG    (1 << 1)
+#define PL011_UART_CONTROLHI_EPS_FLAG    (1 << 2)
+#define PL011_UART_CONTROLHI_STP2_FLAG   (1 << 3)
+#define PL011_UART_CONTROLHI_FEN_FLAG    (1 << 4)
+#define PL011_UART_CONTROLHI_WLEN_MASK   0x3
+#define PL011_UART_CONTROLHI_WLEN_SHIFT    5
+#define PL011_UART_CONTROLHI_SPS_FLAG    (1 << 5)
+
+	ioport32_t control;
+#define PL011_UART_CONTROL_UARTEN_FLAG   (1 << 0)
+#define PL011_UART_CONTROL_SIREN_FLAG    (1 << 1)
+#define PL011_UART_CONTROL_SIRLP_FLAG    (1 << 2)
+#define PL011_UART_CONTROL_LBE_FLAG      (1 << 7)
+#define PL011_UART_CONTROL_TXE_FLAG      (1 << 8)
+#define PL011_UART_CONTROL_RXE_FLAG      (1 << 9)
+#define PL011_UART_CONTROL_DTR_FLAG     (1 << 10)
+#define PL011_UART_CONTROL_RTS_FLAG     (1 << 11)
+#define PL011_UART_CONTROL_OUT1_FLAG    (1 << 12)
+#define PL011_UART_CONTROL_OUT2_FLAG    (1 << 13)
+#define PL011_UART_CONTROL_RTSE_FLAG    (1 << 14)
+#define PL011_UART_CONTROL_CTSE_FLAG    (1 << 15)
+
+	ioport32_t interrupt_fifo;
+#define PL011_UART_INTERRUPTFIFO_TX_MASK   0x7
+#define PL011_UART_INTERRUPTFIFO_TX_SHIFT    0
+#define PL011_UART_INTERRUPTFIFO_RX_MASK   0x7
+#define PL011_UART_INTERRUPTFIFO_RX_SHIFT    3
+
+	/** Interrupt mask register */
+	ioport32_t interrupt_mask;
+	/** Pending interrupts before applying the mask */
+	const ioport32_t raw_interrupt_status;
+	/** Pending interrupts after applying the mask */
+	const ioport32_t masked_interrupt_status;
+	/** Write 1s to clear pending interrupts */
+	ioport32_t interrupt_clear;
+#define PL011_UART_INTERRUPT_RIM_FLAG    (1 << 0)
+#define PL011_UART_INTERRUPT_CTSM_FLAG   (1 << 1)
+#define PL011_UART_INTERRUPT_DCDM_FLAG   (1 << 2)
+#define PL011_UART_INTERRUPT_DSRM_FLAG   (1 << 3)
+#define PL011_UART_INTERRUPT_RX_FLAG     (1 << 4)
+#define PL011_UART_INTERRUPT_TX_FLAG     (1 << 5)
+#define PL011_UART_INTERRUPT_RT_FLAG     (1 << 6)
+#define PL011_UART_INTERRUPT_FE_FLAG     (1 << 7)
+#define PL011_UART_INTERRUPT_PE_FLAG     (1 << 8)
+#define PL011_UART_INTERRUPT_BE_FLAG     (1 << 9)
+#define PL011_UART_INTERRUPT_OE_FLAG    (1 << 10)
+#define PL011_UART_INTERRUPT_ALL           0x3ff
+
+	ioport32_t dma_control;
+#define PL011_UART_DMACONTROL_RXDMAEN_FLAG    (1 << 0)
+#define PL011_UART_DMACONTROL_TXDMAEN_FLAG    (1 << 1)
+#define PL011_UART_DMACONTROL_DMAONERR_FLAG   (1 << 2)
+
+	// TODO There is some reserved space here followed by
+	// peripheral identification registers.
+} pl011_uart_regs_t;
+
+typedef struct {
+	pl011_uart_regs_t *regs;
+	indev_t *indev;
+	outdev_t outdev;
+	irq_t irq;
+} pl011_uart_t;
+
+bool pl011_uart_init(pl011_uart_t *, inr_t, uintptr_t, size_t);
+void pl011_uart_input_wire(pl011_uart_t *, indev_t *);
+
+#endif
+/**
+ * @}
+ */
Index: kernel/genarch/include/genarch/drivers/bcm2835/timer.h
===================================================================
--- kernel/genarch/include/genarch/drivers/bcm2835/timer.h	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
+++ kernel/genarch/include/genarch/drivers/bcm2835/timer.h	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013 Beniamino Galvani
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup genarch
+ * @{
+ */
+/**
+ * @file
+ * @brief Broadcom BCM2835 system timer driver.
+ */
+
+#ifndef KERN_BCM2835_TIMER_H_
+
+#include <typedefs.h>
+#include <mm/km.h>
+
+#define BCM2835_TIMER_ADDR 0x20003000
+#define BCM2835_CLOCK_FREQ 1000000
+
+typedef struct {
+	/** System Timer Control/Status */
+	ioport32_t cs;
+#define BCM2835_TIMER_CS_M0 (1 << 0)
+#define BCM2835_TIMER_CS_M1 (1 << 1)
+#define BCM2835_TIMER_CS_M2 (1 << 2)
+#define BCM2835_TIMER_CS_M3 (1 << 3)
+	/** System Timer Counter Lower 32 bits */
+	ioport32_t clo;
+	/** System Timer Counter Higher 32 bits */
+	ioport32_t chi;
+	/** System Timer Compare 0 */
+	ioport32_t c0;
+	/** System Timer Compare 1 */
+	ioport32_t c1;
+	/** System Timer Compare 2 */
+	ioport32_t c2;
+	/** System Timer Compare 3 */
+	ioport32_t c3;
+} bcm2835_timer_t;
+
+
+static inline void bcm2835_timer_start(bcm2835_timer_t* timer)
+{
+	ASSERT(timer);
+	/* Clear pending interrupt on channel 1 */
+	timer->cs |= BCM2835_TIMER_CS_M1;
+	/* Initialize compare value for match channel 1 */
+	timer->c1 = timer->clo + (BCM2835_CLOCK_FREQ / HZ);
+}
+
+static inline void bcm2835_timer_irq_ack(bcm2835_timer_t* timer)
+{
+	ASSERT(timer);
+	/* Clear pending interrupt on channel 1 */
+	timer->cs |= BCM2835_TIMER_CS_M1;
+	/* Reprogram compare value for match channel 1 */
+	timer->c1 = timer->clo + (BCM2835_CLOCK_FREQ / HZ);
+}
+
+#endif /* KERN_BCM2835_TIMER_H_ */
Index: kernel/genarch/src/drivers/bcm2835/pl011_uart.c
===================================================================
--- kernel/genarch/src/drivers/bcm2835/pl011_uart.c	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
+++ kernel/genarch/src/drivers/bcm2835/pl011_uart.c	(revision 8f9d70b5498ff71a9096be68b3f615349ee58ed3)
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2012 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genarch
+ * @{
+ */
+/**
+ * @file
+ * @brief PL011 on-chip UART (PrimeCell UART, PL011) driver.
+ */
+
+#include <genarch/drivers/bcm2835/pl011_uart.h>
+#include <console/chardev.h>
+#include <console/console.h>
+#include <ddi/device.h>
+#include <arch/asm.h>
+#include <mm/slab.h>
+#include <mm/page.h>
+#include <mm/km.h>
+#include <sysinfo/sysinfo.h>
+#include <str.h>
+
+static void pl011_uart_sendb(pl011_uart_t *uart, uint8_t byte)
+{
+	/* Wait for space becoming available in Tx FIFO. */
+	// TODO make pio_read accept consts pointers and remove the cast
+	while ((pio_read_32((ioport32_t*)&uart->regs->flag) & PL011_UART_FLAG_TXFF_FLAG) != 0)
+		;
+
+	pio_write_32(&uart->regs->data, byte);
+}
+
+static void pl011_uart_putchar(outdev_t *dev, wchar_t ch)
+{
+	pl011_uart_t *uart = dev->data;
+
+	if (!ascii_check(ch)) {
+		pl011_uart_sendb(uart, U_SPECIAL);
+	} else {
+		if (ch == '\n')
+			pl011_uart_sendb(uart, (uint8_t) '\r');
+		pl011_uart_sendb(uart, (uint8_t) ch);
+	}
+}
+
+static outdev_operations_t pl011_uart_ops = {
+	.write = pl011_uart_putchar,
+	.redraw = NULL,
+};
+
+static irq_ownership_t pl011_uart_claim(irq_t *irq)
+{
+	return IRQ_ACCEPT;
+}
+
+static void pl011_uart_irq_handler(irq_t *irq)
+{
+	pl011_uart_t *uart = irq->instance;
+
+	// TODO make pio_read accept const pointers and remove the cast
+	while ((pio_read_32((ioport32_t*)&uart->regs->flag) & PL011_UART_FLAG_RXFE_FLAG) == 0) {
+		/* We ignore all error flags here */
+		const uint8_t data = pio_read_32(&uart->regs->data);
+		if (uart->indev)
+			indev_push_character(uart->indev, data);
+	}
+	/* Ack interrupts */
+	pio_write_32(&uart->regs->interrupt_clear, PL011_UART_INTERRUPT_ALL);
+}
+
+bool pl011_uart_init(pl011_uart_t *uart, inr_t interrupt, uintptr_t addr, size_t size)
+{
+	ASSERT(uart);
+	uart->regs = (void*)km_map(addr, size, PAGE_NOT_CACHEABLE);
+
+	ASSERT(uart->regs);
+
+	uart->regs->control = 0;
+	uart->regs->interrupt_clear = 0x7f;
+	uart->regs->int_baud_divisor = 1;
+	uart->regs->fract_baud_divisor = 40;
+	uart->regs->line_control_high = PL011_UART_CONTROLHI_FEN_FLAG |
+		(3 << PL011_UART_CONTROLHI_WLEN_SHIFT);
+
+	/* Enable TX and RX */
+	uart->regs->control = 0 |
+		PL011_UART_CONTROL_UARTEN_FLAG |
+		PL011_UART_CONTROL_TXE_FLAG |
+		PL011_UART_CONTROL_RXE_FLAG;
+
+	/* Mask all interrupts */
+	uart->regs->interrupt_mask = 0;
+
+	outdev_initialize("pl011_uart_dev", &uart->outdev, &pl011_uart_ops);
+	uart->outdev.data = uart;
+
+	/* Initialize IRQ */
+	irq_initialize(&uart->irq);
+	uart->irq.devno = device_assign_devno();
+	uart->irq.inr = interrupt;
+	uart->irq.claim = pl011_uart_claim;
+	uart->irq.handler = pl011_uart_irq_handler;
+	uart->irq.instance = uart;
+	return true;
+}
+
+void pl011_uart_input_wire(pl011_uart_t *uart, indev_t *indev)
+{
+	ASSERT(uart);
+	ASSERT(indev);
+
+	uart->indev = indev;
+	irq_register(&uart->irq);
+	/* Enable receive interrupt */
+	uart->regs->interrupt_mask |= (PL011_UART_INTERRUPT_RX_FLAG |
+				       PL011_UART_INTERRUPT_RT_FLAG);
+}
+
+/** @}
+ */
+
