summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bootloader/SOURCES3
-rw-r--r--bootloader/rk27xx.c45
-rw-r--r--firmware/SOURCES24
-rw-r--r--firmware/export/config.h13
-rw-r--r--firmware/export/config/rk27generic.h175
-rw-r--r--firmware/export/cpu.h3
-rw-r--r--firmware/export/i2c-rk27xx.h32
-rw-r--r--firmware/export/rk27xx.h1022
-rw-r--r--firmware/target/arm/rk27xx/adc-rk27xx.c47
-rw-r--r--firmware/target/arm/rk27xx/adc-target.h33
-rw-r--r--firmware/target/arm/rk27xx/ata-nand-rk27xx.c118
-rw-r--r--firmware/target/arm/rk27xx/backlight-rk27xx.c86
-rw-r--r--firmware/target/arm/rk27xx/backlight-target.h29
-rw-r--r--firmware/target/arm/rk27xx/boot.lds81
-rw-r--r--firmware/target/arm/rk27xx/crt0.S209
-rw-r--r--firmware/target/arm/rk27xx/ftl-rk27xx.c56
-rw-r--r--firmware/target/arm/rk27xx/ftl-target.h45
-rw-r--r--firmware/target/arm/rk27xx/i2c-rk27xx.c242
-rw-r--r--firmware/target/arm/rk27xx/kernel-rk27xx.c54
-rw-r--r--firmware/target/arm/rk27xx/lcd-rk27xx.c304
-rw-r--r--firmware/target/arm/rk27xx/nand-target.h58
-rw-r--r--firmware/target/arm/rk27xx/rk27generic/button-rk27generic.c39
-rw-r--r--firmware/target/arm/rk27xx/rk27generic/button-target.h51
-rw-r--r--firmware/target/arm/rk27xx/sd-rk27xx.c719
-rw-r--r--firmware/target/arm/rk27xx/spfd5420a.h107
-rw-r--r--firmware/target/arm/rk27xx/system-rk27xx.c164
-rw-r--r--firmware/target/arm/rk27xx/system-target.h44
-rw-r--r--firmware/target/arm/rk27xx/timer-rk27xx.c74
-rw-r--r--firmware/target/arm/thread-arm.c2
-rwxr-xr-xtools/configure34
-rw-r--r--tools/scramble.c4
31 files changed, 3910 insertions, 7 deletions
diff --git a/bootloader/SOURCES b/bootloader/SOURCES
index 3e173386e7..9448515a58 100644
--- a/bootloader/SOURCES
+++ b/bootloader/SOURCES
@@ -69,4 +69,7 @@ main-pp.c
show_logo.c
#elif defined(MPIO_HD200) || defined(MPIO_HD300)
mpio_hd200_hd300.c
+#elif defined(RK27_GENERIC)
+rk27xx.c
+show_logo.c
#endif
diff --git a/bootloader/rk27xx.c b/bootloader/rk27xx.c
new file mode 100644
index 0000000000..37778db6dc
--- /dev/null
+++ b/bootloader/rk27xx.c
@@ -0,0 +1,45 @@
+#include "config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "inttypes.h"
+#include "string.h"
+#include "cpu.h"
+#include "system.h"
+#include "lcd.h"
+#include "kernel.h"
+#include "thread.h"
+#include "backlight.h"
+#include "backlight-target.h"
+#include "font.h"
+#include "common.h"
+#include "version.h"
+
+extern int show_logo( void );
+void main(void)
+{
+
+ _backlight_init();
+
+ system_init();
+ kernel_init();
+ enable_irq();
+
+ lcd_init_device();
+ _backlight_on();
+ font_init();
+ lcd_setfont(FONT_SYSFIXED);
+
+ show_logo();
+ sleep(HZ*2);
+
+ while(1)
+ {
+ reset_screen();
+ printf("GPIOA: 0x%0x", GPIO_PADR);
+ printf("GPIOB: 0x%0x", GPIO_PBDR);
+ printf("GPIOC: 0x%0x", GPIO_PCDR);
+ printf("GPIOD: 0x%0x", GPIO_PDDR);
+ sleep(HZ/10);
+ }
+}
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 6d4ef9fe2b..eee0c864eb 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -210,6 +210,9 @@ target/arm/ata-nand-telechips.c
#if (CONFIG_STORAGE & STORAGE_NAND) && (CONFIG_NAND == NAND_SAMSUNG)
target/arm/s5l8700/ata-nand-s5l8700.c
#endif
+#if (CONFIG_STORAGE & STORAGE_NAND) && (CONFIG_NAND == NAND_RK27XX)
+target/arm/rk27xx/ata-nand-rk27xx.c
+#endif
#if (CONFIG_STORAGE & STORAGE_ATA) && !defined(IPOD_6G)
drivers/ata.c
#endif
@@ -473,6 +476,8 @@ target/arm/i2c-telechips.c
target/arm/s5l8700/i2c-s5l8700.c
#elif CONFIG_I2C == I2C_S5L8702
target/arm/s5l8702/i2c-s5l8702.c
+#elif CONFIG_I2C == I2C_RK27XX
+target/arm/rk27xx/i2c-rk27xx.c
#endif
#if CONFIG_CPU == PNX0101
@@ -562,6 +567,8 @@ target/arm/s5l8700/crt0.S
target/arm/s5l8702/crt0.S
#elif CONFIG_CPU==IMX233
target/arm/imx233/crt0.S
+#elif CONFIG_CPU==RK27XX
+target/arm/rk27xx/crt0.S
#elif defined(CPU_ARM)
target/arm/crt0.S
#endif /* defined(CPU_*) */
@@ -1605,6 +1612,23 @@ target/arm/s5l8702/ipod6g/adc-ipod6g.c
#endif
#ifndef SIMULATOR
+#if CONFIG_CPU == RK27XX
+target/arm/rk27xx/kernel-rk27xx.c
+target/arm/rk27xx/system-rk27xx.c
+target/arm/rk27xx/timer-rk27xx.c
+target/arm/rk27xx/backlight-rk27xx.c
+target/arm/rk27xx/lcd-rk27xx.c
+target/arm/rk27xx/adc-rk27xx.c
+target/arm/rk27xx/sd-rk27xx.c
+target/arm/rk27xx/ftl-rk27xx.c
+#endif
+
+#if defined(RK27_GENERIC)
+target/arm/rk27xx/rk27generic/button-rk27generic.c
+#endif
+#endif
+
+#ifndef SIMULATOR
#if CONFIG_CPU == JZ4732
target/mips/ingenic_jz47xx/ata-nand-jz4740.c
target/mips/ingenic_jz47xx/ata-sd-jz4740.c
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 003f68335a..2c7c6e89db 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -75,6 +75,7 @@
#define AT91SAM9260 9260
#define AS3525v2 35252
#define IMX233 233
+#define RK27XX 2700
/* platforms
* bit fields to allow PLATFORM_HOSTED to be OR'ed e.g. with a
@@ -222,6 +223,7 @@
#define LCD_VIBE500 39 /* as used by the Packard Bell Vibe 500 */
#define LCD_IPOD6G 40 /* as used by the iPod Nano 2nd Generation */
#define LCD_FUZEPLUS 41
+#define LCD_SPFD5420A 42 /* rk27xx */
/* LCD_PIXELFORMAT */
#define HORIZONTAL_PACKING 1
@@ -260,6 +262,7 @@ Lyre prototype 1 */
#define I2C_AS3525 15
#define I2C_S5L8702 16 /* Same as S5L8700, but with two channels */
#define I2C_IMX233 17
+#define I2C_RK27XX 18
/* CONFIG_LED */
#define LED_REAL 1 /* SW controlled LED (Archos recorders, player) */
@@ -271,6 +274,7 @@ Lyre prototype 1 */
#define NAND_TCC 2
#define NAND_SAMSUNG 3
#define NAND_CC 4 /* ChinaChip */
+#define NAND_RK27XX 5
/* CONFIG_RTC */
#define RTC_M41ST84W 1 /* Archos Recorder */
@@ -448,6 +452,8 @@ Lyre prototype 1 */
#include "config/mpiohd200.h"
#elif defined(MPIO_HD300)
#include "config/mpiohd300.h"
+#elif defined(RK27_GENERIC)
+#include "config/rk27generic.h"
#elif defined(SDLAPP)
#include "config/sdlapp.h"
#elif defined(ANDROID)
@@ -533,8 +539,8 @@ Lyre prototype 1 */
#elif defined(CPU_TCC77X) || defined(CPU_TCC780X) || (CONFIG_CPU == DM320) \
|| (CONFIG_CPU == AT91SAM9260) || (CONFIG_CPU == AS3525v2) \
- || (CONFIG_CPU == S5L8702) || (CONFIG_PLATFORM & PLATFORM_ANDROID) \
- || (CONFIG_CPU == IMX233)
+ || (CONFIG_CPU == S5L8702) || (CONFIG_CPU == IMX233) \
+ || (CONFIG_CPU == RK27XX) ||(CONFIG_PLATFORM & PLATFORM_ANDROID)
#define CPU_ARM
#define ARM_ARCH 5 /* ARMv5 */
@@ -774,7 +780,8 @@ Lyre prototype 1 */
#if defined(HAVE_USBSTACK) || (CONFIG_CPU == JZ4732) \
|| (CONFIG_CPU == AS3525) || (CONFIG_CPU == AS3525v2) \
|| defined(CPU_S5L870X) || (CONFIG_CPU == S3C2440) \
- || defined(APPLICATION) || (CONFIG_CPU == PP5002)
+ || defined(APPLICATION) || (CONFIG_CPU == PP5002) \
+ || (CONFIG_CPU == RK27XX)
#define HAVE_SEMAPHORE_OBJECTS
#endif
diff --git a/firmware/export/config/rk27generic.h b/firmware/export/config/rk27generic.h
new file mode 100644
index 0000000000..5427d1fed4
--- /dev/null
+++ b/firmware/export/config/rk27generic.h
@@ -0,0 +1,175 @@
+/*
+ * This config file is for Rockchip rk27xx reference design
+ */
+#define TARGET_TREE /* this target is using the target tree system */
+
+/* For Rolo and boot loader */
+#define MODEL_NUMBER 78
+
+#define MODEL_NAME "Rockchip 27xx generic"
+
+/* define this if you have recording possibility */
+/* #define HAVE_RECORDING */
+
+/* Define bitmask of input sources - recordable bitmask can be defined
+ explicitly if different */
+#define INPUT_SRC_CAPS (SRC_CAP_LINEIN)
+
+/* define the bitmask of hardware sample rates */
+#define HW_SAMPR_CAPS (SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11 \
+ | SAMPR_CAP_48 | SAMPR_CAP_24 | SAMPR_CAP_12 \
+ | SAMPR_CAP_32 | SAMPR_CAP_16 | SAMPR_CAP_8)
+
+/* define the bitmask of recording sample rates */
+#define REC_SAMPR_CAPS (SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11 \
+ | SAMPR_CAP_48 | SAMPR_CAP_24 | SAMPR_CAP_12 \
+ | SAMPR_CAP_32 | SAMPR_CAP_16 | SAMPR_CAP_8)
+
+/* define this if you have a bitmap LCD display */
+#define HAVE_LCD_BITMAP
+
+/* define this if you can flip your LCD */
+/* #define HAVE_LCD_FLIP */
+
+/* define this if you have a colour LCD */
+#define HAVE_LCD_COLOR
+
+/* define this if you want album art for this target */
+#define HAVE_ALBUMART
+
+/* define this to enable bitmap scaling */
+#define HAVE_BMP_SCALING
+
+/* define this to enable JPEG decoding */
+#define HAVE_JPEG
+
+/* define this if you can invert the colours on your LCD */
+/* #define HAVE_LCD_INVERT */
+
+/* define this if you have access to the quickscreen */
+#define HAVE_QUICKSCREEN
+
+/* define this if you have access to the pitchscreen */
+#define HAVE_PITCHSCREEN
+
+/* define this if you would like tagcache to build on this target */
+#define HAVE_TAGCACHE
+
+/* define this if you have a flash memory storage */
+#define HAVE_FLASH_STORAGE
+
+#define CONFIG_STORAGE (STORAGE_SD | STORAGE_NAND)
+
+#define CONFIG_NAND NAND_RK27XX
+
+/* commented for now */
+/* #define HAVE_HOTSWAP */
+
+#define NUM_DRIVES 2
+#define SECTOR_SIZE 512
+
+/* for small(ish) SD cards */
+#define HAVE_FAT16SUPPORT
+
+/* LCD dimensions */
+#define LCD_WIDTH 400
+#define LCD_HEIGHT 240
+#define LCD_DEPTH 16 /* pseudo 262.144 colors */
+#define LCD_PIXELFORMAT RGB565 /* rgb565 */
+
+/* Define this if the LCD can shut down */
+/* #define HAVE_LCD_SHUTDOWN */
+
+/* Define this if your LCD can be enabled/disabled */
+/* #define HAVE_LCD_ENABLE */
+
+/* Define this if your LCD can be put to sleep. HAVE_LCD_ENABLE
+ should be defined as well. */
+#ifndef BOOTLOADER
+/* TODO: #define HAVE_LCD_SLEEP */
+/* TODO: #define HAVE_LCD_SLEEP_SETTING */
+#endif
+
+#define CONFIG_KEYPAD IPOD_4G_PAD
+
+/* Define this to enable morse code input */
+#define HAVE_MORSE_INPUT
+
+/* Define this if you do software codec */
+#define CONFIG_CODEC SWCODEC
+
+/* define this if you have a real-time clock */
+/* #define CONFIG_RTC RTC_NANO2G */
+
+/* Define if the device can wake from an RTC alarm */
+/* #define HAVE_RTC_ALARM */
+
+#define CONFIG_LCD LCD_SPFD5420A
+
+/* Define the type of audio codec */
+/* #define HAVE_RK27XX_CODEC */
+
+/* #define HAVE_PCM_DMA_ADDRESS */
+
+/* Define this for LCD backlight available */
+#define HAVE_BACKLIGHT
+
+/* Doesn't work so comment it out for now */
+/* #define HAVE_BACKLIGHT_BRIGHTNESS */
+
+/* Define this if you have a software controlled poweroff */
+#define HAVE_SW_POWEROFF
+
+/* The number of bytes reserved for loadable codecs */
+#define CODEC_SIZE 0x100000
+
+/* The number of bytes reserved for loadable plugins */
+#define PLUGIN_BUFFER_SIZE 0x80000
+
+/* TODO: Figure out real values */
+#define BATTERY_CAPACITY_DEFAULT 400 /* default battery capacity */
+#define BATTERY_CAPACITY_MIN 300 /* min. capacity selectable */
+#define BATTERY_CAPACITY_MAX 500 /* max. capacity selectable */
+#define BATTERY_CAPACITY_INC 10 /* capacity increment */
+#define BATTERY_TYPES_COUNT 1 /* only one type */
+
+/* Hardware controlled charging with monitoring */
+#define CONFIG_CHARGING CHARGING_MONITOR
+
+/* define current usage levels */
+/* TODO: #define CURRENT_NORMAL
+ * TODO: #define CURRENT_BACKLIGHT 23
+ */
+
+/* define this if the unit can be powered or charged via USB */
+#define HAVE_USB_POWER
+
+/* Define this if your LCD can set contrast */
+/* #define HAVE_LCD_CONTRAST */
+
+/* The exact type of CPU */
+#define CONFIG_CPU RK27XX
+
+/* I2C interface */
+#define CONFIG_I2C I2C_RK27XX
+
+/* Define this to the CPU frequency */
+#define CPU_FREQ 200000000
+
+/* define this if the hardware can be powered off while charging */
+#define HAVE_POWEROFF_WHILE_CHARGING
+
+/* Offset ( in the firmware file's header ) to the file CRC */
+#define FIRMWARE_OFFSET_FILE_CRC 0
+
+/* Offset ( in the firmware file's header ) to the real data */
+#define FIRMWARE_OFFSET_FILE_DATA 8
+
+#define STORAGE_NEEDS_ALIGN
+
+/* Define this if you have adjustable CPU frequency */
+/* #define HAVE_ADJUSTABLE_CPU_FREQ */
+
+#define BOOTFILE_EXT "rk27"
+#define BOOTFILE "rockbox." BOOTFILE_EXT
+#define BOOTDIR "/.rockbox"
diff --git a/firmware/export/cpu.h b/firmware/export/cpu.h
index 777e36f62d..7405319822 100644
--- a/firmware/export/cpu.h
+++ b/firmware/export/cpu.h
@@ -77,3 +77,6 @@
#if CONFIG_CPU == IMX233
#include "imx233.h"
#endif
+#if CONFIG_CPU == RK27XX
+#include "rk27xx.h"
+#endif
diff --git a/firmware/export/i2c-rk27xx.h b/firmware/export/i2c-rk27xx.h
new file mode 100644
index 0000000000..96baf566a7
--- /dev/null
+++ b/firmware/export/i2c-rk27xx.h
@@ -0,0 +1,32 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 by Bertrik Sikken
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef _I2C_RK27XX_H
+#define _I2C_RK27XX_H
+
+#include "config.h"
+
+void i2c_init(void);
+int i2c_write(unsigned char slave, int address, int len, const unsigned char *data);
+int i2c_read(unsigned char slave, int address, int len, unsigned char *data);
+
+#endif /* _I2C_RK27XX_H */
+
diff --git a/firmware/export/rk27xx.h b/firmware/export/rk27xx.h
new file mode 100644
index 0000000000..a5cd396a33
--- /dev/null
+++ b/firmware/export/rk27xx.h
@@ -0,0 +1,1022 @@
+/* ARM part only for now */
+#define AHB_SRAM 0x00000000
+
+#define ARM_BUS0_BASE 0x18000000
+#define ARM_BUS1_BASE 0x18400000
+
+#define FLASH_BANK0 0x10000000
+#define FLASH_BANK1 0x11000000
+
+/* Timers */
+#define APB0_TIMER (ARM_BUS0_BASE + 0x00000000)
+#define TMR0LR (*(volatile unsigned long *)(APB0_TIMER + 0x00))
+#define TMR0CVR (*(volatile unsigned long *)(APB0_TIMER + 0x04))
+#define TMR0CON (*(volatile unsigned long *)(APB0_TIMER + 0x08))
+
+#define TMR1LR (*(volatile unsigned long *)(APB0_TIMER + 0x10))
+#define TMR1CVR (*(volatile unsigned long *)(APB0_TIMER + 0x14))
+#define TMR1CON (*(volatile unsigned long *)(APB0_TIMER + 0x18))
+
+#define TMR2LR (*(volatile unsigned long *)(APB0_TIMER + 0x20))
+#define TMR2CVR (*(volatile unsigned long *)(APB0_TIMER + 0x24))
+#define TMR2CON (*(volatile unsigned long *)(APB0_TIMER + 0x28))
+
+/* UART0 */
+#define APB0_UART0 (ARM_BUS0_BASE + 0x00004000)
+#define UART0_RBR (*(volatile unsigned long *)(APB0_UART0 + 0x00))
+#define UART0_THR (*(volatile unsigned long *)(APB0_UART0 + 0x00))
+#define UART0_DLL (*(volatile unsigned long *)(APB0_UART0 + 0x00))
+#define UART0_DLH (*(volatile unsigned long *)(APB0_UART0 + 0x04))
+#define UART0_IER (*(volatile unsigned long *)(APB0_UART0 + 0x04))
+#define UART0_IIR (*(volatile unsigned long *)(APB0_UART0 + 0x08))
+#define UART0_FCR (*(volatile unsigned long *)(APB0_UART0 + 0x08))
+#define UART0_LCR (*(volatile unsigned long *)(APB0_UART0 + 0x0C))
+#define UART0_MCR (*(volatile unsigned long *)(APB0_UART0 + 0x10))
+#define UART0_LSR (*(volatile unsigned long *)(APB0_UART0 + 0x14))
+#define UART0_MSR (*(volatile unsigned long *)(APB0_UART0 + 0x18))
+
+/* UART1 */
+#define APB0_UART1 (ARM_BUS0_BASE + 0x00008000)
+#define UART1_RBR (*(volatile unsigned long *)(APB0_UART1 + 0x00))
+#define UART1_THR (*(volatile unsigned long *)(APB0_UART1 + 0x00))
+#define UART1_DLL (*(volatile unsigned long *)(APB0_UART1 + 0x00))
+#define UART1_DLH (*(volatile unsigned long *)(APB0_UART1 + 0x04))
+#define UART1_IER (*(volatile unsigned long *)(APB0_UART1 + 0x04))
+#define UART1_IIR (*(volatile unsigned long *)(APB0_UART1 + 0x08))
+#define UART1_FCR (*(volatile unsigned long *)(APB0_UART1 + 0x08))
+#define UART1_LCR (*(volatile unsigned long *)(APB0_UART1 + 0x0C))
+#define UART1_MCR (*(volatile unsigned long *)(APB0_UART1 + 0x10))
+#define UART1_LSR (*(volatile unsigned long *)(APB0_UART1 + 0x14))
+#define UART1_MSR (*(volatile unsigned long *)(APB0_UART1 + 0x18))
+
+/* GPIO ports A,B,C,D */
+#define APB0_GPIO0 (ARM_BUS0_BASE + 0x0000C000)
+#define GPIO_PADR (*(volatile unsigned long *)(APB0_GPIO0 + 0x00))
+#define GPIO_PACON (*(volatile unsigned long *)(APB0_GPIO0 + 0x04))
+#define GPIO_PBDR (*(volatile unsigned long *)(APB0_GPIO0 + 0x08))
+#define GPIO_PBCON (*(volatile unsigned long *)(APB0_GPIO0 + 0x0C))
+#define GPIO_PCDR (*(volatile unsigned long *)(APB0_GPIO0 + 0x10))
+#define GPIO_PCCON (*(volatile unsigned long *)(APB0_GPIO0 + 0x14))
+#define GPIO_PDDR (*(volatile unsigned long *)(APB0_GPIO0 + 0x18))
+#define GPIO_PDCON (*(volatile unsigned long *)(APB0_GPIO0 + 0x1C))
+#define GPIO_TEST (*(volatile unsigned long *)(APB0_GPIO0 + 0x20))
+#define GPIO_IEA (*(volatile unsigned long *)(APB0_GPIO0 + 0x24))
+#define GPIO_IEB (*(volatile unsigned long *)(APB0_GPIO0 + 0x28))
+#define GPIO_IEC (*(volatile unsigned long *)(APB0_GPIO0 + 0x2C))
+#define GPIO_IED (*(volatile unsigned long *)(APB0_GPIO0 + 0x30))
+#define GPIO_ISA (*(volatile unsigned long *)(APB0_GPIO0 + 0x34))
+#define GPIO_ISB (*(volatile unsigned long *)(APB0_GPIO0 + 0x38))
+#define GPIO_ISC (*(volatile unsigned long *)(APB0_GPIO0 + 0x3C))
+#define GPIO_ISD (*(volatile unsigned long *)(APB0_GPIO0 + 0x40))
+#define GPIO_IBEA (*(volatile unsigned long *)(APB0_GPIO0 + 0x44))
+#define GPIO_IBEB (*(volatile unsigned long *)(APB0_GPIO0 + 0x48))
+#define GPIO_IBEC (*(volatile unsigned long *)(APB0_GPIO0 + 0x4C))
+#define GPIO_IBED (*(volatile unsigned long *)(APB0_GPIO0 + 0x50))
+#define GPIO_IEVA (*(volatile unsigned long *)(APB0_GPIO0 + 0x54))
+#define GPIO_IEVB (*(volatile unsigned long *)(APB0_GPIO0 + 0x58))
+#define GPIO_IEVC (*(volatile unsigned long *)(APB0_GPIO0 + 0x5C))
+#define GPIO_IEVD (*(volatile unsigned long *)(APB0_GPIO0 + 0x60))
+#define GPIO_ICA (*(volatile unsigned long *)(APB0_GPIO0 + 0x64))
+#define GPIO_ICB (*(volatile unsigned long *)(APB0_GPIO0 + 0x68))
+#define GPIO_ICC (*(volatile unsigned long *)(APB0_GPIO0 + 0x6C))
+#define GPIO_ICD (*(volatile unsigned long *)(APB0_GPIO0 + 0x70))
+#define GPIO_ISR (*(volatile unsigned long *)(APB0_GPIO0 + 0x74))
+
+/* Watchdog */
+#define APB0_WDT (ARM_BUS0_BASE + 0x00010000)
+#define WDTLR (*(volatile unsigned long *)(APB0_WDT + 0x00))
+#define WDTCVR (*(volatile unsigned long *)(APB0_WDT + 0x04))
+#define WDTCON (*(volatile unsigned long *)(APB0_WDT + 0x08))
+
+/* RTC module documentation missing */
+#define APB0_RTC (ARM_BUS0_BASE + 0x00014000)
+#define RTC_TIME (*(volatile unsigned long *)(APB0_RTC + 0x00))
+#define RTC_DATE (*(volatile unsigned long *)(APB0_RTC + 0x04))
+#define RTC_TALARM (*(volatile unsigned long *)(APB0_RTC + 0x08))
+#define RTC_DALARM (*(volatile unsigned long *)(APB0_RTC + 0x0C))
+#define RTC_CTRL (*(volatile unsigned long *)(APB0_RTC + 0x10))
+#define RTC_RESET (*(volatile unsigned long *)(APB0_RTC + 0x14))
+#define RTC_PWOFF (*(volatile unsigned long *)(APB0_RTC + 0x18))
+#define RTC_PWFAIL (*(volatile unsigned long *)(APB0_RTC + 0x1C))
+
+/* SPI */
+#define APB0_SPI (ARM_BUS0_BASE + 0x00018000)
+#define SPI_TXR (*(volatile unsigned long *)(APB0_SPI + 0x00))
+#define SPI_RXR (*(volatile unsigned long *)(APB0_SPI + 0x00))
+#define SPI_IER (*(volatile unsigned long *)(APB0_SPI + 0x04))
+#define SPI_FCR (*(volatile unsigned long *)(APB0_SPI + 0x08))
+#define SPI_FWCR (*(volatile unsigned long *)(APB0_SPI + 0x0C))
+#define SPI_DLYCR (*(volatile unsigned long *)(APB0_SPI + 0x10))
+#define SPI_TXCR (*(volatile unsigned long *)(APB0_SPI + 0x14))
+#define SPI_RXCR (*(volatile unsigned long *)(APB0_SPI + 0x18))
+#define SPI_SSCR (*(volatile unsigned long *)(APB0_SPI + 0x1C))
+#define SPI_ISR (*(volatile unsigned long *)(APB0_SPI + 0x20))
+
+/* SCU module */
+#define APB0_SCU (ARM_BUS0_BASE + 0x0001C000)
+#define SCU_ID (*(volatile unsigned long *)(APB0_SCU + 0x00))
+#define SCU_REMAP (*(volatile unsigned long *)(APB0_SCU + 0x04))
+#define SCU_PLLCON1 (*(volatile unsigned long *)(APB0_SCU + 0x08))
+#define SCU_PLLCON2 (*(volatile unsigned long *)(APB0_SCU + 0x0C))
+#define SCU_PLLCON3 (*(volatile unsigned long *)(APB0_SCU + 0x10))
+#define SCU_DIVCON1 (*(volatile unsigned long *)(APB0_SCU + 0x14))
+#define SCU_CLKCFG (*(volatile unsigned long *)(APB0_SCU + 0x18))
+#define SCU_RSTCFG (*(volatile unsigned long *)(APB0_SCU + 0x1C))
+#define SCU_PWM (*(volatile unsigned long *)(APB0_SCU + 0x20))
+#define SCU_CPUPD (*(volatile unsigned long *)(APB0_SCU + 0x24))
+#define SCU_CHIPCFG (*(volatile unsigned long *)(APB0_SCU + 0x28))
+#define SCU_STATUS (*(volatile unsigned long *)(APB0_SCU + 0x2C))
+#define SCU_IOMUXA_CON (*(volatile unsigned long *)(APB0_SCU + 0x30))
+/* 20 - 31 reserved */
+#define IOMUX_I2S_PAD (1<<19)
+#define IOMUX_I2S_CODEC (0<<19)
+#define IOMUX_I2C_PAD (1<<18)
+#define IOMUX_I2C_CODEC (0<<18)
+#define IOMUX_GPIO_B7 (2<<16)
+#define IOMUX_NAND_CS3 (1<<16)
+#define IOMUX_I2C_SDA (0<<16)
+#define IOMUX_GPIO_B6 (2<<14)
+#define IOMUX_NAND_CS2 (1<<14)
+#define IOMUX_I2C_SCL (0<<14)
+#define IOMUX_SPI (2<<12)
+#define IOMUX_SD (1<<12)
+#define IOMUX_GPIO_B05 (0<<12)
+#define IOMUX_LCD_VSYNC (1<<11)
+#define IOMUX_GPIO_A7 (0<<11)
+#define IOMUX_LCD_DEN (1<<10)
+#define IOMUX_GPIO_A6 (0<<10)
+#define IOMUX_NAND_CS1 (1<<9)
+#define IOMUX_GPIO_A5 (0<<9)
+#define IOMUX_LCD_D22 (1<<8)
+#define IOMUX_GPIO_A4 (0<<8)
+#define IOMUX_UART0_NRTS (2<<6)
+#define IOMUX_LCD_D20 (1<<6)
+#define IOMUX_GPIO_A3 (0<<6)
+#define IOMUX_UART0_NCTS (2<<4)
+#define IOMUX_LCD_D18 (1<<4)
+#define IOMUX_GPIO_A2 (0<<4)
+#define IOMUX_UART0_TXD (2<<2)
+#define IOMUX_LCD_D17 (1<<2)
+#define IOMUX_GPIO_A1 (0<<2)
+#define IOMUX_UART0_RXD (2<<0)
+#define IOMUX_LCD_D16 (1<<0)
+#define IOMUX_GPIO_A0 (0<<0)
+
+#define SCU_IOMUXB_CON (*(volatile unsigned long *)(APB0_SCU + 0x34))
+/* bits 31 - 23 reserved */
+#define IOMUX_HADC (1<<22)
+#define IOMUX_VIP (0<<22)
+#define IOMUX_SDRAM_CKE (1<<21)
+#define IOMUX_GPIO_D3 (0<<21)
+#define IOMUX_UHC_VBUS (1<<20)
+#define IOMUX_GPIO_F4 (0<<20)
+#define IOMUX_UHC_OCUR (1<<19)
+#define IOMUX_GPIO_F3 (0<<19)
+#define IOMUX_GPIO_F2 (1<<18)
+#define IOMUX_SDRAM_A12 (0<<18)
+#define IOMUX_GPIO_F1 (1<<17)
+#define IOMUX_SDRAM_A11 (0<<17)
+#define IOMUX_VIP_CLK (1<<16)
+#define IOMUX_GPIO_F0 (0<<16)
+#define IOMUX_LCD_D815 (1<<15)
+#define IOMUX_GPIO_E07 (0<<15)
+#define IOMUX_PWM3 (1<<14)
+#define IOMUX_GPIO_D7 (0<<14)
+#define IOMUX_PWM2 (1<<13)
+#define IOMUX_GPIO_D6 (0<<13)
+#define IOMUX_PWM1 (1<<12)
+#define IOMUX_GPIO_D5 (0<<12)
+#define IOMUX_PWM0 (1<<11)
+#define IOMUX_GPIO_D4 (0<<11)
+#define IOMUX_SD_WPA (1<<10)
+#define IOMUX_GPIO_D2 (0<<10)
+#define IOMUX_UART1_RXD (2<<8)
+#define IOMUX_SD_CDA (1<<8)
+#define IOMUX_GPIO_D1 (0<<8)
+#define IOMUX_UART1_TXD (2<<6)
+#define IOMUX_SD_PCA (1<<6)
+#define IOMUX_GPIO_D0 (0<<6)
+#define IOMUX_STMEM_CS1 (1<<5)
+#define IOMUX_GPIO_C7 (0<<5)
+#define IOMUX_I2S_CLK (1<<4)
+#define IOMUX_GPIO_C6 (0<<4)
+#define IOMUX_I2S_SDO (1<<3)
+#define IOMUX_GPIO_C5 (0<<3)
+#define IOMUX_I2S_SDI (1<<2)
+#define IOMUX_GPIO_C4 (0<<2)
+#define IOMUX_I2S_LRCK (1<<1)
+#define IOMUX_GPIO_C3 (0<<1)
+#define IOMUX_I2S_SCLK (1<<0)
+#define IOMUX_GPIO_C2 (0<<0)
+
+#define SCU_GPIOUPCON (*(volatile unsigned long *)(APB0_SCU + 0x38))
+#define SCU_DIVCON2 (*(volatile unsigned long *)(APB0_SCU + 0x3C))
+
+/* I2C controller */
+#define APB0_I2C (ARM_BUS0_BASE + 0x00020000)
+#define I2C_MTXR (*(volatile unsigned long *)(APB0_I2C + 0x00))
+#define I2C_MRXR (*(volatile unsigned long *)(APB0_I2C + 0x04))
+#define I2C_STXR (*(volatile unsigned long *)(APB0_I2C + 0x08))
+#define I2C_SRXR (*(volatile unsigned long *)(APB0_I2C + 0x0C))
+#define I2C_SADDR (*(volatile unsigned long *)(APB0_I2C + 0x10))
+#define I2C_IER (*(volatile unsigned long *)(APB0_I2C + 0x14))
+#define I2C_ISR (*(volatile unsigned long *)(APB0_I2C + 0x18))
+#define I2C_LCMR (*(volatile unsigned long *)(APB0_I2C + 0x1C))
+#define I2C_LSR (*(volatile unsigned long *)(APB0_I2C + 0x20))
+#define I2C_CONR (*(volatile unsigned long *)(APB0_I2C + 0x24))
+#define I2C_OPR (*(volatile unsigned long *)(APB0_I2C + 0x28))
+
+/* SD card controller */
+#define APB0_SD (ARM_BUS0_BASE + 0x00024000)
+#define MMU_CTRL (*(volatile unsigned long *)(APB0_SD + 0x00))
+#define MMU_BIG_ENDIAN (1<<12)
+#define MMU_DMA_START (1<<11)
+#define MMU_DMA_WRITE (1<<10)
+#define MMU_MMU0_BUFI (0<<9)
+#define MMU_MMU0_BUFII (1<<9)
+#define MMU_CPU_BUFI (0<<8)
+#define MMU_CPU_BUFII (1<<8)
+#define MMU_BUFII_RESET (1<<7)
+#define MMU_BUFII_END (1<<6)
+#define MMU_BUFII_BYTE (0<<4)
+#define MMU_BUFII_HALFWORD (1<<4)
+#define MMU_BUFII_WORD (3<<4)
+#define MMU_BUFI_RESET (1<<3)
+#define MMU_BUFI_END (1<<2)
+#define MMU_BUFI_BYTE (0<<0)
+#define MMU_BUFI_HALFWORD (1<<0)
+#define MMU_BUFI_WORD (3<<0)
+
+#define MMU_PNRI (*(volatile unsigned long *)(APB0_SD + 0x04))
+#define CUR_PNRI (*(volatile unsigned long *)(APB0_SD + 0x08))
+#define MMU_PNRII (*(volatile unsigned long *)(APB0_SD + 0x0C))
+#define CUR_PNRII (*(volatile unsigned long *)(APB0_SD + 0x10))
+#define MMU_ADDR (*(volatile unsigned long *)(APB0_SD + 0x14))
+#define CUR_ADDR (*(volatile unsigned long *)(APB0_SD + 0x18))
+#define MMU_DATA (*(volatile unsigned long *)(APB0_SD + 0x1C))
+
+#define SD_CTRL (*(volatile unsigned long *)(APB0_SD + 0x20))
+#define SD_PWR_CD (1<<13)
+#define SD_PWR_CPU (0<<13)
+#define SD_DETECT_CDDAT3 (1<<12)
+#define SD_DETECT_MECH (0<<12)
+#define SD_CLOCK_DIS (1<<11)
+#define SD_CLOCK_EN (0<<11)
+#define SD_DIV(x) ((x)&0x7ff)
+
+#define SD_INT (*(volatile unsigned long *)(APB0_SD + 0x24))
+#define CMD_RES_STAT (1<<6)
+#define DATA_XFER_STAT (1<<5)
+#define CD_DETECT_STAT (1<<4)
+#define CMD_RES_INT_EN (1<<2)
+#define DATA_XFER_INT_EN (1<<1)
+#define CD_DETECT_IN_EN (1<<0)
+
+#define SD_CARD (*(volatile unsigned long *)(APB0_SD + 0x28))
+#define SD_CARD_SELECT (1<<7)
+#define SD_CARD_PWR_EN (1<<6)
+#define SD_CARD_DETECT_INT_EN (1<<5)
+#define SD_CARD_BSY (1<<2)
+#define SD_CARD_WRITE_PROTECT (1<<1)
+#define SD_CARD_DETECT (1<<0)
+
+#define SD_CMDREST (*(volatile unsigned long *)(APB0_SD + 0x30))
+#define CMD_XFER_START (1<<13)
+#define CMD_XFER_END (0<<13)
+#define RES_XFER_START (1<<12)
+#define RES_XFER_END (0<<12)
+#define RES_R1 (0<<9)
+#define RES_R1b (1<<9)
+#define RES_R2 (2<<9)
+#define RES_R3 (3<<9)
+#define RES_R6 (6<<9)
+#define CMD_RES_ERROR (1<<8)
+/* bits 0-5 cmd index */
+
+#define SD_CMDRES (*(volatile unsigned long *)(APB0_SD + 0x34))
+#define STAT_CMD_XFER_START (1<<8)
+#define STAT_RES_XFER_START (1<<7)
+#define STAT_CMD_RES_ERR (1<<6)
+#define STAT_CMD_RES_BUS_ERR (1<<5)
+#define STAT_RES_TIMEOUT_ERR (1<<4)
+#define STAT_RES_STARTBIT_ERR (1<<3)
+#define STAT_RES_INDEX_ERR (1<<2)
+#define STAT_RES_CRC_ERR (1<<1)
+#define STAT_RES_ENDBIT_ERR (1<<0)
+
+#define SD_DATAT (*(volatile unsigned long *)(APB0_SD + 0x3C))
+#define DATA_XFER_START (1<<13)
+#define DATA_XFER_WRITE (1<<12)
+#define DATA_XFER_READ (0<<12)
+#define DATA_BUS_4LINES (1<<11) /* rk2705/6/8 does not support this mode */
+#define DATA_BUS_1LINE (0<<11)
+#define DATA_XFER_DMA_EN (1<<10)
+#define DATA_XFER_DMA_DIS (0<<10)
+#define DATA_XFER_MULTI (1<<9)
+#define DATA_XFER_SINGLE (0<<9)
+#define DATA_XFER_ERR (1<<8)
+#define DATA_BUS_ERR (1<<7)
+#define DATA_TIMEOUT_ERR (1<<6)
+#define DATA_CRC_ERR (1<<5)
+#define READ_DAT_STARTBIT_ERR (1<<4)
+#define READ_DAT_ENDBIT_ERR (1<<3)
+#define WRITE_DAT_NOERR (2<<0)
+#define WRITE_DAT_CRC_ERR (5<<0)
+#define WRITE_DAT_NO_RES (7<<0)
+
+#define SD_CMD (*(volatile unsigned long *)(APB0_SD + 0x40))
+#define SD_RES3 (*(volatile unsigned long *)(APB0_SD + 0x44))
+#define SD_RES2 (*(volatile unsigned long *)(APB0_SD + 0x48))
+#define SD_RES1 (*(volatile unsigned long *)(APB0_SD + 0x4C))
+#define SD_RES0 (*(volatile unsigned long *)(APB0_SD + 0x50))
+
+/* I2S controller */
+#define APB0_I2S (ARM_BUS0_BASE + 0x00028000)
+#define I2S_OPR (*(volatile unsigned long *)(APB0_I2S + 0x00))
+#define I2S_TXR (*(volatile unsigned long *)(APB0_I2S + 0x04))
+#define I2S_RXR (*(volatile unsigned long *)(APB0_I2S + 0x08))
+#define I2S_TXCTL (*(volatile unsigned long *)(APB0_I2S + 0x0C))
+#define I2S_RXCTL (*(volatile unsigned long *)(APB0_I2S + 0x10))
+#define I2S_FIFOSTS (*(volatile unsigned long *)(APB0_I2S + 0x14))
+#define I2S_IER (*(volatile unsigned long *)(APB0_I2S + 0x18))
+#define I2S_ISR (*(volatile unsigned long *)(APB0_I2S + 0x1C))
+
+/* PWM timer */
+#define APB0_PWM (ARM_BUS0_BASE + 0x0002C000)
+#define PWMT0_CNTR (*(volatile unsigned long *)(APB0_PWM + 0x00))
+#define PWMT0_HRC (*(volatile unsigned long *)(APB0_PWM + 0x04))
+#define PWMT0_LRC (*(volatile unsigned long *)(APB0_PWM + 0x08))
+#define PWMT0_CTRL (*(volatile unsigned long *)(APB0_PWM + 0x0C))
+#define PWMT1_CNTR (*(volatile unsigned long *)(APB0_PWM + 0x10))
+#define PWMT1_HRC (*(volatile unsigned long *)(APB0_PWM + 0x14))
+#define PWMT1_LRC (*(volatile unsigned long *)(APB0_PWM + 0x18))
+#define PWMT1_CTRL (*(volatile unsigned long *)(APB0_PWM + 0x1C))
+#define PWMT2_CNTR (*(volatile unsigned long *)(APB0_PWM + 0x20))
+#define PWMT2_HRC (*(volatile unsigned long *)(APB0_PWM + 0x24))
+#define PWMT2_LRC (*(volatile unsigned long *)(APB0_PWM + 0x28))
+#define PWMT2_CTRL (*(volatile unsigned long *)(APB0_PWM + 0x2C))
+#define PWMT3_CNTR (*(volatile unsigned long *)(APB0_PWM + 0x30))
+#define PWMT3_HRC (*(volatile unsigned long *)(APB0_PWM + 0x34))
+#define PWMT3_LRC (*(volatile unsigned long *)(APB0_PWM + 0x38))
+#define PWMT3_CTRL (*(volatile unsigned long *)(APB0_PWM + 0x3C))
+
+/* ADC converter */
+#define APB0_ADC0 (ARM_BUS0_BASE + 0x00030000)
+#define ADC_DATA (*(volatile unsigned long *)(APB0_ADC0 + 0x00))
+#define ADC_STAT (*(volatile unsigned long *)(APB0_ADC0 + 0x04))
+#define ADC_CTRL (*(volatile unsigned long *)(APB0_ADC0 + 0x08))
+
+/* 0x18034000 - 0x18038000 reserved */
+
+/* GPIO ports E,F */
+#define APB0_GPIO1 (ARM_BUS0_BASE + 0x00038000)
+#define GPIO_PEDR (*(volatile unsigned long *)(APB0_GPIO1 + 0x00))
+#define GPIO_PECON (*(volatile unsigned long *)(APB0_GPIO1 + 0x04))
+#define GPIO_PFDR (*(volatile unsigned long *)(APB0_GPIO1 + 0x08))
+#define GPIO_PFCON (*(volatile unsigned long *)(APB0_GPIO1 + 0x0C))
+
+#define GPIO1_TEST (*(volatile unsigned long *)(APB0_GPIO1 + 0x20))
+#define GPIO_IEE (*(volatile unsigned long *)(APB0_GPIO1 + 0x24))
+#define GPIO_IEF (*(volatile unsigned long *)(APB0_GPIO1 + 0x28))
+
+#define GPIO_ISE (*(volatile unsigned long *)(APB0_GPIO1 + 0x34))
+#define GPIO_ISF (*(volatile unsigned long *)(APB0_GPIO1 + 0x38))
+
+#define GPIO_IBEE (*(volatile unsigned long *)(APB0_GPIO1 + 0x44))
+#define GPIO_IBEF (*(volatile unsigned long *)(APB0_GPIO1 + 0x48))
+
+#define GPIO_IEVE (*(volatile unsigned long *)(APB0_GPIO1 + 0x54))
+#define GPIO_IEVF (*(volatile unsigned long *)(APB0_GPIO1 + 0x58))
+
+#define GPIO_ICE (*(volatile unsigned long *)(APB0_GPIO1 + 0x64))
+#define GPIO_ICF (*(volatile unsigned long *)(APB0_GPIO1 + 0x68))
+
+#define GPIO1_ISR (*(volatile unsigned long *)(APB0_GPIO1 + 0x74))
+
+
+/* 0x1803C000 - 0x18080000 reserved */
+
+/* Interrupt controller */
+#define AHB0_INTC (ARM_BUS0_BASE + 0x00080000)
+#define INTC_SCR0 (*(volatile unsigned long *)(AHB0_INTC + 0x00))
+#define INTC_SCR1 (*(volatile unsigned long *)(AHB0_INTC + 0x04))
+#define INTC_SCR2 (*(volatile unsigned long *)(AHB0_INTC + 0x08))
+#define INTC_SCR3 (*(volatile unsigned long *)(AHB0_INTC + 0x0C))
+#define INTC_SCR4 (*(volatile unsigned long *)(AHB0_INTC + 0x10))
+#define INTC_SCR5 (*(volatile unsigned long *)(AHB0_INTC + 0x14))
+#define INTC_SCR6 (*(volatile unsigned long *)(AHB0_INTC + 0x18))
+#define INTC_SCR7 (*(volatile unsigned long *)(AHB0_INTC + 0x1C))
+#define INTC_SCR8 (*(volatile unsigned long *)(AHB0_INTC + 0x20))
+#define INTC_SCR9 (*(volatile unsigned long *)(AHB0_INTC + 0x24))
+#define INTC_SCR10 (*(volatile unsigned long *)(AHB0_INTC + 0x28))
+#define INTC_SCR11 (*(volatile unsigned long *)(AHB0_INTC + 0x2C))
+#define INTC_SCR12 (*(volatile unsigned long *)(AHB0_INTC + 0x30))
+#define INTC_SCR13 (*(volatile unsigned long *)(AHB0_INTC + 0x34))
+#define INTC_SCR14 (*(volatile unsigned long *)(AHB0_INTC + 0x38))
+#define INTC_SCR15 (*(volatile unsigned long *)(AHB0_INTC + 0x3C))
+#define INTC_SCR16 (*(volatile unsigned long *)(AHB0_INTC + 0x40))
+#define INTC_SCR17 (*(volatile unsigned long *)(AHB0_INTC + 0x44))
+#define INTC_SCR18 (*(volatile unsigned long *)(AHB0_INTC + 0x48))
+#define INTC_SCR19 (*(volatile unsigned long *)(AHB0_INTC + 0x4C))
+#define INTC_SCR20 (*(volatile unsigned long *)(AHB0_INTC + 0x50))
+#define INTC_SCR21 (*(volatile unsigned long *)(AHB0_INTC + 0x54))
+#define INTC_SCR22 (*(volatile unsigned long *)(AHB0_INTC + 0x58))
+#define INTC_SCR23 (*(volatile unsigned long *)(AHB0_INTC + 0x5C))
+#define INTC_SCR24 (*(volatile unsigned long *)(AHB0_INTC + 0x60))
+#define INTC_SCR25 (*(volatile unsigned long *)(AHB0_INTC + 0x64))
+#define INTC_SCR26 (*(volatile unsigned long *)(AHB0_INTC + 0x68))
+#define INTC_SCR27 (*(volatile unsigned long *)(AHB0_INTC + 0x6C))
+#define INTC_SCR28 (*(volatile unsigned long *)(AHB0_INTC + 0x70))
+#define INTC_SCR29 (*(volatile unsigned long *)(AHB0_INTC + 0x74))
+#define INTC_SCR30 (*(volatile unsigned long *)(AHB0_INTC + 0x78))
+#define INTC_SCR31 (*(volatile unsigned long *)(AHB0_INTC + 0x7C))
+
+#define INTC_ISR (*(volatile unsigned long *)(AHB0_INTC + 0x104))
+#define INTC_IPR (*(volatile unsigned long *)(AHB0_INTC + 0x108))
+#define INTC_IMR (*(volatile unsigned long *)(AHB0_INTC + 0x10C))
+
+#define INTC_IECR (*(volatile unsigned long *)(AHB0_INTC + 0x114))
+#define INTC_ICCR (*(volatile unsigned long *)(AHB0_INTC + 0x118))
+#define INTC_ISCR (*(volatile unsigned long *)(AHB0_INTC + 0x11C))
+
+#define INTC_TEST (*(volatile unsigned long *)(AHB0_INTC + 0x124))
+
+/* Bus arbiter module */
+#define AHB0_ARBITER (ARM_BUS0_BASE + 0x00084000)
+#define ARB_MODE (*(volatile unsigned long *)(AHB0_ARBITER + 0x00))
+#define ARB_PRIO1 (*(volatile unsigned long *)(AHB0_ARBITER + 0x04))
+#define ARB_PRIO2 (*(volatile unsigned long *)(AHB0_ARBITER + 0x08))
+#define ARB_PRIO3 (*(volatile unsigned long *)(AHB0_ARBITER + 0x0C))
+#define ARB_PRIO4 (*(volatile unsigned long *)(AHB0_ARBITER + 0x10))
+#define ARB_PRIO5 (*(volatile unsigned long *)(AHB0_ARBITER + 0x14))
+#define ARB_PRIO6 (*(volatile unsigned long *)(AHB0_ARBITER + 0x18))
+#define ARB_PRIO7 (*(volatile unsigned long *)(AHB0_ARBITER + 0x1C))
+#define ARB_PRIO8 (*(volatile unsigned long *)(AHB0_ARBITER + 0x20))
+#define ARB_PRIO9 (*(volatile unsigned long *)(AHB0_ARBITER + 0x24))
+#define ARB_PRIO10 (*(volatile unsigned long *)(AHB0_ARBITER + 0x28))
+#define ARB_PRIO11 (*(volatile unsigned long *)(AHB0_ARBITER + 0x2C))
+#define ARB_PRIO12 (*(volatile unsigned long *)(AHB0_ARBITER + 0x30))
+#define ARB_PRIO13 (*(volatile unsigned long *)(AHB0_ARBITER + 0x34))
+#define ARB_PRIO14 (*(volatile unsigned long *)(AHB0_ARBITER + 0x38))
+#define ARB_PRIO15 (*(volatile unsigned long *)(AHB0_ARBITER + 0x3C))
+
+/* Interprocessor communication module */
+#define AHB0_CPU_MAILBOX (ARM_BUS0_BASE + 0x00088000)
+#define MAILBOX_ID (*(volatile unsigned long *)(AHB0_CPU_MAILBOX + 0x00))
+#define H2C_STA (*(volatile unsigned long *)(AHB0_CPU_MAILBOX + 0x10))
+#define H2C0_DATA (*(volatile unsigned long *)(AHB0_CPU_MAILBOC + 0x20))
+#define H2C0_CMD (*(volatile unsigned long *)(AHB0_CPU_MAILBOC + 0x24))
+#define H2C1_DATA (*(volatile unsigned long *)(AHB0_CPU_MAILBOC + 0x28))
+#define H2C1_CMD (*(volatile unsigned long *)(AHB0_CPU_MAILBOC + 0x2C))
+#define H2C2_DATA (*(volatile unsigned long *)(AHB0_CPU_MAILBOC + 0x30))
+#define H2C2_CMD (*(volatile unsigned long *)(AHB0_CPU_MAILBOC + 0x24))
+#define H2C3_DATA (*(volatile unsigned long *)(AHB0_CPU_MAILBOC + 0x38))
+#define H2C3_CMD (*(volatile unsigned long *)(AHB0_CPU_MAILBOC + 0x3C))
+
+#define C2H_STA (*(volatile unsigned long *)(AHB0_CPU_MAILBOC + 0x40))
+#define C2H0_DATA (*(volatile unsigned long *)(AHB0_CPU_MAILBOC + 0x50))
+#define C2H0_CMD (*(volatile unsigned long *)(AHB0_CPU_MAILBOC + 0x54))
+#define C2H1_DATA (*(volatile unsigned long *)(AHB0_CPU_MAILBOC + 0x58))
+#define C2H1_CMD (*(volatile unsigned long *)(AHB0_CPU_MAILBOC + 0x5C))
+#define C2H2_DATA (*(volatile unsigned long *)(AHB0_CPU_MAILBOC + 0x60))
+#define C2H2_CMD (*(volatile unsigned long *)(AHB0_CPU_MAILBOC + 0x64))
+#define C2H3_DATA (*(volatile unsigned long *)(AHB0_CPU_MAILBOC + 0x68))
+#define C2H3_CMD (*(volatile unsigned long *)(AHB0_CPU_MAILBOC + 0x6C))
+
+/* Debug module */
+#define AHB0_CPU_DEBUGIF (ARM_BUS0_BASE + 0x0008C000)
+
+/* AHB DMA */
+#define AHB0_HDMA (ARM_BUS0_BASE + 0x00090000)
+#define HDMA_CON0 (*(volatile unsigned long *)(AHB0_HDMA + 0x00))
+#define HDMA_CON1 (*(volatile unsigned long *)(AHB0_HDMA + 0x04))
+#define HDMA_ISRC0 (*(volatile unsigned long *)(AHB0_HDMA + 0x08))
+#define HDMA_IDST0 (*(volatile unsigned long *)(AHB0_HDMA + 0x0C))
+#define HDMA_ICNT0 (*(volatile unsigned long *)(AHB0_HDMA + 0x10))
+#define HDMA_ISRC1 (*(volatile unsigned long *)(AHB0_HDMA + 0x14))
+#define HDMA_IDST1 (*(volatile unsigned long *)(AHB0_HDMA + 0x18))
+#define HDMA_ICNT1 (*(volatile unsigned long *)(AHB0_HDMA + 0x1C))
+#define HDMA_CSRC0 (*(volatile unsigned long *)(AHB0_HDMA + 0x20))
+#define HDMA_CDST0 (*(volatile unsigned long *)(AHB0_HDMA + 0x24))
+#define HDMA_CCNT0 (*(volatile unsigned long *)(AHB0_HDMA + 0x28))
+#define HDMA_CSRC1 (*(volatile unsigned long *)(AHB0_HDMA + 0x2C))
+#define HDMA_CDST1 (*(volatile unsigned long *)(AHB0_HDMA + 0x30))
+#define HDMA_CCNT1 (*(volatile unsigned long *)(AHB0_HDMA + 0x34))
+#define HDMA_ISR (*(volatile unsigned long *)(AHB0_HDMA + 0x38))
+#define HDMA_DSR (*(volatile unsigned long *)(AHB0_HDMA + 0x3C))
+#define HDMA_ISCNT0 (*(volatile unsigned long *)(AHB0_HDMA + 0x40))
+#define HDMA_IPNCNTD0 (*(volatile unsigned long *)(AHB0_HDMA + 0x44))
+#define HDMA_IADDR_BS0 (*(volatile unsigned long *)(AHB0_HDMA + 0x48))
+#define HDMA_ISCNT1 (*(volatile unsigned long *)(AHB0_HDMA + 0x4C))
+#define HDMA_IPNCNTD1 (*(volatile unsigned long *)(AHB0_HDMA + 0x50))
+#define HDMA_IADDR_BS1 (*(volatile unsigned long *)(AHB0_HDMA + 0x54))
+#define HDMA_CSCNT0 (*(volatile unsigned long *)(AHB0_HDMA + 0x58))
+#define HDMA_CPNCNTD0 (*(volatile unsigned long *)(AHB0_HDMA + 0x5C))
+#define HDMA_CADDR_BS0 (*(volatile unsigned long *)(AHB0_HDMA + 0x60))
+#define HDMA_CSCNT1 (*(volatile unsigned long *)(AHB0_HDMA + 0x64))
+#define HDMA_CPNCNTD1 (*(volatile unsigned long *)(AHB0_HDMA + 0x68))
+#define HDMA_CADDR_BS1 (*(volatile unsigned long *)(AHB0_HDMA + 0x6C))
+#define HDMA_PACNT0 (*(volatile unsigned long *)(AHB0_HDMA + 0x70))
+#define HDMA_PACNT1 (*(volatile unsigned long *)(AHB0_HDMA + 0x74))
+
+/* AHB-to-AHB bridge controller */
+#define AHB0_A2A_DMA (ARM_BUS0_BASE + 0x00094000)
+#define A2A_CON0 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x00))
+#define A2A_ISRC0 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x04))
+#define A2A_IDST0 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x08))
+#define A2A_ICNT0 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x0C))
+#define A2A_CSRC0 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x10))
+#define A2A_CDST0 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x14))
+#define A2A_CCNT0 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x18))
+#define A2A_CON1 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x1C))
+#define A2A_ISRC1 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x20))
+#define A2A_IDST1 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x24))
+#define A2A_ICNT1 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x28))
+#define A2A_CSRC1 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x2C))
+#define A2A_CDST1 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x30))
+#define A2A_CCNT1 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x34))
+#define A2A_INT_STS (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x38))
+#define A2A_DMA_STS (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x3C))
+#define A2A_ERR_ADR0 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x40))
+#define A2A_ERR_OP0 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x44))
+#define A2A_ERR_ADR1 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x48))
+#define A2A_ERR_OP1 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x4C))
+#define A2A_LCNT0 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x50))
+#define A2A_LCNT1 (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x54))
+#define A2A_DOMAIN (*(volatile unsigned long *)(AHB0_A2A_DMA + 0x58))
+
+/* 0x18098000 - 0x180A000 reserved */
+
+/* USB device controller */
+#define AHB0_UDC (ARM_BUS0_BASE + 0x000A0000)
+#define PHY_TEST_EN (*(volatile unsigned long *)(AHB0_UDC + 0x00))
+#define PHY_TEST (*(volatile unsigned long *)(AHB0_UDC + 0x04))
+#define DEV_CTL (*(volatile unsigned long *)(AHB0_UDC + 0x08))
+
+#define DEV_INFO (*(volatile unsigned long *)(AHB0_UDC + 0x10))
+#define EN_INT (*(volatile unsigned long *)(AHB0_UDC + 0x14))
+#define EN_SOF_INTR (1<<0)
+#define EN_SETUP_INTR (1<<1)
+#define EN_IN0_INTR (1<<2)
+#define EN_OUT0_INTR (1<<3)
+#define EN_USBRST_INTR (1<<4)
+#define EN_RESUME_INTR (1<<5)
+#define EN_SUSP_INTR (1<<6)
+/* bit 7 reserved */
+#define EN_BOUT1_INTR (1<<8)
+#define EN_BIN2_INTR (1<<9)
+#define EN_IIN3_INTR (1<<10)
+#define EN_BOUT4_INTR (1<<11)
+#define EN_BIN5_INTR (1<<12)
+#define EN_IIN6_INTR (1<<13)
+#define EN_BOUT7_INTR (1<<14)
+#define EN_BIN8_INTR (1<<15)
+#define EN_IIN9_INTR (1<<16)
+#define EN_BOUT10_INTR (1<<17)
+#define EN_BIN11_INTR (1<<18)
+#define EN_IIN12_INTR (1<<19)
+#define EN_BOUT13_INTR (1<<20)
+#define EN_BIN14_INTR (1<<21)
+#define EN_IIN15_INTR (1<<22)
+/* bits 23-26 TEST */
+/* bits 27-31 reserved */
+
+#define INT2FLAG (*(volatile unsigned long *)(AHB0_UDC + 0x18))
+#define SOF_INTR (1<<0)
+#define SETUP_INTR (1<<1)
+#define IN0_INTR (1<<2)
+#define OUT0_INTR (1<<3)
+#define USBRST_INTR (1<<4)
+#define RESUME_INTR (1<<5)
+#define SUSP_INTR (1<<6)
+/* bit 7 reserved */
+#define BOUT1_INTR (1<<8)
+#define BIN2_INTR (1<<9)
+#define IIN3_INTR (1<<10)
+#define BOUT4_INTR (1<<11)
+#define BIN5_INTR (1<<12)
+#define IIN6_INTR (1<<13)
+#define BOUT7_INTR (1<<14)
+#define BIN8_INTR (1<<15)
+#define IIN9_INTR (1<<16)
+#define BOUT10_INTR (1<<17)
+#define BIN11_INTR (1<<18)
+#define IIN12_INTR (1<<19)
+#define BOUT13_INTR (1<<20)
+#define BIN14_INTR (1<<21)
+#define IIN15_INTR (1<<22)
+/* bits 23-26 TEST */
+/* bits 27-31 reserved */
+
+#define INTCON (*(volatile unsigned long *)(AHB0_UDC + 0x1C))
+#define SETUP1 (*(volatile unsigned long *)(AHB0_UDC + 0x20))
+#define SETUP2 (*(volatile unsigned long *)(AHB0_UDC + 0x24))
+#define AHBCON (*(volatile unsigned long *)(AHB0_UDC + 0x28))
+
+#define RX0STAT (*(volatile unsigned long *)(AHB0_UDC + 0x30))
+#define RX0CON (*(volatile unsigned long *)(AHB0_UDC + 0x34))
+#define RX0FFRC (1<<0)
+#define RX0CLR (1<<1)
+#define RX0STALL (1<<2)
+#define RX0NAK (1<<3)
+#define EP0EN (1<<4)
+#define RX0VOIDINTEN (1<<5)
+#define RX0ERRINTEN (1<<6)
+#define RX0ACKINTEN (1<<7)
+/* bits 8-31 reserved */
+
+#define RX0DMACTLO (*(volatile unsigned long *)(AHB0_UDC + 0x38))
+#define RX0DMAOUTLMADDR (*(volatile unsigned long *)(AHB0_UDC + 0x3C))
+#define TX0STAT (*(volatile unsigned long *)(AHB0_UDC + 0x40))
+#define TX0CON (*(volatile unsigned long *)(AHB0_UDC + 0x44))
+#define TX0CLR (1<<0)
+#define TX0STALL (1<<1)
+#define TX0NAK (1<<2)
+/* bit 3 reserved */
+#define TX0VOIDINTEN (1<<4)
+#define TX0ERRINTEN (1<<5)
+#define TX0ACKINTEN (1<<6)
+/* bits 7-31 reserved */
+
+#define TX0BUF (*(volatile unsigned long *)(AHB0_UDC + 0x48))
+#define TX0FULL (1<<0)
+#define TX0URF (1<<1)
+/* bits 2-31 reserved */
+
+#define TX0DMAINCTL (*(volatile unsigned long *)(AHB0_UDC + 0x4C))
+#define TX0DMAINSTA (1<<0)
+/* bits 1-31 reserved */
+
+#define TX0DMALM_IADDR (*(volatile unsigned long *)(AHB0_UDC + 0x50))
+#define RX1STAT (*(volatile unsigned long *)(AHB0_UDC + 0x54))
+#define RX1CON (*(volatile unsigned long *)(AHB0_UDC + 0x58))
+#define RX1DMACTLO (*(volatile unsigned long *)(AHB0_UDC + 0x5C))
+#define RX1DMAOUTLMADDR (*(volatile unsigned long *)(AHB0_UDC + 0x60))
+#define TX2STAT (*(volatile unsigned long *)(AHB0_UDC + 0x64))
+#define TX2CON (*(volatile unsigned long *)(AHB0_UDC + 0x68))
+#define TX2BUF (*(volatile unsigned long *)(AHB0_UDC + 0x6C))
+#define TX2DMAINCTL (*(volatile unsigned long *)(AHB0_UDC + 0x70))
+#define TX2DMALM_IADDR (*(volatile unsigned long *)(AHB0_UDC + 0x74))
+#define TX3STAT (*(volatile unsigned long *)(AHB0_UDC + 0x78))
+#define TX3CON (*(volatile unsigned long *)(AHB0_UDC + 0x7C))
+#define TX3BUF (*(volatile unsigned long *)(AHB0_UDC + 0x80))
+#define TX3DMAINCTL (*(volatile unsigned long *)(AHB0_UDC + 0x84))
+#define TX3DMALM_IADDR (*(volatile unsigned long *)(AHB0_UDC + 0x88))
+#define RX4STAT (*(volatile unsigned long *)(AHB0_UDC + 0x8C))
+#define RX4CON (*(volatile unsigned long *)(AHB0_UDC + 0x90))
+#define RX4DMACTLO (*(volatile unsigned long *)(AHB0_UDC + 0x94))
+#define RX4DMAOUTLMADDR (*(volatile unsigned long *)(AHB0_UDC + 0x98))
+#define TX5STAT (*(volatile unsigned long *)(AHB0_UDC + 0x9C))
+#define TX5CON (*(volatile unsigned long *)(AHB0_UDC + 0xA0))
+#define TX5BUF (*(volatile unsigned long *)(AHB0_UDC + 0xA4))
+#define TX5DMAINCTL (*(volatile unsigned long *)(AHB0_UDC + 0xA8))
+#define TX5DMALM_IADDR (*(volatile unsigned long *)(AHB0_UDC + 0xAC))
+#define TX6STAT (*(volatile unsigned long *)(AHB0_UDC + 0xB0))
+#define TX6CON (*(volatile unsigned long *)(AHB0_UDC + 0xB4))
+#define TX6BUF (*(volatile unsigned long *)(AHB0_UDC + 0xB8))
+#define TX6DMAINCTL (*(volatile unsigned long *)(AHB0_UDC + 0xBC))
+#define TX6DMALM_IADDR (*(volatile unsigned long *)(AHB0_UDC + 0xC0))
+#define RX7STAT (*(volatile unsigned long *)(AHB0_UDC + 0xC4))
+#define RX7CON (*(volatile unsigned long *)(AHB0_UDC + 0xC8))
+#define RX7DMACTLO (*(volatile unsigned long *)(AHB0_UDC + 0xCC))
+#define RX7DMAOUTLMADDR (*(volatile unsigned long *)(AHB0_UDC + 0xD0))
+#define TX8STAT (*(volatile unsigned long *)(AHB0_UDC + 0xD4))
+#define TX8CON (*(volatile unsigned long *)(AHB0_UDC + 0xD8))
+#define TX8BUF (*(volatile unsigned long *)(AHB0_UDC + 0xDC))
+#define TX8DMAINCTL (*(volatile unsigned long *)(AHB0_UDC + 0xE0))
+#define TX8DMALM_IADDR (*(volatile unsigned long *)(AHB0_UDC + 0xE4))
+#define TX9STAT (*(volatile unsigned long *)(AHB0_UDC + 0xE8))
+#define TX9CON (*(volatile unsigned long *)(AHB0_UDC + 0xEC))
+#define TX9BUF (*(volatile unsigned long *)(AHB0_UDC + 0xF0))
+#define TX9DMAINCTL (*(volatile unsigned long *)(AHB0_UDC + 0xF4))
+#define TX9DMALM_IADDR (*(volatile unsigned long *)(AHB0_UDC + 0xF8))
+#define RX10STAT (*(volatile unsigned long *)(AHB0_UDC + 0xFC))
+#define RX10CON (*(volatile unsigned long *)(AHB0_UDC + 0x100))
+#define RX10DMACTLO (*(volatile unsigned long *)(AHB0_UDC + 0x104))
+#define RX10DMAOUTLMADDR (*(volatile unsigned long *)(AHB0_UDC + 0x108))
+#define TX11STAT (*(volatile unsigned long *)(AHB0_UDC + 0x10C))
+#define TX11CON (*(volatile unsigned long *)(AHB0_UDC + 0x110))
+#define TX11BUF (*(volatile unsigned long *)(AHB0_UDC + 0x114))
+#define TX11DMAINCTL (*(volatile unsigned long *)(AHB0_UDC + 0x118))
+#define TX11DMALM_IADDR (*(volatile unsigned long *)(AHB0_UDC + 0x11C))
+#define TX12STAT (*(volatile unsigned long *)(AHB0_UDC + 0x120))
+#define TX12CON (*(volatile unsigned long *)(AHB0_UDC + 0x124))
+#define TX12BUF (*(volatile unsigned long *)(AHB0_UDC + 0x128))
+#define TX12DMAINCTL (*(volatile unsigned long *)(AHB0_UDC + 0x12C))
+#define TX12DMALM_IADDR (*(volatile unsigned long *)(AHB0_UDC + 0x130))
+#define RX13STAT (*(volatile unsigned long *)(AHB0_UDC + 0x134))
+#define RX13CON (*(volatile unsigned long *)(AHB0_UDC + 0x138))
+#define RX13DMACTLO (*(volatile unsigned long *)(AHB0_UDC + 0x13C))
+#define RX13DMAOUTLMADDR (*(volatile unsigned long *)(AHB0_UDC + 0x140))
+#define TX14STAT (*(volatile unsigned long *)(AHB0_UDC + 0x144))
+#define TX14CON (*(volatile unsigned long *)(AHB0_UDC + 0x148))
+#define TX14BUF (*(volatile unsigned long *)(AHB0_UDC + 0x14C))
+#define TX14DMAINCTL (*(volatile unsigned long *)(AHB0_UDC + 0x150))
+#define TX14DMALM_IADDR (*(volatile unsigned long *)(AHB0_UDC + 0x154))
+#define TX15STAT (*(volatile unsigned long *)(AHB0_UDC + 0x158))
+#define TX15CON (*(volatile unsigned long *)(AHB0_UDC + 0x15C))
+#define TX15BUF (*(volatile unsigned long *)(AHB0_UDC + 0x160))
+#define TX15DMAINCTL (*(volatile unsigned long *)(AHB0_UDC + 0x164))
+#define TX15DMALM_IADDR (*(volatile unsigned long *)(AHB0_UDC + 0x168))
+
+/* USB host controller */
+#define AHB0_UHC (ARM_BUS0_BASE + 0x000A4000)
+/* documentation missing */
+
+/* 0x180A8000 - 0x180B0000 reserved */
+
+/* Static/SDRAM memory controller */
+#define AHB0_SDRSTMC (ARM_BUS0_BASE + 0x000B0000)
+#define MCSDR_MODE (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x100))
+#define MCSDR_ADDMAP (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x104))
+#define MCSDR_ADDCFG (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x108))
+#define MCSDR_BASIC (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x10C))
+#define MCSDR_T_REF (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x110))
+#define MCSDR_T_RFC (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x114))
+#define MCSDR_T_MRD (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x118))
+#define MCSDR_T_RP (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x120))
+#define MCSDR_T_RCD (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x124))
+
+#define MCST0_T_CEWD (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x200))
+#define MCST0_T_CE2WE (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x204))
+#define MCST0_WEWD (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x208))
+#define MCST0_T_WE2CE (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x20C))
+#define MCST0_T_CEWDR (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x210))
+#define MCST0_T_CE2RD (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x214))
+#define MCST0_T_RDWD (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x218))
+#define MCST0_T_RD2CE (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x21C))
+#define MCST0_BASIC (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x220))
+
+#define MCST1_T_CEWD (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x300))
+#define MCST1_T_CE2WE (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x304))
+#define MCST1_WEWD (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x308))
+#define MCST1_T_WE2CE (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x30C))
+#define MCST1_T_CEWDR (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x310))
+#define MCST1_T_CE2RD (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x314))
+#define MCST1_T_RDWD (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x318))
+#define MCST1_T_RD2CE (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x31C))
+#define MCST1_BASIC (*(volatile unsigned long *)(AHB0_SDRSTMC + 0x320))
+
+/* 0x180B4000 - 0x180C000 reserved */
+
+/* VIP - video input processor */
+#define AHB0_VIP (ARM_BUS0_BASE + 0x000C0000)
+
+/* 0x180C4000 - 0x180E8000 reserved */
+
+/* NAND flash controller */
+#define AHB0_NANDC (ARM_BUS0_BASE + 0x000E8000)
+
+#define FMCTL (*(volatile unsigned long *)(AHB0_NANDC))
+#define FM_RDY (1<<5) /* status of line R/B# */
+#define FM_PROTECT (1<<4) /* WP# line (active low) */
+/* bits 0-3 are chip selects */
+
+#define FMWAIT (*(volatile unsigned long *)(AHB0_NANDC + 0x04))
+#define FLCTL (*(volatile unsigned long *)(AHB0_NANDC + 0x08))
+#define FL_RDY (1<<12)
+#define FL_COR_EN (1<<11)
+#define FL_INT_EN (1<<10)
+#define FL_XFER_EN (1<<9)
+#define FL_INTCLR_EN (1<<8)
+/* bits 3-7 unknown */
+#define FL_START (1<<2)
+#define FL_WR (1<<1)
+#define FL_RST (1<<0)
+
+#define BCHCTL (*(volatile unsigned long *)(AHB0_NANDC + 0x0C))
+/* bit 13 is used but unknown */
+/* bit 12 is used but unknown */
+#define BCH_WR (1<<1)
+#define BCH_RST (1<<0)
+
+#define BCHST (*(volatile unsigned long *)(AHB0_NANDC + 0xD0))
+/* bit 2 ERR ?? */
+/* bit 0 ?? */
+
+#define FLASH_DATA(n) (*(volatile unsigned char *)(AHB0_NANDC + 0x200 + (n<<9)))
+#define FLASH_ADDR(n) (*(volatile unsigned char *)(AHB0_NANDC + 0x204 + (n<<9)))
+#define FLASH_CMD(n) (*(volatile unsigned char *)(AHB0_NANDC + 0x208 + (n<<9)))
+
+#define PAGE_BUF (*(volatile unsigned char *)(AHB0_NANDC + 0xA00))
+#define SPARE_BUF (*(volatile unsigned char *)(AHB0_NANDC + 0x1200))
+
+#define AHB0_ROM (ARM_BUS0_BASE + 0x000EC000)
+#define AHB0_ES3 (ARM_BUS0_BASE + 0x000F4000)
+#define AHB0_ES4 (ARM_BUS0_BASE + 0x000F8000)
+#define AHB0_ES5 (ARM_BUS0_BASE + 0x000FC000)
+#define AHB0_ES6 (ARM_BUS0_BASE + 0x00100000)
+#define AHB0_EMD_SRAM (ARM_BUS0_BASE + 0x00200000)
+
+/* 0x18204000 - 0x1840000 reserved */
+
+/* 0x18400000 - 0x18484000 reserved*/
+
+#define AHB1_ARBITER 0x18484000
+/* 0x18488000 - 0x186E8000 reserved*/
+
+/* LCD controller */
+#define AHB1_LCDC 0x186E8000
+#define LCDC_CTRL (*(volatile unsigned long *)(AHB1_LCDC + 0x00))
+/* bits 14-31 reserved */
+#define ALPHA24B (1<<13)
+#define UVBUFEXCH (1<<12)
+#define ALPHA(x) (((x)&0x07)<<9)
+#define Y_MIX (1<<8)
+#define LCDC_MCU (1<<7)
+#define RGB24B (1<<6)
+#define START_EVEN (1<<5)
+#define EVEN_EN (1<<4)
+#define RGB_DUMMY(x) (((x)&0x03)<<2)
+#define LCDC_EN (1<<1)
+#define LCDC_STOP (1<<0)
+#define MCU_CTRL (*(volatile unsigned long *)(AHB1_LCDC + 0x04))
+
+#define ALPHA_BASE(x) (((x)&0x3f)<<8)
+#define MCU_CTRL_FIFO_EN (1<<6)
+#define MCU_CTRL_RS_HIGH (1<<5)
+#define MCU_CTRL_BUFF_WRITE (1<<2)
+#define MCU_CTRL_BUFF_START (1<<1)
+#define MCU_CTRL_BYPASS (1<<0)
+
+#define HOR_PERIOD (*(volatile unsigned long *)(AHB1_LCDC + 0x08))
+#define VERT_PERIOD (*(volatile unsigned long *)(AHB1_LCDC + 0x0C))
+#define HOR_PW (*(volatile unsigned long *)(AHB1_LCDC + 0x10))
+#define VERT_PW (*(volatile unsigned long *)(AHB1_LCDC + 0x14))
+#define HOR_ACT (*(volatile unsigned long *)(AHB1_LCDC + 0x18))
+#define VERT_ACT (*(volatile unsigned long *)(AHB1_LCDC + 0x1C))
+#define HOR_BP (*(volatile unsigned long *)(AHB1_LCDC + 0x20))
+#define VERT_BP (*(volatile unsigned long *)(AHB1_LCDC + 0x24))
+#define LINE0_YADDR (*(volatile unsigned long *)(AHB1_LCDC + 0x28))
+#define LINE_ALPHA_EN (1<<14)
+#define LINE_SCALE_EN (1<<13)
+#define LINE_GBR (1<<12)
+#define LINE_RGB (0<<12)
+#define LINE_YUV_SRC (1<<11)
+#define LINE_RGB_SRC (0<<11)
+/* bits 0-10 Y_BASE */
+
+#define LINE0_UVADDR (*(volatile unsigned long *)(AHB1_LCDC + 0x2C))
+#define LINE1_YADDR (*(volatile unsigned long *)(AHB1_LCDC + 0x30))
+#define LINE1_UVADDR (*(volatile unsigned long *)(AHB1_LCDC + 0x34))
+#define LINE2_YADDR (*(volatile unsigned long *)(AHB1_LCDC + 0x38))
+#define LINE2_UVADDR (*(volatile unsigned long *)(AHB1_LCDC + 0x3C))
+#define LINE3_YADDR (*(volatile unsigned long *)(AHB1_LCDC + 0x40))
+#define LINE3_UVADDR (*(volatile unsigned long *)(AHB1_LCDC + 0x44))
+#define START_X (*(volatile unsigned long *)(AHB1_LCDC + 0x48))
+#define START_Y (*(volatile unsigned long *)(AHB1_LCDC + 0x4C))
+#define DELTA_X (*(volatile unsigned long *)(AHB1_LCDC + 0x50))
+#define DELTA_Y (*(volatile unsigned long *)(AHB1_LCDC + 0x54))
+#define LCDC_INTR_MASK (*(volatile unsigned long *)(AHB1_LCDC + 0x58))
+#define INTR_MASK_LINE (1<<3)
+#define INTR_MASK_EVENLINE (0<<3)
+#define INTR_MASK_BUFF (1<<2)
+#define INTR_MASK_VERT (1<<1)
+#define INTR_MASK_HOR (1<<0)
+
+#define LCDC_STA (*(volatile unsigned long *)(AHB1_LCDC + 0x7C))
+#define LCDC_MCU_IDLE (1<<12)
+
+#define LCD_COMMAND (*(volatile unsigned long *)(AHB1_LCDC + 0x1000))
+#define LCD_DATA (*(volatile unsigned long *)(AHB1_LCDC + 0x1004))
+
+#define LCD_BUFF (*(volatile unsigned long *)(AHB1_LCDC + 0x2000))
+/* High speed ADC interface */
+#define AHB1_HS_ADC 0x186EC000
+#define HSADC_DATA (*(volatile unsigned long *)(AHB1_HS_ADC + 0x00))
+#define HSADC_CTRL (*(volatile unsigned long *)(AHB1_HS_ADC + 0x04))
+#define HSADC_IER (*(volatile unsigned long *)(AHB1_HS_ADC + 0x08))
+#define HSADC_ISR (*(volatile unsigned long *)(AHB1_HS_ADC + 0x0C))
+
+/* AHB-to-AHB DMA controller */
+#define AHB1_DWDMA 0x186F0000
+#define DWDMA_SAR(n) (*(volatile unsigned long *)(AHB1_DWDMA + 0x00 + 0x58*n))
+#define DWDMA_DAR(n) (*(volatile unsigned long *)(AHB1_DWDMA + 0x08 + 0x58*n))
+#define DWDMA_LLP(n) (*(volatile unsigned long *)(AHB1_DWDMA + 0x10 + 0x58*n))
+#define DWDMA_CTL_L(n) (*(volatile unsigned long *)(AHB1_DWDMA + 0x18 + 0x58*n))
+#define CTLL_LLP_SRC_EN (1<<28)
+#define CTLL_LLP_DST_EN (1<<27)
+#define CTLL_SMS_M2 (1<<25)
+#define CTLL_SMS_M1 (0<<25)
+#define CTLL_DMS_M2 (1<<23)
+#define CTLL_DMS_M1 (0<<23)
+#define CTLL_FC_PER2PER (3<<20)
+#define CTLL_FC_PER2MEM (2<<20)
+#define CTLL_FC_MEM2PER (1<<20)
+#define CTLL_FC_MEM2MEM (0<<20)
+/* bit 19 reserved */
+#define CTLL_DST_SCATTER_EN (1<<18)
+#define CTLL_SRC_GATHER_EN (1<<17)
+#define CTLL_SRC_MSIZE_32 (4<<14)
+#define CTLL_SRC_MSIZE_16 (3<<14)
+#define CTLL_SRC_MSIZE_8 (2<<14)
+#define CTLL_SRC_MSIZE_4 (1<<14)
+#define CTLL_SRC_MSIZE_1 (0<<14)
+#define CTLL_DST_MSIZE_32 (4<<11)
+#define CTLL_DST_MSIZE_16 (3<<11)
+#define CTLL_DST_MSIZE_8 (2<<11)
+#define CTLL_DST_MSIZE_4 (1<<11)
+#define CTLL_DST_MSIZE_1 (0<<11)
+#define CTLL_SINC_NO (2<<9)
+#define CTLL_SINC_DEC (1<<9)
+#define CTLL_SINC_INC (0<<9)
+#define CTLL_DINC_NO (2<<7)
+#define CTLL_DINC_DEC (1<<7)
+#define CTLL_DINC_INC (0<<7)
+#define CTLL_SRC_TR_WIDTH_32 (2<<4)
+#define CTLL_SRC_TR_WIDTH_16 (1<<4)
+#define CTLL_SRC_TR_WIDTH_8 (0<<4)
+#define CTLL_DST_TR_WIDTH_32 (2<<1)
+#define CTLL_DST_TR_WIDTH_16 (1<<1)
+#define CTLL_DST_TR_WIDTH_8 (0<<1)
+#define CTLL_INT_EN (1<<0)
+
+#define DWDMA_CTL_H(n) (*(volatile unsigned long *)(AHB1_DWDMA + 0x1C + 0x58*n))
+#define DWDMA_SSTAT(n) (*(volatile unsigned long *)(AHB1_DWDMA + 0x20 + 0x58*n))
+#define DWDMA_DSTAT(n) (*(volatile unsigned long *)(AHB1_DWDMA + 0x28 + 0x58*n))
+#define DWDMA_SSTATAR(n) (*(volatile unsigned long *)(AHB1_DWDMA + 0x30 + 0x58*n))
+#define DWDMA_DSTATAR(n) (*(volatile unsigned long *)(AHB1_DWDMA + 0x38 + 0x58*n))
+#define DWDMA_CFG_L(n) (*(volatile unsigned long *)(AHB1_DWDMA + 0x40 + 0x58*n))
+#define CFGL_RELOAD_DST (1<<31)
+#define CFGL_RELOAD_SRC (1<<30)
+#define CFGL_MAX_ABRST(n) ((n)<<20)
+#define CFGL_SRC_HS_POL_LOW (1<<19)
+#define CFGL_DST_HS_POL_LOW (1<<18)
+#define CFGL_LOCK_B (1<<17)
+#define CFGL_LOCK_CH (1<<16)
+#define CFGL_LOCK_B_L(n) (((n)&0x03)<<14)
+#define CFGL_LOCK_CH_L(n) (((n)&0x03)<<12)
+#define CFGL_HS_SEL_SRC (1<<11)
+#define CFGL_HS_SEL_DST (1<<10)
+#define CFGL_FIFO_EMPTY (1<<9)
+#define CFGL_CH_SUSP (1<<8)
+#define CFGL_CH_PRIOR(n) (((n) & 0x03)<<5)
+/* bits 0-4 reserved */
+#define DWDMA_CFG_H(n) (*(volatile unsigned long *)(AHB1_DWDMA + 0x44 + 0x58*n))
+#define CFGH_DST_PER(n) (((n)&0x0F)<<11)
+#define CFGH_SRC_PER(n) (((n)&0x0F)<<7)
+#define CFGH_SRC_UPD_EN (1<<6)
+#define CFGH_DST_UPD_EN (1<<5)
+#define CFGH_PROTCTL(n) (((n)&0x07)<<2)
+#define CFGH_FIFO_MODE (1<<1)
+#define CFGH_FC_MODE (1<<0)
+
+#define DWDMA_SGR(n) (*(volatile unsigned long *)(AHB1_DWDMA + 0x48 + 0x58*n))
+#define DWDMA_DSR(n) (*(volatile unsigned long *)(AHB1_DWDMA + 0x50 + 0x58*n))
+
+#define DWDMA_RAW_TFR (*(volatile unsigned long *)(AHB1_DWDMA + 0x2C0))
+#define DWDMA_RAW_BLOCK (*(volatile unsigned long *)(AHB1_DWDMA + 0x2C8))
+#define DWDMA_RAW_SRCTRAN (*(volatile unsigned long *)(AHB1_DWDMA + 0x2D0))
+#define DWDMA_RAW_DSTTRAN (*(volatile unsigned long *)(AHB1_DWDMA + 0x2D8))
+#define DWDMA_RAW_ERR (*(volatile unsigned long *)(AHB1_DWDMA + 0x2E0))
+
+#define DWDMA_STATUS_TFR (*(volatile unsigned long *)(AHB1_DWDMA + 0x2E8))
+#define DWDMA_STATUS_BLOCK (*(volatile unsigned long *)(AHB1_DWDMA + 0x2F0))
+#define DWDMA_STATUS_SRCTRAN (*(volatile unsigned long *)(AHB1_DWDMA + 0x2F8))
+#define DWDMA_STATUS_DSTTRAN (*(volatile unsigned long *)(AHB1_DWDMA + 0x300))
+#define DWDMA_STATUS_ERR (*(volatile unsigned long *)(AHB1_DWDMA + 0x308))
+
+#define DWDMA_MASK_TFR (*(volatile unsigned long *)(AHB1_DWDMA + 0x310))
+#define DWDMA_MASK_BLOCK (*(volatile unsigned long *)(AHB1_DWDMA + 0x318))
+#define DWDMA_MASK_SRCTRAN (*(volatile unsigned long *)(AHB1_DWDMA + 0x320))
+#define DWDMA_MASK_DSTTRAN (*(volatile unsigned long *)(AHB1_DWDMA + 0x328))
+#define DWDMA_MASK_ERR (*(volatile unsigned long *)(AHB1_DWDMA + 0x330))
+
+#define DWDMA_CLEAR_TFR (*(volatile unsigned long *)(AHB1_DWDMA + 0x338))
+#define DWDMA_CLEAR_BLOCK (*(volatile unsigned long *)(AHB1_DWDMA + 0x340))
+#define DWDMA_CLEAR_SRCTRAN (*(volatile unsigned long *)(AHB1_DWDMA + 0x348))
+#define DWDMA_CLEAR_DSTTRAN (*(volatile unsigned long *)(AHB1_DWDMA + 0x350))
+#define DWDMA_CLEAR_ERR (*(volatile unsigned long *)(AHB1_DWDMA + 0x358))
+
+#define DWDMA_STATUS_INT (*(volatile unsigned long *)(AHB1_DWDMA + 0x360))
+
+#define DWDMA_REQ_SRC (*(volatile unsigned long *)(AHB1_DWDMA + 0x368))
+#define DWDMA_REQ_DST (*(volatile unsigned long *)(AHB1_DWDMA + 0x370))
+#define DWDMA_S_REQ_SRC (*(volatile unsigned long *)(AHB1_DWDMA + 0x378))
+#define DWDMA_S_REQ_DST (*(volatile unsigned long *)(AHB1_DWDMA + 0x380))
+#define DWDMA_L_REQ_SRC (*(volatile unsigned long *)(AHB1_DWDMA + 0x388))
+#define DWDMA_L_REQ_DST (*(volatile unsigned long *)(AHB1_DWDMA + 0x390))
+
+#define DWDMA_DMA_CFG (*(volatile unsigned long *)(AHB1_DWDMA + 0x398))
+#define GLOB_EN (1<<0)
+#define DWDMA_DMA_CHEN (*(volatile unsigned long *)(AHB1_DWDMA + 0x3A0))
+#define DMACHEN_CH0 (0x101<<0)
+#define DMACHEN_CH1 (0x101<<1)
+#define DMACHEN_CH2 (0x101<<2)
+#define DMACHEN_CH3 (0x101<<3)
+
+/* ARM7 cache controller */
+#define ARM_CACHE_CNTRL 0xEFFF0000
+#define DEVID (*(volatile unsigned long *)(ARM_CACHE_CTRL + 0x00))
+#define CACHEOP (*(volatile unsigned long *)(ARM_CACHE_CTRL + 0x04))
+#define CACHELKDN (*(volatile unsigned long *)(ARM_CACHE_CTRL + 0x08))
+
+#define MEMMAPA (*(volatile unsigned long *)(ARM_CACHE_CTRL + 0x10))
+#define MEMMAPB (*(volatile unsigned long *)(ARM_CACHE_CTRL + 0x14))
+#define MEMMAPC (*(volatile unsigned long *)(ARM_CACHE_CTRL + 0x18))
+#define MEMMAPD (*(volatile unsigned long *)(ARM_CACHE_CTRL + 0x1C))
+#define PFCNTRA_CTRL (*(volatile unsigned long *)(ARM_CACHE_CTRL + 0x20))
+#define PFCNTRA (*(volatile unsigned long *)(ARM_CACHE_CTRL + 0x24))
+#define PFCNTRB_CTRL (*(volatile unsigned long *)(ARM_CACHE_CTRL + 0x28))
+#define PFCNTRB (*(volatile unsigned long *)(ARM_CACHE_CTRL + 0x2C))
+
diff --git a/firmware/target/arm/rk27xx/adc-rk27xx.c b/firmware/target/arm/rk27xx/adc-rk27xx.c
new file mode 100644
index 0000000000..c8bbae7514
--- /dev/null
+++ b/firmware/target/arm/rk27xx/adc-rk27xx.c
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2011 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include "cpu.h"
+#include "system.h"
+#include "kernel.h"
+#include "thread.h"
+#include "adc.h"
+
+unsigned int adc_scan(int channel)
+{
+ ADC_CTRL = (1<<4) | (1<<3) | (channel & (NUM_ADC_CHANNELS - 1));
+
+ /* wait for conversion ready ~10us */
+ while (ADC_STAT & 0x01);
+
+ /* 10bits result */
+ return (ADC_DATA & 0x3ff);
+}
+
+void adc_init(void)
+{
+ /* ADC clock divider to reach max 1MHz */
+ SCU_DIVCON1 = (SCU_DIVCON1 & ~(0xff<<10)) | (49<<10);
+
+ /* enable clocks for ADC */
+ SCU_CLKCFG |= 3<<23;
+}
diff --git a/firmware/target/arm/rk27xx/adc-target.h b/firmware/target/arm/rk27xx/adc-target.h
new file mode 100644
index 0000000000..f6b8c98bb9
--- /dev/null
+++ b/firmware/target/arm/rk27xx/adc-target.h
@@ -0,0 +1,33 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2011 by Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _ADC_TARGET_H_
+#define _ADC_TARGET_H_
+
+#define NUM_ADC_CHANNELS 4
+
+#define ADC_BATTERY 0
+#define ADC_UNKNOWN_1 1
+#define ADC_UNKNOWN_2 2
+#define ADC_VREF 3 /* that is what datasheet says */
+
+#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */
+
+#endif
diff --git a/firmware/target/arm/rk27xx/ata-nand-rk27xx.c b/firmware/target/arm/rk27xx/ata-nand-rk27xx.c
new file mode 100644
index 0000000000..dad49d48d2
--- /dev/null
+++ b/firmware/target/arm/rk27xx/ata-nand-rk27xx.c
@@ -0,0 +1,118 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2007 Dave Chapman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "config.h"
+#include "system.h"
+#include <string.h>
+#include "thread.h"
+#include "disk.h"
+#include "storage.h"
+#include "panic.h"
+#include "usb.h"
+#include "ftl-target.h"
+#include "nand-target.h"
+
+/* This file provides only STUBS for now */
+
+/** static, private data **/
+static bool initialized = false;
+
+/* API Functions */
+int nand_read_sectors(IF_MD2(int drive,) unsigned long start, int incount,
+ void* inbuf)
+{
+ (void)drive;
+ return ftl_read(start, incount, inbuf);
+}
+
+int nand_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
+ const void* outbuf)
+{
+ (void)drive;
+ return ftl_write(start, count, outbuf);
+}
+
+void nand_spindown(int seconds)
+{
+ (void)seconds;
+}
+
+void nand_sleep(void)
+{
+ nand_power_down();
+}
+
+void nand_sleepnow(void)
+{
+ nand_power_down();
+}
+
+void nand_spin(void)
+{
+ nand_set_active();
+}
+
+void nand_enable(bool on)
+{
+ (void)on;
+}
+
+void nand_get_info(IF_MD2(int drive,) struct storage_info *info)
+{
+ (void)drive;
+ uint32_t ppb = ftl_banks * (*ftl_nand_type).pagesperblock;
+ (*info).sector_size = SECTOR_SIZE;
+ (*info).num_sectors = (*ftl_nand_type).userblocks * ppb;
+ (*info).vendor = "Apple";
+ (*info).product = "iPod Nano 2G";
+ (*info).revision = "1.0";
+}
+
+long nand_last_disk_activity(void)
+{
+ return nand_last_activity();
+}
+
+#ifdef HAVE_STORAGE_FLUSH
+int nand_flush(void)
+{
+ int rc = ftl_sync();
+ if (rc != 0) panicf("Failed to unmount flash: %X", rc);
+ return rc;
+}
+#endif
+
+int nand_init(void)
+{
+ if (ftl_init()) return 1;
+
+ initialized = true;
+ return 0;
+}
+
+#ifdef CONFIG_STORAGE_MULTI
+int nand_num_drives(int first_drive)
+{
+ /* We don't care which logical drive number(s) we have been assigned */
+ (void)first_drive;
+
+ return 1;
+}
+#endif
diff --git a/firmware/target/arm/rk27xx/backlight-rk27xx.c b/firmware/target/arm/rk27xx/backlight-rk27xx.c
new file mode 100644
index 0000000000..0d871924ea
--- /dev/null
+++ b/firmware/target/arm/rk27xx/backlight-rk27xx.c
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2011 by Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include <stdbool.h>
+
+#include "config.h"
+#include "backlight.h"
+#include "backlight-target.h"
+#include "system.h"
+
+bool _backlight_init(void)
+{
+ /* configure PD4 as output */
+ GPIO_PDCON |= (1<<4);
+
+ /* set PD4 low (backlight off) */
+ GPIO_PDDR &= ~(1<<4);
+
+ /* IOMUXB - set PWM0 pin as GPIO */
+ SCU_IOMUXB_CON &= ~(1 << 11); /* type<<11<<channel */
+
+ /* setup pwm */
+ PWMT0_CTRL = (0<<9) | (1<<7);
+
+ /* set pwm frequency ~10kHz */
+ /* (apb_freq/pwm_freq)/pwm_div = (50 000 000/10 000)/2 */
+ PWMT0_LRC = 2500;
+ PWMT0_HRC = 1;
+
+ PWMT0_CNTR = 0x00;
+ PWMT0_CTRL = (0<<9) | (1<<3) | (1<<0);
+
+ return true;
+}
+
+void _backlight_on(void)
+{
+ /* enable PWM clock */
+ SCU_CLKCFG &= ~(1<<29);
+
+ /* set output pin as PWM pin */
+ SCU_IOMUXB_CON |= (1<<11); /* type<<11<<channel */
+
+ /* 100% duty cycle. Other settings doesn't work for
+ * unknown reason
+ */
+ PWMT0_HRC = PWMT0_LRC;
+
+ /* pwm enable */
+ PWMT0_CTRL |= (1<<3) | (1<<0);
+}
+
+void _backlight_off(void)
+{
+ /* setup PWM0 pin as GPIO which is pulled low */
+ SCU_IOMUXB_CON &= ~(1<<11);
+
+ /* stop pwm timer */
+ PWMT0_CTRL &= ~(1<<3) | (1<<0);
+
+ /* disable PWM clock */
+ SCU_CLKCFG |= (1<<29);
+}
+
+void _backlight_set_brightness(int brightness)
+{
+ (void)brightness;
+ /* doesn't work for unknown reason */
+}
diff --git a/firmware/target/arm/rk27xx/backlight-target.h b/firmware/target/arm/rk27xx/backlight-target.h
new file mode 100644
index 0000000000..91579b080d
--- /dev/null
+++ b/firmware/target/arm/rk27xx/backlight-target.h
@@ -0,0 +1,29 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2008 by Marcoen Hirschberg
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef BACKLIGHT_TARGET_H
+#define BACKLIGHT_TARGET_H
+
+bool _backlight_init(void);
+void _backlight_on(void);
+void _backlight_off(void);
+void _backlight_set_brightness(int brightness);
+
+#endif
diff --git a/firmware/target/arm/rk27xx/boot.lds b/firmware/target/arm/rk27xx/boot.lds
new file mode 100644
index 0000000000..b7bc9beac0
--- /dev/null
+++ b/firmware/target/arm/rk27xx/boot.lds
@@ -0,0 +1,81 @@
+#include "config.h"
+
+ENTRY(start)
+#ifdef ROCKBOX_LITTLE_ENDIAN
+OUTPUT_FORMAT(elf32-littlearm)
+#else
+OUTPUT_FORMAT(elf32-bigarm)
+#endif
+OUTPUT_ARCH(arm)
+STARTUP(target/arm/rk27xx/crt0.o)
+
+#define DRAMORIG 0x60000000
+#define DRAMSIZE (MEMORYSIZE * 0x100000)
+
+#define IRAMORIG 0x00000000
+#define IRAMSIZE 4K
+
+MEMORY
+{
+ DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
+ IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
+}
+
+SECTIONS
+{
+ .intvect : {
+ _intvectstart = . ;
+ *(.intvect)
+ _intvectend = _newstart ;
+ } > IRAM AT > DRAM
+ _intvectcopy = LOADADDR(.intvect) ;
+
+ .text : {
+ *(.init.text)
+ *(.text*)
+ *(.glue_7*)
+ } > DRAM
+
+ .data : {
+ *(.rodata*)
+ *(.data*)
+ *(.ncdata*);
+ . = ALIGN(0x4);
+ } > DRAM
+
+ .idata : {
+ _datastart = . ;
+ *(.irodata)
+ *(.icode)
+ *(.idata)
+ . = ALIGN(0x4);
+ _dataend = . ;
+ } > DRAM
+ _datacopy = LOADADDR(.idata) ;
+
+ .stack (NOLOAD) :
+ {
+ *(.stack)
+ _stackbegin = .;
+ stackbegin = .;
+ . += 0x2000;
+ _stackend = .;
+ stackend = .;
+ _irqstackbegin = .;
+ . += 0x400;
+ _irqstackend = .;
+ _fiqstackbegin = .;
+ . += 0x400;
+ _fiqstackend = .;
+ } > DRAM
+
+ .bss (NOLOAD) : {
+ _edata = .;
+ *(.bss*);
+ *(.ibss);
+ *(.ncbss*);
+ *(COMMON);
+ . = ALIGN(0x4);
+ _end = .;
+ } > DRAM
+}
diff --git a/firmware/target/arm/rk27xx/crt0.S b/firmware/target/arm/rk27xx/crt0.S
new file mode 100644
index 0000000000..032c637458
--- /dev/null
+++ b/firmware/target/arm/rk27xx/crt0.S
@@ -0,0 +1,209 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id: crt0.S 18776 2008-10-11 18:32:17Z gevaerts $
+ *
+ * Copyright (C) 2008 by Marcoen Hirschberg
+ * Copyright (C) 2008 by Denes Balatoni
+ * Copyright (C) 2010 by Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#define ASM
+#include "config.h"
+#include "cpu.h"
+
+ .section .intvect,"ax",%progbits
+ .global start
+ .global _newstart
+ /* Exception vectors */
+start:
+ b _newstart
+ ldr pc, =undef_instr_handler
+ ldr pc, =software_int_handler
+ ldr pc, =prefetch_abort_handler
+ ldr pc, =data_abort_handler
+ ldr pc, =reserved_handler
+ ldr pc, =irq_handler
+ ldr pc, =fiq_handler
+ .ltorg
+_newstart:
+ ldr pc, =newstart2
+ .section .init.text,"ax",%progbits
+newstart2:
+ msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */
+
+ mov r0, #0x18000000
+ add r0, r0, #0x1c000
+
+ /* setup ARM core freq = 200MHz */
+ /* AHB bus freq (HCLK) = 100MHz */
+ /* APB bus freq (PCLK) = 50MHz */
+ ldr r1, [r0,#0x14] /* SCU_DIVCON1 */
+ orr r1, #9 /* ARM slow mode, HCLK:PCLK = 2:1 */
+ str r1, [r0,#0x14]
+
+ ldr r1,=0x01970c70 /* (1<<24) | (1<<23) | (23<<16) | (199<<4) */
+ str r1, [r0,#0x08]
+
+ ldr r2,=0x40000
+1:
+ ldr r1, [r0,#0x2c] /* SCU_STATUS */
+ tst r1, #1 /* ARM pll lock */
+ bne 1f
+ subs r2, #1
+ bne 1b
+1:
+ ldr r1, [r0,#0x14] /* SCU_DIVCON1 */
+ bic r1, #5 /* leave ARM slow mode, ARMclk:HCLK = 2:1 */
+ str r1, [r0,#0x14]
+
+#if defined(BOOTLOADER)
+ /* remap iram to 0x00000000 */
+ ldr r1,=0xdeadbeef
+ str r1, [r0, #4]
+#endif
+
+#if 0
+ /* setup caches */
+ ldr r0, =0xefff0000 /* cache controler base address */
+ ldrh r1, [r0]
+ strh r1, [r0] /* global cache disable */
+
+ /* setup uncached regions */
+ mov r1, #0x18000000
+ orr r1, r1, #0xfe
+ str r1, [r0,#0x10] /* MemMapA BUS0IP, 32MB */
+ str r1, [r0,#0x14] /* MemMapB BUS0IP, 32MB */
+ mov r1, #0x30000000
+ orr r1, r1, #0xfe
+ str r1, [r0,#0x18] /* MemMapC DSPMEM, 32MB */
+ mov r1, #0xee000000 /* 0xefff0000 & 0xfe000000 */
+ orr r1, r1, #0xfe
+ str r1, [r0,#0x1c] /* MemMapD cache controller, 32MB */
+
+ mov r1, #2 /* invalidate way opcode */
+ str r1, [r0,#4] /* invalidate way0 */
+1:
+ ldr r2, [r0,#4]
+ tst r2, #3
+ bne 1b /* wait for invalidate to complete */
+
+ orr r1, r1, #0x80000000
+ str r1, [r0,#4] /* invalidate way1 */
+1:
+ ldr r2, [r0,#4]
+ tst r2, #3
+ bne 1b /* wait for invalidate to complete */
+
+ ldr r1, [r0]
+ orr r1, r1, #0x80000000
+ str r1, [r0] /* global cache enable */
+#endif
+
+ /* Copy interrupt vectors to iram */
+ ldr r2, =_intvectstart
+ ldr r3, =_intvectend
+ ldr r4, =_intvectcopy
+1:
+ cmp r3, r2
+ ldrhi r1, [r4], #4
+ strhi r1, [r2], #4
+ bhi 1b
+
+ /* Initialise bss section to zero */
+ ldr r2, =_edata
+ ldr r3, =_end
+ mov r4, #0
+1:
+ cmp r3, r2
+ strhi r4, [r2], #4
+ bhi 1b
+
+#ifndef BOOTLOADER
+ /* Copy icode and data to ram */
+ ldr r2, =_iramstart
+ ldr r3, =_iramend
+ ldr r4, =_iramcopy
+1:
+ cmp r3, r2
+ ldrhi r1, [r4], #4
+ strhi r1, [r2], #4
+ bhi 1b
+
+ /* Initialise ibss section to zero */
+ ldr r2, =_iedata
+ ldr r3, =_iend
+ mov r4, #0
+1:
+ cmp r3, r2
+ strhi r4, [r2], #4
+ bhi 1b
+#endif
+
+ /* Set up some stack and munge it with 0xdeadbeef */
+ ldr sp, =stackend
+ ldr r2, =stackbegin
+ ldr r3, =0xdeadbeef
+1:
+ cmp sp, r2
+ strhi r3, [r2], #4
+ bhi 1b
+
+ /* Set up stack for IRQ mode */
+ msr cpsr_c, #0xd2
+ ldr sp, =_irqstackend
+
+ /* Set up stack for FIQ mode */
+ msr cpsr_c, #0xd1
+ ldr sp, =_fiqstackend
+
+ /* Let abort and undefined modes use IRQ stack */
+ msr cpsr_c, #0xd7
+ ldr sp, =_irqstackend
+ msr cpsr_c, #0xdb
+ ldr sp, =_irqstackend
+
+ /* Switch back to supervisor mode */
+ msr cpsr_c, #0xd3
+
+ bl main
+
+ .text
+/* .global UIE*/
+
+/* All illegal exceptions call into UIE with exception address as first
+ * parameter. This is calculated differently depending on which exception
+ * we're in. Second parameter is exception number, used for a string lookup
+ * in UIE. */
+undef_instr_handler:
+ sub r0, lr, #4
+ mov r1, #0
+ b UIE
+
+/* We run supervisor mode most of the time, and should never see a software
+ * exception being thrown. Perhaps make it illegal and call UIE? */
+software_int_handler:
+reserved_handler:
+ movs pc, lr
+
+prefetch_abort_handler:
+ sub r0, lr, #4
+ mov r1, #1
+ b UIE
+
+data_abort_handler:
+ sub r0, lr, #8
+ mov r1, #2
+ b UIE
diff --git a/firmware/target/arm/rk27xx/ftl-rk27xx.c b/firmware/target/arm/rk27xx/ftl-rk27xx.c
new file mode 100644
index 0000000000..40248ab6f3
--- /dev/null
+++ b/firmware/target/arm/rk27xx/ftl-rk27xx.c
@@ -0,0 +1,56 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 by Bertrik Sikken
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include "ftl-target.h"
+
+/* this file provides empty STUBS for now */
+
+uint32_t ftl_init(void)
+{
+ /* TODO implement */
+ return 0;
+}
+
+uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer)
+{
+ /* TODO implement */
+ (void)sector;
+ (void)count;
+ (void)buffer;
+ return 0;
+}
+
+uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer)
+{
+ /* TODO implement */
+ (void)sector;
+ (void)count;
+ (void)buffer;
+ return 0;
+}
+
+uint32_t ftl_sync(void)
+{
+ /* TODO implement */
+ return 0;
+}
+
diff --git a/firmware/target/arm/rk27xx/ftl-target.h b/firmware/target/arm/rk27xx/ftl-target.h
new file mode 100644
index 0000000000..ad4dc04db1
--- /dev/null
+++ b/firmware/target/arm/rk27xx/ftl-target.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 by Michael Sparmann
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __FTL_TARGET_H__
+#define __FTL_TARGET_H__
+
+#include "config.h"
+#include "inttypes.h"
+
+#ifdef BOOTLOADER
+/* Bootloaders don't need write access */
+#define FTL_READONLY
+#endif
+
+/* Pointer to an info structure regarding the flash type used */
+const struct nand_device_info_type* ftl_nand_type;
+
+/* Number of banks we detected a chip on */
+uint32_t ftl_banks;
+
+uint32_t ftl_init(void);
+uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer);
+uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer);
+uint32_t ftl_sync(void);
+
+
+#endif
diff --git a/firmware/target/arm/rk27xx/i2c-rk27xx.c b/firmware/target/arm/rk27xx/i2c-rk27xx.c
new file mode 100644
index 0000000000..34a6f49a32
--- /dev/null
+++ b/firmware/target/arm/rk27xx/i2c-rk27xx.c
@@ -0,0 +1,242 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2011 by Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include "system.h"
+#include "kernel.h"
+#include "i2c-rk27xx.h"
+
+/* NOT TESTED YET */
+
+/* Driver for the rockchip rk27xx built-in I2C controller in master mode
+
+ Both the i2c_read and i2c_write function take the following arguments:
+ * slave, the address of the i2c slave device to read from / write to
+ * address, optional sub-address in the i2c slave (unused if -1)
+ * len, number of bytes to be transfered
+ * data, pointer to data to be transfered
+ A return value other than 0 indicates an error.
+*/
+
+static struct mutex i2c_mtx;
+
+static bool i2c_write_byte(uint8_t data, bool start)
+{
+ long timeout = current_tick + HZ / 50;
+
+ /* START */
+ I2C_CONR |= (1<<3) | (1<<2); /* master port enable, transmit bit */
+ I2C_MTXR = data;
+
+ if (start)
+ I2C_LCMR = (1<<2) | (1<<0); /* resume op, start bit */
+ else
+ I2C_LCMR = (1<<2); /* resume op */
+
+ I2C_CONR &= ~(1<<4); /* ACK enable */
+
+ /* wait for ACK from slave */
+ while ( !(I2C_ISR & (1<<0)) || (I2C_LSR & (1<<0)) )
+ if (TIME_AFTER(current_tick, timeout))
+ return false;
+
+ /* clear status bit */
+ I2C_ISR &= ~(1<<0);
+
+ return true;
+}
+
+static bool i2c_read_byte(unsigned char *data)
+{
+ long timeout = current_tick + HZ / 50;
+
+ I2C_LCMR = (1<<2); /* resume op */
+
+ while (I2C_ISR & (1<<1))
+ if (TIME_AFTER(current_tick, timeout))
+ return false;
+
+ *data = I2C_MRXR;
+
+ /* clear status bit */
+ I2C_ISR &= ~(1<<1);
+
+ return true;
+}
+
+static bool i2c_stop(void)
+{
+ long timeout = current_tick + HZ / 50;
+
+ I2C_CONR &= ~(1<<4);
+ I2C_LCMR |= (1<<2) | (1<<1); /* resume op, stop */
+
+ while (I2C_LCMR & (1<<1))
+ if (TIME_AFTER(current_tick, timeout))
+ return false;
+
+ return true;
+}
+
+/* route i2c bus to internal codec or external bus
+ * internal codec has 0x27 i2c slave address so
+ * access to this address is routed to internal bus.
+ * All other addresses are routed to external pads
+ */
+static void i2c_iomux(unsigned char slave)
+{
+ unsigned long muxa = SCU_IOMUXA_CON & ~(0x1f<<14);
+
+ if (slave == (0x27<<1))
+ {
+ /* internal codec */
+ SCU_IOMUXA_CON = muxa | (1<<16) | (1<<14);
+ }
+ else
+ {
+ /* external I2C bus */
+ SCU_IOMUXA_CON = muxa | (1<<18);
+ }
+}
+
+void i2c_init(void)
+{
+ mutex_init(&i2c_mtx);
+
+ SCU_CLKCFG &= ~(1<< 20);
+
+ I2C_OPR |= (1<<7); /* reset state machine */
+ sleep(HZ/100);
+ I2C_OPR &= ~((1<<7) | (1<<6)); /* clear ENABLE bit, deasert reset */
+
+ /* set I2C divider to stay within allowed SCL freq limit
+ * APBfreq = 50Mhz
+ * SCLfreq = (APBfreq/5*(I2CCDVR[5:3] + 1) * 2^((I2CCDVR[2:0] + 1))
+ */
+ I2C_OPR = (I2C_OPR & ~(0x3F)) | (6<<3) | 1<<0;
+
+ I2C_IER = 0x00;
+
+ I2C_OPR |= (1<<6); /* enable i2c core */
+}
+
+int i2c_write(unsigned char slave, int address, int len,
+ const unsigned char *data)
+{
+ mutex_lock(&i2c_mtx);
+
+ i2c_iomux(slave);
+
+ /* START */
+ if (! i2c_write_byte(slave & ~1, true))
+ {
+ mutex_unlock(&i2c_mtx);
+ return 1;
+ }
+
+ if (address >= 0)
+ {
+ if (! i2c_write_byte(address, false))
+ {
+ mutex_unlock(&i2c_mtx);
+ return 2;
+ }
+ }
+
+ /* write data */
+ while (len--)
+ {
+ if (! i2c_write_byte(*data++, false))
+ {
+ mutex_unlock(&i2c_mtx);
+ return 4;
+ }
+ }
+
+ /* STOP */
+ if (! i2c_stop())
+ {
+ mutex_unlock(&i2c_mtx);
+ return 5;
+ }
+
+ mutex_unlock(&i2c_mtx);
+ return 0;
+}
+
+int i2c_read(unsigned char slave, int address, int len, unsigned char *data)
+{
+ mutex_lock(&i2c_mtx);
+
+ i2c_iomux(slave);
+
+ if (address >= 0)
+ {
+ /* START */
+ if (! i2c_write_byte(slave & ~1, true))
+ {
+ mutex_unlock(&i2c_mtx);
+ return 1;
+ }
+
+ /* write address */
+ if (! i2c_write_byte(address, false))
+ {
+ mutex_unlock(&i2c_mtx);
+ return 2;
+ }
+ }
+
+ /* (repeated) START */
+ if (! i2c_write_byte(slave | 1, true))
+ {
+ mutex_unlock(&i2c_mtx);
+ return 3;
+ }
+
+ I2C_CONR &= ~(1<<3); /* clear transmit bit (switch to receive mode) */
+
+ while (len)
+ {
+ if (! i2c_read_byte(data++))
+ {
+ mutex_unlock(&i2c_mtx);
+ return 4;
+ }
+
+ if (len == 1)
+ I2C_CONR |= (1<<4); /* NACK */
+ else
+ I2C_CONR &= ~(1<<4); /* ACK */
+
+ len--;
+ }
+
+ /* STOP */
+ if (! i2c_stop())
+ {
+ mutex_unlock(&i2c_mtx);
+ return 5;
+ }
+
+ mutex_unlock(&i2c_mtx);
+ return 0;
+}
diff --git a/firmware/target/arm/rk27xx/kernel-rk27xx.c b/firmware/target/arm/rk27xx/kernel-rk27xx.c
new file mode 100644
index 0000000000..d54a09dd1f
--- /dev/null
+++ b/firmware/target/arm/rk27xx/kernel-rk27xx.c
@@ -0,0 +1,54 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2011 by Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "config.h"
+#include "system.h"
+#include "kernel.h"
+
+/* rockchip rk27xx driver for the kernel timer */
+
+/* sys timer ISR */
+void INT_TIMER0(void)
+{
+ /* clear interrupt */
+ TMR0CON &= ~0x04;
+
+ call_tick_tasks(); /* Run through the list of tick tasks */
+}
+
+/* this assumes 50MHz APB bus frequency */
+void tick_start(unsigned int interval_in_ms)
+{
+ unsigned int cycles = 50000 * interval_in_ms;
+
+ /* enable timer clock */
+ SCU_CLKCFG &= (1<<28);
+
+ /* configure timer0 */
+ TMR0LR = cycles;
+ TMR0CON = (1<<8) | (1<<7) | (1<<1); /* periodic, 1/1, interrupt enable */
+
+ /* unmask timer0 interrupt */
+ INTC_IMR |= 0x04;
+
+ /* enable timer0 interrupt */
+ INTC_IECR |= 0x04;
+}
+
diff --git a/firmware/target/arm/rk27xx/lcd-rk27xx.c b/firmware/target/arm/rk27xx/lcd-rk27xx.c
new file mode 100644
index 0000000000..bb71458195
--- /dev/null
+++ b/firmware/target/arm/rk27xx/lcd-rk27xx.c
@@ -0,0 +1,304 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2011 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include "kernel.h"
+#include "lcd.h"
+#include "system.h"
+#include "cpu.h"
+#include "spfd5420a.h"
+
+static inline void delay_nop(int cycles)
+{
+ asm volatile ("1: subs %[n], %[n], #1 \n\t"
+ " bne 1b"
+ :
+ : [n] "r" (cycles));
+}
+
+static unsigned int lcd_data_transform(unsigned int data)
+{
+ /* 18 bit interface */
+ unsigned int r, g, b;
+ r = (data & 0x0000fc00)<<8;
+ /* g = ((data & 0x00000300) >> 2) | ((data & 0x000000e0) >> 3); */
+ g = ((data & 0x00000300) << 6) | ((data & 0x000000e0) << 5);
+ b = (data & 0x00000001f) << 3;
+
+ return (r | g | b);
+}
+
+/* converts RGB565 pixel into internal lcd bus format */
+static unsigned int lcd_pixel_transform(unsigned short rgb565)
+{
+ unsigned int r, g, b;
+ b = rgb565 & 0x1f;
+ g = (rgb565 >> 5) & 0x3f;
+ r = (rgb565 >> 11) & 0x1f;
+
+ return r<<19 | g<<10 | b<<3;
+}
+
+static void lcd_cmd(unsigned int cmd)
+{
+ LCD_COMMAND = lcd_data_transform(cmd);
+}
+
+static void lcd_data(unsigned int data)
+{
+ LCD_DATA = lcd_data_transform(data);
+}
+
+static void lcd_write_reg(unsigned int reg, unsigned int val)
+{
+ lcd_cmd(reg);
+ lcd_data(val);
+}
+
+static void lcdctrl_bypass(unsigned int on_off)
+{
+ while (!(LCDC_STA & LCDC_MCU_IDLE));
+
+ if (on_off)
+ MCU_CTRL |= MCU_CTRL_BYPASS;
+ else
+ MCU_CTRL &= ~MCU_CTRL_BYPASS;
+}
+
+/* This part is unclear. I am unable to use buffered/FIFO based writes
+ * to lcd. Depending on settings of IF I get various patterns on display
+ * but not what I want to display apparently.
+ */
+static void lcdctrl_init(void)
+{
+ /* alpha b111
+ * stop at current frame complete
+ * MCU mode
+ * 24b RGB
+ */
+ LCDC_CTRL = ALPHA(7) | LCDC_STOP | LCDC_MCU | RGB24B;
+ MCU_CTRL = ALPHA_BASE(0x3f) | MCU_CTRL_BYPASS;
+
+ HOR_ACT = 400 + 3; /* define horizonatal active region */
+ VERT_ACT = 240; /* define vertical active region */
+ VERT_PERIOD = 0xfff; /* CSn/WEn/RDn signal timings */
+
+ LINE0_YADDR = LINE_ALPHA_EN | 0x7fe;
+ LINE1_YADDR = LINE_ALPHA_EN | ((1 * 400) - 2);
+ LINE2_YADDR = LINE_ALPHA_EN | ((2 * 400) - 2);
+ LINE3_YADDR = LINE_ALPHA_EN | ((3 * 400) - 2);
+
+ LINE0_UVADDR = 0x7fe + 1;
+ LINE1_UVADDR = ((1 * 400) - 2 + 1);
+ LINE2_UVADDR = ((2 * 400) - 2 + 1);
+ LINE3_UVADDR = ((3 * 400) - 2 + 1);
+
+#if 0
+ LINE0_YADDR = 0;
+ LINE1_YADDR = (1 * 400);
+ LINE2_YADDR = (2 * 400);
+ LINE3_YADDR = (3 * 400);
+
+ LINE0_UVADDR = 1;
+ LINE1_UVADDR = (1 * 400) + 1;
+ LINE2_UVADDR = (2 * 400) + 1;
+ LINE3_UVADDR = (3 * 400) + 1;
+
+ START_X = 0;
+ START_Y = 0;
+ DELTA_X = 0x200; /* no scaling */
+ DELTA_Y = 0x200; /* no scaling */
+#endif
+ LCDC_INTR_MASK = INTR_MASK_LINE; /* INTR_MASK_EVENLINE; */
+}
+
+/* configure pins to drive lcd in 18bit mode */
+static void iomux_lcd(void)
+{
+ unsigned long muxa;
+
+ muxa = SCU_IOMUXA_CON & ~(IOMUX_LCD_VSYNC|IOMUX_LCD_DEN|0xff);
+ muxa |= IOMUX_LCD_D18|IOMUX_LCD_D20|IOMUX_LCD_D22|IOMUX_LCD_D17|IOMUX_LCD_D16;
+
+ SCU_IOMUXA_CON = muxa;
+ SCU_IOMUXB_CON |= IOMUX_LCD_D815;
+}
+
+/* not tested */
+static void lcd_sleep(unsigned int sleep)
+{
+ if (sleep)
+ {
+ /* enter sleep mode */
+ lcd_write_reg(DISPLAY_CTRL1, 0x0170);
+ delay_nop(50);
+ lcd_write_reg(DISPLAY_CTRL1, 0x0000);
+ delay_nop(50);
+ lcd_write_reg(PWR_CTRL1, 0x14B4);
+ }
+ else
+ {
+ /* return to normal operation */
+ lcd_write_reg(PWR_CTRL1, 0x14B0);
+ delay_nop(50);
+ lcd_write_reg(DISPLAY_CTRL1, 0x0173);
+ }
+
+ lcd_cmd(GRAM_WRITE);
+}
+
+void lcd_init_device()
+{
+ unsigned int x, y;
+
+ iomux_lcd(); /* setup pins for 18bit lcd interface */
+ lcdctrl_init(); /* basic lcdc module configuration */
+
+ lcdctrl_bypass(1); /* run in bypass mode - all writes goes directly to lcd controller */
+
+ lcd_write_reg(RESET, 0x0001);
+ delay_nop(10000);
+ lcd_write_reg(RESET, 0x0000);
+ delay_nop(10000);
+ lcd_write_reg(IF_ENDIAN, 0x0000); /* order of receiving data */
+ lcd_write_reg(DRIVER_OUT_CTRL, 0x0000);
+ lcd_write_reg(ENTRY_MODE, 0x1038);
+ lcd_write_reg(WAVEFORM_CTRL, 0x0100);
+ lcd_write_reg(SHAPENING_CTRL, 0x0000);
+ lcd_write_reg(DISPLAY_CTRL2, 0x0808);
+ lcd_write_reg(LOW_PWR_CTRL1, 0x0001);
+ lcd_write_reg(LOW_PWR_CTRL2, 0x0010);
+ lcd_write_reg(EXT_DISP_CTRL1, 0x0000);
+ lcd_write_reg(EXT_DISP_CTRL2, 0x0000);
+ lcd_write_reg(BASE_IMG_SIZE, 0x3100);
+ lcd_write_reg(BASE_IMG_CTRL, 0x0001);
+ lcd_write_reg(VSCROLL_CTRL, 0x0000);
+ lcd_write_reg(PART1_POS, 0x0000);
+ lcd_write_reg(PART1_START, 0x0000);
+ lcd_write_reg(PART1_END, 0x018F);
+ lcd_write_reg(PART2_POS, 0x0000);
+ lcd_write_reg(PART2_START, 0x0000);
+ lcd_write_reg(PART2_END, 0x0000);
+
+ lcd_write_reg(PANEL_IF_CTRL1, 0x0011);
+ delay_nop(10000);
+ lcd_write_reg(PANEL_IF_CTRL2, 0x0202);
+ lcd_write_reg(PANEL_IF_CTRL3, 0x0300);
+ delay_nop(10000);
+ lcd_write_reg(PANEL_IF_CTRL4, 0x021E);
+ lcd_write_reg(PANEL_IF_CTRL5, 0x0202);
+ lcd_write_reg(PANEL_IF_CTRL6, 0x0100);
+ lcd_write_reg(FRAME_MKR_CTRL, 0x0000);
+ lcd_write_reg(MDDI_CTRL, 0x0000);
+
+ lcd_write_reg(GAMMA_CTRL1, 0x0101);
+ lcd_write_reg(GAMMA_CTRL2, 0x0000);
+ lcd_write_reg(GAMMA_CTRL3, 0x0016);
+ lcd_write_reg(GAMMA_CTRL4, 0x2913);
+ lcd_write_reg(GAMMA_CTRL5, 0x260B);
+ lcd_write_reg(GAMMA_CTRL6, 0x0101);
+ lcd_write_reg(GAMMA_CTRL7, 0x1204);
+ lcd_write_reg(GAMMA_CTRL8, 0x0415);
+ lcd_write_reg(GAMMA_CTRL9, 0x0205);
+ lcd_write_reg(GAMMA_CTRL10, 0x0303);
+ lcd_write_reg(GAMMA_CTRL11, 0x0E05);
+ lcd_write_reg(GAMMA_CTRL12, 0x0D01);
+ lcd_write_reg(GAMMA_CTRL13, 0x010D);
+ lcd_write_reg(GAMMA_CTRL14, 0x050E);
+ lcd_write_reg(GAMMA_CTRL15, 0x0303);
+ lcd_write_reg(GAMMA_CTRL16, 0x0502);
+
+ /* power on */
+ lcd_write_reg(DISPLAY_CTRL1, 0x0001);
+ lcd_write_reg(PWR_CTRL6, 0x0001);
+ lcd_write_reg(PWR_CTRL7, 0x0060);
+ delay_nop(50000);
+ lcd_write_reg(PWR_CTRL1, 0x16B0);
+ delay_nop(10000);
+ lcd_write_reg(PWR_CTRL2, 0x0147);
+ delay_nop(10000);
+ lcd_write_reg(PWR_CTRL3, 0x0117);
+ delay_nop(10000);
+ lcd_write_reg(PWR_CTRL4, 0x2F00);
+ delay_nop(50000);
+ lcd_write_reg(VCOM_HV2, 0x0000); /* src 0x0090 */
+ delay_nop(10000);
+ lcd_write_reg(VCOM_HV1, 0x0008); /* src 0x000A */
+ lcd_write_reg(PWR_CTRL3, 0x01BE);
+ delay_nop(10000);
+
+ /* addresses setup */
+ lcd_write_reg(WINDOW_H_START, 0x0000);
+ lcd_write_reg(WINDOW_H_END, 0x00EF); /* 239 */
+ lcd_write_reg(WINDOW_V_START, 0x0000);
+ lcd_write_reg(WINDOW_V_END, 0x018F); /* 399 */
+ lcd_write_reg(GRAM_H_ADDR, 0x0000);
+ lcd_write_reg(GRAM_V_ADDR, 0x0000);
+
+ /* display on */
+ lcd_write_reg(DISPLAY_CTRL1, 0x0021);
+ delay_nop(40000);
+ lcd_write_reg(DISPLAY_CTRL1, 0x0061);
+ delay_nop(100000);
+ lcd_write_reg(DISPLAY_CTRL1, 0x0173);
+ delay_nop(300000);
+
+
+ /* clear screen */
+ lcd_cmd(GRAM_WRITE);
+
+ for (x=0; x<400; x++)
+ for(y=0; y<240; y++)
+ lcd_data(0x000000);
+
+ lcd_sleep(0);
+}
+
+/* This is ugly hack. We drive lcd in bypass mode
+ * where all writes goes directly to lcd controller.
+ * This is suboptimal at best. IF module povides
+ * FIFO, internal sram buffer, hardware scaller,
+ * DMA signals, hardware alpha blending and more.
+ * BUT the fact is that I have no idea how to use
+ * this modes. Datasheet floating around is very
+ * unclean in this regard and OF uses ackward
+ * lcd update routines which are hard to understand.
+ * Moreover OF sets some bits in IF module registers
+ * which are referred as reseved in datasheet.
+ */
+void lcd_update()
+{
+ unsigned int x,y;
+
+ for (y=0; y<240; y++)
+ for (x=0; x<400; x++)
+ LCD_DATA = lcd_pixel_transform(lcd_framebuffer[y][x]);
+}
+
+/* not implemented yet */
+void lcd_update_rect(int x, int y, int width, int height)
+{
+ (void)x;
+ (void)y;
+ (void)width;
+ (void)height;
+ lcd_update();
+}
diff --git a/firmware/target/arm/rk27xx/nand-target.h b/firmware/target/arm/rk27xx/nand-target.h
new file mode 100644
index 0000000000..dee690e5e6
--- /dev/null
+++ b/firmware/target/arm/rk27xx/nand-target.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 by Michael Sparmann
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __NAND_TARGET_H__
+#define __NAND_TARGET_H__
+
+#include "config.h"
+#include "inttypes.h"
+
+
+struct nand_device_info_type
+{
+ uint32_t id;
+ uint16_t blocks;
+ uint16_t userblocks;
+ uint16_t pagesperblock;
+ uint8_t blocksizeexponent;
+ uint8_t tunk1;
+ uint8_t twp;
+ uint8_t tunk2;
+ uint8_t tunk3;
+} __attribute__((packed));
+
+uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer,
+ void* sparebuffer, uint32_t doecc,
+ uint32_t checkempty);
+uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer,
+ void* sparebuffer, uint32_t doecc);
+uint32_t nand_block_erase(uint32_t bank, uint32_t page);
+
+const struct nand_device_info_type* nand_get_device_type(uint32_t bank);
+uint32_t nand_reset(uint32_t bank);
+uint32_t nand_device_init(void);
+void nand_set_active(void);
+long nand_last_activity(void);
+void nand_power_up(void);
+void nand_power_down(void);
+
+
+#endif
diff --git a/firmware/target/arm/rk27xx/rk27generic/button-rk27generic.c b/firmware/target/arm/rk27xx/rk27generic/button-rk27generic.c
new file mode 100644
index 0000000000..cd60482b0f
--- /dev/null
+++ b/firmware/target/arm/rk27xx/rk27generic/button-rk27generic.c
@@ -0,0 +1,39 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2011 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include "cpu.h"
+#include "system.h"
+#include "button.h"
+
+void button_init_device(void)
+{
+ /* setup button gpios as input */
+ GPIO_PCCON &= ~(BUTTON_MAIN);
+}
+
+/*
+ * Get button pressed from hardware
+ */
+int button_read_device(void)
+{
+ return (GPIO_PCDR & BUTTON_MAIN);
+}
diff --git a/firmware/target/arm/rk27xx/rk27generic/button-target.h b/firmware/target/arm/rk27xx/rk27generic/button-target.h
new file mode 100644
index 0000000000..cc14dfc32b
--- /dev/null
+++ b/firmware/target/arm/rk27xx/rk27generic/button-target.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2011 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _BUTTON_TARGET_H_
+#define _BUTTON_TARGET_H_
+
+#include <stdbool.h>
+#include "config.h"
+
+void button_init_device(void);
+int button_read_device(void);
+
+/* Main unit's buttons */
+/* values assigned corespond to GPIOs numbers */
+#define BUTTON_PLAY 0x00000002
+
+#define BUTTON_REW 0x00000008
+#define BUTTON_FF 0x00000004
+#define BUTTON_VOL 0x00000040
+#define BUTTON_M 0x00000010
+
+#define BUTTON_LEFT BUTTON_REW
+#define BUTTON_RIGHT BUTTON_FF
+#define BUTTON_ON BUTTON_PLAY
+
+#define BUTTON_REMOTE 0
+
+#define BUTTON_MAIN (BUTTON_PLAY|BUTTON_REW|BUTTON_FF|\
+ BUTTON_VOL|BUTTON_M)
+
+#define POWEROFF_BUTTON BUTTON_PLAY
+#define POWEROFF_COUNT 30
+
+#endif /* _BUTTON_TARGET_H_ */
diff --git a/firmware/target/arm/rk27xx/sd-rk27xx.c b/firmware/target/arm/rk27xx/sd-rk27xx.c
new file mode 100644
index 0000000000..c5a23ad00d
--- /dev/null
+++ b/firmware/target/arm/rk27xx/sd-rk27xx.c
@@ -0,0 +1,719 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Daniel Ankers
+ * Copyright © 2008-2009 Rafaël Carré
+ * Copyright (C) 2011 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h" /* for HAVE_MULTIVOLUME */
+#include "fat.h"
+#include "thread.h"
+#include "gcc_extensions.h"
+#include "led.h"
+#include "sdmmc.h"
+#include "system.h"
+#include "kernel.h"
+#include "cpu.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "panic.h"
+#include "stdbool.h"
+#include "ata_idle_notify.h"
+#include "sd.h"
+#include "usb.h"
+
+#ifdef HAVE_HOTSWAP
+#include "disk.h"
+#endif
+
+#include "lcd.h"
+#include <stdarg.h>
+#include "sysfont.h"
+
+#define RES_NO (-1)
+
+static tCardInfo card_info;
+
+/* for compatibility */
+static long last_disk_activity = -1;
+
+static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)];
+static const char sd_thread_name[] = "ata/sd";
+static struct mutex sd_mtx SHAREDBSS_ATTR;
+static struct event_queue sd_queue;
+#ifndef BOOTLOADER
+bool sd_enabled = false;
+#endif
+
+static struct semaphore transfer_completion_signal;
+static struct semaphore command_completion_signal;
+static volatile bool retry;
+static volatile int cmd_error;
+
+/* interrupt handler for SD */
+void INT_SD(void)
+{
+ const int status = SD_INT;
+
+ SD_INT = 0; /* disable sd interrupts, clear pending interrupts */
+
+ /* cmd and response status pending */
+ if(status & CMD_RES_STAT)
+ {
+ /* get the status */
+ cmd_error = SD_CMDRES;
+ semaphore_release(&command_completion_signal);
+ }
+
+ /* data transfer status pending */
+ if(status & DATA_XFER_STAT)
+ {
+ cmd_error = SD_DATAT;
+ if (cmd_error & DATA_XFER_ERR)
+ retry = true;
+
+ semaphore_release(&transfer_completion_signal);
+ }
+
+ SD_INT = CMD_RES_INT_EN | DATA_XFER_INT_EN;
+}
+
+/* Exchange buffers - the one where SD module puts into/reads from
+ * data and the one controlled by MCU. This allows some overlap
+ * in transfer operations and should increase throuput.
+ */
+static void mmu_switch_buff(void)
+{
+ static unsigned int i = 0;
+
+ if (i++ & 0x01)
+ {
+ MMU_CTRL = MMU_MMU0_BUFII | MMU_CPU_BUFI | MMU_BUFII_RESET |
+ MMU_BUFII_BYTE | MMU_BUFI_RESET | MMU_BUFI_WORD;
+ }
+ else
+ {
+ MMU_CTRL = MMU_MMU0_BUFI | MMU_CPU_BUFII | MMU_BUFII_RESET |
+ MMU_BUFII_WORD | MMU_BUFI_RESET | MMU_BUFI_BYTE;
+ }
+}
+
+/* Reset internal pointers of the MMU submodule */
+static void mmu_buff_reset(void)
+{
+ MMU_CTRL |= MMU_BUFII_RESET | MMU_BUFI_RESET;
+}
+
+/* My generic device uses PC7 pin, active low */
+static inline bool card_detect_target(void)
+{
+ return !(GPIO_PCDR & 0x80);
+}
+
+/* Send command to the SD card. Command finish is signaled in ISR */
+static bool send_cmd(const int cmd, const int arg, const int res,
+ unsigned long *response)
+{
+ SD_CMD = arg;
+
+ if (res > 0)
+ SD_CMDREST = CMD_XFER_START | RES_XFER_START | res | cmd;
+ else
+ SD_CMDREST = CMD_XFER_START | RES_XFER_END | RES_R1 | cmd;
+
+ semaphore_wait(&command_completion_signal, TIMEOUT_BLOCK);
+
+ /* Handle command responses & errors */
+ if(res != RES_NO)
+ {
+ if(cmd_error & STAT_CMD_RES_ERR)
+ return false;
+
+ if(res == RES_R2)
+ {
+ response[0] = SD_RES3;
+ response[1] = SD_RES2;
+ response[2] = SD_RES1;
+ response[3] = SD_RES0;
+ }
+ else
+ response[0] = SD_RES3;
+ }
+ return true;
+}
+
+#if 0
+/* for some misterious reason the card does not report itself as being in TRAN
+ * but transfers are successful. Rockchip OF does not check the card state
+ * after SELECT. I checked two different cards.
+ */
+static void print_card_status(void)
+{
+ unsigned long response;
+ send_cmd(SD_SEND_STATUS, card_info.rca, RES_R1,
+ &response);
+
+ printf("card status: 0x%0x, state: 0x%0x", response, (response>>9)&0xf);
+}
+
+static int sd_wait_for_tran_state(void)
+{
+ unsigned long response;
+ unsigned int timeout = current_tick + 5*HZ;
+ int cmd_retry = 10;
+
+ while (1)
+ {
+ while (!send_cmd(SD_SEND_STATUS, card_info.rca, RES_R1,
+ &response) && cmd_retry > 0)
+ {
+ cmd_retry--;
+ }
+
+ if (cmd_retry <= 0)
+ {
+ return -1;
+ }
+
+ if (((response >> 9) & 0xf) == SD_TRAN)
+ {
+ return 0;
+ }
+
+ if(TIME_AFTER(current_tick, timeout))
+ {
+ return -10 * ((response >> 9) & 0xf);
+ }
+
+ last_disk_activity = current_tick;
+ }
+}
+#endif
+
+static bool sd_wait_card_busy(void)
+{
+ unsigned int timeout = current_tick + 5*HZ;
+
+ while (!(SD_CARD & SD_CARD_BSY))
+ {
+ if(TIME_AFTER(current_tick, timeout))
+ return false;
+ }
+
+ return true;
+}
+
+static int sd_init_card(void)
+{
+ unsigned long response;
+ long init_timeout;
+ bool sd_v2 = false;
+
+ card_info.rca = 0;
+
+ /* assume 50 MHz APB freq / 125 = 400 kHz */
+ SD_CTRL = (SD_CTRL & ~(0x7FF)) | 0x7D;
+
+ /* 100 - 400kHz clock required for Identification Mode */
+ /* Start of Card Identification Mode ************************************/
+
+ /* CMD0 Go Idle */
+ if(!send_cmd(SD_GO_IDLE_STATE, 0, RES_NO, NULL))
+ return -1;
+
+ sleep(1);
+
+ /* CMD8 Check for v2 sd card. Must be sent before using ACMD41
+ Non v2 cards will not respond to this command*/
+ if(send_cmd(SD_SEND_IF_COND, 0x1AA, RES_R6, &response))
+ if((response & 0xFFF) == 0x1AA)
+ sd_v2 = true;
+
+ /* timeout for initialization is 1sec, from SD Specification 2.00 */
+ init_timeout = current_tick + HZ;
+
+ do {
+ /* this timeout is the only valid error for this loop*/
+ if(TIME_AFTER(current_tick, init_timeout))
+ return -2;
+
+ if(!send_cmd(SD_APP_CMD, card_info.rca, RES_R1, &response))
+ return -3;
+
+ sleep(1); /* bus conflict otherwise */
+
+ /* ACMD41 For v2 cards set HCS bit[30] & send host voltage range to all */
+ if(!send_cmd(SD_APP_OP_COND, (0x00FF8000 | (sd_v2 ? 1<<30 : 0)),
+ RES_R3, &card_info.ocr))
+ return -4;
+ } while(!(card_info.ocr & (1<<31)) );
+
+ /* CMD2 send CID */
+ if(!send_cmd(SD_ALL_SEND_CID, 0, RES_R2, card_info.cid))
+ return -5;
+
+ /* CMD3 send RCA */
+ if(!send_cmd(SD_SEND_RELATIVE_ADDR, 0, RES_R6, &card_info.rca))
+ return -6;
+
+ /* End of Card Identification Mode ************************************/
+
+ /* Card back to full speed 25MHz*/
+ SD_CTRL = (SD_CTRL & ~0x7FF) | 1; /* FIXME check this divider - OF uses 0 here*/
+
+ /* CMD9 send CSD */
+ if(!send_cmd(SD_SEND_CSD, card_info.rca, RES_R2, card_info.csd))
+ return -11;
+
+ sd_parse_csd(&card_info);
+
+ if(!send_cmd(SD_SELECT_CARD, card_info.rca, RES_R1b, &response))
+ return -20;
+
+ if (!sd_wait_card_busy())
+ return -21;
+
+ card_info.initialized = 1;
+
+ return 0;
+}
+
+static void sd_thread(void) NORETURN_ATTR;
+static void sd_thread(void)
+{
+ struct queue_event ev;
+ bool idle_notified = false;
+
+ while (1)
+ {
+ queue_wait_w_tmo(&sd_queue, &ev, HZ);
+
+ switch ( ev.id )
+ {
+#ifdef HAVE_HOTSWAP
+ case SYS_HOTSWAP_INSERTED:
+ case SYS_HOTSWAP_EXTRACTED:
+ {
+ int microsd_init = 1;
+ fat_lock(); /* lock-out FAT activity first -
+ prevent deadlocking via disk_mount that
+ would cause a reverse-order attempt with
+ another thread */
+ mutex_lock(&sd_mtx); /* lock-out card activity - direct calls
+ into driver that bypass the fat cache */
+
+ /* We now have exclusive control of fat cache and ata */
+
+ disk_unmount(sd_first_drive); /* release "by force", ensure file
+ descriptors aren't leaked and any busy
+ ones are invalid if mounting */
+ /* Force card init for new card, re-init for re-inserted one or
+ * clear if the last attempt to init failed with an error. */
+ card_info.initialized = 0;
+
+ if (ev.id == SYS_HOTSWAP_INSERTED)
+ {
+ sd_enable(true);
+ microsd_init = sd_init_card(sd_first_drive);
+ if (microsd_init < 0) /* initialisation failed */
+ panicf("microSD init failed : %d", microsd_init);
+
+ microsd_init = disk_mount(sd_first_drive); /* 0 if fail */
+ }
+
+ /*
+ * Mount succeeded, or this was an EXTRACTED event,
+ * in both cases notify the system about the changed filesystems
+ */
+ if (microsd_init)
+ queue_broadcast(SYS_FS_CHANGED, 0);
+
+ sd_enable(false);
+
+ /* Access is now safe */
+ mutex_unlock(&sd_mtx);
+ fat_unlock();
+ }
+ break;
+#endif
+ case SYS_TIMEOUT:
+ if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
+ {
+ idle_notified = false;
+ }
+ else if (!idle_notified)
+ {
+ call_storage_idle_notifys(false);
+ idle_notified = true;
+ }
+ break;
+
+ case SYS_USB_CONNECTED:
+ usb_acknowledge(SYS_USB_CONNECTED_ACK);
+ /* Wait until the USB cable is extracted again */
+ usb_wait_for_disconnect(&sd_queue);
+
+ break;
+ }
+ }
+}
+
+static void init_controller(void)
+{
+ /* reset SD module */
+ SCU_RSTCFG |= (1<<9);
+ sleep(1);
+ SCU_RSTCFG &= ~(1<<9);
+
+ /* set pins functions as SD signals */
+ SCU_IOMUXA_CON |= IOMUX_SD;
+
+ /* enable and unmask SD interrupts in interrupt controller */
+ INTC_IMR |= (1<<10);
+ INTC_IECR |= (1<<10);
+
+ SD_CTRL = SD_PWR_CPU | SD_DETECT_MECH | SD_CLOCK_EN | 0x7D;
+ SD_INT = CMD_RES_INT_EN | DATA_XFER_INT_EN;
+ SD_CARD = SD_CARD_SELECT | SD_CARD_PWR_EN;
+
+ /* setup mmu buffers */
+ MMU_PNRI = 0x1ff;
+ MMU_PNRII = 0x1ff;
+ MMU_CTRL = MMU_MMU0_BUFII | MMU_CPU_BUFI | MMU_BUFII_RESET |
+ MMU_BUFII_BYTE | MMU_BUFI_RESET | MMU_BUFI_WORD;
+
+}
+
+int sd_init(void)
+{
+ int ret;
+
+ semaphore_init(&transfer_completion_signal, 1, 0);
+ semaphore_init(&command_completion_signal, 1, 0);
+
+ init_controller();
+
+ ret = sd_init_card();
+ if(ret < 0)
+ return ret;
+
+ /* init mutex */
+ mutex_init(&sd_mtx);
+
+ queue_init(&sd_queue, true);
+ create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
+ sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU));
+
+ return 0;
+}
+
+int sd_read_sectors(IF_MD2(int drive,) unsigned long start, int count,
+ void* buf)
+{
+#ifdef HAVE_MULTIDRIVE
+ (void)drive;
+#endif
+ unsigned long response;
+ unsigned int retry_cnt = 0;
+ int cnt, ret = 0;
+ unsigned char *dst;
+
+ mutex_lock(&sd_mtx);
+ sd_enable(true);
+
+ if (count <= 0 || start + count > card_info.numblocks)
+ return -1;
+
+ if(!(card_info.ocr & (1<<30)))
+ start <<= 9; /* not SDHC */
+
+ /* setup A2A DMA CH0 */
+ A2A_ISRC0 = (unsigned long)(&MMU_DATA);
+ A2A_ICNT0 = 512;
+ A2A_LCNT0 = 1;
+ A2A_DOMAIN = 0;
+
+ while (retry_cnt++ < 20)
+ {
+ cnt = count;
+ dst = (unsigned char *)buf;
+
+ ret = 0;
+ retry = false; /* reset retry flag */
+ mmu_buff_reset(); /* reset recive buff state */
+
+ /* issue read command to the card */
+ if (!send_cmd(SD_READ_MULTIPLE_BLOCK, start, RES_R1, &response))
+ {
+ ret = -4;
+ continue;
+ }
+
+ while (cnt > 0)
+ {
+ if (cnt == 1)
+ {
+ /* last block to tranfer */
+ SD_DATAT = DATA_XFER_START | DATA_XFER_READ |
+ DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
+ DATA_XFER_SINGLE;
+ }
+ else
+ {
+ /* more than one block to transfer */
+ SD_DATAT = DATA_XFER_START | DATA_XFER_READ |
+ DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
+ DATA_XFER_MULTI;
+ }
+
+ /* wait for transfer completion */
+ semaphore_wait(&transfer_completion_signal, TIMEOUT_BLOCK);
+
+ if (retry)
+ {
+ /* data transfer error */
+ ret = -5;
+ break;
+ }
+
+ /* exchange buffers */
+ mmu_switch_buff();
+
+ last_disk_activity = current_tick;
+
+ /* transfer data from receive buffer to the dest
+ * for (i=0; i<(512/4); i++)
+ * *dst++ = MMU_DATA;
+ *
+ * below is DMA version in software mode.
+ * SD module provides DMAreq signals and all this
+ * can be done in hardware in theory but I can't
+ * figure this out. OF doesn't use DMA at all.
+ */
+ A2A_IDST0 = (unsigned long)dst;
+ A2A_CON0 = (3<<9) | (1<<6) | (1<<3) | (2<<1) | (1<<0);
+
+ /* wait for DMA engine to finish transfer */
+ while (A2A_DMA_STS & 1);
+
+ dst += 512;
+ cnt--;
+ } /* while (cnt > 0) */
+
+ if (!send_cmd(SD_STOP_TRANSMISSION, 0, RES_R1b, &response))
+ ret = -6;
+
+ /* transfer successfull - leave retry loop */
+ if (ret == 0)
+ break;
+ }
+
+ sd_enable(false);
+ mutex_unlock(&sd_mtx);
+
+ return ret;
+}
+
+/* Not tested */
+int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
+ const void* buf)
+{
+#ifdef HAVE_MULTIDRIVE
+ (void) drive;
+#endif
+#if defined(BOOTLOADER) /* we don't need write support in bootloader */
+ (void) start;
+ (void) count;
+ (void) buf;
+ return -1;
+#else
+ unsigned long response;
+ unsigned int retry_cnt = 0;
+ int cnt, ret = 0;
+ unsigned char *src;
+ bool card_selected = false;
+
+ mutex_lock(&sd_mtx);
+ sd_enable(true);
+
+ if (count <= 0 || start + count > card_info.numblocks)
+ return -1;
+
+ if(!(card_info.ocr & (1<<30)))
+ start <<= 9; /* not SDHC */
+
+ /* setup A2A DMA CH0 */
+ A2A_IDST0 = (unsigned long)(&MMU_DATA);
+ A2A_ICNT0 = 512;
+ A2A_LCNT0 = 1;
+ A2A_DOMAIN = 0;
+
+ while (retry_cnt++ < 20)
+ {
+ cnt = count;
+ src = (unsigned char *)buf;
+
+ ret = 0;
+ retry = false; /* reset retry flag */
+ mmu_buff_reset(); /* reset recive buff state */
+
+ if (!send_cmd(SD_WRITE_MULTIPLE_BLOCK, start, RES_R1, &response))
+ {
+ ret = -3;
+ continue;
+ }
+
+ while (cnt > 0)
+ {
+ /* transfer data from receive buffer to the dest
+ * for (i=0; i<(512/4); i++)
+ * MMU_DATA = *src++;
+ *
+ * Below is DMA version in software mode.
+ */
+
+ A2A_ISRC0 = (unsigned long)src;
+ A2A_CON0 = (3<<9) | (1<<5) | (1<<3) | (2<<1) | (1<<0);
+
+ while (A2A_DMA_STS & 1);
+
+ src += 512;
+
+ /* exchange buffers */
+ mmu_switch_buff();
+
+ if (cnt == 1)
+ {
+ /* last block to tranfer */
+ SD_DATAT = DATA_XFER_START | DATA_XFER_WRITE |
+ DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
+ DATA_XFER_SINGLE;
+
+ }
+ else
+ {
+ /* more than one block to transfer */
+ SD_DATAT = DATA_XFER_START | DATA_XFER_WRITE |
+ DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
+ DATA_XFER_MULTI;
+
+ }
+
+ /* wait for transfer completion */
+ semaphore_wait(&transfer_completion_signal, TIMEOUT_BLOCK);
+
+ if (retry)
+ {
+ /* data transfer error */
+ ret = -3;
+ break;
+ }
+
+ cnt--;
+ } /* while (cnt > 0) */
+
+ if (!send_cmd(SD_STOP_TRANSMISSION, 0, RES_R1b, &response))
+ ret = -4;
+
+ if (!sd_wait_card_busy())
+ ret = -5;
+
+ /* transfer successfull - leave retry loop */
+ if (ret == 0)
+ break;
+ }
+
+ sd_enable(false);
+ mutex_unlock(&sd_mtx);
+
+ return ret;
+
+#endif /* defined(BOOTLOADER) */
+}
+
+void sd_enable(bool on)
+{
+ /* enable or disable clock signal for SD module */
+ if (on)
+ {
+ SCU_CLKCFG &= ~(1<<22);
+ }
+ else
+ {
+ SCU_CLKCFG |= (1<<22);
+ }
+}
+
+#ifndef BOOTLOADER
+long sd_last_disk_activity(void)
+{
+ return last_disk_activity;
+}
+
+tCardInfo *card_get_info_target(int card_no)
+{
+ (void)card_no;
+ return &card_info;
+}
+#endif /* BOOTLOADER */
+
+#ifdef HAVE_HOTSWAP
+/* Not complete and disabled in config */
+bool sd_removable(IF_MD_NONVOID(int drive))
+{
+ (void)drive;
+ return true;
+}
+
+bool sd_present(IF_MD_NONVOID(int drive))
+{
+ (void)drive;
+ return card_detect_target();
+}
+
+static int sd_oneshot_callback(struct timeout *tmo)
+{
+ (void)tmo;
+
+ /* This is called only if the state was stable for 300ms - check state
+ * and post appropriate event. */
+ if (card_detect_target())
+ {
+ queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
+ }
+ else
+ queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
+
+ return 0;
+}
+
+/* interrupt handler for SD detect */
+
+#endif /* HAVE_HOTSWAP */
+
+#ifdef CONFIG_STORAGE_MULTI
+int sd_num_drives(int first_drive)
+{
+ (void)first_drive;
+
+ /* we have only one SD drive */
+ return 1;
+}
+#endif /* CONFIG_STORAGE_MULTI */
diff --git a/firmware/target/arm/rk27xx/spfd5420a.h b/firmware/target/arm/rk27xx/spfd5420a.h
new file mode 100644
index 0000000000..fcb998dfd1
--- /dev/null
+++ b/firmware/target/arm/rk27xx/spfd5420a.h
@@ -0,0 +1,107 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2011 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#define ID_READ 0x000
+#define DRIVER_OUT_CTRL 0x001
+#define WAVEFORM_CTRL 0x002
+#define ENTRY_MODE 0x003
+/* 0x004 - 0x005 reserved */
+#define SHAPENING_CTRL 0x006 /* not present in datasheet */
+#define DISPLAY_CTRL1 0x007
+#define DISPLAY_CTRL2 0x008
+#define LOW_PWR_CTRL1 0x009
+/* 0x00A reserved */
+#define LOW_PWR_CTRL2 0x00B
+#define EXT_DISP_CTRL1 0x00C
+/* 0x00D - 0x00E reserved */
+#define EXT_DISP_CTRL2 0x00F
+#define PANEL_IF_CTRL1 0x010
+#define PANEL_IF_CTRL2 0x011
+#define PANEL_IF_CTRL3 0x012
+/* 0x013 - 0x01F reserved */
+#define PANEL_IF_CTRL4 0x020
+#define PANEL_IF_CTRL5 0x021
+#define PANEL_IF_CTRL6 0x022
+/* 0x023 - 0x08F reserved */
+#define FRAME_MKR_CTRL 0x090
+/* 0x091 reserved */
+#define MDDI_CTRL 0x092 /* not present in datasheet */
+/* 0x093 - 0x0FF reserved */
+#define PWR_CTRL1 0x100
+#define PWR_CTRL2 0x101
+#define PWR_CTRL3 0x102
+#define PWR_CTRL4 0x103 /* amplitude to VCOM */
+/* 0x104 - 0x106 reserved */
+#define PWR_CTRL5 0x107
+/* 0x108 - 0x10F reserved */
+#define PWR_CTRL6 0x110
+#define PWR_CTRL7 0x112 /* not present in datasheet */
+/* 0x113 - 0x1FF reserved */
+#define GRAM_H_ADDR 0x200
+#define GRAM_V_ADDR 0x201
+#define GRAM_READ 0x202
+#define GRAM_WRITE 0x202
+/* 0x203 - 0x20F reserved */
+#define WINDOW_H_START 0x210
+#define WINDOW_H_END 0x211
+#define WINDOW_V_START 0x212
+#define WINDOW_V_END 0x213
+/* 0x214 - 0x27F reserved */
+#define NVM_READ 0x280
+#define NVM_WRITE 0x280
+#define VCOM_HV1 0x281
+#define VCOM_HV2 0x282
+/* 0x283 - 0x2FF reserved */
+#define GAMMA_CTRL1 0x300
+#define GAMMA_CTRL2 0x301
+#define GAMMA_CTRL3 0x302
+#define GAMMA_CTRL4 0x303
+#define GAMMA_CTRL5 0x304
+#define GAMMA_CTRL6 0x305
+#define GAMMA_CTRL7 0x306
+#define GAMMA_CTRL8 0x307
+#define GAMMA_CTRL9 0x308
+#define GAMMA_CTRL10 0x309
+#define GAMMA_CTRL11 0x30A
+#define GAMMA_CTRL12 0x30B
+#define GAMMA_CTRL13 0x30C
+#define GAMMA_CTRL14 0x30D
+#define GAMMA_CTRL15 0x30E
+#define GAMMA_CTRL16 0x30F
+/* 0x310 - 0x3FF reserved */
+#define BASE_IMG_SIZE 0x400
+#define BASE_IMG_CTRL 0x401
+/* 0x402 - 0x403 reserved */
+#define VSCROLL_CTRL 0x404
+/* 0x405 - 0x4FF reserved */
+#define PART1_POS 0x500
+#define PART1_START 0x501
+#define PART1_END 0x502
+#define PART2_POS 0x503
+#define PART2_START 0x504
+#define PART2_END 0x505
+/* 0x506 - 0x5FF reserved */
+#define RESET 0x600 /* not present in datasheet */
+/* 0x601 - 0x605 */
+#define IF_ENDIAN 0x606
+/* 0x607 - 0x6EF reserved */
+#define NVM_CTRL 0x6F0
+/* 0x6F1 - 0xFFF reserved */
diff --git a/firmware/target/arm/rk27xx/system-rk27xx.c b/firmware/target/arm/rk27xx/system-rk27xx.c
new file mode 100644
index 0000000000..67024a5fea
--- /dev/null
+++ b/firmware/target/arm/rk27xx/system-rk27xx.c
@@ -0,0 +1,164 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2011 by Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "kernel.h"
+#include "system.h"
+#include "panic.h"
+#include "system-target.h"
+
+#define default_interrupt(name) \
+ extern __attribute__((weak,alias("UIRQ"))) void name (void)
+
+void irq_handler(void) __attribute__((interrupt ("IRQ"), naked));
+void fiq_handler(void) __attribute__((interrupt ("FIQ"), naked, \
+ weak, alias("fiq_dummy")));
+
+default_interrupt(INT_UART0);
+default_interrupt(INT_UART1);
+default_interrupt(INT_TIMER0);
+default_interrupt(INT_TIMER1);
+default_interrupt(INT_TIMER2);
+default_interrupt(INT_GPIO0);
+default_interrupt(INT_SW_INT0);
+default_interrupt(INT_AHB0_MAILBOX);
+default_interrupt(INT_RTC);
+default_interrupt(INT_SCU);
+default_interrupt(INT_SD);
+default_interrupt(INT_SPI);
+default_interrupt(INT_HDMA);
+default_interrupt(INT_A2A_BRIDGE);
+default_interrupt(INT_I2C);
+default_interrupt(INT_I2S);
+default_interrupt(INT_UDC);
+default_interrupt(INT_UHC);
+default_interrupt(INT_PWM0);
+default_interrupt(INT_PWM1);
+default_interrupt(INT_PWM2);
+default_interrupt(INT_ADC);
+default_interrupt(INT_GPIO1);
+default_interrupt(INT_VIP);
+default_interrupt(INT_DWDMA);
+default_interrupt(INT_NANDC);
+default_interrupt(INT_LCDC);
+default_interrupt(INT_DSP);
+default_interrupt(INT_SW_INT1);
+default_interrupt(INT_SW_INT2);
+default_interrupt(INT_SW_INT3);
+
+static void (* const irqvector[])(void) =
+{
+ INT_UART0,INT_UART1,INT_TIMER0,INT_TIMER1,INT_TIMER2,INT_GPIO0,INT_SW_INT0,INT_AHB0_MAILBOX,
+ INT_RTC,INT_SCU,INT_SD,INT_SPI,INT_HDMA,INT_A2A_BRIDGE,INT_I2C,
+ INT_I2S,INT_UDC,INT_UHC,INT_PWM0,INT_PWM1,INT_PWM2,INT_ADC,INT_GPIO1,
+ INT_VIP,INT_DWDMA,INT_NANDC,INT_LCDC,INT_DSP,INT_SW_INT1,INT_SW_INT2,INT_SW_INT3
+};
+
+static const char * const irqname[] =
+{
+ "INT_UART0","INT_UART1","INT_TIMER0","INT_TIMER1","INT_TIMER2","INT_GPIO0","INT_SW_INT0","INT_AHB0_MAILBOX",
+ "INT_RTC","INT_SCU","INT_SD","INT_SPI","INT_HDMA","INT_A2A_BRIDGE","INT_I2C",
+ "INT_I2S","INT_UDC","INT_UHC","INT_PWM0","INT_PWM1","INT_PWM2","INT_ADC","INT_GPIO1",
+ "INT_VIP","INT_DWDMA","INT_NANDC","INT_LCDC","INT_DSP","INT_SW_INT1","INT_SW_INT2","INT_SW_INT3"
+};
+
+static void UIRQ(void)
+{
+ unsigned int offset = INTC_ISR & 0x1f;
+ panicf("Unhandled IRQ %02X: %s", offset, irqname[offset]);
+}
+
+void irq_handler(void)
+{
+ /*
+ * Based on: linux/arch/arm/kernel/entry-armv.S and system-meg-fx.c
+ */
+
+ asm volatile( "stmfd sp!, {r0-r7, ip, lr} \n" /* Store context */
+ "sub sp, sp, #8 \n"); /* Reserve stack */
+
+ int irq_no = INTC_ISR & 0x1f;
+
+ irqvector[irq_no]();
+
+ /* clear interrupt */
+ INTC_ICCR = (1 << irq_no);
+
+ asm volatile( "add sp, sp, #8 \n" /* Cleanup stack */
+ "ldmfd sp!, {r0-r7, ip, lr} \n" /* Restore context */
+ "subs pc, lr, #4 \n"); /* Return from IRQ */
+}
+
+void fiq_dummy(void)
+{
+ asm volatile (
+ "subs pc, lr, #4 \r\n"
+ );
+}
+
+
+void system_init(void)
+{
+ return;
+}
+
+/* not tested */
+void system_reboot(void)
+{
+ /* use Watchdog to reset */
+ WDTLR = 1;
+ WDTCON = (1<<4) | (1<<3);
+
+ /* Wait for reboot to kick in */
+ while(1);
+}
+
+void system_exception_wait(void)
+{
+ while(1);
+}
+
+int system_memory_guard(int newmode)
+{
+ (void)newmode;
+ return 0;
+}
+
+/* usecs may be at most 2^32/200 (~21 seconds) for 200MHz max cpu freq */
+void udelay(unsigned usecs)
+{
+ unsigned cycles_per_usec;
+ unsigned delay;
+
+ if (cpu_frequency == CPUFREQ_MAX) {
+ cycles_per_usec = (CPUFREQ_MAX + 999999) / 1000000;
+ } else {
+ cycles_per_usec = (CPUFREQ_NORMAL + 999999) / 1000000;
+ }
+
+ delay = (usecs * cycles_per_usec + 3) / 4;
+
+ asm volatile(
+ "1: subs %0, %0, #1 \n" /* 1 cycle */
+ " bne 1b \n" /* 3 cycles */
+ : : "r"(delay)
+ );
+}
+
diff --git a/firmware/target/arm/rk27xx/system-target.h b/firmware/target/arm/rk27xx/system-target.h
new file mode 100644
index 0000000000..fb904091b1
--- /dev/null
+++ b/firmware/target/arm/rk27xx/system-target.h
@@ -0,0 +1,44 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2008 Rafaël Carré
+ * Copyright (C) 2011 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef SYSTEM_TARGET_H
+#define SYSTEM_TARGET_H
+
+#include "system-arm.h"
+#include "panic.h"
+
+void udelay(unsigned usecs);
+static inline void mdelay(unsigned msecs)
+{
+ udelay(1000 * msecs);
+}
+
+/* this needs more testing */
+static inline void core_sleep(void)
+{
+ enable_irq();
+ SCU_CPUPD = 0xdeedbabe;
+}
+
+#define CPUFREQ_NORMAL 200000000
+#define CPUFREQ_MAX 200000000
+
+#endif /* SYSTEM_TARGET_H */
diff --git a/firmware/target/arm/rk27xx/timer-rk27xx.c b/firmware/target/arm/rk27xx/timer-rk27xx.c
new file mode 100644
index 0000000000..4493ccdfa9
--- /dev/null
+++ b/firmware/target/arm/rk27xx/timer-rk27xx.c
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2011 by Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+
+#include "inttypes.h"
+#include "system.h"
+#include "timer.h"
+
+void INT_TIMER1(void)
+{
+ /* clear interrupt */
+ TMR1CON &= ~(1<<2);
+
+ if (pfn_timer != NULL)
+ {
+ pfn_timer();
+ }
+}
+
+bool timer_set(long cycles, bool start)
+{
+ /* optionally unregister any previously registered timer user */
+ if (start)
+ {
+ if (pfn_unregister != NULL)
+ {
+ pfn_unregister();
+ pfn_unregister = NULL;
+ }
+ }
+
+ TMR1LR = cycles;
+ TMR1CON = (1<<7) | (1<<1); /* periodic, 1/1 */
+
+ /* unmask timer1 interrupt */
+ INTC_IMR |= (1<<3);
+
+ /* enable timer1 interrupt */
+ INTC_IECR |= (1<<3);
+
+ return true;
+}
+
+bool timer_start(void)
+{
+ TMR1CON |= (1 << 8); /* timer1 enable */
+
+ return true;
+}
+
+void timer_stop(void)
+{
+ TMR1CON &= ~(1 << 8); /* timer1 disable */
+}
+
diff --git a/firmware/target/arm/thread-arm.c b/firmware/target/arm/thread-arm.c
index 84a3aecbd7..83bdb9288d 100644
--- a/firmware/target/arm/thread-arm.c
+++ b/firmware/target/arm/thread-arm.c
@@ -109,7 +109,7 @@ static inline void core_sleep(void)
}
#else
/* Skip this if special code is required and implemented */
-#ifndef CPU_PP
+#if !(defined(CPU_PP)) && CONFIG_CPU != RK27XX
static inline void core_sleep(void)
{
#warning core_sleep not implemented, battery life will be decreased
diff --git a/tools/configure b/tools/configure
index 96953c8b50..d988e75d63 100755
--- a/tools/configure
+++ b/tools/configure
@@ -500,6 +500,13 @@ arm1176jzscc () {
endian="little"
}
+arm7ejscc () {
+ findarmgcc
+ GCCOPTS="$CCOPTS -march=armv5te"
+ GCCOPTIMIZE="-fomit-frame-pointer"
+ endian="little"
+}
+
mipselcc () {
prefixtools mipsel-elf-
# mips is predefined, but we want it for paths. use __mips instead
@@ -1271,8 +1278,8 @@ cat <<EOF
200) SDL 170) HD200 131) Mini2440
201) Android 171) HD300
202) Nokia N8xx
- 203) Nokia N900
- 204) Pandora
+ 203) Nokia N900 ==ROCKCHIP==
+ 204) Pandora 180) rk27xx generic
EOF
@@ -2969,6 +2976,29 @@ fi
t_model="hd300"
;;
+ 180|rk27generic)
+ target_id=78
+ modelname="rk27generic"
+ target="-DRK27_GENERIC"
+ memory=16 # always
+ arm7ejscc
+ tool="$rootdir/tools/scramble -add=rk27"
+ bmp2rb_mono="$rootdir/tools/bmp2rb -f 0"
+ bmp2rb_native="$rootdir/tools/bmp2rb -f 4"
+ output="rockbox.rk27"
+ bootoutput="bootloader.rk27"
+ appextra="recorder:gui:radio"
+ plugins="yes"
+ swcodec="yes"
+ # toolset is the tools within the tools directory that we build for
+ # this particular target.
+ toolset="$genericbitmaptools"
+ # architecture, manufacturer and model for the target-tree build
+ t_cpu="arm"
+ t_manufacturer="rk27xx"
+ t_model="rk27generic"
+ ;;
+
200|sdlapp)
application="yes"
target_id=73
diff --git a/tools/scramble.c b/tools/scramble.c
index dbf41fde44..683973321c 100644
--- a/tools/scramble.c
+++ b/tools/scramble.c
@@ -126,7 +126,7 @@ void usage(void)
printf("\t 9200, 1630, 6330, ldax, m200, c100, clip, e2v2,\n"
"\t m2v4, fuze, c2v2, clv2, y820, y920, y925, x747,\n"
"\t 747p, x777, nn2g, m244, cli+, fuz2, hd20, hd30,\n"
- "\t ip6g)\n");
+ "\t ip6g, rk27)\n");
printf("\nNo option results in Archos standard player/recorder format.\n");
exit(1);
@@ -337,6 +337,8 @@ int main (int argc, char** argv)
modelnum = 71;
else if (!strcmp(&argv[1][5], "fuz+")) /* Sansa Fuze+ */
modelnum = 72;
+ else if (!strcmp(&argv[1][5], "rk27")) /* rockchip 27xx generic */
+ modelnum = 73;
else {
fprintf(stderr, "unsupported model: %s\n", &argv[1][5]);
return 2;