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