[U-Boot] [PATCH v5 7/9] k2hk: add support for k2hk SOC and EVM
Ivan Khoronzhuk
ivan.khoronzhuk at ti.com
Thu Apr 3 14:32:20 CEST 2014
On 04/01/2014 09:44 PM, Murali Karicheri wrote:
> From: Vitaly Andrianov<vitalya at ti.com>
>
> 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<vitalya at ti.com>
> Signed-off-by: Murali Karicheri<m-karicheri2 at ti.com>
> Signed-off-by: WingMan Kwok<w-kwok2 at ti.com>
> Signed-off-by: Sandeep Nair<sandeep_n at ti.com>
> ---
> 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, <www.ti.com>
> +#
> +# 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, <www.ti.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/emif_defs.h>
> +
> +#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, <www.ti.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <asm-generic/errno.h>
> +#include <asm/io.h>
> +#include <asm/processor.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/clock_defs.h>
> +
> +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, <www.ti.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +#include <asm/arch/hardware.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/psc_defs.h>
> +
> +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",
> + "<pa|arm|ddr3a|ddr3b> <mult> <div> <OD>\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",
> + "<clk index>\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,
> + "<enable/disable psc module os disable domain>",
> + "<mod/domain index> <en|di|domain>\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, <www.ti.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +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 <coreid> <oper>\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, <www.ti.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <asm/arch/hardware.h>
> +#include <asm/io.h>
> +
> +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, <www.ti.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/hardware.h>
> +
> +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
More information about the U-Boot
mailing list