diff options
author | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
---|---|---|
committer | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/arch/arm/mach-uniphier | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/arch/arm/mach-uniphier')
94 files changed, 7843 insertions, 0 deletions
diff --git a/roms/u-boot/arch/arm/mach-uniphier/Kconfig b/roms/u-boot/arch/arm/mach-uniphier/Kconfig new file mode 100644 index 000000000..3a8eee7b8 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/Kconfig @@ -0,0 +1,120 @@ +if ARCH_UNIPHIER + +config SYS_CONFIG_NAME + default "uniphier" + +choice + prompt "UniPhier SoC select" + +config ARCH_UNIPHIER_V7_MULTI + bool "UniPhier V7 SoCs" + select ARCH_SUPPORT_PSCI + select ARMV7_NONSEC + select CPU_V7A + select CPU_V7_HAS_NONSEC + +config ARCH_UNIPHIER_V8_MULTI + bool "UniPhier V8 SoCs" + depends on !SPL + select ARM64 + select CMD_UNZIP + +endchoice + +config ARCH_UNIPHIER_LD4 + bool "Enable UniPhier LD4 SoC support" + depends on ARCH_UNIPHIER_V7_MULTI + depends on !SPL || SPL_TEXT_BASE = 0x00040000 + default y + +config ARCH_UNIPHIER_SLD8 + bool "Enable UniPhier sLD8 SoC support" + depends on ARCH_UNIPHIER_V7_MULTI + depends on !SPL || SPL_TEXT_BASE = 0x00040000 + default y + +config ARCH_UNIPHIER_PRO4 + bool "Enable UniPhier Pro4 SoC support" + depends on ARCH_UNIPHIER_V7_MULTI + depends on !SPL || SPL_TEXT_BASE = 0x00100000 + default y + +config ARCH_UNIPHIER_PRO5 + bool "Enable UniPhier Pro5 SoC support" + depends on ARCH_UNIPHIER_V7_MULTI + depends on !SPL || SPL_TEXT_BASE = 0x00100000 + default y + +config ARCH_UNIPHIER_PXS2 + bool "Enable UniPhier Pxs2 SoC support" + depends on ARCH_UNIPHIER_V7_MULTI + depends on !SPL || SPL_TEXT_BASE = 0x00100000 + default y + +config ARCH_UNIPHIER_LD6B + bool "Enable UniPhier LD6b SoC support" + depends on ARCH_UNIPHIER_V7_MULTI + depends on !SPL || SPL_TEXT_BASE = 0x00100000 + default y + +config ARCH_UNIPHIER_LD11 + bool "Enable UniPhier LD11 SoC support" + depends on ARCH_UNIPHIER_V8_MULTI + default y + +config ARCH_UNIPHIER_LD20 + bool "Enable UniPhier LD20 SoC support" + depends on ARCH_UNIPHIER_V8_MULTI + default y + select OF_BOARD_SETUP + +config ARCH_UNIPHIER_PXS3 + bool "Enable UniPhier PXs3 SoC support" + depends on ARCH_UNIPHIER_V8_MULTI + default y + +config CACHE_UNIPHIER + bool "Enable the UniPhier L2 cache controller" + depends on ARCH_UNIPHIER_V7_MULTI + default y + select SYS_CACHE_SHIFT_7 + help + This option allows to use the UniPhier System Cache as L2 cache. + +config MICRO_SUPPORT_CARD + bool "Use Micro Support Card" + depends on UNIPHIER_SYSTEM_BUS + help + This option provides support for the expansion board, available + on some UniPhier reference boards. + + Say Y to use the on-board UART, Ether, LED devices. + +config CMD_PINMON + bool "Enable boot mode pins monitor command" + default y + help + The command "pinmon" shows the state of the boot mode pins. + The boot mode pins are latched when the system reset is deasserted + and determine which device the system should load a boot image from. + +config CMD_DDRPHY_DUMP + bool "Enable dump command of DDR PHY parameters" + depends on ARCH_UNIPHIER_LD4 || ARCH_UNIPHIER_PRO4 || \ + ARCH_UNIPHIER_SLD8 || ARCH_UNIPHIER_LD11 + default y + help + The command "ddrphy" shows the resulting parameters of DDR PHY + training; it is useful for the evaluation of DDR PHY training. + +config CMD_DDRMPHY_DUMP + bool "Enable dump command of DDR Multi PHY parameters" + depends on ARCH_UNIPHIER_PXS2 || ARCH_UNIPHIER_LD6B + default y + help + The command "ddrmphy" shows the resulting parameters of DDR Multi PHY + training; it is useful for the evaluation of DDR Multi PHY training. + +config SYS_SOC + default "uniphier-v7" if ARCH_UNIPHIER_V7_MULTI +endif diff --git a/roms/u-boot/arch/arm/mach-uniphier/Makefile b/roms/u-boot/arch/arm/mach-uniphier/Makefile new file mode 100644 index 000000000..d333b7091 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/Makefile @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0+ + +ifdef CONFIG_SPL_BUILD + +obj-y += boards.o +obj-y += spl_board_init.o +obj-y += memconf.o +obj-y += bcu/ +obj-$(CONFIG_SPL_MMC_SUPPORT) += mmc-boot-mode.o + +else + +obj-$(CONFIG_DISPLAY_CPUINFO) += cpu-info.o +obj-y += dram_init.o +obj-y += board_init.o +obj-$(CONFIG_ARCH_UNIPHIER_V8_MULTI) += base-address.o +obj-$(CONFIG_BOARD_LATE_INIT) += board_late_init.o +ifndef CONFIG_SYSRESET +obj-y += reset.o +endif + +obj-$(CONFIG_MICRO_SUPPORT_CARD) += micro-support-card.o +obj-$(CONFIG_MMC) += mmc-first-dev.o +obj-y += fdt-fixup.o + +endif + +obj-y += soc-info.o +obj-y += boot-device/ +obj-y += clk/ +obj-y += dram/ + +obj-$(CONFIG_DEBUG_UART_UNIPHIER) += debug-uart/ + +obj-$(CONFIG_CPU_V7A) += arm32/ +obj-$(CONFIG_ARM64) += arm64/ diff --git a/roms/u-boot/arch/arm/mach-uniphier/arm32/Makefile b/roms/u-boot/arch/arm/mach-uniphier/arm32/Makefile new file mode 100644 index 000000000..3cd00b7e5 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/arm32/Makefile @@ -0,0 +1,12 @@ +# 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 +obj-$(CONFIG_ARMV7_PSCI) += psci.o psci_smp.o +endif + +obj-y += timer.o diff --git a/roms/u-boot/arch/arm/mach-uniphier/arm32/arm-mpcore.h b/roms/u-boot/arch/arm/mach-uniphier/arm32/arm-mpcore.h new file mode 100644 index 000000000..27eac90a0 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/arm32/arm-mpcore.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2011-2014 Panasonic Corporation + */ + +#ifndef ARCH_ARM_MPCORE_H +#define ARCH_ARM_MPCORE_H + +/* Snoop Control Unit */ +#define SCU_OFFSET 0x00 + +/* SCU Control Register */ +#define SCU_CTRL 0x00 +#define SCU_ENABLE (1 << 0) +#define SCU_STANDBY_ENABLE (1 << 5) + +/* 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/roms/u-boot/arch/arm/mach-uniphier/arm32/cache-uniphier.c b/roms/u-boot/arch/arm/mach-uniphier/arm32/cache-uniphier.c new file mode 100644 index 000000000..cde2a8124 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/arm32/cache-uniphier.c @@ -0,0 +1,292 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2012-2014 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <cpu_func.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <asm/armv7.h> +#include <asm/processor.h> + +#include "cache-uniphier.h" + +/* control registers */ +#define UNIPHIER_SSCC 0x500c0000 /* Control Register */ +#define UNIPHIER_SSCC_BST (0x1 << 20) /* UCWG burst read */ +#define UNIPHIER_SSCC_ACT (0x1 << 19) /* Inst-Data separate */ +#define UNIPHIER_SSCC_WTG (0x1 << 18) /* WT gathering on */ +#define UNIPHIER_SSCC_PRD (0x1 << 17) /* enable pre-fetch */ +#define UNIPHIER_SSCC_ON (0x1 << 0) /* enable cache */ +#define UNIPHIER_SSCLPDAWCR 0x500c0030 /* Unified/Data Active Way Control */ +#define UNIPHIER_SSCLPIAWCR 0x500c0034 /* Instruction Active Way Control */ + +/* revision registers */ +#define UNIPHIER_SSCID 0x503c0100 /* ID Register */ + +/* operation registers */ +#define UNIPHIER_SSCOPE 0x506c0244 /* Cache Operation Primitive Entry */ +#define UNIPHIER_SSCOPE_CM_INV 0x0 /* invalidate */ +#define UNIPHIER_SSCOPE_CM_CLEAN 0x1 /* clean */ +#define UNIPHIER_SSCOPE_CM_FLUSH 0x2 /* flush */ +#define UNIPHIER_SSCOPE_CM_SYNC 0x8 /* sync (drain bufs) */ +#define UNIPHIER_SSCOPE_CM_FLUSH_PREFETCH 0x9 /* flush p-fetch buf */ +#define UNIPHIER_SSCOQM 0x506c0248 +#define UNIPHIER_SSCOQM_TID_MASK (0x3 << 21) +#define UNIPHIER_SSCOQM_TID_LRU_DATA (0x0 << 21) +#define UNIPHIER_SSCOQM_TID_LRU_INST (0x1 << 21) +#define UNIPHIER_SSCOQM_TID_WAY (0x2 << 21) +#define UNIPHIER_SSCOQM_S_MASK (0x3 << 17) +#define UNIPHIER_SSCOQM_S_RANGE (0x0 << 17) +#define UNIPHIER_SSCOQM_S_ALL (0x1 << 17) +#define UNIPHIER_SSCOQM_S_WAY (0x2 << 17) +#define UNIPHIER_SSCOQM_CE (0x1 << 15) /* notify completion */ +#define UNIPHIER_SSCOQM_CW (0x1 << 14) +#define UNIPHIER_SSCOQM_CM_MASK (0x7) +#define UNIPHIER_SSCOQM_CM_INV 0x0 /* invalidate */ +#define UNIPHIER_SSCOQM_CM_CLEAN 0x1 /* clean */ +#define UNIPHIER_SSCOQM_CM_FLUSH 0x2 /* flush */ +#define UNIPHIER_SSCOQM_CM_PREFETCH 0x3 /* prefetch to cache */ +#define UNIPHIER_SSCOQM_CM_PREFETCH_BUF 0x4 /* prefetch to pf-buf */ +#define UNIPHIER_SSCOQM_CM_TOUCH 0x5 /* touch */ +#define UNIPHIER_SSCOQM_CM_TOUCH_ZERO 0x6 /* touch to zero */ +#define UNIPHIER_SSCOQM_CM_TOUCH_DIRTY 0x7 /* touch with dirty */ +#define UNIPHIER_SSCOQAD 0x506c024c /* Cache Operation Queue Address */ +#define UNIPHIER_SSCOQSZ 0x506c0250 /* Cache Operation Queue Size */ +#define UNIPHIER_SSCOQMASK 0x506c0254 /* Cache Operation Queue Address Mask */ +#define UNIPHIER_SSCOQWN 0x506c0258 /* Cache Operation Queue Way Number */ +#define UNIPHIER_SSCOPPQSEF 0x506c025c /* Cache Operation Queue Set Complete */ +#define UNIPHIER_SSCOPPQSEF_FE (0x1 << 1) +#define UNIPHIER_SSCOPPQSEF_OE (0x1 << 0) +#define UNIPHIER_SSCOLPQS 0x506c0260 /* Cache Operation Queue Status */ +#define UNIPHIER_SSCOLPQS_EF (0x1 << 2) +#define UNIPHIER_SSCOLPQS_EST (0x1 << 1) +#define UNIPHIER_SSCOLPQS_QST (0x1 << 0) + +#define UNIPHIER_SSC_LINE_SIZE 128 +#define UNIPHIER_SSC_RANGE_OP_MAX_SIZE (0x00400000 - (UNIPHIER_SSC_LINE_SIZE)) + +#define UNIPHIER_SSCOQAD_IS_NEEDED(op) \ + ((op & UNIPHIER_SSCOQM_S_MASK) == UNIPHIER_SSCOQM_S_RANGE) +#define UNIPHIER_SSCOQWM_IS_NEEDED(op) \ + (((op & UNIPHIER_SSCOQM_S_MASK) == UNIPHIER_SSCOQM_S_WAY) || \ + ((op & UNIPHIER_SSCOQM_TID_MASK) == UNIPHIER_SSCOQM_TID_WAY)) + +/* uniphier_cache_sync - perform a sync point for a particular cache level */ +static void uniphier_cache_sync(void) +{ + /* drain internal buffers */ + writel(UNIPHIER_SSCOPE_CM_SYNC, UNIPHIER_SSCOPE); + /* need a read back to confirm */ + readl(UNIPHIER_SSCOPE); +} + +/** + * uniphier_cache_maint_common - run a queue operation + * + * @start: start address of range operation (don't care for "all" operation) + * @size: data size of range operation (don't care for "all" operation) + * @ways: target ways (don't care for operations other than pre-fetch, touch + * @operation: flags to specify the desired cache operation + */ +static void uniphier_cache_maint_common(u32 start, u32 size, u32 ways, + u32 operation) +{ + /* clear the complete notification flag */ + writel(UNIPHIER_SSCOLPQS_EF, UNIPHIER_SSCOLPQS); + + do { + /* set cache operation */ + writel(UNIPHIER_SSCOQM_CE | operation, UNIPHIER_SSCOQM); + + /* set address range if needed */ + if (likely(UNIPHIER_SSCOQAD_IS_NEEDED(operation))) { + writel(start, UNIPHIER_SSCOQAD); + writel(size, UNIPHIER_SSCOQSZ); + } + + /* set target ways if needed */ + if (unlikely(UNIPHIER_SSCOQWM_IS_NEEDED(operation))) + writel(ways, UNIPHIER_SSCOQWN); + } while (unlikely(readl(UNIPHIER_SSCOPPQSEF) & + (UNIPHIER_SSCOPPQSEF_FE | UNIPHIER_SSCOPPQSEF_OE))); + + /* wait until the operation is completed */ + while (likely(readl(UNIPHIER_SSCOLPQS) != UNIPHIER_SSCOLPQS_EF)) + cpu_relax(); +} + +static void uniphier_cache_maint_all(u32 operation) +{ + uniphier_cache_maint_common(0, 0, 0, UNIPHIER_SSCOQM_S_ALL | operation); + + uniphier_cache_sync(); +} + +static void uniphier_cache_maint_range(u32 start, u32 end, u32 ways, + u32 operation) +{ + u32 size; + + /* + * If the start address is not aligned, + * perform a cache operation for the first cache-line + */ + start = start & ~(UNIPHIER_SSC_LINE_SIZE - 1); + + size = end - start; + + if (unlikely(size >= (u32)(-UNIPHIER_SSC_LINE_SIZE))) { + /* this means cache operation for all range */ + uniphier_cache_maint_all(operation); + return; + } + + /* + * If the end address is not aligned, + * perform a cache operation for the last cache-line + */ + size = ALIGN(size, UNIPHIER_SSC_LINE_SIZE); + + while (size) { + u32 chunk_size = min_t(u32, size, UNIPHIER_SSC_RANGE_OP_MAX_SIZE); + + uniphier_cache_maint_common(start, chunk_size, ways, + UNIPHIER_SSCOQM_S_RANGE | operation); + + start += chunk_size; + size -= chunk_size; + } + + uniphier_cache_sync(); +} + +void uniphier_cache_prefetch_range(u32 start, u32 end, u32 ways) +{ + uniphier_cache_maint_range(start, end, ways, + UNIPHIER_SSCOQM_TID_WAY | + UNIPHIER_SSCOQM_CM_PREFETCH); +} + +void uniphier_cache_touch_range(u32 start, u32 end, u32 ways) +{ + uniphier_cache_maint_range(start, end, ways, + UNIPHIER_SSCOQM_TID_WAY | + UNIPHIER_SSCOQM_CM_TOUCH); +} + +void uniphier_cache_touch_zero_range(u32 start, u32 end, u32 ways) +{ + uniphier_cache_maint_range(start, end, ways, + UNIPHIER_SSCOQM_TID_WAY | + UNIPHIER_SSCOQM_CM_TOUCH_ZERO); +} + +void uniphier_cache_inv_way(u32 ways) +{ + uniphier_cache_maint_common(0, 0, ways, + UNIPHIER_SSCOQM_S_WAY | + UNIPHIER_SSCOQM_CM_INV); +} + +void uniphier_cache_set_active_ways(int cpu, u32 active_ways) +{ + void __iomem *base = (void __iomem *)UNIPHIER_SSCC + 0xc00; + + switch (readl(UNIPHIER_SSCID)) { /* revision */ + case 0x12: /* LD4 */ + case 0x16: /* sld8 */ + base = (void __iomem *)UNIPHIER_SSCC + 0x840; + break; + default: + base = (void __iomem *)UNIPHIER_SSCC + 0xc00; + break; + } + + writel(active_ways, base + 4 * cpu); +} + +static void uniphier_cache_endisable(int enable) +{ + u32 tmp; + + tmp = readl(UNIPHIER_SSCC); + if (enable) + tmp |= UNIPHIER_SSCC_ON; + else + tmp &= ~UNIPHIER_SSCC_ON; + writel(tmp, UNIPHIER_SSCC); +} + +void uniphier_cache_enable(void) +{ + uniphier_cache_endisable(1); +} + +void uniphier_cache_disable(void) +{ + uniphier_cache_endisable(0); +} + +#ifdef CONFIG_CACHE_UNIPHIER +void v7_outer_cache_flush_all(void) +{ + uniphier_cache_maint_all(UNIPHIER_SSCOQM_CM_FLUSH); +} + +void v7_outer_cache_inval_all(void) +{ + uniphier_cache_maint_all(UNIPHIER_SSCOQM_CM_INV); +} + +void v7_outer_cache_flush_range(u32 start, u32 end) +{ + uniphier_cache_maint_range(start, end, 0, UNIPHIER_SSCOQM_CM_FLUSH); +} + +void v7_outer_cache_inval_range(u32 start, u32 end) +{ + if (start & (UNIPHIER_SSC_LINE_SIZE - 1)) { + start &= ~(UNIPHIER_SSC_LINE_SIZE - 1); + uniphier_cache_maint_range(start, UNIPHIER_SSC_LINE_SIZE, 0, + UNIPHIER_SSCOQM_CM_FLUSH); + start += UNIPHIER_SSC_LINE_SIZE; + } + + if (start >= end) { + uniphier_cache_sync(); + return; + } + + if (end & (UNIPHIER_SSC_LINE_SIZE - 1)) { + end &= ~(UNIPHIER_SSC_LINE_SIZE - 1); + uniphier_cache_maint_range(end, UNIPHIER_SSC_LINE_SIZE, 0, + UNIPHIER_SSCOQM_CM_FLUSH); + } + + if (start >= end) { + uniphier_cache_sync(); + return; + } + + uniphier_cache_maint_range(start, end, 0, UNIPHIER_SSCOQM_CM_INV); +} + +void v7_outer_cache_enable(void) +{ + uniphier_cache_set_active_ways(0, U32_MAX); /* activate all ways */ + uniphier_cache_enable(); +} + +void v7_outer_cache_disable(void) +{ + uniphier_cache_disable(); +} +#endif + +void enable_caches(void) +{ + dcache_enable(); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/arm32/cache-uniphier.h b/roms/u-boot/arch/arm/mach-uniphier/arm32/cache-uniphier.h new file mode 100644 index 000000000..40838244d --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/arm32/cache-uniphier.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#ifndef __CACHE_UNIPHIER_H +#define __CACHE_UNIPHIER_H + +#include <linux/types.h> + +void uniphier_cache_prefetch_range(u32 start, u32 end, u32 ways); +void uniphier_cache_touch_range(u32 start, u32 end, u32 ways); +void uniphier_cache_touch_zero_range(u32 start, u32 end, u32 ways); +void uniphier_cache_inv_way(u32 ways); +void uniphier_cache_set_active_ways(int cpu, u32 active_ways); +void uniphier_cache_enable(void); +void uniphier_cache_disable(void); + +#endif /* __CACHE_UNIPHIER_H */ diff --git a/roms/u-boot/arch/arm/mach-uniphier/arm32/debug_ll.S b/roms/u-boot/arch/arm/mach-uniphier/arm32/debug_ll.S new file mode 100644 index 000000000..3fed7985f --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/arm32/debug_ll.S @@ -0,0 +1,175 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * On-chip UART initializaion for low-level debugging + * + * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#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 SG_REVISION_TYPE_SHIFT 16 +#define SG_REVISION_TYPE_MASK (0xff << SG_REVISION_TYPE_SHIFT) +#define BAUDRATE 115200 +#define DIV_ROUND(x, d) (((x) + ((d) / 2)) / (d)) + +.macro sg_set_pinsel, pin, muxval, mux_bits, reg_stride, ra, rd + ldr \ra, =(SG_BASE + SG_PINCTRL_BASE + \pin * \mux_bits / 32 * \reg_stride) + ldr \rd, [\ra] + and \rd, \rd, #~(((1 << \mux_bits) - 1) << (\pin * \mux_bits % 32)) + orr \rd, \rd, #(\muxval << (\pin * \mux_bits % 32)) + str \rd, [\ra] +.endm + +ENTRY(debug_ll_init) + ldr r0, =(SG_BASE + 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_LD4) +#define UNIPHIER_LD4_UART_CLK 36864000 + cmp r1, #0x26 + bne ld4_end + + ldr r0, =(SG_BASE + 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(UNIPHIER_LD4_UART_CLK, 16 * BAUDRATE) + + b init_uart +ld4_end: +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PRO4) +#define UNIPHIER_PRO4_UART_CLK 73728000 + cmp r1, #0x28 + bne pro4_end + + sg_set_pinsel 128, 0, 4, 8, r0, r1 @ TXD0 -> TXD0 + + ldr r0, =(SG_BASE + SG_LOADPINCTRL) + mov r1, #1 + str r1, [r0] + + ldr r0, =(SC_BASE + SC_CLKCTRL) + ldr r1, [r0] + orr r1, r1, #SC_CLKCTRL_CEN_PERI + str r1, [r0] + + ldr r3, =DIV_ROUND(UNIPHIER_PRO4_UART_CLK, 16 * BAUDRATE) + + b init_uart +pro4_end: +#endif +#if defined(CONFIG_ARCH_UNIPHIER_SLD8) +#define UNIPHIER_SLD8_UART_CLK 80000000 + cmp r1, #0x29 + bne sld8_end + + ldr r0, =(SG_BASE + 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(UNIPHIER_SLD8_UART_CLK, 16 * BAUDRATE) + + b init_uart +sld8_end: +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PRO5) +#define UNIPHIER_PRO5_UART_CLK 73728000 + cmp r1, #0x2A + bne 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_BASE + SG_LOADPINCTRL) + mov r1, #1 + str r1, [r0] + + ldr r0, =(SC_BASE + SC_CLKCTRL) + ldr r1, [r0] + orr r1, r1, #SC_CLKCTRL_CEN_PERI + str r1, [r0] + + ldr r3, =DIV_ROUND(UNIPHIER_PRO5_UART_CLK, 16 * BAUDRATE) + + b init_uart +pro5_end: +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PXS2) +#define UNIPHIER_PXS2_UART_CLK 88900000 + cmp r1, #0x2E + bne pxs2_end + + ldr r0, =(SG_BASE + 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_BASE + SC_CLKCTRL) + ldr r1, [r0] + orr r1, r1, #SC_CLKCTRL_CEN_PERI + str r1, [r0] + + ldr r3, =DIV_ROUND(UNIPHIER_PXS2_UART_CLK, 16 * BAUDRATE) + + b init_uart +pxs2_end: +#endif +#if defined(CONFIG_ARCH_UNIPHIER_LD6B) +#define UNIPHIER_LD6B_UART_CLK 88900000 + cmp r1, #0x2F + bne ld6b_end + + ldr r0, =(SG_BASE + 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_BASE + SC_CLKCTRL) + ldr r1, [r0] + orr r1, r1, #SC_CLKCTRL_CEN_PERI + str r1, [r0] + + ldr r3, =DIV_ROUND(UNIPHIER_LD6B_UART_CLK, 16 * BAUDRATE) + + b init_uart +ld6b_end: +#endif + mov pc, lr + +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/roms/u-boot/arch/arm/mach-uniphier/arm32/late_lowlevel_init.S b/roms/u-boot/arch/arm/mach-uniphier/arm32/late_lowlevel_init.S new file mode 100644 index 000000000..36db50fd9 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/arm32/late_lowlevel_init.S @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2015 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <config.h> +#include <linux/linkage.h> + +ENTRY(lowlevel_init) + ldr sp, = CONFIG_SYS_INIT_SP_ADDR + b uniphier_cache_disable +ENDPROC(lowlevel_init) diff --git a/roms/u-boot/arch/arm/mach-uniphier/arm32/lowlevel_init.S b/roms/u-boot/arch/arm/mach-uniphier/arm32/lowlevel_init.S new file mode 100644 index 000000000..3f9f135bc --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/arm32/lowlevel_init.S @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2012-2015 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <config.h> +#include <linux/linkage.h> +#include <linux/sizes.h> +#include <asm/system.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 table + + /* + * Now we are using the page table embedded in the Boot ROM. + * 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_RAM_WAYS (0x00000100) @ way 8 + +#define SSCO_BASE 0x506c0000 +#define SSCOPE 0x244 +#define SSCOQM 0x248 +#define SSCOQAD 0x24c +#define SSCOQSZ 0x250 +#define SSCOQWN 0x258 +#define SSCOPPQSEF 0x25c +#define SSCOLPQS 0x260 + +ENTRY(setup_init_ram) + ldr r1, = SSCO_BASE + + /* Touch to zero for the boot way */ +0: ldr r0, = 0x00408006 @ touch to zero with address range + str r0, [r1, #SSCOQM] + ldr r0, = BOOT_RAM_BASE + str r0, [r1, #SSCOQAD] + ldr r0, = BOOT_RAM_SIZE + str r0, [r1, #SSCOQSZ] + ldr r0, = BOOT_RAM_WAYS + str r0, [r1, #SSCOQWN] + ldr r0, [r1, #SSCOPPQSEF] + cmp r0, #0 @ check if the command is successfully set + bne 0b @ try again if an error occurs + +1: ldr r0, [r1, #SSCOLPQS] + cmp r0, #0x4 + bne 1b @ wait until the operation is completed + str r0, [r1, #SSCOLPQS] @ 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) diff --git a/roms/u-boot/arch/arm/mach-uniphier/arm32/psci.c b/roms/u-boot/arch/arm/mach-uniphier/arm32/psci.c new file mode 100644 index 000000000..fbb6ebca7 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/arm32/psci.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <cpu_func.h> +#include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/printk.h> +#include <linux/psci.h> +#include <linux/sizes.h> +#include <asm/processor.h> +#include <asm/psci.h> +#include <asm/secure.h> +#include <asm/system.h> + +#include "../debug.h" +#include "../soc-info.h" +#include "arm-mpcore.h" +#include "cache-uniphier.h" + +#define UNIPHIER_SMPCTRL_ROM_RSV2 0x59801208 + +void uniphier_smp_trampoline(void); +void uniphier_smp_trampoline_end(void); +u32 uniphier_smp_booted[CONFIG_ARMV7_PSCI_NR_CPUS]; + +static int uniphier_get_nr_cpus(void) +{ + switch (uniphier_get_soc_id()) { + case UNIPHIER_PRO4_ID: + case UNIPHIER_PRO5_ID: + return 2; + case UNIPHIER_PXS2_ID: + case UNIPHIER_LD6B_ID: + return 4; + default: + return 1; + } +} + +static void uniphier_smp_kick_all_cpus(void) +{ + const u32 target_ways = BIT(0); + size_t trmp_size; + u32 trmp_src = (unsigned long)uniphier_smp_trampoline; + u32 trmp_src_end = (unsigned long)uniphier_smp_trampoline_end; + u32 trmp_dest, trmp_dest_end; + int nr_cpus, i; + int timeout = 1000; + + nr_cpus = uniphier_get_nr_cpus(); + if (nr_cpus == 1) + return; + + for (i = 0; i < nr_cpus; i++) /* lock ways for all CPUs */ + uniphier_cache_set_active_ways(i, 0); + uniphier_cache_inv_way(target_ways); + uniphier_cache_enable(); + + /* copy trampoline code */ + uniphier_cache_prefetch_range(trmp_src, trmp_src_end, target_ways); + + trmp_size = trmp_src_end - trmp_src; + + trmp_dest = trmp_src & (SZ_64K - 1); + trmp_dest += SZ_1M - SZ_64K * 2; + + trmp_dest_end = trmp_dest + trmp_size; + + uniphier_cache_touch_range(trmp_dest, trmp_dest_end, target_ways); + + writel(trmp_dest, UNIPHIER_SMPCTRL_ROM_RSV2); + + asm("dsb ishst\n" /* Ensure the write to ROM_RSV2 is visible */ + "sev"); /* Bring up all secondary CPUs from Boot ROM into U-Boot */ + + while (--timeout) { + int all_booted = 1; + + for (i = 1; i < nr_cpus; i++) + if (!uniphier_smp_booted[i]) + all_booted = 0; + if (all_booted) + break; + udelay(1); + + /* barrier here because uniphier_smp_booted[] may be updated */ + cpu_relax(); + } + + if (!timeout) + pr_warn("warning: some of secondary CPUs may not boot\n"); + + uniphier_cache_disable(); +} + +void psci_board_init(void) +{ + unsigned long scu_base; + u32 scu_ctrl, tmp; + + asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (scu_base)); + + scu_ctrl = readl(scu_base + 0x30); + if (!(scu_ctrl & 1)) + writel(scu_ctrl | 0x1, scu_base + 0x30); + + scu_ctrl = readl(scu_base + SCU_CTRL); + scu_ctrl |= SCU_ENABLE | SCU_STANDBY_ENABLE; + writel(scu_ctrl, scu_base + SCU_CTRL); + + tmp = readl(scu_base + SCU_SNSAC); + tmp |= 0xfff; + writel(tmp, scu_base + SCU_SNSAC); + + uniphier_smp_kick_all_cpus(); +} + +void psci_arch_init(void) +{ + u32 actlr; + + asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (actlr)); + actlr |= 0x41; /* set SMP and FW bits */ + asm("mcr p15, 0, %0, c1, c0, 1" : : "r" (actlr)); +} + +u32 uniphier_psci_holding_pen_release __secure_data = 0xffffffff; + +s32 __secure psci_cpu_on(u32 function_id, u32 cpuid, u32 entry_point, + u32 context_id) +{ + u32 cpu = cpuid & 0xff; + + debug_puts("[U-Boot PSCI] psci_cpu_on: cpuid="); + debug_puth(cpuid); + debug_puts(", entry_point="); + debug_puth(entry_point); + debug_puts(", context_id="); + debug_puth(context_id); + debug_puts("\n"); + + psci_save(cpu, entry_point, context_id); + + /* We assume D-cache is off, so do not call flush_dcache() here */ + uniphier_psci_holding_pen_release = cpu; + + /* Send an event to wake up the secondary CPU. */ + asm("dsb ishst\n" + "sev"); + + return PSCI_RET_SUCCESS; +} + +void __secure psci_system_reset(void) +{ + reset_cpu(); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/arm32/psci_smp.S b/roms/u-boot/arch/arm/mach-uniphier/arm32/psci_smp.S new file mode 100644 index 000000000..65a06ae23 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/arm32/psci_smp.S @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <linux/linkage.h> +#include <asm/system.h> + + .section ._secure.text, "ax" + +ENTRY(uniphier_smp_trampoline) + ldr r0, 0f + mrc p15, 0, r1, c1, c0, 0 @ SCTLR (System Control Register) + orr r1, r1, #CR_I @ Enable ICache + bic r1, r1, #(CR_C | CR_M) @ Disable MMU and Dcache + mcr p15, 0, r1, c1, c0, 0 + + bx r0 +0: .word uniphier_secondary_startup + .globl uniphier_smp_trampoline_end +uniphier_smp_trampoline_end: +ENDPROC(uniphier_smp_trampoline) + +LENTRY(uniphier_secondary_startup) + mrc p15, 0, r1, c0, c0, 5 @ MPIDR (Multiprocessor Affinity Reg) + and r1, r1, #0xff + + ldr r2, =uniphier_smp_booted + mov r0, #1 + str r0, [r2, r1, lsl #2] + + ldr r2, =uniphier_psci_holding_pen_release +pen: ldr r0, [r2] + cmp r0, r1 + beq psci_cpu_entry + wfe + b pen +ENDPROC(uniphier_secondary_startup) diff --git a/roms/u-boot/arch/arm/mach-uniphier/arm32/timer.c b/roms/u-boot/arch/arm/mach-uniphier/arm32/timer.c new file mode 100644 index 000000000..a40bdf170 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/arm32/timer.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <config.h> +#include <init.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; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/arm64/Makefile b/roms/u-boot/arch/arm/mach-uniphier/arm64/Makefile new file mode 100644 index 000000000..750c4f756 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/arm64/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-y += mem_map.o diff --git a/roms/u-boot/arch/arm/mach-uniphier/arm64/mem_map.c b/roms/u-boot/arch/arm/mach-uniphier/arm64/mem_map.c new file mode 100644 index 000000000..a8bd4eee8 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/arm64/mem_map.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <linux/types.h> +#include <asm/armv8/mmu.h> + +#include "../init.h" + +static struct mm_region uniphier_mem_map[] = { + { + .virt = 0x00000000, + .phys = 0x00000000, + .size = 0x80000000, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { + .virt = 0x80000000, + .phys = 0x80000000, + .size = 0xc0000000, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, + { /* sentinel */ } +}; + +struct mm_region *mem_map = uniphier_mem_map; + +void uniphier_mem_map_init(unsigned long dram_base, unsigned long dram_size) +{ + uniphier_mem_map[0].size = dram_base; + uniphier_mem_map[1].virt = dram_base; + uniphier_mem_map[1].phys = dram_base; + uniphier_mem_map[1].size = dram_size; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/base-address.c b/roms/u-boot/arch/arm/mach-uniphier/base-address.c new file mode 100644 index 000000000..d7456f8df --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/base-address.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (C) 2019 Socionext Inc. +// Author: Masahiro Yamada <yamada.masahiro@socionext.com> + +#include <dm/of.h> +#include <fdt_support.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/libfdt.h> +#include <linux/sizes.h> +#include <asm/global_data.h> + +#include "base-address.h" +#include "sc64-regs.h" +#include "sg-regs.h" + +/* + * Dummy initializers are needed to allocate these to .data section instead of + * .bss section. The .bss section is unusable before relocation because the + * .bss section and DT share the same address. Without the initializers, + * DT would be broken. + */ +void __iomem *sc_base = (void *)0xdeadbeef; +void __iomem *sg_base = (void *)0xdeadbeef; + +static u64 uniphier_base_address_get(const char *compat_tail) +{ + DECLARE_GLOBAL_DATA_PTR; + const void *fdt = gd->fdt_blob; + int offset, len, i; + const char *str; + + for (offset = fdt_next_node(fdt, 0, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + for (i = 0; + (str = fdt_stringlist_get(fdt, offset, "compatible", i, &len)); + i++) { + if (!memcmp(compat_tail, + str + len - strlen(compat_tail), + strlen(compat_tail))) + return fdt_get_base_address(fdt, offset); + } + } + + return OF_BAD_ADDR; +} + +int uniphier_base_address_init(void) +{ + u64 base; + + base = uniphier_base_address_get("-soc-glue"); + if (base == OF_BAD_ADDR) + return -EINVAL; + + sg_base = ioremap(base, SZ_8K); + + base = uniphier_base_address_get("-sysctrl"); + if (base == OF_BAD_ADDR) + return -EINVAL; + + sc_base = ioremap(base, SZ_64K); + + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/base-address.h b/roms/u-boot/arch/arm/mach-uniphier/base-address.h new file mode 100644 index 000000000..6158ce7d6 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/base-address.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2019 Socionext Inc. + */ + +#ifndef __UNIPHIER_BASE_ADDRESS_H +#define __UNIPHIER_BASE_ADDRESS_H + +#ifdef CONFIG_ARCH_UNIPHIER_V8_MULTI +int uniphier_base_address_init(void); +#else +static inline int uniphier_base_address_init(void) +{ + return 0; +} +#endif + +#endif /* __UNIPHIER_BASE_ADDRESS_H */ diff --git a/roms/u-boot/arch/arm/mach-uniphier/bcu/Makefile b/roms/u-boot/arch/arm/mach-uniphier/bcu/Makefile new file mode 100644 index 000000000..88730205a --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/bcu/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-$(CONFIG_ARCH_UNIPHIER_LD4) += bcu-ld4.o +obj-$(CONFIG_ARCH_UNIPHIER_SLD8) += bcu-ld4.o diff --git a/roms/u-boot/arch/arm/mach-uniphier/bcu/bcu-ld4.c b/roms/u-boot/arch/arm/mach-uniphier/bcu/bcu-ld4.c new file mode 100644 index 000000000..ea6088ba1 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/bcu/bcu-ld4.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011-2014 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <linux/io.h> + +#include "../init.h" +#include "bcu-regs.h" + +#define ch(x) ((x) >= 32 ? 0 : (x) < 0 ? 0x11111111 : 0x11111111 << (x)) + +void uniphier_ld4_bcu_init(const struct uniphier_board_data *bd) +{ + int shift; + + writel(0x44444444, BCSCR0); /* 0x20000000-0x3fffffff: ASM bus */ + writel(0x11111111, BCSCR2); /* 0x80000000-0x9fffffff: IPPC/IPPD-bus */ + writel(0x11111111, BCSCR3); /* 0xa0000000-0xbfffffff: IPPC/IPPD-bus */ + writel(0x11111111, BCSCR4); /* 0xc0000000-0xdfffffff: IPPC/IPPD-bus */ + writel(0x11111111, BCSCR5); /* 0xe0000000-0Xffffffff: IPPC/IPPD-bus */ + + /* Specify DDR channel */ + shift = bd->dram_ch[0].size / 0x04000000 * 4; + writel(ch(shift), BCIPPCCHR2); /* 0x80000000-0x9fffffff */ + + shift -= 32; + writel(ch(shift), BCIPPCCHR3); /* 0xa0000000-0xbfffffff */ + + shift -= 32; + writel(ch(shift), BCIPPCCHR4); /* 0xc0000000-0xdfffffff */ +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/bcu/bcu-regs.h b/roms/u-boot/arch/arm/mach-uniphier/bcu/bcu-regs.h new file mode 100644 index 000000000..9f6cf540b --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/bcu/bcu-regs.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * UniPhier BCU (Bus Control Unit) registers + * + * Copyright (C) 2011-2014 Panasonic Corporation + */ + +#ifndef ARCH_BCU_REGS_H +#define ARCH_BCU_REGS_H + +#define BCU_BASE 0x50080000 + +#define BCSCR(x) (BCU_BASE + 0x180 + (x) * 4) +#define BCSCR0 (BCSCR(0)) +#define BCSCR1 (BCSCR(1)) +#define BCSCR2 (BCSCR(2)) +#define BCSCR3 (BCSCR(3)) +#define BCSCR4 (BCSCR(4)) +#define BCSCR5 (BCSCR(5)) + +#define BCIPPCCHR(x) (BCU_BASE + 0x0280 + (x) * 4) +#define BCIPPCCHR0 (BCIPPCCHR(0)) +#define BCIPPCCHR1 (BCIPPCCHR(1)) +#define BCIPPCCHR2 (BCIPPCCHR(2)) +#define BCIPPCCHR3 (BCIPPCCHR(3)) +#define BCIPPCCHR4 (BCIPPCCHR(4)) +#define BCIPPCCHR5 (BCIPPCCHR(5)) + +#endif /* ARCH_BCU_REGS_H */ diff --git a/roms/u-boot/arch/arm/mach-uniphier/board_init.c b/roms/u-boot/arch/arm/mach-uniphier/board_init.c new file mode 100644 index 000000000..30e4e23a6 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/board_init.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2012-2015 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/printk.h> + +#include "init.h" +#include "micro-support-card.h" +#include "soc-info.h" + +#define PC0CTRL 0x598000c0 + +#if defined(CONFIG_ARCH_UNIPHIER_LD4) || defined(CONFIG_ARCH_UNIPHIER_SLD8) +static void uniphier_ld4_sbc_init(void) +{ + u32 tmp; + + /* system bus output enable */ + tmp = readl(PC0CTRL); + tmp &= 0xfffffcff; + writel(tmp, PC0CTRL); +} +#endif + +#if defined(CONFIG_ARCH_UNIPHIER_PXS2) || \ + defined(CONFIG_ARCH_UNIPHIER_LD6B) || \ + defined(CONFIG_ARCH_UNIPHIER_LD11) || \ + defined(CONFIG_ARCH_UNIPHIER_LD20) || \ + defined(CONFIG_ARCH_UNIPHIER_PXS3) +static void uniphier_pxs2_sbc_init(void) +{ + /* necessary for ROM boot ?? */ + /* system bus output enable */ + writel(0x17, PC0CTRL); +} +#endif + +#ifdef CONFIG_ARCH_UNIPHIER_LD20 +static void uniphier_ld20_misc_init(void) +{ + /* ES1 errata: increase VDD09 supply to suppress VBO noise */ + if (uniphier_get_soc_revision() == 1) { + writel(0x00000003, 0x6184e004); + writel(0x00000100, 0x6184e040); + writel(0x0000b500, 0x6184e024); + writel(0x00000001, 0x6184e000); + } +} +#endif + +struct uniphier_initdata { + unsigned int soc_id; + void (*sbc_init)(void); + void (*pll_init)(void); + void (*clk_init)(void); + void (*misc_init)(void); +}; + +static const struct uniphier_initdata uniphier_initdata[] = { +#if defined(CONFIG_ARCH_UNIPHIER_LD4) + { + .soc_id = UNIPHIER_LD4_ID, + .sbc_init = uniphier_ld4_sbc_init, + .pll_init = uniphier_ld4_pll_init, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PRO4) + { + .soc_id = UNIPHIER_PRO4_ID, + .pll_init = uniphier_pro4_pll_init, + .clk_init = uniphier_pro4_clk_init, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_SLD8) + { + .soc_id = UNIPHIER_SLD8_ID, + .sbc_init = uniphier_ld4_sbc_init, + .pll_init = uniphier_ld4_pll_init, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PRO5) + { + .soc_id = UNIPHIER_PRO5_ID, + .clk_init = uniphier_pro5_clk_init, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PXS2) + { + .soc_id = UNIPHIER_PXS2_ID, + .sbc_init = uniphier_pxs2_sbc_init, + .clk_init = uniphier_pxs2_clk_init, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_LD6B) + { + .soc_id = UNIPHIER_LD6B_ID, + .sbc_init = uniphier_pxs2_sbc_init, + .clk_init = uniphier_pxs2_clk_init, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_LD11) + { + .soc_id = UNIPHIER_LD11_ID, + .sbc_init = uniphier_pxs2_sbc_init, + .pll_init = uniphier_ld11_pll_init, + .clk_init = uniphier_ld11_clk_init, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_LD20) + { + .soc_id = UNIPHIER_LD20_ID, + .sbc_init = uniphier_pxs2_sbc_init, + .pll_init = uniphier_ld20_pll_init, + .clk_init = uniphier_ld20_clk_init, + .misc_init = uniphier_ld20_misc_init, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PXS3) + { + .soc_id = UNIPHIER_PXS3_ID, + .sbc_init = uniphier_pxs2_sbc_init, + .pll_init = uniphier_pxs3_pll_init, + .clk_init = uniphier_pxs3_clk_init, + }, +#endif +}; +UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_initdata, uniphier_initdata) + +int board_init(void) +{ + const struct uniphier_initdata *initdata; + + led_puts("U0"); + + initdata = uniphier_get_initdata(); + if (!initdata) { + pr_err("unsupported SoC\n"); + return -EINVAL; + } + + if (initdata->sbc_init) + initdata->sbc_init(); + + support_card_init(); + + led_puts("U0"); + + if (initdata->pll_init) + initdata->pll_init(); + + led_puts("U1"); + + if (initdata->clk_init) + initdata->clk_init(); + + led_puts("U2"); + + if (initdata->misc_init) + initdata->misc_init(); + + led_puts("Uboo"); + + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/board_late_init.c b/roms/u-boot/arch/arm/mach-uniphier/board_late_init.c new file mode 100644 index 000000000..b33c4b193 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/board_late_init.c @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <env.h> +#include <init.h> +#include <spl.h> +#include <asm/global_data.h> +#include <linux/libfdt.h> +#include <stdio.h> +#include <linux/printk.h> + +#include "init.h" + +static void uniphier_set_env_fdt_file(void) +{ + DECLARE_GLOBAL_DATA_PTR; + const char *compat; + char dtb_name[256]; + int buf_len = sizeof(dtb_name); + int ret; + + if (env_get("fdtfile")) + return; /* do nothing if it is already set */ + + compat = fdt_stringlist_get(gd->fdt_blob, 0, "compatible", 0, NULL); + if (!compat) + goto fail; + + /* rip off the vendor prefix "socionext," */ + compat = strchr(compat, ','); + if (!compat) + goto fail; + compat++; + + strncpy(dtb_name, compat, buf_len); + buf_len -= strlen(compat); + + strncat(dtb_name, ".dtb", buf_len); + + ret = env_set("fdtfile", dtb_name); + if (ret) + goto fail; + + return; +fail: + pr_warn("\"fdt_file\" environment variable was not set correctly\n"); +} + +static void uniphier_set_env_addr(const char *env, const char *offset_env) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned long offset = 0; + const char *str; + char *end; + int ret; + + if (env_get(env)) + return; /* do nothing if it is already set */ + + if (offset_env) { + str = env_get(offset_env); + if (!str) + goto fail; + + offset = simple_strtoul(str, &end, 16); + if (*end) + goto fail; + } + + ret = env_set_hex(env, gd->ram_base + offset); + if (ret) + goto fail; + + return; + +fail: + pr_warn("\"%s\" environment variable was not set correctly\n", env); +} + +int board_late_init(void) +{ + puts("MODE: "); + + switch (uniphier_boot_device_raw()) { + case BOOT_DEVICE_MMC1: + printf("eMMC Boot"); + env_set("bootdev", "emmc"); + break; + case BOOT_DEVICE_MMC2: + printf("SD Boot"); + env_set("bootdev", "sd"); + break; + case BOOT_DEVICE_NAND: + printf("NAND Boot"); + env_set("bootdev", "nand"); + break; + case BOOT_DEVICE_NOR: + printf("NOR Boot"); + env_set("bootdev", "nor"); + break; + case BOOT_DEVICE_USB: + printf("USB Boot"); + env_set("bootdev", "usb"); + break; + default: + printf("Unknown"); + break; + } + + if (uniphier_have_internal_stm()) + printf(" (STM: %s)", + uniphier_boot_from_backend() ? "OFF" : "ON"); + + printf("\n"); + + uniphier_set_env_fdt_file(); + + uniphier_set_env_addr("dram_base", NULL); + + uniphier_set_env_addr("loadaddr", "loadaddr_offset"); + + uniphier_set_env_addr("kernel_addr_r", "kernel_addr_r_offset"); + uniphier_set_env_addr("ramdisk_addr_r", "ramdisk_addr_r_offset"); + uniphier_set_env_addr("fdt_addr_r", "fdt_addr_r_offset"); + + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/boards.c b/roms/u-boot/arch/arm/mach-uniphier/boards.c new file mode 100644 index 000000000..3e2ec9b26 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/boards.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <linux/libfdt.h> +#include <linux/kernel.h> +#include <asm/global_data.h> + +#include "init.h" + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_ARCH_UNIPHIER_LD4) +static const struct uniphier_board_data uniphier_ld4_data = { + .dram_freq = 1600, + .dram_ch[0] = { + .size = 0x10000000, + .width = 16, + }, + .dram_ch[1] = { + .size = 0x10000000, + .width = 16, + }, + .flags = UNIPHIER_BD_DDR3PLUS, +}; +#endif + +#if defined(CONFIG_ARCH_UNIPHIER_PRO4) +/* 1GB RAM board */ +static const struct uniphier_board_data uniphier_pro4_data = { + .dram_freq = 1600, + .dram_ch[0] = { + .size = 0x20000000, + .width = 32, + }, + .dram_ch[1] = { + .size = 0x20000000, + .width = 32, + }, +}; + +/* 2GB RAM board */ +static const struct uniphier_board_data uniphier_pro4_2g_data = { + .dram_freq = 1600, + .dram_ch[0] = { + .size = 0x40000000, + .width = 32, + }, + .dram_ch[1] = { + .size = 0x40000000, + .width = 32, + }, +}; +#endif + +#if defined(CONFIG_ARCH_UNIPHIER_SLD8) +static const struct uniphier_board_data uniphier_sld8_data = { + .dram_freq = 1333, + .dram_ch[0] = { + .size = 0x10000000, + .width = 16, + }, + .dram_ch[1] = { + .size = 0x10000000, + .width = 16, + }, + .flags = UNIPHIER_BD_DDR3PLUS, +}; +#endif + +#if defined(CONFIG_ARCH_UNIPHIER_PRO5) +static const struct uniphier_board_data uniphier_pro5_data = { + .dram_freq = 1866, + .dram_ch[0] = { + .size = 0x20000000, + .width = 32, + }, + .dram_ch[1] = { + .size = 0x20000000, + .width = 32, + }, +}; +#endif + +#if defined(CONFIG_ARCH_UNIPHIER_PXS2) +static const struct uniphier_board_data uniphier_pxs2_data = { + .dram_freq = 2133, + .dram_ch[0] = { + .size = 0x40000000, + .width = 32, + }, + .dram_ch[1] = { + .size = 0x20000000, + .width = 32, + }, + .dram_ch[2] = { + .size = 0x20000000, + .width = 16, + }, +}; +#endif + +#if defined(CONFIG_ARCH_UNIPHIER_LD6B) +static const struct uniphier_board_data uniphier_ld6b_data = { + .dram_freq = 1866, + .dram_ch[0] = { + .size = 0x40000000, + .width = 32, + }, + .dram_ch[1] = { + .size = 0x20000000, + .width = 32, + }, + .dram_ch[2] = { + .size = 0x20000000, + .width = 16, + }, +}; +#endif + +struct uniphier_board_id { + const char *compatible; + const struct uniphier_board_data *param; +}; + +static const struct uniphier_board_id uniphier_boards[] = { +#if defined(CONFIG_ARCH_UNIPHIER_LD4) + { "socionext,uniphier-ld4", &uniphier_ld4_data, }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PRO4) + { "socionext,uniphier-pro4-ace", &uniphier_pro4_2g_data, }, + { "socionext,uniphier-pro4-sanji", &uniphier_pro4_2g_data, }, + { "socionext,uniphier-pro4", &uniphier_pro4_data, }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_SLD8) + { "socionext,uniphier-sld8", &uniphier_sld8_data, }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PRO5) + { "socionext,uniphier-pro5", &uniphier_pro5_data, }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PXS2) + { "socionext,uniphier-pxs2", &uniphier_pxs2_data, }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_LD6B) + { "socionext,uniphier-ld6b", &uniphier_ld6b_data, }, +#endif +}; + +const struct uniphier_board_data *uniphier_get_board_param(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(uniphier_boards); i++) { + if (!fdt_node_check_compatible(gd->fdt_blob, 0, + uniphier_boards[i].compatible)) + return uniphier_boards[i].param; + } + + return NULL; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/boot-device/Makefile b/roms/u-boot/arch/arm/mach-uniphier/boot-device/Makefile new file mode 100644 index 000000000..97d54443c --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/boot-device/Makefile @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-y += boot-device.o + +obj-$(CONFIG_ARCH_UNIPHIER_LD4) += boot-device-ld4.o +obj-$(CONFIG_ARCH_UNIPHIER_PRO4) += boot-device-ld4.o +obj-$(CONFIG_ARCH_UNIPHIER_SLD8) += boot-device-ld4.o +obj-$(CONFIG_ARCH_UNIPHIER_PRO5) += boot-device-pro5.o +obj-$(CONFIG_ARCH_UNIPHIER_PXS2) += boot-device-pxs2.o +obj-$(CONFIG_ARCH_UNIPHIER_LD6B) += boot-device-pxs2.o +obj-$(CONFIG_ARCH_UNIPHIER_LD11) += boot-device-ld11.o +obj-$(CONFIG_ARCH_UNIPHIER_LD20) += boot-device-ld11.o +obj-$(CONFIG_ARCH_UNIPHIER_PXS3) += boot-device-pxs3.o diff --git a/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device-ld11.c b/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device-ld11.c new file mode 100644 index 000000000..4689ed79f --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device-ld11.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <spl.h> +#include <linux/io.h> +#include <linux/kernel.h> + +#include "boot-device.h" + +const struct uniphier_boot_device uniphier_ld11_boot_device_table[] = { + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 128KB, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 128KB, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 128KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 128KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 256KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 256KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, EraseSize 128KB, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, EraseSize 128KB, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, EraseSize 128KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, EraseSize 128KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, EraseSize 256KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, EraseSize 256KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, ONFI, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, ONFI, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, ONFI, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, ONFI, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, ONFI Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, ONFI Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, ONFI Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, ONFI Addr 5)"}, + {BOOT_DEVICE_MMC1, "eMMC (Legacy, 4bit, 1.8V, Training Off)"}, + {BOOT_DEVICE_MMC1, "eMMC (Legacy, 4bit, 1.8V, Training On)"}, + {BOOT_DEVICE_MMC1, "eMMC (Legacy, 8bit, 1.8V, Training Off)"}, + {BOOT_DEVICE_MMC1, "eMMC (Legacy, 8bit, 1.8V, Training On)"}, + {BOOT_DEVICE_MMC1, "eMMC (High Speed SDR, 8bit, 1.8V, Training Off)"}, + {BOOT_DEVICE_MMC1, "eMMC (High Speed SDR, 8bit, 1.8V, Training On)"}, + {BOOT_DEVICE_MMC1, "eMMC (Legacy, 4bit, 1.8V, Training Off)"}, + {BOOT_DEVICE_NOR, "NOR (XECS1)"}, +}; + +const unsigned uniphier_ld11_boot_device_count = + ARRAY_SIZE(uniphier_ld11_boot_device_table); + +int uniphier_ld11_boot_device_is_usb(u32 pinmon) +{ + return !!(~pinmon & 0x00000080); +} + +int uniphier_ld20_boot_device_is_usb(u32 pinmon) +{ + return !!(~pinmon & 0x00000780); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device-ld4.c b/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device-ld4.c new file mode 100644 index 000000000..c6aef18c1 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device-ld4.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014 Panasonic Corporation + * Copyright (C) 2015-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <spl.h> +#include <linux/io.h> +#include <linux/kernel.h> + +#include "boot-device.h" + +const struct uniphier_boot_device uniphier_ld4_boot_device_table[] = { + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 128KB, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 128KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 128KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 256KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 256KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 24, EraseSize 1MB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 4, ECC 24, EraseSize 1MB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, EraseSize 128KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, EraseSize 128KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, EraseSize 256KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, EraseSize 256KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 24, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, ONFI, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, ONFI, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, ONFI, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 24, ONFI, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 4, ECC 24, ONFI, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, ONFI, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, ONFI, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 24, ONFI, Addr 5)"}, + {BOOT_DEVICE_MMC1, "eMMC (3.3V)"}, + {BOOT_DEVICE_MMC1, "eMMC (1.8V)"}, + {BOOT_DEVICE_NONE, "Reserved"}, + {BOOT_DEVICE_NONE, "Reserved"}, + {BOOT_DEVICE_NONE, "Reserved"}, + {BOOT_DEVICE_NONE, "Reserved"}, + {BOOT_DEVICE_NONE, "Reserved"}, + {BOOT_DEVICE_NOR, "NOR (XECS0)"}, +}; + +const unsigned uniphier_ld4_boot_device_count = + ARRAY_SIZE(uniphier_ld4_boot_device_table); diff --git a/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device-pro5.c b/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device-pro5.c new file mode 100644 index 000000000..efd07a329 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device-pro5.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <spl.h> +#include <linux/io.h> +#include <linux/kernel.h> + +#include "boot-device.h" + +const struct uniphier_boot_device uniphier_pro5_boot_device_table[] = { + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, EraseSize 128KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, EraseSize 128KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, EraseSize 256KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, EraseSize 256KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, EraseSize 128KB, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, EraseSize 128MB, Addr 4)"}, + {BOOT_DEVICE_NONE, "Reserved"}, + {BOOT_DEVICE_NONE, "Reserved"}, + {BOOT_DEVICE_NONE, "Reserved"}, + {BOOT_DEVICE_NONE, "Reserved"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 512MB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 128KB, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 128KB, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, ONFI, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, ONFI, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, ONFI, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, ONFI, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, ONFI, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, ONFI, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, ONFI, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, ONFI, Addr 4)"}, + {BOOT_DEVICE_NONE, "Reserved"}, + {BOOT_DEVICE_MMC1, "eMMC (1.8V)"}, + {BOOT_DEVICE_NONE, "Reserved"}, + {BOOT_DEVICE_NONE, "Reserved"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 128MB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 128KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 256KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 256KB, Addr 5)"}, +}; + +const unsigned uniphier_pro5_boot_device_count = + ARRAY_SIZE(uniphier_pro5_boot_device_table); diff --git a/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device-pxs2.c b/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device-pxs2.c new file mode 100644 index 000000000..677470cdc --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device-pxs2.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <spl.h> +#include <linux/io.h> +#include <linux/kernel.h> + +#include "boot-device.h" + +const struct uniphier_boot_device uniphier_pxs2_boot_device_table[] = { + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 128KB, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 128KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 128KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 256KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 256KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 128KB, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, EraseSize 128KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, EraseSize 128KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, EraseSize 256KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, EraseSize 256KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, EraseSize 128KB, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, EraseSize 128KB, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, ONFI, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, ONFI, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, ONFI, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, ONFI, Addr 4)"}, + {BOOT_DEVICE_MMC1, "eMMC (1.8V)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, ONFI, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, ONFI, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 8, ONFI, Addr 4)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, ONFI, Addr 4)"}, + {BOOT_DEVICE_SPI, "SPI (3Byte CS0)"}, + {BOOT_DEVICE_SPI, "SPI (4Byte CS0)"}, + {BOOT_DEVICE_SPI, "SPI (3Byte CS1)"}, + {BOOT_DEVICE_SPI, "SPI (4Byte CS1)"}, + {BOOT_DEVICE_SPI, "SPI (4Byte CS0)"}, + {BOOT_DEVICE_SPI, "SPI (3Byte CS0)"}, + {BOOT_DEVICE_NONE, "Reserved"}, +}; + +const unsigned uniphier_pxs2_boot_device_count = + ARRAY_SIZE(uniphier_pxs2_boot_device_table); + +int uniphier_pxs2_boot_device_is_usb(u32 pinmon) +{ + return !!(pinmon & 0x00000040); +} + +unsigned int uniphier_pxs2_boot_device_fixup(unsigned int mode) +{ + if (mode == BOOT_DEVICE_USB) + return BOOT_DEVICE_NOR; + + return mode; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device-pxs3.c b/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device-pxs3.c new file mode 100644 index 000000000..688809931 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device-pxs3.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <spl.h> +#include <linux/bitops.h> +#include <linux/io.h> +#include <linux/kernel.h> + +#include "../sg-regs.h" +#include "boot-device.h" + +const struct uniphier_boot_device uniphier_pxs3_boot_device_table[] = { + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 128KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 128KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 256KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 256KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 512KB, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, ONFI, Addr 5)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, ONFI, Addr 5)"}, + {BOOT_DEVICE_MMC1, "eMMC (Legacy, 4bit, 1.8V, Training Off)"}, + {BOOT_DEVICE_MMC1, "eMMC (Legacy, 4bit, 1.8V, Training On)"}, + {BOOT_DEVICE_MMC1, "eMMC (Legacy, 8bit, 1.8V, Training Off)"}, + {BOOT_DEVICE_MMC1, "eMMC (Legacy, 8bit, 1.8V, Training On)"}, + {BOOT_DEVICE_MMC1, "eMMC (High Speed SDR, 8bit, 1.8V, Training Off)"}, + {BOOT_DEVICE_MMC1, "eMMC (High Speed SDR, 8bit, 1.8V, Training On)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 8, ONFI, Addr 5, BBM Last Page)"}, + {BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, ONFI, Addr 5, BBM Last Page)"}, +}; + +const unsigned uniphier_pxs3_boot_device_count = + ARRAY_SIZE(uniphier_pxs3_boot_device_table); + +int uniphier_pxs3_boot_device_is_usb(u32 pinmon) +{ + return !!(readl(sg_base + SG_PINMON2) & BIT(31)); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device.c b/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device.c new file mode 100644 index 000000000..98ff34cfa --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device.c @@ -0,0 +1,269 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <command.h> +#include <spl.h> +#include <stdio.h> +#include <linux/bitops.h> +#include <linux/bug.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/log2.h> + +#include "../init.h" +#include "../sg-regs.h" +#include "../soc-info.h" +#include "boot-device.h" + +#define SBBASE0 0x58c00100 +#define SBBASE_BANK_ENABLE BIT(0) + +static int uniphier_sbc_boot_is_swapped(void) +{ + return !(readl(SBBASE0) & SBBASE_BANK_ENABLE); +} + +struct uniphier_boot_device_info { + unsigned int soc_id; + unsigned int boot_device_sel_shift; + const struct uniphier_boot_device *boot_device_table; + const unsigned int *boot_device_count; + int (*boot_device_is_sd)(u32 pinmon); + int (*boot_device_is_usb)(u32 pinmon); + unsigned int (*boot_device_fixup)(unsigned int mode); + int (*boot_is_swapped)(void); + bool have_internal_stm; +}; + +static const struct uniphier_boot_device_info uniphier_boot_device_info[] = { +#if defined(CONFIG_ARCH_UNIPHIER_LD4) + { + .soc_id = UNIPHIER_LD4_ID, + .boot_device_sel_shift = 1, + .boot_device_table = uniphier_ld4_boot_device_table, + .boot_device_count = &uniphier_ld4_boot_device_count, + .boot_is_swapped = uniphier_sbc_boot_is_swapped, + .have_internal_stm = true, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PRO4) + { + .soc_id = UNIPHIER_PRO4_ID, + .boot_device_sel_shift = 1, + .boot_device_table = uniphier_ld4_boot_device_table, + .boot_device_count = &uniphier_ld4_boot_device_count, + .boot_is_swapped = uniphier_sbc_boot_is_swapped, + .have_internal_stm = false, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_SLD8) + { + .soc_id = UNIPHIER_SLD8_ID, + .boot_device_sel_shift = 1, + .boot_device_table = uniphier_ld4_boot_device_table, + .boot_device_count = &uniphier_ld4_boot_device_count, + .boot_is_swapped = uniphier_sbc_boot_is_swapped, + .have_internal_stm = true, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PRO5) + { + .soc_id = UNIPHIER_PRO5_ID, + .boot_device_sel_shift = 1, + .boot_device_table = uniphier_pro5_boot_device_table, + .boot_device_count = &uniphier_pro5_boot_device_count, + .boot_is_swapped = uniphier_sbc_boot_is_swapped, + .have_internal_stm = false, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PXS2) + { + .soc_id = UNIPHIER_PXS2_ID, + .boot_device_sel_shift = 1, + .boot_device_table = uniphier_pxs2_boot_device_table, + .boot_device_count = &uniphier_pxs2_boot_device_count, + .boot_device_is_usb = uniphier_pxs2_boot_device_is_usb, + .boot_device_fixup = uniphier_pxs2_boot_device_fixup, + .boot_is_swapped = uniphier_sbc_boot_is_swapped, + .have_internal_stm = false, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_LD6B) + { + .soc_id = UNIPHIER_LD6B_ID, + .boot_device_sel_shift = 1, + .boot_device_table = uniphier_pxs2_boot_device_table, + .boot_device_count = &uniphier_pxs2_boot_device_count, + .boot_device_is_usb = uniphier_pxs2_boot_device_is_usb, + .boot_device_fixup = uniphier_pxs2_boot_device_fixup, + .boot_is_swapped = uniphier_sbc_boot_is_swapped, + .have_internal_stm = true, /* STM on A-chip */ + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_LD11) + { + .soc_id = UNIPHIER_LD11_ID, + .boot_device_sel_shift = 1, + .boot_device_table = uniphier_ld11_boot_device_table, + .boot_device_count = &uniphier_ld11_boot_device_count, + .boot_device_is_usb = uniphier_ld11_boot_device_is_usb, + .boot_is_swapped = uniphier_sbc_boot_is_swapped, + .have_internal_stm = true, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_LD20) + { + .soc_id = UNIPHIER_LD20_ID, + .boot_device_sel_shift = 1, + .boot_device_table = uniphier_ld11_boot_device_table, + .boot_device_count = &uniphier_ld11_boot_device_count, + .boot_device_is_usb = uniphier_ld20_boot_device_is_usb, + .boot_is_swapped = uniphier_sbc_boot_is_swapped, + .have_internal_stm = true, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PXS3) + { + .soc_id = UNIPHIER_PXS3_ID, + .boot_device_sel_shift = 1, + .boot_device_table = uniphier_pxs3_boot_device_table, + .boot_device_count = &uniphier_pxs3_boot_device_count, + .boot_device_is_usb = uniphier_pxs3_boot_device_is_usb, + .boot_is_swapped = uniphier_sbc_boot_is_swapped, + .have_internal_stm = false, + }, +#endif +}; +UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_boot_device_info, + uniphier_boot_device_info) + +static unsigned int __uniphier_boot_device_raw( + const struct uniphier_boot_device_info *info) +{ + u32 pinmon; + unsigned int boot_sel; + + if (info->boot_is_swapped && info->boot_is_swapped()) + return BOOT_DEVICE_NOR; + + pinmon = readl(sg_base + SG_PINMON0); + + if (info->boot_device_is_sd && info->boot_device_is_sd(pinmon)) + return BOOT_DEVICE_MMC2; + + if (info->boot_device_is_usb && info->boot_device_is_usb(pinmon)) + return BOOT_DEVICE_USB; + + boot_sel = pinmon >> info->boot_device_sel_shift; + + BUG_ON(!is_power_of_2(*info->boot_device_count)); + boot_sel &= *info->boot_device_count - 1; + + return info->boot_device_table[boot_sel].boot_device; +} + +unsigned int uniphier_boot_device_raw(void) +{ + const struct uniphier_boot_device_info *info; + + info = uniphier_get_boot_device_info(); + if (!info) { + pr_err("unsupported SoC\n"); + return BOOT_DEVICE_NONE; + } + + return __uniphier_boot_device_raw(info); +} + +u32 spl_boot_device(void) +{ + const struct uniphier_boot_device_info *info; + u32 raw_mode; + + info = uniphier_get_boot_device_info(); + if (!info) { + pr_err("unsupported SoC\n"); + return BOOT_DEVICE_NONE; + } + + raw_mode = __uniphier_boot_device_raw(info); + + return info->boot_device_fixup ? + info->boot_device_fixup(raw_mode) : raw_mode; +} + +int uniphier_have_internal_stm(void) +{ + const struct uniphier_boot_device_info *info; + + info = uniphier_get_boot_device_info(); + if (!info) { + pr_err("unsupported SoC\n"); + return -ENOTSUPP; + } + + return info->have_internal_stm; +} + +int uniphier_boot_from_backend(void) +{ + return !!(readl(sg_base + SG_PINMON0) & BIT(27)); +} + +#ifndef CONFIG_SPL_BUILD + +static int do_pinmon(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + const struct uniphier_boot_device_info *info; + u32 pinmon; + unsigned int boot_device_count, boot_sel; + int i; + + info = uniphier_get_boot_device_info(); + if (!info) { + pr_err("unsupported SoC\n"); + return CMD_RET_FAILURE; + } + + if (uniphier_have_internal_stm()) + printf("STB Micon: %s\n", + uniphier_boot_from_backend() ? "OFF" : "ON"); + + if (info->boot_is_swapped) + printf("Boot Swap: %s\n", + info->boot_is_swapped() ? "ON" : "OFF"); + + pinmon = readl(sg_base + SG_PINMON0); + + if (info->boot_device_is_sd) + printf("SD Boot: %s\n", + info->boot_device_is_sd(pinmon) ? "ON" : "OFF"); + + if (info->boot_device_is_usb) + printf("USB Boot: %s\n", + info->boot_device_is_usb(pinmon) ? "ON" : "OFF"); + + boot_device_count = *info->boot_device_count; + + boot_sel = pinmon >> info->boot_device_sel_shift; + boot_sel &= boot_device_count - 1; + + printf("\nBoot Mode Sel:\n"); + for (i = 0; i < boot_device_count; i++) + printf(" %c %02x %s\n", i == boot_sel ? '*' : ' ', i, + info->boot_device_table[i].desc); + + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD( + pinmon, 1, 1, do_pinmon, + "pin monitor", + "" +); + +#endif /* !CONFIG_SPL_BUILD */ diff --git a/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device.h b/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device.h new file mode 100644 index 000000000..bbb634316 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/boot-device/boot-device.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#ifndef _UNIPHIER_BOOT_DEVICE_H_ +#define _UNIPHIER_BOOT_DEVICE_H_ + +struct uniphier_boot_device { + unsigned int boot_device; + const char *desc; +}; + +extern const struct uniphier_boot_device uniphier_ld4_boot_device_table[]; +extern const struct uniphier_boot_device uniphier_pro5_boot_device_table[]; +extern const struct uniphier_boot_device uniphier_pxs2_boot_device_table[]; +extern const struct uniphier_boot_device uniphier_ld11_boot_device_table[]; +extern const struct uniphier_boot_device uniphier_pxs3_boot_device_table[]; + +extern const unsigned int uniphier_ld4_boot_device_count; +extern const unsigned int uniphier_pro5_boot_device_count; +extern const unsigned int uniphier_pxs2_boot_device_count; +extern const unsigned int uniphier_ld11_boot_device_count; +extern const unsigned int uniphier_pxs3_boot_device_count; + +int uniphier_pxs2_boot_device_is_usb(u32 pinmon); +int uniphier_ld11_boot_device_is_usb(u32 pinmon); +int uniphier_ld20_boot_device_is_usb(u32 pinmon); +int uniphier_pxs3_boot_device_is_usb(u32 pinmon); + +unsigned int uniphier_pxs2_boot_device_fixup(unsigned int mode); + +#endif /* _UNIPHIER_BOOT_DEVICE_H_ */ diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/Makefile b/roms/u-boot/arch/arm/mach-uniphier/clk/Makefile new file mode 100644 index 000000000..c49e44754 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/Makefile @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0+ + +ifdef CONFIG_SPL_BUILD + +obj-$(CONFIG_ARCH_UNIPHIER_LD4) += clk-early-ld4.o clk-dram-ld4.o dpll-ld4.o +obj-$(CONFIG_ARCH_UNIPHIER_PRO4) += clk-early-ld4.o clk-dram-ld4.o dpll-pro4.o +obj-$(CONFIG_ARCH_UNIPHIER_SLD8) += clk-early-ld4.o clk-dram-ld4.o dpll-sld8.o +obj-$(CONFIG_ARCH_UNIPHIER_PRO5) += clk-early-ld4.o clk-dram-pro5.o dpll-pro5.o +obj-$(CONFIG_ARCH_UNIPHIER_PXS2) += clk-early-ld4.o clk-dram-pxs2.o dpll-pxs2.o +obj-$(CONFIG_ARCH_UNIPHIER_LD6B) += clk-early-ld4.o clk-dram-pxs2.o dpll-pxs2.o + +else + +obj-$(CONFIG_ARCH_UNIPHIER_LD4) += pll-ld4.o dpll-tail.o +obj-$(CONFIG_ARCH_UNIPHIER_PRO4) += clk-pro4.o pll-pro4.o dpll-tail.o +obj-$(CONFIG_ARCH_UNIPHIER_SLD8) += pll-ld4.o dpll-tail.o +obj-$(CONFIG_ARCH_UNIPHIER_PRO5) += clk-pro5.o +obj-$(CONFIG_ARCH_UNIPHIER_PXS2) += clk-pxs2.o +obj-$(CONFIG_ARCH_UNIPHIER_LD6B) += clk-pxs2.o +obj-$(CONFIG_ARCH_UNIPHIER_LD11) += clk-ld11.o pll-base-ld20.o pll-ld11.o +obj-$(CONFIG_ARCH_UNIPHIER_LD20) += clk-ld20.o pll-base-ld20.o pll-ld20.o +obj-$(CONFIG_ARCH_UNIPHIER_PXS3) += clk-pxs3.o pll-base-ld20.o pll-pxs3.o + +endif diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/clk-dram-ld4.c b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-dram-ld4.c new file mode 100644 index 000000000..3b721eaf2 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-dram-ld4.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011-2014 Panasonic Corporation + * Copyright (C) 2015-2017 Socionext Inc. + */ + +#include <spl.h> +#include <linux/io.h> + +#include "../init.h" +#include "../sc-regs.h" + +void uniphier_ld4_dram_clk_init(void) +{ + u32 tmp; + + /* deassert reset */ + tmp = readl(sc_base + SC_RSTCTRL); + tmp |= SC_RSTCTRL_NRST_UMC1 | SC_RSTCTRL_NRST_UMC0; + writel(tmp, sc_base + SC_RSTCTRL); + readl(sc_base + SC_RSTCTRL); /* dummy read */ + + /* provide clocks */ + tmp = readl(sc_base + SC_CLKCTRL); + tmp |= SC_CLKCTRL_CEN_UMC; + writel(tmp, sc_base + SC_CLKCTRL); + readl(sc_base + SC_CLKCTRL); /* dummy read */ +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/clk-dram-pro5.c b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-dram-pro5.c new file mode 100644 index 000000000..808d1ebfe --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-dram-pro5.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015-2017 Socionext Inc. + */ + +#include <linux/io.h> + +#include "../init.h" +#include "../sc-regs.h" + +void uniphier_pro5_dram_clk_init(void) +{ + u32 tmp; + + /* + * deassert reset + * UMCA2: Ch1 (DDR3) + * UMCA1, UMC31: Ch0 (WIO1) + * UMCA0, UMC30: Ch0 (WIO0) + */ + tmp = readl(sc_base + SC_RSTCTRL4); + tmp |= SC_RSTCTRL4_NRST_UMCSB | SC_RSTCTRL4_NRST_UMCA2 | + SC_RSTCTRL4_NRST_UMCA1 | SC_RSTCTRL4_NRST_UMCA0 | + SC_RSTCTRL4_NRST_UMC31 | SC_RSTCTRL4_NRST_UMC30; + writel(tmp, sc_base + SC_RSTCTRL4); + readl(sc_base + SC_RSTCTRL4); /* dummy read */ + + /* provide clocks */ + tmp = readl(sc_base + SC_CLKCTRL4); + tmp |= SC_CLKCTRL4_CEN_UMCSB | SC_CLKCTRL4_CEN_UMC1 | + SC_CLKCTRL4_CEN_UMC0; + writel(tmp, sc_base + SC_CLKCTRL4); + readl(sc_base + SC_CLKCTRL4); /* dummy read */ +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/clk-dram-pxs2.c b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-dram-pxs2.c new file mode 100644 index 000000000..75d3e70d6 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-dram-pxs2.c @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016-2017 Socionext Inc. + */ + +#include <spl.h> +#include <linux/io.h> + +#include "../init.h" +#include "../sc-regs.h" + +void uniphier_pxs2_dram_clk_init(void) +{ + u32 tmp; + + /* deassert reset */ + tmp = readl(sc_base + SC_RSTCTRL4); + tmp |= SC_RSTCTRL4_NRST_UMCSB | SC_RSTCTRL4_NRST_UMCA2 | + SC_RSTCTRL4_NRST_UMCA1 | SC_RSTCTRL4_NRST_UMCA0 | + SC_RSTCTRL4_NRST_UMC32 | SC_RSTCTRL4_NRST_UMC31 | + SC_RSTCTRL4_NRST_UMC30; + writel(tmp, sc_base + SC_RSTCTRL4); + readl(sc_base + SC_RSTCTRL4); /* dummy read */ + + /* provide clocks */ + tmp = readl(sc_base + SC_CLKCTRL4); + tmp |= SC_CLKCTRL4_CEN_UMCSB | SC_CLKCTRL4_CEN_UMC2 | + SC_CLKCTRL4_CEN_UMC1 | SC_CLKCTRL4_CEN_UMC0; + writel(tmp, sc_base + SC_CLKCTRL4); + readl(sc_base + SC_CLKCTRL4); /* dummy read */ +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/clk-early-ld4.c b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-early-ld4.c new file mode 100644 index 000000000..25b72d892 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-early-ld4.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011-2014 Panasonic Corporation + * Copyright (C) 2015-2017 Socionext Inc. + */ + +#include <spl.h> +#include <linux/io.h> + +#include "../init.h" +#include "../sc-regs.h" + +void uniphier_ld4_early_clk_init(void) +{ + u32 tmp; + + /* provide clocks */ + tmp = readl(sc_base + SC_CLKCTRL); + tmp |= SC_CLKCTRL_CEN_SBC | SC_CLKCTRL_CEN_PERI; + writel(tmp, sc_base + SC_CLKCTRL); + readl(sc_base + SC_CLKCTRL); /* dummy read */ +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/clk-ld11.c b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-ld11.c new file mode 100644 index 000000000..d241a6538 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-ld11.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Socionext Inc. + */ + +#include <spl.h> +#include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/io.h> + +#include "../init.h" +#include "../sc64-regs.h" +#include "../sg-regs.h" + +#define SDCTRL_EMMC_HW_RESET 0x59810280 + +void uniphier_ld11_clk_init(void) +{ + /* if booted from a device other than USB, without stand-by MPU */ + if ((readl(sg_base + SG_PINMON0) & BIT(27)) && + uniphier_boot_device_raw() != BOOT_DEVICE_USB) { + writel(1, sg_base + SG_ETPHYPSHUT); + writel(1, sg_base + SG_ETPHYCNT); + + udelay(1); /* wait for regulator level 1.1V -> 2.5V */ + + writel(3, sg_base + SG_ETPHYCNT); + writel(3, sg_base + SG_ETPHYPSHUT); + writel(7, sg_base + SG_ETPHYCNT); + } + + /* TODO: use "mmc-pwrseq-emmc" */ + writel(1, SDCTRL_EMMC_HW_RESET); + +#ifdef CONFIG_USB_EHCI_HCD + { + int ch; + + for (ch = 0; ch < 3; ch++) { + void __iomem *phyctrl = sg_base + SG_USBPHYCTRL; + + writel(0x82280600, phyctrl + 8 * ch); + writel(0x00000106, phyctrl + 8 * ch + 4); + } + } +#endif +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/clk-ld20.c b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-ld20.c new file mode 100644 index 000000000..397b2d738 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-ld20.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Socionext Inc. + */ + +#include <linux/bitops.h> +#include <linux/io.h> + +#include "../init.h" +#include "../sc64-regs.h" + +#define SDCTRL_EMMC_HW_RESET 0x59810280 + +void uniphier_ld20_clk_init(void) +{ + u32 tmp; + + tmp = readl(sc_base + SC_RSTCTRL6); + tmp |= BIT(8); /* Mali */ + writel(tmp, sc_base + SC_RSTCTRL6); + + tmp = readl(sc_base + SC_CLKCTRL6); + tmp |= BIT(8); /* Mali */ + writel(tmp, sc_base + SC_CLKCTRL6); + + /* TODO: use "mmc-pwrseq-emmc" */ + writel(1, SDCTRL_EMMC_HW_RESET); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/clk-pro4.c b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-pro4.c new file mode 100644 index 000000000..798128b30 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-pro4.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011-2015 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <linux/io.h> + +#include "../init.h" +#include "../sc-regs.h" + +void uniphier_pro4_clk_init(void) +{ +#ifdef CONFIG_USB_DWC3_UNIPHIER + u32 tmp; + + /* deassert reset */ + tmp = readl(sc_base + SC_RSTCTRL); + tmp |= SC_RSTCTRL_NRST_USB3B0 | SC_RSTCTRL_NRST_USB3C0 | + SC_RSTCTRL_NRST_GIO; + writel(tmp, sc_base + SC_RSTCTRL); + readl(sc_base + SC_RSTCTRL); /* dummy read */ + + tmp = readl(sc_base + SC_RSTCTRL2); + tmp |= SC_RSTCTRL2_NRST_USB3B1 | SC_RSTCTRL2_NRST_USB3C1; + writel(tmp, sc_base + SC_RSTCTRL2); + readl(sc_base + SC_RSTCTRL2); /* dummy read */ + + /* provide clocks */ + tmp = readl(sc_base + SC_CLKCTRL); + tmp |= SC_CLKCTRL_CEN_USB31 | SC_CLKCTRL_CEN_USB30 | + SC_CLKCTRL_CEN_GIO; + writel(tmp, sc_base + SC_CLKCTRL); + readl(sc_base + SC_CLKCTRL); /* dummy read */ +#endif +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/clk-pro5.c b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-pro5.c new file mode 100644 index 000000000..36006fd25 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-pro5.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <linux/io.h> + +#include "../init.h" +#include "../sc-regs.h" + +void uniphier_pro5_clk_init(void) +{ +#ifdef CONFIG_USB_DWC3_UNIPHIER + u32 tmp; + + /* deassert reset */ + tmp = readl(sc_base + SC_RSTCTRL); + tmp |= SC_RSTCTRL_NRST_USB3B0 | SC_RSTCTRL_NRST_GIO; + writel(tmp, sc_base + SC_RSTCTRL); + readl(sc_base + SC_RSTCTRL); /* dummy read */ + + tmp = readl(sc_base + SC_RSTCTRL2); + tmp |= SC_RSTCTRL2_NRST_USB3B1; + writel(tmp, sc_base + SC_RSTCTRL2); + readl(sc_base + SC_RSTCTRL2); /* dummy read */ + + /* provide clocks */ + tmp = readl(sc_base + SC_CLKCTRL); + tmp |= SC_CLKCTRL_CEN_USB31 | SC_CLKCTRL_CEN_USB30 | + SC_CLKCTRL_CEN_GIO; + writel(tmp, sc_base + SC_CLKCTRL); + readl(sc_base + SC_CLKCTRL); /* dummy read */ +#endif +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/clk-pxs2.c b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-pxs2.c new file mode 100644 index 000000000..c2a75ce00 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-pxs2.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <linux/bitops.h> +#include <linux/io.h> + +#include "../init.h" +#include "../sc-regs.h" + +void uniphier_pxs2_clk_init(void) +{ +#ifdef CONFIG_USB_DWC3_UNIPHIER + u32 tmp; + + /* deassert reset */ + tmp = readl(sc_base + SC_RSTCTRL); + tmp |= SC_RSTCTRL_NRST_USB3B0 | SC_RSTCTRL_NRST_GIO; + writel(tmp, sc_base + SC_RSTCTRL); + readl(sc_base + SC_RSTCTRL); /* dummy read */ + + tmp = readl(sc_base + SC_RSTCTRL2); + tmp |= SC_RSTCTRL2_NRST_USB3B1; + writel(tmp, sc_base + SC_RSTCTRL2); + readl(sc_base + SC_RSTCTRL2); /* dummy read */ + + tmp = readl(sc_base + SC_RSTCTRL6); + tmp |= 0x37; + writel(tmp, sc_base + SC_RSTCTRL6); + + /* provide clocks */ + tmp = readl(sc_base + SC_CLKCTRL); + tmp |= BIT(20) | BIT(19) | SC_CLKCTRL_CEN_USB31 | SC_CLKCTRL_CEN_USB30 | + SC_CLKCTRL_CEN_GIO; + writel(tmp, sc_base + SC_CLKCTRL); + readl(sc_base + SC_CLKCTRL); /* dummy read */ +#endif +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/clk-pxs3.c b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-pxs3.c new file mode 100644 index 000000000..33b9c5b73 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/clk-pxs3.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Socionext Inc. + */ + +#include <linux/bitops.h> +#include <linux/io.h> + +#include "../init.h" +#include "../sc64-regs.h" + +#define SDCTRL_EMMC_HW_RESET 0x59810280 + +void uniphier_pxs3_clk_init(void) +{ + u32 tmp; + + tmp = readl(sc_base + SC_RSTCTRL6); + tmp |= BIT(8); /* Mali */ + writel(tmp, sc_base + SC_RSTCTRL6); + + tmp = readl(sc_base + SC_CLKCTRL6); + tmp |= BIT(8); /* Mali */ + writel(tmp, sc_base + SC_CLKCTRL6); + + /* TODO: use "mmc-pwrseq-emmc" */ + writel(1, SDCTRL_EMMC_HW_RESET); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-ld4.c b/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-ld4.c new file mode 100644 index 000000000..3ccaf0224 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-ld4.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013-2014 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + */ + +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/io.h> + +#include "../init.h" +#include "../sc-regs.h" + +#undef DPLL_SSC_RATE_1PER + +int uniphier_ld4_dpll_init(const struct uniphier_board_data *bd) +{ + unsigned int dram_freq = bd->dram_freq; + u32 tmp; + + /* + * Set Frequency + * Set 0xc(1600MHz)/0xd(1333MHz)/0xe(1066MHz) + * to FOUT (DPLLCTRL.bit[29:20]) + */ + tmp = readl(sc_base + SC_DPLLCTRL); + tmp &= ~0x000f0000; + switch (dram_freq) { + case 1333: + tmp |= 0x000d0000; + break; + case 1600: + tmp |= 0x000c0000; + break; + default: + pr_err("Unsupported frequency"); + return -EINVAL; + } + +#if defined(DPLL_SSC_RATE_1PER) + tmp &= ~SC_DPLLCTRL_SSC_RATE; +#else + tmp |= SC_DPLLCTRL_SSC_RATE; +#endif + writel(tmp, sc_base + SC_DPLLCTRL); + + tmp = readl(sc_base + SC_DPLLCTRL2); + tmp |= SC_DPLLCTRL2_NRSTDS; + writel(tmp, sc_base + SC_DPLLCTRL2); + + /* Wait 500 usec until dpll gets stable */ + udelay(500); + + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-pro4.c b/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-pro4.c new file mode 100644 index 000000000..44006ae6d --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-pro4.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013-2014 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + */ + +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/io.h> + +#include "../init.h" +#include "../sc-regs.h" + +#undef DPLL_SSC_RATE_1PER + +int uniphier_pro4_dpll_init(const struct uniphier_board_data *bd) +{ + unsigned int dram_freq = bd->dram_freq; + u32 tmp; + + /* + * Set Frequency + * Set 0xc(1600MHz)/0xd(1333MHz)/0xe(1066MHz) + * to FOUT ( DPLLCTRL.bit[29:20] ) + */ + tmp = readl(sc_base + SC_DPLLCTRL); + tmp &= ~(0x000f0000); + switch (dram_freq) { + case 1333: + tmp |= 0x000d0000; + break; + case 1600: + tmp |= 0x000c0000; + break; + default: + pr_err("Unsupported frequency"); + return -EINVAL; + } + + /* + * Set Moduration rate + * Set 0x0(1%)/0x1(2%) to SSC_RATE(DPLLCTRL.bit[15]) + */ +#if defined(DPLL_SSC_RATE_1PER) + tmp &= ~0x00008000; +#else + tmp |= 0x00008000; +#endif + writel(tmp, sc_base + SC_DPLLCTRL); + + tmp = readl(sc_base + SC_DPLLCTRL2); + tmp |= SC_DPLLCTRL2_NRSTDS; + writel(tmp, sc_base + SC_DPLLCTRL2); + + /* Wait until dpll gets stable */ + udelay(500); + + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-pro5.c b/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-pro5.c new file mode 100644 index 000000000..d3a42c7b4 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-pro5.c @@ -0,0 +1,6 @@ +#include "../init.h" + +int uniphier_pro5_dpll_init(const struct uniphier_board_data *bd) +{ + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-pxs2.c b/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-pxs2.c new file mode 100644 index 000000000..328ebf61f --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-pxs2.c @@ -0,0 +1,6 @@ +#include "../init.h" + +int uniphier_pxs2_dpll_init(const struct uniphier_board_data *bd) +{ + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-sld8.c b/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-sld8.c new file mode 100644 index 000000000..1ac52d11f --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-sld8.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013-2014 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + */ + +#include <linux/delay.h> +#include <linux/io.h> + +#include "../init.h" +#include "../sc-regs.h" + +int uniphier_sld8_dpll_init(const struct uniphier_board_data *bd) +{ + u32 tmp; + /* + * Set DPLL SSC parameters for DPLLCTRL3 + * [23] DIVN_TEST 0x1 + * [22:16] DIVN 0x50 + * [10] FREFSEL_TEST 0x1 + * [9:8] FREFSEL 0x2 + * [4] ICPD_TEST 0x1 + * [3:0] ICPD 0xb + */ + tmp = readl(sc_base + SC_DPLLCTRL3); + tmp &= ~0x00ff0717; + tmp |= 0x00d0061b; + writel(tmp, sc_base + SC_DPLLCTRL3); + + /* + * Set DPLL SSC parameters for DPLLCTRL + * <-1%> <-2%> + * [29:20] SSC_UPCNT 132 (0x084) 132 (0x084) + * [14:0] SSC_dK 6335(0x18bf) 12710(0x31a6) + */ + tmp = readl(sc_base + SC_DPLLCTRL); + tmp &= ~0x3ff07fff; +#ifdef DPLL_SSC_RATE_1PER + tmp |= 0x084018bf; +#else + tmp |= 0x084031a6; +#endif + writel(tmp, sc_base + SC_DPLLCTRL); + + /* + * Set DPLL SSC parameters for DPLLCTRL2 + * [31:29] SSC_STEP 0 + * [27] SSC_REG_REF 1 + * [26:20] SSC_M 79 (0x4f) + * [19:0] SSC_K 964689 (0xeb851) + */ + tmp = readl(sc_base + SC_DPLLCTRL2); + tmp &= ~0xefffffff; + tmp |= 0x0cfeb851; + writel(tmp, sc_base + SC_DPLLCTRL2); + + /* Wait 500 usec until dpll gets stable */ + udelay(500); + + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-tail.c b/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-tail.c new file mode 100644 index 000000000..6ba5a3672 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/dpll-tail.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011-2014 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <linux/io.h> + +#include "../sc-regs.h" +#include "pll.h" + +void uniphier_ld4_dpll_ssc_en(void) +{ + u32 tmp; + + tmp = readl(sc_base + SC_DPLLCTRL); + tmp |= SC_DPLLCTRL_SSC_EN; + writel(tmp, sc_base + SC_DPLLCTRL); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/pll-base-ld20.c b/roms/u-boot/arch/arm/mach-uniphier/clk/pll-base-ld20.c new file mode 100644 index 000000000..ea96d739c --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/pll-base-ld20.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <linux/bitfield.h> +#include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/sizes.h> + +#include "../sc64-regs.h" +#include "pll.h" + +/* PLL type: SSC */ +#define SC_PLLCTRL_SSC_DK_MASK GENMASK(14, 0) +#define SC_PLLCTRL_SSC_EN BIT(31) +#define SC_PLLCTRL2_NRSTDS BIT(28) +#define SC_PLLCTRL2_SSC_JK_MASK GENMASK(26, 0) +#define SC_PLLCTRL3_REGI_MASK GENMASK(19, 16) + +/* PLL type: VPLL27 */ +#define SC_VPLL27CTRL_WP BIT(0) +#define SC_VPLL27CTRL3_K_LD BIT(28) + +/* PLL type: DSPLL */ +#define SC_DSPLLCTRL2_K_LD BIT(28) + +int uniphier_ld20_sscpll_init(unsigned long reg_base, unsigned int freq, + unsigned int ssc_rate, unsigned int divn) +{ + void __iomem *base = sc_base + reg_base; + u32 tmp; + + if (freq != UNIPHIER_PLL_FREQ_DEFAULT) { + tmp = readl(base); /* SSCPLLCTRL */ + tmp &= ~SC_PLLCTRL_SSC_DK_MASK; + tmp |= FIELD_PREP(SC_PLLCTRL_SSC_DK_MASK, + DIV_ROUND_CLOSEST(487UL * freq * ssc_rate, + divn * 512)); + writel(tmp, base); + + tmp = readl(base + 4); + tmp &= ~SC_PLLCTRL2_SSC_JK_MASK; + tmp |= FIELD_PREP(SC_PLLCTRL2_SSC_JK_MASK, + DIV_ROUND_CLOSEST(21431887UL * freq, + divn * 512)); + writel(tmp, base + 4); + + udelay(50); + } + + tmp = readl(base + 4); /* SSCPLLCTRL2 */ + tmp |= SC_PLLCTRL2_NRSTDS; + writel(tmp, base + 4); + + return 0; +} + +int uniphier_ld20_sscpll_ssc_en(unsigned long reg_base) +{ + void __iomem *base = sc_base + reg_base; + u32 tmp; + + tmp = readl(base); /* SSCPLLCTRL */ + tmp |= SC_PLLCTRL_SSC_EN; + writel(tmp, base); + + return 0; +} + +int uniphier_ld20_sscpll_set_regi(unsigned long reg_base, unsigned regi) +{ + void __iomem *base = sc_base + reg_base; + u32 tmp; + + tmp = readl(base + 8); /* SSCPLLCTRL3 */ + tmp &= ~SC_PLLCTRL3_REGI_MASK; + tmp |= FIELD_PREP(SC_PLLCTRL3_REGI_MASK, regi); + writel(tmp, base + 8); + + return 0; +} + +int uniphier_ld20_vpll27_init(unsigned long reg_base) +{ + void __iomem *base = sc_base + reg_base; + u32 tmp; + + tmp = readl(base); /* VPLL27CTRL */ + tmp |= SC_VPLL27CTRL_WP; /* write protect off */ + writel(tmp, base); + + tmp = readl(base + 8); /* VPLL27CTRL3 */ + tmp |= SC_VPLL27CTRL3_K_LD; + writel(tmp, base + 8); + + tmp = readl(base); /* VPLL27CTRL */ + tmp &= ~SC_VPLL27CTRL_WP; /* write protect on */ + writel(tmp, base); + + return 0; +} + +int uniphier_ld20_dspll_init(unsigned long reg_base) +{ + void __iomem *base = sc_base + reg_base; + u32 tmp; + + tmp = readl(base + 4); /* DSPLLCTRL2 */ + tmp |= SC_DSPLLCTRL2_K_LD; + writel(tmp, base + 4); + + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/pll-ld11.c b/roms/u-boot/arch/arm/mach-uniphier/clk/pll-ld11.c new file mode 100644 index 000000000..7f07e3e92 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/pll-ld11.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Socionext Inc. + */ + +#include <linux/delay.h> +#include <linux/io.h> + +#include "../init.h" +#include "../sc64-regs.h" +#include "pll.h" + +/* PLL type: SSC */ +#define SC_CPLLCTRL 0x1400 /* CPU/ARM */ +#define SC_SPLLCTRL 0x1410 /* misc */ +#define SC_MPLLCTRL 0x1430 /* DSP */ +#define SC_VSPLLCTRL 0x1440 /* Video codec, VPE etc. */ +#define SC_DPLLCTRL 0x1460 /* DDR memory */ + +/* PLL type: VPLL27 */ +#define SC_VPLL27FCTRL 0x1500 +#define SC_VPLL27ACTRL 0x1520 + +void uniphier_ld11_pll_init(void) +{ + uniphier_ld20_sscpll_init(SC_CPLLCTRL, 1960, 1, 2); /* 2000MHz -> 1960MHz */ + /* do nothing for SPLL */ + uniphier_ld20_sscpll_init(SC_MPLLCTRL, 1600, 1, 2); /* 1500MHz -> 1600MHz */ + uniphier_ld20_sscpll_init(SC_VSPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 2); + + uniphier_ld20_sscpll_set_regi(SC_MPLLCTRL, 5); + + mdelay(1); + + uniphier_ld20_sscpll_ssc_en(SC_CPLLCTRL); + uniphier_ld20_sscpll_ssc_en(SC_MPLLCTRL); + uniphier_ld20_sscpll_ssc_en(SC_VSPLLCTRL); + uniphier_ld20_sscpll_ssc_en(SC_DPLLCTRL); + + uniphier_ld20_vpll27_init(SC_VPLL27FCTRL); + uniphier_ld20_vpll27_init(SC_VPLL27ACTRL); + + writel(0, sc_base + SC_CA53_GEARSET); /* Gear0: CPLL/2 */ + writel(SC_CA_GEARUPD, sc_base + SC_CA53_GEARUPD); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/pll-ld20.c b/roms/u-boot/arch/arm/mach-uniphier/clk/pll-ld20.c new file mode 100644 index 000000000..04b3312a2 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/pll-ld20.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <linux/delay.h> + +#include "../init.h" +#include "../sc64-regs.h" +#include "pll.h" + +/* PLL type: SSC */ +#define SC_CPLLCTRL 0x1400 /* CPU/ARM */ +#define SC_SPLLCTRL 0x1410 /* misc */ +#define SC_SPLL2CTRL 0x1420 /* DSP */ +#define SC_MPLLCTRL 0x1430 /* Video codec */ +#define SC_VPPLLCTRL 0x1440 /* VPE etc. */ +#define SC_GPPLLCTRL 0x1450 /* GPU/Mali */ +#define SC_DPLL0CTRL 0x1460 /* DDR memory 0 */ +#define SC_DPLL1CTRL 0x1470 /* DDR memory 1 */ +#define SC_DPLL2CTRL 0x1480 /* DDR memory 2 */ + +/* PLL type: VPLL27 */ +#define SC_VPLL27FCTRL 0x1500 +#define SC_VPLL27ACTRL 0x1520 + +/* PLL type: DSPLL */ +#define SC_VPLL8KCTRL 0x1540 +#define SC_A2PLLCTRL 0x15C0 + +void uniphier_ld20_pll_init(void) +{ + uniphier_ld20_sscpll_init(SC_CPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 4); + /* do nothing for SPLL */ + uniphier_ld20_sscpll_init(SC_SPLL2CTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 4); + uniphier_ld20_sscpll_init(SC_MPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 2); + uniphier_ld20_sscpll_init(SC_VPPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 4); + uniphier_ld20_sscpll_init(SC_GPPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 2); + + mdelay(1); + + uniphier_ld20_sscpll_ssc_en(SC_CPLLCTRL); + uniphier_ld20_sscpll_ssc_en(SC_SPLL2CTRL); + uniphier_ld20_sscpll_ssc_en(SC_MPLLCTRL); + uniphier_ld20_sscpll_ssc_en(SC_VPPLLCTRL); + uniphier_ld20_sscpll_ssc_en(SC_GPPLLCTRL); + uniphier_ld20_sscpll_ssc_en(SC_DPLL0CTRL); + uniphier_ld20_sscpll_ssc_en(SC_DPLL1CTRL); + uniphier_ld20_sscpll_ssc_en(SC_DPLL2CTRL); + + uniphier_ld20_vpll27_init(SC_VPLL27FCTRL); + uniphier_ld20_vpll27_init(SC_VPLL27ACTRL); + + uniphier_ld20_dspll_init(SC_VPLL8KCTRL); + uniphier_ld20_dspll_init(SC_A2PLLCTRL); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/pll-ld4.c b/roms/u-boot/arch/arm/mach-uniphier/clk/pll-ld4.c new file mode 100644 index 000000000..c66031bdd --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/pll-ld4.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013-2014 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + */ + +#include <linux/delay.h> +#include <linux/io.h> + +#include "../init.h" +#include "../sc-regs.h" +#include "../sg-regs.h" +#include "pll.h" + +static void upll_init(void) +{ + u32 tmp, clk_mode_upll, clk_mode_axosel; + + tmp = readl(sg_base + SG_PINMON0); + clk_mode_upll = tmp & SG_PINMON0_CLK_MODE_UPLLSRC_MASK; + clk_mode_axosel = tmp & SG_PINMON0_CLK_MODE_AXOSEL_MASK; + + /* set 0 to SNRT(UPLLCTRL.bit28) and K_LD(UPLLCTRL.bit[27]) */ + tmp = readl(sc_base + SC_UPLLCTRL); + tmp &= ~0x18000000; + writel(tmp, sc_base + SC_UPLLCTRL); + + if (clk_mode_upll == SG_PINMON0_CLK_MODE_UPLLSRC_DEFAULT) { + if (clk_mode_axosel == SG_PINMON0_CLK_MODE_AXOSEL_25000KHZ_U || + clk_mode_axosel == SG_PINMON0_CLK_MODE_AXOSEL_25000KHZ_A) { + /* AXO: 25MHz */ + tmp &= ~0x07ffffff; + tmp |= 0x0228f5c0; + } else { + /* AXO: default 24.576MHz */ + tmp &= ~0x07ffffff; + tmp |= 0x02328000; + } + } + + writel(tmp, sc_base + SC_UPLLCTRL); + + /* set 1 to K_LD(UPLLCTRL.bit[27]) */ + tmp |= 0x08000000; + writel(tmp, sc_base + SC_UPLLCTRL); + + /* wait 10 usec */ + udelay(10); + + /* set 1 to SNRT(UPLLCTRL.bit[28]) */ + tmp |= 0x10000000; + writel(tmp, sc_base + SC_UPLLCTRL); +} + +static void vpll_init(void) +{ + u32 tmp, clk_mode_axosel; + + tmp = readl(sg_base + SG_PINMON0); + clk_mode_axosel = tmp & SG_PINMON0_CLK_MODE_AXOSEL_MASK; + + /* set 1 to VPLA27WP and VPLA27WP */ + tmp = readl(sc_base + SC_VPLL27ACTRL); + tmp |= 0x00000001; + writel(tmp, sc_base + SC_VPLL27ACTRL); + tmp = readl(sc_base + SC_VPLL27BCTRL); + tmp |= 0x00000001; + writel(tmp, sc_base + SC_VPLL27BCTRL); + + /* Set 0 to VPLA_K_LD and VPLB_K_LD */ + tmp = readl(sc_base + SC_VPLL27ACTRL3); + tmp &= ~0x10000000; + writel(tmp, sc_base + SC_VPLL27ACTRL3); + tmp = readl(sc_base + SC_VPLL27BCTRL3); + tmp &= ~0x10000000; + writel(tmp, sc_base + SC_VPLL27BCTRL3); + + /* Set 0 to VPLA_SNRST and VPLB_SNRST */ + tmp = readl(sc_base + SC_VPLL27ACTRL2); + tmp &= ~0x10000000; + writel(tmp, sc_base + SC_VPLL27ACTRL2); + tmp = readl(sc_base + SC_VPLL27BCTRL2); + tmp &= ~0x10000000; + writel(tmp, sc_base + SC_VPLL27BCTRL2); + + /* Set 0x20 to VPLA_SNRST and VPLB_SNRST */ + tmp = readl(sc_base + SC_VPLL27ACTRL2); + tmp &= ~0x0000007f; + tmp |= 0x00000020; + writel(tmp, sc_base + SC_VPLL27ACTRL2); + tmp = readl(sc_base + SC_VPLL27BCTRL2); + tmp &= ~0x0000007f; + tmp |= 0x00000020; + writel(tmp, sc_base + SC_VPLL27BCTRL2); + + if (clk_mode_axosel == SG_PINMON0_CLK_MODE_AXOSEL_25000KHZ_U || + clk_mode_axosel == SG_PINMON0_CLK_MODE_AXOSEL_25000KHZ_A) { + /* AXO: 25MHz */ + tmp = readl(sc_base + SC_VPLL27ACTRL3); + tmp &= ~0x000fffff; + tmp |= 0x00066664; + writel(tmp, sc_base + SC_VPLL27ACTRL3); + tmp = readl(sc_base + SC_VPLL27BCTRL3); + tmp &= ~0x000fffff; + tmp |= 0x00066664; + writel(tmp, sc_base + SC_VPLL27BCTRL3); + } else { + /* AXO: default 24.576MHz */ + tmp = readl(sc_base + SC_VPLL27ACTRL3); + tmp &= ~0x000fffff; + tmp |= 0x000f5800; + writel(tmp, sc_base + SC_VPLL27ACTRL3); + tmp = readl(sc_base + SC_VPLL27BCTRL3); + tmp &= ~0x000fffff; + tmp |= 0x000f5800; + writel(tmp, sc_base + SC_VPLL27BCTRL3); + } + + /* Set 1 to VPLA_K_LD and VPLB_K_LD */ + tmp = readl(sc_base + SC_VPLL27ACTRL3); + tmp |= 0x10000000; + writel(tmp, sc_base + SC_VPLL27ACTRL3); + tmp = readl(sc_base + SC_VPLL27BCTRL3); + tmp |= 0x10000000; + writel(tmp, sc_base + SC_VPLL27BCTRL3); + + /* wait 10 usec */ + udelay(10); + + /* Set 0 to VPLA_SNRST and VPLB_SNRST */ + tmp = readl(sc_base + SC_VPLL27ACTRL2); + tmp |= 0x10000000; + writel(tmp, sc_base + SC_VPLL27ACTRL2); + tmp = readl(sc_base + SC_VPLL27BCTRL2); + tmp |= 0x10000000; + writel(tmp, sc_base + SC_VPLL27BCTRL2); + + /* set 0 to VPLA27WP and VPLA27WP */ + tmp = readl(sc_base + SC_VPLL27ACTRL); + tmp &= ~0x00000001; + writel(tmp, sc_base + SC_VPLL27ACTRL); + tmp = readl(sc_base + SC_VPLL27BCTRL); + tmp |= ~0x00000001; + writel(tmp, sc_base + SC_VPLL27BCTRL); +} + +void uniphier_ld4_pll_init(void) +{ + upll_init(); + vpll_init(); + uniphier_ld4_dpll_ssc_en(); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/pll-pro4.c b/roms/u-boot/arch/arm/mach-uniphier/clk/pll-pro4.c new file mode 100644 index 000000000..b7dc3e261 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/pll-pro4.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013-2014 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + */ + +#include <linux/delay.h> +#include <linux/io.h> + +#include "../init.h" +#include "../sc-regs.h" +#include "../sg-regs.h" +#include "pll.h" + +static void vpll_init(void) +{ + u32 tmp, clk_mode_axosel; + + /* Set VPLL27A & VPLL27B */ + tmp = readl(sg_base + SG_PINMON0); + clk_mode_axosel = tmp & SG_PINMON0_CLK_MODE_AXOSEL_MASK; + + /* 25MHz or 6.25MHz is default for Pro4R, no need to set VPLLA/B */ + if (clk_mode_axosel == SG_PINMON0_CLK_MODE_AXOSEL_25000KHZ || + clk_mode_axosel == SG_PINMON0_CLK_MODE_AXOSEL_6250KHZ) + return; + + /* Disable write protect of VPLL27ACTRL[2-7]*, VPLL27BCTRL[2-8] */ + tmp = readl(sc_base + SC_VPLL27ACTRL); + tmp |= 0x00000001; + writel(tmp, sc_base + SC_VPLL27ACTRL); + tmp = readl(sc_base + SC_VPLL27BCTRL); + tmp |= 0x00000001; + writel(tmp, sc_base + SC_VPLL27BCTRL); + + /* Unset VPLA_K_LD and VPLB_K_LD bit */ + tmp = readl(sc_base + SC_VPLL27ACTRL3); + tmp &= ~0x10000000; + writel(tmp, sc_base + SC_VPLL27ACTRL3); + tmp = readl(sc_base + SC_VPLL27BCTRL3); + tmp &= ~0x10000000; + writel(tmp, sc_base + SC_VPLL27BCTRL3); + + /* Set VPLA_M and VPLB_M to 0x20 */ + tmp = readl(sc_base + SC_VPLL27ACTRL2); + tmp &= ~0x0000007f; + tmp |= 0x00000020; + writel(tmp, sc_base + SC_VPLL27ACTRL2); + tmp = readl(sc_base + SC_VPLL27BCTRL2); + tmp &= ~0x0000007f; + tmp |= 0x00000020; + writel(tmp, sc_base + SC_VPLL27BCTRL2); + + if (clk_mode_axosel == SG_PINMON0_CLK_MODE_AXOSEL_25000KHZ || + clk_mode_axosel == SG_PINMON0_CLK_MODE_AXOSEL_6250KHZ) { + /* Set VPLA_K and VPLB_K for AXO: 25MHz */ + tmp = readl(sc_base + SC_VPLL27ACTRL3); + tmp &= ~0x000fffff; + tmp |= 0x00066666; + writel(tmp, sc_base + SC_VPLL27ACTRL3); + tmp = readl(sc_base + SC_VPLL27BCTRL3); + tmp &= ~0x000fffff; + tmp |= 0x00066666; + writel(tmp, sc_base + SC_VPLL27BCTRL3); + } else { + /* Set VPLA_K and VPLB_K for AXO: 24.576 MHz */ + tmp = readl(sc_base + SC_VPLL27ACTRL3); + tmp &= ~0x000fffff; + tmp |= 0x000f5800; + writel(tmp, sc_base + SC_VPLL27ACTRL3); + tmp = readl(sc_base + SC_VPLL27BCTRL3); + tmp &= ~0x000fffff; + tmp |= 0x000f5800; + writel(tmp, sc_base + SC_VPLL27BCTRL3); + } + + /* wait 1 usec */ + udelay(1); + + /* Set VPLA_K_LD and VPLB_K_LD to load K parameters */ + tmp = readl(sc_base + SC_VPLL27ACTRL3); + tmp |= 0x10000000; + writel(tmp, sc_base + SC_VPLL27ACTRL3); + tmp = readl(sc_base + SC_VPLL27BCTRL3); + tmp |= 0x10000000; + writel(tmp, sc_base + SC_VPLL27BCTRL3); + + /* Unset VPLA_SNRST and VPLB_SNRST bit */ + tmp = readl(sc_base + SC_VPLL27ACTRL2); + tmp |= 0x10000000; + writel(tmp, sc_base + SC_VPLL27ACTRL2); + tmp = readl(sc_base + SC_VPLL27BCTRL2); + tmp |= 0x10000000; + writel(tmp, sc_base + SC_VPLL27BCTRL2); + + /* Enable write protect of VPLL27ACTRL[2-7]*, VPLL27BCTRL[2-8] */ + tmp = readl(sc_base + SC_VPLL27ACTRL); + tmp &= ~0x00000001; + writel(tmp, sc_base + SC_VPLL27ACTRL); + tmp = readl(sc_base + SC_VPLL27BCTRL); + tmp &= ~0x00000001; + writel(tmp, sc_base + SC_VPLL27BCTRL); +} + +void uniphier_pro4_pll_init(void) +{ + vpll_init(); + uniphier_ld4_dpll_ssc_en(); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/pll-pxs3.c b/roms/u-boot/arch/arm/mach-uniphier/clk/pll-pxs3.c new file mode 100644 index 000000000..278f530ea --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/pll-pxs3.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Socionext Inc. + */ + +#include <linux/delay.h> + +#include "../init.h" +#include "../sc64-regs.h" +#include "pll.h" + +/* PLL type: SSC */ +#define SC_CPLLCTRL 0x1400 /* CPU/ARM */ +#define SC_SPLLCTRL 0x1410 /* misc */ +#define SC_SPLL2CTRL 0x1420 /* DSP */ +#define SC_VPPLLCTRL 0x1430 /* VPE */ +#define SC_VGPLLCTRL 0x1440 +#define SC_DECPLLCTRL 0x1450 +#define SC_ENCPLLCTRL 0x1460 +#define SC_PXFPLLCTRL 0x1470 +#define SC_DPLL0CTRL 0x1480 /* DDR memory 0 */ +#define SC_DPLL1CTRL 0x1490 /* DDR memory 1 */ +#define SC_DPLL2CTRL 0x14a0 /* DDR memory 2 */ +#define SC_VSPLLCTRL 0x14c0 + +/* PLL type: VPLL27 */ +#define SC_VPLL27FCTRL 0x1500 +#define SC_VPLL27ACTRL 0x1520 + +/* PLL type: DSPLL */ +#define SC_VPLL8KCTRL 0x1540 + +void uniphier_pxs3_pll_init(void) +{ + uniphier_ld20_sscpll_init(SC_CPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 4); + /* do nothing for SPLL */ + uniphier_ld20_sscpll_init(SC_SPLL2CTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 4); + uniphier_ld20_sscpll_init(SC_VPPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 2); + uniphier_ld20_sscpll_init(SC_VGPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 2); + uniphier_ld20_sscpll_init(SC_DECPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 2); + uniphier_ld20_sscpll_init(SC_ENCPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 4); + uniphier_ld20_sscpll_init(SC_PXFPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 2); + uniphier_ld20_sscpll_init(SC_VSPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 2); + + mdelay(1); + + uniphier_ld20_sscpll_ssc_en(SC_CPLLCTRL); + uniphier_ld20_sscpll_ssc_en(SC_SPLL2CTRL); + uniphier_ld20_sscpll_ssc_en(SC_VPPLLCTRL); + uniphier_ld20_sscpll_ssc_en(SC_VGPLLCTRL); + uniphier_ld20_sscpll_ssc_en(SC_DECPLLCTRL); + uniphier_ld20_sscpll_ssc_en(SC_ENCPLLCTRL); + uniphier_ld20_sscpll_ssc_en(SC_PXFPLLCTRL); + uniphier_ld20_sscpll_ssc_en(SC_DPLL0CTRL); + uniphier_ld20_sscpll_ssc_en(SC_DPLL1CTRL); + uniphier_ld20_sscpll_ssc_en(SC_DPLL2CTRL); + uniphier_ld20_sscpll_ssc_en(SC_VSPLLCTRL); + + uniphier_ld20_vpll27_init(SC_VPLL27FCTRL); + uniphier_ld20_vpll27_init(SC_VPLL27ACTRL); + + uniphier_ld20_dspll_init(SC_VPLL8KCTRL); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/clk/pll.h b/roms/u-boot/arch/arm/mach-uniphier/clk/pll.h new file mode 100644 index 000000000..dbdbd2b45 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/clk/pll.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#ifndef MACH_PLL_H +#define MACH_PLL_H + +#define UNIPHIER_PLL_FREQ_DEFAULT (0) + +void uniphier_ld4_dpll_ssc_en(void); + +int uniphier_ld20_sscpll_init(unsigned long reg_base, unsigned int freq, + unsigned int ssc_rate, unsigned int divn); +int uniphier_ld20_sscpll_ssc_en(unsigned long reg_base); +int uniphier_ld20_sscpll_set_regi(unsigned long reg_base, unsigned regi); +int uniphier_ld20_vpll27_init(unsigned long reg_base); +int uniphier_ld20_dspll_init(unsigned long reg_base); + +#endif /* MACH_PLL_H */ diff --git a/roms/u-boot/arch/arm/mach-uniphier/cpu-info.c b/roms/u-boot/arch/arm/mach-uniphier/cpu-info.c new file mode 100644 index 000000000..1ede50771 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/cpu-info.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013-2014 Panasonic Corporation + * Copyright (C) 2015-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <init.h> +#include <stdio.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/printk.h> + +#include "base-address.h" +#include "soc-info.h" + +int print_cpuinfo(void) +{ + unsigned int id, model, rev, required_model = 1, required_rev = 1; + int ret; + + ret = uniphier_base_address_init(); + if (ret) + return ret; + + id = uniphier_get_soc_id(); + model = uniphier_get_soc_model(); + rev = uniphier_get_soc_revision(); + + puts("SoC: "); + + switch (id) { + case UNIPHIER_LD4_ID: + puts("LD4"); + required_rev = 2; + break; + case UNIPHIER_PRO4_ID: + puts("Pro4"); + break; + case UNIPHIER_SLD8_ID: + puts("sLD8"); + break; + case UNIPHIER_PRO5_ID: + puts("Pro5"); + break; + case UNIPHIER_PXS2_ID: + puts("PXs2"); + break; + case UNIPHIER_LD6B_ID: + puts("LD6b"); + break; + case UNIPHIER_LD11_ID: + puts("LD11"); + break; + case UNIPHIER_LD20_ID: + puts("LD20"); + break; + case UNIPHIER_PXS3_ID: + puts("PXs3"); + break; + default: + printf("Unknown Processor ID (0x%x)\n", id); + return -ENOTSUPP; + } + + printf(" (model %d, revision %d)\n", model, rev); + + if (model < required_model) { + pr_err("Only model %d or newer is supported.\n", + required_model); + return -ENOTSUPP; + } else if (rev < required_rev) { + pr_err("Only revision %d or newer is supported.\n", + required_rev); + return -ENOTSUPP; + } + + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/debug-uart/Makefile b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/Makefile new file mode 100644 index 000000000..81e9314a5 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0+ + +ifdef CONFIG_SPL_BUILD +obj-$(CONFIG_ARCH_UNIPHIER_LD4) += debug-uart-ld4.o +obj-$(CONFIG_ARCH_UNIPHIER_PRO4) += debug-uart-pro4.o +obj-$(CONFIG_ARCH_UNIPHIER_SLD8) += debug-uart-sld8.o +obj-$(CONFIG_ARCH_UNIPHIER_PRO5) += debug-uart-pro5.o +obj-$(CONFIG_ARCH_UNIPHIER_PXS2) += debug-uart-pxs2.o +obj-$(CONFIG_ARCH_UNIPHIER_LD6B) += debug-uart-ld6b.o +endif + +obj-y += debug-uart.o diff --git a/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-ld4.c b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-ld4.c new file mode 100644 index 000000000..10a7087c0 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-ld4.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <config.h> +#include <linux/kernel.h> + +#include "../sg-regs.h" +#include "debug-uart.h" + +#define UNIPHIER_LD4_UART_CLK 36864000 + +unsigned int uniphier_ld4_debug_uart_init(void) +{ + sg_set_iectrl(0); + sg_set_pinsel(88, 1, 8, 4); /* HSDOUT6 -> TXD0 */ + + return DIV_ROUND_CLOSEST(UNIPHIER_LD4_UART_CLK, 16 * CONFIG_BAUDRATE); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-ld6b.c b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-ld6b.c new file mode 100644 index 000000000..f64ff39c9 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-ld6b.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <config.h> +#include <linux/kernel.h> +#include <linux/io.h> + +#include "../sc-regs.h" +#include "../sg-regs.h" +#include "debug-uart.h" + +#define UNIPHIER_LD6B_UART_CLK 88888888 + +unsigned int uniphier_ld6b_debug_uart_init(void) +{ + u32 tmp; + + sg_set_iectrl(0); + sg_set_pinsel(135, 3, 8, 4); /* PORT10 -> TXD0 */ + sg_set_pinsel(115, 0, 8, 4); /* TXD1 -> TXD1 */ + sg_set_pinsel(113, 2, 8, 4); /* SBO0 -> TXD2 */ + + tmp = readl(sc_base + SC_CLKCTRL); + tmp |= SC_CLKCTRL_CEN_PERI; + writel(tmp, sc_base + SC_CLKCTRL); + + return DIV_ROUND_CLOSEST(UNIPHIER_LD6B_UART_CLK, 16 * CONFIG_BAUDRATE); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-pro4.c b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-pro4.c new file mode 100644 index 000000000..79c6c101e --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-pro4.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <config.h> +#include <linux/kernel.h> +#include <linux/io.h> + +#include "../sc-regs.h" +#include "../sg-regs.h" +#include "debug-uart.h" + +#define UNIPHIER_PRO4_UART_CLK 73728000 + +unsigned int uniphier_pro4_debug_uart_init(void) +{ + u32 tmp; + + sg_set_iectrl(0); + sg_set_pinsel(128, 0, 4, 8); /* TXD0 -> TXD0 */ + + writel(1, sg_base + SG_LOADPINCTRL); + + tmp = readl(sc_base + SC_CLKCTRL); + tmp |= SC_CLKCTRL_CEN_PERI; + writel(tmp, sc_base + SC_CLKCTRL); + + return DIV_ROUND_CLOSEST(UNIPHIER_PRO4_UART_CLK, 16 * CONFIG_BAUDRATE); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-pro5.c b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-pro5.c new file mode 100644 index 000000000..ef3b383ee --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-pro5.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <config.h> +#include <linux/kernel.h> +#include <linux/io.h> + +#include "../sc-regs.h" +#include "../sg-regs.h" +#include "debug-uart.h" + +#define UNIPHIER_PRO5_UART_CLK 73728000 + +unsigned int uniphier_pro5_debug_uart_init(void) +{ + u32 tmp; + + sg_set_iectrl(0); + sg_set_pinsel(47, 0, 4, 8); /* TXD0 -> TXD0 */ + sg_set_pinsel(49, 0, 4, 8); /* TXD1 -> TXD1 */ + sg_set_pinsel(51, 0, 4, 8); /* TXD2 -> TXD2 */ + sg_set_pinsel(53, 0, 4, 8); /* TXD3 -> TXD3 */ + + writel(1, sg_base + SG_LOADPINCTRL); + + tmp = readl(sc_base + SC_CLKCTRL); + tmp |= SC_CLKCTRL_CEN_PERI; + writel(tmp, sc_base + SC_CLKCTRL); + + return DIV_ROUND_CLOSEST(UNIPHIER_PRO5_UART_CLK, 16 * CONFIG_BAUDRATE); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-pxs2.c b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-pxs2.c new file mode 100644 index 000000000..ee8caad1d --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-pxs2.c @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <config.h> +#include <linux/kernel.h> +#include <linux/io.h> + +#include "../sc-regs.h" +#include "../sg-regs.h" +#include "debug-uart.h" + +#define UNIPHIER_PXS2_UART_CLK 88888888 + +unsigned int uniphier_pxs2_debug_uart_init(void) +{ + u32 tmp; + + sg_set_iectrl(0); + sg_set_pinsel(217, 8, 8, 4); /* TXD0 -> TXD0 */ + sg_set_pinsel(115, 8, 8, 4); /* TXD1 -> TXD1 */ + sg_set_pinsel(113, 8, 8, 4); /* TXD2 -> TXD2 */ + sg_set_pinsel(219, 8, 8, 4); /* TXD3 -> TXD3 */ + + tmp = readl(sc_base + SC_CLKCTRL); + tmp |= SC_CLKCTRL_CEN_PERI; + writel(tmp, sc_base + SC_CLKCTRL); + + return DIV_ROUND_CLOSEST(UNIPHIER_PXS2_UART_CLK, 16 * CONFIG_BAUDRATE); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-sld8.c b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-sld8.c new file mode 100644 index 000000000..da16abdba --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart-sld8.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <config.h> +#include <linux/kernel.h> + +#include "../sg-regs.h" +#include "debug-uart.h" + +#define UNIPHIER_SLD8_UART_CLK 80000000 + +unsigned int uniphier_sld8_debug_uart_init(void) +{ + sg_set_iectrl(0); + sg_set_pinsel(70, 3, 8, 4); /* HSDOUT6 -> TXD0 */ + + return DIV_ROUND_CLOSEST(UNIPHIER_SLD8_UART_CLK, 16 * CONFIG_BAUDRATE); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart.c b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart.c new file mode 100644 index 000000000..d116d4681 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <debug_uart.h> +#include <linux/io.h> +#include <linux/serial_reg.h> + +#include "../sg-regs.h" +#include "../soc-info.h" +#include "debug-uart.h" + +#define UNIPHIER_UART_TX 0x00 +#define UNIPHIER_UART_LCR_MCR 0x10 +#define UNIPHIER_UART_LSR 0x14 +#define UNIPHIER_UART_LDR 0x24 + +static void _debug_uart_putc(int c) +{ + void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE; + + while (!(readl(base + UNIPHIER_UART_LSR) & UART_LSR_THRE)) + ; + + writel(c, base + UNIPHIER_UART_TX); +} + +#ifdef CONFIG_SPL_BUILD +void sg_set_pinsel(unsigned int pin, unsigned int muxval, + unsigned int mux_bits, unsigned int reg_stride) +{ + unsigned int shift = pin * mux_bits % 32; + void __iomem *reg = sg_base + SG_PINCTRL_BASE + + pin * mux_bits / 32 * reg_stride; + u32 mask = (1U << mux_bits) - 1; + u32 tmp; + + tmp = readl(reg); + tmp &= ~(mask << shift); + tmp |= (mask & muxval) << shift; + writel(tmp, reg); +} + +void sg_set_iectrl(unsigned int pin) +{ + unsigned int bit = pin % 32; + void __iomem *reg = sg_base + SG_IECTRL + pin / 32 * 4; + u32 tmp; + + tmp = readl(reg); + tmp |= 1 << bit; + writel(tmp, reg); +} +#endif + +void _debug_uart_init(void) +{ +#ifdef CONFIG_SPL_BUILD + void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE; + unsigned int divisor; + + switch (uniphier_get_soc_id()) { +#if defined(CONFIG_ARCH_UNIPHIER_LD4) + case UNIPHIER_LD4_ID: + divisor = uniphier_ld4_debug_uart_init(); + break; +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PRO4) + case UNIPHIER_PRO4_ID: + divisor = uniphier_pro4_debug_uart_init(); + break; +#endif +#if defined(CONFIG_ARCH_UNIPHIER_SLD8) + case UNIPHIER_SLD8_ID: + divisor = uniphier_sld8_debug_uart_init(); + break; +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PRO5) + case UNIPHIER_PRO5_ID: + divisor = uniphier_pro5_debug_uart_init(); + break; +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PXS2) + case UNIPHIER_PXS2_ID: + divisor = uniphier_pxs2_debug_uart_init(); + break; +#endif +#if defined(CONFIG_ARCH_UNIPHIER_LD6B) + case UNIPHIER_LD6B_ID: + divisor = uniphier_ld6b_debug_uart_init(); + break; +#endif + default: + return; + } + + writel(UART_LCR_WLEN8 << 8, base + UNIPHIER_UART_LCR_MCR); + + writel(divisor, base + UNIPHIER_UART_LDR); +#endif +} +DEBUG_UART_FUNCS diff --git a/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart.h b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart.h new file mode 100644 index 000000000..f4e98c0bb --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/debug-uart/debug-uart.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#ifndef _MACH_DEBUG_UART_H +#define _MACH_DEBUG_UART_H + +unsigned int uniphier_ld4_debug_uart_init(void); +unsigned int uniphier_pro4_debug_uart_init(void); +unsigned int uniphier_sld8_debug_uart_init(void); +unsigned int uniphier_pro5_debug_uart_init(void); +unsigned int uniphier_pxs2_debug_uart_init(void); +unsigned int uniphier_ld6b_debug_uart_init(void); + +void sg_set_pinsel(unsigned int pin, unsigned int muxval, + unsigned int mux_bits, unsigned int reg_stride); +void sg_set_iectrl(unsigned int pin); + +#endif /* _MACH_DEBUG_UART_H */ diff --git a/roms/u-boot/arch/arm/mach-uniphier/debug.h b/roms/u-boot/arch/arm/mach-uniphier/debug.h new file mode 100644 index 000000000..466dc9b03 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/debug.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +#include <linux/io.h> +#include <linux/serial_reg.h> + +#define DEBUG_UART_BASE 0x54006800 +#define UART_SHIFT 2 + +#define UNIPHIER_UART_TX 0 +#define UNIPHIER_UART_LSR (5 * 4) + +/* All functions are inline so that they can be called from .secure section. */ + +#ifdef DEBUG +static inline void debug_putc(int c) +{ + void __iomem *base = (void __iomem *)DEBUG_UART_BASE; + + while (!(readl(base + UNIPHIER_UART_LSR) & UART_LSR_THRE)) + ; + + writel(c, base + UNIPHIER_UART_TX); +} + +static inline void debug_puts(const char *s) +{ + while (*s) { + if (*s == '\n') + debug_putc('\r'); + + debug_putc(*s++); + } +} + +static inline void debug_puth(unsigned long val) +{ + int i; + unsigned char c; + + for (i = 8; i--; ) { + c = ((val >> (i * 4)) & 0xf); + c += (c >= 10) ? 'a' - 10 : '0'; + debug_putc(c); + } +} +#else +static inline void debug_putc(int c) +{ +} + +static inline void debug_puts(const char *s) +{ +} + +static inline void debug_puth(unsigned long val) +{ +} +#endif + +#endif /* __DEBUG_H__ */ diff --git a/roms/u-boot/arch/arm/mach-uniphier/dram/Makefile b/roms/u-boot/arch/arm/mach-uniphier/dram/Makefile new file mode 100644 index 000000000..7d11315d0 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/dram/Makefile @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0+ + +ifdef CONFIG_SPL_BUILD + +obj-$(CONFIG_ARCH_UNIPHIER_LD4) += umc-ld4.o \ + ddrphy-training.o ddrphy-ld4.o +obj-$(CONFIG_ARCH_UNIPHIER_PRO4) += umc-pro4.o \ + ddrphy-training.o ddrphy-ld4.o +obj-$(CONFIG_ARCH_UNIPHIER_SLD8) += umc-sld8.o \ + ddrphy-training.o ddrphy-ld4.o +obj-$(CONFIG_ARCH_UNIPHIER_PRO5) += umc-pro5.o +obj-$(CONFIG_ARCH_UNIPHIER_PXS2) += umc-pxs2.o +obj-$(CONFIG_ARCH_UNIPHIER_LD6B) += umc-pxs2.o + +else + +obj-$(CONFIG_CMD_DDRPHY_DUMP) += cmd_ddrphy.o +obj-$(CONFIG_CMD_DDRMPHY_DUMP) += cmd_ddrmphy.o + +endif diff --git a/roms/u-boot/arch/arm/mach-uniphier/dram/cmd_ddrmphy.c b/roms/u-boot/arch/arm/mach-uniphier/dram/cmd_ddrmphy.c new file mode 100644 index 000000000..629f8b90c --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/dram/cmd_ddrmphy.c @@ -0,0 +1,346 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <command.h> +#include <stdio.h> +#include <linux/io.h> +#include <linux/printk.h> +#include <linux/sizes.h> + +#include "../soc-info.h" +#include "ddrmphy-regs.h" + +/* Select either decimal or hexadecimal */ +#if 1 +#define PRINTF_FORMAT "%2d" +#else +#define PRINTF_FORMAT "%02x" +#endif +/* field separator */ +#define FS " " + +#define ptr_to_uint(p) ((unsigned int)(unsigned long)(p)) + +#define UNIPHIER_MAX_NR_DDRMPHY 3 + +struct uniphier_ddrmphy_param { + unsigned int soc_id; + unsigned int nr_phy; + struct { + resource_size_t base; + unsigned int nr_zq; + unsigned int nr_dx; + } phy[UNIPHIER_MAX_NR_DDRMPHY]; +}; + +static const struct uniphier_ddrmphy_param uniphier_ddrmphy_param[] = { + { + .soc_id = UNIPHIER_PXS2_ID, + .nr_phy = 3, + .phy = { + { .base = 0x5b830000, .nr_zq = 3, .nr_dx = 4, }, + { .base = 0x5ba30000, .nr_zq = 3, .nr_dx = 4, }, + { .base = 0x5bc30000, .nr_zq = 2, .nr_dx = 2, }, + }, + }, + { + .soc_id = UNIPHIER_LD6B_ID, + .nr_phy = 3, + .phy = { + { .base = 0x5b830000, .nr_zq = 3, .nr_dx = 4, }, + { .base = 0x5ba30000, .nr_zq = 3, .nr_dx = 4, }, + { .base = 0x5bc30000, .nr_zq = 2, .nr_dx = 2, }, + }, + }, +}; +UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_ddrmphy_param, uniphier_ddrmphy_param) + +static void print_bdl(void __iomem *reg, int n) +{ + u32 val = readl(reg); + int i; + + for (i = 0; i < n; i++) + printf(FS PRINTF_FORMAT, (val >> i * 8) & 0x1f); +} + +static void dump_loop(const struct uniphier_ddrmphy_param *param, + void (*callback)(void __iomem *)) +{ + void __iomem *phy_base, *dx_base; + int phy, dx; + + for (phy = 0; phy < param->nr_phy; phy++) { + phy_base = ioremap(param->phy[phy].base, SZ_4K); + dx_base = phy_base + MPHY_DX_BASE; + + for (dx = 0; dx < param->phy[phy].nr_dx; dx++) { + printf("PHY%dDX%d:", phy, dx); + (*callback)(dx_base); + dx_base += MPHY_DX_STRIDE; + printf("\n"); + } + + iounmap(phy_base); + } +} + +static void zq_dump(const struct uniphier_ddrmphy_param *param) +{ + void __iomem *phy_base, *zq_base; + u32 val; + int phy, zq, i; + + printf("\n--- Impedance Data ---\n"); + printf(" ZPD ZPU OPD OPU ZDV ODV\n"); + + for (phy = 0; phy < param->nr_phy; phy++) { + phy_base = ioremap(param->phy[phy].base, SZ_4K); + zq_base = phy_base + MPHY_ZQ_BASE; + + for (zq = 0; zq < param->phy[phy].nr_zq; zq++) { + printf("PHY%dZQ%d:", phy, zq); + + val = readl(zq_base + MPHY_ZQ_DR); + for (i = 0; i < 4; i++) { + printf(FS PRINTF_FORMAT, val & 0x7f); + val >>= 7; + } + + val = readl(zq_base + MPHY_ZQ_PR); + for (i = 0; i < 2; i++) { + printf(FS PRINTF_FORMAT, val & 0xf); + val >>= 4; + } + + zq_base += MPHY_ZQ_STRIDE; + printf("\n"); + } + + iounmap(phy_base); + } +} + +static void __wbdl_dump(void __iomem *dx_base) +{ + print_bdl(dx_base + MPHY_DX_BDLR0, 4); + print_bdl(dx_base + MPHY_DX_BDLR1, 4); + print_bdl(dx_base + MPHY_DX_BDLR2, 2); + + printf(FS "(+" PRINTF_FORMAT ")", + readl(dx_base + MPHY_DX_LCDLR1) & 0xff); +} + +static void wbdl_dump(const struct uniphier_ddrmphy_param *param) +{ + printf("\n--- Write Bit Delay Line ---\n"); + printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM DQS (WDQD)\n"); + + dump_loop(param, &__wbdl_dump); +} + +static void __rbdl_dump(void __iomem *dx_base) +{ + print_bdl(dx_base + MPHY_DX_BDLR3, 4); + print_bdl(dx_base + MPHY_DX_BDLR4, 4); + print_bdl(dx_base + MPHY_DX_BDLR5, 1); + + printf(FS "(+" PRINTF_FORMAT ")", + (readl(dx_base + MPHY_DX_LCDLR1) >> 8) & 0xff); + + printf(FS "(+" PRINTF_FORMAT ")", + (readl(dx_base + MPHY_DX_LCDLR1) >> 16) & 0xff); +} + +static void rbdl_dump(const struct uniphier_ddrmphy_param *param) +{ + printf("\n--- Read Bit Delay Line ---\n"); + printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM (RDQSD) (RDQSND)\n"); + + dump_loop(param, &__rbdl_dump); +} + +static void __wld_dump(void __iomem *dx_base) +{ + int rank; + u32 lcdlr0 = readl(dx_base + MPHY_DX_LCDLR0); + u32 gtr = readl(dx_base + MPHY_DX_GTR); + + for (rank = 0; rank < 4; rank++) { + u32 wld = (lcdlr0 >> (8 * rank)) & 0xff; /* Delay */ + u32 wlsl = (gtr >> (12 + 2 * rank)) & 0x3; /* System Latency */ + + printf(FS PRINTF_FORMAT "%sT", wld, + wlsl == 0 ? "-1" : wlsl == 1 ? "+0" : "+1"); + } +} + +static void wld_dump(const struct uniphier_ddrmphy_param *param) +{ + printf("\n--- Write Leveling Delay ---\n"); + printf(" Rank0 Rank1 Rank2 Rank3\n"); + + dump_loop(param, &__wld_dump); +} + +static void __dqsgd_dump(void __iomem *dx_base) +{ + int rank; + u32 lcdlr2 = readl(dx_base + MPHY_DX_LCDLR2); + u32 gtr = readl(dx_base + MPHY_DX_GTR); + + for (rank = 0; rank < 4; rank++) { + u32 dqsgd = (lcdlr2 >> (8 * rank)) & 0xff; /* Delay */ + u32 dgsl = (gtr >> (3 * rank)) & 0x7; /* System Latency */ + + printf(FS PRINTF_FORMAT "+%dT", dqsgd, dgsl); + } +} + +static void dqsgd_dump(const struct uniphier_ddrmphy_param *param) +{ + printf("\n--- DQS Gating Delay ---\n"); + printf(" Rank0 Rank1 Rank2 Rank3\n"); + + dump_loop(param, &__dqsgd_dump); +} + +static void __mdl_dump(void __iomem *dx_base) +{ + int i; + u32 mdl = readl(dx_base + MPHY_DX_MDLR); + + for (i = 0; i < 3; i++) + printf(FS PRINTF_FORMAT, (mdl >> (8 * i)) & 0xff); +} + +static void mdl_dump(const struct uniphier_ddrmphy_param *param) +{ + printf("\n--- Master Delay Line ---\n"); + printf(" IPRD TPRD MDLD\n"); + + dump_loop(param, &__mdl_dump); +} + +#define REG_DUMP(x) \ + { int ofst = MPHY_ ## x; void __iomem *reg = phy_base + ofst; \ + printf("%3d: %-10s: %p : %08x\n", \ + ofst >> MPHY_SHIFT, #x, reg, readl(reg)); } + +#define DX_REG_DUMP(dx, x) \ + { int ofst = MPHY_DX_BASE + MPHY_DX_STRIDE * (dx) + \ + MPHY_DX_## x; \ + void __iomem *reg = phy_base + ofst; \ + printf("%3d: DX%d%-7s: %p : %08x\n", \ + ofst >> MPHY_SHIFT, (dx), #x, reg, readl(reg)); } + +static void reg_dump(const struct uniphier_ddrmphy_param *param) +{ + void __iomem *phy_base; + int phy, dx; + + printf("\n--- DDR Multi PHY registers ---\n"); + + for (phy = 0; phy < param->nr_phy; phy++) { + phy_base = ioremap(param->phy[phy].base, SZ_4K); + + printf("== PHY%d (base: %08x) ==\n", phy, + ptr_to_uint(phy_base)); + printf(" No: Name : Address : Data\n"); + + REG_DUMP(RIDR); + REG_DUMP(PIR); + REG_DUMP(PGCR0); + REG_DUMP(PGCR1); + REG_DUMP(PGCR2); + REG_DUMP(PGCR3); + REG_DUMP(PGSR0); + REG_DUMP(PGSR1); + REG_DUMP(PLLCR); + REG_DUMP(PTR0); + REG_DUMP(PTR1); + REG_DUMP(PTR2); + REG_DUMP(PTR3); + REG_DUMP(PTR4); + REG_DUMP(ACMDLR); + REG_DUMP(ACBDLR0); + REG_DUMP(DXCCR); + REG_DUMP(DSGCR); + REG_DUMP(DCR); + REG_DUMP(DTPR0); + REG_DUMP(DTPR1); + REG_DUMP(DTPR2); + REG_DUMP(DTPR3); + REG_DUMP(MR0); + REG_DUMP(MR1); + REG_DUMP(MR2); + REG_DUMP(MR3); + + for (dx = 0; dx < param->phy[phy].nr_dx; dx++) { + DX_REG_DUMP(dx, GCR0); + DX_REG_DUMP(dx, GCR1); + DX_REG_DUMP(dx, GCR2); + DX_REG_DUMP(dx, GCR3); + DX_REG_DUMP(dx, GTR); + } + + iounmap(phy_base); + } +} + +static int do_ddrm(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + const struct uniphier_ddrmphy_param *param; + char *cmd; + + param = uniphier_get_ddrmphy_param(); + if (!param) { + pr_err("unsupported SoC\n"); + return CMD_RET_FAILURE; + } + + if (argc == 1) + cmd = "all"; + else + cmd = argv[1]; + + if (!strcmp(cmd, "zq") || !strcmp(cmd, "all")) + zq_dump(param); + + if (!strcmp(cmd, "wbdl") || !strcmp(cmd, "all")) + wbdl_dump(param); + + if (!strcmp(cmd, "rbdl") || !strcmp(cmd, "all")) + rbdl_dump(param); + + if (!strcmp(cmd, "wld") || !strcmp(cmd, "all")) + wld_dump(param); + + if (!strcmp(cmd, "dqsgd") || !strcmp(cmd, "all")) + dqsgd_dump(param); + + if (!strcmp(cmd, "mdl") || !strcmp(cmd, "all")) + mdl_dump(param); + + if (!strcmp(cmd, "reg") || !strcmp(cmd, "all")) + reg_dump(param); + + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD( + ddrm, 2, 1, do_ddrm, + "UniPhier DDR Multi PHY parameters dumper", + "- dump all of the following\n" + "ddrm zq - dump Impedance Data\n" + "ddrm wbdl - dump Write Bit Delay\n" + "ddrm rbdl - dump Read Bit Delay\n" + "ddrm wld - dump Write Leveling\n" + "ddrm dqsgd - dump DQS Gating Delay\n" + "ddrm mdl - dump Master Delay Line\n" + "ddrm reg - dump registers\n" +); diff --git a/roms/u-boot/arch/arm/mach-uniphier/dram/cmd_ddrphy.c b/roms/u-boot/arch/arm/mach-uniphier/dram/cmd_ddrphy.c new file mode 100644 index 000000000..ca519d1c7 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/dram/cmd_ddrphy.c @@ -0,0 +1,312 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014 Panasonic Corporation + * Copyright (C) 2015-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <command.h> +#include <stdio.h> +#include <linux/io.h> +#include <linux/printk.h> +#include <linux/sizes.h> + +#include "../soc-info.h" +#include "ddrphy-regs.h" + +/* Select either decimal or hexadecimal */ +#if 1 +#define PRINTF_FORMAT "%2d" +#else +#define PRINTF_FORMAT "%02x" +#endif +/* field separator */ +#define FS " " + +#define ptr_to_uint(p) ((unsigned int)(unsigned long)(p)) + +#define UNIPHIER_MAX_NR_DDRPHY 4 + +struct uniphier_ddrphy_param { + unsigned int soc_id; + unsigned int nr_phy; + struct { + resource_size_t base; + unsigned int nr_dx; + } phy[UNIPHIER_MAX_NR_DDRPHY]; +}; + +static const struct uniphier_ddrphy_param uniphier_ddrphy_param[] = { + { + .soc_id = UNIPHIER_LD4_ID, + .nr_phy = 2, + .phy = { + { .base = 0x5bc01000, .nr_dx = 2, }, + { .base = 0x5be01000, .nr_dx = 2, }, + }, + }, + { + .soc_id = UNIPHIER_PRO4_ID, + .nr_phy = 4, + .phy = { + { .base = 0x5bc01000, .nr_dx = 2, }, + { .base = 0x5bc02000, .nr_dx = 2, }, + { .base = 0x5be01000, .nr_dx = 2, }, + { .base = 0x5be02000, .nr_dx = 2, }, + }, + }, + { + .soc_id = UNIPHIER_SLD8_ID, + .nr_phy = 2, + .phy = { + { .base = 0x5bc01000, .nr_dx = 2, }, + { .base = 0x5be01000, .nr_dx = 2, }, + }, + }, + { + .soc_id = UNIPHIER_LD11_ID, + .nr_phy = 1, + .phy = { + { .base = 0x5bc01000, .nr_dx = 4, }, + }, + }, +}; +UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_ddrphy_param, uniphier_ddrphy_param) + +static void print_bdl(void __iomem *reg, int n) +{ + u32 val = readl(reg); + int i; + + for (i = 0; i < n; i++) + printf(FS PRINTF_FORMAT, (val >> i * 6) & 0x3f); +} + +static void dump_loop(const struct uniphier_ddrphy_param *param, + void (*callback)(void __iomem *)) +{ + void __iomem *phy_base, *dx_base; + int phy, dx; + + for (phy = 0; phy < param->nr_phy; phy++) { + phy_base = ioremap(param->phy[phy].base, SZ_4K); + dx_base = phy_base + PHY_DX_BASE; + + for (dx = 0; dx < param->phy[phy].nr_dx; dx++) { + printf("PHY%dDX%d:", phy, dx); + (*callback)(dx_base); + dx_base += PHY_DX_STRIDE; + printf("\n"); + } + + iounmap(phy_base); + } +} + +static void __wbdl_dump(void __iomem *dx_base) +{ + print_bdl(dx_base + PHY_DX_BDLR0, 5); + print_bdl(dx_base + PHY_DX_BDLR1, 5); + + printf(FS "(+" PRINTF_FORMAT ")", + readl(dx_base + PHY_DX_LCDLR1) & 0xff); +} + +static void wbdl_dump(const struct uniphier_ddrphy_param *param) +{ + printf("\n--- Write Bit Delay Line ---\n"); + printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM DQS (WDQD)\n"); + + dump_loop(param, &__wbdl_dump); +} + +static void __rbdl_dump(void __iomem *dx_base) +{ + print_bdl(dx_base + PHY_DX_BDLR3, 5); + print_bdl(dx_base + PHY_DX_BDLR4, 4); + + printf(FS "(+" PRINTF_FORMAT ")", + (readl(dx_base + PHY_DX_LCDLR1) >> 8) & 0xff); +} + +static void rbdl_dump(const struct uniphier_ddrphy_param *param) +{ + printf("\n--- Read Bit Delay Line ---\n"); + printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM (RDQSD)\n"); + + dump_loop(param, &__rbdl_dump); +} + +static void __wld_dump(void __iomem *dx_base) +{ + int rank; + u32 lcdlr0 = readl(dx_base + PHY_DX_LCDLR0); + u32 gtr = readl(dx_base + PHY_DX_GTR); + + for (rank = 0; rank < 4; rank++) { + u32 wld = (lcdlr0 >> (8 * rank)) & 0xff; /* Delay */ + u32 wlsl = (gtr >> (12 + 2 * rank)) & 0x3; /* System Latency */ + + printf(FS PRINTF_FORMAT "%sT", wld, + wlsl == 0 ? "-1" : wlsl == 1 ? "+0" : "+1"); + } +} + +static void wld_dump(const struct uniphier_ddrphy_param *param) +{ + printf("\n--- Write Leveling Delay ---\n"); + printf(" Rank0 Rank1 Rank2 Rank3\n"); + + dump_loop(param, &__wld_dump); +} + +static void __dqsgd_dump(void __iomem *dx_base) +{ + int rank; + u32 lcdlr2 = readl(dx_base + PHY_DX_LCDLR2); + u32 gtr = readl(dx_base + PHY_DX_GTR); + + for (rank = 0; rank < 4; rank++) { + u32 dqsgd = (lcdlr2 >> (8 * rank)) & 0xff; /* Delay */ + u32 dgsl = (gtr >> (3 * rank)) & 0x7; /* System Latency */ + + printf(FS PRINTF_FORMAT "+%dT", dqsgd, dgsl); + } +} + +static void dqsgd_dump(const struct uniphier_ddrphy_param *param) +{ + printf("\n--- DQS Gating Delay ---\n"); + printf(" Rank0 Rank1 Rank2 Rank3\n"); + + dump_loop(param, &__dqsgd_dump); +} + +static void __mdl_dump(void __iomem *dx_base) +{ + int i; + u32 mdl = readl(dx_base + PHY_DX_MDLR); + + for (i = 0; i < 3; i++) + printf(FS PRINTF_FORMAT, (mdl >> (8 * i)) & 0xff); +} + +static void mdl_dump(const struct uniphier_ddrphy_param *param) +{ + printf("\n--- Master Delay Line ---\n"); + printf(" IPRD TPRD MDLD\n"); + + dump_loop(param, &__mdl_dump); +} + +#define REG_DUMP(x) \ + { int ofst = PHY_ ## x; void __iomem *reg = phy_base + ofst; \ + printf("%3d: %-10s: %08x : %08x\n", \ + ofst >> PHY_REG_SHIFT, #x, \ + ptr_to_uint(reg), readl(reg)); } + +#define DX_REG_DUMP(dx, x) \ + { int ofst = PHY_DX_BASE + PHY_DX_STRIDE * (dx) + \ + PHY_DX_## x; \ + void __iomem *reg = phy_base + ofst; \ + printf("%3d: DX%d%-7s: %08x : %08x\n", \ + ofst >> PHY_REG_SHIFT, (dx), #x, \ + ptr_to_uint(reg), readl(reg)); } + +static void reg_dump(const struct uniphier_ddrphy_param *param) +{ + void __iomem *phy_base; + int phy, dx; + + printf("\n--- DDR PHY registers ---\n"); + + for (phy = 0; phy < param->nr_phy; phy++) { + phy_base = ioremap(param->phy[phy].base, SZ_4K); + + printf("== PHY%d (base: %08x) ==\n", + phy, ptr_to_uint(phy_base)); + printf(" No: Name : Address : Data\n"); + + REG_DUMP(RIDR); + REG_DUMP(PIR); + REG_DUMP(PGCR0); + REG_DUMP(PGCR1); + REG_DUMP(PGSR0); + REG_DUMP(PGSR1); + REG_DUMP(PLLCR); + REG_DUMP(PTR0); + REG_DUMP(PTR1); + REG_DUMP(PTR2); + REG_DUMP(PTR3); + REG_DUMP(PTR4); + REG_DUMP(ACMDLR); + REG_DUMP(ACBDLR); + REG_DUMP(DXCCR); + REG_DUMP(DSGCR); + REG_DUMP(DCR); + REG_DUMP(DTPR0); + REG_DUMP(DTPR1); + REG_DUMP(DTPR2); + REG_DUMP(MR0); + REG_DUMP(MR1); + REG_DUMP(MR2); + REG_DUMP(MR3); + + for (dx = 0; dx < param->phy[phy].nr_dx; dx++) { + DX_REG_DUMP(dx, GCR); + DX_REG_DUMP(dx, GTR); + } + + iounmap(phy_base); + } +} + +static int do_ddr(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + const struct uniphier_ddrphy_param *param; + char *cmd; + + param = uniphier_get_ddrphy_param(); + if (!param) { + pr_err("unsupported SoC\n"); + return CMD_RET_FAILURE; + } + + if (argc == 1) + cmd = "all"; + else + cmd = argv[1]; + + if (!strcmp(cmd, "wbdl") || !strcmp(cmd, "all")) + wbdl_dump(param); + + if (!strcmp(cmd, "rbdl") || !strcmp(cmd, "all")) + rbdl_dump(param); + + if (!strcmp(cmd, "wld") || !strcmp(cmd, "all")) + wld_dump(param); + + if (!strcmp(cmd, "dqsgd") || !strcmp(cmd, "all")) + dqsgd_dump(param); + + if (!strcmp(cmd, "mdl") || !strcmp(cmd, "all")) + mdl_dump(param); + + if (!strcmp(cmd, "reg") || !strcmp(cmd, "all")) + reg_dump(param); + + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD( + ddr, 2, 1, do_ddr, + "UniPhier DDR PHY parameters dumper", + "- dump all of the following\n" + "ddr wbdl - dump Write Bit Delay\n" + "ddr rbdl - dump Read Bit Delay\n" + "ddr wld - dump Write Leveling\n" + "ddr dqsgd - dump DQS Gating Delay\n" + "ddr mdl - dump Master Delay Line\n" + "ddr reg - dump registers\n" +); diff --git a/roms/u-boot/arch/arm/mach-uniphier/dram/ddrmphy-regs.h b/roms/u-boot/arch/arm/mach-uniphier/dram/ddrmphy-regs.h new file mode 100644 index 000000000..96bab9de5 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/dram/ddrmphy-regs.h @@ -0,0 +1,145 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * UniPhier DDR MultiPHY registers + * + * Copyright (C) 2015-2017 Socionext Inc. + */ + +#ifndef UNIPHIER_DDRMPHY_REGS_H +#define UNIPHIER_DDRMPHY_REGS_H + +#include <linux/bitops.h> + +#define MPHY_SHIFT 2 + +#define MPHY_RIDR (0x000 << MPHY_SHIFT) +#define MPHY_PIR (0x001 << MPHY_SHIFT) +#define MPHY_PIR_INIT BIT(0) /* Initialization Trigger */ +#define MPHY_PIR_ZCAL BIT(1) /* Impedance Calibration */ +#define MPHY_PIR_PLLINIT BIT(4) /* PLL Initialization */ +#define MPHY_PIR_DCAL BIT(5) /* DDL Calibration */ +#define MPHY_PIR_PHYRST BIT(6) /* PHY Reset */ +#define MPHY_PIR_DRAMRST BIT(7) /* DRAM Reset */ +#define MPHY_PIR_DRAMINIT BIT(8) /* DRAM Initialization */ +#define MPHY_PIR_WL BIT(9) /* Write Leveling */ +#define MPHY_PIR_QSGATE BIT(10) /* Read DQS Gate Training */ +#define MPHY_PIR_WLADJ BIT(11) /* Write Leveling Adjust */ +#define MPHY_PIR_RDDSKW BIT(12) /* Read Data Bit Deskew */ +#define MPHY_PIR_WRDSKW BIT(13) /* Write Data Bit Deskew */ +#define MPHY_PIR_RDEYE BIT(14) /* Read Data Eye Training */ +#define MPHY_PIR_WREYE BIT(15) /* Write Data Eye Training */ +#define MPHY_PIR_ZCALBYP BIT(30) /* Impedance Calib Bypass */ +#define MPHY_PIR_INITBYP BIT(31) /* Initialization Bypass */ +#define MPHY_PGCR0 (0x002 << MPHY_SHIFT) +#define MPHY_PGCR0_PHYFRST BIT(26) /* PHY FIFO Reset */ +#define MPHY_PGCR1 (0x003 << MPHY_SHIFT) +#define MPHY_PGCR1_INHVT BIT(26) /* VT Calculation Inhibit */ +#define MPHY_PGCR2 (0x004 << MPHY_SHIFT) +#define MPHY_PGCR2_DUALCHN BIT(28) /* Dual Channel Configuration*/ +#define MPHY_PGCR2_ACPDDC BIT(29) /* AC Power-Down with Dual Ch*/ +#define MPHY_PGCR3 (0x005 << MPHY_SHIFT) +#define MPHY_PGSR0 (0x006 << MPHY_SHIFT) +#define MPHY_PGSR0_IDONE BIT(0) /* Initialization Done */ +#define MPHY_PGSR0_PLDONE BIT(1) /* PLL Lock Done */ +#define MPHY_PGSR0_DCDONE BIT(2) /* DDL Calibration Done */ +#define MPHY_PGSR0_ZCDONE BIT(3) /* Impedance Calibration Done */ +#define MPHY_PGSR0_DIDONE BIT(4) /* DRAM Initialization Done */ +#define MPHY_PGSR0_WLDONE BIT(5) /* Write Leveling Done */ +#define MPHY_PGSR0_QSGDONE BIT(6) /* DQS Gate Training Done */ +#define MPHY_PGSR0_WLADONE BIT(7) /* Write Leveling Adjust Done */ +#define MPHY_PGSR0_RDDONE BIT(8) /* Read Bit Deskew Done */ +#define MPHY_PGSR0_WDDONE BIT(9) /* Write Bit Deskew Done */ +#define MPHY_PGSR0_REDONE BIT(10) /* Read Eye Training Done */ +#define MPHY_PGSR0_WEDONE BIT(11) /* Write Eye Training Done */ +#define MPHY_PGSR0_ZCERR BIT(20) /* Impedance Calib Error */ +#define MPHY_PGSR0_WLERR BIT(21) /* Write Leveling Error */ +#define MPHY_PGSR0_QSGERR BIT(22) /* DQS Gate Training Error */ +#define MPHY_PGSR0_WLAERR BIT(23) /* Write Leveling Adj Error */ +#define MPHY_PGSR0_RDERR BIT(24) /* Read Bit Deskew Error */ +#define MPHY_PGSR0_WDERR BIT(25) /* Write Bit Deskew Error */ +#define MPHY_PGSR0_REERR BIT(26) /* Read Eye Training Error */ +#define MPHY_PGSR0_WEERR BIT(27) /* Write Eye Training Error */ +#define MPHY_PGSR1 (0x007 << MPHY_SHIFT) +#define MPHY_PGSR1_VTSTOP BIT(30) /* VT Stop */ +#define MPHY_PLLCR (0x008 << MPHY_SHIFT) +#define MPHY_PTR0 (0x009 << MPHY_SHIFT) +#define MPHY_PTR1 (0x00A << MPHY_SHIFT) +#define MPHY_PTR2 (0x00B << MPHY_SHIFT) +#define MPHY_PTR3 (0x00C << MPHY_SHIFT) +#define MPHY_PTR4 (0x00D << MPHY_SHIFT) +#define MPHY_ACMDLR (0x00E << MPHY_SHIFT) +#define MPHY_ACLCDLR (0x00F << MPHY_SHIFT) +#define MPHY_ACBDLR0 (0x010 << MPHY_SHIFT) +#define MPHY_ACBDLR1 (0x011 << MPHY_SHIFT) +#define MPHY_ACBDLR2 (0x012 << MPHY_SHIFT) +#define MPHY_ACBDLR3 (0x013 << MPHY_SHIFT) +#define MPHY_ACBDLR4 (0x014 << MPHY_SHIFT) +#define MPHY_ACBDLR5 (0x015 << MPHY_SHIFT) +#define MPHY_ACBDLR6 (0x016 << MPHY_SHIFT) +#define MPHY_ACBDLR7 (0x017 << MPHY_SHIFT) +#define MPHY_ACBDLR8 (0x018 << MPHY_SHIFT) +#define MPHY_ACBDLR9 (0x019 << MPHY_SHIFT) +#define MPHY_ACIOCR0 (0x01A << MPHY_SHIFT) +#define MPHY_ACIOCR1 (0x01B << MPHY_SHIFT) +#define MPHY_ACIOCR2 (0x01C << MPHY_SHIFT) +#define MPHY_ACIOCR3 (0x01D << MPHY_SHIFT) +#define MPHY_ACIOCR4 (0x01E << MPHY_SHIFT) +#define MPHY_ACIOCR5 (0x01F << MPHY_SHIFT) +#define MPHY_DXCCR (0x020 << MPHY_SHIFT) +#define MPHY_DSGCR (0x021 << MPHY_SHIFT) +#define MPHY_DCR (0x022 << MPHY_SHIFT) +#define MPHY_DTPR0 (0x023 << MPHY_SHIFT) +#define MPHY_DTPR1 (0x024 << MPHY_SHIFT) +#define MPHY_DTPR2 (0x025 << MPHY_SHIFT) +#define MPHY_DTPR3 (0x026 << MPHY_SHIFT) +#define MPHY_MR0 (0x027 << MPHY_SHIFT) +#define MPHY_MR1 (0x028 << MPHY_SHIFT) +#define MPHY_MR2 (0x029 << MPHY_SHIFT) +#define MPHY_MR3 (0x02A << MPHY_SHIFT) +#define MPHY_ODTCR (0x02B << MPHY_SHIFT) +#define MPHY_DTCR (0x02C << MPHY_SHIFT) +#define MPHY_DTCR_RANKEN_SHIFT 24 /* Rank Enable */ +#define MPHY_DTCR_RANKEN_MASK (0xf << (MPHY_DTCR_RANKEN_SHIFT)) +#define MPHY_DTAR0 (0x02D << MPHY_SHIFT) +#define MPHY_DTAR1 (0x02E << MPHY_SHIFT) +#define MPHY_DTAR2 (0x02F << MPHY_SHIFT) +#define MPHY_DTAR3 (0x030 << MPHY_SHIFT) +#define MPHY_DTDR0 (0x031 << MPHY_SHIFT) +#define MPHY_DTDR1 (0x032 << MPHY_SHIFT) +#define MPHY_DTEDR0 (0x033 << MPHY_SHIFT) +#define MPHY_DTEDR1 (0x034 << MPHY_SHIFT) +#define MPHY_ZQCR (0x090 << MPHY_SHIFT) +#define MPHY_ZQCR_AVGEN BIT(16) /* Average Algorithm */ +#define MPHY_ZQCR_FORCE_ZCAL_VT_UPDATE BIT(27) /* force VT update */ +/* ZQ */ +#define MPHY_ZQ_BASE (0x091 << MPHY_SHIFT) +#define MPHY_ZQ_STRIDE (0x004 << MPHY_SHIFT) +#define MPHY_ZQ_PR (0x000 << MPHY_SHIFT) +#define MPHY_ZQ_DR (0x001 << MPHY_SHIFT) +#define MPHY_ZQ_SR (0x002 << MPHY_SHIFT) +/* DATX8 */ +#define MPHY_DX_BASE (0x0A0 << MPHY_SHIFT) +#define MPHY_DX_STRIDE (0x020 << MPHY_SHIFT) +#define MPHY_DX_GCR0 (0x000 << MPHY_SHIFT) +#define MPHY_DX_GCR0_WLRKEN_SHIFT 26 /* Write Level Rank Enable */ +#define MPHY_DX_GCR0_WLRKEN_MASK (0xf << (MPHY_DX_GCR0_WLRKEN_SHIFT)) +#define MPHY_DX_GCR1 (0x001 << MPHY_SHIFT) +#define MPHY_DX_GCR2 (0x002 << MPHY_SHIFT) +#define MPHY_DX_GCR3 (0x003 << MPHY_SHIFT) +#define MPHY_DX_GSR0 (0x004 << MPHY_SHIFT) +#define MPHY_DX_GSR1 (0x005 << MPHY_SHIFT) +#define MPHY_DX_GSR2 (0x006 << MPHY_SHIFT) +#define MPHY_DX_BDLR0 (0x007 << MPHY_SHIFT) +#define MPHY_DX_BDLR1 (0x008 << MPHY_SHIFT) +#define MPHY_DX_BDLR2 (0x009 << MPHY_SHIFT) +#define MPHY_DX_BDLR3 (0x00A << MPHY_SHIFT) +#define MPHY_DX_BDLR4 (0x00B << MPHY_SHIFT) +#define MPHY_DX_BDLR5 (0x00C << MPHY_SHIFT) +#define MPHY_DX_BDLR6 (0x00D << MPHY_SHIFT) +#define MPHY_DX_LCDLR0 (0x00E << MPHY_SHIFT) +#define MPHY_DX_LCDLR1 (0x00F << MPHY_SHIFT) +#define MPHY_DX_LCDLR2 (0x010 << MPHY_SHIFT) +#define MPHY_DX_MDLR (0x011 << MPHY_SHIFT) +#define MPHY_DX_GTR (0x012 << MPHY_SHIFT) + +#endif /* UNIPHIER_DDRMPHY_REGS_H */ diff --git a/roms/u-boot/arch/arm/mach-uniphier/dram/ddrphy-init.h b/roms/u-boot/arch/arm/mach-uniphier/dram/ddrphy-init.h new file mode 100644 index 000000000..09981f6e0 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/dram/ddrphy-init.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2016 Socionext Inc. + */ + +#ifndef ARCH_DDRPHY_INIT_H +#define ARCH_DDRPHY_INTT_H + +#include <linux/compiler.h> +#include <linux/types.h> + +int uniphier_ld4_ddrphy_init(void __iomem *phy_base, int freq, bool ddr3plus); +void ddrphy_prepare_training(void __iomem *phy_base, int rank); +int ddrphy_training(void __iomem *phy_base); + +#endif /* ARCH_DDRPHY_INT_H */ diff --git a/roms/u-boot/arch/arm/mach-uniphier/dram/ddrphy-ld4.c b/roms/u-boot/arch/arm/mach-uniphier/dram/ddrphy-ld4.c new file mode 100644 index 000000000..26f3ba9d5 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/dram/ddrphy-ld4.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + */ + +#include <linux/bitops.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/printk.h> + +#include "ddrphy-init.h" +#include "ddrphy-regs.h" + +enum dram_freq { + DRAM_FREQ_1333M, + DRAM_FREQ_1600M, + DRAM_FREQ_NR, +}; + +static u32 ddrphy_ptr0[DRAM_FREQ_NR] = {0x0a806844, 0x0c807d04}; +static u32 ddrphy_ptr1[DRAM_FREQ_NR] = {0x208e0124, 0x2710015E}; +static u32 ddrphy_ptr3[DRAM_FREQ_NR] = {0x0f051616, 0x12061A80}; +static u32 ddrphy_ptr4[DRAM_FREQ_NR] = {0x06ae08d6, 0x08027100}; +static u32 ddrphy_dtpr0[DRAM_FREQ_NR] = {0x85589955, 0x999cbb66}; +static u32 ddrphy_dtpr1[DRAM_FREQ_NR] = {0x1a8363c0, 0x1a878400}; +static u32 ddrphy_dtpr2[DRAM_FREQ_NR] = {0x5002c200, 0xa00214f8}; +static u32 ddrphy_mr0[DRAM_FREQ_NR] = {0x00000b51, 0x00000d71}; +static u32 ddrphy_mr2[DRAM_FREQ_NR] = {0x00000290, 0x00000298}; + +int uniphier_ld4_ddrphy_init(void __iomem *phy_base, int freq, bool ddr3plus) +{ + enum dram_freq freq_e; + u32 tmp; + + switch (freq) { + case 1333: + freq_e = DRAM_FREQ_1333M; + break; + case 1600: + freq_e = DRAM_FREQ_1600M; + break; + default: + pr_err("unsupported DRAM frequency %d MHz\n", freq); + return -EINVAL; + } + + writel(0x0300c473, phy_base + PHY_PGCR1); + writel(ddrphy_ptr0[freq_e], phy_base + PHY_PTR0); + writel(ddrphy_ptr1[freq_e], phy_base + PHY_PTR1); + writel(0x00083DEF, phy_base + PHY_PTR2); + writel(ddrphy_ptr3[freq_e], phy_base + PHY_PTR3); + writel(ddrphy_ptr4[freq_e], phy_base + PHY_PTR4); + writel(0xF004001A, phy_base + PHY_DSGCR); + + /* change the value of the on-die pull-up/pull-down registors */ + tmp = readl(phy_base + PHY_DXCCR); + tmp &= ~0x0ee0; + tmp |= PHY_DXCCR_DQSNRES_688_OHM | PHY_DXCCR_DQSRES_688_OHM; + writel(tmp, phy_base + PHY_DXCCR); + + writel(0x0000040B, phy_base + PHY_DCR); + writel(ddrphy_dtpr0[freq_e], phy_base + PHY_DTPR0); + writel(ddrphy_dtpr1[freq_e], phy_base + PHY_DTPR1); + writel(ddrphy_dtpr2[freq_e], phy_base + PHY_DTPR2); + writel(ddrphy_mr0[freq_e], phy_base + PHY_MR0); + writel(0x00000006, phy_base + PHY_MR1); + writel(ddrphy_mr2[freq_e], phy_base + PHY_MR2); + writel(ddr3plus ? 0x00000800 : 0x00000000, phy_base + PHY_MR3); + + while (!(readl(phy_base + PHY_PGSR0) & PHY_PGSR0_IDONE)) + ; + + writel(0x0300C473, phy_base + PHY_PGCR1); + writel(0x0000005D, phy_base + PHY_ZQ_BASE + PHY_ZQ_CR1); + + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/dram/ddrphy-regs.h b/roms/u-boot/arch/arm/mach-uniphier/dram/ddrphy-regs.h new file mode 100644 index 000000000..8b342921b --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/dram/ddrphy-regs.h @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * UniPhier DDR PHY registers + * + * Copyright (C) 2014 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + */ + +#ifndef ARCH_DDRPHY_REGS_H +#define ARCH_DDRPHY_REGS_H + +#include <linux/bitops.h> +#define PHY_REG_SHIFT 2 + +#define PHY_RIDR (0x000 << PHY_REG_SHIFT) +#define PHY_PIR (0x001 << PHY_REG_SHIFT) +#define PHY_PIR_INIT BIT(0) /* Initialization Trigger */ +#define PHY_PIR_ZCAL BIT(1) /* Impedance Calibration */ +#define PHY_PIR_PLLINIT BIT(4) /* PLL Initialization */ +#define PHY_PIR_DCAL BIT(5) /* DDL Calibration */ +#define PHY_PIR_PHYRST BIT(6) /* PHY Reset */ +#define PHY_PIR_DRAMRST BIT(7) /* DRAM Reset */ +#define PHY_PIR_DRAMINIT BIT(8) /* DRAM Initialization */ +#define PHY_PIR_WL BIT(9) /* Write Leveling */ +#define PHY_PIR_QSGATE BIT(10) /* Read DQS Gate Training */ +#define PHY_PIR_WLADJ BIT(11) /* Write Leveling Adjust */ +#define PHY_PIR_RDDSKW BIT(12) /* Read Data Bit Deskew */ +#define PHY_PIR_WRDSKW BIT(13) /* Write Data Bit Deskew */ +#define PHY_PIR_RDEYE BIT(14) /* Read Data Eye Training */ +#define PHY_PIR_WREYE BIT(15) /* Write Data Eye Training */ +#define PHY_PIR_LOCKBYP BIT(28) /* PLL Lock Bypass */ +#define PHY_PIR_DCALBYP BIT(29) /* DDL Calibration Bypass */ +#define PHY_PIR_ZCALBYP BIT(30) /* Impedance Calib Bypass */ +#define PHY_PIR_INITBYP BIT(31) /* Initialization Bypass */ +#define PHY_PGCR0 (0x002 << PHY_REG_SHIFT) +#define PHY_PGCR1 (0x003 << PHY_REG_SHIFT) +#define PHY_PGCR1_INHVT BIT(26) /* VT Calculation Inhibit */ +#define PHY_PGSR0 (0x004 << PHY_REG_SHIFT) +#define PHY_PGSR0_IDONE BIT(0) /* Initialization Done */ +#define PHY_PGSR0_PLDONE BIT(1) /* PLL Lock Done */ +#define PHY_PGSR0_DCDONE BIT(2) /* DDL Calibration Done */ +#define PHY_PGSR0_ZCDONE BIT(3) /* Impedance Calibration Done */ +#define PHY_PGSR0_DIDONE BIT(4) /* DRAM Initialization Done */ +#define PHY_PGSR0_WLDONE BIT(5) /* Write Leveling Done */ +#define PHY_PGSR0_QSGDONE BIT(6) /* DQS Gate Training Done */ +#define PHY_PGSR0_WLADONE BIT(7) /* Write Leveling Adjust Done */ +#define PHY_PGSR0_RDDONE BIT(8) /* Read Bit Deskew Done */ +#define PHY_PGSR0_WDDONE BIT(9) /* Write Bit Deskew Done */ +#define PHY_PGSR0_REDONE BIT(10) /* Read Eye Training Done */ +#define PHY_PGSR0_WEDONE BIT(11) /* Write Eye Training Done */ +#define PHY_PGSR0_DIERR BIT(20) /* DRAM Initialization Error */ +#define PHY_PGSR0_WLERR BIT(21) /* Write Leveling Error */ +#define PHY_PGSR0_QSGERR BIT(22) /* DQS Gate Training Error */ +#define PHY_PGSR0_WLAERR BIT(23) /* Write Leveling Adj Error */ +#define PHY_PGSR0_RDERR BIT(24) /* Read Bit Deskew Error */ +#define PHY_PGSR0_WDERR BIT(25) /* Write Bit Deskew Error */ +#define PHY_PGSR0_REERR BIT(26) /* Read Eye Training Error */ +#define PHY_PGSR0_WEERR BIT(27) /* Write Eye Training Error */ +#define PHY_PGSR0_DTERR_SHIFT 28 /* Data Training Error Status*/ +#define PHY_PGSR0_DTERR (7 << (PHY_PGSR0_DTERR_SHIFT)) +#define PHY_PGSR1 (0x005 << PHY_REG_SHIFT) +#define PHY_PGSR1_VTSTOP BIT(30) /* VT Stop (v3-) */ +#define PHY_PLLCR (0x006 << PHY_REG_SHIFT) +#define PHY_PTR0 (0x007 << PHY_REG_SHIFT) +#define PHY_PTR1 (0x008 << PHY_REG_SHIFT) +#define PHY_PTR2 (0x009 << PHY_REG_SHIFT) +#define PHY_PTR3 (0x00A << PHY_REG_SHIFT) +#define PHY_PTR4 (0x00B << PHY_REG_SHIFT) +#define PHY_ACMDLR (0x00C << PHY_REG_SHIFT) +#define PHY_ACBDLR (0x00D << PHY_REG_SHIFT) +#define PHY_ACIOCR (0x00E << PHY_REG_SHIFT) +#define PHY_DXCCR (0x00F << PHY_REG_SHIFT) +#define PHY_DXCCR_DQSRES_OPEN (0 << 5) +#define PHY_DXCCR_DQSRES_688_OHM (1 << 5) +#define PHY_DXCCR_DQSRES_611_OHM (2 << 5) +#define PHY_DXCCR_DQSRES_550_OHM (3 << 5) +#define PHY_DXCCR_DQSRES_500_OHM (4 << 5) +#define PHY_DXCCR_DQSRES_458_OHM (5 << 5) +#define PHY_DXCCR_DQSRES_393_OHM (6 << 5) +#define PHY_DXCCR_DQSRES_344_OHM (7 << 5) +#define PHY_DXCCR_DQSNRES_OPEN (0 << 9) +#define PHY_DXCCR_DQSNRES_688_OHM (1 << 9) +#define PHY_DXCCR_DQSNRES_611_OHM (2 << 9) +#define PHY_DXCCR_DQSNRES_550_OHM (3 << 9) +#define PHY_DXCCR_DQSNRES_500_OHM (4 << 9) +#define PHY_DXCCR_DQSNRES_458_OHM (5 << 9) +#define PHY_DXCCR_DQSNRES_393_OHM (6 << 9) +#define PHY_DXCCR_DQSNRES_344_OHM (7 << 9) +#define PHY_DSGCR (0x010 << PHY_REG_SHIFT) +#define PHY_DCR (0x011 << PHY_REG_SHIFT) +#define PHY_DTPR0 (0x012 << PHY_REG_SHIFT) +#define PHY_DTPR1 (0x013 << PHY_REG_SHIFT) +#define PHY_DTPR2 (0x014 << PHY_REG_SHIFT) +#define PHY_MR0 (0x015 << PHY_REG_SHIFT) +#define PHY_MR1 (0x016 << PHY_REG_SHIFT) +#define PHY_MR2 (0x017 << PHY_REG_SHIFT) +#define PHY_MR3 (0x018 << PHY_REG_SHIFT) +#define PHY_ODTCR (0x019 << PHY_REG_SHIFT) +#define PHY_DTCR (0x01A << PHY_REG_SHIFT) +#define PHY_DTCR_DTRANK_SHIFT 4 /* Data Training Rank */ +#define PHY_DTCR_DTRANK_MASK (0x3 << (PHY_DTCR_DTRANK_SHIFT)) +#define PHY_DTCR_DTMPR BIT(6) /* Data Training using MPR */ +#define PHY_DTCR_RANKEN_SHIFT 24 /* Rank Enable */ +#define PHY_DTCR_RANKEN_MASK (0xf << (PHY_DTCR_RANKEN_SHIFT)) +#define PHY_DTAR0 (0x01B << PHY_REG_SHIFT) +#define PHY_DTAR1 (0x01C << PHY_REG_SHIFT) +#define PHY_DTAR2 (0x01D << PHY_REG_SHIFT) +#define PHY_DTAR3 (0x01E << PHY_REG_SHIFT) +#define PHY_DTDR0 (0x01F << PHY_REG_SHIFT) +#define PHY_DTDR1 (0x020 << PHY_REG_SHIFT) +#define PHY_DTEDR0 (0x021 << PHY_REG_SHIFT) +#define PHY_DTEDR1 (0x022 << PHY_REG_SHIFT) +#define PHY_PGCR2 (0x023 << PHY_REG_SHIFT) +#define PHY_GPR0 (0x05E << PHY_REG_SHIFT) +#define PHY_GPR1 (0x05F << PHY_REG_SHIFT) +/* ZQ */ +#define PHY_ZQ_BASE (0x060 << PHY_REG_SHIFT) +#define PHY_ZQ_STRIDE (0x004 << PHY_REG_SHIFT) +#define PHY_ZQ_CR0 (0x000 << PHY_REG_SHIFT) +#define PHY_ZQ_CR1 (0x001 << PHY_REG_SHIFT) +#define PHY_ZQ_SR0 (0x002 << PHY_REG_SHIFT) +#define PHY_ZQ_SR1 (0x003 << PHY_REG_SHIFT) +/* DATX8 */ +#define PHY_DX_BASE (0x070 << PHY_REG_SHIFT) +#define PHY_DX_STRIDE (0x010 << PHY_REG_SHIFT) +#define PHY_DX_GCR (0x000 << PHY_REG_SHIFT) +#define PHY_DX_GCR_WLRKEN_SHIFT 26 /* Write Level Rank Enable */ +#define PHY_DX_GCR_WLRKEN_MASK (0xf << (PHY_DX_GCR_WLRKEN_SHIFT)) +#define PHY_DX_GSR0 (0x001 << PHY_REG_SHIFT) +#define PHY_DX_GSR1 (0x002 << PHY_REG_SHIFT) +#define PHY_DX_BDLR0 (0x003 << PHY_REG_SHIFT) +#define PHY_DX_BDLR1 (0x004 << PHY_REG_SHIFT) +#define PHY_DX_BDLR2 (0x005 << PHY_REG_SHIFT) +#define PHY_DX_BDLR3 (0x006 << PHY_REG_SHIFT) +#define PHY_DX_BDLR4 (0x007 << PHY_REG_SHIFT) +#define PHY_DX_LCDLR0 (0x008 << PHY_REG_SHIFT) +#define PHY_DX_LCDLR1 (0x009 << PHY_REG_SHIFT) +#define PHY_DX_LCDLR2 (0x00A << PHY_REG_SHIFT) +#define PHY_DX_MDLR (0x00B << PHY_REG_SHIFT) +#define PHY_DX_GTR (0x00C << PHY_REG_SHIFT) +#define PHY_DX_GSR2 (0x00D << PHY_REG_SHIFT) + +#endif /* ARCH_DDRPHY_REGS_H */ diff --git a/roms/u-boot/arch/arm/mach-uniphier/dram/ddrphy-training.c b/roms/u-boot/arch/arm/mach-uniphier/dram/ddrphy-training.c new file mode 100644 index 000000000..1decdf1cb --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/dram/ddrphy-training.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011-2014 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + */ + +#include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/printk.h> +#include <time.h> + +#include "ddrphy-init.h" +#include "ddrphy-regs.h" + +/* for LD4, Pro4, sLD8 */ +#define NR_DATX8_PER_DDRPHY 2 + +void ddrphy_prepare_training(void __iomem *phy_base, int rank) +{ + void __iomem *dx_base = phy_base + PHY_DX_BASE; + int dx; + u32 tmp; + + for (dx = 0; dx < NR_DATX8_PER_DDRPHY; dx++) { + tmp = readl(dx_base + PHY_DX_GCR); + /* Specify the rank that should be write leveled */ + tmp &= ~PHY_DX_GCR_WLRKEN_MASK; + tmp |= (1 << (PHY_DX_GCR_WLRKEN_SHIFT + rank)) & + PHY_DX_GCR_WLRKEN_MASK; + writel(tmp, dx_base + PHY_DX_GCR); + dx_base += PHY_DX_STRIDE; + } + + tmp = readl(phy_base + PHY_DTCR); + /* Specify the rank used during data bit deskew and eye centering */ + tmp &= ~PHY_DTCR_DTRANK_MASK; + tmp |= (rank << PHY_DTCR_DTRANK_SHIFT) & PHY_DTCR_DTRANK_MASK; + /* Use Multi-Purpose Register for DQS gate training */ + tmp |= PHY_DTCR_DTMPR; + /* Specify the rank enabled for data-training */ + tmp &= ~PHY_DTCR_RANKEN_MASK; + tmp |= (1 << (PHY_DTCR_RANKEN_SHIFT + rank)) & PHY_DTCR_RANKEN_MASK; + writel(tmp, phy_base + PHY_DTCR); +} + +struct ddrphy_init_sequence { + char *description; + u32 init_flag; + u32 done_flag; + u32 err_flag; +}; + +static const struct ddrphy_init_sequence init_sequence[] = { + { + "DRAM Initialization", + PHY_PIR_DRAMRST | PHY_PIR_DRAMINIT, + PHY_PGSR0_DIDONE, + PHY_PGSR0_DIERR + }, + { + "Write Leveling", + PHY_PIR_WL, + PHY_PGSR0_WLDONE, + PHY_PGSR0_WLERR + }, + { + "Read DQS Gate Training", + PHY_PIR_QSGATE, + PHY_PGSR0_QSGDONE, + PHY_PGSR0_QSGERR + }, + { + "Write Leveling Adjustment", + PHY_PIR_WLADJ, + PHY_PGSR0_WLADONE, + PHY_PGSR0_WLAERR + }, + { + "Read Bit Deskew", + PHY_PIR_RDDSKW, + PHY_PGSR0_RDDONE, + PHY_PGSR0_RDERR + }, + { + "Write Bit Deskew", + PHY_PIR_WRDSKW, + PHY_PGSR0_WDDONE, + PHY_PGSR0_WDERR + }, + { + "Read Eye Training", + PHY_PIR_RDEYE, + PHY_PGSR0_REDONE, + PHY_PGSR0_REERR + }, + { + "Write Eye Training", + PHY_PIR_WREYE, + PHY_PGSR0_WEDONE, + PHY_PGSR0_WEERR + } +}; + +int ddrphy_training(void __iomem *phy_base) +{ + int i; + u32 pgsr0; + u32 init_flag = PHY_PIR_INIT; + u32 done_flag = PHY_PGSR0_IDONE; + int timeout = 50000; /* 50 msec is long enough */ +#ifdef DEBUG + ulong start = get_timer(0); +#endif + + for (i = 0; i < ARRAY_SIZE(init_sequence); i++) { + init_flag |= init_sequence[i].init_flag; + done_flag |= init_sequence[i].done_flag; + } + + writel(init_flag, phy_base + PHY_PIR); + + do { + if (--timeout < 0) { + pr_err("timeout during DDR training\n"); + return -ETIMEDOUT; + } + udelay(1); + pgsr0 = readl(phy_base + PHY_PGSR0); + } while ((pgsr0 & done_flag) != done_flag); + + for (i = 0; i < ARRAY_SIZE(init_sequence); i++) { + if (pgsr0 & init_sequence[i].err_flag) { + pr_err("%s failed\n", init_sequence[i].description); + return -EIO; + } + } + +#ifdef DEBUG + pr_debug("DDR training: elapsed time %ld msec\n", get_timer(start)); +#endif + + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/dram/umc-ld4.c b/roms/u-boot/arch/arm/mach-uniphier/dram/umc-ld4.c new file mode 100644 index 000000000..96acca256 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/dram/umc-ld4.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011-2014 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/sizes.h> +#include <asm/processor.h> + +#include "../init.h" +#include "ddrphy-init.h" +#include "umc-regs.h" + +#define DRAM_CH_NR 2 + +enum dram_freq { + DRAM_FREQ_1333M, + DRAM_FREQ_1600M, + DRAM_FREQ_NR, +}; + +enum dram_size { + DRAM_SZ_128M, + DRAM_SZ_256M, + DRAM_SZ_NR, +}; + +static u32 umc_cmdctla_plus[DRAM_FREQ_NR] = {0x45990b11, 0x36bb0f17}; +static u32 umc_cmdctlb_plus[DRAM_FREQ_NR] = {0x16958924, 0x18c6aa24}; +static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = { + {0x00240512, 0x00350512}, + {0x002b0617, 0x003f0617}, +}; +static u32 umc_spcctlb[DRAM_FREQ_NR] = {0x00ff0006, 0x00ff0008}; +static u32 umc_rdatactl[DRAM_FREQ_NR] = {0x000a00ac, 0x000c00ae}; + +static int umc_get_rank(int ch) +{ + return ch; /* ch0: rank0, ch1: rank1 for this SoC */ +} + +static void umc_start_ssif(void __iomem *ssif_base) +{ + writel(0x00000000, ssif_base + 0x0000b004); + writel(0xffffffff, ssif_base + 0x0000c004); + writel(0x000fffcf, ssif_base + 0x0000c008); + writel(0x00000001, ssif_base + 0x0000b000); + writel(0x00000001, ssif_base + 0x0000c000); + writel(0x03010101, ssif_base + UMC_MDMCHSEL); + writel(0x03010100, ssif_base + UMC_DMDCHSEL); + + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_FETCH); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMQUE0); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMWC0); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMRC0); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMQUE1); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMWC1); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMRC1); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_WC); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_RC); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_DST); + + writel(0x00000001, ssif_base + UMC_CPURST); + writel(0x00000001, ssif_base + UMC_IDSRST); + writel(0x00000001, ssif_base + UMC_IXMRST); + writel(0x00000001, ssif_base + UMC_MDMRST); + writel(0x00000001, ssif_base + UMC_MDDRST); + writel(0x00000001, ssif_base + UMC_SIORST); + writel(0x00000001, ssif_base + UMC_VIORST); + writel(0x00000001, ssif_base + UMC_FRCRST); + writel(0x00000001, ssif_base + UMC_RGLRST); + writel(0x00000001, ssif_base + UMC_AIORST); + writel(0x00000001, ssif_base + UMC_DMDRST); +} + +static int umc_dramcont_init(void __iomem *dc_base, void __iomem *ca_base, + int freq, unsigned long size, bool ddr3plus) +{ + enum dram_freq freq_e; + enum dram_size size_e; + + if (!ddr3plus) { + pr_err("DDR3 standard is not supported\n"); + return -EINVAL; + } + + switch (freq) { + case 1333: + freq_e = DRAM_FREQ_1333M; + break; + case 1600: + freq_e = DRAM_FREQ_1600M; + break; + default: + pr_err("unsupported DRAM frequency %d MHz\n", freq); + return -EINVAL; + } + + switch (size) { + case 0: + return 0; + case SZ_128M: + size_e = DRAM_SZ_128M; + break; + case SZ_256M: + size_e = DRAM_SZ_256M; + break; + default: + pr_err("unsupported DRAM size 0x%08lx\n", size); + return -EINVAL; + } + + writel(umc_cmdctla_plus[freq_e], dc_base + UMC_CMDCTLA); + writel(umc_cmdctlb_plus[freq_e], dc_base + UMC_CMDCTLB); + writel(umc_spcctla[freq_e][size_e], dc_base + UMC_SPCCTLA); + writel(umc_spcctlb[freq_e], dc_base + UMC_SPCCTLB); + writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D0); + writel(0x04060806, dc_base + UMC_WDATACTL_D0); + writel(0x04a02000, dc_base + UMC_DATASET); + writel(0x00000000, ca_base + 0x2300); + writel(0x00400020, dc_base + UMC_DCCGCTL); + writel(0x00000003, dc_base + 0x7000); + writel(0x0000000f, dc_base + 0x8000); + writel(0x000000c3, dc_base + 0x8004); + writel(0x00000071, dc_base + 0x8008); + writel(0x0000003b, dc_base + UMC_DICGCTLA); + writel(0x020a0808, dc_base + UMC_DICGCTLB); + writel(0x00000004, dc_base + UMC_FLOWCTLG); + writel(0x80000201, ca_base + 0xc20); + writel(0x0801e01e, dc_base + UMC_FLOWCTLA); + writel(0x00200000, dc_base + UMC_FLOWCTLB); + writel(0x00004444, dc_base + UMC_FLOWCTLC); + writel(0x200a0a00, dc_base + UMC_SPCSETB); + writel(0x00000000, dc_base + UMC_SPCSETD); + writel(0x00000520, dc_base + UMC_DFICUPDCTLA); + + return 0; +} + +static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base, + int freq, unsigned long size, bool ddr3plus, int ch) +{ + void __iomem *phy_base = dc_base + 0x00001000; + int ret; + + writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET); + while (readl(dc_base + UMC_INITSTAT) & UMC_INITSTAT_INIT1ST) + cpu_relax(); + + writel(0x00000101, dc_base + UMC_DIOCTLA); + + ret = uniphier_ld4_ddrphy_init(phy_base, freq, ddr3plus); + if (ret) + return ret; + + ddrphy_prepare_training(phy_base, umc_get_rank(ch)); + ret = ddrphy_training(phy_base); + if (ret) + return ret; + + return umc_dramcont_init(dc_base, ca_base, freq, size, ddr3plus); +} + +int uniphier_ld4_umc_init(const struct uniphier_board_data *bd) +{ + void __iomem *umc_base = (void __iomem *)0x5b800000; + void __iomem *ca_base = umc_base + 0x00001000; + void __iomem *dc_base = umc_base + 0x00400000; + void __iomem *ssif_base = umc_base; + int ch, ret; + + for (ch = 0; ch < DRAM_CH_NR; ch++) { + ret = umc_ch_init(dc_base, ca_base, bd->dram_freq, + bd->dram_ch[ch].size, + !!(bd->flags & UNIPHIER_BD_DDR3PLUS), ch); + if (ret) { + pr_err("failed to initialize UMC ch%d\n", ch); + return ret; + } + + ca_base += 0x00001000; + dc_base += 0x00200000; + } + + umc_start_ssif(ssif_base); + + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/dram/umc-pro4.c b/roms/u-boot/arch/arm/mach-uniphier/dram/umc-pro4.c new file mode 100644 index 000000000..cde39b499 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/dram/umc-pro4.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011-2014 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/sizes.h> +#include <asm/processor.h> + +#include "../init.h" +#include "ddrphy-init.h" +#include "umc-regs.h" + +#define DRAM_CH_NR 2 + +enum dram_size { + DRAM_SZ_128M, + DRAM_SZ_256M, + DRAM_SZ_512M, + DRAM_SZ_NR, +}; + +static u32 umc_spcctla[DRAM_SZ_NR] = {0x002b0617, 0x003f0617, 0x00770617}; + +static void umc_start_ssif(void __iomem *ssif_base) +{ + writel(0x00000000, ssif_base + 0x0000b004); + writel(0xffffffff, ssif_base + 0x0000c004); + writel(0x000fffcf, ssif_base + 0x0000c008); + writel(0x00000001, ssif_base + 0x0000b000); + writel(0x00000001, ssif_base + 0x0000c000); + + writel(0x03010100, ssif_base + UMC_HDMCHSEL); + writel(0x03010101, ssif_base + UMC_MDMCHSEL); + writel(0x03010100, ssif_base + UMC_DVCCHSEL); + writel(0x03010100, ssif_base + UMC_DMDCHSEL); + + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_FETCH); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMQUE0); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMWC0); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMRC0); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMQUE1); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMWC1); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMRC1); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_WC); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_RC); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_DST); + writel(0x00000000, ssif_base + 0x0000c044); /* DCGIV_SSIF_REG */ + + writel(0x00000001, ssif_base + UMC_CPURST); + writel(0x00000001, ssif_base + UMC_IDSRST); + writel(0x00000001, ssif_base + UMC_IXMRST); + writel(0x00000001, ssif_base + UMC_HDMRST); + writel(0x00000001, ssif_base + UMC_MDMRST); + writel(0x00000001, ssif_base + UMC_HDDRST); + writel(0x00000001, ssif_base + UMC_MDDRST); + writel(0x00000001, ssif_base + UMC_SIORST); + writel(0x00000001, ssif_base + UMC_GIORST); + writel(0x00000001, ssif_base + UMC_HD2RST); + writel(0x00000001, ssif_base + UMC_VIORST); + writel(0x00000001, ssif_base + UMC_DVCRST); + writel(0x00000001, ssif_base + UMC_RGLRST); + writel(0x00000001, ssif_base + UMC_VPERST); + writel(0x00000001, ssif_base + UMC_AIORST); + writel(0x00000001, ssif_base + UMC_DMDRST); +} + +static int umc_dramcont_init(void __iomem *dc_base, void __iomem *ca_base, + int freq, unsigned long size, bool ddr3plus) +{ + enum dram_size size_e; + + if (freq != 1600) { + pr_err("Unsupported DDR frequency %d MHz\n", freq); + return -EINVAL; + } + + if (ddr3plus) { + pr_err("DDR3+ is not supported\n"); + return -EINVAL; + } + + switch (size) { + case SZ_128M: + size_e = DRAM_SZ_128M; + break; + case SZ_256M: + size_e = DRAM_SZ_256M; + break; + case SZ_512M: + size_e = DRAM_SZ_512M; + break; + default: + pr_err("unsupported DRAM size 0x%08lx (per 16bit)\n", size); + return -EINVAL; + } + + writel(0x66bb0f17, dc_base + UMC_CMDCTLA); + writel(0x18c6aa44, dc_base + UMC_CMDCTLB); + writel(umc_spcctla[size_e], dc_base + UMC_SPCCTLA); + writel(0x00ff0008, dc_base + UMC_SPCCTLB); + writel(0x000c00ae, dc_base + UMC_RDATACTL_D0); + writel(0x000c00ae, dc_base + UMC_RDATACTL_D1); + writel(0x04060802, dc_base + UMC_WDATACTL_D0); + writel(0x04060802, dc_base + UMC_WDATACTL_D1); + writel(0x04a02000, dc_base + UMC_DATASET); + writel(0x00000000, ca_base + 0x2300); + writel(0x00400020, dc_base + UMC_DCCGCTL); + writel(0x0000000f, dc_base + 0x7000); + writel(0x0000000f, dc_base + 0x8000); + writel(0x000000c3, dc_base + 0x8004); + writel(0x00000071, dc_base + 0x8008); + writel(0x00000004, dc_base + UMC_FLOWCTLG); + writel(0x00000000, dc_base + 0x0060); + writel(0x80000201, ca_base + 0xc20); + writel(0x0801e01e, dc_base + UMC_FLOWCTLA); + writel(0x00200000, dc_base + UMC_FLOWCTLB); + writel(0x00004444, dc_base + UMC_FLOWCTLC); + writel(0x200a0a00, dc_base + UMC_SPCSETB); + writel(0x00010000, dc_base + UMC_SPCSETD); + writel(0x80000020, dc_base + UMC_DFICUPDCTLA); + + return 0; +} + +static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base, + int freq, unsigned long size, unsigned int width, + bool ddr3plus) +{ + void __iomem *phy_base = dc_base + 0x00001000; + int nr_phy = width / 16; + int phy, ret; + + writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET); + while (readl(dc_base + UMC_INITSTAT) & UMC_INITSTAT_INIT1ST) + cpu_relax(); + + for (phy = 0; phy < nr_phy; phy++) { + writel(0x00000100 | ((1 << (phy + 1)) - 1), + dc_base + UMC_DIOCTLA); + + ret = uniphier_ld4_ddrphy_init(phy_base, freq, ddr3plus); + if (ret) + return ret; + + ddrphy_prepare_training(phy_base, phy); + ret = ddrphy_training(phy_base); + if (ret) + return ret; + + phy_base += 0x00001000; + } + + return umc_dramcont_init(dc_base, ca_base, freq, size / (width / 16), + ddr3plus); +} + +int uniphier_pro4_umc_init(const struct uniphier_board_data *bd) +{ + void __iomem *umc_base = (void __iomem *)0x5b800000; + void __iomem *ca_base = umc_base + 0x00001000; + void __iomem *dc_base = umc_base + 0x00400000; + void __iomem *ssif_base = umc_base; + int ch, ret; + + for (ch = 0; ch < DRAM_CH_NR; ch++) { + ret = umc_ch_init(dc_base, ca_base, bd->dram_freq, + bd->dram_ch[ch].size, + bd->dram_ch[ch].width, + !!(bd->flags & UNIPHIER_BD_DDR3PLUS)); + if (ret) { + pr_err("failed to initialize UMC ch%d\n", ch); + return ret; + } + + ca_base += 0x00001000; + dc_base += 0x00200000; + } + + umc_start_ssif(ssif_base); + + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/dram/umc-pro5.c b/roms/u-boot/arch/arm/mach-uniphier/dram/umc-pro5.c new file mode 100644 index 000000000..a002b309e --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/dram/umc-pro5.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Socionext Inc. + */ + +#include "../init.h" + +int uniphier_pro5_umc_init(const struct uniphier_board_data *bd) +{ + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/dram/umc-pxs2.c b/roms/u-boot/arch/arm/mach-uniphier/dram/umc-pxs2.c new file mode 100644 index 000000000..73574201e --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/dram/umc-pxs2.c @@ -0,0 +1,643 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + * + * based on commit 21b6e480f92ccc38fe0502e3116411d6509d3bf2 of Diag by: + * Copyright (C) 2015 Socionext Inc. + */ + +#include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/printk.h> +#include <linux/sizes.h> +#include <asm/processor.h> +#include <time.h> + +#include "../init.h" +#include "../soc-info.h" +#include "ddrmphy-regs.h" +#include "umc-regs.h" + +#define DRAM_CH_NR 3 + +enum dram_freq { + DRAM_FREQ_1866M, + DRAM_FREQ_2133M, + DRAM_FREQ_NR, +}; + +enum dram_size { + DRAM_SZ_256M, + DRAM_SZ_512M, + DRAM_SZ_NR, +}; + +/* PHY */ +static u32 ddrphy_pgcr2[DRAM_FREQ_NR] = {0x00FC7E5D, 0x00FC90AB}; +static u32 ddrphy_ptr0[DRAM_FREQ_NR] = {0x0EA09205, 0x10C0A6C6}; +static u32 ddrphy_ptr1[DRAM_FREQ_NR] = {0x0DAC041B, 0x0FA104B1}; +static u32 ddrphy_ptr3[DRAM_FREQ_NR] = {0x15171e45, 0x18182357}; +static u32 ddrphy_ptr4[DRAM_FREQ_NR] = {0x0e9ad8e9, 0x10b34157}; +static u32 ddrphy_dtpr0[DRAM_FREQ_NR] = {0x35a00d88, 0x39e40e88}; +static u32 ddrphy_dtpr1[DRAM_FREQ_NR] = {0x2288cc2c, 0x228a04d0}; +static u32 ddrphy_dtpr2[DRAM_FREQ_NR] = {0x50005e00, 0x50006a00}; +static u32 ddrphy_dtpr3[DRAM_FREQ_NR] = {0x0010cb49, 0x0010ec89}; +static u32 ddrphy_mr0[DRAM_FREQ_NR] = {0x00000115, 0x00000125}; +static u32 ddrphy_mr2[DRAM_FREQ_NR] = {0x000002a0, 0x000002a8}; + +/* dependent on package and board design */ +static u32 ddrphy_acbdlr0[DRAM_CH_NR] = {0x0000000c, 0x0000000c, 0x00000009}; + +/* DDR multiPHY */ +static inline int ddrphy_get_rank(int dx) +{ + return dx / 2; +} + +static void ddrphy_fifo_reset(void __iomem *phy_base) +{ + u32 tmp; + + tmp = readl(phy_base + MPHY_PGCR0); + tmp &= ~MPHY_PGCR0_PHYFRST; + writel(tmp, phy_base + MPHY_PGCR0); + + udelay(1); + + tmp |= MPHY_PGCR0_PHYFRST; + writel(tmp, phy_base + MPHY_PGCR0); + + udelay(1); +} + +static void ddrphy_vt_ctrl(void __iomem *phy_base, int enable) +{ + u32 tmp; + + tmp = readl(phy_base + MPHY_PGCR1); + + if (enable) + tmp &= ~MPHY_PGCR1_INHVT; + else + tmp |= MPHY_PGCR1_INHVT; + + writel(tmp, phy_base + MPHY_PGCR1); + + if (!enable) { + while (!(readl(phy_base + MPHY_PGSR1) & MPHY_PGSR1_VTSTOP)) + cpu_relax(); + } +} + +static void ddrphy_dqs_delay_fixup(void __iomem *phy_base, int nr_dx, int step) +{ + int dx; + u32 lcdlr1, rdqsd; + void __iomem *dx_base = phy_base + MPHY_DX_BASE; + + ddrphy_vt_ctrl(phy_base, 0); + + for (dx = 0; dx < nr_dx; dx++) { + lcdlr1 = readl(dx_base + MPHY_DX_LCDLR1); + rdqsd = (lcdlr1 >> 8) & 0xff; + rdqsd = clamp(rdqsd + step, 0U, 0xffU); + lcdlr1 = (lcdlr1 & ~(0xff << 8)) | (rdqsd << 8); + writel(lcdlr1, dx_base + MPHY_DX_LCDLR1); + readl(dx_base + MPHY_DX_LCDLR1); /* relax */ + dx_base += MPHY_DX_STRIDE; + } + + ddrphy_vt_ctrl(phy_base, 1); +} + +static int ddrphy_get_system_latency(void __iomem *phy_base, int width) +{ + void __iomem *dx_base = phy_base + MPHY_DX_BASE; + const int nr_dx = width / 8; + int dx, rank; + u32 gtr; + int dgsl, dgsl_min = INT_MAX, dgsl_max = 0; + + for (dx = 0; dx < nr_dx; dx++) { + gtr = readl(dx_base + MPHY_DX_GTR); + for (rank = 0; rank < 4; rank++) { + dgsl = gtr & 0x7; + /* if dgsl is zero, this rank was not trained. skip. */ + if (dgsl) { + dgsl_min = min(dgsl_min, dgsl); + dgsl_max = max(dgsl_max, dgsl); + } + gtr >>= 3; + } + dx_base += MPHY_DX_STRIDE; + } + + if (dgsl_min != dgsl_max) + pr_warn("DQS Gateing System Latencies are not all leveled.\n"); + + return dgsl_max; +} + +static void ddrphy_init(void __iomem *phy_base, enum dram_freq freq, int width, + int ch) +{ + u32 tmp; + void __iomem *zq_base, *dx_base; + int zq, dx; + int nr_dx; + + nr_dx = width / 8; + + writel(MPHY_PIR_ZCALBYP, phy_base + MPHY_PIR); + /* + * Disable RGLVT bit (Read DQS Gating LCDL Delay VT Compensation) + * to avoid read error issue. + */ + writel(0x07d81e37, phy_base + MPHY_PGCR0); + writel(0x0200c4e0, phy_base + MPHY_PGCR1); + + tmp = ddrphy_pgcr2[freq]; + if (width >= 32) + tmp |= MPHY_PGCR2_DUALCHN | MPHY_PGCR2_ACPDDC; + writel(tmp, phy_base + MPHY_PGCR2); + + writel(ddrphy_ptr0[freq], phy_base + MPHY_PTR0); + writel(ddrphy_ptr1[freq], phy_base + MPHY_PTR1); + writel(0x00083def, phy_base + MPHY_PTR2); + writel(ddrphy_ptr3[freq], phy_base + MPHY_PTR3); + writel(ddrphy_ptr4[freq], phy_base + MPHY_PTR4); + + writel(ddrphy_acbdlr0[ch], phy_base + MPHY_ACBDLR0); + + writel(0x55555555, phy_base + MPHY_ACIOCR1); + writel(0x00000000, phy_base + MPHY_ACIOCR2); + writel(0x55555555, phy_base + MPHY_ACIOCR3); + writel(0x00000000, phy_base + MPHY_ACIOCR4); + writel(0x00000055, phy_base + MPHY_ACIOCR5); + writel(0x00181aa4, phy_base + MPHY_DXCCR); + + writel(0x0024641e, phy_base + MPHY_DSGCR); + writel(0x0000040b, phy_base + MPHY_DCR); + writel(ddrphy_dtpr0[freq], phy_base + MPHY_DTPR0); + writel(ddrphy_dtpr1[freq], phy_base + MPHY_DTPR1); + writel(ddrphy_dtpr2[freq], phy_base + MPHY_DTPR2); + writel(ddrphy_dtpr3[freq], phy_base + MPHY_DTPR3); + writel(ddrphy_mr0[freq], phy_base + MPHY_MR0); + writel(0x00000006, phy_base + MPHY_MR1); + writel(ddrphy_mr2[freq], phy_base + MPHY_MR2); + writel(0x00000000, phy_base + MPHY_MR3); + + tmp = 0; + for (dx = 0; dx < nr_dx; dx++) + tmp |= BIT(MPHY_DTCR_RANKEN_SHIFT + ddrphy_get_rank(dx)); + writel(0x90003087 | tmp, phy_base + MPHY_DTCR); + + writel(0x00000000, phy_base + MPHY_DTAR0); + writel(0x00000008, phy_base + MPHY_DTAR1); + writel(0x00000010, phy_base + MPHY_DTAR2); + writel(0x00000018, phy_base + MPHY_DTAR3); + writel(0xdd22ee11, phy_base + MPHY_DTDR0); + writel(0x7788bb44, phy_base + MPHY_DTDR1); + + /* impedance control settings */ + writel(0x04048900, phy_base + MPHY_ZQCR); + + zq_base = phy_base + MPHY_ZQ_BASE; + for (zq = 0; zq < 4; zq++) { + /* + * board-dependent + * PXS2: CH0ZQ0=0x5B, CH1ZQ0=0x5B, CH2ZQ0=0x59, others=0x5D + */ + writel(0x0007BB5D, zq_base + MPHY_ZQ_PR); + zq_base += MPHY_ZQ_STRIDE; + } + + /* DATX8 settings */ + dx_base = phy_base + MPHY_DX_BASE; + for (dx = 0; dx < 4; dx++) { + tmp = readl(dx_base + MPHY_DX_GCR0); + tmp &= ~MPHY_DX_GCR0_WLRKEN_MASK; + tmp |= BIT(MPHY_DX_GCR0_WLRKEN_SHIFT + ddrphy_get_rank(dx)) & + MPHY_DX_GCR0_WLRKEN_MASK; + writel(tmp, dx_base + MPHY_DX_GCR0); + + writel(0x00000000, dx_base + MPHY_DX_GCR1); + writel(0x00000000, dx_base + MPHY_DX_GCR2); + writel(0x00000000, dx_base + MPHY_DX_GCR3); + dx_base += MPHY_DX_STRIDE; + } + + while (!(readl(phy_base + MPHY_PGSR0) & MPHY_PGSR0_IDONE)) + cpu_relax(); + + ddrphy_dqs_delay_fixup(phy_base, nr_dx, -4); +} + +struct ddrphy_init_sequence { + char *description; + u32 init_flag; + u32 done_flag; + u32 err_flag; +}; + +static const struct ddrphy_init_sequence impedance_calibration_sequence[] = { + { + "Impedance Calibration", + MPHY_PIR_ZCAL, + MPHY_PGSR0_ZCDONE, + MPHY_PGSR0_ZCERR, + }, + { /* sentinel */ } +}; + +static const struct ddrphy_init_sequence dram_init_sequence[] = { + { + "DRAM Initialization", + MPHY_PIR_DRAMRST | MPHY_PIR_DRAMINIT, + MPHY_PGSR0_DIDONE, + 0, + }, + { /* sentinel */ } +}; + +static const struct ddrphy_init_sequence training_sequence[] = { + { + "Write Leveling", + MPHY_PIR_WL, + MPHY_PGSR0_WLDONE, + MPHY_PGSR0_WLERR, + }, + { + "Read DQS Gate Training", + MPHY_PIR_QSGATE, + MPHY_PGSR0_QSGDONE, + MPHY_PGSR0_QSGERR, + }, + { + "Write Leveling Adjustment", + MPHY_PIR_WLADJ, + MPHY_PGSR0_WLADONE, + MPHY_PGSR0_WLAERR, + }, + { + "Read Bit Deskew", + MPHY_PIR_RDDSKW, + MPHY_PGSR0_RDDONE, + MPHY_PGSR0_RDERR, + }, + { + "Write Bit Deskew", + MPHY_PIR_WRDSKW, + MPHY_PGSR0_WDDONE, + MPHY_PGSR0_WDERR, + }, + { + "Read Eye Training", + MPHY_PIR_RDEYE, + MPHY_PGSR0_REDONE, + MPHY_PGSR0_REERR, + }, + { + "Write Eye Training", + MPHY_PIR_WREYE, + MPHY_PGSR0_WEDONE, + MPHY_PGSR0_WEERR, + }, + { /* sentinel */ } +}; + +static int __ddrphy_training(void __iomem *phy_base, + const struct ddrphy_init_sequence *seq) +{ + const struct ddrphy_init_sequence *s; + u32 pgsr0; + u32 init_flag = MPHY_PIR_INIT; + u32 done_flag = MPHY_PGSR0_IDONE; + int timeout = 50000; /* 50 msec is long enough */ + unsigned long start = 0; + +#ifdef DEBUG + start = get_timer(0); +#endif + + for (s = seq; s->description; s++) { + init_flag |= s->init_flag; + done_flag |= s->done_flag; + } + + writel(init_flag, phy_base + MPHY_PIR); + + do { + if (--timeout < 0) { + pr_err("%s: error: timeout during DDR training\n", + __func__); + return -ETIMEDOUT; + } + udelay(1); + pgsr0 = readl(phy_base + MPHY_PGSR0); + } while ((pgsr0 & done_flag) != done_flag); + + for (s = seq; s->description; s++) { + if (pgsr0 & s->err_flag) { + pr_err("%s: error: %s failed\n", __func__, + s->description); + return -EIO; + } + } + + pr_debug("DDRPHY training: elapsed time %ld msec\n", get_timer(start)); + + return 0; +} + +static int ddrphy_impedance_calibration(void __iomem *phy_base) +{ + int ret; + u32 tmp; + + ret = __ddrphy_training(phy_base, impedance_calibration_sequence); + if (ret) + return ret; + + /* + * Because of a hardware bug, IDONE flag is set when the first ZQ block + * is calibrated. The flag does not guarantee the completion for all + * the ZQ blocks. Wait a little more just in case. + */ + udelay(1); + + /* reflect ZQ settings and enable average algorithm*/ + tmp = readl(phy_base + MPHY_ZQCR); + tmp |= MPHY_ZQCR_FORCE_ZCAL_VT_UPDATE; + writel(tmp, phy_base + MPHY_ZQCR); + tmp &= ~MPHY_ZQCR_FORCE_ZCAL_VT_UPDATE; + tmp |= MPHY_ZQCR_AVGEN; + writel(tmp, phy_base + MPHY_ZQCR); + + return 0; +} + +static int ddrphy_dram_init(void __iomem *phy_base) +{ + return __ddrphy_training(phy_base, dram_init_sequence); +} + +static int ddrphy_training(void __iomem *phy_base) +{ + return __ddrphy_training(phy_base, training_sequence); +} + +/* UMC */ +static u32 umc_cmdctla[DRAM_FREQ_NR] = {0x66DD131D, 0x77EE1722}; +/* + * The ch2 is a different generation UMC core. + * The register spec is different, unfortunately. + */ +static u32 umc_cmdctlb_ch01[DRAM_FREQ_NR] = {0x13E87C44, 0x18F88C44}; +static u32 umc_cmdctlb_ch2[DRAM_FREQ_NR] = {0x19E8DC44, 0x1EF8EC44}; +static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = { + {0x004A071D, 0x0078071D}, + {0x0055081E, 0x0089081E}, +}; + +static u32 umc_spcctlb[] = {0x00FF000A, 0x00FF000B}; +/* The ch2 is different for some reason only hardware guys know... */ +static u32 umc_flowctla_ch01[] = {0x0800001E, 0x08000022}; +static u32 umc_flowctla_ch2[] = {0x0800001E, 0x0800001E}; + +static void umc_set_system_latency(void __iomem *dc_base, int phy_latency) +{ + u32 val; + int latency; + + val = readl(dc_base + UMC_RDATACTL_D0); + latency = (val & UMC_RDATACTL_RADLTY_MASK) >> UMC_RDATACTL_RADLTY_SHIFT; + latency += (val & UMC_RDATACTL_RAD2LTY_MASK) >> + UMC_RDATACTL_RAD2LTY_SHIFT; + /* + * UMC works at the half clock rate of the PHY. + * The LSB of latency is ignored + */ + latency += phy_latency & ~1; + + val &= ~(UMC_RDATACTL_RADLTY_MASK | UMC_RDATACTL_RAD2LTY_MASK); + if (latency > 0xf) { + val |= 0xf << UMC_RDATACTL_RADLTY_SHIFT; + val |= (latency - 0xf) << UMC_RDATACTL_RAD2LTY_SHIFT; + } else { + val |= latency << UMC_RDATACTL_RADLTY_SHIFT; + } + + writel(val, dc_base + UMC_RDATACTL_D0); + writel(val, dc_base + UMC_RDATACTL_D1); + + readl(dc_base + UMC_RDATACTL_D1); /* relax */ +} + +/* enable/disable auto refresh */ +static void umc_refresh_ctrl(void __iomem *dc_base, int enable) +{ + u32 tmp; + + tmp = readl(dc_base + UMC_SPCSETB); + tmp &= ~UMC_SPCSETB_AREFMD_MASK; + + if (enable) + tmp |= UMC_SPCSETB_AREFMD_ARB; + else + tmp |= UMC_SPCSETB_AREFMD_REG; + + writel(tmp, dc_base + UMC_SPCSETB); + udelay(1); +} + +static void umc_ud_init(void __iomem *umc_base, int ch) +{ + writel(0x00000003, umc_base + UMC_BITPERPIXELMODE_D0); + + if (ch == 2) + writel(0x00000033, umc_base + UMC_PAIR1DOFF_D0); +} + +static int umc_dc_init(void __iomem *dc_base, enum dram_freq freq, + unsigned long size, int width, int ch) +{ + enum dram_size size_e; + int latency; + u32 val; + + switch (size) { + case 0: + return 0; + case SZ_256M: + size_e = DRAM_SZ_256M; + break; + case SZ_512M: + size_e = DRAM_SZ_512M; + break; + default: + pr_err("unsupported DRAM size 0x%08lx (per 16bit) for ch%d\n", + size, ch); + return -EINVAL; + } + + writel(umc_cmdctla[freq], dc_base + UMC_CMDCTLA); + + writel(ch == 2 ? umc_cmdctlb_ch2[freq] : umc_cmdctlb_ch01[freq], + dc_base + UMC_CMDCTLB); + + writel(umc_spcctla[freq][size_e], dc_base + UMC_SPCCTLA); + writel(umc_spcctlb[freq], dc_base + UMC_SPCCTLB); + + val = 0x000e000e; + latency = 12; + /* ES2 inserted one more FF to the logic. */ + if (uniphier_get_soc_model() >= 2) + latency += 2; + + if (latency > 0xf) { + val |= 0xf << UMC_RDATACTL_RADLTY_SHIFT; + val |= (latency - 0xf) << UMC_RDATACTL_RAD2LTY_SHIFT; + } else { + val |= latency << UMC_RDATACTL_RADLTY_SHIFT; + } + + writel(val, dc_base + UMC_RDATACTL_D0); + if (width >= 32) + writel(val, dc_base + UMC_RDATACTL_D1); + + writel(0x04060A02, dc_base + UMC_WDATACTL_D0); + if (width >= 32) + writel(0x04060A02, dc_base + UMC_WDATACTL_D1); + writel(0x04000000, dc_base + UMC_DATASET); + writel(0x00400020, dc_base + UMC_DCCGCTL); + writel(0x00000084, dc_base + UMC_FLOWCTLG); + writel(0x00000000, dc_base + UMC_ACSSETA); + + writel(ch == 2 ? umc_flowctla_ch2[freq] : umc_flowctla_ch01[freq], + dc_base + UMC_FLOWCTLA); + + writel(0x00004400, dc_base + UMC_FLOWCTLC); + writel(0x200A0A00, dc_base + UMC_SPCSETB); + writel(0x00000520, dc_base + UMC_DFICUPDCTLA); + writel(0x0000000D, dc_base + UMC_RESPCTL); + + if (ch != 2) { + writel(0x00202000, dc_base + UMC_FLOWCTLB); + writel(0xFDBFFFFF, dc_base + UMC_FLOWCTLOB0); + writel(0xFFFFFFFF, dc_base + UMC_FLOWCTLOB1); + writel(0x00080700, dc_base + UMC_BSICMAPSET); + } else { + writel(0x00200000, dc_base + UMC_FLOWCTLB); + writel(0x00000000, dc_base + UMC_BSICMAPSET); + } + + writel(0x00000000, dc_base + UMC_ERRMASKA); + writel(0x00000000, dc_base + UMC_ERRMASKB); + + return 0; +} + +static int umc_ch_init(void __iomem *umc_ch_base, enum dram_freq freq, + unsigned long size, unsigned int width, int ch) +{ + void __iomem *dc_base = umc_ch_base + 0x00011000; + void __iomem *phy_base = umc_ch_base + 0x00030000; + int ret; + + writel(0x00000002, dc_base + UMC_INITSET); + while (readl(dc_base + UMC_INITSTAT) & BIT(2)) + cpu_relax(); + + /* deassert PHY reset signals */ + writel(UMC_DIOCTLA_CTL_NRST | UMC_DIOCTLA_CFG_NRST, + dc_base + UMC_DIOCTLA); + + ddrphy_init(phy_base, freq, width, ch); + + ret = ddrphy_impedance_calibration(phy_base); + if (ret) + return ret; + + ddrphy_dram_init(phy_base); + if (ret) + return ret; + + ret = umc_dc_init(dc_base, freq, size, width, ch); + if (ret) + return ret; + + umc_ud_init(umc_ch_base, ch); + + ret = ddrphy_training(phy_base); + if (ret) + return ret; + + udelay(1); + + /* match the system latency between UMC and PHY */ + umc_set_system_latency(dc_base, + ddrphy_get_system_latency(phy_base, width)); + + udelay(1); + + /* stop auto refresh before clearing FIFO in PHY */ + umc_refresh_ctrl(dc_base, 0); + ddrphy_fifo_reset(phy_base); + umc_refresh_ctrl(dc_base, 1); + + udelay(10); + + return 0; +} + +static void um_init(void __iomem *um_base) +{ + writel(0x000000ff, um_base + UMC_MBUS0); + writel(0x000000ff, um_base + UMC_MBUS1); + writel(0x000000ff, um_base + UMC_MBUS2); + writel(0x000000ff, um_base + UMC_MBUS3); +} + +int uniphier_pxs2_umc_init(const struct uniphier_board_data *bd) +{ + void __iomem *um_base = (void __iomem *)0x5b600000; + void __iomem *umc_ch_base = (void __iomem *)0x5b800000; + enum dram_freq freq; + int ch, ret; + + switch (bd->dram_freq) { + case 1866: + freq = DRAM_FREQ_1866M; + break; + case 2133: + freq = DRAM_FREQ_2133M; + break; + default: + pr_err("unsupported DRAM frequency %d MHz\n", bd->dram_freq); + return -EINVAL; + } + + for (ch = 0; ch < DRAM_CH_NR; ch++) { + unsigned long size = bd->dram_ch[ch].size; + unsigned int width = bd->dram_ch[ch].width; + + if (size) { + ret = umc_ch_init(umc_ch_base, freq, + size / (width / 16), width, ch); + if (ret) { + pr_err("failed to initialize UMC ch%d\n", ch); + return ret; + } + } + + umc_ch_base += 0x00200000; + } + + um_init(um_base); + + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/dram/umc-regs.h b/roms/u-boot/arch/arm/mach-uniphier/dram/umc-regs.h new file mode 100644 index 000000000..02efab384 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/dram/umc-regs.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * UniPhier UMC (Universal Memory Controller) registers + * + * Copyright (C) 2011-2014 Panasonic Corporation + */ + +#ifndef ARCH_UMC_REGS_H +#define ARCH_UMC_REGS_H + +#include <linux/bitops.h> + +#define UMC_CPURST 0x00000700 +#define UMC_IDSRST 0x0000070C +#define UMC_IXMRST 0x00000714 +#define UMC_HDMRST 0x00000718 +#define UMC_MDMRST 0x0000071C +#define UMC_HDDRST 0x00000720 +#define UMC_MDDRST 0x00000724 +#define UMC_SIORST 0x00000728 +#define UMC_GIORST 0x0000072C +#define UMC_HD2RST 0x00000734 +#define UMC_VIORST 0x0000073C +#define UMC_FRCRST 0x00000748 /* LD4/sLD8 */ +#define UMC_DVCRST 0x00000748 /* Pro4 */ +#define UMC_RGLRST 0x00000750 +#define UMC_VPERST 0x00000758 +#define UMC_AIORST 0x00000764 +#define UMC_DMDRST 0x00000770 + +#define UMC_HDMCHSEL 0x00000898 +#define UMC_MDMCHSEL 0x0000089C +#define UMC_DVCCHSEL 0x000008C8 +#define UMC_DMDCHSEL 0x000008F0 + +#define UMC_CLKEN_SSIF_FETCH 0x0000C060 +#define UMC_CLKEN_SSIF_COMQUE0 0x0000C064 +#define UMC_CLKEN_SSIF_COMWC0 0x0000C068 +#define UMC_CLKEN_SSIF_COMRC0 0x0000C06C +#define UMC_CLKEN_SSIF_COMQUE1 0x0000C070 +#define UMC_CLKEN_SSIF_COMWC1 0x0000C074 +#define UMC_CLKEN_SSIF_COMRC1 0x0000C078 +#define UMC_CLKEN_SSIF_WC 0x0000C07C +#define UMC_CLKEN_SSIF_RC 0x0000C080 +#define UMC_CLKEN_SSIF_DST 0x0000C084 + +#define UMC_CMDCTLA 0x00000000 +#define UMC_CMDCTLB 0x00000004 +#define UMC_INITSET 0x00000014 +#define UMC_INITSET_INIT1EN BIT(1) /* init without power-on wait */ +#define UMC_INITSET_INIT0EN BIT(0) /* init with power-on wait */ +#define UMC_INITSTAT 0x00000018 +#define UMC_INITSTAT_INIT1ST BIT(1) /* init without power-on wait */ +#define UMC_INITSTAT_INIT0ST BIT(0) /* init with power-on wait */ +#define UMC_SPCCTLA 0x00000030 +#define UMC_SPCCTLB 0x00000034 +#define UMC_SPCSETA 0x00000038 +#define UMC_SPCSETB 0x0000003C +#define UMC_SPCSETB_AREFMD_MASK (0x3) /* Auto Refresh Mode */ +#define UMC_SPCSETB_AREFMD_ARB (0x0) /* control by arbitor */ +#define UMC_SPCSETB_AREFMD_CONT (0x1) /* control by DRAMCONT */ +#define UMC_SPCSETB_AREFMD_REG (0x2) /* control by register */ +#define UMC_SPCSETC 0x00000040 +#define UMC_SPCSETD 0x00000044 +#define UMC_SPCSTATA 0x00000050 +#define UMC_SPCSTATB 0x00000054 +#define UMC_SPCSTATC 0x00000058 +#define UMC_ACSSETA 0x00000060 +#define UMC_FLOWCTLA 0x00000400 +#define UMC_FLOWCTLB 0x00000404 +#define UMC_FLOWCTLC 0x00000408 +#define UMC_FLOWCTLG 0x00000508 +#define UMC_FLOWCTLOB0 0x00000520 +#define UMC_FLOWCTLOB1 0x00000524 +#define UMC_RDATACTL_D0 0x00000600 +#define UMC_RDATACTL_RADLTY_SHIFT 4 +#define UMC_RDATACTL_RADLTY_MASK (0xf << (UMC_RDATACTL_RADLTY_SHIFT)) +#define UMC_RDATACTL_RAD2LTY_SHIFT 8 +#define UMC_RDATACTL_RAD2LTY_MASK (0xf << (UMC_RDATACTL_RAD2LTY_SHIFT)) +#define UMC_WDATACTL_D0 0x00000604 +#define UMC_RDATACTL_D1 0x00000608 +#define UMC_WDATACTL_D1 0x0000060C +#define UMC_DATASET 0x00000610 +#define UMC_RESPCTL 0x00000624 +#define UMC_DCCGCTL 0x00000720 +#define UMC_DICGCTLA 0x00000724 +#define UMC_DICGCTLB 0x00000728 +#define UMC_ERRMASKA 0x00000958 +#define UMC_ERRMASKB 0x0000095c +#define UMC_BSICMAPSET 0x00000988 +#define UMC_DIOCTLA 0x00000C00 +#define UMC_DIOCTLA_CTL_NRST BIT(8) /* ctl_rst_n */ +#define UMC_DIOCTLA_CFG_NRST BIT(0) /* cfg_rst_n */ +#define UMC_DFICUPDCTLA 0x00000C20 + +/* UM registers */ +#define UMC_MBUS0 0x00080004 +#define UMC_MBUS1 0x00081004 +#define UMC_MBUS2 0x00082004 +#define UMC_MBUS3 0x00083004 + +/* UD registers */ +#define UMC_BITPERPIXELMODE_D0 0x010 +#define UMC_PAIR1DOFF_D0 0x054 + +#endif diff --git a/roms/u-boot/arch/arm/mach-uniphier/dram/umc-sld8.c b/roms/u-boot/arch/arm/mach-uniphier/dram/umc-sld8.c new file mode 100644 index 000000000..a11586952 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/dram/umc-sld8.c @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011-2014 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/sizes.h> +#include <asm/processor.h> + +#include "../init.h" +#include "ddrphy-init.h" +#include "umc-regs.h" + +#define DRAM_CH_NR 2 + +enum dram_freq { + DRAM_FREQ_1333M, + DRAM_FREQ_1600M, + DRAM_FREQ_NR, +}; + +enum dram_size { + DRAM_SZ_128M, + DRAM_SZ_256M, + DRAM_SZ_512M, + DRAM_SZ_NR, +}; + +static u32 umc_cmdctla[DRAM_FREQ_NR] = {0x55990b11, 0x66bb0f17}; +static u32 umc_cmdctla_plus[DRAM_FREQ_NR] = {0x45990b11, 0x46bb0f17}; +static u32 umc_cmdctlb[DRAM_FREQ_NR] = {0x16958944, 0x18c6ab44}; +static u32 umc_cmdctlb_plus[DRAM_FREQ_NR] = {0x16958924, 0x18c6ab24}; +static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = { + {0x00240512, 0x00350512, 0x00000000}, /* no data for 1333MHz,128MB */ + {0x002b0617, 0x003f0617, 0x00670617}, +}; +static u32 umc_spcctlb[DRAM_FREQ_NR] = {0x00ff0006, 0x00ff0008}; +static u32 umc_rdatactl[DRAM_FREQ_NR] = {0x000a00ac, 0x000c00ac}; + +static int umc_get_rank(int ch) +{ + return ch; /* ch0: rank0, ch1: rank1 for this SoC */ +} + +static void umc_start_ssif(void __iomem *ssif_base) +{ + writel(0x00000000, ssif_base + 0x0000b004); + writel(0xffffffff, ssif_base + 0x0000c004); + writel(0x000fffcf, ssif_base + 0x0000c008); + writel(0x00000001, ssif_base + 0x0000b000); + writel(0x00000001, ssif_base + 0x0000c000); + writel(0x03010101, ssif_base + UMC_MDMCHSEL); + writel(0x03010100, ssif_base + UMC_DMDCHSEL); + + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_FETCH); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMQUE0); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMWC0); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMRC0); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMQUE1); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMWC1); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMRC1); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_WC); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_RC); + writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_DST); + + writel(0x00000001, ssif_base + UMC_CPURST); + writel(0x00000001, ssif_base + UMC_IDSRST); + writel(0x00000001, ssif_base + UMC_IXMRST); + writel(0x00000001, ssif_base + UMC_MDMRST); + writel(0x00000001, ssif_base + UMC_MDDRST); + writel(0x00000001, ssif_base + UMC_SIORST); + writel(0x00000001, ssif_base + UMC_VIORST); + writel(0x00000001, ssif_base + UMC_FRCRST); + writel(0x00000001, ssif_base + UMC_RGLRST); + writel(0x00000001, ssif_base + UMC_AIORST); + writel(0x00000001, ssif_base + UMC_DMDRST); +} + +static int umc_dramcont_init(void __iomem *dc_base, void __iomem *ca_base, + int freq, unsigned long size, bool ddr3plus) +{ + enum dram_freq freq_e; + enum dram_size size_e; + + switch (freq) { + case 1333: + freq_e = DRAM_FREQ_1333M; + break; + case 1600: + freq_e = DRAM_FREQ_1600M; + break; + default: + pr_err("unsupported DRAM frequency %d MHz\n", freq); + return -EINVAL; + } + + switch (size) { + case 0: + return 0; + case SZ_128M: + size_e = DRAM_SZ_128M; + break; + case SZ_256M: + size_e = DRAM_SZ_256M; + break; + case SZ_512M: + size_e = DRAM_SZ_512M; + break; + default: + pr_err("unsupported DRAM size 0x%08lx\n", size); + return -EINVAL; + } + + writel((ddr3plus ? umc_cmdctla_plus : umc_cmdctla)[freq_e], + dc_base + UMC_CMDCTLA); + writel((ddr3plus ? umc_cmdctlb_plus : umc_cmdctlb)[freq_e], + dc_base + UMC_CMDCTLB); + writel(umc_spcctla[freq_e][size_e], dc_base + UMC_SPCCTLA); + writel(umc_spcctlb[freq_e], dc_base + UMC_SPCCTLB); + writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D0); + writel(0x04060806, dc_base + UMC_WDATACTL_D0); + writel(0x04a02000, dc_base + UMC_DATASET); + writel(0x00000000, ca_base + 0x2300); + writel(0x00400020, dc_base + UMC_DCCGCTL); + writel(0x00000003, dc_base + 0x7000); + writel(0x0000004f, dc_base + 0x8000); + writel(0x000000c3, dc_base + 0x8004); + writel(0x00000077, dc_base + 0x8008); + writel(0x0000003b, dc_base + UMC_DICGCTLA); + writel(0x020a0808, dc_base + UMC_DICGCTLB); + writel(0x00000004, dc_base + UMC_FLOWCTLG); + writel(0x80000201, ca_base + 0xc20); + writel(0x0801e01e, dc_base + UMC_FLOWCTLA); + writel(0x00200000, dc_base + UMC_FLOWCTLB); + writel(0x00004444, dc_base + UMC_FLOWCTLC); + writel(0x200a0a00, dc_base + UMC_SPCSETB); + writel(0x00000000, dc_base + UMC_SPCSETD); + writel(0x00000520, dc_base + UMC_DFICUPDCTLA); + + return 0; +} + +static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base, + int freq, unsigned long size, bool ddr3plus, int ch) +{ + void __iomem *phy_base = dc_base + 0x00001000; + int ret; + + writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET); + while (readl(dc_base + UMC_INITSTAT) & UMC_INITSTAT_INIT1ST) + cpu_relax(); + + writel(0x00000101, dc_base + UMC_DIOCTLA); + + ret = uniphier_ld4_ddrphy_init(phy_base, freq, ddr3plus); + if (ret) + return ret; + + ddrphy_prepare_training(phy_base, umc_get_rank(ch)); + ret = ddrphy_training(phy_base); + if (ret) + return ret; + + return umc_dramcont_init(dc_base, ca_base, freq, size, ddr3plus); +} + +int uniphier_sld8_umc_init(const struct uniphier_board_data *bd) +{ + void __iomem *umc_base = (void __iomem *)0x5b800000; + void __iomem *ca_base = umc_base + 0x00001000; + void __iomem *dc_base = umc_base + 0x00400000; + void __iomem *ssif_base = umc_base; + int ch, ret; + + for (ch = 0; ch < DRAM_CH_NR; ch++) { + ret = umc_ch_init(dc_base, ca_base, bd->dram_freq, + bd->dram_ch[ch].size, + !!(bd->flags & UNIPHIER_BD_DDR3PLUS), ch); + if (ret) { + pr_err("failed to initialize UMC ch%d\n", ch); + return ret; + } + + ca_base += 0x00001000; + dc_base += 0x00200000; + } + + umc_start_ssif(ssif_base); + + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/dram_init.c b/roms/u-boot/arch/arm/mach-uniphier/dram_init.c new file mode 100644 index 000000000..7f2753190 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/dram_init.c @@ -0,0 +1,304 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2012-2015 Panasonic Corporation + * Copyright (C) 2015-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <init.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/printk.h> +#include <linux/sizes.h> +#include <asm/global_data.h> +#include <asm/u-boot.h> + +#include "init.h" +#include "sg-regs.h" +#include "soc-info.h" + +DECLARE_GLOBAL_DATA_PTR; + +struct uniphier_dram_map { + unsigned long base; + unsigned long size; +}; + +static int uniphier_memconf_decode(struct uniphier_dram_map *dram_map, + unsigned long sparse_ch1_base, bool have_ch2) +{ + unsigned long size; + u32 val; + + val = readl(sg_base + SG_MEMCONF); + + /* set up ch0 */ + dram_map[0].base = 0x80000000; + + switch (val & SG_MEMCONF_CH0_SZ_MASK) { + case SG_MEMCONF_CH0_SZ_64M: + size = SZ_64M; + break; + case SG_MEMCONF_CH0_SZ_128M: + size = SZ_128M; + break; + case SG_MEMCONF_CH0_SZ_256M: + size = SZ_256M; + break; + case SG_MEMCONF_CH0_SZ_512M: + size = SZ_512M; + break; + case SG_MEMCONF_CH0_SZ_1G: + size = SZ_1G; + break; + default: + pr_err("error: invalid value is set to MEMCONF ch0 size\n"); + return -EINVAL; + } + + if ((val & SG_MEMCONF_CH0_NUM_MASK) == SG_MEMCONF_CH0_NUM_2) + size *= 2; + + dram_map[0].size = size; + + /* set up ch1 */ + dram_map[1].base = dram_map[0].base + size; + + if (val & SG_MEMCONF_SPARSEMEM) { + if (dram_map[1].base > sparse_ch1_base) { + pr_warn("Sparse mem is enabled, but ch0 and ch1 overlap\n"); + pr_warn("Only ch0 is available\n"); + dram_map[1].base = 0; + return 0; + } + + dram_map[1].base = sparse_ch1_base; + } + + switch (val & SG_MEMCONF_CH1_SZ_MASK) { + case SG_MEMCONF_CH1_SZ_64M: + size = SZ_64M; + break; + case SG_MEMCONF_CH1_SZ_128M: + size = SZ_128M; + break; + case SG_MEMCONF_CH1_SZ_256M: + size = SZ_256M; + break; + case SG_MEMCONF_CH1_SZ_512M: + size = SZ_512M; + break; + case SG_MEMCONF_CH1_SZ_1G: + size = SZ_1G; + break; + default: + pr_err("error: invalid value is set to MEMCONF ch1 size\n"); + return -EINVAL; + } + + if ((val & SG_MEMCONF_CH1_NUM_MASK) == SG_MEMCONF_CH1_NUM_2) + size *= 2; + + dram_map[1].size = size; + + if (!have_ch2 || val & SG_MEMCONF_CH2_DISABLE) + return 0; + + /* set up ch2 */ + dram_map[2].base = dram_map[1].base + size; + + switch (val & SG_MEMCONF_CH2_SZ_MASK) { + case SG_MEMCONF_CH2_SZ_64M: + size = SZ_64M; + break; + case SG_MEMCONF_CH2_SZ_128M: + size = SZ_128M; + break; + case SG_MEMCONF_CH2_SZ_256M: + size = SZ_256M; + break; + case SG_MEMCONF_CH2_SZ_512M: + size = SZ_512M; + break; + case SG_MEMCONF_CH2_SZ_1G: + size = SZ_1G; + break; + default: + pr_err("error: invalid value is set to MEMCONF ch2 size\n"); + return -EINVAL; + } + + if ((val & SG_MEMCONF_CH2_NUM_MASK) == SG_MEMCONF_CH2_NUM_2) + size *= 2; + + dram_map[2].size = size; + + return 0; +} + +static int uniphier_ld4_dram_map_get(struct uniphier_dram_map dram_map[]) +{ + return uniphier_memconf_decode(dram_map, 0xc0000000, false); +} + +static int uniphier_pro4_dram_map_get(struct uniphier_dram_map dram_map[]) +{ + return uniphier_memconf_decode(dram_map, 0xa0000000, false); +} + +static int uniphier_pxs2_dram_map_get(struct uniphier_dram_map dram_map[]) +{ + return uniphier_memconf_decode(dram_map, 0xc0000000, true); +} + +struct uniphier_dram_init_data { + unsigned int soc_id; + int (*dram_map_get)(struct uniphier_dram_map dram_map[]); +}; + +static const struct uniphier_dram_init_data uniphier_dram_init_data[] = { + { + .soc_id = UNIPHIER_LD4_ID, + .dram_map_get = uniphier_ld4_dram_map_get, + }, + { + .soc_id = UNIPHIER_PRO4_ID, + .dram_map_get = uniphier_pro4_dram_map_get, + }, + { + .soc_id = UNIPHIER_SLD8_ID, + .dram_map_get = uniphier_ld4_dram_map_get, + }, + { + .soc_id = UNIPHIER_PRO5_ID, + .dram_map_get = uniphier_ld4_dram_map_get, + }, + { + .soc_id = UNIPHIER_PXS2_ID, + .dram_map_get = uniphier_pxs2_dram_map_get, + }, + { + .soc_id = UNIPHIER_LD6B_ID, + .dram_map_get = uniphier_pxs2_dram_map_get, + }, + { + .soc_id = UNIPHIER_LD11_ID, + .dram_map_get = uniphier_ld4_dram_map_get, + }, + { + .soc_id = UNIPHIER_LD20_ID, + .dram_map_get = uniphier_pxs2_dram_map_get, + }, + { + .soc_id = UNIPHIER_PXS3_ID, + .dram_map_get = uniphier_pxs2_dram_map_get, + }, +}; +UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_dram_init_data, + uniphier_dram_init_data) + +static int uniphier_dram_map_get(struct uniphier_dram_map *dram_map) +{ + const struct uniphier_dram_init_data *data; + + data = uniphier_get_dram_init_data(); + if (!data) { + pr_err("unsupported SoC\n"); + return -ENOTSUPP; + } + + return data->dram_map_get(dram_map); +} + +int dram_init(void) +{ + struct uniphier_dram_map dram_map[3] = {}; + bool valid_bank_found = false; + unsigned long prev_top; + int ret, i; + + gd->ram_size = 0; + + ret = uniphier_dram_map_get(dram_map); + if (ret) + return ret; + + for (i = 0; i < ARRAY_SIZE(dram_map); i++) { + unsigned long max_size; + + if (!dram_map[i].size) + continue; + + /* + * U-Boot relocates itself to the tail of the memory region, + * but it does not expect sparse memory. We use the first + * contiguous chunk here. + */ + if (valid_bank_found && prev_top < dram_map[i].base) + break; + + /* + * Do not use memory that exceeds 32bit address range. U-Boot + * relocates itself to the end of the effectively available RAM. + * This could be a problem for DMA engines that do not support + * 64bit address (SDMA of SDHCI, UniPhier AV-ether, etc.) + */ + if (dram_map[i].base >= 1ULL << 32) + break; + + max_size = (1ULL << 32) - dram_map[i].base; + + gd->ram_size = min(dram_map[i].size, max_size); + + if (!valid_bank_found) + gd->ram_base = dram_map[i].base; + + prev_top = dram_map[i].base + dram_map[i].size; + valid_bank_found = true; + } + + /* + * LD20 uses the last 64 byte for each channel for dynamic + * DDR PHY training + */ + if (uniphier_get_soc_id() == UNIPHIER_LD20_ID) + gd->ram_size -= 64; + + return 0; +} + +int dram_init_banksize(void) +{ + struct uniphier_dram_map dram_map[3] = {}; + unsigned long base, top; + bool valid_bank_found = false; + int ret, i; + + ret = uniphier_dram_map_get(dram_map); + if (ret) + return ret; + + for (i = 0; i < ARRAY_SIZE(dram_map); i++) { + if (i < ARRAY_SIZE(gd->bd->bi_dram)) { + gd->bd->bi_dram[i].start = dram_map[i].base; + gd->bd->bi_dram[i].size = dram_map[i].size; + } + + if (!dram_map[i].size) + continue; + + if (!valid_bank_found) + base = dram_map[i].base; + top = dram_map[i].base + dram_map[i].size; + valid_bank_found = true; + } + + if (!valid_bank_found) + return -EINVAL; + + /* map all the DRAM regions */ + uniphier_mem_map_init(base, top - base); + + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/fdt-fixup.c b/roms/u-boot/arch/arm/mach-uniphier/fdt-fixup.c new file mode 100644 index 000000000..dfa32fdd4 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/fdt-fixup.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016-2018 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <fdt_support.h> +#include <fdtdec.h> +#include <jffs2/load_kernel.h> +#include <mtd_node.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/printk.h> + +#include "soc-info.h" + +/* + * The DRAM PHY requires 64 byte scratch area in each DRAM channel + * for its dynamic PHY training feature. + */ +static int uniphier_ld20_fdt_mem_rsv(void *fdt, struct bd_info *bd) +{ + unsigned long rsv_addr; + const unsigned long rsv_size = 64; + int i, ret; + + if (!IS_ENABLED(CONFIG_ARCH_UNIPHIER_LD20) || + uniphier_get_soc_id() != UNIPHIER_LD20_ID) + return 0; + + for (i = 0; i < ARRAY_SIZE(bd->bi_dram); i++) { + if (!bd->bi_dram[i].size) + continue; + + rsv_addr = bd->bi_dram[i].start + bd->bi_dram[i].size; + rsv_addr -= rsv_size; + + ret = fdt_add_mem_rsv(fdt, rsv_addr, rsv_size); + if (ret) + return -ENOSPC; + + pr_notice(" Reserved memory region for DRAM PHY training: addr=%lx size=%lx\n", + rsv_addr, rsv_size); + } + + return 0; +} + +int ft_board_setup(void *fdt, struct bd_info *bd) +{ + static const struct node_info nodes[] = { + { "socionext,uniphier-denali-nand-v5a", MTD_DEV_TYPE_NAND }, + { "socionext,uniphier-denali-nand-v5b", MTD_DEV_TYPE_NAND }, + }; + int ret; + + fdt_fixup_mtdparts(fdt, nodes, ARRAY_SIZE(nodes)); + + ret = uniphier_ld20_fdt_mem_rsv(fdt, bd); + if (ret) + return ret; + + return 0; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/init.h b/roms/u-boot/arch/arm/mach-uniphier/init.h new file mode 100644 index 000000000..535c06343 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/init.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#ifndef __MACH_INIT_H +#define __MACH_INIT_H + +#include <linux/bitops.h> +#include <linux/types.h> + +#define UNIPHIER_MAX_NR_DRAM_CH 3 + +struct uniphier_dram_ch { + unsigned long size; + unsigned int width; +}; + +struct uniphier_board_data { + unsigned int dram_freq; + struct uniphier_dram_ch dram_ch[UNIPHIER_MAX_NR_DRAM_CH]; + unsigned int flags; + +#define UNIPHIER_BD_DRAM_SPARSE BIT(9) +#define UNIPHIER_BD_DDR3PLUS BIT(8) +}; + +const struct uniphier_board_data *uniphier_get_board_param(void); + +int uniphier_ld4_init(const struct uniphier_board_data *bd); +int uniphier_pro4_init(const struct uniphier_board_data *bd); +int uniphier_sld8_init(const struct uniphier_board_data *bd); +int uniphier_pro5_init(const struct uniphier_board_data *bd); +int uniphier_pxs2_init(const struct uniphier_board_data *bd); + +void uniphier_ld4_bcu_init(const struct uniphier_board_data *bd); + +int uniphier_memconf_2ch_init(const struct uniphier_board_data *bd); +int uniphier_memconf_3ch_init(const struct uniphier_board_data *bd); + +int uniphier_ld4_dpll_init(const struct uniphier_board_data *bd); +int uniphier_pro4_dpll_init(const struct uniphier_board_data *bd); +int uniphier_sld8_dpll_init(const struct uniphier_board_data *bd); +int uniphier_pro5_dpll_init(const struct uniphier_board_data *bd); +int uniphier_pxs2_dpll_init(const struct uniphier_board_data *bd); + +void uniphier_ld4_early_clk_init(void); + +void uniphier_ld4_dram_clk_init(void); +void uniphier_pro5_dram_clk_init(void); +void uniphier_pxs2_dram_clk_init(void); + +int uniphier_ld4_umc_init(const struct uniphier_board_data *bd); +int uniphier_pro4_umc_init(const struct uniphier_board_data *bd); +int uniphier_sld8_umc_init(const struct uniphier_board_data *bd); +int uniphier_pro5_umc_init(const struct uniphier_board_data *bd); +int uniphier_pxs2_umc_init(const struct uniphier_board_data *bd); + +void uniphier_ld4_pll_init(void); +void uniphier_pro4_pll_init(void); +void uniphier_ld11_pll_init(void); +void uniphier_ld20_pll_init(void); +void uniphier_pxs3_pll_init(void); + +void uniphier_pro4_clk_init(void); +void uniphier_pro5_clk_init(void); +void uniphier_pxs2_clk_init(void); +void uniphier_ld11_clk_init(void); +void uniphier_ld20_clk_init(void); +void uniphier_pxs3_clk_init(void); + +unsigned int uniphier_boot_device_raw(void); +int uniphier_have_internal_stm(void); +int uniphier_boot_from_backend(void); + +#ifdef CONFIG_ARM64 +void uniphier_mem_map_init(unsigned long dram_base, unsigned long dram_size); +#else +static inline void uniphier_mem_map_init(unsigned long dram_base, + unsigned long dram_size) +{ +} +#endif + +#endif /* __MACH_INIT_H */ diff --git a/roms/u-boot/arch/arm/mach-uniphier/memconf.c b/roms/u-boot/arch/arm/mach-uniphier/memconf.c new file mode 100644 index 000000000..57192f015 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/memconf.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011-2015 Panasonic Corporation + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/sizes.h> + +#include "sg-regs.h" +#include "init.h" + +static int __uniphier_memconf_init(const struct uniphier_board_data *bd, + int have_ch2) +{ + u32 val = 0; + unsigned long size_per_word; + + /* set up ch0 */ + switch (bd->dram_ch[0].width) { + case 16: + val |= SG_MEMCONF_CH0_NUM_1; + size_per_word = bd->dram_ch[0].size; + break; + case 32: + val |= SG_MEMCONF_CH0_NUM_2; + size_per_word = bd->dram_ch[0].size >> 1; + break; + default: + pr_err("error: unsupported DRAM ch0 width\n"); + return -EINVAL; + } + + switch (size_per_word) { + case SZ_64M: + val |= SG_MEMCONF_CH0_SZ_64M; + break; + case SZ_128M: + val |= SG_MEMCONF_CH0_SZ_128M; + break; + case SZ_256M: + val |= SG_MEMCONF_CH0_SZ_256M; + break; + case SZ_512M: + val |= SG_MEMCONF_CH0_SZ_512M; + break; + case SZ_1G: + val |= SG_MEMCONF_CH0_SZ_1G; + break; + default: + pr_err("error: unsupported DRAM ch0 size\n"); + return -EINVAL; + } + + /* set up ch1 */ + switch (bd->dram_ch[1].width) { + case 16: + val |= SG_MEMCONF_CH1_NUM_1; + size_per_word = bd->dram_ch[1].size; + break; + case 32: + val |= SG_MEMCONF_CH1_NUM_2; + size_per_word = bd->dram_ch[1].size >> 1; + break; + default: + pr_err("error: unsupported DRAM ch1 width\n"); + return -EINVAL; + } + + switch (size_per_word) { + case SZ_64M: + val |= SG_MEMCONF_CH1_SZ_64M; + break; + case SZ_128M: + val |= SG_MEMCONF_CH1_SZ_128M; + break; + case SZ_256M: + val |= SG_MEMCONF_CH1_SZ_256M; + break; + case SZ_512M: + val |= SG_MEMCONF_CH1_SZ_512M; + break; + case SZ_1G: + val |= SG_MEMCONF_CH1_SZ_1G; + break; + default: + pr_err("error: unsupported DRAM ch1 size\n"); + return -EINVAL; + } + + /* is sparse mem? */ + if (bd->flags & UNIPHIER_BD_DRAM_SPARSE) + val |= SG_MEMCONF_SPARSEMEM; + + if (!have_ch2) + goto out; + + if (!bd->dram_ch[2].size) { + val |= SG_MEMCONF_CH2_DISABLE; + goto out; + } + + /* set up ch2 */ + switch (bd->dram_ch[2].width) { + case 16: + val |= SG_MEMCONF_CH2_NUM_1; + size_per_word = bd->dram_ch[2].size; + break; + case 32: + val |= SG_MEMCONF_CH2_NUM_2; + size_per_word = bd->dram_ch[2].size >> 1; + break; + default: + pr_err("error: unsupported DRAM ch2 width\n"); + return -EINVAL; + } + + switch (size_per_word) { + case SZ_64M: + val |= SG_MEMCONF_CH2_SZ_64M; + break; + case SZ_128M: + val |= SG_MEMCONF_CH2_SZ_128M; + break; + case SZ_256M: + val |= SG_MEMCONF_CH2_SZ_256M; + break; + case SZ_512M: + val |= SG_MEMCONF_CH2_SZ_512M; + break; + case SZ_1G: + val |= SG_MEMCONF_CH2_SZ_1G; + break; + default: + pr_err("error: unsupported DRAM ch2 size\n"); + return -EINVAL; + } + +out: + writel(val, sg_base + SG_MEMCONF); + + return 0; +} + +int uniphier_memconf_2ch_init(const struct uniphier_board_data *bd) +{ + return __uniphier_memconf_init(bd, 0); +} + +int uniphier_memconf_3ch_init(const struct uniphier_board_data *bd) +{ + return __uniphier_memconf_init(bd, 1); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/micro-support-card.c b/roms/u-boot/arch/arm/mach-uniphier/micro-support-card.c new file mode 100644 index 000000000..95780f79c --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/micro-support-card.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2012-2015 Panasonic Corporation + * Copyright (C) 2015-2020 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <dm.h> +#include <fdt_support.h> +#include <linux/ctype.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <asm/global_data.h> + +#include "micro-support-card.h" + +#define SMC911X_OFFSET 0x00000 +#define LED_OFFSET 0x90000 +#define NS16550A_OFFSET 0xb0000 +#define MICRO_SUPPORT_CARD_RESET 0xd0034 +#define MICRO_SUPPORT_CARD_REVISION 0xd00e0 + +static bool support_card_found; +static void __iomem *support_card_base; + +static void support_card_detect(void) +{ + DECLARE_GLOBAL_DATA_PTR; + const void *fdt = gd->fdt_blob; + int offset; + u64 addr, addr2; + + offset = fdt_node_offset_by_compatible(fdt, 0, "smsc,lan9118"); + if (offset < 0) + return; + + addr = fdt_get_base_address(fdt, offset); + if (addr == OF_BAD_ADDR) + return; + addr -= SMC911X_OFFSET; + + offset = fdt_node_offset_by_compatible(fdt, 0, "ns16550a"); + if (offset < 0) + return; + + addr2 = fdt_get_base_address(fdt, offset); + if (addr2 == OF_BAD_ADDR) + return; + addr2 -= NS16550A_OFFSET; + + /* sanity check */ + if (addr != addr2) + return; + + support_card_base = ioremap(addr, 0x100000); + + support_card_found = true; +} + +/* + * 0: reset deassert, 1: reset + * + * bit[0]: LAN, I2C, LED + * bit[1]: UART + */ +static void support_card_reset_deassert(void) +{ + writel(0x00010000, support_card_base + MICRO_SUPPORT_CARD_RESET); +} + +static void support_card_reset(void) +{ + writel(0x00020003, support_card_base + MICRO_SUPPORT_CARD_RESET); +} + +static int support_card_show_revision(void) +{ + u32 revision; + + revision = readl(support_card_base + MICRO_SUPPORT_CARD_REVISION); + revision &= 0xff; + + /* revision 3.6.x card changed the revision format */ + printf("SC: Micro Support Card (CPLD version %s%d.%d)\n", + revision >> 4 == 6 ? "3." : "", + revision >> 4, revision & 0xf); + + return 0; +} + +void support_card_init(void) +{ + struct udevice *dev; + int ret; + + /* The system bus must be initialized for access to the support card. */ + ret = uclass_get_device_by_driver(UCLASS_SIMPLE_BUS, + DM_DRIVER_GET(uniphier_system_bus_driver), + &dev); + if (ret) + return; + + /* Check DT to see if this board has the support card. */ + support_card_detect(); + + if (!support_card_found) + return; + + support_card_reset(); + /* + * After power on, we need to keep the LAN controller in reset state + * for a while. (200 usec) + */ + udelay(200); + support_card_reset_deassert(); + + support_card_show_revision(); +} + +static const u8 ledval_num[] = { + 0x7e, /* 0 */ + 0x0c, /* 1 */ + 0xb6, /* 2 */ + 0x9e, /* 3 */ + 0xcc, /* 4 */ + 0xda, /* 5 */ + 0xfa, /* 6 */ + 0x4e, /* 7 */ + 0xfe, /* 8 */ + 0xde, /* 9 */ +}; + +static const u8 ledval_alpha[] = { + 0xee, /* A */ + 0xf8, /* B */ + 0x72, /* C */ + 0xbc, /* D */ + 0xf2, /* E */ + 0xe2, /* F */ + 0x7a, /* G */ + 0xe8, /* H */ + 0x08, /* I */ + 0x3c, /* J */ + 0xea, /* K */ + 0x70, /* L */ + 0x6e, /* M */ + 0xa8, /* N */ + 0xb8, /* O */ + 0xe6, /* P */ + 0xce, /* Q */ + 0xa0, /* R */ + 0xc8, /* S */ + 0x8c, /* T */ + 0x7c, /* U */ + 0x54, /* V */ + 0xfc, /* W */ + 0xec, /* X */ + 0xdc, /* Y */ + 0xa4, /* Z */ +}; + +static u8 char2ledval(char c) +{ + if (isdigit(c)) + return ledval_num[c - '0']; + else if (isalpha(c)) + return ledval_alpha[toupper(c) - 'A']; + + return 0; +} + +void led_puts(const char *s) +{ + int i; + u32 val = 0; + + if (!support_card_found) + return; + + if (!s) + return; + + for (i = 0; i < 4; i++) { + val <<= 8; + val |= char2ledval(*s); + if (*s != '\0') + s++; + } + + writel(~val, support_card_base + LED_OFFSET); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/micro-support-card.h b/roms/u-boot/arch/arm/mach-uniphier/micro-support-card.h new file mode 100644 index 000000000..a5a94f8ed --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/micro-support-card.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2012-2014 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#ifndef MICRO_SUPPORT_CARD_H +#define MICRO_SUPPORT_CARD_H + +#if defined(CONFIG_MICRO_SUPPORT_CARD) +void support_card_init(void); +void support_card_late_init(void); +void led_puts(const char *s); +#else +static inline void support_card_init(void) +{ +} + +static inline void support_card_late_init(void) +{ +} + +static inline void led_puts(const char *s) +{ +} +#endif + +#endif /* MICRO_SUPPORT_CARD_H */ diff --git a/roms/u-boot/arch/arm/mach-uniphier/mmc-boot-mode.c b/roms/u-boot/arch/arm/mach-uniphier/mmc-boot-mode.c new file mode 100644 index 000000000..e47e5df64 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/mmc-boot-mode.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <mmc.h> +#include <spl.h> + +u32 spl_mmc_boot_mode(const u32 boot_device) +{ + struct mmc *mmc; + + /* + * work around a bug in the Boot ROM of LD4, Pro4, and sLD8: + * + * The boot ROM in these SoCs breaks the PARTITION_CONFIG [179] of + * Extended CSD register; when switching to the Boot Partition 1, the + * Boot ROM should issue the SWITCH command (CMD6) with Set Bits for + * the Access Bits, but in fact it uses Write Byte for the Access Bits. + * As a result, the BOOT_PARTITION_ENABLE field of the PARTITION_CONFIG + * is lost. This bug was fixed for PH1-Pro5 and later SoCs. + * + * Fixup mmc->part_config here because it is used to determine the + * partition which the U-Boot image is read from. + */ + mmc = find_mmc_device(0); + mmc->part_config &= ~EXT_CSD_BOOT_PART_NUM(PART_ACCESS_MASK); + mmc->part_config |= EXT_CSD_BOOT_PARTITION_ENABLE; + + return MMCSD_MODE_EMMCBOOT; +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/mmc-first-dev.c b/roms/u-boot/arch/arm/mach-uniphier/mmc-first-dev.c new file mode 100644 index 000000000..45bb10f8e --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/mmc-first-dev.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <command.h> +#include <env.h> +#include <mmc.h> +#include <linux/errno.h> + +static int find_first_mmc_device(bool is_sd) +{ + struct mmc *mmc; + int i; + + for (i = 0; (mmc = find_mmc_device(i)); i++) { + if (!mmc_init(mmc) && + ((is_sd && IS_SD(mmc)) || (!is_sd && IS_MMC(mmc)))) + return i; + } + + return -ENODEV; +} + +int mmc_get_env_dev(void) +{ + return find_first_mmc_device(false); +} + +static int do_mmcsetn(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + int dev; + + dev = find_first_mmc_device(false); + if (dev < 0) + return CMD_RET_FAILURE; + + env_set_ulong("mmc_first_dev", dev); + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD( + mmcsetn, 1, 1, do_mmcsetn, + "Set the first MMC (not SD) dev number to \"mmc_first_dev\" environment", + "" +); + +static int do_sdsetn(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + int dev; + + dev = find_first_mmc_device(true); + if (dev < 0) + return CMD_RET_FAILURE; + + env_set_ulong("sd_first_dev", dev); + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD( + sdsetn, 1, 1, do_sdsetn, + "Set the first SD dev number to \"sd_first_dev\" environment", + "" +); diff --git a/roms/u-boot/arch/arm/mach-uniphier/reset.c b/roms/u-boot/arch/arm/mach-uniphier/reset.c new file mode 100644 index 000000000..dddb48ec4 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/reset.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2012-2014 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <cpu_func.h> +#include <linux/io.h> +#include <asm/secure.h> + +#include "sc-regs.h" + +/* If PSCI is enabled, this is used for SYSTEM_RESET function */ +#ifdef CONFIG_ARMV7_PSCI +#define __SECURE __secure +#else +#define __SECURE +#endif + +void __SECURE reset_cpu(void) +{ + u32 tmp; + + writel(5, sc_base + SC_IRQTIMSET); /* default value */ + + tmp = readl(sc_base + SC_SLFRSTSEL); + tmp &= ~0x3; /* mask [1:0] */ + tmp |= 0x0; /* XRST reboot */ + writel(tmp, sc_base + SC_SLFRSTSEL); + + tmp = readl(sc_base + SC_SLFRSTCTL); + tmp |= 0x1; + writel(tmp, sc_base + SC_SLFRSTCTL); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/sc-regs.h b/roms/u-boot/arch/arm/mach-uniphier/sc-regs.h new file mode 100644 index 000000000..e43116e06 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/sc-regs.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * UniPhier SC (System Control) block registers + * + * Copyright (C) 2011-2015 Panasonic Corporation + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#ifndef ARCH_SC_REGS_H +#define ARCH_SC_REGS_H + +#ifndef __ASSEMBLY__ +#include <linux/compiler.h> +#define sc_base ((void __iomem *)SC_BASE) +#endif + +#define SC_BASE 0x61840000 + +#define SC_DPLLCTRL 0x1200 +#define SC_DPLLCTRL_SSC_EN (0x1 << 31) +#define SC_DPLLCTRL_FOUTMODE_MASK (0xf << 16) +#define SC_DPLLCTRL_SSC_RATE (0x1 << 15) + +#define SC_DPLLCTRL2 0x1204 +#define SC_DPLLCTRL2_NRSTDS (0x1 << 28) + +#define SC_DPLLCTRL3 0x1208 +#define SC_DPLLCTRL3_LPFSEL_COEF2 (0x0 << 31) +#define SC_DPLLCTRL3_LPFSEL_COEF3 (0x1 << 31) + +#define SC_UPLLCTRL 0x1210 + +#define SC_VPLL27ACTRL 0x1270 +#define SC_VPLL27ACTRL2 0x1274 +#define SC_VPLL27ACTRL3 0x1278 + +#define SC_VPLL27BCTRL 0x1290 +#define SC_VPLL27BCTRL2 0x1294 +#define SC_VPLL27BCTRL3 0x1298 + +#define SC_RSTCTRL 0x2000 +#define SC_RSTCTRL_NRST_USB3B0 (0x1 << 17) /* USB3 #0 bus */ +#define SC_RSTCTRL_NRST_USB3C0 (0x1 << 16) /* USB3 #0 core */ +#define SC_RSTCTRL_NRST_ETHER (0x1 << 12) +#define SC_RSTCTRL_NRST_GIO (0x1 << 6) +/* Pro4 or older */ +#define SC_RSTCTRL_NRST_UMC1 (0x1 << 5) +#define SC_RSTCTRL_NRST_UMC0 (0x1 << 4) +#define SC_RSTCTRL_NRST_NAND (0x1 << 2) + +#define SC_RSTCTRL2 0x2004 +#define SC_RSTCTRL2_NRST_USB3B1 (0x1 << 17) /* USB3 #1 bus */ +#define SC_RSTCTRL2_NRST_USB3C1 (0x1 << 16) /* USB3 #1 core */ + +#define SC_RSTCTRL3 0x2008 + +/* Pro5 or newer */ +#define SC_RSTCTRL4 0x200c +#define SC_RSTCTRL4_NRST_UMCSB (0x1 << 12) /* UMC system bus */ +#define SC_RSTCTRL4_NRST_UMCA2 (0x1 << 10) /* UMC ch2 standby */ +#define SC_RSTCTRL4_NRST_UMCA1 (0x1 << 9) /* UMC ch1 standby */ +#define SC_RSTCTRL4_NRST_UMCA0 (0x1 << 8) /* UMC ch0 standby */ +#define SC_RSTCTRL4_NRST_UMC32 (0x1 << 6) /* UMC ch2 */ +#define SC_RSTCTRL4_NRST_UMC31 (0x1 << 5) /* UMC ch1 */ +#define SC_RSTCTRL4_NRST_UMC30 (0x1 << 4) /* UMC ch0 */ + +#define SC_RSTCTRL5 0x2010 + +#define SC_RSTCTRL6 0x2014 + +#define SC_CLKCTRL 0x2104 +#define SC_CLKCTRL_CEN_USB31 (0x1 << 17) /* USB3 #1 */ +#define SC_CLKCTRL_CEN_USB30 (0x1 << 16) /* USB3 #0 */ +#define SC_CLKCTRL_CEN_ETHER (0x1 << 12) +#define SC_CLKCTRL_CEN_GIO (0x1 << 6) +/* Pro4 or older */ +#define SC_CLKCTRL_CEN_UMC (0x1 << 4) +#define SC_CLKCTRL_CEN_NAND (0x1 << 2) +#define SC_CLKCTRL_CEN_SBC (0x1 << 1) +#define SC_CLKCTRL_CEN_PERI (0x1 << 0) + +/* Pro5 or newer */ +#define SC_CLKCTRL4 0x210c +#define SC_CLKCTRL4_CEN_UMCSB (0x1 << 12) /* UMC system bus */ +#define SC_CLKCTRL4_CEN_UMC2 (0x1 << 2) /* UMC ch2 */ +#define SC_CLKCTRL4_CEN_UMC1 (0x1 << 1) /* UMC ch1 */ +#define SC_CLKCTRL4_CEN_UMC0 (0x1 << 0) /* UMC ch0 */ + +/* System reset control register */ +#define SC_IRQTIMSET 0x3000 +#define SC_SLFRSTSEL 0x3010 +#define SC_SLFRSTCTL 0x3014 + +#endif /* ARCH_SC_REGS_H */ diff --git a/roms/u-boot/arch/arm/mach-uniphier/sc64-regs.h b/roms/u-boot/arch/arm/mach-uniphier/sc64-regs.h new file mode 100644 index 000000000..fdcca232b --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/sc64-regs.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * UniPhier SC (System Control) block registers for ARMv8 SoCs + * + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#ifndef SC64_REGS_H +#define SC64_REGS_H + +#ifndef __ASSEMBLY__ +#include <linux/compiler.h> +extern void __iomem *sc_base; +#endif + +#define SC_BASE 0x61840000 + +#define SC_RSTCTRL 0x2000 +#define SC_RSTCTRL3 0x2008 +#define SC_RSTCTRL4 0x200c +#define SC_RSTCTRL5 0x2010 +#define SC_RSTCTRL6 0x2014 +#define SC_RSTCTRL7 0x2018 + +#define SC_CLKCTRL 0x2100 +#define SC_CLKCTRL3 0x2108 +#define SC_CLKCTRL4 0x210c +#define SC_CLKCTRL5 0x2110 +#define SC_CLKCTRL6 0x2114 +#define SC_CLKCTRL7 0x2118 + +#define SC_CA72_GEARST 0x8000 +#define SC_CA72_GEARSET 0x8004 +#define SC_CA72_GEARUPD 0x8008 +#define SC_CA53_GEARST 0x8080 +#define SC_CA53_GEARSET 0x8084 +#define SC_CA53_GEARUPD 0x8088 +#define SC_CA_GEARUPD (1 << 0) + +#endif /* SC64_REGS_H */ diff --git a/roms/u-boot/arch/arm/mach-uniphier/sg-regs.h b/roms/u-boot/arch/arm/mach-uniphier/sg-regs.h new file mode 100644 index 000000000..a0fa51a8b --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/sg-regs.h @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * UniPhier SG (SoC Glue) block registers + * + * Copyright (C) 2011-2015 Copyright (C) 2011-2015 Panasonic Corporation + * Copyright (C) 2016-2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#ifndef UNIPHIER_SG_REGS_H +#define UNIPHIER_SG_REGS_H + +#include <linux/bitops.h> + +#ifndef __ASSEMBLY__ +#include <linux/compiler.h> +#ifdef CONFIG_ARCH_UNIPHIER_V8_MULTI +extern void __iomem *sg_base; +#else +#define sg_base ((void __iomem *)SG_BASE) +#endif +#endif /* __ASSEMBLY__ */ + +/* Base Address */ +#define SG_BASE 0x5f800000 + +/* Revision */ +#define SG_REVISION 0x0000 +#define SG_REVISION_TYPE_MASK GENMASK(23, 16) +#define SG_REVISION_MODEL_MASK GENMASK(10, 8) +#define SG_REVISION_REV_MASK GENMASK(4, 0) + +/* Memory Configuration */ +#define SG_MEMCONF 0x0400 + +#define SG_MEMCONF_CH0_SZ_MASK ((0x1 << 10) | (0x03 << 0)) +#define SG_MEMCONF_CH0_SZ_64M ((0x0 << 10) | (0x01 << 0)) +#define SG_MEMCONF_CH0_SZ_128M ((0x0 << 10) | (0x02 << 0)) +#define SG_MEMCONF_CH0_SZ_256M ((0x0 << 10) | (0x03 << 0)) +#define SG_MEMCONF_CH0_SZ_512M ((0x1 << 10) | (0x00 << 0)) +#define SG_MEMCONF_CH0_SZ_1G ((0x1 << 10) | (0x01 << 0)) +#define SG_MEMCONF_CH0_NUM_MASK (0x1 << 8) +#define SG_MEMCONF_CH0_NUM_1 (0x1 << 8) +#define SG_MEMCONF_CH0_NUM_2 (0x0 << 8) + +#define SG_MEMCONF_CH1_SZ_MASK ((0x1 << 11) | (0x03 << 2)) +#define SG_MEMCONF_CH1_SZ_64M ((0x0 << 11) | (0x01 << 2)) +#define SG_MEMCONF_CH1_SZ_128M ((0x0 << 11) | (0x02 << 2)) +#define SG_MEMCONF_CH1_SZ_256M ((0x0 << 11) | (0x03 << 2)) +#define SG_MEMCONF_CH1_SZ_512M ((0x1 << 11) | (0x00 << 2)) +#define SG_MEMCONF_CH1_SZ_1G ((0x1 << 11) | (0x01 << 2)) +#define SG_MEMCONF_CH1_NUM_MASK (0x1 << 9) +#define SG_MEMCONF_CH1_NUM_1 (0x1 << 9) +#define SG_MEMCONF_CH1_NUM_2 (0x0 << 9) + +#define SG_MEMCONF_CH2_SZ_MASK ((0x1 << 26) | (0x03 << 16)) +#define SG_MEMCONF_CH2_SZ_64M ((0x0 << 26) | (0x01 << 16)) +#define SG_MEMCONF_CH2_SZ_128M ((0x0 << 26) | (0x02 << 16)) +#define SG_MEMCONF_CH2_SZ_256M ((0x0 << 26) | (0x03 << 16)) +#define SG_MEMCONF_CH2_SZ_512M ((0x1 << 26) | (0x00 << 16)) +#define SG_MEMCONF_CH2_SZ_1G ((0x1 << 26) | (0x01 << 16)) +#define SG_MEMCONF_CH2_NUM_MASK (0x1 << 24) +#define SG_MEMCONF_CH2_NUM_1 (0x1 << 24) +#define SG_MEMCONF_CH2_NUM_2 (0x0 << 24) +/* PH1-LD6b, ProXstream2, PH1-LD20 only */ +#define SG_MEMCONF_CH2_DISABLE (0x1 << 21) + +#define SG_MEMCONF_SPARSEMEM (0x1 << 4) + +#define SG_USBPHYCTRL 0x0500 +#define SG_ETPHYPSHUT 0x0554 +#define SG_ETPHYCNT 0x0550 + +/* Pin Control */ +#define SG_PINCTRL_BASE 0x1000 + +/* PH1-Pro4, PH1-Pro5 */ +#define SG_LOADPINCTRL 0x1700 + +/* Input Enable */ +#define SG_IECTRL 0x1d00 + +/* Pin Monitor */ +#define SG_PINMON0 0x00100100 +#define SG_PINMON2 0x00100108 + +#define SG_PINMON0_CLK_MODE_UPLLSRC_MASK (0x3 << 19) +#define SG_PINMON0_CLK_MODE_UPLLSRC_DEFAULT (0x0 << 19) +#define SG_PINMON0_CLK_MODE_UPLLSRC_VPLL27A (0x2 << 19) +#define SG_PINMON0_CLK_MODE_UPLLSRC_VPLL27B (0x3 << 19) + +#define SG_PINMON0_CLK_MODE_AXOSEL_MASK (0x3 << 16) +#define SG_PINMON0_CLK_MODE_AXOSEL_24576KHZ (0x0 << 16) +#define SG_PINMON0_CLK_MODE_AXOSEL_25000KHZ (0x1 << 16) +#define SG_PINMON0_CLK_MODE_AXOSEL_6144KHZ (0x2 << 16) +#define SG_PINMON0_CLK_MODE_AXOSEL_6250KHZ (0x3 << 16) + +#define SG_PINMON0_CLK_MODE_AXOSEL_DEFAULT (0x0 << 16) +#define SG_PINMON0_CLK_MODE_AXOSEL_25000KHZ_U (0x1 << 16) +#define SG_PINMON0_CLK_MODE_AXOSEL_20480KHZ (0x2 << 16) +#define SG_PINMON0_CLK_MODE_AXOSEL_25000KHZ_A (0x3 << 16) + +#endif /* UNIPHIER_SG_REGS_H */ diff --git a/roms/u-boot/arch/arm/mach-uniphier/soc-info.c b/roms/u-boot/arch/arm/mach-uniphier/soc-info.c new file mode 100644 index 000000000..b0221016d --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/soc-info.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <linux/bitfield.h> +#include <linux/io.h> +#include <linux/types.h> + +#include "sg-regs.h" +#include "soc-info.h" + +unsigned int uniphier_get_soc_id(void) +{ + u32 rev = readl(sg_base + SG_REVISION); + + return FIELD_GET(SG_REVISION_TYPE_MASK, rev); +} + +unsigned int uniphier_get_soc_model(void) +{ + u32 rev = readl(sg_base + SG_REVISION); + + return FIELD_GET(SG_REVISION_MODEL_MASK, rev); +} + +unsigned int uniphier_get_soc_revision(void) +{ + u32 rev = readl(sg_base + SG_REVISION); + + return FIELD_GET(SG_REVISION_REV_MASK, rev); +} diff --git a/roms/u-boot/arch/arm/mach-uniphier/soc-info.h b/roms/u-boot/arch/arm/mach-uniphier/soc-info.h new file mode 100644 index 000000000..73256b7c7 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/soc-info.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2017 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#ifndef __UNIPHIER_SOC_INFO_H__ +#define __UNIPHIER_SOC_INFO_H__ + +#include <linux/kernel.h> +#include <linux/stddef.h> + +#define UNIPHIER_LD4_ID 0x26 +#define UNIPHIER_PRO4_ID 0x28 +#define UNIPHIER_SLD8_ID 0x29 +#define UNIPHIER_PRO5_ID 0x2a +#define UNIPHIER_PXS2_ID 0x2e +#define UNIPHIER_LD6B_ID 0x2f +#define UNIPHIER_LD11_ID 0x31 +#define UNIPHIER_LD20_ID 0x32 +#define UNIPHIER_PXS3_ID 0x35 + +unsigned int uniphier_get_soc_id(void); +unsigned int uniphier_get_soc_model(void); +unsigned int uniphier_get_soc_revision(void); + +#define UNIPHIER_DEFINE_SOCDATA_FUNC(__func_name, __table) \ +static typeof(&__table[0]) __func_name(void) \ +{ \ + unsigned int soc_id; \ + int i; \ + \ + soc_id = uniphier_get_soc_id(); \ + for (i = 0; i < ARRAY_SIZE(__table); i++) { \ + if (__table[i].soc_id == soc_id) \ + return &__table[i]; \ + } \ + \ + return NULL; \ +} + +#endif /* __UNIPHIER_SOC_INFO_H__ */ diff --git a/roms/u-boot/arch/arm/mach-uniphier/spl_board_init.c b/roms/u-boot/arch/arm/mach-uniphier/spl_board_init.c new file mode 100644 index 000000000..a93b8cdc0 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-uniphier/spl_board_init.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015-2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <debug_uart.h> +#include <hang.h> +#include <spl.h> + +#include "init.h" +#include "micro-support-card.h" +#include "soc-info.h" + +struct uniphier_spl_initdata { + unsigned int soc_id; + void (*bcu_init)(const struct uniphier_board_data *bd); + void (*early_clk_init)(void); + int (*dpll_init)(const struct uniphier_board_data *bd); + int (*memconf_init)(const struct uniphier_board_data *bd); + void (*dram_clk_init)(void); + int (*umc_init)(const struct uniphier_board_data *bd); +}; + +static const struct uniphier_spl_initdata uniphier_spl_initdata[] = { +#if defined(CONFIG_ARCH_UNIPHIER_LD4) + { + .soc_id = UNIPHIER_LD4_ID, + .bcu_init = uniphier_ld4_bcu_init, + .early_clk_init = uniphier_ld4_early_clk_init, + .dpll_init = uniphier_ld4_dpll_init, + .memconf_init = uniphier_memconf_2ch_init, + .dram_clk_init = uniphier_ld4_dram_clk_init, + .umc_init = uniphier_ld4_umc_init, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PRO4) + { + .soc_id = UNIPHIER_PRO4_ID, + .early_clk_init = uniphier_ld4_early_clk_init, + .dpll_init = uniphier_pro4_dpll_init, + .memconf_init = uniphier_memconf_2ch_init, + .dram_clk_init = uniphier_ld4_dram_clk_init, + .umc_init = uniphier_pro4_umc_init, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_SLD8) + { + .soc_id = UNIPHIER_SLD8_ID, + .bcu_init = uniphier_ld4_bcu_init, + .early_clk_init = uniphier_ld4_early_clk_init, + .dpll_init = uniphier_sld8_dpll_init, + .memconf_init = uniphier_memconf_2ch_init, + .dram_clk_init = uniphier_ld4_dram_clk_init, + .umc_init = uniphier_sld8_umc_init, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PRO5) + { + .soc_id = UNIPHIER_PRO5_ID, + .early_clk_init = uniphier_ld4_early_clk_init, + .dpll_init = uniphier_pro5_dpll_init, + .memconf_init = uniphier_memconf_2ch_init, + .dram_clk_init = uniphier_pro5_dram_clk_init, + .umc_init = uniphier_pro5_umc_init, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_PXS2) + { + .soc_id = UNIPHIER_PXS2_ID, + .early_clk_init = uniphier_ld4_early_clk_init, + .dpll_init = uniphier_pxs2_dpll_init, + .memconf_init = uniphier_memconf_3ch_init, + .dram_clk_init = uniphier_pxs2_dram_clk_init, + .umc_init = uniphier_pxs2_umc_init, + }, +#endif +#if defined(CONFIG_ARCH_UNIPHIER_LD6B) + { + .soc_id = UNIPHIER_LD6B_ID, + .early_clk_init = uniphier_ld4_early_clk_init, + .dpll_init = uniphier_pxs2_dpll_init, + .memconf_init = uniphier_memconf_3ch_init, + .dram_clk_init = uniphier_pxs2_dram_clk_init, + .umc_init = uniphier_pxs2_umc_init, + }, +#endif +}; +UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_spl_initdata, uniphier_spl_initdata) + +void spl_board_init(void) +{ + const struct uniphier_board_data *bd; + const struct uniphier_spl_initdata *initdata; + int ret; + +#ifdef CONFIG_DEBUG_UART + debug_uart_init(); +#endif + + bd = uniphier_get_board_param(); + if (!bd) + hang(); + + initdata = uniphier_get_spl_initdata(); + if (!initdata) + hang(); + + if (initdata->bcu_init) + initdata->bcu_init(bd); + + initdata->early_clk_init(); + + preloader_console_init(); + + ret = initdata->dpll_init(bd); + if (ret) { + pr_err("failed to init DPLL\n"); + hang(); + } + + ret = initdata->memconf_init(bd); + if (ret) { + pr_err("failed to init MEMCONF\n"); + hang(); + } + + initdata->dram_clk_init(); + + ret = initdata->umc_init(bd); + if (ret) { + pr_err("failed to init DRAM\n"); + hang(); + } +} |