9
0
Fork 0
barebox/arch/arm/mach-omap/omap4_generic.c

522 lines
13 KiB
C

#include <common.h>
#include <init.h>
#include <mach/silicon.h>
#include <io.h>
#include <mach/omap4-silicon.h>
#include <mach/omap4-mux.h>
#include <mach/omap4-clock.h>
#include <mach/syslib.h>
#include <mach/xload.h>
#include <mach/gpmc.h>
/*
* The following several lines are taken from U-Boot to support
* recognizing more revisions of OMAP4 chips.
*/
#define MIDR_CORTEX_A9_R0P1 0x410FC091
#define MIDR_CORTEX_A9_R1P2 0x411FC092
#define MIDR_CORTEX_A9_R1P3 0x411FC093
#define MIDR_CORTEX_A9_R2P10 0x412FC09A
#define CONTROL_ID_CODE 0x4A002204
#define OMAP4_CONTROL_ID_CODE_ES1_0 0x0B85202F
#define OMAP4_CONTROL_ID_CODE_ES2_0 0x1B85202F
#define OMAP4_CONTROL_ID_CODE_ES2_1 0x3B95C02F
#define OMAP4_CONTROL_ID_CODE_ES2_2 0x4B95C02F
#define OMAP4_CONTROL_ID_CODE_ES2_3 0x6B95C02F
#define OMAP4460_CONTROL_ID_CODE_ES1_0 0x0B94E02F
#define OMAP4460_CONTROL_ID_CODE_ES1_1 0x2B94E02F
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;
/* Read Main ID Register (MIDR) */
asm ("mrc p15, 0, %0, c0, c0, 0" : "=r" (i));
return i;
}
unsigned int omap4_revision(void)
{
unsigned int rev = cortex_a9_rev();
switch(rev) {
case MIDR_CORTEX_A9_R0P1:
return OMAP4430_ES1_0;
case MIDR_CORTEX_A9_R1P2:
switch (readl(CONTROL_ID_CODE)) {
case OMAP4_CONTROL_ID_CODE_ES2_0:
return OMAP4430_ES2_0;
break;
case OMAP4_CONTROL_ID_CODE_ES2_1:
return OMAP4430_ES2_1;
break;
case OMAP4_CONTROL_ID_CODE_ES2_2:
return OMAP4430_ES2_2;
break;
default:
return OMAP4430_ES2_0;
break;
}
break;
case MIDR_CORTEX_A9_R1P3:
return OMAP4430_ES2_3;
break;
case MIDR_CORTEX_A9_R2P10:
switch (readl(CONTROL_ID_CODE)) {
case OMAP4460_CONTROL_ID_CODE_ES1_1:
return OMAP4460_ES1_1;
break;
case OMAP4460_CONTROL_ID_CODE_ES1_0:
default:
return OMAP4460_ES1_0;
break;
}
break;
default:
return OMAP4430_SILICON_ID_INVALID;
break;
}
}
/*
* 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;
}
#define I2C_SLAVE 0x12
noinline int omap4_scale_vcores(void)
{
unsigned int rev = omap4_revision();
/* For VC bypass only VCOREx_CGF_FORCE is necessary and
* VCOREx_CFG_VOLTAGE changes can be discarded
*/
writel(0, OMAP44XX_PRM_VC_CFG_I2C_MODE);
writel(0x6026, OMAP44XX_PRM_VC_CFG_I2C_CLK);
/* set VCORE1 force VSEL */
omap4_power_i2c_send((0x3A55 << 8) | I2C_SLAVE);
/* FIXME: set VCORE2 force VSEL, Check the reset value */
omap4_power_i2c_send((0x295B << 8) | I2C_SLAVE);
/* set VCORE3 force VSEL */
switch (rev) {
case OMAP4430_ES2_0:
omap4_power_i2c_send((0x2961 << 8) | I2C_SLAVE);
break;
case OMAP4430_ES2_1:
omap4_power_i2c_send((0x2A61 << 8) | I2C_SLAVE);
break;
}
return 0;
}
void omap4_do_set_mux(u32 base, struct pad_conf_entry const *array, int size)
{
int i;
struct pad_conf_entry *pad = (struct pad_conf_entry *) array;
for (i = 0; i < size; i++, pad++)
writew(pad->val, base + pad->offset);
}
/* GPMC timing for OMAP4 nand device */
const struct gpmc_config omap4_nand_cfg = {
.cfg = {
0x00000800, /* CONF1 */
0x00050500, /* CONF2 */
0x00040400, /* CONF3 */
0x03000300, /* CONF4 */
0x00050808, /* CONF5 */
0x00000000, /* CONF6 */
},
/* GPMC address map as small as possible */
.base = 0x28000000,
.size = GPMC_SIZE_16M,
};