diff options
Diffstat (limited to 'roms/u-boot/arch/arm/cpu/armv7/keystone')
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/armv7/keystone/Makefile | 17 | ||||
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/armv7/keystone/aemif.c | 71 | ||||
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/armv7/keystone/clock.c | 318 | ||||
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/armv7/keystone/cmd_clock.c | 124 | ||||
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/armv7/keystone/cmd_mon.c | 131 | ||||
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/armv7/keystone/ddr3.c | 69 | ||||
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/armv7/keystone/init.c | 56 | ||||
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/armv7/keystone/keystone_nav.c | 376 | ||||
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/armv7/keystone/msmc.c | 68 | ||||
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/armv7/keystone/psc.c | 237 | ||||
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/armv7/keystone/spl.c | 45 | 
11 files changed, 1512 insertions, 0 deletions
diff --git a/roms/u-boot/arch/arm/cpu/armv7/keystone/Makefile b/roms/u-boot/arch/arm/cpu/armv7/keystone/Makefile new file mode 100644 index 00000000..b1bd0224 --- /dev/null +++ b/roms/u-boot/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	+= keystone_nav.o +obj-y	+= msmc.o +obj-$(CONFIG_SPL_BUILD)	+= spl.o +obj-y	+= ddr3.o diff --git a/roms/u-boot/arch/arm/cpu/armv7/keystone/aemif.c b/roms/u-boot/arch/arm/cpu/armv7/keystone/aemif.c new file mode 100644 index 00000000..9b26886d --- /dev/null +++ b/roms/u-boot/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/roms/u-boot/arch/arm/cpu/armv7/keystone/clock.c b/roms/u-boot/arch/arm/cpu/armv7/keystone/clock.c new file mode 100644 index 00000000..bfa4c9d8 --- /dev/null +++ b/roms/u-boot/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 */ +		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/roms/u-boot/arch/arm/cpu/armv7/keystone/cmd_clock.c b/roms/u-boot/arch/arm/cpu/armv7/keystone/cmd_clock.c new file mode 100644 index 00000000..afd30f38 --- /dev/null +++ b/roms/u-boot/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/roms/u-boot/arch/arm/cpu/armv7/keystone/cmd_mon.c b/roms/u-boot/arch/arm/cpu/armv7/keystone/cmd_mon.c new file mode 100644 index 00000000..f9f58a37 --- /dev/null +++ b/roms/u-boot/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 */; +} + +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; + +	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); +	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/roms/u-boot/arch/arm/cpu/armv7/keystone/ddr3.c b/roms/u-boot/arch/arm/cpu/armv7/keystone/ddr3.c new file mode 100644 index 00000000..4875db76 --- /dev/null +++ b/roms/u-boot/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/roms/u-boot/arch/arm/cpu/armv7/keystone/init.c b/roms/u-boot/arch/arm/cpu/armv7/keystone/init.c new file mode 100644 index 00000000..044015ae --- /dev/null +++ b/roms/u-boot/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) +{ +	__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 +} diff --git a/roms/u-boot/arch/arm/cpu/armv7/keystone/keystone_nav.c b/roms/u-boot/arch/arm/cpu/armv7/keystone/keystone_nav.c new file mode 100644 index 00000000..39d6f995 --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/armv7/keystone/keystone_nav.c @@ -0,0 +1,376 @@ +/* + * Multicore Navigator driver for TI Keystone 2 devices. + * + * (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/keystone_nav.h> + +static int soc_type = +#ifdef CONFIG_SOC_K2HK +	k2hk; +#endif + +struct qm_config k2hk_qm_memmap = { +	.stat_cfg	= 0x02a40000, +	.queue		= (struct qm_reg_queue *)0x02a80000, +	.mngr_vbusm	= 0x23a80000, +	.i_lram		= 0x00100000, +	.proxy		= (struct qm_reg_queue *)0x02ac0000, +	.status_ram	= 0x02a06000, +	.mngr_cfg	= (struct qm_cfg_reg *)0x02a02000, +	.intd_cfg	= 0x02a0c000, +	.desc_mem	= (struct descr_mem_setup_reg *)0x02a03000, +	.region_num	= 64, +	.pdsp_cmd	= 0x02a20000, +	.pdsp_ctl	= 0x02a0f000, +	.pdsp_iram	= 0x02a10000, +	.qpool_num	= 4000, +}; + +/* + * We are going to use only one type of descriptors - host packet + * descriptors. We staticaly allocate memory for them here + */ +struct qm_host_desc desc_pool[HDESC_NUM] __aligned(sizeof(struct qm_host_desc)); + +static struct qm_config *qm_cfg; + +inline int num_of_desc_to_reg(int num_descr) +{ +	int j, num; + +	for (j = 0, num = 32; j < 15; j++, num *= 2) { +		if (num_descr <= num) +			return j; +	} + +	return 15; +} + +static int _qm_init(struct qm_config *cfg) +{ +	u32	j; + +	if (cfg == NULL) +		return QM_ERR; + +	qm_cfg = cfg; + +	qm_cfg->mngr_cfg->link_ram_base0	= qm_cfg->i_lram; +	qm_cfg->mngr_cfg->link_ram_size0	= HDESC_NUM * 8; +	qm_cfg->mngr_cfg->link_ram_base1	= 0; +	qm_cfg->mngr_cfg->link_ram_size1	= 0; +	qm_cfg->mngr_cfg->link_ram_base2	= 0; + +	qm_cfg->desc_mem[0].base_addr = (u32)desc_pool; +	qm_cfg->desc_mem[0].start_idx = 0; +	qm_cfg->desc_mem[0].desc_reg_size = +		(((sizeof(struct qm_host_desc) >> 4) - 1) << 16) | +		num_of_desc_to_reg(HDESC_NUM); + +	memset(desc_pool, 0, sizeof(desc_pool)); +	for (j = 0; j < HDESC_NUM; j++) +		qm_push(&desc_pool[j], qm_cfg->qpool_num); + +	return QM_OK; +} + +int qm_init(void) +{ +	switch (soc_type) { +	case k2hk: +		return _qm_init(&k2hk_qm_memmap); +	} + +	return QM_ERR; +} + +void qm_close(void) +{ +	u32	j; + +	if (qm_cfg == NULL) +		return; + +	queue_close(qm_cfg->qpool_num); + +	qm_cfg->mngr_cfg->link_ram_base0	= 0; +	qm_cfg->mngr_cfg->link_ram_size0	= 0; +	qm_cfg->mngr_cfg->link_ram_base1	= 0; +	qm_cfg->mngr_cfg->link_ram_size1	= 0; +	qm_cfg->mngr_cfg->link_ram_base2	= 0; + +	for (j = 0; j < qm_cfg->region_num; j++) { +		qm_cfg->desc_mem[j].base_addr = 0; +		qm_cfg->desc_mem[j].start_idx = 0; +		qm_cfg->desc_mem[j].desc_reg_size = 0; +	} + +	qm_cfg = NULL; +} + +void qm_push(struct qm_host_desc *hd, u32 qnum) +{ +	u32 regd; + +	if (!qm_cfg) +		return; + +	cpu_to_bus((u32 *)hd, sizeof(struct qm_host_desc)/4); +	regd = (u32)hd | ((sizeof(struct qm_host_desc) >> 4) - 1); +	writel(regd, &qm_cfg->queue[qnum].ptr_size_thresh); +} + +void qm_buff_push(struct qm_host_desc *hd, u32 qnum, +		    void *buff_ptr, u32 buff_len) +{ +	hd->orig_buff_len = buff_len; +	hd->buff_len = buff_len; +	hd->orig_buff_ptr = (u32)buff_ptr; +	hd->buff_ptr = (u32)buff_ptr; +	qm_push(hd, qnum); +} + +struct qm_host_desc *qm_pop(u32 qnum) +{ +	u32 uhd; + +	if (!qm_cfg) +		return NULL; + +	uhd = readl(&qm_cfg->queue[qnum].ptr_size_thresh) & ~0xf; +	if (uhd) +		cpu_to_bus((u32 *)uhd, sizeof(struct qm_host_desc)/4); + +	return (struct qm_host_desc *)uhd; +} + +struct qm_host_desc *qm_pop_from_free_pool(void) +{ +	if (!qm_cfg) +		return NULL; + +	return qm_pop(qm_cfg->qpool_num); +} + +void queue_close(u32 qnum) +{ +	struct qm_host_desc *hd; + +	while ((hd = qm_pop(qnum))) +		; +} + +/* + * DMA API + */ + +struct pktdma_cfg k2hk_netcp_pktdma = { +	.global		= (struct global_ctl_regs *)0x02004000, +	.tx_ch		= (struct tx_chan_regs *)0x02004400, +	.tx_ch_num	= 9, +	.rx_ch		= (struct rx_chan_regs *)0x02004800, +	.rx_ch_num	= 26, +	.tx_sched	= (u32 *)0x02004c00, +	.rx_flows	= (struct rx_flow_regs *)0x02005000, +	.rx_flow_num	= 32, +	.rx_free_q	= 4001, +	.rx_rcv_q	= 4002, +	.tx_snd_q	= 648, +}; + +struct pktdma_cfg *netcp; + +static int netcp_rx_disable(void) +{ +	u32 j, v, k; + +	for (j = 0; j < netcp->rx_ch_num; j++) { +		v = readl(&netcp->rx_ch[j].cfg_a); +		if (!(v & CPDMA_CHAN_A_ENABLE)) +			continue; + +		writel(v | CPDMA_CHAN_A_TDOWN, &netcp->rx_ch[j].cfg_a); +		for (k = 0; k < TDOWN_TIMEOUT_COUNT; k++) { +			udelay(100); +			v = readl(&netcp->rx_ch[j].cfg_a); +			if (!(v & CPDMA_CHAN_A_ENABLE)) +				continue; +		} +		/* TODO: teardown error on if TDOWN_TIMEOUT_COUNT is reached */ +	} + +	/* Clear all of the flow registers */ +	for (j = 0; j < netcp->rx_flow_num; j++) { +		writel(0, &netcp->rx_flows[j].control); +		writel(0, &netcp->rx_flows[j].tags); +		writel(0, &netcp->rx_flows[j].tag_sel); +		writel(0, &netcp->rx_flows[j].fdq_sel[0]); +		writel(0, &netcp->rx_flows[j].fdq_sel[1]); +		writel(0, &netcp->rx_flows[j].thresh[0]); +		writel(0, &netcp->rx_flows[j].thresh[1]); +		writel(0, &netcp->rx_flows[j].thresh[2]); +	} + +	return QM_OK; +} + +static int netcp_tx_disable(void) +{ +	u32 j, v, k; + +	for (j = 0; j < netcp->tx_ch_num; j++) { +		v = readl(&netcp->tx_ch[j].cfg_a); +		if (!(v & CPDMA_CHAN_A_ENABLE)) +			continue; + +		writel(v | CPDMA_CHAN_A_TDOWN, &netcp->tx_ch[j].cfg_a); +		for (k = 0; k < TDOWN_TIMEOUT_COUNT; k++) { +			udelay(100); +			v = readl(&netcp->tx_ch[j].cfg_a); +			if (!(v & CPDMA_CHAN_A_ENABLE)) +				continue; +		} +		/* TODO: teardown error on if TDOWN_TIMEOUT_COUNT is reached */ +	} + +	return QM_OK; +} + +static int _netcp_init(struct pktdma_cfg *netcp_cfg, +		       struct rx_buff_desc *rx_buffers) +{ +	u32 j, v; +	struct qm_host_desc *hd; +	u8 *rx_ptr; + +	if (netcp_cfg == NULL || rx_buffers == NULL || +	    rx_buffers->buff_ptr == NULL || qm_cfg == NULL) +		return QM_ERR; + +	netcp = netcp_cfg; +	netcp->rx_flow = rx_buffers->rx_flow; + +	/* init rx queue */ +	rx_ptr = rx_buffers->buff_ptr; + +	for (j = 0; j < rx_buffers->num_buffs; j++) { +		hd = qm_pop(qm_cfg->qpool_num); +		if (hd == NULL) +			return QM_ERR; + +		qm_buff_push(hd, netcp->rx_free_q, +			     rx_ptr, rx_buffers->buff_len); + +		rx_ptr += rx_buffers->buff_len; +	} + +	netcp_rx_disable(); + +	/* configure rx channels */ +	v = CPDMA_REG_VAL_MAKE_RX_FLOW_A(1, 1, 0, 0, 0, 0, 0, netcp->rx_rcv_q); +	writel(v, &netcp->rx_flows[netcp->rx_flow].control); +	writel(0, &netcp->rx_flows[netcp->rx_flow].tags); +	writel(0, &netcp->rx_flows[netcp->rx_flow].tag_sel); + +	v = CPDMA_REG_VAL_MAKE_RX_FLOW_D(0, netcp->rx_free_q, 0, +					 netcp->rx_free_q); + +	writel(v, &netcp->rx_flows[netcp->rx_flow].fdq_sel[0]); +	writel(v, &netcp->rx_flows[netcp->rx_flow].fdq_sel[1]); +	writel(0, &netcp->rx_flows[netcp->rx_flow].thresh[0]); +	writel(0, &netcp->rx_flows[netcp->rx_flow].thresh[1]); +	writel(0, &netcp->rx_flows[netcp->rx_flow].thresh[2]); + +	for (j = 0; j < netcp->rx_ch_num; j++) +		writel(CPDMA_CHAN_A_ENABLE, &netcp->rx_ch[j].cfg_a); + +	/* configure tx channels */ +	/* Disable loopback in the tx direction */ +	writel(0, &netcp->global->emulation_control); + +/* TODO: make it dependend on a soc type variable */ +#ifdef CONFIG_SOC_K2HK +	/* Set QM base address, only for K2x devices */ +	writel(0x23a80000, &netcp->global->qm_base_addr[0]); +#endif + +	/* Enable all channels. The current state isn't important */ +	for (j = 0; j < netcp->tx_ch_num; j++)  { +		writel(0, &netcp->tx_ch[j].cfg_b); +		writel(CPDMA_CHAN_A_ENABLE, &netcp->tx_ch[j].cfg_a); +	} + +	return QM_OK; +} + +int netcp_init(struct rx_buff_desc *rx_buffers) +{ +	switch (soc_type) { +	case k2hk: +		_netcp_init(&k2hk_netcp_pktdma, rx_buffers); +		return QM_OK; +	} +	return QM_ERR; +} + +int netcp_close(void) +{ +	if (!netcp) +		return QM_ERR; + +	netcp_tx_disable(); +	netcp_rx_disable(); + +	queue_close(netcp->rx_free_q); +	queue_close(netcp->rx_rcv_q); +	queue_close(netcp->tx_snd_q); + +	return QM_OK; +} + +int netcp_send(u32 *pkt, int num_bytes, u32 swinfo2) +{ +	struct qm_host_desc *hd; + +	hd = qm_pop(qm_cfg->qpool_num); +	if (hd == NULL) +		return QM_ERR; + +	hd->desc_info	= num_bytes; +	hd->swinfo[2]	= swinfo2; +	hd->packet_info = qm_cfg->qpool_num; + +	qm_buff_push(hd, netcp->tx_snd_q, pkt, num_bytes); + +	return QM_OK; +} + +void *netcp_recv(u32 **pkt, int *num_bytes) +{ +	struct qm_host_desc *hd; + +	hd = qm_pop(netcp->rx_rcv_q); +	if (!hd) +		return NULL; + +	*pkt = (u32 *)hd->buff_ptr; +	*num_bytes = hd->desc_info & 0x3fffff; + +	return hd; +} + +void netcp_release_rxhd(void *hd) +{ +	struct qm_host_desc *_hd = (struct qm_host_desc *)hd; + +	_hd->buff_len = _hd->orig_buff_len; +	_hd->buff_ptr = _hd->orig_buff_ptr; + +	qm_push(_hd, netcp->rx_free_q); +} diff --git a/roms/u-boot/arch/arm/cpu/armv7/keystone/msmc.c b/roms/u-boot/arch/arm/cpu/armv7/keystone/msmc.c new file mode 100644 index 00000000..f3f1621d --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/armv7/keystone/msmc.c @@ -0,0 +1,68 @@ +/* + * MSMC controller utilities + * + * (C) Copyright 2012-2014 + *     Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier:     GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/hardware.h> + +struct mpax { +	u32	mpaxl; +	u32	mpaxh; +}; + +struct msms_regs { +	u32	pid; +	u32	_res_04; +	u32	smcerrar; +	u32	smcerrxr; +	u32	smedcc; +	u32	smcea; +	u32	smsecc; +	u32	smpfar; +	u32	smpfxr; +	u32	smpfr; +	u32	smpfcr; +	u32	_res_2c; +	u32	sbndc[8]; +	u32	sbndm; +	u32	sbnde; +	u32	_res_58; +	u32	cfglck; +	u32	cfgulck; +	u32	cfglckstat; +	u32	sms_mpax_lck; +	u32	sms_mpax_ulck; +	u32	sms_mpax_lckstat; +	u32	ses_mpax_lck; +	u32	ses_mpax_ulck; +	u32	ses_mpax_lckstat; +	u32	smestat; +	u32	smirstat; +	u32	smirc; +	u32	smiestat; +	u32	smiec; +	u32	_res_94_c0[12]; +	u32	smncerrar; +	u32	smncerrxr; +	u32	smncea; +	u32	_res_d0_1fc[76]; +	struct mpax sms[16][8]; +	struct mpax ses[16][8]; +}; + + +void share_all_segments(int priv_id) +{ +	struct msms_regs *msmc = (struct msms_regs *)K2HK_MSMC_CTRL_BASE; +	int j; + +	for (j = 0; j < 8; j++) { +		msmc->sms[priv_id][j].mpaxh &= 0xffffff7ful; +		msmc->ses[priv_id][j].mpaxh &= 0xffffff7ful; +	} +} diff --git a/roms/u-boot/arch/arm/cpu/armv7/keystone/psc.c b/roms/u-boot/arch/arm/cpu/armv7/keystone/psc.c new file mode 100644 index 00000000..c844dc84 --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/armv7/keystone/psc.c @@ -0,0 +1,237 @@ +/* + * Keystone: PSC configuration module + * + * (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/psc_defs.h> + +#define DEVICE_REG32_R(addr)			__raw_readl((u32 *)(addr)) +#define DEVICE_REG32_W(addr, val)		__raw_writel(val, (u32 *)(addr)) + +#ifdef CONFIG_SOC_K2HK +#define DEVICE_PSC_BASE				K2HK_PSC_BASE +#endif + +int psc_delay(void) +{ +	udelay(10); +	return 10; +} + +/* + * FUNCTION PURPOSE: Wait for end of transitional state + * + * DESCRIPTION: Polls pstat for the selected domain and waits for transitions + *              to be complete. + * + *              Since this is boot loader code it is *ASSUMED* that interrupts + *              are disabled and no other core is mucking around with the psc + *              at the same time. + * + *              Returns 0 when the domain is free. Returns -1 if a timeout + *              occurred waiting for the completion. + */ +int psc_wait(u32 domain_num) +{ +	u32 retry; +	u32 ptstat; + +	/* +	 * Do nothing if the power domain is in transition. This should never +	 * happen since the boot code is the only software accesses psc. +	 * It's still remotely possible that the hardware state machines +	 * initiate transitions. +	 * Don't trap if the domain (or a module in this domain) is +	 * stuck in transition. +	 */ +	retry = 0; + +	do { +		ptstat = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_PSTAT); +		ptstat = ptstat & (1 << domain_num); +	} while ((ptstat != 0) && ((retry += psc_delay()) < +		 PSC_PTSTAT_TIMEOUT_LIMIT)); + +	if (retry >= PSC_PTSTAT_TIMEOUT_LIMIT) +		return -1; + +	return 0; +} + +u32 psc_get_domain_num(u32 mod_num) +{ +	u32 domain_num; + +	/* Get the power domain associated with the module number */ +	domain_num = DEVICE_REG32_R(DEVICE_PSC_BASE + +				    PSC_REG_MDCFG(mod_num)); +	domain_num = PSC_REG_MDCFG_GET_PD(domain_num); + +	return domain_num; +} + +/* + * FUNCTION PURPOSE: Power up/down a module + * + * DESCRIPTION: Powers up/down the requested module and the associated power + *		domain if required. No action is taken it the module is + *		already powered up/down. + * + *              This only controls modules. The domain in which the module + *              resides will be left in the power on state. Multiple modules + *              can exist in a power domain, so powering down the domain based + *              on a single module is not done. + * + *              Returns 0 on success, -1 if the module can't be powered up, or + *              if there is a timeout waiting for the transition. + */ +int psc_set_state(u32 mod_num, u32 state) +{ +	u32 domain_num; +	u32 pdctl; +	u32 mdctl; +	u32 ptcmd; +	u32 reset_iso; +	u32 v; + +	/* +	 * Get the power domain associated with the module number, and reset +	 * isolation functionality +	 */ +	v = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_MDCFG(mod_num)); +	domain_num = PSC_REG_MDCFG_GET_PD(v); +	reset_iso  = PSC_REG_MDCFG_GET_RESET_ISO(v); + +	/* Wait for the status of the domain/module to be non-transitional */ +	if (psc_wait(domain_num) != 0) +		return -1; + +	/* +	 * Perform configuration even if the current status matches the +	 * existing state +	 * +	 * Set the next state of the power domain to on. It's OK if the domain +	 * is always on. This code will not ever power down a domain, so no +	 * change is made if the new state is power down. +	 */ +	if (state == PSC_REG_VAL_MDCTL_NEXT_ON) { +		pdctl = DEVICE_REG32_R(DEVICE_PSC_BASE + +				       PSC_REG_PDCTL(domain_num)); +		pdctl = PSC_REG_PDCTL_SET_NEXT(pdctl, +					       PSC_REG_VAL_PDCTL_NEXT_ON); +		DEVICE_REG32_W(DEVICE_PSC_BASE + PSC_REG_PDCTL(domain_num), +			       pdctl); +	} + +	/* Set the next state for the module to enabled/disabled */ +	mdctl = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_MDCTL(mod_num)); +	mdctl = PSC_REG_MDCTL_SET_NEXT(mdctl, state); +	mdctl = PSC_REG_MDCTL_SET_RESET_ISO(mdctl, reset_iso); +	DEVICE_REG32_W(DEVICE_PSC_BASE + PSC_REG_MDCTL(mod_num), mdctl); + +	/* Trigger the enable */ +	ptcmd = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_PTCMD); +	ptcmd |= (u32)(1<<domain_num); +	DEVICE_REG32_W(DEVICE_PSC_BASE + PSC_REG_PTCMD, ptcmd); + +	/* Wait on the complete */ +	return psc_wait(domain_num); +} + +/* + * FUNCTION PURPOSE: Power up a module + * + * DESCRIPTION: Powers up the requested module and the associated power domain + *              if required. No action is taken it the module is already + *              powered up. + * + *              Returns 0 on success, -1 if the module can't be powered up, or + *              if there is a timeout waiting for the transition. + */ +int psc_enable_module(u32 mod_num) +{ +	u32 mdctl; + +	/* Set the bit to apply reset */ +	mdctl = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_MDCTL(mod_num)); +	if ((mdctl & 0x3f) == PSC_REG_VAL_MDSTAT_STATE_ON) +		return 0; + +	return psc_set_state(mod_num, PSC_REG_VAL_MDCTL_NEXT_ON); +} + +/* + * FUNCTION PURPOSE: Power down a module + * + * DESCRIPTION: Powers down the requested module. + * + *              Returns 0 on success, -1 on failure or timeout. + */ +int psc_disable_module(u32 mod_num) +{ +	u32 mdctl; + +	/* Set the bit to apply reset */ +	mdctl = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_MDCTL(mod_num)); +	if ((mdctl & 0x3f) == 0) +		return 0; +	mdctl = PSC_REG_MDCTL_SET_LRSTZ(mdctl, 0); +	DEVICE_REG32_W(DEVICE_PSC_BASE + PSC_REG_MDCTL(mod_num), mdctl); + +	return psc_set_state(mod_num, PSC_REG_VAL_MDCTL_NEXT_SWRSTDISABLE); +} + +/* + * FUNCTION PURPOSE: Set the reset isolation bit in mdctl + * + * DESCRIPTION: The reset isolation enable bit is set. The state of the module + *              is not changed. Returns 0 if the module config showed that + *              reset isolation is supported. Returns 1 otherwise. This is not + *              an error, but setting the bit in mdctl has no effect. + */ +int psc_set_reset_iso(u32 mod_num) +{ +	u32 v; +	u32 mdctl; + +	/* Set the reset isolation bit */ +	mdctl = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_MDCTL(mod_num)); +	mdctl = PSC_REG_MDCTL_SET_RESET_ISO(mdctl, 1); +	DEVICE_REG32_W(DEVICE_PSC_BASE + PSC_REG_MDCTL(mod_num), mdctl); + +	v = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_MDCFG(mod_num)); +	if (PSC_REG_MDCFG_GET_RESET_ISO(v) == 1) +		return 0; + +	return 1; +} + +/* + * FUNCTION PURPOSE: Disable a power domain + * + * DESCRIPTION: The power domain is disabled + */ +int psc_disable_domain(u32 domain_num) +{ +	u32 pdctl; +	u32 ptcmd; + +	pdctl = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_PDCTL(domain_num)); +	pdctl = PSC_REG_PDCTL_SET_NEXT(pdctl, PSC_REG_VAL_PDCTL_NEXT_OFF); +	pdctl = PSC_REG_PDCTL_SET_PDMODE(pdctl, PSC_REG_VAL_PDCTL_PDMODE_SLEEP); +	DEVICE_REG32_W(DEVICE_PSC_BASE + PSC_REG_PDCTL(domain_num), pdctl); + +	ptcmd = DEVICE_REG32_R(DEVICE_PSC_BASE + PSC_REG_PTCMD); +	ptcmd |= (u32)(1 << domain_num); +	DEVICE_REG32_W(DEVICE_PSC_BASE + PSC_REG_PTCMD, ptcmd); + +	return psc_wait(domain_num); +} diff --git a/roms/u-boot/arch/arm/cpu/armv7/keystone/spl.c b/roms/u-boot/arch/arm/cpu/armv7/keystone/spl.c new file mode 100644 index 00000000..e07b64db --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/armv7/keystone/spl.c @@ -0,0 +1,45 @@ +/* + * common spl init code + * + * (C) Copyright 2012-2014 + *     Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier:     GPL-2.0+ + */ +#include <common.h> +#include <config.h> +#include <ns16550.h> +#include <malloc.h> +#include <spl.h> +#include <spi_flash.h> + +#include <asm/u-boot.h> +#include <asm/utils.h> + +DECLARE_GLOBAL_DATA_PTR; + +static struct pll_init_data spl_pll_config[] = { +	CORE_PLL_799, +	TETRIS_PLL_500, +}; + +void spl_init_keystone_plls(void) +{ +	init_plls(ARRAY_SIZE(spl_pll_config), spl_pll_config); +} + +void spl_board_init(void) +{ +	spl_init_keystone_plls(); +	preloader_console_init(); +} + +u32 spl_boot_device(void) +{ +#if defined(CONFIG_SPL_SPI_LOAD) +	return BOOT_DEVICE_SPI; +#else +	puts("Unknown boot device\n"); +	hang(); +#endif +}  | 
