ARM: uniphier: prepare directory structure for ARMv8 SoC support

Before adding ARMv8 support, this commit refactors the directory
structure.  Move ARMv7 specific files to arch/arm/mach-uniphier/arm32
to avoid a mess by mixture of ARMv7 and ARMv8 code.  Also move the
"select CPU_V7" to the lower-level menu because we will have to
select ARM64 instead of CPU_V7 for ARMv8 SoCs.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
diff --git a/arch/arm/mach-uniphier/arm32/Makefile b/arch/arm/mach-uniphier/arm32/Makefile
new file mode 100644
index 0000000..376c06b
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm32/Makefile
@@ -0,0 +1,13 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+ifdef CONFIG_SPL_BUILD
+obj-y += lowlevel_init.o
+obj-$(CONFIG_DEBUG_LL) += debug_ll.o
+else
+obj-y += late_lowlevel_init.o
+obj-y += cache_uniphier.o
+endif
+
+obj-y += timer.o
diff --git a/arch/arm/mach-uniphier/arm32/arm-mpcore.h b/arch/arm/mach-uniphier/arm32/arm-mpcore.h
new file mode 100644
index 0000000..cf7cd46
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm32/arm-mpcore.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011-2014 Panasonic Corporation
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef ARCH_ARM_MPCORE_H
+#define ARCH_ARM_MPCORE_H
+
+/* Snoop Control Unit */
+#define SCU_OFFSET		0x00
+
+/* SCU Control Register */
+#define SCU_CTRL		0x00
+/* SCU Configuration Register */
+#define SCU_CONF		0x04
+/* SCU CPU Power Status Register */
+#define SCU_PWR_STATUS		0x08
+/* SCU Invalidate All Registers in Secure State */
+#define SCU_INV_ALL		0x0C
+/* SCU Filtering Start Address Register */
+#define SCU_FILTER_START	0x40
+/* SCU Filtering End Address Register */
+#define SCU_FILTER_END		0x44
+/* SCU Access Control Register */
+#define SCU_SAC			0x50
+/* SCU Non-secure Access Control Register */
+#define SCU_SNSAC		0x54
+
+/* Global Timer */
+#define GLOBAL_TIMER_OFFSET	0x200
+
+/* Global Timer Counter Registers */
+#define GTIMER_CNT_L		0x00
+#define GTIMER_CNT_H		0x04
+/* Global Timer Control Register */
+#define GTIMER_CTRL		0x08
+/* Global Timer Interrupt Status Register */
+#define GTIMER_STAT		0x0C
+/* Comparator Value Registers */
+#define GTIMER_CMP_L		0x10
+#define GTIMER_CMP_H		0x14
+/* Auto-increment Register */
+#define GTIMER_INC		0x18
+
+#endif /* ARCH_ARM_MPCORE_H */
diff --git a/arch/arm/mach-uniphier/arm32/cache_uniphier.c b/arch/arm/mach-uniphier/arm32/cache_uniphier.c
new file mode 100644
index 0000000..4398114
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm32/cache_uniphier.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/io.h>
+#include <asm/armv7.h>
+
+#include "ssc-regs.h"
+
+#ifdef CONFIG_UNIPHIER_L2CACHE_ON
+static void uniphier_cache_sync(void)
+{
+	writel(SSCOPE_CM_SYNC, SSCOPE); /* drain internal buffers */
+	readl(SSCOPE); /* need a read back to confirm */
+}
+
+static void uniphier_cache_maint_all(u32 operation)
+{
+	/* try until the command is successfully set */
+	do {
+		writel(SSCOQM_S_ALL | SSCOQM_CE | operation, SSCOQM);
+	} while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE));
+
+	/* wait until the operation is completed */
+	while (readl(SSCOLPQS) != SSCOLPQS_EF)
+		;
+
+	/* clear the complete notification flag */
+	writel(SSCOLPQS_EF, SSCOLPQS);
+
+	uniphier_cache_sync();
+}
+
+void v7_outer_cache_flush_all(void)
+{
+	uniphier_cache_maint_all(SSCOQM_CM_WB_INV);
+}
+
+void v7_outer_cache_inval_all(void)
+{
+	uniphier_cache_maint_all(SSCOQM_CM_INV);
+}
+
+static void __uniphier_cache_maint_range(u32 start, u32 size, u32 operation)
+{
+	/* try until the command is successfully set */
+	do {
+		writel(SSCOQM_S_ADDRESS | SSCOQM_CE | operation, SSCOQM);
+		writel(start, SSCOQAD);
+		writel(size, SSCOQSZ);
+
+	} while (readl(SSCOPPQSEF) & (SSCOPPQSEF_FE | SSCOPPQSEF_OE));
+
+	/* wait until the operation is completed */
+	while (readl(SSCOLPQS) != SSCOLPQS_EF)
+		;
+
+	/* clear the complete notification flag */
+	writel(SSCOLPQS_EF, SSCOLPQS);
+}
+
+static void uniphier_cache_maint_range(u32 start, u32 end, u32 operation)
+{
+	u32 size;
+
+	/*
+	 * If start address is not aligned to cache-line,
+	 * do cache operation for the first cache-line
+	 */
+	start = start & ~(SSC_LINE_SIZE - 1);
+
+	size = end - start;
+
+	if (unlikely(size >= (u32)(-SSC_LINE_SIZE))) {
+		/* this means cache operation for all range */
+		uniphier_cache_maint_all(operation);
+		return;
+	}
+
+	/*
+	 * If end address is not aligned to cache-line,
+	 * do cache operation for the last cache-line
+	 */
+	size = ALIGN(size, SSC_LINE_SIZE);
+
+	while (size) {
+		u32 chunk_size = size > SSC_RANGE_OP_MAX_SIZE ?
+						SSC_RANGE_OP_MAX_SIZE : size;
+		__uniphier_cache_maint_range(start, chunk_size, operation);
+
+		start += chunk_size;
+		size -= chunk_size;
+	}
+
+	uniphier_cache_sync();
+}
+
+void v7_outer_cache_flush_range(u32 start, u32 end)
+{
+	uniphier_cache_maint_range(start, end, SSCOQM_CM_WB_INV);
+}
+
+void v7_outer_cache_inval_range(u32 start, u32 end)
+{
+	if (start & (SSC_LINE_SIZE - 1)) {
+		start &= ~(SSC_LINE_SIZE - 1);
+		__uniphier_cache_maint_range(start, SSC_LINE_SIZE,
+					     SSCOQM_CM_WB_INV);
+		start += SSC_LINE_SIZE;
+	}
+
+	if (start >= end) {
+		uniphier_cache_sync();
+		return;
+	}
+
+	if (end & (SSC_LINE_SIZE - 1)) {
+		end &= ~(SSC_LINE_SIZE - 1);
+		__uniphier_cache_maint_range(end, SSC_LINE_SIZE,
+					     SSCOQM_CM_WB_INV);
+	}
+
+	if (start >= end) {
+		uniphier_cache_sync();
+		return;
+	}
+
+	uniphier_cache_maint_range(start, end, SSCOQM_CM_INV);
+}
+
+void v7_outer_cache_enable(void)
+{
+	u32 tmp;
+
+	writel(U32_MAX, SSCLPDAWCR);	/* activate all ways */
+	tmp = readl(SSCC);
+	tmp |= SSCC_ON;
+	writel(tmp, SSCC);
+}
+#endif
+
+void v7_outer_cache_disable(void)
+{
+	u32 tmp;
+	tmp = readl(SSCC);
+	tmp &= ~SSCC_ON;
+	writel(tmp, SSCC);
+}
+
+void enable_caches(void)
+{
+	dcache_enable();
+}
diff --git a/arch/arm/mach-uniphier/arm32/debug_ll.S b/arch/arm/mach-uniphier/arm32/debug_ll.S
new file mode 100644
index 0000000..a70954c
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm32/debug_ll.S
@@ -0,0 +1,186 @@
+/*
+ * On-chip UART initializaion for low-level debugging
+ *
+ * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <linux/serial_reg.h>
+#include <linux/linkage.h>
+
+#include "../bcu/bcu-regs.h"
+#include "../sc-regs.h"
+#include "../sg-regs.h"
+
+#if !defined(CONFIG_DEBUG_SEMIHOSTING)
+#include CONFIG_DEBUG_LL_INCLUDE
+#endif
+
+#define BAUDRATE		115200
+#define DIV_ROUND(x, d)		(((x) + ((d) / 2)) / (d))
+
+ENTRY(debug_ll_init)
+	ldr		r0, =SG_REVISION
+	ldr		r1, [r0]
+	and		r1, r1, #SG_REVISION_TYPE_MASK
+	mov		r1, r1, lsr #SG_REVISION_TYPE_SHIFT
+
+#if defined(CONFIG_ARCH_UNIPHIER_PH1_SLD3)
+#define PH1_SLD3_UART_CLK		36864000
+	cmp		r1, #0x25
+	bne		ph1_sld3_end
+
+	sg_set_pinsel	64, 1, 4, 4, r0, r1	@ TXD0 -> TXD0
+
+	ldr		r0, =BCSCR5
+	ldr		r1, =0x24440000
+	str		r1, [r0]
+
+	ldr		r0, =SC_CLKCTRL
+	ldr		r1, [r0]
+	orr		r1, r1, #SC_CLKCTRL_CEN_PERI
+	str		r1, [r0]
+
+	ldr		r3, =DIV_ROUND(PH1_SLD3_UART_CLK, 16 * BAUDRATE)
+
+	b		init_uart
+ph1_sld3_end:
+#endif
+#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD4)
+#define PH1_LD4_UART_CLK		36864000
+	cmp		r1, #0x26
+	bne		ph1_ld4_end
+
+	ldr		r0, =SG_IECTRL
+	ldr		r1, [r0]
+	orr		r1, r1, #1
+	str		r1, [r0]
+
+	sg_set_pinsel	88, 1, 8, 4, r0, r1	@ HSDOUT6 -> TXD0
+
+	ldr		r3, =DIV_ROUND(PH1_LD4_UART_CLK, 16 * BAUDRATE)
+
+	b		init_uart
+ph1_ld4_end:
+#endif
+#if defined(CONFIG_ARCH_UNIPHIER_PH1_PRO4)
+#define PH1_PRO4_UART_CLK		73728000
+	cmp		r1, #0x28
+	bne		ph1_pro4_end
+
+	sg_set_pinsel	128, 0, 4, 8, r0, r1	@ TXD0 -> TXD0
+
+	ldr		r0, =SG_LOADPINCTRL
+	mov		r1, #1
+	str		r1, [r0]
+
+	ldr		r0, =SC_CLKCTRL
+	ldr		r1, [r0]
+	orr		r1, r1, #SC_CLKCTRL_CEN_PERI
+	str		r1, [r0]
+
+	ldr		r3, =DIV_ROUND(PH1_PRO4_UART_CLK, 16 * BAUDRATE)
+
+	b		init_uart
+ph1_pro4_end:
+#endif
+#if defined(CONFIG_ARCH_UNIPHIER_PH1_SLD8)
+#define PH1_SLD8_UART_CLK		80000000
+	cmp		r1, #0x29
+	bne		ph1_sld8_end
+
+	ldr		r0, =SG_IECTRL
+	ldr		r1, [r0]
+	orr		r1, r1, #1
+	str		r1, [r0]
+
+	sg_set_pinsel	70, 3, 8, 4, r0, r1	@ HSDOUT0 -> TXD0
+
+	ldr		r3, =DIV_ROUND(PH1_SLD8_UART_CLK, 16 * BAUDRATE)
+
+	b		init_uart
+ph1_sld8_end:
+#endif
+#if defined(CONFIG_ARCH_UNIPHIER_PH1_PRO5)
+#define PH1_PRO5_UART_CLK		73728000
+	cmp		r1, #0x2A
+	bne		ph1_pro5_end
+
+	sg_set_pinsel	47, 0, 4, 8, r0, r1	@ TXD0 -> TXD0
+	sg_set_pinsel	49, 0, 4, 8, r0, r1	@ TXD1 -> TXD1
+	sg_set_pinsel	51, 0, 4, 8, r0, r1	@ TXD2 -> TXD2
+	sg_set_pinsel	53, 0, 4, 8, r0, r1	@ TXD3 -> TXD3
+
+	ldr		r0, =SG_LOADPINCTRL
+	mov		r1, #1
+	str		r1, [r0]
+
+	ldr		r0, =SC_CLKCTRL
+	ldr		r1, [r0]
+	orr		r1, r1, #SC_CLKCTRL_CEN_PERI
+	str		r1, [r0]
+
+	ldr		r3, =DIV_ROUND(PH1_PRO5_UART_CLK, 16 * BAUDRATE)
+
+	b		init_uart
+ph1_pro5_end:
+#endif
+#if defined(CONFIG_ARCH_UNIPHIER_PROXSTREAM2)
+#define PROXSTREAM2_UART_CLK		88900000
+	cmp		r1, #0x2E
+	bne		proxstream2_end
+
+	ldr		r0, =SG_IECTRL
+	ldr		r1, [r0]
+	orr		r1, r1, #1
+	str		r1, [r0]
+
+	sg_set_pinsel	217, 8, 8, 4, r0, r1	@ TXD0 -> TXD0
+	sg_set_pinsel	115, 8, 8, 4, r0, r1	@ TXD1 -> TXD1
+	sg_set_pinsel	113, 8, 8, 4, r0, r1	@ TXD2 -> TXD2
+	sg_set_pinsel	219, 8, 8, 4, r0, r1	@ TXD3 -> TXD3
+
+	ldr		r0, =SC_CLKCTRL
+	ldr		r1, [r0]
+	orr		r1, r1, #SC_CLKCTRL_CEN_PERI
+	str		r1, [r0]
+
+	ldr		r3, =DIV_ROUND(PROXSTREAM2_UART_CLK, 16 * BAUDRATE)
+
+	b		init_uart
+proxstream2_end:
+#endif
+#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD6B)
+#define PH1_LD6B_UART_CLK		88900000
+	cmp		r1, #0x2F
+	bne		ph1_ld6b_end
+
+	ldr		r0, =SG_IECTRL
+	ldr		r1, [r0]
+	orr		r1, r1, #1
+	str		r1, [r0]
+
+	sg_set_pinsel	135, 3, 8, 4, r0, r1	@ PORT10 -> TXD0
+	sg_set_pinsel	115, 0, 8, 4, r0, r1	@ TXD1 -> TXD1
+	sg_set_pinsel	113, 2, 8, 4, r0, r1	@ SBO0 -> TXD2
+
+	ldr		r0, =SC_CLKCTRL
+	ldr		r1, [r0]
+	orr		r1, r1, #SC_CLKCTRL_CEN_PERI
+	str		r1, [r0]
+
+	ldr		r3, =DIV_ROUND(PH1_LD6B_UART_CLK, 16 * BAUDRATE)
+
+	b		init_uart
+ph1_ld6b_end:
+#endif
+
+init_uart:
+	addruart	r0, r1, r2
+	mov		r1, #UART_LCR_WLEN8 << 8
+	str		r1, [r0, #0x10]
+	str		r3, [r0, #0x24]
+
+	mov		pc, lr
+ENDPROC(debug_ll_init)
diff --git a/arch/arm/mach-uniphier/arm32/late_lowlevel_init.S b/arch/arm/mach-uniphier/arm32/late_lowlevel_init.S
new file mode 100644
index 0000000..cce91df
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm32/late_lowlevel_init.S
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2015 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <linux/linkage.h>
+
+#include "ssc-regs.h"
+
+ENTRY(lowlevel_init)
+	ldr	r1, = SSCC
+	ldr	r0, [r1]
+	bic	r0, r0, #SSCC_ON	@ L2 disable
+	str	r0, [r1]
+	mov	pc, lr
+ENDPROC(lowlevel_init)
diff --git a/arch/arm/mach-uniphier/arm32/lowlevel_init.S b/arch/arm/mach-uniphier/arm32/lowlevel_init.S
new file mode 100644
index 0000000..dd03ad8
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm32/lowlevel_init.S
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+#include <linux/sizes.h>
+#include <asm/system.h>
+
+#include "ssc-regs.h"
+
+ENTRY(lowlevel_init)
+	mov	r8, lr			@ persevere link reg across call
+
+	/*
+	 * The UniPhier Boot ROM loads SPL code to the L2 cache.
+	 * But CPUs can only do instruction fetch now because start.S has
+	 * cleared C and M bits.
+	 * First we need to turn on MMU and Dcache again to get back
+	 * data access to L2.
+	 */
+	mrc	p15, 0, r0, c1, c0, 0	@ SCTLR (System Control Register)
+	orr	r0, r0, #(CR_C | CR_M)	@ enable MMU and Dcache
+	mcr	p15, 0, r0, c1, c0, 0
+
+#ifdef CONFIG_DEBUG_LL
+	bl	debug_ll_init
+#endif
+
+	bl	setup_init_ram		@ RAM area for stack and page talbe
+
+	/*
+	 * Now we are using the page table embedded in the Boot ROM.
+	 * It is not handy since it is not a straight mapped table for sLD3.
+	 * Also, the access to the external bus is prohibited.  What we need
+	 * to do next is to create a page table and switch over to it.
+	 */
+	bl	create_page_table
+	bl	v7_flush_dcache_all
+
+	/* Disable MMU and Dcache before switching Page Table */
+	mrc	p15, 0, r0, c1, c0, 0	@ SCTLR (System Control Register)
+	bic	r0, r0, #(CR_C | CR_M)	@ disable MMU and Dcache
+	mcr	p15, 0, r0, c1, c0, 0
+
+	bl	enable_mmu
+
+	mov	lr, r8			@ restore link
+	mov	pc, lr			@ back to my caller
+ENDPROC(lowlevel_init)
+
+ENTRY(enable_mmu)
+	mrc	p15, 0, r0, c2, c0, 2	@ TTBCR (Translation Table Base Control Register)
+	bic	r0, r0, #0x37
+	orr	r0, r0, #0x20		@ disable TTBR1
+	mcr	p15, 0, r0, c2, c0, 2
+
+	orr	r0, r12, #0x8		@ Outer Cacheability for table walks: WBWA
+	mcr	p15, 0, r0, c2, c0, 0   @ TTBR0
+
+	mov	r0, #0
+	mcr	p15, 0, r0, c8, c7, 0	@ invalidate TLBs
+
+	mov	r0, #-1			@ manager for all domains (No permission check)
+	mcr	p15, 0, r0, c3, c0, 0   @ DACR (Domain Access Control Register)
+
+	dsb
+	isb
+	/*
+	 * MMU on:
+	 * TLBs was already invalidated in "../start.S"
+	 * So, we don't need to invalidate it here.
+	 */
+	mrc	p15, 0, r0, c1, c0, 0	@ SCTLR (System Control Register)
+	orr	r0, r0, #(CR_C | CR_M)	@ MMU and Dcache enable
+	mcr	p15, 0, r0, c1, c0, 0
+
+	mov	pc, lr
+ENDPROC(enable_mmu)
+
+/*
+ * For PH1-Pro4 or older SoCs, the size of WAY is 32KB.
+ * It is large enough for tmp RAM.
+ */
+#define BOOT_RAM_SIZE	(SZ_32K)
+#define BOOT_RAM_BASE	((CONFIG_SPL_STACK) - (BOOT_RAM_SIZE))
+#define BOOT_WAY_BITS	(0x00000100)   /* way 8 */
+
+ENTRY(setup_init_ram)
+	/*
+	 * Touch to zero for the boot way
+	 */
+0:
+	/*
+	 * set SSCOQM, SSCOQAD, SSCOQSZ, SSCOQWN in this order
+	 */
+	ldr	r0, = 0x00408006	@ touch to zero with address range
+	ldr	r1, = SSCOQM
+	str	r0, [r1]
+	ldr	r0, = BOOT_RAM_BASE
+	ldr	r1, = SSCOQAD
+	str	r0, [r1]
+	ldr	r0, = BOOT_RAM_SIZE
+	ldr	r1, = SSCOQSZ
+	str	r0, [r1]
+	ldr	r0, = BOOT_WAY_BITS
+	ldr	r1, = SSCOQWN
+	str	r0, [r1]
+	ldr	r1, = SSCOPPQSEF
+	ldr	r0, [r1]
+	cmp	r0, #0			@ check if the command is successfully set
+	bne	0b			@ try again if an error occurs
+
+	ldr	r1, = SSCOLPQS
+1:
+	ldr	r0, [r1]
+	cmp	r0, #0x4
+	bne	1b			@ wait until the operation is completed
+	str	r0, [r1]		@ clear the complete notification flag
+
+	mov	pc, lr
+ENDPROC(setup_init_ram)
+
+#define DEVICE	0x00002002 /* Non-shareable Device */
+#define NORMAL	0x0000000e /* Normal Memory Write-Back, No Write-Allocate */
+
+ENTRY(create_page_table)
+	ldr	r0, = DEVICE
+	ldr	r1, = BOOT_RAM_BASE
+	mov	r12, r1			@ r12 is preserved during D-cache flush
+0:	str	r0, [r1], #4		@ specify all the sections as Device
+	adds	r0, r0, #0x00100000
+	bcc	0b
+
+	ldr	r0, = NORMAL
+	str	r0, [r12]		@ mark the first section as Normal
+	add	r0, r0, #0x00100000
+	str	r0, [r12, #4]		@ mark the second section as Normal
+	mov	pc, lr
+ENDPROC(create_page_table)
+
+/* We don't use Thumb instructions for now */
+#define ARM(x...)	x
+#define THUMB(x...)
+
+/*
+ *	v7_flush_dcache_all()
+ *
+ *	Flush the whole D-cache.
+ *
+ *	Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
+ *
+ *	- mm    - mm_struct describing address space
+ *
+ *	Note: copied from arch/arm/mm/cache-v7.S of Linux 4.4
+ */
+ENTRY(v7_flush_dcache_all)
+	dmb					@ ensure ordering with previous memory accesses
+	mrc	p15, 1, r0, c0, c0, 1		@ read clidr
+	mov	r3, r0, lsr #23			@ move LoC into position
+	ands	r3, r3, #7 << 1			@ extract LoC*2 from clidr
+	beq	finished			@ if loc is 0, then no need to clean
+start_flush_levels:
+	mov	r10, #0				@ start clean at cache level 0
+flush_levels:
+	add	r2, r10, r10, lsr #1		@ work out 3x current cache level
+	mov	r1, r0, lsr r2			@ extract cache type bits from clidr
+	and	r1, r1, #7			@ mask of the bits for current cache only
+	cmp	r1, #2				@ see what cache we have at this level
+	blt	skip				@ skip if no cache, or just i-cache
+	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
+	isb					@ isb to sych the new cssr&csidr
+	mrc	p15, 1, r1, c0, c0, 0		@ read the new csidr
+	and	r2, r1, #7			@ extract the length of the cache lines
+	add	r2, r2, #4			@ add 4 (line length offset)
+	movw	r4, #0x3ff
+	ands	r4, r4, r1, lsr #3		@ find maximum number on the way size
+	clz	r5, r4				@ find bit position of way size increment
+	movw	r7, #0x7fff
+	ands	r7, r7, r1, lsr #13		@ extract max number of the index size
+loop1:
+	mov	r9, r7				@ create working copy of max index
+loop2:
+ ARM(	orr	r11, r10, r4, lsl r5	)	@ factor way and cache number into r11
+ THUMB(	lsl	r6, r4, r5		)
+ THUMB(	orr	r11, r10, r6		)	@ factor way and cache number into r11
+ ARM(	orr	r11, r11, r9, lsl r2	)	@ factor index number into r11
+ THUMB(	lsl	r6, r9, r2		)
+ THUMB(	orr	r11, r11, r6		)	@ factor index number into r11
+	mcr	p15, 0, r11, c7, c14, 2		@ clean & invalidate by set/way
+	subs	r9, r9, #1			@ decrement the index
+	bge	loop2
+	subs	r4, r4, #1			@ decrement the way
+	bge	loop1
+skip:
+	add	r10, r10, #2			@ increment cache number
+	cmp	r3, r10
+	bgt	flush_levels
+finished:
+	mov	r10, #0				@ swith back to cache level 0
+	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
+	dsb	st
+	isb
+	mov	pc, lr
+ENDPROC(v7_flush_dcache_all)
diff --git a/arch/arm/mach-uniphier/arm32/ssc-regs.h b/arch/arm/mach-uniphier/arm32/ssc-regs.h
new file mode 100644
index 0000000..02fca3b
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm32/ssc-regs.h
@@ -0,0 +1,65 @@
+/*
+ * UniPhier System Cache (L2 Cache) registers
+ *
+ * Copyright (C) 2011-2014 Panasonic Corporation
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef ARCH_SSC_REGS_H
+#define ARCH_SSC_REGS_H
+
+#define SSCC			0x500c0000
+#define SSCC_BST		(0x1 << 20)
+#define SSCC_ACT		(0x1 << 19)
+#define SSCC_WTG		(0x1 << 18)
+#define SSCC_PRD		(0x1 << 17)
+#define SSCC_WBWA		(0x1 << 16)
+#define SSCC_EX			(0x1 << 13)
+#define SSCC_ON			(0x1 <<  0)
+
+#define SSCLPDAWCR		0x500c0030
+
+#define SSCOPE			0x506c0244
+#define SSCOPE_CM_SYNC		0x00000008
+
+#define SSCOQM			0x506c0248
+#define SSCOQM_TID_MASK		(0x3 << 21)
+#define SSCOQM_TID_BY_WAY	(0x2 << 21)
+#define SSCOQM_TID_BY_INST_WAY	(0x1 << 21)
+#define SSCOQM_TID_BY_DATA_WAY	(0x0 << 21)
+#define SSCOQM_S_MASK		(0x3 << 17)
+#define SSCOQM_S_WAY		(0x2 << 17)
+#define SSCOQM_S_ALL		(0x1 << 17)
+#define SSCOQM_S_ADDRESS	(0x0 << 17)
+#define SSCOQM_CE		(0x1 << 15)
+#define SSCOQM_CW		(0x1 << 14)
+#define SSCOQM_CM_MASK		(0x7)
+#define SSCOQM_CM_DIRT_TOUCH	(0x7)
+#define SSCOQM_CM_ZERO_TOUCH	(0x6)
+#define SSCOQM_CM_NORM_TOUCH	(0x5)
+#define SSCOQM_CM_PREF_FETCH	(0x4)
+#define SSCOQM_CM_SSC_FETCH	(0x3)
+#define SSCOQM_CM_WB_INV	(0x2)
+#define SSCOQM_CM_WB		(0x1)
+#define SSCOQM_CM_INV		(0x0)
+
+#define SSCOQAD			0x506c024c
+#define SSCOQSZ			0x506c0250
+#define SSCOQWN			0x506c0258
+
+#define SSCOPPQSEF		0x506c025c
+#define SSCOPPQSEF_FE		(0x1 << 1)
+#define SSCOPPQSEF_OE		(0x1 << 0)
+
+#define SSCOLPQS		0x506c0260
+#define SSCOLPQS_EF		(0x1 << 2)
+#define SSCOLPQS_EST		(0x1 << 1)
+#define SSCOLPQS_QST		(0x1 << 0)
+
+#define SSCOQCE0		0x506c0270
+
+#define SSC_LINE_SIZE		128
+#define SSC_RANGE_OP_MAX_SIZE	(0x00400000 - (SSC_LINE_SIZE))
+
+#endif  /* ARCH_SSC_REGS_H */
diff --git a/arch/arm/mach-uniphier/arm32/timer.c b/arch/arm/mach-uniphier/arm32/timer.c
new file mode 100644
index 0000000..a34e30b
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm32/timer.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/io.h>
+
+#include "arm-mpcore.h"
+
+#define PERIPHCLK (50 * 1000 * 1000) /* 50 MHz */
+#define PRESCALER ((PERIPHCLK) / (CONFIG_SYS_TIMER_RATE) - 1)
+
+static void *get_global_timer_base(void)
+{
+	void *val;
+
+	asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (val) : : "memory");
+
+	return val + GLOBAL_TIMER_OFFSET;
+}
+
+unsigned long timer_read_counter(void)
+{
+	/*
+	 * ARM 64bit Global Timer is too much for our purpose.
+	 * We use only lower 32 bit of the timer counter.
+	 */
+	return readl(get_global_timer_base() + GTIMER_CNT_L);
+}
+
+int timer_init(void)
+{
+	/* enable timer */
+	writel(PRESCALER << 8 | 1, get_global_timer_base() + GTIMER_CTRL);
+
+	return 0;
+}