From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ivan Khoronzhuk Date: Thu, 3 Apr 2014 15:32:20 +0300 Subject: [U-Boot] [PATCH v5 7/9] k2hk: add support for k2hk SOC and EVM In-Reply-To: <1396377869-15724-8-git-send-email-m-karicheri2@ti.com> References: <1396377869-15724-1-git-send-email-m-karicheri2@ti.com> <1396377869-15724-8-git-send-email-m-karicheri2@ti.com> Message-ID: <533D54D4.7050706@ti.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de On 04/01/2014 09:44 PM, Murali Karicheri wrote: > From: Vitaly Andrianov > > k2hk EVM is based on Texas Instruments Keystone2 Hawking/Kepler > SoC. Keystone2 SoC has ARM v7 Cortex-A15 MPCore processor. Please > refer the ti/k2hk_evm/README for details on the board, build and other > information. > > This patch add support for keystone architecture and k2hk evm. > > Signed-off-by: Vitaly Andrianov > Signed-off-by: Murali Karicheri > Signed-off-by: WingMan Kwok > Signed-off-by: Sandeep Nair > --- > Makefile | 10 + > arch/arm/cpu/armv7/keystone/Makefile | 17 ++ > arch/arm/cpu/armv7/keystone/aemif.c | 71 +++++ > arch/arm/cpu/armv7/keystone/clock.c | 318 ++++++++++++++++++++ > arch/arm/cpu/armv7/keystone/cmd_clock.c | 124 ++++++++ > arch/arm/cpu/armv7/keystone/cmd_mon.c | 131 ++++++++ > arch/arm/cpu/armv7/keystone/ddr3.c | 69 +++++ > arch/arm/cpu/armv7/keystone/init.c | 56 ++++ > arch/arm/cpu/armv7/keystone/msmc.c | 68 +++++ > arch/arm/cpu/armv7/keystone/psc.c | 238 +++++++++++++++ > arch/arm/cpu/armv7/keystone/spl.c | 45 +++ > arch/arm/include/asm/arch-keystone/clock-k2hk.h | 109 +++++++ > arch/arm/include/asm/arch-keystone/clock.h | 17 ++ > arch/arm/include/asm/arch-keystone/clock_defs.h | 111 +++++++ > arch/arm/include/asm/arch-keystone/emif_defs.h | 73 +++++ > arch/arm/include/asm/arch-keystone/hardware-k2hk.h | 150 +++++++++ > arch/arm/include/asm/arch-keystone/hardware.h | 175 +++++++++++ > arch/arm/include/asm/arch-keystone/i2c_defs.h | 17 ++ > arch/arm/include/asm/arch-keystone/nand_defs.h | 23 ++ > arch/arm/include/asm/arch-keystone/psc_defs.h | 90 ++++++ > arch/arm/include/asm/arch-keystone/spl.h | 12 + > board/ti/k2hk_evm/Makefile | 9 + > board/ti/k2hk_evm/README | 122 ++++++++ > board/ti/k2hk_evm/board.c | 236 +++++++++++++++ > board/ti/k2hk_evm/ddr3.c | 269 +++++++++++++++++ > boards.cfg | 1 + > drivers/serial/ns16550.c | 8 + > include/configs/k2hk_evm.h | 212 +++++++++++++ > 28 files changed, 2781 insertions(+) > create mode 100644 arch/arm/cpu/armv7/keystone/Makefile > create mode 100644 arch/arm/cpu/armv7/keystone/aemif.c > create mode 100644 arch/arm/cpu/armv7/keystone/clock.c > create mode 100644 arch/arm/cpu/armv7/keystone/cmd_clock.c > create mode 100644 arch/arm/cpu/armv7/keystone/cmd_mon.c > create mode 100644 arch/arm/cpu/armv7/keystone/ddr3.c > create mode 100644 arch/arm/cpu/armv7/keystone/init.c > create mode 100644 arch/arm/cpu/armv7/keystone/msmc.c > create mode 100644 arch/arm/cpu/armv7/keystone/psc.c > create mode 100644 arch/arm/cpu/armv7/keystone/spl.c > create mode 100644 arch/arm/include/asm/arch-keystone/clock-k2hk.h > create mode 100644 arch/arm/include/asm/arch-keystone/clock.h > create mode 100644 arch/arm/include/asm/arch-keystone/clock_defs.h > create mode 100644 arch/arm/include/asm/arch-keystone/emif_defs.h > create mode 100644 arch/arm/include/asm/arch-keystone/hardware-k2hk.h > create mode 100644 arch/arm/include/asm/arch-keystone/hardware.h > create mode 100644 arch/arm/include/asm/arch-keystone/i2c_defs.h > create mode 100644 arch/arm/include/asm/arch-keystone/nand_defs.h > create mode 100644 arch/arm/include/asm/arch-keystone/psc_defs.h > create mode 100644 arch/arm/include/asm/arch-keystone/spl.h > create mode 100644 board/ti/k2hk_evm/Makefile > create mode 100644 board/ti/k2hk_evm/README > create mode 100644 board/ti/k2hk_evm/board.c > create mode 100644 board/ti/k2hk_evm/ddr3.c > create mode 100644 include/configs/k2hk_evm.h > > diff --git a/Makefile b/Makefile > index 25cbc95..27b85ed 100644 > --- a/Makefile > +++ b/Makefile > @@ -868,6 +868,16 @@ OBJCOPYFLAGS_u-boot.spr = -I binary -O binary --pad-to=$(CONFIG_SPL_PAD_TO) \ > u-boot.spr: spl/u-boot-spl.img u-boot.img FORCE > $(call if_changed,pad_cat) > > +MKIMAGEFLAGS_u-boot-spl.gph = -A $(ARCH) -T gpimage -C none \ > + -a $(CONFIG_SPL_TEXT_BASE) -e $(CONFIG_SPL_TEXT_BASE) -n SPL > +spl/u-boot-spl.gph: spl/u-boot-spl.bin FORCE > + $(call if_changed,mkimage) > + > +OBJCOPYFLAGS_u-boot-spi.gph = -I binary -O binary --pad-to=$(CONFIG_SPL_PAD_TO) \ > + --gap-fill=0 > +u-boot-spi.gph: spl/u-boot-spl.gph u-boot.img FORCE > + $(call if_changed,pad_cat) > + > ifneq ($(CONFIG_TEGRA),) > OBJCOPYFLAGS_u-boot-nodtb-tegra.bin = -O binary --pad-to=$(CONFIG_SYS_TEXT_BASE) > u-boot-nodtb-tegra.bin: spl/u-boot-spl u-boot.bin FORCE > diff --git a/arch/arm/cpu/armv7/keystone/Makefile b/arch/arm/cpu/armv7/keystone/Makefile > new file mode 100644 > index 0000000..7924cfa > --- /dev/null > +++ b/arch/arm/cpu/armv7/keystone/Makefile > @@ -0,0 +1,17 @@ > +# > +# (C) Copyright 2012-2014 > +# Texas Instruments Incorporated, > +# > +# SPDX-License-Identifier: GPL-2.0+ > +# > + > +obj-y += aemif.o > +obj-y += init.o > +obj-y += psc.o > +obj-y += clock.o > +obj-y += cmd_clock.o > +obj-y += cmd_mon.o > +obj-y += msmc.o > +obj-$(CONFIG_SPL_BUILD) += spl.o > +obj-y += ddr3.o > + > diff --git a/arch/arm/cpu/armv7/keystone/aemif.c b/arch/arm/cpu/armv7/keystone/aemif.c > new file mode 100644 > index 0000000..9b26886 > --- /dev/null > +++ b/arch/arm/cpu/armv7/keystone/aemif.c > @@ -0,0 +1,71 @@ > +/* > + * Keystone2: Asynchronous EMIF Configuration > + * > + * (C) Copyright 2012-2014 > + * Texas Instruments Incorporated, > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include > +#include > +#include > +#include > + > +#define AEMIF_CFG_SELECT_STROBE(v) ((v) ? 1 << 31 : 0) > +#define AEMIF_CFG_EXTEND_WAIT(v) ((v) ? 1 << 30 : 0) > +#define AEMIF_CFG_WR_SETUP(v) (((v) & 0x0f) << 26) > +#define AEMIF_CFG_WR_STROBE(v) (((v) & 0x3f) << 20) > +#define AEMIF_CFG_WR_HOLD(v) (((v) & 0x07) << 17) > +#define AEMIF_CFG_RD_SETUP(v) (((v) & 0x0f) << 13) > +#define AEMIF_CFG_RD_STROBE(v) (((v) & 0x3f) << 7) > +#define AEMIF_CFG_RD_HOLD(v) (((v) & 0x07) << 4) > +#define AEMIF_CFG_TURN_AROUND(v) (((v) & 0x03) << 2) > +#define AEMIF_CFG_WIDTH(v) (((v) & 0x03) << 0) > + > +#define set_config_field(reg, field, val) \ > + do { \ > + if (val != -1) { \ > + reg &= ~AEMIF_CFG_##field(0xffffffff); \ > + reg |= AEMIF_CFG_##field(val); \ > + } \ > + } while (0) > + > +void configure_async_emif(int cs, struct async_emif_config *cfg) > +{ > + unsigned long tmp; > + > + if (cfg->mode == ASYNC_EMIF_MODE_NAND) { > + tmp = __raw_readl(&davinci_emif_regs->nandfcr); > + tmp |= (1 << cs); > + __raw_writel(tmp, &davinci_emif_regs->nandfcr); > + > + } else if (cfg->mode == ASYNC_EMIF_MODE_ONENAND) { > + tmp = __raw_readl(&davinci_emif_regs->one_nand_cr); > + tmp |= (1 << cs); > + __raw_writel(tmp, &davinci_emif_regs->one_nand_cr); > + } > + > + tmp = __raw_readl(&davinci_emif_regs->abncr[cs]); > + > + set_config_field(tmp, SELECT_STROBE, cfg->select_strobe); > + set_config_field(tmp, EXTEND_WAIT, cfg->extend_wait); > + set_config_field(tmp, WR_SETUP, cfg->wr_setup); > + set_config_field(tmp, WR_STROBE, cfg->wr_strobe); > + set_config_field(tmp, WR_HOLD, cfg->wr_hold); > + set_config_field(tmp, RD_SETUP, cfg->rd_setup); > + set_config_field(tmp, RD_STROBE, cfg->rd_strobe); > + set_config_field(tmp, RD_HOLD, cfg->rd_hold); > + set_config_field(tmp, TURN_AROUND, cfg->turn_around); > + set_config_field(tmp, WIDTH, cfg->width); > + > + __raw_writel(tmp, &davinci_emif_regs->abncr[cs]); > +} > + > +void init_async_emif(int num_cs, struct async_emif_config *config) > +{ > + int cs; > + > + for (cs = 0; cs < num_cs; cs++) > + configure_async_emif(cs, config + cs); > +} > diff --git a/arch/arm/cpu/armv7/keystone/clock.c b/arch/arm/cpu/armv7/keystone/clock.c > new file mode 100644 > index 0000000..bfa4c9d > --- /dev/null > +++ b/arch/arm/cpu/armv7/keystone/clock.c > @@ -0,0 +1,318 @@ > +/* > + * Keystone2: pll initialization > + * > + * (C) Copyright 2012-2014 > + * Texas Instruments Incorporated, > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +static void wait_for_completion(const struct pll_init_data *data) > +{ > + int i; > + for (i = 0; i < 100; i++) { > + sdelay(450); > + if ((pllctl_reg_read(data->pll, stat) & PLLSTAT_GO) == 0) > + break; > + } > +} > + > +struct pll_regs { > + u32 reg0, reg1; > +}; > + > +static const struct pll_regs pll_regs[] = { > + [CORE_PLL] = { K2HK_MAINPLLCTL0, K2HK_MAINPLLCTL1}, > + [PASS_PLL] = { K2HK_PASSPLLCTL0, K2HK_PASSPLLCTL1}, > + [TETRIS_PLL] = { K2HK_ARMPLLCTL0, K2HK_ARMPLLCTL1}, > + [DDR3A_PLL] = { K2HK_DDR3APLLCTL0, K2HK_DDR3APLLCTL1}, > + [DDR3B_PLL] = { K2HK_DDR3BPLLCTL0, K2HK_DDR3BPLLCTL1}, > +}; > + > +/* Fout = Fref * NF(mult) / NR(prediv) / OD */ > +static unsigned long pll_freq_get(int pll) > +{ > + unsigned long mult = 1, prediv = 1, output_div = 2; > + unsigned long ret; > + u32 tmp, reg; > + > + if (pll == CORE_PLL) { > + ret = external_clk[sys_clk]; > + if (pllctl_reg_read(pll, ctl) & PLLCTL_PLLEN) { > + /* PLL mode */ > + tmp = __raw_readl(K2HK_MAINPLLCTL0); > + prediv = (tmp & PLL_DIV_MASK) + 1; > + mult = (((tmp & PLLM_MULT_HI_SMASK) >> 6) | > + (pllctl_reg_read(pll, mult) & > + PLLM_MULT_LO_MASK)) + 1; > + output_div = ((pllctl_reg_read(pll, secctl) >> > + PLL_CLKOD_SHIFT) & PLL_CLKOD_MASK) + 1; > + > + ret = ret / prediv / output_div * mult; > + } > + } else { > + switch (pll) { > + case PASS_PLL: > + ret = external_clk[pa_clk]; > + reg = K2HK_PASSPLLCTL0; > + break; > + case TETRIS_PLL: > + ret = external_clk[tetris_clk]; > + reg = K2HK_ARMPLLCTL0; > + break; > + case DDR3A_PLL: > + ret = external_clk[ddr3a_clk]; > + reg = K2HK_DDR3APLLCTL0; > + break; > + case DDR3B_PLL: > + ret = external_clk[ddr3b_clk]; > + reg = K2HK_DDR3BPLLCTL0; > + break; > + default: > + return 0; > + } > + > + tmp = __raw_readl(reg); > + > + if (!(tmp & PLLCTL_BYPASS)) { > + /* Bypass disabled */ > + prediv = (tmp & PLL_DIV_MASK) + 1; > + mult = ((tmp >> PLL_MULT_SHIFT) & PLL_MULT_MASK) + 1; > + output_div = ((tmp >> PLL_CLKOD_SHIFT) & > + PLL_CLKOD_MASK) + 1; > + ret = ((ret / prediv) * mult) / output_div; > + } > + } > + > + return ret; > +} > + > +unsigned long clk_get_rate(unsigned int clk) > +{ > + switch (clk) { > + case core_pll_clk: return pll_freq_get(CORE_PLL); > + case pass_pll_clk: return pll_freq_get(PASS_PLL); > + case tetris_pll_clk: return pll_freq_get(TETRIS_PLL); > + case ddr3a_pll_clk: return pll_freq_get(DDR3A_PLL); > + case ddr3b_pll_clk: return pll_freq_get(DDR3B_PLL); > + case sys_clk0_1_clk: > + case sys_clk0_clk: return pll_freq_get(CORE_PLL) / pll0div_read(1); > + case sys_clk1_clk: return pll_freq_get(CORE_PLL) / pll0div_read(2); > + case sys_clk2_clk: return pll_freq_get(CORE_PLL) / pll0div_read(3); > + case sys_clk3_clk: return pll_freq_get(CORE_PLL) / pll0div_read(4); > + case sys_clk0_2_clk: return clk_get_rate(sys_clk0_clk) / 2; > + case sys_clk0_3_clk: return clk_get_rate(sys_clk0_clk) / 3; > + case sys_clk0_4_clk: return clk_get_rate(sys_clk0_clk) / 4; > + case sys_clk0_6_clk: return clk_get_rate(sys_clk0_clk) / 6; > + case sys_clk0_8_clk: return clk_get_rate(sys_clk0_clk) / 8; > + case sys_clk0_12_clk: return clk_get_rate(sys_clk0_clk) / 12; > + case sys_clk0_24_clk: return clk_get_rate(sys_clk0_clk) / 24; > + case sys_clk1_3_clk: return clk_get_rate(sys_clk1_clk) / 3; > + case sys_clk1_4_clk: return clk_get_rate(sys_clk1_clk) / 4; > + case sys_clk1_6_clk: return clk_get_rate(sys_clk1_clk) / 6; > + case sys_clk1_12_clk: return clk_get_rate(sys_clk1_clk) / 12; > + default: > + break; > + } > + return 0; > +} > + > +void init_pll(const struct pll_init_data *data) > +{ > + u32 tmp, tmp_ctl, pllm, plld, pllod, bwadj; > + > + pllm = data->pll_m - 1; > + plld = (data->pll_d - 1) & PLL_DIV_MASK; > + pllod = (data->pll_od - 1) & PLL_CLKOD_MASK; > + > + if (data->pll == MAIN_PLL) { > + /* The requered delay before main PLL configuration */ > + sdelay(210000); > + > + tmp = pllctl_reg_read(data->pll, secctl); > + > + if (tmp & (PLLCTL_BYPASS)) { > + setbits_le32(pll_regs[data->pll].reg1, > + BIT(MAIN_ENSAT_OFFSET)); > + > + pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLEN | > + PLLCTL_PLLENSRC); > + sdelay(340); > + > + pllctl_reg_setbits(data->pll, secctl, PLLCTL_BYPASS); > + pllctl_reg_setbits(data->pll, ctl, PLLCTL_PLLPWRDN); > + sdelay(21000); > + > + pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLPWRDN); > + } else { > + pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLEN | > + PLLCTL_PLLENSRC); > + sdelay(340); > + } > + > + pllctl_reg_write(data->pll, mult, pllm & PLLM_MULT_LO_MASK); > + > + clrsetbits_le32(pll_regs[data->pll].reg0, PLLM_MULT_HI_SMASK, > + (pllm << 6)); > + > + /* Set the BWADJ (12 bit field) */ > + tmp_ctl = pllm >> 1; /* Divide the pllm by 2 */ Don't see any reason in comment: /* Divide the pllm by 2 */ If need to mark out it, may pllm/2 be better. > + clrsetbits_le32(pll_regs[data->pll].reg0, PLL_BWADJ_LO_SMASK, > + (tmp_ctl << PLL_BWADJ_LO_SHIFT)); > + clrsetbits_le32(pll_regs[data->pll].reg1, PLL_BWADJ_HI_MASK, > + (tmp_ctl >> 8)); > + > + /* > + * Set the pll divider (6 bit field) * > + * PLLD[5:0] is located in MAINPLLCTL0 > + */ > + clrsetbits_le32(pll_regs[data->pll].reg0, PLL_DIV_MASK, plld); > + > + /* Set the OUTPUT DIVIDE (4 bit field) in SECCTL */ > + pllctl_reg_rmw(data->pll, secctl, PLL_CLKOD_SMASK, > + (pllod << PLL_CLKOD_SHIFT)); > + wait_for_completion(data); > + > + pllctl_reg_write(data->pll, div1, PLLM_RATIO_DIV1); > + pllctl_reg_write(data->pll, div2, PLLM_RATIO_DIV2); > + pllctl_reg_write(data->pll, div3, PLLM_RATIO_DIV3); > + pllctl_reg_write(data->pll, div4, PLLM_RATIO_DIV4); > + pllctl_reg_write(data->pll, div5, PLLM_RATIO_DIV5); > + > + pllctl_reg_setbits(data->pll, alnctl, 0x1f); > + > + /* > + * Set GOSET bit in PLLCMD to initiate the GO operation > + * to change the divide > + */ > + pllctl_reg_setbits(data->pll, cmd, PLLSTAT_GO); > + sdelay(1500); /* wait for the phase adj */ > + wait_for_completion(data); > + > + /* Reset PLL */ > + pllctl_reg_setbits(data->pll, ctl, PLLCTL_PLLRST); > + sdelay(21000); /* Wait for a minimum of 7 us*/ > + pllctl_reg_clrbits(data->pll, ctl, PLLCTL_PLLRST); > + sdelay(105000); /* Wait for PLL Lock time (min 50 us) */ > + > + pllctl_reg_clrbits(data->pll, secctl, PLLCTL_BYPASS); > + > + tmp = pllctl_reg_setbits(data->pll, ctl, PLLCTL_PLLEN); > + > + } else if (data->pll == TETRIS_PLL) { > + bwadj = pllm >> 1; > + /* 1.5 Set PLLCTL0[BYPASS] =1 (enable bypass), */ > + setbits_le32(pll_regs[data->pll].reg0, PLLCTL_BYPASS); > + /* > + * Set CHIPMISCCTL1[13] = 0 (enable glitchfree bypass) > + * only applicable for Kepler > + */ > + clrbits_le32(K2HK_MISC_CTRL, ARM_PLL_EN); > + /* 2 In PLLCTL1, write PLLRST = 1 (PLL is reset) */ > + setbits_le32(pll_regs[data->pll].reg1 , > + PLL_PLLRST | PLLCTL_ENSAT); > + > + /* > + * 3 Program PLLM and PLLD in PLLCTL0 register > + * 4 Program BWADJ[7:0] in PLLCTL0 and BWADJ[11:8] in > + * PLLCTL1 register. BWADJ value must be set > + * to ((PLLM + 1) >> 1) ? 1) > + */ > + tmp = ((bwadj & PLL_BWADJ_LO_MASK) << PLL_BWADJ_LO_SHIFT) | > + (pllm << 6) | > + (plld & PLL_DIV_MASK) | > + (pllod << PLL_CLKOD_SHIFT) | PLLCTL_BYPASS; > + __raw_writel(tmp, pll_regs[data->pll].reg0); > + > + /* Set BWADJ[11:8] bits */ > + tmp = __raw_readl(pll_regs[data->pll].reg1); > + tmp &= ~(PLL_BWADJ_HI_MASK); > + tmp |= ((bwadj>>8) & PLL_BWADJ_HI_MASK); > + __raw_writel(tmp, pll_regs[data->pll].reg1); > + /* > + * 5 Wait for at least 5 us based on the reference > + * clock (PLL reset time) > + */ > + sdelay(21000); /* Wait for a minimum of 7 us*/ > + > + /* 6 In PLLCTL1, write PLLRST = 0 (PLL reset is released) */ > + clrbits_le32(pll_regs[data->pll].reg1, PLL_PLLRST); > + /* > + * 7 Wait for at least 500 * REFCLK cycles * (PLLD + 1) > + * (PLL lock time) > + */ > + sdelay(105000); > + /* 8 disable bypass */ > + clrbits_le32(pll_regs[data->pll].reg0, PLLCTL_BYPASS); > + /* > + * 9 Set CHIPMISCCTL1[13] = 1 (disable glitchfree bypass) > + * only applicable for Kepler > + */ > + setbits_le32(K2HK_MISC_CTRL, ARM_PLL_EN); > + } else { > + setbits_le32(pll_regs[data->pll].reg1, PLLCTL_ENSAT); > + /* > + * process keeps state of Bypass bit while programming > + * all other DDR PLL settings > + */ > + tmp = __raw_readl(pll_regs[data->pll].reg0); > + tmp &= PLLCTL_BYPASS; /* clear everything except Bypass */ > + > + /* > + * Set the BWADJ[7:0], PLLD[5:0] and PLLM to PLLCTL0, > + * bypass disabled > + */ > + bwadj = pllm >> 1; > + tmp |= ((bwadj & PLL_BWADJ_LO_SHIFT) << PLL_BWADJ_LO_SHIFT) | > + (pllm << PLL_MULT_SHIFT) | > + (plld & PLL_DIV_MASK) | > + (pllod << PLL_CLKOD_SHIFT); > + __raw_writel(tmp, pll_regs[data->pll].reg0); > + > + /* Set BWADJ[11:8] bits */ > + tmp = __raw_readl(pll_regs[data->pll].reg1); > + tmp &= ~(PLL_BWADJ_HI_MASK); > + tmp |= ((bwadj >> 8) & PLL_BWADJ_HI_MASK); > + > + /* set PLL Select (bit 13) for PASS PLL */ > + if (data->pll == PASS_PLL) > + tmp |= PLLCTL_PAPLL; > + > + __raw_writel(tmp, pll_regs[data->pll].reg1); > + > + /* Reset bit: bit 14 for both DDR3 & PASS PLL */ > + tmp = PLL_PLLRST; > + /* Set RESET bit = 1 */ > + setbits_le32(pll_regs[data->pll].reg1, tmp); > + /* Wait for a minimum of 7 us*/ > + sdelay(21000); > + /* Clear RESET bit */ > + clrbits_le32(pll_regs[data->pll].reg1, tmp); > + sdelay(105000); > + > + /* clear BYPASS (Enable PLL Mode) */ > + clrbits_le32(pll_regs[data->pll].reg0, PLLCTL_BYPASS); > + sdelay(21000); /* Wait for a minimum of 7 us*/ > + } > + > + /* > + * This is required to provide a delay between multiple > + * consequent PPL configurations > + */ > + sdelay(210000); > +} > + > +void init_plls(int num_pll, struct pll_init_data *config) > +{ > + int i; > + > + for (i = 0; i < num_pll; i++) > + init_pll(&config[i]); > +} > diff --git a/arch/arm/cpu/armv7/keystone/cmd_clock.c b/arch/arm/cpu/armv7/keystone/cmd_clock.c > new file mode 100644 > index 0000000..afd30f3 > --- /dev/null > +++ b/arch/arm/cpu/armv7/keystone/cmd_clock.c > @@ -0,0 +1,124 @@ > +/* > + * keystone2: commands for clocks > + * > + * (C) Copyright 2012-2014 > + * Texas Instruments Incorporated, > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include > +#include > +#include > +#include > +#include > + > +struct pll_init_data cmd_pll_data = { > + .pll = MAIN_PLL, > + .pll_m = 16, > + .pll_d = 1, > + .pll_od = 2, > +}; > + > +int do_pll_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) > +{ > + if (argc != 5) > + goto pll_cmd_usage; > + > + if (strncmp(argv[1], "pa", 2) == 0) > + cmd_pll_data.pll = PASS_PLL; > + else if (strncmp(argv[1], "arm", 3) == 0) > + cmd_pll_data.pll = TETRIS_PLL; > + else if (strncmp(argv[1], "ddr3a", 5) == 0) > + cmd_pll_data.pll = DDR3A_PLL; > + else if (strncmp(argv[1], "ddr3b", 5) == 0) > + cmd_pll_data.pll = DDR3B_PLL; > + else > + goto pll_cmd_usage; > + > + cmd_pll_data.pll_m = simple_strtoul(argv[2], NULL, 10); > + cmd_pll_data.pll_d = simple_strtoul(argv[3], NULL, 10); > + cmd_pll_data.pll_od = simple_strtoul(argv[4], NULL, 10); > + > + printf("Trying to set pll %d; mult %d; div %d; OD %d\n", > + cmd_pll_data.pll, cmd_pll_data.pll_m, > + cmd_pll_data.pll_d, cmd_pll_data.pll_od); > + init_pll(&cmd_pll_data); > + > + return 0; > + > +pll_cmd_usage: > + return cmd_usage(cmdtp); > +} > + > +U_BOOT_CMD( > + pllset, 5, 0, do_pll_cmd, > + "set pll multiplier and pre divider", > + "
\n" > +); > + > +int do_getclk_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) > +{ > + unsigned int clk; > + unsigned int freq; > + > + if (argc != 2) > + goto getclk_cmd_usage; > + > + clk = simple_strtoul(argv[1], NULL, 10); > + > + freq = clk_get_rate(clk); > + printf("clock index [%d] - frequency %u\n", clk, freq); > + return 0; > + > +getclk_cmd_usage: > + return cmd_usage(cmdtp); > +} > + > +U_BOOT_CMD( > + getclk, 2, 0, do_getclk_cmd, > + "get clock rate", > + "\n" > + "See the 'enum clk_e' in the k2hk clock.h for clk indexes\n" > +); > + > +int do_psc_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) > +{ > + int psc_module; > + int res; > + > + if (argc != 3) > + goto psc_cmd_usage; > + > + psc_module = simple_strtoul(argv[1], NULL, 10); > + if (strcmp(argv[2], "en") == 0) { > + res = psc_enable_module(psc_module); > + printf("psc_enable_module(%d) - %s\n", psc_module, > + (res) ? "ERROR" : "OK"); > + return 0; > + } > + > + if (strcmp(argv[2], "di") == 0) { > + res = psc_disable_module(psc_module); > + printf("psc_disable_module(%d) - %s\n", psc_module, > + (res) ? "ERROR" : "OK"); > + return 0; > + } > + > + if (strcmp(argv[2], "domain") == 0) { > + res = psc_disable_domain(psc_module); > + printf("psc_disable_domain(%d) - %s\n", psc_module, > + (res) ? "ERROR" : "OK"); > + return 0; > + } > + > +psc_cmd_usage: > + return cmd_usage(cmdtp); > +} > + > +U_BOOT_CMD( > + psc, 3, 0, do_psc_cmd, > + "", > + " \n" > + "See the hardware.h for Power and Sleep Controller (PSC) Domains\n" > +); > diff --git a/arch/arm/cpu/armv7/keystone/cmd_mon.c b/arch/arm/cpu/armv7/keystone/cmd_mon.c > new file mode 100644 > index 0000000..f9f58a3 > --- /dev/null > +++ b/arch/arm/cpu/armv7/keystone/cmd_mon.c > @@ -0,0 +1,131 @@ > +/* > + * K2HK: secure kernel command file > + * > + * (C) Copyright 2012-2014 > + * Texas Instruments Incorporated, > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include > +#include > +asm(".arch_extension sec\n\t"); > + > +static int mon_install(u32 addr, u32 dpsc, u32 freq) > +{ > + int result; > + > + __asm__ __volatile__ ( > + "stmfd r13!, {lr}\n" > + "mov r0, %1\n" > + "mov r1, %2\n" > + "mov r2, %3\n" > + "blx r0\n" > + "ldmfd r13!, {lr}\n" > + : "=&r" (result) > + : "r" (addr), "r" (dpsc), "r" (freq) > + : "cc", "r0", "r1", "r2", "memory"); > + return result; > +} > + > +static int do_mon_install(cmd_tbl_t *cmdtp, int flag, int argc, > + char * const argv[]) > +{ > + u32 addr, dpsc_base = 0x1E80000, freq; > + int rcode = 0; > + > + if (argc < 2) > + return CMD_RET_USAGE; > + > + freq = clk_get_rate(sys_clk0_6_clk); > + > + addr = simple_strtoul(argv[1], NULL, 16); > + > + rcode = mon_install(addr, dpsc_base, freq); > + printf("## installed monitor, freq [%d], status %d\n", > + freq, rcode); > + > + return 0; > +} > + > +U_BOOT_CMD(mon_install, 2, 0, do_mon_install, > + "Install boot kernel at 'addr'", > + "" > +); > + > +static void core_spin(void) > +{ > + while (1) > + ; /* forever */; /* forever */ - this comment is redundant And why do you carry ';' ? Why just use while(1); instead > +} > + > +int mon_power_on(int core_id, void *ep) > +{ > + int result; > + > + asm volatile ( > + "stmfd r13!, {lr}\n" > + "mov r1, %1\n" > + "mov r2, %2\n" > + "mov r0, #0\n" > + "smc #0\n" > + "ldmfd r13!, {lr}\n" > + : "=&r" (result) > + : "r" (core_id), "r" (ep) > + : "cc", "r0", "r1", "r2", "memory"); > + return result; > +} > + > +int mon_power_off(int core_id) > +{ > + int result; > + > + asm volatile ( > + "stmfd r13!, {lr}\n" > + "mov r1, %1\n" > + "mov r0, #1\n" > + "smc #1\n" > + "ldmfd r13!, {lr}\n" > + : "=&r" (result) > + : "r" (core_id) > + : "cc", "r0", "r1", "memory"); > + return result; > +} > + > +int do_mon_power(cmd_tbl_t *cmdtp, int flag, int argc, > + char * const argv[]) > +{ > + int rcode = 0, core_id, on; > + void (*fn)(void); > + > + fn = core_spin; why do you need this pointer? > + > + if (argc < 3) > + return CMD_RET_USAGE; > + > + core_id = simple_strtoul(argv[1], NULL, 16); > + on = simple_strtoul(argv[2], NULL, 16); > + > + if (on) > + rcode = mon_power_on(core_id, fn); Maybe there is no need to use fn pointer: rcode = mon_power_on(core_id, core_spin); > + else > + rcode = mon_power_off(core_id); > + > + if (on) { > + if (!rcode) > + printf("core %d powered on successfully\n", core_id); > + else > + printf("core %d power on failure\n", core_id); > + } else { > + printf("core %d powered off successfully\n", core_id); > + } > + > + return 0; > +} > + > +U_BOOT_CMD(mon_power, 3, 0, do_mon_power, > + "Power On/Off secondary core", > + "mon_power \n" > + "- coreid (1-3) and oper (1 - ON, 0 - OFF)\n" > + "" > +); > diff --git a/arch/arm/cpu/armv7/keystone/ddr3.c b/arch/arm/cpu/armv7/keystone/ddr3.c > new file mode 100644 > index 0000000..4875db7 > --- /dev/null > +++ b/arch/arm/cpu/armv7/keystone/ddr3.c > @@ -0,0 +1,69 @@ > +/* > + * Keystone2: DDR3 initialization > + * > + * (C) Copyright 2012-2014 > + * Texas Instruments Incorporated, > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include > +#include > + > +void init_ddrphy(u32 base, struct ddr3_phy_config *phy_cfg) > +{ > + unsigned int tmp; > + > + while ((__raw_readl(base + KS2_DDRPHY_PGSR0_OFFSET) > + & 0x00000001) != 0x00000001) > + ; > + > + __raw_writel(phy_cfg->pllcr, base + KS2_DDRPHY_PLLCR_OFFSET); > + > + tmp = __raw_readl(base + KS2_DDRPHY_PGCR1_OFFSET); > + tmp &= ~(phy_cfg->pgcr1_mask); > + tmp |= phy_cfg->pgcr1_val; > + __raw_writel(tmp, base + KS2_DDRPHY_PGCR1_OFFSET); > + > + __raw_writel(phy_cfg->ptr0, base + KS2_DDRPHY_PTR0_OFFSET); > + __raw_writel(phy_cfg->ptr1, base + KS2_DDRPHY_PTR1_OFFSET); > + __raw_writel(phy_cfg->ptr3, base + KS2_DDRPHY_PTR3_OFFSET); > + __raw_writel(phy_cfg->ptr4, base + KS2_DDRPHY_PTR4_OFFSET); > + > + tmp = __raw_readl(base + KS2_DDRPHY_DCR_OFFSET); > + tmp &= ~(phy_cfg->dcr_mask); > + tmp |= phy_cfg->dcr_val; > + __raw_writel(tmp, base + KS2_DDRPHY_DCR_OFFSET); > + > + __raw_writel(phy_cfg->dtpr0, base + KS2_DDRPHY_DTPR0_OFFSET); > + __raw_writel(phy_cfg->dtpr1, base + KS2_DDRPHY_DTPR1_OFFSET); > + __raw_writel(phy_cfg->dtpr2, base + KS2_DDRPHY_DTPR2_OFFSET); > + __raw_writel(phy_cfg->mr0, base + KS2_DDRPHY_MR0_OFFSET); > + __raw_writel(phy_cfg->mr1, base + KS2_DDRPHY_MR1_OFFSET); > + __raw_writel(phy_cfg->mr2, base + KS2_DDRPHY_MR2_OFFSET); > + __raw_writel(phy_cfg->dtcr, base + KS2_DDRPHY_DTCR_OFFSET); > + __raw_writel(phy_cfg->pgcr2, base + KS2_DDRPHY_PGCR2_OFFSET); > + > + __raw_writel(phy_cfg->zq0cr1, base + KS2_DDRPHY_ZQ0CR1_OFFSET); > + __raw_writel(phy_cfg->zq1cr1, base + KS2_DDRPHY_ZQ1CR1_OFFSET); > + __raw_writel(phy_cfg->zq2cr1, base + KS2_DDRPHY_ZQ2CR1_OFFSET); > + > + __raw_writel(phy_cfg->pir_v1, base + KS2_DDRPHY_PIR_OFFSET); > + while ((__raw_readl(base + KS2_DDRPHY_PGSR0_OFFSET) & 0x1) != 0x1) > + ; > + > + __raw_writel(phy_cfg->pir_v2, base + KS2_DDRPHY_PIR_OFFSET); > + while ((__raw_readl(base + KS2_DDRPHY_PGSR0_OFFSET) & 0x1) != 0x1) > + ; > +} > + > +void init_ddremif(u32 base, struct ddr3_emif_config *emif_cfg) > +{ > + __raw_writel(emif_cfg->sdcfg, base + KS2_DDR3_SDCFG_OFFSET); > + __raw_writel(emif_cfg->sdtim1, base + KS2_DDR3_SDTIM1_OFFSET); > + __raw_writel(emif_cfg->sdtim2, base + KS2_DDR3_SDTIM2_OFFSET); > + __raw_writel(emif_cfg->sdtim3, base + KS2_DDR3_SDTIM3_OFFSET); > + __raw_writel(emif_cfg->sdtim4, base + KS2_DDR3_SDTIM4_OFFSET); > + __raw_writel(emif_cfg->zqcfg, base + KS2_DDR3_ZQCFG_OFFSET); > + __raw_writel(emif_cfg->sdrfc, base + KS2_DDR3_SDRFC_OFFSET); > +} > diff --git a/arch/arm/cpu/armv7/keystone/init.c b/arch/arm/cpu/armv7/keystone/init.c > new file mode 100644 > index 0000000..044015a > --- /dev/null > +++ b/arch/arm/cpu/armv7/keystone/init.c > @@ -0,0 +1,56 @@ > +/* > + * Keystone2: Architecture initialization > + * > + * (C) Copyright 2012-2014 > + * Texas Instruments Incorporated, > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include > +#include > +#include > +#include > + > +void chip_configuration_unlock(void) why not static inline? > +{ > + __raw_writel(KEYSTONE_KICK0_MAGIC, KEYSTONE_KICK0); > + __raw_writel(KEYSTONE_KICK1_MAGIC, KEYSTONE_KICK1); > +} > + > +int arch_cpu_init(void) > +{ > + chip_configuration_unlock(); > + icache_enable(); > + > +#ifdef CONFIG_SOC_K2HK > + share_all_segments(8); > + share_all_segments(9); > + share_all_segments(10); /* QM PDSP */ > + share_all_segments(11); /* PCIE */ > +#endif > + > + return 0; > +} > + > +void reset_cpu(ulong addr) > +{ > + volatile u32 *rstctrl = (volatile u32 *)(KS2_RSTCTRL); > + u32 tmp; > + > + tmp = *rstctrl & KS2_RSTCTRL_MASK; > + *rstctrl = tmp | KS2_RSTCTRL_KEY; > + > + *rstctrl &= KS2_RSTCTRL_SWRST; > + > + for (;;) > + ; > +} > + > +void enable_caches(void) > +{ > +#ifndef CONFIG_SYS_DCACHE_OFF > + /* Enable D-cache. I-cache is already enabled in start.S */ > + dcache_enable(); > +#endif > +} ... -- Regards, Ivan Khoronzhuk