]>
Commit | Line | Data |
---|---|---|
1 | // SPDX-License-Identifier: GPL-2.0+ | |
2 | /* | |
3 | * Texas Instruments' AM654 DDRSS driver | |
4 | * | |
5 | * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ | |
6 | * Lokesh Vutla <[email protected]> | |
7 | */ | |
8 | ||
9 | #include <common.h> | |
10 | #include <clk.h> | |
11 | #include <dm.h> | |
12 | #include <log.h> | |
13 | #include <ram.h> | |
14 | #include <asm/io.h> | |
15 | #include <power-domain.h> | |
16 | #include <dm.h> | |
17 | #include <asm/arch/sys_proto.h> | |
18 | #include <dm/device_compat.h> | |
19 | #include <power/regulator.h> | |
20 | #include "k3-am654-ddrss.h" | |
21 | ||
22 | #define LDELAY 10000 | |
23 | ||
24 | /* DDRSS PHY configuration register fixed values */ | |
25 | #define DDRSS_DDRPHY_RANKIDR_RANK0 0 | |
26 | ||
27 | /** | |
28 | * struct am654_ddrss_desc - Description of ddrss integration. | |
29 | * @dev: DDRSS device pointer | |
30 | * @ddrss_ss_cfg: DDRSS wrapper logic region base address | |
31 | * @ddrss_ctl_cfg: DDRSS controller region base address | |
32 | * @ddrss_phy_cfg: DDRSS PHY region base address | |
33 | * @ddrss_clk: DDRSS clock description | |
34 | * @vtt_supply: VTT Supply regulator | |
35 | * @ddrss_pwrdmn: DDRSS power domain description | |
36 | * @params: SDRAM configuration parameters | |
37 | */ | |
38 | struct am654_ddrss_desc { | |
39 | struct udevice *dev; | |
40 | void __iomem *ddrss_ss_cfg; | |
41 | void __iomem *ddrss_ctl_cfg; | |
42 | void __iomem *ddrss_phy_cfg; | |
43 | struct clk ddrss_clk; | |
44 | struct udevice *vtt_supply; | |
45 | struct power_domain ddrcfg_pwrdmn; | |
46 | struct power_domain ddrdata_pwrdmn; | |
47 | struct ddrss_params params; | |
48 | }; | |
49 | ||
50 | static inline u32 ddrss_readl(void __iomem *addr, unsigned int offset) | |
51 | { | |
52 | return readl(addr + offset); | |
53 | } | |
54 | ||
55 | static inline void ddrss_writel(void __iomem *addr, unsigned int offset, | |
56 | u32 data) | |
57 | { | |
58 | debug("%s: addr = 0x%p, value = 0x%x\n", __func__, addr + offset, data); | |
59 | writel(data, addr + offset); | |
60 | } | |
61 | ||
62 | #define ddrss_ctl_writel(off, val) ddrss_writel(ddrss->ddrss_ctl_cfg, off, val) | |
63 | #define ddrss_ctl_readl(off) ddrss_readl(ddrss->ddrss_ctl_cfg, off) | |
64 | ||
65 | static inline u32 am654_ddrss_get_type(struct am654_ddrss_desc *ddrss) | |
66 | { | |
67 | return ddrss_ctl_readl(DDRSS_DDRCTL_MSTR) & MSTR_DDR_TYPE_MASK; | |
68 | } | |
69 | ||
70 | /** | |
71 | * am654_ddrss_dram_wait_for_init_complete() - Wait for init to complete | |
72 | * | |
73 | * After detecting the DDR type this function will pause until the | |
74 | * initialization is complete. Each DDR type has mask of multiple bits. | |
75 | * The size of the field depends on the DDR Type. If the initialization | |
76 | * does not complete and error will be returned and will cause the boot to halt. | |
77 | * | |
78 | */ | |
79 | static int am654_ddrss_dram_wait_for_init_complt(struct am654_ddrss_desc *ddrss) | |
80 | { | |
81 | u32 val, mask; | |
82 | ||
83 | val = am654_ddrss_get_type(ddrss); | |
84 | ||
85 | switch (val) { | |
86 | case DDR_TYPE_LPDDR4: | |
87 | case DDR_TYPE_DDR4: | |
88 | mask = DDR4_STAT_MODE_MASK; | |
89 | break; | |
90 | case DDR_TYPE_DDR3: | |
91 | mask = DDR3_STAT_MODE_MASK; | |
92 | break; | |
93 | default: | |
94 | printf("Unsupported DDR type 0x%x\n", val); | |
95 | return -EINVAL; | |
96 | } | |
97 | ||
98 | if (!wait_on_value(mask, DDR_MODE_NORMAL, | |
99 | ddrss->ddrss_ctl_cfg + DDRSS_DDRCTL_STAT, LDELAY)) | |
100 | return -ETIMEDOUT; | |
101 | ||
102 | return 0; | |
103 | } | |
104 | ||
105 | /** | |
106 | * am654_ddrss_ctrl_configuration() - Configure Controller specific registers | |
107 | * @dev: corresponding ddrss device | |
108 | */ | |
109 | static void am654_ddrss_ctrl_configuration(struct am654_ddrss_desc *ddrss) | |
110 | { | |
111 | struct ddrss_ddrctl_timing_params *tmg = &ddrss->params.ctl_timing; | |
112 | struct ddrss_ddrctl_reg_params *reg = &ddrss->params.ctl_reg; | |
113 | struct ddrss_ddrctl_ecc_params *ecc = &ddrss->params.ctl_ecc; | |
114 | struct ddrss_ddrctl_crc_params *crc = &ddrss->params.ctl_crc; | |
115 | struct ddrss_ddrctl_map_params *map = &ddrss->params.ctl_map; | |
116 | u32 val; | |
117 | ||
118 | debug("%s: DDR controller register configuration started\n", __func__); | |
119 | ||
120 | ddrss_ctl_writel(DDRSS_DDRCTL_MSTR, reg->ddrctl_mstr); | |
121 | ddrss_ctl_writel(DDRSS_DDRCTL_RFSHCTL0, reg->ddrctl_rfshctl0); | |
122 | ddrss_ctl_writel(DDRSS_DDRCTL_RFSHTMG, reg->ddrctl_rfshtmg); | |
123 | ||
124 | ddrss_ctl_writel(DDRSS_DDRCTL_ECCCFG0, ecc->ddrctl_ecccfg0); | |
125 | ddrss_ctl_writel(DDRSS_DDRCTL_CRCPARCTL0, crc->ddrctl_crcparctl0); | |
126 | ddrss_ctl_writel(DDRSS_DDRCTL_CRCPARCTL1, crc->ddrctl_crcparctl1); | |
127 | ddrss_ctl_writel(DDRSS_DDRCTL_CRCPARCTL2, crc->ddrctl_crcparctl2); | |
128 | ||
129 | ddrss_ctl_writel(DDRSS_DDRCTL_INIT0, reg->ddrctl_init0); | |
130 | ddrss_ctl_writel(DDRSS_DDRCTL_INIT1, reg->ddrctl_init1); | |
131 | ddrss_ctl_writel(DDRSS_DDRCTL_INIT3, reg->ddrctl_init3); | |
132 | ddrss_ctl_writel(DDRSS_DDRCTL_INIT4, reg->ddrctl_init4); | |
133 | ddrss_ctl_writel(DDRSS_DDRCTL_INIT5, reg->ddrctl_init5); | |
134 | ddrss_ctl_writel(DDRSS_DDRCTL_INIT6, reg->ddrctl_init6); | |
135 | ddrss_ctl_writel(DDRSS_DDRCTL_INIT7, reg->ddrctl_init7); | |
136 | ||
137 | ddrss_ctl_writel(DDRSS_DDRCTL_DRAMTMG0, tmg->ddrctl_dramtmg0); | |
138 | ddrss_ctl_writel(DDRSS_DDRCTL_DRAMTMG1, tmg->ddrctl_dramtmg1); | |
139 | ddrss_ctl_writel(DDRSS_DDRCTL_DRAMTMG2, tmg->ddrctl_dramtmg2); | |
140 | ddrss_ctl_writel(DDRSS_DDRCTL_DRAMTMG3, tmg->ddrctl_dramtmg3); | |
141 | ddrss_ctl_writel(DDRSS_DDRCTL_DRAMTMG4, tmg->ddrctl_dramtmg4); | |
142 | ddrss_ctl_writel(DDRSS_DDRCTL_DRAMTMG5, tmg->ddrctl_dramtmg5); | |
143 | ddrss_ctl_writel(DDRSS_DDRCTL_DRAMTMG8, tmg->ddrctl_dramtmg8); | |
144 | ddrss_ctl_writel(DDRSS_DDRCTL_DRAMTMG9, tmg->ddrctl_dramtmg9); | |
145 | ddrss_ctl_writel(DDRSS_DDRCTL_DRAMTMG11, tmg->ddrctl_dramtmg11); | |
146 | ddrss_ctl_writel(DDRSS_DDRCTL_DRAMTMG12, tmg->ddrctl_dramtmg12); | |
147 | ddrss_ctl_writel(DDRSS_DDRCTL_DRAMTMG13, tmg->ddrctl_dramtmg13); | |
148 | ddrss_ctl_writel(DDRSS_DDRCTL_DRAMTMG14, tmg->ddrctl_dramtmg14); | |
149 | ddrss_ctl_writel(DDRSS_DDRCTL_DRAMTMG15, tmg->ddrctl_dramtmg15); | |
150 | ddrss_ctl_writel(DDRSS_DDRCTL_DRAMTMG17, tmg->ddrctl_dramtmg17); | |
151 | ||
152 | ddrss_ctl_writel(DDRSS_DDRCTL_ZQCTL0, reg->ddrctl_zqctl0); | |
153 | ddrss_ctl_writel(DDRSS_DDRCTL_ZQCTL1, reg->ddrctl_zqctl1); | |
154 | ||
155 | ddrss_ctl_writel(DDRSS_DDRCTL_DFITMG0, reg->ddrctl_dfitmg0); | |
156 | ddrss_ctl_writel(DDRSS_DDRCTL_DFITMG1, reg->ddrctl_dfitmg1); | |
157 | ddrss_ctl_writel(DDRSS_DDRCTL_DFITMG2, reg->ddrctl_dfitmg2); | |
158 | ddrss_ctl_writel(DDRSS_DDRCTL_DFIMISC, reg->ddrctl_dfimisc); | |
159 | ||
160 | ddrss_ctl_writel(DDRSS_DDRCTL_ADDRMAP0, map->ddrctl_addrmap0); | |
161 | ddrss_ctl_writel(DDRSS_DDRCTL_ADDRMAP1, map->ddrctl_addrmap1); | |
162 | ddrss_ctl_writel(DDRSS_DDRCTL_ADDRMAP2, map->ddrctl_addrmap2); | |
163 | ddrss_ctl_writel(DDRSS_DDRCTL_ADDRMAP3, map->ddrctl_addrmap3); | |
164 | ddrss_ctl_writel(DDRSS_DDRCTL_ADDRMAP4, map->ddrctl_addrmap4); | |
165 | ddrss_ctl_writel(DDRSS_DDRCTL_ADDRMAP5, map->ddrctl_addrmap5); | |
166 | ddrss_ctl_writel(DDRSS_DDRCTL_ADDRMAP6, map->ddrctl_addrmap6); | |
167 | ddrss_ctl_writel(DDRSS_DDRCTL_ADDRMAP7, map->ddrctl_addrmap7); | |
168 | ddrss_ctl_writel(DDRSS_DDRCTL_ADDRMAP8, map->ddrctl_addrmap8); | |
169 | ddrss_ctl_writel(DDRSS_DDRCTL_ADDRMAP9, map->ddrctl_addrmap9); | |
170 | ddrss_ctl_writel(DDRSS_DDRCTL_ADDRMAP10, map->ddrctl_addrmap10); | |
171 | ddrss_ctl_writel(DDRSS_DDRCTL_ADDRMAP11, map->ddrctl_addrmap11); | |
172 | ||
173 | ddrss_ctl_writel(DDRSS_DDRCTL_ODTCFG, reg->ddrctl_odtcfg); | |
174 | ddrss_ctl_writel(DDRSS_DDRCTL_ODTMAP, reg->ddrctl_odtmap); | |
175 | ||
176 | /* Disable refreshes */ | |
177 | val = ddrss_ctl_readl(DDRSS_DDRCTL_RFSHCTL3); | |
178 | val |= 0x01; | |
179 | ddrss_ctl_writel(DDRSS_DDRCTL_RFSHCTL3, val); | |
180 | ||
181 | debug("%s: DDR controller configuration completed\n", __func__); | |
182 | } | |
183 | ||
184 | #define ddrss_phy_writel(off, val) \ | |
185 | do { \ | |
186 | ddrss_writel(ddrss->ddrss_phy_cfg, off, val); \ | |
187 | sdelay(10); /* Delay at least 20 clock cycles */ \ | |
188 | } while (0) | |
189 | ||
190 | #define ddrss_phy_readl(off) \ | |
191 | ({ \ | |
192 | u32 val = ddrss_readl(ddrss->ddrss_phy_cfg, off); \ | |
193 | sdelay(10); /* Delay at least 20 clock cycles */ \ | |
194 | val; \ | |
195 | }) | |
196 | ||
197 | /** | |
198 | * am654_ddrss_phy_configuration() - Configure PHY specific registers | |
199 | * @ddrss: corresponding ddrss device | |
200 | */ | |
201 | static void am654_ddrss_phy_configuration(struct am654_ddrss_desc *ddrss) | |
202 | { | |
203 | struct ddrss_ddrphy_ioctl_params *ioctl = &ddrss->params.phy_ioctl; | |
204 | struct ddrss_ddrphy_timing_params *tmg = &ddrss->params.phy_timing; | |
205 | struct ddrss_ddrphy_ctrl_params *ctrl = &ddrss->params.phy_ctrl; | |
206 | struct ddrss_ddrphy_cfg_params *cfg = &ddrss->params.phy_cfg; | |
207 | struct ddrss_ddrphy_zq_params *zq = &ddrss->params.phy_zq; | |
208 | ||
209 | debug("%s: DDR phy register configuration started\n", __func__); | |
210 | ||
211 | ddrss_phy_writel(DDRSS_DDRPHY_PGCR0, cfg->ddrphy_pgcr0); | |
212 | ddrss_phy_writel(DDRSS_DDRPHY_PGCR1, cfg->ddrphy_pgcr1); | |
213 | ddrss_phy_writel(DDRSS_DDRPHY_PGCR2, cfg->ddrphy_pgcr2); | |
214 | ddrss_phy_writel(DDRSS_DDRPHY_PGCR3, cfg->ddrphy_pgcr3); | |
215 | ddrss_phy_writel(DDRSS_DDRPHY_PGCR6, cfg->ddrphy_pgcr6); | |
216 | ||
217 | ddrss_phy_writel(DDRSS_DDRPHY_PTR2, tmg->ddrphy_ptr2); | |
218 | ddrss_phy_writel(DDRSS_DDRPHY_PTR3, tmg->ddrphy_ptr3); | |
219 | ddrss_phy_writel(DDRSS_DDRPHY_PTR4, tmg->ddrphy_ptr4); | |
220 | ddrss_phy_writel(DDRSS_DDRPHY_PTR5, tmg->ddrphy_ptr5); | |
221 | ddrss_phy_writel(DDRSS_DDRPHY_PTR6, tmg->ddrphy_ptr6); | |
222 | ||
223 | ddrss_phy_writel(DDRSS_DDRPHY_PLLCR0, ctrl->ddrphy_pllcr0); | |
224 | ||
225 | ddrss_phy_writel(DDRSS_DDRPHY_DXCCR, cfg->ddrphy_dxccr); | |
226 | ddrss_phy_writel(DDRSS_DDRPHY_DSGCR, cfg->ddrphy_dsgcr); | |
227 | ||
228 | ddrss_phy_writel(DDRSS_DDRPHY_DCR, cfg->ddrphy_dcr); | |
229 | ||
230 | ddrss_phy_writel(DDRSS_DDRPHY_DTPR0, tmg->ddrphy_dtpr0); | |
231 | ddrss_phy_writel(DDRSS_DDRPHY_DTPR1, tmg->ddrphy_dtpr1); | |
232 | ddrss_phy_writel(DDRSS_DDRPHY_DTPR2, tmg->ddrphy_dtpr2); | |
233 | ddrss_phy_writel(DDRSS_DDRPHY_DTPR3, tmg->ddrphy_dtpr3); | |
234 | ddrss_phy_writel(DDRSS_DDRPHY_DTPR4, tmg->ddrphy_dtpr4); | |
235 | ddrss_phy_writel(DDRSS_DDRPHY_DTPR5, tmg->ddrphy_dtpr5); | |
236 | ddrss_phy_writel(DDRSS_DDRPHY_DTPR6, tmg->ddrphy_dtpr6); | |
237 | ||
238 | ddrss_phy_writel(DDRSS_DDRPHY_ZQCR, zq->ddrphy_zqcr); | |
239 | ddrss_phy_writel(DDRSS_DDRPHY_ZQ0PR0, zq->ddrphy_zq0pr0); | |
240 | ddrss_phy_writel(DDRSS_DDRPHY_ZQ1PR0, zq->ddrphy_zq1pr0); | |
241 | ||
242 | ddrss_phy_writel(DDRSS_DDRPHY_MR0, ctrl->ddrphy_mr0); | |
243 | ddrss_phy_writel(DDRSS_DDRPHY_MR1, ctrl->ddrphy_mr1); | |
244 | ddrss_phy_writel(DDRSS_DDRPHY_MR2, ctrl->ddrphy_mr2); | |
245 | ddrss_phy_writel(DDRSS_DDRPHY_MR3, ctrl->ddrphy_mr3); | |
246 | ddrss_phy_writel(DDRSS_DDRPHY_MR4, ctrl->ddrphy_mr4); | |
247 | ddrss_phy_writel(DDRSS_DDRPHY_MR5, ctrl->ddrphy_mr5); | |
248 | ddrss_phy_writel(DDRSS_DDRPHY_MR6, ctrl->ddrphy_mr6); | |
249 | ddrss_phy_writel(DDRSS_DDRPHY_MR11, ctrl->ddrphy_mr11); | |
250 | ddrss_phy_writel(DDRSS_DDRPHY_MR12, ctrl->ddrphy_mr12); | |
251 | ddrss_phy_writel(DDRSS_DDRPHY_MR13, ctrl->ddrphy_mr13); | |
252 | ddrss_phy_writel(DDRSS_DDRPHY_MR14, ctrl->ddrphy_mr14); | |
253 | ddrss_phy_writel(DDRSS_DDRPHY_MR22, ctrl->ddrphy_mr22); | |
254 | ||
255 | ddrss_phy_writel(DDRSS_DDRPHY_VTCR0, ctrl->ddrphy_vtcr0); | |
256 | ||
257 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL0PLLCR0, cfg->ddrphy_dx8sl0pllcr0); | |
258 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL1PLLCR0, cfg->ddrphy_dx8sl1pllcr0); | |
259 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL2PLLCR0, cfg->ddrphy_dx8sl2pllcr0); | |
260 | ||
261 | ddrss_phy_writel(DDRSS_DDRPHY_DTCR0, ctrl->ddrphy_dtcr0); | |
262 | ddrss_phy_writel(DDRSS_DDRPHY_DTCR1, ctrl->ddrphy_dtcr1); | |
263 | ||
264 | ddrss_phy_writel(DDRSS_DDRPHY_ACIOCR0, ioctl->ddrphy_aciocr0); | |
265 | ddrss_phy_writel(DDRSS_DDRPHY_ACIOCR3, ioctl->ddrphy_aciocr3); | |
266 | ddrss_phy_writel(DDRSS_DDRPHY_ACIOCR5, ioctl->ddrphy_aciocr5); | |
267 | ddrss_phy_writel(DDRSS_DDRPHY_IOVCR0, ioctl->ddrphy_iovcr0); | |
268 | ||
269 | ddrss_phy_writel(DDRSS_DDRPHY_DX4GCR0, cfg->ddrphy_dx4gcr0); | |
270 | ddrss_phy_writel(DDRSS_DDRPHY_DX4GCR1, cfg->ddrphy_dx4gcr1); | |
271 | ddrss_phy_writel(DDRSS_DDRPHY_DX4GCR2, cfg->ddrphy_dx4gcr2); | |
272 | ddrss_phy_writel(DDRSS_DDRPHY_DX4GCR3, cfg->ddrphy_dx4gcr3); | |
273 | ||
274 | ddrss_phy_writel(DDRSS_DDRPHY_DX0GCR4, cfg->ddrphy_dx0gcr4); | |
275 | ddrss_phy_writel(DDRSS_DDRPHY_DX1GCR4, cfg->ddrphy_dx1gcr4); | |
276 | ddrss_phy_writel(DDRSS_DDRPHY_DX2GCR4, cfg->ddrphy_dx2gcr4); | |
277 | ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR4, cfg->ddrphy_dx3gcr4); | |
278 | ||
279 | ddrss_phy_writel(DDRSS_DDRPHY_PGCR5, cfg->ddrphy_pgcr5); | |
280 | ddrss_phy_writel(DDRSS_DDRPHY_DX0GCR5, cfg->ddrphy_dx0gcr5); | |
281 | ddrss_phy_writel(DDRSS_DDRPHY_DX1GCR5, cfg->ddrphy_dx1gcr5); | |
282 | ddrss_phy_writel(DDRSS_DDRPHY_DX2GCR5, cfg->ddrphy_dx2gcr5); | |
283 | ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR5, cfg->ddrphy_dx3gcr5); | |
284 | ||
285 | ddrss_phy_writel(DDRSS_DDRPHY_RANKIDR, DDRSS_DDRPHY_RANKIDR_RANK0); | |
286 | ||
287 | ddrss_phy_writel(DDRSS_DDRPHY_DX0GTR0, cfg->ddrphy_dx0gtr0); | |
288 | ddrss_phy_writel(DDRSS_DDRPHY_DX1GTR0, cfg->ddrphy_dx1gtr0); | |
289 | ddrss_phy_writel(DDRSS_DDRPHY_DX2GTR0, cfg->ddrphy_dx2gtr0); | |
290 | ddrss_phy_writel(DDRSS_DDRPHY_DX3GTR0, cfg->ddrphy_dx3gtr0); | |
291 | ddrss_phy_writel(DDRSS_DDRPHY_ODTCR, cfg->ddrphy_odtcr); | |
292 | ||
293 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL0IOCR, cfg->ddrphy_dx8sl0iocr); | |
294 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL1IOCR, cfg->ddrphy_dx8sl1iocr); | |
295 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL2IOCR, cfg->ddrphy_dx8sl2iocr); | |
296 | ||
297 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL0DXCTL2, cfg->ddrphy_dx8sl0dxctl2); | |
298 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL1DXCTL2, cfg->ddrphy_dx8sl1dxctl2); | |
299 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL2DXCTL2, cfg->ddrphy_dx8sl2dxctl2); | |
300 | ||
301 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL0DQSCTL, cfg->ddrphy_dx8sl0dqsctl); | |
302 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL1DQSCTL, cfg->ddrphy_dx8sl1dqsctl); | |
303 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL2DQSCTL, cfg->ddrphy_dx8sl2dqsctl); | |
304 | ||
305 | debug("%s: DDR phy register configuration completed\n", __func__); | |
306 | } | |
307 | ||
308 | static int __phy_builtin_init_routine(struct am654_ddrss_desc *ddrss, | |
309 | u32 init_value, u32 sts_mask, | |
310 | u32 err_mask) | |
311 | { | |
312 | int ret; | |
313 | ||
314 | ddrss_phy_writel(DDRSS_DDRPHY_PIR, init_value | PIR_INIT_MASK); | |
315 | ||
316 | sdelay(5); /* Delay at least 10 clock cycles */ | |
317 | ||
318 | if (!wait_on_value(sts_mask, sts_mask, | |
319 | ddrss->ddrss_phy_cfg + DDRSS_DDRPHY_PGSR0, LDELAY)) | |
320 | return -ETIMEDOUT; | |
321 | ||
322 | sdelay(16); /* Delay at least 32 clock cycles */ | |
323 | ||
324 | ret = ddrss_phy_readl(DDRSS_DDRPHY_PGSR0); | |
325 | debug("%s: PGSR0 val = 0x%x\n", __func__, ret); | |
326 | if (ret & err_mask) | |
327 | return -EINVAL; | |
328 | ||
329 | return 0; | |
330 | } | |
331 | ||
332 | int write_leveling(struct am654_ddrss_desc *ddrss) | |
333 | { | |
334 | int ret; | |
335 | ||
336 | debug("%s: Write leveling started\n", __func__); | |
337 | ||
338 | ret = __phy_builtin_init_routine(ddrss, PIR_WL_MASK, PGSR0_WLDONE_MASK, | |
339 | PGSR0_WLERR_MASK); | |
340 | if (ret) { | |
341 | if (ret == -ETIMEDOUT) | |
342 | printf("%s: ERROR: Write leveling timedout\n", | |
343 | __func__); | |
344 | else | |
345 | printf("%s:ERROR: Write leveling failed\n", __func__); | |
346 | return ret; | |
347 | } | |
348 | ||
349 | debug("%s: Write leveling completed\n", __func__); | |
350 | return 0; | |
351 | } | |
352 | ||
353 | int read_dqs_training(struct am654_ddrss_desc *ddrss) | |
354 | { | |
355 | int ret; | |
356 | ||
357 | debug("%s: Read DQS training started\n", __func__); | |
358 | ||
359 | ret = __phy_builtin_init_routine(ddrss, PIR_QSGATE_MASK, | |
360 | PGSR0_QSGDONE_MASK, PGSR0_QSGERR_MASK); | |
361 | if (ret) { | |
362 | if (ret == -ETIMEDOUT) | |
363 | printf("%s: ERROR: Read DQS timedout\n", __func__); | |
364 | else | |
365 | printf("%s:ERROR: Read DQS Gate training failed\n", | |
366 | __func__); | |
367 | return ret; | |
368 | } | |
369 | ||
370 | debug("%s: Read DQS training completed\n", __func__); | |
371 | return 0; | |
372 | } | |
373 | ||
374 | int dqs2dq_training(struct am654_ddrss_desc *ddrss) | |
375 | { | |
376 | int ret; | |
377 | ||
378 | debug("%s: DQS2DQ training started\n", __func__); | |
379 | ||
380 | ret = __phy_builtin_init_routine(ddrss, PIR_DQS2DQ_MASK, | |
381 | PGSR0_DQS2DQDONE_MASK, | |
382 | PGSR0_DQS2DQERR_MASK); | |
383 | if (ret) { | |
384 | if (ret == -ETIMEDOUT) | |
385 | printf("%s: ERROR: DQS2DQ training timedout\n", | |
386 | __func__); | |
387 | else | |
388 | printf("%s:ERROR: DQS2DQ training failed\n", | |
389 | __func__); | |
390 | return ret; | |
391 | } | |
392 | ||
393 | debug("%s: DQS2DQ training completed\n", __func__); | |
394 | return 0; | |
395 | } | |
396 | ||
397 | int write_leveling_adjustment(struct am654_ddrss_desc *ddrss) | |
398 | { | |
399 | int ret; | |
400 | ||
401 | debug("%s: Write Leveling adjustment\n", __func__); | |
402 | ret = __phy_builtin_init_routine(ddrss, PIR_WLADJ_MASK, | |
403 | PGSR0_WLADONE_MASK, PGSR0_WLAERR_MASK); | |
404 | if (ret) { | |
405 | if (ret == -ETIMEDOUT) | |
406 | printf("%s:ERROR: Write Leveling adjustment timedout\n", | |
407 | __func__); | |
408 | else | |
409 | printf("%s: ERROR: Write Leveling adjustment failed\n", | |
410 | __func__); | |
411 | return ret; | |
412 | } | |
413 | return 0; | |
414 | } | |
415 | ||
416 | int rest_training(struct am654_ddrss_desc *ddrss) | |
417 | { | |
418 | int ret; | |
419 | ||
420 | debug("%s: Rest of the training started\n", __func__); | |
421 | ||
422 | debug("%s: Read Deskew adjustment\n", __func__); | |
423 | ret = __phy_builtin_init_routine(ddrss, PIR_RDDSKW_MASK, | |
424 | PGSR0_RDDONE_MASK, PGSR0_RDERR_MASK); | |
425 | if (ret) { | |
426 | if (ret == -ETIMEDOUT) | |
427 | printf("%s: ERROR: Read Deskew timedout\n", __func__); | |
428 | else | |
429 | printf("%s: ERROR: Read Deskew failed\n", __func__); | |
430 | return ret; | |
431 | } | |
432 | ||
433 | debug("%s: Write Deskew adjustment\n", __func__); | |
434 | ret = __phy_builtin_init_routine(ddrss, PIR_WRDSKW_MASK, | |
435 | PGSR0_WDDONE_MASK, PGSR0_WDERR_MASK); | |
436 | if (ret) { | |
437 | if (ret == -ETIMEDOUT) | |
438 | printf("%s: ERROR: Write Deskew timedout\n", __func__); | |
439 | else | |
440 | printf("%s: ERROR: Write Deskew failed\n", __func__); | |
441 | return ret; | |
442 | } | |
443 | ||
444 | debug("%s: Read Eye training\n", __func__); | |
445 | ret = __phy_builtin_init_routine(ddrss, PIR_RDEYE_MASK, | |
446 | PGSR0_REDONE_MASK, PGSR0_REERR_MASK); | |
447 | if (ret) { | |
448 | if (ret == -ETIMEDOUT) | |
449 | printf("%s: ERROR: Read Eye training timedout\n", | |
450 | __func__); | |
451 | else | |
452 | printf("%s: ERROR: Read Eye training failed\n", | |
453 | __func__); | |
454 | return ret; | |
455 | } | |
456 | ||
457 | debug("%s: Write Eye training\n", __func__); | |
458 | ret = __phy_builtin_init_routine(ddrss, PIR_WREYE_MASK, | |
459 | PGSR0_WEDONE_MASK, PGSR0_WEERR_MASK); | |
460 | if (ret) { | |
461 | if (ret == -ETIMEDOUT) | |
462 | printf("%s: ERROR: Write Eye training timedout\n", | |
463 | __func__); | |
464 | else | |
465 | printf("%s: ERROR: Write Eye training failed\n", | |
466 | __func__); | |
467 | return ret; | |
468 | } | |
469 | return 0; | |
470 | } | |
471 | ||
472 | int VREF_training(struct am654_ddrss_desc *ddrss) | |
473 | { | |
474 | int ret; | |
475 | debug("%s: VREF training\n", __func__); | |
476 | ret = __phy_builtin_init_routine(ddrss, PIR_VREF_MASK, PGSR0_VDONE_MASK, | |
477 | PGSR0_VERR_MASK); | |
478 | if (ret) { | |
479 | if (ret == -ETIMEDOUT) | |
480 | printf("%s: ERROR: VREF training timedout\n", __func__); | |
481 | else | |
482 | printf("%s: ERROR: VREF training failed\n", __func__); | |
483 | return ret; | |
484 | } | |
485 | return 0; | |
486 | } | |
487 | ||
488 | int enable_dqs_pd(struct am654_ddrss_desc *ddrss) | |
489 | { | |
490 | u32 val; | |
491 | ||
492 | val = ddrss_phy_readl(DDRSS_DDRPHY_DX8SL0DQSCTL); | |
493 | val &= ~0xFF; | |
494 | val |= 0xF7; | |
495 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL0DQSCTL, val); | |
496 | ||
497 | val = ddrss_phy_readl(DDRSS_DDRPHY_DX8SL1DQSCTL); | |
498 | val &= ~0xFF; | |
499 | val |= 0xF7; | |
500 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL1DQSCTL, val); | |
501 | ||
502 | val = ddrss_phy_readl(DDRSS_DDRPHY_DX8SL2DQSCTL); | |
503 | val &= ~0xFF; | |
504 | val |= 0xF7; | |
505 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL2DQSCTL, val); | |
506 | ||
507 | sdelay(16); | |
508 | return 0; | |
509 | } | |
510 | ||
511 | int disable_dqs_pd(struct am654_ddrss_desc *ddrss) | |
512 | { | |
513 | u32 val; | |
514 | ||
515 | val = ddrss_phy_readl(DDRSS_DDRPHY_DX8SL0DQSCTL); | |
516 | val &= ~0xFF; | |
517 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL0DQSCTL, val); | |
518 | ||
519 | val = ddrss_phy_readl(DDRSS_DDRPHY_DX8SL1DQSCTL); | |
520 | val &= ~0xFF; | |
521 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL1DQSCTL, val); | |
522 | ||
523 | val = ddrss_phy_readl(DDRSS_DDRPHY_DX8SL2DQSCTL); | |
524 | val &= ~0xFF; | |
525 | ddrss_phy_writel(DDRSS_DDRPHY_DX8SL2DQSCTL, val); | |
526 | ||
527 | sdelay(16); | |
528 | return 0; | |
529 | } | |
530 | ||
531 | int cleanup_training(struct am654_ddrss_desc *ddrss) | |
532 | { | |
533 | u32 val; | |
534 | u32 dgsl0, dgsl1, dgsl2, dgsl3, rddly, rd2wr_wr2rd; | |
535 | ||
536 | ddrss_phy_writel(DDRSS_DDRPHY_RANKIDR, 0x00000000); | |
537 | dgsl0 = (ddrss_phy_readl(DDRSS_DDRPHY_DX0GTR0) & 0x1F) >> 2; | |
538 | dgsl1 = (ddrss_phy_readl(DDRSS_DDRPHY_DX1GTR0) & 0x1F) >> 2; | |
539 | dgsl2 = (ddrss_phy_readl(DDRSS_DDRPHY_DX2GTR0) & 0x1F) >> 2; | |
540 | dgsl3 = (ddrss_phy_readl(DDRSS_DDRPHY_DX3GTR0) & 0x1F) >> 2; | |
541 | ||
542 | rddly = dgsl0; | |
543 | if (dgsl1 < rddly) | |
544 | rddly = dgsl1; | |
545 | if (dgsl2 < rddly) | |
546 | rddly = dgsl2; | |
547 | if (dgsl3 < rddly) | |
548 | rddly = dgsl3; | |
549 | ||
550 | rddly += 5; | |
551 | ||
552 | /* Update rddly based on dgsl values */ | |
553 | val = (ddrss_phy_readl(DDRSS_DDRPHY_DX0GCR0) & ~0xF00000); | |
554 | val |= (rddly << 20); | |
555 | ddrss_phy_writel(DDRSS_DDRPHY_DX0GCR0, val); | |
556 | ||
557 | val = (ddrss_phy_readl(DDRSS_DDRPHY_DX1GCR0) & ~0xF00000); | |
558 | val |= (rddly << 20); | |
559 | ddrss_phy_writel(DDRSS_DDRPHY_DX1GCR0, val); | |
560 | ||
561 | val = (ddrss_phy_readl(DDRSS_DDRPHY_DX2GCR0) & ~0xF00000); | |
562 | val |= (rddly << 20); | |
563 | ddrss_phy_writel(DDRSS_DDRPHY_DX2GCR0, val); | |
564 | ||
565 | val = (ddrss_phy_readl(DDRSS_DDRPHY_DX3GCR0) & ~0xF00000); | |
566 | val |= (rddly << 20); | |
567 | ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR0, val); | |
568 | ||
569 | /* | |
570 | * Add system latency derived from training back into rd2wr and wr2rd | |
571 | * rd2wr = RL + BL/2 + 1 + WR_PREAMBLE - WL + max(DXnGTR0.DGSL) / 2 | |
572 | * wr2rd = CWL + PL + BL/2 + tWTR_L + max(DXnGTR0.DGSL) / 2 | |
573 | */ | |
574 | ||
575 | /* Select rank 0 */ | |
576 | ddrss_phy_writel(DDRSS_DDRPHY_RANKIDR, 0x00000000); | |
577 | ||
578 | dgsl0 = (ddrss_phy_readl(DDRSS_DDRPHY_DX0GTR0) & 0x1F); | |
579 | dgsl1 = (ddrss_phy_readl(DDRSS_DDRPHY_DX1GTR0) & 0x1F); | |
580 | dgsl2 = (ddrss_phy_readl(DDRSS_DDRPHY_DX2GTR0) & 0x1F); | |
581 | dgsl3 = (ddrss_phy_readl(DDRSS_DDRPHY_DX3GTR0) & 0x1F); | |
582 | ||
583 | /* Find maximum value across all bytes */ | |
584 | rd2wr_wr2rd = dgsl0; | |
585 | if (dgsl1 > rd2wr_wr2rd) | |
586 | rd2wr_wr2rd = dgsl1; | |
587 | if (dgsl2 > rd2wr_wr2rd) | |
588 | rd2wr_wr2rd = dgsl2; | |
589 | if (dgsl3 > rd2wr_wr2rd) | |
590 | rd2wr_wr2rd = dgsl3; | |
591 | ||
592 | rd2wr_wr2rd >>= 1; | |
593 | ||
594 | /* Now add in adjustment to DRAMTMG2 bit fields for rd2wr and wr2rd */ | |
595 | /* Clear VSWCTL.sw_done */ | |
596 | ddrss_ctl_writel(DDRSS_DDRCTL_SWCTL, | |
597 | ddrss_ctl_readl(DDRSS_DDRCTL_SWCTL) & ~0x1); | |
598 | /* Adjust rd2wr */ | |
599 | ddrss_ctl_writel(DDRSS_DDRCTL_DRAMTMG2, | |
600 | ddrss_ctl_readl(DDRSS_DDRCTL_DRAMTMG2) + | |
601 | (rd2wr_wr2rd << 8)); | |
602 | /* Adjust wr2rd */ | |
603 | ddrss_ctl_writel(DDRSS_DDRCTL_DRAMTMG2, | |
604 | ddrss_ctl_readl(DDRSS_DDRCTL_DRAMTMG2) + | |
605 | rd2wr_wr2rd); | |
606 | /* Set VSWCTL.sw_done */ | |
607 | ddrss_ctl_writel(DDRSS_DDRCTL_SWCTL, | |
608 | ddrss_ctl_readl(DDRSS_DDRCTL_SWCTL) | 0x1); | |
609 | /* Wait until settings are applied */ | |
610 | while (!(ddrss_ctl_readl(DDRSS_DDRCTL_SWSTAT) & 0x1)) { | |
611 | /* Do nothing */ | |
612 | }; | |
613 | ||
614 | debug("%s: Rest of the training completed\n", __func__); | |
615 | return 0; | |
616 | } | |
617 | ||
618 | /** | |
619 | * am654_ddrss_init() - Initialization sequence for enabling the SDRAM | |
620 | * device attached to ddrss. | |
621 | * @dev: corresponding ddrss device | |
622 | * | |
623 | * Does all the initialization sequence that is required to get attached | |
624 | * ddr in a working state. After this point, ddr should be accessible. | |
625 | * Return: 0 if all went ok, else corresponding error message. | |
626 | */ | |
627 | static int am654_ddrss_init(struct am654_ddrss_desc *ddrss) | |
628 | { | |
629 | int ret; | |
630 | u32 val; | |
631 | struct ddrss_ss_reg_params *reg = &ddrss->params.ss_reg; | |
632 | ||
633 | debug("Starting DDR initialization...\n"); | |
634 | ||
635 | debug("%s(ddrss=%p)\n", __func__, ddrss); | |
636 | ||
637 | ddrss_writel(ddrss->ddrss_ss_cfg, DDRSS_V2H_CTL_REG, | |
638 | reg->ddrss_v2h_ctl_reg); | |
639 | ||
640 | am654_ddrss_ctrl_configuration(ddrss); | |
641 | ||
642 | /* Release the reset to the controller */ | |
643 | clrbits_le32(ddrss->ddrss_ss_cfg + DDRSS_SS_CTL_REG, | |
644 | SS_CTL_REG_CTL_ARST_MASK); | |
645 | ||
646 | am654_ddrss_phy_configuration(ddrss); | |
647 | ||
648 | debug("Starting DDR training...\n"); | |
649 | ret = __phy_builtin_init_routine(ddrss, PIR_PHY_INIT, 0x1, 0); | |
650 | if (ret) { | |
651 | dev_err(ddrss->dev, "PHY initialization failed %d\n", ret); | |
652 | return ret; | |
653 | } | |
654 | ||
655 | ret = __phy_builtin_init_routine(ddrss, PIR_DRAM_INIT, | |
656 | PGSR0_DRAM_INIT_MASK, 0); | |
657 | if (ret) { | |
658 | dev_err(ddrss->dev, "DRAM initialization failed %d\n", ret); | |
659 | return ret; | |
660 | } | |
661 | ||
662 | ret = am654_ddrss_dram_wait_for_init_complt(ddrss); | |
663 | if (ret) { | |
664 | printf("%s: ERROR: DRAM Wait for init complete timedout\n", | |
665 | __func__); | |
666 | return ret; | |
667 | } | |
668 | ||
669 | val = am654_ddrss_get_type(ddrss); | |
670 | ||
671 | switch (val) { | |
672 | case DDR_TYPE_LPDDR4: | |
673 | ||
674 | ret = __phy_builtin_init_routine(ddrss, PIR_DRAM_INIT, | |
675 | PGSR0_DRAM_INIT_MASK, 0); | |
676 | if (ret) { | |
677 | dev_err(ddrss->dev, "DRAM initialization failed %d\n", | |
678 | ret); | |
679 | return ret; | |
680 | } | |
681 | ||
682 | /* must perform DRAM_INIT twice for LPDDR4 */ | |
683 | ret = __phy_builtin_init_routine(ddrss, PIR_DRAM_INIT, | |
684 | PGSR0_DRAM_INIT_MASK, 0); | |
685 | if (ret) { | |
686 | dev_err(ddrss->dev, "DRAM initialization failed %d\n", | |
687 | ret); | |
688 | return ret; | |
689 | } | |
690 | ||
691 | ret = am654_ddrss_dram_wait_for_init_complt(ddrss); | |
692 | if (ret) { | |
693 | printf("%s: ERROR: DRAM Wait for init complete timedout\n", | |
694 | __func__); | |
695 | return ret; | |
696 | } | |
697 | ||
698 | ret = write_leveling(ddrss); | |
699 | if (ret) | |
700 | return ret; | |
701 | ||
702 | ret = enable_dqs_pd(ddrss); | |
703 | if (ret) | |
704 | return ret; | |
705 | ||
706 | ret = read_dqs_training(ddrss); | |
707 | if (ret) | |
708 | return ret; | |
709 | ||
710 | ret = disable_dqs_pd(ddrss); | |
711 | if (ret) | |
712 | return ret; | |
713 | ||
714 | ret = dqs2dq_training(ddrss); | |
715 | if (ret) | |
716 | return ret; | |
717 | ||
718 | ret = write_leveling_adjustment(ddrss); | |
719 | if (ret) | |
720 | return ret; | |
721 | ||
722 | ret = rest_training(ddrss); | |
723 | if (ret) | |
724 | return ret; | |
725 | ||
726 | ret = VREF_training(ddrss); | |
727 | if (ret) | |
728 | return ret; | |
729 | ||
730 | debug("LPDDR4 training complete\n"); | |
731 | break; | |
732 | ||
733 | case DDR_TYPE_DDR4: | |
734 | ||
735 | debug("Starting DDR4 training\n"); | |
736 | ||
737 | ret = __phy_builtin_init_routine(ddrss, PIR_DRAM_INIT, | |
738 | PGSR0_DRAM_INIT_MASK, 0); | |
739 | if (ret) { | |
740 | dev_err(ddrss->dev, "DRAM initialization failed %d\n", | |
741 | ret); | |
742 | return ret; | |
743 | } | |
744 | ||
745 | ret = am654_ddrss_dram_wait_for_init_complt(ddrss); | |
746 | if (ret) { | |
747 | printf("%s: ERROR: DRAM Wait for init complete timedout\n", | |
748 | __func__); | |
749 | return ret; | |
750 | } | |
751 | ||
752 | ret = write_leveling(ddrss); | |
753 | if (ret) | |
754 | return ret; | |
755 | ||
756 | ret = read_dqs_training(ddrss); | |
757 | if (ret) | |
758 | return ret; | |
759 | ||
760 | ret = write_leveling_adjustment(ddrss); | |
761 | if (ret) | |
762 | return ret; | |
763 | ||
764 | ret = rest_training(ddrss); | |
765 | if (ret) | |
766 | return ret; | |
767 | ||
768 | ret = VREF_training(ddrss); | |
769 | if (ret) | |
770 | return ret; | |
771 | debug("DDR4 training complete\n"); | |
772 | break; | |
773 | ||
774 | case DDR_TYPE_DDR3: | |
775 | ||
776 | debug("Starting DDR3 training\n"); | |
777 | ||
778 | ret = __phy_builtin_init_routine(ddrss, PIR_DRAM_INIT, | |
779 | PGSR0_DRAM_INIT_MASK, 0); | |
780 | if (ret) { | |
781 | dev_err(ddrss->dev, "DRAM initialization failed %d\n", | |
782 | ret); | |
783 | return ret; | |
784 | } | |
785 | ||
786 | ret = am654_ddrss_dram_wait_for_init_complt(ddrss); | |
787 | if (ret) { | |
788 | printf("%s: ERROR: DRAM Wait for init complete timedout\n", | |
789 | __func__); | |
790 | return ret; | |
791 | } | |
792 | ||
793 | ret = write_leveling(ddrss); | |
794 | if (ret) | |
795 | return ret; | |
796 | ||
797 | ret = enable_dqs_pd(ddrss); | |
798 | if (ret) | |
799 | return ret; | |
800 | ||
801 | ret = read_dqs_training(ddrss); | |
802 | if (ret) | |
803 | return ret; | |
804 | ||
805 | ret = disable_dqs_pd(ddrss); | |
806 | if (ret) | |
807 | return ret; | |
808 | ||
809 | ret = write_leveling_adjustment(ddrss); | |
810 | if (ret) | |
811 | return ret; | |
812 | ||
813 | ret = rest_training(ddrss); | |
814 | if (ret) | |
815 | return ret; | |
816 | ||
817 | debug("DDR3 training complete\n"); | |
818 | break; | |
819 | default: | |
820 | printf("%s: ERROR: Unsupported DDR type\n", __func__); | |
821 | return -EINVAL; | |
822 | } | |
823 | ||
824 | ret = cleanup_training(ddrss); | |
825 | if (ret) | |
826 | return ret; | |
827 | ||
828 | /* Enabling refreshes after training is done */ | |
829 | ddrss_ctl_writel(DDRSS_DDRCTL_RFSHCTL3, | |
830 | ddrss_ctl_readl(DDRSS_DDRCTL_RFSHCTL3) & ~0x1); | |
831 | ||
832 | /* Disable PUBMODE after training is done */ | |
833 | ddrss_phy_writel(DDRSS_DDRPHY_PGCR1, | |
834 | ddrss_phy_readl(DDRSS_DDRPHY_PGCR1) & ~0x40); | |
835 | ||
836 | debug("Completed DDR training\n"); | |
837 | ||
838 | return 0; | |
839 | } | |
840 | ||
841 | /** | |
842 | * am654_ddrss_power_on() - Enable power and clocks for ddrss | |
843 | * @dev: corresponding ddrss device | |
844 | * | |
845 | * Tries to enable all the corresponding clocks to the ddrss and sets it | |
846 | * to the right frequency and then power on the ddrss. | |
847 | * Return: 0 if all went ok, else corresponding error message. | |
848 | */ | |
849 | static int am654_ddrss_power_on(struct am654_ddrss_desc *ddrss) | |
850 | { | |
851 | int ret; | |
852 | ||
853 | debug("%s(ddrss=%p)\n", __func__, ddrss); | |
854 | ||
855 | ret = clk_enable(&ddrss->ddrss_clk); | |
856 | if (ret) { | |
857 | dev_err(ddrss->dev, "clk_enable() failed: %d\n", ret); | |
858 | return ret; | |
859 | } | |
860 | ||
861 | ret = power_domain_on(&ddrss->ddrcfg_pwrdmn); | |
862 | if (ret) { | |
863 | dev_err(ddrss->dev, "power_domain_on() failed: %d\n", ret); | |
864 | return ret; | |
865 | } | |
866 | ||
867 | ret = power_domain_on(&ddrss->ddrdata_pwrdmn); | |
868 | if (ret) { | |
869 | dev_err(ddrss->dev, "power_domain_on() failed: %d\n", ret); | |
870 | return ret; | |
871 | } | |
872 | ||
873 | /* VTT enable */ | |
874 | #if CONFIG_IS_ENABLED(DM_REGULATOR) | |
875 | device_get_supply_regulator(ddrss->dev, "vtt-supply", | |
876 | &ddrss->vtt_supply); | |
877 | ret = regulator_set_value(ddrss->vtt_supply, 3300000); | |
878 | if (ret) | |
879 | return ret; | |
880 | debug("VTT regulator enabled\n"); | |
881 | #endif | |
882 | ||
883 | return 0; | |
884 | } | |
885 | ||
886 | /** | |
887 | * am654_ddrss_ofdata_to_priv() - generate private data from device tree | |
888 | * @dev: corresponding ddrss device | |
889 | * | |
890 | * Return: 0 if all went ok, else corresponding error message. | |
891 | */ | |
892 | static int am654_ddrss_ofdata_to_priv(struct udevice *dev) | |
893 | { | |
894 | struct am654_ddrss_desc *ddrss = dev_get_priv(dev); | |
895 | phys_addr_t reg; | |
896 | int ret; | |
897 | ||
898 | debug("%s(dev=%p)\n", __func__, dev); | |
899 | ||
900 | ret = clk_get_by_index(dev, 0, &ddrss->ddrss_clk); | |
901 | if (ret) { | |
902 | dev_err(dev, "clk_get failed: %d\n", ret); | |
903 | return ret; | |
904 | } | |
905 | ||
906 | ret = power_domain_get_by_index(dev, &ddrss->ddrcfg_pwrdmn, 0); | |
907 | if (ret) { | |
908 | dev_err(dev, "power_domain_get() failed: %d\n", ret); | |
909 | return ret; | |
910 | } | |
911 | ||
912 | ret = power_domain_get_by_index(dev, &ddrss->ddrdata_pwrdmn, 1); | |
913 | if (ret) { | |
914 | dev_err(dev, "power_domain_get() failed: %d\n", ret); | |
915 | return ret; | |
916 | } | |
917 | ||
918 | reg = devfdt_get_addr_name(dev, "ss"); | |
919 | if (reg == FDT_ADDR_T_NONE) { | |
920 | dev_err(dev, "No reg property for DDRSS wrapper logic\n"); | |
921 | return -EINVAL; | |
922 | } | |
923 | ddrss->ddrss_ss_cfg = (void *)reg; | |
924 | ||
925 | reg = devfdt_get_addr_name(dev, "ctl"); | |
926 | if (reg == FDT_ADDR_T_NONE) { | |
927 | dev_err(dev, "No reg property for Controller region\n"); | |
928 | return -EINVAL; | |
929 | } | |
930 | ddrss->ddrss_ctl_cfg = (void *)reg; | |
931 | ||
932 | reg = devfdt_get_addr_name(dev, "phy"); | |
933 | if (reg == FDT_ADDR_T_NONE) { | |
934 | dev_err(dev, "No reg property for PHY region\n"); | |
935 | return -EINVAL; | |
936 | } | |
937 | ddrss->ddrss_phy_cfg = (void *)reg; | |
938 | ||
939 | ret = dev_read_u32_array(dev, "ti,ss-reg", | |
940 | (u32 *)&ddrss->params.ss_reg, | |
941 | sizeof(ddrss->params.ss_reg) / sizeof(u32)); | |
942 | if (ret) { | |
943 | dev_err(dev, "Cannot read ti,ss-reg params\n"); | |
944 | return ret; | |
945 | } | |
946 | ||
947 | ret = dev_read_u32_array(dev, "ti,ctl-reg", | |
948 | (u32 *)&ddrss->params.ctl_reg, | |
949 | sizeof(ddrss->params.ctl_reg) / sizeof(u32)); | |
950 | if (ret) { | |
951 | dev_err(dev, "Cannot read ti,ctl-reg params\n"); | |
952 | return ret; | |
953 | } | |
954 | ||
955 | ret = dev_read_u32_array(dev, "ti,ctl-crc", | |
956 | (u32 *)&ddrss->params.ctl_crc, | |
957 | sizeof(ddrss->params.ctl_crc) / sizeof(u32)); | |
958 | if (ret) { | |
959 | dev_err(dev, "Cannot read ti,ctl-crc params\n"); | |
960 | return ret; | |
961 | } | |
962 | ||
963 | ret = dev_read_u32_array(dev, "ti,ctl-ecc", | |
964 | (u32 *)&ddrss->params.ctl_ecc, | |
965 | sizeof(ddrss->params.ctl_ecc) / sizeof(u32)); | |
966 | if (ret) { | |
967 | dev_err(dev, "Cannot read ti,ctl-ecc params\n"); | |
968 | return ret; | |
969 | } | |
970 | ||
971 | ret = dev_read_u32_array(dev, "ti,ctl-map", | |
972 | (u32 *)&ddrss->params.ctl_map, | |
973 | sizeof(ddrss->params.ctl_map) / sizeof(u32)); | |
974 | if (ret) { | |
975 | dev_err(dev, "Cannot read ti,ctl-map params\n"); | |
976 | return ret; | |
977 | } | |
978 | ||
979 | ret = dev_read_u32_array(dev, "ti,ctl-pwr", | |
980 | (u32 *)&ddrss->params.ctl_pwr, | |
981 | sizeof(ddrss->params.ctl_pwr) / sizeof(u32)); | |
982 | if (ret) { | |
983 | dev_err(dev, "Cannot read ti,ctl-pwr params\n"); | |
984 | return ret; | |
985 | } | |
986 | ||
987 | ret = dev_read_u32_array(dev, "ti,ctl-timing", | |
988 | (u32 *)&ddrss->params.ctl_timing, | |
989 | sizeof(ddrss->params.ctl_timing) / | |
990 | sizeof(u32)); | |
991 | if (ret) { | |
992 | dev_err(dev, "Cannot read ti,ctl-timing params\n"); | |
993 | return ret; | |
994 | } | |
995 | ||
996 | ret = dev_read_u32_array(dev, "ti,phy-cfg", | |
997 | (u32 *)&ddrss->params.phy_cfg, | |
998 | sizeof(ddrss->params.phy_cfg) / sizeof(u32)); | |
999 | if (ret) { | |
1000 | dev_err(dev, "Cannot read ti,phy-cfg params\n"); | |
1001 | return ret; | |
1002 | } | |
1003 | ||
1004 | ret = dev_read_u32_array(dev, "ti,phy-ctl", | |
1005 | (u32 *)&ddrss->params.phy_ctrl, | |
1006 | sizeof(ddrss->params.phy_ctrl) / sizeof(u32)); | |
1007 | if (ret) { | |
1008 | dev_err(dev, "Cannot read ti,phy-ctl params\n"); | |
1009 | return ret; | |
1010 | } | |
1011 | ||
1012 | ret = dev_read_u32_array(dev, "ti,phy-ioctl", | |
1013 | (u32 *)&ddrss->params.phy_ioctl, | |
1014 | sizeof(ddrss->params.phy_ioctl) / sizeof(u32)); | |
1015 | if (ret) { | |
1016 | dev_err(dev, "Cannot read ti,phy-ioctl params\n"); | |
1017 | return ret; | |
1018 | } | |
1019 | ||
1020 | ret = dev_read_u32_array(dev, "ti,phy-timing", | |
1021 | (u32 *)&ddrss->params.phy_timing, | |
1022 | sizeof(ddrss->params.phy_timing) / | |
1023 | sizeof(u32)); | |
1024 | if (ret) { | |
1025 | dev_err(dev, "Cannot read ti,phy-timing params\n"); | |
1026 | return ret; | |
1027 | } | |
1028 | ||
1029 | ret = dev_read_u32_array(dev, "ti,phy-zq", (u32 *)&ddrss->params.phy_zq, | |
1030 | sizeof(ddrss->params.phy_zq) / sizeof(u32)); | |
1031 | if (ret) { | |
1032 | dev_err(dev, "Cannot read ti,phy-zq params\n"); | |
1033 | return ret; | |
1034 | } | |
1035 | ||
1036 | return ret; | |
1037 | } | |
1038 | ||
1039 | /** | |
1040 | * am654_ddrss_probe() - Basic probe | |
1041 | * @dev: corresponding ddrss device | |
1042 | * | |
1043 | * Return: 0 if all went ok, else corresponding error message | |
1044 | */ | |
1045 | static int am654_ddrss_probe(struct udevice *dev) | |
1046 | { | |
1047 | struct am654_ddrss_desc *ddrss = dev_get_priv(dev); | |
1048 | int ret; | |
1049 | ||
1050 | debug("%s(dev=%p)\n", __func__, dev); | |
1051 | ||
1052 | ret = am654_ddrss_ofdata_to_priv(dev); | |
1053 | if (ret) | |
1054 | return ret; | |
1055 | ||
1056 | ddrss->dev = dev; | |
1057 | ret = am654_ddrss_power_on(ddrss); | |
1058 | if (ret) | |
1059 | return ret; | |
1060 | ||
1061 | ret = am654_ddrss_init(ddrss); | |
1062 | ||
1063 | return ret; | |
1064 | } | |
1065 | ||
1066 | static int am654_ddrss_get_info(struct udevice *dev, struct ram_info *info) | |
1067 | { | |
1068 | return 0; | |
1069 | } | |
1070 | ||
1071 | static struct ram_ops am654_ddrss_ops = { | |
1072 | .get_info = am654_ddrss_get_info, | |
1073 | }; | |
1074 | ||
1075 | static const struct udevice_id am654_ddrss_ids[] = { | |
1076 | { .compatible = "ti,am654-ddrss" }, | |
1077 | { } | |
1078 | }; | |
1079 | ||
1080 | U_BOOT_DRIVER(am654_ddrss) = { | |
1081 | .name = "am654_ddrss", | |
1082 | .id = UCLASS_RAM, | |
1083 | .of_match = am654_ddrss_ids, | |
1084 | .ops = &am654_ddrss_ops, | |
1085 | .probe = am654_ddrss_probe, | |
1086 | .priv_auto_alloc_size = sizeof(struct am654_ddrss_desc), | |
1087 | }; |