]>
Commit | Line | Data |
---|---|---|
d81b27a2 SB |
1 | /* |
2 | * Copyright (C) 2012, Stefano Babic <sbabic@denx.de> | |
3 | * | |
1a459660 | 4 | * SPDX-License-Identifier: GPL-2.0+ |
d81b27a2 SB |
5 | */ |
6 | ||
7 | #include <asm/io.h> | |
8 | #include <asm/errno.h> | |
9 | #include <asm/arch/imx-regs.h> | |
10 | #include <linux/types.h> | |
11 | #include <asm/arch/sys_proto.h> | |
12 | ||
13 | #define ESDCTL_DDR2_EMR2 0x04000000 | |
14 | #define ESDCTL_DDR2_EMR3 0x06000000 | |
15 | #define ESDCTL_PRECHARGE 0x00000400 | |
16 | #define ESDCTL_DDR2_EN_DLL 0x02000400 | |
17 | #define ESDCTL_DDR2_RESET_DLL 0x00000333 | |
18 | #define ESDCTL_DDR2_MR 0x00000233 | |
19 | #define ESDCTL_DDR2_OCD_DEFAULT 0x02000780 | |
20 | ||
21 | enum { | |
22 | SMODE_NORMAL = 0, | |
23 | SMODE_PRECHARGE, | |
24 | SMODE_AUTO_REFRESH, | |
25 | SMODE_LOAD_REG, | |
26 | SMODE_MANUAL_REFRESH | |
27 | }; | |
28 | ||
29 | #define set_mode(x, en, m) (x | (en << 31) | (m << 28)) | |
30 | ||
31 | static inline void dram_wait(unsigned int count) | |
32 | { | |
33 | volatile unsigned int wait = count; | |
34 | ||
35 | while (wait--) | |
36 | ; | |
37 | ||
38 | } | |
39 | ||
40 | void mx3_setup_sdram_bank(u32 start_address, u32 ddr2_config, | |
41 | u32 row, u32 col, u32 dsize, u32 refresh) | |
42 | { | |
43 | struct esdc_regs *esdc = (struct esdc_regs *)ESDCTL_BASE_ADDR; | |
44 | u32 *cfg_reg, *ctl_reg; | |
45 | u32 val; | |
46 | u32 ctlval; | |
47 | ||
48 | switch (start_address) { | |
49 | case CSD0_BASE_ADDR: | |
50 | cfg_reg = &esdc->esdcfg0; | |
51 | ctl_reg = &esdc->esdctl0; | |
52 | break; | |
53 | case CSD1_BASE_ADDR: | |
54 | cfg_reg = &esdc->esdcfg1; | |
55 | ctl_reg = &esdc->esdctl1; | |
56 | break; | |
57 | default: | |
58 | return; | |
59 | } | |
60 | ||
61 | /* The MX35 supports 11 up to 14 rows */ | |
62 | if (row < 11 || row > 14 || col < 8 || col > 10) | |
63 | return; | |
64 | ctlval = (row - 11) << 24 | (col - 8) << 20 | (dsize << 16); | |
65 | ||
66 | /* Initialize MISC register for DDR2 */ | |
67 | val = ESDC_MISC_RST | ESDC_MISC_MDDR_EN | ESDC_MISC_MDDR_DL_RST | | |
68 | ESDC_MISC_DDR_EN | ESDC_MISC_DDR2_EN; | |
69 | writel(val, &esdc->esdmisc); | |
70 | val &= ~(ESDC_MISC_RST | ESDC_MISC_MDDR_DL_RST); | |
71 | writel(val, &esdc->esdmisc); | |
72 | ||
73 | /* | |
74 | * according to DDR2 specs, wait a while before | |
75 | * the PRECHARGE_ALL command | |
76 | */ | |
77 | dram_wait(0x20000); | |
78 | ||
79 | /* Load DDR2 config and timing */ | |
80 | writel(ddr2_config, cfg_reg); | |
81 | ||
82 | /* Precharge ALL */ | |
83 | writel(set_mode(ctlval, 1, SMODE_PRECHARGE), | |
84 | ctl_reg); | |
85 | writel(0xda, start_address + ESDCTL_PRECHARGE); | |
86 | ||
87 | /* Load mode */ | |
88 | writel(set_mode(ctlval, 1, SMODE_LOAD_REG), | |
89 | ctl_reg); | |
90 | writeb(0xda, start_address + ESDCTL_DDR2_EMR2); /* EMRS2 */ | |
91 | writeb(0xda, start_address + ESDCTL_DDR2_EMR3); /* EMRS3 */ | |
92 | writeb(0xda, start_address + ESDCTL_DDR2_EN_DLL); /* Enable DLL */ | |
93 | writeb(0xda, start_address + ESDCTL_DDR2_RESET_DLL); /* Reset DLL */ | |
94 | ||
95 | /* Precharge ALL */ | |
96 | writel(set_mode(ctlval, 1, SMODE_PRECHARGE), | |
97 | ctl_reg); | |
98 | writel(0xda, start_address + ESDCTL_PRECHARGE); | |
99 | ||
100 | /* Set mode auto refresh : at least two refresh are required */ | |
101 | writel(set_mode(ctlval, 1, SMODE_AUTO_REFRESH), | |
102 | ctl_reg); | |
103 | writel(0xda, start_address); | |
104 | writel(0xda, start_address); | |
105 | ||
106 | writel(set_mode(ctlval, 1, SMODE_LOAD_REG), | |
107 | ctl_reg); | |
108 | writeb(0xda, start_address + ESDCTL_DDR2_MR); | |
109 | writeb(0xda, start_address + ESDCTL_DDR2_OCD_DEFAULT); | |
110 | ||
111 | /* OCD mode exit */ | |
112 | writeb(0xda, start_address + ESDCTL_DDR2_EN_DLL); /* Enable DLL */ | |
113 | ||
114 | /* Set normal mode */ | |
115 | writel(set_mode(ctlval, 1, SMODE_NORMAL) | refresh, | |
116 | ctl_reg); | |
117 | ||
118 | dram_wait(0x20000); | |
119 | ||
120 | /* Do not set delay lines, only for MDDR */ | |
121 | } |