blob: a86d96aacd2ba669484abd7c35865a5a835ceb3f [file] [log] [blame]
Lokesh Vutlabc9979f2018-08-27 15:57:54 +05301// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
4 *
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;
Faiz Abbasb7f57bb2021-02-04 15:10:48 +0530100#define DLL_PRESENT BIT(0)
101#define IOMUX_PRESENT BIT(1)
102#define FREQSEL_2_BIT BIT(2)
103#define STRBSEL_4_BIT BIT(3)
Faiz Abbas947e8f32021-02-04 15:10:49 +0530104#define DLL_CALIB BIT(4)
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530105};
106
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530107struct timing_data {
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530108 const char *otap_binding;
109 const char *itap_binding;
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530110 u32 capability;
111};
112
113static const struct timing_data td[] = {
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530114 [MMC_LEGACY] = {"ti,otap-del-sel-legacy",
115 "ti,itap-del-sel-legacy",
116 0},
117 [MMC_HS] = {"ti,otap-del-sel-mmc-hs",
118 "ti,itap-del-sel-mms-hs",
119 MMC_CAP(MMC_HS)},
120 [SD_HS] = {"ti,otap-del-sel-sd-hs",
121 "ti,itap-del-sel-sd-hs",
122 MMC_CAP(SD_HS)},
123 [UHS_SDR12] = {"ti,otap-del-sel-sdr12",
124 "ti,itap-del-sel-sdr12",
125 MMC_CAP(UHS_SDR12)},
126 [UHS_SDR25] = {"ti,otap-del-sel-sdr25",
127 "ti,itap-del-sel-sdr25",
128 MMC_CAP(UHS_SDR25)},
129 [UHS_SDR50] = {"ti,otap-del-sel-sdr50",
130 NULL,
131 MMC_CAP(UHS_SDR50)},
132 [UHS_SDR104] = {"ti,otap-del-sel-sdr104",
133 NULL,
134 MMC_CAP(UHS_SDR104)},
135 [UHS_DDR50] = {"ti,otap-del-sel-ddr50",
136 NULL,
137 MMC_CAP(UHS_DDR50)},
138 [MMC_DDR_52] = {"ti,otap-del-sel-ddr52",
139 "ti,itap-del-sel-ddr52",
140 MMC_CAP(MMC_DDR_52)},
141 [MMC_HS_200] = {"ti,otap-del-sel-hs200",
142 NULL,
143 MMC_CAP(MMC_HS_200)},
144 [MMC_HS_400] = {"ti,otap-del-sel-hs400",
145 NULL,
146 MMC_CAP(MMC_HS_400)},
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530147};
148
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530149struct am654_driver_data {
150 const struct sdhci_ops *ops;
151 u32 flags;
152};
153
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530154static int am654_sdhci_setup_dll(struct am654_sdhci_plat *plat,
155 unsigned int speed)
156{
157 int sel50, sel100, freqsel;
158 u32 mask, val;
159 int ret;
160
161 /* Disable delay chain mode */
162 regmap_update_bits(plat->base, PHY_CTRL5,
163 SELDLYTXCLK_MASK | SELDLYRXCLK_MASK, 0);
164
165 if (plat->flags & FREQSEL_2_BIT) {
166 switch (speed) {
167 case 200000000:
168 sel50 = 0;
169 sel100 = 0;
170 break;
171 case 100000000:
172 sel50 = 0;
173 sel100 = 1;
174 break;
175 default:
176 sel50 = 1;
177 sel100 = 0;
178 }
179
180 /* Configure PHY DLL frequency */
181 mask = SEL50_MASK | SEL100_MASK;
182 val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT);
183 regmap_update_bits(plat->base, PHY_CTRL5, mask, val);
184 } else {
185 switch (speed) {
186 case 200000000:
187 freqsel = 0x0;
188 break;
189 default:
190 freqsel = 0x4;
191 }
192 regmap_update_bits(plat->base, PHY_CTRL5, FREQSEL_MASK,
193 freqsel << FREQSEL_SHIFT);
194 }
195
196 /* Configure DLL TRIM */
197 mask = DLL_TRIM_ICP_MASK;
198 val = plat->trm_icp << DLL_TRIM_ICP_SHIFT;
199
200 /* Configure DLL driver strength */
201 mask |= DR_TY_MASK;
202 val |= plat->drv_strength << DR_TY_SHIFT;
203 regmap_update_bits(plat->base, PHY_CTRL1, mask, val);
204
205 /* Enable DLL */
206 regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK,
207 0x1 << ENDLL_SHIFT);
208 /*
209 * Poll for DLL ready. Use a one second timeout.
210 * Works in all experiments done so far
211 */
212 ret = regmap_read_poll_timeout(plat->base, PHY_STAT1, val,
213 val & DLLRDY_MASK, 1000, 1000000);
214
215 return ret;
216}
217
218static void am654_sdhci_write_itapdly(struct am654_sdhci_plat *plat,
219 u32 itapdly)
220{
221 /* Set ITAPCHGWIN before writing to ITAPDLY */
222 regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK,
223 1 << ITAPCHGWIN_SHIFT);
224 regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYSEL_MASK,
225 itapdly << ITAPDLYSEL_SHIFT);
226 regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0);
227}
228
229static void am654_sdhci_setup_delay_chain(struct am654_sdhci_plat *plat,
230 int mode)
231{
232 u32 mask, val;
233
234 val = 1 << SELDLYTXCLK_SHIFT | 1 << SELDLYRXCLK_SHIFT;
235 mask = SELDLYTXCLK_MASK | SELDLYRXCLK_MASK;
236 regmap_update_bits(plat->base, PHY_CTRL5, mask, val);
237
238 am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode]);
239}
240
Faiz Abbase9aed582019-06-11 00:43:38 +0530241static int am654_sdhci_set_ios_post(struct sdhci_host *host)
242{
243 struct udevice *dev = host->mmc->dev;
Simon Glassfa20e932020-12-03 16:55:20 -0700244 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Faiz Abbase9aed582019-06-11 00:43:38 +0530245 unsigned int speed = host->mmc->clock;
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530246 int mode = host->mmc->selected_mode;
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530247 u32 otap_del_sel;
Faiz Abbase9aed582019-06-11 00:43:38 +0530248 u32 mask, val;
249 int ret;
250
251 /* Reset SD Clock Enable */
252 val = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
253 val &= ~SDHCI_CLOCK_CARD_EN;
254 sdhci_writew(host, val, SDHCI_CLOCK_CONTROL);
255
Faiz Abbas2c45a2c2021-02-04 15:10:47 +0530256 regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK, 0);
Faiz Abbase9aed582019-06-11 00:43:38 +0530257
258 /* restart clock */
259 sdhci_set_clock(host->mmc, speed);
260
261 /* switch phy back on */
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530262 otap_del_sel = plat->otap_del_sel[mode];
263 mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
264 val = (1 << OTAPDLYENA_SHIFT) |
265 (otap_del_sel << OTAPDLYSEL_SHIFT);
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530266
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530267 /* Write to STRBSEL for HS400 speed mode */
268 if (host->mmc->selected_mode == MMC_HS_400) {
269 if (plat->flags & STRBSEL_4_BIT)
270 mask |= STRBSEL_4BIT_MASK;
271 else
272 mask |= STRBSEL_8BIT_MASK;
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530273
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530274 val |= plat->strb_sel << STRBSEL_SHIFT;
275 }
Faiz Abbas947e8f32021-02-04 15:10:49 +0530276
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530277 regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
Faiz Abbas947e8f32021-02-04 15:10:49 +0530278
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530279 if (mode > UHS_SDR25 && speed >= CLOCK_TOO_SLOW_HZ) {
280 ret = am654_sdhci_setup_dll(plat, speed);
Faiz Abbase9aed582019-06-11 00:43:38 +0530281 if (ret)
282 return ret;
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530283 } else {
284 am654_sdhci_setup_delay_chain(plat, mode);
Faiz Abbase9aed582019-06-11 00:43:38 +0530285 }
286
Faiz Abbasc73f04e2021-02-04 15:10:52 +0530287 regmap_update_bits(plat->base, PHY_CTRL5, CLKBUFSEL_MASK,
288 plat->clkbuf_sel);
289
Faiz Abbase9aed582019-06-11 00:43:38 +0530290 return 0;
291}
292
Faiz Abbase9aed582019-06-11 00:43:38 +0530293int am654_sdhci_init(struct am654_sdhci_plat *plat)
294{
295 u32 ctl_cfg_2 = 0;
296 u32 mask, val;
297 int ret;
298
299 /* Reset OTAP to default value */
300 mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
301 regmap_update_bits(plat->base, PHY_CTRL4, mask, 0x0);
302
Faiz Abbas947e8f32021-02-04 15:10:49 +0530303 if (plat->flags & DLL_CALIB) {
Faiz Abbasfd8be702019-06-13 10:29:51 +0530304 regmap_read(plat->base, PHY_STAT1, &val);
305 if (~val & CALDONE_MASK) {
306 /* Calibrate IO lines */
307 regmap_update_bits(plat->base, PHY_CTRL1, PDB_MASK,
308 PDB_MASK);
309 ret = regmap_read_poll_timeout(plat->base, PHY_STAT1,
310 val, val & CALDONE_MASK,
311 1, 20);
312 if (ret)
313 return ret;
314 }
Faiz Abbasfd8be702019-06-13 10:29:51 +0530315 }
Faiz Abbase9aed582019-06-11 00:43:38 +0530316
317 /* Enable pins by setting IO mux to 0 */
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530318 if (plat->flags & IOMUX_PRESENT)
319 regmap_update_bits(plat->base, PHY_CTRL1, IOMUX_ENABLE_MASK, 0);
Faiz Abbase9aed582019-06-11 00:43:38 +0530320
321 /* Set slot type based on SD or eMMC */
322 if (plat->non_removable)
323 ctl_cfg_2 = SLOTTYPE_EMBEDDED;
324
325 regmap_update_bits(plat->base, CTL_CFG_2, SLOTTYPE_MASK, ctl_cfg_2);
326
327 return 0;
328}
329
Faiz Abbase4425cb2020-02-26 13:44:34 +0530330#define MAX_SDCD_DEBOUNCE_TIME 2000
331static int am654_sdhci_deferred_probe(struct sdhci_host *host)
332{
333 struct udevice *dev = host->mmc->dev;
Simon Glassfa20e932020-12-03 16:55:20 -0700334 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Faiz Abbase4425cb2020-02-26 13:44:34 +0530335 unsigned long start;
336 int val;
337
338 /*
339 * The controller takes about 1 second to debounce the card detect line
340 * and doesn't let us power on until that time is up. Instead of waiting
341 * for 1 second at every stage, poll on the CARD_PRESENT bit upto a
342 * maximum of 2 seconds to be safe..
343 */
344 start = get_timer(0);
345 do {
346 if (get_timer(start) > MAX_SDCD_DEBOUNCE_TIME)
347 return -ENOMEDIUM;
348
349 val = mmc_getcd(host->mmc);
350 } while (!val);
351
352 am654_sdhci_init(plat);
353
354 return sdhci_probe(dev);
355}
356
Faiz Abbas36c8c5c2021-02-04 15:10:54 +0530357static void am654_sdhci_write_b(struct sdhci_host *host, u8 val, int reg)
358{
359 if (reg == SDHCI_HOST_CONTROL) {
360 switch (host->mmc->selected_mode) {
361 /*
362 * According to the data manual, HISPD bit
363 * should not be set in these speed modes.
364 */
365 case SD_HS:
366 case MMC_HS:
367 case UHS_SDR12:
368 case UHS_SDR25:
369 val &= ~SDHCI_CTRL_HISPD;
370 default:
371 break;
372 }
373 }
374
375 writeb(val, host->ioaddr + reg);
376}
Faiz Abbas7a7e2c72021-02-04 15:10:53 +0530377#ifdef MMC_SUPPORTS_TUNING
378#define ITAP_MAX 32
379static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
380{
381 struct udevice *dev = mmc->dev;
382 struct am654_sdhci_plat *plat = dev_get_plat(dev);
383 int cur_val, prev_val = 1, fail_len = 0, pass_window = 0, pass_len;
384 u32 itap;
385
386 /* Enable ITAPDLY */
387 regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYENA_MASK,
388 1 << ITAPDLYENA_SHIFT);
389
390 for (itap = 0; itap < ITAP_MAX; itap++) {
391 am654_sdhci_write_itapdly(plat, itap);
392
393 cur_val = !mmc_send_tuning(mmc, opcode, NULL);
394 if (cur_val && !prev_val)
395 pass_window = itap;
396
397 if (!cur_val)
398 fail_len++;
399
400 prev_val = cur_val;
401 }
402 /*
403 * Having determined the length of the failing window and start of
404 * the passing window calculate the length of the passing window and
405 * set the final value halfway through it considering the range as a
406 * circular buffer
407 */
408 pass_len = ITAP_MAX - fail_len;
409 itap = (pass_window + (pass_len >> 1)) % ITAP_MAX;
410 am654_sdhci_write_itapdly(plat, itap);
411
412 return 0;
413}
414#endif
Faiz Abbase4425cb2020-02-26 13:44:34 +0530415const struct sdhci_ops am654_sdhci_ops = {
Faiz Abbas7a7e2c72021-02-04 15:10:53 +0530416#ifdef MMC_SUPPORTS_TUNING
417 .platform_execute_tuning = am654_sdhci_execute_tuning,
418#endif
Faiz Abbase4425cb2020-02-26 13:44:34 +0530419 .deferred_probe = am654_sdhci_deferred_probe,
420 .set_ios_post = &am654_sdhci_set_ios_post,
Faiz Abbas9c10cfe2021-02-04 15:10:55 +0530421 .set_control_reg = sdhci_set_control_reg,
Faiz Abbas36c8c5c2021-02-04 15:10:54 +0530422 .write_b = am654_sdhci_write_b,
Faiz Abbase4425cb2020-02-26 13:44:34 +0530423};
424
425const struct am654_driver_data am654_drv_data = {
426 .ops = &am654_sdhci_ops,
Faiz Abbas2c2fc962021-02-04 15:10:50 +0530427 .flags = DLL_PRESENT | IOMUX_PRESENT | FREQSEL_2_BIT | STRBSEL_4_BIT,
428};
429
430const struct am654_driver_data am654_sr1_drv_data = {
431 .ops = &am654_sdhci_ops,
Faiz Abbas947e8f32021-02-04 15:10:49 +0530432 .flags = IOMUX_PRESENT | FREQSEL_2_BIT | DLL_PRESENT | DLL_CALIB |
433 STRBSEL_4_BIT,
Faiz Abbase4425cb2020-02-26 13:44:34 +0530434};
435
436const struct am654_driver_data j721e_8bit_drv_data = {
437 .ops = &am654_sdhci_ops,
Faiz Abbas947e8f32021-02-04 15:10:49 +0530438 .flags = DLL_PRESENT | DLL_CALIB,
Faiz Abbase4425cb2020-02-26 13:44:34 +0530439};
440
441static int j721e_4bit_sdhci_set_ios_post(struct sdhci_host *host)
442{
443 struct udevice *dev = host->mmc->dev;
Simon Glassfa20e932020-12-03 16:55:20 -0700444 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Faiz Abbase4425cb2020-02-26 13:44:34 +0530445 u32 otap_del_sel, mask, val;
446
447 otap_del_sel = plat->otap_del_sel[host->mmc->selected_mode];
448 mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
449 val = (1 << OTAPDLYENA_SHIFT) | (otap_del_sel << OTAPDLYSEL_SHIFT);
450 regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
451
Faiz Abbasc73f04e2021-02-04 15:10:52 +0530452 regmap_update_bits(plat->base, PHY_CTRL5, CLKBUFSEL_MASK,
453 plat->clkbuf_sel);
454
Faiz Abbase4425cb2020-02-26 13:44:34 +0530455 return 0;
456}
457
458const struct sdhci_ops j721e_4bit_sdhci_ops = {
Faiz Abbas7a7e2c72021-02-04 15:10:53 +0530459#ifdef MMC_SUPPORTS_TUNING
460 .platform_execute_tuning = am654_sdhci_execute_tuning,
461#endif
Faiz Abbase4425cb2020-02-26 13:44:34 +0530462 .deferred_probe = am654_sdhci_deferred_probe,
463 .set_ios_post = &j721e_4bit_sdhci_set_ios_post,
Faiz Abbas9c10cfe2021-02-04 15:10:55 +0530464 .set_control_reg = sdhci_set_control_reg,
Faiz Abbas36c8c5c2021-02-04 15:10:54 +0530465 .write_b = am654_sdhci_write_b,
Faiz Abbase4425cb2020-02-26 13:44:34 +0530466};
467
468const struct am654_driver_data j721e_4bit_drv_data = {
469 .ops = &j721e_4bit_sdhci_ops,
470 .flags = IOMUX_PRESENT,
471};
472
Dave Gerlach057d6af2021-04-23 11:27:40 -0500473static const struct am654_driver_data sdhci_am64_8bit_drvdata = {
474 .ops = &am654_sdhci_ops,
475 .flags = DLL_PRESENT | DLL_CALIB,
476};
477
478static const struct am654_driver_data sdhci_am64_4bit_drvdata = {
479 .ops = &j721e_4bit_sdhci_ops,
480 .flags = IOMUX_PRESENT,
481};
482
Faiz Abbas2c2fc962021-02-04 15:10:50 +0530483const struct soc_attr am654_sdhci_soc_attr[] = {
484 { .family = "AM65X", .revision = "SR1.0", .data = &am654_sr1_drv_data},
485 {/* sentinel */}
486};
487
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530488static int sdhci_am654_get_otap_delay(struct udevice *dev,
489 struct mmc_config *cfg)
490{
Simon Glassfa20e932020-12-03 16:55:20 -0700491 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530492 int ret;
493 int i;
494
495 /* ti,otap-del-sel-legacy is mandatory */
496 ret = dev_read_u32(dev, "ti,otap-del-sel-legacy",
497 &plat->otap_del_sel[0]);
498 if (ret)
499 return ret;
500 /*
501 * Remove the corresponding capability if an otap-del-sel
502 * value is not found
503 */
504 for (i = MMC_HS; i <= MMC_HS_400; i++) {
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530505 ret = dev_read_u32(dev, td[i].otap_binding,
506 &plat->otap_del_sel[i]);
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530507 if (ret) {
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530508 dev_dbg(dev, "Couldn't find %s\n", td[i].otap_binding);
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530509 /*
510 * Remove the corresponding capability
511 * if an otap-del-sel value is not found
512 */
513 cfg->host_caps &= ~td[i].capability;
514 }
Faiz Abbasdef2a0f2021-02-04 15:10:51 +0530515
516 if (td[i].itap_binding)
517 dev_read_u32(dev, td[i].itap_binding,
518 &plat->itap_del_sel[i]);
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530519 }
520
521 return 0;
522}
523
Faiz Abbasd8fb3092019-06-11 00:43:31 +0530524static int am654_sdhci_probe(struct udevice *dev)
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530525{
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530526 struct am654_driver_data *drv_data =
527 (struct am654_driver_data *)dev_get_driver_data(dev);
Simon Glassfa20e932020-12-03 16:55:20 -0700528 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530529 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
530 struct sdhci_host *host = dev_get_priv(dev);
Faiz Abbase9aed582019-06-11 00:43:38 +0530531 struct mmc_config *cfg = &plat->cfg;
Faiz Abbas2c2fc962021-02-04 15:10:50 +0530532 const struct soc_attr *soc;
533 const struct am654_driver_data *soc_drv_data;
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530534 struct clk clk;
535 unsigned long clock;
536 int ret;
537
Faiz Abbasdc2bcc22020-01-16 19:42:18 +0530538 ret = clk_get_by_name(dev, "clk_xin", &clk);
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530539 if (ret) {
540 dev_err(dev, "failed to get clock\n");
541 return ret;
542 }
543
544 clock = clk_get_rate(&clk);
545 if (IS_ERR_VALUE(clock)) {
546 dev_err(dev, "failed to get rate\n");
547 return clock;
548 }
549
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530550 host->max_clk = clock;
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530551 host->mmc = &plat->mmc;
Faiz Abbase9aed582019-06-11 00:43:38 +0530552 host->mmc->dev = dev;
Faiz Abbas36c8c5c2021-02-04 15:10:54 +0530553 host->ops = drv_data->ops;
Faiz Abbase9aed582019-06-11 00:43:38 +0530554 ret = sdhci_setup_cfg(cfg, host, cfg->f_max,
555 AM654_SDHCI_MIN_FREQ);
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530556 if (ret)
557 return ret;
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530558
Faiz Abbasc6eb9e72020-02-26 13:44:33 +0530559 ret = sdhci_am654_get_otap_delay(dev, cfg);
560 if (ret)
561 return ret;
562
Faiz Abbas2c2fc962021-02-04 15:10:50 +0530563 /* Update ops based on SoC revision */
564 soc = soc_device_match(am654_sdhci_soc_attr);
565 if (soc && soc->data) {
566 soc_drv_data = soc->data;
567 host->ops = soc_drv_data->ops;
568 }
569
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530570 host->mmc->priv = host;
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530571 upriv->mmc = host->mmc;
572
Faiz Abbase9aed582019-06-11 00:43:38 +0530573 regmap_init_mem_index(dev_ofnode(dev), &plat->base, 1);
574
Faiz Abbase4425cb2020-02-26 13:44:34 +0530575 return 0;
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530576}
577
Simon Glassaad29ae2020-12-03 16:55:21 -0700578static int am654_sdhci_of_to_plat(struct udevice *dev)
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530579{
Simon Glassfa20e932020-12-03 16:55:20 -0700580 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530581 struct sdhci_host *host = dev_get_priv(dev);
Faiz Abbase9aed582019-06-11 00:43:38 +0530582 struct mmc_config *cfg = &plat->cfg;
583 u32 drv_strength;
584 int ret;
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530585
586 host->name = dev->name;
587 host->ioaddr = (void *)dev_read_addr(dev);
Faiz Abbase9aed582019-06-11 00:43:38 +0530588 plat->non_removable = dev_read_bool(dev, "non-removable");
589
Faiz Abbasfd8be702019-06-13 10:29:51 +0530590 if (plat->flags & DLL_PRESENT) {
591 ret = dev_read_u32(dev, "ti,trm-icp", &plat->trm_icp);
592 if (ret)
593 return ret;
594
595 ret = dev_read_u32(dev, "ti,driver-strength-ohm",
596 &drv_strength);
597 if (ret)
598 return ret;
Faiz Abbase9aed582019-06-11 00:43:38 +0530599
Faiz Abbasfd8be702019-06-13 10:29:51 +0530600 switch (drv_strength) {
601 case 50:
602 plat->drv_strength = DRIVER_STRENGTH_50_OHM;
603 break;
604 case 33:
605 plat->drv_strength = DRIVER_STRENGTH_33_OHM;
606 break;
607 case 66:
608 plat->drv_strength = DRIVER_STRENGTH_66_OHM;
609 break;
610 case 100:
611 plat->drv_strength = DRIVER_STRENGTH_100_OHM;
612 break;
613 case 40:
614 plat->drv_strength = DRIVER_STRENGTH_40_OHM;
615 break;
616 default:
617 dev_err(dev, "Invalid driver strength\n");
618 return -EINVAL;
619 }
Faiz Abbase9aed582019-06-11 00:43:38 +0530620 }
621
Faiz Abbasc73f04e2021-02-04 15:10:52 +0530622 dev_read_u32(dev, "ti,clkbuf-sel", &plat->clkbuf_sel);
623
Faiz Abbase9aed582019-06-11 00:43:38 +0530624 ret = mmc_of_parse(dev, cfg);
625 if (ret)
626 return ret;
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530627
628 return 0;
629}
630
Faiz Abbasd8fb3092019-06-11 00:43:31 +0530631static int am654_sdhci_bind(struct udevice *dev)
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530632{
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530633 struct am654_driver_data *drv_data =
634 (struct am654_driver_data *)dev_get_driver_data(dev);
Simon Glassfa20e932020-12-03 16:55:20 -0700635 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Faiz Abbas2c2fc962021-02-04 15:10:50 +0530636 const struct soc_attr *soc;
637 const struct am654_driver_data *soc_drv_data;
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530638
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530639 plat->flags = drv_data->flags;
640
Faiz Abbas2c2fc962021-02-04 15:10:50 +0530641 /* Update flags based on SoC revision */
642 soc = soc_device_match(am654_sdhci_soc_attr);
643 if (soc && soc->data) {
644 soc_drv_data = soc->data;
645 plat->flags = soc_drv_data->flags;
646 }
647
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530648 return sdhci_bind(dev, &plat->mmc, &plat->cfg);
649}
650
Faiz Abbasd8fb3092019-06-11 00:43:31 +0530651static const struct udevice_id am654_sdhci_ids[] = {
Faiz Abbasfd8be702019-06-13 10:29:51 +0530652 {
653 .compatible = "ti,am654-sdhci-5.1",
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530654 .data = (ulong)&am654_drv_data,
Faiz Abbasfd8be702019-06-13 10:29:51 +0530655 },
656 {
657 .compatible = "ti,j721e-sdhci-8bit",
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530658 .data = (ulong)&j721e_8bit_drv_data,
Faiz Abbasfd8be702019-06-13 10:29:51 +0530659 },
660 {
661 .compatible = "ti,j721e-sdhci-4bit",
Faiz Abbas8cc051e2020-01-16 19:42:19 +0530662 .data = (ulong)&j721e_4bit_drv_data,
Faiz Abbasfd8be702019-06-13 10:29:51 +0530663 },
Dave Gerlach057d6af2021-04-23 11:27:40 -0500664 {
665 .compatible = "ti,am64-sdhci-8bit",
666 .data = (ulong)&sdhci_am64_8bit_drvdata,
667 },
668 {
669 .compatible = "ti,am64-sdhci-4bit",
670 .data = (ulong)&sdhci_am64_4bit_drvdata,
671 },
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530672 { }
673};
674
Faiz Abbasd8fb3092019-06-11 00:43:31 +0530675U_BOOT_DRIVER(am654_sdhci_drv) = {
676 .name = "am654_sdhci",
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530677 .id = UCLASS_MMC,
Faiz Abbasd8fb3092019-06-11 00:43:31 +0530678 .of_match = am654_sdhci_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -0700679 .of_to_plat = am654_sdhci_of_to_plat,
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530680 .ops = &sdhci_ops,
Faiz Abbasd8fb3092019-06-11 00:43:31 +0530681 .bind = am654_sdhci_bind,
682 .probe = am654_sdhci_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700683 .priv_auto = sizeof(struct sdhci_host),
Simon Glass71fa5b42020-12-03 16:55:18 -0700684 .plat_auto = sizeof(struct am654_sdhci_plat),
Lokesh Vutlabc9979f2018-08-27 15:57:54 +0530685};