1 /* 2 * Memory setup for board based on EXYNOS4210 3 * 4 * Copyright (C) 2013 Samsung Electronics 5 * Rajeshwari Shinde <rajeshwari.s@samsung.com> 6 * 7 * See file CREDITS for list of people who contributed to this 8 * project. 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License as 12 * published by the Free Software Foundation; either version 2 of 13 * the License, or (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 23 * MA 02111-1307 USA 24 */ 25 26 #include <config.h> 27 #include <asm/arch/dmc.h> 28 #include "common_setup.h" 29 #include "exynos4_setup.h" 30 31 struct mem_timings mem = { 32 .direct_cmd_msr = { 33 DIRECT_CMD1, DIRECT_CMD2, DIRECT_CMD3, DIRECT_CMD4 34 }, 35 .timingref = TIMINGREF_VAL, 36 .timingrow = TIMINGROW_VAL, 37 .timingdata = TIMINGDATA_VAL, 38 .timingpower = TIMINGPOWER_VAL, 39 .zqcontrol = ZQ_CONTROL_VAL, 40 .control0 = CONTROL0_VAL, 41 .control1 = CONTROL1_VAL, 42 .control2 = CONTROL2_VAL, 43 .concontrol = CONCONTROL_VAL, 44 .prechconfig = PRECHCONFIG, 45 .memcontrol = MEMCONTROL_VAL, 46 .memconfig0 = MEMCONFIG0_VAL, 47 .memconfig1 = MEMCONFIG1_VAL, 48 .dll_resync = FORCE_DLL_RESYNC, 49 .dll_on = DLL_CONTROL_ON, 50 }; 51 static void phy_control_reset(int ctrl_no, struct exynos4_dmc *dmc) 52 { 53 if (ctrl_no) { 54 writel((mem.control1 | (1 << mem.dll_resync)), 55 &dmc->phycontrol1); 56 writel((mem.control1 | (0 << mem.dll_resync)), 57 &dmc->phycontrol1); 58 } else { 59 writel((mem.control0 | (0 << mem.dll_on)), 60 &dmc->phycontrol0); 61 writel((mem.control0 | (1 << mem.dll_on)), 62 &dmc->phycontrol0); 63 } 64 } 65 66 static void dmc_config_mrs(struct exynos4_dmc *dmc, int chip) 67 { 68 int i; 69 unsigned long mask = 0; 70 71 if (chip) 72 mask = DIRECT_CMD_CHIP1_SHIFT; 73 74 for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) { 75 writel(mem.direct_cmd_msr[i] | mask, 76 &dmc->directcmd); 77 } 78 } 79 80 static void dmc_init(struct exynos4_dmc *dmc) 81 { 82 /* 83 * DLL Parameter Setting: 84 * Termination: Enable R/W 85 * Phase Delay for DQS Cleaning: 180' Shift 86 */ 87 writel(mem.control1, &dmc->phycontrol1); 88 89 /* 90 * ZQ Calibration 91 * Termination: Disable 92 * Auto Calibration Start: Enable 93 */ 94 writel(mem.zqcontrol, &dmc->phyzqcontrol); 95 sdelay(0x100000); 96 97 /* 98 * Update DLL Information: 99 * Force DLL Resyncronization 100 */ 101 phy_control_reset(1, dmc); 102 phy_control_reset(0, dmc); 103 104 /* Set DLL Parameters */ 105 writel(mem.control1, &dmc->phycontrol1); 106 107 /* DLL Start */ 108 writel((mem.control0 | CTRL_START | CTRL_DLL_ON), &dmc->phycontrol0); 109 110 writel(mem.control2, &dmc->phycontrol2); 111 112 /* Set Clock Ratio of Bus clock to Memory Clock */ 113 writel(mem.concontrol, &dmc->concontrol); 114 115 /* 116 * Memor Burst length: 8 117 * Number of chips: 2 118 * Memory Bus width: 32 bit 119 * Memory Type: DDR3 120 * Additional Latancy for PLL: 1 Cycle 121 */ 122 writel(mem.memcontrol, &dmc->memcontrol); 123 124 writel(mem.memconfig0, &dmc->memconfig0); 125 writel(mem.memconfig1, &dmc->memconfig1); 126 127 /* Config Precharge Policy */ 128 writel(mem.prechconfig, &dmc->prechconfig); 129 /* 130 * TimingAref, TimingRow, TimingData, TimingPower Setting: 131 * Values as per Memory AC Parameters 132 */ 133 writel(mem.timingref, &dmc->timingref); 134 writel(mem.timingrow, &dmc->timingrow); 135 writel(mem.timingdata, &dmc->timingdata); 136 writel(mem.timingpower, &dmc->timingpower); 137 138 /* Chip0: NOP Command: Assert and Hold CKE to high level */ 139 writel(DIRECT_CMD_NOP, &dmc->directcmd); 140 sdelay(0x100000); 141 142 /* Chip0: EMRS2, EMRS3, EMRS, MRS Commands Using Direct Command */ 143 dmc_config_mrs(dmc, 0); 144 sdelay(0x100000); 145 146 /* Chip0: ZQINIT */ 147 writel(DIRECT_CMD_ZQ, &dmc->directcmd); 148 sdelay(0x100000); 149 150 writel((DIRECT_CMD_NOP | DIRECT_CMD_CHIP1_SHIFT), &dmc->directcmd); 151 sdelay(0x100000); 152 153 /* Chip1: EMRS2, EMRS3, EMRS, MRS Commands Using Direct Command */ 154 dmc_config_mrs(dmc, 1); 155 sdelay(0x100000); 156 157 /* Chip1: ZQINIT */ 158 writel((DIRECT_CMD_ZQ | DIRECT_CMD_CHIP1_SHIFT), &dmc->directcmd); 159 sdelay(0x100000); 160 161 phy_control_reset(1, dmc); 162 sdelay(0x100000); 163 164 /* turn on DREX0, DREX1 */ 165 writel((mem.concontrol | AREF_EN), &dmc->concontrol); 166 } 167 168 void mem_ctrl_init(int reset) 169 { 170 struct exynos4_dmc *dmc; 171 172 /* 173 * Async bridge configuration at CPU_core: 174 * 1: half_sync 175 * 0: full_sync 176 */ 177 writel(1, ASYNC_CONFIG); 178 #ifdef CONFIG_ORIGEN 179 /* Interleave: 2Bit, Interleave_bit1: 0x15, Interleave_bit0: 0x7 */ 180 writel(APB_SFR_INTERLEAVE_CONF_VAL, EXYNOS4_MIU_BASE + 181 APB_SFR_INTERLEAVE_CONF_OFFSET); 182 /* Update MIU Configuration */ 183 writel(APB_SFR_ARBRITATION_CONF_VAL, EXYNOS4_MIU_BASE + 184 APB_SFR_ARBRITATION_CONF_OFFSET); 185 #else 186 writel(APB_SFR_INTERLEAVE_CONF_VAL, EXYNOS4_MIU_BASE + 187 APB_SFR_INTERLEAVE_CONF_OFFSET); 188 writel(INTERLEAVE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE + 189 ABP_SFR_INTERLEAVE_ADDRMAP_START_OFFSET); 190 writel(INTERLEAVE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE + 191 ABP_SFR_INTERLEAVE_ADDRMAP_END_OFFSET); 192 writel(INTERLEAVE_ADDR_MAP_EN, EXYNOS4_MIU_BASE + 193 ABP_SFR_SLV_ADDRMAP_CONF_OFFSET); 194 #ifdef CONFIG_MIU_LINEAR 195 writel(SLAVE0_SINGLE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE + 196 ABP_SFR_SLV0_SINGLE_ADDRMAP_START_OFFSET); 197 writel(SLAVE0_SINGLE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE + 198 ABP_SFR_SLV0_SINGLE_ADDRMAP_END_OFFSET); 199 writel(SLAVE1_SINGLE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE + 200 ABP_SFR_SLV1_SINGLE_ADDRMAP_START_OFFSET); 201 writel(SLAVE1_SINGLE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE + 202 ABP_SFR_SLV1_SINGLE_ADDRMAP_END_OFFSET); 203 writel(APB_SFR_SLV_ADDR_MAP_CONF_VAL, EXYNOS4_MIU_BASE + 204 ABP_SFR_SLV_ADDRMAP_CONF_OFFSET); 205 #endif 206 #endif 207 /* DREX0 */ 208 dmc = (struct exynos4_dmc *)samsung_get_base_dmc_ctrl(); 209 dmc_init(dmc); 210 dmc = (struct exynos4_dmc *)(samsung_get_base_dmc_ctrl() 211 + DMC_OFFSET); 212 dmc_init(dmc); 213 } 214