blob: 1b830e3de628903424a64b08b074e8d4b8e6bfdb [file] [log] [blame]
Angel Pons1ddb8942020-04-04 18:51:26 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Gabe Black607c0b62013-05-16 05:45:57 -07002
3/* Mem setup common file for different types of DDR present on SMDK5420 boards.
4 */
5
Kyösti Mälkki13f66502019-03-03 08:01:05 +02006#include <device/mmio.h>
Gabe Black607c0b62013-05-16 05:45:57 -07007#include <delay.h>
Julius Werner80af4422014-10-20 13:18:56 -07008#include <soc/clk.h>
9#include <soc/dmc.h>
10#include <soc/setup.h>
Gabe Black607c0b62013-05-16 05:45:57 -070011
12#define ZQ_INIT_TIMEOUT 10000
13
14int dmc_config_zq(struct mem_timings *mem,
15 struct exynos5_phy_control *phy0_ctrl,
16 struct exynos5_phy_control *phy1_ctrl)
17{
18 unsigned long val = 0;
19 int i;
20
21 /*
22 * ZQ Calibration:
23 * Select Driver Strength,
24 * long calibration for manual calibration
25 */
26 val = PHY_CON16_RESET_VAL;
27 val |= mem->zq_mode_dds << PHY_CON16_ZQ_MODE_DDS_SHIFT;
28 val |= mem->zq_mode_term << PHY_CON16_ZQ_MODE_TERM_SHIFT;
29 val |= ZQ_CLK_DIV_EN;
Julius Werner2f37bd62015-02-19 14:51:15 -080030 write32(&phy0_ctrl->phy_con16, val);
31 write32(&phy1_ctrl->phy_con16, val);
Gabe Black607c0b62013-05-16 05:45:57 -070032
33 /* Disable termination */
34 if (mem->zq_mode_noterm)
35 val |= PHY_CON16_ZQ_MODE_NOTERM_MASK;
Julius Werner2f37bd62015-02-19 14:51:15 -080036 write32(&phy0_ctrl->phy_con16, val);
37 write32(&phy1_ctrl->phy_con16, val);
Gabe Black607c0b62013-05-16 05:45:57 -070038
39 /* ZQ_MANUAL_START: Enable */
40 val |= ZQ_MANUAL_STR;
Julius Werner2f37bd62015-02-19 14:51:15 -080041 write32(&phy0_ctrl->phy_con16, val);
42 write32(&phy1_ctrl->phy_con16, val);
Gabe Black607c0b62013-05-16 05:45:57 -070043
44 /* ZQ_MANUAL_START: Disable */
45 val &= ~ZQ_MANUAL_STR;
46
47 /*
Martin Roth1fc2ba52014-12-07 14:59:11 -070048 * Since we are manually calibrating the ZQ values,
Gabe Black607c0b62013-05-16 05:45:57 -070049 * we are looping for the ZQ_init to complete.
50 */
51 i = ZQ_INIT_TIMEOUT;
Julius Werner2f37bd62015-02-19 14:51:15 -080052 while ((read32(&phy0_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
Gabe Black607c0b62013-05-16 05:45:57 -070053 udelay(1);
54 i--;
55 }
56 if (!i)
57 return -1;
Julius Werner2f37bd62015-02-19 14:51:15 -080058 write32(&phy0_ctrl->phy_con16, val);
Gabe Black607c0b62013-05-16 05:45:57 -070059
60 i = ZQ_INIT_TIMEOUT;
Julius Werner2f37bd62015-02-19 14:51:15 -080061 while ((read32(&phy1_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
Gabe Black607c0b62013-05-16 05:45:57 -070062 udelay(1);
63 i--;
64 }
65 if (!i)
66 return -1;
Julius Werner2f37bd62015-02-19 14:51:15 -080067 write32(&phy1_ctrl->phy_con16, val);
Gabe Black607c0b62013-05-16 05:45:57 -070068
69 return 0;
70}
71
72void update_reset_dll(struct exynos5_dmc *dmc, enum ddr_mode mode)
73{
74 unsigned long val;
75
76 if (mode == DDR_MODE_DDR3) {
77 val = MEM_TERM_EN | PHY_TERM_EN | DMC_CTRL_SHGATE;
Julius Werner2f37bd62015-02-19 14:51:15 -080078 write32(&dmc->phycontrol0, val);
Gabe Black607c0b62013-05-16 05:45:57 -070079 }
80
Martin Roth1fc2ba52014-12-07 14:59:11 -070081 /* Update DLL Information: Force DLL Resynchronization */
Julius Werner2f37bd62015-02-19 14:51:15 -080082 val = read32(&dmc->phycontrol0);
Gabe Black607c0b62013-05-16 05:45:57 -070083 val |= FP_RSYNC;
Julius Werner2f37bd62015-02-19 14:51:15 -080084 write32(&dmc->phycontrol0, val);
Gabe Black607c0b62013-05-16 05:45:57 -070085
Martin Roth1fc2ba52014-12-07 14:59:11 -070086 /* Reset Force DLL Resynchronization */
Julius Werner2f37bd62015-02-19 14:51:15 -080087 val = read32(&dmc->phycontrol0);
Gabe Black607c0b62013-05-16 05:45:57 -070088 val &= ~FP_RSYNC;
Julius Werner2f37bd62015-02-19 14:51:15 -080089 write32(&dmc->phycontrol0, val);
Gabe Black607c0b62013-05-16 05:45:57 -070090}
91
92void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc)
93{
94 int channel, chip;
95
96 for (channel = 0; channel < mem->dmc_channels; channel++) {
97 unsigned long mask;
98
99 mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
100 for (chip = 0; chip < mem->chips_to_configure; chip++) {
101 int i;
102
103 mask |= chip << DIRECT_CMD_CHIP_SHIFT;
104
105 /* Sending NOP command */
Julius Werner2f37bd62015-02-19 14:51:15 -0800106 write32(&dmc->directcmd, DIRECT_CMD_NOP | mask);
Gabe Black607c0b62013-05-16 05:45:57 -0700107
108 /*
109 * TODO(alim.akhtar@samsung.com): Do we need these
110 * delays? This one and the next were not there for
111 * DDR3.
112 */
113 udelay(100);
114
115 /* Sending EMRS/MRS commands */
116 for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) {
Julius Werner2f37bd62015-02-19 14:51:15 -0800117 write32(&dmc->directcmd,
118 mem->direct_cmd_msr[i] | mask);
Gabe Black607c0b62013-05-16 05:45:57 -0700119 udelay(100);
120 }
121
122 if (mem->send_zq_init) {
123 /* Sending ZQINIT command */
Julius Werner2f37bd62015-02-19 14:51:15 -0800124 write32(&dmc->directcmd,
125 DIRECT_CMD_ZQINIT | mask);
Gabe Black607c0b62013-05-16 05:45:57 -0700126 /*
127 * FIXME: This was originally sdelay(10000)
128 * in the imported u-boot code. That may have
129 * been meant to be sdelay(0x10000) since that
130 * was used elsewhere in this function. Either
131 * way seems to work, though.
132 */
133 udelay(12);
134 }
135 }
136 }
137}
138
139void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc)
140{
141 int channel, chip;
142
143 for (channel = 0; channel < mem->dmc_channels; channel++) {
144 unsigned long mask;
145
146 mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
147 for (chip = 0; chip < mem->chips_per_channel; chip++) {
148 mask |= chip << DIRECT_CMD_CHIP_SHIFT;
149
150 /* PALL (all banks precharge) CMD */
Julius Werner2f37bd62015-02-19 14:51:15 -0800151 write32(&dmc->directcmd, DIRECT_CMD_PALL | mask);
Gabe Black607c0b62013-05-16 05:45:57 -0700152 udelay(100);
153 }
154 }
155}