aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/cpu')
-rw-r--r--arch/arm/cpu/armv7/ls102xa/Makefile4
-rw-r--r--arch/arm/cpu/armv7/ls102xa/fdt.c21
-rw-r--r--arch/arm/cpu/armv7/ls102xa/psci.S126
-rw-r--r--arch/arm/cpu/armv7/sunxi/psci_sun6i.S22
-rw-r--r--arch/arm/cpu/armv7/sunxi/psci_sun7i.S22
-rw-r--r--arch/arm/cpu/armv8/fsl-lsch3/README25
-rw-r--r--arch/arm/cpu/armv8/fsl-lsch3/cpu.c64
-rw-r--r--arch/arm/cpu/armv8/fsl-lsch3/fdt.c114
-rw-r--r--arch/arm/cpu/armv8/fsl-lsch3/speed.c2
-rw-r--r--arch/arm/cpu/armv8/start.S8
10 files changed, 337 insertions, 71 deletions
diff --git a/arch/arm/cpu/armv7/ls102xa/Makefile b/arch/arm/cpu/armv7/ls102xa/Makefile
index 2e6a20757f..2d55782749 100644
--- a/arch/arm/cpu/armv7/ls102xa/Makefile
+++ b/arch/arm/cpu/armv7/ls102xa/Makefile
@@ -12,3 +12,7 @@ obj-y += fsl_epu.o
obj-$(CONFIG_OF_LIBFDT) += fdt.o
obj-$(CONFIG_SYS_HAS_SERDES) += fsl_ls1_serdes.o ls102xa_serdes.o
obj-$(CONFIG_SPL) += spl.o
+
+ifdef CONFIG_ARMV7_PSCI
+obj-y += psci.o
+endif
diff --git a/arch/arm/cpu/armv7/ls102xa/fdt.c b/arch/arm/cpu/armv7/ls102xa/fdt.c
index 71a175392f..e01d911780 100644
--- a/arch/arm/cpu/armv7/ls102xa/fdt.c
+++ b/arch/arm/cpu/armv7/ls102xa/fdt.c
@@ -29,29 +29,30 @@ void ft_fixup_enet_phy_connect_type(void *fdt)
char phy[16];
int phy_node;
int i = 0;
- int enet_id = 0;
uint32_t ph;
while ((dev = eth_get_dev_by_index(i++)) != NULL) {
- if (strstr(dev->name, "eTSEC1"))
- enet_id = 0;
- else if (strstr(dev->name, "eTSEC2"))
- enet_id = 1;
- else if (strstr(dev->name, "eTSEC3"))
- enet_id = 2;
- else
+ if (strstr(dev->name, "eTSEC1")) {
+ strcpy(enet, "ethernet0");
+ strcpy(phy, "enet0_rgmii_phy");
+ } else if (strstr(dev->name, "eTSEC2")) {
+ strcpy(enet, "ethernet1");
+ strcpy(phy, "enet1_rgmii_phy");
+ } else if (strstr(dev->name, "eTSEC3")) {
+ strcpy(enet, "ethernet2");
+ strcpy(phy, "enet2_rgmii_phy");
+ } else {
continue;
+ }
priv = dev->priv;
if (priv->flags & TSEC_SGMII)
continue;
- sprintf(enet, "ethernet%d", enet_id);
enet_path = fdt_get_alias(fdt, enet);
if (!enet_path)
continue;
- sprintf(phy, "enet%d_rgmii_phy", enet_id);
phy_path = fdt_get_alias(fdt, phy);
if (!phy_path)
continue;
diff --git a/arch/arm/cpu/armv7/ls102xa/psci.S b/arch/arm/cpu/armv7/ls102xa/psci.S
new file mode 100644
index 0000000000..cf5cd48bcb
--- /dev/null
+++ b/arch/arm/cpu/armv7/ls102xa/psci.S
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ * Author: Wang Dongsheng <dongsheng.wang@freescale.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+
+#include <asm/armv7.h>
+#include <asm/arch-armv7/generictimer.h>
+#include <asm/psci.h>
+
+#define SCFG_CORE0_SFT_RST 0x130
+#define SCFG_CORESRENCR 0x204
+
+#define DCFG_CCSR_BRR 0x0E4
+#define DCFG_CCSR_SCRATCHRW1 0x200
+
+ .pushsection ._secure.text, "ax"
+
+ .arch_extension sec
+
+#define ONE_MS (GENERIC_TIMER_CLK / 1000)
+#define RESET_WAIT (30 * ONE_MS)
+
+ @ r1 = target CPU
+ @ r2 = target PC
+.globl psci_cpu_on
+psci_cpu_on:
+ push {lr}
+
+ @ Clear and Get the correct CPU number
+ @ r1 = 0xf01
+ and r1, r1, #0xff
+
+ mov r0, r1
+ bl psci_get_cpu_stack_top
+ str r2, [r0]
+ dsb
+
+ @ Get DCFG base address
+ movw r4, #(CONFIG_SYS_FSL_GUTS_ADDR & 0xffff)
+ movt r4, #(CONFIG_SYS_FSL_GUTS_ADDR >> 16)
+
+ @ Detect target CPU state
+ ldr r2, [r4, #DCFG_CCSR_BRR]
+ rev r2, r2
+ lsr r2, r2, r1
+ ands r2, r2, #1
+ beq holdoff_release
+
+ @ Reset target CPU
+ @ Get SCFG base address
+ movw r0, #(CONFIG_SYS_FSL_SCFG_ADDR & 0xffff)
+ movt r0, #(CONFIG_SYS_FSL_SCFG_ADDR >> 16)
+
+ @ Enable CORE Soft Reset
+ movw r5, #0
+ movt r5, #(1 << 15)
+ rev r5, r5
+ str r5, [r0, #SCFG_CORESRENCR]
+
+ @ Get CPUx offset register
+ mov r6, #0x4
+ mul r6, r6, r1
+ add r2, r0, r6
+
+ @ Do reset on target CPU
+ movw r5, #0
+ movt r5, #(1 << 15)
+ rev r5, r5
+ str r5, [r2, #SCFG_CORE0_SFT_RST]
+
+ @ Wait target CPU up
+ timer_wait r2, RESET_WAIT
+
+ @ Disable CORE soft reset
+ mov r5, #0
+ str r5, [r0, #SCFG_CORESRENCR]
+
+holdoff_release:
+ @ Release on target CPU
+ ldr r2, [r4, #DCFG_CCSR_BRR]
+ mov r6, #1
+ lsl r6, r6, r1 @ 32 bytes per CPU
+
+ rev r6, r6
+ orr r2, r2, r6
+ str r2, [r4, #DCFG_CCSR_BRR]
+
+ @ Set secondary boot entry
+ ldr r6, =psci_cpu_entry
+ rev r6, r6
+ str r6, [r4, #DCFG_CCSR_SCRATCHRW1]
+
+ isb
+ dsb
+
+ @ Return
+ mov r0, #ARM_PSCI_RET_SUCCESS
+
+ pop {lr}
+ bx lr
+
+.globl psci_cpu_off
+psci_cpu_off:
+ bl psci_cpu_off_common
+
+1: wfi
+ b 1b
+
+.globl psci_arch_init
+psci_arch_init:
+ mov r6, lr
+
+ bl psci_get_cpu_id
+ bl psci_get_cpu_stack_top
+ mov sp, r0
+
+ bx r6
+
+ .globl psci_text_end
+psci_text_end:
+ .popsection
diff --git a/arch/arm/cpu/armv7/sunxi/psci_sun6i.S b/arch/arm/cpu/armv7/sunxi/psci_sun6i.S
index d4cb51e044..4ff46e4fc0 100644
--- a/arch/arm/cpu/armv7/sunxi/psci_sun6i.S
+++ b/arch/arm/cpu/armv7/sunxi/psci_sun6i.S
@@ -18,6 +18,8 @@
*/
#include <config.h>
+
+#include <asm/arch-armv7/generictimer.h>
#include <asm/gic.h>
#include <asm/macro.h>
#include <asm/psci.h>
@@ -43,26 +45,6 @@
#define GICD_BASE 0x1c81000
#define GICC_BASE 0x1c82000
-.macro timer_wait reg, ticks
- @ Program CNTP_TVAL
- movw \reg, #(\ticks & 0xffff)
- movt \reg, #(\ticks >> 16)
- mcr p15, 0, \reg, c14, c2, 0
- isb
- @ Enable physical timer, mask interrupt
- mov \reg, #3
- mcr p15, 0, \reg, c14, c2, 1
- @ Poll physical timer until ISTATUS is on
-1: isb
- mrc p15, 0, \reg, c14, c2, 1
- ands \reg, \reg, #4
- bne 1b
- @ Disable timer
- mov \reg, #0
- mcr p15, 0, \reg, c14, c2, 1
- isb
-.endm
-
.globl psci_fiq_enter
psci_fiq_enter:
push {r0-r12}
diff --git a/arch/arm/cpu/armv7/sunxi/psci_sun7i.S b/arch/arm/cpu/armv7/sunxi/psci_sun7i.S
index bbfeec8ba8..e15d587f29 100644
--- a/arch/arm/cpu/armv7/sunxi/psci_sun7i.S
+++ b/arch/arm/cpu/armv7/sunxi/psci_sun7i.S
@@ -18,6 +18,8 @@
*/
#include <config.h>
+
+#include <asm/arch-armv7/generictimer.h>
#include <asm/gic.h>
#include <asm/macro.h>
#include <asm/psci.h>
@@ -43,26 +45,6 @@
#define GICD_BASE 0x1c81000
#define GICC_BASE 0x1c82000
-.macro timer_wait reg, ticks
- @ Program CNTP_TVAL
- movw \reg, #(\ticks & 0xffff)
- movt \reg, #(\ticks >> 16)
- mcr p15, 0, \reg, c14, c2, 0
- isb
- @ Enable physical timer, mask interrupt
- mov \reg, #3
- mcr p15, 0, \reg, c14, c2, 1
- @ Poll physical timer until ISTATUS is on
-1: isb
- mrc p15, 0, \reg, c14, c2, 1
- ands \reg, \reg, #4
- bne 1b
- @ Disable timer
- mov \reg, #0
- mcr p15, 0, \reg, c14, c2, 1
- isb
-.endm
-
.globl psci_fiq_enter
psci_fiq_enter:
push {r0-r12}
diff --git a/arch/arm/cpu/armv8/fsl-lsch3/README b/arch/arm/cpu/armv8/fsl-lsch3/README
index 37f07fbb76..3c15479315 100644
--- a/arch/arm/cpu/armv8/fsl-lsch3/README
+++ b/arch/arm/cpu/armv8/fsl-lsch3/README
@@ -9,6 +9,31 @@ Freescale LayerScape with Chassis Generation 3
This architecture supports Freescale ARMv8 SoCs with Chassis generation 3,
for example LS2085A.
+DDR Layout
+============
+Entire DDR region splits into two regions.
+ - Region 1 is at address 0x8000_0000 to 0xffff_ffff.
+ - Region 2 is at 0x80_8000_0000 to the top of total memory,
+ for example 16GB, 0x83_ffff_ffff.
+
+All DDR memory is marked as cache-enabled.
+
+When MC and Debug server is enabled, they carve 512MB away from the high
+end of DDR. For example, if the total DDR is 16GB, it shrinks to 15.5GB
+with MC and Debug server enabled. Linux only sees 15.5GB.
+
+The reserved 512MB layout looks like
+
+ +---------------+ <-- top/end of memory
+ | 256MB | debug server
+ +---------------+
+ | 256MB | MC
+ +---------------+
+ | ... |
+
+MC requires the memory to be aligned with 512MB, so even debug server is
+not enabled, 512MB is reserved, not 256MB.
+
Flash Layout
============
diff --git a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
index 67145778b9..d02c0beef9 100644
--- a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
@@ -9,6 +9,7 @@
#include <asm/system.h>
#include <asm/armv8/mmu.h>
#include <asm/io.h>
+#include <asm/arch-fsl-lsch3/soc.h>
#include <asm/arch-fsl-lsch3/immap_lsch3.h>
#include <fsl_debug_server.h>
#include <fsl-mc/fsl_mc.h>
@@ -22,6 +23,35 @@
DECLARE_GLOBAL_DATA_PTR;
+static struct cpu_type cpu_type_list[] = {
+#ifdef CONFIG_LS2085A
+ CPU_TYPE_ENTRY(LS2085, LS2085, 8),
+ CPU_TYPE_ENTRY(LS2080, LS2080, 8),
+ CPU_TYPE_ENTRY(LS2045, LS2045, 4),
+#endif
+};
+
+void cpu_name(char *name)
+{
+ struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+ unsigned int i, svr, ver;
+
+ svr = in_le32(&gur->svr);
+ ver = SVR_SOC_VER(svr);
+
+ for (i = 0; i < ARRAY_SIZE(cpu_type_list); i++)
+ if ((cpu_type_list[i].soc_ver & SVR_WO_E) == ver) {
+ strcpy(name, cpu_type_list[i].name);
+
+ if (IS_E_PROCESSOR(svr))
+ strcat(name, "E");
+ break;
+ }
+
+ if (i == ARRAY_SIZE(cpu_type_list))
+ strcpy(name, "unknown");
+}
+
#ifndef CONFIG_SYS_DCACHE_OFF
/*
* To start MMU before DDR is available, we create MMU table in SRAM.
@@ -52,6 +82,12 @@ DECLARE_GLOBAL_DATA_PTR;
TCR_ORGN_NC | \
TCR_IRGN_NC | \
TCR_T0SZ(LSCH3_VA_BITS))
+#define LSCH3_TCR_FINAL (TCR_TG0_4K | \
+ TCR_EL2_PS_40BIT | \
+ TCR_SHARED_OUTER | \
+ TCR_ORGN_WBWA | \
+ TCR_IRGN_WBWA | \
+ TCR_T0SZ(LSCH3_VA_BITS))
/*
* Final MMU
@@ -236,21 +272,8 @@ static inline void final_mmu_setup(void)
/* point TTBR to the new table */
el = current_el();
- asm volatile("dsb sy");
- if (el == 1) {
- asm volatile("msr ttbr0_el1, %0"
- : : "r" ((u64)level0_table) : "memory");
- } else if (el == 2) {
- asm volatile("msr ttbr0_el2, %0"
- : : "r" ((u64)level0_table) : "memory");
- } else if (el == 3) {
- asm volatile("msr ttbr0_el3, %0"
- : : "r" ((u64)level0_table) : "memory");
- } else {
- hang();
- }
- asm volatile("isb");
-
+ set_ttbr_tcr_mair(el, (u64)level0_table, LSCH3_TCR_FINAL,
+ MEMORY_ATTRIBUTES);
/*
* MMU is already enabled, just need to invalidate TLB to load the
* new table. The new table is compatible with the current table, if
@@ -380,6 +403,13 @@ int print_cpuinfo(void)
unsigned int i, core;
u32 type;
+ puts("SoC: ");
+
+ cpu_name(buf);
+ printf(" %s (0x%x)\n", buf, in_le32(&gur->svr));
+
+ memset((u8 *)buf, 0x00, ARRAY_SIZE(buf));
+
get_sys_info(&sysinfo);
puts("Clock Configuration:");
for_each_cpu(i, core, cpu_numcores(), cpu_mask()) {
@@ -394,8 +424,8 @@ int print_cpuinfo(void)
}
printf("\n Bus: %-4s MHz ",
strmhz(buf, sysinfo.freq_systembus));
- printf("DDR: %-4s MHz", strmhz(buf, sysinfo.freq_ddrbus));
- printf(" DP-DDR: %-4s MHz", strmhz(buf, sysinfo.freq_ddrbus2));
+ printf("DDR: %-4s MT/s", strmhz(buf, sysinfo.freq_ddrbus));
+ printf(" DP-DDR: %-4s MT/s", strmhz(buf, sysinfo.freq_ddrbus2));
puts("\n");
/* Display the RCW, so that no one gets confused as to what RCW
diff --git a/arch/arm/cpu/armv8/fsl-lsch3/fdt.c b/arch/arm/cpu/armv8/fsl-lsch3/fdt.c
index d37002333c..567c41927a 100644
--- a/arch/arm/cpu/armv8/fsl-lsch3/fdt.c
+++ b/arch/arm/cpu/armv8/fsl-lsch3/fdt.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <libfdt.h>
#include <fdt_support.h>
+#include <asm/arch-fsl-lsch3/fdt.h>
#ifdef CONFIG_FSL_ESDHC
#include <fsl_esdhc.h>
#endif
@@ -58,6 +59,113 @@ void ft_fixup_cpu(void *blob)
}
#endif
+/*
+ * the burden is on the the caller to not request a count
+ * exceeding the bounds of the stream_ids[] array
+ */
+void alloc_stream_ids(int start_id, int count, u32 *stream_ids, int max_cnt)
+{
+ int i;
+
+ if (count > max_cnt) {
+ printf("\n%s: ERROR: max per-device stream ID count exceed\n",
+ __func__);
+ return;
+ }
+
+ for (i = 0; i < count; i++)
+ stream_ids[i] = start_id++;
+}
+
+/*
+ * This function updates the mmu-masters property on the SMMU
+ * node as per the SMMU binding-- phandle and list of stream IDs
+ * for each MMU master.
+ */
+void append_mmu_masters(void *blob, const char *smmu_path,
+ const char *master_name, u32 *stream_ids, int count)
+{
+ u32 phandle;
+ int smmu_nodeoffset;
+ int master_nodeoffset;
+ int i;
+
+ /* get phandle of mmu master device */
+ master_nodeoffset = fdt_path_offset(blob, master_name);
+ if (master_nodeoffset < 0) {
+ printf("\n%s: ERROR: master not found\n", __func__);
+ return;
+ }
+ phandle = fdt_get_phandle(blob, master_nodeoffset);
+ if (!phandle) { /* if master has no phandle, create one */
+ phandle = fdt_create_phandle(blob, master_nodeoffset);
+ if (!phandle) {
+ printf("\n%s: ERROR: unable to create phandle\n",
+ __func__);
+ return;
+ }
+ }
+
+ /* append it to mmu-masters */
+ smmu_nodeoffset = fdt_path_offset(blob, smmu_path);
+ if (fdt_appendprop_u32(blob, smmu_nodeoffset, "mmu-masters",
+ phandle) < 0) {
+ printf("\n%s: ERROR: unable to update SMMU node\n", __func__);
+ return;
+ }
+
+ /* for each stream ID, append to mmu-masters */
+ for (i = 0; i < count; i++) {
+ fdt_appendprop_u32(blob, smmu_nodeoffset, "mmu-masters",
+ stream_ids[i]);
+ }
+
+ /* fix up #stream-id-cells with stream ID count */
+ if (fdt_setprop_u32(blob, master_nodeoffset, "#stream-id-cells",
+ count) < 0)
+ printf("\n%s: ERROR: unable to update #stream-id-cells\n",
+ __func__);
+}
+
+
+/*
+ * The info below summarizes how streamID partitioning works
+ * for ls2085a and how it is conveyed to the OS via the device tree.
+ *
+ * -non-PCI legacy, platform devices (USB, SD/MMC, SATA, DMA)
+ * -all legacy devices get a unique ICID assigned and programmed in
+ * their AMQR registers by u-boot
+ * -u-boot updates the hardware device tree with streamID properties
+ * for each platform/legacy device (smmu-masters property)
+ *
+ * -PCIe
+ * -for each PCI controller that is active (as per RCW settings),
+ * u-boot will allocate a range of ICID and convey that to Linux via
+ * the device tree (smmu-masters property)
+ *
+ * -DPAA2
+ * -u-boot will allocate a range of ICIDs to be used by the Management
+ * Complex for containers and will set these values in the MC DPC image.
+ * -the MC is responsible for allocating and setting up ICIDs
+ * for all DPAA2 devices.
+ *
+ */
+static void fdt_fixup_smmu(void *blob)
+{
+ int nodeoffset;
+
+ nodeoffset = fdt_path_offset(blob, "/iommu@5000000");
+ if (nodeoffset < 0) {
+ printf("\n%s: WARNING: no SMMU node found\n", __func__);
+ return;
+ }
+
+ /* fixup for all PCI controllers */
+#ifdef CONFIG_PCI
+ fdt_fixup_smmu_pcie(blob);
+#endif
+}
+
void ft_cpu_setup(void *blob, bd_t *bd)
{
#ifdef CONFIG_MP
@@ -69,7 +177,13 @@ void ft_cpu_setup(void *blob, bd_t *bd)
"clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
#endif
+#ifdef CONFIG_PCI
+ ft_pci_setup(blob, bd);
+#endif
+
#if defined(CONFIG_FSL_ESDHC)
fdt_fixup_esdhc(blob, bd);
#endif
+
+ fdt_fixup_smmu(blob);
}
diff --git a/arch/arm/cpu/armv8/fsl-lsch3/speed.c b/arch/arm/cpu/armv8/fsl-lsch3/speed.c
index cac4f925a4..d9f137cc2d 100644
--- a/arch/arm/cpu/armv8/fsl-lsch3/speed.c
+++ b/arch/arm/cpu/armv8/fsl-lsch3/speed.c
@@ -180,6 +180,8 @@ unsigned int mxc_get_clock(enum mxc_clock clk)
switch (clk) {
case MXC_I2C_CLK:
return get_bus_freq(0) / 2;
+ case MXC_DSPI_CLK:
+ return get_bus_freq(0) / 2;
default:
printf("Unsupported clock\n");
}
diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S
index e5f2766a4a..e70bed462a 100644
--- a/arch/arm/cpu/armv8/start.S
+++ b/arch/arm/cpu/armv8/start.S
@@ -115,18 +115,18 @@ apply_a57_core_errata:
#ifdef CONFIG_ARM_ERRATA_828024
mrs x0, S3_1_c15_c2_0 /* cpuactlr_el1 */
/* Disable non-allocate hint of w-b-n-a memory type */
- mov x0, #0x1 << 49
+ orr x0, x0, #1 << 49
/* Disable write streaming no L1-allocate threshold */
- mov x0, #0x3 << 25
+ orr x0, x0, #3 << 25
/* Disable write streaming no-allocate threshold */
- mov x0, #0x3 << 27
+ orr x0, x0, #3 << 27
msr S3_1_c15_c2_0, x0 /* cpuactlr_el1 */
#endif
#ifdef CONFIG_ARM_ERRATA_826974
mrs x0, S3_1_c15_c2_0 /* cpuactlr_el1 */
/* Disable speculative load execution ahead of a DMB */
- mov x0, #0x1 << 59
+ orr x0, x0, #1 << 59
msr S3_1_c15_c2_0, x0 /* cpuactlr_el1 */
#endif