diff options
Diffstat (limited to 'arch/arm/cpu/armv7/am33xx')
-rw-r--r-- | arch/arm/cpu/armv7/am33xx/Makefile | 48 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/am33xx/board.c | 66 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/am33xx/clock.c | 273 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/am33xx/ddr.c | 147 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/am33xx/emif4.c | 201 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/am33xx/lowlevel_init.S | 72 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/am33xx/sys_info.c | 130 |
7 files changed, 937 insertions, 0 deletions
diff --git a/arch/arm/cpu/armv7/am33xx/Makefile b/arch/arm/cpu/armv7/am33xx/Makefile new file mode 100644 index 0000000000..6beafbbece --- /dev/null +++ b/arch/arm/cpu/armv7/am33xx/Makefile @@ -0,0 +1,48 @@ +# +# 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 "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 $(TOPDIR)/config.mk + +LIB = $(obj)lib$(SOC).o + +SOBJS := lowlevel_init.o + +COBJS += clock.o +COBJS += sys_info.o +COBJS += ddr.o +COBJS += emif4.o +COBJS += board.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS) $(COBJS-y) $(SOBJS)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/arm/cpu/armv7/am33xx/board.c b/arch/arm/cpu/armv7/am33xx/board.c new file mode 100644 index 0000000000..2d6d359e5f --- /dev/null +++ b/arch/arm/cpu/armv7/am33xx/board.c @@ -0,0 +1,66 @@ +/* + * board.c + * + * Common board functions for AM33XX 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 <asm/arch/cpu.h> +#include <asm/arch/hardware.h> +#include <asm/arch/ddr_defs.h> +#include <asm/arch/clock.h> +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE; +struct timer_reg *timerreg = (struct timer_reg *)DM_TIMER2_BASE; + +/* + * early system init of muxing and clocks. + */ +void s_init(u32 in_ddr) +{ + /* 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) + ; + + /* Setup the PLLs and the clocks for the peripherals */ +#ifdef CONFIG_SETUP_PLL + pll_init(); +#endif + if (!in_ddr) + config_ddr(); +} + +/* Initialize timer */ +void init_timer(void) +{ + /* Reset the Timer */ + writel(0x2, (&timerreg->tsicrreg)); + + /* Wait until the reset is done */ + while (readl(&timerreg->tiocpcfgreg) & 1) + ; + + /* Start the Timer */ + writel(0x1, (&timerreg->tclrreg)); +} diff --git a/arch/arm/cpu/armv7/am33xx/clock.c b/arch/arm/cpu/armv7/am33xx/clock.c new file mode 100644 index 0000000000..4ca6c45349 --- /dev/null +++ b/arch/arm/cpu/armv7/am33xx/clock.c @@ -0,0 +1,273 @@ +/* + * clock.c + * + * clocks for AM33XX 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 <asm/arch/cpu.h> +#include <asm/arch/clock.h> +#include <asm/arch/hardware.h> +#include <asm/io.h> + +#define PRCM_MOD_EN 0x2 +#define PRCM_FORCE_WAKEUP 0x2 + +#define PRCM_EMIF_CLK_ACTIVITY BIT(2) +#define PRCM_L3_GCLK_ACTIVITY BIT(4) + +#define PLL_BYPASS_MODE 0x4 +#define ST_MN_BYPASS 0x00000100 +#define ST_DPLL_CLK 0x00000001 +#define CLK_SEL_MASK 0x7ffff +#define CLK_DIV_MASK 0x1f +#define CLK_DIV2_MASK 0x7f +#define CLK_SEL_SHIFT 0x8 +#define CLK_MODE_SEL 0x7 +#define CLK_MODE_MASK 0xfffffff8 +#define CLK_DIV_SEL 0xFFFFFFE0 + + +const struct cm_perpll *cmper = (struct cm_perpll *)CM_PER; +const struct cm_wkuppll *cmwkup = (struct cm_wkuppll *)CM_WKUP; +const struct cm_dpll *cmdpll = (struct cm_dpll *)CM_DPLL; + +static void enable_interface_clocks(void) +{ + /* Enable all the Interconnect Modules */ + writel(PRCM_MOD_EN, &cmper->l3clkctrl); + while (readl(&cmper->l3clkctrl) != PRCM_MOD_EN) + ; + + writel(PRCM_MOD_EN, &cmper->l4lsclkctrl); + while (readl(&cmper->l4lsclkctrl) != PRCM_MOD_EN) + ; + + writel(PRCM_MOD_EN, &cmper->l4fwclkctrl); + while (readl(&cmper->l4fwclkctrl) != PRCM_MOD_EN) + ; + + writel(PRCM_MOD_EN, &cmwkup->wkl4wkclkctrl); + while (readl(&cmwkup->wkl4wkclkctrl) != PRCM_MOD_EN) + ; + + writel(PRCM_MOD_EN, &cmper->l3instrclkctrl); + while (readl(&cmper->l3instrclkctrl) != PRCM_MOD_EN) + ; + + writel(PRCM_MOD_EN, &cmper->l4hsclkctrl); + while (readl(&cmper->l4hsclkctrl) != PRCM_MOD_EN) + ; +} + +/* + * Force power domain wake up transition + * Ensure that the corresponding interface clock is active before + * using the peripheral + */ +static void power_domain_wkup_transition(void) +{ + writel(PRCM_FORCE_WAKEUP, &cmper->l3clkstctrl); + writel(PRCM_FORCE_WAKEUP, &cmper->l4lsclkstctrl); + writel(PRCM_FORCE_WAKEUP, &cmwkup->wkclkstctrl); + writel(PRCM_FORCE_WAKEUP, &cmper->l4fwclkstctrl); + writel(PRCM_FORCE_WAKEUP, &cmper->l3sclkstctrl); +} + +/* + * Enable the peripheral clock for required peripherals + */ +static void enable_per_clocks(void) +{ + /* Enable the control module though RBL would have done it*/ + writel(PRCM_MOD_EN, &cmwkup->wkctrlclkctrl); + while (readl(&cmwkup->wkctrlclkctrl) != PRCM_MOD_EN) + ; + + /* Enable the module clock */ + writel(PRCM_MOD_EN, &cmper->timer2clkctrl); + while (readl(&cmper->timer2clkctrl) != PRCM_MOD_EN) + ; + + /* UART0 */ + writel(PRCM_MOD_EN, &cmwkup->wkup_uart0ctrl); + while (readl(&cmwkup->wkup_uart0ctrl) != PRCM_MOD_EN) + ; +} + +static void mpu_pll_config(void) +{ + u32 clkmode, clksel, div_m2; + + clkmode = readl(&cmwkup->clkmoddpllmpu); + clksel = readl(&cmwkup->clkseldpllmpu); + div_m2 = readl(&cmwkup->divm2dpllmpu); + + /* Set the PLL to bypass Mode */ + writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllmpu); + while (readl(&cmwkup->idlestdpllmpu) != ST_MN_BYPASS) + ; + + clksel = clksel & (~CLK_SEL_MASK); + clksel = clksel | ((MPUPLL_M << CLK_SEL_SHIFT) | MPUPLL_N); + writel(clksel, &cmwkup->clkseldpllmpu); + + div_m2 = div_m2 & ~CLK_DIV_MASK; + div_m2 = div_m2 | MPUPLL_M2; + writel(div_m2, &cmwkup->divm2dpllmpu); + + clkmode = clkmode | CLK_MODE_SEL; + writel(clkmode, &cmwkup->clkmoddpllmpu); + + while (readl(&cmwkup->idlestdpllmpu) != ST_DPLL_CLK) + ; +} + +static void core_pll_config(void) +{ + u32 clkmode, clksel, div_m4, div_m5, div_m6; + + clkmode = readl(&cmwkup->clkmoddpllcore); + clksel = readl(&cmwkup->clkseldpllcore); + div_m4 = readl(&cmwkup->divm4dpllcore); + div_m5 = readl(&cmwkup->divm5dpllcore); + div_m6 = readl(&cmwkup->divm6dpllcore); + + /* Set the PLL to bypass Mode */ + writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllcore); + + while (readl(&cmwkup->idlestdpllcore) != ST_MN_BYPASS) + ; + + clksel = clksel & (~CLK_SEL_MASK); + clksel = clksel | ((COREPLL_M << CLK_SEL_SHIFT) | COREPLL_N); + writel(clksel, &cmwkup->clkseldpllcore); + + div_m4 = div_m4 & ~CLK_DIV_MASK; + div_m4 = div_m4 | COREPLL_M4; + writel(div_m4, &cmwkup->divm4dpllcore); + + div_m5 = div_m5 & ~CLK_DIV_MASK; + div_m5 = div_m5 | COREPLL_M5; + writel(div_m5, &cmwkup->divm5dpllcore); + + div_m6 = div_m6 & ~CLK_DIV_MASK; + div_m6 = div_m6 | COREPLL_M6; + writel(div_m6, &cmwkup->divm6dpllcore); + + clkmode = clkmode | CLK_MODE_SEL; + writel(clkmode, &cmwkup->clkmoddpllcore); + + while (readl(&cmwkup->idlestdpllcore) != ST_DPLL_CLK) + ; +} + +static void per_pll_config(void) +{ + u32 clkmode, clksel, div_m2; + + clkmode = readl(&cmwkup->clkmoddpllper); + clksel = readl(&cmwkup->clkseldpllper); + div_m2 = readl(&cmwkup->divm2dpllper); + + /* Set the PLL to bypass Mode */ + writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllper); + + while (readl(&cmwkup->idlestdpllper) != ST_MN_BYPASS) + ; + + clksel = clksel & (~CLK_SEL_MASK); + clksel = clksel | ((PERPLL_M << CLK_SEL_SHIFT) | PERPLL_N); + writel(clksel, &cmwkup->clkseldpllper); + + div_m2 = div_m2 & ~CLK_DIV2_MASK; + div_m2 = div_m2 | PERPLL_M2; + writel(div_m2, &cmwkup->divm2dpllper); + + clkmode = clkmode | CLK_MODE_SEL; + writel(clkmode, &cmwkup->clkmoddpllper); + + while (readl(&cmwkup->idlestdpllper) != ST_DPLL_CLK) + ; +} + +static void ddr_pll_config(void) +{ + u32 clkmode, clksel, div_m2; + + clkmode = readl(&cmwkup->clkmoddpllddr); + clksel = readl(&cmwkup->clkseldpllddr); + div_m2 = readl(&cmwkup->divm2dpllddr); + + /* Set the PLL to bypass Mode */ + clkmode = (clkmode & CLK_MODE_MASK) | PLL_BYPASS_MODE; + writel(clkmode, &cmwkup->clkmoddpllddr); + + /* Wait till bypass mode is enabled */ + while ((readl(&cmwkup->idlestdpllddr) & ST_MN_BYPASS) + != ST_MN_BYPASS) + ; + + clksel = clksel & (~CLK_SEL_MASK); + clksel = clksel | ((DDRPLL_M << CLK_SEL_SHIFT) | DDRPLL_N); + writel(clksel, &cmwkup->clkseldpllddr); + + div_m2 = div_m2 & CLK_DIV_SEL; + div_m2 = div_m2 | DDRPLL_M2; + writel(div_m2, &cmwkup->divm2dpllddr); + + clkmode = (clkmode & CLK_MODE_MASK) | CLK_MODE_SEL; + writel(clkmode, &cmwkup->clkmoddpllddr); + + /* Wait till dpll is locked */ + while ((readl(&cmwkup->idlestdpllddr) & ST_DPLL_CLK) != ST_DPLL_CLK) + ; +} + +void enable_emif_clocks(void) +{ + /* Enable the EMIF_FW Functional clock */ + writel(PRCM_MOD_EN, &cmper->emiffwclkctrl); + /* Enable EMIF0 Clock */ + writel(PRCM_MOD_EN, &cmper->emifclkctrl); + /* Poll for emif_gclk & L3_G clock are active */ + while ((readl(&cmper->l3clkstctrl) & (PRCM_EMIF_CLK_ACTIVITY | + PRCM_L3_GCLK_ACTIVITY)) != (PRCM_EMIF_CLK_ACTIVITY | + PRCM_L3_GCLK_ACTIVITY)) + ; + /* Poll if module is functional */ + while ((readl(&cmper->emifclkctrl)) != PRCM_MOD_EN) + ; +} + +/* + * Configure the PLL/PRCM for necessary peripherals + */ +void pll_init() +{ + mpu_pll_config(); + core_pll_config(); + per_pll_config(); + ddr_pll_config(); + + /* Enable the required interconnect clocks */ + enable_interface_clocks(); + + /* Power domain wake up transition */ + power_domain_wkup_transition(); + + /* Enable the required peripherals */ + enable_per_clocks(); +} diff --git a/arch/arm/cpu/armv7/am33xx/ddr.c b/arch/arm/cpu/armv7/am33xx/ddr.c new file mode 100644 index 0000000000..ed982c11e8 --- /dev/null +++ b/arch/arm/cpu/armv7/am33xx/ddr.c @@ -0,0 +1,147 @@ +/* + * DDR Configuration for AM33xx devices. + * + * 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 .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 <asm/arch/cpu.h> +#include <asm/arch/ddr_defs.h> +#include <asm/io.h> + +/** + * Base address for EMIF instances + */ +static struct emif_regs *emif_reg = { + (struct emif_regs *)EMIF4_0_CFG_BASE}; + +/** + * Base address for DDR instance + */ +static struct ddr_regs *ddr_reg[2] = { + (struct ddr_regs *)DDR_PHY_BASE_ADDR, + (struct ddr_regs *)DDR_PHY_BASE_ADDR2}; + +/** + * Base address for ddr io control instances + */ +static struct ddr_cmdtctrl *ioctrl_reg = { + (struct ddr_cmdtctrl *)DDR_CONTROL_BASE_ADDR}; + +/** + * As a convention, all functions here return 0 on success + * -1 on failure. + */ + +/** + * Configure SDRAM + */ +int config_sdram(struct sdram_config *cfg) +{ + writel(cfg->sdrcr, &emif_reg->sdrcr); + writel(cfg->sdrcr2, &emif_reg->sdrcr2); + writel(cfg->refresh, &emif_reg->sdrrcr); + writel(cfg->refresh_sh, &emif_reg->sdrrcsr); + + return 0; +} + +/** + * Set SDRAM timings + */ +int set_sdram_timings(struct sdram_timing *t) +{ + writel(t->time1, &emif_reg->sdrtim1); + writel(t->time1_sh, &emif_reg->sdrtim1sr); + writel(t->time2, &emif_reg->sdrtim2); + writel(t->time2_sh, &emif_reg->sdrtim2sr); + writel(t->time3, &emif_reg->sdrtim3); + writel(t->time3_sh, &emif_reg->sdrtim3sr); + + return 0; +} + +/** + * Configure DDR PHY + */ +int config_ddr_phy(struct ddr_phy_control *p) +{ + writel(p->reg, &emif_reg->ddrphycr); + writel(p->reg_sh, &emif_reg->ddrphycsr); + + return 0; +} + +/** + * Configure DDR CMD control registers + */ +int config_cmd_ctrl(struct cmd_control *cmd) +{ + writel(cmd->cmd0csratio, &ddr_reg[0]->cm0csratio); + writel(cmd->cmd0csforce, &ddr_reg[0]->cm0csforce); + writel(cmd->cmd0csdelay, &ddr_reg[0]->cm0csdelay); + writel(cmd->cmd0dldiff, &ddr_reg[0]->cm0dldiff); + writel(cmd->cmd0iclkout, &ddr_reg[0]->cm0iclkout); + + writel(cmd->cmd1csratio, &ddr_reg[0]->cm1csratio); + writel(cmd->cmd1csforce, &ddr_reg[0]->cm1csforce); + writel(cmd->cmd1csdelay, &ddr_reg[0]->cm1csdelay); + writel(cmd->cmd1dldiff, &ddr_reg[0]->cm1dldiff); + writel(cmd->cmd1iclkout, &ddr_reg[0]->cm1iclkout); + + writel(cmd->cmd2csratio, &ddr_reg[0]->cm2csratio); + writel(cmd->cmd2csforce, &ddr_reg[0]->cm2csforce); + writel(cmd->cmd2csdelay, &ddr_reg[0]->cm2csdelay); + writel(cmd->cmd2dldiff, &ddr_reg[0]->cm2dldiff); + writel(cmd->cmd2iclkout, &ddr_reg[0]->cm2iclkout); + + return 0; +} + +/** + * Configure DDR DATA registers + */ +int config_ddr_data(int macrono, struct ddr_data *data) +{ + writel(data->datardsratio0, &ddr_reg[macrono]->dt0rdsratio0); + writel(data->datardsratio1, &ddr_reg[macrono]->dt0rdsratio1); + + writel(data->datawdsratio0, &ddr_reg[macrono]->dt0wdsratio0); + writel(data->datawdsratio1, &ddr_reg[macrono]->dt0wdsratio1); + + writel(data->datawiratio0, &ddr_reg[macrono]->dt0wiratio0); + writel(data->datawiratio1, &ddr_reg[macrono]->dt0wiratio1); + writel(data->datagiratio0, &ddr_reg[macrono]->dt0giratio0); + writel(data->datagiratio1, &ddr_reg[macrono]->dt0giratio1); + + writel(data->datafwsratio0, &ddr_reg[macrono]->dt0fwsratio0); + writel(data->datafwsratio1, &ddr_reg[macrono]->dt0fwsratio1); + + writel(data->datawrsratio0, &ddr_reg[macrono]->dt0wrsratio0); + writel(data->datawrsratio1, &ddr_reg[macrono]->dt0wrsratio1); + + writel(data->datadldiff0, &ddr_reg[macrono]->dt0dldiff0); + + return 0; +} + +int config_io_ctrl(struct ddr_ioctrl *ioctrl) +{ + writel(ioctrl->cmd1ctl, &ioctrl_reg->cm0ioctl); + writel(ioctrl->cmd2ctl, &ioctrl_reg->cm1ioctl); + writel(ioctrl->cmd3ctl, &ioctrl_reg->cm2ioctl); + writel(ioctrl->data1ctl, &ioctrl_reg->dt0ioctl); + writel(ioctrl->data2ctl, &ioctrl_reg->dt1ioctl); + + return 0; +} diff --git a/arch/arm/cpu/armv7/am33xx/emif4.c b/arch/arm/cpu/armv7/am33xx/emif4.c new file mode 100644 index 0000000000..1318365a4a --- /dev/null +++ b/arch/arm/cpu/armv7/am33xx/emif4.c @@ -0,0 +1,201 @@ +/* + * emif4.c + * + * AM33XX emif4 configuration file + * + * 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 <asm/arch/cpu.h> +#include <asm/arch/ddr_defs.h> +#include <asm/arch/hardware.h> +#include <asm/arch/clock.h> +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct ddr_regs *ddrregs = (struct ddr_regs *)DDR_PHY_BASE_ADDR; +struct vtp_reg *vtpreg = (struct vtp_reg *)VTP0_CTRL_ADDR; +struct ddr_ctrl *ddrctrl = (struct ddr_ctrl *)DDR_CTRL_ADDR; + + +int dram_init(void) +{ + /* dram_init must store complete ramsize in gd->ram_size */ + gd->ram_size = get_ram_size( + (void *)CONFIG_SYS_SDRAM_BASE, + CONFIG_MAX_RAM_BANK_SIZE); + return 0; +} + +void dram_init_banksize(void) +{ + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; + gd->bd->bi_dram[0].size = gd->ram_size; +} + + +#ifdef CONFIG_AM335X_CONFIG_DDR +static void data_macro_config(int dataMacroNum) +{ + struct ddr_data data; + + data.datardsratio0 = ((DDR2_RD_DQS<<30)|(DDR2_RD_DQS<<20) + |(DDR2_RD_DQS<<10)|(DDR2_RD_DQS<<0)); + data.datardsratio1 = DDR2_RD_DQS>>2; + data.datawdsratio0 = ((DDR2_WR_DQS<<30)|(DDR2_WR_DQS<<20) + |(DDR2_WR_DQS<<10)|(DDR2_WR_DQS<<0)); + data.datawdsratio1 = DDR2_WR_DQS>>2; + data.datawiratio0 = ((DDR2_PHY_WRLVL<<30)|(DDR2_PHY_WRLVL<<20) + |(DDR2_PHY_WRLVL<<10)|(DDR2_PHY_WRLVL<<0)); + data.datawiratio1 = DDR2_PHY_WRLVL>>2; + data.datagiratio0 = ((DDR2_PHY_GATELVL<<30)|(DDR2_PHY_GATELVL<<20) + |(DDR2_PHY_GATELVL<<10)|(DDR2_PHY_GATELVL<<0)); + data.datagiratio1 = DDR2_PHY_GATELVL>>2; + data.datafwsratio0 = ((DDR2_PHY_FIFO_WE<<30)|(DDR2_PHY_FIFO_WE<<20) + |(DDR2_PHY_FIFO_WE<<10)|(DDR2_PHY_FIFO_WE<<0)); + data.datafwsratio1 = DDR2_PHY_FIFO_WE>>2; + data.datawrsratio0 = ((DDR2_PHY_WR_DATA<<30)|(DDR2_PHY_WR_DATA<<20) + |(DDR2_PHY_WR_DATA<<10)|(DDR2_PHY_WR_DATA<<0)); + data.datawrsratio1 = DDR2_PHY_WR_DATA>>2; + data.datadldiff0 = PHY_DLL_LOCK_DIFF; + + config_ddr_data(dataMacroNum, &data); +} + +static void cmd_macro_config(void) +{ + struct cmd_control cmd; + + cmd.cmd0csratio = DDR2_RATIO; + cmd.cmd0csforce = CMD_FORCE; + cmd.cmd0csdelay = CMD_DELAY; + cmd.cmd0dldiff = DDR2_DLL_LOCK_DIFF; + cmd.cmd0iclkout = DDR2_INVERT_CLKOUT; + + cmd.cmd1csratio = DDR2_RATIO; + cmd.cmd1csforce = CMD_FORCE; + cmd.cmd1csdelay = CMD_DELAY; + cmd.cmd1dldiff = DDR2_DLL_LOCK_DIFF; + cmd.cmd1iclkout = DDR2_INVERT_CLKOUT; + + cmd.cmd2csratio = DDR2_RATIO; + cmd.cmd2csforce = CMD_FORCE; + cmd.cmd2csdelay = CMD_DELAY; + cmd.cmd2dldiff = DDR2_DLL_LOCK_DIFF; + cmd.cmd2iclkout = DDR2_INVERT_CLKOUT; + + config_cmd_ctrl(&cmd); + +} + +static void config_vtp(void) +{ + writel(readl(&vtpreg->vtp0ctrlreg) | VTP_CTRL_ENABLE, + &vtpreg->vtp0ctrlreg); + writel(readl(&vtpreg->vtp0ctrlreg) & (~VTP_CTRL_START_EN), + &vtpreg->vtp0ctrlreg); + writel(readl(&vtpreg->vtp0ctrlreg) | VTP_CTRL_START_EN, + &vtpreg->vtp0ctrlreg); + + /* Poll for READY */ + while ((readl(&vtpreg->vtp0ctrlreg) & VTP_CTRL_READY) != + VTP_CTRL_READY) + ; +} + +static void config_emif_ddr2(void) +{ + int i; + int ret; + struct sdram_config cfg; + struct sdram_timing tmg; + struct ddr_phy_control phyc; + + /*Program EMIF0 CFG Registers*/ + phyc.reg = EMIF_READ_LATENCY; + phyc.reg_sh = EMIF_READ_LATENCY; + phyc.reg2 = EMIF_READ_LATENCY; + + tmg.time1 = EMIF_TIM1; + tmg.time1_sh = EMIF_TIM1; + tmg.time2 = EMIF_TIM2; + tmg.time2_sh = EMIF_TIM2; + tmg.time3 = EMIF_TIM3; + tmg.time3_sh = EMIF_TIM3; + + cfg.sdrcr = EMIF_SDCFG; + cfg.sdrcr2 = EMIF_SDCFG; + cfg.refresh = 0x00004650; + cfg.refresh_sh = 0x00004650; + + /* Program EMIF instance */ + ret = config_ddr_phy(&phyc); + if (ret < 0) + printf("Couldn't configure phyc\n"); + + ret = config_sdram(&cfg); + if (ret < 0) + printf("Couldn't configure SDRAM\n"); + + ret = set_sdram_timings(&tmg); + if (ret < 0) + printf("Couldn't configure timings\n"); + + /* Delay */ + for (i = 0; i < 5000; i++) + ; + + cfg.refresh = EMIF_SDREF; + cfg.refresh_sh = EMIF_SDREF; + cfg.sdrcr = EMIF_SDCFG; + cfg.sdrcr2 = EMIF_SDCFG; + + ret = config_sdram(&cfg); + if (ret < 0) + printf("Couldn't configure SDRAM\n"); +} + +void config_ddr(void) +{ + int data_macro_0 = 0; + int data_macro_1 = 1; + struct ddr_ioctrl ioctrl; + + enable_emif_clocks(); + + config_vtp(); + + cmd_macro_config(); + + data_macro_config(data_macro_0); + data_macro_config(data_macro_1); + + writel(PHY_RANK0_DELAY, &ddrregs->dt0rdelays0); + writel(PHY_RANK0_DELAY, &ddrregs->dt1rdelays0); + + ioctrl.cmd1ctl = DDR_IOCTRL_VALUE; + ioctrl.cmd2ctl = DDR_IOCTRL_VALUE; + ioctrl.cmd3ctl = DDR_IOCTRL_VALUE; + ioctrl.data1ctl = DDR_IOCTRL_VALUE; + ioctrl.data2ctl = DDR_IOCTRL_VALUE; + + config_io_ctrl(&ioctrl); + + writel(readl(&ddrctrl->ddrioctrl) & 0xefffffff, &ddrctrl->ddrioctrl); + writel(readl(&ddrctrl->ddrckectrl) | 0x00000001, &ddrctrl->ddrckectrl); + + config_emif_ddr2(); +} +#endif diff --git a/arch/arm/cpu/armv7/am33xx/lowlevel_init.S b/arch/arm/cpu/armv7/am33xx/lowlevel_init.S new file mode 100644 index 0000000000..17c962ff71 --- /dev/null +++ b/arch/arm/cpu/armv7/am33xx/lowlevel_init.S @@ -0,0 +1,72 @@ +/* + * lowlevel_init.S + * + * AM33XX low level initialization. + * + * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ + * + * Initial Code by: + * Mansoor Ahamed <mansoor.ahamed@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 "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 <config.h> +#include <asm/arch/hardware.h> + +_mark1: + .word mark1 +_lowlevel_init1: + .word lowlevel_init +_s_init_start: + .word s_init_start + +_TEXT_BASE: + .word CONFIG_SYS_TEXT_BASE /* sdram load addr from config.mk */ + +/***************************************************************************** + * lowlevel_init: - Platform low level init. + ****************************************************************************/ +.globl lowlevel_init +lowlevel_init: + + /* The link register is saved in ip by start.S */ + mov r6, ip + /* check if we are already running from RAM */ + ldr r2, _lowlevel_init1 + ldr r3, _TEXT_BASE + sub r4, r2, r3 + sub r0, pc, r4 + ldr sp, SRAM_STACK +mark1: + ldr r5, _mark1 + sub r5, r5, r2 /* bytes between mark1 and lowlevel_init */ + sub r0, r0, r5 /* r0 <- _start w.r.t current place of execution */ + mov r10, #0x0 /* r10 has in_ddr used by s_init() */ + + ands r0, r0, #0xC0000000 + /* MSB 2 bits <> 0 then we are in ocmc or DDR */ + cmp r0, #0x80000000 + bne s_init_start + mov r10, #0x01 + b s_init_start + +s_init_start: + mov r0, r10 /* passing in_ddr in r0 */ + bl s_init + /* back to arch calling code */ + mov pc, r6 + /* the literal pools origin */ + .ltorg + +SRAM_STACK: + /* Place stack at the top */ + .word LOW_LEVEL_SRAM_STACK diff --git a/arch/arm/cpu/armv7/am33xx/sys_info.c b/arch/arm/cpu/armv7/am33xx/sys_info.c new file mode 100644 index 0000000000..507b6180e6 --- /dev/null +++ b/arch/arm/cpu/armv7/am33xx/sys_info.c @@ -0,0 +1,130 @@ +/* + * sys_info.c + * + * System information functions + * + * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ + * + * Derived from Beagle Board and 3430 SDP code by + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Mohammed Khasim <khasim@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 <asm/io.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clock.h> + +struct ctrl_stat *cstat = (struct ctrl_stat *)CTRL_BASE; + +/** + * get_cpu_rev(void) - extract rev info + */ +u32 get_cpu_rev(void) +{ + u32 id; + u32 rev; + + id = readl(DEVICE_ID); + rev = (id >> 28) & 0xff; + + return rev; +} + +/** + * get_cpu_type(void) - extract cpu info + */ +u32 get_cpu_type(void) +{ + u32 id = 0; + u32 partnum; + + id = readl(DEVICE_ID); + partnum = (id >> 12) & 0xffff; + + return partnum; +} + +/** + * get_board_rev() - setup to pass kernel board revision information + * returns:(bit[0-3] sub version, higher bit[7-4] is higher version) + */ +u32 get_board_rev(void) +{ + return BOARD_REV_ID; +} + +/** + * get_device_type(): tell if GP/HS/EMU/TST + */ +u32 get_device_type(void) +{ + int mode; + mode = readl(&cstat->statusreg) & (DEVICE_MASK); + return mode >>= 8; +} + +/** + * get_sysboot_value(void) - return SYS_BOOT[4:0] + */ +u32 get_sysboot_value(void) +{ + int mode; + mode = readl(&cstat->statusreg) & (SYSBOOT_MASK); + return mode; +} + +#ifdef CONFIG_DISPLAY_CPUINFO +/** + * Print CPU information + */ +int print_cpuinfo(void) +{ + char *cpu_s, *sec_s; + int arm_freq, ddr_freq; + + switch (get_cpu_type()) { + case AM335X: + cpu_s = "AM335X"; + break; + default: + cpu_s = "Unknown cpu type"; + break; + } + + switch (get_device_type()) { + case TST_DEVICE: + sec_s = "TST"; + break; + case EMU_DEVICE: + sec_s = "EMU"; + break; + case HS_DEVICE: + sec_s = "HS"; + break; + case GP_DEVICE: + sec_s = "GP"; + break; + default: + sec_s = "?"; + } + + printf("AM%s-%s rev %d\n", + cpu_s, sec_s, get_cpu_rev()); + + /* TODO: Print ARM and DDR frequencies */ + + return 0; +} +#endif /* CONFIG_DISPLAY_CPUINFO */ |