summaryrefslogtreecommitdiff
path: root/arch/arm/cpu/armv8/fsl-lsch3/speed.c
diff options
context:
space:
mode:
authorYork Sun <yorksun@freescale.com>2014-06-23 15:15:54 -0700
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>2014-07-03 08:40:51 +0200
commit2f78eae5064728d6cd907148cfeaf8ba3e63b0ef (patch)
tree80b5d23e3c6d46424909954cbc9504288e8f7156 /arch/arm/cpu/armv8/fsl-lsch3/speed.c
parent22932ffc03e521130cfd33cae1fc2531eb42604a (diff)
downloadu-boot-imx-2f78eae5064728d6cd907148cfeaf8ba3e63b0ef.zip
u-boot-imx-2f78eae5064728d6cd907148cfeaf8ba3e63b0ef.tar.gz
u-boot-imx-2f78eae5064728d6cd907148cfeaf8ba3e63b0ef.tar.bz2
ARMv8/FSL_LSCH3: Add FSL_LSCH3 SoC
Freescale LayerScape with Chassis Generation 3 is a set of SoCs with ARMv8 cores and 3rd generation of Chassis. We use different MMU setup to support memory map and cache attribute for these SoCs. MMU and cache are enabled very early to bootst performance, especially for early development on emulators. After u-boot relocates to DDR, a new MMU table with QBMan cache access is created in DDR. SMMU pagesize is set in SMMU_sACR register. Both DDR3 and DDR4 are supported. Signed-off-by: York Sun <yorksun@freescale.com> Signed-off-by: Varun Sethi <Varun.Sethi@freescale.com> Signed-off-by: Arnab Basu <arnab.basu@freescale.com>
Diffstat (limited to 'arch/arm/cpu/armv8/fsl-lsch3/speed.c')
-rw-r--r--arch/arm/cpu/armv8/fsl-lsch3/speed.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/arch/arm/cpu/armv8/fsl-lsch3/speed.c b/arch/arm/cpu/armv8/fsl-lsch3/speed.c
new file mode 100644
index 0000000..dc4a34b
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-lsch3/speed.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2014, Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * Derived from arch/power/cpu/mpc85xx/speed.c
+ */
+
+#include <common.h>
+#include <linux/compiler.h>
+#include <fsl_ifc.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/arch-fsl-lsch3/immap_lsch3.h>
+#include <asm/arch/clock.h>
+#include "cpu.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_SYS_FSL_NUM_CC_PLLS
+#define CONFIG_SYS_FSL_NUM_CC_PLLS 6
+#endif
+
+
+void get_sys_info(struct sys_info *sys_info)
+{
+ struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+#ifdef CONFIG_FSL_IFC
+ struct fsl_ifc *ifc_regs = (void *)CONFIG_SYS_IFC_ADDR;
+ u32 ccr;
+#endif
+ struct ccsr_clk_cluster_group __iomem *clk_grp[2] = {
+ (void *)(CONFIG_SYS_FSL_CH3_CLK_GRPA_ADDR),
+ (void *)(CONFIG_SYS_FSL_CH3_CLK_GRPB_ADDR)
+ };
+ struct ccsr_clk_ctrl __iomem *clk_ctrl =
+ (void *)(CONFIG_SYS_FSL_CH3_CLK_CTRL_ADDR);
+ unsigned int cpu;
+ const u8 core_cplx_pll[16] = {
+ [0] = 0, /* CC1 PPL / 1 */
+ [1] = 0, /* CC1 PPL / 2 */
+ [2] = 0, /* CC1 PPL / 4 */
+ [4] = 1, /* CC2 PPL / 1 */
+ [5] = 1, /* CC2 PPL / 2 */
+ [6] = 1, /* CC2 PPL / 4 */
+ [8] = 2, /* CC3 PPL / 1 */
+ [9] = 2, /* CC3 PPL / 2 */
+ [10] = 2, /* CC3 PPL / 4 */
+ [12] = 3, /* CC4 PPL / 1 */
+ [13] = 3, /* CC4 PPL / 2 */
+ [14] = 3, /* CC4 PPL / 4 */
+ };
+
+ const u8 core_cplx_pll_div[16] = {
+ [0] = 1, /* CC1 PPL / 1 */
+ [1] = 2, /* CC1 PPL / 2 */
+ [2] = 4, /* CC1 PPL / 4 */
+ [4] = 1, /* CC2 PPL / 1 */
+ [5] = 2, /* CC2 PPL / 2 */
+ [6] = 4, /* CC2 PPL / 4 */
+ [8] = 1, /* CC3 PPL / 1 */
+ [9] = 2, /* CC3 PPL / 2 */
+ [10] = 4, /* CC3 PPL / 4 */
+ [12] = 1, /* CC4 PPL / 1 */
+ [13] = 2, /* CC4 PPL / 2 */
+ [14] = 4, /* CC4 PPL / 4 */
+ };
+
+ uint i, cluster;
+ uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS];
+ uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS];
+ unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
+ int cc_group[12] = CONFIG_SYS_FSL_CLUSTER_CLOCKS;
+ u32 c_pll_sel, cplx_pll;
+ void *offset;
+
+ sys_info->freq_systembus = sysclk;
+#ifdef CONFIG_DDR_CLK_FREQ
+ sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ;
+#else
+ sys_info->freq_ddrbus = sysclk;
+#endif
+
+ sys_info->freq_systembus *= (in_le32(&gur->rcwsr[0]) >>
+ FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_SHIFT) &
+ FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_MASK;
+ sys_info->freq_ddrbus *= (in_le32(&gur->rcwsr[0]) >>
+ FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_SHIFT) &
+ FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_MASK;
+
+ for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) {
+ /*
+ * fixme: prefer to combine the following into one line, but
+ * cannot pass compiling without warning about in_le32.
+ */
+ offset = (void *)((size_t)clk_grp[i/3] +
+ offsetof(struct ccsr_clk_cluster_group,
+ pllngsr[i%3].gsr));
+ ratio[i] = (in_le32(offset) >> 1) & 0x3f;
+ if (ratio[i] > 4)
+ freq_c_pll[i] = sysclk * ratio[i];
+ else
+ freq_c_pll[i] = sys_info->freq_systembus * ratio[i];
+ }
+
+ for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) {
+ cluster = fsl_qoriq_core_to_cluster(cpu);
+ c_pll_sel = (in_le32(&clk_ctrl->clkcncsr[cluster].csr) >> 27)
+ & 0xf;
+ cplx_pll = core_cplx_pll[c_pll_sel];
+ cplx_pll += cc_group[cluster] - 1;
+ sys_info->freq_processor[cpu] =
+ freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
+ }
+
+#if defined(CONFIG_FSL_IFC)
+ ccr = in_le32(&ifc_regs->ifc_ccr);
+ ccr = ((ccr & IFC_CCR_CLK_DIV_MASK) >> IFC_CCR_CLK_DIV_SHIFT) + 1;
+
+ sys_info->freq_localbus = sys_info->freq_systembus / ccr;
+#endif
+}
+
+
+int get_clocks(void)
+{
+ struct sys_info sys_info;
+ get_sys_info(&sys_info);
+ gd->cpu_clk = sys_info.freq_processor[0];
+ gd->bus_clk = sys_info.freq_systembus;
+ gd->mem_clk = sys_info.freq_ddrbus;
+
+#if defined(CONFIG_FSL_ESDHC)
+ gd->arch.sdhc_clk = gd->bus_clk / 2;
+#endif /* defined(CONFIG_FSL_ESDHC) */
+
+ if (gd->cpu_clk != 0)
+ return 0;
+ else
+ return 1;
+}
+
+/********************************************
+ * get_bus_freq
+ * return system bus freq in Hz
+ *********************************************/
+ulong get_bus_freq(ulong dummy)
+{
+ if (!gd->bus_clk)
+ get_clocks();
+
+ return gd->bus_clk;
+}
+
+/********************************************
+ * get_ddr_freq
+ * return ddr bus freq in Hz
+ *********************************************/
+ulong get_ddr_freq(ulong dummy)
+{
+ if (!gd->mem_clk)
+ get_clocks();
+
+ return gd->mem_clk;
+}
+
+unsigned int mxc_get_clock(enum mxc_clock clk)
+{
+ switch (clk) {
+ case MXC_I2C_CLK:
+ return get_bus_freq(0) / 2;
+ default:
+ printf("Unsupported clock\n");
+ }
+ return 0;
+}