blob: 44923dd5520f61a70d586721c512c2f1f643b5f0 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +00002/*
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +05303 * Mem setup common file for different types of DDR present on Exynos boards.
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +00004 *
5 * Copyright (C) 2012 Samsung Electronics
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +00006 */
7
8#include <common.h>
9#include <asm/arch/spl.h>
10
11#include "clock_init.h"
Rajeshwari Shinde643be9c2013-07-04 12:29:17 +053012#include "common_setup.h"
13#include "exynos5_setup.h"
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000014
15#define ZQ_INIT_TIMEOUT 10000
16
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053017int dmc_config_zq(struct mem_timings *mem, uint32_t *phy0_con16,
18 uint32_t *phy1_con16, uint32_t *phy0_con17,
19 uint32_t *phy1_con17)
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000020{
21 unsigned long val = 0;
22 int i;
23
24 /*
25 * ZQ Calibration:
26 * Select Driver Strength,
27 * long calibration for manual calibration
28 */
29 val = PHY_CON16_RESET_VAL;
30 val |= mem->zq_mode_dds << PHY_CON16_ZQ_MODE_DDS_SHIFT;
31 val |= mem->zq_mode_term << PHY_CON16_ZQ_MODE_TERM_SHIFT;
32 val |= ZQ_CLK_DIV_EN;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053033 writel(val, phy0_con16);
34 writel(val, phy1_con16);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000035
36 /* Disable termination */
37 if (mem->zq_mode_noterm)
38 val |= PHY_CON16_ZQ_MODE_NOTERM_MASK;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053039 writel(val, phy0_con16);
40 writel(val, phy1_con16);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000041
42 /* ZQ_MANUAL_START: Enable */
43 val |= ZQ_MANUAL_STR;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053044 writel(val, phy0_con16);
45 writel(val, phy1_con16);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000046
47 /* ZQ_MANUAL_START: Disable */
48 val &= ~ZQ_MANUAL_STR;
49
50 /*
51 * Since we are manaully calibrating the ZQ values,
52 * we are looping for the ZQ_init to complete.
53 */
54 i = ZQ_INIT_TIMEOUT;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053055 while ((readl(phy0_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000056 sdelay(100);
57 i--;
58 }
59 if (!i)
60 return -1;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053061 writel(val, phy0_con16);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000062
63 i = ZQ_INIT_TIMEOUT;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053064 while ((readl(phy1_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000065 sdelay(100);
66 i--;
67 }
68 if (!i)
69 return -1;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053070 writel(val, phy1_con16);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000071
72 return 0;
73}
74
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053075void update_reset_dll(uint32_t *phycontrol0, enum ddr_mode mode)
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000076{
77 unsigned long val;
78
79 if (mode == DDR_MODE_DDR3) {
80 val = MEM_TERM_EN | PHY_TERM_EN | DMC_CTRL_SHGATE;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053081 writel(val, phycontrol0);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000082 }
83
84 /* Update DLL Information: Force DLL Resyncronization */
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053085 val = readl(phycontrol0);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000086 val |= FP_RSYNC;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053087 writel(val, phycontrol0);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000088
89 /* Reset Force DLL Resyncronization */
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053090 val = readl(phycontrol0);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000091 val &= ~FP_RSYNC;
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053092 writel(val, phycontrol0);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000093}
94
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +053095void dmc_config_mrs(struct mem_timings *mem, uint32_t *directcmd)
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +000096{
97 int channel, chip;
98
99 for (channel = 0; channel < mem->dmc_channels; channel++) {
100 unsigned long mask;
101
102 mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
103 for (chip = 0; chip < mem->chips_to_configure; chip++) {
104 int i;
105
106 mask |= chip << DIRECT_CMD_CHIP_SHIFT;
107
108 /* Sending NOP command */
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +0530109 writel(DIRECT_CMD_NOP | mask, directcmd);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +0000110
111 /*
112 * TODO(alim.akhtar@samsung.com): Do we need these
113 * delays? This one and the next were not there for
114 * DDR3.
115 */
116 sdelay(0x10000);
117
118 /* Sending EMRS/MRS commands */
119 for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) {
120 writel(mem->direct_cmd_msr[i] | mask,
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +0530121 directcmd);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +0000122 sdelay(0x10000);
123 }
124
125 if (mem->send_zq_init) {
126 /* Sending ZQINIT command */
127 writel(DIRECT_CMD_ZQINIT | mask,
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +0530128 directcmd);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +0000129
130 sdelay(10000);
131 }
132 }
133 }
134}
135
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +0530136void dmc_config_prech(struct mem_timings *mem, uint32_t *directcmd)
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +0000137{
138 int channel, chip;
139
140 for (channel = 0; channel < mem->dmc_channels; channel++) {
141 unsigned long mask;
142
143 mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
144 for (chip = 0; chip < mem->chips_per_channel; chip++) {
145 mask |= chip << DIRECT_CMD_CHIP_SHIFT;
146
147 /* PALL (all banks precharge) CMD */
Rajeshwari Birjef3d7c2f2013-12-26 09:44:22 +0530148 writel(DIRECT_CMD_PALL | mask, directcmd);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +0000149 sdelay(0x10000);
150 }
151 }
152}
153
Rajeshwari Shinde643be9c2013-07-04 12:29:17 +0530154void mem_ctrl_init(int reset)
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +0000155{
156 struct spl_machine_param *param = spl_get_machine_params();
157 struct mem_timings *mem;
158 int ret;
159
160 mem = clock_get_mem_timings();
161
162 /* If there are any other memory variant, add their init call below */
163 if (param->mem_type == DDR_MODE_DDR3) {
Akshay Saraswatcfde7582014-05-26 19:17:03 +0530164 ret = ddr3_mem_ctrl_init(mem, reset);
Rajeshwari Shinde87f2e072012-07-03 20:02:56 +0000165 if (ret) {
166 /* will hang if failed to init memory control */
167 while (1)
168 ;
169 }
170 } else {
171 /* will hang if unknow memory type */
172 while (1)
173 ;
174 }
175}