Project

General

Profile

Mityarm RGMII1 question » som.c

u-boot som file - david mckinley, 03/19/2014 02:06 PM

 
/*
* 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 */
(5-5/5)