blob: 5790fa3d0dbf8cf4e03fd4d468452c27b7925e73 [file] [log] [blame]
Lokesh Vutlaaaa449f2018-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>
12#include <power-domain.h>
Faiz Abbasce142ff2019-06-11 00:43:38 +053013#include <regmap.h>
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +053014#include <sdhci.h>
Faiz Abbas8c32b5f2021-02-04 15:10:50 +053015#include <soc.h>
Simon Glass336d4612020-02-03 07:36:16 -070016#include <dm/device_compat.h>
Simon Glasscd93d622020-05-10 11:40:13 -060017#include <linux/bitops.h>
Simon Glass61b29b82020-02-03 07:36:15 -070018#include <linux/err.h>
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +053019
Faiz Abbasce142ff2019-06-11 00:43:38 +053020/* 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
Faiz Abbasa20008e2020-01-16 19:42:19 +053043#define STRBSEL_4BIT_MASK GENMASK(27, 24)
44#define STRBSEL_8BIT_MASK GENMASK(31, 24)
Faiz Abbasce142ff2019-06-11 00:43:38 +053045#define SEL50_SHIFT 8
46#define SEL50_MASK BIT(SEL50_SHIFT)
47#define SEL100_SHIFT 9
48#define SEL100_MASK BIT(SEL100_SHIFT)
Faiz Abbasa20008e2020-01-16 19:42:19 +053049#define FREQSEL_SHIFT 8
50#define FREQSEL_MASK GENMASK(10, 8)
Faiz Abbasce142ff2019-06-11 00:43:38 +053051#define DLL_TRIM_ICP_SHIFT 4
52#define DLL_TRIM_ICP_MASK GENMASK(7, 4)
53#define DR_TY_SHIFT 20
54#define DR_TY_MASK GENMASK(22, 20)
55#define ENDLL_SHIFT 1
56#define ENDLL_MASK BIT(ENDLL_SHIFT)
57#define DLLRDY_SHIFT 0
58#define DLLRDY_MASK BIT(DLLRDY_SHIFT)
59#define PDB_SHIFT 0
60#define PDB_MASK BIT(PDB_SHIFT)
61#define CALDONE_SHIFT 1
62#define CALDONE_MASK BIT(CALDONE_SHIFT)
63#define RETRIM_SHIFT 17
64#define RETRIM_MASK BIT(RETRIM_SHIFT)
65
66#define DRIVER_STRENGTH_50_OHM 0x0
67#define DRIVER_STRENGTH_33_OHM 0x1
68#define DRIVER_STRENGTH_66_OHM 0x2
69#define DRIVER_STRENGTH_100_OHM 0x3
70#define DRIVER_STRENGTH_40_OHM 0x4
71
Faiz Abbas3a1a0df2019-06-11 00:43:31 +053072#define AM654_SDHCI_MIN_FREQ 400000
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +053073
Faiz Abbas3a1a0df2019-06-11 00:43:31 +053074struct am654_sdhci_plat {
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +053075 struct mmc_config cfg;
76 struct mmc mmc;
Faiz Abbasce142ff2019-06-11 00:43:38 +053077 struct regmap *base;
78 bool non_removable;
Faiz Abbas7d6f45a2020-07-29 07:03:41 +053079 u32 otap_del_sel[MMC_MODES_END];
Faiz Abbasce142ff2019-06-11 00:43:38 +053080 u32 trm_icp;
81 u32 drv_strength;
Faiz Abbasa20008e2020-01-16 19:42:19 +053082 u32 strb_sel;
Faiz Abbas794453f2019-06-13 10:29:51 +053083 u32 flags;
Faiz Abbas144e1312021-02-04 15:10:48 +053084#define DLL_PRESENT BIT(0)
85#define IOMUX_PRESENT BIT(1)
86#define FREQSEL_2_BIT BIT(2)
87#define STRBSEL_4_BIT BIT(3)
Faiz Abbas5b29fd42021-02-04 15:10:49 +053088#define DLL_CALIB BIT(4)
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +053089};
90
Faiz Abbasc7d106b2020-02-26 13:44:33 +053091struct timing_data {
92 const char *binding;
93 u32 capability;
94};
95
96static const struct timing_data td[] = {
97 [MMC_LEGACY] = {"ti,otap-del-sel-legacy", 0},
98 [MMC_HS] = {"ti,otap-del-sel-mmc-hs", MMC_CAP(MMC_HS)},
99 [SD_HS] = {"ti,otap-del-sel-sd-hs", MMC_CAP(SD_HS)},
100 [UHS_SDR12] = {"ti,otap-del-sel-sdr12", MMC_CAP(UHS_SDR12)},
101 [UHS_SDR25] = {"ti,otap-del-sel-sdr25", MMC_CAP(UHS_SDR25)},
102 [UHS_SDR50] = {"ti,otap-del-sel-sdr50", MMC_CAP(UHS_SDR50)},
103 [UHS_SDR104] = {"ti,otap-del-sel-sdr104", MMC_CAP(UHS_SDR104)},
104 [UHS_DDR50] = {"ti,otap-del-sel-ddr50", MMC_CAP(UHS_DDR50)},
105 [MMC_DDR_52] = {"ti,otap-del-sel-ddr52", MMC_CAP(MMC_DDR_52)},
106 [MMC_HS_200] = {"ti,otap-del-sel-hs200", MMC_CAP(MMC_HS_200)},
107 [MMC_HS_400] = {"ti,otap-del-sel-hs400", MMC_CAP(MMC_HS_400)},
108};
109
Faiz Abbasa20008e2020-01-16 19:42:19 +0530110struct am654_driver_data {
111 const struct sdhci_ops *ops;
112 u32 flags;
113};
114
Faiz Abbasf6058072019-06-11 00:43:41 +0530115static void am654_sdhci_set_control_reg(struct sdhci_host *host)
116{
117 struct mmc *mmc = (struct mmc *)host->mmc;
118 u32 reg;
119
120 if (IS_SD(host->mmc) &&
121 mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
122 reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
123 reg |= SDHCI_CTRL_VDD_180;
124 sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
125 }
126
127 sdhci_set_uhs_timing(host);
128}
129
Faiz Abbasce142ff2019-06-11 00:43:38 +0530130static int am654_sdhci_set_ios_post(struct sdhci_host *host)
131{
132 struct udevice *dev = host->mmc->dev;
Simon Glassc69cda22020-12-03 16:55:20 -0700133 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Faiz Abbasce142ff2019-06-11 00:43:38 +0530134 unsigned int speed = host->mmc->clock;
Faiz Abbasa20008e2020-01-16 19:42:19 +0530135 int sel50, sel100, freqsel;
Faiz Abbasc7d106b2020-02-26 13:44:33 +0530136 u32 otap_del_sel;
Faiz Abbasce142ff2019-06-11 00:43:38 +0530137 u32 mask, val;
138 int ret;
139
140 /* Reset SD Clock Enable */
141 val = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
142 val &= ~SDHCI_CLOCK_CARD_EN;
143 sdhci_writew(host, val, SDHCI_CLOCK_CONTROL);
144
Faiz Abbasc604e202021-02-04 15:10:47 +0530145 regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK, 0);
Faiz Abbasce142ff2019-06-11 00:43:38 +0530146
147 /* restart clock */
148 sdhci_set_clock(host->mmc, speed);
149
150 /* switch phy back on */
151 if (speed > AM654_SDHCI_MIN_FREQ) {
Faiz Abbasc7d106b2020-02-26 13:44:33 +0530152 otap_del_sel = plat->otap_del_sel[host->mmc->selected_mode];
Faiz Abbasce142ff2019-06-11 00:43:38 +0530153 mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
154 val = (1 << OTAPDLYENA_SHIFT) |
Faiz Abbasc7d106b2020-02-26 13:44:33 +0530155 (otap_del_sel << OTAPDLYSEL_SHIFT);
Faiz Abbasa20008e2020-01-16 19:42:19 +0530156
157 /* Write to STRBSEL for HS400 speed mode */
158 if (host->mmc->selected_mode == MMC_HS_400) {
159 if (plat->flags & STRBSEL_4_BIT)
160 mask |= STRBSEL_4BIT_MASK;
161 else
162 mask |= STRBSEL_8BIT_MASK;
163
164 val |= plat->strb_sel << STRBSEL_SHIFT;
Faiz Abbasce142ff2019-06-11 00:43:38 +0530165 }
166
Faiz Abbasa20008e2020-01-16 19:42:19 +0530167 regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
168
169 if (plat->flags & FREQSEL_2_BIT) {
170 switch (speed) {
171 case 200000000:
172 sel50 = 0;
173 sel100 = 0;
174 break;
175 case 100000000:
176 sel50 = 0;
177 sel100 = 1;
178 break;
179 default:
180 sel50 = 1;
181 sel100 = 0;
182 }
183
184 /* Configure PHY DLL frequency */
185 mask = SEL50_MASK | SEL100_MASK;
186 val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT);
187 regmap_update_bits(plat->base, PHY_CTRL5, mask, val);
188 } else {
189 switch (speed) {
190 case 200000000:
191 freqsel = 0x0;
192 break;
193 default:
194 freqsel = 0x4;
195 }
196 regmap_update_bits(plat->base, PHY_CTRL5, FREQSEL_MASK,
197 freqsel << FREQSEL_SHIFT);
198 }
Faiz Abbasce142ff2019-06-11 00:43:38 +0530199
Faiz Abbas5b29fd42021-02-04 15:10:49 +0530200 /* Configure DLL TRIM */
201 mask = DLL_TRIM_ICP_MASK;
202 val = plat->trm_icp << DLL_TRIM_ICP_SHIFT;
203
204 /* Configure DLL driver strength */
205 mask |= DR_TY_MASK;
206 val |= plat->drv_strength << DR_TY_SHIFT;
207 regmap_update_bits(plat->base, PHY_CTRL1, mask, val);
208
Faiz Abbasce142ff2019-06-11 00:43:38 +0530209 /* Enable DLL */
210 regmap_update_bits(plat->base, PHY_CTRL1, ENDLL_MASK,
211 0x1 << ENDLL_SHIFT);
212 /*
213 * Poll for DLL ready. Use a one second timeout.
214 * Works in all experiments done so far
215 */
216 ret = regmap_read_poll_timeout(plat->base, PHY_STAT1, val,
217 val & DLLRDY_MASK, 1000, 1000000);
218 if (ret)
219 return ret;
Faiz Abbasce142ff2019-06-11 00:43:38 +0530220 }
221
222 return 0;
223}
224
Faiz Abbasce142ff2019-06-11 00:43:38 +0530225int am654_sdhci_init(struct am654_sdhci_plat *plat)
226{
227 u32 ctl_cfg_2 = 0;
228 u32 mask, val;
229 int ret;
230
231 /* Reset OTAP to default value */
232 mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
233 regmap_update_bits(plat->base, PHY_CTRL4, mask, 0x0);
234
Faiz Abbas5b29fd42021-02-04 15:10:49 +0530235 if (plat->flags & DLL_CALIB) {
Faiz Abbas794453f2019-06-13 10:29:51 +0530236 regmap_read(plat->base, PHY_STAT1, &val);
237 if (~val & CALDONE_MASK) {
238 /* Calibrate IO lines */
239 regmap_update_bits(plat->base, PHY_CTRL1, PDB_MASK,
240 PDB_MASK);
241 ret = regmap_read_poll_timeout(plat->base, PHY_STAT1,
242 val, val & CALDONE_MASK,
243 1, 20);
244 if (ret)
245 return ret;
246 }
Faiz Abbasce142ff2019-06-11 00:43:38 +0530247 }
248
Faiz Abbasce142ff2019-06-11 00:43:38 +0530249 /* Enable pins by setting IO mux to 0 */
Faiz Abbasa20008e2020-01-16 19:42:19 +0530250 if (plat->flags & IOMUX_PRESENT)
251 regmap_update_bits(plat->base, PHY_CTRL1, IOMUX_ENABLE_MASK, 0);
Faiz Abbasce142ff2019-06-11 00:43:38 +0530252
253 /* Set slot type based on SD or eMMC */
254 if (plat->non_removable)
255 ctl_cfg_2 = SLOTTYPE_EMBEDDED;
256
257 regmap_update_bits(plat->base, CTL_CFG_2, SLOTTYPE_MASK, ctl_cfg_2);
258
259 return 0;
260}
261
Faiz Abbasa8512132020-02-26 13:44:34 +0530262#define MAX_SDCD_DEBOUNCE_TIME 2000
263static int am654_sdhci_deferred_probe(struct sdhci_host *host)
264{
265 struct udevice *dev = host->mmc->dev;
Simon Glassc69cda22020-12-03 16:55:20 -0700266 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Faiz Abbasa8512132020-02-26 13:44:34 +0530267 unsigned long start;
268 int val;
269
270 /*
271 * The controller takes about 1 second to debounce the card detect line
272 * and doesn't let us power on until that time is up. Instead of waiting
273 * for 1 second at every stage, poll on the CARD_PRESENT bit upto a
274 * maximum of 2 seconds to be safe..
275 */
276 start = get_timer(0);
277 do {
278 if (get_timer(start) > MAX_SDCD_DEBOUNCE_TIME)
279 return -ENOMEDIUM;
280
281 val = mmc_getcd(host->mmc);
282 } while (!val);
283
284 am654_sdhci_init(plat);
285
286 return sdhci_probe(dev);
287}
288
289const struct sdhci_ops am654_sdhci_ops = {
290 .deferred_probe = am654_sdhci_deferred_probe,
291 .set_ios_post = &am654_sdhci_set_ios_post,
292 .set_control_reg = &am654_sdhci_set_control_reg,
293};
294
295const struct am654_driver_data am654_drv_data = {
296 .ops = &am654_sdhci_ops,
Faiz Abbas8c32b5f2021-02-04 15:10:50 +0530297 .flags = DLL_PRESENT | IOMUX_PRESENT | FREQSEL_2_BIT | STRBSEL_4_BIT,
298};
299
300const struct am654_driver_data am654_sr1_drv_data = {
301 .ops = &am654_sdhci_ops,
Faiz Abbas5b29fd42021-02-04 15:10:49 +0530302 .flags = IOMUX_PRESENT | FREQSEL_2_BIT | DLL_PRESENT | DLL_CALIB |
303 STRBSEL_4_BIT,
Faiz Abbasa8512132020-02-26 13:44:34 +0530304};
305
306const struct am654_driver_data j721e_8bit_drv_data = {
307 .ops = &am654_sdhci_ops,
Faiz Abbas5b29fd42021-02-04 15:10:49 +0530308 .flags = DLL_PRESENT | DLL_CALIB,
Faiz Abbasa8512132020-02-26 13:44:34 +0530309};
310
311static int j721e_4bit_sdhci_set_ios_post(struct sdhci_host *host)
312{
313 struct udevice *dev = host->mmc->dev;
Simon Glassc69cda22020-12-03 16:55:20 -0700314 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Faiz Abbasa8512132020-02-26 13:44:34 +0530315 u32 otap_del_sel, mask, val;
316
317 otap_del_sel = plat->otap_del_sel[host->mmc->selected_mode];
318 mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
319 val = (1 << OTAPDLYENA_SHIFT) | (otap_del_sel << OTAPDLYSEL_SHIFT);
320 regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
321
322 return 0;
323}
324
325const struct sdhci_ops j721e_4bit_sdhci_ops = {
326 .deferred_probe = am654_sdhci_deferred_probe,
327 .set_ios_post = &j721e_4bit_sdhci_set_ios_post,
328};
329
330const struct am654_driver_data j721e_4bit_drv_data = {
331 .ops = &j721e_4bit_sdhci_ops,
332 .flags = IOMUX_PRESENT,
333};
334
Faiz Abbas8c32b5f2021-02-04 15:10:50 +0530335const struct soc_attr am654_sdhci_soc_attr[] = {
336 { .family = "AM65X", .revision = "SR1.0", .data = &am654_sr1_drv_data},
337 {/* sentinel */}
338};
339
Faiz Abbasc7d106b2020-02-26 13:44:33 +0530340static int sdhci_am654_get_otap_delay(struct udevice *dev,
341 struct mmc_config *cfg)
342{
Simon Glassc69cda22020-12-03 16:55:20 -0700343 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Faiz Abbasc7d106b2020-02-26 13:44:33 +0530344 int ret;
345 int i;
346
347 /* ti,otap-del-sel-legacy is mandatory */
348 ret = dev_read_u32(dev, "ti,otap-del-sel-legacy",
349 &plat->otap_del_sel[0]);
350 if (ret)
351 return ret;
352 /*
353 * Remove the corresponding capability if an otap-del-sel
354 * value is not found
355 */
356 for (i = MMC_HS; i <= MMC_HS_400; i++) {
357 ret = dev_read_u32(dev, td[i].binding, &plat->otap_del_sel[i]);
358 if (ret) {
359 dev_dbg(dev, "Couldn't find %s\n", td[i].binding);
360 /*
361 * Remove the corresponding capability
362 * if an otap-del-sel value is not found
363 */
364 cfg->host_caps &= ~td[i].capability;
365 }
366 }
367
368 return 0;
369}
370
Faiz Abbas3a1a0df2019-06-11 00:43:31 +0530371static int am654_sdhci_probe(struct udevice *dev)
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530372{
Faiz Abbasa20008e2020-01-16 19:42:19 +0530373 struct am654_driver_data *drv_data =
374 (struct am654_driver_data *)dev_get_driver_data(dev);
Simon Glassc69cda22020-12-03 16:55:20 -0700375 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530376 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
377 struct sdhci_host *host = dev_get_priv(dev);
Faiz Abbasce142ff2019-06-11 00:43:38 +0530378 struct mmc_config *cfg = &plat->cfg;
Faiz Abbas8c32b5f2021-02-04 15:10:50 +0530379 const struct soc_attr *soc;
380 const struct am654_driver_data *soc_drv_data;
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530381 struct clk clk;
382 unsigned long clock;
383 int ret;
384
Faiz Abbasfe0e30c2020-01-16 19:42:18 +0530385 ret = clk_get_by_name(dev, "clk_xin", &clk);
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530386 if (ret) {
387 dev_err(dev, "failed to get clock\n");
388 return ret;
389 }
390
391 clock = clk_get_rate(&clk);
392 if (IS_ERR_VALUE(clock)) {
393 dev_err(dev, "failed to get rate\n");
394 return clock;
395 }
396
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530397 host->max_clk = clock;
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530398 host->mmc = &plat->mmc;
Faiz Abbasce142ff2019-06-11 00:43:38 +0530399 host->mmc->dev = dev;
400 ret = sdhci_setup_cfg(cfg, host, cfg->f_max,
401 AM654_SDHCI_MIN_FREQ);
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530402 if (ret)
403 return ret;
Faiz Abbasa20008e2020-01-16 19:42:19 +0530404
Faiz Abbasc7d106b2020-02-26 13:44:33 +0530405 ret = sdhci_am654_get_otap_delay(dev, cfg);
406 if (ret)
407 return ret;
408
Faiz Abbasa20008e2020-01-16 19:42:19 +0530409 host->ops = drv_data->ops;
Faiz Abbas8c32b5f2021-02-04 15:10:50 +0530410
411 /* Update ops based on SoC revision */
412 soc = soc_device_match(am654_sdhci_soc_attr);
413 if (soc && soc->data) {
414 soc_drv_data = soc->data;
415 host->ops = soc_drv_data->ops;
416 }
417
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530418 host->mmc->priv = host;
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530419 upriv->mmc = host->mmc;
420
Faiz Abbasce142ff2019-06-11 00:43:38 +0530421 regmap_init_mem_index(dev_ofnode(dev), &plat->base, 1);
422
Faiz Abbasa8512132020-02-26 13:44:34 +0530423 return 0;
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530424}
425
Simon Glassd1998a92020-12-03 16:55:21 -0700426static int am654_sdhci_of_to_plat(struct udevice *dev)
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530427{
Simon Glassc69cda22020-12-03 16:55:20 -0700428 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530429 struct sdhci_host *host = dev_get_priv(dev);
Faiz Abbasce142ff2019-06-11 00:43:38 +0530430 struct mmc_config *cfg = &plat->cfg;
431 u32 drv_strength;
432 int ret;
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530433
434 host->name = dev->name;
435 host->ioaddr = (void *)dev_read_addr(dev);
Faiz Abbasce142ff2019-06-11 00:43:38 +0530436 plat->non_removable = dev_read_bool(dev, "non-removable");
437
Faiz Abbas794453f2019-06-13 10:29:51 +0530438 if (plat->flags & DLL_PRESENT) {
439 ret = dev_read_u32(dev, "ti,trm-icp", &plat->trm_icp);
440 if (ret)
441 return ret;
Faiz Abbasce142ff2019-06-11 00:43:38 +0530442
Faiz Abbas794453f2019-06-13 10:29:51 +0530443 ret = dev_read_u32(dev, "ti,driver-strength-ohm",
444 &drv_strength);
445 if (ret)
446 return ret;
447
448 switch (drv_strength) {
449 case 50:
450 plat->drv_strength = DRIVER_STRENGTH_50_OHM;
451 break;
452 case 33:
453 plat->drv_strength = DRIVER_STRENGTH_33_OHM;
454 break;
455 case 66:
456 plat->drv_strength = DRIVER_STRENGTH_66_OHM;
457 break;
458 case 100:
459 plat->drv_strength = DRIVER_STRENGTH_100_OHM;
460 break;
461 case 40:
462 plat->drv_strength = DRIVER_STRENGTH_40_OHM;
463 break;
464 default:
465 dev_err(dev, "Invalid driver strength\n");
466 return -EINVAL;
467 }
Faiz Abbasce142ff2019-06-11 00:43:38 +0530468 }
469
470 ret = mmc_of_parse(dev, cfg);
471 if (ret)
472 return ret;
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530473
474 return 0;
475}
476
Faiz Abbas3a1a0df2019-06-11 00:43:31 +0530477static int am654_sdhci_bind(struct udevice *dev)
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530478{
Faiz Abbasa20008e2020-01-16 19:42:19 +0530479 struct am654_driver_data *drv_data =
480 (struct am654_driver_data *)dev_get_driver_data(dev);
Simon Glassc69cda22020-12-03 16:55:20 -0700481 struct am654_sdhci_plat *plat = dev_get_plat(dev);
Faiz Abbas8c32b5f2021-02-04 15:10:50 +0530482 const struct soc_attr *soc;
483 const struct am654_driver_data *soc_drv_data;
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530484
Faiz Abbasa20008e2020-01-16 19:42:19 +0530485 plat->flags = drv_data->flags;
486
Faiz Abbas8c32b5f2021-02-04 15:10:50 +0530487 /* Update flags based on SoC revision */
488 soc = soc_device_match(am654_sdhci_soc_attr);
489 if (soc && soc->data) {
490 soc_drv_data = soc->data;
491 plat->flags = soc_drv_data->flags;
492 }
493
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530494 return sdhci_bind(dev, &plat->mmc, &plat->cfg);
495}
496
Faiz Abbas3a1a0df2019-06-11 00:43:31 +0530497static const struct udevice_id am654_sdhci_ids[] = {
Faiz Abbas794453f2019-06-13 10:29:51 +0530498 {
499 .compatible = "ti,am654-sdhci-5.1",
Faiz Abbasa20008e2020-01-16 19:42:19 +0530500 .data = (ulong)&am654_drv_data,
Faiz Abbas794453f2019-06-13 10:29:51 +0530501 },
502 {
503 .compatible = "ti,j721e-sdhci-8bit",
Faiz Abbasa20008e2020-01-16 19:42:19 +0530504 .data = (ulong)&j721e_8bit_drv_data,
Faiz Abbas794453f2019-06-13 10:29:51 +0530505 },
506 {
507 .compatible = "ti,j721e-sdhci-4bit",
Faiz Abbasa20008e2020-01-16 19:42:19 +0530508 .data = (ulong)&j721e_4bit_drv_data,
Faiz Abbas794453f2019-06-13 10:29:51 +0530509 },
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530510 { }
511};
512
Faiz Abbas3a1a0df2019-06-11 00:43:31 +0530513U_BOOT_DRIVER(am654_sdhci_drv) = {
514 .name = "am654_sdhci",
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530515 .id = UCLASS_MMC,
Faiz Abbas3a1a0df2019-06-11 00:43:31 +0530516 .of_match = am654_sdhci_ids,
Simon Glassd1998a92020-12-03 16:55:21 -0700517 .of_to_plat = am654_sdhci_of_to_plat,
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530518 .ops = &sdhci_ops,
Faiz Abbas3a1a0df2019-06-11 00:43:31 +0530519 .bind = am654_sdhci_bind,
520 .probe = am654_sdhci_probe,
Simon Glass41575d82020-12-03 16:55:17 -0700521 .priv_auto = sizeof(struct sdhci_host),
Simon Glasscaa4daa2020-12-03 16:55:18 -0700522 .plat_auto = sizeof(struct am654_sdhci_plat),
Lokesh Vutlaaaa449f2018-08-27 15:57:54 +0530523};