blob: 638c4b5f46a0bc379194c377027323a29ab816cc [file] [log] [blame]
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -08001/*
Stefan Reinauer08dc3572013-05-14 16:57:50 -07002 * This file is part of the coreboot project.
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -08003 *
4 * Copyright (C) 2012 Samsung Electronics
5 *
Stefan Reinauer08dc3572013-05-14 16:57:50 -07006 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -08009 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080014 */
15
Stefan Reinauer08dc3572013-05-14 16:57:50 -070016/* Mem setup common file for different types of DDR present on SMDK5250 boards.
17 */
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080018
Stefan Reinauer08dc3572013-05-14 16:57:50 -070019#include <arch/io.h>
Julius Werner1ed0c8c2014-10-20 13:16:29 -070020#include <console/console.h>
Stefan Reinauer08dc3572013-05-14 16:57:50 -070021#include <delay.h>
Julius Werner1ed0c8c2014-10-20 13:16:29 -070022#include <soc/clk.h>
23#include <soc/dmc.h>
24#include <soc/setup.h>
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080025
26#define ZQ_INIT_TIMEOUT 10000
27
28int dmc_config_zq(struct mem_timings *mem,
29 struct exynos5_phy_control *phy0_ctrl,
30 struct exynos5_phy_control *phy1_ctrl)
31{
32 unsigned long val = 0;
33 int i;
34
35 /*
36 * ZQ Calibration:
37 * Select Driver Strength,
38 * long calibration for manual calibration
39 */
40 val = PHY_CON16_RESET_VAL;
41 val |= mem->zq_mode_dds << PHY_CON16_ZQ_MODE_DDS_SHIFT;
42 val |= mem->zq_mode_term << PHY_CON16_ZQ_MODE_TERM_SHIFT;
43 val |= ZQ_CLK_DIV_EN;
Julius Werner2f37bd62015-02-19 14:51:15 -080044 write32(&phy0_ctrl->phy_con16, val);
45 write32(&phy1_ctrl->phy_con16, val);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080046
47 /* Disable termination */
48 if (mem->zq_mode_noterm)
49 val |= PHY_CON16_ZQ_MODE_NOTERM_MASK;
Julius Werner2f37bd62015-02-19 14:51:15 -080050 write32(&phy0_ctrl->phy_con16, val);
51 write32(&phy1_ctrl->phy_con16, val);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080052
53 /* ZQ_MANUAL_START: Enable */
54 val |= ZQ_MANUAL_STR;
Julius Werner2f37bd62015-02-19 14:51:15 -080055 write32(&phy0_ctrl->phy_con16, val);
56 write32(&phy1_ctrl->phy_con16, val);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080057
58 /* ZQ_MANUAL_START: Disable */
59 val &= ~ZQ_MANUAL_STR;
60
61 /*
Martin Roth4c3ab732013-07-08 16:23:54 -060062 * Since we are manually calibrating the ZQ values,
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080063 * we are looping for the ZQ_init to complete.
64 */
65 i = ZQ_INIT_TIMEOUT;
Julius Werner2f37bd62015-02-19 14:51:15 -080066 while ((read32(&phy0_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
David Hendricks1fb11d12013-04-12 15:11:05 -070067 udelay(1);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080068 i--;
69 }
70 if (!i)
71 return -1;
Julius Werner2f37bd62015-02-19 14:51:15 -080072 write32(&phy0_ctrl->phy_con16, val);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080073
74 i = ZQ_INIT_TIMEOUT;
Julius Werner2f37bd62015-02-19 14:51:15 -080075 while ((read32(&phy1_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
David Hendricks1fb11d12013-04-12 15:11:05 -070076 udelay(1);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080077 i--;
78 }
79 if (!i)
80 return -1;
Julius Werner2f37bd62015-02-19 14:51:15 -080081 write32(&phy1_ctrl->phy_con16, val);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080082
83 return 0;
84}
85
86void update_reset_dll(struct exynos5_dmc *dmc, enum ddr_mode mode)
87{
88 unsigned long val;
89
90 if (mode == DDR_MODE_DDR3) {
91 val = MEM_TERM_EN | PHY_TERM_EN | DMC_CTRL_SHGATE;
Julius Werner2f37bd62015-02-19 14:51:15 -080092 write32(&dmc->phycontrol0, val);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080093 }
94
Martin Roth4c3ab732013-07-08 16:23:54 -060095 /* Update DLL Information: Force DLL Resynchronization */
Julius Werner2f37bd62015-02-19 14:51:15 -080096 val = read32(&dmc->phycontrol0);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080097 val |= FP_RSYNC;
Julius Werner2f37bd62015-02-19 14:51:15 -080098 write32(&dmc->phycontrol0, val);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080099
Martin Roth4c3ab732013-07-08 16:23:54 -0600100 /* Reset Force DLL Resynchronization */
Julius Werner2f37bd62015-02-19 14:51:15 -0800101 val = read32(&dmc->phycontrol0);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800102 val &= ~FP_RSYNC;
Julius Werner2f37bd62015-02-19 14:51:15 -0800103 write32(&dmc->phycontrol0, val);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800104}
105
106void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc)
107{
108 int channel, chip;
109
110 for (channel = 0; channel < mem->dmc_channels; channel++) {
111 unsigned long mask;
112
113 mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
114 for (chip = 0; chip < mem->chips_to_configure; chip++) {
115 int i;
116
117 mask |= chip << DIRECT_CMD_CHIP_SHIFT;
118
119 /* Sending NOP command */
Julius Werner2f37bd62015-02-19 14:51:15 -0800120 write32(&dmc->directcmd, DIRECT_CMD_NOP | mask);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800121
122 /*
123 * TODO(alim.akhtar@samsung.com): Do we need these
124 * delays? This one and the next were not there for
125 * DDR3.
126 */
David Hendricks1fb11d12013-04-12 15:11:05 -0700127 udelay(100);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800128
129 /* Sending EMRS/MRS commands */
130 for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) {
Julius Werner2f37bd62015-02-19 14:51:15 -0800131 write32(&dmc->directcmd,
132 mem->direct_cmd_msr[i] | mask);
David Hendricks1fb11d12013-04-12 15:11:05 -0700133 udelay(100);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800134 }
135
136 if (mem->send_zq_init) {
137 /* Sending ZQINIT command */
Julius Werner2f37bd62015-02-19 14:51:15 -0800138 write32(&dmc->directcmd,
139 DIRECT_CMD_ZQINIT | mask);
David Hendricks1fb11d12013-04-12 15:11:05 -0700140 /*
141 * FIXME: This was originally sdelay(10000)
142 * in the imported u-boot code. That may have
143 * been meant to be sdelay(0x10000) since that
144 * was used elsewhere in this function. Either
145 * way seems to work, though.
146 */
147 udelay(12);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800148 }
149 }
150 }
151}
152
153void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc)
154{
155 int channel, chip;
156
157 for (channel = 0; channel < mem->dmc_channels; channel++) {
158 unsigned long mask;
159
160 mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
161 for (chip = 0; chip < mem->chips_per_channel; chip++) {
162 mask |= chip << DIRECT_CMD_CHIP_SHIFT;
163
164 /* PALL (all banks precharge) CMD */
Julius Werner2f37bd62015-02-19 14:51:15 -0800165 write32(&dmc->directcmd, DIRECT_CMD_PALL | mask);
David Hendricks1fb11d12013-04-12 15:11:05 -0700166 udelay(100);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800167 }
168 }
169}
170
171void dmc_config_memory(struct mem_timings *mem, struct exynos5_dmc *dmc)
172{
Julius Werner2f37bd62015-02-19 14:51:15 -0800173 write32(&dmc->memconfig0, mem->memconfig);
174 write32(&dmc->memconfig1, mem->memconfig);
175 write32(&dmc->membaseconfig0, DMC_MEMBASECONFIG0_VAL);
176 write32(&dmc->membaseconfig1, DMC_MEMBASECONFIG1_VAL);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800177}