]>
Commit | Line | Data |
---|---|---|
19f627ec MV |
1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
2 | /* | |
3 | * Renesas UFS host controller driver | |
4 | * | |
5 | * Copyright (C) 2022 Renesas Electronics Corporation | |
6 | */ | |
7 | ||
8 | #include <clk.h> | |
19f627ec MV |
9 | #include <dm.h> |
10 | #include <ufs.h> | |
11 | #include <asm/io.h> | |
12 | #include <dm/device_compat.h> | |
13 | #include <linux/bitops.h> | |
14 | #include <linux/delay.h> | |
15 | #include <linux/err.h> | |
16 | #include <linux/bug.h> | |
17 | #include <linux/iopoll.h> | |
18 | ||
19 | #include "ufs.h" | |
20 | ||
21 | struct ufs_renesas_priv { | |
22 | struct clk_bulk clks; | |
23 | bool initialized; /* The hardware needs initialization once */ | |
24 | }; | |
25 | ||
26 | enum { | |
27 | SET_PHY_INDEX_LO = 0, | |
28 | SET_PHY_INDEX_HI, | |
29 | TIMER_INDEX, | |
30 | MAX_INDEX | |
31 | }; | |
32 | ||
33 | enum ufs_renesas_init_param_mode { | |
34 | MODE_RESTORE, | |
35 | MODE_SET, | |
36 | MODE_SAVE, | |
37 | MODE_POLL, | |
38 | MODE_WAIT, | |
39 | MODE_WRITE, | |
40 | }; | |
41 | ||
42 | #define PARAM_RESTORE(_reg, _index) \ | |
43 | { .mode = MODE_RESTORE, .reg = _reg, .index = _index } | |
44 | #define PARAM_SET(_index, _set) \ | |
45 | { .mode = MODE_SET, .index = _index, .u.set = _set } | |
46 | #define PARAM_SAVE(_reg, _mask, _index) \ | |
47 | { .mode = MODE_SAVE, .reg = _reg, .mask = (u32)(_mask), \ | |
48 | .index = _index } | |
49 | #define PARAM_POLL(_reg, _expected, _mask) \ | |
50 | { .mode = MODE_POLL, .reg = _reg, .u.expected = _expected, \ | |
51 | .mask = (u32)(_mask) } | |
52 | #define PARAM_WAIT(_delay_us) \ | |
53 | { .mode = MODE_WAIT, .u.delay_us = _delay_us } | |
54 | ||
55 | #define PARAM_WRITE(_reg, _val) \ | |
56 | { .mode = MODE_WRITE, .reg = _reg, .u.val = _val } | |
57 | ||
58 | #define PARAM_WRITE_D0_D4(_d0, _d4) \ | |
59 | PARAM_WRITE(0xd0, _d0), PARAM_WRITE(0xd4, _d4) | |
60 | ||
61 | #define PARAM_WRITE_800_80C_POLL(_addr, _data_800) \ | |
62 | PARAM_WRITE_D0_D4(0x0000080c, 0x00000100), \ | |
63 | PARAM_WRITE_D0_D4(0x00000800, ((_data_800) << 16) | BIT(8) | (_addr)), \ | |
64 | PARAM_WRITE(0xd0, 0x0000080c), \ | |
65 | PARAM_POLL(0xd4, BIT(8), BIT(8)) | |
66 | ||
67 | #define PARAM_RESTORE_800_80C_POLL(_index) \ | |
68 | PARAM_WRITE_D0_D4(0x0000080c, 0x00000100), \ | |
69 | PARAM_WRITE(0xd0, 0x00000800), \ | |
70 | PARAM_RESTORE(0xd4, (_index)), \ | |
71 | PARAM_WRITE(0xd0, 0x0000080c), \ | |
72 | PARAM_POLL(0xd4, BIT(8), BIT(8)) | |
73 | ||
74 | #define PARAM_WRITE_804_80C_POLL(_addr, _data_804) \ | |
75 | PARAM_WRITE_D0_D4(0x0000080c, 0x00000100), \ | |
76 | PARAM_WRITE_D0_D4(0x00000804, ((_data_804) << 16) | BIT(8) | (_addr)), \ | |
77 | PARAM_WRITE(0xd0, 0x0000080c), \ | |
78 | PARAM_POLL(0xd4, BIT(8), BIT(8)) | |
79 | ||
80 | #define PARAM_WRITE_828_82C_POLL(_data_828) \ | |
81 | PARAM_WRITE_D0_D4(0x0000082c, 0x0f000000), \ | |
82 | PARAM_WRITE_D0_D4(0x00000828, _data_828), \ | |
83 | PARAM_WRITE(0xd0, 0x0000082c), \ | |
84 | PARAM_POLL(0xd4, _data_828, _data_828) | |
85 | ||
86 | #define PARAM_WRITE_PHY(_addr16, _data16) \ | |
87 | PARAM_WRITE(0xf0, 1), \ | |
88 | PARAM_WRITE_800_80C_POLL(0x16, (_addr16) & 0xff), \ | |
89 | PARAM_WRITE_800_80C_POLL(0x17, ((_addr16) >> 8) & 0xff), \ | |
90 | PARAM_WRITE_800_80C_POLL(0x18, (_data16) & 0xff), \ | |
91 | PARAM_WRITE_800_80C_POLL(0x19, ((_data16) >> 8) & 0xff), \ | |
92 | PARAM_WRITE_800_80C_POLL(0x1c, 0x01), \ | |
93 | PARAM_WRITE_828_82C_POLL(0x0f000000), \ | |
94 | PARAM_WRITE(0xf0, 0) | |
95 | ||
96 | #define PARAM_SET_PHY(_addr16, _data16) \ | |
97 | PARAM_WRITE(0xf0, 1), \ | |
98 | PARAM_WRITE_800_80C_POLL(0x16, (_addr16) & 0xff), \ | |
99 | PARAM_WRITE_800_80C_POLL(0x17, ((_addr16) >> 8) & 0xff), \ | |
100 | PARAM_WRITE_800_80C_POLL(0x1c, 0x01), \ | |
101 | PARAM_WRITE_828_82C_POLL(0x0f000000), \ | |
102 | PARAM_WRITE_804_80C_POLL(0x1a, 0), \ | |
103 | PARAM_WRITE(0xd0, 0x00000808), \ | |
104 | PARAM_SAVE(0xd4, 0xff, SET_PHY_INDEX_LO), \ | |
105 | PARAM_WRITE_804_80C_POLL(0x1b, 0), \ | |
106 | PARAM_WRITE(0xd0, 0x00000808), \ | |
107 | PARAM_SAVE(0xd4, 0xff, SET_PHY_INDEX_HI), \ | |
108 | PARAM_WRITE_828_82C_POLL(0x0f000000), \ | |
109 | PARAM_WRITE(0xf0, 0), \ | |
110 | PARAM_WRITE(0xf0, 1), \ | |
111 | PARAM_WRITE_800_80C_POLL(0x16, (_addr16) & 0xff), \ | |
112 | PARAM_WRITE_800_80C_POLL(0x17, ((_addr16) >> 8) & 0xff), \ | |
113 | PARAM_SET(SET_PHY_INDEX_LO, (((_data16) & 0xff) << 16) | BIT(8) | 0x18), \ | |
114 | PARAM_RESTORE_800_80C_POLL(SET_PHY_INDEX_LO), \ | |
115 | PARAM_SET(SET_PHY_INDEX_HI, ((((_data16) >> 8) & 0xff) << 16) | BIT(8) | 0x19), \ | |
116 | PARAM_RESTORE_800_80C_POLL(SET_PHY_INDEX_HI), \ | |
117 | PARAM_WRITE_800_80C_POLL(0x1c, 0x01), \ | |
118 | PARAM_WRITE_828_82C_POLL(0x0f000000), \ | |
119 | PARAM_WRITE(0xf0, 0) | |
120 | ||
121 | #define PARAM_INDIRECT_WRITE(_gpio, _addr, _data_800) \ | |
122 | PARAM_WRITE(0xf0, _gpio), \ | |
123 | PARAM_WRITE_800_80C_POLL((_addr), _data_800), \ | |
124 | PARAM_WRITE_828_82C_POLL(0x0f000000), \ | |
125 | PARAM_WRITE(0xf0, 0) | |
126 | ||
127 | #define PARAM_INDIRECT_POLL(_gpio, _addr, _expected, _mask) \ | |
128 | PARAM_WRITE(0xf0, _gpio), \ | |
129 | PARAM_WRITE_800_80C_POLL((_addr), 0), \ | |
130 | PARAM_WRITE(0xd0, 0x00000808), \ | |
131 | PARAM_POLL(0xd4, (_expected), (_mask)), \ | |
132 | PARAM_WRITE(0xf0, 0) | |
133 | ||
134 | struct ufs_renesas_init_param { | |
135 | enum ufs_renesas_init_param_mode mode; | |
136 | u32 reg; | |
137 | union { | |
138 | u32 expected; | |
139 | u32 delay_us; | |
140 | u32 set; | |
141 | u32 val; | |
142 | } u; | |
143 | u32 mask; | |
144 | u32 index; | |
145 | }; | |
146 | ||
147 | /* This setting is for SERIES B */ | |
148 | static const struct ufs_renesas_init_param ufs_param[] = { | |
149 | PARAM_WRITE(0xc0, 0x49425308), | |
150 | PARAM_WRITE_D0_D4(0x00000104, 0x00000002), | |
151 | PARAM_WAIT(1), | |
152 | PARAM_WRITE_D0_D4(0x00000828, 0x00000200), | |
153 | PARAM_WAIT(1), | |
154 | PARAM_WRITE_D0_D4(0x00000828, 0x00000000), | |
155 | PARAM_WRITE_D0_D4(0x00000104, 0x00000001), | |
156 | PARAM_WRITE_D0_D4(0x00000940, 0x00000001), | |
157 | PARAM_WAIT(1), | |
158 | PARAM_WRITE_D0_D4(0x00000940, 0x00000000), | |
159 | ||
160 | PARAM_WRITE(0xc0, 0x49425308), | |
161 | PARAM_WRITE(0xc0, 0x41584901), | |
162 | ||
163 | PARAM_WRITE_D0_D4(0x0000080c, 0x00000100), | |
164 | PARAM_WRITE_D0_D4(0x00000804, 0x00000000), | |
165 | PARAM_WRITE(0xd0, 0x0000080c), | |
166 | PARAM_POLL(0xd4, BIT(8), BIT(8)), | |
167 | ||
168 | PARAM_WRITE(REG_CONTROLLER_ENABLE, 0x00000001), | |
169 | ||
170 | PARAM_WRITE(0xd0, 0x00000804), | |
171 | PARAM_POLL(0xd4, BIT(8) | BIT(6) | BIT(0), BIT(8) | BIT(6) | BIT(0)), | |
172 | ||
173 | PARAM_WRITE(0xd0, 0x00000d00), | |
174 | PARAM_SAVE(0xd4, 0x0000ffff, TIMER_INDEX), | |
175 | PARAM_WRITE(0xd4, 0x00000000), | |
176 | PARAM_WRITE_D0_D4(0x0000082c, 0x0f000000), | |
177 | PARAM_WRITE_D0_D4(0x00000828, 0x08000000), | |
178 | PARAM_WRITE(0xd0, 0x0000082c), | |
179 | PARAM_POLL(0xd4, BIT(27), BIT(27)), | |
180 | PARAM_WRITE(0xd0, 0x00000d2c), | |
181 | PARAM_POLL(0xd4, BIT(0), BIT(0)), | |
182 | ||
183 | /* phy setup */ | |
184 | PARAM_INDIRECT_WRITE(1, 0x01, 0x001f), | |
185 | PARAM_INDIRECT_WRITE(7, 0x5d, 0x0014), | |
186 | PARAM_INDIRECT_WRITE(7, 0x5e, 0x0014), | |
187 | PARAM_INDIRECT_WRITE(7, 0x0d, 0x0003), | |
188 | PARAM_INDIRECT_WRITE(7, 0x0e, 0x0007), | |
189 | PARAM_INDIRECT_WRITE(7, 0x5f, 0x0003), | |
190 | PARAM_INDIRECT_WRITE(7, 0x60, 0x0003), | |
191 | PARAM_INDIRECT_WRITE(7, 0x5b, 0x00a6), | |
192 | PARAM_INDIRECT_WRITE(7, 0x5c, 0x0003), | |
193 | ||
194 | PARAM_INDIRECT_POLL(7, 0x3c, 0, BIT(7)), | |
195 | PARAM_INDIRECT_POLL(7, 0x4c, 0, BIT(4)), | |
196 | ||
197 | PARAM_INDIRECT_WRITE(1, 0x32, 0x0080), | |
198 | PARAM_INDIRECT_WRITE(1, 0x1f, 0x0001), | |
199 | PARAM_INDIRECT_WRITE(0, 0x2c, 0x0001), | |
200 | PARAM_INDIRECT_WRITE(0, 0x32, 0x0087), | |
201 | ||
202 | PARAM_INDIRECT_WRITE(1, 0x4d, 0x0061), | |
203 | PARAM_INDIRECT_WRITE(4, 0x9b, 0x0009), | |
204 | PARAM_INDIRECT_WRITE(4, 0xa6, 0x0005), | |
205 | PARAM_INDIRECT_WRITE(4, 0xa5, 0x0058), | |
206 | PARAM_INDIRECT_WRITE(1, 0x39, 0x0027), | |
207 | PARAM_INDIRECT_WRITE(1, 0x47, 0x004c), | |
208 | ||
209 | PARAM_INDIRECT_WRITE(7, 0x0d, 0x0002), | |
210 | PARAM_INDIRECT_WRITE(7, 0x0e, 0x0007), | |
211 | ||
212 | PARAM_WRITE_PHY(0x0028, 0x0061), | |
213 | PARAM_WRITE_PHY(0x4014, 0x0061), | |
214 | PARAM_SET_PHY(0x401c, BIT(2)), | |
215 | PARAM_WRITE_PHY(0x4000, 0x0000), | |
216 | PARAM_WRITE_PHY(0x4001, 0x0000), | |
217 | ||
218 | PARAM_WRITE_PHY(0x10ae, 0x0001), | |
219 | PARAM_WRITE_PHY(0x10ad, 0x0000), | |
220 | PARAM_WRITE_PHY(0x10af, 0x0001), | |
221 | PARAM_WRITE_PHY(0x10b6, 0x0001), | |
222 | PARAM_WRITE_PHY(0x10ae, 0x0000), | |
223 | ||
224 | PARAM_WRITE_PHY(0x10ae, 0x0001), | |
225 | PARAM_WRITE_PHY(0x10ad, 0x0000), | |
226 | PARAM_WRITE_PHY(0x10af, 0x0002), | |
227 | PARAM_WRITE_PHY(0x10b6, 0x0001), | |
228 | PARAM_WRITE_PHY(0x10ae, 0x0000), | |
229 | ||
230 | PARAM_WRITE_PHY(0x10ae, 0x0001), | |
231 | PARAM_WRITE_PHY(0x10ad, 0x0080), | |
232 | PARAM_WRITE_PHY(0x10af, 0x0000), | |
233 | PARAM_WRITE_PHY(0x10b6, 0x0001), | |
234 | PARAM_WRITE_PHY(0x10ae, 0x0000), | |
235 | ||
236 | PARAM_WRITE_PHY(0x10ae, 0x0001), | |
237 | PARAM_WRITE_PHY(0x10ad, 0x0080), | |
238 | PARAM_WRITE_PHY(0x10af, 0x001a), | |
239 | PARAM_WRITE_PHY(0x10b6, 0x0001), | |
240 | PARAM_WRITE_PHY(0x10ae, 0x0000), | |
241 | ||
242 | PARAM_INDIRECT_WRITE(7, 0x70, 0x0016), | |
243 | PARAM_INDIRECT_WRITE(7, 0x71, 0x0016), | |
244 | PARAM_INDIRECT_WRITE(7, 0x72, 0x0014), | |
245 | PARAM_INDIRECT_WRITE(7, 0x73, 0x0014), | |
246 | PARAM_INDIRECT_WRITE(7, 0x74, 0x0000), | |
247 | PARAM_INDIRECT_WRITE(7, 0x75, 0x0000), | |
248 | PARAM_INDIRECT_WRITE(7, 0x76, 0x0010), | |
249 | PARAM_INDIRECT_WRITE(7, 0x77, 0x0010), | |
250 | PARAM_INDIRECT_WRITE(7, 0x78, 0x00ff), | |
251 | PARAM_INDIRECT_WRITE(7, 0x79, 0x0000), | |
252 | ||
253 | PARAM_INDIRECT_WRITE(7, 0x19, 0x0007), | |
254 | ||
255 | PARAM_INDIRECT_WRITE(7, 0x1a, 0x0007), | |
256 | ||
257 | PARAM_INDIRECT_WRITE(7, 0x24, 0x000c), | |
258 | ||
259 | PARAM_INDIRECT_WRITE(7, 0x25, 0x000c), | |
260 | ||
261 | PARAM_INDIRECT_WRITE(7, 0x62, 0x0000), | |
262 | PARAM_INDIRECT_WRITE(7, 0x63, 0x0000), | |
263 | PARAM_INDIRECT_WRITE(7, 0x5d, 0x0014), | |
264 | PARAM_INDIRECT_WRITE(7, 0x5e, 0x0017), | |
265 | PARAM_INDIRECT_WRITE(7, 0x5d, 0x0004), | |
266 | PARAM_INDIRECT_WRITE(7, 0x5e, 0x0017), | |
267 | PARAM_INDIRECT_POLL(7, 0x55, 0, BIT(6)), | |
268 | PARAM_INDIRECT_POLL(7, 0x41, 0, BIT(7)), | |
269 | /* end of phy setup */ | |
270 | ||
271 | PARAM_WRITE(0xf0, 0), | |
272 | PARAM_WRITE(0xd0, 0x00000d00), | |
273 | PARAM_RESTORE(0xd4, TIMER_INDEX), | |
274 | }; | |
275 | ||
276 | static void ufs_renesas_reg_control(struct ufs_hba *hba, | |
277 | const struct ufs_renesas_init_param *p) | |
278 | { | |
279 | static u32 save[MAX_INDEX]; | |
280 | int ret; | |
281 | u32 val; | |
282 | ||
283 | WARN_ON(p->index >= MAX_INDEX); | |
284 | ||
285 | switch (p->mode) { | |
286 | case MODE_RESTORE: | |
287 | ufshcd_writel(hba, save[p->index], p->reg); | |
288 | break; | |
289 | case MODE_SET: | |
290 | save[p->index] |= p->u.set; | |
291 | break; | |
292 | case MODE_SAVE: | |
293 | save[p->index] = ufshcd_readl(hba, p->reg) & p->mask; | |
294 | break; | |
295 | case MODE_POLL: | |
296 | ret = readl_poll_timeout(hba->mmio_base + p->reg, val, | |
297 | (val & p->mask) == p->u.expected, | |
298 | 10000); | |
299 | if (ret) | |
300 | dev_err(hba->dev, "%s: poll failed %d (%08x, %08x, %08x)\n", | |
301 | __func__, ret, val, p->mask, p->u.expected); | |
302 | break; | |
303 | case MODE_WAIT: | |
304 | if (p->u.delay_us > 1000) | |
305 | mdelay(DIV_ROUND_UP(p->u.delay_us, 1000)); | |
306 | else | |
307 | udelay(p->u.delay_us); | |
308 | break; | |
309 | case MODE_WRITE: | |
310 | ufshcd_writel(hba, p->u.val, p->reg); | |
311 | break; | |
312 | default: | |
313 | break; | |
314 | } | |
315 | } | |
316 | ||
317 | static void ufs_renesas_pre_init(struct ufs_hba *hba) | |
318 | { | |
319 | const struct ufs_renesas_init_param *p = ufs_param; | |
320 | unsigned int i; | |
321 | ||
322 | for (i = 0; i < ARRAY_SIZE(ufs_param); i++) | |
323 | ufs_renesas_reg_control(hba, &p[i]); | |
324 | } | |
325 | ||
326 | static int ufs_renesas_hce_enable_notify(struct ufs_hba *hba, | |
327 | enum ufs_notify_change_status status) | |
328 | { | |
329 | struct ufs_renesas_priv *priv = dev_get_priv(hba->dev); | |
330 | ||
331 | if (priv->initialized) | |
332 | return 0; | |
333 | ||
334 | if (status == PRE_CHANGE) | |
335 | ufs_renesas_pre_init(hba); | |
336 | ||
337 | priv->initialized = true; | |
338 | ||
339 | return 0; | |
340 | } | |
341 | ||
342 | static int ufs_renesas_init(struct ufs_hba *hba) | |
343 | { | |
344 | hba->quirks |= UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS | UFSHCD_QUIRK_HIBERN_FASTAUTO; | |
345 | ||
346 | return 0; | |
347 | } | |
348 | ||
349 | static struct ufs_hba_ops ufs_renesas_vops = { | |
350 | .init = ufs_renesas_init, | |
351 | .hce_enable_notify = ufs_renesas_hce_enable_notify, | |
352 | }; | |
353 | ||
354 | static int ufs_renesas_pltfm_bind(struct udevice *dev) | |
355 | { | |
356 | struct udevice *scsi_dev; | |
357 | ||
358 | return ufs_scsi_bind(dev, &scsi_dev); | |
359 | } | |
360 | ||
361 | static int ufs_renesas_pltfm_probe(struct udevice *dev) | |
362 | { | |
363 | struct ufs_renesas_priv *priv = dev_get_priv(dev); | |
364 | int err; | |
365 | ||
366 | err = clk_get_bulk(dev, &priv->clks); | |
367 | if (err < 0) | |
368 | return err; | |
369 | ||
370 | err = clk_enable_bulk(&priv->clks); | |
371 | if (err) | |
372 | goto err_clk_enable; | |
373 | ||
374 | err = ufshcd_probe(dev, &ufs_renesas_vops); | |
375 | if (err) { | |
376 | dev_err(dev, "ufshcd_probe() failed %d\n", err); | |
377 | goto err_ufshcd_probe; | |
378 | } | |
379 | ||
380 | return 0; | |
381 | ||
382 | err_ufshcd_probe: | |
383 | clk_disable_bulk(&priv->clks); | |
384 | err_clk_enable: | |
385 | clk_release_bulk(&priv->clks); | |
386 | return err; | |
387 | } | |
388 | ||
389 | static int ufs_renesas_pltfm_remove(struct udevice *dev) | |
390 | { | |
391 | struct ufs_renesas_priv *priv = dev_get_priv(dev); | |
392 | ||
393 | clk_disable_bulk(&priv->clks); | |
394 | clk_release_bulk(&priv->clks); | |
395 | ||
396 | return 0; | |
397 | } | |
398 | ||
399 | static const struct udevice_id ufs_renesas_pltfm_ids[] = { | |
400 | { .compatible = "renesas,r8a779f0-ufs" }, | |
401 | { /* sentinel */ } | |
402 | }; | |
403 | ||
404 | U_BOOT_DRIVER(ufs_renesas) = { | |
405 | .name = "ufs-renesas", | |
406 | .id = UCLASS_UFS, | |
407 | .of_match = ufs_renesas_pltfm_ids, | |
408 | .bind = ufs_renesas_pltfm_bind, | |
409 | .probe = ufs_renesas_pltfm_probe, | |
410 | .remove = ufs_renesas_pltfm_remove, | |
411 | .priv_auto = sizeof(struct ufs_renesas_priv), | |
412 | }; |