diff options
Diffstat (limited to 'arch/arm/cpu/armv7')
52 files changed, 1227 insertions, 5138 deletions
| diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile index 6b2addca1..4fdbee4bc 100644 --- a/arch/arm/cpu/armv7/Makefile +++ b/arch/arm/cpu/armv7/Makefile @@ -32,8 +32,12 @@ COBJS	+= cache_v7.o  COBJS	+= cpu.o  COBJS	+= syslib.o +ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA20),) +SOBJS	+= lowlevel_init.o +endif +  SRCS	:= $(START:.o=.S) $(COBJS:.o=.c) -OBJS	:= $(addprefix $(obj),$(COBJS)) +OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS))  START	:= $(addprefix $(obj),$(START))  all:	$(obj).depend $(START) $(LIB) diff --git a/arch/arm/cpu/armv7/am33xx/board.c b/arch/arm/cpu/armv7/am33xx/board.c index 71309a7f4..ecc26717c 100644 --- a/arch/arm/cpu/armv7/am33xx/board.c +++ b/arch/arm/cpu/armv7/am33xx/board.c @@ -17,22 +17,100 @@   */  #include <common.h> +#include <errno.h>  #include <asm/arch/cpu.h>  #include <asm/arch/hardware.h>  #include <asm/arch/omap.h>  #include <asm/arch/ddr_defs.h>  #include <asm/arch/clock.h> +#include <asm/arch/gpio.h>  #include <asm/arch/mmc_host_def.h> -#include <asm/arch/common_def.h> +#include <asm/arch/sys_proto.h>  #include <asm/io.h>  #include <asm/omap_common.h> +#include <asm/emif.h> +#include <asm/gpio.h> +#include <i2c.h> +#include <miiphy.h> +#include <cpsw.h>  DECLARE_GLOBAL_DATA_PTR;  struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE; -struct gptimer *timer_base = (struct gptimer *)CONFIG_SYS_TIMERBASE;  struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE; +static const struct gpio_bank gpio_bank_am33xx[4] = { +	{ (void *)AM33XX_GPIO0_BASE, METHOD_GPIO_24XX }, +	{ (void *)AM33XX_GPIO1_BASE, METHOD_GPIO_24XX }, +	{ (void *)AM33XX_GPIO2_BASE, METHOD_GPIO_24XX }, +	{ (void *)AM33XX_GPIO3_BASE, METHOD_GPIO_24XX }, +}; + +const struct gpio_bank *const omap_gpio_bank = gpio_bank_am33xx; + +/* MII mode defines */ +#define MII_MODE_ENABLE		0x0 +#define RGMII_MODE_ENABLE	0xA + +/* GPIO that controls power to DDR on EVM-SK */ +#define GPIO_DDR_VTT_EN		7 + +static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; + +static struct am335x_baseboard_id __attribute__((section (".data"))) header; + +static inline int board_is_bone(void) +{ +	return !strncmp(header.name, "A335BONE", HDR_NAME_LEN); +} + +static inline int board_is_evm_sk(void) +{ +	return !strncmp("A335X_SK", header.name, HDR_NAME_LEN); +} + +/* + * Read header information from EEPROM into global structure. + */ +static int read_eeprom(void) +{ +	/* Check if baseboard eeprom is available */ +	if (i2c_probe(CONFIG_SYS_I2C_EEPROM_ADDR)) { +		puts("Could not probe the EEPROM; something fundamentally " +			"wrong on the I2C bus.\n"); +		return -ENODEV; +	} + +	/* read the eeprom using i2c */ +	if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, 2, (uchar *)&header, +							sizeof(header))) { +		puts("Could not read the EEPROM; something fundamentally" +			" wrong on the I2C bus.\n"); +		return -EIO; +	} + +	if (header.magic != 0xEE3355AA) { +		/* +		 * read the eeprom using i2c again, +		 * but use only a 1 byte address +		 */ +		if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, 1, +					(uchar *)&header, sizeof(header))) { +			puts("Could not read the EEPROM; something " +				"fundamentally wrong on the I2C bus.\n"); +			return -EIO; +		} + +		if (header.magic != 0xEE3355AA) { +			printf("Incorrect magic number (0x%x) in EEPROM\n", +					header.magic); +			return -EINVAL; +		} +	} + +	return 0; +} +  /* UART Defines */  #ifdef CONFIG_SPL_BUILD  #define UART_RESET		(0x1 << 1) @@ -40,21 +118,17 @@ struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE;  #define UART_SMART_IDLE_EN	(0x1 << 0x3)  #endif -#ifdef CONFIG_SPL_BUILD -/* Initialize timer */ -static void init_timer(void) +/* + * Determine what type of DDR we have. + */ +static short inline board_memory_type(void)  { -	/* Reset the Timer */ -	writel(0x2, (&timer_base->tscir)); +	/* The following boards are known to use DDR3. */ +	if (board_is_evm_sk()) +		return EMIF_REG_SDRAM_TYPE_DDR3; -	/* Wait until the reset is done */ -	while (readl(&timer_base->tiocp_cfg) & 1) -		; - -	/* Start the Timer */ -	writel(0x1, (&timer_base->tclr)); +	return EMIF_REG_SDRAM_TYPE_DDR2;  } -#endif  /*   * early system init of muxing and clocks. @@ -92,22 +166,38 @@ void s_init(void)  	regVal |= UART_SMART_IDLE_EN;  	writel(regVal, &uart_base->uartsyscfg); -	/* Initialize the Timer */ -	init_timer(); -  	preloader_console_init(); -	config_ddr(); -#endif +	/* Initalize the board header */ +	enable_i2c0_pin_mux(); +	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); +	if (read_eeprom() < 0) +		puts("Could not get board ID.\n"); -	/* Enable MMC0 */ -	enable_mmc0_pin_mux(); +	enable_board_pin_mux(&header); +	if (board_is_evm_sk()) { +		/* +		 * EVM SK 1.2A and later use gpio0_7 to enable DDR3. +		 * This is safe enough to do on older revs. +		 */ +		gpio_request(GPIO_DDR_VTT_EN, "ddr_vtt_en"); +		gpio_direction_output(GPIO_DDR_VTT_EN, 1); +	} + +	config_ddr(board_memory_type()); +#endif  }  #if defined(CONFIG_OMAP_HSMMC) && !defined(CONFIG_SPL_BUILD)  int board_mmc_init(bd_t *bis)  { -	return omap_mmc_init(0, 0, 0); +	int ret; +	 +	ret = omap_mmc_init(0, 0, 0); +	if (ret) +		return ret; + +	return omap_mmc_init(1, 0, 0);  }  #endif @@ -116,3 +206,93 @@ void setup_clocks_for_console(void)  	/* Not yet implemented */  	return;  } + +/* + * Basic board specific setup.  Pinmux has been handled already. + */ +int board_init(void) +{ +	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); +	if (read_eeprom() < 0) +		puts("Could not get board ID.\n"); + +	gd->bd->bi_boot_params = PHYS_DRAM_1 + 0x100; + +	return 0; +} + +#ifdef CONFIG_DRIVER_TI_CPSW +static void cpsw_control(int enabled) +{ +	/* VTP can be added here */ + +	return; +} + +static struct cpsw_slave_data cpsw_slaves[] = { +	{ +		.slave_reg_ofs	= 0x208, +		.sliver_reg_ofs	= 0xd80, +		.phy_id		= 0, +	}, +	{ +		.slave_reg_ofs	= 0x308, +		.sliver_reg_ofs	= 0xdc0, +		.phy_id		= 1, +	}, +}; + +static struct cpsw_platform_data cpsw_data = { +	.mdio_base		= AM335X_CPSW_MDIO_BASE, +	.cpsw_base		= AM335X_CPSW_BASE, +	.mdio_div		= 0xff, +	.channels		= 8, +	.cpdma_reg_ofs		= 0x800, +	.slaves			= 1, +	.slave_data		= cpsw_slaves, +	.ale_reg_ofs		= 0xd00, +	.ale_entries		= 1024, +	.host_port_reg_ofs	= 0x108, +	.hw_stats_reg_ofs	= 0x900, +	.mac_control		= (1 << 5), +	.control		= cpsw_control, +	.host_port_num		= 0, +	.version		= CPSW_CTRL_VERSION_2, +}; + +int board_eth_init(bd_t *bis) +{ +	uint8_t mac_addr[6]; +	uint32_t mac_hi, mac_lo; + +	if (!eth_getenv_enetaddr("ethaddr", mac_addr)) { +		debug("<ethaddr> not set. Reading from E-fuse\n"); +		/* try reading mac address from efuse */ +		mac_lo = readl(&cdev->macid0l); +		mac_hi = readl(&cdev->macid0h); +		mac_addr[0] = mac_hi & 0xFF; +		mac_addr[1] = (mac_hi & 0xFF00) >> 8; +		mac_addr[2] = (mac_hi & 0xFF0000) >> 16; +		mac_addr[3] = (mac_hi & 0xFF000000) >> 24; +		mac_addr[4] = mac_lo & 0xFF; +		mac_addr[5] = (mac_lo & 0xFF00) >> 8; + +		if (is_valid_ether_addr(mac_addr)) +			eth_setenv_enetaddr("ethaddr", mac_addr); +		else +			return -1; +	} + +	if (board_is_bone()) { +		writel(MII_MODE_ENABLE, &cdev->miisel); +		cpsw_slaves[0].phy_if = cpsw_slaves[1].phy_if = +				PHY_INTERFACE_MODE_MII; +	} else { +		writel(RGMII_MODE_ENABLE, &cdev->miisel); +		cpsw_slaves[0].phy_if = cpsw_slaves[1].phy_if = +				PHY_INTERFACE_MODE_RGMII; +	} + +	return cpsw_register(&cpsw_data); +} +#endif diff --git a/arch/arm/cpu/armv7/am33xx/clock.c b/arch/arm/cpu/armv7/am33xx/clock.c index bbb9c1353..2b19506a3 100644 --- a/arch/arm/cpu/armv7/am33xx/clock.c +++ b/arch/arm/cpu/armv7/am33xx/clock.c @@ -24,6 +24,7 @@  #define PRCM_MOD_EN		0x2  #define PRCM_FORCE_WAKEUP	0x2 +#define PRCM_FUNCTL		0x0  #define PRCM_EMIF_CLK_ACTIVITY	BIT(2)  #define PRCM_L3_GCLK_ACTIVITY	BIT(4) @@ -38,7 +39,7 @@  #define CLK_MODE_SEL		0x7  #define CLK_MODE_MASK		0xfffffff8  #define CLK_DIV_SEL		0xFFFFFFE0 - +#define CPGMAC0_IDLE		0x30000  const struct cm_perpll *cmper = (struct cm_perpll *)CM_PER;  const struct cm_wkuppll *cmwkup = (struct cm_wkuppll *)CM_WKUP; @@ -70,6 +71,10 @@ static void enable_interface_clocks(void)  	writel(PRCM_MOD_EN, &cmper->l4hsclkctrl);  	while (readl(&cmper->l4hsclkctrl) != PRCM_MOD_EN)  		; + +	writel(PRCM_MOD_EN, &cmwkup->wkgpio0clkctrl); +	while (readl(&cmwkup->wkgpio0clkctrl) != PRCM_MOD_EN) +		;  }  /* @@ -118,6 +123,36 @@ static void enable_per_clocks(void)  	writel(PRCM_MOD_EN, &cmwkup->wkup_i2c0ctrl);  	while (readl(&cmwkup->wkup_i2c0ctrl) != PRCM_MOD_EN)  		; + +	/* gpio1 module */ +	writel(PRCM_MOD_EN, &cmper->gpio1clkctrl); +	while (readl(&cmper->gpio1clkctrl) != PRCM_MOD_EN) +		; + +	/* gpio2 module */ +	writel(PRCM_MOD_EN, &cmper->gpio2clkctrl); +	while (readl(&cmper->gpio2clkctrl) != PRCM_MOD_EN) +		; + +	/* gpio3 module */ +	writel(PRCM_MOD_EN, &cmper->gpio3clkctrl); +	while (readl(&cmper->gpio3clkctrl) != PRCM_MOD_EN) +		; + +	/* i2c1 */ +	writel(PRCM_MOD_EN, &cmper->i2c1clkctrl); +	while (readl(&cmper->i2c1clkctrl) != PRCM_MOD_EN) +		; + +	/* Ethernet */ +	writel(PRCM_MOD_EN, &cmper->cpgmac0clkctrl); +	while ((readl(&cmper->cpgmac0clkctrl) & CPGMAC0_IDLE) != PRCM_FUNCTL) +		; + +	/* spi0 */ +	writel(PRCM_MOD_EN, &cmper->spi0clkctrl); +	while (readl(&cmper->spi0clkctrl) != PRCM_MOD_EN) +		;  }  static void mpu_pll_config(void) @@ -216,7 +251,7 @@ static void per_pll_config(void)  		;  } -static void ddr_pll_config(void) +void ddr_pll_config(unsigned int ddrpll_m)  {  	u32 clkmode, clksel, div_m2; @@ -234,7 +269,7 @@ static void ddr_pll_config(void)  		;  	clksel = clksel & (~CLK_SEL_MASK); -	clksel = clksel | ((DDRPLL_M << CLK_SEL_SHIFT) | DDRPLL_N); +	clksel = clksel | ((ddrpll_m << CLK_SEL_SHIFT) | DDRPLL_N);  	writel(clksel, &cmwkup->clkseldpllddr);  	div_m2 = div_m2 & CLK_DIV_SEL; @@ -255,11 +290,6 @@ void enable_emif_clocks(void)  	writel(PRCM_MOD_EN, &cmper->emiffwclkctrl);  	/* Enable EMIF0 Clock */  	writel(PRCM_MOD_EN, &cmper->emifclkctrl); -	/* Poll for emif_gclk  & L3_G clock  are active */ -	while ((readl(&cmper->l3clkstctrl) & (PRCM_EMIF_CLK_ACTIVITY | -			PRCM_L3_GCLK_ACTIVITY)) != (PRCM_EMIF_CLK_ACTIVITY | -			PRCM_L3_GCLK_ACTIVITY)) -		;  	/* Poll if module is functional */  	while ((readl(&cmper->emifclkctrl)) != PRCM_MOD_EN)  		; @@ -273,7 +303,6 @@ void pll_init()  	mpu_pll_config();  	core_pll_config();  	per_pll_config(); -	ddr_pll_config();  	/* Enable the required interconnect clocks */  	enable_interface_clocks(); diff --git a/arch/arm/cpu/armv7/am33xx/ddr.c b/arch/arm/cpu/armv7/am33xx/ddr.c index ed982c11e..fd9fc4a72 100644 --- a/arch/arm/cpu/armv7/am33xx/ddr.c +++ b/arch/arm/cpu/armv7/am33xx/ddr.c @@ -17,13 +17,15 @@ http://www.ti.com/  #include <asm/arch/cpu.h>  #include <asm/arch/ddr_defs.h> +#include <asm/arch/sys_proto.h>  #include <asm/io.h> +#include <asm/emif.h>  /**   * Base address for EMIF instances   */ -static struct emif_regs *emif_reg = { -				(struct emif_regs *)EMIF4_0_CFG_BASE}; +static struct emif_reg_struct *emif_reg = { +				(struct emif_reg_struct *)EMIF4_0_CFG_BASE};  /**   * Base address for DDR instance @@ -39,109 +41,79 @@ static struct ddr_cmdtctrl *ioctrl_reg = {  			(struct ddr_cmdtctrl *)DDR_CONTROL_BASE_ADDR};  /** - * As a convention, all functions here return 0 on success - * -1 on failure. - */ - -/**   * Configure SDRAM   */ -int config_sdram(struct sdram_config *cfg) +void config_sdram(const struct emif_regs *regs)  { -	writel(cfg->sdrcr, &emif_reg->sdrcr); -	writel(cfg->sdrcr2, &emif_reg->sdrcr2); -	writel(cfg->refresh, &emif_reg->sdrrcr); -	writel(cfg->refresh_sh, &emif_reg->sdrrcsr); - -	return 0; +	writel(regs->ref_ctrl, &emif_reg->emif_sdram_ref_ctrl); +	writel(regs->ref_ctrl, &emif_reg->emif_sdram_ref_ctrl_shdw); +	if (regs->zq_config){ +		writel(regs->zq_config, &emif_reg->emif_zq_config); +		writel(regs->sdram_config, &cstat->secure_emif_sdram_config); +	} +	writel(regs->sdram_config, &emif_reg->emif_sdram_config);  }  /**   * Set SDRAM timings   */ -int set_sdram_timings(struct sdram_timing *t) +void set_sdram_timings(const struct emif_regs *regs)  { -	writel(t->time1, &emif_reg->sdrtim1); -	writel(t->time1_sh, &emif_reg->sdrtim1sr); -	writel(t->time2, &emif_reg->sdrtim2); -	writel(t->time2_sh, &emif_reg->sdrtim2sr); -	writel(t->time3, &emif_reg->sdrtim3); -	writel(t->time3_sh, &emif_reg->sdrtim3sr); - -	return 0; +	writel(regs->sdram_tim1, &emif_reg->emif_sdram_tim_1); +	writel(regs->sdram_tim1, &emif_reg->emif_sdram_tim_1_shdw); +	writel(regs->sdram_tim2, &emif_reg->emif_sdram_tim_2); +	writel(regs->sdram_tim2, &emif_reg->emif_sdram_tim_2_shdw); +	writel(regs->sdram_tim3, &emif_reg->emif_sdram_tim_3); +	writel(regs->sdram_tim3, &emif_reg->emif_sdram_tim_3_shdw);  }  /**   * Configure DDR PHY   */ -int config_ddr_phy(struct ddr_phy_control *p) +void config_ddr_phy(const struct emif_regs *regs)  { -	writel(p->reg, &emif_reg->ddrphycr); -	writel(p->reg_sh, &emif_reg->ddrphycsr); - -	return 0; +	writel(regs->emif_ddr_phy_ctlr_1, &emif_reg->emif_ddr_phy_ctrl_1); +	writel(regs->emif_ddr_phy_ctlr_1, &emif_reg->emif_ddr_phy_ctrl_1_shdw);  }  /**   * Configure DDR CMD control registers   */ -int config_cmd_ctrl(struct cmd_control *cmd) +void config_cmd_ctrl(const struct cmd_control *cmd)  {  	writel(cmd->cmd0csratio, &ddr_reg[0]->cm0csratio); -	writel(cmd->cmd0csforce, &ddr_reg[0]->cm0csforce); -	writel(cmd->cmd0csdelay, &ddr_reg[0]->cm0csdelay);  	writel(cmd->cmd0dldiff, &ddr_reg[0]->cm0dldiff);  	writel(cmd->cmd0iclkout, &ddr_reg[0]->cm0iclkout);  	writel(cmd->cmd1csratio, &ddr_reg[0]->cm1csratio); -	writel(cmd->cmd1csforce, &ddr_reg[0]->cm1csforce); -	writel(cmd->cmd1csdelay, &ddr_reg[0]->cm1csdelay);  	writel(cmd->cmd1dldiff, &ddr_reg[0]->cm1dldiff);  	writel(cmd->cmd1iclkout, &ddr_reg[0]->cm1iclkout);  	writel(cmd->cmd2csratio, &ddr_reg[0]->cm2csratio); -	writel(cmd->cmd2csforce, &ddr_reg[0]->cm2csforce); -	writel(cmd->cmd2csdelay, &ddr_reg[0]->cm2csdelay);  	writel(cmd->cmd2dldiff, &ddr_reg[0]->cm2dldiff);  	writel(cmd->cmd2iclkout, &ddr_reg[0]->cm2iclkout); - -	return 0;  }  /**   * Configure DDR DATA registers   */ -int config_ddr_data(int macrono, struct ddr_data *data) +void config_ddr_data(int macrono, const struct ddr_data *data)  {  	writel(data->datardsratio0, &ddr_reg[macrono]->dt0rdsratio0); -	writel(data->datardsratio1, &ddr_reg[macrono]->dt0rdsratio1); -  	writel(data->datawdsratio0, &ddr_reg[macrono]->dt0wdsratio0); -	writel(data->datawdsratio1, &ddr_reg[macrono]->dt0wdsratio1); -  	writel(data->datawiratio0, &ddr_reg[macrono]->dt0wiratio0); -	writel(data->datawiratio1, &ddr_reg[macrono]->dt0wiratio1);  	writel(data->datagiratio0, &ddr_reg[macrono]->dt0giratio0); -	writel(data->datagiratio1, &ddr_reg[macrono]->dt0giratio1); -  	writel(data->datafwsratio0, &ddr_reg[macrono]->dt0fwsratio0); -	writel(data->datafwsratio1, &ddr_reg[macrono]->dt0fwsratio1); -  	writel(data->datawrsratio0, &ddr_reg[macrono]->dt0wrsratio0); -	writel(data->datawrsratio1, &ddr_reg[macrono]->dt0wrsratio1); - +	writel(data->datauserank0delay, &ddr_reg[macrono]->dt0rdelays0);  	writel(data->datadldiff0, &ddr_reg[macrono]->dt0dldiff0); - -	return 0;  } -int config_io_ctrl(struct ddr_ioctrl *ioctrl) +void config_io_ctrl(unsigned long val)  { -	writel(ioctrl->cmd1ctl, &ioctrl_reg->cm0ioctl); -	writel(ioctrl->cmd2ctl, &ioctrl_reg->cm1ioctl); -	writel(ioctrl->cmd3ctl, &ioctrl_reg->cm2ioctl); -	writel(ioctrl->data1ctl, &ioctrl_reg->dt0ioctl); -	writel(ioctrl->data2ctl, &ioctrl_reg->dt1ioctl); - -	return 0; +	writel(val, &ioctrl_reg->cm0ioctl); +	writel(val, &ioctrl_reg->cm1ioctl); +	writel(val, &ioctrl_reg->cm2ioctl); +	writel(val, &ioctrl_reg->dt0ioctl); +	writel(val, &ioctrl_reg->dt1ioctl);  } diff --git a/arch/arm/cpu/armv7/am33xx/emif4.c b/arch/arm/cpu/armv7/am33xx/emif4.c index 2f4164df8..b2d7c0d95 100644 --- a/arch/arm/cpu/armv7/am33xx/emif4.c +++ b/arch/arm/cpu/armv7/am33xx/emif4.c @@ -21,15 +21,12 @@  #include <asm/arch/ddr_defs.h>  #include <asm/arch/hardware.h>  #include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h>  #include <asm/io.h> +#include <asm/emif.h>  DECLARE_GLOBAL_DATA_PTR; -struct ddr_regs *ddrregs = (struct ddr_regs *)DDR_PHY_BASE_ADDR; -struct vtp_reg *vtpreg = (struct vtp_reg *)VTP0_CTRL_ADDR; -struct ddr_ctrl *ddrctrl = (struct ddr_ctrl *)DDR_CTRL_ADDR; - -  int dram_init(void)  {  	/* dram_init must store complete ramsize in gd->ram_size */ @@ -47,58 +44,80 @@ void dram_init_banksize(void)  #ifdef CONFIG_SPL_BUILD -static void data_macro_config(int dataMacroNum) -{ -	struct ddr_data data; +static struct vtp_reg *vtpreg = (struct vtp_reg *)VTP0_CTRL_ADDR; +static struct ddr_ctrl *ddrctrl = (struct ddr_ctrl *)DDR_CTRL_ADDR; -	data.datardsratio0 = ((DDR2_RD_DQS<<30)|(DDR2_RD_DQS<<20) -				|(DDR2_RD_DQS<<10)|(DDR2_RD_DQS<<0)); -	data.datardsratio1 = DDR2_RD_DQS>>2; -	data.datawdsratio0 = ((DDR2_WR_DQS<<30)|(DDR2_WR_DQS<<20) -				|(DDR2_WR_DQS<<10)|(DDR2_WR_DQS<<0)); -	data.datawdsratio1 = DDR2_WR_DQS>>2; -	data.datawiratio0 = ((DDR2_PHY_WRLVL<<30)|(DDR2_PHY_WRLVL<<20) -				|(DDR2_PHY_WRLVL<<10)|(DDR2_PHY_WRLVL<<0)); -	data.datawiratio1 = DDR2_PHY_WRLVL>>2; -	data.datagiratio0 = ((DDR2_PHY_GATELVL<<30)|(DDR2_PHY_GATELVL<<20) -				|(DDR2_PHY_GATELVL<<10)|(DDR2_PHY_GATELVL<<0)); -	data.datagiratio1 = DDR2_PHY_GATELVL>>2; -	data.datafwsratio0 = ((DDR2_PHY_FIFO_WE<<30)|(DDR2_PHY_FIFO_WE<<20) -				|(DDR2_PHY_FIFO_WE<<10)|(DDR2_PHY_FIFO_WE<<0)); -	data.datafwsratio1 = DDR2_PHY_FIFO_WE>>2; -	data.datawrsratio0 = ((DDR2_PHY_WR_DATA<<30)|(DDR2_PHY_WR_DATA<<20) -				|(DDR2_PHY_WR_DATA<<10)|(DDR2_PHY_WR_DATA<<0)); -	data.datawrsratio1 = DDR2_PHY_WR_DATA>>2; -	data.datadldiff0 = PHY_DLL_LOCK_DIFF; +static const struct ddr_data ddr2_data = { +	.datardsratio0 = ((DDR2_RD_DQS<<30)|(DDR2_RD_DQS<<20) +				|(DDR2_RD_DQS<<10)|(DDR2_RD_DQS<<0)), +	.datawdsratio0 = ((DDR2_WR_DQS<<30)|(DDR2_WR_DQS<<20) +				|(DDR2_WR_DQS<<10)|(DDR2_WR_DQS<<0)), +	.datawiratio0 = ((DDR2_PHY_WRLVL<<30)|(DDR2_PHY_WRLVL<<20) +				|(DDR2_PHY_WRLVL<<10)|(DDR2_PHY_WRLVL<<0)), +	.datagiratio0 = ((DDR2_PHY_GATELVL<<30)|(DDR2_PHY_GATELVL<<20) +				|(DDR2_PHY_GATELVL<<10)|(DDR2_PHY_GATELVL<<0)), +	.datafwsratio0 = ((DDR2_PHY_FIFO_WE<<30)|(DDR2_PHY_FIFO_WE<<20) +				|(DDR2_PHY_FIFO_WE<<10)|(DDR2_PHY_FIFO_WE<<0)), +	.datawrsratio0 = ((DDR2_PHY_WR_DATA<<30)|(DDR2_PHY_WR_DATA<<20) +				|(DDR2_PHY_WR_DATA<<10)|(DDR2_PHY_WR_DATA<<0)), +	.datauserank0delay = DDR2_PHY_RANK0_DELAY, +	.datadldiff0 = PHY_DLL_LOCK_DIFF, +}; -	config_ddr_data(dataMacroNum, &data); -} +static const struct cmd_control ddr2_cmd_ctrl_data = { +	.cmd0csratio = DDR2_RATIO, +	.cmd0dldiff = DDR2_DLL_LOCK_DIFF, +	.cmd0iclkout = DDR2_INVERT_CLKOUT, -static void cmd_macro_config(void) -{ -	struct cmd_control cmd; +	.cmd1csratio = DDR2_RATIO, +	.cmd1dldiff = DDR2_DLL_LOCK_DIFF, +	.cmd1iclkout = DDR2_INVERT_CLKOUT, -	cmd.cmd0csratio = DDR2_RATIO; -	cmd.cmd0csforce = CMD_FORCE; -	cmd.cmd0csdelay = CMD_DELAY; -	cmd.cmd0dldiff = DDR2_DLL_LOCK_DIFF; -	cmd.cmd0iclkout = DDR2_INVERT_CLKOUT; +	.cmd2csratio = DDR2_RATIO, +	.cmd2dldiff = DDR2_DLL_LOCK_DIFF, +	.cmd2iclkout = DDR2_INVERT_CLKOUT, +}; -	cmd.cmd1csratio = DDR2_RATIO; -	cmd.cmd1csforce = CMD_FORCE; -	cmd.cmd1csdelay = CMD_DELAY; -	cmd.cmd1dldiff = DDR2_DLL_LOCK_DIFF; -	cmd.cmd1iclkout = DDR2_INVERT_CLKOUT; +static const struct emif_regs ddr2_emif_reg_data = { +	.sdram_config = DDR2_EMIF_SDCFG, +	.ref_ctrl = DDR2_EMIF_SDREF, +	.sdram_tim1 = DDR2_EMIF_TIM1, +	.sdram_tim2 = DDR2_EMIF_TIM2, +	.sdram_tim3 = DDR2_EMIF_TIM3, +	.emif_ddr_phy_ctlr_1 = DDR2_EMIF_READ_LATENCY, +}; -	cmd.cmd2csratio = DDR2_RATIO; -	cmd.cmd2csforce = CMD_FORCE; -	cmd.cmd2csdelay = CMD_DELAY; -	cmd.cmd2dldiff = DDR2_DLL_LOCK_DIFF; -	cmd.cmd2iclkout = DDR2_INVERT_CLKOUT; +static const struct ddr_data ddr3_data = { +	.datardsratio0 = DDR3_RD_DQS, +	.datawdsratio0 = DDR3_WR_DQS, +	.datafwsratio0 = DDR3_PHY_FIFO_WE, +	.datawrsratio0 = DDR3_PHY_WR_DATA, +	.datadldiff0 = PHY_DLL_LOCK_DIFF, +}; -	config_cmd_ctrl(&cmd); +static const struct cmd_control ddr3_cmd_ctrl_data = { +	.cmd0csratio = DDR3_RATIO, +	.cmd0dldiff = DDR3_DLL_LOCK_DIFF, +	.cmd0iclkout = DDR3_INVERT_CLKOUT, -} +	.cmd1csratio = DDR3_RATIO, +	.cmd1dldiff = DDR3_DLL_LOCK_DIFF, +	.cmd1iclkout = DDR3_INVERT_CLKOUT, + +	.cmd2csratio = DDR3_RATIO, +	.cmd2dldiff = DDR3_DLL_LOCK_DIFF, +	.cmd2iclkout = DDR3_INVERT_CLKOUT, +}; + +static struct emif_regs ddr3_emif_reg_data = { +	.sdram_config = DDR3_EMIF_SDCFG, +	.ref_ctrl = DDR3_EMIF_SDREF, +	.sdram_tim1 = DDR3_EMIF_TIM1, +	.sdram_tim2 = DDR3_EMIF_TIM2, +	.sdram_tim3 = DDR3_EMIF_TIM3, +	.zq_config = DDR3_ZQ_CFG, +	.emif_ddr_phy_ctlr_1 = DDR3_EMIF_READ_LATENCY, +};  static void config_vtp(void)  { @@ -115,87 +134,46 @@ static void config_vtp(void)  		;  } -static void config_emif_ddr2(void) +void config_ddr(short ddr_type)  { -	int i; -	int ret; -	struct sdram_config cfg; -	struct sdram_timing tmg; -	struct ddr_phy_control phyc; - -	/*Program EMIF0 CFG Registers*/ -	phyc.reg = EMIF_READ_LATENCY; -	phyc.reg_sh = EMIF_READ_LATENCY; -	phyc.reg2 = EMIF_READ_LATENCY; - -	tmg.time1 = EMIF_TIM1; -	tmg.time1_sh = EMIF_TIM1; -	tmg.time2 = EMIF_TIM2; -	tmg.time2_sh = EMIF_TIM2; -	tmg.time3 = EMIF_TIM3; -	tmg.time3_sh = EMIF_TIM3; - -	cfg.sdrcr = EMIF_SDCFG; -	cfg.sdrcr2 = EMIF_SDCFG; -	cfg.refresh = 0x00004650; -	cfg.refresh_sh = 0x00004650; - -	/* Program EMIF instance */ -	ret = config_ddr_phy(&phyc); -	if (ret < 0) -		printf("Couldn't configure phyc\n"); +	int ddr_pll, ioctrl_val; +	const struct emif_regs *emif_regs; +	const struct ddr_data *ddr_data; +	const struct cmd_control *cmd_ctrl_data; -	ret = config_sdram(&cfg); -	if (ret < 0) -		printf("Couldn't configure SDRAM\n"); - -	ret = set_sdram_timings(&tmg); -	if (ret < 0) -		printf("Couldn't configure timings\n"); - -	/* Delay */ -	for (i = 0; i < 5000; i++) -		; - -	cfg.refresh = EMIF_SDREF; -	cfg.refresh_sh = EMIF_SDREF; -	cfg.sdrcr = EMIF_SDCFG; -	cfg.sdrcr2 = EMIF_SDCFG; - -	ret = config_sdram(&cfg); -	if (ret < 0) -		printf("Couldn't configure SDRAM\n"); -} - -void config_ddr(void) -{ -	int data_macro_0 = 0; -	int data_macro_1 = 1; -	struct ddr_ioctrl ioctrl; +	if (ddr_type == EMIF_REG_SDRAM_TYPE_DDR2) { +		ddr_pll = 266; +		cmd_ctrl_data = &ddr2_cmd_ctrl_data; +		ddr_data = &ddr2_data; +		ioctrl_val = DDR2_IOCTRL_VALUE; +		emif_regs = &ddr2_emif_reg_data; +	} else if (ddr_type == EMIF_REG_SDRAM_TYPE_DDR3) { +		ddr_pll = 303; +		cmd_ctrl_data = &ddr3_cmd_ctrl_data; +		ddr_data = &ddr3_data; +		ioctrl_val = DDR3_IOCTRL_VALUE; +		emif_regs = &ddr3_emif_reg_data; +	} else { +		puts("Unknown memory type"); +		hang(); +	}  	enable_emif_clocks(); - +	ddr_pll_config(ddr_pll);  	config_vtp(); +	config_cmd_ctrl(cmd_ctrl_data); -	cmd_macro_config(); - -	data_macro_config(data_macro_0); -	data_macro_config(data_macro_1); +	config_ddr_data(0, ddr_data); +	config_ddr_data(1, ddr_data); -	writel(PHY_RANK0_DELAY, &ddrregs->dt0rdelays0); -	writel(PHY_RANK0_DELAY, &ddrregs->dt1rdelays0); +	config_io_ctrl(ioctrl_val); -	ioctrl.cmd1ctl = DDR_IOCTRL_VALUE; -	ioctrl.cmd2ctl = DDR_IOCTRL_VALUE; -	ioctrl.cmd3ctl = DDR_IOCTRL_VALUE; -	ioctrl.data1ctl = DDR_IOCTRL_VALUE; -	ioctrl.data2ctl = DDR_IOCTRL_VALUE; +	/* Set CKE to be controlled by EMIF/DDR PHY */ +	writel(DDR_CKE_CTRL_NORMAL, &ddrctrl->ddrckectrl); -	config_io_ctrl(&ioctrl); - -	writel(readl(&ddrctrl->ddrioctrl) & 0xefffffff, &ddrctrl->ddrioctrl); -	writel(readl(&ddrctrl->ddrckectrl) | 0x00000001, &ddrctrl->ddrckectrl); - -	config_emif_ddr2(); +	/* Program EMIF instance */ +	config_ddr_phy(emif_regs); +	set_sdram_timings(emif_regs); +	config_sdram(emif_regs);  }  #endif diff --git a/arch/arm/cpu/armv7/config.mk b/arch/arm/cpu/armv7/config.mk index 560c084dc..5407cb68a 100644 --- a/arch/arm/cpu/armv7/config.mk +++ b/arch/arm/cpu/armv7/config.mk @@ -26,8 +26,6 @@ PLATFORM_RELFLAGS += -fno-common -ffixed-r8 -msoft-float  # supported by more tool-chains  PF_CPPFLAGS_ARMV7 := $(call cc-option, -march=armv7-a, -march=armv5)  PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_ARMV7) -PF_CPPFLAGS_NO_UNALIGNED := $(call cc-option, -mno-unaligned-access,) -PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_NO_UNALIGNED)  # =========================================================================  # diff --git a/arch/arm/cpu/armv7/cpu.c b/arch/arm/cpu/armv7/cpu.c index c6fa8ef13..39a80237c 100644 --- a/arch/arm/cpu/armv7/cpu.c +++ b/arch/arm/cpu/armv7/cpu.c @@ -36,13 +36,9 @@  #include <asm/system.h>  #include <asm/cache.h>  #include <asm/armv7.h> +#include <linux/compiler.h> -void save_boot_params_default(u32 r0, u32 r1, u32 r2, u32 r3) -{ -} - -void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) -	__attribute__((weak, alias("save_boot_params_default"))); +void __weak cpu_cache_initialization(void){}  int cleanup_before_linux(void)  { @@ -81,5 +77,10 @@ int cleanup_before_linux(void)  	 */  	invalidate_dcache_all(); +	/* +	 * Some CPU need more cache attention before starting the kernel. +	 */ +	cpu_cache_initialization(); +  	return 0;  } diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index f7829b2cc..4f3b451be 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -98,7 +98,7 @@ static unsigned long exynos5_get_pll_clk(int pllreg)  	struct exynos5_clock *clk =  		(struct exynos5_clock *)samsung_get_base_clock();  	unsigned long r, m, p, s, k = 0, mask, fout; -	unsigned int freq; +	unsigned int freq, pll_div2_sel, fout_sel;  	switch (pllreg) {  	case APLL: @@ -115,6 +115,9 @@ static unsigned long exynos5_get_pll_clk(int pllreg)  		r = readl(&clk->vpll_con0);  		k = readl(&clk->vpll_con1);  		break; +	case BPLL: +		r = readl(&clk->bpll_con0); +		break;  	default:  		printf("Unsupported PLL (%d)\n", pllreg);  		return 0; @@ -125,8 +128,9 @@ static unsigned long exynos5_get_pll_clk(int pllreg)  	 * MPLL_CON: MIDV [25:16]  	 * EPLL_CON: MIDV [24:16]  	 * VPLL_CON: MIDV [24:16] +	 * BPLL_CON: MIDV [25:16]  	 */ -	if (pllreg == APLL || pllreg == MPLL) +	if (pllreg == APLL || pllreg == MPLL || pllreg == BPLL)  		mask = 0x3ff;  	else  		mask = 0x1ff; @@ -155,6 +159,29 @@ static unsigned long exynos5_get_pll_clk(int pllreg)  		fout = m * (freq / (p * (1 << (s - 1))));  	} +	/* According to the user manual, in EVT1 MPLL and BPLL always gives +	 * 1.6GHz clock, so divide by 2 to get 800MHz MPLL clock.*/ +	if (pllreg == MPLL || pllreg == BPLL) { +		pll_div2_sel = readl(&clk->pll_div2_sel); + +		switch (pllreg) { +		case MPLL: +			fout_sel = (pll_div2_sel >> MPLL_FOUT_SEL_SHIFT) +					& MPLL_FOUT_SEL_MASK; +			break; +		case BPLL: +			fout_sel = (pll_div2_sel >> BPLL_FOUT_SEL_SHIFT) +					& BPLL_FOUT_SEL_MASK; +			break; +		default: +			fout_sel = -1; +			break; +		} + +		if (fout_sel == 0) +			fout /= 2; +	} +  	return fout;  } @@ -456,6 +483,48 @@ static unsigned long exynos4_get_lcd_clk(void)  	return pclk;  } +/* get_lcd_clk: return lcd clock frequency */ +static unsigned long exynos5_get_lcd_clk(void) +{ +	struct exynos5_clock *clk = +		(struct exynos5_clock *)samsung_get_base_clock(); +	unsigned long pclk, sclk; +	unsigned int sel; +	unsigned int ratio; + +	/* +	 * CLK_SRC_LCD0 +	 * FIMD0_SEL [3:0] +	 */ +	sel = readl(&clk->src_disp1_0); +	sel = sel & 0xf; + +	/* +	 * 0x6: SCLK_MPLL +	 * 0x7: SCLK_EPLL +	 * 0x8: SCLK_VPLL +	 */ +	if (sel == 0x6) +		sclk = get_pll_clk(MPLL); +	else if (sel == 0x7) +		sclk = get_pll_clk(EPLL); +	else if (sel == 0x8) +		sclk = get_pll_clk(VPLL); +	else +		return 0; + +	/* +	 * CLK_DIV_LCD0 +	 * FIMD0_RATIO [3:0] +	 */ +	ratio = readl(&clk->div_disp1_0); +	ratio = ratio & 0xf; + +	pclk = sclk / (ratio + 1); + +	return pclk; +} +  void exynos4_set_lcd_clk(void)  {  	struct exynos4_clock *clk = @@ -518,6 +587,68 @@ void exynos4_set_lcd_clk(void)  	writel(cfg, &clk->div_lcd0);  } +void exynos5_set_lcd_clk(void) +{ +	struct exynos5_clock *clk = +	    (struct exynos5_clock *)samsung_get_base_clock(); +	unsigned int cfg = 0; + +	/* +	 * CLK_GATE_BLOCK +	 * CLK_CAM	[0] +	 * CLK_TV	[1] +	 * CLK_MFC	[2] +	 * CLK_G3D	[3] +	 * CLK_LCD0	[4] +	 * CLK_LCD1	[5] +	 * CLK_GPS	[7] +	 */ +	cfg = readl(&clk->gate_block); +	cfg |= 1 << 4; +	writel(cfg, &clk->gate_block); + +	/* +	 * CLK_SRC_LCD0 +	 * FIMD0_SEL		[3:0] +	 * MDNIE0_SEL		[7:4] +	 * MDNIE_PWM0_SEL	[8:11] +	 * MIPI0_SEL		[12:15] +	 * set lcd0 src clock 0x6: SCLK_MPLL +	 */ +	cfg = readl(&clk->src_disp1_0); +	cfg &= ~(0xf); +	cfg |= 0x8; +	writel(cfg, &clk->src_disp1_0); + +	/* +	 * CLK_GATE_IP_LCD0 +	 * CLK_FIMD0		[0] +	 * CLK_MIE0		[1] +	 * CLK_MDNIE0		[2] +	 * CLK_DSIM0		[3] +	 * CLK_SMMUFIMD0	[4] +	 * CLK_PPMULCD0		[5] +	 * Gating all clocks for FIMD0 +	 */ +	cfg = readl(&clk->gate_ip_disp1); +	cfg |= 1 << 0; +	writel(cfg, &clk->gate_ip_disp1); + +	/* +	 * CLK_DIV_LCD0 +	 * FIMD0_RATIO		[3:0] +	 * MDNIE0_RATIO		[7:4] +	 * MDNIE_PWM0_RATIO	[11:8] +	 * MDNIE_PWM_PRE_RATIO	[15:12] +	 * MIPI0_RATIO		[19:16] +	 * MIPI0_PRE_RATIO	[23:20] +	 * set fimd ratio +	 */ +	cfg &= ~(0xf); +	cfg |= 0x0; +	writel(cfg, &clk->div_disp1_0); +} +  void exynos4_set_mipi_clk(void)  {  	struct exynos4_clock *clk = @@ -656,13 +787,15 @@ unsigned long get_lcd_clk(void)  	if (cpu_is_exynos4())  		return exynos4_get_lcd_clk();  	else -		return 0; +		return exynos5_get_lcd_clk();  }  void set_lcd_clk(void)  {  	if (cpu_is_exynos4())  		exynos4_set_lcd_clk(); +	else +		exynos5_set_lcd_clk();  }  void set_mipi_clk(void) diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c index d28f05557..7776add9d 100644 --- a/arch/arm/cpu/armv7/exynos/pinmux.c +++ b/arch/arm/cpu/armv7/exynos/pinmux.c @@ -40,8 +40,8 @@ static void exynos5_uart_config(int peripheral)  		count = 4;  		break;  	case PERIPH_ID_UART1: -		bank = &gpio1->a0; -		start = 4; +		bank = &gpio1->d0; +		start = 0;  		count = 4;  		break;  	case PERIPH_ID_UART2: @@ -66,23 +66,27 @@ static int exynos5_mmc_config(int peripheral, int flags)  	struct exynos5_gpio_part1 *gpio1 =  		(struct exynos5_gpio_part1 *) samsung_get_base_gpio_part1();  	struct s5p_gpio_bank *bank, *bank_ext; -	int i; +	int i, start = 0, gpio_func = 0;  	switch (peripheral) {  	case PERIPH_ID_SDMMC0:  		bank = &gpio1->c0;  		bank_ext = &gpio1->c1; +		start = 0; +		gpio_func = GPIO_FUNC(0x2);  		break;  	case PERIPH_ID_SDMMC1: -		bank = &gpio1->c1; +		bank = &gpio1->c2;  		bank_ext = NULL;  		break;  	case PERIPH_ID_SDMMC2: -		bank = &gpio1->c2; -		bank_ext = &gpio1->c3; +		bank = &gpio1->c3; +		bank_ext = &gpio1->c4; +		start = 3; +		gpio_func = GPIO_FUNC(0x3);  		break;  	case PERIPH_ID_SDMMC3: -		bank = &gpio1->c3; +		bank = &gpio1->c4;  		bank_ext = NULL;  		break;  	} @@ -92,8 +96,8 @@ static int exynos5_mmc_config(int peripheral, int flags)  		return -1;  	}  	if (flags & PINMUX_FLAG_8BIT_MODE) { -		for (i = 3; i <= 6; i++) { -			s5p_gpio_cfg_pin(bank_ext, i, GPIO_FUNC(0x3)); +		for (i = start; i <= (start + 3); i++) { +			s5p_gpio_cfg_pin(bank_ext, i, gpio_func);  			s5p_gpio_set_pull(bank_ext, i, GPIO_PULL_UP);  			s5p_gpio_set_drv(bank_ext, i, GPIO_DRV_4X);  		} diff --git a/arch/arm/cpu/armv7/exynos/power.c b/arch/arm/cpu/armv7/exynos/power.c index 4116781a3..d4bce6d4d 100644 --- a/arch/arm/cpu/armv7/exynos/power.c +++ b/arch/arm/cpu/armv7/exynos/power.c @@ -74,3 +74,24 @@ void set_usbhost_phy_ctrl(unsigned int enable)  	if (cpu_is_exynos5())  		exynos5_set_usbhost_phy_ctrl(enable);  } + +static void exynos5_dp_phy_control(unsigned int enable) +{ +	unsigned int cfg; +	struct exynos5_power *power = +	    (struct exynos5_power *)samsung_get_base_power(); + +	cfg = readl(&power->dptx_phy_control); +	if (enable) +		cfg |= EXYNOS_DP_PHY_ENABLE; +	else +		cfg &= ~EXYNOS_DP_PHY_ENABLE; + +	writel(cfg, &power->dptx_phy_control); +} + +void set_dp_phy_ctrl(unsigned int enable) +{ +	if (cpu_is_exynos5()) +		exynos5_dp_phy_control(enable); +} diff --git a/arch/arm/cpu/armv7/exynos/soc.c b/arch/arm/cpu/armv7/exynos/soc.c index dcfcec22d..ab65b8d3a 100644 --- a/arch/arm/cpu/armv7/exynos/soc.c +++ b/arch/arm/cpu/armv7/exynos/soc.c @@ -28,3 +28,11 @@ void reset_cpu(ulong addr)  {  	writel(0x1, samsung_get_base_swreset());  } + +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ +	/* Enable D-cache. I-cache is already enabled in start.S */ +	dcache_enable(); +} +#endif diff --git a/arch/arm/cpu/armv7/exynos/system.c b/arch/arm/cpu/armv7/exynos/system.c index 4426611d1..8424c57e9 100644 --- a/arch/arm/cpu/armv7/exynos/system.c +++ b/arch/arm/cpu/armv7/exynos/system.c @@ -62,8 +62,26 @@ static void exynos4_set_system_display(void)  	writel(cfg, &sysreg->display_ctrl);  } +static void exynos5_set_system_display(void) +{ +	struct exynos5_sysreg *sysreg = +	    (struct exynos5_sysreg *)samsung_get_base_sysreg(); +	unsigned int cfg = 0; + +	/* +	 * system register path set +	 * 0: MIE/MDNIE +	 * 1: FIMD Bypass +	 */ +	cfg = readl(&sysreg->disp1blk_cfg); +	cfg |= (1 << 15); +	writel(cfg, &sysreg->disp1blk_cfg); +} +  void set_system_display_ctrl(void)  {  	if (cpu_is_exynos4())  		exynos4_set_system_display(); +	else +		exynos5_set_system_display();  } diff --git a/arch/arm/cpu/armv7/highbank/Makefile b/arch/arm/cpu/armv7/highbank/Makefile index 917c3a36b..76faeb0fe 100644 --- a/arch/arm/cpu/armv7/highbank/Makefile +++ b/arch/arm/cpu/armv7/highbank/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk  LIB	= $(obj)lib$(SOC).o -COBJS	:= timer.o bootcount.o +COBJS	:= timer.o  SOBJS	:=  SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/arch/arm/cpu/armv7/highbank/bootcount.c b/arch/arm/cpu/armv7/highbank/bootcount.c deleted file mode 100644 index 9ca06567a..000000000 --- a/arch/arm/cpu/armv7/highbank/bootcount.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2011 Calxeda, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program.  If not, see <http://www.gnu.org/licenses/>. - */ - -#include <common.h> -#include <asm/io.h> - -#ifdef CONFIG_BOOTCOUNT_LIMIT -void bootcount_store(ulong a) -{ -	writel((BOOTCOUNT_MAGIC & 0xffff0000) | a, CONFIG_SYS_BOOTCOUNT_ADDR); -} - -ulong bootcount_load(void) -{ -	u32 tmp = readl(CONFIG_SYS_BOOTCOUNT_ADDR); - -	if ((tmp & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000)) -		return 0; -	else -		return tmp & 0x0000ffff; -} -#endif diff --git a/arch/arm/cpu/armv7/imx-common/cpu.c b/arch/arm/cpu/armv7/imx-common/cpu.c deleted file mode 100644 index b3195dd6f..000000000 --- a/arch/arm/cpu/armv7/imx-common/cpu.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * (C) Copyright 2007 - * Sascha Hauer, Pengutronix - * - * (C) Copyright 2009 Freescale Semiconductor, Inc. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/errno.h> -#include <asm/io.h> -#include <asm/arch/imx-regs.h> -#include <asm/arch/clock.h> -#include <asm/arch/sys_proto.h> -#include <asm/arch/crm_regs.h> - -#ifdef CONFIG_FSL_ESDHC -#include <fsl_esdhc.h> -#endif - -char *get_reset_cause(void) -{ -	u32 cause; -	struct src *src_regs = (struct src *)SRC_BASE_ADDR; - -	cause = readl(&src_regs->srsr); -	writel(cause, &src_regs->srsr); - -	switch (cause) { -	case 0x00001: -	case 0x00011: -		return "POR"; -	case 0x00004: -		return "CSU"; -	case 0x00008: -		return "IPP USER"; -	case 0x00010: -		return "WDOG"; -	case 0x00020: -		return "JTAG HIGH-Z"; -	case 0x00040: -		return "JTAG SW"; -	case 0x10000: -		return "WARM BOOT"; -	default: -		return "unknown reset"; -	} -} - -#if defined(CONFIG_DISPLAY_CPUINFO) - -static char *get_imx_type(u32 imxtype) -{ -	switch (imxtype) { -	case 0x63: -		return "6Q";	/* Quad-core version of the mx6 */ -	case 0x61: -		return "6DS";	/* Dual/Solo version of the mx6 */ -	case 0x60: -		return "6SL";	/* Solo-Lite version of the mx6 */ -	case 0x51: -		return "51"; -	case 0x53: -		return "53"; -	default: -		return "unknown"; -	} -} - -int print_cpuinfo(void) -{ -	u32 cpurev; - -	cpurev = get_cpu_rev(); - -	printf("CPU:   Freescale i.MX%s rev%d.%d at %d MHz\n", -		get_imx_type((cpurev & 0xFF000) >> 12), -		(cpurev & 0x000F0) >> 4, -		(cpurev & 0x0000F) >> 0, -		mxc_get_clock(MXC_ARM_CLK) / 1000000); -	printf("Reset cause: %s\n", get_reset_cause()); -	return 0; -} -#endif - -int cpu_eth_init(bd_t *bis) -{ -	int rc = -ENODEV; - -#if defined(CONFIG_FEC_MXC) -	rc = fecmxc_initialize(bis); -#endif - -	return rc; -} - -/* - * Initializes on-chip MMC controllers. - * to override, implement board_mmc_init() - */ -int cpu_mmc_init(bd_t *bis) -{ -#ifdef CONFIG_FSL_ESDHC -	return fsl_esdhc_mmc_init(bis); -#else -	return 0; -#endif -} - -void reset_cpu(ulong addr) -{ -	__raw_writew(4, WDOG1_BASE_ADDR); -} - -u32 get_ahb_clk(void) -{ -	struct mxc_ccm_reg *imx_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; -	u32 reg, ahb_podf; - -	reg = __raw_readl(&imx_ccm->cbcdr); -	reg &= MXC_CCM_CBCDR_AHB_PODF_MASK; -	ahb_podf = reg >> MXC_CCM_CBCDR_AHB_PODF_OFFSET; - -	return get_periph_clk() / (ahb_podf + 1); -} diff --git a/arch/arm/cpu/armv7/imx-common/i2c.c b/arch/arm/cpu/armv7/imx-common/i2c.c deleted file mode 100644 index da2b26f43..000000000 --- a/arch/arm/cpu/armv7/imx-common/i2c.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2012 Boundary Devices Inc. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ -#include <common.h> -#include <asm/arch/clock.h> -#include <asm/arch/imx-regs.h> -#include <asm/errno.h> -#include <asm/gpio.h> -#include <asm/imx-common/mxc_i2c.h> -#include <watchdog.h> - -static int force_idle_bus(void *priv) -{ -	int i; -	int sda, scl; -	ulong elapsed, start_time; -	struct i2c_pads_info *p = (struct i2c_pads_info *)priv; -	int ret = 0; - -	gpio_direction_input(p->sda.gp); -	gpio_direction_input(p->scl.gp); - -	imx_iomux_v3_setup_pad(p->sda.gpio_mode); -	imx_iomux_v3_setup_pad(p->scl.gpio_mode); - -	sda = gpio_get_value(p->sda.gp); -	scl = gpio_get_value(p->scl.gp); -	if ((sda & scl) == 1) -		goto exit;		/* Bus is idle already */ - -	printf("%s: sda=%d scl=%d sda.gp=0x%x scl.gp=0x%x\n", __func__, -		sda, scl, p->sda.gp, p->scl.gp); -	/* Send high and low on the SCL line */ -	for (i = 0; i < 9; i++) { -		gpio_direction_output(p->scl.gp, 0); -		udelay(50); -		gpio_direction_input(p->scl.gp); -		udelay(50); -	} -	start_time = get_timer(0); -	for (;;) { -		sda = gpio_get_value(p->sda.gp); -		scl = gpio_get_value(p->scl.gp); -		if ((sda & scl) == 1) -			break; -		WATCHDOG_RESET(); -		elapsed = get_timer(start_time); -		if (elapsed > (CONFIG_SYS_HZ / 5)) {	/* .2 seconds */ -			ret = -EBUSY; -			printf("%s: failed to clear bus, sda=%d scl=%d\n", -					__func__, sda, scl); -			break; -		} -	} -exit: -	imx_iomux_v3_setup_pad(p->sda.i2c_mode); -	imx_iomux_v3_setup_pad(p->scl.i2c_mode); -	return ret; -} - -static void * const i2c_bases[] = { -	(void *)I2C1_BASE_ADDR, -	(void *)I2C2_BASE_ADDR, -#ifdef I2C3_BASE_ADDR -	(void *)I2C3_BASE_ADDR, -#endif -}; - -/* i2c_index can be from 0 - 2 */ -void setup_i2c(unsigned i2c_index, int speed, int slave_addr, -		struct i2c_pads_info *p) -{ -	if (i2c_index >= ARRAY_SIZE(i2c_bases)) -		return; -	/* Enable i2c clock */ -	enable_i2c_clk(1, i2c_index); -	/* Make sure bus is idle */ -	force_idle_bus(p); -	bus_i2c_init(i2c_bases[i2c_index], speed, slave_addr, -			force_idle_bus, p); -} diff --git a/arch/arm/cpu/armv7/imx-common/iomux-v3.c b/arch/arm/cpu/armv7/imx-common/iomux-v3.c deleted file mode 100644 index da093fbe1..000000000 --- a/arch/arm/cpu/armv7/imx-common/iomux-v3.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Based on the iomux-v3.c from Linux kernel: - * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de> - * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH, - *                       <armlinux@phytec.de> - * - * Copyright (C) 2004-2011 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ -#include <common.h> -#include <asm/io.h> -#include <asm/arch/imx-regs.h> -#include <asm/imx-common/iomux-v3.h> - -static void *base = (void *)IOMUXC_BASE_ADDR; - -/* - * configures a single pad in the iomuxer - */ -int imx_iomux_v3_setup_pad(iomux_v3_cfg_t pad) -{ -	u32 mux_ctrl_ofs = (pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT; -	u32 mux_mode = (pad & MUX_MODE_MASK) >> MUX_MODE_SHIFT; -	u32 sel_input_ofs = -		(pad & MUX_SEL_INPUT_OFS_MASK) >> MUX_SEL_INPUT_OFS_SHIFT; -	u32 sel_input = -		(pad & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT; -	u32 pad_ctrl_ofs = -		(pad & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT; -	u32 pad_ctrl = (pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT; - -	if (mux_ctrl_ofs) -		__raw_writel(mux_mode, base + mux_ctrl_ofs); - -	if (sel_input_ofs) -		__raw_writel(sel_input, base + sel_input_ofs); - -	if (!(pad_ctrl & NO_PAD_CTRL) && pad_ctrl_ofs) -		__raw_writel(pad_ctrl, base + pad_ctrl_ofs); - -	return 0; -} - -int imx_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t *pad_list, unsigned count) -{ -	iomux_v3_cfg_t *p = pad_list; -	int i; -	int ret; - -	for (i = 0; i < count; i++) { -		ret = imx_iomux_v3_setup_pad(*p); -		if (ret) -			return ret; -		p++; -	} -	return 0; -} diff --git a/arch/arm/cpu/armv7/imx-common/speed.c b/arch/arm/cpu/armv7/imx-common/speed.c deleted file mode 100644 index 80989c498..000000000 --- a/arch/arm/cpu/armv7/imx-common/speed.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * (C) Copyright 2000-2003 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * Copyright (C) 2004-2007 Freescale Semiconductor, Inc. - * TsiChung Liew (Tsi-Chung.Liew@freescale.com) - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/arch/imx-regs.h> -#include <asm/arch/clock.h> - -#ifdef CONFIG_FSL_ESDHC -DECLARE_GLOBAL_DATA_PTR; -#endif - -int get_clocks(void) -{ -#ifdef CONFIG_FSL_ESDHC -#ifdef CONFIG_FSL_USDHC -	gd->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK); -#else -	gd->sdhc_clk = mxc_get_clock(MXC_IPG_PERCLK); -#endif -#endif -	return 0; -} diff --git a/arch/arm/cpu/armv7/imx-common/timer.c b/arch/arm/cpu/armv7/imx-common/timer.c deleted file mode 100644 index 1645ff83f..000000000 --- a/arch/arm/cpu/armv7/imx-common/timer.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * (C) Copyright 2007 - * Sascha Hauer, Pengutronix - * - * (C) Copyright 2009 Freescale Semiconductor, Inc. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/io.h> -#include <div64.h> -#include <asm/arch/imx-regs.h> - -/* General purpose timers registers */ -struct mxc_gpt { -	unsigned int control; -	unsigned int prescaler; -	unsigned int status; -	unsigned int nouse[6]; -	unsigned int counter; -}; - -static struct mxc_gpt *cur_gpt = (struct mxc_gpt *)GPT1_BASE_ADDR; - -/* General purpose timers bitfields */ -#define GPTCR_SWR		(1 << 15)	/* Software reset */ -#define GPTCR_FRR		(1 << 9)	/* Freerun / restart */ -#define GPTCR_CLKSOURCE_32	(4 << 6)	/* Clock source */ -#define GPTCR_TEN		1		/* Timer enable */ -#define CLK_32KHZ		32768		/* 32Khz input */ - -DECLARE_GLOBAL_DATA_PTR; - -#define timestamp (gd->tbl) -#define lastinc (gd->lastinc) - -static inline unsigned long long tick_to_time(unsigned long long tick) -{ -	tick *= CONFIG_SYS_HZ; -	do_div(tick, CLK_32KHZ); - -	return tick; -} - -static inline unsigned long long us_to_tick(unsigned long long usec) -{ -	usec *= CLK_32KHZ; -	do_div(usec, 1000000); - -	return usec; -} - -int timer_init(void) -{ -	int i; -	ulong val; - -	/* setup GP Timer 1 */ -	__raw_writel(GPTCR_SWR, &cur_gpt->control); - -	/* We have no udelay by now */ -	for (i = 0; i < 100; i++) -		__raw_writel(0, &cur_gpt->control); - -	__raw_writel(0, &cur_gpt->prescaler); /* 32Khz */ - -	/* Freerun Mode, PERCLK1 input */ -	i = __raw_readl(&cur_gpt->control); -	__raw_writel(i | GPTCR_CLKSOURCE_32 | GPTCR_TEN, &cur_gpt->control); - -	val = __raw_readl(&cur_gpt->counter); -	lastinc = val / (CLK_32KHZ / CONFIG_SYS_HZ); -	timestamp = 0; - -	return 0; -} - -unsigned long long get_ticks(void) -{ -	ulong now = __raw_readl(&cur_gpt->counter); /* current tick value */ - -	if (now >= lastinc) { -		/* -		 * normal mode (non roll) -		 * move stamp forward with absolut diff ticks -		 */ -		timestamp += (now - lastinc); -	} else { -		/* we have rollover of incrementer */ -		timestamp += (0xFFFFFFFF - lastinc) + now; -	} -	lastinc = now; -	return timestamp; -} - -ulong get_timer_masked(void) -{ -	/* -	 * get_ticks() returns a long long (64 bit), it wraps in -	 * 2^64 / CONFIG_MX25_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~ -	 * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in -	 * 5 * 10^6 days - long enough. -	 */ -	return tick_to_time(get_ticks()); -} - -ulong get_timer(ulong base) -{ -	return get_timer_masked() - base; -} - -/* delay x useconds AND preserve advance timstamp value */ -void __udelay(unsigned long usec) -{ -	unsigned long long tmp; -	ulong tmo; - -	tmo = us_to_tick(usec); -	tmp = get_ticks() + tmo;	/* get current timestamp */ - -	while (get_ticks() < tmp)	/* loop till event */ -		 /*NOP*/; -} - -/* - * This function is derived from PowerPC code (timebase clock frequency). - * On ARM it returns the number of timer ticks per second. - */ -ulong get_tbclk(void) -{ -	return CLK_32KHZ; -} diff --git a/arch/arm/cpu/armv7/tegra2/lowlevel_init.S b/arch/arm/cpu/armv7/lowlevel_init.S index d117f23a6..0d45528e9 100644 --- a/arch/arm/cpu/armv7/tegra2/lowlevel_init.S +++ b/arch/arm/cpu/armv7/lowlevel_init.S @@ -1,8 +1,12 @@  /* - * SoC-specific setup info + * A lowlevel_init function that sets up the stack to call a C function to + * perform further init.   * - * (C) Copyright 2010,2011 - * NVIDIA Corporation <www.nvidia.com> + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Author : + *	Aneesh V	<aneesh@ti.com>   *   * See file CREDITS for list of people who contributed to this   * project. @@ -14,7 +18,7 @@   *   * This program is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License @@ -23,20 +27,25 @@   * MA 02111-1307 USA   */ +#include <asm-offsets.h>  #include <config.h> -#include <version.h>  #include <linux/linkage.h> -	.align	5 -ENTRY(reset_cpu) -	ldr	r1, rstctl			@ get addr for global reset -						@ reg -	ldr	r3, [r1] -	orr	r3, r3, #0x10 -	str	r3, [r1]			@ force reset -	mov	r0, r0 -_loop_forever: -	b	_loop_forever -rstctl: -	.word	PRM_RSTCTRL -ENDPROC(reset_cpu) +ENTRY(lowlevel_init) +	/* +	 * Setup a temporary stack +	 */ +	ldr	sp, =CONFIG_SYS_INIT_SP_ADDR +	bic	sp, sp, #7 /* 8-byte alignment for ABI compliance */ + +	/* +	 * Save the old lr(passed in ip) and the current lr to stack +	 */ +	push	{ip, lr} + +	/* +	 * go setup pll, mux, memory +	 */ +	bl	s_init +	pop	{ip, pc} +ENDPROC(lowlevel_init) diff --git a/arch/arm/cpu/armv7/mx5/lowlevel_init.S b/arch/arm/cpu/armv7/mx5/lowlevel_init.S index 683a7b53a..a40b84fee 100644 --- a/arch/arm/cpu/armv7/mx5/lowlevel_init.S +++ b/arch/arm/cpu/armv7/mx5/lowlevel_init.S @@ -36,9 +36,9 @@  	/* reconfigure L2 cache aux control reg */  	mov r0, #0xC0			/* tag RAM */  	add r0, r0, #0x4		/* data RAM */ -	orr r0, r0, #(1 << 24)		/* disable write allocate delay */ -	orr r0, r0, #(1 << 23)		/* disable write allocate combine */ -	orr r0, r0, #(1 << 22)		/* disable write allocate */ +	orr r0, r0, #1 << 24		/* disable write allocate delay */ +	orr r0, r0, #1 << 23		/* disable write allocate combine */ +	orr r0, r0, #1 << 22		/* disable write allocate */  #if defined(CONFIG_MX51)  	ldr r1, =0x0 @@ -46,7 +46,7 @@  	cmp r3, #0x10  	/* disable write combine for TO 2 and lower revs */ -	orrls r0, r0, #(1 << 25) +	orrls r0, r0, #1 << 25  #endif  	mcr 15, 1, r0, c9, c0, 2 @@ -247,9 +247,9 @@  	movhi r1, #0  #else  	mov r1, #0 -  #endif  	str r1, [r0, #CLKCTL_CACRR] +  	/* Switch ARM back to PLL 1 */  	mov r1, #0  	str r1, [r0, #CLKCTL_CCSR] @@ -288,9 +288,9 @@  	/* Switch peripheral to PLL2 */  	ldr r0, =CCM_BASE_ADDR  	ldr r1, =0x00808145 -	orr r1, r1, #(2 << 10) -	orr r1, r1, #(0 << 16) -	orr r1, r1, #(1 << 19) +	orr r1, r1, #2 << 10 +	orr r1, r1, #0 << 16 +	orr r1, r1, #1 << 19  	str r1, [r0, #CLKCTL_CBCDR]  	ldr r1, =0x00016154 @@ -331,10 +331,10 @@ ENTRY(lowlevel_init)  #if defined(CONFIG_MX51)  	ldr r0, =GPIO1_BASE_ADDR  	ldr r1, [r0, #0x0] -	orr r1, r1, #(1 << 23) +	orr r1, r1, #1 << 23  	str r1, [r0, #0x0]  	ldr r1, [r0, #0x4] -	orr r1, r1, #(1 << 23) +	orr r1, r1, #1 << 23  	str r1, [r0, #0x4]  #endif @@ -351,16 +351,16 @@ ENTRY(lowlevel_init)  ENDPROC(lowlevel_init)  /* Board level setting value */ -W_DP_OP_864:              .word DP_OP_864 -W_DP_MFD_864:             .word DP_MFD_864 -W_DP_MFN_864:             .word DP_MFN_864 -W_DP_MFN_800_DIT:         .word DP_MFN_800_DIT -W_DP_OP_800:              .word DP_OP_800 -W_DP_MFD_800:             .word DP_MFD_800 -W_DP_MFN_800:             .word DP_MFN_800 -W_DP_OP_665:              .word DP_OP_665 -W_DP_MFD_665:             .word DP_MFD_665 -W_DP_MFN_665:             .word DP_MFN_665 -W_DP_OP_216:              .word DP_OP_216 -W_DP_MFD_216:             .word DP_MFD_216 -W_DP_MFN_216:             .word DP_MFN_216 +W_DP_OP_864:		.word DP_OP_864 +W_DP_MFD_864:		.word DP_MFD_864 +W_DP_MFN_864:		.word DP_MFN_864 +W_DP_MFN_800_DIT:	.word DP_MFN_800_DIT +W_DP_OP_800:		.word DP_OP_800 +W_DP_MFD_800:		.word DP_MFD_800 +W_DP_MFN_800:		.word DP_MFN_800 +W_DP_OP_665:		.word DP_OP_665 +W_DP_MFD_665:		.word DP_MFD_665 +W_DP_MFN_665:		.word DP_MFN_665 +W_DP_OP_216:		.word DP_OP_216 +W_DP_MFD_216:		.word DP_MFD_216 +W_DP_MFN_216:		.word DP_MFN_216 diff --git a/arch/arm/cpu/armv7/mx5/soc.c b/arch/arm/cpu/armv7/mx5/soc.c index 3f5a4f726..263658aa4 100644 --- a/arch/arm/cpu/armv7/mx5/soc.c +++ b/arch/arm/cpu/armv7/mx5/soc.c @@ -30,6 +30,7 @@  #include <asm/errno.h>  #include <asm/io.h> +#include <asm/imx-common/boot_mode.h>  #if !(defined(CONFIG_MX51) || defined(CONFIG_MX53))  #error "CPU_TYPE not defined" @@ -71,6 +72,14 @@ u32 get_cpu_rev(void)  	return system_rev;  } +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ +	/* Enable D-cache. I-cache is already enabled in start.S */ +	dcache_enable(); +} +#endif +  #if defined(CONFIG_FEC_MXC)  void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)  { @@ -115,3 +124,33 @@ void set_chipselect_size(int const cs_size)  	writel(reg, &iomuxc_regs->gpr1);  } + +#ifdef CONFIG_MX53 +void boot_mode_apply(unsigned cfg_val) +{ +	writel(cfg_val, &((struct srtc_regs *)SRTC_BASE_ADDR)->lpgr); +} +/* + * cfg_val will be used for + * Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0] + * + * If bit 28 of LPGR is set upon watchdog reset, + * bits[25:0] of LPGR will move to SBMR. + */ +const struct boot_mode soc_boot_modes[] = { +	{"normal",	MAKE_CFGVAL(0x00, 0x00, 0x00, 0x00)}, +	/* usb or serial download */ +	{"usb",		MAKE_CFGVAL(0x00, 0x00, 0x00, 0x13)}, +	{"sata",	MAKE_CFGVAL(0x28, 0x00, 0x00, 0x12)}, +	{"escpi1:0",	MAKE_CFGVAL(0x38, 0x20, 0x00, 0x12)}, +	{"escpi1:1",	MAKE_CFGVAL(0x38, 0x20, 0x04, 0x12)}, +	{"escpi1:2",	MAKE_CFGVAL(0x38, 0x20, 0x08, 0x12)}, +	{"escpi1:3",	MAKE_CFGVAL(0x38, 0x20, 0x0c, 0x12)}, +	/* 4 bit bus width */ +	{"esdhc1",	MAKE_CFGVAL(0x40, 0x20, 0x00, 0x12)}, +	{"esdhc2",	MAKE_CFGVAL(0x40, 0x20, 0x08, 0x12)}, +	{"esdhc3",	MAKE_CFGVAL(0x40, 0x20, 0x10, 0x12)}, +	{"esdhc4",	MAKE_CFGVAL(0x40, 0x20, 0x18, 0x12)}, +	{NULL,		0}, +}; +#endif diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c index 84b458c7e..7380ffe46 100644 --- a/arch/arm/cpu/armv7/mx6/soc.c +++ b/arch/arm/cpu/armv7/mx6/soc.c @@ -29,6 +29,7 @@  #include <asm/arch/imx-regs.h>  #include <asm/arch/clock.h>  #include <asm/arch/sys_proto.h> +#include <asm/imx-common/boot_mode.h>  u32 get_cpu_rev(void)  { @@ -141,3 +142,38 @@ void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)  }  #endif + +void boot_mode_apply(unsigned cfg_val) +{ +	unsigned reg; +	struct src_regs *psrc = (struct src_regs *)SRC_BASE_ADDR; +	writel(cfg_val, &psrc->gpr9); +	reg = readl(&psrc->gpr10); +	if (cfg_val) +		reg |= 1 << 28; +	else +		reg &= ~(1 << 28); +	writel(reg, &psrc->gpr10); +} +/* + * cfg_val will be used for + * Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0] + * After reset, if GPR10[28] is 1, ROM will copy GPR9[25:0] + * to SBMR1, which will determine the boot device. + */ +const struct boot_mode soc_boot_modes[] = { +	{"normal",	MAKE_CFGVAL(0x00, 0x00, 0x00, 0x00)}, +	/* reserved value should start rom usb */ +	{"usb",		MAKE_CFGVAL(0x01, 0x00, 0x00, 0x00)}, +	{"sata",	MAKE_CFGVAL(0x20, 0x00, 0x00, 0x00)}, +	{"escpi1:0",	MAKE_CFGVAL(0x30, 0x00, 0x00, 0x08)}, +	{"escpi1:1",	MAKE_CFGVAL(0x30, 0x00, 0x00, 0x18)}, +	{"escpi1:2",	MAKE_CFGVAL(0x30, 0x00, 0x00, 0x28)}, +	{"escpi1:3",	MAKE_CFGVAL(0x30, 0x00, 0x00, 0x38)}, +	/* 4 bit bus width */ +	{"esdhc1",	MAKE_CFGVAL(0x40, 0x20, 0x00, 0x00)}, +	{"esdhc2",	MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)}, +	{"esdhc3",	MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)}, +	{"esdhc4",	MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)}, +	{NULL,		0}, +}; diff --git a/arch/arm/cpu/armv7/omap-common/Makefile b/arch/arm/cpu/armv7/omap-common/Makefile index 2a6625f1c..d37b22d98 100644 --- a/arch/arm/cpu/armv7/omap-common/Makefile +++ b/arch/arm/cpu/armv7/omap-common/Makefile @@ -29,9 +29,6 @@ SOBJS	:= reset.o  COBJS	:= timer.o  COBJS	+= utils.o -ifdef CONFIG_OMAP -COBJS	+= gpio.o -endif  ifneq ($(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),)  COBJS	+= hwinit-common.o diff --git a/arch/arm/cpu/armv7/omap-common/gpio.c b/arch/arm/cpu/armv7/omap-common/gpio.c deleted file mode 100644 index fc89f2a42..000000000 --- a/arch/arm/cpu/armv7/omap-common/gpio.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2009 Wind River Systems, Inc. - * Tom Rix <Tom.Rix@windriver.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * This work is derived from the linux 2.6.27 kernel source - * To fetch, use the kernel repository - * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git - * Use the v2.6.27 tag. - * - * Below is the original's header including its copyright - * - *  linux/arch/arm/plat-omap/gpio.c - * - * Support functions for OMAP GPIO - * - * Copyright (C) 2003-2005 Nokia Corporation - * Written by Juha Yrjölä <juha.yrjola@nokia.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <common.h> -#include <asm/gpio.h> -#include <asm/io.h> -#include <asm/errno.h> - -#define OMAP_GPIO_DIR_OUT	0 -#define OMAP_GPIO_DIR_IN	1 - -static inline const struct gpio_bank *get_gpio_bank(int gpio) -{ -	return &omap_gpio_bank[gpio >> 5]; -} - -static inline int get_gpio_index(int gpio) -{ -	return gpio & 0x1f; -} - -static inline int gpio_valid(int gpio) -{ -	if (gpio < 0) -		return -1; -	if (gpio < 192) -		return 0; -	return -1; -} - -static int check_gpio(int gpio) -{ -	if (gpio_valid(gpio) < 0) { -		printf("ERROR : check_gpio: invalid GPIO %d\n", gpio); -		return -1; -	} -	return 0; -} - -static void _set_gpio_direction(const struct gpio_bank *bank, int gpio, -				int is_input) -{ -	void *reg = bank->base; -	u32 l; - -	switch (bank->method) { -	case METHOD_GPIO_24XX: -		reg += OMAP_GPIO_OE; -		break; -	default: -		return; -	} -	l = __raw_readl(reg); -	if (is_input) -		l |= 1 << gpio; -	else -		l &= ~(1 << gpio); -	__raw_writel(l, reg); -} - -/** - * Get the direction of the GPIO by reading the GPIO_OE register - * corresponding to the specified bank. - */ -static int _get_gpio_direction(const struct gpio_bank *bank, int gpio) -{ -	void *reg = bank->base; -	u32 v; - -	switch (bank->method) { -	case METHOD_GPIO_24XX: -		reg += OMAP_GPIO_OE; -		break; -	default: -		return -1; -	} - -	v = __raw_readl(reg); - -	if (v & (1 << gpio)) -		return OMAP_GPIO_DIR_IN; -	else -		return OMAP_GPIO_DIR_OUT; -} - -static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio, -				int enable) -{ -	void *reg = bank->base; -	u32 l = 0; - -	switch (bank->method) { -	case METHOD_GPIO_24XX: -		if (enable) -			reg += OMAP_GPIO_SETDATAOUT; -		else -			reg += OMAP_GPIO_CLEARDATAOUT; -		l = 1 << gpio; -		break; -	default: -		printf("omap3-gpio unknown bank method %s %d\n", -		       __FILE__, __LINE__); -		return; -	} -	__raw_writel(l, reg); -} - -/** - * Set value of the specified gpio - */ -int gpio_set_value(unsigned gpio, int value) -{ -	const struct gpio_bank *bank; - -	if (check_gpio(gpio) < 0) -		return -1; -	bank = get_gpio_bank(gpio); -	_set_gpio_dataout(bank, get_gpio_index(gpio), value); - -	return 0; -} - -/** - * Get value of the specified gpio - */ -int gpio_get_value(unsigned gpio) -{ -	const struct gpio_bank *bank; -	void *reg; -	int input; - -	if (check_gpio(gpio) < 0) -		return -1; -	bank = get_gpio_bank(gpio); -	reg = bank->base; -	switch (bank->method) { -	case METHOD_GPIO_24XX: -		input = _get_gpio_direction(bank, get_gpio_index(gpio)); -		switch (input) { -		case OMAP_GPIO_DIR_IN: -			reg += OMAP_GPIO_DATAIN; -			break; -		case OMAP_GPIO_DIR_OUT: -			reg += OMAP_GPIO_DATAOUT; -			break; -		default: -			return -1; -		} -		break; -	default: -		return -1; -	} -	return (__raw_readl(reg) -			& (1 << get_gpio_index(gpio))) != 0; -} - -/** - * Set gpio direction as input - */ -int gpio_direction_input(unsigned gpio) -{ -	const struct gpio_bank *bank; - -	if (check_gpio(gpio) < 0) -		return -1; - -	bank = get_gpio_bank(gpio); -	_set_gpio_direction(bank, get_gpio_index(gpio), 1); - -	return 0; -} - -/** - * Set gpio direction as output - */ -int gpio_direction_output(unsigned gpio, int value) -{ -	const struct gpio_bank *bank; - -	if (check_gpio(gpio) < 0) -		return -1; - -	bank = get_gpio_bank(gpio); -	_set_gpio_dataout(bank, get_gpio_index(gpio), value); -	_set_gpio_direction(bank, get_gpio_index(gpio), 0); - -	return 0; -} - -/** - * Request a gpio before using it. - * - * NOTE: Argument 'label' is unused. - */ -int gpio_request(unsigned gpio, const char *label) -{ -	if (check_gpio(gpio) < 0) -		return -1; - -	return 0; -} - -/** - * Reset and free the gpio after using it. - */ -int gpio_free(unsigned gpio) -{ -	return 0; -} diff --git a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S index ccc6bb6b8..1ece07363 100644 --- a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S +++ b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S @@ -78,24 +78,6 @@ ENTRY(save_boot_params)  	bx	lr  ENDPROC(save_boot_params) -ENTRY(lowlevel_init) -	/* -	 * Setup a temporary stack -	 */ -	ldr	sp, =LOW_LEVEL_SRAM_STACK - -	/* -	 * Save the old lr(passed in ip) and the current lr to stack -	 */ -	push	{ip, lr} - -	/* -	 * go setup pll, mux, memory -	 */ -	bl	s_init -	pop	{ip, pc} -ENDPROC(lowlevel_init) -  ENTRY(set_pl310_ctrl_reg)  	PUSH	{r4-r11, lr}	@ save registers - ROM code may pollute  				@ our registers diff --git a/arch/arm/cpu/armv7/s5p-common/pwm.c b/arch/arm/cpu/armv7/s5p-common/pwm.c index 58d279e00..44d7bc360 100644 --- a/arch/arm/cpu/armv7/s5p-common/pwm.c +++ b/arch/arm/cpu/armv7/s5p-common/pwm.c @@ -170,7 +170,7 @@ int pwm_init(int pwm_id, int div, int invert)  	timer_rate_hz = get_pwm_clk() / ((prescaler + 1) *  			(div + 1)); -	timer_rate_hz = timer_rate_hz / 100; +	timer_rate_hz = timer_rate_hz / CONFIG_SYS_HZ;  	/* set count value */  	offset = pwm_id * 3; diff --git a/arch/arm/cpu/armv7/s5p-common/timer.c b/arch/arm/cpu/armv7/s5p-common/timer.c index 359c21f5e..bb0e795e6 100644 --- a/arch/arm/cpu/armv7/s5p-common/timer.c +++ b/arch/arm/cpu/armv7/s5p-common/timer.c @@ -31,6 +31,8 @@  DECLARE_GLOBAL_DATA_PTR; +unsigned long get_current_tick(void); +  /* macro to read the 16 bit timer */  static inline struct s5p_timer *s5p_get_base_timer(void)  { @@ -44,6 +46,8 @@ int timer_init(void)  	pwm_config(4, 0, 0);  	pwm_enable(4); +	reset_timer_masked(); +  	return 0;  } @@ -72,16 +76,16 @@ void __udelay(unsigned long usec)  		 * 3. finish normalize.  		 */  		tmo = usec / 1000; -		tmo *= (CONFIG_SYS_HZ * count_value / 10); +		tmo *= (CONFIG_SYS_HZ * count_value);  		tmo /= 1000;  	} else {  		/* else small number, don't kill it prior to HZ multiply */ -		tmo = usec * CONFIG_SYS_HZ * count_value / 10; +		tmo = usec * CONFIG_SYS_HZ * count_value;  		tmo /= (1000 * 1000);  	}  	/* get current timestamp */ -	tmp = get_timer(0); +	tmp = get_current_tick();  	/* if setting this fordward will roll time stamp */  	/* reset "advancing" timestamp to 0, set lastinc value */ @@ -92,7 +96,7 @@ void __udelay(unsigned long usec)  		tmo += tmp;  	/* loop till event */ -	while (get_timer_masked() < tmo) +	while (get_current_tick() < tmo)  		;	/* nop */  } @@ -108,6 +112,14 @@ void reset_timer_masked(void)  unsigned long get_timer_masked(void)  {  	struct s5p_timer *const timer = s5p_get_base_timer(); +	unsigned long count_value = readl(&timer->tcntb4); + +	return get_current_tick() / count_value; +} + +unsigned long get_current_tick(void) +{ +	struct s5p_timer *const timer = s5p_get_base_timer();  	unsigned long now = readl(&timer->tcnto4);  	unsigned long count_value = readl(&timer->tcntb4); diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S index aee27fdc4..32658eb7a 100644 --- a/arch/arm/cpu/armv7/start.S +++ b/arch/arm/cpu/armv7/start.S @@ -133,7 +133,6 @@ reset:  	orr	r0, r0, #0xd3  	msr	cpsr,r0 -#if !defined(CONFIG_TEGRA2)  /*   * Setup vector:   * (OMAP4 spl TEXT_BASE is not 32 byte aligned. @@ -149,7 +148,6 @@ reset:  	ldr	r0, =_start  	mcr	p15, 0, r0, c12, c0, 0	@Set VBAR  #endif -#endif	/* !Tegra2 */  	/* the mask ROM code should have PLL and others stable */  #ifndef CONFIG_SKIP_LOWLEVEL_INIT @@ -282,14 +280,14 @@ jump_2_ram:  /*   * Move vector table   */ -#if !defined(CONFIG_TEGRA2) +#if !defined(CONFIG_TEGRA20)  #if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))  	/* Set vector address in CP15 VBAR register */  	ldr     r0, =_start  	add     r0, r0, r9  	mcr     p15, 0, r0, c12, c0, 0  @Set VBAR  #endif -#endif /* !Tegra2 */ +#endif /* !Tegra20 */  	ldr	r0, _board_init_r_ofs  	adr	r1, _start @@ -307,6 +305,20 @@ ENDPROC(relocate_code)  /*************************************************************************   * + * void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) + *	__attribute__((weak)); + * + * Stack pointer is not yet initialized at this moment + * Don't save anything to stack even if compiled with -O0 + * + *************************************************************************/ +ENTRY(save_boot_params) +	bx	lr			@ back to my caller +ENDPROC(save_boot_params) +	.weak	save_boot_params + +/************************************************************************* + *   * cpu_init_cp15   *   * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless diff --git a/arch/arm/cpu/armv7/tegra2/Makefile b/arch/arm/cpu/armv7/tegra2/Makefile deleted file mode 100644 index 80da4536d..000000000 --- a/arch/arm/cpu/armv7/tegra2/Makefile +++ /dev/null @@ -1,60 +0,0 @@ -# -# (C) Copyright 2010,2011 Nvidia Corporation. -# -# (C) Copyright 2000-2003 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. -# -# See file CREDITS for list of people who contributed to this -# project. -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, -# MA 02111-1307 USA -# - -# The AVP is ARMv4T architecture so we must use special compiler -# flags for any startup files it might use. -CFLAGS_arch/arm/cpu/armv7/tegra2/ap20.o += -march=armv4t -CFLAGS_arch/arm/cpu/armv7/tegra2/clock.o += -march=armv4t -CFLAGS_arch/arm/cpu/armv7/tegra2/warmboot_avp.o += -march=armv4t - -include $(TOPDIR)/config.mk - -LIB	=  $(obj)lib$(SOC).o - -SOBJS	:= lowlevel_init.o -COBJS-y	:= ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o timer.o -COBJS-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o -COBJS-$(CONFIG_TEGRA_PMU) += pmu.o -COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o -COBJS-$(CONFIG_TEGRA2_LP0) += crypto.o warmboot.o warmboot_avp.o -COBJS-$(CONFIG_CMD_ENTERRCM) += cmd_enterrcm.o - -COBJS	:= $(COBJS-y) -SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS)) - -all:	 $(obj).depend $(LIB) - -$(LIB):	$(OBJS) -	$(call cmd_link_o_target, $(OBJS)) - -######################################################################### - -# defines $(obj).depend target -include $(SRCTREE)/rules.mk - -sinclude $(obj).depend - -######################################################################### diff --git a/arch/arm/cpu/armv7/tegra2/ap20.c b/arch/arm/cpu/armv7/tegra2/ap20.c deleted file mode 100644 index 1aad3879e..000000000 --- a/arch/arm/cpu/armv7/tegra2/ap20.c +++ /dev/null @@ -1,388 +0,0 @@ -/* -* (C) Copyright 2010-2011 -* NVIDIA Corporation <www.nvidia.com> -* -* See file CREDITS for list of people who contributed to this -* project. -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License as -* published by the Free Software Foundation; either version 2 of -* the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, -* MA 02111-1307 USA -*/ - -#include <asm/io.h> -#include <asm/arch/tegra2.h> -#include <asm/arch/ap20.h> -#include <asm/arch/clk_rst.h> -#include <asm/arch/clock.h> -#include <asm/arch/fuse.h> -#include <asm/arch/gp_padctrl.h> -#include <asm/arch/pmc.h> -#include <asm/arch/pinmux.h> -#include <asm/arch/scu.h> -#include <asm/arch/warmboot.h> -#include <common.h> - -int tegra_get_chip_type(void) -{ -	struct apb_misc_gp_ctlr *gp; -	struct fuse_regs *fuse = (struct fuse_regs *)TEGRA2_FUSE_BASE; -	uint tegra_sku_id, rev; - -	/* -	 * This is undocumented, Chip ID is bits 15:8 of the register -	 * APB_MISC + 0x804, and has value 0x20 for Tegra20, 0x30 for -	 * Tegra30 -	 */ -	gp = (struct apb_misc_gp_ctlr *)TEGRA2_APB_MISC_GP_BASE; -	rev = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT; - -	tegra_sku_id = readl(&fuse->sku_info) & 0xff; - -	switch (rev) { -	case CHIPID_TEGRA2: -		switch (tegra_sku_id) { -		case SKU_ID_T20: -			return TEGRA_SOC_T20; -		case SKU_ID_T25SE: -		case SKU_ID_AP25: -		case SKU_ID_T25: -		case SKU_ID_AP25E: -		case SKU_ID_T25E: -			return TEGRA_SOC_T25; -		} -		break; -	} -	/* unknown sku id */ -	return TEGRA_SOC_UNKNOWN; -} - -/* Returns 1 if the current CPU executing is a Cortex-A9, else 0 */ -static int ap20_cpu_is_cortexa9(void) -{ -	u32 id = readb(NV_PA_PG_UP_BASE + PG_UP_TAG_0); -	return id == (PG_UP_TAG_0_PID_CPU & 0xff); -} - -void init_pllx(void) -{ -	struct clk_rst_ctlr *clkrst = -			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; -	struct clk_pll_simple *pll = -		&clkrst->crc_pll_simple[CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE]; -	u32 reg; - -	/* If PLLX is already enabled, just return */ -	if (readl(&pll->pll_base) & PLL_ENABLE_MASK) -		return; - -	/* Set PLLX_MISC */ -	writel(1 << PLL_CPCON_SHIFT, &pll->pll_misc); - -	/* Use 12MHz clock here */ -	reg = PLL_BYPASS_MASK | (12 << PLL_DIVM_SHIFT); -	reg |= 1000 << PLL_DIVN_SHIFT; -	writel(reg, &pll->pll_base); - -	reg |= PLL_ENABLE_MASK; -	writel(reg, &pll->pll_base); - -	reg &= ~PLL_BYPASS_MASK; -	writel(reg, &pll->pll_base); -} - -static void enable_cpu_clock(int enable) -{ -	struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; -	u32 clk; - -	/* -	 * NOTE: -	 * Regardless of whether the request is to enable or disable the CPU -	 * clock, every processor in the CPU complex except the master (CPU 0) -	 * will have it's clock stopped because the AVP only talks to the -	 * master. The AVP does not know (nor does it need to know) that there -	 * are multiple processors in the CPU complex. -	 */ - -	if (enable) { -		/* Initialize PLLX */ -		init_pllx(); - -		/* Wait until all clocks are stable */ -		udelay(PLL_STABILIZATION_DELAY); - -		writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol); -		writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div); -	} - -	/* -	 * Read the register containing the individual CPU clock enables and -	 * always stop the clock to CPU 1. -	 */ -	clk = readl(&clkrst->crc_clk_cpu_cmplx); -	clk |= 1 << CPU1_CLK_STP_SHIFT; - -	/* Stop/Unstop the CPU clock */ -	clk &= ~CPU0_CLK_STP_MASK; -	clk |= !enable << CPU0_CLK_STP_SHIFT; -	writel(clk, &clkrst->crc_clk_cpu_cmplx); - -	clock_enable(PERIPH_ID_CPU); -} - -static int is_cpu_powered(void) -{ -	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; - -	return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0; -} - -static void remove_cpu_io_clamps(void) -{ -	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; -	u32 reg; - -	/* Remove the clamps on the CPU I/O signals */ -	reg = readl(&pmc->pmc_remove_clamping); -	reg |= CPU_CLMP; -	writel(reg, &pmc->pmc_remove_clamping); - -	/* Give I/O signals time to stabilize */ -	udelay(IO_STABILIZATION_DELAY); -} - -static void powerup_cpu(void) -{ -	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; -	u32 reg; -	int timeout = IO_STABILIZATION_DELAY; - -	if (!is_cpu_powered()) { -		/* Toggle the CPU power state (OFF -> ON) */ -		reg = readl(&pmc->pmc_pwrgate_toggle); -		reg &= PARTID_CP; -		reg |= START_CP; -		writel(reg, &pmc->pmc_pwrgate_toggle); - -		/* Wait for the power to come up */ -		while (!is_cpu_powered()) { -			if (timeout-- == 0) -				printf("CPU failed to power up!\n"); -			else -				udelay(10); -		} - -		/* -		 * Remove the I/O clamps from CPU power partition. -		 * Recommended only on a Warm boot, if the CPU partition gets -		 * power gated. Shouldn't cause any harm when called after a -		 * cold boot according to HW, probably just redundant. -		 */ -		remove_cpu_io_clamps(); -	} -} - -static void enable_cpu_power_rail(void) -{ -	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; -	u32 reg; - -	reg = readl(&pmc->pmc_cntrl); -	reg |= CPUPWRREQ_OE; -	writel(reg, &pmc->pmc_cntrl); - -	/* -	 * The TI PMU65861C needs a 3.75ms delay between enabling -	 * the power rail and enabling the CPU clock.  This delay -	 * between SM1EN and SM1 is for switching time + the ramp -	 * up of the voltage to the CPU (VDD_CPU from PMU). -	 */ -	udelay(3750); -} - -static void reset_A9_cpu(int reset) -{ -	/* -	* NOTE:  Regardless of whether the request is to hold the CPU in reset -	*        or take it out of reset, every processor in the CPU complex -	*        except the master (CPU 0) will be held in reset because the -	*        AVP only talks to the master. The AVP does not know that there -	*        are multiple processors in the CPU complex. -	*/ - -	/* Hold CPU 1 in reset, and CPU 0 if asked */ -	reset_cmplx_set_enable(1, crc_rst_cpu | crc_rst_de | crc_rst_debug, 1); -	reset_cmplx_set_enable(0, crc_rst_cpu | crc_rst_de | crc_rst_debug, -			       reset); - -	/* Enable/Disable master CPU reset */ -	reset_set_enable(PERIPH_ID_CPU, reset); -} - -static void clock_enable_coresight(int enable) -{ -	u32 rst, src; - -	clock_set_enable(PERIPH_ID_CORESIGHT, enable); -	reset_set_enable(PERIPH_ID_CORESIGHT, !enable); - -	if (enable) { -		/* -		 * Put CoreSight on PLLP_OUT0 (216 MHz) and divide it down by -		 *  1.5, giving an effective frequency of 144MHz. -		 * Set PLLP_OUT0 [bits31:30 = 00], and use a 7.1 divisor -		 *  (bits 7:0), so 00000001b == 1.5 (n+1 + .5) -		 */ -		src = CLK_DIVIDER(NVBL_PLLP_KHZ, 144000); -		clock_ll_set_source_divisor(PERIPH_ID_CSI, 0, src); - -		/* Unlock the CPU CoreSight interfaces */ -		rst = 0xC5ACCE55; -		writel(rst, CSITE_CPU_DBG0_LAR); -		writel(rst, CSITE_CPU_DBG1_LAR); -	} -} - -void start_cpu(u32 reset_vector) -{ -	/* Enable VDD_CPU */ -	enable_cpu_power_rail(); - -	/* Hold the CPUs in reset */ -	reset_A9_cpu(1); - -	/* Disable the CPU clock */ -	enable_cpu_clock(0); - -	/* Enable CoreSight */ -	clock_enable_coresight(1); - -	/* -	 * Set the entry point for CPU execution from reset, -	 *  if it's a non-zero value. -	 */ -	if (reset_vector) -		writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR); - -	/* Enable the CPU clock */ -	enable_cpu_clock(1); - -	/* If the CPU doesn't already have power, power it up */ -	powerup_cpu(); - -	/* Take the CPU out of reset */ -	reset_A9_cpu(0); -} - - -void halt_avp(void) -{ -	for (;;) { -		writel((HALT_COP_EVENT_JTAG | HALT_COP_EVENT_IRQ_1 \ -			| HALT_COP_EVENT_FIQ_1 | (FLOW_MODE_STOP<<29)), -			FLOW_CTLR_HALT_COP_EVENTS); -	} -} - -void enable_scu(void) -{ -	struct scu_ctlr *scu = (struct scu_ctlr *)NV_PA_ARM_PERIPHBASE; -	u32 reg; - -	/* If SCU already setup/enabled, return */ -	if (readl(&scu->scu_ctrl) & SCU_CTRL_ENABLE) -		return; - -	/* Invalidate all ways for all processors */ -	writel(0xFFFF, &scu->scu_inv_all); - -	/* Enable SCU - bit 0 */ -	reg = readl(&scu->scu_ctrl); -	reg |= SCU_CTRL_ENABLE; -	writel(reg, &scu->scu_ctrl); -} - -static u32 get_odmdata(void) -{ -	/* -	 * ODMDATA is stored in the BCT in IRAM by the BootROM. -	 * The BCT start and size are stored in the BIT in IRAM. -	 * Read the data @ bct_start + (bct_size - 12). This works -	 * on T20 and T30 BCTs, which are locked down. If this changes -	 * in new chips (T114, etc.), we can revisit this algorithm. -	 */ - -	u32 bct_start, odmdata; - -	bct_start = readl(AP20_BASE_PA_SRAM + NVBOOTINFOTABLE_BCTPTR); -	odmdata = readl(bct_start + BCT_ODMDATA_OFFSET); - -	return odmdata; -} - -void init_pmc_scratch(void) -{ -	struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; -	u32 odmdata; -	int i; - -	/* SCRATCH0 is initialized by the boot ROM and shouldn't be cleared */ -	for (i = 0; i < 23; i++) -		writel(0, &pmc->pmc_scratch1+i); - -	/* ODMDATA is for kernel use to determine RAM size, LP config, etc. */ -	odmdata = get_odmdata(); -	writel(odmdata, &pmc->pmc_scratch20); - -#ifdef CONFIG_TEGRA2_LP0 -	/* save Sdram params to PMC 2, 4, and 24 for WB0 */ -	warmboot_save_sdram_params(); -#endif -} - -void tegra2_start(void) -{ -	struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; - -	/* If we are the AVP, start up the first Cortex-A9 */ -	if (!ap20_cpu_is_cortexa9()) { -		/* enable JTAG */ -		writel(0xC0, &pmt->pmt_cfg_ctl); - -		/* -		 * If we are ARM7 - give it a different stack. We are about to -		 * start up the A9 which will want to use this one. -		 */ -		asm volatile("mov	sp, %0\n" -			: : "r"(AVP_EARLY_BOOT_STACK_LIMIT)); - -		start_cpu((u32)_start); -		halt_avp(); -		/* not reached */ -	} - -	/* Init PMC scratch memory */ -	init_pmc_scratch(); - -	enable_scu(); - -	/* enable SMP mode and FW for CPU0, by writing to Auxiliary Ctl reg */ -	asm volatile( -		"mrc	p15, 0, r0, c1, c0, 1\n" -		"orr	r0, r0, #0x41\n" -		"mcr	p15, 0, r0, c1, c0, 1\n"); - -	/* FIXME: should have ap20's L2 disabled too? */ -} diff --git a/arch/arm/cpu/armv7/tegra2/board.c b/arch/arm/cpu/armv7/tegra2/board.c deleted file mode 100644 index 923678d06..000000000 --- a/arch/arm/cpu/armv7/tegra2/board.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - *  (C) Copyright 2010,2011 - *  NVIDIA Corporation <www.nvidia.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/io.h> -#include <asm/arch/ap20.h> -#include <asm/arch/clock.h> -#include <asm/arch/funcmux.h> -#include <asm/arch/pmc.h> -#include <asm/arch/sys_proto.h> -#include <asm/arch/tegra2.h> - -DECLARE_GLOBAL_DATA_PTR; - -enum { -	/* UARTs which we can enable */ -	UARTA	= 1 << 0, -	UARTB	= 1 << 1, -	UARTD	= 1 << 3, -	UART_COUNT = 4, -}; - -/* - * Boot ROM initializes the odmdata in APBDEV_PMC_SCRATCH20_0, - * so we are using this value to identify memory size. - */ - -unsigned int query_sdram_size(void) -{ -	struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; -	u32 reg; - -	reg = readl(&pmc->pmc_scratch20); -	debug("pmc->pmc_scratch20 (ODMData) = 0x%08x\n", reg); - -	/* bits 31:28 in OdmData are used for RAM size  */ -	switch ((reg) >> 28) { -	case 1: -		return 0x10000000;	/* 256 MB */ -	case 2: -	default: -		return 0x20000000;	/* 512 MB */ -	case 3: -		return 0x40000000;	/* 1GB */ -	} -} - -int dram_init(void) -{ -	/* We do not initialise DRAM here. We just query the size */ -	gd->ram_size = query_sdram_size(); -	return 0; -} - -#ifdef CONFIG_DISPLAY_BOARDINFO -int checkboard(void) -{ -	printf("Board: %s\n", sysinfo.board_string); -	return 0; -} -#endif	/* CONFIG_DISPLAY_BOARDINFO */ - -#ifdef CONFIG_ARCH_CPU_INIT -/* - * Note this function is executed by the ARM7TDMI AVP. It does not return - * in this case. It is also called once the A9 starts up, but does nothing in - * that case. - */ -int arch_cpu_init(void) -{ -	/* Fire up the Cortex A9 */ -	tegra2_start(); - -	/* We didn't do this init in start.S, so do it now */ -	cpu_init_cp15(); - -	/* Initialize essential common plls */ -	clock_early_init(); - -	return 0; -} -#endif - -static int uart_configs[] = { -#if defined(CONFIG_TEGRA2_UARTA_UAA_UAB) -	FUNCMUX_UART1_UAA_UAB, -#elif defined(CONFIG_TEGRA2_UARTA_GPU) -	FUNCMUX_UART1_GPU, -#elif defined(CONFIG_TEGRA2_UARTA_SDIO1) -	FUNCMUX_UART1_SDIO1, -#else -	FUNCMUX_UART1_IRRX_IRTX, -#endif -	FUNCMUX_UART2_IRDA, -	-1, -	FUNCMUX_UART4_GMC, -	-1, -}; - -/** - * Set up the specified uarts - * - * @param uarts_ids	Mask containing UARTs to init (UARTx) - */ -static void setup_uarts(int uart_ids) -{ -	static enum periph_id id_for_uart[] = { -		PERIPH_ID_UART1, -		PERIPH_ID_UART2, -		PERIPH_ID_UART3, -		PERIPH_ID_UART4, -	}; -	size_t i; - -	for (i = 0; i < UART_COUNT; i++) { -		if (uart_ids & (1 << i)) { -			enum periph_id id = id_for_uart[i]; - -			funcmux_select(id, uart_configs[i]); -			clock_ll_start_uart(id); -		} -	} -} - -void board_init_uart_f(void) -{ -	int uart_ids = 0;	/* bit mask of which UART ids to enable */ - -#ifdef CONFIG_TEGRA2_ENABLE_UARTA -	uart_ids |= UARTA; -#endif -#ifdef CONFIG_TEGRA2_ENABLE_UARTB -	uart_ids |= UARTB; -#endif -#ifdef CONFIG_TEGRA2_ENABLE_UARTD -	uart_ids |= UARTD; -#endif -	setup_uarts(uart_ids); -} - -#ifndef CONFIG_SYS_DCACHE_OFF -void enable_caches(void) -{ -	/* Enable D-cache. I-cache is already enabled in start.S */ -	dcache_enable(); -} -#endif diff --git a/arch/arm/cpu/armv7/tegra2/clock.c b/arch/arm/cpu/armv7/tegra2/clock.c deleted file mode 100644 index 602589cde..000000000 --- a/arch/arm/cpu/armv7/tegra2/clock.c +++ /dev/null @@ -1,1087 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -/* Tegra2 Clock control functions */ - -#include <asm/io.h> -#include <asm/arch/clk_rst.h> -#include <asm/arch/clock.h> -#include <asm/arch/timer.h> -#include <asm/arch/tegra2.h> -#include <common.h> -#include <div64.h> -#include <fdtdec.h> - -/* - * This is our record of the current clock rate of each clock. We don't - * fill all of these in since we are only really interested in clocks which - * we use as parents. - */ -static unsigned pll_rate[CLOCK_ID_COUNT]; - -/* - * The oscillator frequency is fixed to one of four set values. Based on this - * the other clocks are set up appropriately. - */ -static unsigned osc_freq[CLOCK_OSC_FREQ_COUNT] = { -	13000000, -	19200000, -	12000000, -	26000000, -}; - -/* - * Clock types that we can use as a source. The Tegra2 has muxes for the - * peripheral clocks, and in most cases there are four options for the clock - * source. This gives us a clock 'type' and exploits what commonality exists - * in the device. - * - * Letters are obvious, except for T which means CLK_M, and S which means the - * clock derived from 32KHz. Beware that CLK_M (also called OSC in the - * datasheet) and PLL_M are different things. The former is the basic - * clock supplied to the SOC from an external oscillator. The latter is the - * memory clock PLL. - * - * See definitions in clock_id in the header file. - */ -enum clock_type_id { -	CLOCK_TYPE_AXPT,	/* PLL_A, PLL_X, PLL_P, CLK_M */ -	CLOCK_TYPE_MCPA,	/* and so on */ -	CLOCK_TYPE_MCPT, -	CLOCK_TYPE_PCM, -	CLOCK_TYPE_PCMT, -	CLOCK_TYPE_PCMT16,	/* CLOCK_TYPE_PCMT with 16-bit divider */ -	CLOCK_TYPE_PCXTS, -	CLOCK_TYPE_PDCT, - -	CLOCK_TYPE_COUNT, -	CLOCK_TYPE_NONE = -1,	/* invalid clock type */ -}; - -/* return 1 if a peripheral ID is in range */ -#define clock_type_id_isvalid(id) ((id) >= 0 && \ -		(id) < CLOCK_TYPE_COUNT) - -char pllp_valid = 1;	/* PLLP is set up correctly */ - -enum { -	CLOCK_MAX_MUX	= 4	/* number of source options for each clock */ -}; - -/* - * Clock source mux for each clock type. This just converts our enum into - * a list of mux sources for use by the code. Note that CLOCK_TYPE_PCXTS - * is special as it has 5 sources. Since it also has a different number of - * bits in its register for the source, we just handle it with a special - * case in the code. - */ -#define CLK(x) CLOCK_ID_ ## x -static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX] = { -	{ CLK(AUDIO),	CLK(XCPU),	CLK(PERIPH),	CLK(OSC)	}, -	{ CLK(MEMORY),	CLK(CGENERAL),	CLK(PERIPH),	CLK(AUDIO)	}, -	{ CLK(MEMORY),	CLK(CGENERAL),	CLK(PERIPH),	CLK(OSC)	}, -	{ CLK(PERIPH),	CLK(CGENERAL),	CLK(MEMORY),	CLK(NONE)	}, -	{ CLK(PERIPH),	CLK(CGENERAL),	CLK(MEMORY),	CLK(OSC)	}, -	{ CLK(PERIPH),	CLK(CGENERAL),	CLK(MEMORY),	CLK(OSC)	}, -	{ CLK(PERIPH),	CLK(CGENERAL),	CLK(XCPU),	CLK(OSC)	}, -	{ CLK(PERIPH),	CLK(DISPLAY),	CLK(CGENERAL),	CLK(OSC)	}, -}; - -/* - * Clock peripheral IDs which sadly don't match up with PERIPH_ID. This is - * not in the header file since it is for purely internal use - we want - * callers to use the PERIPH_ID for all access to peripheral clocks to avoid - * confusion bewteen PERIPH_ID_... and PERIPHC_... - * - * We don't call this CLOCK_PERIPH_ID or PERIPH_CLOCK_ID as it would just be - * confusing. - * - * Note to SOC vendors: perhaps define a unified numbering for peripherals and - * use it for reset, clock enable, clock source/divider and even pinmuxing - * if you can. - */ -enum periphc_internal_id { -	/* 0x00 */ -	PERIPHC_I2S1, -	PERIPHC_I2S2, -	PERIPHC_SPDIF_OUT, -	PERIPHC_SPDIF_IN, -	PERIPHC_PWM, -	PERIPHC_SPI1, -	PERIPHC_SPI2, -	PERIPHC_SPI3, - -	/* 0x08 */ -	PERIPHC_XIO, -	PERIPHC_I2C1, -	PERIPHC_DVC_I2C, -	PERIPHC_TWC, -	PERIPHC_0c, -	PERIPHC_10,	/* PERIPHC_SPI1, what is this really? */ -	PERIPHC_DISP1, -	PERIPHC_DISP2, - -	/* 0x10 */ -	PERIPHC_CVE, -	PERIPHC_IDE0, -	PERIPHC_VI, -	PERIPHC_1c, -	PERIPHC_SDMMC1, -	PERIPHC_SDMMC2, -	PERIPHC_G3D, -	PERIPHC_G2D, - -	/* 0x18 */ -	PERIPHC_NDFLASH, -	PERIPHC_SDMMC4, -	PERIPHC_VFIR, -	PERIPHC_EPP, -	PERIPHC_MPE, -	PERIPHC_MIPI, -	PERIPHC_UART1, -	PERIPHC_UART2, - -	/* 0x20 */ -	PERIPHC_HOST1X, -	PERIPHC_21, -	PERIPHC_TVO, -	PERIPHC_HDMI, -	PERIPHC_24, -	PERIPHC_TVDAC, -	PERIPHC_I2C2, -	PERIPHC_EMC, - -	/* 0x28 */ -	PERIPHC_UART3, -	PERIPHC_29, -	PERIPHC_VI_SENSOR, -	PERIPHC_2b, -	PERIPHC_2c, -	PERIPHC_SPI4, -	PERIPHC_I2C3, -	PERIPHC_SDMMC3, - -	/* 0x30 */ -	PERIPHC_UART4, -	PERIPHC_UART5, -	PERIPHC_VDE, -	PERIPHC_OWR, -	PERIPHC_NOR, -	PERIPHC_CSITE, - -	PERIPHC_COUNT, - -	PERIPHC_NONE = -1, -}; - -/* return 1 if a periphc_internal_id is in range */ -#define periphc_internal_id_isvalid(id) ((id) >= 0 && \ -		(id) < PERIPHC_COUNT) - -/* - * Clock type for each peripheral clock source. We put the name in each - * record just so it is easy to match things up - */ -#define TYPE(name, type) type -static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = { -	/* 0x00 */ -	TYPE(PERIPHC_I2S1,	CLOCK_TYPE_AXPT), -	TYPE(PERIPHC_I2S2,	CLOCK_TYPE_AXPT), -	TYPE(PERIPHC_SPDIF_OUT,	CLOCK_TYPE_AXPT), -	TYPE(PERIPHC_SPDIF_IN,	CLOCK_TYPE_PCM), -	TYPE(PERIPHC_PWM,	CLOCK_TYPE_PCXTS), -	TYPE(PERIPHC_SPI1,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_SPI22,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_SPI3,	CLOCK_TYPE_PCMT), - -	/* 0x08 */ -	TYPE(PERIPHC_XIO,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_I2C1,	CLOCK_TYPE_PCMT16), -	TYPE(PERIPHC_DVC_I2C,	CLOCK_TYPE_PCMT16), -	TYPE(PERIPHC_TWC,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE), -	TYPE(PERIPHC_SPI1,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_DISP1,	CLOCK_TYPE_PDCT), -	TYPE(PERIPHC_DISP2,	CLOCK_TYPE_PDCT), - -	/* 0x10 */ -	TYPE(PERIPHC_CVE,	CLOCK_TYPE_PDCT), -	TYPE(PERIPHC_IDE0,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_VI,	CLOCK_TYPE_MCPA), -	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE), -	TYPE(PERIPHC_SDMMC1,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_SDMMC2,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_G3D,	CLOCK_TYPE_MCPA), -	TYPE(PERIPHC_G2D,	CLOCK_TYPE_MCPA), - -	/* 0x18 */ -	TYPE(PERIPHC_NDFLASH,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_SDMMC4,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_VFIR,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_EPP,	CLOCK_TYPE_MCPA), -	TYPE(PERIPHC_MPE,	CLOCK_TYPE_MCPA), -	TYPE(PERIPHC_MIPI,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_UART1,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_UART2,	CLOCK_TYPE_PCMT), - -	/* 0x20 */ -	TYPE(PERIPHC_HOST1X,	CLOCK_TYPE_MCPA), -	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE), -	TYPE(PERIPHC_TVO,	CLOCK_TYPE_PDCT), -	TYPE(PERIPHC_HDMI,	CLOCK_TYPE_PDCT), -	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE), -	TYPE(PERIPHC_TVDAC,	CLOCK_TYPE_PDCT), -	TYPE(PERIPHC_I2C2,	CLOCK_TYPE_PCMT16), -	TYPE(PERIPHC_EMC,	CLOCK_TYPE_MCPT), - -	/* 0x28 */ -	TYPE(PERIPHC_UART3,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE), -	TYPE(PERIPHC_VI,	CLOCK_TYPE_MCPA), -	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE), -	TYPE(PERIPHC_NONE,	CLOCK_TYPE_NONE), -	TYPE(PERIPHC_SPI4,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_I2C3,	CLOCK_TYPE_PCMT16), -	TYPE(PERIPHC_SDMMC3,	CLOCK_TYPE_PCMT), - -	/* 0x30 */ -	TYPE(PERIPHC_UART4,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_UART5,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_VDE,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_OWR,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_NOR,	CLOCK_TYPE_PCMT), -	TYPE(PERIPHC_CSITE,	CLOCK_TYPE_PCMT), -}; - -/* - * This array translates a periph_id to a periphc_internal_id - * - * Not present/matched up: - *	uint vi_sensor;	 _VI_SENSOR_0,		0x1A8 - *	SPDIF - which is both 0x08 and 0x0c - * - */ -#define NONE(name) (-1) -#define OFFSET(name, value) PERIPHC_ ## name -static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = { -	/* Low word: 31:0 */ -	NONE(CPU), -	NONE(RESERVED1), -	NONE(RESERVED2), -	NONE(AC97), -	NONE(RTC), -	NONE(TMR), -	PERIPHC_UART1, -	PERIPHC_UART2,	/* and vfir 0x68 */ - -	/* 0x08 */ -	NONE(GPIO), -	PERIPHC_SDMMC2, -	NONE(SPDIF),		/* 0x08 and 0x0c, unclear which to use */ -	PERIPHC_I2S1, -	PERIPHC_I2C1, -	PERIPHC_NDFLASH, -	PERIPHC_SDMMC1, -	PERIPHC_SDMMC4, - -	/* 0x10 */ -	PERIPHC_TWC, -	PERIPHC_PWM, -	PERIPHC_I2S2, -	PERIPHC_EPP, -	PERIPHC_VI, -	PERIPHC_G2D, -	NONE(USBD), -	NONE(ISP), - -	/* 0x18 */ -	PERIPHC_G3D, -	PERIPHC_IDE0, -	PERIPHC_DISP2, -	PERIPHC_DISP1, -	PERIPHC_HOST1X, -	NONE(VCP), -	NONE(RESERVED30), -	NONE(CACHE2), - -	/* Middle word: 63:32 */ -	NONE(MEM), -	NONE(AHBDMA), -	NONE(APBDMA), -	NONE(RESERVED35), -	NONE(KBC), -	NONE(STAT_MON), -	NONE(PMC), -	NONE(FUSE), - -	/* 0x28 */ -	NONE(KFUSE), -	NONE(SBC1),	/* SBC1, 0x34, is this SPI1? */ -	PERIPHC_NOR, -	PERIPHC_SPI1, -	PERIPHC_SPI2, -	PERIPHC_XIO, -	PERIPHC_SPI3, -	PERIPHC_DVC_I2C, - -	/* 0x30 */ -	NONE(DSI), -	PERIPHC_TVO,	/* also CVE 0x40 */ -	PERIPHC_MIPI, -	PERIPHC_HDMI, -	PERIPHC_CSITE, -	PERIPHC_TVDAC, -	PERIPHC_I2C2, -	PERIPHC_UART3, - -	/* 0x38 */ -	NONE(RESERVED56), -	PERIPHC_EMC, -	NONE(USB2), -	NONE(USB3), -	PERIPHC_MPE, -	PERIPHC_VDE, -	NONE(BSEA), -	NONE(BSEV), - -	/* Upper word 95:64 */ -	NONE(SPEEDO), -	PERIPHC_UART4, -	PERIPHC_UART5, -	PERIPHC_I2C3, -	PERIPHC_SPI4, -	PERIPHC_SDMMC3, -	NONE(PCIE), -	PERIPHC_OWR, - -	/* 0x48 */ -	NONE(AFI), -	NONE(CORESIGHT), -	NONE(RESERVED74), -	NONE(AVPUCQ), -	NONE(RESERVED76), -	NONE(RESERVED77), -	NONE(RESERVED78), -	NONE(RESERVED79), - -	/* 0x50 */ -	NONE(RESERVED80), -	NONE(RESERVED81), -	NONE(RESERVED82), -	NONE(RESERVED83), -	NONE(IRAMA), -	NONE(IRAMB), -	NONE(IRAMC), -	NONE(IRAMD), - -	/* 0x58 */ -	NONE(CRAM2), -}; - -/* - * Get the oscillator frequency, from the corresponding hardware configuration - * field. - */ -enum clock_osc_freq clock_get_osc_freq(void) -{ -	struct clk_rst_ctlr *clkrst = -			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; -	u32 reg; - -	reg = readl(&clkrst->crc_osc_ctrl); -	return (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT; -} - -int clock_get_osc_bypass(void) -{ -	struct clk_rst_ctlr *clkrst = -			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; -	u32 reg; - -	reg = readl(&clkrst->crc_osc_ctrl); -	return (reg & OSC_XOBP_MASK) >> OSC_XOBP_SHIFT; -} - -/* Returns a pointer to the registers of the given pll */ -static struct clk_pll *get_pll(enum clock_id clkid) -{ -	struct clk_rst_ctlr *clkrst = -			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; - -	assert(clock_id_is_pll(clkid)); -	return &clkrst->crc_pll[clkid]; -} - -int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn, -		u32 *divp, u32 *cpcon, u32 *lfcon) -{ -	struct clk_pll *pll = get_pll(clkid); -	u32 data; - -	assert(clkid != CLOCK_ID_USB); - -	/* Safety check, adds to code size but is small */ -	if (!clock_id_is_pll(clkid) || clkid == CLOCK_ID_USB) -		return -1; -	data = readl(&pll->pll_base); -	*divm = (data & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT; -	*divn = (data & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT; -	*divp = (data & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT; -	data = readl(&pll->pll_misc); -	*cpcon = (data & PLL_CPCON_MASK) >> PLL_CPCON_SHIFT; -	*lfcon = (data & PLL_LFCON_MASK) >> PLL_LFCON_SHIFT; - -	return 0; -} - -unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn, -		u32 divp, u32 cpcon, u32 lfcon) -{ -	struct clk_pll *pll = get_pll(clkid); -	u32 data; - -	/* -	 * We cheat by treating all PLL (except PLLU) in the same fashion. -	 * This works only because: -	 * - same fields are always mapped at same offsets, except DCCON -	 * - DCCON is always 0, doesn't conflict -	 * - M,N, P of PLLP values are ignored for PLLP -	 */ -	data = (cpcon << PLL_CPCON_SHIFT) | (lfcon << PLL_LFCON_SHIFT); -	writel(data, &pll->pll_misc); - -	data = (divm << PLL_DIVM_SHIFT) | (divn << PLL_DIVN_SHIFT) | -			(0 << PLL_BYPASS_SHIFT) | (1 << PLL_ENABLE_SHIFT); - -	if (clkid == CLOCK_ID_USB) -		data |= divp << PLLU_VCO_FREQ_SHIFT; -	else -		data |= divp << PLL_DIVP_SHIFT; -	writel(data, &pll->pll_base); - -	/* calculate the stable time */ -	return timer_get_us() + CLOCK_PLL_STABLE_DELAY_US; -} - -/* return 1 if a peripheral ID is in range and valid */ -static int clock_periph_id_isvalid(enum periph_id id) -{ -	if (id < PERIPH_ID_FIRST || id >= PERIPH_ID_COUNT) -		printf("Peripheral id %d out of range\n", id); -	else { -		switch (id) { -		case PERIPH_ID_RESERVED1: -		case PERIPH_ID_RESERVED2: -		case PERIPH_ID_RESERVED30: -		case PERIPH_ID_RESERVED35: -		case PERIPH_ID_RESERVED56: -		case PERIPH_ID_RESERVED74: -		case PERIPH_ID_RESERVED76: -		case PERIPH_ID_RESERVED77: -		case PERIPH_ID_RESERVED78: -		case PERIPH_ID_RESERVED79: -		case PERIPH_ID_RESERVED80: -		case PERIPH_ID_RESERVED81: -		case PERIPH_ID_RESERVED82: -		case PERIPH_ID_RESERVED83: -			printf("Peripheral id %d is reserved\n", id); -			break; -		default: -			return 1; -		} -	} -	return 0; -} - -/* Returns a pointer to the clock source register for a peripheral */ -static u32 *get_periph_source_reg(enum periph_id periph_id) -{ -	struct clk_rst_ctlr *clkrst = -			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; -	enum periphc_internal_id internal_id; - -	assert(clock_periph_id_isvalid(periph_id)); -	internal_id = periph_id_to_internal_id[periph_id]; -	assert(internal_id != -1); -	return &clkrst->crc_clk_src[internal_id]; -} - -void clock_ll_set_source_divisor(enum periph_id periph_id, unsigned source, -			      unsigned divisor) -{ -	u32 *reg = get_periph_source_reg(periph_id); -	u32 value; - -	value = readl(reg); - -	value &= ~OUT_CLK_SOURCE_MASK; -	value |= source << OUT_CLK_SOURCE_SHIFT; - -	value &= ~OUT_CLK_DIVISOR_MASK; -	value |= divisor << OUT_CLK_DIVISOR_SHIFT; - -	writel(value, reg); -} - -void clock_ll_set_source(enum periph_id periph_id, unsigned source) -{ -	u32 *reg = get_periph_source_reg(periph_id); - -	clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK, -			source << OUT_CLK_SOURCE_SHIFT); -} - -/** - * Given the parent's rate and the required rate for the children, this works - * out the peripheral clock divider to use, in 7.1 binary format. - * - * @param divider_bits	number of divider bits (8 or 16) - * @param parent_rate	clock rate of parent clock in Hz - * @param rate		required clock rate for this clock - * @return divider which should be used - */ -static int clk_get_divider(unsigned divider_bits, unsigned long parent_rate, -			   unsigned long rate) -{ -	u64 divider = parent_rate * 2; -	unsigned max_divider = 1 << divider_bits; - -	divider += rate - 1; -	do_div(divider, rate); - -	if ((s64)divider - 2 < 0) -		return 0; - -	if ((s64)divider - 2 >= max_divider) -		return -1; - -	return divider - 2; -} - -/** - * Given the parent's rate and the divider in 7.1 format, this works out the - * resulting peripheral clock rate. - * - * @param parent_rate	clock rate of parent clock in Hz - * @param divider which should be used in 7.1 format - * @return effective clock rate of peripheral - */ -static unsigned long get_rate_from_divider(unsigned long parent_rate, -					   int divider) -{ -	u64 rate; - -	rate = (u64)parent_rate * 2; -	do_div(rate, divider + 2); -	return rate; -} - -unsigned long clock_get_periph_rate(enum periph_id periph_id, -		enum clock_id parent) -{ -	u32 *reg = get_periph_source_reg(periph_id); - -	return get_rate_from_divider(pll_rate[parent], -		(readl(reg) & OUT_CLK_DIVISOR_MASK) >> OUT_CLK_DIVISOR_SHIFT); -} - -/** - * Find the best available 7.1 format divisor given a parent clock rate and - * required child clock rate. This function assumes that a second-stage - * divisor is available which can divide by powers of 2 from 1 to 256. - * - * @param divider_bits	number of divider bits (8 or 16) - * @param parent_rate	clock rate of parent clock in Hz - * @param rate		required clock rate for this clock - * @param extra_div	value for the second-stage divisor (not set if this - *			function returns -1. - * @return divider which should be used, or -1 if nothing is valid - * - */ -static int find_best_divider(unsigned divider_bits, unsigned long parent_rate, -			     unsigned long rate, int *extra_div) -{ -	int shift; -	int best_divider = -1; -	int best_error = rate; - -	/* try dividers from 1 to 256 and find closest match */ -	for (shift = 0; shift <= 8 && best_error > 0; shift++) { -		unsigned divided_parent = parent_rate >> shift; -		int divider = clk_get_divider(divider_bits, divided_parent, -					      rate); -		unsigned effective_rate = get_rate_from_divider(divided_parent, -						       divider); -		int error = rate - effective_rate; - -		/* Given a valid divider, look for the lowest error */ -		if (divider != -1 && error < best_error) { -			best_error = error; -			*extra_div = 1 << shift; -			best_divider = divider; -		} -	} - -	/* return what we found - *extra_div will already be set */ -	return best_divider; -} - -/** - * Given a peripheral ID and the required source clock, this returns which - * value should be programmed into the source mux for that peripheral. - * - * There is special code here to handle the one source type with 5 sources. - * - * @param periph_id	peripheral to start - * @param source	PLL id of required parent clock - * @param mux_bits	Set to number of bits in mux register: 2 or 4 - * @param divider_bits	Set to number of divider bits (8 or 16) - * @return mux value (0-4, or -1 if not found) - */ -static int get_periph_clock_source(enum periph_id periph_id, -		enum clock_id parent, int *mux_bits, int *divider_bits) -{ -	enum clock_type_id type; -	enum periphc_internal_id internal_id; -	int mux; - -	assert(clock_periph_id_isvalid(periph_id)); - -	internal_id = periph_id_to_internal_id[periph_id]; -	assert(periphc_internal_id_isvalid(internal_id)); - -	type = clock_periph_type[internal_id]; -	assert(clock_type_id_isvalid(type)); - -	/* -	 * Special cases here for the clock with a 4-bit source mux and I2C -	 * with its 16-bit divisor -	 */ -	if (type == CLOCK_TYPE_PCXTS) -		*mux_bits = 4; -	else -		*mux_bits = 2; -	if (type == CLOCK_TYPE_PCMT16) -		*divider_bits = 16; -	else -		*divider_bits = 8; - -	for (mux = 0; mux < CLOCK_MAX_MUX; mux++) -		if (clock_source[type][mux] == parent) -			return mux; - -	/* -	 * Not found: it might be looking for the 'S' in CLOCK_TYPE_PCXTS -	 * which is not in our table. If not, then they are asking for a -	 * source which this peripheral can't access through its mux. -	 */ -	assert(type == CLOCK_TYPE_PCXTS); -	assert(parent == CLOCK_ID_SFROM32KHZ); -	if (type == CLOCK_TYPE_PCXTS && parent == CLOCK_ID_SFROM32KHZ) -		return 4;	/* mux value for this clock */ - -	/* if we get here, either us or the caller has made a mistake */ -	printf("Caller requested bad clock: periph=%d, parent=%d\n", periph_id, -		parent); -	return -1; -} - -/** - * Adjust peripheral PLL to use the given divider and source. - * - * @param periph_id	peripheral to adjust - * @param source	Source number (0-3 or 0-7) - * @param mux_bits	Number of mux bits (2 or 4) - * @param divider	Required divider in 7.1 or 15.1 format - * @return 0 if ok, -1 on error (requesting a parent clock which is not valid - *		for this peripheral) - */ -static int adjust_periph_pll(enum periph_id periph_id, int source, -			     int mux_bits, unsigned divider) -{ -	u32 *reg = get_periph_source_reg(periph_id); - -	clrsetbits_le32(reg, OUT_CLK_DIVISOR_MASK, -			divider << OUT_CLK_DIVISOR_SHIFT); -	udelay(1); - -	/* work out the source clock and set it */ -	if (source < 0) -		return -1; -	if (mux_bits == 4) { -		clrsetbits_le32(reg, OUT_CLK_SOURCE4_MASK, -			source << OUT_CLK_SOURCE4_SHIFT); -	} else { -		clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK, -			source << OUT_CLK_SOURCE_SHIFT); -	} -	udelay(2); -	return 0; -} - -unsigned clock_adjust_periph_pll_div(enum periph_id periph_id, -		enum clock_id parent, unsigned rate, int *extra_div) -{ -	unsigned effective_rate; -	int mux_bits, divider_bits, source; -	int divider; - -	/* work out the source clock and set it */ -	source = get_periph_clock_source(periph_id, parent, &mux_bits, -					 ÷r_bits); - -	if (extra_div) -		divider = find_best_divider(divider_bits, pll_rate[parent], -					    rate, extra_div); -	else -		divider = clk_get_divider(divider_bits, pll_rate[parent], -					  rate); -	assert(divider >= 0); -	if (adjust_periph_pll(periph_id, source, mux_bits, divider)) -		return -1U; -	debug("periph %d, rate=%d, reg=%p = %x\n", periph_id, rate, -		get_periph_source_reg(periph_id), -		readl(get_periph_source_reg(periph_id))); - -	/* Check what we ended up with. This shouldn't matter though */ -	effective_rate = clock_get_periph_rate(periph_id, parent); -	if (extra_div) -		effective_rate /= *extra_div; -	if (rate != effective_rate) -		debug("Requested clock rate %u not honored (got %u)\n", -		       rate, effective_rate); -	return effective_rate; -} - -unsigned clock_start_periph_pll(enum periph_id periph_id, -		enum clock_id parent, unsigned rate) -{ -	unsigned effective_rate; - -	reset_set_enable(periph_id, 1); -	clock_enable(periph_id); - -	effective_rate = clock_adjust_periph_pll_div(periph_id, parent, rate, -						 NULL); - -	reset_set_enable(periph_id, 0); -	return effective_rate; -} - -void clock_set_enable(enum periph_id periph_id, int enable) -{ -	struct clk_rst_ctlr *clkrst = -			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; -	u32 *clk = &clkrst->crc_clk_out_enb[PERIPH_REG(periph_id)]; -	u32 reg; - -	/* Enable/disable the clock to this peripheral */ -	assert(clock_periph_id_isvalid(periph_id)); -	reg = readl(clk); -	if (enable) -		reg |= PERIPH_MASK(periph_id); -	else -		reg &= ~PERIPH_MASK(periph_id); -	writel(reg, clk); -} - -void clock_enable(enum periph_id clkid) -{ -	clock_set_enable(clkid, 1); -} - -void clock_disable(enum periph_id clkid) -{ -	clock_set_enable(clkid, 0); -} - -void reset_set_enable(enum periph_id periph_id, int enable) -{ -	struct clk_rst_ctlr *clkrst = -			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; -	u32 *reset = &clkrst->crc_rst_dev[PERIPH_REG(periph_id)]; -	u32 reg; - -	/* Enable/disable reset to the peripheral */ -	assert(clock_periph_id_isvalid(periph_id)); -	reg = readl(reset); -	if (enable) -		reg |= PERIPH_MASK(periph_id); -	else -		reg &= ~PERIPH_MASK(periph_id); -	writel(reg, reset); -} - -void reset_periph(enum periph_id periph_id, int us_delay) -{ -	/* Put peripheral into reset */ -	reset_set_enable(periph_id, 1); -	udelay(us_delay); - -	/* Remove reset */ -	reset_set_enable(periph_id, 0); - -	udelay(us_delay); -} - -void reset_cmplx_set_enable(int cpu, int which, int reset) -{ -	struct clk_rst_ctlr *clkrst = -			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; -	u32 mask; - -	/* Form the mask, which depends on the cpu chosen. Tegra2 has 2 */ -	assert(cpu >= 0 && cpu < 2); -	mask = which << cpu; - -	/* either enable or disable those reset for that CPU */ -	if (reset) -		writel(mask, &clkrst->crc_cpu_cmplx_set); -	else -		writel(mask, &clkrst->crc_cpu_cmplx_clr); -} - -unsigned clock_get_rate(enum clock_id clkid) -{ -	struct clk_pll *pll; -	u32 base; -	u32 divm; -	u64 parent_rate; -	u64 rate; - -	parent_rate = osc_freq[clock_get_osc_freq()]; -	if (clkid == CLOCK_ID_OSC) -		return parent_rate; - -	pll = get_pll(clkid); -	base = readl(&pll->pll_base); - -	/* Oh for bf_unpack()... */ -	rate = parent_rate * ((base & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT); -	divm = (base & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT; -	if (clkid == CLOCK_ID_USB) -		divm <<= (base & PLLU_VCO_FREQ_MASK) >> PLLU_VCO_FREQ_SHIFT; -	else -		divm <<= (base & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT; -	do_div(rate, divm); -	return rate; -} - -/** - * Set the output frequency you want for each PLL clock. - * PLL output frequencies are programmed by setting their N, M and P values. - * The governing equations are: - *     VCO = (Fi / m) * n, Fo = VCO / (2^p) - *     where Fo is the output frequency from the PLL. - * Example: Set the output frequency to 216Mhz(Fo) with 12Mhz OSC(Fi) - *     216Mhz = ((12Mhz / m) * n) / (2^p) so n=432,m=12,p=1 - * Please see Tegra TRM section 5.3 to get the detail for PLL Programming - * - * @param n PLL feedback divider(DIVN) - * @param m PLL input divider(DIVN) - * @param p post divider(DIVP) - * @param cpcon base PLL charge pump(CPCON) - * @return 0 if ok, -1 on error (the requested PLL is incorrect and cannot - *		be overriden), 1 if PLL is already correct - */ -static int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon) -{ -	u32 base_reg; -	u32 misc_reg; -	struct clk_pll *pll; - -	pll = get_pll(clkid); - -	base_reg = readl(&pll->pll_base); - -	/* Set BYPASS, m, n and p to PLL_BASE */ -	base_reg &= ~PLL_DIVM_MASK; -	base_reg |= m << PLL_DIVM_SHIFT; - -	base_reg &= ~PLL_DIVN_MASK; -	base_reg |= n << PLL_DIVN_SHIFT; - -	base_reg &= ~PLL_DIVP_MASK; -	base_reg |= p << PLL_DIVP_SHIFT; - -	if (clkid == CLOCK_ID_PERIPH) { -		/* -		 * If the PLL is already set up, check that it is correct -		 * and record this info for clock_verify() to check. -		 */ -		if (base_reg & PLL_BASE_OVRRIDE_MASK) { -			base_reg |= PLL_ENABLE_MASK; -			if (base_reg != readl(&pll->pll_base)) -				pllp_valid = 0; -			return pllp_valid ? 1 : -1; -		} -		base_reg |= PLL_BASE_OVRRIDE_MASK; -	} - -	base_reg |= PLL_BYPASS_MASK; -	writel(base_reg, &pll->pll_base); - -	/* Set cpcon to PLL_MISC */ -	misc_reg = readl(&pll->pll_misc); -	misc_reg &= ~PLL_CPCON_MASK; -	misc_reg |= cpcon << PLL_CPCON_SHIFT; -	writel(misc_reg, &pll->pll_misc); - -	/* Enable PLL */ -	base_reg |= PLL_ENABLE_MASK; -	writel(base_reg, &pll->pll_base); - -	/* Disable BYPASS */ -	base_reg &= ~PLL_BYPASS_MASK; -	writel(base_reg, &pll->pll_base); - -	return 0; -} - -void clock_ll_start_uart(enum periph_id periph_id) -{ -	/* Assert UART reset and enable clock */ -	reset_set_enable(periph_id, 1); -	clock_enable(periph_id); -	clock_ll_set_source(periph_id, 0); /* UARTx_CLK_SRC = 00, PLLP_OUT0 */ - -	/* wait for 2us */ -	udelay(2); - -	/* De-assert reset to UART */ -	reset_set_enable(periph_id, 0); -} - -#ifdef CONFIG_OF_CONTROL -/* - * Convert a device tree clock ID to our peripheral ID. They are mostly - * the same but we are very cautious so we check that a valid clock ID is - * provided. - * - * @param clk_id	Clock ID according to tegra2 device tree binding - * @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid - */ -static enum periph_id clk_id_to_periph_id(int clk_id) -{ -	if (clk_id > 95) -		return PERIPH_ID_NONE; - -	switch (clk_id) { -	case 1: -	case 2: -	case 7: -	case 10: -	case 20: -	case 30: -	case 35: -	case 49: -	case 56: -	case 74: -	case 76: -	case 77: -	case 78: -	case 79: -	case 80: -	case 81: -	case 82: -	case 83: -	case 91: -	case 95: -		return PERIPH_ID_NONE; -	default: -		return clk_id; -	} -} - -int clock_decode_periph_id(const void *blob, int node) -{ -	enum periph_id id; -	u32 cell[2]; -	int err; - -	err = fdtdec_get_int_array(blob, node, "clocks", cell, -				   ARRAY_SIZE(cell)); -	if (err) -		return -1; -	id = clk_id_to_periph_id(cell[1]); -	assert(clock_periph_id_isvalid(id)); -	return id; -} -#endif /* CONFIG_OF_CONTROL */ - -int clock_verify(void) -{ -	struct clk_pll *pll = get_pll(CLOCK_ID_PERIPH); -	u32 reg = readl(&pll->pll_base); - -	if (!pllp_valid) { -		printf("Warning: PLLP %x is not correct\n", reg); -		return -1; -	} -	debug("PLLX %x is correct\n", reg); -	return 0; -} - -void clock_early_init(void) -{ -	/* -	 * PLLP output frequency set to 216MHz -	 * PLLC output frequency set to 600Mhz -	 * -	 * TODO: Can we calculate these values instead of hard-coding? -	 */ -	switch (clock_get_osc_freq()) { -	case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */ -		clock_set_rate(CLOCK_ID_PERIPH, 432, 12, 1, 8); -		clock_set_rate(CLOCK_ID_CGENERAL, 600, 12, 0, 8); -		break; - -	case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */ -		clock_set_rate(CLOCK_ID_PERIPH, 432, 26, 1, 8); -		clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8); -		break; - -	case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */ -		clock_set_rate(CLOCK_ID_PERIPH, 432, 13, 1, 8); -		clock_set_rate(CLOCK_ID_CGENERAL, 600, 13, 0, 8); -		break; -	case CLOCK_OSC_FREQ_19_2: -	default: -		/* -		 * These are not supported. It is too early to print a -		 * message and the UART likely won't work anyway due to the -		 * oscillator being wrong. -		 */ -		break; -	} -} - -void clock_init(void) -{ -	pll_rate[CLOCK_ID_MEMORY] = clock_get_rate(CLOCK_ID_MEMORY); -	pll_rate[CLOCK_ID_PERIPH] = clock_get_rate(CLOCK_ID_PERIPH); -	pll_rate[CLOCK_ID_CGENERAL] = clock_get_rate(CLOCK_ID_CGENERAL); -	pll_rate[CLOCK_ID_OSC] = clock_get_rate(CLOCK_ID_OSC); -	pll_rate[CLOCK_ID_SFROM32KHZ] = 32768; -	debug("Osc = %d\n", pll_rate[CLOCK_ID_OSC]); -	debug("PLLM = %d\n", pll_rate[CLOCK_ID_MEMORY]); -	debug("PLLP = %d\n", pll_rate[CLOCK_ID_PERIPH]); -} diff --git a/arch/arm/cpu/armv7/tegra2/crypto.c b/arch/arm/cpu/armv7/tegra2/crypto.c deleted file mode 100644 index 5f0b240e2..000000000 --- a/arch/arm/cpu/armv7/tegra2/crypto.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * (C) Copyright 2010 - 2011 NVIDIA Corporation <www.nvidia.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/errno.h> -#include "crypto.h" -#include "aes.h" - -static u8 zero_key[16]; - -#define AES_CMAC_CONST_RB 0x87  /* from RFC 4493, Figure 2.2 */ - -enum security_op { -	SECURITY_SIGN		= 1 << 0,	/* Sign the data */ -	SECURITY_ENCRYPT	= 1 << 1,	/* Encrypt the data */ -}; - -static void debug_print_vector(char *name, u32 num_bytes, u8 *data) -{ -	u32 i; - -	debug("%s [%d] @0x%08x", name, num_bytes, (u32)data); -	for (i = 0; i < num_bytes; i++) { -		if (i % 16 == 0) -			debug(" = "); -		debug("%02x", data[i]); -		if ((i+1) % 16 != 0) -			debug(" "); -	} -	debug("\n"); -} - -/** - * Apply chain data to the destination using EOR - * - * Each array is of length AES_AES_KEY_LENGTH. - * - * \param cbc_chain_data	Chain data - * \param src			Source data - * \param dst			Destination data, which is modified here - */ -static void apply_cbc_chain_data(u8 *cbc_chain_data, u8 *src, u8 *dst) -{ -	int i; - -	for (i = 0; i < 16; i++) -		*dst++ = *src++ ^ *cbc_chain_data++; -} - -/** - * Encrypt some data with AES. - * - * \param key_schedule		Expanded key to use - * \param src			Source data to encrypt - * \param dst			Destination buffer - * \param num_aes_blocks	Number of AES blocks to encrypt - */ -static void encrypt_object(u8 *key_schedule, u8 *src, u8 *dst, -			   u32 num_aes_blocks) -{ -	u8 tmp_data[AES_KEY_LENGTH]; -	u8 *cbc_chain_data; -	u32 i; - -	cbc_chain_data = zero_key;	/* Convenient array of 0's for IV */ - -	for (i = 0; i < num_aes_blocks; i++) { -		debug("encrypt_object: block %d of %d\n", i, num_aes_blocks); -		debug_print_vector("AES Src", AES_KEY_LENGTH, src); - -		/* Apply the chain data */ -		apply_cbc_chain_data(cbc_chain_data, src, tmp_data); -		debug_print_vector("AES Xor", AES_KEY_LENGTH, tmp_data); - -		/* encrypt the AES block */ -		aes_encrypt(tmp_data, key_schedule, dst); -		debug_print_vector("AES Dst", AES_KEY_LENGTH, dst); - -		/* Update pointers for next loop. */ -		cbc_chain_data = dst; -		src += AES_KEY_LENGTH; -		dst += AES_KEY_LENGTH; -	} -} - -/** - * Shift a vector left by one bit - * - * \param in	Input vector - * \param out	Output vector - * \param size	Length of vector in bytes - */ -static void left_shift_vector(u8 *in, u8 *out, int size) -{ -	int carry = 0; -	int i; - -	for (i = size - 1; i >= 0; i--) { -		out[i] = (in[i] << 1) | carry; -		carry = in[i] >> 7;	/* get most significant bit */ -	} -} - -/** - * Sign a block of data, putting the result into dst. - * - * \param key			Input AES key, length AES_KEY_LENGTH - * \param key_schedule		Expanded key to use - * \param src			Source data of length 'num_aes_blocks' blocks - * \param dst			Destination buffer, length AES_KEY_LENGTH - * \param num_aes_blocks	Number of AES blocks to encrypt - */ -static void sign_object(u8 *key, u8 *key_schedule, u8 *src, u8 *dst, -			u32 num_aes_blocks) -{ -	u8 tmp_data[AES_KEY_LENGTH]; -	u8 left[AES_KEY_LENGTH]; -	u8 k1[AES_KEY_LENGTH]; -	u8 *cbc_chain_data; -	unsigned i; - -	cbc_chain_data = zero_key;	/* Convenient array of 0's for IV */ - -	/* compute K1 constant needed by AES-CMAC calculation */ -	for (i = 0; i < AES_KEY_LENGTH; i++) -		tmp_data[i] = 0; - -	encrypt_object(key_schedule, tmp_data, left, 1); -	debug_print_vector("AES(key, nonce)", AES_KEY_LENGTH, left); - -	left_shift_vector(left, k1, sizeof(left)); -	debug_print_vector("L", AES_KEY_LENGTH, left); - -	if ((left[0] >> 7) != 0) /* get MSB of L */ -		k1[AES_KEY_LENGTH-1] ^= AES_CMAC_CONST_RB; -	debug_print_vector("K1", AES_KEY_LENGTH, k1); - -	/* compute the AES-CMAC value */ -	for (i = 0; i < num_aes_blocks; i++) { -		/* Apply the chain data */ -		apply_cbc_chain_data(cbc_chain_data, src, tmp_data); - -		/* for the final block, XOR K1 into the IV */ -		if (i == num_aes_blocks - 1) -			apply_cbc_chain_data(tmp_data, k1, tmp_data); - -		/* encrypt the AES block */ -		aes_encrypt(tmp_data, key_schedule, dst); - -		debug("sign_obj: block %d of %d\n", i, num_aes_blocks); -		debug_print_vector("AES-CMAC Src", AES_KEY_LENGTH, src); -		debug_print_vector("AES-CMAC Xor", AES_KEY_LENGTH, tmp_data); -		debug_print_vector("AES-CMAC Dst", AES_KEY_LENGTH, dst); - -		/* Update pointers for next loop. */ -		cbc_chain_data = dst; -		src += AES_KEY_LENGTH; -	} - -	debug_print_vector("AES-CMAC Hash", AES_KEY_LENGTH, dst); -} - -/** - * Encrypt and sign a block of data (depending on security mode). - * - * \param key		Input AES key, length AES_KEY_LENGTH - * \param oper		Security operations mask to perform (enum security_op) - * \param src		Source data - * \param length	Size of source data - * \param sig_dst	Destination address for signature, AES_KEY_LENGTH bytes - */ -static int encrypt_and_sign(u8 *key, enum security_op oper, u8 *src, -			    u32 length, u8 *sig_dst) -{ -	u32 num_aes_blocks; -	u8 key_schedule[AES_EXPAND_KEY_LENGTH]; - -	debug("encrypt_and_sign: length = %d\n", length); -	debug_print_vector("AES key", AES_KEY_LENGTH, key); - -	/* -	 * The only need for a key is for signing/checksum purposes, so -	 * if not encrypting, expand a key of 0s. -	 */ -	aes_expand_key(oper & SECURITY_ENCRYPT ? key : zero_key, key_schedule); - -	num_aes_blocks = (length + AES_KEY_LENGTH - 1) / AES_KEY_LENGTH; - -	if (oper & SECURITY_ENCRYPT) { -		/* Perform this in place, resulting in src being encrypted. */ -		debug("encrypt_and_sign: begin encryption\n"); -		encrypt_object(key_schedule, src, src, num_aes_blocks); -		debug("encrypt_and_sign: end encryption\n"); -	} - -	if (oper & SECURITY_SIGN) { -		/* encrypt the data, overwriting the result in signature. */ -		debug("encrypt_and_sign: begin signing\n"); -		sign_object(key, key_schedule, src, sig_dst, num_aes_blocks); -		debug("encrypt_and_sign: end signing\n"); -	} - -	return 0; -} - -int sign_data_block(u8 *source, unsigned length, u8 *signature) -{ -	return encrypt_and_sign(zero_key, SECURITY_SIGN, source, -				length, signature); -} diff --git a/arch/arm/cpu/armv7/tegra2/crypto.h b/arch/arm/cpu/armv7/tegra2/crypto.h deleted file mode 100644 index aff67e77b..000000000 --- a/arch/arm/cpu/armv7/tegra2/crypto.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * (C) Copyright 2010 - 2011 NVIDIA Corporation <www.nvidia.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef _CRYPTO_H_ -#define _CRYPTO_H_ - -/** - * Sign a block of data - * - * \param source	Source data - * \param length	Size of source data - * \param signature	Destination address for signature, AES_KEY_LENGTH bytes - */ -int sign_data_block(u8 *source, unsigned length, u8 *signature); - -#endif /* #ifndef _CRYPTO_H_ */ diff --git a/arch/arm/cpu/armv7/tegra2/emc.c b/arch/arm/cpu/armv7/tegra2/emc.c deleted file mode 100644 index c0e5c565f..000000000 --- a/arch/arm/cpu/armv7/tegra2/emc.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <fdtdec.h> -#include <asm/io.h> -#include <asm/arch/ap20.h> -#include <asm/arch/apb_misc.h> -#include <asm/arch/clock.h> -#include <asm/arch/emc.h> -#include <asm/arch/tegra2.h> - -/* - * The EMC registers have shadow registers.  When the EMC clock is updated - * in the clock controller, the shadow registers are copied to the active - * registers, allowing glitchless memory bus frequency changes. - * This function updates the shadow registers for a new clock frequency, - * and relies on the clock lock on the emc clock to avoid races between - * multiple frequency changes - */ - -/* - * This table defines the ordering of the registers provided to - * tegra_set_mmc() - * TODO: Convert to fdt version once available - */ -static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = { -	0x2c,	/* RC */ -	0x30,	/* RFC */ -	0x34,	/* RAS */ -	0x38,	/* RP */ -	0x3c,	/* R2W */ -	0x40,	/* W2R */ -	0x44,	/* R2P */ -	0x48,	/* W2P */ -	0x4c,	/* RD_RCD */ -	0x50,	/* WR_RCD */ -	0x54,	/* RRD */ -	0x58,	/* REXT */ -	0x5c,	/* WDV */ -	0x60,	/* QUSE */ -	0x64,	/* QRST */ -	0x68,	/* QSAFE */ -	0x6c,	/* RDV */ -	0x70,	/* REFRESH */ -	0x74,	/* BURST_REFRESH_NUM */ -	0x78,	/* PDEX2WR */ -	0x7c,	/* PDEX2RD */ -	0x80,	/* PCHG2PDEN */ -	0x84,	/* ACT2PDEN */ -	0x88,	/* AR2PDEN */ -	0x8c,	/* RW2PDEN */ -	0x90,	/* TXSR */ -	0x94,	/* TCKE */ -	0x98,	/* TFAW */ -	0x9c,	/* TRPAB */ -	0xa0,	/* TCLKSTABLE */ -	0xa4,	/* TCLKSTOP */ -	0xa8,	/* TREFBW */ -	0xac,	/* QUSE_EXTRA */ -	0x114,	/* FBIO_CFG6 */ -	0xb0,	/* ODT_WRITE */ -	0xb4,	/* ODT_READ */ -	0x104,	/* FBIO_CFG5 */ -	0x2bc,	/* CFG_DIG_DLL */ -	0x2c0,	/* DLL_XFORM_DQS */ -	0x2c4,	/* DLL_XFORM_QUSE */ -	0x2e0,	/* ZCAL_REF_CNT */ -	0x2e4,	/* ZCAL_WAIT_CNT */ -	0x2a8,	/* AUTO_CAL_INTERVAL */ -	0x2d0,	/* CFG_CLKTRIM_0 */ -	0x2d4,	/* CFG_CLKTRIM_1 */ -	0x2d8,	/* CFG_CLKTRIM_2 */ -}; - -struct emc_ctlr *emc_get_controller(const void *blob) -{ -	fdt_addr_t addr; -	int node; - -	node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_EMC); -	if (node > 0) { -		addr = fdtdec_get_addr(blob, node, "reg"); -		if (addr != FDT_ADDR_T_NONE) -			return (struct emc_ctlr *)addr; -	} -	return NULL; -} - -/* Error codes we use */ -enum { -	ERR_NO_EMC_NODE = -10, -	ERR_NO_EMC_REG, -	ERR_NO_FREQ, -	ERR_FREQ_NOT_FOUND, -	ERR_BAD_REGS, -	ERR_NO_RAM_CODE, -	ERR_RAM_CODE_NOT_FOUND, -}; - -/** - * Find EMC tables for the given ram code. - * - * The tegra EMC binding has two options, one using the ram code and one not. - * We detect which is in use by looking for the nvidia,use-ram-code property. - * If this is not present, then the EMC tables are directly below 'node', - * otherwise we select the correct emc-tables subnode based on the 'ram_code' - * value. - * - * @param blob		Device tree blob - * @param node		EMC node (nvidia,tegra20-emc compatible string) - * @param ram_code	RAM code to select (0-3, or -1 if unknown) - * @return 0 if ok, otherwise a -ve ERR_ code (see enum above) - */ -static int find_emc_tables(const void *blob, int node, int ram_code) -{ -	int need_ram_code; -	int depth; -	int offset; - -	/* If we are using RAM codes, scan through the tables for our code */ -	need_ram_code = fdtdec_get_bool(blob, node, "nvidia,use-ram-code"); -	if (!need_ram_code) -		return node; -	if (ram_code == -1) { -		debug("%s: RAM code required but not supplied\n", __func__); -		return ERR_NO_RAM_CODE; -	} - -	offset = node; -	depth = 0; -	do { -		/* -		 * Sadly there is no compatible string so we cannot use -		 * fdtdec_next_compatible_subnode(). -		 */ -		offset = fdt_next_node(blob, offset, &depth); -		if (depth <= 0) -			break; - -		/* Make sure this is a direct subnode */ -		if (depth != 1) -			continue; -		if (strcmp("emc-tables", fdt_get_name(blob, offset, NULL))) -			continue; - -		if (fdtdec_get_int(blob, offset, "nvidia,ram-code", -1) -				== ram_code) -			return offset; -	} while (1); - -	debug("%s: Could not find tables for RAM code %d\n", __func__, -	      ram_code); -	return ERR_RAM_CODE_NOT_FOUND; -} - -/** - * Decode the EMC node of the device tree, returning a pointer to the emc - * controller and the table to be used for the given rate. - * - * @param blob	Device tree blob - * @param rate	Clock speed of memory controller in Hz (=2x memory bus rate) - * @param emcp	Returns address of EMC controller registers - * @param tablep Returns pointer to table to program into EMC. There are - *		TEGRA_EMC_NUM_REGS entries, destined for offsets as per the - *		emc_reg_addr array. - * @return 0 if ok, otherwise a -ve error code which will allow someone to - * figure out roughly what went wrong by looking at this code. - */ -static int decode_emc(const void *blob, unsigned rate, struct emc_ctlr **emcp, -		      const u32 **tablep) -{ -	struct apb_misc_pp_ctlr *pp = -		(struct apb_misc_pp_ctlr *)NV_PA_APB_MISC_BASE; -	int ram_code; -	int depth; -	int node; - -	ram_code = (readl(&pp->strapping_opt_a) & RAM_CODE_MASK) -			>> RAM_CODE_SHIFT; -	/* -	 * The EMC clock rate is twice the bus rate, and the bus rate is -	 * measured in kHz -	 */ -	rate = rate / 2 / 1000; - -	node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_EMC); -	if (node < 0) { -		debug("%s: No EMC node found in FDT\n", __func__); -		return ERR_NO_EMC_NODE; -	} -	*emcp = (struct emc_ctlr *)fdtdec_get_addr(blob, node, "reg"); -	if (*emcp == (struct emc_ctlr *)FDT_ADDR_T_NONE) { -		debug("%s: No EMC node reg property\n", __func__); -		return ERR_NO_EMC_REG; -	} - -	/* Work out the parent node which contains our EMC tables */ -	node = find_emc_tables(blob, node, ram_code & 3); -	if (node < 0) -		return node; - -	depth = 0; -	for (;;) { -		int node_rate; - -		node = fdtdec_next_compatible_subnode(blob, node, -				COMPAT_NVIDIA_TEGRA20_EMC_TABLE, &depth); -		if (node < 0) -			break; -		node_rate = fdtdec_get_int(blob, node, "clock-frequency", -1); -		if (node_rate == -1) { -			debug("%s: Missing clock-frequency\n", __func__); -			return ERR_NO_FREQ; /* we expect this property */ -		} - -		if (node_rate == rate) -			break; -	} -	if (node < 0) { -		debug("%s: No node found for clock frequency %d\n", __func__, -		      rate); -		return ERR_FREQ_NOT_FOUND; -	} - -	*tablep = fdtdec_locate_array(blob, node, "nvidia,emc-registers", -				      TEGRA_EMC_NUM_REGS); -	if (!*tablep) { -		debug("%s: node '%s' array missing / wrong size\n", __func__, -		      fdt_get_name(blob, node, NULL)); -		return ERR_BAD_REGS; -	} - -	/* All seems well */ -	return 0; -} - -int tegra_set_emc(const void *blob, unsigned rate) -{ -	struct emc_ctlr *emc; -	const u32 *table; -	int err, i; - -	err = decode_emc(blob, rate, &emc, &table); -	if (err) { -		debug("Warning: no valid EMC (%d), memory timings unset\n", -		       err); -		return err; -	} - -	debug("%s: Table found, setting EMC values as follows:\n", __func__); -	for (i = 0; i < TEGRA_EMC_NUM_REGS; i++) { -		u32 value = fdt32_to_cpu(table[i]); -		u32 addr = (uintptr_t)emc + emc_reg_addr[i]; - -		debug("   %#x: %#x\n", addr, value); -		writel(value, addr); -	} - -	/* trigger emc with new settings */ -	clock_adjust_periph_pll_div(PERIPH_ID_EMC, CLOCK_ID_MEMORY, -				clock_get_rate(CLOCK_ID_MEMORY), NULL); -	debug("EMC clock set to %lu\n", -	      clock_get_periph_rate(PERIPH_ID_EMC, CLOCK_ID_MEMORY)); - -	return 0; -} diff --git a/arch/arm/cpu/armv7/tegra2/funcmux.c b/arch/arm/cpu/armv7/tegra2/funcmux.c deleted file mode 100644 index 4a31a4cf0..000000000 --- a/arch/arm/cpu/armv7/tegra2/funcmux.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -/* Tegra2 high-level function multiplexing */ -#include <common.h> -#include <asm/arch/clock.h> -#include <asm/arch/funcmux.h> -#include <asm/arch/pinmux.h> - -int funcmux_select(enum periph_id id, int config) -{ -	int bad_config = config != FUNCMUX_DEFAULT; - -	switch (id) { -	case PERIPH_ID_UART1: -		switch (config) { -		case FUNCMUX_UART1_IRRX_IRTX: -			pinmux_set_func(PINGRP_IRRX, PMUX_FUNC_UARTA); -			pinmux_set_func(PINGRP_IRTX, PMUX_FUNC_UARTA); -			pinmux_tristate_disable(PINGRP_IRRX); -			pinmux_tristate_disable(PINGRP_IRTX); -			break; -		case FUNCMUX_UART1_UAA_UAB: -			pinmux_set_func(PINGRP_UAA, PMUX_FUNC_UARTA); -			pinmux_set_func(PINGRP_UAB, PMUX_FUNC_UARTA); -			pinmux_tristate_disable(PINGRP_UAA); -			pinmux_tristate_disable(PINGRP_UAB); -			bad_config = 0; -			break; -		case FUNCMUX_UART1_GPU: -			pinmux_set_func(PINGRP_GPU, PMUX_FUNC_UARTA); -			pinmux_tristate_disable(PINGRP_GPU); -			bad_config = 0; -			break; -		case FUNCMUX_UART1_SDIO1: -			pinmux_set_func(PINGRP_SDIO1, PMUX_FUNC_UARTA); -			pinmux_tristate_disable(PINGRP_SDIO1); -			bad_config = 0; -			break; -		} -		if (!bad_config) { -			/* -			 * Tegra appears to boot with function UARTA pre- -			 * selected on mux group SDB. If two mux groups are -			 * both set to the same function, it's unclear which -			 * group's pins drive the RX signals into the HW. -			 * For UARTA, SDB certainly overrides group IRTX in -			 * practice. To solve this, configure some alternative -			 * function on SDB to avoid the conflict. Also, tri- -			 * state the group to avoid driving any signal onto it -			 * until we know what's connected. -			 */ -			pinmux_tristate_enable(PINGRP_SDB); -			pinmux_set_func(PINGRP_SDB,  PMUX_FUNC_SDIO3); -		} -		break; - -	case PERIPH_ID_UART2: -		if (config == FUNCMUX_UART2_IRDA) { -			pinmux_set_func(PINGRP_UAD, PMUX_FUNC_IRDA); -			pinmux_tristate_disable(PINGRP_UAD); -		} -		break; - -	case PERIPH_ID_UART4: -		if (config == FUNCMUX_UART4_GMC) { -			pinmux_set_func(PINGRP_GMC, PMUX_FUNC_UARTD); -			pinmux_tristate_disable(PINGRP_GMC); -		} -		break; - -	case PERIPH_ID_DVC_I2C: -		/* there is only one selection, pinmux_config is ignored */ -		if (config == FUNCMUX_DVC_I2CP) { -			pinmux_set_func(PINGRP_I2CP, PMUX_FUNC_I2C); -			pinmux_tristate_disable(PINGRP_I2CP); -		} -		break; - -	case PERIPH_ID_I2C1: -		/* support pinmux_config of 0 for now, */ -		if (config == FUNCMUX_I2C1_RM) { -			pinmux_set_func(PINGRP_RM, PMUX_FUNC_I2C); -			pinmux_tristate_disable(PINGRP_RM); -		} -		break; -	case PERIPH_ID_I2C2: /* I2C2 */ -		switch (config) { -		case FUNCMUX_I2C2_DDC:	/* DDC pin group, select I2C2 */ -			pinmux_set_func(PINGRP_DDC, PMUX_FUNC_I2C2); -			/* PTA to HDMI */ -			pinmux_set_func(PINGRP_PTA, PMUX_FUNC_HDMI); -			pinmux_tristate_disable(PINGRP_DDC); -			break; -		case FUNCMUX_I2C2_PTA:	/* PTA pin group, select I2C2 */ -			pinmux_set_func(PINGRP_PTA, PMUX_FUNC_I2C2); -			/* set DDC_SEL to RSVDx (RSVD2 works for now) */ -			pinmux_set_func(PINGRP_DDC, PMUX_FUNC_RSVD2); -			pinmux_tristate_disable(PINGRP_PTA); -			bad_config = 0; -			break; -		} -		break; -	case PERIPH_ID_I2C3: /* I2C3 */ -		/* support pinmux_config of 0 for now */ -		if (config == FUNCMUX_I2C3_DTF) { -			pinmux_set_func(PINGRP_DTF, PMUX_FUNC_I2C3); -			pinmux_tristate_disable(PINGRP_DTF); -		} -		break; - -	case PERIPH_ID_SDMMC1: -		if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) { -			pinmux_set_func(PINGRP_SDIO1, PMUX_FUNC_SDIO1); -			pinmux_tristate_disable(PINGRP_SDIO1); -		} -		break; - -	case PERIPH_ID_SDMMC2: -		if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) { -			pinmux_set_func(PINGRP_DTA, PMUX_FUNC_SDIO2); -			pinmux_set_func(PINGRP_DTD, PMUX_FUNC_SDIO2); - -			pinmux_tristate_disable(PINGRP_DTA); -			pinmux_tristate_disable(PINGRP_DTD); -		} -		break; - -	case PERIPH_ID_SDMMC3: -		switch (config) { -		case FUNCMUX_SDMMC3_SDB_SLXA_8BIT: -			pinmux_set_func(PINGRP_SLXA, PMUX_FUNC_SDIO3); -			pinmux_set_func(PINGRP_SLXC, PMUX_FUNC_SDIO3); -			pinmux_set_func(PINGRP_SLXD, PMUX_FUNC_SDIO3); -			pinmux_set_func(PINGRP_SLXK, PMUX_FUNC_SDIO3); - -			pinmux_tristate_disable(PINGRP_SLXA); -			pinmux_tristate_disable(PINGRP_SLXC); -			pinmux_tristate_disable(PINGRP_SLXD); -			pinmux_tristate_disable(PINGRP_SLXK); -			/* fall through */ - -		case FUNCMUX_SDMMC3_SDB_4BIT: -			pinmux_set_func(PINGRP_SDB, PMUX_FUNC_SDIO3); -			pinmux_set_func(PINGRP_SDC, PMUX_FUNC_SDIO3); -			pinmux_set_func(PINGRP_SDD, PMUX_FUNC_SDIO3); - -			pinmux_tristate_disable(PINGRP_SDB); -			pinmux_tristate_disable(PINGRP_SDC); -			pinmux_tristate_disable(PINGRP_SDD); -			bad_config = 0; -			break; -		} -		break; - -	case PERIPH_ID_SDMMC4: -		switch (config) { -		case FUNCMUX_SDMMC4_ATC_ATD_8BIT: -			pinmux_set_func(PINGRP_ATC, PMUX_FUNC_SDIO4); -			pinmux_set_func(PINGRP_ATD, PMUX_FUNC_SDIO4); - -			pinmux_tristate_disable(PINGRP_ATC); -			pinmux_tristate_disable(PINGRP_ATD); -			break; - -		case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT: -			pinmux_set_func(PINGRP_GME, PMUX_FUNC_SDIO4); -			pinmux_tristate_disable(PINGRP_GME); -			/* fall through */ - -		case FUNCMUX_SDMMC4_ATB_GMA_4_BIT: -			pinmux_set_func(PINGRP_ATB, PMUX_FUNC_SDIO4); -			pinmux_set_func(PINGRP_GMA, PMUX_FUNC_SDIO4); - -			pinmux_tristate_disable(PINGRP_ATB); -			pinmux_tristate_disable(PINGRP_GMA); -			bad_config = 0; -			break; -		} -		break; - -	case PERIPH_ID_KBC: -		if (config == FUNCMUX_DEFAULT) { -			enum pmux_pingrp grp[] = {PINGRP_KBCA, PINGRP_KBCB, -				PINGRP_KBCC, PINGRP_KBCD, PINGRP_KBCE, -				PINGRP_KBCF}; -			int i; - -			for (i = 0; i < ARRAY_SIZE(grp); i++) { -				pinmux_tristate_disable(grp[i]); -				pinmux_set_func(grp[i], PMUX_FUNC_KBC); -				pinmux_set_pullupdown(grp[i], PMUX_PULL_UP); -			} -		} -		break; - -	case PERIPH_ID_USB2: -		if (config == FUNCMUX_USB2_ULPI) { -			pinmux_set_func(PINGRP_UAA, PMUX_FUNC_ULPI); -			pinmux_set_func(PINGRP_UAB, PMUX_FUNC_ULPI); -			pinmux_set_func(PINGRP_UDA, PMUX_FUNC_ULPI); - -			pinmux_tristate_disable(PINGRP_UAA); -			pinmux_tristate_disable(PINGRP_UAB); -			pinmux_tristate_disable(PINGRP_UDA); -		} -		break; - -	case PERIPH_ID_SPI1: -		if (config == FUNCMUX_SPI1_GMC_GMD) { -			pinmux_set_func(PINGRP_GMC, PMUX_FUNC_SFLASH); -			pinmux_set_func(PINGRP_GMD, PMUX_FUNC_SFLASH); - -			pinmux_tristate_disable(PINGRP_GMC); -			pinmux_tristate_disable(PINGRP_GMD); -		} -		break; - -	default: -		debug("%s: invalid periph_id %d", __func__, id); -		return -1; -	} - -	if (bad_config) { -		debug("%s: invalid config %d for periph_id %d", __func__, -		      config, id); -		return -1; -	} - -	return 0; -} diff --git a/arch/arm/cpu/armv7/tegra2/pinmux.c b/arch/arm/cpu/armv7/tegra2/pinmux.c deleted file mode 100644 index b053f9060..000000000 --- a/arch/arm/cpu/armv7/tegra2/pinmux.c +++ /dev/null @@ -1,572 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -/* Tegra2 pin multiplexing functions */ - -#include <asm/io.h> -#include <asm/arch/tegra2.h> -#include <asm/arch/pinmux.h> -#include <common.h> - - -/* - * This defines the order of the pin mux control bits in the registers. For - * some reason there is no correspendence between the tristate, pin mux and - * pullup/pulldown registers. - */ -enum pmux_ctlid { -	/* 0: APB_MISC_PP_PIN_MUX_CTL_A_0 */ -	MUXCTL_UAA, -	MUXCTL_UAB, -	MUXCTL_UAC, -	MUXCTL_UAD, -	MUXCTL_UDA, -	MUXCTL_RESERVED5, -	MUXCTL_ATE, -	MUXCTL_RM, - -	MUXCTL_ATB, -	MUXCTL_RESERVED9, -	MUXCTL_ATD, -	MUXCTL_ATC, -	MUXCTL_ATA, -	MUXCTL_KBCF, -	MUXCTL_KBCE, -	MUXCTL_SDMMC1, - -	/* 16: APB_MISC_PP_PIN_MUX_CTL_B_0 */ -	MUXCTL_GMA, -	MUXCTL_GMC, -	MUXCTL_HDINT, -	MUXCTL_SLXA, -	MUXCTL_OWC, -	MUXCTL_SLXC, -	MUXCTL_SLXD, -	MUXCTL_SLXK, - -	MUXCTL_UCA, -	MUXCTL_UCB, -	MUXCTL_DTA, -	MUXCTL_DTB, -	MUXCTL_RESERVED28, -	MUXCTL_DTC, -	MUXCTL_DTD, -	MUXCTL_DTE, - -	/* 32: APB_MISC_PP_PIN_MUX_CTL_C_0 */ -	MUXCTL_DDC, -	MUXCTL_CDEV1, -	MUXCTL_CDEV2, -	MUXCTL_CSUS, -	MUXCTL_I2CP, -	MUXCTL_KBCA, -	MUXCTL_KBCB, -	MUXCTL_KBCC, - -	MUXCTL_IRTX, -	MUXCTL_IRRX, -	MUXCTL_DAP1, -	MUXCTL_DAP2, -	MUXCTL_DAP3, -	MUXCTL_DAP4, -	MUXCTL_GMB, -	MUXCTL_GMD, - -	/* 48: APB_MISC_PP_PIN_MUX_CTL_D_0 */ -	MUXCTL_GME, -	MUXCTL_GPV, -	MUXCTL_GPU, -	MUXCTL_SPDO, -	MUXCTL_SPDI, -	MUXCTL_SDB, -	MUXCTL_SDC, -	MUXCTL_SDD, - -	MUXCTL_SPIH, -	MUXCTL_SPIG, -	MUXCTL_SPIF, -	MUXCTL_SPIE, -	MUXCTL_SPID, -	MUXCTL_SPIC, -	MUXCTL_SPIB, -	MUXCTL_SPIA, - -	/* 64: APB_MISC_PP_PIN_MUX_CTL_E_0 */ -	MUXCTL_LPW0, -	MUXCTL_LPW1, -	MUXCTL_LPW2, -	MUXCTL_LSDI, -	MUXCTL_LSDA, -	MUXCTL_LSPI, -	MUXCTL_LCSN, -	MUXCTL_LDC, - -	MUXCTL_LSCK, -	MUXCTL_LSC0, -	MUXCTL_LSC1, -	MUXCTL_LHS, -	MUXCTL_LVS, -	MUXCTL_LM0, -	MUXCTL_LM1, -	MUXCTL_LVP0, - -	/* 80: APB_MISC_PP_PIN_MUX_CTL_F_0 */ -	MUXCTL_LD0, -	MUXCTL_LD1, -	MUXCTL_LD2, -	MUXCTL_LD3, -	MUXCTL_LD4, -	MUXCTL_LD5, -	MUXCTL_LD6, -	MUXCTL_LD7, - -	MUXCTL_LD8, -	MUXCTL_LD9, -	MUXCTL_LD10, -	MUXCTL_LD11, -	MUXCTL_LD12, -	MUXCTL_LD13, -	MUXCTL_LD14, -	MUXCTL_LD15, - -	/* 96: APB_MISC_PP_PIN_MUX_CTL_G_0 */ -	MUXCTL_LD16, -	MUXCTL_LD17, -	MUXCTL_LHP1, -	MUXCTL_LHP2, -	MUXCTL_LVP1, -	MUXCTL_LHP0, -	MUXCTL_RESERVED102, -	MUXCTL_LPP, - -	MUXCTL_LDI, -	MUXCTL_PMC, -	MUXCTL_CRTP, -	MUXCTL_PTA, -	MUXCTL_RESERVED108, -	MUXCTL_KBCD, -	MUXCTL_GPU7, -	MUXCTL_DTF, - -	MUXCTL_NONE = -1, -}; - -/* - * And this defines the order of the pullup/pulldown controls which are again - * in a different order - */ -enum pmux_pullid { -	/* 0: APB_MISC_PP_PULLUPDOWN_REG_A_0 */ -	PUCTL_ATA, -	PUCTL_ATB, -	PUCTL_ATC, -	PUCTL_ATD, -	PUCTL_ATE, -	PUCTL_DAP1, -	PUCTL_DAP2, -	PUCTL_DAP3, - -	PUCTL_DAP4, -	PUCTL_DTA, -	PUCTL_DTB, -	PUCTL_DTC, -	PUCTL_DTD, -	PUCTL_DTE, -	PUCTL_DTF, -	PUCTL_GPV, - -	/* 16: APB_MISC_PP_PULLUPDOWN_REG_B_0 */ -	PUCTL_RM, -	PUCTL_I2CP, -	PUCTL_PTA, -	PUCTL_GPU7, -	PUCTL_KBCA, -	PUCTL_KBCB, -	PUCTL_KBCC, -	PUCTL_KBCD, - -	PUCTL_SPDI, -	PUCTL_SPDO, -	PUCTL_GPSLXAU, -	PUCTL_CRTP, -	PUCTL_SLXC, -	PUCTL_SLXD, -	PUCTL_SLXK, - -	/* 32: APB_MISC_PP_PULLUPDOWN_REG_C_0 */ -	PUCTL_CDEV1, -	PUCTL_CDEV2, -	PUCTL_SPIA, -	PUCTL_SPIB, -	PUCTL_SPIC, -	PUCTL_SPID, -	PUCTL_SPIE, -	PUCTL_SPIF, - -	PUCTL_SPIG, -	PUCTL_SPIH, -	PUCTL_IRTX, -	PUCTL_IRRX, -	PUCTL_GME, -	PUCTL_RESERVED45, -	PUCTL_XM2D, -	PUCTL_XM2C, - -	/* 48: APB_MISC_PP_PULLUPDOWN_REG_D_0 */ -	PUCTL_UAA, -	PUCTL_UAB, -	PUCTL_UAC, -	PUCTL_UAD, -	PUCTL_UCA, -	PUCTL_UCB, -	PUCTL_LD17, -	PUCTL_LD19_18, - -	PUCTL_LD21_20, -	PUCTL_LD23_22, -	PUCTL_LS, -	PUCTL_LC, -	PUCTL_CSUS, -	PUCTL_DDRC, -	PUCTL_SDC, -	PUCTL_SDD, - -	/* 64: APB_MISC_PP_PULLUPDOWN_REG_E_0 */ -	PUCTL_KBCF, -	PUCTL_KBCE, -	PUCTL_PMCA, -	PUCTL_PMCB, -	PUCTL_PMCC, -	PUCTL_PMCD, -	PUCTL_PMCE, -	PUCTL_CK32, - -	PUCTL_UDA, -	PUCTL_SDMMC1, -	PUCTL_GMA, -	PUCTL_GMB, -	PUCTL_GMC, -	PUCTL_GMD, -	PUCTL_DDC, -	PUCTL_OWC, - -	PUCTL_NONE = -1 -}; - -struct tegra_pingroup_desc { -	const char *name; -	enum pmux_func funcs[4]; -	enum pmux_func func_safe; -	enum pmux_vddio vddio; -	enum pmux_ctlid ctl_id; -	enum pmux_pullid pull_id; -}; - - -/* Converts a pmux_pingrp number to a tristate register: 0=A, 1=B, 2=C, 3=D */ -#define TRISTATE_REG(pmux_pingrp) ((pmux_pingrp) >> 5) - -/* Mask value for a tristate (within TRISTATE_REG(id)) */ -#define TRISTATE_MASK(pmux_pingrp) (1 << ((pmux_pingrp) & 0x1f)) - -/* Converts a PUCTL id to a pull register: 0=A, 1=B...4=E */ -#define PULL_REG(pmux_pullid) ((pmux_pullid) >> 4) - -/* Converts a PUCTL id to a shift position */ -#define PULL_SHIFT(pmux_pullid) ((pmux_pullid << 1) & 0x1f) - -/* Converts a MUXCTL id to a ctl register: 0=A, 1=B...6=G */ -#define MUXCTL_REG(pmux_ctlid) ((pmux_ctlid) >> 4) - -/* Converts a MUXCTL id to a shift position */ -#define MUXCTL_SHIFT(pmux_ctlid) ((pmux_ctlid << 1) & 0x1f) - -/* Convenient macro for defining pin group properties */ -#define PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe, mux, pupd)		\ -	{						\ -		.vddio = PMUX_VDDIO_ ## vdd,		\ -		.funcs = {				\ -			PMUX_FUNC_ ## f0,			\ -			PMUX_FUNC_ ## f1,			\ -			PMUX_FUNC_ ## f2,			\ -			PMUX_FUNC_ ## f3,			\ -		},					\ -		.func_safe = PMUX_FUNC_ ## f_safe,		\ -		.ctl_id = mux,				\ -		.pull_id = pupd				\ -	} - -/* A normal pin group where the mux name and pull-up name match */ -#define PIN(pg_name, vdd, f0, f1, f2, f3, f_safe)		\ -		PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe,	\ -			MUXCTL_ ## pg_name, PUCTL_ ## pg_name) - -/* A pin group where the pull-up name doesn't have a 1-1 mapping */ -#define PINP(pg_name, vdd, f0, f1, f2, f3, f_safe, pupd)		\ -		PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe,	\ -			MUXCTL_ ## pg_name, PUCTL_ ## pupd) - -/* A pin group number which is not used */ -#define PIN_RESERVED \ -	PIN(NONE, NONE, NONE, NONE, NONE, NONE, NONE) - -const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = { -	PIN(ATA,  NAND,  IDE,    NAND,   GMI,       RSVD,        IDE), -	PIN(ATB,  NAND,  IDE,    NAND,   GMI,       SDIO4,       IDE), -	PIN(ATC,  NAND,  IDE,    NAND,   GMI,       SDIO4,       IDE), -	PIN(ATD,  NAND,  IDE,    NAND,   GMI,       SDIO4,       IDE), -	PIN(CDEV1, AUDIO, OSC,   PLLA_OUT, PLLM_OUT1, AUDIO_SYNC, OSC), -	PIN(CDEV2, AUDIO, OSC,   AHB_CLK, APB_CLK, PLLP_OUT4,    OSC), -	PIN(CSUS, VI, PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, -		PLLC_OUT1), -	PIN(DAP1, AUDIO, DAP1,   RSVD,   GMI,       SDIO2,       DAP1), - -	PIN(DAP2, AUDIO, DAP2,   TWC,    RSVD,      GMI,         DAP2), -	PIN(DAP3, BB,    DAP3,   RSVD,   RSVD,      RSVD,        DAP3), -	PIN(DAP4, UART,  DAP4,   RSVD,   GMI,       RSVD,        DAP4), -	PIN(DTA,  VI,    RSVD,   SDIO2,  VI,        RSVD,        RSVD4), -	PIN(DTB,  VI,    RSVD,   RSVD,   VI,        SPI1,        RSVD1), -	PIN(DTC,  VI,    RSVD,   RSVD,   VI,        RSVD,        RSVD1), -	PIN(DTD,  VI,    RSVD,   SDIO2,  VI,        RSVD,        RSVD1), -	PIN(DTE,  VI,    RSVD,   RSVD,   VI,        SPI1,        RSVD1), - -	PINP(GPU, UART,  PWM,    UARTA,  GMI,       RSVD,        RSVD4, -		GPSLXAU), -	PIN(GPV,  SD,    PCIE,   RSVD,   RSVD,      RSVD,        PCIE), -	PIN(I2CP, SYS,   I2C,    RSVD,   RSVD,      RSVD,        RSVD4), -	PIN(IRTX, UART,  UARTA,  UARTB,  GMI,       SPI4,        UARTB), -	PIN(IRRX, UART,  UARTA,  UARTB,  GMI,       SPI4,        UARTB), -	PIN(KBCB, SYS,   KBC,    NAND,   SDIO2,     MIO,         KBC), -	PIN(KBCA, SYS,   KBC,    NAND,   SDIO2,     EMC_TEST0_DLL, KBC), -	PINP(PMC, SYS,   PWR_ON, PWR_INTR, RSVD,    RSVD,        PWR_ON, NONE), - -	PIN(PTA,  NAND,  I2C2,   HDMI,   GMI,       RSVD,        RSVD4), -	PIN(RM,   UART,  I2C,    RSVD,   RSVD,      RSVD,        RSVD4), -	PIN(KBCE, SYS,   KBC,    NAND,   OWR,       RSVD,        KBC), -	PIN(KBCF, SYS,   KBC,    NAND,   TRACE,     MIO,         KBC), -	PIN(GMA,  NAND,  UARTE,  SPI3,   GMI,       SDIO4,       SPI3), -	PIN(GMC,  NAND,  UARTD,  SPI4,   GMI,       SFLASH,      SPI4), -	PIN(SDMMC1, BB,  SDIO1,  RSVD,   UARTE,     UARTA,       RSVD2), -	PIN(OWC,  SYS,   OWR,    RSVD,   RSVD,      RSVD,        OWR), - -	PIN(GME,  NAND,  RSVD,   DAP5,   GMI,       SDIO4,       GMI), -	PIN(SDC,  SD,    PWM,    TWC,    SDIO3,     SPI3,        TWC), -	PIN(SDD,  SD,    UARTA,  PWM,    SDIO3,     SPI3,        PWM), -	PIN_RESERVED, -	PINP(SLXA, SD,   PCIE,   SPI4,   SDIO3,     SPI2,        PCIE, CRTP), -	PIN(SLXC, SD,    SPDIF,  SPI4,   SDIO3,     SPI2,        SPI4), -	PIN(SLXD, SD,    SPDIF,  SPI4,   SDIO3,     SPI2,        SPI4), -	PIN(SLXK, SD,    PCIE,   SPI4,   SDIO3,     SPI2,        PCIE), - -	PIN(SPDI, AUDIO, SPDIF,  RSVD,   I2C,       SDIO2,       RSVD2), -	PIN(SPDO, AUDIO, SPDIF,  RSVD,   I2C,       SDIO2,       RSVD2), -	PIN(SPIA, AUDIO, SPI1,   SPI2,   SPI3,      GMI,         GMI), -	PIN(SPIB, AUDIO, SPI1,   SPI2,   SPI3,      GMI,         GMI), -	PIN(SPIC, AUDIO, SPI1,   SPI2,   SPI3,      GMI,         GMI), -	PIN(SPID, AUDIO, SPI2,   SPI1,   SPI2_ALT,  GMI,         GMI), -	PIN(SPIE, AUDIO, SPI2,   SPI1,   SPI2_ALT,  GMI,         GMI), -	PIN(SPIF, AUDIO, SPI3,   SPI1,   SPI2,      RSVD,        RSVD4), - -	PIN(SPIG, AUDIO, SPI3,   SPI2,   SPI2_ALT,  I2C,         SPI2_ALT), -	PIN(SPIH, AUDIO, SPI3,   SPI2,   SPI2_ALT,  I2C,         SPI2_ALT), -	PIN(UAA,  BB,    SPI3,   MIPI_HS, UARTA,    ULPI,        MIPI_HS), -	PIN(UAB,  BB,    SPI2,   MIPI_HS, UARTA,    ULPI,        MIPI_HS), -	PIN(UAC,  BB,    OWR,    RSVD,   RSVD,      RSVD,        RSVD4), -	PIN(UAD,  UART,  IRDA,   SPDIF,  UARTA,     SPI4,        SPDIF), -	PIN(UCA,  UART,  UARTC,  RSVD,   GMI,       RSVD,        RSVD4), -	PIN(UCB,  UART,  UARTC,  PWM,    GMI,       RSVD,        RSVD4), - -	PIN_RESERVED, -	PIN(ATE,  NAND,  IDE,    NAND,   GMI,       RSVD,        IDE), -	PIN(KBCC, SYS,   KBC,    NAND,   TRACE,     EMC_TEST1_DLL, KBC), -	PIN_RESERVED, -	PIN_RESERVED, -	PIN(GMB,  NAND,  IDE,    NAND,   GMI,       GMI_INT,     GMI), -	PIN(GMD,  NAND,  RSVD,   NAND,   GMI,       SFLASH,      GMI), -	PIN(DDC,  LCD,   I2C2,   RSVD,   RSVD,      RSVD,        RSVD4), - -	/* 64 */ -	PINP(LD0,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17), -	PINP(LD1,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17), -	PINP(LD2,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17), -	PINP(LD3,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17), -	PINP(LD4,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17), -	PINP(LD5,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17), -	PINP(LD6,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17), -	PINP(LD7,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17), - -	PINP(LD8,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17), -	PINP(LD9,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17), -	PINP(LD10, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17), -	PINP(LD11, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17), -	PINP(LD12, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17), -	PINP(LD13, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17), -	PINP(LD14, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17), -	PINP(LD15, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17), - -	PINP(LD16, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LD17), -	PINP(LD17, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD17), -	PINP(LHP0, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD21_20), -	PINP(LHP1, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD19_18), -	PINP(LHP2, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD19_18), -	PINP(LVP0, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LC), -	PINP(LVP1, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD21_20), -	PINP(HDINT, LCD, HDMI,   RSVD,   RSVD,      RSVD,     HDMI , LC), - -	PINP(LM0,  LCD,  DISPA,  DISPB,  SPI3,      RSVD,     RSVD4, LC), -	PINP(LM1,  LCD,  DISPA,  DISPB,  RSVD,      CRT,      RSVD3, LC), -	PINP(LVS,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LC), -	PINP(LSC0, LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LC), -	PINP(LSC1, LCD,  DISPA,  DISPB,  SPI3,      HDMI,     DISPA, LS), -	PINP(LSCK, LCD,  DISPA,  DISPB,  SPI3,      HDMI,     DISPA, LS), -	PINP(LDC,  LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LS), -	PINP(LCSN, LCD,  DISPA,  DISPB,  SPI3,      RSVD,     RSVD4, LS), - -	/* 96 */ -	PINP(LSPI, LCD,  DISPA,  DISPB,  XIO,       HDMI,     DISPA, LC), -	PINP(LSDA, LCD,  DISPA,  DISPB,  SPI3,      HDMI,     DISPA, LS), -	PINP(LSDI, LCD,  DISPA,  DISPB,  SPI3,      RSVD,     DISPA, LS), -	PINP(LPW0, LCD,  DISPA,  DISPB,  SPI3,      HDMI,     DISPA, LS), -	PINP(LPW1, LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LS), -	PINP(LPW2, LCD,  DISPA,  DISPB,  SPI3,      HDMI,     DISPA, LS), -	PINP(LDI,  LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD23_22), -	PINP(LHS,  LCD,  DISPA,  DISPB,  XIO,       RSVD,     RSVD4, LC), - -	PINP(LPP,  LCD,  DISPA,  DISPB,  RSVD,      RSVD,     RSVD4, LD23_22), -	PIN_RESERVED, -	PIN(KBCD,  SYS,  KBC,    NAND,   SDIO2,     MIO,      KBC), -	PIN(GPU7,  SYS,  RTCK,   RSVD,   RSVD,      RSVD,     RTCK), -	PIN(DTF,   VI,   I2C3,   RSVD,   VI,        RSVD,     RSVD4), -	PIN(UDA,   BB,   SPI1,   RSVD,   UARTD,     ULPI,     RSVD2), -	PIN(CRTP,  LCD,  CRT,    RSVD,   RSVD,      RSVD,     RSVD), -	PINP(SDB,  SD,   UARTA,  PWM,    SDIO3,     SPI2,     PWM,   NONE), - -	/* these pin groups only have pullup and pull down control */ -	PINALL(CK32,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE, -		PUCTL_NONE), -	PINALL(DDRC,  DDR,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE, -		PUCTL_NONE), -	PINALL(PMCA,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE, -		PUCTL_NONE), -	PINALL(PMCB,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE, -		PUCTL_NONE), -	PINALL(PMCC,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE, -		PUCTL_NONE), -	PINALL(PMCD,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE, -		PUCTL_NONE), -	PINALL(PMCE,  SYS,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE, -		PUCTL_NONE), -	PINALL(XM2C,  DDR,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE, -		PUCTL_NONE), -	PINALL(XM2D,  DDR,   RSVD, RSVD, RSVD, RSVD,  RSVD, MUXCTL_NONE, -		PUCTL_NONE), -}; - -void pinmux_set_tristate(enum pmux_pingrp pin, int enable) -{ -	struct pmux_tri_ctlr *pmt = -			(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; -	u32 *tri = &pmt->pmt_tri[TRISTATE_REG(pin)]; -	u32 reg; - -	reg = readl(tri); -	if (enable) -		reg |= TRISTATE_MASK(pin); -	else -		reg &= ~TRISTATE_MASK(pin); -	writel(reg, tri); -} - -void pinmux_tristate_enable(enum pmux_pingrp pin) -{ -	pinmux_set_tristate(pin, 1); -} - -void pinmux_tristate_disable(enum pmux_pingrp pin) -{ -	pinmux_set_tristate(pin, 0); -} - -void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd) -{ -	struct pmux_tri_ctlr *pmt = -			(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; -	enum pmux_pullid pull_id = tegra_soc_pingroups[pin].pull_id; -	u32 *pull = &pmt->pmt_pull[PULL_REG(pull_id)]; -	u32 mask_bit; -	u32 reg; -	mask_bit = PULL_SHIFT(pull_id); - -	reg = readl(pull); -	reg &= ~(0x3 << mask_bit); -	reg |= pupd << mask_bit; -	writel(reg, pull); -} - -void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func) -{ -	struct pmux_tri_ctlr *pmt = -			(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; -	enum pmux_ctlid mux_id = tegra_soc_pingroups[pin].ctl_id; -	u32 *muxctl = &pmt->pmt_ctl[MUXCTL_REG(mux_id)]; -	u32 mask_bit; -	int i, mux = -1; -	u32 reg; - -	assert(pmux_func_isvalid(func)); - -	/* Handle special values */ -	if (func >= PMUX_FUNC_RSVD1) { -		mux = (func - PMUX_FUNC_RSVD1) & 0x3; -	} else { -		/* Search for the appropriate function */ -		for (i = 0; i < 4; i++) { -			if (tegra_soc_pingroups[pin].funcs[i] == func) { -				mux = i; -				break; -			} -		} -	} -	assert(mux != -1); - -	mask_bit = MUXCTL_SHIFT(mux_id); -	reg = readl(muxctl); -	reg &= ~(0x3 << mask_bit); -	reg |= mux << mask_bit; -	writel(reg, muxctl); -} - -void pinmux_config_pingroup(struct pingroup_config *config) -{ -	enum pmux_pingrp pin = config->pingroup; - -	pinmux_set_func(pin, config->func); -	pinmux_set_pullupdown(pin, config->pull); -	pinmux_set_tristate(pin, config->tristate); -} - -void pinmux_config_table(struct pingroup_config *config, int len) -{ -	int i; - -	for (i = 0; i < len; i++) -		pinmux_config_pingroup(&config[i]); -} diff --git a/arch/arm/cpu/armv7/tegra2/pmu.c b/arch/arm/cpu/armv7/tegra2/pmu.c deleted file mode 100644 index 46738023f..000000000 --- a/arch/arm/cpu/armv7/tegra2/pmu.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * (C) Copyright 2010,2011 NVIDIA Corporation <www.nvidia.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <tps6586x.h> -#include <asm/io.h> -#include <asm/arch/ap20.h> -#include <asm/arch/tegra2.h> -#include <asm/arch/tegra_i2c.h> -#include <asm/arch/sys_proto.h> - -#define VDD_CORE_NOMINAL_T25	0x17	/* 1.3v */ -#define VDD_CPU_NOMINAL_T25	0x10	/* 1.125v */ - -#define VDD_CORE_NOMINAL_T20	0x16	/* 1.275v */ -#define VDD_CPU_NOMINAL_T20	0x0f	/* 1.1v */ - -#define VDD_RELATION		0x02	/*  50mv */ -#define VDD_TRANSITION_STEP	0x06	/* 150mv */ -#define VDD_TRANSITION_RATE	0x06	/* 3.52mv/us */ - -int pmu_set_nominal(void) -{ -	int core, cpu, bus; - -	/* by default, the table has been filled with T25 settings */ -	switch (tegra_get_chip_type()) { -	case TEGRA_SOC_T20: -		core = VDD_CORE_NOMINAL_T20; -		cpu = VDD_CPU_NOMINAL_T20; -		break; -	case TEGRA_SOC_T25: -		core = VDD_CORE_NOMINAL_T25; -		cpu = VDD_CPU_NOMINAL_T25; -		break; -	default: -		debug("%s: Unknown chip type\n", __func__); -		return -1; -	} - -	bus = tegra_i2c_get_dvc_bus_num(); -	if (bus == -1) { -		debug("%s: Cannot find DVC I2C bus\n", __func__); -		return -1; -	} -	tps6586x_init(bus); -	tps6586x_set_pwm_mode(TPS6586X_PWM_SM1); -	return tps6586x_adjust_sm0_sm1(core, cpu, VDD_TRANSITION_STEP, -				VDD_TRANSITION_RATE, VDD_RELATION); -} diff --git a/arch/arm/cpu/armv7/tegra2/sys_info.c b/arch/arm/cpu/armv7/tegra2/sys_info.c deleted file mode 100644 index 6d11dc16b..000000000 --- a/arch/arm/cpu/armv7/tegra2/sys_info.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * (C) Copyright 2010,2011 - * NVIDIA Corporation <www.nvidia.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> - -#ifdef CONFIG_DISPLAY_CPUINFO -/* Print CPU information */ -int print_cpuinfo(void) -{ -	puts("TEGRA2\n"); - -	/* TBD: Add printf of major/minor rev info, stepping, etc. */ -	return 0; -} -#endif	/* CONFIG_DISPLAY_CPUINFO */ diff --git a/arch/arm/cpu/armv7/tegra2/timer.c b/arch/arm/cpu/armv7/tegra2/timer.c deleted file mode 100644 index b12b12cc3..000000000 --- a/arch/arm/cpu/armv7/tegra2/timer.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * (C) Copyright 2010,2011 - * NVIDIA Corporation <www.nvidia.com> - * - * (C) Copyright 2008 - * Texas Instruments - * - * Richard Woodruff <r-woodruff2@ti.com> - * Syed Moahmmed Khasim <khasim@ti.com> - * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH <www.elinos.com> - * Marius Groeger <mgroeger@sysgo.de> - * Alex Zuepke <azu@sysgo.de> - * - * (C) Copyright 2002 - * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/io.h> -#include <asm/arch/tegra2.h> -#include <asm/arch/timer.h> - -DECLARE_GLOBAL_DATA_PTR; - -/* counter runs at 1MHz */ -#define TIMER_CLK	1000000 -#define TIMER_LOAD_VAL	0xffffffff - -/* timer without interrupts */ -ulong get_timer(ulong base) -{ -	return get_timer_masked() - base; -} - -/* delay x useconds */ -void __udelay(unsigned long usec) -{ -	long tmo = usec * (TIMER_CLK / 1000) / 1000; -	unsigned long now, last = timer_get_us(); - -	while (tmo > 0) { -		now = timer_get_us(); -		if (last > now) /* count up timer overflow */ -			tmo -= TIMER_LOAD_VAL - last + now; -		else -			tmo -= now - last; -		last = now; -	} -} - -ulong get_timer_masked(void) -{ -	ulong now; - -	/* current tick value */ -	now = timer_get_us() / (TIMER_CLK / CONFIG_SYS_HZ); - -	if (now >= gd->lastinc)	/* normal mode (non roll) */ -		/* move stamp forward with absolute diff ticks */ -		gd->tbl += (now - gd->lastinc); -	else	/* we have rollover of incrementer */ -		gd->tbl += ((TIMER_LOAD_VAL / (TIMER_CLK / CONFIG_SYS_HZ)) -				- gd->lastinc) + now; -	gd->lastinc = now; -	return gd->tbl; -} - -/* - * This function is derived from PowerPC code (read timebase as long long). - * On ARM it just returns the timer value. - */ -unsigned long long get_ticks(void) -{ -	return get_timer(0); -} - -/* - * This function is derived from PowerPC code (timebase clock frequency). - * On ARM it returns the number of timer ticks per second. - */ -ulong get_tbclk(void) -{ -	return CONFIG_SYS_HZ; -} - -unsigned long timer_get_us(void) -{ -	struct timerus *timer_base = (struct timerus *)NV_PA_TMRUS_BASE; - -	return readl(&timer_base->cntr_1us); -} diff --git a/arch/arm/cpu/armv7/tegra2/warmboot.c b/arch/arm/cpu/armv7/tegra2/warmboot.c deleted file mode 100644 index 25d896888..000000000 --- a/arch/arm/cpu/armv7/tegra2/warmboot.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * (C) Copyright 2010 - 2011 - * NVIDIA Corporation <www.nvidia.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/io.h> -#include <asm/errno.h> -#include <asm/arch/ap20.h> -#include <asm/arch/clk_rst.h> -#include <asm/arch/clock.h> -#include <asm/arch/pmc.h> -#include <asm/arch/pinmux.h> -#include <asm/arch/tegra2.h> -#include <asm/arch/fuse.h> -#include <asm/arch/emc.h> -#include <asm/arch/gp_padctrl.h> -#include <asm/arch/warmboot.h> -#include <asm/arch/sdram_param.h> - -DECLARE_GLOBAL_DATA_PTR; - -#ifndef CONFIG_TEGRA_CLOCK_SCALING -#error "You must enable CONFIG_TEGRA_CLOCK_SCALING to use CONFIG_TEGRA2_LP0" -#endif - -/* - * This is the place in SRAM where the SDRAM parameters are stored. There - * are 4 blocks, one for each RAM code - */ -#define SDRAM_PARAMS_BASE	(AP20_BASE_PA_SRAM + 0x188) - -/* TODO: If we later add support for the Misc GP controller, refactor this */ -union xm2cfga_reg { -	struct { -		u32 reserved0:2; -		u32 hsm_en:1; -		u32 reserved1:2; -		u32 preemp_en:1; -		u32 vref_en:1; -		u32 reserved2:5; -		u32 cal_drvdn:5; -		u32 reserved3:3; -		u32 cal_drvup:5; -		u32 reserved4:3; -		u32 cal_drvdn_slwr:2; -		u32 cal_drvup_slwf:2; -	}; -	u32 word; -}; - -union xm2cfgd_reg { -	struct { -		u32 reserved0:2; -		u32 hsm_en:1; -		u32 schmt_en:1; -		u32 lpmd:2; -		u32 vref_en:1; -		u32 reserved1:5; -		u32 cal_drvdn:5; -		u32 reserved2:3; -		u32 cal_drvup:5; -		u32 reserved3:3; -		u32 cal_drvdn_slwr:2; -		u32 cal_drvup_slwf:2; -	}; -	u32 word; -}; - -/* - * TODO: This register is not documented in the TRM yet. We could move this - * into the EMC and give it a proper interface, but not while it is - * undocumented. - */ -union fbio_spare_reg { -	struct { -		u32 reserved:24; -		u32 cfg_wb0:8; -	}; -	u32 word; -}; - -/* We pack the resume information into these unions for later */ -union scratch2_reg { -	struct { -		u32 pllm_base_divm:5; -		u32 pllm_base_divn:10; -		u32 pllm_base_divp:3; -		u32 pllm_misc_lfcon:4; -		u32 pllm_misc_cpcon:4; -		u32 gp_xm2cfga_padctrl_preemp:1; -		u32 gp_xm2cfgd_padctrl_schmt:1; -		u32 osc_ctrl_xobp:1; -		u32 memory_type:3; -	}; -	u32 word; -}; - -union scratch4_reg { -	struct { -		u32 emc_clock_divider:8; -		u32 pllm_stable_time:8; -		u32 pllx_stable_time:8; -		u32 emc_fbio_spare_cfg_wb0:8; -	}; -	u32 word; -}; - -union scratch24_reg { -	struct { -		u32 emc_auto_cal_wait:8; -		u32 emc_pin_program_wait:8; -		u32 warmboot_wait:8; -		u32 reserved:8; -	}; -	u32 word; -}; - -int warmboot_save_sdram_params(void) -{ -	u32 ram_code; -	struct sdram_params sdram; -	struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; -	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; -	struct apb_misc_gp_ctlr *gp = -			(struct apb_misc_gp_ctlr *)TEGRA2_APB_MISC_GP_BASE; -	struct emc_ctlr *emc = emc_get_controller(gd->fdt_blob); -	union scratch2_reg scratch2; -	union scratch4_reg scratch4; -	union scratch24_reg scratch24; -	union xm2cfga_reg xm2cfga; -	union xm2cfgd_reg xm2cfgd; -	union fbio_spare_reg fbio_spare; - -	/* get ram code that is used as index to array sdram_params in BCT */ -	ram_code = (readl(&pmt->pmt_strap_opt_a) >> -			STRAP_OPT_A_RAM_CODE_SHIFT) & 3; -	memcpy(&sdram, -	       (char *)((struct sdram_params *)SDRAM_PARAMS_BASE + ram_code), -	       sizeof(sdram)); - -	xm2cfga.word = readl(&gp->xm2cfga); -	xm2cfgd.word = readl(&gp->xm2cfgd); - -	scratch2.word = 0; -	scratch2.osc_ctrl_xobp = clock_get_osc_bypass(); - -	/* Get the memory PLL settings */ -	{ -		u32 divm, divn, divp, cpcon, lfcon; - -		if (clock_ll_read_pll(CLOCK_ID_MEMORY, &divm, &divn, &divp, -					&cpcon, &lfcon)) -			return -1; -		scratch2.pllm_base_divm = divm; -		scratch2.pllm_base_divn = divn; -		scratch2.pllm_base_divp = divp; -		scratch2.pllm_misc_cpcon = cpcon; -		scratch2.pllm_misc_lfcon = lfcon; -	} - -	scratch2.gp_xm2cfga_padctrl_preemp = xm2cfga.preemp_en; -	scratch2.gp_xm2cfgd_padctrl_schmt = xm2cfgd.schmt_en; -	scratch2.memory_type = sdram.memory_type; -	writel(scratch2.word, &pmc->pmc_scratch2); - -	/* collect data from various sources for pmc_scratch4 */ -	fbio_spare.word = readl(&emc->fbio_spare); -	scratch4.word = 0; -	scratch4.emc_fbio_spare_cfg_wb0 = fbio_spare.cfg_wb0; -	scratch4.emc_clock_divider = sdram.emc_clock_divider; -	scratch4.pllm_stable_time = -1; -	scratch4.pllx_stable_time = -1; -	writel(scratch4.word, &pmc->pmc_scratch4); - -	/* collect various data from sdram for pmc_scratch24 */ -	scratch24.word = 0; -	scratch24.emc_pin_program_wait = sdram.emc_pin_program_wait; -	scratch24.emc_auto_cal_wait = sdram.emc_auto_cal_wait; -	scratch24.warmboot_wait = sdram.warm_boot_wait; -	writel(scratch24.word, &pmc->pmc_scratch24); - -	return 0; -} - -static u32 get_major_version(void) -{ -	u32 major_id; -	struct apb_misc_gp_ctlr *gp = -		(struct apb_misc_gp_ctlr *)TEGRA2_APB_MISC_GP_BASE; - -	major_id = (readl(&gp->hidrev) & HIDREV_MAJORPREV_MASK) >> -			HIDREV_MAJORPREV_SHIFT; -	return major_id; -} - -static int is_production_mode_fuse_set(struct fuse_regs *fuse) -{ -	return readl(&fuse->production_mode); -} - -static int is_odm_production_mode_fuse_set(struct fuse_regs *fuse) -{ -	return readl(&fuse->security_mode); -} - -static int is_failure_analysis_mode(struct fuse_regs *fuse) -{ -	return readl(&fuse->fa); -} - -static int ap20_is_odm_production_mode(void) -{ -	struct fuse_regs *fuse = (struct fuse_regs *)TEGRA2_FUSE_BASE; - -	if (!is_failure_analysis_mode(fuse) && -	    is_odm_production_mode_fuse_set(fuse)) -		return 1; -	else -		return 0; -} - -static int ap20_is_production_mode(void) -{ -	struct fuse_regs *fuse = (struct fuse_regs *)TEGRA2_FUSE_BASE; - -	if (get_major_version() == 0) -		return 1; - -	if (!is_failure_analysis_mode(fuse) && -	    is_production_mode_fuse_set(fuse) && -	    !is_odm_production_mode_fuse_set(fuse)) -		return 1; -	else -		return 0; -} - -static enum fuse_operating_mode fuse_get_operation_mode(void) -{ -	u32 chip_id; -	struct apb_misc_gp_ctlr *gp = -		(struct apb_misc_gp_ctlr *)TEGRA2_APB_MISC_GP_BASE; - -	chip_id = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> -			HIDREV_CHIPID_SHIFT; -	if (chip_id == CHIPID_TEGRA2) { -		if (ap20_is_odm_production_mode()) { -			printf("!! odm_production_mode is not supported !!\n"); -			return MODE_UNDEFINED; -		} else -			if (ap20_is_production_mode()) -				return MODE_PRODUCTION; -			else -				return MODE_UNDEFINED; -	} -	return MODE_UNDEFINED; -} - -static void determine_crypto_options(int *is_encrypted, int *is_signed, -				     int *use_zero_key) -{ -	switch (fuse_get_operation_mode()) { -	case MODE_PRODUCTION: -		*is_encrypted = 0; -		*is_signed = 1; -		*use_zero_key = 1; -		break; -	case MODE_UNDEFINED: -	default: -		*is_encrypted = 0; -		*is_signed = 0; -		*use_zero_key  = 0; -		break; -	} -} - -static int sign_wb_code(u32 start, u32 length, int use_zero_key) -{ -	int err; -	u8 *source;		/* Pointer to source */ -	u8 *hash; - -	/* Calculate AES block parameters. */ -	source = (u8 *)(start + offsetof(struct wb_header, random_aes_block)); -	length -= offsetof(struct wb_header, random_aes_block); -	hash = (u8 *)(start + offsetof(struct wb_header, hash)); -	err = sign_data_block(source, length, hash); - -	return err; -} - -int warmboot_prepare_code(u32 seg_address, u32 seg_length) -{ -	int err = 0; -	u32 length;			/* length of the signed/encrypt code */ -	struct wb_header *dst_header;	/* Pointer to dest WB header */ -	int is_encrypted;		/* Segment is encrypted */ -	int is_signed;			/* Segment is signed */ -	int use_zero_key;		/* Use key of all zeros */ - -	/* Determine crypto options. */ -	determine_crypto_options(&is_encrypted, &is_signed, &use_zero_key); - -	/* Get the actual code limits. */ -	length = roundup(((u32)wb_end - (u32)wb_start), 16); - -	/* -	 * The region specified by seg_address must be in SDRAM and must be -	 * nonzero in length. -	 */ -	if (seg_length == 0 || seg_address < NV_PA_SDRAM_BASE || -		seg_address + seg_length >= NV_PA_SDRAM_BASE + gd->ram_size) { -		err = -EFAULT; -		goto fail; -	} - -	/* Things must be 16-byte aligned. */ -	if ((seg_length & 0xF) || (seg_address & 0xF)) { -		err = -EINVAL; -		goto fail; -	} - -	/* Will the code fit? (destination includes wb_header + wb code) */ -	if (seg_length < (length + sizeof(struct wb_header))) { -		err = -EINVAL; -		goto fail; -	} - -	dst_header = (struct wb_header *)seg_address; -	memset((char *)dst_header, 0, sizeof(struct wb_header)); - -	/* Populate the random_aes_block as requested. */ -	{ -		u32 *aes_block = (u32 *)&(dst_header->random_aes_block); -		u32 *end = (u32 *)(((u32)aes_block) + -				   sizeof(dst_header->random_aes_block)); - -		do { -			*aes_block++ = 0; -		} while (aes_block < end); -	} - -	/* Populate the header. */ -	dst_header->length_insecure = length + sizeof(struct wb_header); -	dst_header->length_secure = length + sizeof(struct wb_header); -	dst_header->destination = AP20_WB_RUN_ADDRESS; -	dst_header->entry_point = AP20_WB_RUN_ADDRESS; -	dst_header->code_length = length; - -	if (is_encrypted) { -		printf("!!!! Encryption is not supported !!!!\n"); -		dst_header->length_insecure = 0; -		err = -EACCES; -		goto fail; -	} else -		/* copy the wb code directly following dst_header. */ -		memcpy((char *)(dst_header+1), (char *)wb_start, length); - -	if (is_signed) -		err = sign_wb_code(seg_address, dst_header->length_insecure, -				   use_zero_key); - -fail: -	if (err) -		printf("Warning: warmboot code copy failed (error=%d)\n", err); - -	return err; -} diff --git a/arch/arm/cpu/armv7/tegra2/warmboot_avp.c b/arch/arm/cpu/armv7/tegra2/warmboot_avp.c deleted file mode 100644 index 70bcd8e5f..000000000 --- a/arch/arm/cpu/armv7/tegra2/warmboot_avp.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * (C) Copyright 2010 - 2011 - * NVIDIA Corporation <www.nvidia.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/io.h> -#include <asm/arch/ap20.h> -#include <asm/arch/clk_rst.h> -#include <asm/arch/clock.h> -#include <asm/arch/flow.h> -#include <asm/arch/pinmux.h> -#include <asm/arch/pmc.h> -#include <asm/arch/tegra2.h> -#include <asm/arch/warmboot.h> -#include "warmboot_avp.h" - -#define DEBUG_RESET_CORESIGHT - -void wb_start(void) -{ -	struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; -	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; -	struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE; -	struct clk_rst_ctlr *clkrst = -			(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; -	union osc_ctrl_reg osc_ctrl; -	union pllx_base_reg pllx_base; -	union pllx_misc_reg pllx_misc; -	union scratch3_reg scratch3; -	u32 reg; - -	/* enable JTAG & TBE */ -	writel(CONFIG_CTL_TBE | CONFIG_CTL_JTAG, &pmt->pmt_cfg_ctl); - -	/* Are we running where we're supposed to be? */ -	asm volatile ( -		"adr	%0, wb_start;"	/* reg: wb_start address */ -		: "=r"(reg)		/* output */ -					/* no input, no clobber list */ -	); - -	if (reg != AP20_WB_RUN_ADDRESS) -		goto do_reset; - -	/* Are we running with AVP? */ -	if (readl(NV_PA_PG_UP_BASE + PG_UP_TAG_0) != PG_UP_TAG_AVP) -		goto do_reset; - -#ifdef DEBUG_RESET_CORESIGHT -	/* Assert CoreSight reset */ -	reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_U]); -	reg |= SWR_CSITE_RST; -	writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_U]); -#endif - -	/* TODO: Set the drive strength - maybe make this a board parameter? */ -	osc_ctrl.word = readl(&clkrst->crc_osc_ctrl); -	osc_ctrl.xofs = 4; -	osc_ctrl.xoe = 1; -	writel(osc_ctrl.word, &clkrst->crc_osc_ctrl); - -	/* Power up the CPU complex if necessary */ -	if (!(readl(&pmc->pmc_pwrgate_status) & PWRGATE_STATUS_CPU)) { -		reg = PWRGATE_TOGGLE_PARTID_CPU | PWRGATE_TOGGLE_START; -		writel(reg, &pmc->pmc_pwrgate_toggle); -		while (!(readl(&pmc->pmc_pwrgate_status) & PWRGATE_STATUS_CPU)) -			; -	} - -	/* Remove the I/O clamps from the CPU power partition. */ -	reg = readl(&pmc->pmc_remove_clamping); -	reg |= CPU_CLMP; -	writel(reg, &pmc->pmc_remove_clamping); - -	reg = EVENT_ZERO_VAL_20 | EVENT_MSEC | EVENT_MODE_STOP; -	writel(reg, &flow->halt_cop_events); - -	/* Assert CPU complex reset */ -	reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_L]); -	reg |= CPU_RST; -	writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_L]); - -	/* Hold both CPUs in reset */ -	reg = CPU_CMPLX_CPURESET0 | CPU_CMPLX_CPURESET1 | CPU_CMPLX_DERESET0 | -	      CPU_CMPLX_DERESET1 | CPU_CMPLX_DBGRESET0 | CPU_CMPLX_DBGRESET1; -	writel(reg, &clkrst->crc_cpu_cmplx_set); - -	/* Halt CPU1 at the flow controller for uni-processor configurations */ -	writel(EVENT_MODE_STOP, &flow->halt_cpu1_events); - -	/* -	 * Set the CPU reset vector. SCRATCH41 contains the physical -	 * address of the CPU-side restoration code. -	 */ -	reg = readl(&pmc->pmc_scratch41); -	writel(reg, EXCEP_VECTOR_CPU_RESET_VECTOR); - -	/* Select CPU complex clock source */ -	writel(CCLK_PLLP_BURST_POLICY, &clkrst->crc_cclk_brst_pol); - -	/* Start the CPU0 clock and stop the CPU1 clock */ -	reg = CPU_CMPLX_CPU_BRIDGE_CLKDIV_4 | CPU_CMPLX_CPU0_CLK_STP_RUN | -	      CPU_CMPLX_CPU1_CLK_STP_STOP; -	writel(reg, &clkrst->crc_clk_cpu_cmplx); - -	/* Enable the CPU complex clock */ -	reg = readl(&clkrst->crc_clk_out_enb[TEGRA_DEV_L]); -	reg |= CLK_ENB_CPU; -	writel(reg, &clkrst->crc_clk_out_enb[TEGRA_DEV_L]); - -	/* Make sure the resets were held for at least 2 microseconds */ -	reg = readl(TIMER_USEC_CNTR); -	while (readl(TIMER_USEC_CNTR) <= (reg + 2)) -		; - -#ifdef DEBUG_RESET_CORESIGHT -	/* -	 * De-assert CoreSight reset. -	 * NOTE: We're leaving the CoreSight clock on the oscillator for -	 *	now. It will be restored to its original clock source -	 *	when the CPU-side restoration code runs. -	 */ -	reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_U]); -	reg &= ~SWR_CSITE_RST; -	writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_U]); -#endif - -	/* Unlock the CPU CoreSight interfaces */ -	reg = 0xC5ACCE55; -	writel(reg, CSITE_CPU_DBG0_LAR); -	writel(reg, CSITE_CPU_DBG1_LAR); - -	/* -	 * Sample the microsecond timestamp again. This is the time we must -	 * use when returning from LP0 for PLL stabilization delays. -	 */ -	reg = readl(TIMER_USEC_CNTR); -	writel(reg, &pmc->pmc_scratch1); - -	pllx_base.word = 0; -	pllx_misc.word = 0; -	scratch3.word = readl(&pmc->pmc_scratch3); - -	/* Get the OSC. For 19.2 MHz, use 19 to make the calculations easier */ -	reg = (readl(TIMER_USEC_CFG) & USEC_CFG_DIVISOR_MASK) + 1; - -	/* -	 * According to the TRM, for 19.2MHz OSC, the USEC_DIVISOR is 0x5f, and -	 * USEC_DIVIDEND is 0x04. So, if USEC_DIVISOR > 26, OSC is 19.2 MHz. -	 * -	 * reg is used to calculate the pllx freq, which is used to determine if -	 * to set dccon or not. -	 */ -	if (reg > 26) -		reg = 19; - -	/* PLLX_BASE.PLLX_DIVM */ -	if (scratch3.pllx_base_divm == reg) -		reg = 0; -	else -		reg = 1; - -	/* PLLX_BASE.PLLX_DIVN */ -	pllx_base.divn = scratch3.pllx_base_divn; -	reg = scratch3.pllx_base_divn << reg; - -	/* PLLX_BASE.PLLX_DIVP */ -	pllx_base.divp = scratch3.pllx_base_divp; -	reg = reg >> scratch3.pllx_base_divp; - -	pllx_base.bypass = 1; - -	/* PLLX_MISC_DCCON must be set for pllx frequency > 600 MHz. */ -	if (reg > 600) -		pllx_misc.dccon = 1; - -	/* PLLX_MISC_LFCON */ -	pllx_misc.lfcon = scratch3.pllx_misc_lfcon; - -	/* PLLX_MISC_CPCON */ -	pllx_misc.cpcon = scratch3.pllx_misc_cpcon; - -	writel(pllx_misc.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_misc); -	writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base); - -	pllx_base.enable = 1; -	writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base); -	pllx_base.bypass = 0; -	writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base); - -	writel(0, flow->halt_cpu_events); - -	reg = CPU_CMPLX_CPURESET0 | CPU_CMPLX_DBGRESET0 | CPU_CMPLX_DERESET0; -	writel(reg, &clkrst->crc_cpu_cmplx_clr); - -	reg = PLLM_OUT1_RSTN_RESET_DISABLE | PLLM_OUT1_CLKEN_ENABLE | -	      PLLM_OUT1_RATIO_VAL_8; -	writel(reg, &clkrst->crc_pll[CLOCK_ID_MEMORY].pll_out); - -	reg = SCLK_SWAKE_FIQ_SRC_PLLM_OUT1 | SCLK_SWAKE_IRQ_SRC_PLLM_OUT1 | -	      SCLK_SWAKE_RUN_SRC_PLLM_OUT1 | SCLK_SWAKE_IDLE_SRC_PLLM_OUT1 | -	      SCLK_SYS_STATE_IDLE; -	writel(reg, &clkrst->crc_sclk_brst_pol); - -	/* avp_resume: no return after the write */ -	reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_L]); -	reg &= ~CPU_RST; -	writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_L]); - -	/* avp_halt: */ -avp_halt: -	reg = EVENT_MODE_STOP | EVENT_JTAG; -	writel(reg, flow->halt_cop_events); -	goto avp_halt; - -do_reset: -	/* -	 * Execution comes here if something goes wrong. The chip is reset and -	 * a cold boot is performed. -	 */ -	writel(SWR_TRIG_SYS_RST, &clkrst->crc_rst_dev[TEGRA_DEV_L]); -	goto do_reset; -} - -/* - * wb_end() is a dummy function, and must be directly following wb_start(), - * and is used to calculate the size of wb_start(). - */ -void wb_end(void) -{ -} diff --git a/arch/arm/cpu/armv7/tegra2/warmboot_avp.h b/arch/arm/cpu/armv7/tegra2/warmboot_avp.h deleted file mode 100644 index 4b71c0784..000000000 --- a/arch/arm/cpu/armv7/tegra2/warmboot_avp.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * (C) Copyright 2010, 2011 - * NVIDIA Corporation <www.nvidia.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef _WARMBOOT_AVP_H_ -#define _WARMBOOT_AVP_H_ - -#define TEGRA_DEV_L			0 -#define TEGRA_DEV_H			1 -#define TEGRA_DEV_U			2 - -#define SIMPLE_PLLX			(CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE) -#define SIMPLE_PLLE			(CLOCK_ID_EPCI - CLOCK_ID_FIRST_SIMPLE) - -#define TIMER_USEC_CNTR			(NV_PA_TMRUS_BASE + 0) -#define TIMER_USEC_CFG			(NV_PA_TMRUS_BASE + 4) - -#define USEC_CFG_DIVISOR_MASK		0xffff - -#define CONFIG_CTL_TBE			(1 << 7) -#define CONFIG_CTL_JTAG			(1 << 6) - -#define CPU_RST				(1 << 0) -#define CLK_ENB_CPU			(1 << 0) -#define SWR_TRIG_SYS_RST		(1 << 2) -#define SWR_CSITE_RST			(1 << 9) - -#define PWRGATE_STATUS_CPU		(1 << 0) -#define PWRGATE_TOGGLE_PARTID_CPU	(0 << 0) -#define PWRGATE_TOGGLE_START		(1 << 8) - -#define CPU_CMPLX_CPU_BRIDGE_CLKDIV_4	(3 << 0) -#define CPU_CMPLX_CPU0_CLK_STP_STOP	(1 << 8) -#define CPU_CMPLX_CPU0_CLK_STP_RUN	(0 << 8) -#define CPU_CMPLX_CPU1_CLK_STP_STOP	(1 << 9) -#define CPU_CMPLX_CPU1_CLK_STP_RUN	(0 << 9) - -#define CPU_CMPLX_CPURESET0		(1 << 0) -#define CPU_CMPLX_CPURESET1		(1 << 1) -#define CPU_CMPLX_DERESET0		(1 << 4) -#define CPU_CMPLX_DERESET1		(1 << 5) -#define CPU_CMPLX_DBGRESET0		(1 << 12) -#define CPU_CMPLX_DBGRESET1		(1 << 13) - -#define PLLM_OUT1_RSTN_RESET_DISABLE	(1 << 0) -#define PLLM_OUT1_CLKEN_ENABLE		(1 << 1) -#define PLLM_OUT1_RATIO_VAL_8		(8 << 8) - -#define SCLK_SYS_STATE_IDLE		(1 << 28) -#define SCLK_SWAKE_FIQ_SRC_PLLM_OUT1	(7 << 12) -#define SCLK_SWAKE_IRQ_SRC_PLLM_OUT1	(7 << 8) -#define SCLK_SWAKE_RUN_SRC_PLLM_OUT1	(7 << 4) -#define SCLK_SWAKE_IDLE_SRC_PLLM_OUT1	(7 << 0) - -#define EVENT_ZERO_VAL_20		(20 << 0) -#define EVENT_MSEC			(1 << 24) -#define EVENT_JTAG			(1 << 28) -#define EVENT_MODE_STOP			(2 << 29) - -#define CCLK_PLLP_BURST_POLICY		0x20004444 - -#endif diff --git a/arch/arm/cpu/armv7/imx-common/Makefile b/arch/arm/cpu/armv7/tegra20/Makefile index bf36be576..5f4035d79 100644 --- a/arch/arm/cpu/armv7/imx-common/Makefile +++ b/arch/arm/cpu/armv7/tegra20/Makefile @@ -1,8 +1,8 @@  # -# (C) Copyright 2000-2006 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# (C) Copyright 2010,2011 Nvidia Corporation.  # -# (C) Copyright 2011 Freescale Semiconductor, Inc. +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de.  #  # See file CREDITS for list of people who contributed to this  # project. @@ -25,16 +25,16 @@  include $(TOPDIR)/config.mk -LIB     = $(obj)libimx-common.o +LIB	=  $(obj)lib$(SOC).o -COBJS-y	= iomux-v3.o timer.o cpu.o speed.o -COBJS-$(CONFIG_I2C_MXC) += i2c.o -COBJS	:= $(sort $(COBJS-y)) +COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o +COBJS-$(CONFIG_CMD_ENTERRCM) += cmd_enterrcm.o -SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS)) +COBJS	:= $(COBJS-y) +SRCS	:= $(COBJS:.o=.c) +OBJS	:= $(addprefix $(obj),$(COBJS)) -all:	$(obj).depend $(LIB) +all:	 $(obj).depend $(LIB)  $(LIB):	$(OBJS)  	$(call cmd_link_o_target, $(OBJS)) diff --git a/arch/arm/cpu/armv7/tegra2/cmd_enterrcm.c b/arch/arm/cpu/armv7/tegra20/cmd_enterrcm.c index 2fcd107df..925f8414c 100644 --- a/arch/arm/cpu/armv7/tegra2/cmd_enterrcm.c +++ b/arch/arm/cpu/armv7/tegra20/cmd_enterrcm.c @@ -40,13 +40,13 @@   */  #include <common.h> -#include <asm/arch/tegra2.h> +#include <asm/arch/tegra20.h>  #include <asm/arch/pmc.h>  static int do_enterrcm(cmd_tbl_t *cmdtp, int flag, int argc,  		       char * const argv[])  { -	struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; +	struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;  	puts("Entering RCM...\n");  	udelay(50000); diff --git a/arch/arm/cpu/armv7/tegra2/config.mk b/arch/arm/cpu/armv7/tegra20/config.mk index 4dd8cb844..6432e754e 100644 --- a/arch/arm/cpu/armv7/tegra2/config.mk +++ b/arch/arm/cpu/armv7/tegra20/config.mk @@ -23,16 +23,4 @@  # Foundation, Inc., 59 Temple Place, Suite 330, Boston,  # MA 02111-1307 USA  # - -# Tegra has an ARMv4T CPU which runs board_init_f(), so we must build these -# files with compatible flags -ifdef CONFIG_TEGRA2 -CFLAGS_arch/arm/lib/board.o += -march=armv4t -CFLAGS_arch/arm/lib/memset.o += -march=armv4t -CFLAGS_lib/string.o += -march=armv4t -CFLAGS_common/cmd_nvedit.o += -march=armv4t -endif - -USE_PRIVATE_LIBGCC = yes -  CONFIG_ARCH_DEVICE_TREE := tegra20 diff --git a/arch/arm/cpu/armv7/tegra2/usb.c b/arch/arm/cpu/armv7/tegra20/usb.c index 5f2b24375..cac0918ff 100644 --- a/arch/arm/cpu/armv7/tegra2/usb.c +++ b/arch/arm/cpu/armv7/tegra20/usb.c @@ -24,7 +24,7 @@  #include <common.h>  #include <asm/io.h>  #include <asm-generic/gpio.h> -#include <asm/arch/tegra2.h> +#include <asm/arch/tegra20.h>  #include <asm/arch/clk_rst.h>  #include <asm/arch/clock.h>  #include <asm/arch/gpio.h> @@ -137,24 +137,29 @@ static const u8 utmip_elastic_limit = 16;  /* UTMIP High Speed Sync Start Delay */  static const u8 utmip_hs_sync_start_delay = 9; -/* Put the port into host mode (this only works for OTG ports) */ +/* Put the port into host mode */  static void set_host_mode(struct fdt_usb *config)  { -	if (config->dr_mode == DR_MODE_OTG) { -		/* Check whether remote host from USB1 is driving VBus */ -		if (readl(&config->reg->phy_vbus_sensors) & VBUS_VLD_STS) -			return; +	/* +	 * If we are an OTG port, check if remote host is driving VBus and +	 * bail out in this case. +	 */ +	if (config->dr_mode == DR_MODE_OTG && +		(readl(&config->reg->phy_vbus_sensors) & VBUS_VLD_STS)) +		return; -		/* -		 * If not driving, we set the GPIO to enable VBUS. We assume -		 * that the pinmux is set up correctly for this. -		 */ -		if (fdt_gpio_isvalid(&config->vbus_gpio)) { -			fdtdec_setup_gpio(&config->vbus_gpio); -			gpio_direction_output(config->vbus_gpio.gpio, 1); -			debug("set_host_mode: GPIO %d high\n", -			      config->vbus_gpio.gpio); -		} +	/* +	 * If not driving, we set the GPIO to enable VBUS. We assume +	 * that the pinmux is set up correctly for this. +	 */ +	if (fdt_gpio_isvalid(&config->vbus_gpio)) { +		fdtdec_setup_gpio(&config->vbus_gpio); +		gpio_direction_output(config->vbus_gpio.gpio, +			(config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ? +				 0 : 1); +		debug("set_host_mode: GPIO %d %s\n", config->vbus_gpio.gpio, +			(config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ? +				"low" : "high");  	}  } diff --git a/arch/arm/cpu/armv7/u8500/Makefile b/arch/arm/cpu/armv7/u8500/Makefile index 270aa40c8..ce8af9603 100644 --- a/arch/arm/cpu/armv7/u8500/Makefile +++ b/arch/arm/cpu/armv7/u8500/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk  LIB	= $(obj)lib$(SOC).o -COBJS	= timer.o clock.o +COBJS	= timer.o clock.o prcmu.o cpu.o  SOBJS	= lowlevel.o  SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/arch/arm/cpu/armv7/u8500/clock.c b/arch/arm/cpu/armv7/u8500/clock.c index 9e3b87394..fcfd61a1f 100644 --- a/arch/arm/cpu/armv7/u8500/clock.c +++ b/arch/arm/cpu/armv7/u8500/clock.c @@ -54,3 +54,37 @@ void u8500_clock_enable(int periph, int cluster, int kern)  	if (cluster != -1)  		writel(1 << cluster, &clkrst->pcken);  } + +void db8500_clocks_init(void) +{ +	/* +	 * Enable all clocks. This is u-boot, we can enable it all. There is no +	 * powersave in u-boot. +	 */ + +	u8500_clock_enable(1, 9, -1); /* GPIO0 */ +	u8500_clock_enable(2, 11, -1);/* GPIO1 */ +	u8500_clock_enable(3, 8, -1); /* GPIO2 */ +	u8500_clock_enable(5, 1, -1); /* GPIO3 */ +	u8500_clock_enable(3, 6, 6);  /* UART2 */ +	u8500_clock_enable(3, 3, 3);  /* I2C0 */ +	u8500_clock_enable(1, 5, 5);  /* SDI0 */ +	u8500_clock_enable(2, 4, 2);  /* SDI4 */ +	u8500_clock_enable(6, 6, -1); /* MTU0 */ +	u8500_clock_enable(3, 4, 4);  /* SDI2 */ + +	/* +	 * Enabling clocks for all devices which are AMBA devices in the +	 * kernel.  Otherwise they will not get probe()'d because the +	 * peripheral ID register will not be powered. +	 */ + +	/* XXX: some of these differ between ED/V1 */ + +	u8500_clock_enable(1, 1, 1);  /* UART1 */ +	u8500_clock_enable(1, 0, 0);  /* UART0 */ +	u8500_clock_enable(3, 2, 2);  /* SSP1 */ +	u8500_clock_enable(3, 1, 1);  /* SSP0 */ +	u8500_clock_enable(2, 8, -1); /* SPI0 */ +	u8500_clock_enable(2, 5, 3);  /* MSP2 */ +} diff --git a/arch/arm/cpu/armv7/u8500/cpu.c b/arch/arm/cpu/armv7/u8500/cpu.c new file mode 100644 index 000000000..6f95c3067 --- /dev/null +++ b/arch/arm/cpu/armv7/u8500/cpu.c @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2012 Linaro Limited + * Mathieu Poirier <mathieu.poirier@linaro.org> + * + * Based on original code from Joakim Axelsson at ST-Ericsson + * (C) Copyright 2010 ST-Ericsson + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/prcmu.h> +#include <asm/arch/clock.h> +#include <asm/arch/hardware.h> + +#include <asm/arch/hardware.h> + +#define CPUID_DB8500V1		0x411fc091 +#define CPUID_DB8500V2		0x412fc091 +#define ASICID_DB8500V11	0x008500A1 + +#define CACHE_CONTR_BASE	0xA0412000 +/* Cache controller register offsets + * as found in ARM's technical reference manual + */ +#define CACHE_INVAL_BY_WAY	(CACHE_CONTR_BASE + 0x77C) +#define CACHE_LOCKDOWN_BY_D	(CACHE_CONTR_BASE + 0X900) +#define CACHE_LOCKDOWN_BY_I	(CACHE_CONTR_BASE + 0X904) + +static unsigned int read_asicid(void); + +static inline unsigned int read_cpuid(void) +{ +	unsigned int val; + +	/* Main ID register (MIDR) */ +	asm("mrc        p15, 0, %0, c0, c0, 0" +	   : "=r" (val) +	   : +	   : "cc"); + +	return val; +} + +static int cpu_is_u8500v11(void) +{ +	return read_asicid() == ASICID_DB8500V11; +} + +static int cpu_is_u8500v2(void) +{ +	return read_cpuid() == CPUID_DB8500V2; +} + +static unsigned int read_asicid(void) +{ +	unsigned int *address; + +	if (cpu_is_u8500v2()) +		address = (void *) U8500_ASIC_ID_LOC_V2; +	else +		address = (void *) U8500_ASIC_ID_LOC_ED_V1; + +	return readl(address); +} + +void cpu_cache_initialization(void) +{ +	unsigned int value; +	/* invalidate all cache entries */ +	writel(0xFFFF, CACHE_INVAL_BY_WAY); + +	/* ways are set to '0' when they are totally +	 * cleaned and invalidated +	 */ +	do { +		value = readl(CACHE_INVAL_BY_WAY); +	} while (value & 0xFF); + +	/* Invalidate register 9 D and I lockdown */ +	writel(0xFF, CACHE_LOCKDOWN_BY_D); +	writel(0xFF, CACHE_LOCKDOWN_BY_I); +} + +#ifdef CONFIG_ARCH_CPU_INIT +/* + * SOC specific cpu init + */ +int arch_cpu_init(void) +{ +	db8500_prcmu_init(); +	db8500_clocks_init(); + +	return 0; +} +#endif /* CONFIG_ARCH_CPU_INIT */ + +#ifdef CONFIG_MMC + +int u8500_mmc_power_init(void) +{ +	int ret; +	int enable, voltage; +	int ab8500_revision; + +	if (!cpu_is_u8500v11() && !cpu_is_u8500v2()) +		return 0; + +	/* Get AB8500 revision */ +	ret = ab8500_read(AB8500_MISC, AB8500_REV_REG); +	if (ret < 0) +		goto out; + +	ab8500_revision = ret; + +	/* +	 * On v1.1 HREF boards (HREF+), Vaux3 needs to be enabled for the SD +	 * card to work.  This is done by enabling the regulators in the AB8500 +	 * via PRCMU I2C transactions. +	 * +	 * This code is derived from the handling of AB8500_LDO_VAUX3 in +	 * ab8500_ldo_enable() and ab8500_ldo_disable() in Linux. +	 * +	 * Turn off and delay is required to have it work across soft reboots. +	 */ + +	/* Turn off (read-modify-write) */ +	ret = ab8500_read(AB8500_REGU_CTRL2, +				AB8500_REGU_VRF1VAUX3_REGU_REG); +	if (ret < 0) +		goto out; + +	enable = ret; + +	/* Turn off */ +	ret = ab8500_write(AB8500_REGU_CTRL2, +			AB8500_REGU_VRF1VAUX3_REGU_REG, +			enable & ~LDO_VAUX3_ENABLE_MASK); +	if (ret < 0) +		goto out; + +	udelay(10 * 1000); + +	/* Set the voltage to 2.91 V or 2.9 V without overriding VRF1 value */ +	ret = ab8500_read(AB8500_REGU_CTRL2, +			AB8500_REGU_VRF1VAUX3_SEL_REG); +	if (ret < 0) +		goto out; + +	voltage = ret; + +	if (ab8500_revision < 0x20) { +		voltage &= ~LDO_VAUX3_SEL_MASK; +		voltage |= LDO_VAUX3_SEL_2V9; +	} else { +		voltage &= ~LDO_VAUX3_V2_SEL_MASK; +		voltage |= LDO_VAUX3_V2_SEL_2V91; +	} + +	ret = ab8500_write(AB8500_REGU_CTRL2, +			AB8500_REGU_VRF1VAUX3_SEL_REG, voltage); +	if (ret < 0) +		goto out; + +	/* Turn on the supply */ +	enable &= ~LDO_VAUX3_ENABLE_MASK; +	enable |= LDO_VAUX3_ENABLE_VAL; + +	ret = ab8500_write(AB8500_REGU_CTRL2, +			AB8500_REGU_VRF1VAUX3_REGU_REG, enable); + +out: +	return ret; +} +#endif /* CONFIG_MMC */ diff --git a/arch/arm/cpu/armv7/u8500/prcmu.c b/arch/arm/cpu/armv7/u8500/prcmu.c new file mode 100644 index 000000000..934428fb8 --- /dev/null +++ b/arch/arm/cpu/armv7/u8500/prcmu.c @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2009 ST-Ericsson SA + * + * Adapted from the Linux version: + * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + */ + +/* + * NOTE: This currently does not support the I2C workaround access method. + */ + +#include <common.h> +#include <config.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/types.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/arch/prcmu.h> + +/* CPU mailbox registers */ +#define PRCMU_I2C_WRITE(slave)  \ +	(((slave) << 1) | I2CWRITE | (1 << 6)) +#define PRCMU_I2C_READ(slave) \ +	(((slave) << 1) | I2CREAD | (1 << 6)) + +#define I2C_MBOX_BIT    (1 << 5) + +static int prcmu_is_ready(void) +{ +	int ready = readb(PRCM_XP70_CUR_PWR_STATE) == AP_EXECUTE; +	if (!ready) +		printf("PRCMU firmware not ready\n"); +	return ready; +} + +static int wait_for_i2c_mbx_rdy(void) +{ +	int timeout = 10000; + +	if (readl(PRCM_ARM_IT1_VAL) & I2C_MBOX_BIT) { +		printf("prcmu: warning i2c mailbox was not acked\n"); +		/* clear mailbox 5 ack irq */ +		writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR); +	} + +	/* check any already on-going transaction */ +	while ((readl(PRCM_MBOX_CPU_VAL) & I2C_MBOX_BIT) && timeout) +		timeout--; + +	if (timeout == 0) +		return -1; + +	return 0; +} + +static int wait_for_i2c_req_done(void) +{ +	int timeout = 10000; + +	/* Set an interrupt to XP70 */ +	writel(I2C_MBOX_BIT, PRCM_MBOX_CPU_SET); + +	/* wait for mailbox 5 (i2c) ack */ +	while (!(readl(PRCM_ARM_IT1_VAL) & I2C_MBOX_BIT) && timeout) +		timeout--; + +	if (timeout == 0) +		return -1; + +	return 0; +} + +/** + * prcmu_i2c_read - PRCMU - 4500 communication using PRCMU I2C + * @reg: - db8500 register bank to be accessed + * @slave:  - db8500 register to be accessed + * Returns: ACK_MB5  value containing the status + */ +int prcmu_i2c_read(u8 reg, u16 slave) +{ +	uint8_t i2c_status; +	uint8_t i2c_val; +	int ret; + +	if (!prcmu_is_ready()) +		return -1; + +	debug("\nprcmu_4500_i2c_read:bank=%x;reg=%x;\n", +			reg, slave); + +	ret = wait_for_i2c_mbx_rdy(); +	if (ret) { +		printf("prcmu_i2c_read: mailbox became not ready\n"); +		return ret; +	} + +	/* prepare the data for mailbox 5 */ +	writeb(PRCMU_I2C_READ(reg), PRCM_REQ_MB5_I2COPTYPE_REG); +	writeb((1 << 3) | 0x0, PRCM_REQ_MB5_BIT_FIELDS); +	writeb(slave, PRCM_REQ_MB5_I2CSLAVE); +	writeb(0, PRCM_REQ_MB5_I2CVAL); + +	ret = wait_for_i2c_req_done(); +	if (ret) { +		printf("prcmu_i2c_read: mailbox request timed out\n"); +		return ret; +	} + +	/* retrieve values */ +	debug("ack-mb5:transfer status = %x\n", +			readb(PRCM_ACK_MB5_STATUS)); +	debug("ack-mb5:reg bank = %x\n", readb(PRCM_ACK_MB5) >> 1); +	debug("ack-mb5:slave_add = %x\n", +			readb(PRCM_ACK_MB5_SLAVE)); +	debug("ack-mb5:reg_val = %d\n", readb(PRCM_ACK_MB5_VAL)); + +	i2c_status = readb(PRCM_ACK_MB5_STATUS); +	i2c_val = readb(PRCM_ACK_MB5_VAL); +	/* clear mailbox 5 ack irq */ +	writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR); + +	if (i2c_status == I2C_RD_OK) +		return i2c_val; + +	printf("prcmu_i2c_read:read return status= %d\n", i2c_status); +	return -1; +} + +/** + * prcmu_i2c_write - PRCMU-db8500 communication using PRCMU I2C + * @reg: - db8500 register bank to be accessed + * @slave:  - db800 register to be written to + * @reg_data: - the data to write + * Returns: ACK_MB5 value containing the status + */ +int prcmu_i2c_write(u8 reg, u16 slave, u8 reg_data) +{ +	uint8_t i2c_status; +	int ret; + +	if (!prcmu_is_ready()) +		return -1; + +	debug("\nprcmu_4500_i2c_write:bank=%x;reg=%x;\n", +			reg, slave); + +	ret = wait_for_i2c_mbx_rdy(); +	if (ret) { +		printf("prcmu_i2c_write: mailbox became not ready\n"); +		return ret; +	} + +	/* prepare the data for mailbox 5 */ +	writeb(PRCMU_I2C_WRITE(reg), PRCM_REQ_MB5_I2COPTYPE_REG); +	writeb((1 << 3) | 0x0, PRCM_REQ_MB5_BIT_FIELDS); +	writeb(slave, PRCM_REQ_MB5_I2CSLAVE); +	writeb(reg_data, PRCM_REQ_MB5_I2CVAL); + +	ret = wait_for_i2c_req_done(); +	if (ret) { +		printf("prcmu_i2c_write: mailbox request timed out\n"); +		return ret; +	} + +	/* retrieve values */ +	debug("ack-mb5:transfer status = %x\n", +			readb(PRCM_ACK_MB5_STATUS)); +	debug("ack-mb5:reg bank = %x\n", readb(PRCM_ACK_MB5) >> 1); +	debug("ack-mb5:slave_add = %x\n", +			readb(PRCM_ACK_MB5_SLAVE)); +	debug("ack-mb5:reg_val = %d\n", readb(PRCM_ACK_MB5_VAL)); + +	i2c_status = readb(PRCM_ACK_MB5_STATUS); +	debug("\ni2c_status = %x\n", i2c_status); +	/* clear mailbox 5 ack irq */ +	writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR); + +	if (i2c_status == I2C_WR_OK) +		return 0; + +	printf("%s: i2c_status : 0x%x\n", __func__, i2c_status); +	return -1; +} + +void u8500_prcmu_enable(u32 *reg) +{ +	writel(readl(reg) | (1 << 8), reg); +} + +void db8500_prcmu_init(void) +{ +	/* Enable timers */ +	writel(1 << 17, PRCM_TCR); + +	u8500_prcmu_enable((u32 *)PRCM_PER1CLK_MGT_REG); +	u8500_prcmu_enable((u32 *)PRCM_PER2CLK_MGT_REG); +	u8500_prcmu_enable((u32 *)PRCM_PER3CLK_MGT_REG); +	/* PER4CLK does not exist */ +	u8500_prcmu_enable((u32 *)PRCM_PER5CLK_MGT_REG); +	u8500_prcmu_enable((u32 *)PRCM_PER6CLK_MGT_REG); +	/* Only exists in ED but is always ok to write to */ +	u8500_prcmu_enable((u32 *)PRCM_PER7CLK_MGT_REG); + +	u8500_prcmu_enable((u32 *)PRCM_UARTCLK_MGT_REG); +	u8500_prcmu_enable((u32 *)PRCM_I2CCLK_MGT_REG); + +	u8500_prcmu_enable((u32 *)PRCM_SDMMCCLK_MGT_REG); + +	/* Clean up the mailbox interrupts after pre-u-boot code. */ +	writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR); +} |