blob: 1bbb533b818cd603035e2de4b5d200c8d1ef1858 [file] [log] [blame]
Angel Pons1ddb8942020-04-04 18:51:26 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -08002
Stefan Reinauer08dc3572013-05-14 16:57:50 -07003/* Mem setup common file for different types of DDR present on SMDK5250 boards.
4 */
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -08005
Kyösti Mälkki13f66502019-03-03 08:01:05 +02006#include <device/mmio.h>
Stefan Reinauer08dc3572013-05-14 16:57:50 -07007#include <delay.h>
Julius Werner1ed0c8c2014-10-20 13:16:29 -07008#include <soc/clk.h>
9#include <soc/dmc.h>
10#include <soc/setup.h>
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080011
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);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080032
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);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080038
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);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080043
44 /* ZQ_MANUAL_START: Disable */
45 val &= ~ZQ_MANUAL_STR;
46
47 /*
Martin Roth4c3ab732013-07-08 16:23:54 -060048 * Since we are manually calibrating the ZQ values,
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080049 * 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) {
David Hendricks1fb11d12013-04-12 15:11:05 -070053 udelay(1);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080054 i--;
55 }
56 if (!i)
57 return -1;
Julius Werner2f37bd62015-02-19 14:51:15 -080058 write32(&phy0_ctrl->phy_con16, val);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080059
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) {
David Hendricks1fb11d12013-04-12 15:11:05 -070062 udelay(1);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080063 i--;
64 }
65 if (!i)
66 return -1;
Julius Werner2f37bd62015-02-19 14:51:15 -080067 write32(&phy1_ctrl->phy_con16, val);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080068
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);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080079 }
80
Martin Roth4c3ab732013-07-08 16:23:54 -060081 /* Update DLL Information: Force DLL Resynchronization */
Julius Werner2f37bd62015-02-19 14:51:15 -080082 val = read32(&dmc->phycontrol0);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080083 val |= FP_RSYNC;
Julius Werner2f37bd62015-02-19 14:51:15 -080084 write32(&dmc->phycontrol0, val);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080085
Martin Roth4c3ab732013-07-08 16:23:54 -060086 /* Reset Force DLL Resynchronization */
Julius Werner2f37bd62015-02-19 14:51:15 -080087 val = read32(&dmc->phycontrol0);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080088 val &= ~FP_RSYNC;
Julius Werner2f37bd62015-02-19 14:51:15 -080089 write32(&dmc->phycontrol0, val);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080090}
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);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800107
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 */
David Hendricks1fb11d12013-04-12 15:11:05 -0700113 udelay(100);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800114
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);
David Hendricks1fb11d12013-04-12 15:11:05 -0700119 udelay(100);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800120 }
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);
David Hendricks1fb11d12013-04-12 15:11:05 -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);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800134 }
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);
David Hendricks1fb11d12013-04-12 15:11:05 -0700152 udelay(100);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800153 }
154 }
155}
156
157void dmc_config_memory(struct mem_timings *mem, struct exynos5_dmc *dmc)
158{
Julius Werner2f37bd62015-02-19 14:51:15 -0800159 write32(&dmc->memconfig0, mem->memconfig);
160 write32(&dmc->memconfig1, mem->memconfig);
161 write32(&dmc->membaseconfig0, DMC_MEMBASECONFIG0_VAL);
162 write32(&dmc->membaseconfig1, DMC_MEMBASECONFIG1_VAL);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800163}