aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/orion/patches
diff options
context:
space:
mode:
authorImre Kaloz <kaloz@openwrt.org>2008-06-04 13:51:17 +0000
committerImre Kaloz <kaloz@openwrt.org>2008-06-04 13:51:17 +0000
commit7bb65fb9d7860faa4b9b1e07790fb5823a0249e2 (patch)
tree701aabf12d94bdeddafbf8d328dee2492eef9ad5 /target/linux/orion/patches
parent0244e57bb9fb9ebd1dd224bd5789ad9cc24b0175 (diff)
downloadupstream-7bb65fb9d7860faa4b9b1e07790fb5823a0249e2.tar.gz
upstream-7bb65fb9d7860faa4b9b1e07790fb5823a0249e2.tar.bz2
upstream-7bb65fb9d7860faa4b9b1e07790fb5823a0249e2.zip
add preliminary Marvell Orion support
SVN-Revision: 11352
Diffstat (limited to 'target/linux/orion/patches')
-rw-r--r--target/linux/orion/patches/001-latencytop_support.patch82
-rw-r--r--target/linux/orion/patches/002-feroceon__speed_up_flushing_of_the_entire_cache.patch117
-rw-r--r--target/linux/orion/patches/003-fix_various_whitespace_and_coding_style.patch647
-rw-r--r--target/linux/orion/patches/004-make_window_setup_a_little_more_safe.patch79
-rw-r--r--target/linux/orion/patches/005-dram_mapping_granularity_is_64kib.patch26
-rw-r--r--target/linux/orion/patches/006-add_a_separate_BRIDGE_INT_TIMER1_CLR_define.patch37
-rw-r--r--target/linux/orion/patches/007-annotate_88fr531-vd_cpu_entries.patch58
-rw-r--r--target/linux/orion/patches/008-top-level_irqs_are_level-triggered.patch35
-rw-r--r--target/linux/orion/patches/009-delete_unused_IO_SPACE_REMAP_define.patch17
-rw-r--r--target/linux/orion/patches/010-move_EHCI_I2C_UART_peripheral_init.patch710
-rw-r--r--target/linux/orion/patches/011-move_setting_up_pcie_wa_window_into_pcie.patch90
-rw-r--r--target/linux/orion/patches/012-rework_mpp_handling.patch583
-rw-r--r--target/linux/orion/patches/013-add_88f5181l_support.patch56
-rw-r--r--target/linux/orion/patches/014-avoid_setting_force_phy_addr.patch71
-rw-r--r--target/linux/orion/patches/015-implement_power-off_method_for_kurobox_pro.patch192
-rw-r--r--target/linux/orion/patches/016-add_qnap_ts-409_support.patch418
-rw-r--r--target/linux/orion/patches/017-add_linksys_wrt350n_v2_support.patch205
-rw-r--r--target/linux/orion/patches/018-add_hp_media_vault_mv2120_support.patch263
-rw-r--r--target/linux/orion/patches/019-add_technologic_systems_ts-78xx_support.patch305
19 files changed, 3991 insertions, 0 deletions
diff --git a/target/linux/orion/patches/001-latencytop_support.patch b/target/linux/orion/patches/001-latencytop_support.patch
new file mode 100644
index 0000000000..a1fbc17f54
--- /dev/null
+++ b/target/linux/orion/patches/001-latencytop_support.patch
@@ -0,0 +1,82 @@
+From: Nicolas Pitre <nico@cam.org>
+
+Signed-off-by: Nicolas Pitre <nico@marvell.com>
+Tested-by: Lennert Buytenhek <buytenh@marvell.com>
+Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
+---
+ arch/arm/Kconfig | 4 ++++
+ arch/arm/kernel/stacktrace.c | 26 ++++++++++++++++++++++----
+ 2 files changed, 26 insertions(+), 4 deletions(-)
+
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -84,6 +84,10 @@
+ bool
+ default y
+
++config HAVE_LATENCYTOP_SUPPORT
++ bool
++ default y
++
+ config LOCKDEP_SUPPORT
+ bool
+ default y
+--- a/arch/arm/kernel/stacktrace.c
++++ b/arch/arm/kernel/stacktrace.c
+@@ -36,6 +36,7 @@
+ #ifdef CONFIG_STACKTRACE
+ struct stack_trace_data {
+ struct stack_trace *trace;
++ unsigned int no_sched_functions;
+ unsigned int skip;
+ };
+
+@@ -43,27 +44,44 @@
+ {
+ struct stack_trace_data *data = d;
+ struct stack_trace *trace = data->trace;
++ unsigned long addr = frame->lr;
+
++ if (data->no_sched_functions && in_sched_functions(addr))
++ return 0;
+ if (data->skip) {
+ data->skip--;
+ return 0;
+ }
+
+- trace->entries[trace->nr_entries++] = frame->lr;
++ trace->entries[trace->nr_entries++] = addr;
+
+ return trace->nr_entries >= trace->max_entries;
+ }
+
+-void save_stack_trace(struct stack_trace *trace)
++void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
+ {
+ struct stack_trace_data data;
+ unsigned long fp, base;
+
+ data.trace = trace;
+ data.skip = trace->skip;
+- base = (unsigned long)task_stack_page(current);
+- asm("mov %0, fp" : "=r" (fp));
++ base = (unsigned long)task_stack_page(tsk);
++
++ if (tsk != current) {
++ data.no_sched_functions = 1;
++ fp = thread_saved_fp(tsk);
++ } else {
++ data.no_sched_functions = 0;
++ asm("mov %0, fp" : "=r" (fp));
++ }
+
+ walk_stackframe(fp, base, base + THREAD_SIZE, save_trace, &data);
++ if (trace->nr_entries < trace->max_entries)
++ trace->entries[trace->nr_entries++] = ULONG_MAX;
++}
++
++void save_stack_trace(struct stack_trace *trace)
++{
++ save_stack_trace_tsk(current, trace);
+ }
+ #endif
diff --git a/target/linux/orion/patches/002-feroceon__speed_up_flushing_of_the_entire_cache.patch b/target/linux/orion/patches/002-feroceon__speed_up_flushing_of_the_entire_cache.patch
new file mode 100644
index 0000000000..c2efe5be22
--- /dev/null
+++ b/target/linux/orion/patches/002-feroceon__speed_up_flushing_of_the_entire_cache.patch
@@ -0,0 +1,117 @@
+Flushing the L1 D cache with a test/clean/invalidate loop is very
+easy in software, but it is not the quickest way of doing it, as
+there is a lot of overhead involved in re-scanning the cache from
+the beginning every time we hit a dirty line.
+
+This patch makes proc-feroceon.S use "clean+invalidate by set/way"
+loops according to possible cache configuration of Feroceon CPUs
+(either direct-mapped or 4-way set associative).
+
+[nico: optimized the assembly a bit]
+
+Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
+Signed-off-by: Nicolas Pitre <nico@marvell.com>
+---
+ arch/arm/mm/proc-feroceon.S | 53 ++++++++++++++++++++++++++++++++++---------
+ 1 files changed, 42 insertions(+), 11 deletions(-)
+
+--- a/arch/arm/mm/proc-feroceon.S
++++ b/arch/arm/mm/proc-feroceon.S
+@@ -44,11 +44,31 @@
+ */
+ #define CACHE_DLINESIZE 32
+
++ .bss
++ .align 3
++__cache_params_loc:
++ .space 8
++
+ .text
++__cache_params:
++ .word __cache_params_loc
++
+ /*
+ * cpu_feroceon_proc_init()
+ */
+ ENTRY(cpu_feroceon_proc_init)
++ mrc p15, 0, r0, c0, c0, 1 @ read cache type register
++ ldr r1, __cache_params
++ mov r2, #(16 << 5)
++ tst r0, #(1 << 16) @ get way
++ mov r0, r0, lsr #18 @ get cache size order
++ movne r3, #((4 - 1) << 30) @ 4-way
++ and r0, r0, #0xf
++ moveq r3, #0 @ 1-way
++ mov r2, r2, lsl r0 @ actual cache size
++ movne r2, r2, lsr #2 @ turned into # of sets
++ sub r2, r2, #(1 << 5)
++ stmia r1, {r2, r3}
+ mov pc, lr
+
+ /*
+@@ -117,11 +137,19 @@
+ */
+ ENTRY(feroceon_flush_kern_cache_all)
+ mov r2, #VM_EXEC
+- mov ip, #0
++
+ __flush_whole_cache:
+-1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate
+- bne 1b
++ ldr r1, __cache_params
++ ldmia r1, {r1, r3}
++1: orr ip, r1, r3
++2: mcr p15, 0, ip, c7, c14, 2 @ clean + invalidate D set/way
++ subs ip, ip, #(1 << 30) @ next way
++ bcs 2b
++ subs r1, r1, #(1 << 5) @ next set
++ bcs 1b
++
+ tst r2, #VM_EXEC
++ mov ip, #0
+ mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
+ mcrne p15, 0, ip, c7, c10, 4 @ drain WB
+ mov pc, lr
+@@ -138,7 +166,6 @@
+ */
+ .align 5
+ ENTRY(feroceon_flush_user_cache_range)
+- mov ip, #0
+ sub r3, r1, r0 @ calculate total size
+ cmp r3, #CACHE_DLIMIT
+ bgt __flush_whole_cache
+@@ -152,6 +179,7 @@
+ cmp r0, r1
+ blo 1b
+ tst r2, #VM_EXEC
++ mov ip, #0
+ mcrne p15, 0, ip, c7, c10, 4 @ drain WB
+ mov pc, lr
+
+@@ -306,16 +334,19 @@
+ .align 5
+ ENTRY(cpu_feroceon_switch_mm)
+ #ifdef CONFIG_MMU
+- mov ip, #0
+-@ && 'Clean & Invalidate whole DCache'
+-1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate
+- bne 1b
+- mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
+- mcr p15, 0, ip, c7, c10, 4 @ drain WB
++ mov r2, lr @ abuse r2 to preserve lr
++ bl __flush_whole_cache
++ @ if r2 contains the VM_EXEC bit then the next 2 ops are done already
++ tst r2, #VM_EXEC
++ mcreq p15, 0, ip, c7, c5, 0 @ invalidate I cache
++ mcreq p15, 0, ip, c7, c10, 4 @ drain WB
++
+ mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
+ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
+-#endif
++ mov pc, r2
++#else
+ mov pc, lr
++#endif
+
+ /*
+ * cpu_feroceon_set_pte_ext(ptep, pte, ext)
diff --git a/target/linux/orion/patches/003-fix_various_whitespace_and_coding_style.patch b/target/linux/orion/patches/003-fix_various_whitespace_and_coding_style.patch
new file mode 100644
index 0000000000..02126ca33f
--- /dev/null
+++ b/target/linux/orion/patches/003-fix_various_whitespace_and_coding_style.patch
@@ -0,0 +1,647 @@
+More cosmetic cleanup:
+- Replace 8-space indents by proper tab indents.
+- In structure initialisers, use a trailing comma for every member.
+- Collapse "},\n{" in structure initialiers to "}, {".
+
+Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
+---
+ arch/arm/mach-orion5x/common.c | 91 +++++++++++--------------
+ arch/arm/mach-orion5x/db88f5281-setup.c | 13 ++--
+ arch/arm/mach-orion5x/dns323-setup.c | 33 +++++----
+ arch/arm/mach-orion5x/kurobox_pro-setup.c | 8 +--
+ arch/arm/mach-orion5x/pci.c | 14 ++--
+ arch/arm/mach-orion5x/rd88f5182-setup.c | 3 +-
+ arch/arm/mach-orion5x/ts209-setup.c | 103 +++++++++++++++--------------
+ arch/arm/mm/proc-feroceon.S | 8 +-
+ 8 files changed, 132 insertions(+), 141 deletions(-)
+
+--- a/arch/arm/mach-orion5x/common.c
++++ b/arch/arm/mach-orion5x/common.c
+@@ -39,25 +39,22 @@
+ .virtual = ORION5X_REGS_VIRT_BASE,
+ .pfn = __phys_to_pfn(ORION5X_REGS_PHYS_BASE),
+ .length = ORION5X_REGS_SIZE,
+- .type = MT_DEVICE
+- },
+- {
++ .type = MT_DEVICE,
++ }, {
+ .virtual = ORION5X_PCIE_IO_VIRT_BASE,
+ .pfn = __phys_to_pfn(ORION5X_PCIE_IO_PHYS_BASE),
+ .length = ORION5X_PCIE_IO_SIZE,
+- .type = MT_DEVICE
+- },
+- {
++ .type = MT_DEVICE,
++ }, {
+ .virtual = ORION5X_PCI_IO_VIRT_BASE,
+ .pfn = __phys_to_pfn(ORION5X_PCI_IO_PHYS_BASE),
+ .length = ORION5X_PCI_IO_SIZE,
+- .type = MT_DEVICE
+- },
+- {
++ .type = MT_DEVICE,
++ }, {
+ .virtual = ORION5X_PCIE_WA_VIRT_BASE,
+ .pfn = __phys_to_pfn(ORION5X_PCIE_WA_PHYS_BASE),
+ .length = ORION5X_PCIE_WA_SIZE,
+- .type = MT_DEVICE
++ .type = MT_DEVICE,
+ },
+ };
+
+@@ -75,18 +72,15 @@
+ .start = UART0_PHYS_BASE,
+ .end = UART0_PHYS_BASE + 0xff,
+ .flags = IORESOURCE_MEM,
+- },
+- {
++ }, {
+ .start = IRQ_ORION5X_UART0,
+ .end = IRQ_ORION5X_UART0,
+ .flags = IORESOURCE_IRQ,
+- },
+- {
++ }, {
+ .start = UART1_PHYS_BASE,
+ .end = UART1_PHYS_BASE + 0xff,
+ .flags = IORESOURCE_MEM,
+- },
+- {
++ }, {
+ .start = IRQ_ORION5X_UART1,
+ .end = IRQ_ORION5X_UART1,
+ .flags = IORESOURCE_IRQ,
+@@ -102,8 +96,7 @@
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = ORION5X_TCLK,
+- },
+- {
++ }, {
+ .mapbase = UART1_PHYS_BASE,
+ .membase = (char *)UART1_VIRT_BASE,
+ .irq = IRQ_ORION5X_UART1,
+@@ -111,8 +104,8 @@
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = ORION5X_TCLK,
++ }, {
+ },
+- { },
+ };
+
+ static struct platform_device orion5x_uart = {
+@@ -134,8 +127,7 @@
+ .start = ORION5X_USB0_PHYS_BASE,
+ .end = ORION5X_USB0_PHYS_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+- },
+- {
++ }, {
+ .start = IRQ_ORION5X_USB0_CTRL,
+ .end = IRQ_ORION5X_USB0_CTRL,
+ .flags = IORESOURCE_IRQ,
+@@ -147,8 +139,7 @@
+ .start = ORION5X_USB1_PHYS_BASE,
+ .end = ORION5X_USB1_PHYS_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+- },
+- {
++ }, {
+ .start = IRQ_ORION5X_USB1_CTRL,
+ .end = IRQ_ORION5X_USB1_CTRL,
+ .flags = IORESOURCE_IRQ,
+@@ -219,7 +210,7 @@
+ .start = IRQ_ORION5X_ETH_SUM,
+ .end = IRQ_ORION5X_ETH_SUM,
+ .flags = IORESOURCE_IRQ,
+- }
++ },
+ };
+
+ static struct platform_device orion5x_eth = {
+@@ -251,16 +242,15 @@
+
+ static struct resource orion5x_i2c_resources[] = {
+ {
+- .name = "i2c base",
+- .start = I2C_PHYS_BASE,
+- .end = I2C_PHYS_BASE + 0x20 -1,
+- .flags = IORESOURCE_MEM,
+- },
+- {
+- .name = "i2c irq",
+- .start = IRQ_ORION5X_I2C,
+- .end = IRQ_ORION5X_I2C,
+- .flags = IORESOURCE_IRQ,
++ .name = "i2c base",
++ .start = I2C_PHYS_BASE,
++ .end = I2C_PHYS_BASE + 0x20 -1,
++ .flags = IORESOURCE_MEM,
++ }, {
++ .name = "i2c irq",
++ .start = IRQ_ORION5X_I2C,
++ .end = IRQ_ORION5X_I2C,
++ .flags = IORESOURCE_IRQ,
+ },
+ };
+
+@@ -270,7 +260,7 @@
+ .num_resources = ARRAY_SIZE(orion5x_i2c_resources),
+ .resource = orion5x_i2c_resources,
+ .dev = {
+- .platform_data = &orion5x_i2c_pdata,
++ .platform_data = &orion5x_i2c_pdata,
+ },
+ };
+
+@@ -278,28 +268,27 @@
+ * Sata port
+ ****************************************************************************/
+ static struct resource orion5x_sata_resources[] = {
+- {
+- .name = "sata base",
+- .start = ORION5X_SATA_PHYS_BASE,
+- .end = ORION5X_SATA_PHYS_BASE + 0x5000 - 1,
+- .flags = IORESOURCE_MEM,
+- },
+ {
+- .name = "sata irq",
+- .start = IRQ_ORION5X_SATA,
+- .end = IRQ_ORION5X_SATA,
+- .flags = IORESOURCE_IRQ,
+- },
++ .name = "sata base",
++ .start = ORION5X_SATA_PHYS_BASE,
++ .end = ORION5X_SATA_PHYS_BASE + 0x5000 - 1,
++ .flags = IORESOURCE_MEM,
++ }, {
++ .name = "sata irq",
++ .start = IRQ_ORION5X_SATA,
++ .end = IRQ_ORION5X_SATA,
++ .flags = IORESOURCE_IRQ,
++ },
+ };
+
+ static struct platform_device orion5x_sata = {
+- .name = "sata_mv",
+- .id = 0,
++ .name = "sata_mv",
++ .id = 0,
+ .dev = {
+ .coherent_dma_mask = 0xffffffff,
+ },
+- .num_resources = ARRAY_SIZE(orion5x_sata_resources),
+- .resource = orion5x_sata_resources,
++ .num_resources = ARRAY_SIZE(orion5x_sata_resources),
++ .resource = orion5x_sata_resources,
+ };
+
+ void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data)
+@@ -319,7 +308,7 @@
+ }
+
+ struct sys_timer orion5x_timer = {
+- .init = orion5x_timer_init,
++ .init = orion5x_timer_init,
+ };
+
+ /*****************************************************************************
+--- a/arch/arm/mach-orion5x/db88f5281-setup.c
++++ b/arch/arm/mach-orion5x/db88f5281-setup.c
+@@ -86,7 +86,7 @@
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+- .platform_data = &db88f5281_boot_flash_data,
++ .platform_data = &db88f5281_boot_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &db88f5281_boot_flash_resource,
+@@ -110,7 +110,7 @@
+ .name = "physmap-flash",
+ .id = 1,
+ .dev = {
+- .platform_data = &db88f5281_nor_flash_data,
++ .platform_data = &db88f5281_nor_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &db88f5281_nor_flash_resource,
+@@ -125,18 +125,15 @@
+ .name = "kernel",
+ .offset = 0,
+ .size = SZ_2M,
+- },
+- {
++ }, {
+ .name = "root",
+ .offset = SZ_2M,
+ .size = (SZ_16M - SZ_2M),
+- },
+- {
++ }, {
+ .name = "user",
+ .offset = SZ_16M,
+ .size = SZ_8M,
+- },
+- {
++ }, {
+ .name = "recovery",
+ .offset = (SZ_16M + SZ_8M),
+ .size = SZ_8M,
+--- a/arch/arm/mach-orion5x/dns323-setup.c
++++ b/arch/arm/mach-orion5x/dns323-setup.c
+@@ -119,7 +119,7 @@
+ .name = "u-boot",
+ .size = 0x00030000,
+ .offset = 0x007d0000,
+- }
++ },
+ };
+
+ static struct physmap_flash_data dns323_nor_flash_data = {
+@@ -137,7 +137,9 @@
+ static struct platform_device dns323_nor_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+- .dev = { .platform_data = &dns323_nor_flash_data, },
++ .dev = {
++ .platform_data = &dns323_nor_flash_data,
++ },
+ .resource = &dns323_nor_flash_resource,
+ .num_resources = 1,
+ };
+@@ -170,7 +172,9 @@
+ static struct platform_device dns323_gpio_leds = {
+ .name = "leds-gpio",
+ .id = -1,
+- .dev = { .platform_data = &dns323_led_data, },
++ .dev = {
++ .platform_data = &dns323_led_data,
++ },
+ };
+
+ /****************************************************************************
+@@ -183,25 +187,26 @@
+ .gpio = DNS323_GPIO_KEY_RESET,
+ .desc = "Reset Button",
+ .active_low = 1,
+- },
+- {
++ }, {
+ .code = KEY_POWER,
+ .gpio = DNS323_GPIO_KEY_POWER,
+ .desc = "Power Button",
+ .active_low = 1,
+- }
++ },
+ };
+
+ static struct gpio_keys_platform_data dns323_button_data = {
+ .buttons = dns323_buttons,
+- .nbuttons = ARRAY_SIZE(dns323_buttons),
++ .nbuttons = ARRAY_SIZE(dns323_buttons),
+ };
+
+ static struct platform_device dns323_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+- .dev = { .platform_data = &dns323_button_data, },
++ .dev = {
++ .platform_data = &dns323_button_data,
++ },
+ };
+
+ /****************************************************************************
+@@ -225,17 +230,15 @@
+ static struct i2c_board_info __initdata dns323_i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("g760a", 0x3e),
+- },
+ #if 0
+ /* this entry requires the new-style driver model lm75 driver,
+ * for the meantime "insmod lm75.ko force_lm75=0,0x48" is needed */
+- {
++ }, {
+ I2C_BOARD_INFO("g751", 0x48),
+- },
+ #endif
+- {
++ }, {
+ I2C_BOARD_INFO("m41t80", 0x68),
+- }
++ },
+ };
+
+ /* DNS-323 specific power off method */
+@@ -292,8 +295,8 @@
+ orion5x_gpio_set_valid_pins(0x07f6);
+
+ /* register dns323 specific power-off method */
+- if ((gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0)
+- || (gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0))
++ if (gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0 ||
++ gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0)
+ pr_err("DNS323: failed to setup power-off GPIO\n");
+
+ pm_power_off = dns323_power_off;
+--- a/arch/arm/mach-orion5x/kurobox_pro-setup.c
++++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
+@@ -53,13 +53,11 @@
+ .name = "uImage",
+ .offset = 0,
+ .size = SZ_4M,
+- },
+- {
++ }, {
+ .name = "rootfs",
+ .offset = SZ_4M,
+ .size = SZ_64M,
+- },
+- {
++ }, {
+ .name = "extra",
+ .offset = SZ_4M + SZ_64M,
+ .size = SZ_256M - (SZ_4M + SZ_64M),
+@@ -175,7 +173,7 @@
+ * SATA
+ ****************************************************************************/
+ static struct mv_sata_platform_data kurobox_pro_sata_data = {
+- .n_ports = 2,
++ .n_ports = 2,
+ };
+
+ /*****************************************************************************
+--- a/arch/arm/mach-orion5x/pci.c
++++ b/arch/arm/mach-orion5x/pci.c
+@@ -240,13 +240,13 @@
+ * PCI Address Decode Windows registers
+ */
+ #define PCI_BAR_SIZE_DDR_CS(n) (((n) == 0) ? ORION5X_PCI_REG(0xc08) : \
+- ((n) == 1) ? ORION5X_PCI_REG(0xd08) : \
+- ((n) == 2) ? ORION5X_PCI_REG(0xc0c) : \
+- ((n) == 3) ? ORION5X_PCI_REG(0xd0c) : 0)
+-#define PCI_BAR_REMAP_DDR_CS(n) (((n) ==0) ? ORION5X_PCI_REG(0xc48) : \
+- ((n) == 1) ? ORION5X_PCI_REG(0xd48) : \
+- ((n) == 2) ? ORION5X_PCI_REG(0xc4c) : \
+- ((n) == 3) ? ORION5X_PCI_REG(0xd4c) : 0)
++ ((n) == 1) ? ORION5X_PCI_REG(0xd08) : \
++ ((n) == 2) ? ORION5X_PCI_REG(0xc0c) : \
++ ((n) == 3) ? ORION5X_PCI_REG(0xd0c) : 0)
++#define PCI_BAR_REMAP_DDR_CS(n) (((n) == 0) ? ORION5X_PCI_REG(0xc48) : \
++ ((n) == 1) ? ORION5X_PCI_REG(0xd48) : \
++ ((n) == 2) ? ORION5X_PCI_REG(0xc4c) : \
++ ((n) == 3) ? ORION5X_PCI_REG(0xd4c) : 0)
+ #define PCI_BAR_ENABLE ORION5X_PCI_REG(0xc3c)
+ #define PCI_ADDR_DECODE_CTRL ORION5X_PCI_REG(0xd3c)
+
+--- a/arch/arm/mach-orion5x/rd88f5182-setup.c
++++ b/arch/arm/mach-orion5x/rd88f5182-setup.c
+@@ -125,6 +125,7 @@
+
+ leds_event = rd88f5182_dbgled_event;
+ }
++
+ return 0;
+ }
+
+@@ -234,7 +235,7 @@
+ * Sata
+ ****************************************************************************/
+ static struct mv_sata_platform_data rd88f5182_sata_data = {
+- .n_ports = 2,
++ .n_ports = 2,
+ };
+
+ /*****************************************************************************
+--- a/arch/arm/mach-orion5x/ts209-setup.c
++++ b/arch/arm/mach-orion5x/ts209-setup.c
+@@ -47,52 +47,54 @@
+ ***************************************************************************/
+ static struct mtd_partition qnap_ts209_partitions[] = {
+ {
+- .name = "U-Boot",
+- .size = 0x00080000,
+- .offset = 0x00780000,
+- .mask_flags = MTD_WRITEABLE,
++ .name = "U-Boot",
++ .size = 0x00080000,
++ .offset = 0x00780000,
++ .mask_flags = MTD_WRITEABLE,
+ }, {
+- .name = "Kernel",
+- .size = 0x00200000,
+- .offset = 0,
++ .name = "Kernel",
++ .size = 0x00200000,
++ .offset = 0,
+ }, {
+- .name = "RootFS1",
+- .size = 0x00400000,
+- .offset = 0x00200000,
++ .name = "RootFS1",
++ .size = 0x00400000,
++ .offset = 0x00200000,
+ }, {
+- .name = "RootFS2",
+- .size = 0x00100000,
+- .offset = 0x00600000,
++ .name = "RootFS2",
++ .size = 0x00100000,
++ .offset = 0x00600000,
+ }, {
+- .name = "U-Boot Config",
+- .size = 0x00020000,
+- .offset = 0x00760000,
++ .name = "U-Boot Config",
++ .size = 0x00020000,
++ .offset = 0x00760000,
+ }, {
+- .name = "NAS Config",
+- .size = 0x00060000,
+- .offset = 0x00700000,
+- .mask_flags = MTD_WRITEABLE,
+- }
++ .name = "NAS Config",
++ .size = 0x00060000,
++ .offset = 0x00700000,
++ .mask_flags = MTD_WRITEABLE,
++ },
+ };
+
+ static struct physmap_flash_data qnap_ts209_nor_flash_data = {
+- .width = 1,
+- .parts = qnap_ts209_partitions,
+- .nr_parts = ARRAY_SIZE(qnap_ts209_partitions)
++ .width = 1,
++ .parts = qnap_ts209_partitions,
++ .nr_parts = ARRAY_SIZE(qnap_ts209_partitions)
+ };
+
+ static struct resource qnap_ts209_nor_flash_resource = {
+- .flags = IORESOURCE_MEM,
+- .start = QNAP_TS209_NOR_BOOT_BASE,
+- .end = QNAP_TS209_NOR_BOOT_BASE + QNAP_TS209_NOR_BOOT_SIZE - 1,
++ .flags = IORESOURCE_MEM,
++ .start = QNAP_TS209_NOR_BOOT_BASE,
++ .end = QNAP_TS209_NOR_BOOT_BASE + QNAP_TS209_NOR_BOOT_SIZE - 1,
+ };
+
+ static struct platform_device qnap_ts209_nor_flash = {
+- .name = "physmap-flash",
+- .id = 0,
+- .dev = { .platform_data = &qnap_ts209_nor_flash_data, },
+- .resource = &qnap_ts209_nor_flash_resource,
+- .num_resources = 1,
++ .name = "physmap-flash",
++ .id = 0,
++ .dev = {
++ .platform_data = &qnap_ts209_nor_flash_data,
++ },
++ .resource = &qnap_ts209_nor_flash_resource,
++ .num_resources = 1,
+ };
+
+ /*****************************************************************************
+@@ -164,12 +166,12 @@
+ }
+
+ static struct hw_pci qnap_ts209_pci __initdata = {
+- .nr_controllers = 2,
+- .preinit = qnap_ts209_pci_preinit,
+- .swizzle = pci_std_swizzle,
+- .setup = orion5x_pci_sys_setup,
+- .scan = orion5x_pci_sys_scan_bus,
+- .map_irq = qnap_ts209_pci_map_irq,
++ .nr_controllers = 2,
++ .preinit = qnap_ts209_pci_preinit,
++ .swizzle = pci_std_swizzle,
++ .setup = orion5x_pci_sys_setup,
++ .scan = orion5x_pci_sys_scan_bus,
++ .map_irq = qnap_ts209_pci_map_irq,
+ };
+
+ static int __init qnap_ts209_pci_init(void)
+@@ -187,8 +189,8 @@
+ ****************************************************************************/
+
+ static struct mv643xx_eth_platform_data qnap_ts209_eth_data = {
+- .phy_addr = 8,
+- .force_phy_addr = 1,
++ .phy_addr = 8,
++ .force_phy_addr = 1,
+ };
+
+ static int __init parse_hex_nibble(char n)
+@@ -280,7 +282,7 @@
+
+ static struct i2c_board_info __initdata qnap_ts209_i2c_rtc = {
+ I2C_BOARD_INFO("s35390a", 0x30),
+- .irq = 0,
++ .irq = 0,
+ };
+
+ /****************************************************************************
+@@ -297,32 +299,33 @@
+ .gpio = QNAP_TS209_GPIO_KEY_MEDIA,
+ .desc = "USB Copy Button",
+ .active_low = 1,
+- },
+- {
++ }, {
+ .code = KEY_POWER,
+ .gpio = QNAP_TS209_GPIO_KEY_RESET,
+ .desc = "Reset Button",
+ .active_low = 1,
+- }
++ },
+ };
+
+ static struct gpio_keys_platform_data qnap_ts209_button_data = {
+ .buttons = qnap_ts209_buttons,
+- .nbuttons = ARRAY_SIZE(qnap_ts209_buttons),
++ .nbuttons = ARRAY_SIZE(qnap_ts209_buttons),
+ };
+
+ static struct platform_device qnap_ts209_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+- .dev = { .platform_data = &qnap_ts209_button_data, },
++ .dev = {
++ .platform_data = &qnap_ts209_button_data,
++ },
+ };
+
+ /*****************************************************************************
+ * SATA
+ ****************************************************************************/
+ static struct mv_sata_platform_data qnap_ts209_sata_data = {
+- .n_ports = 2,
++ .n_ports = 2,
+ };
+
+ /*****************************************************************************
+@@ -339,7 +342,7 @@
+ * QNAP TS-[12]09 specific power off method via UART1-attached PIC
+ */
+
+-#define UART1_REG(x) (UART1_VIRT_BASE + ((UART_##x) << 2))
++#define UART1_REG(x) (UART1_VIRT_BASE + ((UART_##x) << 2))
+
+ static void qnap_ts209_power_off(void)
+ {
+@@ -372,7 +375,7 @@
+ * Setup flash mapping
+ */
+ orion5x_setup_dev_boot_win(QNAP_TS209_NOR_BOOT_BASE,
+- QNAP_TS209_NOR_BOOT_SIZE);
++ QNAP_TS209_NOR_BOOT_SIZE);
+
+ /*
+ * Open a special address decode windows for the PCIe WA.
+@@ -432,7 +435,7 @@
+ }
+
+ MACHINE_START(TS209, "QNAP TS-109/TS-209")
+- /* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
++ /* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
+ .phys_io = ORION5X_REGS_PHYS_BASE,
+ .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
+ .boot_params = 0x00000100,
+--- a/arch/arm/mm/proc-feroceon.S
++++ b/arch/arm/mm/proc-feroceon.S
+@@ -454,13 +454,13 @@
+ __feroceon_old_id_proc_info:
+ .long 0x41069260
+ .long 0xfffffff0
+- .long PMD_TYPE_SECT | \
++ .long PMD_TYPE_SECT | \
+ PMD_SECT_BUFFERABLE | \
+ PMD_SECT_CACHEABLE | \
+ PMD_BIT4 | \
+ PMD_SECT_AP_WRITE | \
+ PMD_SECT_AP_READ
+- .long PMD_TYPE_SECT | \
++ .long PMD_TYPE_SECT | \
+ PMD_BIT4 | \
+ PMD_SECT_AP_WRITE | \
+ PMD_SECT_AP_READ
+@@ -480,13 +480,13 @@
+ __feroceon_proc_info:
+ .long 0x56055310
+ .long 0xfffffff0
+- .long PMD_TYPE_SECT | \
++ .long PMD_TYPE_SECT | \
+ PMD_SECT_BUFFERABLE | \
+ PMD_SECT_CACHEABLE | \
+ PMD_BIT4 | \
+ PMD_SECT_AP_WRITE | \
+ PMD_SECT_AP_READ
+- .long PMD_TYPE_SECT | \
++ .long PMD_TYPE_SECT | \
+ PMD_BIT4 | \
+ PMD_SECT_AP_WRITE | \
+ PMD_SECT_AP_READ
diff --git a/target/linux/orion/patches/004-make_window_setup_a_little_more_safe.patch b/target/linux/orion/patches/004-make_window_setup_a_little_more_safe.patch
new file mode 100644
index 0000000000..f5f1de4c2f
--- /dev/null
+++ b/target/linux/orion/patches/004-make_window_setup_a_little_more_safe.patch
@@ -0,0 +1,79 @@
+Currently, Orion window setup uses hardcoded window indexes for each
+of the boot/cs0/cs1/cs2/PCIe WA windows. The static window allocation
+used can clash if board support code will ever attempt to configure
+both a dev2 and a PCIe WA window, as both of those use CPU mbus window
+#7 at present.
+
+This patch keeps track of the last used window, and opens subsequently
+requested windows sequentially, starting from 4. (Windows 0-3 are used
+as MEM/IO windows for the PCI/PCIe buses.)
+
+Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
+---
+ arch/arm/mach-orion5x/addr-map.c | 20 +++++++++++++++-----
+ 1 files changed, 15 insertions(+), 5 deletions(-)
+
+--- a/arch/arm/mach-orion5x/addr-map.c
++++ b/arch/arm/mach-orion5x/addr-map.c
+@@ -70,6 +70,7 @@
+
+
+ struct mbus_dram_target_info orion5x_mbus_dram_info;
++static int __initdata win_alloc_count;
+
+ static int __init orion5x_cpu_win_can_remap(int win)
+ {
+@@ -87,6 +88,9 @@
+ static void __init setup_cpu_win(int win, u32 base, u32 size,
+ u8 target, u8 attr, int remap)
+ {
++ if (win >= 8)
++ panic("setup_cpu_win: trying to allocate window %d\n", win);
++
+ orion5x_write(CPU_WIN_BASE(win), base & 0xffff0000);
+ orion5x_write(CPU_WIN_CTRL(win),
+ ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | 1);
+@@ -128,6 +132,7 @@
+ TARGET_PCIE, ATTR_PCIE_MEM, -1);
+ setup_cpu_win(3, ORION5X_PCI_MEM_PHYS_BASE, ORION5X_PCI_MEM_SIZE,
+ TARGET_PCI, ATTR_PCI_MEM, -1);
++ win_alloc_count = 4;
+
+ /*
+ * Setup MBUS dram target info.
+@@ -156,25 +161,30 @@
+
+ void __init orion5x_setup_dev_boot_win(u32 base, u32 size)
+ {
+- setup_cpu_win(4, base, size, TARGET_DEV_BUS, ATTR_DEV_BOOT, -1);
++ setup_cpu_win(win_alloc_count++, base, size,
++ TARGET_DEV_BUS, ATTR_DEV_BOOT, -1);
+ }
+
+ void __init orion5x_setup_dev0_win(u32 base, u32 size)
+ {
+- setup_cpu_win(5, base, size, TARGET_DEV_BUS, ATTR_DEV_CS0, -1);
++ setup_cpu_win(win_alloc_count++, base, size,
++ TARGET_DEV_BUS, ATTR_DEV_CS0, -1);
+ }
+
+ void __init orion5x_setup_dev1_win(u32 base, u32 size)
+ {
+- setup_cpu_win(6, base, size, TARGET_DEV_BUS, ATTR_DEV_CS1, -1);
++ setup_cpu_win(win_alloc_count++, base, size,
++ TARGET_DEV_BUS, ATTR_DEV_CS1, -1);
+ }
+
+ void __init orion5x_setup_dev2_win(u32 base, u32 size)
+ {
+- setup_cpu_win(7, base, size, TARGET_DEV_BUS, ATTR_DEV_CS2, -1);
++ setup_cpu_win(win_alloc_count++, base, size,
++ TARGET_DEV_BUS, ATTR_DEV_CS2, -1);
+ }
+
+ void __init orion5x_setup_pcie_wa_win(u32 base, u32 size)
+ {
+- setup_cpu_win(7, base, size, TARGET_PCIE, ATTR_PCIE_WA, -1);
++ setup_cpu_win(win_alloc_count++, base, size,
++ TARGET_PCIE, ATTR_PCIE_WA, -1);
+ }
diff --git a/target/linux/orion/patches/005-dram_mapping_granularity_is_64kib.patch b/target/linux/orion/patches/005-dram_mapping_granularity_is_64kib.patch
new file mode 100644
index 0000000000..2e7815de27
--- /dev/null
+++ b/target/linux/orion/patches/005-dram_mapping_granularity_is_64kib.patch
@@ -0,0 +1,26 @@
+The DRAM base address and size fields in the CPU's MBUS bridge have
+64KiB granularity, instead of the currently used 16MiB. Since all
+of the currently supported MBUS peripherals support 64KiB granularity
+as well, this patch changes the Orion address map code to stop
+rounding base addresses down and sizes up to multiples of 16MiB.
+
+Found by Ke Wei <kewei@marvell.com>.
+
+Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
+---
+ arch/arm/mach-orion5x/addr-map.c | 4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/mach-orion5x/addr-map.c
++++ b/arch/arm/mach-orion5x/addr-map.c
+@@ -152,8 +152,8 @@
+ w = &orion5x_mbus_dram_info.cs[cs++];
+ w->cs_index = i;
+ w->mbus_attr = 0xf & ~(1 << i);
+- w->base = base & 0xff000000;
+- w->size = (size | 0x00ffffff) + 1;
++ w->base = base & 0xffff0000;
++ w->size = (size | 0x0000ffff) + 1;
+ }
+ }
+ orion5x_mbus_dram_info.num_cs = cs;
diff --git a/target/linux/orion/patches/006-add_a_separate_BRIDGE_INT_TIMER1_CLR_define.patch b/target/linux/orion/patches/006-add_a_separate_BRIDGE_INT_TIMER1_CLR_define.patch
new file mode 100644
index 0000000000..75daedd84c
--- /dev/null
+++ b/target/linux/orion/patches/006-add_a_separate_BRIDGE_INT_TIMER1_CLR_define.patch
@@ -0,0 +1,37 @@
+From: Ke Wei <kewei@marvell.com>
+
+Some Feroceon-based SoCs have an MBUS bridge interrupt controller
+that requires writing a one instead of a zero to clear edge
+interrupt sources such as timer expiry.
+
+This patch adds a new BRIDGE_INT_TIMER1_CLR define, which platform
+code can set to either ~BRIDGE_INT_TIMER1 (write-zero-to-clear) or
+BRIDGE_INT_TIMER1 (write-one-to-clear) depending on the platform.
+
+Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
+---
+ arch/arm/plat-orion/time.c | 2 +-
+ include/asm-arm/arch-orion5x/orion5x.h | 1 +
+ 2 files changed, 2 insertions(+), 1 deletions(-)
+
+--- a/arch/arm/plat-orion/time.c
++++ b/arch/arm/plat-orion/time.c
+@@ -74,7 +74,7 @@
+ /*
+ * Clear and enable clockevent timer interrupt.
+ */
+- writel(~BRIDGE_INT_TIMER1, BRIDGE_CAUSE);
++ writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
+
+ u = readl(BRIDGE_MASK);
+ u |= BRIDGE_INT_TIMER1;
+--- a/include/asm-arm/arch-orion5x/orion5x.h
++++ b/include/asm-arm/arch-orion5x/orion5x.h
+@@ -152,6 +152,7 @@
+ #define BRIDGE_MASK ORION5X_BRIDGE_REG(0x114)
+ #define BRIDGE_INT_TIMER0 0x0002
+ #define BRIDGE_INT_TIMER1 0x0004
++#define BRIDGE_INT_TIMER1_CLR ~0x0004
+ #define MAIN_IRQ_CAUSE ORION5X_BRIDGE_REG(0x200)
+ #define MAIN_IRQ_MASK ORION5X_BRIDGE_REG(0x204)
+
diff --git a/target/linux/orion/patches/007-annotate_88fr531-vd_cpu_entries.patch b/target/linux/orion/patches/007-annotate_88fr531-vd_cpu_entries.patch
new file mode 100644
index 0000000000..5aab94bb86
--- /dev/null
+++ b/target/linux/orion/patches/007-annotate_88fr531-vd_cpu_entries.patch
@@ -0,0 +1,58 @@
+Annotate the entries for the 88fr531-vd CPU core in
+arch/arm/boot/compressed/head.S and arch/arm/mm/proc-feroceon.S
+with the full name of the core.
+
+Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
+---
+ arch/arm/boot/compressed/head.S | 2 +-
+ arch/arm/mm/proc-feroceon.S | 13 +++++++++----
+ 2 files changed, 10 insertions(+), 5 deletions(-)
+
+--- a/arch/arm/boot/compressed/head.S
++++ b/arch/arm/boot/compressed/head.S
+@@ -623,7 +623,7 @@
+ b __armv4_mmu_cache_off
+ b __armv4_mmu_cache_flush
+
+- .word 0x56055310 @ Feroceon
++ .word 0x56055310 @ Feroceon 88FR531-vd
+ .word 0xfffffff0
+ b __armv4_mmu_cache_on
+ b __armv4_mmu_cache_off
+--- a/arch/arm/mm/proc-feroceon.S
++++ b/arch/arm/mm/proc-feroceon.S
+@@ -445,6 +445,11 @@
+ .asciz "Feroceon"
+ .size cpu_feroceon_name, . - cpu_feroceon_name
+
++ .type cpu_88fr531_name, #object
++cpu_88fr531_name:
++ .asciz "Feroceon 88FR531-vd"
++ .size cpu_88fr531_name, . - cpu_88fr531_name
++
+ .align
+
+ .section ".proc.info.init", #alloc, #execinstr
+@@ -476,8 +481,8 @@
+ .size __feroceon_old_id_proc_info, . - __feroceon_old_id_proc_info
+ #endif
+
+- .type __feroceon_proc_info,#object
+-__feroceon_proc_info:
++ .type __88fr531_proc_info,#object
++__88fr531_proc_info:
+ .long 0x56055310
+ .long 0xfffffff0
+ .long PMD_TYPE_SECT | \
+@@ -494,9 +499,9 @@
+ .long cpu_arch_name
+ .long cpu_elf_name
+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+- .long cpu_feroceon_name
++ .long cpu_88fr531_name
+ .long feroceon_processor_functions
+ .long v4wbi_tlb_fns
+ .long feroceon_user_fns
+ .long feroceon_cache_fns
+- .size __feroceon_proc_info, . - __feroceon_proc_info
++ .size __88fr531_proc_info, . - __88fr531_proc_info
diff --git a/target/linux/orion/patches/008-top-level_irqs_are_level-triggered.patch b/target/linux/orion/patches/008-top-level_irqs_are_level-triggered.patch
new file mode 100644
index 0000000000..add15900c9
--- /dev/null
+++ b/target/linux/orion/patches/008-top-level_irqs_are_level-triggered.patch
@@ -0,0 +1,35 @@
+Make it clear that Orion top-level IRQs are level-triggered. This
+means that we don't need an ->ack() handler, or at least, we don't
+need the ->ack() handler (or the acking part of the ->mask_ack()
+handler) to actually do anything.
+
+Given that, we might as well point our ->mask_ack() handler at the
+->mask() handler instead of providing a dummy ->ack() handler, since
+providing a ->mask_ack() handler on level IRQ sources will prevent
+->ack() from ever being called.
+
+Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
+---
+ arch/arm/plat-orion/irq.c | 3 ++-
+ 1 files changed, 2 insertions(+), 1 deletions(-)
+
+--- a/arch/arm/plat-orion/irq.c
++++ b/arch/arm/plat-orion/irq.c
+@@ -36,8 +36,8 @@
+
+ static struct irq_chip orion_irq_chip = {
+ .name = "orion_irq",
+- .ack = orion_irq_mask,
+ .mask = orion_irq_mask,
++ .mask_ack = orion_irq_mask,
+ .unmask = orion_irq_unmask,
+ };
+
+@@ -59,6 +59,7 @@
+ set_irq_chip(irq, &orion_irq_chip);
+ set_irq_chip_data(irq, maskaddr);
+ set_irq_handler(irq, handle_level_irq);
++ irq_desc[irq].status |= IRQ_LEVEL;
+ set_irq_flags(irq, IRQF_VALID);
+ }
+ }
diff --git a/target/linux/orion/patches/009-delete_unused_IO_SPACE_REMAP_define.patch b/target/linux/orion/patches/009-delete_unused_IO_SPACE_REMAP_define.patch
new file mode 100644
index 0000000000..222a6dabcd
--- /dev/null
+++ b/target/linux/orion/patches/009-delete_unused_IO_SPACE_REMAP_define.patch
@@ -0,0 +1,17 @@
+This define isn't used anywhere in the kernel tree -- nuke it.
+
+Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
+---
+ include/asm-arm/arch-orion5x/io.h | 1 -
+ 1 files changed, 0 insertions(+), 1 deletions(-)
+
+--- a/include/asm-arm/arch-orion5x/io.h
++++ b/include/asm-arm/arch-orion5x/io.h
+@@ -14,7 +14,6 @@
+ #include "orion5x.h"
+
+ #define IO_SPACE_LIMIT 0xffffffff
+-#define IO_SPACE_REMAP ORION5X_PCI_SYS_IO_BASE
+
+ static inline void __iomem *
+ __arch_ioremap(unsigned long paddr, size_t size, unsigned int mtype)
diff --git a/target/linux/orion/patches/010-move_EHCI_I2C_UART_peripheral_init.patch b/target/linux/orion/patches/010-move_EHCI_I2C_UART_peripheral_init.patch
new file mode 100644
index 0000000000..6f11eefad3
--- /dev/null
+++ b/target/linux/orion/patches/010-move_EHCI_I2C_UART_peripheral_init.patch
@@ -0,0 +1,710 @@
+This patch moves initialisation of EHCI/I2C/UART platform devices
+from the common orion5x_init() into the board support code.
+
+The rationale behind this is that only the board support code knows
+whether certain peripherals have been brought out on the board, and
+not initialising peripherals that haven't been brought out is
+desirable for example:
+- to reduce user confusion (e.g. seeing both 'eth0' and 'eth1'
+ appear while there is only one ethernet port on the board); and
+- to allow for future power savings (peripherals that have not
+ been brought out can be clock gated off entirely.)
+
+Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
+---
+ arch/arm/mach-orion5x/common.c | 226 +++++++++++++++++------------
+ arch/arm/mach-orion5x/common.h | 35 ++---
+ arch/arm/mach-orion5x/db88f5281-setup.c | 39 +++---
+ arch/arm/mach-orion5x/dns323-setup.c | 40 +++---
+ arch/arm/mach-orion5x/kurobox_pro-setup.c | 28 +++--
+ arch/arm/mach-orion5x/rd88f5182-setup.c | 29 ++--
+ arch/arm/mach-orion5x/ts209-setup.c | 38 ++---
+ 7 files changed, 240 insertions(+), 195 deletions(-)
+
+--- a/arch/arm/mach-orion5x/common.c
++++ b/arch/arm/mach-orion5x/common.c
+@@ -63,65 +63,20 @@
+ iotable_init(orion5x_io_desc, ARRAY_SIZE(orion5x_io_desc));
+ }
+
++
+ /*****************************************************************************
+- * UART
++ * EHCI
+ ****************************************************************************/
+-
+-static struct resource orion5x_uart_resources[] = {
+- {
+- .start = UART0_PHYS_BASE,
+- .end = UART0_PHYS_BASE + 0xff,
+- .flags = IORESOURCE_MEM,
+- }, {
+- .start = IRQ_ORION5X_UART0,
+- .end = IRQ_ORION5X_UART0,
+- .flags = IORESOURCE_IRQ,
+- }, {
+- .start = UART1_PHYS_BASE,
+- .end = UART1_PHYS_BASE + 0xff,
+- .flags = IORESOURCE_MEM,
+- }, {
+- .start = IRQ_ORION5X_UART1,
+- .end = IRQ_ORION5X_UART1,
+- .flags = IORESOURCE_IRQ,
+- },
+-};
+-
+-static struct plat_serial8250_port orion5x_uart_data[] = {
+- {
+- .mapbase = UART0_PHYS_BASE,
+- .membase = (char *)UART0_VIRT_BASE,
+- .irq = IRQ_ORION5X_UART0,
+- .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+- .iotype = UPIO_MEM,
+- .regshift = 2,
+- .uartclk = ORION5X_TCLK,
+- }, {
+- .mapbase = UART1_PHYS_BASE,
+- .membase = (char *)UART1_VIRT_BASE,
+- .irq = IRQ_ORION5X_UART1,
+- .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
+- .iotype = UPIO_MEM,
+- .regshift = 2,
+- .uartclk = ORION5X_TCLK,
+- }, {
+- },
++static struct orion_ehci_data orion5x_ehci_data = {
++ .dram = &orion5x_mbus_dram_info,
+ };
+
+-static struct platform_device orion5x_uart = {
+- .name = "serial8250",
+- .id = PLAT8250_DEV_PLATFORM,
+- .dev = {
+- .platform_data = orion5x_uart_data,
+- },
+- .resource = orion5x_uart_resources,
+- .num_resources = ARRAY_SIZE(orion5x_uart_resources),
+-};
++static u64 ehci_dmamask = 0xffffffffUL;
+
+-/*******************************************************************************
+- * USB Controller - 2 interfaces
+- ******************************************************************************/
+
++/*****************************************************************************
++ * EHCI0
++ ****************************************************************************/
+ static struct resource orion5x_ehci0_resources[] = {
+ {
+ .start = ORION5X_USB0_PHYS_BASE,
+@@ -134,24 +89,6 @@
+ },
+ };
+
+-static struct resource orion5x_ehci1_resources[] = {
+- {
+- .start = ORION5X_USB1_PHYS_BASE,
+- .end = ORION5X_USB1_PHYS_BASE + SZ_4K - 1,
+- .flags = IORESOURCE_MEM,
+- }, {
+- .start = IRQ_ORION5X_USB1_CTRL,
+- .end = IRQ_ORION5X_USB1_CTRL,
+- .flags = IORESOURCE_IRQ,
+- },
+-};
+-
+-static struct orion_ehci_data orion5x_ehci_data = {
+- .dram = &orion5x_mbus_dram_info,
+-};
+-
+-static u64 ehci_dmamask = 0xffffffffUL;
+-
+ static struct platform_device orion5x_ehci0 = {
+ .name = "orion-ehci",
+ .id = 0,
+@@ -164,6 +101,27 @@
+ .num_resources = ARRAY_SIZE(orion5x_ehci0_resources),
+ };
+
++void __init orion5x_ehci0_init(void)
++{
++ platform_device_register(&orion5x_ehci0);
++}
++
++
++/*****************************************************************************
++ * EHCI1
++ ****************************************************************************/
++static struct resource orion5x_ehci1_resources[] = {
++ {
++ .start = ORION5X_USB1_PHYS_BASE,
++ .end = ORION5X_USB1_PHYS_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ }, {
++ .start = IRQ_ORION5X_USB1_CTRL,
++ .end = IRQ_ORION5X_USB1_CTRL,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
+ static struct platform_device orion5x_ehci1 = {
+ .name = "orion-ehci",
+ .id = 1,
+@@ -176,11 +134,15 @@
+ .num_resources = ARRAY_SIZE(orion5x_ehci1_resources),
+ };
+
++void __init orion5x_ehci1_init(void)
++{
++ platform_device_register(&orion5x_ehci1);
++}
++
++
+ /*****************************************************************************
+- * Gigabit Ethernet port
+- * (The Orion and Discovery (MV643xx) families use the same Ethernet driver)
++ * GigE
+ ****************************************************************************/
+-
+ struct mv643xx_eth_shared_platform_data orion5x_eth_shared_data = {
+ .dram = &orion5x_mbus_dram_info,
+ .t_clk = ORION5X_TCLK,
+@@ -229,11 +191,10 @@
+ platform_device_register(&orion5x_eth);
+ }
+
++
+ /*****************************************************************************
+- * I2C controller
+- * (The Orion and Discovery (MV643xx) families share the same I2C controller)
++ * I2C
+ ****************************************************************************/
+-
+ static struct mv64xxx_i2c_pdata orion5x_i2c_pdata = {
+ .freq_m = 8, /* assumes 166 MHz TCLK */
+ .freq_n = 3,
+@@ -244,7 +205,7 @@
+ {
+ .name = "i2c base",
+ .start = I2C_PHYS_BASE,
+- .end = I2C_PHYS_BASE + 0x20 -1,
++ .end = I2C_PHYS_BASE + 0x1f,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .name = "i2c irq",
+@@ -264,8 +225,14 @@
+ },
+ };
+
++void __init orion5x_i2c_init(void)
++{
++ platform_device_register(&orion5x_i2c);
++}
++
++
+ /*****************************************************************************
+- * Sata port
++ * SATA
+ ****************************************************************************/
+ static struct resource orion5x_sata_resources[] = {
+ {
+@@ -298,10 +265,98 @@
+ platform_device_register(&orion5x_sata);
+ }
+
++
+ /*****************************************************************************
+- * Time handling
++ * UART0
++ ****************************************************************************/
++static struct plat_serial8250_port orion5x_uart0_data[] = {
++ {
++ .mapbase = UART0_PHYS_BASE,
++ .membase = (char *)UART0_VIRT_BASE,
++ .irq = IRQ_ORION5X_UART0,
++ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
++ .iotype = UPIO_MEM,
++ .regshift = 2,
++ .uartclk = ORION5X_TCLK,
++ }, {
++ },
++};
++
++static struct resource orion5x_uart0_resources[] = {
++ {
++ .start = UART0_PHYS_BASE,
++ .end = UART0_PHYS_BASE + 0xff,
++ .flags = IORESOURCE_MEM,
++ }, {
++ .start = IRQ_ORION5X_UART0,
++ .end = IRQ_ORION5X_UART0,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device orion5x_uart0 = {
++ .name = "serial8250",
++ .id = PLAT8250_DEV_PLATFORM,
++ .dev = {
++ .platform_data = orion5x_uart0_data,
++ },
++ .resource = orion5x_uart0_resources,
++ .num_resources = ARRAY_SIZE(orion5x_uart0_resources),
++};
++
++void __init orion5x_uart0_init(void)
++{
++ platform_device_register(&orion5x_uart0);
++}
++
++
++/*****************************************************************************
++ * UART1
+ ****************************************************************************/
++static struct plat_serial8250_port orion5x_uart1_data[] = {
++ {
++ .mapbase = UART1_PHYS_BASE,
++ .membase = (char *)UART1_VIRT_BASE,
++ .irq = IRQ_ORION5X_UART1,
++ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
++ .iotype = UPIO_MEM,
++ .regshift = 2,
++ .uartclk = ORION5X_TCLK,
++ }, {
++ },
++};
++
++static struct resource orion5x_uart1_resources[] = {
++ {
++ .start = UART1_PHYS_BASE,
++ .end = UART1_PHYS_BASE + 0xff,
++ .flags = IORESOURCE_MEM,
++ }, {
++ .start = IRQ_ORION5X_UART1,
++ .end = IRQ_ORION5X_UART1,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device orion5x_uart1 = {
++ .name = "serial8250",
++ .id = PLAT8250_DEV_PLATFORM1,
++ .dev = {
++ .platform_data = orion5x_uart1_data,
++ },
++ .resource = orion5x_uart1_resources,
++ .num_resources = ARRAY_SIZE(orion5x_uart1_resources),
++};
++
++void __init orion5x_uart1_init(void)
++{
++ platform_device_register(&orion5x_uart1);
++}
+
++
++/*****************************************************************************
++ * Time handling
++ ****************************************************************************/
+ static void orion5x_timer_init(void)
+ {
+ orion_time_init(IRQ_ORION5X_BRIDGE, ORION5X_TCLK);
+@@ -311,10 +366,10 @@
+ .init = orion5x_timer_init,
+ };
+
++
+ /*****************************************************************************
+ * General
+ ****************************************************************************/
+-
+ /*
+ * Identify device ID and rev from PCIe configuration header space '0'.
+ */
+@@ -359,15 +414,6 @@
+ * Setup Orion address map
+ */
+ orion5x_setup_cpu_mbus_bridge();
+-
+- /*
+- * Register devices.
+- */
+- platform_device_register(&orion5x_uart);
+- platform_device_register(&orion5x_ehci0);
+- if (dev == MV88F5182_DEV_ID)
+- platform_device_register(&orion5x_ehci1);
+- platform_device_register(&orion5x_i2c);
+ }
+
+ /*
+--- a/arch/arm/mach-orion5x/common.h
++++ b/arch/arm/mach-orion5x/common.h
+@@ -1,10 +1,12 @@
+ #ifndef __ARCH_ORION5X_COMMON_H
+ #define __ARCH_ORION5X_COMMON_H
+
++struct mv643xx_eth_platform_data;
++struct mv_sata_platform_data;
++
+ /*
+ * Basic Orion init functions used early by machine-setup.
+ */
+-
+ void orion5x_map_io(void);
+ void orion5x_init_irq(void);
+ void orion5x_init(void);
+@@ -23,13 +25,19 @@
+ void orion5x_setup_dev2_win(u32 base, u32 size);
+ void orion5x_setup_pcie_wa_win(u32 base, u32 size);
+
++void orion5x_ehci0_init(void);
++void orion5x_ehci1_init(void);
++void orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data);
++void orion5x_i2c_init(void);
++void orion5x_sata_init(struct mv_sata_platform_data *sata_data);
++void orion5x_uart0_init(void);
++void orion5x_uart1_init(void);
++
+ /*
+- * Shared code used internally by other Orion core functions.
+- * (/mach-orion/pci.c)
++ * PCIe/PCI functions.
+ */
+-
+-struct pci_sys_data;
+ struct pci_bus;
++struct pci_sys_data;
+
+ void orion5x_pcie_id(u32 *dev, u32 *rev);
+ int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys);
+@@ -40,26 +48,9 @@
+ * Valid GPIO pins according to MPP setup, used by machine-setup.
+ * (/mach-orion/gpio.c).
+ */
+-
+ void orion5x_gpio_set_valid_pins(u32 pins);
+ void gpio_display(void); /* debug */
+
+-/*
+- * Pull in Orion Ethernet platform_data, used by machine-setup
+- */
+-
+-struct mv643xx_eth_platform_data;
+-
+-void orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data);
+-
+-/*
+- * Orion Sata platform_data, used by machine-setup
+- */
+-
+-struct mv_sata_platform_data;
+-
+-void orion5x_sata_init(struct mv_sata_platform_data *sata_data);
+-
+ struct machine_desc;
+ struct meminfo;
+ struct tag;
+--- a/arch/arm/mach-orion5x/db88f5281-setup.c
++++ b/arch/arm/mach-orion5x/db88f5281-setup.c
+@@ -298,13 +298,6 @@
+ /*****************************************************************************
+ * General Setup
+ ****************************************************************************/
+-
+-static struct platform_device *db88f5281_devs[] __initdata = {
+- &db88f5281_boot_flash,
+- &db88f5281_nor_flash,
+- &db88f5281_nand_flash,
+-};
+-
+ static void __init db88f5281_init(void)
+ {
+ /*
+@@ -313,15 +306,6 @@
+ orion5x_init();
+
+ /*
+- * Setup the CPU address decode windows for our on-board devices
+- */
+- orion5x_setup_dev_boot_win(DB88F5281_NOR_BOOT_BASE,
+- DB88F5281_NOR_BOOT_SIZE);
+- orion5x_setup_dev0_win(DB88F5281_7SEG_BASE, DB88F5281_7SEG_SIZE);
+- orion5x_setup_dev1_win(DB88F5281_NOR_BASE, DB88F5281_NOR_SIZE);
+- orion5x_setup_dev2_win(DB88F5281_NAND_BASE, DB88F5281_NAND_SIZE);
+-
+- /*
+ * Setup Multiplexing Pins:
+ * MPP0: GPIO (USB Over Current) MPP1: GPIO (USB Vbat input)
+ * MPP2: PCI_REQn[2] MPP3: PCI_GNTn[2]
+@@ -342,9 +326,28 @@
+
+ orion5x_gpio_set_valid_pins(0x00003fc3);
+
+- platform_add_devices(db88f5281_devs, ARRAY_SIZE(db88f5281_devs));
+- i2c_register_board_info(0, &db88f5281_i2c_rtc, 1);
++ /*
++ * Configure peripherals.
++ */
++ orion5x_ehci0_init();
+ orion5x_eth_init(&db88f5281_eth_data);
++ orion5x_i2c_init();
++ orion5x_uart0_init();
++ orion5x_uart1_init();
++
++ orion5x_setup_dev_boot_win(DB88F5281_NOR_BOOT_BASE,
++ DB88F5281_NOR_BOOT_SIZE);
++ platform_device_register(&db88f5281_boot_flash);
++
++ orion5x_setup_dev0_win(DB88F5281_7SEG_BASE, DB88F5281_7SEG_SIZE);
++
++ orion5x_setup_dev1_win(DB88F5281_NOR_BASE, DB88F5281_NOR_SIZE);
++ platform_device_register(&db88f5281_nor_flash);
++
++ orion5x_setup_dev2_win(DB88F5281_NAND_BASE, DB88F5281_NAND_SIZE);
++ platform_device_register(&db88f5281_nand_flash);
++
++ i2c_register_board_info(0, &db88f5281_i2c_rtc, 1);
+ }
+
+ MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board")
+--- a/arch/arm/mach-orion5x/dns323-setup.c
++++ b/arch/arm/mach-orion5x/dns323-setup.c
+@@ -213,12 +213,6 @@
+ * General Setup
+ */
+
+-static struct platform_device *dns323_plat_devices[] __initdata = {
+- &dns323_nor_flash,
+- &dns323_gpio_leds,
+- &dns323_button_device,
+-};
+-
+ /*
+ * On the DNS-323 the following devices are attached via I2C:
+ *
+@@ -253,11 +247,6 @@
+ /* Setup basic Orion functions. Need to be called early. */
+ orion5x_init();
+
+- /* setup flash mapping
+- * CS3 holds a 8 MB Spansion S29GL064M90TFIR4
+- */
+- orion5x_setup_dev_boot_win(DNS323_NOR_BOOT_BASE, DNS323_NOR_BOOT_SIZE);
+-
+ /* DNS-323 has a Marvell 88X7042 SATA controller attached via PCIe
+ *
+ * Open a special address decode windows for the PCIe WA.
+@@ -294,21 +283,32 @@
+ */
+ orion5x_gpio_set_valid_pins(0x07f6);
+
+- /* register dns323 specific power-off method */
+- if (gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0 ||
+- gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0)
+- pr_err("DNS323: failed to setup power-off GPIO\n");
++ /*
++ * Configure peripherals.
++ */
++ orion5x_ehci0_init();
++ orion5x_eth_init(&dns323_eth_data);
++ orion5x_i2c_init();
++ orion5x_uart0_init();
+
+- pm_power_off = dns323_power_off;
++ /* setup flash mapping
++ * CS3 holds a 8 MB Spansion S29GL064M90TFIR4
++ */
++ orion5x_setup_dev_boot_win(DNS323_NOR_BOOT_BASE, DNS323_NOR_BOOT_SIZE);
++ platform_device_register(&dns323_nor_flash);
++
++ platform_device_register(&dns323_gpio_leds);
+
+- /* register flash and other platform devices */
+- platform_add_devices(dns323_plat_devices,
+- ARRAY_SIZE(dns323_plat_devices));
++ platform_device_register(&dns323_button_device);
+
+ i2c_register_board_info(0, dns323_i2c_devices,
+ ARRAY_SIZE(dns323_i2c_devices));
+
+- orion5x_eth_init(&dns323_eth_data);
++ /* register dns323 specific power-off method */
++ if (gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0 ||
++ gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0)
++ pr_err("DNS323: failed to setup power-off GPIO\n");
++ pm_power_off = dns323_power_off;
+ }
+
+ /* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */
+--- a/arch/arm/mach-orion5x/kurobox_pro-setup.c
++++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
+@@ -188,13 +188,6 @@
+ orion5x_init();
+
+ /*
+- * Setup the CPU address decode windows for our devices
+- */
+- orion5x_setup_dev_boot_win(KUROBOX_PRO_NOR_BOOT_BASE,
+- KUROBOX_PRO_NOR_BOOT_SIZE);
+- orion5x_setup_dev0_win(KUROBOX_PRO_NAND_BASE, KUROBOX_PRO_NAND_SIZE);
+-
+- /*
+ * Open a special address decode windows for the PCIe WA.
+ */
+ orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
+@@ -221,12 +214,27 @@
+
+ orion5x_gpio_set_valid_pins(0x0000000c);
+
++ /*
++ * Configure peripherals.
++ */
++ orion5x_ehci0_init();
++ orion5x_ehci1_init();
++ orion5x_eth_init(&kurobox_pro_eth_data);
++ orion5x_i2c_init();
++ orion5x_sata_init(&kurobox_pro_sata_data);
++ orion5x_uart0_init();
++
++ orion5x_setup_dev_boot_win(KUROBOX_PRO_NOR_BOOT_BASE,
++ KUROBOX_PRO_NOR_BOOT_SIZE);
+ platform_device_register(&kurobox_pro_nor_flash);
+- if (machine_is_kurobox_pro())
++
++ if (machine_is_kurobox_pro()) {
++ orion5x_setup_dev0_win(KUROBOX_PRO_NAND_BASE,
++ KUROBOX_PRO_NAND_SIZE);
+ platform_device_register(&kurobox_pro_nand_flash);
++ }
++
+ i2c_register_board_info(0, &kurobox_pro_i2c_rtc, 1);
+- orion5x_eth_init(&kurobox_pro_eth_data);
+- orion5x_sata_init(&kurobox_pro_sata_data);
+ }
+
+ #ifdef CONFIG_MACH_KUROBOX_PRO
+--- a/arch/arm/mach-orion5x/rd88f5182-setup.c
++++ b/arch/arm/mach-orion5x/rd88f5182-setup.c
+@@ -241,11 +241,6 @@
+ /*****************************************************************************
+ * General Setup
+ ****************************************************************************/
+-
+-static struct platform_device *rd88f5182_devices[] __initdata = {
+- &rd88f5182_nor_flash,
+-};
+-
+ static void __init rd88f5182_init(void)
+ {
+ /*
+@@ -254,13 +249,6 @@
+ orion5x_init();
+
+ /*
+- * Setup the CPU address decode windows for our devices
+- */
+- orion5x_setup_dev_boot_win(RD88F5182_NOR_BOOT_BASE,
+- RD88F5182_NOR_BOOT_SIZE);
+- orion5x_setup_dev1_win(RD88F5182_NOR_BASE, RD88F5182_NOR_SIZE);
+-
+- /*
+ * Open a special address decode windows for the PCIe WA.
+ */
+ orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
+@@ -296,10 +284,23 @@
+
+ orion5x_gpio_set_valid_pins(0x000000fb);
+
+- platform_add_devices(rd88f5182_devices, ARRAY_SIZE(rd88f5182_devices));
+- i2c_register_board_info(0, &rd88f5182_i2c_rtc, 1);
++ /*
++ * Configure peripherals.
++ */
++ orion5x_ehci0_init();
++ orion5x_ehci1_init();
+ orion5x_eth_init(&rd88f5182_eth_data);
++ orion5x_i2c_init();
+ orion5x_sata_init(&rd88f5182_sata_data);
++ orion5x_uart0_init();
++
++ orion5x_setup_dev_boot_win(RD88F5182_NOR_BOOT_BASE,
++ RD88F5182_NOR_BOOT_SIZE);
++
++ orion5x_setup_dev1_win(RD88F5182_NOR_BASE, RD88F5182_NOR_SIZE);
++ platform_device_register(&rd88f5182_nor_flash);
++
++ i2c_register_board_info(0, &rd88f5182_i2c_rtc, 1);
+ }
+
+ MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design")
+--- a/arch/arm/mach-orion5x/ts209-setup.c
++++ b/arch/arm/mach-orion5x/ts209-setup.c
+@@ -332,16 +332,9 @@
+
+ * General Setup
+ ****************************************************************************/
+-
+-static struct platform_device *qnap_ts209_devices[] __initdata = {
+- &qnap_ts209_nor_flash,
+- &qnap_ts209_button_device,
+-};
+-
+ /*
+ * QNAP TS-[12]09 specific power off method via UART1-attached PIC
+ */
+-
+ #define UART1_REG(x) (UART1_VIRT_BASE + ((UART_##x) << 2))
+
+ static void qnap_ts209_power_off(void)
+@@ -372,12 +365,6 @@
+ orion5x_init();
+
+ /*
+- * Setup flash mapping
+- */
+- orion5x_setup_dev_boot_win(QNAP_TS209_NOR_BOOT_BASE,
+- QNAP_TS209_NOR_BOOT_SIZE);
+-
+- /*
+ * Open a special address decode windows for the PCIe WA.
+ */
+ orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
+@@ -411,11 +398,22 @@
+ orion5x_write(MPP_16_19_CTRL, 0x5500);
+ orion5x_gpio_set_valid_pins(0x3cc0fff);
+
+- /* register ts209 specific power-off method */
+- pm_power_off = qnap_ts209_power_off;
++ /*
++ * Configure peripherals.
++ */
++ orion5x_ehci0_init();
++ orion5x_ehci1_init();
++ ts209_find_mac_addr();
++ orion5x_eth_init(&qnap_ts209_eth_data);
++ orion5x_i2c_init();
++ orion5x_sata_init(&qnap_ts209_sata_data);
++ orion5x_uart0_init();
++
++ orion5x_setup_dev_boot_win(QNAP_TS209_NOR_BOOT_BASE,
++ QNAP_TS209_NOR_BOOT_SIZE);
++ platform_device_register(&qnap_ts209_nor_flash);
+
+- platform_add_devices(qnap_ts209_devices,
+- ARRAY_SIZE(qnap_ts209_devices));
++ platform_device_register(&qnap_ts209_button_device);
+
+ /* Get RTC IRQ and register the chip */
+ if (gpio_request(TS209_RTC_GPIO, "rtc") == 0) {
+@@ -428,10 +426,8 @@
+ pr_warning("qnap_ts209_init: failed to get RTC IRQ\n");
+ i2c_register_board_info(0, &qnap_ts209_i2c_rtc, 1);
+
+- ts209_find_mac_addr();
+- orion5x_eth_init(&qnap_ts209_eth_data);
+-
+- orion5x_sata_init(&qnap_ts209_sata_data);
++ /* register ts209 specific power-off method */
++ pm_power_off = qnap_ts209_power_off;
+ }
+
+ MACHINE_START(TS209, "QNAP TS-109/TS-209")
diff --git a/target/linux/orion/patches/011-move_setting_up_pcie_wa_window_into_pcie.patch b/target/linux/orion/patches/011-move_setting_up_pcie_wa_window_into_pcie.patch
new file mode 100644
index 0000000000..f6e78d84d8
--- /dev/null
+++ b/target/linux/orion/patches/011-move_setting_up_pcie_wa_window_into_pcie.patch
@@ -0,0 +1,90 @@
+It makes no sense to do PCIe WA window setup in the individual
+board support files while the decision whether or not to use the
+PCIe WA access method is made in a different place, in the PCIe
+support code.
+
+This patch moves the configuration of a PCIe WA window from the
+individual Orion board support files to the central Orion PCIe
+support code.
+
+Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
+---
+ arch/arm/mach-orion5x/dns323-setup.c | 7 -------
+ arch/arm/mach-orion5x/kurobox_pro-setup.c | 6 ------
+ arch/arm/mach-orion5x/pci.c | 2 ++
+ arch/arm/mach-orion5x/rd88f5182-setup.c | 6 ------
+ arch/arm/mach-orion5x/ts209-setup.c | 6 ------
+ 5 files changed, 2 insertions(+), 25 deletions(-)
+
+--- a/arch/arm/mach-orion5x/dns323-setup.c
++++ b/arch/arm/mach-orion5x/dns323-setup.c
+@@ -247,13 +247,6 @@
+ /* Setup basic Orion functions. Need to be called early. */
+ orion5x_init();
+
+- /* DNS-323 has a Marvell 88X7042 SATA controller attached via PCIe
+- *
+- * Open a special address decode windows for the PCIe WA.
+- */
+- orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
+- ORION5X_PCIE_WA_SIZE);
+-
+ /* set MPP to 0 as D-Link's 2.6.12.6 kernel did */
+ orion5x_write(MPP_0_7_CTRL, 0);
+ orion5x_write(MPP_8_15_CTRL, 0);
+--- a/arch/arm/mach-orion5x/kurobox_pro-setup.c
++++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
+@@ -188,12 +188,6 @@
+ orion5x_init();
+
+ /*
+- * Open a special address decode windows for the PCIe WA.
+- */
+- orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
+- ORION5X_PCIE_WA_SIZE);
+-
+- /*
+ * Setup Multiplexing Pins --
+ * MPP[0-1] Not used
+ * MPP[2] GPIO Micon
+--- a/arch/arm/mach-orion5x/pci.c
++++ b/arch/arm/mach-orion5x/pci.c
+@@ -152,6 +152,8 @@
+ if (dev == MV88F5181_DEV_ID || dev == MV88F5182_DEV_ID) {
+ printk(KERN_NOTICE "Applying Orion-1/Orion-NAS PCIe config "
+ "read transaction workaround\n");
++ orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
++ ORION5X_PCIE_WA_SIZE);
+ pcie_ops.read = pcie_rd_conf_wa;
+ }
+
+--- a/arch/arm/mach-orion5x/rd88f5182-setup.c
++++ b/arch/arm/mach-orion5x/rd88f5182-setup.c
+@@ -249,12 +249,6 @@
+ orion5x_init();
+
+ /*
+- * Open a special address decode windows for the PCIe WA.
+- */
+- orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
+- ORION5X_PCIE_WA_SIZE);
+-
+- /*
+ * Setup Multiplexing Pins --
+ * MPP[0] Debug Led (GPIO - Out)
+ * MPP[1] Debug Led (GPIO - Out)
+--- a/arch/arm/mach-orion5x/ts209-setup.c
++++ b/arch/arm/mach-orion5x/ts209-setup.c
+@@ -365,12 +365,6 @@
+ orion5x_init();
+
+ /*
+- * Open a special address decode windows for the PCIe WA.
+- */
+- orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
+- ORION5X_PCIE_WA_SIZE);
+-
+- /*
+ * Setup Multiplexing Pins --
+ * MPP[0] Reserved
+ * MPP[1] USB copy button (0 active)
diff --git a/target/linux/orion/patches/012-rework_mpp_handling.patch b/target/linux/orion/patches/012-rework_mpp_handling.patch
new file mode 100644
index 0000000000..05e1881259
--- /dev/null
+++ b/target/linux/orion/patches/012-rework_mpp_handling.patch
@@ -0,0 +1,583 @@
+Instead of having board code poke directly into the MPP configuration
+registers, and separately calling orion5x_gpio_set_valid_pins() to
+indicate which MPP pins can be used as GPIO pins, introduce a helper
+function for configuring the roles of each of the MPP pins, and have
+that helper function handle gpio validity internally.
+
+Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
+Acked-by: Sylver Bruneau <sylver.bruneau@googlemail.com>
+---
+ arch/arm/mach-orion5x/Makefile | 2 +-
+ arch/arm/mach-orion5x/common.h | 2 +-
+ arch/arm/mach-orion5x/db88f5281-setup.c | 42 +++++----
+ arch/arm/mach-orion5x/dns323-setup.c | 50 +++++------
+ arch/arm/mach-orion5x/gpio.c | 7 +-
+ arch/arm/mach-orion5x/kurobox_pro-setup.c | 41 ++++----
+ arch/arm/mach-orion5x/mpp.c | 142 +++++++++++++++++++++++++++++
+ arch/arm/mach-orion5x/mpp.h | 63 +++++++++++++
+ arch/arm/mach-orion5x/rd88f5182-setup.c | 43 +++++----
+ arch/arm/mach-orion5x/ts209-setup.c | 43 +++++----
+ 10 files changed, 321 insertions(+), 114 deletions(-)
+ create mode 100644 arch/arm/mach-orion5x/mpp.c
+ create mode 100644 arch/arm/mach-orion5x/mpp.h
+
+--- a/arch/arm/mach-orion5x/Makefile
++++ b/arch/arm/mach-orion5x/Makefile
+@@ -1,4 +1,4 @@
+-obj-y += common.o addr-map.o pci.o gpio.o irq.o
++obj-y += common.o addr-map.o pci.o gpio.o irq.o mpp.o
+ obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o
+ obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o
+ obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobox_pro-setup.o
+--- a/arch/arm/mach-orion5x/common.h
++++ b/arch/arm/mach-orion5x/common.h
+@@ -48,7 +48,7 @@
+ * Valid GPIO pins according to MPP setup, used by machine-setup.
+ * (/mach-orion/gpio.c).
+ */
+-void orion5x_gpio_set_valid_pins(u32 pins);
++void orion5x_gpio_set_valid(unsigned pin, int valid);
+ void gpio_display(void); /* debug */
+
+ struct machine_desc;
+--- a/arch/arm/mach-orion5x/db88f5281-setup.c
++++ b/arch/arm/mach-orion5x/db88f5281-setup.c
+@@ -27,6 +27,7 @@
+ #include <asm/arch/orion5x.h>
+ #include <asm/plat-orion/orion_nand.h>
+ #include "common.h"
++#include "mpp.h"
+
+ /*****************************************************************************
+ * DB-88F5281 on board devices
+@@ -305,26 +306,27 @@
+ */
+ orion5x_init();
+
+- /*
+- * Setup Multiplexing Pins:
+- * MPP0: GPIO (USB Over Current) MPP1: GPIO (USB Vbat input)
+- * MPP2: PCI_REQn[2] MPP3: PCI_GNTn[2]
+- * MPP4: PCI_REQn[3] MPP5: PCI_GNTn[3]
+- * MPP6: GPIO (JP0, CON17.2) MPP7: GPIO (JP1, CON17.1)
+- * MPP8: GPIO (JP2, CON11.2) MPP9: GPIO (JP3, CON11.3)
+- * MPP10: GPIO (RTC int) MPP11: GPIO (Baud Rate Generator)
+- * MPP12: GPIO (PCI int 1) MPP13: GPIO (PCI int 2)
+- * MPP14: NAND_REn[2] MPP15: NAND_WEn[2]
+- * MPP16: UART1_RX MPP17: UART1_TX
+- * MPP18: UART1_CTS MPP19: UART1_RTS
+- * MPP-DEV: DEV_D[16:31]
+- */
+- orion5x_write(MPP_0_7_CTRL, 0x00222203);
+- orion5x_write(MPP_8_15_CTRL, 0x44000000);
+- orion5x_write(MPP_16_19_CTRL, 0);
+- orion5x_write(MPP_DEV_CTRL, 0);
+-
+- orion5x_gpio_set_valid_pins(0x00003fc3);
++ orion5x_mpp_conf(0, MPP_GPIO); /* USB Over Current */
++ orion5x_mpp_conf(1, MPP_GPIO); /* USB Vbat input */
++ orion5x_mpp_conf(2, MPP_PCI_ARB); /* PCI_REQn[2] */
++ orion5x_mpp_conf(3, MPP_PCI_ARB); /* PCI_GNTn[2] */
++ orion5x_mpp_conf(4, MPP_PCI_ARB); /* PCI_REQn[3] */
++ orion5x_mpp_conf(5, MPP_PCI_ARB); /* PCI_GNTn[3] */
++ orion5x_mpp_conf(6, MPP_GPIO); /* JP0, CON17.2 */
++ orion5x_mpp_conf(7, MPP_GPIO); /* JP1, CON17.1 */
++ orion5x_mpp_conf(8, MPP_GPIO); /* JP2, CON11.2 */
++ orion5x_mpp_conf(9, MPP_GPIO); /* JP3, CON11.3 */
++ orion5x_mpp_conf(10, MPP_GPIO); /* RTC int */
++ orion5x_mpp_conf(11, MPP_GPIO); /* Baud Rate Generator */
++ orion5x_mpp_conf(12, MPP_GPIO); /* PCI int 1 */
++ orion5x_mpp_conf(13, MPP_GPIO); /* PCI int 2 */
++ orion5x_mpp_conf(14, MPP_NAND); /* NAND_REn[2] */
++ orion5x_mpp_conf(15, MPP_NAND); /* NAND_WEn[2] */
++ orion5x_mpp_conf(16, MPP_UART); /* UART1_RX */
++ orion5x_mpp_conf(17, MPP_UART); /* UART1_TX */
++ orion5x_mpp_conf(18, MPP_UART); /* UART1_CTSn */
++ orion5x_mpp_conf(19, MPP_UART); /* UART1_RTSn */
++ orion5x_write(MPP_DEV_CTRL, 0); /* DEV_D[31:16] */
+
+ /*
+ * Configure peripherals.
+--- a/arch/arm/mach-orion5x/dns323-setup.c
++++ b/arch/arm/mach-orion5x/dns323-setup.c
+@@ -27,6 +27,7 @@
+ #include <asm/mach/pci.h>
+ #include <asm/arch/orion5x.h>
+ #include "common.h"
++#include "mpp.h"
+
+ #define DNS323_GPIO_LED_RIGHT_AMBER 1
+ #define DNS323_GPIO_LED_LEFT_AMBER 2
+@@ -247,34 +248,27 @@
+ /* Setup basic Orion functions. Need to be called early. */
+ orion5x_init();
+
+- /* set MPP to 0 as D-Link's 2.6.12.6 kernel did */
+- orion5x_write(MPP_0_7_CTRL, 0);
+- orion5x_write(MPP_8_15_CTRL, 0);
+- orion5x_write(MPP_16_19_CTRL, 0);
+- orion5x_write(MPP_DEV_CTRL, 0);
+-
+- /* Define used GPIO pins
+-
+- GPIO Map:
+-
+- | 0 | | PEX_RST_OUT (not controlled by GPIO)
+- | 1 | Out | right amber LED (= sata ch0 LED) (low-active)
+- | 2 | Out | left amber LED (= sata ch1 LED) (low-active)
+- | 3 | Out | //unknown//
+- | 4 | Out | power button LED (low-active, together with pin #5)
+- | 5 | Out | power button LED (low-active, together with pin #4)
+- | 6 | In | GMT G751-2f overtemp. shutdown signal (low-active)
+- | 7 | In | M41T80 nIRQ/OUT/SQW signal
+- | 8 | Out | triggers power off (high-active)
+- | 9 | In | power button switch (low-active)
+- | 10 | In | reset button switch (low-active)
+- | 11 | Out | //unknown//
+- | 12 | Out | //unknown//
+- | 13 | Out | //unknown//
+- | 14 | Out | //unknown//
+- | 15 | Out | //unknown//
+- */
+- orion5x_gpio_set_valid_pins(0x07f6);
++ orion5x_mpp_conf(0, MPP_PCIE_RST_OUTn);
++ orion5x_mpp_conf(1, MPP_GPIO); /* right amber LED (sata ch0) */
++ orion5x_mpp_conf(2, MPP_GPIO); /* left amber LED (sata ch1) */
++ orion5x_mpp_conf(3, MPP_UNUSED);
++ orion5x_mpp_conf(4, MPP_GPIO); /* power button LED */
++ orion5x_mpp_conf(5, MPP_GPIO); /* power button LED */
++ orion5x_mpp_conf(6, MPP_GPIO); /* GMT G751-2f overtemp */
++ orion5x_mpp_conf(7, MPP_GPIO); /* M41T80 nIRQ/OUT/SQW */
++ orion5x_mpp_conf(8, MPP_GPIO); /* triggers power off */
++ orion5x_mpp_conf(9, MPP_GPIO); /* power button switch */
++ orion5x_mpp_conf(10, MPP_GPIO); /* reset button switch */
++ orion5x_mpp_conf(11, MPP_UNUSED);
++ orion5x_mpp_conf(12, MPP_UNUSED);
++ orion5x_mpp_conf(13, MPP_UNUSED);
++ orion5x_mpp_conf(14, MPP_UNUSED);
++ orion5x_mpp_conf(15, MPP_UNUSED);
++ orion5x_mpp_conf(16, MPP_UNUSED);
++ orion5x_mpp_conf(17, MPP_UNUSED);
++ orion5x_mpp_conf(18, MPP_UNUSED);
++ orion5x_mpp_conf(19, MPP_UNUSED);
++ orion5x_write(MPP_DEV_CTRL, 0); /* DEV_D[31:16] */
+
+ /*
+ * Configure peripherals.
+--- a/arch/arm/mach-orion5x/gpio.c
++++ b/arch/arm/mach-orion5x/gpio.c
+@@ -24,9 +24,12 @@
+ static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)];
+ static const char *gpio_label[GPIO_MAX]; /* non null for allocated GPIOs */
+
+-void __init orion5x_gpio_set_valid_pins(u32 pins)
++void __init orion5x_gpio_set_valid(unsigned pin, int valid)
+ {
+- gpio_valid[0] = pins;
++ if (valid)
++ __set_bit(pin, gpio_valid);
++ else
++ __clear_bit(pin, gpio_valid);
+ }
+
+ /*
+--- a/arch/arm/mach-orion5x/kurobox_pro-setup.c
++++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
+@@ -25,6 +25,7 @@
+ #include <asm/arch/orion5x.h>
+ #include <asm/plat-orion/orion_nand.h>
+ #include "common.h"
++#include "mpp.h"
+
+ /*****************************************************************************
+ * KUROBOX-PRO Info
+@@ -187,26 +188,26 @@
+ */
+ orion5x_init();
+
+- /*
+- * Setup Multiplexing Pins --
+- * MPP[0-1] Not used
+- * MPP[2] GPIO Micon
+- * MPP[3] GPIO RTC
+- * MPP[4-5] Not used
+- * MPP[6] Nand Flash REn
+- * MPP[7] Nand Flash WEn
+- * MPP[8-11] Not used
+- * MPP[12] SATA 0 presence Indication
+- * MPP[13] SATA 1 presence Indication
+- * MPP[14] SATA 0 active Indication
+- * MPP[15] SATA 1 active indication
+- * MPP[16-19] Not used
+- */
+- orion5x_write(MPP_0_7_CTRL, 0x44220003);
+- orion5x_write(MPP_8_15_CTRL, 0x55550000);
+- orion5x_write(MPP_16_19_CTRL, 0x0);
+-
+- orion5x_gpio_set_valid_pins(0x0000000c);
++ orion5x_mpp_conf(0, MPP_UNUSED);
++ orion5x_mpp_conf(1, MPP_UNUSED);
++ orion5x_mpp_conf(2, MPP_GPIO); /* GPIO Micon */
++ orion5x_mpp_conf(3, MPP_GPIO); /* GPIO Rtc */
++ orion5x_mpp_conf(4, MPP_UNUSED);
++ orion5x_mpp_conf(5, MPP_UNUSED);
++ orion5x_mpp_conf(6, MPP_NAND); /* NAND Flash REn */
++ orion5x_mpp_conf(7, MPP_NAND); /* NAND Flash WEn */
++ orion5x_mpp_conf(8, MPP_UNUSED);
++ orion5x_mpp_conf(9, MPP_UNUSED);
++ orion5x_mpp_conf(10, MPP_UNUSED);
++ orion5x_mpp_conf(11, MPP_UNUSED);
++ orion5x_mpp_conf(12, MPP_SATA_LED); /* SATA 0 presence */
++ orion5x_mpp_conf(13, MPP_SATA_LED); /* SATA 1 presence */
++ orion5x_mpp_conf(14, MPP_SATA_LED); /* SATA 0 active */
++ orion5x_mpp_conf(15, MPP_SATA_LED); /* SATA 1 active */
++ orion5x_mpp_conf(16, MPP_UNUSED);
++ orion5x_mpp_conf(17, MPP_UNUSED);
++ orion5x_mpp_conf(18, MPP_UNUSED);
++ orion5x_mpp_conf(19, MPP_UNUSED);
+
+ /*
+ * Configure peripherals.
+--- /dev/null
++++ b/arch/arm/mach-orion5x/mpp.c
+@@ -0,0 +1,142 @@
++/*
++ * arch/arm/mach-orion5x/mpp.c
++ *
++ * MPP functions for Marvell Orion 5x SoCs
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/mbus.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include "common.h"
++#include "mpp.h"
++
++static int is_5182(void)
++{
++ u32 dev;
++ u32 rev;
++
++ orion5x_pcie_id(&dev, &rev);
++
++ return !!(dev == MV88F5182_DEV_ID);
++}
++
++static int is_5281(void)
++{
++ u32 dev;
++ u32 rev;
++
++ orion5x_pcie_id(&dev, &rev);
++
++ return !!(dev == MV88F5281_DEV_ID);
++}
++
++static int __init determine_type_encoding(int mpp, enum orion5x_mpp_type type)
++{
++ switch (type) {
++ case MPP_UNUSED:
++ case MPP_GPIO:
++ if (mpp == 0)
++ return 3;
++ if (mpp >= 1 && mpp <= 15)
++ return 0;
++ if (mpp >= 16 && mpp <= 19) {
++ if (is_5182())
++ return 5;
++ if (type == MPP_UNUSED)
++ return 0;
++ }
++ return -1;
++
++ case MPP_PCIE_RST_OUTn:
++ if (mpp == 0)
++ return 0;
++ return -1;
++
++ case MPP_PCI_ARB:
++ if (mpp >= 0 && mpp <= 7)
++ return 2;
++ return -1;
++
++ case MPP_PCI_PMEn:
++ if (mpp == 2)
++ return 3;
++ return -1;
++
++ case MPP_GIGE:
++ if (mpp >= 8 && mpp <= 15)
++ return 1;
++ return -1;
++
++ case MPP_NAND:
++ if (is_5182() || is_5281()) {
++ if (mpp >= 4 && mpp <= 7)
++ return 4;
++ if (mpp >= 12 && mpp <= 17)
++ return 4;
++ }
++ return -1;
++
++
++ case MPP_SATA_LED:
++ if (is_5182()) {
++ if (mpp >= 4 && mpp <= 7)
++ return 5;
++ if (mpp >= 12 && mpp <= 15)
++ return 5;
++ }
++ return -1;
++
++ case MPP_UART:
++ if (mpp >= 16 && mpp <= 19)
++ return 0;
++ return -1;
++ }
++
++ printk(KERN_INFO "unknown MPP type %d\n", type);
++
++ return -1;
++}
++
++static void __init set_mpp_type(int mpp, int num_type)
++{
++ unsigned long reg;
++ u32 value;
++
++ if (mpp >= 0 && mpp <= 7)
++ reg = MPP_0_7_CTRL;
++ else if (mpp >= 8 && mpp <= 15)
++ reg = MPP_8_15_CTRL;
++ else if (mpp >= 16 && mpp <= 19)
++ reg = MPP_16_19_CTRL;
++ else
++ return;
++
++ mpp &= 7;
++
++ value = readl(reg);
++ value &= ~(0xf << (mpp << 2));
++ value |= (num_type & 0xf) << (mpp << 2);
++ writel(value, reg);
++}
++
++void __init orion5x_mpp_conf(int mpp, enum orion5x_mpp_type type)
++{
++ int num_type;
++
++ num_type = determine_type_encoding(mpp, type);
++ if (num_type < 0) {
++ printk(KERN_ERR "orion5x_mpp_conf: invalid MPP "
++ "combination (%d, %d)\n", mpp, type);
++ return;
++ }
++
++ set_mpp_type(mpp, num_type);
++
++ orion5x_gpio_set_valid(mpp, (type == MPP_GPIO) ? 1 : 0);
++}
+--- /dev/null
++++ b/arch/arm/mach-orion5x/mpp.h
+@@ -0,0 +1,63 @@
++#ifndef __ARCH_ORION5X_MPP_H
++#define __ARCH_ORION5X_MPP_H
++
++enum orion5x_mpp_type {
++ /*
++ * This MPP is unused.
++ */
++ MPP_UNUSED,
++
++ /*
++ * This MPP pin is used as a generic GPIO pin. Valid for
++ * MPPs 0-15 and device bus data pins 16-31. On 5182, also
++ * valid for MPPs 16-19.
++ */
++ MPP_GPIO,
++
++ /*
++ * This MPP is used as PCIe_RST_OUTn pin. Valid for
++ * MPP 0 only.
++ */
++ MPP_PCIE_RST_OUTn,
++
++ /*
++ * This MPP is used as PCI arbiter pin (REQn/GNTn.)
++ * Valid for MPPs 0-7 only.
++ */
++ MPP_PCI_ARB,
++
++ /*
++ * This MPP is used as PCI_PMEn pin. Valid for MPP 2 only.
++ */
++ MPP_PCI_PMEn,
++
++ /*
++ * This MPP is used as GigE half-duplex (COL, CRS) or GMII
++ * (RXERR, CRS, TXERR, TXD[7:4], RXD[7:4]) pin. Valid for
++ * MPPs 8-19 only.
++ */
++ MPP_GIGE,
++
++ /*
++ * This MPP is used as NAND REn/WEn pin. Valid for MPPs
++ * 4-7 and 12-17 only, and only on the 5181l/5182/5281.
++ */
++ MPP_NAND,
++
++ /*
++ * This MPP is used as a SATA presence/activity LED.
++ * Valid for MPPs 4-7 and 12-15 only, and only on the 5182.
++ */
++ MPP_SATA_LED,
++
++ /*
++ * This MPP is used as UART1 RXD/TXD/CTSn/RTSn pin.
++ * Valid for MPPs 16-19 only.
++ */
++ MPP_UART,
++};
++
++void orion5x_mpp_conf(int mpp, enum orion5x_mpp_type type);
++
++
++#endif
+--- a/arch/arm/mach-orion5x/rd88f5182-setup.c
++++ b/arch/arm/mach-orion5x/rd88f5182-setup.c
+@@ -26,6 +26,7 @@
+ #include <asm/mach/pci.h>
+ #include <asm/arch/orion5x.h>
+ #include "common.h"
++#include "mpp.h"
+
+ /*****************************************************************************
+ * RD-88F5182 Info
+@@ -248,22 +249,28 @@
+ */
+ orion5x_init();
+
++ orion5x_mpp_conf(0, MPP_GPIO); /* Debug Led */
++ orion5x_mpp_conf(1, MPP_GPIO); /* Reset Switch */
++ orion5x_mpp_conf(2, MPP_UNUSED);
++ orion5x_mpp_conf(3, MPP_GPIO); /* RTC Int */
++ orion5x_mpp_conf(4, MPP_GPIO);
++ orion5x_mpp_conf(5, MPP_GPIO);
++ orion5x_mpp_conf(6, MPP_GPIO); /* PCI_intA */
++ orion5x_mpp_conf(7, MPP_GPIO); /* PCI_intB */
++ orion5x_mpp_conf(8, MPP_UNUSED);
++ orion5x_mpp_conf(9, MPP_UNUSED);
++ orion5x_mpp_conf(10, MPP_UNUSED);
++ orion5x_mpp_conf(11, MPP_UNUSED);
++ orion5x_mpp_conf(12, MPP_SATA_LED); /* SATA 0 presence */
++ orion5x_mpp_conf(13, MPP_SATA_LED); /* SATA 1 presence */
++ orion5x_mpp_conf(14, MPP_SATA_LED); /* SATA 0 active */
++ orion5x_mpp_conf(15, MPP_SATA_LED); /* SATA 1 active */
++ orion5x_mpp_conf(16, MPP_UNUSED);
++ orion5x_mpp_conf(17, MPP_UNUSED);
++ orion5x_mpp_conf(18, MPP_UNUSED);
++ orion5x_mpp_conf(19, MPP_UNUSED);
++
+ /*
+- * Setup Multiplexing Pins --
+- * MPP[0] Debug Led (GPIO - Out)
+- * MPP[1] Debug Led (GPIO - Out)
+- * MPP[2] N/A
+- * MPP[3] RTC_Int (GPIO - In)
+- * MPP[4] GPIO
+- * MPP[5] GPIO
+- * MPP[6] PCI_intA (GPIO - In)
+- * MPP[7] PCI_intB (GPIO - In)
+- * MPP[8-11] N/A
+- * MPP[12] SATA 0 presence Indication
+- * MPP[13] SATA 1 presence Indication
+- * MPP[14] SATA 0 active Indication
+- * MPP[15] SATA 1 active indication
+- * MPP[16-19] Not used
+ * MPP[20] PCI Clock to MV88F5182
+ * MPP[21] PCI Clock to mini PCI CON11
+ * MPP[22] USB 0 over current indication
+@@ -272,12 +279,6 @@
+ * MPP[25] USB 0 over current enable
+ */
+
+- orion5x_write(MPP_0_7_CTRL, 0x00000003);
+- orion5x_write(MPP_8_15_CTRL, 0x55550000);
+- orion5x_write(MPP_16_19_CTRL, 0x5555);
+-
+- orion5x_gpio_set_valid_pins(0x000000fb);
+-
+ /*
+ * Configure peripherals.
+ */
+--- a/arch/arm/mach-orion5x/ts209-setup.c
++++ b/arch/arm/mach-orion5x/ts209-setup.c
+@@ -28,6 +28,7 @@
+ #include <asm/mach/pci.h>
+ #include <asm/arch/orion5x.h>
+ #include "common.h"
++#include "mpp.h"
+
+ #define QNAP_TS209_NOR_BOOT_BASE 0xf4000000
+ #define QNAP_TS209_NOR_BOOT_SIZE SZ_8M
+@@ -364,33 +365,33 @@
+ */
+ orion5x_init();
+
++ orion5x_mpp_conf(0, MPP_UNUSED);
++ orion5x_mpp_conf(1, MPP_GPIO); /* USB copy button */
++ orion5x_mpp_conf(2, MPP_GPIO); /* Load defaults button */
++ orion5x_mpp_conf(3, MPP_GPIO); /* GPIO RTC */
++ orion5x_mpp_conf(4, MPP_UNUSED);
++ orion5x_mpp_conf(5, MPP_UNUSED);
++ orion5x_mpp_conf(6, MPP_GPIO); /* PCI Int A */
++ orion5x_mpp_conf(7, MPP_GPIO); /* PCI Int B */
++ orion5x_mpp_conf(8, MPP_UNUSED);
++ orion5x_mpp_conf(9, MPP_UNUSED);
++ orion5x_mpp_conf(10, MPP_UNUSED);
++ orion5x_mpp_conf(11, MPP_UNUSED);
++ orion5x_mpp_conf(12, MPP_SATA_LED); /* SATA 0 presence */
++ orion5x_mpp_conf(13, MPP_SATA_LED); /* SATA 1 presence */
++ orion5x_mpp_conf(14, MPP_SATA_LED); /* SATA 0 active */
++ orion5x_mpp_conf(15, MPP_SATA_LED); /* SATA 1 active */
++ orion5x_mpp_conf(16, MPP_UART); /* UART1 RXD */
++ orion5x_mpp_conf(17, MPP_UART); /* UART1 TXD */
++ orion5x_mpp_conf(18, MPP_GPIO); /* SW_RST */
++ orion5x_mpp_conf(19, MPP_UNUSED);
++
+ /*
+- * Setup Multiplexing Pins --
+- * MPP[0] Reserved
+- * MPP[1] USB copy button (0 active)
+- * MPP[2] Load defaults button (0 active)
+- * MPP[3] GPIO RTC
+- * MPP[4-5] Reserved
+- * MPP[6] PCI Int A
+- * MPP[7] PCI Int B
+- * MPP[8-11] Reserved
+- * MPP[12] SATA 0 presence
+- * MPP[13] SATA 1 presence
+- * MPP[14] SATA 0 active
+- * MPP[15] SATA 1 active
+- * MPP[16] UART1 RXD
+- * MPP[17] UART1 TXD
+- * MPP[18] SW_RST (0 active)
+- * MPP[19] Reserved
+ * MPP[20] PCI clock 0
+ * MPP[21] PCI clock 1
+ * MPP[22] USB 0 over current
+ * MPP[23-25] Reserved
+ */
+- orion5x_write(MPP_0_7_CTRL, 0x3);
+- orion5x_write(MPP_8_15_CTRL, 0x55550000);
+- orion5x_write(MPP_16_19_CTRL, 0x5500);
+- orion5x_gpio_set_valid_pins(0x3cc0fff);
+
+ /*
+ * Configure peripherals.
diff --git a/target/linux/orion/patches/013-add_88f5181l_support.patch b/target/linux/orion/patches/013-add_88f5181l_support.patch
new file mode 100644
index 0000000000..b902777701
--- /dev/null
+++ b/target/linux/orion/patches/013-add_88f5181l_support.patch
@@ -0,0 +1,56 @@
+Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
+---
+ arch/arm/Kconfig | 3 ++-
+ arch/arm/mach-orion5x/common.c | 4 +++-
+ include/asm-arm/arch-orion5x/orion5x.h | 5 +++--
+ 3 files changed, 8 insertions(+), 4 deletions(-)
+
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -385,7 +385,8 @@
+ select PLAT_ORION
+ help
+ Support for the following Marvell Orion 5x series SoCs:
+- Orion-1 (5181), Orion-NAS (5182), Orion-2 (5281.)
++ Orion-1 (5181), Orion-VoIP (5181L), Orion-NAS (5182),
++ Orion-2 (5281.)
+
+ config ARCH_PNX4008
+ bool "Philips Nexperia PNX4008 Mobile"
+--- a/arch/arm/mach-orion5x/common.c
++++ b/arch/arm/mach-orion5x/common.c
+@@ -394,8 +394,10 @@
+ } else if (*dev == MV88F5181_DEV_ID) {
+ if (*rev == MV88F5181_REV_B1) {
+ *dev_name = "MV88F5181-Rev-B1";
++ } else if (*rev == MV88F5181L_REV_A1) {
++ *dev_name = "MV88F5181L-Rev-A1";
+ } else {
+- *dev_name = "MV88F5181-Rev-Unsupported";
++ *dev_name = "MV88F5181(L)-Rev-Unsupported";
+ }
+ } else {
+ *dev_name = "Device-Unknown";
+--- a/include/asm-arm/arch-orion5x/orion5x.h
++++ b/include/asm-arm/arch-orion5x/orion5x.h
+@@ -2,7 +2,7 @@
+ * include/asm-arm/arch-orion5x/orion5x.h
+ *
+ * Generic definitions of Orion SoC flavors:
+- * Orion-1, Orion-NAS, Orion-VoIP, and Orion-2.
++ * Orion-1, Orion-VoIP, Orion-NAS, and Orion-2.
+ *
+ * Maintainer: Tzachi Perelstein <tzachi@marvell.com>
+ *
+@@ -63,9 +63,10 @@
+ /*******************************************************************************
+ * Supported Devices & Revisions
+ ******************************************************************************/
+-/* Orion-1 (88F5181) */
++/* Orion-1 (88F5181) and Orion-VoIP (88F5181L) */
+ #define MV88F5181_DEV_ID 0x5181
+ #define MV88F5181_REV_B1 3
++#define MV88F5181L_REV_A1 9
+ /* Orion-NAS (88F5182) */
+ #define MV88F5182_DEV_ID 0x5182
+ #define MV88F5182_REV_A2 2
diff --git a/target/linux/orion/patches/014-avoid_setting_force_phy_addr.patch b/target/linux/orion/patches/014-avoid_setting_force_phy_addr.patch
new file mode 100644
index 0000000000..d47e5dd281
--- /dev/null
+++ b/target/linux/orion/patches/014-avoid_setting_force_phy_addr.patch
@@ -0,0 +1,71 @@
+The mv643xx_eth platform data field ->force_phy_addr only needs
+to be set if the passed-in ->phy_addr field is zero (to distinguish
+the case of not having specified a phy address
+(force_phy_addr = 0) from the case where a phy address of zero needs
+to be used (force_phy_addr = 1.))
+
+Also, the ->force_phy_addr field will hopefully disappear in a
+future mv643xx_eth reorganisation.
+
+Therefore, this patch deletes the ->force_phy_addr field initialiser
+from all Orion board code.
+
+Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
+---
+ arch/arm/mach-orion5x/db88f5281-setup.c | 1 -
+ arch/arm/mach-orion5x/dns323-setup.c | 1 -
+ arch/arm/mach-orion5x/kurobox_pro-setup.c | 1 -
+ arch/arm/mach-orion5x/rd88f5182-setup.c | 1 -
+ arch/arm/mach-orion5x/ts209-setup.c | 1 -
+ 5 files changed, 0 insertions(+), 5 deletions(-)
+
+--- a/arch/arm/mach-orion5x/db88f5281-setup.c
++++ b/arch/arm/mach-orion5x/db88f5281-setup.c
+@@ -286,7 +286,6 @@
+ ****************************************************************************/
+ static struct mv643xx_eth_platform_data db88f5281_eth_data = {
+ .phy_addr = 8,
+- .force_phy_addr = 1,
+ };
+
+ /*****************************************************************************
+--- a/arch/arm/mach-orion5x/dns323-setup.c
++++ b/arch/arm/mach-orion5x/dns323-setup.c
+@@ -82,7 +82,6 @@
+
+ static struct mv643xx_eth_platform_data dns323_eth_data = {
+ .phy_addr = 8,
+- .force_phy_addr = 1,
+ };
+
+ /****************************************************************************
+--- a/arch/arm/mach-orion5x/kurobox_pro-setup.c
++++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
+@@ -160,7 +160,6 @@
+
+ static struct mv643xx_eth_platform_data kurobox_pro_eth_data = {
+ .phy_addr = 8,
+- .force_phy_addr = 1,
+ };
+
+ /*****************************************************************************
+--- a/arch/arm/mach-orion5x/rd88f5182-setup.c
++++ b/arch/arm/mach-orion5x/rd88f5182-setup.c
+@@ -222,7 +222,6 @@
+
+ static struct mv643xx_eth_platform_data rd88f5182_eth_data = {
+ .phy_addr = 8,
+- .force_phy_addr = 1,
+ };
+
+ /*****************************************************************************
+--- a/arch/arm/mach-orion5x/ts209-setup.c
++++ b/arch/arm/mach-orion5x/ts209-setup.c
+@@ -191,7 +191,6 @@
+
+ static struct mv643xx_eth_platform_data qnap_ts209_eth_data = {
+ .phy_addr = 8,
+- .force_phy_addr = 1,
+ };
+
+ static int __init parse_hex_nibble(char n)
diff --git a/target/linux/orion/patches/015-implement_power-off_method_for_kurobox_pro.patch b/target/linux/orion/patches/015-implement_power-off_method_for_kurobox_pro.patch
new file mode 100644
index 0000000000..5814852388
--- /dev/null
+++ b/target/linux/orion/patches/015-implement_power-off_method_for_kurobox_pro.patch
@@ -0,0 +1,192 @@
+From: Sylver Bruneau <sylver.bruneau@googlemail.com>
+
+This patch implements the communication with the microcontroller on the
+Kurobox Pro and Linkstation Pro/Live boards. This is allowing to send
+the commands needed to power-off the board correctly.
+
+Signed-off-by: Sylver Bruneau <sylver.bruneau@googlemail.com>
+---
+ arch/arm/mach-orion5x/kurobox_pro-setup.c | 147 ++++++++++++++++++++++++++++-
+ 1 files changed, 143 insertions(+), 4 deletions(-)
+
+--- a/arch/arm/mach-orion5x/kurobox_pro-setup.c
++++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
+@@ -13,10 +13,12 @@
+ #include <linux/platform_device.h>
+ #include <linux/pci.h>
+ #include <linux/irq.h>
++#include <linux/delay.h>
+ #include <linux/mtd/physmap.h>
+ #include <linux/mtd/nand.h>
+ #include <linux/mv643xx_eth.h>
+ #include <linux/i2c.h>
++#include <linux/serial_reg.h>
+ #include <linux/ata_platform.h>
+ #include <asm/mach-types.h>
+ #include <asm/gpio.h>
+@@ -177,6 +179,140 @@
+ };
+
+ /*****************************************************************************
++ * Kurobox Pro specific power off method via UART1-attached microcontroller
++ ****************************************************************************/
++
++#define UART1_REG(x) (UART1_VIRT_BASE + ((UART_##x) << 2))
++
++static int kurobox_pro_miconread(unsigned char *buf, int count)
++{
++ int i;
++ int timeout;
++
++ for (i = 0; i < count; i++) {
++ timeout = 10;
++
++ while (!(readl(UART1_REG(LSR)) & UART_LSR_DR)) {
++ if (--timeout == 0)
++ break;
++ udelay(1000);
++ }
++
++ if (timeout == 0)
++ break;
++ buf[i] = readl(UART1_REG(RX));
++ }
++
++ /* return read bytes */
++ return i;
++}
++
++static int kurobox_pro_miconwrite(const unsigned char *buf, int count)
++{
++ int i = 0;
++
++ while (count--) {
++ while (!(readl(UART1_REG(LSR)) & UART_LSR_THRE))
++ barrier();
++ writel(buf[i++], UART1_REG(TX));
++ }
++
++ return 0;
++}
++
++static int kurobox_pro_miconsend(const unsigned char *data, int count)
++{
++ int i;
++ unsigned char checksum = 0;
++ unsigned char recv_buf[40];
++ unsigned char send_buf[40];
++ unsigned char correct_ack[3];
++ int retry = 2;
++
++ /* Generate checksum */
++ for (i = 0; i < count; i++)
++ checksum -= data[i];
++
++ do {
++ /* Send data */
++ kurobox_pro_miconwrite(data, count);
++
++ /* send checksum */
++ kurobox_pro_miconwrite(&checksum, 1);
++
++ if (kurobox_pro_miconread(recv_buf, sizeof(recv_buf)) <= 3) {
++ printk(KERN_ERR ">%s: receive failed.\n", __func__);
++
++ /* send preamble to clear the receive buffer */
++ memset(&send_buf, 0xff, sizeof(send_buf));
++ kurobox_pro_miconwrite(send_buf, sizeof(send_buf));
++
++ /* make dummy reads */
++ mdelay(100);
++ kurobox_pro_miconread(recv_buf, sizeof(recv_buf));
++ } else {
++ /* Generate expected ack */
++ correct_ack[0] = 0x01;
++ correct_ack[1] = data[1];
++ correct_ack[2] = 0x00;
++
++ /* checksum Check */
++ if ((recv_buf[0] + recv_buf[1] + recv_buf[2] +
++ recv_buf[3]) & 0xFF) {
++ printk(KERN_ERR ">%s: Checksum Error : "
++ "Received data[%02x, %02x, %02x, %02x]"
++ "\n", __func__, recv_buf[0],
++ recv_buf[1], recv_buf[2], recv_buf[3]);
++ } else {
++ /* Check Received Data */
++ if (correct_ack[0] == recv_buf[0] &&
++ correct_ack[1] == recv_buf[1] &&
++ correct_ack[2] == recv_buf[2]) {
++ /* Interval for next command */
++ mdelay(10);
++
++ /* Receive ACK */
++ return 0;
++ }
++ }
++ /* Received NAK or illegal Data */
++ printk(KERN_ERR ">%s: Error : NAK or Illegal Data "
++ "Received\n", __func__);
++ }
++ } while (retry--);
++
++ /* Interval for next command */
++ mdelay(10);
++
++ return -1;
++}
++
++static void kurobox_pro_power_off(void)
++{
++ const unsigned char watchdogkill[] = {0x01, 0x35, 0x00};
++ const unsigned char shutdownwait[] = {0x00, 0x0c};
++ const unsigned char poweroff[] = {0x00, 0x06};
++ /* 38400 baud divisor */
++ const unsigned divisor = ((ORION5X_TCLK + (8 * 38400)) / (16 * 38400));
++
++ pr_info("%s: triggering power-off...\n", __func__);
++
++ /* hijack uart1 and reset into sane state (38400,8n1,even parity) */
++ writel(0x83, UART1_REG(LCR));
++ writel(divisor & 0xff, UART1_REG(DLL));
++ writel((divisor >> 8) & 0xff, UART1_REG(DLM));
++ writel(0x1b, UART1_REG(LCR));
++ writel(0x00, UART1_REG(IER));
++ writel(0x07, UART1_REG(FCR));
++ writel(0x00, UART1_REG(MCR));
++
++ /* Send the commands to shutdown the Kurobox Pro */
++ kurobox_pro_miconsend(watchdogkill, sizeof(watchdogkill)) ;
++ kurobox_pro_miconsend(shutdownwait, sizeof(shutdownwait)) ;
++ kurobox_pro_miconsend(poweroff, sizeof(poweroff));
++}
++
++/*****************************************************************************
+ * General Setup
+ ****************************************************************************/
+
+@@ -203,10 +339,10 @@
+ orion5x_mpp_conf(13, MPP_SATA_LED); /* SATA 1 presence */
+ orion5x_mpp_conf(14, MPP_SATA_LED); /* SATA 0 active */
+ orion5x_mpp_conf(15, MPP_SATA_LED); /* SATA 1 active */
+- orion5x_mpp_conf(16, MPP_UNUSED);
+- orion5x_mpp_conf(17, MPP_UNUSED);
+- orion5x_mpp_conf(18, MPP_UNUSED);
+- orion5x_mpp_conf(19, MPP_UNUSED);
++ orion5x_mpp_conf(16, MPP_UART); /* UART1 RXD */
++ orion5x_mpp_conf(17, MPP_UART); /* UART1 TXD */
++ orion5x_mpp_conf(18, MPP_UART); /* UART1 CTSn */
++ orion5x_mpp_conf(19, MPP_UART); /* UART1 RTSn */
+
+ /*
+ * Configure peripherals.
+@@ -229,6 +365,9 @@
+ }
+
+ i2c_register_board_info(0, &kurobox_pro_i2c_rtc, 1);
++
++ /* register Kurobox Pro specific power-off method */
++ pm_power_off = kurobox_pro_power_off;
+ }
+
+ #ifdef CONFIG_MACH_KUROBOX_PRO
diff --git a/target/linux/orion/patches/016-add_qnap_ts-409_support.patch b/target/linux/orion/patches/016-add_qnap_ts-409_support.patch
new file mode 100644
index 0000000000..a0d22f75eb
--- /dev/null
+++ b/target/linux/orion/patches/016-add_qnap_ts-409_support.patch
@@ -0,0 +1,418 @@
+From: Sylver Bruneau <sylver.bruneau@googlemail.com>
+
+Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
+---
+ arch/arm/mach-orion5x/Kconfig | 6 +
+ arch/arm/mach-orion5x/Makefile | 1 +
+ arch/arm/mach-orion5x/ts409-setup.c | 383 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 390 insertions(+), 0 deletions(-)
+ create mode 100644 arch/arm/mach-orion5x/ts409-setup.c
+
+--- a/arch/arm/mach-orion5x/Kconfig
++++ b/arch/arm/mach-orion5x/Kconfig
+@@ -44,6 +44,12 @@
+ Buffalo Linkstation Pro/Live platform. Both v1 and
+ v2 devices are supported.
+
++config MACH_TS409
++ bool "QNAP TS-409"
++ help
++ Say 'Y' here if you want your kernel to support the
++ QNAP TS-409 platform.
++
+ endmenu
+
+ endif
+--- a/arch/arm/mach-orion5x/Makefile
++++ b/arch/arm/mach-orion5x/Makefile
+@@ -5,3 +5,4 @@
+ obj-$(CONFIG_MACH_LINKSTATION_PRO) += kurobox_pro-setup.o
+ obj-$(CONFIG_MACH_DNS323) += dns323-setup.o
+ obj-$(CONFIG_MACH_TS209) += ts209-setup.o
++obj-$(CONFIG_MACH_TS409) += ts409-setup.o
+--- /dev/null
++++ b/arch/arm/mach-orion5x/ts409-setup.c
+@@ -0,0 +1,383 @@
++/*
++ * QNAP TS-409 Board Setup
++ *
++ * Maintainer: Sylver Bruneau <sylver.bruneau@gmail.com>
++ *
++ * 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.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/pci.h>
++#include <linux/irq.h>
++#include <linux/mtd/physmap.h>
++#include <linux/mv643xx_eth.h>
++#include <linux/gpio_keys.h>
++#include <linux/input.h>
++#include <linux/i2c.h>
++#include <linux/serial_reg.h>
++#include <asm/mach-types.h>
++#include <asm/gpio.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/pci.h>
++#include <asm/arch/orion5x.h>
++#include "common.h"
++#include "mpp.h"
++
++/*****************************************************************************
++ * QNAP TS-409 Info
++ ****************************************************************************/
++
++/*
++ * QNAP TS-409 hardware :
++ * - Marvell 88F5281-D0
++ * - Marvell 88SX7042 SATA controller (PCIe)
++ * - Marvell 88E1118 Gigabit Ethernet PHY
++ * - RTC S35390A (@0x30) on I2C bus
++ * - 8MB NOR flash
++ * - 256MB of DDR-2 RAM
++ */
++
++/*
++ * 8MB NOR flash Device bus boot chip select
++ */
++
++#define QNAP_TS409_NOR_BOOT_BASE 0xff800000
++#define QNAP_TS409_NOR_BOOT_SIZE SZ_8M
++
++/****************************************************************************
++ * 8MiB NOR flash. The struct mtd_partition is not in the same order as the
++ * partitions on the device because we want to keep compatability with
++ * existing QNAP firmware.
++ *
++ * Layout as used by QNAP:
++ * [2] 0x00000000-0x00200000 : "Kernel"
++ * [3] 0x00200000-0x00600000 : "RootFS1"
++ * [4] 0x00600000-0x00700000 : "RootFS2"
++ * [6] 0x00700000-0x00760000 : "NAS Config" (read-only)
++ * [5] 0x00760000-0x00780000 : "U-Boot Config"
++ * [1] 0x00780000-0x00800000 : "U-Boot" (read-only)
++ ***************************************************************************/
++static struct mtd_partition qnap_ts409_partitions[] = {
++ {
++ .name = "U-Boot",
++ .size = 0x00080000,
++ .offset = 0x00780000,
++ .mask_flags = MTD_WRITEABLE,
++ }, {
++ .name = "Kernel",
++ .size = 0x00200000,
++ .offset = 0,
++ }, {
++ .name = "RootFS1",
++ .size = 0x00400000,
++ .offset = 0x00200000,
++ }, {
++ .name = "RootFS2",
++ .size = 0x00100000,
++ .offset = 0x00600000,
++ }, {
++ .name = "U-Boot Config",
++ .size = 0x00020000,
++ .offset = 0x00760000,
++ }, {
++ .name = "NAS Config",
++ .size = 0x00060000,
++ .offset = 0x00700000,
++ .mask_flags = MTD_WRITEABLE,
++ },
++};
++
++static struct physmap_flash_data qnap_ts409_nor_flash_data = {
++ .width = 1,
++ .parts = qnap_ts409_partitions,
++ .nr_parts = ARRAY_SIZE(qnap_ts409_partitions)
++};
++
++static struct resource qnap_ts409_nor_flash_resource = {
++ .flags = IORESOURCE_MEM,
++ .start = QNAP_TS409_NOR_BOOT_BASE,
++ .end = QNAP_TS409_NOR_BOOT_BASE + QNAP_TS409_NOR_BOOT_SIZE - 1,
++};
++
++static struct platform_device qnap_ts409_nor_flash = {
++ .name = "physmap-flash",
++ .id = 0,
++ .dev = { .platform_data = &qnap_ts409_nor_flash_data, },
++ .num_resources = 1,
++ .resource = &qnap_ts409_nor_flash_resource,
++};
++
++/*****************************************************************************
++ * PCI
++ ****************************************************************************/
++
++static int __init qnap_ts409_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ int irq;
++
++ /*
++ * Check for devices with hard-wired IRQs.
++ */
++ irq = orion5x_pci_map_irq(dev, slot, pin);
++ if (irq != -1)
++ return irq;
++
++ /*
++ * PCI isn't used on the TS-409
++ */
++ printk(KERN_ERR "kurobox_pro_pci_map_irq failed, unknown bus\n");
++ return -1;
++}
++
++static struct hw_pci qnap_ts409_pci __initdata = {
++ .nr_controllers = 2,
++ .swizzle = pci_std_swizzle,
++ .setup = orion5x_pci_sys_setup,
++ .scan = orion5x_pci_sys_scan_bus,
++ .map_irq = qnap_ts409_pci_map_irq,
++};
++
++static int __init qnap_ts409_pci_init(void)
++{
++ if (machine_is_ts409())
++ pci_common_init(&qnap_ts409_pci);
++
++ return 0;
++}
++
++subsys_initcall(qnap_ts409_pci_init);
++
++/*****************************************************************************
++ * Ethernet
++ ****************************************************************************/
++
++static struct mv643xx_eth_platform_data qnap_ts409_eth_data = {
++ .phy_addr = 8,
++};
++
++static int __init parse_hex_nibble(char n)
++{
++ if (n >= '0' && n <= '9')
++ return n - '0';
++
++ if (n >= 'A' && n <= 'F')
++ return n - 'A' + 10;
++
++ if (n >= 'a' && n <= 'f')
++ return n - 'a' + 10;
++
++ return -1;
++}
++
++static int __init parse_hex_byte(const char *b)
++{
++ int hi;
++ int lo;
++
++ hi = parse_hex_nibble(b[0]);
++ lo = parse_hex_nibble(b[1]);
++
++ if (hi < 0 || lo < 0)
++ return -1;
++
++ return (hi << 4) | lo;
++}
++
++static int __init check_mac_addr(const char *addr_str)
++{
++ u_int8_t addr[6];
++ int i;
++
++ for (i = 0; i < 6; i++) {
++ int byte;
++
++ /*
++ * Enforce "xx:xx:xx:xx:xx:xx\n" format.
++ */
++ if (addr_str[(i * 3) + 2] != ((i < 5) ? ':' : '\n'))
++ return -1;
++
++ byte = parse_hex_byte(addr_str + (i * 3));
++ if (byte < 0)
++ return -1;
++ addr[i] = byte;
++ }
++
++ printk(KERN_INFO "ts409: found ethernet mac address ");
++ for (i = 0; i < 6; i++)
++ printk("%.2x%s", addr[i], (i < 5) ? ":" : ".\n");
++
++ memcpy(qnap_ts409_eth_data.mac_addr, addr, 6);
++
++ return 0;
++}
++
++/*
++ * The 'NAS Config' flash partition has an ext2 filesystem which
++ * contains a file that has the ethernet MAC address in plain text
++ * (format "xx:xx:xx:xx:xx:xx\n".)
++ */
++static void __init ts409_find_mac_addr(void)
++{
++ unsigned long addr;
++
++ for (addr = 0x00700000; addr < 0x00760000; addr += 1024) {
++ char *nor_page;
++ int ret = 0;
++
++ nor_page = ioremap(QNAP_TS409_NOR_BOOT_BASE + addr, 1024);
++ if (nor_page != NULL) {
++ ret = check_mac_addr(nor_page);
++ iounmap(nor_page);
++ }
++
++ if (ret == 0)
++ break;
++ }
++}
++
++/*****************************************************************************
++ * RTC S35390A on I2C bus
++ ****************************************************************************/
++
++#define TS409_RTC_GPIO 10
++
++static struct i2c_board_info __initdata qnap_ts409_i2c_rtc = {
++ I2C_BOARD_INFO("s35390a", 0x30),
++ .irq = 0,
++};
++
++/****************************************************************************
++ * GPIO Attached Keys
++ * Power button is attached to the PIC microcontroller
++ ****************************************************************************/
++
++#define QNAP_TS409_GPIO_KEY_MEDIA 15
++
++static struct gpio_keys_button qnap_ts409_buttons[] = {
++ {
++ .code = KEY_RESTART,
++ .gpio = QNAP_TS409_GPIO_KEY_MEDIA,
++ .desc = "USB Copy Button",
++ .active_low = 1,
++ },
++};
++
++static struct gpio_keys_platform_data qnap_ts409_button_data = {
++ .buttons = qnap_ts409_buttons,
++ .nbuttons = ARRAY_SIZE(qnap_ts409_buttons),
++};
++
++static struct platform_device qnap_ts409_button_device = {
++ .name = "gpio-keys",
++ .id = -1,
++ .num_resources = 0,
++ .dev = {
++ .platform_data = &qnap_ts409_button_data,
++ },
++};
++
++/*****************************************************************************
++ * General Setup
++ ****************************************************************************/
++
++/*
++ * QNAP TS-409 specific power off method via UART1-attached PIC
++ */
++
++#define UART1_REG(x) (UART1_VIRT_BASE + ((UART_##x) << 2))
++
++static void qnap_ts409_power_off(void)
++{
++ /* 19200 baud divisor */
++ const unsigned divisor = ((ORION5X_TCLK + (8 * 19200)) / (16 * 19200));
++
++ pr_info("%s: triggering power-off...\n", __func__);
++
++ /* hijack uart1 and reset into sane state (19200,8n1) */
++ writel(0x83, UART1_REG(LCR));
++ writel(divisor & 0xff, UART1_REG(DLL));
++ writel((divisor >> 8) & 0xff, UART1_REG(DLM));
++ writel(0x03, UART1_REG(LCR));
++ writel(0x00, UART1_REG(IER));
++ writel(0x00, UART1_REG(FCR));
++ writel(0x00, UART1_REG(MCR));
++
++ /* send the power-off command 'A' to PIC */
++ writel('A', UART1_REG(TX));
++}
++
++static void __init qnap_ts409_init(void)
++{
++ /*
++ * Setup basic Orion functions. Need to be called early.
++ */
++ orion5x_init();
++
++ orion5x_mpp_conf(0, MPP_UNUSED);
++ orion5x_mpp_conf(1, MPP_UNUSED);
++ orion5x_mpp_conf(2, MPP_UNUSED);
++ orion5x_mpp_conf(3, MPP_UNUSED);
++ orion5x_mpp_conf(4, MPP_GPIO); /* HDD 1 status */
++ orion5x_mpp_conf(5, MPP_GPIO); /* HDD 2 status */
++ orion5x_mpp_conf(6, MPP_GPIO); /* HDD 3 status */
++ orion5x_mpp_conf(7, MPP_GPIO); /* HDD 4 status */
++ orion5x_mpp_conf(8, MPP_UNUSED);
++ orion5x_mpp_conf(9, MPP_UNUSED);
++ orion5x_mpp_conf(10, MPP_GPIO); /* RTC int */
++ orion5x_mpp_conf(11, MPP_UNUSED);
++ orion5x_mpp_conf(12, MPP_UNUSED);
++ orion5x_mpp_conf(13, MPP_UNUSED);
++ orion5x_mpp_conf(14, MPP_GPIO); /* SW_RST */
++ orion5x_mpp_conf(15, MPP_GPIO); /* USB copy button */
++ orion5x_mpp_conf(16, MPP_UART); /* UART1 RXD */
++ orion5x_mpp_conf(17, MPP_UART); /* UART1 TXD */
++ orion5x_mpp_conf(18, MPP_UNUSED);
++ orion5x_mpp_conf(19, MPP_UNUSED);
++
++ /*
++ * Configure peripherals.
++ */
++ orion5x_ehci0_init();
++ ts409_find_mac_addr();
++ orion5x_eth_init(&qnap_ts409_eth_data);
++ orion5x_i2c_init();
++ orion5x_uart0_init();
++
++ orion5x_setup_dev_boot_win(QNAP_TS409_NOR_BOOT_BASE,
++ QNAP_TS409_NOR_BOOT_SIZE);
++ platform_device_register(&qnap_ts409_nor_flash);
++
++ platform_device_register(&qnap_ts409_button_device);
++
++ /* Get RTC IRQ and register the chip */
++ if (gpio_request(TS409_RTC_GPIO, "rtc") == 0) {
++ if (gpio_direction_input(TS409_RTC_GPIO) == 0)
++ qnap_ts409_i2c_rtc.irq = gpio_to_irq(TS409_RTC_GPIO);
++ else
++ gpio_free(TS409_RTC_GPIO);
++ }
++ if (qnap_ts409_i2c_rtc.irq == 0)
++ pr_warning("qnap_ts409_init: failed to get RTC IRQ\n");
++ i2c_register_board_info(0, &qnap_ts409_i2c_rtc, 1);
++
++ /* register ts409 specific power-off method */
++ pm_power_off = qnap_ts409_power_off;
++}
++
++MACHINE_START(TS409, "QNAP TS-409")
++ /* Maintainer: Sylver Bruneau <sylver.bruneau@gmail.com> */
++ .phys_io = ORION5X_REGS_PHYS_BASE,
++ .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
++ .boot_params = 0x00000100,
++ .init_machine = qnap_ts409_init,
++ .map_io = orion5x_map_io,
++ .init_irq = orion5x_init_irq,
++ .timer = &orion5x_timer,
++ .fixup = tag_fixup_mem32,
++MACHINE_END
diff --git a/target/linux/orion/patches/017-add_linksys_wrt350n_v2_support.patch b/target/linux/orion/patches/017-add_linksys_wrt350n_v2_support.patch
new file mode 100644
index 0000000000..5faa9597a0
--- /dev/null
+++ b/target/linux/orion/patches/017-add_linksys_wrt350n_v2_support.patch
@@ -0,0 +1,205 @@
+Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
+Tested-by: Dirk Teurlings <dirk@upexia.nl>
+Tested-by: Peter van Valderen <p.v.valderen@gmail.com>
+---
+ arch/arm/mach-orion5x/Kconfig | 6 +
+ arch/arm/mach-orion5x/Makefile | 1 +
+ arch/arm/mach-orion5x/wrt350n-v2-setup.c | 170 ++++++++++++++++++++++++++++++
+ 3 files changed, 177 insertions(+), 0 deletions(-)
+ create mode 100644 arch/arm/mach-orion5x/wrt350n-v2-setup.c
+
+--- a/arch/arm/mach-orion5x/Kconfig
++++ b/arch/arm/mach-orion5x/Kconfig
+@@ -50,6 +50,12 @@
+ Say 'Y' here if you want your kernel to support the
+ QNAP TS-409 platform.
+
++config MACH_WRT350N_V2
++ bool "Linksys WRT350N v2"
++ help
++ Say 'Y' here if you want your kernel to support the
++ Linksys WRT350N v2 platform.
++
+ endmenu
+
+ endif
+--- a/arch/arm/mach-orion5x/Makefile
++++ b/arch/arm/mach-orion5x/Makefile
+@@ -6,3 +6,4 @@
+ obj-$(CONFIG_MACH_DNS323) += dns323-setup.o
+ obj-$(CONFIG_MACH_TS209) += ts209-setup.o
+ obj-$(CONFIG_MACH_TS409) += ts409-setup.o
++obj-$(CONFIG_MACH_WRT350N_V2) += wrt350n-v2-setup.o
+--- /dev/null
++++ b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
+@@ -0,0 +1,170 @@
++/*
++ * arch/arm/mach-orion5x/wrt350n-v2-setup.c
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/pci.h>
++#include <linux/irq.h>
++#include <linux/delay.h>
++#include <linux/mtd/physmap.h>
++#include <linux/mv643xx_eth.h>
++#include <asm/mach-types.h>
++#include <asm/gpio.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/pci.h>
++#include <asm/arch/orion5x.h>
++#include "common.h"
++#include "mpp.h"
++
++/*
++ * 8M NOR flash Device bus boot chip select
++ */
++#define WRT350N_V2_NOR_BOOT_BASE 0xf4000000
++#define WRT350N_V2_NOR_BOOT_SIZE SZ_8M
++
++static struct mtd_partition wrt350n_v2_nor_flash_partitions[] = {
++ {
++ .name = "kernel",
++ .offset = 0x00000000,
++ .size = 0x00760000,
++ }, {
++ .name = "rootfs",
++ .offset = 0x001a0000,
++ .size = 0x005c0000,
++ }, {
++ .name = "lang",
++ .offset = 0x00760000,
++ .size = 0x00040000,
++ }, {
++ .name = "nvram",
++ .offset = 0x007a0000,
++ .size = 0x00020000,
++ }, {
++ .name = "u-boot",
++ .offset = 0x007c0000,
++ .size = 0x00040000,
++ },
++};
++
++static struct physmap_flash_data wrt350n_v2_nor_flash_data = {
++ .width = 1,
++ .parts = wrt350n_v2_nor_flash_partitions,
++ .nr_parts = ARRAY_SIZE(wrt350n_v2_nor_flash_partitions),
++};
++
++static struct resource wrt350n_v2_nor_flash_resource = {
++ .flags = IORESOURCE_MEM,
++ .start = WRT350N_V2_NOR_BOOT_BASE,
++ .end = WRT350N_V2_NOR_BOOT_BASE + WRT350N_V2_NOR_BOOT_SIZE - 1,
++};
++
++static struct platform_device wrt350n_v2_nor_flash = {
++ .name = "physmap-flash",
++ .id = 0,
++ .dev = {
++ .platform_data = &wrt350n_v2_nor_flash_data,
++ },
++ .num_resources = 1,
++ .resource = &wrt350n_v2_nor_flash_resource,
++};
++
++static struct mv643xx_eth_platform_data wrt350n_v2_eth_data = {
++ .phy_addr = -1,
++};
++
++static void __init wrt350n_v2_init(void)
++{
++ /*
++ * Setup basic Orion functions. Need to be called early.
++ */
++ orion5x_init();
++
++ orion5x_mpp_conf(0, MPP_GPIO); /* Power LED green (0=on) */
++ orion5x_mpp_conf(1, MPP_GPIO); /* Security LED (0=on) */
++ orion5x_mpp_conf(2, MPP_GPIO); /* Internal Button (0=on) */
++ orion5x_mpp_conf(3, MPP_GPIO); /* Reset Button (0=on) */
++ orion5x_mpp_conf(4, MPP_GPIO); /* PCI int */
++ orion5x_mpp_conf(5, MPP_GPIO); /* Power LED orange (0=on) */
++ orion5x_mpp_conf(6, MPP_GPIO); /* USB LED (0=on) */
++ orion5x_mpp_conf(7, MPP_GPIO); /* Wireless LED (0=on) */
++ orion5x_mpp_conf(8, MPP_UNUSED); /* ??? */
++ orion5x_mpp_conf(9, MPP_GIGE); /* GE_RXERR */
++ orion5x_mpp_conf(10, MPP_UNUSED); /* ??? */
++ orion5x_mpp_conf(11, MPP_UNUSED); /* ??? */
++ orion5x_mpp_conf(12, MPP_GIGE); /* GE_TXD[4] */
++ orion5x_mpp_conf(13, MPP_GIGE); /* GE_TXD[5] */
++ orion5x_mpp_conf(14, MPP_GIGE); /* GE_TXD[6] */
++ orion5x_mpp_conf(15, MPP_GIGE); /* GE_TXD[7] */
++ orion5x_mpp_conf(16, MPP_GIGE); /* GE_RXD[4] */
++ orion5x_mpp_conf(17, MPP_GIGE); /* GE_RXD[5] */
++ orion5x_mpp_conf(18, MPP_GIGE); /* GE_RXD[6] */
++ orion5x_mpp_conf(19, MPP_GIGE); /* GE_RXD[7] */
++
++ /*
++ * Configure peripherals.
++ */
++ orion5x_ehci0_init();
++ orion5x_eth_init(&wrt350n_v2_eth_data);
++ orion5x_uart0_init();
++
++ orion5x_setup_dev_boot_win(WRT350N_V2_NOR_BOOT_BASE,
++ WRT350N_V2_NOR_BOOT_SIZE);
++ platform_device_register(&wrt350n_v2_nor_flash);
++}
++
++static int __init wrt350n_v2_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ int irq;
++
++ /*
++ * Check for devices with hard-wired IRQs.
++ */
++ irq = orion5x_pci_map_irq(dev, slot, pin);
++ if (irq != -1)
++ return irq;
++
++ /*
++ * Mini-PCI slot.
++ */
++ if (slot == 7)
++ return gpio_to_irq(4);
++
++ printk(KERN_ERR "wrt350n_v2_pci_map_irq failed, unknown bus\n");
++
++ return -1;
++}
++
++static struct hw_pci wrt350n_v2_pci __initdata = {
++ .nr_controllers = 2,
++ .swizzle = pci_std_swizzle,
++ .setup = orion5x_pci_sys_setup,
++ .scan = orion5x_pci_sys_scan_bus,
++ .map_irq = wrt350n_v2_pci_map_irq,
++};
++
++static int __init wrt350n_v2_pci_init(void)
++{
++ if (machine_is_wrt350n_v2())
++ pci_common_init(&wrt350n_v2_pci);
++
++ return 0;
++}
++subsys_initcall(wrt350n_v2_pci_init);
++
++MACHINE_START(WRT350N_V2, "Linksys WRT350N v2")
++ /* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
++ .phys_io = ORION5X_REGS_PHYS_BASE,
++ .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
++ .boot_params = 0x00000100,
++ .init_machine = wrt350n_v2_init,
++ .map_io = orion5x_map_io,
++ .init_irq = orion5x_init_irq,
++ .timer = &orion5x_timer,
++ .fixup = tag_fixup_mem32,
++MACHINE_END
diff --git a/target/linux/orion/patches/018-add_hp_media_vault_mv2120_support.patch b/target/linux/orion/patches/018-add_hp_media_vault_mv2120_support.patch
new file mode 100644
index 0000000000..02a93c95c5
--- /dev/null
+++ b/target/linux/orion/patches/018-add_hp_media_vault_mv2120_support.patch
@@ -0,0 +1,263 @@
+From: Martin Michlmayr <tbm@cyrius.com>
+
+Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
+---
+ arch/arm/mach-orion5x/Kconfig | 6 +
+ arch/arm/mach-orion5x/Makefile | 1 +
+ arch/arm/mach-orion5x/mv2120-setup.c | 228 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 235 insertions(+), 0 deletions(-)
+ create mode 100644 arch/arm/mach-orion5x/mv2120-setup.c
+
+--- a/arch/arm/mach-orion5x/Kconfig
++++ b/arch/arm/mach-orion5x/Kconfig
+@@ -56,6 +56,12 @@
+ Say 'Y' here if you want your kernel to support the
+ Linksys WRT350N v2 platform.
+
++config MACH_MV2120
++ bool "HP Media Vault mv2120"
++ help
++ Say 'Y' here if you want your kernel to support the
++ HP Media Vault mv2120 or mv5100.
++
+ endmenu
+
+ endif
+--- a/arch/arm/mach-orion5x/Makefile
++++ b/arch/arm/mach-orion5x/Makefile
+@@ -7,3 +7,4 @@
+ obj-$(CONFIG_MACH_TS209) += ts209-setup.o
+ obj-$(CONFIG_MACH_TS409) += ts409-setup.o
+ obj-$(CONFIG_MACH_WRT350N_V2) += wrt350n-v2-setup.o
++obj-$(CONFIG_MACH_MV2120) += mv2120-setup.o
+--- /dev/null
++++ b/arch/arm/mach-orion5x/mv2120-setup.c
+@@ -0,0 +1,228 @@
++/*
++ * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
++ * Copyright (C) 2008 Martin Michlmayr <tbm@cyrius.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/pci.h>
++#include <linux/irq.h>
++#include <linux/mtd/physmap.h>
++#include <linux/mv643xx_eth.h>
++#include <linux/leds.h>
++#include <linux/gpio_keys.h>
++#include <linux/input.h>
++#include <linux/i2c.h>
++#include <linux/ata_platform.h>
++#include <asm/mach-types.h>
++#include <asm/gpio.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/pci.h>
++#include <asm/arch/orion5x.h>
++#include "common.h"
++#include "mpp.h"
++
++#define MV2120_NOR_BOOT_BASE 0xf4000000
++#define MV2120_NOR_BOOT_SIZE SZ_512K
++
++#define MV2120_GPIO_RTC_IRQ 3
++#define MV2120_GPIO_KEY_RESET 17
++#define MV2120_GPIO_KEY_POWER 18
++#define MV2120_GPIO_POWER_OFF 19
++
++
++/****************************************************************************
++ * PCI setup
++ ****************************************************************************/
++static int __init mv2120_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ int irq;
++
++ /*
++ * Check for devices with hard-wired IRQs.
++ */
++ irq = orion5x_pci_map_irq(dev, slot, pin);
++ if (irq != -1)
++ return irq;
++
++ pr_err("%s: requested mapping for unknown bus\n", __func__);
++
++ return -1;
++}
++
++static struct hw_pci mv2120_pci __initdata = {
++ .nr_controllers = 2,
++ .swizzle = pci_std_swizzle,
++ .setup = orion5x_pci_sys_setup,
++ .scan = orion5x_pci_sys_scan_bus,
++ .map_irq = mv2120_pci_map_irq,
++};
++
++static int __init mv2120_pci_init(void)
++{
++ if (machine_is_mv2120())
++ pci_common_init(&mv2120_pci);
++
++ return 0;
++}
++subsys_initcall(mv2120_pci_init);
++
++
++/*****************************************************************************
++ * Ethernet
++ ****************************************************************************/
++static struct mv643xx_eth_platform_data mv2120_eth_data = {
++ .phy_addr = 8,
++};
++
++static struct mv_sata_platform_data mv2120_sata_data = {
++ .n_ports = 2,
++};
++
++static struct mtd_partition mv2120_partitions[] = {
++ {
++ .name = "firmware",
++ .size = 0x00080000,
++ .offset = 0,
++ },
++};
++
++static struct physmap_flash_data mv2120_nor_flash_data = {
++ .width = 1,
++ .parts = mv2120_partitions,
++ .nr_parts = ARRAY_SIZE(mv2120_partitions)
++};
++
++static struct resource mv2120_nor_flash_resource = {
++ .flags = IORESOURCE_MEM,
++ .start = MV2120_NOR_BOOT_BASE,
++ .end = MV2120_NOR_BOOT_BASE + MV2120_NOR_BOOT_SIZE - 1,
++};
++
++static struct platform_device mv2120_nor_flash = {
++ .name = "physmap-flash",
++ .id = 0,
++ .dev = {
++ .platform_data = &mv2120_nor_flash_data,
++ },
++ .resource = &mv2120_nor_flash_resource,
++ .num_resources = 1,
++};
++
++static struct gpio_keys_button mv2120_buttons[] = {
++ {
++ .code = KEY_RESTART,
++ .gpio = MV2120_GPIO_KEY_RESET,
++ .desc = "Reset Button",
++ .active_low = 1,
++ }, {
++ .code = KEY_POWER,
++ .gpio = MV2120_GPIO_KEY_POWER,
++ .desc = "Power Button",
++ .active_low = 1,
++ },
++};
++
++static struct gpio_keys_platform_data mv2120_button_data = {
++ .buttons = mv2120_buttons,
++ .nbuttons = ARRAY_SIZE(mv2120_buttons),
++};
++
++static struct platform_device mv2120_button_device = {
++ .name = "gpio-keys",
++ .id = -1,
++ .num_resources = 0,
++ .dev = {
++ .platform_data = &mv2120_button_data,
++ },
++};
++
++
++/****************************************************************************
++ * General Setup
++ ****************************************************************************/
++static struct i2c_board_info __initdata mv2120_i2c_rtc = {
++ I2C_BOARD_INFO("rtc-pcf8563", 0x51),
++ .irq = 0,
++};
++
++static void mv2120_power_off(void)
++{
++ pr_info("%s: triggering power-off...\n", __func__);
++ gpio_set_value(MV2120_GPIO_POWER_OFF, 0);
++}
++
++static void __init mv2120_init(void)
++{
++ /* Setup basic Orion functions. Need to be called early. */
++ orion5x_init();
++
++ orion5x_mpp_conf(0, MPP_GPIO); /* Sys status LED */
++ orion5x_mpp_conf(1, MPP_GPIO); /* Sys error LED */
++ orion5x_mpp_conf(2, MPP_GPIO); /* OverTemp interrupt */
++ orion5x_mpp_conf(3, MPP_GPIO); /* RTC interrupt */
++ orion5x_mpp_conf(4, MPP_GPIO); /* V_LED 5V */
++ orion5x_mpp_conf(5, MPP_GPIO); /* V_LED 3.3V */
++ orion5x_mpp_conf(6, MPP_UNUSED);
++ orion5x_mpp_conf(7, MPP_UNUSED);
++ orion5x_mpp_conf(8, MPP_GPIO); /* SATA 0 fail LED */
++ orion5x_mpp_conf(9, MPP_GPIO); /* SATA 1 fail LED */
++ orion5x_mpp_conf(10, MPP_UNUSED);
++ orion5x_mpp_conf(11, MPP_UNUSED);
++ orion5x_mpp_conf(12, MPP_SATA_LED); /* SATA 0 presence */
++ orion5x_mpp_conf(13, MPP_SATA_LED); /* SATA 1 presence */
++ orion5x_mpp_conf(14, MPP_SATA_LED); /* SATA 0 active */
++ orion5x_mpp_conf(15, MPP_SATA_LED); /* SATA 1 active */
++ orion5x_mpp_conf(16, MPP_UNUSED);
++ orion5x_mpp_conf(17, MPP_GPIO); /* Reset button */
++ orion5x_mpp_conf(18, MPP_GPIO); /* Power button */
++ orion5x_mpp_conf(19, MPP_GPIO); /* Power off */
++
++ /*
++ * Configure peripherals.
++ */
++ orion5x_ehci0_init();
++ orion5x_ehci1_init();
++ orion5x_eth_init(&mv2120_eth_data);
++ orion5x_i2c_init();
++ orion5x_sata_init(&mv2120_sata_data);
++ orion5x_uart0_init();
++
++ orion5x_setup_dev_boot_win(MV2120_NOR_BOOT_BASE, MV2120_NOR_BOOT_SIZE);
++ platform_device_register(&mv2120_nor_flash);
++
++ platform_device_register(&mv2120_button_device);
++
++ if (gpio_request(MV2120_GPIO_RTC_IRQ, "rtc") == 0) {
++ if (gpio_direction_input(MV2120_GPIO_RTC_IRQ) == 0)
++ mv2120_i2c_rtc.irq = gpio_to_irq(MV2120_GPIO_RTC_IRQ);
++ else
++ gpio_free(MV2120_GPIO_RTC_IRQ);
++ }
++ i2c_register_board_info(0, &mv2120_i2c_rtc, 1);
++
++ /* register mv2120 specific power-off method */
++ if (gpio_request(MV2120_GPIO_POWER_OFF, "POWEROFF") != 0 ||
++ gpio_direction_output(MV2120_GPIO_POWER_OFF, 1) != 0)
++ pr_err("mv2120: failed to setup power-off GPIO\n");
++ pm_power_off = mv2120_power_off;
++}
++
++/* Warning: HP uses a wrong mach-type (=526) in their bootloader */
++MACHINE_START(MV2120, "HP Media Vault mv2120")
++ /* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
++ .phys_io = ORION5X_REGS_PHYS_BASE,
++ .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
++ .boot_params = 0x00000100,
++ .init_machine = mv2120_init,
++ .map_io = orion5x_map_io,
++ .init_irq = orion5x_init_irq,
++ .timer = &orion5x_timer,
++ .fixup = tag_fixup_mem32
++MACHINE_END
diff --git a/target/linux/orion/patches/019-add_technologic_systems_ts-78xx_support.patch b/target/linux/orion/patches/019-add_technologic_systems_ts-78xx_support.patch
new file mode 100644
index 0000000000..a74464c7bb
--- /dev/null
+++ b/target/linux/orion/patches/019-add_technologic_systems_ts-78xx_support.patch
@@ -0,0 +1,305 @@
+Hi,
+
+The following patch series adds support for the Technologic Systems
+TS-7800[1]. This is an updated driver to the one I posted before[2] which
+takes on all the advice and fixes suggested here.
+
+Cheers
+
+Alex
+
+Signed-off-by: Alexander Clouter <alex@digriz.org.uk>
+
+[1] http://www.embeddedarm.com/products/board-detail.php?product=TS-7800
+[2] http://lists.arm.linux.org.uk/lurker/message/20080522.190133.54887e96.en.html
+
+---
+ arch/arm/mach-orion5x/Kconfig | 7 +
+ arch/arm/mach-orion5x/Makefile | 1 +
+ arch/arm/mach-orion5x/ts78xx-setup.c | 257 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 265 insertions(+), 0 deletions(-)
+ create mode 100644 arch/arm/mach-orion5x/ts78xx-setup.c
+
+--- a/arch/arm/mach-orion5x/Kconfig
++++ b/arch/arm/mach-orion5x/Kconfig
+@@ -62,6 +62,13 @@
+ Say 'Y' here if you want your kernel to support the
+ HP Media Vault mv2120 or mv5100.
+
++config MACH_TS78XX
++ bool "Technologic Systems TS-78xx"
++ select CPU_FEROCEON_OLD_ID
++ help
++ Say 'Y' here if you want your kernel to support the
++ Technologic Systems TS-78xx platform.
++
+ endmenu
+
+ endif
+--- a/arch/arm/mach-orion5x/Makefile
++++ b/arch/arm/mach-orion5x/Makefile
+@@ -8,3 +8,4 @@
+ obj-$(CONFIG_MACH_TS409) += ts409-setup.o
+ obj-$(CONFIG_MACH_WRT350N_V2) += wrt350n-v2-setup.o
+ obj-$(CONFIG_MACH_MV2120) += mv2120-setup.o
++obj-$(CONFIG_MACH_TS78XX) += ts78xx-setup.o
+--- /dev/null
++++ b/arch/arm/mach-orion5x/ts78xx-setup.c
+@@ -0,0 +1,257 @@
++/*
++ * arch/arm/mach-orion5x/ts78xx-setup.c
++ *
++ * Maintainer: Alexander Clouter <alex@digriz.org.uk>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/mtd/physmap.h>
++#include <linux/mv643xx_eth.h>
++#include <linux/ata_platform.h>
++#include <linux/m48t86.h>
++#include <asm/mach-types.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/arch/orion5x.h>
++#include "common.h"
++#include "mpp.h"
++
++/*****************************************************************************
++ * TS-78xx Info
++ ****************************************************************************/
++
++/*
++ * FPGA - lives where the PCI bus would be at ORION5X_PCI_MEM_PHYS_BASE
++ */
++#define TS78XX_FPGA_REGS_PHYS_BASE 0xe8000000
++#define TS78XX_FPGA_REGS_VIRT_BASE 0xff900000
++#define TS78XX_FPGA_REGS_SIZE SZ_1M
++
++#define TS78XX_FPGA_REGS_RTC_CTRL TS78XX_FPGA_REGS_VIRT_BASE | 0x808
++#define TS78XX_FPGA_REGS_RTC_DATA TS78XX_FPGA_REGS_VIRT_BASE | 0x80c
++
++/*
++ * 512kB NOR flash Device
++ */
++#define TS78XX_NOR_BOOT_BASE 0xff800000
++#define TS78XX_NOR_BOOT_SIZE SZ_512K
++
++/*****************************************************************************
++ * I/O Address Mapping
++ ****************************************************************************/
++static struct map_desc ts78xx_io_desc[] __initdata = {
++ {
++ .virtual = TS78XX_FPGA_REGS_VIRT_BASE,
++ .pfn = __phys_to_pfn(TS78XX_FPGA_REGS_PHYS_BASE),
++ .length = TS78XX_FPGA_REGS_SIZE,
++ .type = MT_DEVICE,
++ },
++};
++
++void __init ts78xx_map_io(void)
++{
++ orion5x_map_io();
++ iotable_init(ts78xx_io_desc, ARRAY_SIZE(ts78xx_io_desc));
++}
++
++/*****************************************************************************
++ * 512kB NOR Boot Flash - the chip is a M25P40
++ ****************************************************************************/
++static struct mtd_partition ts78xx_nor_boot_flash_resources[] = {
++ {
++ .name = "ts-bootrom",
++ .offset = 0,
++ /* only the first 256kB is used */
++ .size = SZ_256K,
++ .mask_flags = MTD_WRITEABLE,
++ },
++};
++
++static struct physmap_flash_data ts78xx_nor_boot_flash_data = {
++ .width = 1,
++ .parts = ts78xx_nor_boot_flash_resources,
++ .nr_parts = ARRAY_SIZE(ts78xx_nor_boot_flash_resources),
++};
++
++static struct resource ts78xx_nor_boot_flash_resource = {
++ .flags = IORESOURCE_MEM,
++ .start = TS78XX_NOR_BOOT_BASE,
++ .end = TS78XX_NOR_BOOT_BASE + TS78XX_NOR_BOOT_SIZE - 1,
++};
++
++static struct platform_device ts78xx_nor_boot_flash = {
++ .name = "physmap-flash",
++ .id = -1,
++ .dev = {
++ .platform_data = &ts78xx_nor_boot_flash_data,
++ },
++ .num_resources = 1,
++ .resource = &ts78xx_nor_boot_flash_resource,
++};
++
++/*****************************************************************************
++ * PCI
++ ****************************************************************************/
++
++/*
++ * WARNING: TS shunt the PCI IO via the FPGA so that you could build soft-PCI
++ * devices for it and what-not. There is nothing on the PCI or
++ * PCIe buses so probably nothing really to do yet here, if ever
++ */
++
++/*****************************************************************************
++ * Ethernet
++ ****************************************************************************/
++static struct mv643xx_eth_platform_data ts78xx_eth_data = {
++ .phy_addr = 0,
++ .force_phy_addr = 1,
++};
++
++/*****************************************************************************
++ * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c
++ ****************************************************************************/
++static unsigned char ts78xx_rtc_readbyte(unsigned long addr)
++{
++ writeb(addr, TS78XX_FPGA_REGS_RTC_CTRL);
++ return readb(TS78XX_FPGA_REGS_RTC_DATA);
++}
++
++static void ts78xx_rtc_writebyte(unsigned char value, unsigned long addr)
++{
++ writeb(addr, TS78XX_FPGA_REGS_RTC_CTRL);
++ writeb(value, TS78XX_FPGA_REGS_RTC_DATA);
++}
++
++static struct m48t86_ops ts78xx_rtc_ops = {
++ .readbyte = ts78xx_rtc_readbyte,
++ .writebyte = ts78xx_rtc_writebyte,
++};
++
++static struct platform_device ts78xx_rtc_device = {
++ .name = "rtc-m48t86",
++ .id = -1,
++ .dev = {
++ .platform_data = &ts78xx_rtc_ops,
++ },
++ .num_resources = 0,
++};
++
++/*****************************************************************************
++ * SATA
++ ****************************************************************************/
++static struct mv_sata_platform_data ts78xx_sata_data = {
++ .n_ports = 2,
++};
++
++/*****************************************************************************
++ * General Setup
++ ****************************************************************************/
++static void __init ts78xx_init(void)
++{
++#ifdef CONFIG_RTC_DRV_M48T86
++ unsigned char tmp_rtc0, tmp_rtc1;
++#endif
++
++ /*
++ * Setup basic Orion functions. Need to be called early.
++ */
++ orion5x_init();
++
++ orion5x_mpp_conf(0, MPP_UNUSED);
++
++ /*
++ * MPP[1] JTAG Clock
++ * MPP[2] JTAG Data In
++ * MPP[3] Lattice ECP2 256 FPGA - PB2B
++ * MPP[4] JTAG Data Out
++ * MPP[5] JTAG TMS
++ * MPP[6] Lattice ECP2 256 FPGA - PB31A_CLK4+
++ * MPP[7] Lattice ECP2 256 FPGA - PB22B
++ */
++
++ orion5x_mpp_conf(8, MPP_UNUSED);
++ orion5x_mpp_conf(9, MPP_UNUSED);
++ orion5x_mpp_conf(10, MPP_UNUSED);
++ orion5x_mpp_conf(11, MPP_UNUSED);
++ orion5x_mpp_conf(12, MPP_UNUSED);
++ orion5x_mpp_conf(13, MPP_UNUSED);
++ orion5x_mpp_conf(14, MPP_UNUSED);
++ orion5x_mpp_conf(15, MPP_UNUSED);
++ orion5x_mpp_conf(16, MPP_UART);
++ orion5x_mpp_conf(17, MPP_UART);
++ orion5x_mpp_conf(18, MPP_UART);
++ orion5x_mpp_conf(19, MPP_UART);
++
++ /*
++ * MPP[20] PCI Clock Out 1
++ * MPP[21] PCI Clock Out 0
++ * MPP[22] Unused
++ * MPP[23] Unused
++ * MPP[24] Unused
++ * MPP[25] Unused
++ */
++
++ /*
++ * Configure peripherals.
++ */
++ orion5x_ehci0_init();
++ orion5x_ehci1_init();
++ orion5x_eth_init(&ts78xx_eth_data);
++ orion5x_sata_init(&ts78xx_sata_data);
++ orion5x_uart0_init();
++ orion5x_uart1_init();
++
++ orion5x_setup_dev_boot_win(TS78XX_NOR_BOOT_BASE,
++ TS78XX_NOR_BOOT_SIZE);
++ platform_device_register(&ts78xx_nor_boot_flash);
++
++#ifdef CONFIG_RTC_DRV_M48T86
++ /*
++ * TS uses some of the user storage space on the RTC chip so see if it
++ * is present; as it's an optional feature at purchase time and not all
++ * boards will have it present
++ *
++ * I've used the method TS use in their rtc7800.c example for the
++ * detection logic; a little 'funky' but thats what floats my boat
++ *
++ * TODO: track down a guinea pig without an RTC to see if we can work
++ * out a better RTC detection routine
++ */
++ tmp_rtc0 = ts78xx_rtc_readbyte(126);
++ tmp_rtc1 = ts78xx_rtc_readbyte(127);
++
++ ts78xx_rtc_writebyte(0x00, 126);
++ ts78xx_rtc_writebyte(0x55, 127);
++ if (ts78xx_rtc_readbyte(127) == 0x55) {
++ ts78xx_rtc_writebyte(0xaa, 127);
++ if (ts78xx_rtc_readbyte(127) == 0xaa
++ && ts78xx_rtc_readbyte(126) == 0x00) {
++ ts78xx_rtc_writebyte(tmp_rtc0, 126);
++ ts78xx_rtc_writebyte(tmp_rtc1, 127);
++ platform_device_register(&ts78xx_rtc_device);
++ goto rtcok;
++ }
++ }
++ printk(KERN_INFO "TS-78xx RTC not detected\n");
++
++ rtcok:
++ ;
++#endif
++}
++
++MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC")
++ /* Maintainer: Alexander Clouter <alex@digriz.org.uk> */
++ .phys_io = ORION5X_REGS_PHYS_BASE,
++ .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
++ .boot_params = 0x00000100,
++ .init_machine = ts78xx_init,
++ .map_io = ts78xx_map_io,
++ .init_irq = orion5x_init_irq,
++ .timer = &orion5x_timer,
++MACHINE_END