diff options
Diffstat (limited to 'board/ti/am43xx/board.c')
| -rw-r--r-- | board/ti/am43xx/board.c | 355 | 
1 files changed, 351 insertions, 4 deletions
| diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c index 51b257683..ed87cd97b 100644 --- a/board/ti/am43xx/board.c +++ b/board/ti/am43xx/board.c @@ -9,22 +9,326 @@   */  #include <common.h> +#include <i2c.h> +#include <asm/errno.h>  #include <spl.h>  #include <asm/arch/clock.h>  #include <asm/arch/sys_proto.h>  #include <asm/arch/mux.h> +#include <asm/arch/ddr_defs.h> +#include <asm/arch/gpio.h> +#include <asm/emif.h>  #include "board.h"  DECLARE_GLOBAL_DATA_PTR; +/* + * Read header information from EEPROM into global structure. + */ +static int read_eeprom(struct am43xx_board_id *header) +{ +	/* Check if baseboard eeprom is available */ +	if (i2c_probe(CONFIG_SYS_I2C_EEPROM_ADDR)) { +		printf("Could not probe the EEPROM at 0x%x\n", +		       CONFIG_SYS_I2C_EEPROM_ADDR); +		return -ENODEV; +	} + +	/* read the eeprom using i2c */ +	if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, 2, (uchar *)header, +		     sizeof(struct am43xx_board_id))) { +		printf("Could not read the EEPROM\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(struct am43xx_board_id))) { +			printf("Could not read the EEPROM at 0x%x\n", +			       CONFIG_SYS_I2C_EEPROM_ADDR); +			return -EIO; +		} + +		if (header->magic != 0xEE3355AA) { +			printf("Incorrect magic number (0x%x) in EEPROM\n", +			       header->magic); +			return -EINVAL; +		} +	} + +	strncpy(am43xx_board_name, (char *)header->name, sizeof(header->name)); +	am43xx_board_name[sizeof(header->name)] = 0; + +	return 0; +} +  #ifdef CONFIG_SPL_BUILD -const struct dpll_params dpll_ddr = { -		-1, -1, -1, -1, -1, -1, -1}; +#define NUM_OPPS	6 + +const struct dpll_params dpll_mpu[NUM_CRYSTAL_FREQ][NUM_OPPS] = { +	{	/* 19.2 MHz */ +		{-1, -1, -1, -1, -1, -1, -1},	/* OPP 50 */ +		{-1, -1, -1, -1, -1, -1, -1},	/* OPP RESERVED	*/ +		{-1, -1, -1, -1, -1, -1, -1},	/* OPP 100 */ +		{-1, -1, -1, -1, -1, -1, -1},	/* OPP 120 */ +		{-1, -1, -1, -1, -1, -1, -1},	/* OPP TB */ +		{-1, -1, -1, -1, -1, -1, -1}	/* OPP NT */ +	}, +	{	/* 24 MHz */ +		{300, 23, 1, -1, -1, -1, -1},	/* OPP 50 */ +		{-1, -1, -1, -1, -1, -1, -1},	/* OPP RESERVED	*/ +		{600, 23, 1, -1, -1, -1, -1},	/* OPP 100 */ +		{720, 23, 1, -1, -1, -1, -1},	/* OPP 120 */ +		{800, 23, 1, -1, -1, -1, -1},	/* OPP TB */ +		{1000, 23, 1, -1, -1, -1, -1}	/* OPP NT */ +	}, +	{	/* 25 MHz */ +		{300, 24, 1, -1, -1, -1, -1},	/* OPP 50 */ +		{-1, -1, -1, -1, -1, -1, -1},	/* OPP RESERVED	*/ +		{600, 24, 1, -1, -1, -1, -1},	/* OPP 100 */ +		{720, 24, 1, -1, -1, -1, -1},	/* OPP 120 */ +		{800, 24, 1, -1, -1, -1, -1},	/* OPP TB */ +		{1000, 24, 1, -1, -1, -1, -1}	/* OPP NT */ +	}, +	{	/* 26 MHz */ +		{300, 25, 1, -1, -1, -1, -1},	/* OPP 50 */ +		{-1, -1, -1, -1, -1, -1, -1},	/* OPP RESERVED	*/ +		{600, 25, 1, -1, -1, -1, -1},	/* OPP 100 */ +		{720, 25, 1, -1, -1, -1, -1},	/* OPP 120 */ +		{800, 25, 1, -1, -1, -1, -1},	/* OPP TB */ +		{1000, 25, 1, -1, -1, -1, -1}	/* OPP NT */ +	}, +}; + +const struct dpll_params dpll_core[NUM_CRYSTAL_FREQ] = { +		{-1, -1, -1, -1, -1, -1, -1},	/* 19.2 MHz */ +		{1000, 23, -1, -1, 10, 8, 4},	/* 24 MHz */ +		{1000, 24, -1, -1, 10, 8, 4},	/* 25 MHz */ +		{1000, 25, -1, -1, 10, 8, 4}	/* 26 MHz */ +}; + +const struct dpll_params dpll_per[NUM_CRYSTAL_FREQ] = { +		{-1, -1, -1, -1, -1, -1, -1},	/* 19.2 MHz */ +		{960, 23, 5, -1, -1, -1, -1},	/* 24 MHz */ +		{960, 24, 5, -1, -1, -1, -1},	/* 25 MHz */ +		{960, 25, 5, -1, -1, -1, -1}	/* 26 MHz */ +}; + +const struct dpll_params epos_evm_dpll_ddr = { +		266, 24, 1, -1, 1, -1, -1}; + +const struct dpll_params gp_evm_dpll_ddr = { +		400, 23, 1, -1, 1, -1, -1}; + +const struct ctrl_ioregs ioregs_lpddr2 = { +	.cm0ioctl		= LPDDR2_ADDRCTRL_IOCTRL_VALUE, +	.cm1ioctl		= LPDDR2_ADDRCTRL_WD0_IOCTRL_VALUE, +	.cm2ioctl		= LPDDR2_ADDRCTRL_WD1_IOCTRL_VALUE, +	.dt0ioctl		= LPDDR2_DATA0_IOCTRL_VALUE, +	.dt1ioctl		= LPDDR2_DATA0_IOCTRL_VALUE, +	.dt2ioctrl		= LPDDR2_DATA0_IOCTRL_VALUE, +	.dt3ioctrl		= LPDDR2_DATA0_IOCTRL_VALUE, +	.emif_sdram_config_ext	= 0x1, +}; + +const struct emif_regs emif_regs_lpddr2 = { +	.sdram_config			= 0x808012BA, +	.ref_ctrl			= 0x0000040D, +	.sdram_tim1			= 0xEA86B411, +	.sdram_tim2			= 0x103A094A, +	.sdram_tim3			= 0x0F6BA37F, +	.read_idle_ctrl			= 0x00050000, +	.zq_config			= 0x50074BE4, +	.temp_alert_config		= 0x0, +	.emif_rd_wr_lvl_rmp_win		= 0x0, +	.emif_rd_wr_lvl_rmp_ctl		= 0x0, +	.emif_rd_wr_lvl_ctl		= 0x0, +	.emif_ddr_phy_ctlr_1		= 0x0E084006, +	.emif_rd_wr_exec_thresh		= 0x00000405, +	.emif_ddr_ext_phy_ctrl_1	= 0x04010040, +	.emif_ddr_ext_phy_ctrl_2	= 0x00500050, +	.emif_ddr_ext_phy_ctrl_3	= 0x00500050, +	.emif_ddr_ext_phy_ctrl_4	= 0x00500050, +	.emif_ddr_ext_phy_ctrl_5	= 0x00500050 +}; + +const u32 ext_phy_ctrl_const_base_lpddr2[] = { +	0x00500050, +	0x00350035, +	0x00350035, +	0x00350035, +	0x00350035, +	0x00350035, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x40001000, +	0x08102040 +}; + +const struct ctrl_ioregs ioregs_ddr3 = { +	.cm0ioctl		= DDR3_ADDRCTRL_IOCTRL_VALUE, +	.cm1ioctl		= DDR3_ADDRCTRL_WD0_IOCTRL_VALUE, +	.cm2ioctl		= DDR3_ADDRCTRL_WD1_IOCTRL_VALUE, +	.dt0ioctl		= DDR3_DATA0_IOCTRL_VALUE, +	.dt1ioctl		= DDR3_DATA0_IOCTRL_VALUE, +	.dt2ioctrl		= DDR3_DATA0_IOCTRL_VALUE, +	.dt3ioctrl		= DDR3_DATA0_IOCTRL_VALUE, +	.emif_sdram_config_ext	= 0x0043, +}; + +const struct emif_regs ddr3_emif_regs_400Mhz = { +	.sdram_config			= 0x638413B2, +	.ref_ctrl			= 0x00000C30, +	.sdram_tim1			= 0xEAAAD4DB, +	.sdram_tim2			= 0x266B7FDA, +	.sdram_tim3			= 0x107F8678, +	.read_idle_ctrl			= 0x00050000, +	.zq_config			= 0x50074BE4, +	.temp_alert_config		= 0x0, +	.emif_ddr_phy_ctlr_1		= 0x0E084008, +	.emif_ddr_ext_phy_ctrl_1	= 0x08020080, +	.emif_ddr_ext_phy_ctrl_2	= 0x00400040, +	.emif_ddr_ext_phy_ctrl_3	= 0x00400040, +	.emif_ddr_ext_phy_ctrl_4	= 0x00400040, +	.emif_ddr_ext_phy_ctrl_5	= 0x00400040, +	.emif_rd_wr_lvl_rmp_win		= 0x0, +	.emif_rd_wr_lvl_rmp_ctl		= 0x0, +	.emif_rd_wr_lvl_ctl		= 0x0, +	.emif_rd_wr_exec_thresh		= 0x00000405 +}; + +const u32 ext_phy_ctrl_const_base_ddr3[] = { +	0x00400040, +	0x00350035, +	0x00350035, +	0x00350035, +	0x00350035, +	0x00350035, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00340034, +	0x00340034, +	0x00340034, +	0x00340034, +	0x00340034, +	0x0, +	0x0, +	0x40000000, +	0x08102040 +}; + +void emif_get_ext_phy_ctrl_const_regs(const u32 **regs, u32 *size) +{ +	if (board_is_eposevm()) { +		*regs = ext_phy_ctrl_const_base_lpddr2; +		*size = ARRAY_SIZE(ext_phy_ctrl_const_base_lpddr2); +	} else if (board_is_gpevm()) { +		*regs = ext_phy_ctrl_const_base_ddr3; +		*size = ARRAY_SIZE(ext_phy_ctrl_const_base_ddr3); +	} + +	return; +}  const struct dpll_params *get_dpll_ddr_params(void)  { -	return &dpll_ddr; +	struct am43xx_board_id header; + +	enable_i2c0_pin_mux(); +	i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE); +	if (read_eeprom(&header) < 0) +		puts("Could not get board ID.\n"); + +	if (board_is_eposevm()) +		return &epos_evm_dpll_ddr; +	else if (board_is_gpevm()) +		return &gp_evm_dpll_ddr; + +	puts(" Board not supported\n"); +	return NULL; +} + +/* + * get_sys_clk_index : returns the index of the sys_clk read from + *			ctrl status register. This value is either + *			read from efuse or sysboot pins. + */ +static u32 get_sys_clk_index(void) +{ +	struct ctrl_stat *ctrl = (struct ctrl_stat *)CTRL_BASE; +	u32 ind = readl(&ctrl->statusreg), src; + +	src = (ind & CTRL_CRYSTAL_FREQ_SRC_MASK) >> CTRL_CRYSTAL_FREQ_SRC_SHIFT; +	if (src == CTRL_CRYSTAL_FREQ_SRC_EFUSE) /* Value read from EFUSE */ +		return ((ind & CTRL_CRYSTAL_FREQ_SELECTION_MASK) >> +			CTRL_CRYSTAL_FREQ_SELECTION_SHIFT); +	else /* Value read from SYS BOOT pins */ +		return ((ind & CTRL_SYSBOOT_15_14_MASK) >> +			CTRL_SYSBOOT_15_14_SHIFT); +} + +/* + * get_opp_offset: + * Returns the index for safest OPP of the device to boot. + * max_off:	Index of the MAX OPP in DEV ATTRIBUTE register. + * min_off:	Index of the MIN OPP in DEV ATTRIBUTE register. + * This data is read from dev_attribute register which is e-fused. + * A'1' in bit indicates OPP disabled and not available, a '0' indicates + * OPP available. Lowest OPP starts with min_off. So returning the + * bit with rightmost '0'. + */ +static int get_opp_offset(int max_off, int min_off) +{ +	struct ctrl_stat *ctrl = (struct ctrl_stat *)CTRL_BASE; +	int opp = readl(&ctrl->dev_attr), offset, i; + +	for (i = max_off; i >= min_off; i--) { +		offset = opp & (1 << i); +		if (!offset) +			return i; +	} + +	return min_off; +} + +const struct dpll_params *get_dpll_mpu_params(void) +{ +	int opp = get_opp_offset(DEV_ATTR_MAX_OFFSET, DEV_ATTR_MIN_OFFSET); +	u32 ind = get_sys_clk_index(); + +	return &dpll_mpu[ind][opp]; +} + +const struct dpll_params *get_dpll_core_params(void) +{ +	int ind = get_sys_clk_index(); + +	return &dpll_core[ind]; +} + +const struct dpll_params *get_dpll_per_params(void) +{ +	int ind = get_sys_clk_index(); + +	return &dpll_per[ind];  }  void set_uart_mux_conf(void) @@ -37,14 +341,41 @@ void set_mux_conf_regs(void)  	enable_board_pin_mux();  } +static void enable_vtt_regulator(void) +{ +	u32 temp; + +	/* enable module */ +	writel(GPIO_CTRL_ENABLEMODULE, AM33XX_GPIO0_BASE + OMAP_GPIO_CTRL); + +	/* enable output for GPIO0_22 */ +	writel(GPIO_SETDATAOUT(GPIO_22), +	       AM33XX_GPIO0_BASE + OMAP_GPIO_SETDATAOUT); +	temp = readl(AM33XX_GPIO0_BASE + OMAP_GPIO_OE); +	temp = temp & ~(GPIO_OE_ENABLE(GPIO_22)); +	writel(temp, AM33XX_GPIO0_BASE + OMAP_GPIO_OE); +} +  void sdram_init(void)  { +	/* +	 * EPOS EVM has 1GB LPDDR2 connected to EMIF. +	 * GP EMV has 1GB DDR3 connected to EMIF +	 * along with VTT regulator. +	 */ +	if (board_is_eposevm()) { +		config_ddr(0, &ioregs_lpddr2, NULL, NULL, &emif_regs_lpddr2, 0); +	} else if (board_is_gpevm()) { +		enable_vtt_regulator(); +		config_ddr(0, &ioregs_ddr3, NULL, NULL, +			   &ddr3_emif_regs_400Mhz, 0); +	}  }  #endif  int board_init(void)  { -	gd->bd->bi_boot_params = PHYS_DRAM_1 + 0x100; +	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;  	return 0;  } @@ -52,6 +383,22 @@ int board_init(void)  #ifdef CONFIG_BOARD_LATE_INIT  int board_late_init(void)  { +#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG +	char safe_string[HDR_NAME_LEN + 1]; +	struct am43xx_board_id header; + +	if (read_eeprom(&header) < 0) +		puts("Could not get board ID.\n"); + +	/* Now set variables based on the header. */ +	strncpy(safe_string, (char *)header.name, sizeof(header.name)); +	safe_string[sizeof(header.name)] = 0; +	setenv("board_name", safe_string); + +	strncpy(safe_string, (char *)header.version, sizeof(header.version)); +	safe_string[sizeof(header.version)] = 0; +	setenv("board_rev", safe_string); +#endif  	return 0;  }  #endif |