#include #include #include #include #include #include #include #include #include #include /* * 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 /* EMIF_L3_CONFIG register value */ #define EMIF_L3_CONFIG_VAL_SYS_10_LL_0 0x0A0000FF #define EMIF_L3_CONFIG_VAL_SYS_10_MPU_3_LL_0 0x0A300000 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) { unsigned int val = readl(base + IODFT_TLGC); val |= (1 << 10); writel(val, base + IODFT_TLGC); } void omap4_ddr_init(const struct ddr_regs *ddr_regs, const struct dpll_param *core) { unsigned int 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); writel(0x00000000, OMAP44XX_DMM_BASE + DMM_LISA_MAP_2); writel(0xFF020100, OMAP44XX_DMM_BASE + DMM_LISA_MAP_3); if (rev >= OMAP4460_ES1_0) { writel(0x80640300, OMAP44XX_MA_BASE + DMM_LISA_MAP_0); writel(0x00000000, OMAP44XX_MA_BASE + DMM_LISA_MAP_2); writel(0xFF020100, OMAP44XX_MA_BASE + DMM_LISA_MAP_3); } /* 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 ((readl(CM_MEMIF_CLKSTCTRL) & 0x700) != 0x700); writel(0x0, OMAP44XX_EMIF1_BASE + EMIF_PWR_MGMT_CTRL); writel(0x0, OMAP44XX_EMIF2_BASE + EMIF_PWR_MGMT_CTRL); 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 */ writel(0x0, CM_DLL_CTRL); delay(200); /* Check for DDR PHY ready for EMIF1 & EMIF2 */ while (((readl(OMAP44XX_EMIF1_BASE + EMIF_STATUS) & 0x04) != 0x04) \ || ((readl(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 ((readl(CM_MEMIF_CLKSTCTRL) & 0x700) != 0x700); writel(0x80000000, OMAP44XX_EMIF1_BASE + EMIF_PWR_MGMT_CTRL); writel(0x80000000, OMAP44XX_EMIF2_BASE + EMIF_PWR_MGMT_CTRL); if (rev >= OMAP4460_ES1_0) { writel(EMIF_L3_CONFIG_VAL_SYS_10_MPU_3_LL_0, OMAP44XX_EMIF1_BASE + EMIF_L3_CONFIG); writel(EMIF_L3_CONFIG_VAL_SYS_10_MPU_3_LL_0, OMAP44XX_EMIF2_BASE + EMIF_L3_CONFIG); } /* * 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); writel(0, 0x80000000); writel(0, 0x80000080); } 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(unsigned vsel0_pin) { 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); /* TPS - supplies vdd_mpu on 4460 */ if (rev >= OMAP4460_ES1_0) { /* * Setup SET1 and SET0 with right values so that kernel * can use either of them based on its needs. */ omap4_do_scale_tps62361(TPS62361_REG_ADDR_SET0, 1430); omap4_do_scale_tps62361(TPS62361_REG_ADDR_SET1, 1430); /* * Select SET1 in TPS62361: * VSEL1 is grounded on board. So the following selects * VSEL1 = 0 and VSEL0 = 1 */ gpio_direction_output(vsel0_pin, 0); gpio_set_value(vsel0_pin, 1); } /* set VCORE1 force VSEL */ /* * 4430 : supplies vdd_mpu * Setting a high voltage for Nitro mode as smart reflex is not enabled. * We use the maximum possible value in the AVS range because the next * higher voltage in the discrete range (code >= 0b111010) is way too * high * * 4460 : supplies vdd_core * */ if (rev < OMAP4460_ES1_0) /* 0x55: i2c addr, 3A: ~ 1430 mvolts*/ omap4_power_i2c_send((0x3A55 << 8) | I2C_SLAVE); else /* 0x55: i2c addr, 28: ~ 1200 mvolts*/ omap4_power_i2c_send((0x2855 << 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; /* > OMAP4460_ES1_0 : VCORE3 not connected */ } 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, }; static int omap4_gpio_init(void) { add_generic_device("omap-gpio", 0, NULL, 0x4a310100, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("omap-gpio", 1, NULL, 0x48055100, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("omap-gpio", 2, NULL, 0x48057100, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("omap-gpio", 3, NULL, 0x48059100, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("omap-gpio", 4, NULL, 0x4805b100, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("omap-gpio", 5, NULL, 0x4805d100, 0x1000, IORESOURCE_MEM, NULL); return 0; } coredevice_initcall(omap4_gpio_init);