/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common_def.h" #include "pmic.h" #include "tps65217.h" #include #include #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(" 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 ] \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 */