blob: cab53561e42ecbc4e35701f41e2feadbd23def2b [file] [log] [blame]
developer29b37c52020-04-21 09:28:34 +02001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2020 MediaTek Inc.
4 *
5 * Author: Weijie Gao <weijie.gao@mediatek.com>
6 */
7
developer29b37c52020-04-21 09:28:34 +02008#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -06009#include <linux/delay.h>
developer29b37c52020-04-21 09:28:34 +020010#include <linux/io.h>
11#include <linux/sizes.h>
12#include <mach/ddr.h>
13#include <mach/mc.h>
14
15#define DDR_BW_TEST_PAT 0xaa5555aa
16
developerd14cd5b2020-11-12 16:35:43 +080017static const u32 sdr_size_cfg1[] = {
18 [DRAM_8MB] = (1 << NUMROWS_S),
19 [DRAM_16MB] = (1 << NUMROWS_S) | (1 << NUMCOLS_S),
20 [DRAM_32MB] = (2 << NUMROWS_S) | (1 << NUMCOLS_S),
21 [DRAM_64MB] = (2 << NUMROWS_S) | (2 << NUMCOLS_S),
22};
23
developer29b37c52020-04-21 09:28:34 +020024static const u32 dram_size[] = {
25 [DRAM_8MB] = SZ_8M,
26 [DRAM_16MB] = SZ_16M,
27 [DRAM_32MB] = SZ_32M,
28 [DRAM_64MB] = SZ_64M,
29 [DRAM_128MB] = SZ_128M,
30 [DRAM_256MB] = SZ_256M,
31};
32
33static void dram_test_write(u32 addr, u32 val)
34{
35 volatile ulong *target = (volatile ulong *)(KSEG1 + addr);
36
37 sync();
38 *target = val;
39 sync();
40}
41
42static u32 dram_test_read(u32 addr)
43{
44 volatile ulong *target = (volatile ulong *)(KSEG1 + addr);
45 u32 val;
46
47 sync();
48 val = *target;
49 sync();
50
51 return val;
52}
53
54static int dram_addr_test_bit(u32 bit)
55{
56 u32 val;
57
58 dram_test_write(0, 0);
59 dram_test_write(BIT(bit), DDR_BW_TEST_PAT);
60 val = dram_test_read(0);
61
62 if (val == DDR_BW_TEST_PAT)
63 return 1;
64
65 return 0;
66}
67
68static void mc_ddr_init(void __iomem *memc, const struct mc_ddr_cfg *cfg,
69 u32 dq_dly, u32 dqs_dly, mc_reset_t mc_reset, u32 bw)
70{
71 u32 val;
72
73 mc_reset(1);
74 __udelay(200);
75 mc_reset(0);
76
77 clrbits_32(memc + MEMCTL_SDRAM_CFG1_REG, RBC_MAPPING);
78
79 writel(cfg->cfg2, memc + MEMCTL_DDR_CFG2_REG);
80 writel(cfg->cfg3, memc + MEMCTL_DDR_CFG3_REG);
81 writel(cfg->cfg4, memc + MEMCTL_DDR_CFG4_REG);
82 writel(dq_dly, memc + MEMCTL_DDR_DQ_DLY_REG);
83 writel(dqs_dly, memc + MEMCTL_DDR_DQS_DLY_REG);
84
85 writel(cfg->cfg0, memc + MEMCTL_DDR_CFG0_REG);
86
87 val = cfg->cfg1;
88 if (bw) {
89 val &= ~IND_SDRAM_WIDTH_M;
90 val |= (bw << IND_SDRAM_WIDTH_S) & IND_SDRAM_WIDTH_M;
91 }
92
93 writel(val, memc + MEMCTL_DDR_CFG1_REG);
94
95 clrsetbits_32(memc + MEMCTL_PWR_SAVE_CNT_REG, SR_TAR_CNT_M,
96 1 << SR_TAR_CNT_S);
97
98 setbits_32(memc + MEMCTL_DDR_SELF_REFRESH_REG, SR_AUTO_EN);
99}
100
101void ddr1_init(struct mc_ddr_init_param *param)
102{
103 enum mc_dram_size sz;
104 u32 bw = 0;
105
106 /* First initialization, determine bus width */
107 mc_ddr_init(param->memc, &param->cfgs[DRAM_8MB], param->dq_dly,
108 param->dqs_dly, param->mc_reset, IND_SDRAM_WIDTH_16BIT);
109
110 /* Test bus width */
111 dram_test_write(0, DDR_BW_TEST_PAT);
112 if (dram_test_read(0) == DDR_BW_TEST_PAT)
113 bw = IND_SDRAM_WIDTH_16BIT;
114 else
115 bw = IND_SDRAM_WIDTH_8BIT;
116
117 /* Second initialization, determine DDR capacity */
118 mc_ddr_init(param->memc, &param->cfgs[DRAM_128MB], param->dq_dly,
119 param->dqs_dly, param->mc_reset, bw);
120
121 if (dram_addr_test_bit(9)) {
122 sz = DRAM_8MB;
123 } else {
124 if (dram_addr_test_bit(10)) {
125 if (dram_addr_test_bit(23))
126 sz = DRAM_16MB;
127 else
128 sz = DRAM_32MB;
129 } else {
130 if (dram_addr_test_bit(24))
131 sz = DRAM_64MB;
132 else
133 sz = DRAM_128MB;
134 }
135 }
136
137 /* Final initialization, with DDR calibration */
138 mc_ddr_init(param->memc, &param->cfgs[sz], param->dq_dly,
139 param->dqs_dly, param->mc_reset, bw);
140
141 /* Return actual DDR configuration */
142 param->memsize = dram_size[sz];
143 param->bus_width = bw;
144}
145
146void ddr2_init(struct mc_ddr_init_param *param)
147{
148 enum mc_dram_size sz;
149 u32 bw = 0;
150
151 /* First initialization, determine bus width */
152 mc_ddr_init(param->memc, &param->cfgs[DRAM_32MB], param->dq_dly,
153 param->dqs_dly, param->mc_reset, IND_SDRAM_WIDTH_16BIT);
154
155 /* Test bus width */
156 dram_test_write(0, DDR_BW_TEST_PAT);
157 if (dram_test_read(0) == DDR_BW_TEST_PAT)
158 bw = IND_SDRAM_WIDTH_16BIT;
159 else
160 bw = IND_SDRAM_WIDTH_8BIT;
161
162 /* Second initialization, determine DDR capacity */
163 mc_ddr_init(param->memc, &param->cfgs[DRAM_256MB], param->dq_dly,
164 param->dqs_dly, param->mc_reset, bw);
165
166 if (bw == IND_SDRAM_WIDTH_16BIT) {
167 if (dram_addr_test_bit(10)) {
168 sz = DRAM_32MB;
169 } else {
170 if (dram_addr_test_bit(24)) {
171 if (dram_addr_test_bit(27))
172 sz = DRAM_64MB;
173 else
174 sz = DRAM_128MB;
175 } else {
176 sz = DRAM_256MB;
177 }
178 }
179 } else {
180 if (dram_addr_test_bit(23)) {
181 sz = DRAM_32MB;
182 } else {
183 if (dram_addr_test_bit(24)) {
184 if (dram_addr_test_bit(27))
185 sz = DRAM_64MB;
186 else
187 sz = DRAM_128MB;
188 } else {
189 sz = DRAM_256MB;
190 }
191 }
192 }
193
194 /* Final initialization, with DDR calibration */
195 mc_ddr_init(param->memc, &param->cfgs[sz], param->dq_dly,
196 param->dqs_dly, param->mc_reset, bw);
197
198 /* Return actual DDR configuration */
199 param->memsize = dram_size[sz];
200 param->bus_width = bw;
201}
developerd14cd5b2020-11-12 16:35:43 +0800202
203static void mc_sdr_init(void __iomem *memc, mc_reset_t mc_reset, u32 cfg0,
204 u32 cfg1)
205{
206 mc_reset(1);
207 __udelay(200);
208 mc_reset(0);
209
210 writel(cfg0, memc + MEMCTL_SDRAM_CFG0_REG);
211 writel(cfg1, memc + MEMCTL_SDRAM_CFG1_REG);
212
213 while (!(readl(memc + MEMCTL_SDRAM_CFG1_REG) & SDRAM_INIT_DONE))
214 ;
215
216 clrsetbits_32(memc + MEMCTL_PWR_SAVE_CNT_REG, SR_TAR_CNT_M,
217 1 << SR_TAR_CNT_S);
218
219 setbits_32(memc + MEMCTL_DDR_SELF_REFRESH_REG, SR_AUTO_EN);
220}
221
222void sdr_init(struct mc_ddr_init_param *param)
223{
224 enum mc_dram_size sz;
225 u32 cfg1;
226
227 cfg1 = param->sdr_cfg1 | SDRAM_INIT_START;
228 cfg1 &= ~(NUMCOLS_M | NUMROWS_M);
229
230 /* First initialization, determine SDR capacity */
231 mc_sdr_init(param->memc, param->mc_reset, param->sdr_cfg0,
232 cfg1 | sdr_size_cfg1[DRAM_64MB]);
233
234 if (dram_addr_test_bit(9)) {
235 sz = DRAM_8MB;
236 } else {
237 if (dram_addr_test_bit(10)) {
238 if (dram_addr_test_bit(23))
239 sz = DRAM_16MB;
240 else
241 sz = DRAM_32MB;
242 } else {
243 sz = DRAM_64MB;
244 }
245 }
246
247 /* Final initialization */
248 mc_sdr_init(param->memc, param->mc_reset, param->sdr_cfg0,
249 cfg1 | sdr_size_cfg1[sz]);
250
251 /* Return actual DDR configuration */
252 param->memsize = dram_size[sz];
253}