[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