]> Git Repo - J-u-boot.git/blame - drivers/mmc/am654_sdhci.c
Merge patch series "xtensa: Enable qemu-xtensa board"
[J-u-boot.git] / drivers / mmc / am654_sdhci.c
CommitLineData
aaa449fb
LV
1// SPDX-License-Identifier: GPL-2.0+
2/*
a94a4071 3 * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/
aaa449fb
LV
4 *
5 * Texas Instruments' K3 SD Host Controller Interface
6 */
7
8#include <clk.h>
aaa449fb
LV
9#include <dm.h>
10#include <malloc.h>
a759abf5 11#include <mmc.h>
aaa449fb 12#include <power-domain.h>
ce142ff0 13#include <regmap.h>
aaa449fb 14#include <sdhci.h>
8c32b5f3 15#include <soc.h>
336d4615 16#include <dm/device_compat.h>
cd93d625 17#include <linux/bitops.h>
61b29b82 18#include <linux/err.h>
aaa449fb 19
ce142ff0
FA
20/* CTL_CFG Registers */
21#define CTL_CFG_2 0x14
22
23#define SLOTTYPE_MASK GENMASK(31, 30)
24#define SLOTTYPE_EMBEDDED BIT(30)
25
26/* PHY Registers */
27#define PHY_CTRL1 0x100
28#define PHY_CTRL2 0x104
29#define PHY_CTRL3 0x108
30#define PHY_CTRL4 0x10C
31#define PHY_CTRL5 0x110
32#define PHY_CTRL6 0x114
33#define PHY_STAT1 0x130
34#define PHY_STAT2 0x134
35
36#define IOMUX_ENABLE_SHIFT 31
37#define IOMUX_ENABLE_MASK BIT(IOMUX_ENABLE_SHIFT)
38#define OTAPDLYENA_SHIFT 20
39#define OTAPDLYENA_MASK BIT(OTAPDLYENA_SHIFT)
40#define OTAPDLYSEL_SHIFT 12
41#define OTAPDLYSEL_MASK GENMASK(15, 12)
42#define STRBSEL_SHIFT 24
a20008ea
FA
43#define STRBSEL_4BIT_MASK GENMASK(27, 24)
44#define STRBSEL_8BIT_MASK GENMASK(31, 24)
ce142ff0
FA
45#define SEL50_SHIFT 8
46#define SEL50_MASK BIT(SEL50_SHIFT)
47#define SEL100_SHIFT 9
48#define SEL100_MASK BIT(SEL100_SHIFT)
a20008ea
FA
49#define FREQSEL_SHIFT 8
50#define FREQSEL_MASK GENMASK(10, 8)
194c3756
FA
51#define CLKBUFSEL_SHIFT 0
52#define CLKBUFSEL_MASK GENMASK(2, 0)
ce142ff0
FA
53#define DLL_TRIM_ICP_SHIFT 4
54#define DLL_TRIM_ICP_MASK GENMASK(7, 4)
55#define DR_TY_SHIFT 20
56#define DR_TY_MASK GENMASK(22, 20)
57#define ENDLL_SHIFT 1
58#define ENDLL_MASK BIT(ENDLL_SHIFT)
59#define DLLRDY_SHIFT 0
60#define DLLRDY_MASK BIT(DLLRDY_SHIFT)
61#define PDB_SHIFT 0
62#define PDB_MASK BIT(PDB_SHIFT)
63#define CALDONE_SHIFT 1
64#define CALDONE_MASK BIT(CALDONE_SHIFT)
65#define RETRIM_SHIFT 17
66#define RETRIM_MASK BIT(RETRIM_SHIFT)
c964447e
FA
67#define SELDLYTXCLK_SHIFT 17
68#define SELDLYTXCLK_MASK BIT(SELDLYTXCLK_SHIFT)
69#define SELDLYRXCLK_SHIFT 16
70#define SELDLYRXCLK_MASK BIT(SELDLYRXCLK_SHIFT)
71#define ITAPDLYSEL_SHIFT 0
72#define ITAPDLYSEL_MASK GENMASK(4, 0)
73#define ITAPDLYENA_SHIFT 8
74#define ITAPDLYENA_MASK BIT(ITAPDLYENA_SHIFT)
75#define ITAPCHGWIN_SHIFT 9
76#define ITAPCHGWIN_MASK BIT(ITAPCHGWIN_SHIFT)
ce142ff0
FA
77
78#define DRIVER_STRENGTH_50_OHM 0x0
79#define DRIVER_STRENGTH_33_OHM 0x1
80#define DRIVER_STRENGTH_66_OHM 0x2
81#define DRIVER_STRENGTH_100_OHM 0x3
82#define DRIVER_STRENGTH_40_OHM 0x4
83
3a1a0dfc 84#define AM654_SDHCI_MIN_FREQ 400000
c964447e 85#define CLOCK_TOO_SLOW_HZ 50000000
aaa449fb 86
056af04a
JM
87#define ENABLE 0x1
88
3a1a0dfc 89struct am654_sdhci_plat {
aaa449fb
LV
90 struct mmc_config cfg;
91 struct mmc mmc;
ce142ff0
FA
92 struct regmap *base;
93 bool non_removable;
7d6f45a2 94 u32 otap_del_sel[MMC_MODES_END];
c964447e 95 u32 itap_del_sel[MMC_MODES_END];
056af04a 96 u32 itap_del_ena[MMC_MODES_END];
ce142ff0
FA
97 u32 trm_icp;
98 u32 drv_strength;
a20008ea 99 u32 strb_sel;
194c3756 100 u32 clkbuf_sel;
794453f9 101 u32 flags;
6b8dd9ca 102 bool dll_enable;
144e131d
FA
103#define DLL_PRESENT BIT(0)
104#define IOMUX_PRESENT BIT(1)
105#define FREQSEL_2_BIT BIT(2)
106#define STRBSEL_4_BIT BIT(3)
5b29fd4a 107#define DLL_CALIB BIT(4)
ce142ff0
FA
108};
109
c7d106b4 110struct timing_data {
c964447e
FA
111 const char *otap_binding;
112 const char *itap_binding;
c7d106b4
FA
113 u32 capability;
114};
115
6b8dd9ca
JM
116struct window {
117 u8 start;
118 u8 end;
119 u8 length;
120};
121
c7d106b4 122static const struct timing_data td[] = {
c964447e
FA
123 [MMC_LEGACY] = {"ti,otap-del-sel-legacy",
124 "ti,itap-del-sel-legacy",
125 0},
126 [MMC_HS] = {"ti,otap-del-sel-mmc-hs",
127 "ti,itap-del-sel-mms-hs",
128 MMC_CAP(MMC_HS)},
129 [SD_HS] = {"ti,otap-del-sel-sd-hs",
130 "ti,itap-del-sel-sd-hs",
131 MMC_CAP(SD_HS)},
132 [UHS_SDR12] = {"ti,otap-del-sel-sdr12",
133 "ti,itap-del-sel-sdr12",
134 MMC_CAP(UHS_SDR12)},
135 [UHS_SDR25] = {"ti,otap-del-sel-sdr25",
136 "ti,itap-del-sel-sdr25",
137 MMC_CAP(UHS_SDR25)},
138 [UHS_SDR50] = {"ti,otap-del-sel-sdr50",
139 NULL,
140 MMC_CAP(UHS_SDR50)},
141 [UHS_SDR104] = {"ti,otap-del-sel-sdr104",
142 NULL,
143 MMC_CAP(UHS_SDR104)},
144 [UHS_DDR50] = {"ti,otap-del-sel-ddr50",
145 NULL,
146 MMC_CAP(UHS_DDR50)},
147 [MMC_DDR_52] = {"ti,otap-del-sel-ddr52",
148 "ti,itap-del-sel-ddr52",
149 MMC_CAP(MMC_DDR_52)},
150 [MMC_HS_200] = {"ti,otap-del-sel-hs200",
151 NULL,
152 MMC_CAP(MMC_HS_200)},
153 [MMC_HS_400] = {"ti,otap-del-sel-hs400",
154 NULL,
155 MMC_CAP(MMC_HS_400)},
c7d106b4
FA
156};
157
a20008ea
FA
158struct am654_driver_data {
159 const struct sdhci_ops *ops;
160 u32 flags;
161};
162
c964447e
FA
163static int am654_sdhci_setup_dll(struct am654_sdhci_plat *plat,
164 unsigned int speed)
165{
166 int sel50, sel100, freqsel;
167 u32 mask, val;
168 int ret;
169
170 /* Disable delay chain mode */
171 regmap_update_bits(plat->base, PHY_CTRL5,
172 SELDLYTXCLK_MASK | SELDLYRXCLK_MASK, 0);
173
174 if (plat->flags & FREQSEL_2_BIT) {
175 switch (speed) {
176 case 200000000:
177 sel50 = 0;
178 sel100 = 0;
179 break;
180 case 100000000:
181 sel50 = 0;
182 sel100 = 1;
183 break;
184 default:
185 sel50 = 1;
186 sel100 = 0;
187 }
188
189 /* Configure PHY DLL frequency */
190 mask = SEL50_MASK | SEL100_MASK;
191 val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT);
192 regmap_update_bits(plat->base, PHY_CTRL5, mask, val);
193 } else {
194 switch (speed) {
195 case 200000000:
196 freqsel = 0x0;
197 break;
198 default:
199 freqsel = 0x4;
200 }
201 regmap_update_bits(plat->base, PHY_CTRL5, FREQSEL_MASK,
202 freqsel << FREQSEL_SHIFT);
203 }
204
205 /* Configure DLL TRIM */
206 mask = DLL_TRIM_ICP_MASK;
207 val = plat->trm_icp << DLL_TRIM_ICP_SHIFT;
208
209 /* Configure DLL driver strength */
210 mask |= DR_TY_MASK;
211 val |= plat->drv_strength << DR_TY_SHIFT;
212 regmap_update_bits(plat->base, PHY_CTRL1, mask, val);
213
214 /* Enable DLL */
215 regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK,
216 0x1 << ENDLL_SHIFT);
217 /*
218 * Poll for DLL ready. Use a one second timeout.
219 * Works in all experiments done so far
220 */
221 ret = regmap_read_poll_timeout(plat->base, PHY_STAT1, val,
222 val & DLLRDY_MASK, 1000, 1000000);
223
224 return ret;
225}
226
227static void am654_sdhci_write_itapdly(struct am654_sdhci_plat *plat,
056af04a 228 u32 itapdly, u32 enable)
c964447e 229{
056af04a
JM
230 regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYENA_MASK,
231 enable << ITAPDLYENA_SHIFT);
c964447e
FA
232 /* Set ITAPCHGWIN before writing to ITAPDLY */
233 regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK,
234 1 << ITAPCHGWIN_SHIFT);
235 regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYSEL_MASK,
236 itapdly << ITAPDLYSEL_SHIFT);
237 regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0);
238}
239
240static void am654_sdhci_setup_delay_chain(struct am654_sdhci_plat *plat,
241 int mode)
242{
243 u32 mask, val;
244
245 val = 1 << SELDLYTXCLK_SHIFT | 1 << SELDLYRXCLK_SHIFT;
246 mask = SELDLYTXCLK_MASK | SELDLYRXCLK_MASK;
247 regmap_update_bits(plat->base, PHY_CTRL5, mask, val);
248
056af04a
JM
249 am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode],
250 plat->itap_del_ena[mode]);
c964447e
FA
251}
252
ce142ff0
FA
253static int am654_sdhci_set_ios_post(struct sdhci_host *host)
254{
255 struct udevice *dev = host->mmc->dev;
c69cda25 256 struct am654_sdhci_plat *plat = dev_get_plat(dev);
ce142ff0 257 unsigned int speed = host->mmc->clock;
c964447e 258 int mode = host->mmc->selected_mode;
c7d106b4 259 u32 otap_del_sel;
ce142ff0
FA
260 u32 mask, val;
261 int ret;
262
263 /* Reset SD Clock Enable */
264 val = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
265 val &= ~SDHCI_CLOCK_CARD_EN;
266 sdhci_writew(host, val, SDHCI_CLOCK_CONTROL);
267
c604e204 268 regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK, 0);
ce142ff0
FA
269
270 /* restart clock */
271 sdhci_set_clock(host->mmc, speed);
272
273 /* switch phy back on */
c964447e
FA
274 otap_del_sel = plat->otap_del_sel[mode];
275 mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
276 val = (1 << OTAPDLYENA_SHIFT) |
277 (otap_del_sel << OTAPDLYSEL_SHIFT);
ce142ff0 278
c964447e
FA
279 /* Write to STRBSEL for HS400 speed mode */
280 if (host->mmc->selected_mode == MMC_HS_400) {
281 if (plat->flags & STRBSEL_4_BIT)
282 mask |= STRBSEL_4BIT_MASK;
283 else
284 mask |= STRBSEL_8BIT_MASK;
285
286 val |= plat->strb_sel << STRBSEL_SHIFT;
287 }
288
289 regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
ce142ff0 290
a124e31a 291 if ((mode > UHS_SDR25 || mode == MMC_DDR_52) && speed >= CLOCK_TOO_SLOW_HZ) {
c964447e 292 ret = am654_sdhci_setup_dll(plat, speed);
ce142ff0
FA
293 if (ret)
294 return ret;
6b8dd9ca
JM
295
296 plat->dll_enable = true;
f13a830e
JM
297 if (mode == MMC_HS_400) {
298 plat->itap_del_ena[mode] = ENABLE;
299 plat->itap_del_sel[mode] = plat->itap_del_sel[mode - 1];
300 }
301
a124e31a
JM
302 am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode],
303 plat->itap_del_ena[mode]);
c964447e
FA
304 } else {
305 am654_sdhci_setup_delay_chain(plat, mode);
6b8dd9ca 306 plat->dll_enable = false;
ce142ff0
FA
307 }
308
194c3756
FA
309 regmap_update_bits(plat->base, PHY_CTRL5, CLKBUFSEL_MASK,
310 plat->clkbuf_sel);
311
ce142ff0
FA
312 return 0;
313}
314
ce142ff0
FA
315int am654_sdhci_init(struct am654_sdhci_plat *plat)
316{
317 u32 ctl_cfg_2 = 0;
318 u32 mask, val;
319 int ret;
320
321 /* Reset OTAP to default value */
322 mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
323 regmap_update_bits(plat->base, PHY_CTRL4, mask, 0x0);
324
5b29fd4a 325 if (plat->flags & DLL_CALIB) {
794453f9
FA
326 regmap_read(plat->base, PHY_STAT1, &val);
327 if (~val & CALDONE_MASK) {
328 /* Calibrate IO lines */
329 regmap_update_bits(plat->base, PHY_CTRL1, PDB_MASK,
330 PDB_MASK);
331 ret = regmap_read_poll_timeout(plat->base, PHY_STAT1,
332 val, val & CALDONE_MASK,
333 1, 20);
334 if (ret)
335 return ret;
336 }
794453f9 337 }
ce142ff0
FA
338
339 /* Enable pins by setting IO mux to 0 */
a20008ea
FA
340 if (plat->flags & IOMUX_PRESENT)
341 regmap_update_bits(plat->base, PHY_CTRL1, IOMUX_ENABLE_MASK, 0);
ce142ff0
FA
342
343 /* Set slot type based on SD or eMMC */
344 if (plat->non_removable)
345 ctl_cfg_2 = SLOTTYPE_EMBEDDED;
346
347 regmap_update_bits(plat->base, CTL_CFG_2, SLOTTYPE_MASK, ctl_cfg_2);
348
349 return 0;
350}
351
a8512139
FA
352#define MAX_SDCD_DEBOUNCE_TIME 2000
353static int am654_sdhci_deferred_probe(struct sdhci_host *host)
354{
355 struct udevice *dev = host->mmc->dev;
c69cda25 356 struct am654_sdhci_plat *plat = dev_get_plat(dev);
a8512139
FA
357 unsigned long start;
358 int val;
359
360 /*
361 * The controller takes about 1 second to debounce the card detect line
362 * and doesn't let us power on until that time is up. Instead of waiting
363 * for 1 second at every stage, poll on the CARD_PRESENT bit upto a
364 * maximum of 2 seconds to be safe..
365 */
366 start = get_timer(0);
367 do {
368 if (get_timer(start) > MAX_SDCD_DEBOUNCE_TIME)
369 return -ENOMEDIUM;
370
371 val = mmc_getcd(host->mmc);
372 } while (!val);
373
374 am654_sdhci_init(plat);
375
376 return sdhci_probe(dev);
377}
378
27a87c83
FA
379static void am654_sdhci_write_b(struct sdhci_host *host, u8 val, int reg)
380{
381 if (reg == SDHCI_HOST_CONTROL) {
382 switch (host->mmc->selected_mode) {
383 /*
384 * According to the data manual, HISPD bit
385 * should not be set in these speed modes.
386 */
387 case SD_HS:
388 case MMC_HS:
389 case UHS_SDR12:
390 case UHS_SDR25:
391 val &= ~SDHCI_CTRL_HISPD;
392 default:
393 break;
394 }
395 }
396
397 writeb(val, host->ioaddr + reg);
398}
03de305e 399#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
6b8dd9ca
JM
400#define ITAPDLY_LENGTH 32
401#define ITAPDLY_LAST_INDEX (ITAPDLY_LENGTH - 1)
402
403static u32 am654_sdhci_calculate_itap(struct udevice *dev, struct window
404 *fail_window, u8 num_fails, bool circular_buffer)
405{
406 u8 itap = 0, start_fail = 0, end_fail = 0, pass_length = 0;
407 u8 first_fail_start = 0, last_fail_end = 0;
408 struct window pass_window = {0, 0, 0};
409 int prev_fail_end = -1;
410 u8 i;
411
412 if (!num_fails)
413 return ITAPDLY_LAST_INDEX >> 1;
414
415 if (fail_window->length == ITAPDLY_LENGTH) {
416 dev_err(dev, "No passing ITAPDLY, return 0\n");
417 return 0;
418 }
419
420 first_fail_start = fail_window->start;
421 last_fail_end = fail_window[num_fails - 1].end;
422
423 for (i = 0; i < num_fails; i++) {
424 start_fail = fail_window[i].start;
425 end_fail = fail_window[i].end;
426 pass_length = start_fail - (prev_fail_end + 1);
427
428 if (pass_length > pass_window.length) {
429 pass_window.start = prev_fail_end + 1;
430 pass_window.length = pass_length;
431 }
432 prev_fail_end = end_fail;
433 }
434
435 if (!circular_buffer)
436 pass_length = ITAPDLY_LAST_INDEX - last_fail_end;
437 else
438 pass_length = ITAPDLY_LAST_INDEX - last_fail_end + first_fail_start;
439
440 if (pass_length > pass_window.length) {
441 pass_window.start = last_fail_end + 1;
442 pass_window.length = pass_length;
443 }
444
445 if (!circular_buffer)
446 itap = pass_window.start + (pass_window.length >> 1);
447 else
448 itap = (pass_window.start + (pass_window.length >> 1)) % ITAPDLY_LENGTH;
449
450 return (itap > ITAPDLY_LAST_INDEX) ? ITAPDLY_LAST_INDEX >> 1 : itap;
451}
452
a759abf5
FA
453static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
454{
455 struct udevice *dev = mmc->dev;
456 struct am654_sdhci_plat *plat = dev_get_plat(dev);
6b8dd9ca 457 struct window fail_window[ITAPDLY_LENGTH];
056af04a 458 int mode = mmc->selected_mode;
6b8dd9ca
JM
459 u8 curr_pass, itap;
460 u8 fail_index = 0;
461 u8 prev_pass = 1;
462
463 memset(fail_window, 0, sizeof(fail_window));
a759abf5
FA
464
465 /* Enable ITAPDLY */
056af04a 466 plat->itap_del_ena[mode] = ENABLE;
a759abf5 467
6b8dd9ca 468 for (itap = 0; itap < ITAPDLY_LENGTH; itap++) {
056af04a 469 am654_sdhci_write_itapdly(plat, itap, plat->itap_del_ena[mode]);
a759abf5 470
6b8dd9ca
JM
471 curr_pass = !mmc_send_tuning(mmc, opcode);
472
473 if (!curr_pass && prev_pass)
474 fail_window[fail_index].start = itap;
a759abf5 475
6b8dd9ca
JM
476 if (!curr_pass) {
477 fail_window[fail_index].end = itap;
478 fail_window[fail_index].length++;
479 }
a759abf5 480
6b8dd9ca
JM
481 if (curr_pass && !prev_pass)
482 fail_index++;
483
484 prev_pass = curr_pass;
a759abf5 485 }
6b8dd9ca
JM
486
487 if (fail_window[fail_index].length != 0)
488 fail_index++;
489
490 itap = am654_sdhci_calculate_itap(dev, fail_window, fail_index,
491 plat->dll_enable);
492
f13a830e
JM
493 /* Save ITAPDLY */
494 plat->itap_del_sel[mode] = itap;
495
056af04a 496 am654_sdhci_write_itapdly(plat, itap, plat->itap_del_ena[mode]);
a759abf5
FA
497
498 return 0;
499}
500#endif
a8512139 501const struct sdhci_ops am654_sdhci_ops = {
03de305e 502#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
a759abf5
FA
503 .platform_execute_tuning = am654_sdhci_execute_tuning,
504#endif
a8512139
FA
505 .deferred_probe = am654_sdhci_deferred_probe,
506 .set_ios_post = &am654_sdhci_set_ios_post,
e9fbbba4 507 .set_control_reg = sdhci_set_control_reg,
27a87c83 508 .write_b = am654_sdhci_write_b,
a8512139
FA
509};
510
511const struct am654_driver_data am654_drv_data = {
8c32b5f3
FA
512 .ops = &am654_sdhci_ops,
513 .flags = DLL_PRESENT | IOMUX_PRESENT | FREQSEL_2_BIT | STRBSEL_4_BIT,
514};
515
516const struct am654_driver_data am654_sr1_drv_data = {
a8512139 517 .ops = &am654_sdhci_ops,
5b29fd4a
FA
518 .flags = IOMUX_PRESENT | FREQSEL_2_BIT | DLL_PRESENT | DLL_CALIB |
519 STRBSEL_4_BIT,
a8512139
FA
520};
521
522const struct am654_driver_data j721e_8bit_drv_data = {
523 .ops = &am654_sdhci_ops,
5b29fd4a 524 .flags = DLL_PRESENT | DLL_CALIB,
a8512139
FA
525};
526
527static int j721e_4bit_sdhci_set_ios_post(struct sdhci_host *host)
528{
529 struct udevice *dev = host->mmc->dev;
c69cda25 530 struct am654_sdhci_plat *plat = dev_get_plat(dev);
5048b5c6
NY
531 int mode = host->mmc->selected_mode;
532 u32 otap_del_sel;
056af04a 533 u32 itap_del_ena;
5048b5c6
NY
534 u32 itap_del_sel;
535 u32 mask, val;
536
537 otap_del_sel = plat->otap_del_sel[mode];
a8512139 538
a8512139 539 mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
5048b5c6
NY
540 val = (1 << OTAPDLYENA_SHIFT) |
541 (otap_del_sel << OTAPDLYSEL_SHIFT);
542
056af04a 543 itap_del_ena = plat->itap_del_ena[mode];
5048b5c6
NY
544 itap_del_sel = plat->itap_del_sel[mode];
545
546 mask |= ITAPDLYENA_MASK | ITAPDLYSEL_MASK;
056af04a 547 val |= (itap_del_ena << ITAPDLYENA_SHIFT) |
5048b5c6
NY
548 (itap_del_sel << ITAPDLYSEL_SHIFT);
549
550 regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK,
551 1 << ITAPCHGWIN_SHIFT);
a8512139 552 regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
5048b5c6 553 regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0);
a8512139 554
194c3756
FA
555 regmap_update_bits(plat->base, PHY_CTRL5, CLKBUFSEL_MASK,
556 plat->clkbuf_sel);
557
a8512139
FA
558 return 0;
559}
560
561const struct sdhci_ops j721e_4bit_sdhci_ops = {
03de305e 562#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING)
a759abf5
FA
563 .platform_execute_tuning = am654_sdhci_execute_tuning,
564#endif
a8512139
FA
565 .deferred_probe = am654_sdhci_deferred_probe,
566 .set_ios_post = &j721e_4bit_sdhci_set_ios_post,
e9fbbba4 567 .set_control_reg = sdhci_set_control_reg,
27a87c83 568 .write_b = am654_sdhci_write_b,
a8512139
FA
569};
570
571const struct am654_driver_data j721e_4bit_drv_data = {
572 .ops = &j721e_4bit_sdhci_ops,
573 .flags = IOMUX_PRESENT,
574};
575
7288beaa
DG
576static const struct am654_driver_data sdhci_am64_8bit_drvdata = {
577 .ops = &am654_sdhci_ops,
578 .flags = DLL_PRESENT | DLL_CALIB,
579};
580
581static const struct am654_driver_data sdhci_am64_4bit_drvdata = {
582 .ops = &j721e_4bit_sdhci_ops,
583 .flags = IOMUX_PRESENT,
584};
585
8c32b5f3
FA
586const struct soc_attr am654_sdhci_soc_attr[] = {
587 { .family = "AM65X", .revision = "SR1.0", .data = &am654_sr1_drv_data},
588 {/* sentinel */}
589};
590
c7d106b4
FA
591static int sdhci_am654_get_otap_delay(struct udevice *dev,
592 struct mmc_config *cfg)
593{
c69cda25 594 struct am654_sdhci_plat *plat = dev_get_plat(dev);
c7d106b4
FA
595 int ret;
596 int i;
597
598 /* ti,otap-del-sel-legacy is mandatory */
599 ret = dev_read_u32(dev, "ti,otap-del-sel-legacy",
600 &plat->otap_del_sel[0]);
601 if (ret)
602 return ret;
603 /*
604 * Remove the corresponding capability if an otap-del-sel
605 * value is not found
606 */
5048b5c6 607 for (i = MMC_LEGACY; i <= MMC_HS_400; i++) {
c964447e
FA
608 ret = dev_read_u32(dev, td[i].otap_binding,
609 &plat->otap_del_sel[i]);
c7d106b4 610 if (ret) {
c964447e 611 dev_dbg(dev, "Couldn't find %s\n", td[i].otap_binding);
c7d106b4
FA
612 /*
613 * Remove the corresponding capability
614 * if an otap-del-sel value is not found
615 */
616 cfg->host_caps &= ~td[i].capability;
617 }
c964447e 618
056af04a
JM
619 if (td[i].itap_binding) {
620 ret = dev_read_u32(dev, td[i].itap_binding,
621 &plat->itap_del_sel[i]);
622
623 if (!ret)
624 plat->itap_del_ena[i] = ENABLE;
625 }
c7d106b4
FA
626 }
627
628 return 0;
629}
630
3a1a0dfc 631static int am654_sdhci_probe(struct udevice *dev)
aaa449fb 632{
a20008ea
FA
633 struct am654_driver_data *drv_data =
634 (struct am654_driver_data *)dev_get_driver_data(dev);
c69cda25 635 struct am654_sdhci_plat *plat = dev_get_plat(dev);
aaa449fb
LV
636 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
637 struct sdhci_host *host = dev_get_priv(dev);
ce142ff0 638 struct mmc_config *cfg = &plat->cfg;
8c32b5f3
FA
639 const struct soc_attr *soc;
640 const struct am654_driver_data *soc_drv_data;
aaa449fb
LV
641 struct clk clk;
642 unsigned long clock;
643 int ret;
644
fe0e30c7 645 ret = clk_get_by_name(dev, "clk_xin", &clk);
aaa449fb
LV
646 if (ret) {
647 dev_err(dev, "failed to get clock\n");
648 return ret;
649 }
650
651 clock = clk_get_rate(&clk);
652 if (IS_ERR_VALUE(clock)) {
653 dev_err(dev, "failed to get rate\n");
654 return clock;
655 }
656
aaa449fb 657 host->max_clk = clock;
aaa449fb 658 host->mmc = &plat->mmc;
ce142ff0 659 host->mmc->dev = dev;
27a87c83 660 host->ops = drv_data->ops;
ce142ff0
FA
661 ret = sdhci_setup_cfg(cfg, host, cfg->f_max,
662 AM654_SDHCI_MIN_FREQ);
aaa449fb
LV
663 if (ret)
664 return ret;
a20008ea 665
c7d106b4
FA
666 ret = sdhci_am654_get_otap_delay(dev, cfg);
667 if (ret)
668 return ret;
669
8c32b5f3
FA
670 /* Update ops based on SoC revision */
671 soc = soc_device_match(am654_sdhci_soc_attr);
672 if (soc && soc->data) {
673 soc_drv_data = soc->data;
674 host->ops = soc_drv_data->ops;
675 }
676
aaa449fb 677 host->mmc->priv = host;
aaa449fb
LV
678 upriv->mmc = host->mmc;
679
ce142ff0
FA
680 regmap_init_mem_index(dev_ofnode(dev), &plat->base, 1);
681
a8512139 682 return 0;
aaa449fb
LV
683}
684
d1998a9f 685static int am654_sdhci_of_to_plat(struct udevice *dev)
aaa449fb 686{
c69cda25 687 struct am654_sdhci_plat *plat = dev_get_plat(dev);
aaa449fb 688 struct sdhci_host *host = dev_get_priv(dev);
ce142ff0
FA
689 struct mmc_config *cfg = &plat->cfg;
690 u32 drv_strength;
691 int ret;
aaa449fb
LV
692
693 host->name = dev->name;
a12a73b6 694 host->ioaddr = dev_read_addr_ptr(dev);
ce142ff0
FA
695 plat->non_removable = dev_read_bool(dev, "non-removable");
696
794453f9
FA
697 if (plat->flags & DLL_PRESENT) {
698 ret = dev_read_u32(dev, "ti,trm-icp", &plat->trm_icp);
699 if (ret)
700 return ret;
701
702 ret = dev_read_u32(dev, "ti,driver-strength-ohm",
703 &drv_strength);
704 if (ret)
705 return ret;
ce142ff0 706
794453f9
FA
707 switch (drv_strength) {
708 case 50:
709 plat->drv_strength = DRIVER_STRENGTH_50_OHM;
710 break;
711 case 33:
712 plat->drv_strength = DRIVER_STRENGTH_33_OHM;
713 break;
714 case 66:
715 plat->drv_strength = DRIVER_STRENGTH_66_OHM;
716 break;
717 case 100:
718 plat->drv_strength = DRIVER_STRENGTH_100_OHM;
719 break;
720 case 40:
721 plat->drv_strength = DRIVER_STRENGTH_40_OHM;
722 break;
723 default:
724 dev_err(dev, "Invalid driver strength\n");
725 return -EINVAL;
726 }
ce142ff0
FA
727 }
728
46077ef2 729 dev_read_u32(dev, "ti,strobe-sel", &plat->strb_sel);
194c3756
FA
730 dev_read_u32(dev, "ti,clkbuf-sel", &plat->clkbuf_sel);
731
ce142ff0
FA
732 ret = mmc_of_parse(dev, cfg);
733 if (ret)
734 return ret;
aaa449fb
LV
735
736 return 0;
737}
738
3a1a0dfc 739static int am654_sdhci_bind(struct udevice *dev)
aaa449fb 740{
a20008ea
FA
741 struct am654_driver_data *drv_data =
742 (struct am654_driver_data *)dev_get_driver_data(dev);
c69cda25 743 struct am654_sdhci_plat *plat = dev_get_plat(dev);
8c32b5f3
FA
744 const struct soc_attr *soc;
745 const struct am654_driver_data *soc_drv_data;
aaa449fb 746
a20008ea
FA
747 plat->flags = drv_data->flags;
748
8c32b5f3
FA
749 /* Update flags based on SoC revision */
750 soc = soc_device_match(am654_sdhci_soc_attr);
751 if (soc && soc->data) {
752 soc_drv_data = soc->data;
753 plat->flags = soc_drv_data->flags;
754 }
755
aaa449fb
LV
756 return sdhci_bind(dev, &plat->mmc, &plat->cfg);
757}
758
3a1a0dfc 759static const struct udevice_id am654_sdhci_ids[] = {
794453f9
FA
760 {
761 .compatible = "ti,am654-sdhci-5.1",
a20008ea 762 .data = (ulong)&am654_drv_data,
794453f9
FA
763 },
764 {
765 .compatible = "ti,j721e-sdhci-8bit",
a20008ea 766 .data = (ulong)&j721e_8bit_drv_data,
794453f9
FA
767 },
768 {
769 .compatible = "ti,j721e-sdhci-4bit",
a20008ea 770 .data = (ulong)&j721e_4bit_drv_data,
794453f9 771 },
7288beaa
DG
772 {
773 .compatible = "ti,am64-sdhci-8bit",
774 .data = (ulong)&sdhci_am64_8bit_drvdata,
775 },
776 {
777 .compatible = "ti,am64-sdhci-4bit",
778 .data = (ulong)&sdhci_am64_4bit_drvdata,
779 },
ed6d7814
AG
780 {
781 .compatible = "ti,am62-sdhci",
782 .data = (ulong)&sdhci_am64_4bit_drvdata,
783 },
aaa449fb
LV
784 { }
785};
786
3a1a0dfc
FA
787U_BOOT_DRIVER(am654_sdhci_drv) = {
788 .name = "am654_sdhci",
aaa449fb 789 .id = UCLASS_MMC,
3a1a0dfc 790 .of_match = am654_sdhci_ids,
d1998a9f 791 .of_to_plat = am654_sdhci_of_to_plat,
aaa449fb 792 .ops = &sdhci_ops,
3a1a0dfc
FA
793 .bind = am654_sdhci_bind,
794 .probe = am654_sdhci_probe,
41575d8e 795 .priv_auto = sizeof(struct sdhci_host),
caa4daa2 796 .plat_auto = sizeof(struct am654_sdhci_plat),
aaa449fb 797};
This page took 0.255986 seconds and 4 git commands to generate.