summaryrefslogtreecommitdiff
path: root/arch/arm/cpu/armv7
diff options
context:
space:
mode:
authorTom Rini <trini@ti.com>2014-08-29 11:06:51 -0400
committerTom Rini <trini@ti.com>2014-08-29 11:06:51 -0400
commit5a1095a830299aef8dd32495e505e92ab1749e89 (patch)
tree9383de2534455119d51200bc87766a330591df27 /arch/arm/cpu/armv7
parent6af857c50df4e62ec08e51ad73c96f63f1480386 (diff)
parentd145878d59c80a44d8c6e6d606b898ab87d205ee (diff)
downloadu-boot-imx-5a1095a830299aef8dd32495e505e92ab1749e89.zip
u-boot-imx-5a1095a830299aef8dd32495e505e92ab1749e89.tar.gz
u-boot-imx-5a1095a830299aef8dd32495e505e92ab1749e89.tar.bz2
Merge branch 'master' of git://www.denx.de/git/u-boot-imx
Diffstat (limited to 'arch/arm/cpu/armv7')
-rw-r--r--arch/arm/cpu/armv7/mx6/Makefile1
-rw-r--r--arch/arm/cpu/armv7/mx6/clock.c51
-rw-r--r--arch/arm/cpu/armv7/mx6/ddr.c8
-rw-r--r--arch/arm/cpu/armv7/mx6/mp.c87
-rw-r--r--arch/arm/cpu/armv7/mx6/soc.c36
5 files changed, 180 insertions, 3 deletions
diff --git a/arch/arm/cpu/armv7/mx6/Makefile b/arch/arm/cpu/armv7/mx6/Makefile
index 6dc9f8e..bf6effc 100644
--- a/arch/arm/cpu/armv7/mx6/Makefile
+++ b/arch/arm/cpu/armv7/mx6/Makefile
@@ -10,3 +10,4 @@
obj-y := soc.o clock.o
obj-$(CONFIG_SPL_BUILD) += ddr.o
obj-$(CONFIG_SECURE_BOOT) += hab.o
+obj-$(CONFIG_MP) += mp.o
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c
index 7dd83ec..820b8d5 100644
--- a/arch/arm/cpu/armv7/mx6/clock.c
+++ b/arch/arm/cpu/armv7/mx6/clock.c
@@ -71,6 +71,24 @@ int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
}
#endif
+/* spi_num can be from 0 - SPI_MAX_NUM */
+int enable_spi_clk(unsigned char enable, unsigned spi_num)
+{
+ u32 reg;
+ u32 mask;
+
+ if (spi_num > SPI_MAX_NUM)
+ return -EINVAL;
+
+ mask = MXC_CCM_CCGR_CG_MASK << (spi_num << 1);
+ reg = __raw_readl(&imx_ccm->CCGR1);
+ if (enable)
+ reg |= mask;
+ else
+ reg &= ~mask;
+ __raw_writel(reg, &imx_ccm->CCGR1);
+ return 0;
+}
static u32 decode_pll(enum pll_clocks pll, u32 infreq)
{
u32 div;
@@ -214,7 +232,7 @@ static u32 get_uart_clk(void)
u32 reg, uart_podf;
u32 freq = decode_pll(PLL_USBOTG, MXC_HCLK) / 6; /* static divider */
reg = __raw_readl(&imx_ccm->cscdr1);
-#ifdef CONFIG_MX6SL
+#if (defined(CONFIG_MX6SL) || defined(CONFIG_MX6SX))
if (reg & MXC_CCM_CSCDR1_UART_CLK_SEL)
freq = MXC_HCLK;
#endif
@@ -282,7 +300,7 @@ static u32 get_emi_slow_clk(void)
return root_freq / (emi_slow_podf + 1);
}
-#ifdef CONFIG_MX6SL
+#if (defined(CONFIG_MX6SL) || defined(CONFIG_MX6SX))
static u32 get_mmdc_ch0_clk(void)
{
u32 cbcmr = __raw_readl(&imx_ccm->cbcmr);
@@ -355,6 +373,27 @@ int enable_fec_anatop_clock(enum enet_freq freq)
reg &= ~BM_ANADIG_PLL_ENET_BYPASS;
writel(reg, &anatop->pll_enet);
+#ifdef CONFIG_MX6SX
+ /*
+ * Set enet ahb clock to 200MHz
+ * pll2_pfd2_396m-> ENET_PODF-> ENET_AHB
+ */
+ reg = readl(&imx_ccm->chsccdr);
+ reg &= ~(MXC_CCM_CHSCCDR_ENET_PRE_CLK_SEL_MASK
+ | MXC_CCM_CHSCCDR_ENET_PODF_MASK
+ | MXC_CCM_CHSCCDR_ENET_CLK_SEL_MASK);
+ /* PLL2 PFD2 */
+ reg |= (4 << MXC_CCM_CHSCCDR_ENET_PRE_CLK_SEL_OFFSET);
+ /* Div = 2*/
+ reg |= (1 << MXC_CCM_CHSCCDR_ENET_PODF_OFFSET);
+ reg |= (0 << MXC_CCM_CHSCCDR_ENET_CLK_SEL_OFFSET);
+ writel(reg, &imx_ccm->chsccdr);
+
+ /* Enable enet system clock */
+ reg = readl(&imx_ccm->CCGR3);
+ reg |= MXC_CCM_CCGR3_ENET_MASK;
+ writel(reg, &imx_ccm->CCGR3);
+#endif
return 0;
}
#endif
@@ -437,6 +476,7 @@ static int enable_enet_pll(uint32_t en)
return 0;
}
+#ifndef CONFIG_MX6SX
static void ungate_sata_clock(void)
{
struct mxc_ccm_reg *const imx_ccm =
@@ -445,6 +485,7 @@ static void ungate_sata_clock(void)
/* Enable SATA clock. */
setbits_le32(&imx_ccm->CCGR5, MXC_CCM_CCGR5_SATA_MASK);
}
+#endif
static void ungate_pcie_clock(void)
{
@@ -455,11 +496,13 @@ static void ungate_pcie_clock(void)
setbits_le32(&imx_ccm->CCGR4, MXC_CCM_CCGR4_PCIE_MASK);
}
+#ifndef CONFIG_MX6SX
int enable_sata_clock(void)
{
ungate_sata_clock();
return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA);
}
+#endif
int enable_pcie_clock(void)
{
@@ -491,7 +534,9 @@ int enable_pcie_clock(void)
clrbits_le32(&ccm_regs->cbcmr, MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL);
/* Party time! Ungate the clock to the PCIe. */
+#ifndef CONFIG_MX6SX
ungate_sata_clock();
+#endif
ungate_pcie_clock();
return enable_enet_pll(BM_ANADIG_PLL_ENET_ENABLE_SATA |
@@ -573,6 +618,7 @@ int do_mx6_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
return 0;
}
+#ifndef CONFIG_MX6SX
void enable_ipu_clock(void)
{
struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
@@ -581,6 +627,7 @@ void enable_ipu_clock(void)
reg |= MXC_CCM_CCGR3_IPU1_IPU_MASK;
writel(reg, &mxc_ccm->CCGR3);
}
+#endif
/***************************************************/
U_BOOT_CMD(
diff --git a/arch/arm/cpu/armv7/mx6/ddr.c b/arch/arm/cpu/armv7/mx6/ddr.c
index 0434211..1ab69f6 100644
--- a/arch/arm/cpu/armv7/mx6/ddr.c
+++ b/arch/arm/cpu/armv7/mx6/ddr.c
@@ -197,6 +197,7 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *i,
u16 trcd, trc, tras, twr, tmrd, trtp, trp, twtr, trfc, txs, txpr;
u16 CS0_END;
u16 tdllk = 0x1ff; /* DLL locking time: 512 cycles (JEDEC DDR3) */
+ u8 coladdr;
int clkper; /* clock period in picoseconds */
int clock; /* clock freq in mHz */
int cs;
@@ -422,8 +423,13 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *i,
mmdc0->mdor = reg;
/* Step 5: Configure DDR physical parameters (density and burst len) */
+ coladdr = m->coladdr;
+ if (m->coladdr == 8) /* 8-bit COL is 0x3 */
+ coladdr += 4;
+ else if (m->coladdr == 12) /* 12-bit COL is 0x4 */
+ coladdr += 1;
reg = (m->rowaddr - 11) << 24 | /* ROW */
- (m->coladdr - 9) << 20 | /* COL */
+ (coladdr - 9) << 20 | /* COL */
(1 << 19) | /* Burst Length = 8 for DDR3 */
(i->dsize << 16); /* DDR data bus size */
mmdc0->mdctl = reg;
diff --git a/arch/arm/cpu/armv7/mx6/mp.c b/arch/arm/cpu/armv7/mx6/mp.c
new file mode 100644
index 0000000..9f034d6
--- /dev/null
+++ b/arch/arm/cpu/armv7/mx6/mp.c
@@ -0,0 +1,87 @@
+/*
+ * (C) Copyright 2014
+ * Gabriel Huau <contact@huau-gabriel.fr>
+ *
+ * (C) Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/imx-regs.h>
+
+#define MAX_CPUS 4
+static struct src *src = (struct src *)SRC_BASE_ADDR;
+
+static uint32_t cpu_reset_mask[MAX_CPUS] = {
+ 0, /* We don't really want to modify the cpu0 */
+ SRC_SCR_CORE_1_RESET_MASK,
+ SRC_SCR_CORE_2_RESET_MASK,
+ SRC_SCR_CORE_3_RESET_MASK
+};
+
+static uint32_t cpu_ctrl_mask[MAX_CPUS] = {
+ 0, /* We don't really want to modify the cpu0 */
+ SRC_SCR_CORE_1_ENABLE_MASK,
+ SRC_SCR_CORE_2_ENABLE_MASK,
+ SRC_SCR_CORE_3_ENABLE_MASK
+};
+
+int cpu_reset(int nr)
+{
+ /* Software reset of the CPU N */
+ src->scr |= cpu_reset_mask[nr];
+ return 0;
+}
+
+int cpu_status(int nr)
+{
+ printf("core %d => %d\n", nr, !!(src->scr & cpu_ctrl_mask[nr]));
+ return 0;
+}
+
+int cpu_release(int nr, int argc, char *const argv[])
+{
+ uint32_t boot_addr;
+
+ boot_addr = simple_strtoul(argv[0], NULL, 16);
+
+ switch (nr) {
+ case 1:
+ src->gpr3 = boot_addr;
+ break;
+ case 2:
+ src->gpr5 = boot_addr;
+ break;
+ case 3:
+ src->gpr7 = boot_addr;
+ break;
+ default:
+ return 1;
+ }
+
+ /* CPU N is ready to start */
+ src->scr |= cpu_ctrl_mask[nr];
+
+ return 0;
+}
+
+int is_core_valid(unsigned int core)
+{
+ uint32_t nr_cores = get_nr_cpus();
+
+ if (core > nr_cores)
+ return 0;
+
+ return 1;
+}
+
+int cpu_disable(int nr)
+{
+ /* Disable the CPU N */
+ src->scr &= ~cpu_ctrl_mask[nr];
+ return 0;
+}
diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c
index f20bdeb..ac84a1f 100644
--- a/arch/arm/cpu/armv7/mx6/soc.c
+++ b/arch/arm/cpu/armv7/mx6/soc.c
@@ -35,6 +35,12 @@ struct scu_regs {
u32 fpga_rev;
};
+u32 get_nr_cpus(void)
+{
+ struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR;
+ return readl(&scu->config) & 3;
+}
+
u32 get_cpu_rev(void)
{
struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
@@ -79,9 +85,15 @@ u32 __weak get_board_rev(void)
void init_aips(void)
{
struct aipstz_regs *aips1, *aips2;
+#ifdef CONFIG_MX6SX
+ struct aipstz_regs *aips3;
+#endif
aips1 = (struct aipstz_regs *)AIPS1_BASE_ADDR;
aips2 = (struct aipstz_regs *)AIPS2_BASE_ADDR;
+#ifdef CONFIG_MX6SX
+ aips3 = (struct aipstz_regs *)AIPS3_BASE_ADDR;
+#endif
/*
* Set all MPROTx to be non-bufferable, trusted for R/W,
@@ -107,6 +119,26 @@ void init_aips(void)
writel(0x00000000, &aips2->opacr2);
writel(0x00000000, &aips2->opacr3);
writel(0x00000000, &aips2->opacr4);
+
+#ifdef CONFIG_MX6SX
+ /*
+ * Set all MPROTx to be non-bufferable, trusted for R/W,
+ * not forced to user-mode.
+ */
+ writel(0x77777777, &aips3->mprot0);
+ writel(0x77777777, &aips3->mprot1);
+
+ /*
+ * Set all OPACRx to be non-bufferable, not require
+ * supervisor privilege level for access,allow for
+ * write access and untrusted master access.
+ */
+ writel(0x00000000, &aips3->opacr0);
+ writel(0x00000000, &aips3->opacr1);
+ writel(0x00000000, &aips3->opacr2);
+ writel(0x00000000, &aips3->opacr3);
+ writel(0x00000000, &aips3->opacr4);
+#endif
}
static void clear_ldo_ramp(void)
@@ -311,6 +343,10 @@ void s_init(void)
u32 mask480;
u32 mask528;
+
+ if (is_cpu_type(MXC_CPU_MX6SX))
+ return;
+
/* Due to hardware limitation, on MX6Q we need to gate/ungate all PFDs
* to make sure PFD is working right, otherwise, PFDs may
* not output clock after reset, MX6DL and MX6SL have added 396M pfd