From fe5ea57bdbdeb8429793faaca2d6bd5f38218fe3 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 26 Feb 2016 18:59:44 +0900 Subject: 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 --- arch/arm/mach-uniphier/arm32/Makefile | 13 ++ arch/arm/mach-uniphier/arm32/arm-mpcore.h | 46 +++++ arch/arm/mach-uniphier/arm32/cache_uniphier.c | 156 ++++++++++++++++ arch/arm/mach-uniphier/arm32/debug_ll.S | 186 +++++++++++++++++++ arch/arm/mach-uniphier/arm32/late_lowlevel_init.S | 18 ++ arch/arm/mach-uniphier/arm32/lowlevel_init.S | 207 ++++++++++++++++++++++ arch/arm/mach-uniphier/arm32/ssc-regs.h | 65 +++++++ arch/arm/mach-uniphier/arm32/timer.c | 39 ++++ 8 files changed, 730 insertions(+) create mode 100644 arch/arm/mach-uniphier/arm32/Makefile create mode 100644 arch/arm/mach-uniphier/arm32/arm-mpcore.h create mode 100644 arch/arm/mach-uniphier/arm32/cache_uniphier.c create mode 100644 arch/arm/mach-uniphier/arm32/debug_ll.S create mode 100644 arch/arm/mach-uniphier/arm32/late_lowlevel_init.S create mode 100644 arch/arm/mach-uniphier/arm32/lowlevel_init.S create mode 100644 arch/arm/mach-uniphier/arm32/ssc-regs.h create mode 100644 arch/arm/mach-uniphier/arm32/timer.c (limited to 'arch/arm/mach-uniphier/arm32') diff --git a/arch/arm/mach-uniphier/arm32/Makefile b/arch/arm/mach-uniphier/arm32/Makefile new file mode 100644 index 0000000000..376c06b597 --- /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 0000000000..cf7cd46c10 --- /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 0000000000..4398114658 --- /dev/null +++ b/arch/arm/mach-uniphier/arm32/cache_uniphier.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2012-2015 Masahiro Yamada + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +#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 0000000000..a70954cbee --- /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 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +#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 0000000000..cce91dfac7 --- /dev/null +++ b/arch/arm/mach-uniphier/arm32/late_lowlevel_init.S @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2015 Socionext Inc. + * Author: Masahiro Yamada + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +#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 0000000000..dd03ad8143 --- /dev/null +++ b/arch/arm/mach-uniphier/arm32/lowlevel_init.S @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2012-2015 Masahiro Yamada + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +#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 0000000000..02fca3b6f6 --- /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 0000000000..a34e30b72b --- /dev/null +++ b/arch/arm/mach-uniphier/arm32/timer.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2012-2015 Masahiro Yamada + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +#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; +} -- cgit v1.2.1