|
/*
|
|
* som.c
|
|
*
|
|
* Copyright (C) 2012 Critical Link LLC - http://www.criticallink.com/
|
|
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.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 version 2.
|
|
*
|
|
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
|
* kind, whether express or implied; without even the implied warranty
|
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <asm/cache.h>
|
|
#include <asm/omap_common.h>
|
|
#include <asm/io.h>
|
|
#include <asm/arch/cpu.h>
|
|
#include <asm/arch/ddr_defs.h>
|
|
#include <asm/arch/hardware.h>
|
|
#include <asm/arch/mmc_host_def.h>
|
|
#include <asm/arch/sys_proto.h>
|
|
#include <asm/arch/mem.h>
|
|
#include <asm/arch/nand.h>
|
|
#include <asm/arch/clock.h>
|
|
#include <linux/mtd/nand.h>
|
|
#include <nand.h>
|
|
#include <net.h>
|
|
#include <miiphy.h>
|
|
#include <netdev.h>
|
|
#include <spi_flash.h>
|
|
#include "common_def.h"
|
|
#include "pmic.h"
|
|
#include "tps65217.h"
|
|
#include <i2c.h>
|
|
#include <serial.h>
|
|
#include "config_block.h"
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
/* Profile 0 is the dev kit board, profile 1 is the test fixture */
|
|
#ifdef CONFIG_AM335X_TF
|
|
static unsigned char profile = PROFILE_1;
|
|
#else
|
|
static unsigned char profile = PROFILE_0;
|
|
#endif
|
|
|
|
/* UART Defines */
|
|
#define UART_SYSCFG_OFFSET (0x54)
|
|
#define UART_SYSSTS_OFFSET (0x58)
|
|
|
|
#define UART_RESET (0x1 << 1)
|
|
#define UART_CLK_RUNNING_MASK 0x1
|
|
#define UART_SMART_IDLE_EN (0x1 << 0x3)
|
|
|
|
/* Timer Defines */
|
|
#define TSICR_REG 0x54
|
|
#define TIOCP_CFG_REG 0x10
|
|
#define TCLR_REG 0x38
|
|
|
|
/*
|
|
* I2C Address of various board
|
|
*/
|
|
#define I2C_EEPROM_ADDR 0x50
|
|
#define I2C_EEPROM_BUS 1
|
|
#define I2C_PMIC_CTL_BUS 2
|
|
#define I2C_PMIC_SMT_BUS 1
|
|
|
|
/* RGMII mode define */
|
|
#define RGMII_MODE_ENABLE 0xA
|
|
#define RMII_MODE_ENABLE 0x5
|
|
#define MII_MODE_ENABLE 0x0
|
|
|
|
/* TLK110 PHY registers */
|
|
#define TLK110_COARSEGAIN_REG 0x00A3
|
|
#define TLK110_LPFHPF_REG 0x00AC
|
|
#define TLK110_SPAREANALOG_REG 0x00B9
|
|
#define TLK110_VRCR_REG 0x00D0
|
|
#define TLK110_SETFFE_REG (unsigned char)0x0107
|
|
#define TLK110_FTSP_REG (unsigned char)0x0154
|
|
#define TLK110_ALFATPIDL_REG 0x002A
|
|
#define TLK110_PSCOEF21_REG 0x0096
|
|
#define TLK110_PSCOEF3_REG 0x0097
|
|
#define TLK110_ALFAFACTOR1_REG 0x002C
|
|
#define TLK110_ALFAFACTOR2_REG 0x0023
|
|
#define TLK110_CFGPS_REG 0x0095
|
|
#define TLK110_FTSPTXGAIN_REG (unsigned char)0x0150
|
|
#define TLK110_SWSCR3_REG 0x000B
|
|
#define TLK110_SCFALLBACK_REG 0x0040
|
|
#define TLK110_PHYRCR_REG 0x001F
|
|
|
|
/* TLK110 register writes values */
|
|
#define TLK110_COARSEGAIN_VAL 0x0000
|
|
#define TLK110_LPFHPF_VAL 0x8000
|
|
#define TLK110_SPAREANALOG_VAL 0x0000
|
|
#define TLK110_VRCR_VAL 0x0008
|
|
#define TLK110_SETFFE_VAL 0x0605
|
|
#define TLK110_FTSP_VAL 0x0255
|
|
#define TLK110_ALFATPIDL_VAL 0x7998
|
|
#define TLK110_PSCOEF21_VAL 0x3A20
|
|
#define TLK110_PSCOEF3_VAL 0x003F
|
|
#define TLK110_ALFAFACTOR1_VAL 0xFF80
|
|
#define TLK110_ALFAFACTOR2_VAL 0x021C
|
|
#define TLK110_CFGPS_VAL 0x0000
|
|
#define TLK110_FTSPTXGAIN_VAL 0x6A88
|
|
#define TLK110_SWSCR3_VAL 0x0000
|
|
#define TLK110_SCFALLBACK_VAL 0xC11D
|
|
#define TLK110_PHYRCR_VAL 0x4000
|
|
#define TLK110_PHYIDR1 0x2000
|
|
#define TLK110_PHYIDR2 0xA201
|
|
|
|
#define NO_OF_MAC_ADDR 3
|
|
#define ETH_ALEN 6
|
|
|
|
|
|
|
|
/* set the D3 LED to on of off. This LED is hooked up to the GPIO0
|
|
* output of the PMIC.
|
|
* \param[in] b if non-zero, turn LED on, else off
|
|
*/
|
|
inline void set_led_d3(int b) {
|
|
unsigned char v;
|
|
// save the bus number
|
|
int bus = i2c_get_bus_num();
|
|
i2c_set_bus_num(I2C_PMIC_CTL_BUS);
|
|
i2c_read(PMIC_CTRL_I2C_ADDR, PMIC_GPIO0_REG, 1, &v, 1);
|
|
if(b)
|
|
v |= 1;
|
|
else
|
|
v &= 0xfe;
|
|
i2c_write(PMIC_CTRL_I2C_ADDR, PMIC_GPIO0_REG, 1, &v, 1);
|
|
// put it back
|
|
i2c_set_bus_num(bus);
|
|
}
|
|
|
|
/*
|
|
* dram_init:
|
|
* At this point we have initialized the i2c bus and can read the
|
|
* EEPROM which will tell us what board and revision we are on.
|
|
*/
|
|
int dram_init(void)
|
|
{
|
|
gd->ram_size = PHYS_DRAM_1_SIZE;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void dram_init_banksize (void)
|
|
{
|
|
/* Fill up board info */
|
|
gd->bd->bi_dram[0].start = PHYS_DRAM_1;
|
|
gd->bd->bi_dram[0].size = PHYS_DRAM_1_SIZE;
|
|
}
|
|
|
|
#ifdef CONFIG_SPL_BUILD
|
|
static void Data_Macro_Config(int dataMacroNum)
|
|
{
|
|
u32 BaseAddrOffset = 0x00;;
|
|
|
|
if (dataMacroNum == 1)
|
|
BaseAddrOffset = 0xA4;
|
|
|
|
__raw_writel(((DDR2_RD_DQS<<30)|(DDR2_RD_DQS<<20)
|
|
|(DDR2_RD_DQS<<10)|(DDR2_RD_DQS<<0)),
|
|
(DATA0_RD_DQS_SLAVE_RATIO_0 + BaseAddrOffset));
|
|
__raw_writel(DDR2_RD_DQS>>2,
|
|
(DATA0_RD_DQS_SLAVE_RATIO_1 + BaseAddrOffset));
|
|
__raw_writel(((DDR2_WR_DQS<<30)|(DDR2_WR_DQS<<20)
|
|
|(DDR2_WR_DQS<<10)|(DDR2_WR_DQS<<0)),
|
|
(DATA0_WR_DQS_SLAVE_RATIO_0 + BaseAddrOffset));
|
|
__raw_writel(DDR2_WR_DQS>>2,
|
|
(DATA0_WR_DQS_SLAVE_RATIO_1 + BaseAddrOffset));
|
|
__raw_writel(((DDR2_PHY_WRLVL<<30)|(DDR2_PHY_WRLVL<<20)
|
|
|(DDR2_PHY_WRLVL<<10)|(DDR2_PHY_WRLVL<<0)),
|
|
(DATA0_WRLVL_INIT_RATIO_0 + BaseAddrOffset));
|
|
__raw_writel(DDR2_PHY_WRLVL>>2,
|
|
(DATA0_WRLVL_INIT_RATIO_1 + BaseAddrOffset));
|
|
__raw_writel(((DDR2_PHY_GATELVL<<30)|(DDR2_PHY_GATELVL<<20)
|
|
|(DDR2_PHY_GATELVL<<10)|(DDR2_PHY_GATELVL<<0)),
|
|
(DATA0_GATELVL_INIT_RATIO_0 + BaseAddrOffset));
|
|
__raw_writel(DDR2_PHY_GATELVL>>2,
|
|
(DATA0_GATELVL_INIT_RATIO_1 + BaseAddrOffset));
|
|
__raw_writel(((DDR2_PHY_FIFO_WE<<30)|(DDR2_PHY_FIFO_WE<<20)
|
|
|(DDR2_PHY_FIFO_WE<<10)|(DDR2_PHY_FIFO_WE<<0)),
|
|
(DATA0_FIFO_WE_SLAVE_RATIO_0 + BaseAddrOffset));
|
|
__raw_writel(DDR2_PHY_FIFO_WE>>2,
|
|
(DATA0_FIFO_WE_SLAVE_RATIO_1 + BaseAddrOffset));
|
|
__raw_writel(((DDR2_PHY_WR_DATA<<30)|(DDR2_PHY_WR_DATA<<20)
|
|
|(DDR2_PHY_WR_DATA<<10)|(DDR2_PHY_WR_DATA<<0)),
|
|
(DATA0_WR_DATA_SLAVE_RATIO_0 + BaseAddrOffset));
|
|
__raw_writel(DDR2_PHY_WR_DATA>>2,
|
|
(DATA0_WR_DATA_SLAVE_RATIO_1 + BaseAddrOffset));
|
|
__raw_writel(PHY_DLL_LOCK_DIFF,
|
|
(DATA0_DLL_LOCK_DIFF_0 + BaseAddrOffset));
|
|
}
|
|
|
|
static void Cmd_Macro_Config(void)
|
|
{
|
|
__raw_writel(DDR2_RATIO, CMD0_CTRL_SLAVE_RATIO_0);
|
|
__raw_writel(CMD_FORCE, CMD0_CTRL_SLAVE_FORCE_0);
|
|
__raw_writel(CMD_DELAY, CMD0_CTRL_SLAVE_DELAY_0);
|
|
__raw_writel(DDR2_DLL_LOCK_DIFF, CMD0_DLL_LOCK_DIFF_0);
|
|
__raw_writel(DDR2_INVERT_CLKOUT, CMD0_INVERT_CLKOUT_0);
|
|
|
|
__raw_writel(DDR2_RATIO, CMD1_CTRL_SLAVE_RATIO_0);
|
|
__raw_writel(CMD_FORCE, CMD1_CTRL_SLAVE_FORCE_0);
|
|
__raw_writel(CMD_DELAY, CMD1_CTRL_SLAVE_DELAY_0);
|
|
__raw_writel(DDR2_DLL_LOCK_DIFF, CMD1_DLL_LOCK_DIFF_0);
|
|
__raw_writel(DDR2_INVERT_CLKOUT, CMD1_INVERT_CLKOUT_0);
|
|
|
|
__raw_writel(DDR2_RATIO, CMD2_CTRL_SLAVE_RATIO_0);
|
|
__raw_writel(CMD_FORCE, CMD2_CTRL_SLAVE_FORCE_0);
|
|
__raw_writel(CMD_DELAY, CMD2_CTRL_SLAVE_DELAY_0);
|
|
__raw_writel(DDR2_DLL_LOCK_DIFF, CMD2_DLL_LOCK_DIFF_0);
|
|
__raw_writel(DDR2_INVERT_CLKOUT, CMD2_INVERT_CLKOUT_0);
|
|
}
|
|
|
|
static void config_vtp(void)
|
|
{
|
|
__raw_writel(__raw_readl(VTP0_CTRL_REG) | VTP_CTRL_ENABLE,
|
|
VTP0_CTRL_REG);
|
|
__raw_writel(__raw_readl(VTP0_CTRL_REG) & (~VTP_CTRL_START_EN),
|
|
VTP0_CTRL_REG);
|
|
__raw_writel(__raw_readl(VTP0_CTRL_REG) | VTP_CTRL_START_EN,
|
|
VTP0_CTRL_REG);
|
|
|
|
/* Poll for READY */
|
|
while ((__raw_readl(VTP0_CTRL_REG) & VTP_CTRL_READY) != VTP_CTRL_READY);
|
|
}
|
|
|
|
static void config_emif_ddr2(void)
|
|
{
|
|
u32 i;
|
|
|
|
/*Program EMIF0 CFG Registers*/
|
|
__raw_writel(EMIF_READ_LATENCY, EMIF4_0_DDR_PHY_CTRL_1);
|
|
__raw_writel(EMIF_READ_LATENCY, EMIF4_0_DDR_PHY_CTRL_1_SHADOW);
|
|
__raw_writel(EMIF_READ_LATENCY, EMIF4_0_DDR_PHY_CTRL_2);
|
|
__raw_writel(EMIF_TIM1, EMIF4_0_SDRAM_TIM_1);
|
|
__raw_writel(EMIF_TIM1, EMIF4_0_SDRAM_TIM_1_SHADOW);
|
|
__raw_writel(EMIF_TIM2, EMIF4_0_SDRAM_TIM_2);
|
|
__raw_writel(EMIF_TIM2, EMIF4_0_SDRAM_TIM_2_SHADOW);
|
|
__raw_writel(EMIF_TIM3, EMIF4_0_SDRAM_TIM_3);
|
|
__raw_writel(EMIF_TIM3, EMIF4_0_SDRAM_TIM_3_SHADOW);
|
|
|
|
__raw_writel(EMIF_SDCFG, EMIF4_0_SDRAM_CONFIG);
|
|
__raw_writel(EMIF_SDCFG, EMIF4_0_SDRAM_CONFIG2);
|
|
|
|
/* __raw_writel(EMIF_SDMGT, EMIF0_0_SDRAM_MGMT_CTRL);
|
|
__raw_writel(EMIF_SDMGT, EMIF0_0_SDRAM_MGMT_CTRL_SHD); */
|
|
__raw_writel(0x00004650, EMIF4_0_SDRAM_REF_CTRL);
|
|
__raw_writel(0x00004650, EMIF4_0_SDRAM_REF_CTRL_SHADOW);
|
|
|
|
for (i = 0; i < 5000; i++) {
|
|
|
|
}
|
|
|
|
/* __raw_writel(EMIF_SDMGT, EMIF0_0_SDRAM_MGMT_CTRL);
|
|
__raw_writel(EMIF_SDMGT, EMIF0_0_SDRAM_MGMT_CTRL_SHD); */
|
|
__raw_writel(EMIF_SDREF, EMIF4_0_SDRAM_REF_CTRL);
|
|
__raw_writel(EMIF_SDREF, EMIF4_0_SDRAM_REF_CTRL_SHADOW);
|
|
|
|
__raw_writel(EMIF_SDCFG, EMIF4_0_SDRAM_CONFIG);
|
|
__raw_writel(EMIF_SDCFG, EMIF4_0_SDRAM_CONFIG2);
|
|
}
|
|
|
|
/* void DDR2_EMIF_Config(void); */
|
|
|
|
/**
|
|
* MityARM335X uses the Micron Mt47H128M16RT-25E
|
|
* 16M x 16 x 8 bank [128M x 16 = 256MB] DDR2 RAM
|
|
* This part has:
|
|
* 14 Addr lines A[13:0]
|
|
* 3 bank address lines BA[2:0]
|
|
* 10 Column address lines A[9:0]
|
|
* CaS Latency = 5
|
|
*/
|
|
static void config_am335x_ddr(void)
|
|
{
|
|
int data_macro_0 = 0;
|
|
int data_macro_1 = 1;
|
|
|
|
enable_ddr_clocks();
|
|
|
|
config_vtp();
|
|
|
|
Cmd_Macro_Config();
|
|
|
|
Data_Macro_Config(data_macro_0);
|
|
Data_Macro_Config(data_macro_1);
|
|
|
|
__raw_writel(PHY_RANK0_DELAY, DATA0_RANK0_DELAYS_0);
|
|
__raw_writel(PHY_RANK0_DELAY, DATA1_RANK0_DELAYS_0);
|
|
|
|
__raw_writel(DDR_IOCTRL_VALUE, DDR_CMD0_IOCTRL);
|
|
__raw_writel(DDR_IOCTRL_VALUE, DDR_CMD1_IOCTRL);
|
|
__raw_writel(DDR_IOCTRL_VALUE, DDR_CMD2_IOCTRL);
|
|
__raw_writel(DDR_IOCTRL_VALUE, DDR_DATA0_IOCTRL);
|
|
__raw_writel(DDR_IOCTRL_VALUE, DDR_DATA1_IOCTRL);
|
|
|
|
__raw_writel(__raw_readl(DDR_IO_CTRL) & 0xefffffff, DDR_IO_CTRL);
|
|
__raw_writel(__raw_readl(DDR_CKE_CTRL) | 0x00000001, DDR_CKE_CTRL);
|
|
|
|
config_emif_ddr2();
|
|
}
|
|
|
|
static void init_timer(void)
|
|
{
|
|
/* Reset the Timer */
|
|
__raw_writel(0x2, (DM_TIMER2_BASE + TSICR_REG));
|
|
|
|
/* Wait until the reset is done */
|
|
while (__raw_readl(DM_TIMER2_BASE + TIOCP_CFG_REG) & 1);
|
|
|
|
/* Start the Timer */
|
|
__raw_writel(0x1, (DM_TIMER2_BASE + TCLR_REG));
|
|
}
|
|
|
|
#endif // CONFIG_SPL_BUILD
|
|
|
|
|
|
/*
|
|
* Read header information from EEPROM into global structure.
|
|
*/
|
|
int read_eeprom(void)
|
|
{
|
|
|
|
/* Check if baseboard eeprom is available */
|
|
i2c_set_bus_num(I2C_EEPROM_BUS);
|
|
if (i2c_probe(I2C_EEPROM_ADDR)) {
|
|
printf("Could not probe the EEPROM; something fundamentally "
|
|
"wrong on the I2C bus.\n");
|
|
return 1;
|
|
}
|
|
|
|
|
|
// set the profile here based on the factory_config_block
|
|
/* try and read our configuration block */
|
|
if(0 == get_factory_config_block()) {
|
|
// set the profile here based on the factory_config_block
|
|
factory_config_block.PartNumber[31] = '\0'; // just to be safe
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
printf("Error reading factory config block\n");
|
|
return -1;
|
|
}
|
|
|
|
printf("MityARM335x profile %d - Model No: %32s Serial No: %d\n", profile,
|
|
factory_config_block.PartNumber, factory_config_block.SerialNumber);
|
|
|
|
#ifdef CONFIG_HAVE_CL_CONFIG
|
|
if(0 == get_config_block()) {
|
|
if(0 != config_block.UBootLocation[0])
|
|
{
|
|
config_block.UBootLocation[63] = '\0';
|
|
/* printf("U-Boot location = %s\n",config_block.UBootLocation ); */
|
|
}
|
|
else
|
|
{
|
|
/* printf("U-Boot located in SPI flash"); */
|
|
}
|
|
}
|
|
#endif /* CONFIG_HAVE_CL_CONFIG */
|
|
}
|
|
|
|
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_BOARD_INIT)
|
|
|
|
/*
|
|
* voltage switching for MPU frequency switching.
|
|
* @module = mpu - 0, core - 1
|
|
* @vddx_op_vol_sel = vdd voltage to set
|
|
*/
|
|
|
|
#define MPU 0
|
|
#define CORE 1
|
|
|
|
int voltage_update(unsigned int module, unsigned char vddx_op_vol_sel)
|
|
{
|
|
uchar buf[4];
|
|
unsigned int reg_offset;
|
|
|
|
i2c_set_bus_num(I2C_PMIC_CTL_BUS);
|
|
if(module == MPU)
|
|
reg_offset = PMIC_VDD1_OP_REG;
|
|
else
|
|
reg_offset = PMIC_VDD2_OP_REG;
|
|
|
|
/* Select VDDx OP */
|
|
if (i2c_read(PMIC_CTRL_I2C_ADDR, reg_offset, 1, buf, 1))
|
|
return 1;
|
|
|
|
buf[0] &= ~PMIC_OP_REG_CMD_MASK;
|
|
|
|
if (i2c_write(PMIC_CTRL_I2C_ADDR, reg_offset, 1, buf, 1))
|
|
return 1;
|
|
|
|
/* Configure VDDx OP Voltage */
|
|
if (i2c_read(PMIC_CTRL_I2C_ADDR, reg_offset, 1, buf, 1))
|
|
return 1;
|
|
|
|
buf[0] &= ~PMIC_OP_REG_SEL_MASK;
|
|
buf[0] |= vddx_op_vol_sel;
|
|
|
|
if (i2c_write(PMIC_CTRL_I2C_ADDR, reg_offset, 1, buf, 1))
|
|
return 1;
|
|
|
|
if (i2c_read(PMIC_CTRL_I2C_ADDR, reg_offset, 1, buf, 1))
|
|
return 1;
|
|
|
|
if ((buf[0] & PMIC_OP_REG_SEL_MASK ) != vddx_op_vol_sel)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void spl_board_init(void)
|
|
{
|
|
int ii = 0;
|
|
uchar buf[4];
|
|
|
|
/* Configure the i2c1 and 2 pin mux */
|
|
enable_i2c1_pin_mux();
|
|
enable_i2c2_pin_mux();
|
|
#ifdef CONFIG_SPL_ENET_SUPPORT_NOT
|
|
mem_malloc_init(0x82000000, 0x00100000);
|
|
set_default_env(NULL);
|
|
#endif
|
|
|
|
#ifdef CONFIG_SPL_MMC_SUPPORT
|
|
enable_mmc0_pin_mux();
|
|
#endif
|
|
printf("\n Sandia Pin Configuration is setting up \n");
|
|
enable_sandia_pin_mux();
|
|
configure_evm_pin_mux(profile);
|
|
printf(" Sandia Pin config is complete.... \n");
|
|
|
|
i2c_set_bus_num(I2C_PMIC_CTL_BUS); /* calls i2c_init... */
|
|
|
|
|
|
printf("Critical Link AM335X %s\n",(PROFILE_1 == profile)?"Test Fixture":"Dev Kit");
|
|
/*
|
|
* EVM PMIC code. All boards currently want an MPU voltage
|
|
* of 1.2625V and CORE voltage of 1.1375V to operate at
|
|
* 720MHz.
|
|
*/
|
|
if (i2c_probe(PMIC_CTRL_I2C_ADDR))
|
|
{
|
|
printf("No PMIC At I2C addr %d\n", PMIC_CTRL_I2C_ADDR);
|
|
for(; ii < 128; ++ii)
|
|
if(0 == i2c_probe(ii))
|
|
printf("I2C device found at addr %d\n", ii);
|
|
return;
|
|
}
|
|
|
|
/* Enable the GPIO pin as output */
|
|
buf[0] = 0x4;
|
|
i2c_write(PMIC_CTRL_I2C_ADDR, PMIC_GPIO0_REG,1, buf, 1);
|
|
|
|
if (read_eeprom()) {
|
|
printf("read_eeprom() failure\n");
|
|
}
|
|
|
|
set_led_d3(1);
|
|
i2c_set_bus_num(I2C_PMIC_CTL_BUS);
|
|
|
|
/* Turn off pull down resistors for BOOT0P, BOOT1P. Som has
|
|
* pullup resistor which wastes power. */
|
|
buf[0] = 0;
|
|
if(0 != i2c_read(PMIC_CTRL_I2C_ADDR, PMIC_PUADEN_REG, 1, buf, 1)) {
|
|
printf("Unable to read I2C reg %d:%d.%d %x\n",
|
|
i2c_get_bus_num(), PMIC_CTRL_I2C_ADDR, PMIC_PUADEN_REG,
|
|
buf[0]);
|
|
}
|
|
buf[0] &= PMIC_PUADEN_REG_BOOTP_PD_DISABLE;
|
|
|
|
if (0 != i2c_write(PMIC_CTRL_I2C_ADDR, PMIC_PUADEN_REG, 1, buf, 1)) {
|
|
printf("Unable to write I2C reg %d:%d.%d %x\n",
|
|
i2c_get_bus_num(), PMIC_CTRL_I2C_ADDR, PMIC_PUADEN_REG,
|
|
buf[0]);
|
|
}
|
|
|
|
/* VDD1/2 voltage selection register access by control i/f */
|
|
buf[0] = 0;
|
|
if (0 != i2c_read(PMIC_CTRL_I2C_ADDR, PMIC_DEVCTRL_REG, 1, buf, 1))
|
|
{
|
|
printf("Unable to read I2C reg %d:%d.%d %x\n",
|
|
i2c_get_bus_num(), PMIC_CTRL_I2C_ADDR, PMIC_DEVCTRL_REG, buf[0]);
|
|
//return;
|
|
}
|
|
buf[0] |= PMIC_DEVCTRL_REG_SR_CTL_I2C_SEL_CTL_I2C;
|
|
|
|
if (0 != i2c_write(PMIC_CTRL_I2C_ADDR, PMIC_DEVCTRL_REG, 1, buf, 1))
|
|
{
|
|
printf("Unable to write I2C reg %d:%d.%d %x\n",
|
|
i2c_get_bus_num(), PMIC_CTRL_I2C_ADDR, PMIC_DEVCTRL_REG, buf[0]);
|
|
//return;
|
|
}
|
|
if (!voltage_update(MPU, PMIC_OP_REG_SEL_1_2_6) &&
|
|
!voltage_update(CORE, PMIC_OP_REG_SEL_1_1_3))
|
|
{
|
|
/* Frequency switching for OPP 120 */
|
|
mpu_pll_config(MPUPLL_M_720);
|
|
printf("PLL configuration complete\n");
|
|
}
|
|
else
|
|
{
|
|
printf("voltage update failed\n");
|
|
}
|
|
#if defined(CONFIG_SPL_ENET_SUPPORT_NOT) && defined(CONFIG_SPL_BUILD)
|
|
miiphy_init();
|
|
board_eth_init(NULL);
|
|
#endif
|
|
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* early system init of muxing and clocks.
|
|
*/
|
|
void s_init(void)
|
|
{
|
|
/* Can be removed as A8 comes up with L2 enabled */
|
|
l2_cache_enable();
|
|
|
|
|
|
/* WDT1 is already running when the bootloader gets control
|
|
* Disable it to avoid "random" resets
|
|
*/
|
|
__raw_writel(0xAAAA, WDT_WSPR);
|
|
while(__raw_readl(WDT_WWPS) != 0x0);
|
|
__raw_writel(0x5555, WDT_WSPR);
|
|
while(__raw_readl(WDT_WWPS) != 0x0);
|
|
|
|
#ifdef CONFIG_SPL_BUILD
|
|
/* Setup the PLLs and the clocks for the peripherals */
|
|
pll_init();
|
|
|
|
|
|
/* UART softreset */
|
|
u32 regVal;
|
|
u32 uart_base = DEFAULT_UART_BASE;
|
|
|
|
enable_uart0_pin_mux();
|
|
|
|
regVal = __raw_readl(uart_base + UART_SYSCFG_OFFSET);
|
|
regVal |= UART_RESET;
|
|
__raw_writel(regVal, (uart_base + UART_SYSCFG_OFFSET) );
|
|
while ((__raw_readl(uart_base + UART_SYSSTS_OFFSET) &
|
|
UART_CLK_RUNNING_MASK) != UART_CLK_RUNNING_MASK);
|
|
|
|
/* Disable smart idle */
|
|
regVal = __raw_readl((uart_base + UART_SYSCFG_OFFSET));
|
|
regVal |= UART_SMART_IDLE_EN;
|
|
__raw_writel(regVal, (uart_base + UART_SYSCFG_OFFSET));
|
|
|
|
/* Initialize the Timer */
|
|
init_timer();
|
|
|
|
preloader_console_init();
|
|
|
|
config_am335x_ddr();
|
|
#endif
|
|
|
|
}
|
|
|
|
/*
|
|
* Basic board specific setup
|
|
*/
|
|
#ifndef CONFIG_SPL_BUILD
|
|
int board_evm_init(void)
|
|
{
|
|
|
|
/* arch number of the board */
|
|
gd->bd->bi_arch_number = MACH_TYPE_MITYARM335X;
|
|
|
|
/* address of boot parameters */
|
|
gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR;
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
int board_init(void)
|
|
{
|
|
/* Configure the i2c1 and 2 pin mux */
|
|
enable_i2c1_pin_mux();
|
|
enable_i2c2_pin_mux();
|
|
|
|
configure_evm_pin_mux(profile);
|
|
|
|
if (0 != read_eeprom())
|
|
{
|
|
printf("board_init:unable to read eeprom\n");
|
|
}
|
|
|
|
#ifndef CONFIG_SPL_BUILD
|
|
board_evm_init();
|
|
#endif
|
|
|
|
gpmc_init();
|
|
|
|
set_led_d3(0);
|
|
return 0;
|
|
|
|
configure_evm_pin_mux(profile);
|
|
|
|
#ifndef CONFIG_SPL_BUILD
|
|
board_evm_init();
|
|
#endif
|
|
|
|
gpmc_init();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int misc_init_r(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#define MII_EXTPAGE 0x1F
|
|
#define RGMII_SKEW 0x1C
|
|
|
|
static int init_vsc8601(char *name, int addr)
|
|
{
|
|
unsigned short val = 0;
|
|
// enable the extended page access
|
|
if (miiphy_write(name, addr, MII_EXTPAGE, 1) != 0) {
|
|
printf("Error enabling extended PHY regs\n");
|
|
return 1;
|
|
}
|
|
if (miiphy_read(name, addr, RGMII_SKEW, &val) != 0) {
|
|
printf("Error reading RGMII skew reg\n");
|
|
return 1;
|
|
}
|
|
val &= 0x0FFF; // clear skew values
|
|
val |= 0x3000; /* 0 Tx skew, 2.0ns Rx skew */
|
|
if (miiphy_write(name, addr, RGMII_SKEW, val) != 0) {
|
|
printf("failed to write RGMII_SKEW\n");
|
|
return 1;
|
|
}
|
|
// disable the extended page access
|
|
if (miiphy_write(name, addr, MII_EXTPAGE, 0) != 0) {
|
|
printf("Error disabling extended PHY regs\n");
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_DRIVER_TI_CPSW
|
|
|
|
/* TODO : Check for the board specific PHY */
|
|
static void evm_phy_init(char *name, int addr)
|
|
{
|
|
/* TODO This currently breaks straight-up network booting and needs to be fixed. */
|
|
#if !defined(CONFIG_SPL_BUILD)
|
|
unsigned short val=0;
|
|
unsigned int cntr = 0;
|
|
unsigned short phyid1, phyid2;
|
|
|
|
/** AM3359 EVM has a Vitesse VSC8601 PHY OUI = 00010007 */
|
|
if(0 != miiphy_read(name, addr, MII_PHYSID1, &phyid1))
|
|
phyid1 = 0xDEAD;
|
|
if(0 != miiphy_read(name, addr, MII_PHYSID2, &phyid2))
|
|
phyid2 = 0xBEEF;
|
|
/*printf("Phy ID = %04x %04x\n", phyid1, phyid2); */
|
|
if(0x7 == phyid1 && 0x420 ==(phyid2& 0xFF0))
|
|
{
|
|
printf("Vitesse VSC8601 PHY detected at addr %d\n", addr);
|
|
val = init_vsc8601(name, addr);
|
|
if(0 != val)
|
|
printf("Error initializing VSC8601 at addr %d\n", addr);
|
|
}
|
|
/* Enable Autonegotiation */
|
|
if (miiphy_read(name, addr, MII_BMCR, &val) != 0) {
|
|
printf("failed to read bmcr on phy id %d\n", addr);
|
|
return;
|
|
}
|
|
|
|
val |= BMCR_FULLDPLX | BMCR_ANENABLE | BMCR_SPEED100;
|
|
|
|
if (miiphy_write(name, addr, MII_BMCR, val) != 0) {
|
|
printf("failed to write bmcr\n");
|
|
return;
|
|
}
|
|
miiphy_read(name, addr, MII_BMCR, &val);
|
|
|
|
/* Setup general advertisement */
|
|
if (miiphy_read(name, addr, MII_ADVERTISE, &val) != 0) {
|
|
printf("failed to read anar on phy id %d\n", addr);
|
|
return;
|
|
}
|
|
|
|
|
|
val |= (LPA_10HALF | LPA_10FULL | LPA_100HALF | LPA_100FULL);
|
|
|
|
if (miiphy_write(name, addr, MII_ADVERTISE, val) != 0) {
|
|
printf("failed to write anar on phy id %d\n", addr);
|
|
return;
|
|
}
|
|
miiphy_read(name, addr, MII_ADVERTISE, &val);
|
|
|
|
/* Restart auto negotiation*/
|
|
miiphy_read(name, addr, MII_BMCR, &val);
|
|
val |= BMCR_ANRESTART;
|
|
miiphy_write(name, addr, MII_BMCR, val);
|
|
|
|
/*check AutoNegotiate complete - it can take upto 3 secs*/
|
|
do {
|
|
udelay(40000);
|
|
cntr++;
|
|
if (!miiphy_read(name, addr, MII_BMSR, &val)) {
|
|
if (val & BMSR_ANEGCOMPLETE)
|
|
break;
|
|
}
|
|
} while (cntr < 250);
|
|
|
|
if (cntr >= 250)
|
|
printf("Auto negotitation failed\n");
|
|
else
|
|
printf("Auto negotiation took %d ms\n", cntr * 40);
|
|
|
|
#endif /* CONFIG_SPL_BUILD */
|
|
return;
|
|
}
|
|
|
|
static void cpsw_control(int enabled)
|
|
{
|
|
/* Enable/disable the RGMII2 port */
|
|
|
|
return;
|
|
}
|
|
|
|
static struct cpsw_slave_data cpsw_slaves[] = {
|
|
{
|
|
.slave_reg_ofs = 0x208,
|
|
.sliver_reg_ofs = 0xd80,
|
|
#ifdef CONFIG_SPL_ENET_SUPPORT
|
|
.phy_id = 1,
|
|
#else
|
|
.phy_id = 2,
|
|
#endif
|
|
},
|
|
{
|
|
.slave_reg_ofs = 0x308,
|
|
.sliver_reg_ofs = 0xdc0,
|
|
#ifdef CONFIG_SPL_ENET_SUPPORT
|
|
.phy_id = 2,
|
|
#else
|
|
.phy_id = 1,
|
|
#endif
|
|
},
|
|
};
|
|
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 = 2,
|
|
.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) /* MIIEN */,
|
|
.control = cpsw_control,
|
|
.phy_init = evm_phy_init,
|
|
.gigabit_en = 1,
|
|
.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;
|
|
int valid_mac = 0;
|
|
|
|
#ifndef CONFIG_SPL_BUILD
|
|
/*
|
|
* Environment set MAC address trumps all...
|
|
*/
|
|
if (eth_getenv_enetaddr("ethaddr", mac_addr)) {
|
|
valid_mac = 1;
|
|
}
|
|
/*
|
|
* Factory configuration MAC address overides built-in
|
|
*/
|
|
else if(is_valid_ether_addr(factory_config_block.MACADDR)) {
|
|
memcpy(mac_addr,factory_config_block.MACADDR, 6);
|
|
eth_setenv_enetaddr("ethaddr", mac_addr);
|
|
valid_mac = 1;
|
|
}
|
|
/* Fall back to MAC address in the eFuse eeprom in part */
|
|
else
|
|
{
|
|
|
|
debug("<ethaddr> not set. Reading from E-fuse\n");
|
|
/* try reading mac address from efuse */
|
|
#if (CONFIG_ETH_PORT == 1)
|
|
mac_lo = __raw_readl(MAC_ID0_LO);
|
|
mac_hi = __raw_readl(MAC_ID0_HI);
|
|
#else
|
|
mac_lo = __raw_readl(MAC_ID1_LO);
|
|
mac_hi = __raw_readl(MAC_ID1_HI);
|
|
#endif
|
|
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);
|
|
valid_mac = 1;
|
|
}
|
|
}
|
|
if(valid_mac) {
|
|
/* Enable gigabit */
|
|
cpsw_data.gigabit_en = 0;
|
|
__raw_writel(RGMII_MODE_ENABLE, MAC_MII_SEL);
|
|
}
|
|
else {
|
|
printf("Warning: MAC Address not found. Ethernet disabled\n");
|
|
}
|
|
|
|
return cpsw_register(&cpsw_data);
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef CONFIG_SPL_BUILD
|
|
#ifdef CONFIG_GENERIC_MMC
|
|
int board_mmc_init(bd_t *bis)
|
|
{
|
|
omap_mmc_init(0);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_NAND_TI81XX
|
|
static void print_nand_ecc_info()
|
|
{
|
|
struct nand_chip *nand;
|
|
struct mtd_info *mtd;
|
|
|
|
if (nand_curr_device < 0 ||
|
|
nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE) {
|
|
printf("Error: Can't switch ecc, no devices available\n");
|
|
return;
|
|
}
|
|
|
|
mtd = &nand_info[nand_curr_device];
|
|
nand = mtd->priv;
|
|
|
|
if(!nand)
|
|
{
|
|
printf("Error: NULL NAND device\n");
|
|
return;
|
|
}
|
|
switch(nand->ecc.mode) {
|
|
case NAND_ECC_HW:
|
|
printf("nand ecc mode = HW BCH8\n"); /* BCH8 is the only HW ECC mode supported */
|
|
break;
|
|
case NAND_ECC_SOFT:
|
|
printf("nand ecc mode = SW\n");
|
|
break;
|
|
default:
|
|
printf("nand ecc is disabled!\n");
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Command to switch between NAND HW and SW ecc
|
|
*****************************************************************************/
|
|
extern void ti81xx_nand_switch_ecc(nand_ecc_modes_t hardware, int32_t mode);
|
|
static int do_switch_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
|
|
{
|
|
int type = 0;
|
|
if (argc < 2) {
|
|
print_nand_ecc_info();
|
|
return 0;
|
|
}
|
|
if (strncmp(argv[1], "hw", 2) == 0) {
|
|
if (argc == 3)
|
|
type = simple_strtoul(argv[2], NULL, 10);
|
|
ti81xx_nand_switch_ecc(NAND_ECC_HW, type);
|
|
}
|
|
else if (strncmp(argv[1], "sw", 2) == 0)
|
|
ti81xx_nand_switch_ecc(NAND_ECC_SOFT, 0);
|
|
else
|
|
goto usage;
|
|
|
|
return 0;
|
|
|
|
usage:
|
|
printf("Usage: nandecc %s\n", cmdtp->usage);
|
|
return 1;
|
|
}
|
|
|
|
U_BOOT_CMD(
|
|
nandecc, 3, 1, do_switch_ecc,
|
|
"Switch NAND ECC calculation algorithm b/w hardware and software",
|
|
"[sw|hw <hw_type>] \n"
|
|
" [sw|hw]- Switch b/w hardware(hw) & software(sw) ecc algorithm\n"
|
|
" hw_type- 0 for Hamming code\n"
|
|
" 1 for bch4\n"
|
|
" 2 for bch8\n"
|
|
" 3 for bch16\n"
|
|
);
|
|
|
|
int board_late_init(void)
|
|
{
|
|
return 0;
|
|
}
|
|
#if 0
|
|
void omap_rev_string(char *str)
|
|
{
|
|
// 0x44E10000 is the CONTROL MODULE register base
|
|
sprintf(str, "Dev ID register = 0x%08x", *(uint32_t*)(0x44E10000));
|
|
}
|
|
#endif
|
|
#endif /* CONFIG_NAND_TI81XX */
|
|
#endif /* CONFIG_SPL_BUILD */
|