Index: HelenOS.config
===================================================================
--- HelenOS.config	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ HelenOS.config	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -88,14 +88,30 @@
 
 % CPU type
+@ "cortex_a8" ARM Cortex A-8
+! [PLATFORM=arm32&(MACHINE=beagleboardxm|MACHINE=beaglebone)] PROCESSOR (choice)
+
+% CPU type
+@ "arm920t" ARM920T
+! [PLATFORM=arm32&MACHINE=gta02] PROCESSOR (choice)
+
+% CPU type
+@ "arm926ej_s" ARM926EJ-S
+! [PLATFORM=arm32&MACHINE=integratorcp] PROCESSOR (choice)
+
+
+# Add more ARMv4 CPUs
+% CPU arch
 @ "armv4" ARMv4
-! [PLATFORM=arm32&(MACHINE=gta02)] PROCESSOR (choice)
-
-% CPU type
+! [PLATFORM=arm32&(PROCESSOR=arm920t)] PROCESSOR_ARCH (choice)
+
+# Add more ARMv5 CPUs
+% CPU arch
 @ "armv5" ARMv5
-! [PLATFORM=arm32&MACHINE=integratorcp] PROCESSOR (choice)
-
-% CPU type
+! [PLATFORM=arm32&(PROCESSOR=arm926ej_s)] PROCESSOR_ARCH (choice)
+
+# Add more ARMv7-A CPUs
+% CPU arch
 @ "armv7_a" ARMv7-A
-! [PLATFORM=arm32&(MACHINE=beagleboardxm|MACHINE=beaglebone)] PROCESSOR (choice)
+! [PLATFORM=arm32&(PROCESSOR=cortex_a8)] PROCESSOR_ARCH (choice)
 
 % RAM disk format
@@ -349,5 +365,5 @@
 ## armv7 made fpu hardware compulsory
 % FPU support
-! [PLATFORM=arm32&PROCESSOR=armv7_a] CONFIG_FPU (y)
+! [PLATFORM=arm32&PROCESSOR_ARCH=armv7_a] CONFIG_FPU (y)
 
 % FPU support
Index: boot/arch/arm32/Makefile.inc
===================================================================
--- boot/arch/arm32/Makefile.inc	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ boot/arch/arm32/Makefile.inc	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -49,5 +49,5 @@
 BITS = 32
 ENDIANESS = LE
-EXTRA_CFLAGS = -march=$(subst _,-,$(PROCESSOR)) -mno-unaligned-access
+EXTRA_CFLAGS = -march=$(subst _,-,$(PROCESSOR_ARCH)) -mno-unaligned-access
 
 ifeq ($(MACHINE), gta02)
@@ -59,4 +59,5 @@
 RD_DRVS += \
 	infrastructure/rootamdm37x \
+	fb/amdm37x_dispc \
 	bus/usb/ehci \
 	bus/usb/ohci \
Index: boot/arch/arm32/_link.ld.in
===================================================================
--- boot/arch/arm32/_link.ld.in	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ boot/arch/arm32/_link.ld.in	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -11,4 +11,5 @@
 	. = BOOT_BASE + 0x8000;
 	.data : {
+		bdata_start = .;
 		*(BOOTPT);      /* bootstrap page table */
 		*(BOOTSTACK);   /* bootstrap stack */
@@ -24,5 +25,6 @@
 [[COMPONENTS]]
 	}
-	
+	bdata_end = .;
+
 	/DISCARD/ : {
 		*(.gnu.*);
Index: boot/arch/arm32/include/mm.h
===================================================================
--- boot/arch/arm32/include/mm.h	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ boot/arch/arm32/include/mm.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -58,4 +58,10 @@
 #define GTA02_IOMEM_END  0x60000000
 
+/** Start of ram memory on BBxM */
+#define BBXM_RAM_START   0x80000000
+/** Start of ram memory on BBxM */
+#define BBXM_RAM_END   0xc0000000
+
+
 /* Page table level 0 entry - "section" format is used
  * (one-level paging, 1 MB sized pages). Used only while booting the kernel.
Index: boot/arch/arm32/src/asm.S
===================================================================
--- boot/arch/arm32/src/asm.S	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ boot/arch/arm32/src/asm.S	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -61,17 +61,48 @@
 	#
 
-#if defined(MACHINE_gta02)
+	#
+	# r0 is kernel entry point
+	# r1 is pointer to the bootinfo structure
 
 #define CP15_C1_IC		12
+#define CP15_C1_BP		11
 #define CP15_C1_DC		2
-#define CP15_C7_SEG_SHIFT	5
-#define CP15_C7_SEG_SIZE	3
-#define CP15_C7_IDX_SHIFT	26
-
 	# Disable I-cache and D-cache before the kernel is started.
 	mrc	p15, 0, r4, c1, c0, 0
 	bic	r4, r4, #(1 << CP15_C1_DC)
 	bic	r4, r4, #(1 << CP15_C1_IC)
+	bic	r4, r4, #(1 << CP15_C1_BP)
 	mcr	p15, 0, r4, c1, c0, 0
+
+	
+	#Wait for the operations to complete
+#ifdef PROCESSOR_ARCH_armv7_a
+	dsb
+#else
+	#cp15 dsb, r4 is ignored (should be zero)
+	mcr p15, 0, r4, c7, c10, 4
+#endif
+	
+	# Clean ICache and BPredictors, r4 ignored (SBZ)
+	mcr p15, 0, r4, c7, c5, 0
+	nop
+
+	#Wait for the operations to complete
+#ifdef PROCESSOR_ARCH_armv7_a
+	isb
+	nop
+#else
+	# cp15 isb
+	mcr p15, 0, r4, c7, c5, 4
+	nop
+#endif
+	
+#TODO:This should not be necessary
+
+#if defined(MACHINE_gta02)
+
+#define CP15_C7_SEG_SHIFT	5
+#define CP15_C7_SEG_SIZE	3
+#define CP15_C7_IDX_SHIFT	26
 
 	# Now clean D-cache to guarantee coherency between I-cache and D-cache.
Index: boot/arch/arm32/src/main.c
===================================================================
--- boot/arch/arm32/src/main.c	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ boot/arch/arm32/src/main.c	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -50,11 +50,48 @@
 #define TOP2ADDR(top)  (((void *) PA2KA(BOOT_OFFSET)) + (top))
 
+extern void *bdata_start;
+extern void *bdata_end;
+
+
+static inline void invalidate_icache(void)
+{
+	/* ICIALLU Invalidate entire ICache */
+	asm volatile ("mov r0, #0\n" "mcr p15, 0, r0, c7, c5, 0\n" ::: "r0" );
+}
+
+static inline void invalidate_dcache(void *address, size_t size)
+{
+	const uintptr_t addr = (uintptr_t)address;
+	/* DCIMVAC - invalidate by address to the point of coherence */
+	for (uintptr_t a = addr; a < addr + size; a += 4) {
+		asm volatile ("mcr p15, 0, %[a], c7, c6, 1\n" :: [a]"r"(a) : );
+	}
+}
+
+static inline void clean_dcache_poc(void *address, size_t size)
+{
+	const uintptr_t addr = (uintptr_t)address;
+	/* DCCMVAC - clean by address to the point of coherence */
+	for (uintptr_t a = addr; a < addr + size; a += 4) {
+		asm volatile ("mcr p15, 0, %[a], c7, c10, 1\n" :: [a]"r"(a) : );
+	}
+}
+
 static bootinfo_t bootinfo;
 
 void bootstrap(void)
 {
+	/* Make sure  we run in memory code when caches are enabled,
+	 * make sure we read memory data too. This part is ARMv7 specific as
+	 * ARMv7 no longer invalidates caches on restart.
+	 * See chapter B2.2.2 of ARM Architecture Reference Manual p. B2-1263*/
+	invalidate_icache();
+	invalidate_dcache(&bdata_start, &bdata_end - &bdata_start);
+
+	/* Enable MMU and caches */
 	mmu_start();
 	version_print();
 	
+	printf("Boot data: %p -> %p\n", &bdata_start, &bdata_end);
 	printf("\nMemory statistics\n");
 	printf(" %p|%p: bootstrap stack\n", &boot_stack, &boot_stack);
@@ -64,9 +101,10 @@
 	    (void *) PA2KA(BOOT_OFFSET), (void *) BOOT_OFFSET);
 	
-	size_t i;
-	for (i = 0; i < COMPONENTS; i++)
+	for (size_t i = 0; i < COMPONENTS; i++) {
 		printf(" %p|%p: %s image (%u/%u bytes)\n", components[i].start,
 		    components[i].start, components[i].name, components[i].inflated,
 		    components[i].size);
+		invalidate_dcache(components[i].start, components[i].size);
+	}
 	
 	void *dest[COMPONENTS];
@@ -74,5 +112,5 @@
 	size_t cnt = 0;
 	bootinfo.cnt = 0;
-	for (i = 0; i < min(COMPONENTS, TASKMAP_MAX_RECORDS); i++) {
+	for (size_t i = 0; i < min(COMPONENTS, TASKMAP_MAX_RECORDS); i++) {
 		top = ALIGN_UP(top, PAGE_SIZE);
 		
@@ -94,5 +132,5 @@
 	printf("\nInflating components ... ");
 	
-	for (i = cnt; i > 0; i--) {
+	for (size_t i = cnt; i > 0; i--) {
 		void *tail = components[i - 1].start + components[i - 1].size;
 		if (tail >= dest[i - 1]) {
@@ -106,14 +144,15 @@
 		int err = inflate(components[i - 1].start, components[i - 1].size,
 		    dest[i - 1], components[i - 1].inflated);
-		
 		if (err != EOK) {
 			printf("\n%s: Inflating error %d\n", components[i - 1].name, err);
 			halt();
 		}
+		clean_dcache_poc(dest[i - 1], components[i - 1].inflated);
 	}
 	
 	printf(".\n");
 	
-	printf("Booting the kernel... \n");
+	void *kernel_end = (void *) PA2KA(BOOT_OFFSET + components[0].inflated);
+	printf("Booting the kernel...\n");
 	jump_to_kernel((void *) PA2KA(BOOT_OFFSET), &bootinfo);
 }
Index: boot/arch/arm32/src/mm.c
===================================================================
--- boot/arch/arm32/src/mm.c	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ boot/arch/arm32/src/mm.c	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -66,7 +66,10 @@
 	else
 		return 1;
-#else
+#elif defined MACHINE_beagleboardxm
+	const unsigned long address = section << PTE_SECTION_SHIFT;
+	if (address >= BBXM_RAM_START && address < BBXM_RAM_END)
+		return 1;
+#endif
 	return 0;
-#endif
 }
 
@@ -129,17 +132,10 @@
 		"mrc p15, 0, r0, c1, c0, 0\n"
 		
-#ifdef PROCESSOR_armv7_a
-		/* Mask to enable paging, caching */
-		"ldr r1, =0x00000005\n"
-#else
-#ifdef MACHINE_gta02
-		/* Mask to enable paging (bit 0),
-		   D-cache (bit 2), I-cache (bit 12) */
-		"ldr r1, =0x00001005\n"
-#else
-		/* Mask to enable paging */
-		"ldr r1, =0x00000001\n"
-#endif
-#endif
+		/* Enable ICache, DCache, BPredictors and MMU,
+		 * we disable caches before jumping to kernel
+		 * so this is safe for all archs.
+		 */
+		"ldr r1, =0x00001805\n"
+		
 		"orr r0, r0, r1\n"
 
Index: kernel/arch/arm32/Makefile.inc
===================================================================
--- kernel/arch/arm32/Makefile.inc	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ kernel/arch/arm32/Makefile.inc	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -33,10 +33,10 @@
 ATSIGN = %
 
-GCC_CFLAGS += -fno-omit-frame-pointer -mapcs-frame -march=$(subst _,-,$(PROCESSOR)) -mno-unaligned-access
+GCC_CFLAGS += -fno-omit-frame-pointer -mapcs-frame -march=$(subst _,-,$(PROCESSOR_ARCH)) -mno-unaligned-access
 
 ifeq ($(CONFIG_FPU),y)
 # This is necessary to allow vmsr insn and fpexc manipulation
 # Use vfp32 to allow context save/restore of d16-d31 regs.
-GCC_CFLAGS += -mfloat-abi=hard -mfpu=vfp3
+AFLAGS += -mfloat-abi=hard -mfpu=vfp3
 endif
 
@@ -70,4 +70,5 @@
 ifeq ($(CONFIG_FPU),y)
 	ARCH_SOURCES +=	arch/$(KARCH)/src/fpu_context.c
+	ARCH_SOURCES +=	arch/$(KARCH)/src/fpu.s
 endif
 
Index: kernel/arch/arm32/include/asm.h
===================================================================
--- kernel/arch/arm32/include/asm.h	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ kernel/arch/arm32/include/asm.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -43,16 +43,22 @@
 #include <trace.h>
 
-/** No such instruction on old ARM to sleep CPU.
+/** CPU specific way to sleep cpu.
  *
  * ARMv7 introduced wait for event and wait for interrupt (wfe/wfi).
  * ARM920T has custom coprocessor action to do the same. See ARM920T Technical
  * Reference Manual ch 4.9 p. 4-23 (103 in the PDF)
+ * ARM926EJ-S uses the same coprocessor instruction as ARM920T. See ARM926EJ-S
+ * chapter 2.3.8 p.2-22 (52 in the PDF)
+ *
+ * @note Although mcr p15, 0, R0, c7, c0, 4 is defined in ARM Architecture
+ * reference manual for armv4/5 CP15 implementation is mandatory only for
+ * armv6+.
  */
 NO_TRACE static inline void cpu_sleep(void)
 {
-#ifdef PROCESSOR_armv7_a
-	asm volatile ( "wfe" :: );
-#elif defined(MACHINE_gta02)
-	asm volatile ( "mcr p15,0,R0,c7,c0,4" :: );
+#ifdef PROCESSOR_ARCH_armv7_a
+	asm volatile ( "wfe" );
+#elif defined(PROCESSOR_ARCH_armv6) | defined(PROCESSOR_arm926ej_s) | defined(PROCESSOR_arm920t)
+	asm volatile ( "mcr p15, 0, R0, c7, c0, 4" );
 #endif
 }
Index: kernel/arch/arm32/include/barrier.h
===================================================================
--- kernel/arch/arm32/include/barrier.h	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ kernel/arch/arm32/include/barrier.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -37,13 +37,53 @@
 #define KERN_arm32_BARRIER_H_
 
-/*
- * TODO: implement true ARM memory barriers for macros below.
- */
+#ifdef KERNEL
+#include <arch/cp15.h>
+#else
+#include <libarch/cp15.h>
+#endif
+
 #define CS_ENTER_BARRIER()  asm volatile ("" ::: "memory")
 #define CS_LEAVE_BARRIER()  asm volatile ("" ::: "memory")
 
+#if defined PROCESSOR_ARCH_armv7_a
+/* ARMv7 uses instructions for memory barriers see ARM Architecture reference
+ * manual for details:
+ * DMB: ch. A8.8.43 page A8-376
+ * DSB: ch. A8.8.44 page A8-378
+ * See ch. A3.8.3 page A3-148 for details about memory barrier implementation
+ * and functionality on armv7 architecture.
+ */
+#define memory_barrier()  asm volatile ("dmb" ::: "memory")
+#define read_barrier()    asm volatile ("dsb" ::: "memory")
+#define write_barrier()   asm volatile ("dsb st" ::: "memory")
+#define inst_barrier()    asm volatile ("isb" ::: "memory")
+#elif defined PROCESSOR_ARCH_armv6 | defined KERNEL
+/*
+ * ARMv6 introduced user access of the following commands:
+ * - Prefetch flush
+ * - Data synchronization barrier
+ * - Data memory barrier
+ * - Clean and prefetch range operations.
+ * ARM Architecture Reference Manual version I ch. B.3.2.1 p. B3-4
+ */
+/* ARMv6- use system control coprocessor (CP15) for memory barrier instructions.
+ * Although at least mcr p15, 0, r0, c7, c10, 4 is mentioned in earlier archs,
+ * CP15 implementation is mandatory only for armv6+.
+ */
+#define memory_barrier()  CP15DMB_write(0)
+#define read_barrier()    CP15DSB_write(0)
+#define write_barrier()   read_barrier()
+#define inst_barrier()    CP15ISB_write(0)
+#else
+/* Older manuals mention syscalls as a way to implement cache coherency and
+ * barriers. See for example ARM Architecture Reference Manual Version D
+ * chapter 2.7.4 Prefetching and self-modifying code (p. A2-28)
+ */
+// TODO implement on per PROCESSOR basis or via syscalls
 #define memory_barrier()  asm volatile ("" ::: "memory")
 #define read_barrier()    asm volatile ("" ::: "memory")
 #define write_barrier()   asm volatile ("" ::: "memory")
+#define inst_barrier()    asm volatile ("" ::: "memory")
+#endif
 
 /*
@@ -62,8 +102,26 @@
  */
 
-/* Available on both all supported arms,
+#if defined PROCESSOR_ARCH_armv7_a | defined PROCESSOR_ARCH_armv6 | defined KERNEL
+/* Available on all supported arms,
  * invalidates entire ICache so the written value does not matter. */
-#define smc_coherence(a) asm volatile ( "mcr p15, 0, r0, c7, c5, 0")
-#define smc_coherence_block(a, l) smc_coherence(a)
+//TODO might be PL1 only on armv5-
+#define smc_coherence(a) \
+do { \
+	DCCMVAU_write((uint32_t)(a));  /* Flush changed memory */\
+	write_barrier();               /* Wait for completion */\
+	ICIALLU_write(0);              /* Flush ICache */\
+	inst_barrier();                /* Wait for Inst refetch */\
+} while (0)
+/* @note: Cache type register is not available in uspace. We would need
+ * to export the cache line value, or use syscall for uspace smc_coherence */
+#define smc_coherence_block(a, l) \
+do { \
+	for (uintptr_t addr = (uintptr_t)a; addr < (uintptr_t)a + l; addr += 4)\
+		smc_coherence(addr); \
+} while (0)
+#else
+#define smc_coherence(a)
+#define smc_coherence_block(a, l)
+#endif
 
 
Index: kernel/arch/arm32/include/cache.h
===================================================================
--- kernel/arch/arm32/include/cache.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
+++ kernel/arch/arm32/include/cache.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 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 arm32
+ * @{
+ */
+/** @file
+ *  @brief Security Extensions Routines
+ */
+
+#ifndef KERN_arm32_CACHE_H_
+#define KERN_arm32_CACHE_H_
+
+unsigned dcache_levels(void);
+
+void dcache_flush(void);
+void dcache_flush_invalidate(void);
+void cpu_dcache_flush(void);
+void cpu_dcache_flush_invalidate(void);
+void icache_invalidate(void);
+
+#endif
+/** @}
+ */
+
Index: kernel/arch/arm32/include/cp15.h
===================================================================
--- kernel/arch/arm32/include/cp15.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
+++ kernel/arch/arm32/include/cp15.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -0,0 +1,525 @@
+/*
+ * Copyright (c) 2013 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 arm32
+ * @{
+ */
+/** @file
+ *  @brief System Control Coprocessor (CP15)
+ */
+
+#ifndef KERN_arm32_CP15_H_
+#define KERN_arm32_CP15_H_
+
+
+/** See ARM Architecture reference manual ch. B3.17.1 page B3-1456
+ * for the list */
+
+#define CONTROL_REG_GEN_READ(name, crn, opc1, crm, opc2) \
+static inline uint32_t name##_read() \
+{ \
+	uint32_t val; \
+	asm volatile ( "mrc p15, "#opc1", %0, "#crn", "#crm", "#opc2"\n" : "=r" (val) ); \
+	return val; \
+}
+#define CONTROL_REG_GEN_WRITE(name, crn, opc1, crm, opc2) \
+static inline void name##_write(uint32_t val) \
+{ \
+	asm volatile ( "mcr p15, "#opc1", %0, "#crn", "#crm", "#opc2"\n" :: "r" (val) ); \
+}
+
+/* Identification registers */
+enum {
+	MIDR_IMPLEMENTER_MASK = 0xff,
+	MIDR_IMPLEMENTER_SHIFT = 24,
+	MIDR_VARIANT_MASK = 0xf,
+	MIDR_VARIANT_SHIFT = 20,
+	MIDR_ARCHITECTURE_MASK = 0xf,
+	MIDR_ARCHITECTURE_SHIFT = 16,
+	MIDR_PART_NUMBER_MASK = 0xfff,
+	MIDR_PART_NUMBER_SHIFT = 4,
+	MIDR_REVISION_MASK = 0xf,
+	MIDR_REVISION_SHIFT = 0,
+};
+CONTROL_REG_GEN_READ(MIDR, c0, 0, c0, 0);
+
+enum {
+	CTR_FORMAT_MASK = 0xe0000000,
+	CTR_FORMAT_ARMv7 = 0x80000000,
+	CTR_FORMAT_ARMv6 = 0x00000000,
+	/* ARMv7 format */
+	CTR_CWG_MASK = 0xf,
+	CTR_CWG_SHIFT = 24,
+	CTR_ERG_MASK = 0xf,
+	CTR_ERG_SHIFT = 20,
+	CTR_D_MIN_LINE_MASK = 0xf,
+	CTR_D_MIN_LINE_SHIFT = 16,
+	CTR_I_MIN_LINE_MASK = 0xf,
+	CTR_I_MIN_LINE_SHIFT = 0,
+	CTR_L1I_POLICY_MASK = 0x0000c000,
+	CTR_L1I_POLICY_AIVIVT = 0x00004000,
+	CTR_L1I_POLICY_VIPT = 0x00008000,
+	CTR_L1I_POLICY_PIPT = 0x0000c000,
+	/* ARMv6 format */
+	CTR_CTYPE_MASK = 0x1e000000,
+	CTR_CTYPE_WT = 0x00000000,
+	CTR_CTYPE_WB_NL = 0x04000000,
+	CTR_CTYPE_WB_D = 0x0a000000,
+	CTR_CTYPE_WB_A = 0x0c000000, /**< ARMv5- only */
+	CTR_CTYPE_WB_B = 0x0e000000, /**< ARMv5- only */
+	CTR_CTYPE_WB_C = 0x1c000000,
+	CTR_SEP_FLAG = 1 << 24,
+	CTR_DCACHE_P_FLAG = 1 << 23,
+	CTR_DCACHE_SIZE_MASK = 0xf,
+	CTR_DCACHE_SIZE_SHIFT = 18,
+	CTR_DCACHE_ASSOC_MASK = 0x7,
+	CTR_DCACHE_ASSOC_SHIFT = 15,
+	CTR_DCACHE_M_FLAG = 1 << 14,
+	CTR_DCACHE_LEN_MASK = 0x3,
+	CTR_DCACHE_LEN_SHIFT = 0,
+	CTR_ICACHE_P_FLAG = 1 << 11,
+	CTR_ICACHE_SIZE_MASK = 0xf,
+	CTR_ICACHE_SIZE_SHIFT = 6,
+	CTR_ICACHE_ASSOC_MASK = 0x7,
+	CTR_ICACHE_ASSOC_SHIFT = 3,
+	CTR_ICACHE_M_FLAG = 1 << 2,
+	CTR_ICACHE_LEN_MASK = 0x3,
+	CTR_ICACHE_LEN_SHIFT = 0,
+};
+CONTROL_REG_GEN_READ(CTR, c0, 0, c0, 1);
+CONTROL_REG_GEN_READ(TCMR, c0, 0, c0, 2);
+CONTROL_REG_GEN_READ(TLBTR, c0, 0, c0, 3);
+CONTROL_REG_GEN_READ(MPIDR, c0, 0, c0, 5);
+CONTROL_REG_GEN_READ(REVIDR, c0, 0, c0, 6);
+
+enum {
+	ID_PFR0_THUMBEE_MASK = 0xf << 12,
+	ID_PFR0_THUMBEE = 0x1 << 12,
+	ID_PFR0_JAZELLE_MASK = 0xf << 8,
+	ID_PFR0_JAZELLE = 0x1 << 8,
+	ID_PFR0_JAZELLE_CV_CLEAR = 0x2 << 8,
+	ID_PFR0_THUMB_MASK = 0xf << 4,
+	ID_PFR0_THUMB = 0x1 << 4,
+	ID_PFR0_THUMB2 = 0x3 << 4,
+	ID_PFR0_ARM_MASK = 0xf << 0,
+	ID_PFR0_ARM = 0x1 << 0,
+};
+CONTROL_REG_GEN_READ(ID_PFR0, c0, 0, c1, 0);
+
+enum {
+	ID_PFR1_GEN_TIMER_EXT_MASK = 0xf << 16,
+	ID_PFR1_GEN_TIMER_EXT = 0x1 << 16,
+	ID_PFR1_VIRT_EXT_MASK = 0xf << 12,
+	ID_PFR1_VIRT_EXT = 0x1 << 12,
+	ID_PFR1_M_PROF_MASK = 0xf << 8,
+	ID_PFR1_M_PROF_MODEL = 0x2 << 8,
+	ID_PFR1_SEC_EXT_MASK = 0xf << 4,
+	ID_PFR1_SEC_EXT = 0x1 << 4,
+	ID_PFR1_SEC_EXT_RFR = 0x2 << 4,
+	ID_PFR1_ARMV4_MODEL_MASK = 0xf << 0,
+	ID_PFR1_ARMV4_MODEL = 0x1 << 0,
+};
+CONTROL_REG_GEN_READ(ID_PFR1, c0, 0, c1, 1);
+CONTROL_REG_GEN_READ(ID_DFR0, c0, 0, c1, 2);
+CONTROL_REG_GEN_READ(ID_AFR0, c0, 0, c1, 3);
+CONTROL_REG_GEN_READ(ID_MMFR0, c0, 0, c1, 4);
+CONTROL_REG_GEN_READ(ID_MMFR1, c0, 0, c1, 5);
+CONTROL_REG_GEN_READ(ID_MMFR2, c0, 0, c1, 6);
+CONTROL_REG_GEN_READ(ID_MMFR3, c0, 0, c1, 7);
+
+CONTROL_REG_GEN_READ(ID_ISAR0, c0, 0, c2, 0);
+CONTROL_REG_GEN_READ(ID_ISAR1, c0, 0, c2, 1);
+CONTROL_REG_GEN_READ(ID_ISAR2, c0, 0, c2, 2);
+CONTROL_REG_GEN_READ(ID_ISAR3, c0, 0, c2, 3);
+CONTROL_REG_GEN_READ(ID_ISAR4, c0, 0, c2, 4);
+CONTROL_REG_GEN_READ(ID_ISAR5, c0, 0, c2, 5);
+
+enum {
+	CCSIDR_WT_FLAG = 1 << 31,
+	CCSIDR_WB_FLAG = 1 << 30,
+	CCSIDR_RA_FLAG = 1 << 29,
+	CCSIDR_WA_FLAG = 1 << 28,
+	CCSIDR_NUMSETS_MASK = 0x7fff,
+	CCSIDR_NUMSETS_SHIFT = 13,
+	CCSIDR_ASSOC_MASK = 0x3ff,
+	CCSIDR_ASSOC_SHIFT = 3,
+	CCSIDR_LINESIZE_MASK = 0x7,
+	CCSIDR_LINESIZE_SHIFT = 0,
+};
+CONTROL_REG_GEN_READ(CCSIDR, c0, 1, c0, 0);
+
+enum {
+	CLIDR_LOUU_MASK = 0x7,
+	CLIDR_LOUU_SHIFT = 27,
+	CLIDR_LOC_MASK = 0x7,
+	CLIDR_LOC_SHIFT = 24,
+	CLIDR_LOUIS_MASK = 0x7,
+	CLIDR_LOUIS_SHIFT = 21,
+	CLIDR_NOCACHE = 0x0,
+	CLIDR_ICACHE_ONLY = 0x1,
+	CLIDR_DCACHE_ONLY = 0x2,
+	CLIDR_SEP_CACHE = 0x3,
+	CLIDR_UNI_CACHE = 0x4,
+	CLIDR_CACHE_MASK = 0x7,
+#define CLIDR_CACHE(level, val)   ((val >> (level - 1) * 3) & CLIDR_CACHE_MASK)
+};
+CONTROL_REG_GEN_READ(CLIDR, c0, 1, c0, 1);
+CONTROL_REG_GEN_READ(AIDR, c0, 1, c0, 7); /* Implementation defined or MIDR */
+
+enum {
+	CCSELR_LEVEL_MASK = 0x7,
+	CCSELR_LEVEL_SHIFT = 1,
+	CCSELR_INSTRUCTION_FLAG = 1 << 0,
+};
+CONTROL_REG_GEN_READ(CSSELR, c0, 2, c0, 0);
+CONTROL_REG_GEN_WRITE(CSSELR, c0, 2, c0, 0);
+CONTROL_REG_GEN_READ(VPIDR, c0, 4, c0, 0);
+CONTROL_REG_GEN_WRITE(VPIDR, c0, 4, c0, 0);
+CONTROL_REG_GEN_READ(VMPIDR, c0, 4, c0, 5);
+CONTROL_REG_GEN_WRITE(VMPIDR, c0, 4, c0, 5);
+
+/* System control registers */
+/* COntrol register bit values see ch. B4.1.130 of ARM Architecture Reference
+ * Manual ARMv7-A and ARMv7-R edition, page 1687 */
+enum {
+	SCTLR_MMU_EN_FLAG            = 1 << 0,
+	SCTLR_ALIGN_CHECK_EN_FLAG    = 1 << 1,  /* Allow alignemnt check */
+	SCTLR_CACHE_EN_FLAG          = 1 << 2,
+	SCTLR_CP15_BARRIER_EN_FLAG   = 1 << 5,
+	SCTLR_B_EN_FLAG              = 1 << 7,  /* ARMv6-, big endian switch */
+	SCTLR_SWAP_EN_FLAG           = 1 << 10,
+	SCTLR_BRANCH_PREDICT_EN_FLAG = 1 << 11,
+	SCTLR_INST_CACHE_EN_FLAG     = 1 << 12,
+	SCTLR_HIGH_VECTORS_EN_FLAG   = 1 << 13,
+	SCTLR_ROUND_ROBIN_EN_FLAG    = 1 << 14,
+	SCTLR_HW_ACCESS_FLAG_EN_FLAG = 1 << 17,
+	SCTLR_WRITE_XN_EN_FLAG       = 1 << 19, /* Only if virt. supported */
+	SCTLR_USPCE_WRITE_XN_EN_FLAG = 1 << 20, /* Only if virt. supported */
+	SCTLR_FAST_IRQ_EN_FLAG       = 1 << 21, /* Disable impl. specific feat*/
+	SCTLR_UNALIGNED_EN_FLAG      = 1 << 22, /* Must be 1 on armv7 */
+	SCTLR_IRQ_VECTORS_EN_FLAG    = 1 << 24,
+	SCTLR_BIG_ENDIAN_EXC_FLAG    = 1 << 25,
+	SCTLR_NMFI_EN_FLAG           = 1 << 27,
+	SCTLR_TEX_REMAP_EN_FLAG      = 1 << 28,
+	SCTLR_ACCESS_FLAG_EN_FLAG    = 1 << 29,
+	SCTLR_THUMB_EXC_EN_FLAG      = 1 << 30,
+};
+CONTROL_REG_GEN_READ(SCTLR, c1, 0, c0, 0);
+CONTROL_REG_GEN_WRITE(SCTLR, c1, 0, c0, 0);
+CONTROL_REG_GEN_READ(ACTLR, c1, 0, c0, 1);
+CONTROL_REG_GEN_WRITE(ACTLR, c1, 0, c0, 1);
+
+enum {
+	CPACR_ASEDIS_FLAG = 1 << 31,
+	CPACR_D32DIS_FLAG = 1 << 30,
+	CPACR_TRCDIS_FLAG = 1 << 28,
+#define CPACR_CP_MASK(cp) (0x3 << (cp * 2))
+#define CPACR_CP_NO_ACCESS(cp) (0x0 << (cp * 2))
+#define CPACR_CP_PL1_ACCESS(cp) (0x1 << (cp * 2))
+#define CPACR_CP_FULL_ACCESS(cp) (0x3 << (cp * 2))
+};
+CONTROL_REG_GEN_READ(CPACR, c1, 0, c0, 2);
+CONTROL_REG_GEN_WRITE(CPACR, c1, 0, c0, 2);
+
+/* Implemented as part of Security extensions */
+enum {
+	SCR_SIF_FLAG = 1 << 9,
+	SCR_HCE_FLAG = 1 << 8,
+	SCR_SCD_FLAG = 1 << 7,
+	SCR_nET_FLAG = 1 << 6,
+	SCR_AW_FLAG = 1 << 5,
+	SCR_FW_FLAG = 1 << 4,
+	SCR_EA_FLAG = 1 << 3,
+	SCR_FIQ_FLAG = 1 << 2,
+	SCR_IRQ_FLAG = 1 << 1,
+	SCR_NS_FLAG = 1 << 0,
+};
+CONTROL_REG_GEN_READ(SCR, c1, 0, c1, 0);
+CONTROL_REG_GEN_WRITE(SCR, c1, 0, c1, 0);
+CONTROL_REG_GEN_READ(SDER, c1, 0, c1, 1);
+CONTROL_REG_GEN_WRITE(SDER, c1, 0, c1, 1);
+
+enum {
+	NSACR_NSTRCDIS_FLAG = 1 << 20,
+	NSACR_RFR_FLAG = 1 << 19,
+	NSACR_NSASEDIS = 1 << 15,
+	NSACR_NSD32DIS = 1 << 14,
+#define NSACR_CP_FLAG(cp) (1 << cp)
+};
+CONTROL_REG_GEN_READ(NSACR, c1, 0, c1, 2);
+CONTROL_REG_GEN_WRITE(NSACR, c1, 0, c1, 2);
+
+/* Implemented as part of Virtualization extensions */
+CONTROL_REG_GEN_READ(HSCTLR, c1, 4, c0, 0);
+CONTROL_REG_GEN_WRITE(HSCTLR, c1, 4, c0, 0);
+CONTROL_REG_GEN_READ(HACTLR, c1, 4, c0, 1);
+CONTROL_REG_GEN_WRITE(HACTLR, c1, 4, c0, 1);
+
+CONTROL_REG_GEN_READ(HCR, c1, 4, c1, 0);
+CONTROL_REG_GEN_WRITE(HCR, c1, 4, c1, 0);
+CONTROL_REG_GEN_READ(HDCR, c1, 4, c1, 1);
+CONTROL_REG_GEN_WRITE(HDCR, c1, 4, c1, 1);
+CONTROL_REG_GEN_READ(HCPTR, c1, 4, c1, 2);
+CONTROL_REG_GEN_WRITE(HCPTR, c1, 4, c1, 2);
+CONTROL_REG_GEN_READ(HSTR, c1, 4, c1, 3);
+CONTROL_REG_GEN_WRITE(HSTR, c1, 4, c1, 3);
+CONTROL_REG_GEN_READ(HACR, c1, 4, c1, 7);
+CONTROL_REG_GEN_WRITE(HACR, c1, 4, c1, 7);
+
+/* Memory protection and control registers */
+CONTROL_REG_GEN_READ(TTBR0, c2, 0, c0, 0);
+CONTROL_REG_GEN_WRITE(TTBR0, c2, 0, c0, 0);
+CONTROL_REG_GEN_READ(TTBR1, c2, 0, c0, 1);
+CONTROL_REG_GEN_WRITE(TTBR1, c2, 0, c0, 1);
+CONTROL_REG_GEN_READ(TTBCR, c2, 0, c0, 2);
+CONTROL_REG_GEN_WRITE(TTBCR, c2, 0, c0, 2);
+
+CONTROL_REG_GEN_READ(HTCR, c2, 4, c0, 2);
+CONTROL_REG_GEN_WRITE(HTCR, c2, 4, c0, 2);
+CONTROL_REG_GEN_READ(VTCR, c2, 4, c1, 2);
+CONTROL_REG_GEN_WRITE(VTCR, c2, 4, c1, 2);
+
+/* PAE */
+CONTROL_REG_GEN_READ(TTBR0H, c2, 0, c2, 0);
+CONTROL_REG_GEN_WRITE(TTBR0H, c2, 0, c2, 0);
+CONTROL_REG_GEN_READ(TTBR1H, c2, 0, c2, 1);
+CONTROL_REG_GEN_WRITE(TTBR1H, c2, 0, c2, 1);
+CONTROL_REG_GEN_READ(HTTBRH, c2, 0, c2, 4);
+CONTROL_REG_GEN_WRITE(HTTBRH, c2, 0, c2, 4);
+CONTROL_REG_GEN_READ(VTTBRH, c2, 0, c2, 6);
+CONTROL_REG_GEN_WRITE(VTTBRH, c2, 0, c2, 6);
+
+CONTROL_REG_GEN_READ(DACR, c3, 0, c0, 0);
+CONTROL_REG_GEN_WRITE(DACR, c3, 0, c0, 0);
+
+/* Memory system fault registers */
+CONTROL_REG_GEN_READ(DFSR, c5, 0, c0, 0);
+CONTROL_REG_GEN_WRITE(DFSR, c5, 0, c0, 0);
+CONTROL_REG_GEN_READ(IFSR, c5, 0, c0, 1);
+CONTROL_REG_GEN_WRITE(IFSR, c5, 0, c0, 1);
+
+CONTROL_REG_GEN_READ(ADFSR, c5, 0, c1, 0);
+CONTROL_REG_GEN_WRITE(ADFSR, c5, 0, c1, 0);
+CONTROL_REG_GEN_READ(AIFSR, c5, 0, c1, 1);
+CONTROL_REG_GEN_WRITE(AIFSR, c5, 0, c1, 1);
+
+CONTROL_REG_GEN_READ(HADFSR, c5, 4, c1, 0);
+CONTROL_REG_GEN_WRITE(HADFSR, c5, 4, c1, 0);
+CONTROL_REG_GEN_READ(HAIFSR, c5, 4, c1, 1);
+CONTROL_REG_GEN_WRITE(HAIFSR, c5, 4, c1, 1);
+CONTROL_REG_GEN_READ(HSR, c5, 4, c2, 0);
+CONTROL_REG_GEN_WRITE(HSR, c5, 4, c2, 0);
+
+CONTROL_REG_GEN_READ(DFAR, c6, 0, c0, 0);
+CONTROL_REG_GEN_WRITE(DFAR, c6, 0, c0, 0);
+CONTROL_REG_GEN_READ(IFAR, c6, 0, c0, 2);
+CONTROL_REG_GEN_WRITE(IFAR, c6, 0, c0, 2);
+
+CONTROL_REG_GEN_READ(HDFAR, c6, 4, c0, 0);
+CONTROL_REG_GEN_WRITE(HDFAR, c6, 4, c0, 0);
+CONTROL_REG_GEN_READ(HIFAR, c6, 4, c0, 2);
+CONTROL_REG_GEN_WRITE(HIFAR, c6, 4, c0, 2);
+CONTROL_REG_GEN_READ(HPFAR, c6, 4, c0, 4);
+CONTROL_REG_GEN_WRITE(HPFAR, c6, 4, c0, 4);
+
+/* Cache maintenance, address translation and other */
+CONTROL_REG_GEN_WRITE(WFI, c7, 0, c0, 4); /* armv6 only */
+CONTROL_REG_GEN_WRITE(ICIALLLUIS, c7, 0, c1, 0);
+CONTROL_REG_GEN_WRITE(BPIALLIS, c7, 0, c1, 6);
+CONTROL_REG_GEN_READ(PAR, c7, 0, c4, 0);
+CONTROL_REG_GEN_WRITE(PAR, c7, 0, c4, 0);
+CONTROL_REG_GEN_READ(PARH, c7, 0, c7, 0);   /* PAE */
+CONTROL_REG_GEN_WRITE(PARH, c7, 0, c7, 0);   /* PAE */
+CONTROL_REG_GEN_WRITE(ICIALLU, c7, 0, c5, 0);
+CONTROL_REG_GEN_WRITE(ICIMVAU, c7, 0, c5, 1);
+CONTROL_REG_GEN_WRITE(CP15ISB, c7, 0, c5, 4);
+CONTROL_REG_GEN_WRITE(BPIALL, c7, 0, c5, 6);
+CONTROL_REG_GEN_WRITE(BPIMVA, c7, 0, c5, 7);
+
+CONTROL_REG_GEN_WRITE(DCIMVAC, c7, 0, c6, 1);
+CONTROL_REG_GEN_WRITE(DCIMSW, c7, 0, c6, 2);
+
+CONTROL_REG_GEN_WRITE(ATS1CPR, c7, 0, c8, 0);
+CONTROL_REG_GEN_WRITE(ATS1CPW, c7, 0, c8, 1);
+CONTROL_REG_GEN_WRITE(ATS1CUR, c7, 0, c8, 2);
+CONTROL_REG_GEN_WRITE(ATS1CUW, c7, 0, c8, 3);
+CONTROL_REG_GEN_WRITE(ATS1NSOPR, c7, 0, c8, 4);
+CONTROL_REG_GEN_WRITE(ATS1NSOPW, c7, 0, c8, 5);
+CONTROL_REG_GEN_WRITE(ATS1NSOUR, c7, 0, c8, 6);
+CONTROL_REG_GEN_WRITE(ATS1NSOUW, c7, 0, c8, 7);
+
+
+CONTROL_REG_GEN_WRITE(DCCMVAC, c7, 0, c10, 1);
+CONTROL_REG_GEN_WRITE(DCCSW, c7, 0, c10, 2);
+CONTROL_REG_GEN_WRITE(CP15DSB, c7, 0, c10, 4);
+CONTROL_REG_GEN_WRITE(CP15DMB, c7, 0, c10, 5);
+CONTROL_REG_GEN_WRITE(DCCMVAU, c7, 0, c11, 1);
+
+CONTROL_REG_GEN_WRITE(PFI, c7, 0, c11, 1); /* armv6 only */
+
+CONTROL_REG_GEN_WRITE(DCCIMVAC, c7, 0, c14, 1);
+CONTROL_REG_GEN_WRITE(DCCISW, c7, 0, c14, 2);
+
+CONTROL_REG_GEN_WRITE(ATS1HR, c7, 4, c8, 0);
+CONTROL_REG_GEN_WRITE(ATS1HW, c7, 4, c8, 1);
+
+/* TLB maintenance */
+CONTROL_REG_GEN_WRITE(TLBIALLIS, c8, 0, c3, 0); /* Inner shareable */
+CONTROL_REG_GEN_WRITE(TLBIMVAIS, c8, 0, c3, 1); /* Inner shareable */
+CONTROL_REG_GEN_WRITE(TLBIASIDIS, c8, 0, c3, 2); /* Inner shareable */
+CONTROL_REG_GEN_WRITE(TLBIMVAAIS, c8, 0, c3, 3); /* Inner shareable */
+
+CONTROL_REG_GEN_WRITE(ITLBIALL, c8, 0, c5, 0);
+CONTROL_REG_GEN_WRITE(ITLBIMVA, c8, 0, c5, 1);
+CONTROL_REG_GEN_WRITE(ITLBIASID, c8, 0, c5, 2);
+
+CONTROL_REG_GEN_WRITE(DTLBIALL, c8, 0, c6, 0);
+CONTROL_REG_GEN_WRITE(DTLBIMVA, c8, 0, c6, 1);
+CONTROL_REG_GEN_WRITE(DTLBIASID, c8, 0, c6, 2);
+
+CONTROL_REG_GEN_WRITE(TLBIALL, c8, 0, c7, 0);
+CONTROL_REG_GEN_WRITE(TLBIMVA, c8, 0, c7, 1);
+CONTROL_REG_GEN_WRITE(TLBIASID, c8, 0, c7, 2);
+CONTROL_REG_GEN_WRITE(TLBIMVAA, c8, 0, c7, 3);
+
+CONTROL_REG_GEN_WRITE(TLBIALLHIS, c8, 4, c3, 0); /* Inner shareable */
+CONTROL_REG_GEN_WRITE(TLBIMVAHIS, c8, 4, c3, 1); /* Inner shareable */
+CONTROL_REG_GEN_WRITE(TLBIALLNSNHIS, c8, 4, c3, 4); /* Inner shareable */
+
+CONTROL_REG_GEN_WRITE(TLBIALLH, c8, 4, c7, 0);
+CONTROL_REG_GEN_WRITE(TLBIMVAH, c8, 4, c7, 1);
+CONTROL_REG_GEN_WRITE(TLBIALLNSNHS, c8, 4, c7, 4);
+
+/* c9 are performance monitoring resgisters */
+enum {
+	PMCR_IMP_MASK = 0xff,
+	PMCR_IMP_SHIFT = 24,
+	PMCR_IDCODE_MASK = 0xff,
+	PMCR_IDCODE_SHIFT = 16,
+	PMCR_EVENT_NUM_MASK = 0x1f,
+	PMCR_EVENT_NUM_SHIFT = 11,
+	PMCR_DP_FLAG = 1 << 5,
+	PMCR_X_FLAG = 1 << 4,
+	PMCR_D_FLAG = 1 << 3,
+	PMCR_C_FLAG = 1 << 2,
+	PMCR_P_FLAG = 1 << 1,
+	PMCR_E_FLAG = 1 << 0,
+};
+CONTROL_REG_GEN_READ(PMCR, c9, 0, c12, 0);
+CONTROL_REG_GEN_WRITE(PMCR, c9, 0, c12, 0);
+enum {
+	PMCNTENSET_CYCLE_COUNTER_EN_FLAG = 1 << 31,
+#define PMCNTENSET_COUNTER_EN_FLAG(c)   (1 << c)
+};
+CONTROL_REG_GEN_READ(PMCNTENSET, c9, 0, c12, 1);
+CONTROL_REG_GEN_WRITE(PMCNTENSET, c9, 0, c12, 1);
+CONTROL_REG_GEN_READ(PMCCNTR, c9, 0, c13, 0);
+CONTROL_REG_GEN_WRITE(PMCCNTR, c9, 0, c13, 0);
+
+
+/*c10 has tons of reserved too */
+CONTROL_REG_GEN_READ(PRRR, c10, 0, c2, 0); /* no PAE */
+CONTROL_REG_GEN_WRITE(PRRR, c10, 0, c2, 0); /* no PAE */
+CONTROL_REG_GEN_READ(MAIR0, c10, 0, c2, 0); /* PAE */
+CONTROL_REG_GEN_WRITE(MAIR0, c10, 0, c2, 0); /* PAE */
+CONTROL_REG_GEN_READ(NMRR, c10, 0, c2, 1); /* no PAE */
+CONTROL_REG_GEN_WRITE(NMRR, c10, 0, c2, 1); /* no PAE */
+CONTROL_REG_GEN_READ(MAIR1, c10, 0, c2, 1); /* PAE */
+CONTROL_REG_GEN_WRITE(MAIR1, c10, 0, c2, 1); /* PAE */
+
+CONTROL_REG_GEN_READ(AMAIR0, c10, 0, c3, 0); /* PAE */
+CONTROL_REG_GEN_WRITE(AMAIR0, c10, 0, c3, 0); /* PAE */
+CONTROL_REG_GEN_READ(AMAIR1, c10, 0, c3, 1); /* PAE */
+CONTROL_REG_GEN_WRITE(AMAIR1, c10, 0, c3, 1); /* PAE */
+
+CONTROL_REG_GEN_READ(HMAIR0, c10, 4, c2, 0);
+CONTROL_REG_GEN_WRITE(HMAIR0, c10, 4, c2, 0);
+CONTROL_REG_GEN_READ(HMAIR1, c10, 4, c2, 1);
+CONTROL_REG_GEN_WRITE(HMAIR1, c10, 4, c2, 1);
+
+CONTROL_REG_GEN_READ(HAMAIR0, c10, 4, c3, 0);
+CONTROL_REG_GEN_WRITE(HAMAIR0, c10, 4, c3, 0);
+CONTROL_REG_GEN_READ(HAMAIR1, c10, 4, c3, 1);
+CONTROL_REG_GEN_WRITE(HAMAIR1, c10, 4, c3, 1);
+
+/* c11 is reserved for TCM and DMA */
+
+/* Security extensions */
+CONTROL_REG_GEN_READ(VBAR, c12, 0, c0, 0);
+CONTROL_REG_GEN_WRITE(VBAR, c12, 0, c0, 0);
+CONTROL_REG_GEN_READ(MVBAR, c12, 0, c0, 1);
+CONTROL_REG_GEN_WRITE(MVBAR, c12, 0, c0, 1);
+
+CONTROL_REG_GEN_READ(ISR, c12, 0, c1, 0);
+
+CONTROL_REG_GEN_READ(HVBAR, c12, 4, c0, 0);
+CONTROL_REG_GEN_WRITE(HVBAR, c12, 4, c0, 0);
+
+/* Process context and thread id (FCSE) */
+CONTROL_REG_GEN_READ(FCSEIDR, c13, 0, c0, 0);
+
+CONTROL_REG_GEN_READ(CONTEXTIDR, c13, 0, c0, 1);
+CONTROL_REG_GEN_WRITE(CONTEXTIDR, c13, 0, c0, 1);
+CONTROL_REG_GEN_READ(TPIDRURW, c13, 0, c0, 2);
+CONTROL_REG_GEN_WRITE(TPIDRURW, c13, 0, c0, 2);
+CONTROL_REG_GEN_READ(TPIDRURO, c13, 0, c0, 3);
+CONTROL_REG_GEN_WRITE(TPIDRURO, c13, 0, c0, 3);
+CONTROL_REG_GEN_READ(TPIDRPRW, c13, 0, c0, 4);
+CONTROL_REG_GEN_WRITE(TPIDRPRW, c13, 0, c0, 4);
+
+CONTROL_REG_GEN_READ(HTPIDR, c13, 4, c0, 2);
+CONTROL_REG_GEN_WRITE(HTPIDR, c13, 4, c0, 2);
+
+/* Generic Timer Extensions */
+CONTROL_REG_GEN_READ(CNTFRQ, c14, 0, c0, 0);
+CONTROL_REG_GEN_WRITE(CNTFRQ, c14, 0, c0, 0);
+CONTROL_REG_GEN_READ(CNTKCTL, c14, 0, c1, 0);
+CONTROL_REG_GEN_WRITE(CNTKCTL, c14, 0, c1, 0);
+
+CONTROL_REG_GEN_READ(CNTP_TVAL, c14, 0, c2, 0);
+CONTROL_REG_GEN_WRITE(CNTP_TVAL, c14, 0, c2, 0);
+CONTROL_REG_GEN_READ(CNTP_CTL, c14, 0, c2, 1);
+CONTROL_REG_GEN_WRITE(CNTP_CTL, c14, 0, c2, 1);
+
+CONTROL_REG_GEN_READ(CNTV_TVAL, c14, 0, c3, 0);
+CONTROL_REG_GEN_WRITE(CNTV_TVAL, c14, 0, c3, 0);
+CONTROL_REG_GEN_READ(CNTV_CTL, c14, 0, c3, 1);
+CONTROL_REG_GEN_WRITE(CNTV_CTL, c14, 0, c3, 1);
+
+CONTROL_REG_GEN_READ(CNTHCTL, c14, 4, c1, 0);
+CONTROL_REG_GEN_WRITE(CNTHCTL, c14, 4, c1, 0);
+
+CONTROL_REG_GEN_READ(CNTHP_TVAL, c14, 4, c2, 0);
+CONTROL_REG_GEN_WRITE(CNTHP_TVAL, c14, 4, c2, 0);
+CONTROL_REG_GEN_READ(CNTHP_CTL, c14, 4, c2, 1);
+CONTROL_REG_GEN_WRITE(CNTHP_CTL, c14, 4, c2, 1);
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/arm32/include/cpu.h
===================================================================
--- kernel/arch/arm32/include/cpu.h	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ kernel/arch/arm32/include/cpu.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -40,4 +40,7 @@
 #include <arch/asm.h>
 
+enum {
+	ARM_MAX_CACHE_LEVELS = 7,
+};
 
 /** Struct representing ARM CPU identification. */
@@ -57,4 +60,13 @@
 	/** Revision number. */
 	uint32_t rev_num;
+
+	struct {
+		unsigned ways;
+		unsigned sets;
+		unsigned line_size;
+		unsigned way_shift;
+		unsigned set_shift;
+	} dcache[ARM_MAX_CACHE_LEVELS];
+	unsigned dcache_levels;
 } cpu_arch_t;
 
Index: kernel/arch/arm32/include/cycle.h
===================================================================
--- kernel/arch/arm32/include/cycle.h	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ kernel/arch/arm32/include/cycle.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -38,4 +38,5 @@
 
 #include <trace.h>
+#include <arch/cp15.h>
 
 /** Return count of CPU cycles.
@@ -48,4 +49,14 @@
 NO_TRACE static inline uint64_t get_cycle(void)
 {
+#ifdef PROCESSOR_ARCH_armv7_a
+	if ((ID_PFR1_read() & ID_PFR1_GEN_TIMER_EXT_MASK) ==
+	    ID_PFR1_GEN_TIMER_EXT) {
+	    uint32_t low = 0, high = 0;
+	    asm volatile( "MRRC p15, 0, %[low], %[high], c14": [low]"=r"(low), [high]"=r"(high));
+	   return ((uint64_t)high << 32) | low;
+	} else {
+		return (uint64_t)PMCCNTR_read() * 64;
+	}
+#endif
 	return 0;
 }
Index: kernel/arch/arm32/include/mm/frame.h
===================================================================
--- kernel/arch/arm32/include/mm/frame.h	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ kernel/arch/arm32/include/mm/frame.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -47,25 +47,27 @@
 
 #ifdef MACHINE_gta02
+
+#define PHYSMEM_START_ADDR       0x30008000
 #define BOOT_PAGE_TABLE_ADDRESS  0x30010000
+
 #elif defined MACHINE_beagleboardxm
+
+#define PHYSMEM_START_ADDR       0x80000000
 #define BOOT_PAGE_TABLE_ADDRESS  0x80008000
+
 #elif defined MACHINE_beaglebone
+
+#define PHYSMEM_START_ADDR       0x80000000
 #define BOOT_PAGE_TABLE_ADDRESS  0x80008000
+
 #else
+
+#define PHYSMEM_START_ADDR       0x00000000
 #define BOOT_PAGE_TABLE_ADDRESS  0x00008000
+
 #endif
 
 #define BOOT_PAGE_TABLE_START_FRAME     (BOOT_PAGE_TABLE_ADDRESS >> FRAME_WIDTH)
 #define BOOT_PAGE_TABLE_SIZE_IN_FRAMES  (BOOT_PAGE_TABLE_SIZE >> FRAME_WIDTH)
-
-#ifdef MACHINE_gta02
-#define PHYSMEM_START_ADDR	0x30008000
-#elif defined MACHINE_beagleboardxm
-#define PHYSMEM_START_ADDR      0x80000000
-#elif defined MACHINE_beaglebone
-#define PHYSMEM_START_ADDR      0x80000000
-#else
-#define PHYSMEM_START_ADDR	0x00000000
-#endif
 
 extern void frame_low_arch_init(void);
Index: kernel/arch/arm32/include/mm/page.h
===================================================================
--- kernel/arch/arm32/include/mm/page.h	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ kernel/arch/arm32/include/mm/page.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -129,7 +129,7 @@
 	set_pt_level1_present((pte_t *) (ptl3), (size_t) (i))
 
-#if defined(PROCESSOR_armv6) | defined(PROCESSOR_armv7_a)
+#if defined(PROCESSOR_ARCH_armv6) | defined(PROCESSOR_ARCH_armv7_a)
 #include "page_armv6.h"
-#elif defined(PROCESSOR_armv4) | defined(PROCESSOR_armv5)
+#elif defined(PROCESSOR_ARCH_armv4) | defined(PROCESSOR_ARCH_armv5)
 #include "page_armv4.h"
 #else
Index: kernel/arch/arm32/include/mm/page_fault.h
===================================================================
--- kernel/arch/arm32/include/mm/page_fault.h	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ kernel/arch/arm32/include/mm/page_fault.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -42,5 +42,11 @@
 /** Decribes CP15 "fault status register" (FSR).
  *
- * See ARM Architecture Reference Manual ch. B4.9.6 (pdf p.743).
+ * "VMSAv6 added a fifth fault status bit (bit[10]) to both the IFSR and DFSR.
+ * It is IMPLEMENTATION DEFINED how this bit is encoded in earlier versions of
+ * the architecture. A write flag (bit[11] of the DFSR) has also been
+ * introduced."
+ * ARM Architecture Reference Manual version i ch. B4.6 (PDF p. 719)
+ *
+ * See ARM Architecture Reference Manual ch. B4.9.6 (pdf p.743). for FSR info
  */
 typedef union {
Index: kernel/arch/arm32/include/regutils.h
===================================================================
--- kernel/arch/arm32/include/regutils.h	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ kernel/arch/arm32/include/regutils.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -41,37 +41,17 @@
 #define STATUS_REG_MODE_MASK         0x1f
 
-/* COntrol register bit values see ch. B4.1.130 of ARM Architecture Reference
- * Manual ARMv7-A and ARMv7-R edition, page 1687 */
-#define CP15_R1_MMU_EN            (1 << 0)
-#define CP15_R1_ALIGN_CHECK_EN    (1 << 1)  /* Allow alignemnt check */
-#define CP15_R1_CACHE_EN          (1 << 2)
-#define CP15_R1_CP15_BARRIER_EN   (1 << 5)
-#define CP15_R1_B_EN              (1 << 7)  /* ARMv6- only big endian switch */
-#define CP15_R1_SWAP_EN           (1 << 10)
-#define CP15_R1_BRANCH_PREDICT_EN (1 << 11)
-#define CP15_R1_INST_CACHE_EN     (1 << 12)
-#define CP15_R1_HIGH_VECTORS_EN   (1 << 13)
-#define CP15_R1_ROUND_ROBIN_EN    (1 << 14)
-#define CP15_R1_HW_ACCESS_FLAG_EN (1 << 17)
-#define CP15_R1_WRITE_XN_EN       (1 << 19) /* Only if virt. supported */
-#define CP15_R1_USPCE_WRITE_XN_EN (1 << 20) /* Only if virt. supported */
-#define CP15_R1_FAST_IRQ_EN       (1 << 21) /* Disbale impl.specific features */
-#define CP15_R1_UNALIGNED_EN      (1 << 22) /* Must be 1 on armv7 */
-#define CP15_R1_IRQ_VECTORS_EN    (1 << 24)
-#define CP15_R1_BIG_ENDIAN_EXC    (1 << 25)
-#define CP15_R1_NMFI_EN           (1 << 27)
-#define CP15_R1_TEX_REMAP_EN      (1 << 28)
-#define CP15_R1_ACCESS_FLAG_EN    (1 << 29)
-#define CP15_R1_THUMB_EXC_EN      (1 << 30)
-
 /* ARM Processor Operation Modes */
-#define USER_MODE        0x10
-#define FIQ_MODE         0x11
-#define IRQ_MODE         0x12
-#define SUPERVISOR_MODE  0x13
-#define ABORT_MODE       0x17
-#define UNDEFINED_MODE   0x1b
-#define SYSTEM_MODE      0x1f
-
+enum {
+	USER_MODE = 0x10,
+	FIQ_MODE = 0x11,
+	IRQ_MODE = 0x12,
+	SUPERVISOR_MODE = 0x13,
+	MONITOR_MODE = 0x16,
+	ABORT_MODE = 0x17,
+	HYPERVISOR_MODE = 0x1a,
+	UNDEFINED_MODE = 0x1b,
+	SYSTEM_MODE = 0x1f,
+	MODE_MASK = 0x1f,
+};
 /* [CS]PRS manipulation macros */
 #define GEN_STATUS_READ(nm, reg) \
Index: kernel/arch/arm32/include/security_ext.h
===================================================================
--- kernel/arch/arm32/include/security_ext.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
+++ kernel/arch/arm32/include/security_ext.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013 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 arm32
+ * @{
+ */
+/** @file
+ *  @brief Security Extensions Routines
+ */
+
+#ifndef KERN_arm32_SECURITY_EXT_H_
+#define KERN_arm32_SECURITY_EXT_H_
+
+#include <arch/cp15.h>
+#include <arch/regutils.h>
+
+/** Test whether the current cpu supports security extensions.
+ * return true if security extensions are supported, false otherwise.
+ * @note The Processor Feature Register 1 that provides this information
+ * is available only on armv7+. This function returns false on all\
+ * older archs.
+ */
+static inline bool sec_ext_is_implemented()
+{
+#ifdef PROCESSOR_ARCH_armv7_a
+	const uint32_t idpfr = ID_PFR1_read() & ID_PFR1_SEC_EXT_MASK;
+	return idpfr == ID_PFR1_SEC_EXT || idpfr == ID_PFR1_SEC_EXT_RFR;
+#endif
+	return false;
+}
+
+/** Test whether we are running in monitor mode.
+ * return true, if the current mode is Monitor mode, false otherwise.
+ * @note this is safe to call even on machines that do not implement monitor
+ * mode.
+ */
+static inline bool sec_ext_is_monitor_mode()
+{
+	return (current_status_reg_read() & MODE_MASK) == MONITOR_MODE;
+}
+
+/** Test whether we are running in a secure state.
+ * return true if the current state is secure, false otherwise.
+ *
+ * @note: This functions will cause undef isntruction trap if we
+ * are not running in the secure state.
+ *
+ * @note: u-boot enables non-secure access to cp 10/11, as well as some other
+ * features and switches to non-secure state during boot.
+ * Look for 'secureworld_exit' in arch/arm/cpu/armv7/omap3/board.c.
+ */
+static inline bool sec_ext_is_secure()
+{
+	return sec_ext_is_implemented()
+	    && (sec_ext_is_monitor_mode() || !(SCR_read() & SCR_NS_FLAG));
+}
+
+#endif
+/** @}
+ */
Index: kernel/arch/arm32/src/cpu/cpu.c
===================================================================
--- kernel/arch/arm32/src/cpu/cpu.c	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ kernel/arch/arm32/src/cpu/cpu.c	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -34,8 +34,26 @@
  */
 
+#include <arch/cache.h>
 #include <arch/cpu.h>
+#include <arch/cp15.h>
 #include <cpu.h>
 #include <arch.h>
 #include <print.h>
+
+static inline unsigned log2(unsigned val)
+{
+	unsigned log = 0;
+	--val;
+	while (val) {
+		++log;
+		val >>= 1;
+	}
+	return log;
+}
+
+static unsigned dcache_ways(unsigned level);
+static unsigned dcache_sets(unsigned level);
+static unsigned dcache_linesize_log(unsigned level);
+
 
 /** Implementers (vendor) names */
@@ -81,16 +99,26 @@
 static void arch_cpu_identify(cpu_arch_t *cpu)
 {
-	uint32_t ident;
-	asm volatile (
-		"mrc p15, 0, %[ident], c0, c0, 0\n"
-		: [ident] "=r" (ident)
-	);
-	
-	cpu->imp_num = ident >> 24;
-	cpu->variant_num = (ident << 8) >> 28;
-	cpu->arch_num = (ident << 12) >> 28;
-	cpu->prim_part_num = (ident << 16) >> 20;
-	cpu->rev_num = (ident << 28) >> 28;
+	const uint32_t ident = MIDR_read();
+
+	cpu->imp_num = (ident >> MIDR_IMPLEMENTER_SHIFT) & MIDR_IMPLEMENTER_MASK;
+	cpu->variant_num = (ident >> MIDR_VARIANT_SHIFT) & MIDR_VARIANT_MASK;
+	cpu->arch_num = (ident >> MIDR_ARCHITECTURE_SHIFT) & MIDR_ARCHITECTURE_MASK;
+	cpu->prim_part_num = (ident >> MIDR_PART_NUMBER_SHIFT) & MIDR_PART_NUMBER_MASK;
+	cpu->rev_num = (ident >> MIDR_REVISION_SHIFT) & MIDR_REVISION_MASK;
+
 	// TODO CPUs with arch_num == 0xf use CPUID scheme for identification
+	cpu->dcache_levels = dcache_levels();
+
+	for (unsigned i = 0; i < cpu->dcache_levels; ++i) {
+		cpu->dcache[i].ways = dcache_ways(i);
+		cpu->dcache[i].sets = dcache_sets(i);
+		cpu->dcache[i].way_shift = 31 - log2(cpu->dcache[i].ways);
+		cpu->dcache[i].set_shift = dcache_linesize_log(i);
+		cpu->dcache[i].line_size = 1 << dcache_linesize_log(i);
+		printf("Found DCache L%u: %u-way, %u sets, %u byte lines "
+		    "(shifts: w%u, s%u)\n", i + 1, cpu->dcache[i].ways,
+		    cpu->dcache[i].sets, cpu->dcache[i].line_size,
+		    cpu->dcache[i].way_shift, cpu->dcache[i].set_shift);
+	}
 }
 
@@ -98,23 +126,21 @@
 void cpu_arch_init(void)
 {
-#if defined(PROCESSOR_armv7_a) | defined(PROCESSOR_armv6)
-	uint32_t control_reg = 0;
-	asm volatile (
-		"mrc p15, 0, %[control_reg], c1, c0"
-		: [control_reg] "=r" (control_reg)
-	);
+	uint32_t control_reg = SCTLR_read();
 	
-	/* Turn off tex remap, RAZ ignores writes prior to armv7 */
-	control_reg &= ~CP15_R1_TEX_REMAP_EN;
-	/* Turn off accessed flag, RAZ ignores writes prior to armv7 */
-	control_reg &= ~(CP15_R1_ACCESS_FLAG_EN | CP15_R1_HW_ACCESS_FLAG_EN);
-	/* Enable unaligned access, RAZ ignores writes prior to armv6
-	 * switchable on armv6, RAO ignores writes on armv7,
+	/* Turn off tex remap, RAZ/WI prior to armv7 */
+	control_reg &= ~SCTLR_TEX_REMAP_EN_FLAG;
+	/* Turn off accessed flag, RAZ/WI prior to armv7 */
+	control_reg &= ~(SCTLR_ACCESS_FLAG_EN_FLAG | SCTLR_HW_ACCESS_FLAG_EN_FLAG);
+
+	/* Unaligned access is supported on armv6+ */
+#if defined(PROCESSOR_ARCH_armv7_a) | defined(PROCESSOR_ARCH_armv6)
+	/* Enable unaligned access, RAZ/WI prior to armv6
+	 * switchable on armv6, RAO/WI writes on armv7,
 	 * see ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition
 	 * L.3.1 (p. 2456) */
-	control_reg |= CP15_R1_UNALIGNED_EN;
+	control_reg |= SCTLR_UNALIGNED_EN_FLAG;
 	/* Disable alignment checks, this turns unaligned access to undefined,
 	 * unless U bit is set. */
-	control_reg &= ~CP15_R1_ALIGN_CHECK_EN;
+	control_reg &= ~SCTLR_ALIGN_CHECK_EN_FLAG;
 	/* Enable caching, On arm prior to armv7 there is only one level
 	 * of caches. Data cache is coherent.
@@ -124,16 +150,34 @@
 	 *    ARM Architecture Reference Manual ARMv7-A and ARMv7-R Edition
 	 *    B3.11.1 (p. 1383)
-	 * ICache coherency is elaborate on in barrier.h.
-	 * We are safe to turn these on.
+	 * We are safe to turn this on. For arm v6 see ch L.6.2 (p. 2469)
+	 * L2 Cache for armv7 is enabled by default (i.e. controlled by
+	 * this flag).
 	 */
-	control_reg |= CP15_R1_CACHE_EN | CP15_R1_INST_CACHE_EN;
-	
-	asm volatile (
-		"mcr p15, 0, %[control_reg], c1, c0"
-		:: [control_reg] "r" (control_reg)
-	);
-#endif
+	control_reg |= SCTLR_CACHE_EN_FLAG;
+#endif
+#ifdef PROCESSOR_ARCH_armv7_a
+	 /* ICache coherency is elaborate on in barrier.h.
+	  * VIPT and PIPT caches need maintenance only on code modify,
+	  * so it should be safe for general use.
+	  * Enable branch predictors too as they follow the same rules
+	  * as ICache and they can be flushed together
+	  */
+	if ((CTR_read() & CTR_L1I_POLICY_MASK) != CTR_L1I_POLICY_AIVIVT) {
+		control_reg |=
+		    SCTLR_INST_CACHE_EN_FLAG | SCTLR_BRANCH_PREDICT_EN_FLAG;
+	}
+#endif
+	SCTLR_write(control_reg);
+
 #ifdef CONFIG_FPU
 	fpu_setup();
+#endif
+
+#ifdef PROCESSOR_ARCH_armv7_a
+	if ((ID_PFR1_read() & ID_PFR1_GEN_TIMER_EXT_MASK) !=
+	    ID_PFR1_GEN_TIMER_EXT) {
+		PMCR_write(PMCR_read() | PMCR_E_FLAG | PMCR_D_FLAG);
+		PMCNTENSET_write(PMCNTENSET_CYCLE_COUNTER_EN_FLAG);
+	}
 #endif
 }
@@ -155,4 +199,127 @@
 }
 
+/** See chapter B4.1.19 of ARM Architecture Reference Manual */
+static unsigned dcache_linesize_log(unsigned level)
+{
+#ifdef PROCESSOR_ARCH_armv7_a
+	CSSELR_write((level & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT);
+	const unsigned ls_log = 2 +
+	    ((CCSIDR_read() >> CCSIDR_LINESIZE_SHIFT) & CCSIDR_LINESIZE_MASK);
+	return ls_log + 2; //return log2(bytes)
+#endif
+	return 0;
+
+}
+
+/** See chapter B4.1.19 of ARM Architecture Reference Manual */
+static unsigned dcache_ways(unsigned level)
+{
+#ifdef PROCESSOR_ARCH_armv7_a
+	CSSELR_write((level & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT);
+	const unsigned ways = 1 +
+	    ((CCSIDR_read() >> CCSIDR_ASSOC_SHIFT) & CCSIDR_ASSOC_MASK);
+	return ways;
+#endif
+	return 0;
+}
+
+/** See chapter B4.1.19 of ARM Architecture Reference Manual */
+static unsigned dcache_sets(unsigned level)
+{
+#ifdef PROCESSOR_ARCH_armv7_a
+	CSSELR_write((level & CCSELR_LEVEL_MASK) << CCSELR_LEVEL_SHIFT);
+	const unsigned sets = 1 +
+	    ((CCSIDR_read() >> CCSIDR_NUMSETS_SHIFT) & CCSIDR_NUMSETS_MASK);
+	return sets;
+#endif
+	return 0;
+}
+
+unsigned dcache_levels(void)
+{
+	unsigned levels = 0;
+#ifdef PROCESSOR_ARCH_armv7_a
+	const uint32_t val = CLIDR_read();
+	for (unsigned i = 1; i <= 7; ++i) {
+		const unsigned ctype = CLIDR_CACHE(i, val);
+		switch (ctype) {
+		case CLIDR_DCACHE_ONLY:
+		case CLIDR_SEP_CACHE:
+		case CLIDR_UNI_CACHE:
+			++levels;
+		default:
+			(void)0;
+		}
+	}
+#endif
+	return levels;
+}
+
+static void dcache_clean_manual(unsigned level, bool invalidate,
+    unsigned ways, unsigned sets, unsigned way_shift, unsigned set_shift)
+{
+
+	for (unsigned i = 0; i < ways; ++i) {
+		for (unsigned j = 0; j < sets; ++j) {
+			const uint32_t val =
+			    ((level & 0x7) << 1) |
+			    (j << set_shift) | (i << way_shift);
+			if (invalidate)
+				DCCISW_write(val);
+			else
+				DCCSW_write(val);
+		}
+	}
+}
+
+void dcache_flush(void)
+{
+	/* See ARM Architecture Reference Manual ch. B4.2.1 p. B4-1724 */
+	const unsigned levels = dcache_levels();
+	for (unsigned i = 0; i < levels; ++i) {
+		const unsigned ways = dcache_ways(i);
+		const unsigned sets = dcache_sets(i);
+		const unsigned way_shift =  31 - log2(ways);
+		const unsigned set_shift = dcache_linesize_log(i);
+		dcache_clean_manual(i, false, ways, sets, way_shift, set_shift);
+	}
+}
+
+void dcache_flush_invalidate(void)
+{
+	/* See ARM Architecture Reference Manual ch. B4.2.1 p. B4-1724 */
+	const unsigned levels = dcache_levels();
+	for (unsigned i = 0; i < levels; ++i) {
+		const unsigned ways = dcache_ways(i);
+		const unsigned sets = dcache_sets(i);
+		const unsigned way_shift =  31 - log2(ways);
+		const unsigned set_shift = dcache_linesize_log(i);
+		dcache_clean_manual(i, true, ways, sets, way_shift, set_shift);
+	}
+}
+
+
+void cpu_dcache_flush(void)
+{
+	for (unsigned i = 0; i < CPU->arch.dcache_levels; ++i)
+		dcache_clean_manual(i, false,
+		    CPU->arch.dcache[i].ways, CPU->arch.dcache[i].sets,
+		    CPU->arch.dcache[i].way_shift, CPU->arch.dcache[i].set_shift);
+}
+
+void cpu_dcache_flush_invalidate(void)
+{
+	const unsigned levels =  dcache_levels();
+	for (unsigned i = 0; i < levels; ++i)
+		dcache_clean_manual(i, true,
+		    CPU->arch.dcache[i].ways, CPU->arch.dcache[i].sets,
+		    CPU->arch.dcache[i].way_shift, CPU->arch.dcache[i].set_shift);
+}
+
+void icache_invalidate(void)
+{
+	ICIALLU_write(0);
+}
+
 /** @}
  */
Index: kernel/arch/arm32/src/exception.c
===================================================================
--- kernel/arch/arm32/src/exception.c	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ kernel/arch/arm32/src/exception.c	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -39,4 +39,5 @@
 #include <interrupt.h>
 #include <arch/mm/page_fault.h>
+#include <arch/cp15.h>
 #include <arch/barrier.h>
 #include <print.h>
@@ -73,5 +74,5 @@
 	/* make it LDR instruction and store at exception vector */
 	*vector = handler_address_ptr | LDR_OPCODE;
-	smc_coherence(*vector);
+	smc_coherence(vector);
 	
 	/* store handler's address */
@@ -136,17 +137,10 @@
 static void high_vectors(void)
 {
-	uint32_t control_reg = 0;
-	asm volatile (
-		"mrc p15, 0, %[control_reg], c1, c0"
-		: [control_reg] "=r" (control_reg)
-	);
+	uint32_t control_reg = SCTLR_read();
 	
 	/* switch on the high vectors bit */
-	control_reg |= CP15_R1_HIGH_VECTORS_EN;
-	
-	asm volatile (
-		"mcr p15, 0, %[control_reg], c1, c0"
-		:: [control_reg] "r" (control_reg)
-	);
+	control_reg |= SCTLR_HIGH_VECTORS_EN_FLAG;
+	
+	SCTLR_write(control_reg);
 }
 #endif
Index: kernel/arch/arm32/src/fpu.s
===================================================================
--- kernel/arch/arm32/src/fpu.s	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
+++ kernel/arch/arm32/src/fpu.s	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2013 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.
+ */
+
+.text
+
+.global fpsid_read
+.global mvfr0_read
+.global fpscr_read
+.global fpscr_write
+.global fpexc_read
+.global fpexc_write
+
+.global fpu_context_save_s32
+.global fpu_context_restore_s32
+.global fpu_context_save_d16
+.global fpu_context_restore_d16
+.global fpu_context_save_d32
+.global fpu_context_restore_d32
+
+fpsid_read:
+	vmrs r0, fpsid
+	mov pc, lr
+
+mvfr0_read:
+	vmrs r0, mvfr0
+	mov pc, lr
+
+fpscr_read:
+	vmrs r0, fpscr
+	mov pc, lr
+
+fpscr_write:
+	vmsr fpscr, r0
+	mov pc, lr
+
+fpexc_read:
+	vmrs r0, fpexc
+	mov pc, lr
+
+fpexc_write:
+	vmsr fpexc, r0
+	mov pc, lr
+
+fpu_context_save_s32:
+	vmrs r1, fpexc
+	vmrs r2, fpscr
+	stmia r0!, {r1, r2}
+	vstmia r0!, {s0-s31}
+	mov pc, lr
+
+fpu_context_restore_s32:
+	ldmia r0!, {r1, r2}
+	vmsr fpexc, r1
+	vmsr fpscr, r2
+	vldmia r0!, {s0-s31}
+	mov pc, lr
+
+fpu_context_save_d16:
+	vmrs r1, fpexc
+	vmrs r2, fpscr
+	stmia r0!, {r1, r2}
+	vstmia r0!, {d0-d15}
+	mov pc, lr
+
+fpu_context_restore_d16:
+	ldmia r0!, {r1, r2}
+	vmsr fpexc, r1
+	vmsr fpscr, r2
+	vldmia r0!, {d0-d15}
+	mov pc, lr
+
+fpu_context_save_d32:
+	vmrs r1, fpexc
+	stmia r0!, {r1}
+	vmrs r1, fpscr
+	stmia r0!, {r1}
+	vstmia r0!, {d0-d15}
+	vstmia r0!, {d16-d31}
+	mov pc, lr
+
+fpu_context_restore_d32:
+	ldmia r0!, {r1, r2}
+	vmsr fpexc, r1
+	vmsr fpscr, r2
+	vldmia r0!, {d0-d15}
+	vldmia r0!, {d16-d31}
+	mov pc, lr
+
+
+
Index: kernel/arch/arm32/src/fpu_context.c
===================================================================
--- kernel/arch/arm32/src/fpu_context.c	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ kernel/arch/arm32/src/fpu_context.c	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -37,4 +37,6 @@
 #include <arch.h>
 #include <arch/types.h>
+#include <arch/security_ext.h>
+#include <arch/cp15.h>
 #include <cpu.h>
 
@@ -55,8 +57,13 @@
 };
 
+extern uint32_t fpsid_read(void);
+extern uint32_t mvfr0_read(void);
+
 enum {
 	FPEXC_EX_FLAG = (1 << 31),
 	FPEXC_ENABLED_FLAG = (1 << 30),
 };
+extern uint32_t fpexc_read(void);
+extern void fpexc_write(uint32_t);
 
 /** ARM Architecture Reference Manual ch. B4.1.58, p. B$-1551 */
@@ -94,140 +101,69 @@
 	FPSCR_EN_ALL = FPSCR_DENORMAL_EN_FLAG | FPSCR_INEXACT_EN_FLAG | FPSCR_UNDERFLOW_EN_FLAG | FPSCR_OVERFLOW_EN_FLAG | FPSCR_ZERO_DIV_EN_FLAG | FPSCR_INVALID_OP_EN_FLAG,
 };
-
-static inline uint32_t fpscr_read()
-{
-	uint32_t reg;
-	asm volatile (
-		"vmrs %0, fpscr\n"
-		:"=r" (reg)::
-	);
-	return reg;
-}
-
-static inline void fpscr_write(uint32_t val)
-{
-	asm volatile (
-		"vmsr fpscr, %0\n"
-		::"r" (val):
-	);
-}
-
-static inline uint32_t fpexc_read()
-{
-	uint32_t reg;
-	asm volatile (
-		"vmrs %0, fpexc\n"
-		:"=r" (reg)::
-	);
-	return reg;
-}
-
-static inline void fpexc_write(uint32_t val)
-{
-	asm volatile (
-		"vmsr fpexc, %0\n"
-		::"r" (val):
-	);
-}
+extern uint32_t fpscr_read(void);
+extern void fpscr_write(uint32_t);
+
+extern void fpu_context_save_s32(fpu_context_t *);
+extern void fpu_context_restore_s32(fpu_context_t *);
+extern void fpu_context_save_d16(fpu_context_t *);
+extern void fpu_context_restore_d16(fpu_context_t *);
+extern void fpu_context_save_d32(fpu_context_t *);
+extern void fpu_context_restore_d32(fpu_context_t *);
 
 static void (*save_context)(fpu_context_t *ctx);
 static void (*restore_context)(fpu_context_t *ctx);
 
-/** Saves 32 single precision fpu registers.
- * @param ctx FPU context area.
- * Used by VFPv1
- */
-static void fpu_context_save_s32(fpu_context_t *ctx)
-{
-	asm volatile (
-		"vmrs r1, fpexc\n"
-		"vmrs r2, fpscr\n"
-		"stmia %0!, {r1, r2}\n"
-		"vstmia %0!, {s0-s31}\n"
-		::"r" (ctx): "r1","r2","memory"
-	);
-}
-
-/** Restores 32 single precision fpu registers.
- * @param ctx FPU context area.
- * Used by VFPv1
- */
-static void fpu_context_restore_s32(fpu_context_t *ctx)
-{
-	asm volatile (
-		"ldmia %0!, {r1, r2}\n"
-		"vmsr fpexc, r1\n"
-		"vmsr fpscr, r2\n"
-		"vldmia %0!, {s0-s31}\n"
-		::"r" (ctx): "r1","r2"
-	);
-}
-
-/** Saves 16 double precision fpu registers.
- * @param ctx FPU context area.
- * Used by VFPv2, VFPv3-d16, and VFPv4-d16.
- */
-static void fpu_context_save_d16(fpu_context_t *ctx)
-{
-	asm volatile (
-		"vmrs r1, fpexc\n"
-		"vmrs r2, fpscr\n"
-		"stmia %0!, {r1, r2}\n"
-		"vstmia %0!, {d0-d15}\n"
-		::"r" (ctx): "r1","r2","memory"
-	);
-}
-
-/** Restores 16 double precision fpu registers.
- * @param ctx FPU context area.
- * Used by VFPv2, VFPv3-d16, and VFPv4-d16.
- */
-static void fpu_context_restore_d16(fpu_context_t *ctx)
-{
-	asm volatile (
-		"ldmia %0!, {r1, r2}\n"
-		"vmsr fpexc, r1\n"
-		"vmsr fpscr, r2\n"
-		"vldmia %0!, {d0-d15}\n"
-		::"r" (ctx): "r1","r2"
-	);
-}
-
-/** Saves 32 double precision fpu registers.
- * @param ctx FPU context area.
- * Used by VFPv3-d32, VFPv4-d32, and advanced SIMD.
- */
-static void fpu_context_save_d32(fpu_context_t *ctx)
-{
-	asm volatile (
-		"vmrs r1, fpexc\n"
-		"stmia %0!, {r1}\n"
-		"vmrs r1, fpscr\n"
-		"stmia %0!, {r1}\n"
-		"vstmia %0!, {d0-d15}\n"
-		"vstmia %0!, {d16-d31}\n"
-		::"r" (ctx): "r1","memory"
-	);
-}
-
-/** Restores 32 double precision fpu registers.
- * @param ctx FPU context area.
- * Used by VFPv3-d32, VFPv4-d32, and advanced SIMD.
- */
-static void fpu_context_restore_d32(fpu_context_t *ctx)
-{
-	asm volatile (
-		"ldmia %0!, {r1}\n"
-		"vmsr fpexc, r1\n"
-		"ldmia %0!, {r1}\n"
-		"vmsr fpscr, r1\n"
-		"vldmia %0!, {d0-d15}\n"
-		"vldmia %0!, {d16-d31}\n"
-		::"r" (ctx): "r1"
-	);
-}
+static int fpu_have_coprocessor_access()
+{
+/* The register containing the information (CPACR) is not available on armv6-
+ * rely on user decision to use CONFIG_FPU.
+ */
+#ifdef PROCESSOR_ARC_armv7_a
+	const uint32_t cpacr = CPACR_read();
+	/* FPU needs access to coprocessor 10 and 11.
+	 * Moreover they need to have same access enabledd */
+	if (((cpacr & CPACR_CP_MASK(10)) != CPACR_CP_FULL_ACCESS(10)) &&
+	   ((cpacr & CPACR_CP_MASK(11)) != CPACR_CP_FULL_ACCESS(11))) {
+		printf("No access to CP10 and CP11: %" PRIx32 "\n", cpacr);
+		return 0;
+	}
+#endif
+	return 1;
+}
+
+/** Enable coprocessor access. Turn both non-secure mode bit and generic access.
+ * Cortex A8 Manual says:
+ * "You must execute an Instruction Memory Barrier (IMB) sequence immediately
+ * after an update of the Coprocessor Access Control Register, see Memory
+ * Barriers in the ARM Architecture Reference Manual. You must not attempt to
+ * execute any instructions that are affected by the change of access rights
+ * between the IMB sequence and the register update."
+ * Cortex a8 TRM ch. 3.2.27. c1, Coprocessor Access Control Register
+ *
+ * @note do we need to call secure monitor here?
+ */
+static void fpu_enable_coprocessor_access()
+{
+/* The register containing the information (CPACR) is not available on armv6-
+ * rely on user decision to use CONFIG_FPU.
+ */
+#ifdef PROCESSOR_ARCH_armv7_a
+	/* Allow coprocessor access */
+	uint32_t cpacr = CPACR_read();
+	/* FPU needs access to coprocessor 10 and 11.
+	 * Moreover, they need to have same access enabled */
+	cpacr &= ~(CPACR_CP_MASK(10) | CPACR_CP_MASK(11));
+	cpacr |= (CPACR_CP_FULL_ACCESS(10) | CPACR_CP_FULL_ACCESS(11));
+	CPACR_write(cpacr);
+#endif
+}
+
 
 void fpu_init(void)
 {
+	/* Check if we have access */
+	if (!fpu_have_coprocessor_access())
+		return;
+
 	/* Clear all fpu flags */
 	fpexc_write(0);
@@ -241,9 +177,12 @@
 void fpu_setup(void)
 {
-	uint32_t fpsid = 0;
-	asm volatile (
-		"vmrs %0, fpsid\n"
-		:"=r"(fpsid)::
-	);
+	/* Enable coprocessor access*/
+	fpu_enable_coprocessor_access();
+
+	/* Check if we succeeded */
+	if (!fpu_have_coprocessor_access())
+		return;
+
+	const uint32_t fpsid = fpsid_read();
 	if (fpsid & FPSID_SW_ONLY_FLAG) {
 		printf("No FPU avaiable\n");
@@ -265,9 +204,5 @@
 	case FPU_VFPv3_NO_COMMON:
 	case FPU_VFPv3_COMMONv3: {
-		uint32_t mvfr0 = 0;
-		asm volatile (
-			"vmrs %0,mvfr0\n"
-			:"=r"(mvfr0)::
-		);
+		const uint32_t mvfr0 = mvfr0_read();
 		/* See page B4-1637 */
 		if ((mvfr0 & 0xf) == 0x1) {
@@ -288,4 +223,8 @@
 bool handle_if_fpu_exception(void)
 {
+	/* Check if we have access */
+	if (!fpu_have_coprocessor_access())
+		return false;
+
 	const uint32_t fpexc = fpexc_read();
 	if (fpexc & FPEXC_ENABLED_FLAG) {
@@ -305,4 +244,7 @@
 void fpu_enable(void)
 {
+	/* Check if we have access */
+	if (!fpu_have_coprocessor_access())
+		return;
 	/* Enable FPU instructions */
 	fpexc_write(fpexc_read() | FPEXC_ENABLED_FLAG);
@@ -311,4 +253,7 @@
 void fpu_disable(void)
 {
+	/* Check if we have access */
+	if (!fpu_have_coprocessor_access())
+		return;
 	/* Disable FPU instructions */
 	fpexc_write(fpexc_read() & ~FPEXC_ENABLED_FLAG);
@@ -317,4 +262,6 @@
 void fpu_context_save(fpu_context_t *ctx)
 {
+	/* This is only necessary if we enable fpu exceptions. */
+#if 0
 	const uint32_t fpexc = fpexc_read();
 
@@ -323,4 +270,5 @@
 		//TODO implement common subarch context saving
 	}
+#endif
 	if (save_context)
 		save_context(ctx);
Index: kernel/arch/arm32/src/mach/beagleboardxm/beagleboardxm.c
===================================================================
--- kernel/arch/arm32/src/mach/beagleboardxm/beagleboardxm.c	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ kernel/arch/arm32/src/mach/beagleboardxm/beagleboardxm.c	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -38,5 +38,4 @@
 #include <genarch/drivers/amdm37x/irc.h>
 #include <genarch/drivers/amdm37x/gpt.h>
-#include <genarch/drivers/amdm37x/dispc.h>
 #include <genarch/fb/fb.h>
 #include <genarch/srln/srln.h>
@@ -61,5 +60,4 @@
 
 static struct beagleboard {
-	amdm37x_dispc_regs_t *dispc;
 	amdm37x_irc_regs_t *irc_addr;
 	amdm37x_uart_t uart;
@@ -85,53 +83,4 @@
 }
 
-static void bbxm_setup_fb(unsigned width, unsigned height, unsigned bpp)
-{
-	const unsigned pixel_bytes = (bpp / 8);
-	const size_t size = ALIGN_UP(width * height * pixel_bytes, FRAME_SIZE);
-	const unsigned frames = size / FRAME_SIZE;
-	unsigned order = 0;
-	unsigned frame = 1;
-	while (frame < frames) {
-		frame *= 2;
-		++order;
-	}
-	/* prefer highmem as we don't care about virtual mapping. */
-	void *buffer = frame_alloc(order, FRAME_LOWMEM);
-	if (!buffer) {
-		printf("Failed to allocate framebuffer.\n");
-		return;
-	}
-
-	amdm37x_dispc_setup_fb(beagleboard.dispc, width, height, bpp,
-	    (uintptr_t) buffer);
-
-	fb_properties_t prop = {
-		.addr = (uintptr_t)buffer,
-		.offset = 0,
-		.x = width,
-		.y = height,
-		.scan = width * pixel_bytes,
-		.visual = VISUAL_RGB_5_6_5_LE
-	};
-	switch (bpp)
-	{
-	case 8:
-		prop.visual = VISUAL_INDIRECT_8; break;
-	case 16:
-		prop.visual = VISUAL_RGB_5_6_5_LE; break;
-	case 24:
-		prop.visual = VISUAL_BGR_8_8_8; break;
-	case 32:
-		prop.visual = VISUAL_RGB_8_8_8_0; break;
-	default:
-		printf("Invalid framebuffer bit depth: bailing out.\n");
-		return;
-	}
-	outdev_t *fb_dev = fb_init(&prop);
-	if (fb_dev)
-		stdout_wire(fb_dev);
-
-}
-
 static void bb_timer_irq_handler(irq_t *irq)
 {
@@ -154,9 +103,4 @@
 	ASSERT(beagleboard.irc_addr);
 	amdm37x_irc_init(beagleboard.irc_addr);
-
-	/* Map display controller */
-	beagleboard.dispc = (void*) km_map(AMDM37x_DISPC_BASE_ADDRESS,
-	    AMDM37x_DISPC_SIZE, PAGE_NOT_CACHEABLE);
-	ASSERT(beagleboard.dispc);
 
 	/* Initialize timer. Use timer1, because it is in WKUP power domain
@@ -223,9 +167,4 @@
 static void bbxm_output_init(void)
 {
-#ifdef CONFIG_FB
-	bbxm_setup_fb(CONFIG_BFB_WIDTH, CONFIG_BFB_HEIGHT, CONFIG_BFB_BPP);
-#else
-	(void)bbxm_setup_fb;
-#endif
 	/* UART3 is wired to external RS232 connector */
 	const bool ok = amdm37x_uart_init(&beagleboard.uart,
Index: kernel/arch/arm32/src/mm/page_fault.c
===================================================================
--- kernel/arch/arm32/src/mm/page_fault.c	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ kernel/arch/arm32/src/mm/page_fault.c	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -34,4 +34,5 @@
  */
 #include <panic.h>
+#include <arch/cp15.h>
 #include <arch/exception.h>
 #include <arch/mm/page_fault.h>
@@ -127,52 +128,5 @@
 }
 
-
-/** Returns value stored in comnbined/data fault status register.
- *
- *  @return Value stored in CP15 fault status register (FSR).
- *
- *  "VMSAv6 added a fifth fault status bit (bit[10]) to both the IFSR and DFSR.
- *  It is IMPLEMENTATION DEFINED how this bit is encoded in earlier versions of
- *  the architecture. A write flag (bit[11] of the DFSR) has also been
- *  introduced."
- *  ARM Architecture Reference Manual version i ch. B4.6 (PDF p. 719)
- *
- *  See ch. B4.9.6 for location of data/instruction FSR.
- *
- */
-static inline fault_status_t read_data_fault_status_register(void)
-{
-	fault_status_t fsu;
-	
-	/* Combined/Data fault status is stored in CP15 register 5, c0. */
-	asm volatile (
-		"mrc p15, 0, %[dummy], c5, c0, 0"
-		: [dummy] "=r" (fsu.raw)
-	);
-	
-	return fsu;
-}
-
-/** Returns DFAR (fault address register) content.
- *
- * This register is equivalent to FAR on pre armv6 machines.
- *
- * @return DFAR (fault address register) content (address that caused a page
- *         fault)
- */
-static inline uintptr_t read_data_fault_address_register(void)
-{
-	uintptr_t ret;
-	
-	/* fault adress is stored in CP15 register 6 */
-	asm volatile (
-		"mrc p15, 0, %[ret], c6, c0, 0"
-		: [ret] "=r" (ret)
-	);
-	
-	return ret;
-}
-
-#if defined(PROCESSOR_armv4) | defined(PROCESSOR_armv5)
+#if defined(PROCESSOR_ARCH_armv4) | defined(PROCESSOR_ARCH_armv5)
 /** Decides whether read or write into memory is requested.
  *
@@ -244,6 +198,6 @@
 void data_abort(unsigned int exc_no, istate_t *istate)
 {
-	const uintptr_t badvaddr = read_data_fault_address_register();
-	const fault_status_t fsr = read_data_fault_status_register();
+	const uintptr_t badvaddr = DFAR_read();
+	const fault_status_t fsr = { .raw = DFSR_read() };
 	const dfsr_source_t source = fsr.raw & DFSR_SOURCE_MASK;
 
@@ -281,8 +235,8 @@
 	}
 
-#if defined(PROCESSOR_armv6) | defined(PROCESSOR_armv7_a)
+#if defined(PROCESSOR_ARCH_armv6) | defined(PROCESSOR_ARCH_armv7_a)
 	const pf_access_t access =
 	    fsr.data.wr ? PF_ACCESS_WRITE : PF_ACCESS_READ;
-#elif defined(PROCESSOR_armv4) | defined(PROCESSOR_armv5)
+#elif defined(PROCESSOR_ARCH_armv4) | defined(PROCESSOR_ARCH_armv5)
 	const pf_access_t access = get_memory_access_type(istate->pc, badvaddr);
 #else
Index: rnel/genarch/include/drivers/amdm37x/dispc.h
===================================================================
--- kernel/genarch/include/drivers/amdm37x/dispc.h	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ 	(revision )
@@ -1,394 +1,0 @@
-/*
- * 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 Texas Instruments AM/DM37x SDRAM Memory Scheduler.
- */
-
-#ifndef KERN_AMDM37x_DISPC_H_
-#define KERN_AMDM37x_DISPC_H_
-
-/* AMDM37x TRM p. 1813 */
-#define AMDM37x_DISPC_BASE_ADDRESS 0x48050400
-#define AMDM37x_DISPC_SIZE 1024
-
-#define __paddname(line) PADD32_ ## line
-#define _paddname(line) __paddname(line)
-#define PADD32(count) uint32_t _paddname(__LINE__)[count]
-
-#include <typedefs.h>
-
-typedef struct {
-	const ioport32_t revision;
-#define AMDM37X_DISPC_REVISION_MASK  0xff
-
-	PADD32(3);
-	ioport32_t sysconfig;
-#define AMDM37X_DISPC_SYSCONFIG_AUTOIDLE_FLAG  (1 << 0)
-#define AMDM37X_DISPC_SYSCONFIG_SOFTRESET_FLAG  (1 << 1)
-#define AMDM37X_DISPC_SYSCONFIG_ENWAKEUP_FLAG  (1 << 2)
-#define AMDM37X_DISPC_SYSCONFIG_SIDLEMODE_MASK  0x3
-#define AMDM37X_DISPC_SYSCONFIG_SIDLEMODE_SHIFT  3
-#define AMDM37X_DISPC_SYSCONFIG_CLOCKACTIVITY_MASK  0x3
-#define AMDM37X_DISPC_SYSCONFIG_CLOCKACTIVITY_SHIFT  8
-#define AMDM37X_DISPC_SYSCONFIG_MIDLEMODE_MASK  0x3
-#define AMDM37X_DISPC_SYSCONFIG_MIDLEMODE_SHIFT  12
-
-	const ioport32_t sysstatus;
-#define AMDM37X_DISPC_SYSSTATUS_RESETDONE_FLAG  (1 << 0)
-
-	ioport32_t irqstatus;
-	ioport32_t irqenable;
-#define AMDM37X_DISPC_IRQ_FRAMEDONE_FLAG  (1 << 0)
-#define AMDM37X_DISPC_IRQ_VSYNC_FLAG  (1 << 1)
-#define AMDM37X_DISPC_IRQ_EVSYNCEVEN_FLAG  (1 << 2)
-#define AMDM37X_DISPC_IRQ_EVSYNCODD_FLAG  (1 << 3)
-#define AMDM37X_DISPC_IRQ_ACBIASCOUNTSTATUS_FLAG  (1 << 4)
-#define AMDM37X_DISPC_IRQ_PROGRAMMEDLINENUMBER_FLAG  (1 << 5)
-#define AMDM37X_DISPC_IRQ_GFXFIFOUNDERFLOW_FLAG  (1 << 6)
-#define AMDM37X_DISPC_IRQ_GFXENDWINDOW_FLAG  (1 << 7)
-#define AMDM37X_DISPC_IRQ_PALETTEGAMMALOADING_FLAG  (1 << 8)
-#define AMDM37X_DISPC_IRQ_OPCERROR_FLAG  (1 << 9)
-#define AMDM37X_DISPC_IRQ_VID1FIFOUNDERFLOW_FLAG  (1 << 10)
-#define AMDM37X_DISPC_IRQ_VID1ENDWINDOW_FLAG  (1 << 11)
-#define AMDM37X_DISPC_IRQ_VID2FIFOUNDERFLOW_FLAG  (1 << 12)
-#define AMDM37X_DISPC_IRQ_VID2ENDWINDOW_FLAG  (1 << 13)
-#define AMDM37X_DISPC_IRQ_SYNCLOST_FLAG  (1 << 14)
-#define AMDM37X_DISPC_IRQ_SYNCLOSTDIGITAL_FLAG  (1 << 15)
-#define AMDM37X_DISPC_IRQ_WAKEUP_FLAG  (1 << 16)
-
-	PADD32(8);
-	ioport32_t control;
-#define AMDM37X_DISPC_CONTROL_LCD_ENABLE_FLAG  (1 << 0)
-#define AMDM37X_DISPC_CONTROL_DIGITAL_ENABLE_FLAG  (1 << 1)
-#define AMDM37X_DISPC_CONTROL_MONOCOLOR_FLAG  (1 << 2)
-#define AMDM37X_DISPC_CONTROL_STNTFT_FLAG  (1 << 3)
-#define AMDM37X_DISPC_CONTROL_M8B_FLAG  (1 << 4)
-#define AMDM37X_DISPC_CONTROL_GOLCD_FLAG  (1 << 5)
-#define AMDM37X_DISPC_CONTROL_GODIGITAL_FLAG  (1 << 6)
-#define AMDM37X_DISPC_CONTROL_STDITHERENABLE_FLAG  (1 << 7)
-#define AMDM37X_DISPC_CONTROL_TFTDATALINES_MASK  0x3
-#define AMDM37X_DISPC_CONTROL_TFTDATALINES_SHIFT  8
-#define AMDM37X_DISPC_CONTROL_TFTDATALINES_12B  0
-#define AMDM37X_DISPC_CONTROL_TFTDATALINES_16B  1
-#define AMDM37X_DISPC_CONTROL_TFTDATALINES_18B  2
-#define AMDM37X_DISPC_CONTROL_TFTDATALINES_24B  3
-#define AMDM37X_DISPC_CONTROL_STALLMODE_FLAG  (1 << 11)
-#define AMDM37X_DISPC_CONTROL_OVERLAYOPTIMIZATION_FLAG  (1 << 12)
-#define AMDM37X_DISPC_CONTROL_GPIN0_FLAG  (1 << 13)
-#define AMDM37X_DISPC_CONTROL_GPIN1_FLAG  (1 << 14)
-#define AMDM37X_DISPC_CONTROL_GPOUT0_FLAG  (1 << 15)
-#define AMDM37X_DISPC_CONTROL_GPOUT1_FLAG  (1 << 16)
-#define AMDM37X_DISPC_CONTROL_HT_MASK  0x7
-#define AMDM37X_DISPC_CONTROL_HT_SHIFT  17
-#define AMDM37X_DISPC_CONTROL_TDMENABLE_FLAG  (1 << 20)
-#define AMDM37X_DISPC_CONTROL_TDMPARALLELMODE_MASK  0x3
-#define AMDM37X_DISPC_CONTROL_TDMPARELLELMODE_SHIFT  21
-#define AMDM37X_DISPC_CONTROL_TDMCYCLEFORMAT_MASK  0x3
-#define AMDM37X_DISPC_CONTROL_TDMCYCLEFORMAT_SHIFT  23
-#define AMDM37X_DISPC_CONTROL_TDMUNUSEDBITS_MASK  0x3
-#define AMDM37X_DISPC_CONTROL_TDMUNUSEDBITS_SHIFT  25
-#define AMDM37X_DISPC_CONTROL_PCKFREEENABLE_FLAG  (1 << 27)
-#define AMDM37X_DISPC_CONTROL_LCDENABLESIGNAL_FLAG  (1 << 28)
-#define AMDM37X_DISPC_CONTROL_KCDENABLEPOL_FLAG  (1 << 29)
-#define AMDM37X_DISPC_CONTROL_SPATIALTEMPORALDITHERINGFRAMES_MASK  0x3
-#define AMDM37X_DISPC_CONTROL_SPATIALTEMPORALDITHERINGFRAMES_SHIFT  30
-
-	ioport32_t config;
-#define AMDM37X_DISPC_CONFIG_PIXELGATED_FLAG  (1 << 0)
-#define AMDM37X_DISPC_CONFIG_LOADMODE_MASK  0x3
-#define AMDM37X_DISPC_CONFIG_LOADMODE_SHIFT  1
-#define AMDM37X_DISPC_CONFIG_LOADMODE_PGDATAEVERYFRAME  0x0
-#define AMDM37X_DISPC_CONFIG_LOADMODE_PGUSER  0x1
-#define AMDM37X_DISPC_CONFIG_LOADMODE_DATAEVERYFRAME  0x2
-#define AMDM37X_DISPC_CONFIG_LOADMODE_PGDFIRSTFRAME  0x3
-#define AMDM37X_DISPC_CONFIG_PALETTEGAMMATABLE_FLAG  (1 << 3)
-#define AMDM37X_DISPC_CONFIG_PIXELDATAGATED_FLAG  (1 << 4)
-#define AMDM37X_DISPC_CONFIG_PIXELCLOCKGATED_FLAG  (1 << 5)
-#define AMDM37X_DISPC_CONFIG_HSYNCGATED_FLAG  (1 << 6)
-#define AMDM37X_DISPC_CONFIG_VSYNCGATED_FLAG  (1 << 7)
-#define AMDM37X_DISPC_CONFIG_ACBIASGATED_FLAG  (1 << 8)
-#define AMDM37X_DISPC_CONFIG_FUNCGATED_FLAG  (1 << 9)
-#define AMDM37X_DISPC_CONFIG_TCKLCDENABLE_FLAG  (1 << 10)
-#define AMDM37X_DISPC_CONFIG_TCKLCDSELECTION_FLAG  (1 << 11)
-#define AMDM37X_DISPC_CONFIG_TCKDIGENABLE_FLAG  (1 << 12)
-#define AMDM37X_DISPC_CONFIG_TCKDIGSELECTION_FLAG  (1 << 13)
-#define AMDM37X_DISPC_CONFIG_FIFOMERGE_FLAG  (1 << 14)
-#define AMDM37X_DISPC_CONFIG_CPR_FLAG  (1 << 15)
-#define AMDM37X_DISPC_CONFIG_FIFOHANDCHECK_FLAG  (1 << 16)
-#define AMDM37X_DISPC_CONFIG_FIFOFILLING_FLAG  (1 << 17)
-#define AMDM37X_DISPC_CONFIG_LCDPALPHABLENDERENABLDE_FLAG  (1 << 18)
-#define AMDM37X_DISPC_CONFIG_TVALPHABLENDERENABLE_FLAG  (1 << 19)
-
-	PADD32(1);
-	ioport32_t default_color[2];
-	ioport32_t trans_color[2];
-#define AMDM37X_DISPC_COLOR_MASK 0xffffff
-
-	const ioport32_t line_status;
-	ioport32_t line_number;
-#define AMDM37X_DISPC_LINE_NUMBER_MASK 0x3ff
-
-	ioport32_t timing_h;
-#define AMDM37X_DISPC_TIMING_H_HSW_MASK 0xff
-#define AMDM37X_DISPC_TIMING_H_HSW_SHIFT 0
-#define AMDM37X_DISPC_TIMING_H_HFP_MASK 0xfff
-#define AMDM37X_DISPC_TIMING_H_HFP_SHIFT 8
-#define AMDM37X_DISPC_TIMING_H_HBP_MASK 0xfff
-#define AMDM37X_DISPC_TIMING_H_HBP_SHIFT 20
-
-	ioport32_t timing_v;
-#define AMDM37X_DISPC_TIMING_V_VSW_MASK 0xff
-#define AMDM37X_DISPC_TIMING_V_VSW_SHIFT 0
-#define AMDM37X_DISPC_TIMING_V_VFP_MASK 0xfff
-#define AMDM37X_DISPC_TIMING_V_VFP_SHIFT 8
-#define AMDM37X_DISPC_TIMING_V_VBP_MASK 0xfff
-#define AMDM37X_DISPC_TIMING_V_VBP_SHIFT 20
-
-	ioport32_t pol_freq;
-#define AMDM37X_DISPC_POL_FREQ_ACB_MASK  0xff
-#define AMDM37X_DISPC_POL_FREQ_ACB_SHIFT 0
-#define AMDM37X_DISPC_POL_FREQ_ACBI_MASK  0xf
-#define AMDM37X_DISPC_POL_FREQ_ACBI_SHIFT 8
-#define AMDM37X_DISPC_POL_FREQ_IVS_FLAG  (1 << 12)
-#define AMDM37X_DISPC_POL_FREQ_IHS_FLAG  (1 << 13)
-#define AMDM37X_DISPC_POL_FREQ_IPC_FLAG  (1 << 14)
-#define AMDM37X_DISPC_POL_FREQ_IEO_FLAG  (1 << 15)
-#define AMDM37X_DISPC_POL_FREQ_RF_FLAG  (1 << 16)
-#define AMDM37X_DISPC_POL_FREQ_ONOFF_FLAG  (1 << 17)
-
-	ioport32_t divisor;
-#define AMDM37X_DISPC_DIVISOR_PCD_MASK  0xff
-#define AMDM37X_DISPC_DIVISOR_PCD_SHIFT  0
-#define AMDM37X_DISPC_DIVISOR_LCD_MASK  0xff
-#define AMDM37X_DISPC_DIVISOR_LCD_SHIFT  16
-
-	ioport32_t global_alpha;
-#define AMDM37X_DISPC_GLOBAL_ALPHA_GFXGLOBALALPHA_MASK  0xff
-#define AMDM37X_DISPC_GLOBAL_ALPHA_GFXGLOBALALPHA_SHIFT  0
-#define AMDM37X_DISPC_GLOBAL_ALPHA_VID2GLOBALALPHA_MASK  0xff
-#define AMDM37X_DISPC_GLOBAL_ALPHA_VID2GLOBALALPHA_SHIFT  16
-
-	ioport32_t size_dig;
-	ioport32_t size_lcd;
-
-	struct {
-		ioport32_t ba[2];
-		ioport32_t position;
-#define AMDM37X_DISPC_GFX_POSITION_GFXPOSX_MASK  0x7ff
-#define AMDM37X_DISPC_GFX_POSITION_GFXPOSX_SHIFT  0
-#define AMDM37X_DISPC_GFX_POSITION_GFXPOSY_MASK  0x7ff
-#define AMDM37X_DISPC_GFX_POSITION_GFXPOSY_SHIFT  16
-
-		ioport32_t size;
-#define AMDM37X_DISPC_SIZE_WIDTH_MASK  0x7ff
-#define AMDM37X_DISPC_SIZE_WIDTH_SHIFT  0
-#define AMDM37X_DISPC_SIZE_HEIGHT_MASK  0x7ff
-#define AMDM37X_DISPC_SIZE_HEIGHT_SHIFT  16
-
-		PADD32(4);
-		ioport32_t attributes;
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_ENABLE_FLAG  (1 << 0)
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_MASK  0xf
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_SHIFT  1
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_ARGB16  0x5
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGB16  0x6
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGB24_32  0x8
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGB24  0x9
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_ARGB  0xc
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGBA  0xd
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGBX  0xe
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_REPLICATIONENABLE_FLAG  (1 << 5)
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXBURSTSIZE_MASK  0x3
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXBURSTSIZE_SHIFT  6
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXCHANNELOUT_FLAG  (1 << 8)
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXNIBBLEMODE_FLAG  (1 << 9)
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXENDIANNES_FLAG  (1 << 10)
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXFIFOPRELOAD_FLAG  (1 << 11)
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXROTATION_MASK  0x3
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXROTATION_SHIFT  12
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXARBITRATION_FLAG  (1 << 14)
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXSELFREFRESH_FLAG  (1 << 15)
-#define AMDM37X_DISPC_GFX_ATTRIBUTES_PREMULTIALPHA_FLAG  (1 << 28)
-
-
-		ioport32_t fifo_threshold;
-		const ioport32_t fifo_size_status;
-		ioport32_t row_inc;
-		ioport32_t pixel_inc;
-		ioport32_t window_skip;
-		ioport32_t table_ba;
-	} gfx;
-
-	struct {
-		ioport32_t ba[2];
-		ioport32_t position;
-		ioport32_t size;
-		ioport32_t attributes;
-		ioport32_t fifo_threshold;
-		const ioport32_t fifo_size_status;
-		ioport32_t row_inc;
-		ioport32_t pixel_inc;
-		ioport32_t fir;
-		ioport32_t picture_size;
-		ioport32_t accui[2];
-		struct {
-			ioport32_t hi;
-			ioport32_t hvi;
-		} fir_coef[8];
-		ioport32_t conv_coef[5];
-		PADD32(2);
-	} vid[2];
-	/* 0x1d4 */
-	ioport32_t data_cycle[3];
-	/* 0x1e0 */
-	ioport32_t vid_fir_coef_v[8];
-	/* 0x200 */
-	PADD32(8);
-	/* 0x220 */
-	ioport32_t cpr_coef_r;
-	ioport32_t cpr_coef_g;
-	ioport32_t cpr_coef_b;
-	ioport32_t gfx_preload;
-
-	/* 0x230 */
-	ioport32_t vid_preload[2];
-
-} __attribute__((packed)) amdm37x_dispc_regs_t;
-
-
-static inline void amdm37x_dispc_setup_fb(amdm37x_dispc_regs_t *regs,
-    unsigned x, unsigned y, unsigned bpp, uintptr_t pa)
-{
-	ASSERT(regs);
-	/* Init sequence for dispc is in chapter 7.6.5.1.4 p. 1810,
-	 * no idea what parts of that work. */
-
-	/* Disable all interrupts */
-	regs->irqenable = 0;
-
-	/* Pixel format specifics*/
-	uint32_t attrib_pixel_format = 0;
-	uint32_t control_data_lanes = 0;
-	switch (bpp)
-	{
-	case 32:
-		attrib_pixel_format = AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGBX;
-		control_data_lanes = AMDM37X_DISPC_CONTROL_TFTDATALINES_24B;
-		break;
-	case 24:
-		attrib_pixel_format = AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGB24;
-		control_data_lanes = AMDM37X_DISPC_CONTROL_TFTDATALINES_24B;
-		break;
-	case 16:
-		attrib_pixel_format = AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGB16;
-		control_data_lanes = AMDM37X_DISPC_CONTROL_TFTDATALINES_16B;
-		break;
-	default:
-		ASSERT(false);
-	}
-
-	/* Prepare sizes */
-	const uint32_t size_reg =
-	    (((x - 1) & AMDM37X_DISPC_SIZE_WIDTH_MASK)
-	        << AMDM37X_DISPC_SIZE_WIDTH_SHIFT) |
-	    (((y - 1) & AMDM37X_DISPC_SIZE_HEIGHT_MASK)
-	        << AMDM37X_DISPC_SIZE_HEIGHT_SHIFT);
-
-	/* modes taken from u-boot, for 1024x768 */
-	// TODO replace magic values with actual correct values
-//	regs->timing_h = 0x1a4024c9;
-//	regs->timing_v = 0x02c00509;
-//	regs->pol_freq = 0x00007028;
-//	regs->divisor  = 0x00010001;
-
-	/* setup output */
-	regs->size_lcd = size_reg;
-	regs->size_dig = size_reg;
-
-	/* Nice blue default color */
-	regs->default_color[0] = 0x0000ff;
-	regs->default_color[1] = 0x0000ff;
-
-	/* Setup control register */
-	uint32_t control = 0 |
-		AMDM37X_DISPC_CONTROL_PCKFREEENABLE_FLAG |
-		(control_data_lanes << AMDM37X_DISPC_CONTROL_TFTDATALINES_SHIFT) |
-		AMDM37X_DISPC_CONTROL_GPOUT0_FLAG |
-		AMDM37X_DISPC_CONTROL_GPOUT1_FLAG;
-	regs->control = control;
-
-	/* No gamma stuff only data */
-	uint32_t config = (AMDM37X_DISPC_CONFIG_LOADMODE_DATAEVERYFRAME
-	            << AMDM37X_DISPC_CONFIG_LOADMODE_SHIFT);
-	regs->config = config;
-
-
-	/* Set framebuffer base address */
-	regs->gfx.ba[0] = pa;
-	regs->gfx.ba[1] = pa;
-	regs->gfx.position = 0;
-
-	/* Setup fb size */
-	regs->gfx.size = size_reg;
-
-	/* Set pixel format */
-	uint32_t attribs = 0 |
-	    (attrib_pixel_format << AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_SHIFT);
-	regs->gfx.attributes = attribs;
-
-	/* 0x03ff03c0 is the default */
-	regs->gfx.fifo_threshold = 0x03ff03c0;
-	/* This value should be stride - width, 1 means next pixel i.e.
-	 * stride == width */
-	regs->gfx.row_inc = 1;
-	/* number of bytes to next pixel in BPP multiples */
-	regs->gfx.pixel_inc = 1;
-	/* only used if video is played over fb */
-	regs->gfx.window_skip = 0;
-	/* Gamma and palette table */
-	regs->gfx.table_ba = 0;
-
-	/* enable frame buffer graphics */
-	regs->gfx.attributes |= AMDM37X_DISPC_GFX_ATTRIBUTES_ENABLE_FLAG;
-	/* Update register values */
-	regs->control |= AMDM37X_DISPC_CONTROL_GOLCD_FLAG;
-	regs->control |= AMDM37X_DISPC_CONTROL_GODIGITAL_FLAG;
-	/* Enable output */
-	regs->control |= AMDM37X_DISPC_CONTROL_LCD_ENABLE_FLAG;
-	regs->control |= AMDM37X_DISPC_CONTROL_DIGITAL_ENABLE_FLAG;
-}
-
-
-#endif
-/**
- * @}
- */
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ uspace/Makefile	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -194,5 +194,6 @@
 ifeq ($(UARCH),arm32)
 	DIRS += \
-		drv/infrastructure/rootamdm37x
+		drv/infrastructure/rootamdm37x \
+		drv/fb/amdm37x_dispc
 endif
 
Index: uspace/drv/fb/amdm37x_dispc/Makefile
===================================================================
--- uspace/drv/fb/amdm37x_dispc/Makefile	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
+++ uspace/drv/fb/amdm37x_dispc/Makefile	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -0,0 +1,49 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# Copyright (c) 2011 Petr Koupy
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+
+LIBS = \
+	$(LIBDRV_PREFIX)/libdrv.a \
+	$(LIBGRAPH_PREFIX)/libgraph.a \
+	$(LIBSOFTREND_PREFIX)/libsoftrend.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBDRV_PREFIX)/include \
+	-I$(LIBGRAPH_PREFIX) \
+	-I$(LIBSOFTREND_PREFIX)
+
+BINARY = amdm37x_dispc
+
+SOURCES = \
+	amdm37x_dispc.c \
+	main.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.c
===================================================================
--- uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.c	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
+++ uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.c	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2013 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 amdm37x
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <ddf/log.h>
+#include <ddi.h>
+#include <abi/mm/as.h>
+
+#include "amdm37x_dispc.h"
+
+static int change_mode(visualizer_t *vis, vslmode_t mode);
+static int handle_damage(visualizer_t *vs,
+    sysarg_t x0, sysarg_t y0, sysarg_t width, sysarg_t height,
+    sysarg_t x_offset, sysarg_t y_offset);
+static int dummy(visualizer_t *vs)
+{
+	return EOK;
+}
+
+static const visualizer_ops_t amdm37x_dispc_vis_ops = {
+	.change_mode = change_mode,
+	.handle_damage = handle_damage,
+	.claim = dummy,
+	.yield = dummy,
+	.suspend = dummy,
+	.wakeup = dummy,
+};
+
+static const struct {
+	unsigned bpp;
+	pixel2visual_t func;
+} pixel2visual_table[] = {
+	[VISUAL_INDIRECT_8] = { .bpp = 1, .func = pixel2bgr_323 },
+	[VISUAL_RGB_5_5_5_LE] = { .bpp = 2, .func = pixel2rgb_555_le },
+	[VISUAL_RGB_5_5_5_BE] = { .bpp = 2, .func = pixel2rgb_555_be },
+	[VISUAL_RGB_5_6_5_LE] = { .bpp = 2, .func = pixel2rgb_565_le },
+	[VISUAL_RGB_5_6_5_BE] = { .bpp = 2, .func = pixel2rgb_565_be },
+	[VISUAL_BGR_8_8_8] = { .bpp = 3, .func = pixel2bgr_888 },
+	[VISUAL_RGB_8_8_8] = { .bpp = 3, .func = pixel2rgb_888 },
+	[VISUAL_BGR_0_8_8_8] = { .bpp = 4, .func = pixel2rgb_0888 },
+	[VISUAL_BGR_8_8_8_0] = { .bpp = 4, .func = pixel2bgr_8880 },
+	[VISUAL_ABGR_8_8_8_8] = { .bpp = 4, .func = pixel2abgr_8888 },
+	[VISUAL_BGRA_8_8_8_8] = { .bpp = 4, .func = pixel2bgra_8888 },
+	[VISUAL_RGB_0_8_8_8] = { .bpp = 4, .func = pixel2rgb_0888 },
+	[VISUAL_RGB_8_8_8_0] = { .bpp = 4, .func = pixel2rgb_8880 },
+	[VISUAL_ARGB_8_8_8_8] = { .bpp = 4, .func = pixel2argb_8888 },
+	[VISUAL_RGBA_8_8_8_8] = { .bpp = 4, .func = pixel2rgba_8888 },
+};
+
+
+
+static void mode_init(vslmode_list_element_t *mode,
+    unsigned width, unsigned height, visual_t visual)
+{
+	mode->mode.index = 0;
+	mode->mode.version = 0;
+	mode->mode.refresh_rate = 0;
+	mode->mode.screen_aspect.width = width;
+	mode->mode.screen_aspect.height = height;
+	mode->mode.screen_width = width;
+	mode->mode.screen_height = height;
+	mode->mode.cell_aspect.width = 1;
+	mode->mode.cell_aspect.height = 1;
+	mode->mode.cell_visual.pixel_visual = visual;
+
+	link_initialize(&mode->link);
+
+}
+
+int amdm37x_dispc_init(amdm37x_dispc_t *instance, visualizer_t *vis)
+{
+	assert(instance);
+	assert(vis);
+
+	instance->fb_data = NULL;
+	instance->size = 0;
+
+	visual_t visual = VISUAL_UNKNOWN;
+
+	switch (CONFIG_BFB_BPP)	{
+	case 8: visual = VISUAL_INDIRECT_8; break;
+	case 16: visual = VISUAL_RGB_5_6_5_LE; break;
+	case 24: visual = VISUAL_BGR_8_8_8; break;
+	case 32: visual = VISUAL_RGB_8_8_8_0; break;
+	default:
+		return EINVAL;
+	}
+
+	int ret = pio_enable((void*)AMDM37x_DISPC_BASE_ADDRESS,
+	    AMDM37x_DISPC_SIZE, (void**)&instance->regs);
+	if (ret != EOK) {
+		return EIO;
+	}
+
+	mode_init(&instance->modes[0],
+	    CONFIG_BFB_WIDTH, CONFIG_BFB_HEIGHT, visual);
+
+	/* Handle vis stuff */
+	vis->dev_ctx = instance;
+	vis->def_mode_idx = 0;
+	vis->ops = amdm37x_dispc_vis_ops;
+	list_append(&instance->modes[0].link, &vis->modes);
+
+	return EOK;
+};
+
+int amdm37x_dispc_fini(amdm37x_dispc_t *instance)
+{
+	return EOK;
+};
+
+static int amdm37x_dispc_setup_fb(amdm37x_dispc_regs_t *regs,
+    unsigned x, unsigned y, unsigned bpp, uint32_t pa)
+{
+	assert(regs);
+	/* Init sequence for dispc is in chapter 7.6.5.1.4 p. 1810,
+	 * no idea what parts of that work. */
+
+	/* Disable all interrupts */
+	regs->irqenable = 0;
+
+	/* Pixel format specifics*/
+	uint32_t attrib_pixel_format = 0;
+	uint32_t control_data_lanes = 0;
+	switch (bpp)
+	{
+	case 32:
+		attrib_pixel_format = AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGBX;
+		control_data_lanes = AMDM37X_DISPC_CONTROL_TFTDATALINES_24B;
+		break;
+	case 24:
+		attrib_pixel_format = AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGB24;
+		control_data_lanes = AMDM37X_DISPC_CONTROL_TFTDATALINES_24B;
+		break;
+	case 16:
+		attrib_pixel_format = AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGB16;
+		control_data_lanes = AMDM37X_DISPC_CONTROL_TFTDATALINES_16B;
+		break;
+	default:
+		return EINVAL;
+	}
+
+	/* Prepare sizes */
+	const uint32_t size_reg =
+	    (((x - 1) & AMDM37X_DISPC_SIZE_WIDTH_MASK)
+	        << AMDM37X_DISPC_SIZE_WIDTH_SHIFT) |
+	    (((y - 1) & AMDM37X_DISPC_SIZE_HEIGHT_MASK)
+	        << AMDM37X_DISPC_SIZE_HEIGHT_SHIFT);
+
+	/* modes taken from u-boot, for 1024x768 */
+	// TODO replace magic values with actual correct values
+//	regs->timing_h = 0x1a4024c9;
+//	regs->timing_v = 0x02c00509;
+//	regs->pol_freq = 0x00007028;
+//	regs->divisor  = 0x00010001;
+
+	/* setup output */
+	regs->size_lcd = size_reg;
+	regs->size_dig = size_reg;
+
+	/* Nice blue default color */
+	regs->default_color[0] = 0x0000ff;
+	regs->default_color[1] = 0x0000ff;
+
+	/* Setup control register */
+	uint32_t control = 0 |
+		AMDM37X_DISPC_CONTROL_PCKFREEENABLE_FLAG |
+		(control_data_lanes << AMDM37X_DISPC_CONTROL_TFTDATALINES_SHIFT) |
+		AMDM37X_DISPC_CONTROL_GPOUT0_FLAG |
+		AMDM37X_DISPC_CONTROL_GPOUT1_FLAG;
+	regs->control = control;
+
+	/* No gamma stuff only data */
+	uint32_t config = (AMDM37X_DISPC_CONFIG_LOADMODE_DATAEVERYFRAME
+	            << AMDM37X_DISPC_CONFIG_LOADMODE_SHIFT);
+	regs->config = config;
+
+
+	/* Set framebuffer base address */
+	regs->gfx.ba[0] = pa;
+	regs->gfx.ba[1] = pa;
+	regs->gfx.position = 0;
+
+	/* Setup fb size */
+	regs->gfx.size = size_reg;
+
+	/* Set pixel format */
+	uint32_t attribs = 0 |
+	    (attrib_pixel_format << AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_SHIFT);
+	regs->gfx.attributes = attribs;
+
+	/* 0x03ff03c0 is the default */
+	regs->gfx.fifo_threshold = 0x03ff03c0;
+	/* This value should be stride - width, 1 means next pixel i.e.
+	 * stride == width */
+	regs->gfx.row_inc = 1;
+	/* number of bytes to next pixel in BPP multiples */
+	regs->gfx.pixel_inc = 1;
+	/* only used if video is played over fb */
+	regs->gfx.window_skip = 0;
+	/* Gamma and palette table */
+	regs->gfx.table_ba = 0;
+
+	/* enable frame buffer graphics */
+	regs->gfx.attributes |= AMDM37X_DISPC_GFX_ATTRIBUTES_ENABLE_FLAG;
+	/* Update register values */
+	regs->control |= AMDM37X_DISPC_CONTROL_GOLCD_FLAG;
+	regs->control |= AMDM37X_DISPC_CONTROL_GODIGITAL_FLAG;
+	/* Enable output */
+	regs->control |= AMDM37X_DISPC_CONTROL_LCD_ENABLE_FLAG;
+	regs->control |= AMDM37X_DISPC_CONTROL_DIGITAL_ENABLE_FLAG;
+	return EOK;
+}
+
+static int change_mode(visualizer_t *vis, vslmode_t mode)
+{
+	assert(vis);
+	assert(vis->dev_ctx);
+
+	amdm37x_dispc_t *dispc = vis->dev_ctx;
+	const visual_t visual = mode.cell_visual.pixel_visual;
+	assert(visual < sizeof(pixel2visual_table) / sizeof(pixel2visual_table[0]));
+	const unsigned bpp = pixel2visual_table[visual].bpp;
+	pixel2visual_t p2v = pixel2visual_table[visual].func;
+	const unsigned x = mode.screen_width;
+	const unsigned y = mode.screen_height;
+	ddf_log_note("Setting mode: %ux%ux%u\n", x, y, bpp*8);
+	const size_t size = ALIGN_UP(x * y * bpp, PAGE_SIZE);
+	void *buffer, *pa;
+	int ret = dmamem_map_anonymous(size, AS_AREA_READ | AS_AREA_WRITE,
+	    0, &pa, &buffer);
+	if (ret != EOK) {
+		ddf_log_error("Failed to get new FB\n");
+		return ret;
+	}
+	amdm37x_dispc_setup_fb(dispc->regs, x, y, bpp *8, (uint32_t)pa);
+	dispc->active_fb.idx = mode.index;
+	dispc->active_fb.width = x;
+	dispc->active_fb.height = y;
+	dispc->active_fb.pitch = 0;
+	dispc->active_fb.bpp = bpp;
+	dispc->active_fb.pixel2visual = p2v;
+	dispc->fb_data = buffer;
+	dispc->size = size;
+	assert(mode.index < 1);
+
+	if (dispc->fb_data)
+		dmamem_unmap_anonymous(dispc->fb_data);
+	return EOK;
+}
+
+static int handle_damage(visualizer_t *vs,
+    sysarg_t x0, sysarg_t y0, sysarg_t width, sysarg_t height,
+    sysarg_t x_offset, sysarg_t y_offset)
+{
+	assert(vs);
+	assert(vs->dev_ctx);
+	amdm37x_dispc_t *dispc = vs->dev_ctx;
+	pixelmap_t *map = &vs->cells;
+
+#define FB_POS(x, y) \
+	(((y) * (dispc->active_fb.width + dispc->active_fb.pitch) + (x)) \
+	    * dispc->active_fb.bpp)
+	if (x_offset == 0 && y_offset == 0) {
+		/* Faster damage routine ignoring offsets. */
+		for (sysarg_t y = y0; y < height + y0; ++y) {
+			pixel_t *pixel = pixelmap_pixel_at(map, x0, y);
+			for (sysarg_t x = x0; x < width + x0; ++x) {
+				dispc->active_fb.pixel2visual(
+				    dispc->fb_data + FB_POS(x, y), *pixel++);
+			}
+		}
+	} else {
+		for (sysarg_t y = y0; y < height + y0; ++y) {
+			for (sysarg_t x = x0; x < width + x0; ++x) {
+				dispc->active_fb.pixel2visual(
+				    dispc->fb_data + FB_POS(x, y),
+				    *pixelmap_pixel_at(map,
+				        (x + x_offset) % map->width,
+				        (y + y_offset) % map->height));
+			}
+		}
+	}
+
+	return EOK;
+}
Index: uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.h
===================================================================
--- uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
+++ uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 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 kgraph
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef AMDM37X_DISPC_H_
+#define AMDM37X_DISPC_H_
+
+#include <graph.h>
+#include <abi/fb/visuals.h>
+#include <pixconv.h>
+
+#include "amdm37x_dispc_regs.h"
+
+typedef struct {
+	amdm37x_dispc_regs_t *regs;
+
+	struct {
+		pixel2visual_t pixel2visual;
+		unsigned width;
+		unsigned height;
+		unsigned pitch;
+		unsigned bpp;
+		unsigned idx;
+	} active_fb;
+
+	size_t size;
+	void *fb_data;
+
+	vslmode_list_element_t modes[1];
+} amdm37x_dispc_t;
+
+int amdm37x_dispc_init(amdm37x_dispc_t *instance, visualizer_t *vis);
+int amdm37x_dispc_fini(amdm37x_dispc_t *instance);
+
+#endif
+/** @}
+ */
Index: uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.ma
===================================================================
--- uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.ma	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
+++ uspace/drv/fb/amdm37x_dispc/amdm37x_dispc.ma	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -0,0 +1,1 @@
+100 amdm37x&dispc
Index: uspace/drv/fb/amdm37x_dispc/amdm37x_dispc_regs.h
===================================================================
--- uspace/drv/fb/amdm37x_dispc/amdm37x_dispc_regs.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
+++ uspace/drv/fb/amdm37x_dispc/amdm37x_dispc_regs.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2013 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 Texas Instruments AM/DM37x SDRAM Memory Scheduler.
+ */
+
+#ifndef AMDM37x_DISPC_REGS_H_
+#define AMDM37x_DISPC_REGS_H_
+
+/* AMDM37x TRM p. 1813 */
+#define AMDM37x_DISPC_BASE_ADDRESS 0x48050400
+#define AMDM37x_DISPC_SIZE 1024
+
+#include <macros.h>
+
+typedef struct {
+	const ioport32_t revision;
+#define AMDM37X_DISPC_REVISION_MASK  0xff
+
+	PADD32[3];
+	ioport32_t sysconfig;
+#define AMDM37X_DISPC_SYSCONFIG_AUTOIDLE_FLAG  (1 << 0)
+#define AMDM37X_DISPC_SYSCONFIG_SOFTRESET_FLAG  (1 << 1)
+#define AMDM37X_DISPC_SYSCONFIG_ENWAKEUP_FLAG  (1 << 2)
+#define AMDM37X_DISPC_SYSCONFIG_SIDLEMODE_MASK  0x3
+#define AMDM37X_DISPC_SYSCONFIG_SIDLEMODE_SHIFT  3
+#define AMDM37X_DISPC_SYSCONFIG_CLOCKACTIVITY_MASK  0x3
+#define AMDM37X_DISPC_SYSCONFIG_CLOCKACTIVITY_SHIFT  8
+#define AMDM37X_DISPC_SYSCONFIG_MIDLEMODE_MASK  0x3
+#define AMDM37X_DISPC_SYSCONFIG_MIDLEMODE_SHIFT  12
+
+	const ioport32_t sysstatus;
+#define AMDM37X_DISPC_SYSSTATUS_RESETDONE_FLAG  (1 << 0)
+
+	ioport32_t irqstatus;
+	ioport32_t irqenable;
+#define AMDM37X_DISPC_IRQ_FRAMEDONE_FLAG  (1 << 0)
+#define AMDM37X_DISPC_IRQ_VSYNC_FLAG  (1 << 1)
+#define AMDM37X_DISPC_IRQ_EVSYNCEVEN_FLAG  (1 << 2)
+#define AMDM37X_DISPC_IRQ_EVSYNCODD_FLAG  (1 << 3)
+#define AMDM37X_DISPC_IRQ_ACBIASCOUNTSTATUS_FLAG  (1 << 4)
+#define AMDM37X_DISPC_IRQ_PROGRAMMEDLINENUMBER_FLAG  (1 << 5)
+#define AMDM37X_DISPC_IRQ_GFXFIFOUNDERFLOW_FLAG  (1 << 6)
+#define AMDM37X_DISPC_IRQ_GFXENDWINDOW_FLAG  (1 << 7)
+#define AMDM37X_DISPC_IRQ_PALETTEGAMMALOADING_FLAG  (1 << 8)
+#define AMDM37X_DISPC_IRQ_OPCERROR_FLAG  (1 << 9)
+#define AMDM37X_DISPC_IRQ_VID1FIFOUNDERFLOW_FLAG  (1 << 10)
+#define AMDM37X_DISPC_IRQ_VID1ENDWINDOW_FLAG  (1 << 11)
+#define AMDM37X_DISPC_IRQ_VID2FIFOUNDERFLOW_FLAG  (1 << 12)
+#define AMDM37X_DISPC_IRQ_VID2ENDWINDOW_FLAG  (1 << 13)
+#define AMDM37X_DISPC_IRQ_SYNCLOST_FLAG  (1 << 14)
+#define AMDM37X_DISPC_IRQ_SYNCLOSTDIGITAL_FLAG  (1 << 15)
+#define AMDM37X_DISPC_IRQ_WAKEUP_FLAG  (1 << 16)
+
+	PADD32[8];
+	ioport32_t control;
+#define AMDM37X_DISPC_CONTROL_LCD_ENABLE_FLAG  (1 << 0)
+#define AMDM37X_DISPC_CONTROL_DIGITAL_ENABLE_FLAG  (1 << 1)
+#define AMDM37X_DISPC_CONTROL_MONOCOLOR_FLAG  (1 << 2)
+#define AMDM37X_DISPC_CONTROL_STNTFT_FLAG  (1 << 3)
+#define AMDM37X_DISPC_CONTROL_M8B_FLAG  (1 << 4)
+#define AMDM37X_DISPC_CONTROL_GOLCD_FLAG  (1 << 5)
+#define AMDM37X_DISPC_CONTROL_GODIGITAL_FLAG  (1 << 6)
+#define AMDM37X_DISPC_CONTROL_STDITHERENABLE_FLAG  (1 << 7)
+#define AMDM37X_DISPC_CONTROL_TFTDATALINES_MASK  0x3
+#define AMDM37X_DISPC_CONTROL_TFTDATALINES_SHIFT  8
+#define AMDM37X_DISPC_CONTROL_TFTDATALINES_12B  0
+#define AMDM37X_DISPC_CONTROL_TFTDATALINES_16B  1
+#define AMDM37X_DISPC_CONTROL_TFTDATALINES_18B  2
+#define AMDM37X_DISPC_CONTROL_TFTDATALINES_24B  3
+#define AMDM37X_DISPC_CONTROL_STALLMODE_FLAG  (1 << 11)
+#define AMDM37X_DISPC_CONTROL_OVERLAYOPTIMIZATION_FLAG  (1 << 12)
+#define AMDM37X_DISPC_CONTROL_GPIN0_FLAG  (1 << 13)
+#define AMDM37X_DISPC_CONTROL_GPIN1_FLAG  (1 << 14)
+#define AMDM37X_DISPC_CONTROL_GPOUT0_FLAG  (1 << 15)
+#define AMDM37X_DISPC_CONTROL_GPOUT1_FLAG  (1 << 16)
+#define AMDM37X_DISPC_CONTROL_HT_MASK  0x7
+#define AMDM37X_DISPC_CONTROL_HT_SHIFT  17
+#define AMDM37X_DISPC_CONTROL_TDMENABLE_FLAG  (1 << 20)
+#define AMDM37X_DISPC_CONTROL_TDMPARALLELMODE_MASK  0x3
+#define AMDM37X_DISPC_CONTROL_TDMPARELLELMODE_SHIFT  21
+#define AMDM37X_DISPC_CONTROL_TDMCYCLEFORMAT_MASK  0x3
+#define AMDM37X_DISPC_CONTROL_TDMCYCLEFORMAT_SHIFT  23
+#define AMDM37X_DISPC_CONTROL_TDMUNUSEDBITS_MASK  0x3
+#define AMDM37X_DISPC_CONTROL_TDMUNUSEDBITS_SHIFT  25
+#define AMDM37X_DISPC_CONTROL_PCKFREEENABLE_FLAG  (1 << 27)
+#define AMDM37X_DISPC_CONTROL_LCDENABLESIGNAL_FLAG  (1 << 28)
+#define AMDM37X_DISPC_CONTROL_KCDENABLEPOL_FLAG  (1 << 29)
+#define AMDM37X_DISPC_CONTROL_SPATIALTEMPORALDITHERINGFRAMES_MASK  0x3
+#define AMDM37X_DISPC_CONTROL_SPATIALTEMPORALDITHERINGFRAMES_SHIFT  30
+
+	ioport32_t config;
+#define AMDM37X_DISPC_CONFIG_PIXELGATED_FLAG  (1 << 0)
+#define AMDM37X_DISPC_CONFIG_LOADMODE_MASK  0x3
+#define AMDM37X_DISPC_CONFIG_LOADMODE_SHIFT  1
+#define AMDM37X_DISPC_CONFIG_LOADMODE_PGDATAEVERYFRAME  0x0
+#define AMDM37X_DISPC_CONFIG_LOADMODE_PGUSER  0x1
+#define AMDM37X_DISPC_CONFIG_LOADMODE_DATAEVERYFRAME  0x2
+#define AMDM37X_DISPC_CONFIG_LOADMODE_PGDFIRSTFRAME  0x3
+#define AMDM37X_DISPC_CONFIG_PALETTEGAMMATABLE_FLAG  (1 << 3)
+#define AMDM37X_DISPC_CONFIG_PIXELDATAGATED_FLAG  (1 << 4)
+#define AMDM37X_DISPC_CONFIG_PIXELCLOCKGATED_FLAG  (1 << 5)
+#define AMDM37X_DISPC_CONFIG_HSYNCGATED_FLAG  (1 << 6)
+#define AMDM37X_DISPC_CONFIG_VSYNCGATED_FLAG  (1 << 7)
+#define AMDM37X_DISPC_CONFIG_ACBIASGATED_FLAG  (1 << 8)
+#define AMDM37X_DISPC_CONFIG_FUNCGATED_FLAG  (1 << 9)
+#define AMDM37X_DISPC_CONFIG_TCKLCDENABLE_FLAG  (1 << 10)
+#define AMDM37X_DISPC_CONFIG_TCKLCDSELECTION_FLAG  (1 << 11)
+#define AMDM37X_DISPC_CONFIG_TCKDIGENABLE_FLAG  (1 << 12)
+#define AMDM37X_DISPC_CONFIG_TCKDIGSELECTION_FLAG  (1 << 13)
+#define AMDM37X_DISPC_CONFIG_FIFOMERGE_FLAG  (1 << 14)
+#define AMDM37X_DISPC_CONFIG_CPR_FLAG  (1 << 15)
+#define AMDM37X_DISPC_CONFIG_FIFOHANDCHECK_FLAG  (1 << 16)
+#define AMDM37X_DISPC_CONFIG_FIFOFILLING_FLAG  (1 << 17)
+#define AMDM37X_DISPC_CONFIG_LCDPALPHABLENDERENABLDE_FLAG  (1 << 18)
+#define AMDM37X_DISPC_CONFIG_TVALPHABLENDERENABLE_FLAG  (1 << 19)
+
+	PADD32[1];
+	ioport32_t default_color[2];
+	ioport32_t trans_color[2];
+#define AMDM37X_DISPC_COLOR_MASK 0xffffff
+
+	const ioport32_t line_status;
+	ioport32_t line_number;
+#define AMDM37X_DISPC_LINE_NUMBER_MASK 0x3ff
+
+	ioport32_t timing_h;
+#define AMDM37X_DISPC_TIMING_H_HSW_MASK 0xff
+#define AMDM37X_DISPC_TIMING_H_HSW_SHIFT 0
+#define AMDM37X_DISPC_TIMING_H_HFP_MASK 0xfff
+#define AMDM37X_DISPC_TIMING_H_HFP_SHIFT 8
+#define AMDM37X_DISPC_TIMING_H_HBP_MASK 0xfff
+#define AMDM37X_DISPC_TIMING_H_HBP_SHIFT 20
+
+	ioport32_t timing_v;
+#define AMDM37X_DISPC_TIMING_V_VSW_MASK 0xff
+#define AMDM37X_DISPC_TIMING_V_VSW_SHIFT 0
+#define AMDM37X_DISPC_TIMING_V_VFP_MASK 0xfff
+#define AMDM37X_DISPC_TIMING_V_VFP_SHIFT 8
+#define AMDM37X_DISPC_TIMING_V_VBP_MASK 0xfff
+#define AMDM37X_DISPC_TIMING_V_VBP_SHIFT 20
+
+	ioport32_t pol_freq;
+#define AMDM37X_DISPC_POL_FREQ_ACB_MASK  0xff
+#define AMDM37X_DISPC_POL_FREQ_ACB_SHIFT 0
+#define AMDM37X_DISPC_POL_FREQ_ACBI_MASK  0xf
+#define AMDM37X_DISPC_POL_FREQ_ACBI_SHIFT 8
+#define AMDM37X_DISPC_POL_FREQ_IVS_FLAG  (1 << 12)
+#define AMDM37X_DISPC_POL_FREQ_IHS_FLAG  (1 << 13)
+#define AMDM37X_DISPC_POL_FREQ_IPC_FLAG  (1 << 14)
+#define AMDM37X_DISPC_POL_FREQ_IEO_FLAG  (1 << 15)
+#define AMDM37X_DISPC_POL_FREQ_RF_FLAG  (1 << 16)
+#define AMDM37X_DISPC_POL_FREQ_ONOFF_FLAG  (1 << 17)
+
+	ioport32_t divisor;
+#define AMDM37X_DISPC_DIVISOR_PCD_MASK  0xff
+#define AMDM37X_DISPC_DIVISOR_PCD_SHIFT  0
+#define AMDM37X_DISPC_DIVISOR_LCD_MASK  0xff
+#define AMDM37X_DISPC_DIVISOR_LCD_SHIFT  16
+
+	ioport32_t global_alpha;
+#define AMDM37X_DISPC_GLOBAL_ALPHA_GFXGLOBALALPHA_MASK  0xff
+#define AMDM37X_DISPC_GLOBAL_ALPHA_GFXGLOBALALPHA_SHIFT  0
+#define AMDM37X_DISPC_GLOBAL_ALPHA_VID2GLOBALALPHA_MASK  0xff
+#define AMDM37X_DISPC_GLOBAL_ALPHA_VID2GLOBALALPHA_SHIFT  16
+
+	ioport32_t size_dig;
+	ioport32_t size_lcd;
+
+	struct {
+		ioport32_t ba[2];
+		ioport32_t position;
+#define AMDM37X_DISPC_GFX_POSITION_GFXPOSX_MASK  0x7ff
+#define AMDM37X_DISPC_GFX_POSITION_GFXPOSX_SHIFT  0
+#define AMDM37X_DISPC_GFX_POSITION_GFXPOSY_MASK  0x7ff
+#define AMDM37X_DISPC_GFX_POSITION_GFXPOSY_SHIFT  16
+
+		ioport32_t size;
+#define AMDM37X_DISPC_SIZE_WIDTH_MASK  0x7ff
+#define AMDM37X_DISPC_SIZE_WIDTH_SHIFT  0
+#define AMDM37X_DISPC_SIZE_HEIGHT_MASK  0x7ff
+#define AMDM37X_DISPC_SIZE_HEIGHT_SHIFT  16
+
+		PADD32[4];
+		ioport32_t attributes;
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_ENABLE_FLAG  (1 << 0)
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_MASK  0xf
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_SHIFT  1
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_ARGB16  0x5
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGB16  0x6
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGB24_32  0x8
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGB24  0x9
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_ARGB  0xc
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGBA  0xd
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_FORMAT_RGBX  0xe
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_REPLICATIONENABLE_FLAG  (1 << 5)
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXBURSTSIZE_MASK  0x3
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXBURSTSIZE_SHIFT  6
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXCHANNELOUT_FLAG  (1 << 8)
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXNIBBLEMODE_FLAG  (1 << 9)
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXENDIANNES_FLAG  (1 << 10)
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXFIFOPRELOAD_FLAG  (1 << 11)
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXROTATION_MASK  0x3
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXROTATION_SHIFT  12
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXARBITRATION_FLAG  (1 << 14)
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_GFXSELFREFRESH_FLAG  (1 << 15)
+#define AMDM37X_DISPC_GFX_ATTRIBUTES_PREMULTIALPHA_FLAG  (1 << 28)
+
+
+		ioport32_t fifo_threshold;
+		const ioport32_t fifo_size_status;
+		ioport32_t row_inc;
+		ioport32_t pixel_inc;
+		ioport32_t window_skip;
+		ioport32_t table_ba;
+	} gfx;
+
+	struct {
+		ioport32_t ba[2];
+		ioport32_t position;
+		ioport32_t size;
+		ioport32_t attributes;
+		ioport32_t fifo_threshold;
+		const ioport32_t fifo_size_status;
+		ioport32_t row_inc;
+		ioport32_t pixel_inc;
+		ioport32_t fir;
+		ioport32_t picture_size;
+		ioport32_t accui[2];
+		struct {
+			ioport32_t hi;
+			ioport32_t hvi;
+		} fir_coef[8];
+		ioport32_t conv_coef[5];
+		PADD32[2];
+	} vid[2];
+	/* 0x1d4 */
+	ioport32_t data_cycle[3];
+	/* 0x1e0 */
+	ioport32_t vid_fir_coef_v[8];
+	/* 0x200 */
+	PADD32[8];
+	/* 0x220 */
+	ioport32_t cpr_coef_r;
+	ioport32_t cpr_coef_g;
+	ioport32_t cpr_coef_b;
+	ioport32_t gfx_preload;
+
+	/* 0x230 */
+	ioport32_t vid_preload[2];
+
+} amdm37x_dispc_regs_t;
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/fb/amdm37x_dispc/main.c
===================================================================
--- uspace/drv/fb/amdm37x_dispc/main.c	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
+++ uspace/drv/fb/amdm37x_dispc/main.c	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2013 Jan Vesely
+ * Copyright (c) 2011 Petr Koupy
+ * 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 amdm37x
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <ddf/log.h>
+#include <errno.h>
+#include <str_error.h>
+#include <stdio.h>
+#include <ops/graph_dev.h>
+#include <graph.h>
+
+#include "amdm37x_dispc.h"
+
+#define NAME  "amdm37x_dispc"
+
+static graph_dev_ops_t graph_vsl_dev_ops = {
+	.connect = (connect_func) &graph_visualizer_connection
+};
+
+static ddf_dev_ops_t graph_fun_ops = {
+	.interfaces[GRAPH_DEV_IFACE] = &graph_vsl_dev_ops
+};
+
+static int amdm37x_dispc_dev_add(ddf_dev_t *dev)
+{
+	assert(dev);
+	/* Visualizer part */
+	ddf_fun_t *fun = ddf_fun_create(dev, fun_exposed, "viz");
+	if (!fun) {
+		ddf_log_error("Failed to create visualizer function\n");
+		return ENOMEM;
+	}
+
+	visualizer_t *vis = ddf_fun_data_alloc(fun, sizeof(visualizer_t));
+	if (!vis) {
+		ddf_log_error("Failed to allocate visualizer structure\n");
+		ddf_fun_destroy(fun);
+		return ENOMEM;
+	}
+
+	graph_init_visualizer(vis);
+	vis->reg_svc_handle = ddf_fun_get_handle(fun);
+
+	ddf_fun_set_ops(fun, &graph_fun_ops);
+	/* Hw part */
+	amdm37x_dispc_t *dispc =
+	    ddf_dev_data_alloc(dev, sizeof(amdm37x_dispc_t));
+	if (!dispc) {
+		ddf_log_error("Failed to allocate dispc structure\n");
+		ddf_fun_destroy(fun);
+		return ENOMEM;
+	}
+
+	int ret = amdm37x_dispc_init(dispc, vis);
+	if (ret != EOK) {
+		ddf_log_error("Failed to init dispc: %s\n", str_error(ret));
+		ddf_fun_destroy(fun);
+		return ret;
+	}
+
+	/* Report to devman */
+	ret = ddf_fun_bind(fun);
+	if (ret != EOK) {
+		ddf_log_error("Failed to bind function: %s\n", str_error(ret));
+		amdm37x_dispc_fini(dispc);
+		ddf_fun_destroy(fun);
+		return ret;
+	}
+	ddf_fun_add_to_category(fun, "visualizer");
+
+	ddf_log_note("Added device `%s'\n", ddf_dev_get_name(dev));
+	return EOK;
+}
+
+static driver_ops_t amdm37x_dispc_driver_ops = {
+	.dev_add = amdm37x_dispc_dev_add,
+};
+
+static driver_t amdm37x_dispc_driver = {
+	.name = NAME,
+	.driver_ops = &amdm37x_dispc_driver_ops
+};
+
+int main(int argc, char *argv[])
+{
+	printf("%s: HelenOS AM/DM37x framebuffer driver\n", NAME);
+	ddf_log_init(NAME);
+	return ddf_driver_main(&amdm37x_dispc_driver);
+}
+
+/** @}
+ */
Index: uspace/drv/infrastructure/rootamdm37x/rootamdm37x.c
===================================================================
--- uspace/drv/infrastructure/rootamdm37x/rootamdm37x.c	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ uspace/drv/infrastructure/rootamdm37x/rootamdm37x.c	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -195,4 +195,7 @@
 		ddf_msg(LVL_ERROR, "Failed to add EHCI function for "
 		    "BeagleBoard-xM platform.");
+	if (rootamdm37x_add_fun(dev, "dispc", "amdm37x&dispc", &ehci) != EOK)
+		ddf_msg(LVL_ERROR, "Failed to add dispc function for "
+		    "BeagleBoard-xM platform.");
 
 	return EOK;
Index: uspace/lib/c/arch/arm32/Makefile.common
===================================================================
--- uspace/lib/c/arch/arm32/Makefile.common	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ uspace/lib/c/arch/arm32/Makefile.common	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -28,5 +28,5 @@
 #
 
-GCC_CFLAGS += -ffixed-r9 -mtp=soft -fno-omit-frame-pointer -mapcs-frame -march=$(subst _,-,$(PROCESSOR))
+GCC_CFLAGS += -ffixed-r9 -mtp=soft -fno-omit-frame-pointer -mapcs-frame -march=$(subst _,-,$(PROCESSOR_ARCH))
 
 ifeq ($(CONFIG_FPU),y)
Index: uspace/lib/c/arch/arm32/include/cp15.h
===================================================================
--- uspace/lib/c/arch/arm32/include/cp15.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
+++ uspace/lib/c/arch/arm32/include/cp15.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/arm32/include/cp15.h
Index: uspace/lib/drv/include/ddf/log.h
===================================================================
--- uspace/lib/drv/include/ddf/log.h	(revision 5e761f3f5b0673834135c4074edbe2f0fd8ae9c3)
+++ uspace/lib/drv/include/ddf/log.h	(revision b1011daeaf9246e478ae5a898c0c81350f86f286)
@@ -44,4 +44,11 @@
     size_t);
 
+#define ddf_log_fatal(msg...) ddf_msg(LVL_FATAL, msg)
+#define ddf_log_error(msg...) ddf_msg(LVL_ERROR, msg)
+#define ddf_log_warning(msg...) ddf_msg(LVL_WARN, msg)
+#define ddf_log_note(msg...) ddf_msg(LVL_NOTE, msg)
+#define ddf_log_debug(msg...) ddf_msg(LVL_DEBUG, msg)
+#define ddf_log_verbose(msg...) ddf_msg(LVL_DEBUG2, msg)
+
 #endif
 
