blob: 313e5e997bf13c392e7c4d90e9d22d4576712b7f [file] [log] [blame]
#include <common.h>
#include <init.h>
#include <mach/silicon.h>
#include <asm/io.h>
#include <mach/omap4-silicon.h>
#include <mach/omap4-clock.h>
#include <mach/syslib.h>
#include <mach/xload.h>
void __noreturn reset_cpu(unsigned long addr)
{
writel(PRM_RSTCTRL_RESET, PRM_RSTCTRL);
while (1);
}
#define WATCHDOG_WSPR 0x48
#define WATCHDOG_WWPS 0x34
static void wait_for_command_complete(void)
{
int pending = 1;
do {
pending = readl(OMAP44XX_WDT2_BASE + WATCHDOG_WWPS);
} while (pending);
}
/* EMIF */
#define EMIF_MOD_ID_REV 0x0000
#define EMIF_STATUS 0x0004
#define EMIF_SDRAM_CONFIG 0x0008
#define EMIF_LPDDR2_NVM_CONFIG 0x000C
#define EMIF_SDRAM_REF_CTRL 0x0010
#define EMIF_SDRAM_REF_CTRL_SHDW 0x0014
#define EMIF_SDRAM_TIM_1 0x0018
#define EMIF_SDRAM_TIM_1_SHDW 0x001C
#define EMIF_SDRAM_TIM_2 0x0020
#define EMIF_SDRAM_TIM_2_SHDW 0x0024
#define EMIF_SDRAM_TIM_3 0x0028
#define EMIF_SDRAM_TIM_3_SHDW 0x002C
#define EMIF_LPDDR2_NVM_TIM 0x0030
#define EMIF_LPDDR2_NVM_TIM_SHDW 0x0034
#define EMIF_PWR_MGMT_CTRL 0x0038
#define EMIF_PWR_MGMT_CTRL_SHDW 0x003C
#define EMIF_LPDDR2_MODE_REG_DATA 0x0040
#define EMIF_LPDDR2_MODE_REG_CFG 0x0050
#define EMIF_L3_CONFIG 0x0054
#define EMIF_L3_CFG_VAL_1 0x0058
#define EMIF_L3_CFG_VAL_2 0x005C
#define IODFT_TLGC 0x0060
#define EMIF_PERF_CNT_1 0x0080
#define EMIF_PERF_CNT_2 0x0084
#define EMIF_PERF_CNT_CFG 0x0088
#define EMIF_PERF_CNT_SEL 0x008C
#define EMIF_PERF_CNT_TIM 0x0090
#define EMIF_READ_IDLE_CTRL 0x0098
#define EMIF_READ_IDLE_CTRL_SHDW 0x009c
#define EMIF_ZQ_CONFIG 0x00C8
#define EMIF_DDR_PHY_CTRL_1 0x00E4
#define EMIF_DDR_PHY_CTRL_1_SHDW 0x00E8
#define EMIF_DDR_PHY_CTRL_2 0x00EC
#define DMM_LISA_MAP_0 0x0040
#define DMM_LISA_MAP_1 0x0044
#define DMM_LISA_MAP_2 0x0048
#define DMM_LISA_MAP_3 0x004C
#define MR0_ADDR 0
#define MR1_ADDR 1
#define MR2_ADDR 2
#define MR4_ADDR 4
#define MR10_ADDR 10
#define MR16_ADDR 16
#define REF_EN 0x40000000
/* defines for MR1 */
#define MR1_BL4 2
#define MR1_BL8 3
#define MR1_BL16 4
#define MR1_BT_SEQ 0
#define BT_INT 1
#define MR1_WC 0
#define MR1_NWC 1
#define MR1_NWR3 1
#define MR1_NWR4 2
#define MR1_NWR5 3
#define MR1_NWR6 4
#define MR1_NWR7 5
#define MR1_NWR8 6
#define MR1_VALUE (MR1_NWR3 << 5) | (MR1_WC << 4) | (MR1_BT_SEQ << 3) \
| (MR1_BL8 << 0)
/* defines for MR2 */
#define MR2_RL3_WL1 1
#define MR2_RL4_WL2 2
#define MR2_RL5_WL2 3
#define MR2_RL6_WL3 4
/* defines for MR10 */
#define MR10_ZQINIT 0xFF
#define MR10_ZQRESET 0xC3
#define MR10_ZQCL 0xAB
#define MR10_ZQCS 0x56
/* TODO: FREQ update method is not working so shadow registers programming
* is just for same of completeness. This would be safer if auto
* trasnitions are working
*/
#define FREQ_UPDATE_EMIF
/* EMIF Needs to be configured@19.2 MHz and shadow registers
* should be programmed for new OPP.
*/
/* Elpida 2x2Gbit */
#define SDRAM_CONFIG_INIT 0x80800EB1
#define DDR_PHY_CTRL_1_INIT 0x849FFFF5
#define READ_IDLE_CTRL 0x000501FF
#define PWR_MGMT_CTRL 0x4000000f
#define PWR_MGMT_CTRL_OPP100 0x4000000f
#define ZQ_CONFIG 0x500b3215
#define CS1_MR(mr) ((mr) | 0x80000000)
static inline void delay(unsigned long loops)
{
__asm__ volatile ("1:\n" "subs %0, %1, #1\n"
"bne 1b" : "=r" (loops) : "0"(loops));
}
int omap4_emif_config(unsigned int base, const struct ddr_regs *ddr_regs)
{
/*
* set SDRAM CONFIG register
* EMIF_SDRAM_CONFIG[31:29] REG_SDRAM_TYPE = 4 for LPDDR2-S4
* EMIF_SDRAM_CONFIG[28:27] REG_IBANK_POS = 0
* EMIF_SDRAM_CONFIG[13:10] REG_CL = 3
* EMIF_SDRAM_CONFIG[6:4] REG_IBANK = 3 - 8 banks
* EMIF_SDRAM_CONFIG[3] REG_EBANK = 0 - CS0
* EMIF_SDRAM_CONFIG[2:0] REG_PAGESIZE = 2 - 512- 9 column
* JDEC specs - S4-2Gb --8 banks -- R0-R13, C0-c8
*/
writel(readl(base + EMIF_LPDDR2_NVM_CONFIG) & 0xbfffffff,
base + EMIF_LPDDR2_NVM_CONFIG);
writel(ddr_regs->config_init, base + EMIF_SDRAM_CONFIG);
/* PHY control values */
writel(DDR_PHY_CTRL_1_INIT, base + EMIF_DDR_PHY_CTRL_1);
writel(ddr_regs->phy_ctrl_1, base + EMIF_DDR_PHY_CTRL_1_SHDW);
/*
* EMIF_READ_IDLE_CTRL
*/
writel(READ_IDLE_CTRL, base + EMIF_READ_IDLE_CTRL);
writel(READ_IDLE_CTRL, base + EMIF_READ_IDLE_CTRL);
/*
* EMIF_SDRAM_TIM_1
*/
writel(ddr_regs->tim1, base + EMIF_SDRAM_TIM_1);
writel(ddr_regs->tim1, base + EMIF_SDRAM_TIM_1_SHDW);
/*
* EMIF_SDRAM_TIM_2
*/
writel(ddr_regs->tim2, base + EMIF_SDRAM_TIM_2);
writel(ddr_regs->tim2, base + EMIF_SDRAM_TIM_2_SHDW);
/*
* EMIF_SDRAM_TIM_3
*/
writel(ddr_regs->tim3, base + EMIF_SDRAM_TIM_3);
writel(ddr_regs->tim3, base + EMIF_SDRAM_TIM_3_SHDW);
writel(ddr_regs->zq_config, base + EMIF_ZQ_CONFIG);
/*
* poll MR0 register (DAI bit)
* REG_CS[31] = 0 -- Mode register command to CS0
* REG_REFRESH_EN[30] = 1 -- Refresh enable after MRW
* REG_ADDRESS[7:0] = 00 -- Refresh enable after MRW
*/
writel(MR0_ADDR, base + EMIF_LPDDR2_MODE_REG_CFG);
while (readl(base + EMIF_LPDDR2_MODE_REG_DATA) & 1)
;
writel(CS1_MR(MR0_ADDR), base + EMIF_LPDDR2_MODE_REG_CFG);
while (readl(base + EMIF_LPDDR2_MODE_REG_DATA) & 1)
;
/* set MR10 register */
writel(MR10_ADDR, base + EMIF_LPDDR2_MODE_REG_CFG);
writel(MR10_ZQINIT, base + EMIF_LPDDR2_MODE_REG_DATA);
writel(CS1_MR(MR10_ADDR), base + EMIF_LPDDR2_MODE_REG_CFG);
writel(MR10_ZQINIT, base + EMIF_LPDDR2_MODE_REG_DATA);
/* wait for tZQINIT=1us */
delay(10);
/* set MR1 register */
writel(MR1_ADDR, base + EMIF_LPDDR2_MODE_REG_CFG);
writel(ddr_regs->mr1, base + EMIF_LPDDR2_MODE_REG_DATA);
writel(CS1_MR(MR1_ADDR), base + EMIF_LPDDR2_MODE_REG_CFG);
writel(ddr_regs->mr1, base + EMIF_LPDDR2_MODE_REG_DATA);
/* set MR2 register RL=6 for OPP100 */
writel(MR2_ADDR, base + EMIF_LPDDR2_MODE_REG_CFG);
writel(ddr_regs->mr2, base + EMIF_LPDDR2_MODE_REG_DATA);
writel(CS1_MR(MR2_ADDR), base + EMIF_LPDDR2_MODE_REG_CFG);
writel(ddr_regs->mr2, base + EMIF_LPDDR2_MODE_REG_DATA);
/* Set SDRAM CONFIG register again here with final RL-WL value */
writel(ddr_regs->config_final, base + EMIF_SDRAM_CONFIG);
writel(ddr_regs->phy_ctrl_1, base + EMIF_DDR_PHY_CTRL_1);
/*
* EMIF_SDRAM_REF_CTRL
* refresh rate = DDR_CLK / reg_refresh_rate
* 3.9 uS = (400MHz) / reg_refresh_rate
*/
writel(ddr_regs->ref_ctrl, base + EMIF_SDRAM_REF_CTRL);
writel(ddr_regs->ref_ctrl, base + EMIF_SDRAM_REF_CTRL_SHDW);
/* set MR16 register */
writel(MR16_ADDR | REF_EN, base + EMIF_LPDDR2_MODE_REG_CFG);
writel(0, base + EMIF_LPDDR2_MODE_REG_DATA);
writel(CS1_MR(MR16_ADDR | REF_EN),
base + EMIF_LPDDR2_MODE_REG_CFG);
writel(0, base + EMIF_LPDDR2_MODE_REG_DATA);
/* LPDDR2 init complete */
return 0;
}
static void reset_phy(unsigned int base)
{
*(volatile int*)(base + IODFT_TLGC) |= (1 << 10);
}
void omap4_ddr_init(const struct ddr_regs *ddr_regs,
const struct dpll_param *core)
{
unsigned int rev;
rev = omap4_revision();
if (rev == OMAP4430_ES2_0) {
writel(0x9e9e9e9e, 0x4A100638);
writel(0x9e9e9e9e, 0x4A10063c);
writel(0x9e9e9e9e, 0x4A100640);
writel(0x9e9e9e9e, 0x4A100648);
writel(0x9e9e9e9e, 0x4A10064c);
writel(0x9e9e9e9e, 0x4A100650);
/* LPDDR2IO set to NMOS PTV */
writel(0x00ffc000, 0x4A100704);
}
/*
* DMM Configuration
*/
/* Both EMIFs 128 byte interleaved */
writel(0x80640300, OMAP44XX_DMM_BASE + DMM_LISA_MAP_0);
*(volatile int*)(OMAP44XX_DMM_BASE + DMM_LISA_MAP_2) = 0x00000000;
*(volatile int*)(OMAP44XX_DMM_BASE + DMM_LISA_MAP_3) = 0xFF020100;
/* DDR needs to be initialised @ 19.2 MHz
* So put core DPLL in bypass mode
* Configure the Core DPLL but don't lock it
*/
omap4_configure_core_dpll_no_lock(core);
/* No IDLE: BUG in SDC */
sr32(CM_MEMIF_CLKSTCTRL, 0, 32, 0x2);
while(((*(volatile int*)CM_MEMIF_CLKSTCTRL) & 0x700) != 0x700);
*(volatile int*)(OMAP44XX_EMIF1_BASE + EMIF_PWR_MGMT_CTRL) = 0x0;
*(volatile int*)(OMAP44XX_EMIF2_BASE + EMIF_PWR_MGMT_CTRL) = 0x0;
omap4_emif_config(OMAP44XX_EMIF1_BASE, ddr_regs);
omap4_emif_config(OMAP44XX_EMIF2_BASE, ddr_regs);
/* Lock Core using shadow CM_SHADOW_FREQ_CONFIG1 */
omap4_lock_core_dpll_shadow(core);
/* Set DLL_OVERRIDE = 0 */
*(volatile int*)CM_DLL_CTRL = 0x0;
delay(200);
/* Check for DDR PHY ready for EMIF1 & EMIF2 */
while((((*(volatile int*)(OMAP44XX_EMIF1_BASE + EMIF_STATUS))&(0x04)) != 0x04) \
|| (((*(volatile int*)(OMAP44XX_EMIF2_BASE + EMIF_STATUS))&(0x04)) != 0x04));
/* Reprogram the DDR PYHY Control register */
/* PHY control values */
sr32(CM_MEMIF_EMIF_1_CLKCTRL, 0, 32, 0x1);
sr32(CM_MEMIF_EMIF_2_CLKCTRL, 0, 32, 0x1);
/* Put the Core Subsystem PD to ON State */
/* No IDLE: BUG in SDC */
//sr32(CM_MEMIF_CLKSTCTRL, 0, 32, 0x2);
//while(((*(volatile int*)CM_MEMIF_CLKSTCTRL) & 0x700) != 0x700);
*(volatile int*)(OMAP44XX_EMIF1_BASE + EMIF_PWR_MGMT_CTRL) = 0x80000000;
*(volatile int*)(OMAP44XX_EMIF2_BASE + EMIF_PWR_MGMT_CTRL) = 0x80000000;
/*
* DMM : DMM_LISA_MAP_0(Section_0)
* [31:24] SYS_ADDR 0x80
* [22:20] SYS_SIZE 0x7 - 2Gb
* [19:18] SDRC_INTLDMM 0x1 - 128 byte
* [17:16] SDRC_ADDRSPC 0x0
* [9:8] SDRC_MAP 0x3
* [7:0] SDRC_ADDR 0X0
*/
reset_phy(OMAP44XX_EMIF1_BASE);
reset_phy(OMAP44XX_EMIF2_BASE);
*((volatile int *)0x80000000) = 0;
*((volatile int *)0x80000080) = 0;
}
void omap4_power_i2c_send(u32 r)
{
u32 val;
writel(r, OMAP44XX_PRM_VC_VAL_BYPASS);
val = readl(OMAP44XX_PRM_VC_VAL_BYPASS);
val |= 0x1000000;
writel(val, OMAP44XX_PRM_VC_VAL_BYPASS);
while (readl(OMAP44XX_PRM_VC_VAL_BYPASS) & 0x1000000)
;
val = readl(OMAP44XX_PRM_IRQSTATUS_MPU_A9);
writel(val, OMAP44XX_PRM_IRQSTATUS_MPU_A9);
}
static unsigned int cortex_a9_rev(void)
{
unsigned int i;
asm ("mrc p15, 0, %0, c0, c0, 0" : "=r" (i));
return i;
}
unsigned int omap4_revision(void)
{
unsigned int chip_rev = 0;
unsigned int rev = cortex_a9_rev();
switch(rev) {
case 0x410FC091:
return OMAP4430_ES1_0;
case 0x411FC092:
chip_rev = (readl(OMAP44XX_CTRL_BASE + 0x204) >> 28) & 0xF;
if (chip_rev == 3)
return OMAP4430_ES2_1;
else if (chip_rev >= 4)
return OMAP4430_ES2_2;
else
return OMAP4430_ES2_0;
}
return OMAP4430_SILICON_ID_INVALID;
}
/*
* shutdown watchdog
*/
static int watchdog_init(void)
{
void __iomem *wd2_base = (void *)OMAP44XX_WDT2_BASE;
writel(WD_UNLOCK1, wd2_base + WATCHDOG_WSPR);
wait_for_command_complete();
writel(WD_UNLOCK2, wd2_base + WATCHDOG_WSPR);
return 0;
}
late_initcall(watchdog_init);
static int omap_vector_init(void)
{
__asm__ __volatile__ (
"mov r0, #0;"
"mcr p15, #0, r0, c12, c0, #0;"
:
:
: "r0"
);
return 0;
}
core_initcall(omap_vector_init);
#define OMAP4_TRACING_VECTOR3 0x4030d048
enum omap_boot_src omap4_bootsrc(void)
{
u32 bootsrc = readl(OMAP4_TRACING_VECTOR3);
if (bootsrc & (1 << 5))
return OMAP_BOOTSRC_MMC1;
if (bootsrc & (1 << 3))
return OMAP_BOOTSRC_NAND;
return OMAP_BOOTSRC_UNKNOWN;
}