diff options
Diffstat (limited to 'board/ti')
-rw-r--r-- | board/ti/am335x/Makefile | 1 | ||||
-rw-r--r-- | board/ti/am335x/board.c | 376 | ||||
-rw-r--r-- | board/ti/am335x/board.h | 49 | ||||
-rw-r--r-- | board/ti/am335x/mux.c | 250 |
4 files changed, 428 insertions, 248 deletions
diff --git a/board/ti/am335x/Makefile b/board/ti/am335x/Makefile index ca50eef..67a87a1 100644 --- a/board/ti/am335x/Makefile +++ b/board/ti/am335x/Makefile @@ -22,6 +22,7 @@ ifdef CONFIG_SPL_BUILD COBJS := mux.o endif +COBJS += board.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) SOBJS := $(addprefix $(obj),$(SOBJS)) diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c new file mode 100644 index 0000000..5d279ec --- /dev/null +++ b/board/ti/am335x/board.c @@ -0,0 +1,376 @@ +/* + * board.c + * + * Board functions for TI AM335X based boards + * + * 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; 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. + */ + +#include <common.h> +#include <errno.h> +#include <spl.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/sys_proto.h> +#include <asm/io.h> +#include <asm/emif.h> +#include <asm/gpio.h> +#include <i2c.h> +#include <miiphy.h> +#include <cpsw.h> +#include "board.h" + +DECLARE_GLOBAL_DATA_PTR; + +static struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE; +#ifdef CONFIG_SPL_BUILD +static struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE; +#endif + +/* 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_bone_lt(void) +{ + return !strncmp(header.name, "A335BNLT", 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) +#define UART_CLK_RUNNING_MASK 0x1 +#define UART_SMART_IDLE_EN (0x1 << 0x3) + +static void rtc32k_enable(void) +{ + struct rtc_regs *rtc = (struct rtc_regs *)AM335X_RTC_BASE; + + /* + * Unlock the RTC's registers. For more details please see the + * RTC_SS section of the TRM. In order to unlock we need to + * write these specific values (keys) in this order. + */ + writel(0x83e70b13, &rtc->kick0r); + writel(0x95a4f1e0, &rtc->kick1r); + + /* Enable the RTC 32K OSC by setting bits 3 and 6. */ + writel((1 << 3) | (1 << 6), &rtc->osc); +} + +static const struct ddr_data ddr2_data = { + .datardsratio0 = ((MT47H128M16RT25E_RD_DQS<<30) | + (MT47H128M16RT25E_RD_DQS<<20) | + (MT47H128M16RT25E_RD_DQS<<10) | + (MT47H128M16RT25E_RD_DQS<<0)), + .datawdsratio0 = ((MT47H128M16RT25E_WR_DQS<<30) | + (MT47H128M16RT25E_WR_DQS<<20) | + (MT47H128M16RT25E_WR_DQS<<10) | + (MT47H128M16RT25E_WR_DQS<<0)), + .datawiratio0 = ((MT47H128M16RT25E_PHY_WRLVL<<30) | + (MT47H128M16RT25E_PHY_WRLVL<<20) | + (MT47H128M16RT25E_PHY_WRLVL<<10) | + (MT47H128M16RT25E_PHY_WRLVL<<0)), + .datagiratio0 = ((MT47H128M16RT25E_PHY_GATELVL<<30) | + (MT47H128M16RT25E_PHY_GATELVL<<20) | + (MT47H128M16RT25E_PHY_GATELVL<<10) | + (MT47H128M16RT25E_PHY_GATELVL<<0)), + .datafwsratio0 = ((MT47H128M16RT25E_PHY_FIFO_WE<<30) | + (MT47H128M16RT25E_PHY_FIFO_WE<<20) | + (MT47H128M16RT25E_PHY_FIFO_WE<<10) | + (MT47H128M16RT25E_PHY_FIFO_WE<<0)), + .datawrsratio0 = ((MT47H128M16RT25E_PHY_WR_DATA<<30) | + (MT47H128M16RT25E_PHY_WR_DATA<<20) | + (MT47H128M16RT25E_PHY_WR_DATA<<10) | + (MT47H128M16RT25E_PHY_WR_DATA<<0)), + .datauserank0delay = MT47H128M16RT25E_PHY_RANK0_DELAY, + .datadldiff0 = PHY_DLL_LOCK_DIFF, +}; + +static const struct cmd_control ddr2_cmd_ctrl_data = { + .cmd0csratio = MT47H128M16RT25E_RATIO, + .cmd0dldiff = MT47H128M16RT25E_DLL_LOCK_DIFF, + .cmd0iclkout = MT47H128M16RT25E_INVERT_CLKOUT, + + .cmd1csratio = MT47H128M16RT25E_RATIO, + .cmd1dldiff = MT47H128M16RT25E_DLL_LOCK_DIFF, + .cmd1iclkout = MT47H128M16RT25E_INVERT_CLKOUT, + + .cmd2csratio = MT47H128M16RT25E_RATIO, + .cmd2dldiff = MT47H128M16RT25E_DLL_LOCK_DIFF, + .cmd2iclkout = MT47H128M16RT25E_INVERT_CLKOUT, +}; + +static const struct emif_regs ddr2_emif_reg_data = { + .sdram_config = MT47H128M16RT25E_EMIF_SDCFG, + .ref_ctrl = MT47H128M16RT25E_EMIF_SDREF, + .sdram_tim1 = MT47H128M16RT25E_EMIF_TIM1, + .sdram_tim2 = MT47H128M16RT25E_EMIF_TIM2, + .sdram_tim3 = MT47H128M16RT25E_EMIF_TIM3, + .emif_ddr_phy_ctlr_1 = MT47H128M16RT25E_EMIF_READ_LATENCY, +}; + +static const struct ddr_data ddr3_data = { + .datardsratio0 = MT41J128MJT125_RD_DQS, + .datawdsratio0 = MT41J128MJT125_WR_DQS, + .datafwsratio0 = MT41J128MJT125_PHY_FIFO_WE, + .datawrsratio0 = MT41J128MJT125_PHY_WR_DATA, + .datadldiff0 = PHY_DLL_LOCK_DIFF, +}; + +static const struct cmd_control ddr3_cmd_ctrl_data = { + .cmd0csratio = MT41J128MJT125_RATIO, + .cmd0dldiff = MT41J128MJT125_DLL_LOCK_DIFF, + .cmd0iclkout = MT41J128MJT125_INVERT_CLKOUT, + + .cmd1csratio = MT41J128MJT125_RATIO, + .cmd1dldiff = MT41J128MJT125_DLL_LOCK_DIFF, + .cmd1iclkout = MT41J128MJT125_INVERT_CLKOUT, + + .cmd2csratio = MT41J128MJT125_RATIO, + .cmd2dldiff = MT41J128MJT125_DLL_LOCK_DIFF, + .cmd2iclkout = MT41J128MJT125_INVERT_CLKOUT, +}; + +static struct emif_regs ddr3_emif_reg_data = { + .sdram_config = MT41J128MJT125_EMIF_SDCFG, + .ref_ctrl = MT41J128MJT125_EMIF_SDREF, + .sdram_tim1 = MT41J128MJT125_EMIF_TIM1, + .sdram_tim2 = MT41J128MJT125_EMIF_TIM2, + .sdram_tim3 = MT41J128MJT125_EMIF_TIM3, + .zq_config = MT41J128MJT125_ZQ_CFG, + .emif_ddr_phy_ctlr_1 = MT41J128MJT125_EMIF_READ_LATENCY, +}; +#endif + +/* + * early system init of muxing and clocks. + */ +void s_init(void) +{ + /* WDT1 is already running when the bootloader gets control + * Disable it to avoid "random" resets + */ + writel(0xAAAA, &wdtimer->wdtwspr); + while (readl(&wdtimer->wdtwwps) != 0x0) + ; + writel(0x5555, &wdtimer->wdtwspr); + while (readl(&wdtimer->wdtwwps) != 0x0) + ; + +#ifdef CONFIG_SPL_BUILD + /* Setup the PLLs and the clocks for the peripherals */ + pll_init(); + + /* Enable RTC32K clock */ + rtc32k_enable(); + + /* UART softreset */ + u32 regVal; + + enable_uart0_pin_mux(); + + regVal = readl(&uart_base->uartsyscfg); + regVal |= UART_RESET; + writel(regVal, &uart_base->uartsyscfg); + while ((readl(&uart_base->uartsyssts) & + UART_CLK_RUNNING_MASK) != UART_CLK_RUNNING_MASK) + ; + + /* Disable smart idle */ + regVal = readl(&uart_base->uartsyscfg); + regVal |= UART_SMART_IDLE_EN; + writel(regVal, &uart_base->uartsyscfg); + + gd = &gdata; + + preloader_console_init(); + + /* 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_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); + } + + if (board_is_evm_sk() || board_is_bone_lt()) + config_ddr(303, MT41J128MJT125_IOCTRL_VALUE, &ddr3_data, + &ddr3_cmd_ctrl_data, &ddr3_emif_reg_data); + else + config_ddr(266, MT47H128M16RT25E_IOCTRL_VALUE, &ddr2_data, + &ddr2_cmd_ctrl_data, &ddr2_emif_reg_data); +#endif +} + +/* + * 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() || board_is_bone_lt()) { + 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/board/ti/am335x/board.h b/board/ti/am335x/board.h new file mode 100644 index 0000000..7985ab2 --- /dev/null +++ b/board/ti/am335x/board.h @@ -0,0 +1,49 @@ +/* + * board.h + * + * TI AM335x boards information header + * + * 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; 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. + */ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +/* + * TI AM335x parts define a system EEPROM that defines certain sub-fields. + * We use these fields to in turn see what board we are on, and what + * that might require us to set or not set. + */ +#define HDR_NO_OF_MAC_ADDR 3 +#define HDR_ETH_ALEN 6 +#define HDR_NAME_LEN 8 + +struct am335x_baseboard_id { + unsigned int magic; + char name[HDR_NAME_LEN]; + char version[4]; + char serial[12]; + char config[32]; + char mac_addr[HDR_NO_OF_MAC_ADDR][HDR_ETH_ALEN]; +}; + +/* + * We have three pin mux functions that must exist. We must be able to enable + * uart0, for initial output and i2c0 to read the main EEPROM. We then have a + * main pinmux function that can be overridden to enable all other pinmux that + * is required on the board. + */ +void enable_uart0_pin_mux(void); +void enable_i2c0_pin_mux(void); +void enable_board_pin_mux(struct am335x_baseboard_id *header); +#endif diff --git a/board/ti/am335x/mux.c b/board/ti/am335x/mux.c index 80becd5..2992979 100644 --- a/board/ti/am335x/mux.c +++ b/board/ti/am335x/mux.c @@ -16,242 +16,10 @@ #include <common.h> #include <asm/arch/sys_proto.h> #include <asm/arch/hardware.h> +#include <asm/arch/mux.h> #include <asm/io.h> #include <i2c.h> - -#define MUX_CFG(value, offset) \ - __raw_writel(value, (CTRL_BASE + offset)); - -/* PAD Control Fields */ -#define SLEWCTRL (0x1 << 6) -#define RXACTIVE (0x1 << 5) -#define PULLUP_EN (0x1 << 4) /* Pull UP Selection */ -#define PULLUDEN (0x0 << 3) /* Pull up enabled */ -#define PULLUDDIS (0x1 << 3) /* Pull up disabled */ -#define MODE(val) val /* used for Readability */ - -/* - * PAD CONTROL OFFSETS - * Field names corresponds to the pad signal name - */ -struct pad_signals { - int gpmc_ad0; - int gpmc_ad1; - int gpmc_ad2; - int gpmc_ad3; - int gpmc_ad4; - int gpmc_ad5; - int gpmc_ad6; - int gpmc_ad7; - int gpmc_ad8; - int gpmc_ad9; - int gpmc_ad10; - int gpmc_ad11; - int gpmc_ad12; - int gpmc_ad13; - int gpmc_ad14; - int gpmc_ad15; - int gpmc_a0; - int gpmc_a1; - int gpmc_a2; - int gpmc_a3; - int gpmc_a4; - int gpmc_a5; - int gpmc_a6; - int gpmc_a7; - int gpmc_a8; - int gpmc_a9; - int gpmc_a10; - int gpmc_a11; - int gpmc_wait0; - int gpmc_wpn; - int gpmc_be1n; - int gpmc_csn0; - int gpmc_csn1; - int gpmc_csn2; - int gpmc_csn3; - int gpmc_clk; - int gpmc_advn_ale; - int gpmc_oen_ren; - int gpmc_wen; - int gpmc_be0n_cle; - int lcd_data0; - int lcd_data1; - int lcd_data2; - int lcd_data3; - int lcd_data4; - int lcd_data5; - int lcd_data6; - int lcd_data7; - int lcd_data8; - int lcd_data9; - int lcd_data10; - int lcd_data11; - int lcd_data12; - int lcd_data13; - int lcd_data14; - int lcd_data15; - int lcd_vsync; - int lcd_hsync; - int lcd_pclk; - int lcd_ac_bias_en; - int mmc0_dat3; - int mmc0_dat2; - int mmc0_dat1; - int mmc0_dat0; - int mmc0_clk; - int mmc0_cmd; - int mii1_col; - int mii1_crs; - int mii1_rxerr; - int mii1_txen; - int mii1_rxdv; - int mii1_txd3; - int mii1_txd2; - int mii1_txd1; - int mii1_txd0; - int mii1_txclk; - int mii1_rxclk; - int mii1_rxd3; - int mii1_rxd2; - int mii1_rxd1; - int mii1_rxd0; - int rmii1_refclk; - int mdio_data; - int mdio_clk; - int spi0_sclk; - int spi0_d0; - int spi0_d1; - int spi0_cs0; - int spi0_cs1; - int ecap0_in_pwm0_out; - int uart0_ctsn; - int uart0_rtsn; - int uart0_rxd; - int uart0_txd; - int uart1_ctsn; - int uart1_rtsn; - int uart1_rxd; - int uart1_txd; - int i2c0_sda; - int i2c0_scl; - int mcasp0_aclkx; - int mcasp0_fsx; - int mcasp0_axr0; - int mcasp0_ahclkr; - int mcasp0_aclkr; - int mcasp0_fsr; - int mcasp0_axr1; - int mcasp0_ahclkx; - int xdma_event_intr0; - int xdma_event_intr1; - int nresetin_out; - int porz; - int nnmi; - int osc0_in; - int osc0_out; - int rsvd1; - int tms; - int tdi; - int tdo; - int tck; - int ntrst; - int emu0; - int emu1; - int osc1_in; - int osc1_out; - int pmic_power_en; - int rtc_porz; - int rsvd2; - int ext_wakeup; - int enz_kaldo_1p8v; - int usb0_dm; - int usb0_dp; - int usb0_ce; - int usb0_id; - int usb0_vbus; - int usb0_drvvbus; - int usb1_dm; - int usb1_dp; - int usb1_ce; - int usb1_id; - int usb1_vbus; - int usb1_drvvbus; - int ddr_resetn; - int ddr_csn0; - int ddr_cke; - int ddr_ck; - int ddr_nck; - int ddr_casn; - int ddr_rasn; - int ddr_wen; - int ddr_ba0; - int ddr_ba1; - int ddr_ba2; - int ddr_a0; - int ddr_a1; - int ddr_a2; - int ddr_a3; - int ddr_a4; - int ddr_a5; - int ddr_a6; - int ddr_a7; - int ddr_a8; - int ddr_a9; - int ddr_a10; - int ddr_a11; - int ddr_a12; - int ddr_a13; - int ddr_a14; - int ddr_a15; - int ddr_odt; - int ddr_d0; - int ddr_d1; - int ddr_d2; - int ddr_d3; - int ddr_d4; - int ddr_d5; - int ddr_d6; - int ddr_d7; - int ddr_d8; - int ddr_d9; - int ddr_d10; - int ddr_d11; - int ddr_d12; - int ddr_d13; - int ddr_d14; - int ddr_d15; - int ddr_dqm0; - int ddr_dqm1; - int ddr_dqs0; - int ddr_dqsn0; - int ddr_dqs1; - int ddr_dqsn1; - int ddr_vref; - int ddr_vtp; - int ddr_strben0; - int ddr_strben1; - int ain7; - int ain6; - int ain5; - int ain4; - int ain3; - int ain2; - int ain1; - int ain0; - int vrefp; - int vrefn; -}; - -struct module_pin_mux { - short reg_offset; - unsigned char val; -}; - -/* Pad control register offset */ -#define PAD_CTRL_BASE 0x800 -#define OFFSET(x) (unsigned int) (&((struct pad_signals *) \ - (PAD_CTRL_BASE))->x) +#include "board.h" static struct module_pin_mux uart0_pin_mux[] = { {OFFSET(uart0_rxd), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* UART0_RXD */ @@ -362,20 +130,6 @@ static struct module_pin_mux mii1_pin_mux[] = { {-1}, }; -/* - * Configure the pin mux for the module - */ -static void configure_module_pin_mux(struct module_pin_mux *mod_pin_mux) -{ - int i; - - if (!mod_pin_mux) - return; - - for (i = 0; mod_pin_mux[i].reg_offset != -1; i++) - MUX_CFG(mod_pin_mux[i].val, mod_pin_mux[i].reg_offset); -} - void enable_uart0_pin_mux(void) { configure_module_pin_mux(uart0_pin_mux); |