blob: 765a2141d130d4fc87b3bd7a0ba4288b6c577a44 [file] [log] [blame]
Giulio Benetticd647fc2020-01-10 15:51:44 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2019
4 * Author(s): Giulio Benetti <giulio.benetti@benettiengineering.com>
5 */
6
7#include <common.h>
8#include <clk.h>
9#include <dm.h>
Simon Glass691d7192020-05-10 11:40:02 -060010#include <init.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060011#include <log.h>
Giulio Benetticd647fc2020-01-10 15:51:44 +010012#include <ram.h>
13#include <asm/io.h>
Simon Glasscd93d622020-05-10 11:40:13 -060014#include <linux/bitops.h>
Simon Glassc05ed002020-05-10 11:40:11 -060015#include <linux/delay.h>
Simon Glassf2176512020-02-03 07:36:17 -070016#include <linux/err.h>
Giulio Benetticd647fc2020-01-10 15:51:44 +010017
18/* SDRAM Command Code */
19#define SD_CC_ARD 0x0 /* Master Bus (AXI) command - Read */
20#define SD_CC_AWR 0x1 /* Master Bus (AXI) command - Write */
21#define SD_CC_IRD 0x8 /* IP command - Read */
22#define SD_CC_IWR 0x9 /* IP command - Write */
23#define SD_CC_IMS 0xA /* IP command - Set Mode Register */
24#define SD_CC_IACT 0xB /* IP command - ACTIVE */
25#define SD_CC_IAF 0xC /* IP command - Auto Refresh */
26#define SD_CC_ISF 0xD /* IP Command - Self Refresh */
27#define SD_CC_IPRE 0xE /* IP command - Precharge */
28#define SD_CC_IPREA 0xF /* IP command - Precharge ALL */
29
30#define SEMC_MCR_MDIS BIT(1)
31#define SEMC_MCR_DQSMD BIT(2)
32
33#define SEMC_INTR_IPCMDERR BIT(1)
34#define SEMC_INTR_IPCMDDONE BIT(0)
35
36#define SEMC_IPCMD_KEY 0xA55A0000
37
38struct imxrt_semc_regs {
39 /* 0x0 */
40 u32 mcr;
41 u32 iocr;
42 u32 bmcr0;
43 u32 bmcr1;
44 u32 br[9];
45
46 /* 0x34 */
47 u32 res1;
48 u32 inten;
49 u32 intr;
50 /* 0x40 */
51 u32 sdramcr0;
52 u32 sdramcr1;
53 u32 sdramcr2;
54 u32 sdramcr3;
55 /* 0x50 */
56 u32 nandcr0;
57 u32 nandcr1;
58 u32 nandcr2;
59 u32 nandcr3;
60 /* 0x60 */
61 u32 norcr0;
62 u32 norcr1;
63 u32 norcr2;
64 u32 norcr3;
65 /* 0x70 */
66 u32 sramcr0;
67 u32 sramcr1;
68 u32 sramcr2;
69 u32 sramcr3;
70 /* 0x80 */
71 u32 dbicr0;
72 u32 dbicr1;
73 u32 res2[2];
74 /* 0x90 */
75 u32 ipcr0;
76 u32 ipcr1;
77 u32 ipcr2;
78 u32 ipcmd;
79 /* 0xA0 */
80 u32 iptxdat;
81 u32 res3[3];
82 /* 0xB0 */
83 u32 iprxdat;
84 u32 res4[3];
85 /* 0xC0 */
86 u32 sts[16];
87};
88
89#define SEMC_IOCR_MUX_A8_SHIFT 0
90#define SEMC_IOCR_MUX_CSX0_SHIFT 3
91#define SEMC_IOCR_MUX_CSX1_SHIFT 6
92#define SEMC_IOCR_MUX_CSX2_SHIFT 9
93#define SEMC_IOCR_MUX_CSX3_SHIFT 12
94#define SEMC_IOCR_MUX_RDY_SHIFT 15
95
96struct imxrt_sdram_mux {
97 u8 a8;
98 u8 csx0;
99 u8 csx1;
100 u8 csx2;
101 u8 csx3;
102 u8 rdy;
103};
104
105#define SEMC_SDRAMCR0_PS_SHIFT 0
106#define SEMC_SDRAMCR0_BL_SHIFT 4
107#define SEMC_SDRAMCR0_COL_SHIFT 8
108#define SEMC_SDRAMCR0_CL_SHIFT 10
109
110struct imxrt_sdram_control {
111 u8 memory_width;
112 u8 burst_len;
113 u8 no_columns;
114 u8 cas_latency;
115};
116
117#define SEMC_SDRAMCR1_PRE2ACT_SHIFT 0
118#define SEMC_SDRAMCR1_ACT2RW_SHIFT 4
119#define SEMC_SDRAMCR1_RFRC_SHIFT 8
120#define SEMC_SDRAMCR1_WRC_SHIFT 13
121#define SEMC_SDRAMCR1_CKEOFF_SHIFT 16
122#define SEMC_SDRAMCR1_ACT2PRE_SHIFT 20
123
124#define SEMC_SDRAMCR2_SRRC_SHIFT 0
125#define SEMC_SDRAMCR2_REF2REF_SHIFT 8
126#define SEMC_SDRAMCR2_ACT2ACT_SHIFT 16
127#define SEMC_SDRAMCR2_ITO_SHIFT 24
128
129#define SEMC_SDRAMCR3_REN BIT(0)
130#define SEMC_SDRAMCR3_REBL_SHIFT 1
131#define SEMC_SDRAMCR3_PRESCALE_SHIFT 8
132#define SEMC_SDRAMCR3_RT_SHIFT 16
133#define SEMC_SDRAMCR3_UT_SHIFT 24
134
135struct imxrt_sdram_timing {
136 u8 pre2act;
137 u8 act2rw;
138 u8 rfrc;
139 u8 wrc;
140 u8 ckeoff;
141 u8 act2pre;
142
143 u8 srrc;
144 u8 ref2ref;
145 u8 act2act;
146 u8 ito;
147
148 u8 rebl;
149 u8 prescale;
150 u8 rt;
151 u8 ut;
152};
153
154enum imxrt_semc_bank {
155 SDRAM_BANK1,
156 SDRAM_BANK2,
157 SDRAM_BANK3,
158 SDRAM_BANK4,
159 MAX_SDRAM_BANK,
160};
161
162#define SEMC_BR_VLD_MASK 1
163#define SEMC_BR_MS_SHIFT 1
164
165struct bank_params {
166 enum imxrt_semc_bank target_bank;
167 u32 base_address;
168 u32 memory_size;
169};
170
171struct imxrt_sdram_params {
172 struct imxrt_semc_regs *base;
173
174 struct imxrt_sdram_mux *sdram_mux;
175 struct imxrt_sdram_control *sdram_control;
176 struct imxrt_sdram_timing *sdram_timing;
177
178 struct bank_params bank_params[MAX_SDRAM_BANK];
179 u8 no_sdram_banks;
180};
181
182static int imxrt_sdram_wait_ipcmd_done(struct imxrt_semc_regs *regs)
183{
184 do {
185 readl(&regs->intr);
186
187 if (regs->intr & SEMC_INTR_IPCMDDONE)
188 return 0;
189 if (regs->intr & SEMC_INTR_IPCMDERR)
190 return -EIO;
191
192 mdelay(50);
193 } while (1);
194}
195
196static int imxrt_sdram_ipcmd(struct imxrt_semc_regs *regs, u32 mem_addr,
197 u32 ipcmd, u32 wd, u32 *rd)
198{
199 int ret;
200
201 if (ipcmd == SD_CC_IWR || ipcmd == SD_CC_IMS)
202 writel(wd, &regs->iptxdat);
203
204 /* set slave address for every command as specified on RM */
205 writel(mem_addr, &regs->ipcr0);
206
207 /* execute command */
208 writel(SEMC_IPCMD_KEY | ipcmd, &regs->ipcmd);
209
210 ret = imxrt_sdram_wait_ipcmd_done(regs);
211 if (ret < 0)
212 return ret;
213
214 if (ipcmd == SD_CC_IRD) {
215 if (!rd)
216 return -EINVAL;
217
218 *rd = readl(&regs->iprxdat);
219 }
220
221 return 0;
222}
223
224int imxrt_sdram_init(struct udevice *dev)
225{
226 struct imxrt_sdram_params *params = dev_get_platdata(dev);
227 struct imxrt_sdram_mux *mux = params->sdram_mux;
228 struct imxrt_sdram_control *ctrl = params->sdram_control;
229 struct imxrt_sdram_timing *time = params->sdram_timing;
230 struct imxrt_semc_regs *regs = params->base;
231 struct bank_params *bank_params;
232 u32 rd;
233 int i;
234
235 /* enable the SEMC controller */
236 clrbits_le32(&regs->mcr, SEMC_MCR_MDIS);
237 /* set DQS mode from DQS pad */
238 setbits_le32(&regs->mcr, SEMC_MCR_DQSMD);
239
240 for (i = 0, bank_params = params->bank_params;
241 i < params->no_sdram_banks; bank_params++,
242 i++)
243 writel((bank_params->base_address & 0xfffff000)
244 | bank_params->memory_size << SEMC_BR_MS_SHIFT
245 | SEMC_BR_VLD_MASK,
246 &regs->br[bank_params->target_bank]);
247
248 writel(mux->a8 << SEMC_IOCR_MUX_A8_SHIFT
249 | mux->csx0 << SEMC_IOCR_MUX_CSX0_SHIFT
250 | mux->csx1 << SEMC_IOCR_MUX_CSX1_SHIFT
251 | mux->csx2 << SEMC_IOCR_MUX_CSX2_SHIFT
252 | mux->csx3 << SEMC_IOCR_MUX_CSX3_SHIFT
253 | mux->rdy << SEMC_IOCR_MUX_RDY_SHIFT,
254 &regs->iocr);
255
256 writel(ctrl->memory_width << SEMC_SDRAMCR0_PS_SHIFT
257 | ctrl->burst_len << SEMC_SDRAMCR0_BL_SHIFT
258 | ctrl->no_columns << SEMC_SDRAMCR0_COL_SHIFT
259 | ctrl->cas_latency << SEMC_SDRAMCR0_CL_SHIFT,
260 &regs->sdramcr0);
261
262 writel(time->pre2act << SEMC_SDRAMCR1_PRE2ACT_SHIFT
263 | time->act2rw << SEMC_SDRAMCR1_ACT2RW_SHIFT
264 | time->rfrc << SEMC_SDRAMCR1_RFRC_SHIFT
265 | time->wrc << SEMC_SDRAMCR1_WRC_SHIFT
266 | time->ckeoff << SEMC_SDRAMCR1_CKEOFF_SHIFT
267 | time->act2pre << SEMC_SDRAMCR1_ACT2PRE_SHIFT,
268 &regs->sdramcr1);
269
270 writel(time->srrc << SEMC_SDRAMCR2_SRRC_SHIFT
271 | time->ref2ref << SEMC_SDRAMCR2_REF2REF_SHIFT
272 | time->act2act << SEMC_SDRAMCR2_ACT2ACT_SHIFT
273 | time->ito << SEMC_SDRAMCR2_ITO_SHIFT,
274 &regs->sdramcr2);
275
276 writel(time->rebl << SEMC_SDRAMCR3_REBL_SHIFT
277 | time->prescale << SEMC_SDRAMCR3_PRESCALE_SHIFT
278 | time->rt << SEMC_SDRAMCR3_RT_SHIFT
279 | time->ut << SEMC_SDRAMCR3_UT_SHIFT
280 | SEMC_SDRAMCR3_REN,
281 &regs->sdramcr3);
282
283 writel(2, &regs->ipcr1);
284
285 for (i = 0, bank_params = params->bank_params;
286 i < params->no_sdram_banks; bank_params++,
287 i++) {
288 mdelay(250);
289 imxrt_sdram_ipcmd(regs, bank_params->base_address, SD_CC_IPREA,
290 0, &rd);
291 imxrt_sdram_ipcmd(regs, bank_params->base_address, SD_CC_IAF,
292 0, &rd);
293 imxrt_sdram_ipcmd(regs, bank_params->base_address, SD_CC_IAF,
294 0, &rd);
295 imxrt_sdram_ipcmd(regs, bank_params->base_address, SD_CC_IMS,
296 ctrl->burst_len | (ctrl->cas_latency << 4),
297 &rd);
298 mdelay(250);
299 }
300
301 return 0;
302}
303
304static int imxrt_semc_ofdata_to_platdata(struct udevice *dev)
305{
306 struct imxrt_sdram_params *params = dev_get_platdata(dev);
307 ofnode bank_node;
308 u8 bank = 0;
309
310 params->sdram_mux =
311 (struct imxrt_sdram_mux *)
312 dev_read_u8_array_ptr(dev,
313 "fsl,sdram-mux",
314 sizeof(struct imxrt_sdram_mux));
315 if (!params->sdram_mux) {
316 pr_err("fsl,sdram-mux not found");
317 return -EINVAL;
318 }
319
320 params->sdram_control =
321 (struct imxrt_sdram_control *)
322 dev_read_u8_array_ptr(dev,
323 "fsl,sdram-control",
324 sizeof(struct imxrt_sdram_control));
325 if (!params->sdram_control) {
326 pr_err("fsl,sdram-control not found");
327 return -EINVAL;
328 }
329
330 params->sdram_timing =
331 (struct imxrt_sdram_timing *)
332 dev_read_u8_array_ptr(dev,
333 "fsl,sdram-timing",
334 sizeof(struct imxrt_sdram_timing));
335 if (!params->sdram_timing) {
336 pr_err("fsl,sdram-timing not found");
337 return -EINVAL;
338 }
339
340 dev_for_each_subnode(bank_node, dev) {
341 struct bank_params *bank_params;
342 char *bank_name;
343 int ret;
344
345 /* extract the bank index from DT */
346 bank_name = (char *)ofnode_get_name(bank_node);
347 strsep(&bank_name, "@");
348 if (!bank_name) {
349 pr_err("missing sdram bank index");
350 return -EINVAL;
351 }
352
353 bank_params = &params->bank_params[bank];
354 strict_strtoul(bank_name, 10,
355 (unsigned long *)&bank_params->target_bank);
356 if (bank_params->target_bank >= MAX_SDRAM_BANK) {
357 pr_err("Found bank %d , but only bank 0,1,2,3 are supported",
358 bank_params->target_bank);
359 return -EINVAL;
360 }
361
362 ret = ofnode_read_u32(bank_node,
363 "fsl,memory-size",
364 &bank_params->memory_size);
365 if (ret < 0) {
366 pr_err("fsl,memory-size not found");
367 return -EINVAL;
368 }
369
370 ret = ofnode_read_u32(bank_node,
371 "fsl,base-address",
372 &bank_params->base_address);
373 if (ret < 0) {
374 pr_err("fsl,base-address not found");
375 return -EINVAL;
376 }
377
378 debug("Found bank %s %u\n", bank_name,
379 bank_params->target_bank);
380 bank++;
381 }
382
383 params->no_sdram_banks = bank;
384 debug("%s, no of banks = %d\n", __func__, params->no_sdram_banks);
385
386 return 0;
387}
388
389static int imxrt_semc_probe(struct udevice *dev)
390{
391 struct imxrt_sdram_params *params = dev_get_platdata(dev);
392 int ret;
393 fdt_addr_t addr;
394
395 addr = dev_read_addr(dev);
396 if (addr == FDT_ADDR_T_NONE)
397 return -EINVAL;
398
399 params->base = (struct imxrt_semc_regs *)addr;
400
401#ifdef CONFIG_CLK
402 struct clk clk;
403
404 ret = clk_get_by_index(dev, 0, &clk);
405 if (ret < 0)
406 return ret;
407
408 ret = clk_enable(&clk);
409
410 if (ret) {
411 dev_err(dev, "failed to enable clock\n");
412 return ret;
413 }
414#endif
415 ret = imxrt_sdram_init(dev);
416 if (ret)
417 return ret;
418
419 return 0;
420}
421
422static int imxrt_semc_get_info(struct udevice *dev, struct ram_info *info)
423{
424 return 0;
425}
426
427static struct ram_ops imxrt_semc_ops = {
428 .get_info = imxrt_semc_get_info,
429};
430
431static const struct udevice_id imxrt_semc_ids[] = {
432 { .compatible = "fsl,imxrt-semc", .data = 0 },
433 { }
434};
435
436U_BOOT_DRIVER(imxrt_semc) = {
437 .name = "imxrt_semc",
438 .id = UCLASS_RAM,
439 .of_match = imxrt_semc_ids,
440 .ops = &imxrt_semc_ops,
441 .ofdata_to_platdata = imxrt_semc_ofdata_to_platdata,
442 .probe = imxrt_semc_probe,
443 .platdata_auto_alloc_size = sizeof(struct imxrt_sdram_params),
444};