blob: becb35508994da0359ba2df60da57d042b19e17d [file] [log] [blame]
Lokesh Vutlabc9979f2018-08-27 15:57:54 +05301// SPDX-License-Identifier: GPL-2.0+
2/*
Nishanth Menoneaa39c62023-11-01 15:56:03 -05003 * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/
Lokesh Vutlabc9979f2018-08-27 15:57:54 +05304 *
5 * Texas Instruments' K3 SD Host Controller Interface
6 */
7
8#include <clk.h>
9#include <common.h>
10#include <dm.h>
11#include <malloc.h>
Faiz Abbas7a7e2c72021-02-04 15:10:53 +053012#include <mmc.h>
Lokesh Vutlabc9979f2018-08-27 15:57:54 +053013#include <power-domain.h>
Faiz Abbase9aed582019-06-11 00:43:38 +053014#include <regmap.h>
Lokesh Vutlabc9979f2018-08-27 15:57:54 +053015#include <sdhci.h>
Faiz Abbas2c2fc962021-02-04 15:10:50 +053016#include <soc.h>
Simon Glass9bc15642020-02-03 07:36:16 -070017#include <dm/device_compat.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060018#include <linux/bitops.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070019#include <linux/err.h>
Lokesh Vutlabc9979f2018-08-27 15:57:54 +053020
Faiz Abbase9aed582019-06-11 00:43:38 +053021/* CTL_CFG Registers */
22#define CTL_CFG_2 0x14
23
24#define SLOTTYPE_MASK GENMASK(31, 30)
25#define SLOTTYPE_EMBEDDED BIT(30)
26
27/* PHY Registers */
28#define PHY_CTRL1 0x100
29#define PHY_CTRL2 0x104
30#define PHY_CTRL3 0x108
31#define PHY_CTRL4 0x10C
32#define PHY_CTRL5 0x110
33#define PHY_CTRL6 0x114
34#define PHY_STAT1 0x130
35#define PHY_STAT2 0x134
36
37#define IOMUX_ENABLE_SHIFT 31
38#define IOMUX_ENABLE_MASK BIT(IOMUX_ENABLE_SHIFT)
39#define OTAPDLYENA_SHIFT 20
40#define OTAPDLYENA_MASK BIT(OTAPDLYENA_SHIFT)
41#define OTAPDLYSEL_SHIFT 12
42#define OTAPDLYSEL_MASK GENMASK(15, 12)
43#define STRBSEL_SHIFT 24
Faiz Abbas8cc051e2020-01-16 19:42:19 +053044#define STRBSEL_4BIT_MASK GENMASK(27, 24)
45#define STRBSEL_8BIT_MASK GENMASK(31, 24)
Faiz Abbase9aed582019-06-11 00:43:38 +053046#define SEL50_SHIFT 8
47#define SEL50_MASK BIT(SEL50_SHIFT)
48#define SEL100_SHIFT 9
49#define SEL100_MASK BIT(SEL100_SHIFT)
Faiz Abbas8cc051e2020-01-16 19:42:19 +053050#define FREQSEL_SHIFT 8
51#define FREQSEL_MASK GENMASK(10, 8)
Faiz Abbasc73f04e2021-02-04 15:10:52 +053052#define CLKBUFSEL_SHIFT 0
53#define CLKBUFSEL_MASK GENMASK(2, 0)
Faiz Abbase9aed582019-06-11 00:43:38 +053054#define DLL_TRIM_ICP_SHIFT 4
55#define DLL_TRIM_ICP_MASK GENMASK(7, 4)
56#define DR_TY_SHIFT 20
57#define DR_TY_MASK GENMASK(22, 20)
58#define ENDLL_SHIFT 1
59#define ENDLL_MASK BIT(ENDLL_SHIFT)
60#define DLLRDY_SHIFT 0
61#define DLLRDY_MASK BIT(DLLRDY_SHIFT)
62#define PDB_SHIFT 0
63#define PDB_MASK BIT(PDB_SHIFT)
64#define CALDONE_SHIFT 1
65#define CALDONE_MASK BIT(CALDONE_SHIFT)
66#define RETRIM_SHIFT 17
67#define RETRIM_MASK BIT(RETRIM_SHIFT)
Faiz Abbasdef2a0f2021-02-04 15:10:51 +053068#define SELDLYTXCLK_SHIFT 17
69#define SELDLYTXCLK_MASK BIT(SELDLYTXCLK_SHIFT)
70#define SELDLYRXCLK_SHIFT 16
71#define SELDLYRXCLK_MASK BIT(SELDLYRXCLK_SHIFT)
72#define ITAPDLYSEL_SHIFT 0
73#define ITAPDLYSEL_MASK GENMASK(4, 0)
74#define ITAPDLYENA_SHIFT 8
75#define ITAPDLYENA_MASK BIT(ITAPDLYENA_SHIFT)
76#define ITAPCHGWIN_SHIFT 9
77#define ITAPCHGWIN_MASK BIT(ITAPCHGWIN_SHIFT)
Faiz Abbase9aed582019-06-11 00:43:38 +053078
79#define DRIVER_STRENGTH_50_OHM 0x0
80#define DRIVER_STRENGTH_33_OHM 0x1
81#define DRIVER_STRENGTH_66_OHM 0x2
82#define DRIVER_STRENGTH_100_OHM 0x3
83#define DRIVER_STRENGTH_40_OHM 0x4
84
Faiz Abbasd8fb3092019-06-11 00:43:31 +053085#define AM654_SDHCI_MIN_FREQ 400000
Faiz Abbasdef2a0f2021-02-04 15:10:51 +053086#define CLOCK_TOO_SLOW_HZ 50000000
Lokesh Vutlabc9979f2018-08-27 15:57:54 +053087
Faiz Abbasd8fb3092019-06-11 00:43:31 +053088struct am654_sdhci_plat {
Lokesh Vutlabc9979f2018-08-27 15:57:54 +053089 struct mmc_config cfg;
90 struct mmc mmc;
Faiz Abbase9aed582019-06-11 00:43:38 +053091 struct regmap *base;
92 bool non_removable;
Faiz Abbas7101e122020-07-29 07:03:41 +053093 u32 otap_del_sel[MMC_MODES_END];
Faiz Abbasdef2a0f2021-02-04 15:10:51 +053094 u32 itap_del_sel[MMC_MODES_END];
Faiz Abbase9aed582019-06-11 00:43:38 +053095 u32 trm_icp;
96 u32 drv_strength;
Faiz Abbas8cc051e2020-01-16 19:42:19 +053097 u32 strb_sel;
Faiz Abbasc73f04e2021-02-04 15:10:52 +053098 u32 clkbuf_sel;
Faiz Abbasfd8be702019-06-13 10:29:51 +053099 u32 flags;
Judith Mendez81c1d442024-04-18 14:00:56 -0500100 bool dll_enable;
Faiz Abbasb7f57bb2021-02-04 15:10:48 +0530101#define DLL_PRESENT BIT(0)
102#define IOMUX_PRESENT BIT(1)
103#define FREQSEL_2_BIT BIT(2)
104#define STRBSEL_4_BIT BIT(3)
Faiz Abbas947e8f32021-02-04 15:10:49 +0530105#define DLL_CALIB BIT(4)
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530106};
107
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530108struct timing_data {
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530109 const char *otap_binding;
110 const char *itap_binding;
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530111 u32 capability;
112};
113
Judith Mendez81c1d442024-04-18 14:00:56 -0500114struct window {
115 u8 start;
116 u8 end;
117 u8 length;
118};
119
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530120static const struct timing_data td[] = {
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530121 [MMC_LEGACY] = {"ti,otap-del-sel-legacy",
122 "ti,itap-del-sel-legacy",
123 0},
124 [MMC_HS] = {"ti,otap-del-sel-mmc-hs",
125 "ti,itap-del-sel-mms-hs",
126 MMC_CAP(MMC_HS)},
127 [SD_HS] = {"ti,otap-del-sel-sd-hs",
128 "ti,itap-del-sel-sd-hs",
129 MMC_CAP(SD_HS)},
130 [UHS_SDR12] = {"ti,otap-del-sel-sdr12",
131 "ti,itap-del-sel-sdr12",
132 MMC_CAP(UHS_SDR12)},
133 [UHS_SDR25] = {"ti,otap-del-sel-sdr25",
134 "ti,itap-del-sel-sdr25",
135 MMC_CAP(UHS_SDR25)},
136 [UHS_SDR50] = {"ti,otap-del-sel-sdr50",
137 NULL,
138 MMC_CAP(UHS_SDR50)},
139 [UHS_SDR104] = {"ti,otap-del-sel-sdr104",
140 NULL,
141 MMC_CAP(UHS_SDR104)},
142 [UHS_DDR50] = {"ti,otap-del-sel-ddr50",
143 NULL,
144 MMC_CAP(UHS_DDR50)},
145 [MMC_DDR_52] = {"ti,otap-del-sel-ddr52",
146 "ti,itap-del-sel-ddr52",
147 MMC_CAP(MMC_DDR_52)},
148 [MMC_HS_200] = {"ti,otap-del-sel-hs200",
149 NULL,
150 MMC_CAP(MMC_HS_200)},
151 [MMC_HS_400] = {"ti,otap-del-sel-hs400",
152 NULL,
153 MMC_CAP(MMC_HS_400)},
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530154};
155
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530156struct am654_driver_data {
157 const struct sdhci_ops *ops;
158 u32 flags;
159};
160
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530161static int am654_sdhci_setup_dll(struct am654_sdhci_plat *plat,
162 unsigned int speed)
163{
164 int sel50, sel100, freqsel;
165 u32 mask, val;
166 int ret;
167
168 /* Disable delay chain mode */
169 regmap_update_bits(plat->base, PHY_CTRL5,
170 SELDLYTXCLK_MASK | SELDLYRXCLK_MASK, 0);
171
172 if (plat->flags & FREQSEL_2_BIT) {
173 switch (speed) {
174 case 200000000:
175 sel50 = 0;
176 sel100 = 0;
177 break;
178 case 100000000:
179 sel50 = 0;
180 sel100 = 1;
181 break;
182 default:
183 sel50 = 1;
184 sel100 = 0;
185 }
186
187 /* Configure PHY DLL frequency */
188 mask = SEL50_MASK | SEL100_MASK;
189 val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT);
190 regmap_update_bits(plat->base, PHY_CTRL5, mask, val);
191 } else {
192 switch (speed) {
193 case 200000000:
194 freqsel = 0x0;
195 break;
196 default:
197 freqsel = 0x4;
198 }
199 regmap_update_bits(plat->base, PHY_CTRL5, FREQSEL_MASK,
200 freqsel << FREQSEL_SHIFT);
201 }
202
203 /* Configure DLL TRIM */
204 mask = DLL_TRIM_ICP_MASK;
205 val = plat->trm_icp << DLL_TRIM_ICP_SHIFT;
206
207 /* Configure DLL driver strength */
208 mask |= DR_TY_MASK;
209 val |= plat->drv_strength << DR_TY_SHIFT;
210 regmap_update_bits(plat->base, PHY_CTRL1, mask, val);
211
212 /* Enable DLL */
213 regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK,
214 0x1 << ENDLL_SHIFT);
215 /*
216 * Poll for DLL ready. Use a one second timeout.
217 * Works in all experiments done so far
218 */
219 ret = regmap_read_poll_timeout(plat->base, PHY_STAT1, val,
220 val & DLLRDY_MASK, 1000, 1000000);
221
222 return ret;
223}
224
225static void am654_sdhci_write_itapdly(struct am654_sdhci_plat *plat,
226 u32 itapdly)
227{
228 /* Set ITAPCHGWIN before writing to ITAPDLY */
229 regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK,
230 1 << ITAPCHGWIN_SHIFT);
231 regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYSEL_MASK,
232 itapdly << ITAPDLYSEL_SHIFT);
233 regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0);
234}
235
236static void am654_sdhci_setup_delay_chain(struct am654_sdhci_plat *plat,
237 int mode)
238{
239 u32 mask, val;
240
241 val = 1 << SELDLYTXCLK_SHIFT | 1 << SELDLYRXCLK_SHIFT;
242 mask = SELDLYTXCLK_MASK | SELDLYRXCLK_MASK;
243 regmap_update_bits(plat->base, PHY_CTRL5, mask, val);
244
245 am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode]);
246}
247
Faiz Abbase9aed582019-06-11 00:43:38 +0530248static int am654_sdhci_set_ios_post(struct sdhci_host *host)
249{
250 struct udevice *dev = host->mmc->dev;
Simon Glassfa20e932020-12-03 16:55:20 -0700251 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Faiz Abbase9aed582019-06-11 00:43:38 +0530252 unsigned int speed = host->mmc->clock;
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530253 int mode = host->mmc->selected_mode;
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530254 u32 otap_del_sel;
Faiz Abbase9aed582019-06-11 00:43:38 +0530255 u32 mask, val;
256 int ret;
257
258 /* Reset SD Clock Enable */
259 val = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
260 val &= ~SDHCI_CLOCK_CARD_EN;
261 sdhci_writew(host, val, SDHCI_CLOCK_CONTROL);
262
Faiz Abbas2c45a2c2021-02-04 15:10:47 +0530263 regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK, 0);
Faiz Abbase9aed582019-06-11 00:43:38 +0530264
265 /* restart clock */
266 sdhci_set_clock(host->mmc, speed);
267
268 /* switch phy back on */
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530269 otap_del_sel = plat->otap_del_sel[mode];
270 mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
271 val = (1 << OTAPDLYENA_SHIFT) |
272 (otap_del_sel << OTAPDLYSEL_SHIFT);
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530273
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530274 /* Write to STRBSEL for HS400 speed mode */
275 if (host->mmc->selected_mode == MMC_HS_400) {
276 if (plat->flags & STRBSEL_4_BIT)
277 mask |= STRBSEL_4BIT_MASK;
278 else
279 mask |= STRBSEL_8BIT_MASK;
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530280
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530281 val |= plat->strb_sel << STRBSEL_SHIFT;
282 }
Faiz Abbas947e8f32021-02-04 15:10:49 +0530283
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530284 regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
Faiz Abbas947e8f32021-02-04 15:10:49 +0530285
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530286 if (mode > UHS_SDR25 && speed >= CLOCK_TOO_SLOW_HZ) {
287 ret = am654_sdhci_setup_dll(plat, speed);
Faiz Abbase9aed582019-06-11 00:43:38 +0530288 if (ret)
289 return ret;
Judith Mendez81c1d442024-04-18 14:00:56 -0500290
291 plat->dll_enable = true;
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530292 } else {
293 am654_sdhci_setup_delay_chain(plat, mode);
Judith Mendez81c1d442024-04-18 14:00:56 -0500294 plat->dll_enable = false;
Faiz Abbase9aed582019-06-11 00:43:38 +0530295 }
296
Faiz Abbasc73f04e2021-02-04 15:10:52 +0530297 regmap_update_bits(plat->base, PHY_CTRL5, CLKBUFSEL_MASK,
298 plat->clkbuf_sel);
299
Faiz Abbase9aed582019-06-11 00:43:38 +0530300 return 0;
301}
302
Faiz Abbase9aed582019-06-11 00:43:38 +0530303int am654_sdhci_init(struct am654_sdhci_plat *plat)
304{
305 u32 ctl_cfg_2 = 0;
306 u32 mask, val;
307 int ret;
308
309 /* Reset OTAP to default value */
310 mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
311 regmap_update_bits(plat->base, PHY_CTRL4, mask, 0x0);
312
Faiz Abbas947e8f32021-02-04 15:10:49 +0530313 if (plat->flags & DLL_CALIB) {
Faiz Abbasfd8be702019-06-13 10:29:51 +0530314 regmap_read(plat->base, PHY_STAT1, &val);
315 if (~val & CALDONE_MASK) {
316 /* Calibrate IO lines */
317 regmap_update_bits(plat->base, PHY_CTRL1, PDB_MASK,
318 PDB_MASK);
319 ret = regmap_read_poll_timeout(plat->base, PHY_STAT1,
320 val, val & CALDONE_MASK,
321 1, 20);
322 if (ret)
323 return ret;
324 }
Faiz Abbasfd8be702019-06-13 10:29:51 +0530325 }
Faiz Abbase9aed582019-06-11 00:43:38 +0530326
327 /* Enable pins by setting IO mux to 0 */
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530328 if (plat->flags & IOMUX_PRESENT)
329 regmap_update_bits(plat->base, PHY_CTRL1, IOMUX_ENABLE_MASK, 0);
Faiz Abbase9aed582019-06-11 00:43:38 +0530330
331 /* Set slot type based on SD or eMMC */
332 if (plat->non_removable)
333 ctl_cfg_2 = SLOTTYPE_EMBEDDED;
334
335 regmap_update_bits(plat->base, CTL_CFG_2, SLOTTYPE_MASK, ctl_cfg_2);
336
337 return 0;
338}
339
Faiz Abbase4425cb2020-02-26 13:44:34 +0530340#define MAX_SDCD_DEBOUNCE_TIME 2000
341static int am654_sdhci_deferred_probe(struct sdhci_host *host)
342{
343 struct udevice *dev = host->mmc->dev;
Simon Glassfa20e932020-12-03 16:55:20 -0700344 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Faiz Abbase4425cb2020-02-26 13:44:34 +0530345 unsigned long start;
346 int val;
347
348 /*
349 * The controller takes about 1 second to debounce the card detect line
350 * and doesn't let us power on until that time is up. Instead of waiting
351 * for 1 second at every stage, poll on the CARD_PRESENT bit upto a
352 * maximum of 2 seconds to be safe..
353 */
354 start = get_timer(0);
355 do {
356 if (get_timer(start) > MAX_SDCD_DEBOUNCE_TIME)
357 return -ENOMEDIUM;
358
359 val = mmc_getcd(host->mmc);
360 } while (!val);
361
362 am654_sdhci_init(plat);
363
364 return sdhci_probe(dev);
365}
366
Faiz Abbas36c8c5c2021-02-04 15:10:54 +0530367static void am654_sdhci_write_b(struct sdhci_host *host, u8 val, int reg)
368{
369 if (reg == SDHCI_HOST_CONTROL) {
370 switch (host->mmc->selected_mode) {
371 /*
372 * According to the data manual, HISPD bit
373 * should not be set in these speed modes.
374 */
375 case SD_HS:
376 case MMC_HS:
377 case UHS_SDR12:
378 case UHS_SDR25:
379 val &= ~SDHCI_CTRL_HISPD;
380 default:
381 break;
382 }
383 }
384
385 writeb(val, host->ioaddr + reg);
386}
Faiz Abbas7a7e2c72021-02-04 15:10:53 +0530387#ifdef MMC_SUPPORTS_TUNING
Judith Mendez81c1d442024-04-18 14:00:56 -0500388#define ITAPDLY_LENGTH 32
389#define ITAPDLY_LAST_INDEX (ITAPDLY_LENGTH - 1)
390
391static u32 am654_sdhci_calculate_itap(struct udevice *dev, struct window
392 *fail_window, u8 num_fails, bool circular_buffer)
393{
394 u8 itap = 0, start_fail = 0, end_fail = 0, pass_length = 0;
395 u8 first_fail_start = 0, last_fail_end = 0;
396 struct window pass_window = {0, 0, 0};
397 int prev_fail_end = -1;
398 u8 i;
399
400 if (!num_fails)
401 return ITAPDLY_LAST_INDEX >> 1;
402
403 if (fail_window->length == ITAPDLY_LENGTH) {
404 dev_err(dev, "No passing ITAPDLY, return 0\n");
405 return 0;
406 }
407
408 first_fail_start = fail_window->start;
409 last_fail_end = fail_window[num_fails - 1].end;
410
411 for (i = 0; i < num_fails; i++) {
412 start_fail = fail_window[i].start;
413 end_fail = fail_window[i].end;
414 pass_length = start_fail - (prev_fail_end + 1);
415
416 if (pass_length > pass_window.length) {
417 pass_window.start = prev_fail_end + 1;
418 pass_window.length = pass_length;
419 }
420 prev_fail_end = end_fail;
421 }
422
423 if (!circular_buffer)
424 pass_length = ITAPDLY_LAST_INDEX - last_fail_end;
425 else
426 pass_length = ITAPDLY_LAST_INDEX - last_fail_end + first_fail_start;
427
428 if (pass_length > pass_window.length) {
429 pass_window.start = last_fail_end + 1;
430 pass_window.length = pass_length;
431 }
432
433 if (!circular_buffer)
434 itap = pass_window.start + (pass_window.length >> 1);
435 else
436 itap = (pass_window.start + (pass_window.length >> 1)) % ITAPDLY_LENGTH;
437
438 return (itap > ITAPDLY_LAST_INDEX) ? ITAPDLY_LAST_INDEX >> 1 : itap;
439}
440
Faiz Abbas7a7e2c72021-02-04 15:10:53 +0530441static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
442{
443 struct udevice *dev = mmc->dev;
444 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Judith Mendez81c1d442024-04-18 14:00:56 -0500445 struct window fail_window[ITAPDLY_LENGTH];
446 u8 curr_pass, itap;
447 u8 fail_index = 0;
448 u8 prev_pass = 1;
449
450 memset(fail_window, 0, sizeof(fail_window));
Faiz Abbas7a7e2c72021-02-04 15:10:53 +0530451
452 /* Enable ITAPDLY */
453 regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYENA_MASK,
454 1 << ITAPDLYENA_SHIFT);
455
Judith Mendez81c1d442024-04-18 14:00:56 -0500456 for (itap = 0; itap < ITAPDLY_LENGTH; itap++) {
Faiz Abbas7a7e2c72021-02-04 15:10:53 +0530457 am654_sdhci_write_itapdly(plat, itap);
458
Judith Mendez81c1d442024-04-18 14:00:56 -0500459 curr_pass = !mmc_send_tuning(mmc, opcode);
460
461 if (!curr_pass && prev_pass)
462 fail_window[fail_index].start = itap;
Faiz Abbas7a7e2c72021-02-04 15:10:53 +0530463
Judith Mendez81c1d442024-04-18 14:00:56 -0500464 if (!curr_pass) {
465 fail_window[fail_index].end = itap;
466 fail_window[fail_index].length++;
467 }
468
469 if (curr_pass && !prev_pass)
470 fail_index++;
Faiz Abbas7a7e2c72021-02-04 15:10:53 +0530471
Judith Mendez81c1d442024-04-18 14:00:56 -0500472 prev_pass = curr_pass;
Faiz Abbas7a7e2c72021-02-04 15:10:53 +0530473 }
Judith Mendez81c1d442024-04-18 14:00:56 -0500474
475 if (fail_window[fail_index].length != 0)
476 fail_index++;
477
478 itap = am654_sdhci_calculate_itap(dev, fail_window, fail_index,
479 plat->dll_enable);
480
Faiz Abbas7a7e2c72021-02-04 15:10:53 +0530481 am654_sdhci_write_itapdly(plat, itap);
482
483 return 0;
484}
485#endif
Faiz Abbase4425cb2020-02-26 13:44:34 +0530486const struct sdhci_ops am654_sdhci_ops = {
Faiz Abbas7a7e2c72021-02-04 15:10:53 +0530487#ifdef MMC_SUPPORTS_TUNING
488 .platform_execute_tuning = am654_sdhci_execute_tuning,
489#endif
Faiz Abbase4425cb2020-02-26 13:44:34 +0530490 .deferred_probe = am654_sdhci_deferred_probe,
491 .set_ios_post = &am654_sdhci_set_ios_post,
Faiz Abbas9c10cfe2021-02-04 15:10:55 +0530492 .set_control_reg = sdhci_set_control_reg,
Faiz Abbas36c8c5c2021-02-04 15:10:54 +0530493 .write_b = am654_sdhci_write_b,
Faiz Abbase4425cb2020-02-26 13:44:34 +0530494};
495
496const struct am654_driver_data am654_drv_data = {
497 .ops = &am654_sdhci_ops,
Faiz Abbas2c2fc962021-02-04 15:10:50 +0530498 .flags = DLL_PRESENT | IOMUX_PRESENT | FREQSEL_2_BIT | STRBSEL_4_BIT,
499};
500
501const struct am654_driver_data am654_sr1_drv_data = {
502 .ops = &am654_sdhci_ops,
Faiz Abbas947e8f32021-02-04 15:10:49 +0530503 .flags = IOMUX_PRESENT | FREQSEL_2_BIT | DLL_PRESENT | DLL_CALIB |
504 STRBSEL_4_BIT,
Faiz Abbase4425cb2020-02-26 13:44:34 +0530505};
506
507const struct am654_driver_data j721e_8bit_drv_data = {
508 .ops = &am654_sdhci_ops,
Faiz Abbas947e8f32021-02-04 15:10:49 +0530509 .flags = DLL_PRESENT | DLL_CALIB,
Faiz Abbase4425cb2020-02-26 13:44:34 +0530510};
511
512static int j721e_4bit_sdhci_set_ios_post(struct sdhci_host *host)
513{
514 struct udevice *dev = host->mmc->dev;
Simon Glassfa20e932020-12-03 16:55:20 -0700515 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Nitin Yadav83db1f92024-04-18 14:00:57 -0500516 int mode = host->mmc->selected_mode;
517 u32 otap_del_sel;
518 u32 itap_del_sel;
519 u32 mask, val;
Faiz Abbase4425cb2020-02-26 13:44:34 +0530520
Nitin Yadav83db1f92024-04-18 14:00:57 -0500521 otap_del_sel = plat->otap_del_sel[mode];
522
Faiz Abbase4425cb2020-02-26 13:44:34 +0530523 mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
Nitin Yadav83db1f92024-04-18 14:00:57 -0500524 val = (1 << OTAPDLYENA_SHIFT) |
525 (otap_del_sel << OTAPDLYSEL_SHIFT);
526
527 itap_del_sel = plat->itap_del_sel[mode];
528
529 mask |= ITAPDLYENA_MASK | ITAPDLYSEL_MASK;
530 val |= (1 << ITAPDLYENA_SHIFT) |
531 (itap_del_sel << ITAPDLYSEL_SHIFT);
532
533 regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK,
534 1 << ITAPCHGWIN_SHIFT);
Faiz Abbase4425cb2020-02-26 13:44:34 +0530535 regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
Nitin Yadav83db1f92024-04-18 14:00:57 -0500536 regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0);
Faiz Abbase4425cb2020-02-26 13:44:34 +0530537
Faiz Abbasc73f04e2021-02-04 15:10:52 +0530538 regmap_update_bits(plat->base, PHY_CTRL5, CLKBUFSEL_MASK,
539 plat->clkbuf_sel);
540
Faiz Abbase4425cb2020-02-26 13:44:34 +0530541 return 0;
542}
543
544const struct sdhci_ops j721e_4bit_sdhci_ops = {
Faiz Abbas7a7e2c72021-02-04 15:10:53 +0530545#ifdef MMC_SUPPORTS_TUNING
546 .platform_execute_tuning = am654_sdhci_execute_tuning,
547#endif
Faiz Abbase4425cb2020-02-26 13:44:34 +0530548 .deferred_probe = am654_sdhci_deferred_probe,
549 .set_ios_post = &j721e_4bit_sdhci_set_ios_post,
Faiz Abbas9c10cfe2021-02-04 15:10:55 +0530550 .set_control_reg = sdhci_set_control_reg,
Faiz Abbas36c8c5c2021-02-04 15:10:54 +0530551 .write_b = am654_sdhci_write_b,
Faiz Abbase4425cb2020-02-26 13:44:34 +0530552};
553
554const struct am654_driver_data j721e_4bit_drv_data = {
555 .ops = &j721e_4bit_sdhci_ops,
556 .flags = IOMUX_PRESENT,
557};
558
Dave Gerlach057d6af2021-04-23 11:27:40 -0500559static const struct am654_driver_data sdhci_am64_8bit_drvdata = {
560 .ops = &am654_sdhci_ops,
561 .flags = DLL_PRESENT | DLL_CALIB,
562};
563
564static const struct am654_driver_data sdhci_am64_4bit_drvdata = {
565 .ops = &j721e_4bit_sdhci_ops,
566 .flags = IOMUX_PRESENT,
567};
568
Faiz Abbas2c2fc962021-02-04 15:10:50 +0530569const struct soc_attr am654_sdhci_soc_attr[] = {
570 { .family = "AM65X", .revision = "SR1.0", .data = &am654_sr1_drv_data},
571 {/* sentinel */}
572};
573
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530574static int sdhci_am654_get_otap_delay(struct udevice *dev,
575 struct mmc_config *cfg)
576{
Simon Glassfa20e932020-12-03 16:55:20 -0700577 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530578 int ret;
579 int i;
580
581 /* ti,otap-del-sel-legacy is mandatory */
582 ret = dev_read_u32(dev, "ti,otap-del-sel-legacy",
583 &plat->otap_del_sel[0]);
584 if (ret)
585 return ret;
586 /*
587 * Remove the corresponding capability if an otap-del-sel
588 * value is not found
589 */
Nitin Yadav83db1f92024-04-18 14:00:57 -0500590 for (i = MMC_LEGACY; i <= MMC_HS_400; i++) {
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530591 ret = dev_read_u32(dev, td[i].otap_binding,
592 &plat->otap_del_sel[i]);
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530593 if (ret) {
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530594 dev_dbg(dev, "Couldn't find %s\n", td[i].otap_binding);
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530595 /*
596 * Remove the corresponding capability
597 * if an otap-del-sel value is not found
598 */
599 cfg->host_caps &= ~td[i].capability;
600 }
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530601
602 if (td[i].itap_binding)
603 dev_read_u32(dev, td[i].itap_binding,
604 &plat->itap_del_sel[i]);
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530605 }
606
607 return 0;
608}
609
Faiz Abbasd8fb3092019-06-11 00:43:31 +0530610static int am654_sdhci_probe(struct udevice *dev)
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530611{
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530612 struct am654_driver_data *drv_data =
613 (struct am654_driver_data *)dev_get_driver_data(dev);
Simon Glassfa20e932020-12-03 16:55:20 -0700614 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530615 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
616 struct sdhci_host *host = dev_get_priv(dev);
Faiz Abbase9aed582019-06-11 00:43:38 +0530617 struct mmc_config *cfg = &plat->cfg;
Faiz Abbas2c2fc962021-02-04 15:10:50 +0530618 const struct soc_attr *soc;
619 const struct am654_driver_data *soc_drv_data;
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530620 struct clk clk;
621 unsigned long clock;
622 int ret;
623
Faiz Abbasdc2bcc22020-01-16 19:42:18 +0530624 ret = clk_get_by_name(dev, "clk_xin", &clk);
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530625 if (ret) {
626 dev_err(dev, "failed to get clock\n");
627 return ret;
628 }
629
630 clock = clk_get_rate(&clk);
631 if (IS_ERR_VALUE(clock)) {
632 dev_err(dev, "failed to get rate\n");
633 return clock;
634 }
635
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530636 host->max_clk = clock;
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530637 host->mmc = &plat->mmc;
Faiz Abbase9aed582019-06-11 00:43:38 +0530638 host->mmc->dev = dev;
Faiz Abbas36c8c5c2021-02-04 15:10:54 +0530639 host->ops = drv_data->ops;
Faiz Abbase9aed582019-06-11 00:43:38 +0530640 ret = sdhci_setup_cfg(cfg, host, cfg->f_max,
641 AM654_SDHCI_MIN_FREQ);
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530642 if (ret)
643 return ret;
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530644
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530645 ret = sdhci_am654_get_otap_delay(dev, cfg);
646 if (ret)
647 return ret;
648
Faiz Abbas2c2fc962021-02-04 15:10:50 +0530649 /* Update ops based on SoC revision */
650 soc = soc_device_match(am654_sdhci_soc_attr);
651 if (soc && soc->data) {
652 soc_drv_data = soc->data;
653 host->ops = soc_drv_data->ops;
654 }
655
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530656 host->mmc->priv = host;
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530657 upriv->mmc = host->mmc;
658
Faiz Abbase9aed582019-06-11 00:43:38 +0530659 regmap_init_mem_index(dev_ofnode(dev), &plat->base, 1);
660
Faiz Abbase4425cb2020-02-26 13:44:34 +0530661 return 0;
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530662}
663
Simon Glassaad29ae2020-12-03 16:55:21 -0700664static int am654_sdhci_of_to_plat(struct udevice *dev)
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530665{
Simon Glassfa20e932020-12-03 16:55:20 -0700666 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530667 struct sdhci_host *host = dev_get_priv(dev);
Faiz Abbase9aed582019-06-11 00:43:38 +0530668 struct mmc_config *cfg = &plat->cfg;
669 u32 drv_strength;
670 int ret;
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530671
672 host->name = dev->name;
Johan Jonker8d5d8e02023-03-13 01:32:04 +0100673 host->ioaddr = dev_read_addr_ptr(dev);
Faiz Abbase9aed582019-06-11 00:43:38 +0530674 plat->non_removable = dev_read_bool(dev, "non-removable");
675
Faiz Abbasfd8be702019-06-13 10:29:51 +0530676 if (plat->flags & DLL_PRESENT) {
677 ret = dev_read_u32(dev, "ti,trm-icp", &plat->trm_icp);
678 if (ret)
679 return ret;
680
681 ret = dev_read_u32(dev, "ti,driver-strength-ohm",
682 &drv_strength);
683 if (ret)
684 return ret;
Faiz Abbase9aed582019-06-11 00:43:38 +0530685
Faiz Abbasfd8be702019-06-13 10:29:51 +0530686 switch (drv_strength) {
687 case 50:
688 plat->drv_strength = DRIVER_STRENGTH_50_OHM;
689 break;
690 case 33:
691 plat->drv_strength = DRIVER_STRENGTH_33_OHM;
692 break;
693 case 66:
694 plat->drv_strength = DRIVER_STRENGTH_66_OHM;
695 break;
696 case 100:
697 plat->drv_strength = DRIVER_STRENGTH_100_OHM;
698 break;
699 case 40:
700 plat->drv_strength = DRIVER_STRENGTH_40_OHM;
701 break;
702 default:
703 dev_err(dev, "Invalid driver strength\n");
704 return -EINVAL;
705 }
Faiz Abbase9aed582019-06-11 00:43:38 +0530706 }
707
Aswath Govindraju4509fb62021-05-25 15:08:23 +0530708 dev_read_u32(dev, "ti,strobe-sel", &plat->strb_sel);
Faiz Abbasc73f04e2021-02-04 15:10:52 +0530709 dev_read_u32(dev, "ti,clkbuf-sel", &plat->clkbuf_sel);
710
Faiz Abbase9aed582019-06-11 00:43:38 +0530711 ret = mmc_of_parse(dev, cfg);
712 if (ret)
713 return ret;
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530714
715 return 0;
716}
717
Faiz Abbasd8fb3092019-06-11 00:43:31 +0530718static int am654_sdhci_bind(struct udevice *dev)
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530719{
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530720 struct am654_driver_data *drv_data =
721 (struct am654_driver_data *)dev_get_driver_data(dev);
Simon Glassfa20e932020-12-03 16:55:20 -0700722 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Faiz Abbas2c2fc962021-02-04 15:10:50 +0530723 const struct soc_attr *soc;
724 const struct am654_driver_data *soc_drv_data;
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530725
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530726 plat->flags = drv_data->flags;
727
Faiz Abbas2c2fc962021-02-04 15:10:50 +0530728 /* Update flags based on SoC revision */
729 soc = soc_device_match(am654_sdhci_soc_attr);
730 if (soc && soc->data) {
731 soc_drv_data = soc->data;
732 plat->flags = soc_drv_data->flags;
733 }
734
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530735 return sdhci_bind(dev, &plat->mmc, &plat->cfg);
736}
737
Faiz Abbasd8fb3092019-06-11 00:43:31 +0530738static const struct udevice_id am654_sdhci_ids[] = {
Faiz Abbasfd8be702019-06-13 10:29:51 +0530739 {
740 .compatible = "ti,am654-sdhci-5.1",
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530741 .data = (ulong)&am654_drv_data,
Faiz Abbasfd8be702019-06-13 10:29:51 +0530742 },
743 {
744 .compatible = "ti,j721e-sdhci-8bit",
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530745 .data = (ulong)&j721e_8bit_drv_data,
Faiz Abbasfd8be702019-06-13 10:29:51 +0530746 },
747 {
748 .compatible = "ti,j721e-sdhci-4bit",
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530749 .data = (ulong)&j721e_4bit_drv_data,
Faiz Abbasfd8be702019-06-13 10:29:51 +0530750 },
Dave Gerlach057d6af2021-04-23 11:27:40 -0500751 {
752 .compatible = "ti,am64-sdhci-8bit",
753 .data = (ulong)&sdhci_am64_8bit_drvdata,
754 },
755 {
756 .compatible = "ti,am64-sdhci-4bit",
757 .data = (ulong)&sdhci_am64_4bit_drvdata,
758 },
Aswath Govindraju71b9a7b2022-05-25 13:38:39 +0530759 {
760 .compatible = "ti,am62-sdhci",
761 .data = (ulong)&sdhci_am64_4bit_drvdata,
762 },
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530763 { }
764};
765
Faiz Abbasd8fb3092019-06-11 00:43:31 +0530766U_BOOT_DRIVER(am654_sdhci_drv) = {
767 .name = "am654_sdhci",
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530768 .id = UCLASS_MMC,
Faiz Abbasd8fb3092019-06-11 00:43:31 +0530769 .of_match = am654_sdhci_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -0700770 .of_to_plat = am654_sdhci_of_to_plat,
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530771 .ops = &sdhci_ops,
Faiz Abbasd8fb3092019-06-11 00:43:31 +0530772 .bind = am654_sdhci_bind,
773 .probe = am654_sdhci_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700774 .priv_auto = sizeof(struct sdhci_host),
Simon Glass71fa5b42020-12-03 16:55:18 -0700775 .plat_auto = sizeof(struct am654_sdhci_plat),
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530776};