blob: 5107fcd836259285da36f93dbecff24d9b7ba888 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Sandeep Paulraj50347172010-12-20 20:01:21 -05002/*
3 * Davinci MMC Controller Driver
4 *
5 * Copyright (C) 2010 Texas Instruments Incorporated
Sandeep Paulraj50347172010-12-20 20:01:21 -05006 */
7
8#include <config.h>
Adam Ford8ce7bdd2018-08-09 06:15:12 -05009#include <dm.h>
Jaehoon Chung7825d202016-07-19 16:33:36 +090010#include <errno.h>
Sandeep Paulraj50347172010-12-20 20:01:21 -050011#include <mmc.h>
Adam Ford8ce7bdd2018-08-09 06:15:12 -050012#include <command.h>
Sandeep Paulraj50347172010-12-20 20:01:21 -050013#include <part.h>
14#include <malloc.h>
15#include <asm/io.h>
16#include <asm/arch/sdmmc_defs.h>
Adam Ford7d9bdcc2018-09-03 03:47:52 -050017#include <asm-generic/gpio.h>
Simon Glassdbd79542020-05-10 11:40:11 -060018#include <linux/delay.h>
Sandeep Paulraj50347172010-12-20 20:01:21 -050019
Sandeep Paulraj50347172010-12-20 20:01:21 -050020#define WATCHDOG_COUNT (100000)
21
22#define get_val(addr) REG(addr)
23#define set_val(addr, val) REG(addr) = (val)
24#define set_bit(addr, val) set_val((addr), (get_val(addr) | (val)))
25#define clear_bit(addr, val) set_val((addr), (get_val(addr) & ~(val)))
26
Adam Ford8ce7bdd2018-08-09 06:15:12 -050027#ifdef CONFIG_DM_MMC
Adam Ford8ce7bdd2018-08-09 06:15:12 -050028/* Davinci MMC board definitions */
29struct davinci_mmc_priv {
30 struct davinci_mmc_regs *reg_base; /* Register base address */
31 uint input_clk; /* Input clock to MMC controller */
Adam Ford7d9bdcc2018-09-03 03:47:52 -050032 struct gpio_desc cd_gpio; /* Card Detect GPIO */
33 struct gpio_desc wp_gpio; /* Write Protect GPIO */
Tom Rini131f4ad2020-01-03 12:00:04 -050034};
Adam Ford8ce7bdd2018-08-09 06:15:12 -050035#endif
36
Sandeep Paulraj50347172010-12-20 20:01:21 -050037/* Set davinci clock prescalar value based on the required clock in HZ */
Adam Ford8ce7bdd2018-08-09 06:15:12 -050038#if !CONFIG_IS_ENABLED(DM_MMC)
Sandeep Paulraj50347172010-12-20 20:01:21 -050039static void dmmc_set_clock(struct mmc *mmc, uint clock)
40{
41 struct davinci_mmc *host = mmc->priv;
Adam Ford8ce7bdd2018-08-09 06:15:12 -050042#else
43
44static void davinci_mmc_set_clock(struct udevice *dev, uint clock)
45{
46 struct davinci_mmc_priv *host = dev_get_priv(dev);
47 struct mmc *mmc = mmc_get_mmc_dev(dev);
48#endif
Sandeep Paulraj50347172010-12-20 20:01:21 -050049 struct davinci_mmc_regs *regs = host->reg_base;
50 uint clkrt, sysclk2, act_clock;
51
Pantelis Antoniou2c850462014-03-11 19:34:20 +020052 if (clock < mmc->cfg->f_min)
53 clock = mmc->cfg->f_min;
54 if (clock > mmc->cfg->f_max)
55 clock = mmc->cfg->f_max;
Sandeep Paulraj50347172010-12-20 20:01:21 -050056
57 set_val(&regs->mmcclk, 0);
58 sysclk2 = host->input_clk;
59 clkrt = (sysclk2 / (2 * clock)) - 1;
60
61 /* Calculate the actual clock for the divider used */
62 act_clock = (sysclk2 / (2 * (clkrt + 1)));
63
64 /* Adjust divider if actual clock exceeds the required clock */
65 if (act_clock > clock)
66 clkrt++;
67
68 /* check clock divider boundary and correct it */
69 if (clkrt > 0xFF)
70 clkrt = 0xFF;
71
72 set_val(&regs->mmcclk, (clkrt | MMCCLK_CLKEN));
73}
74
75/* Status bit wait loop for MMCST1 */
76static int
77dmmc_wait_fifo_status(volatile struct davinci_mmc_regs *regs, uint status)
78{
Heiko Schocher1a3d7492011-10-30 19:15:53 +000079 uint wdog = WATCHDOG_COUNT;
80
Sandeep Paulraj50347172010-12-20 20:01:21 -050081 while (--wdog && ((get_val(&regs->mmcst1) & status) != status))
82 udelay(10);
83
84 if (!(get_val(&regs->mmcctl) & MMCCTL_WIDTH_4_BIT))
85 udelay(100);
86
87 if (wdog == 0)
Jaehoon Chung7825d202016-07-19 16:33:36 +090088 return -ECOMM;
Sandeep Paulraj50347172010-12-20 20:01:21 -050089
90 return 0;
91}
92
93/* Busy bit wait loop for MMCST1 */
94static int dmmc_busy_wait(volatile struct davinci_mmc_regs *regs)
95{
Heiko Schocher1a3d7492011-10-30 19:15:53 +000096 uint wdog = WATCHDOG_COUNT;
Sandeep Paulraj50347172010-12-20 20:01:21 -050097
Sandeep Paulraj50347172010-12-20 20:01:21 -050098 while (--wdog && (get_val(&regs->mmcst1) & MMCST1_BUSY))
99 udelay(10);
100
101 if (wdog == 0)
Jaehoon Chung7825d202016-07-19 16:33:36 +0900102 return -ECOMM;
Sandeep Paulraj50347172010-12-20 20:01:21 -0500103
104 return 0;
105}
106
107/* Status bit wait loop for MMCST0 - Checks for error bits as well */
108static int dmmc_check_status(volatile struct davinci_mmc_regs *regs,
109 uint *cur_st, uint st_ready, uint st_error)
110{
111 uint wdog = WATCHDOG_COUNT;
112 uint mmcstatus = *cur_st;
113
114 while (wdog--) {
115 if (mmcstatus & st_ready) {
116 *cur_st = mmcstatus;
117 mmcstatus = get_val(&regs->mmcst1);
118 return 0;
119 } else if (mmcstatus & st_error) {
120 if (mmcstatus & MMCST0_TOUTRS)
Jaehoon Chung7825d202016-07-19 16:33:36 +0900121 return -ETIMEDOUT;
Sandeep Paulraj50347172010-12-20 20:01:21 -0500122 printf("[ ST0 ERROR %x]\n", mmcstatus);
123 /*
124 * Ignore CRC errors as some MMC cards fail to
125 * initialize on DM365-EVM on the SD1 slot
126 */
127 if (mmcstatus & MMCST0_CRCRS)
128 return 0;
Jaehoon Chung7825d202016-07-19 16:33:36 +0900129 return -ECOMM;
Sandeep Paulraj50347172010-12-20 20:01:21 -0500130 }
131 udelay(10);
132
133 mmcstatus = get_val(&regs->mmcst0);
134 }
135
136 printf("Status %x Timeout ST0:%x ST1:%x\n", st_ready, mmcstatus,
137 get_val(&regs->mmcst1));
Jaehoon Chung7825d202016-07-19 16:33:36 +0900138 return -ECOMM;
Sandeep Paulraj50347172010-12-20 20:01:21 -0500139}
140
141/*
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500142 * Sends a command out on the bus. Takes the device pointer,
Sandeep Paulraj50347172010-12-20 20:01:21 -0500143 * a command pointer, and an optional data pointer.
144 */
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500145#if !CONFIG_IS_ENABLED(DM_MMC)
146static int dmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
Sandeep Paulraj50347172010-12-20 20:01:21 -0500147{
148 struct davinci_mmc *host = mmc->priv;
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500149#else
150static int
151davinci_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct mmc_data *data)
152{
153 struct davinci_mmc_priv *host = dev_get_priv(dev);
154#endif
Sandeep Paulraj50347172010-12-20 20:01:21 -0500155 volatile struct davinci_mmc_regs *regs = host->reg_base;
156 uint mmcstatus, status_rdy, status_err;
157 uint i, cmddata, bytes_left = 0;
158 int fifo_words, fifo_bytes, err;
159 char *data_buf = NULL;
160
161 /* Clear status registers */
162 mmcstatus = get_val(&regs->mmcst0);
Bartosz Golaszewski3dffb442019-11-14 16:10:28 +0100163 fifo_words = 16;
Sandeep Paulraj50347172010-12-20 20:01:21 -0500164 fifo_bytes = fifo_words << 2;
165
166 /* Wait for any previous busy signal to be cleared */
167 dmmc_busy_wait(regs);
168
169 cmddata = cmd->cmdidx;
170 cmddata |= MMCCMD_PPLEN;
171
172 /* Send init clock for CMD0 */
173 if (cmd->cmdidx == MMC_CMD_GO_IDLE_STATE)
174 cmddata |= MMCCMD_INITCK;
175
176 switch (cmd->resp_type) {
177 case MMC_RSP_R1b:
178 cmddata |= MMCCMD_BSYEXP;
179 /* Fall-through */
180 case MMC_RSP_R1: /* R1, R1b, R5, R6, R7 */
181 cmddata |= MMCCMD_RSPFMT_R1567;
182 break;
183 case MMC_RSP_R2:
184 cmddata |= MMCCMD_RSPFMT_R2;
185 break;
186 case MMC_RSP_R3: /* R3, R4 */
187 cmddata |= MMCCMD_RSPFMT_R3;
188 break;
189 }
190
191 set_val(&regs->mmcim, 0);
192
193 if (data) {
194 /* clear previous data transfer if any and set new one */
195 bytes_left = (data->blocksize * data->blocks);
196
197 /* Reset FIFO - Always use 32 byte fifo threshold */
198 set_val(&regs->mmcfifoctl,
199 (MMCFIFOCTL_FIFOLEV | MMCFIFOCTL_FIFORST));
200
Bartosz Golaszewski3dffb442019-11-14 16:10:28 +0100201 cmddata |= MMCCMD_DMATRIG;
Sandeep Paulraj50347172010-12-20 20:01:21 -0500202
203 cmddata |= MMCCMD_WDATX;
204 if (data->flags == MMC_DATA_READ) {
205 set_val(&regs->mmcfifoctl, MMCFIFOCTL_FIFOLEV);
206 } else if (data->flags == MMC_DATA_WRITE) {
207 set_val(&regs->mmcfifoctl,
208 (MMCFIFOCTL_FIFOLEV |
209 MMCFIFOCTL_FIFODIR));
210 cmddata |= MMCCMD_DTRW;
211 }
212
213 set_val(&regs->mmctod, 0xFFFF);
214 set_val(&regs->mmcnblk, (data->blocks & MMCNBLK_NBLK_MASK));
215 set_val(&regs->mmcblen, (data->blocksize & MMCBLEN_BLEN_MASK));
216
217 if (data->flags == MMC_DATA_WRITE) {
218 uint val;
219 data_buf = (char *)data->src;
220 /* For write, fill FIFO with data before issue of CMD */
221 for (i = 0; (i < fifo_words) && bytes_left; i++) {
222 memcpy((char *)&val, data_buf, 4);
223 set_val(&regs->mmcdxr, val);
224 data_buf += 4;
225 bytes_left -= 4;
226 }
227 }
228 } else {
229 set_val(&regs->mmcblen, 0);
230 set_val(&regs->mmcnblk, 0);
231 }
232
233 set_val(&regs->mmctor, 0x1FFF);
234
235 /* Send the command */
236 set_val(&regs->mmcarghl, cmd->cmdarg);
237 set_val(&regs->mmccmd, cmddata);
238
239 status_rdy = MMCST0_RSPDNE;
240 status_err = (MMCST0_TOUTRS | MMCST0_TOUTRD |
241 MMCST0_CRCWR | MMCST0_CRCRD);
242 if (cmd->resp_type & MMC_RSP_CRC)
243 status_err |= MMCST0_CRCRS;
244
245 mmcstatus = get_val(&regs->mmcst0);
246 err = dmmc_check_status(regs, &mmcstatus, status_rdy, status_err);
247 if (err)
248 return err;
249
250 /* For R1b wait for busy done */
251 if (cmd->resp_type == MMC_RSP_R1b)
252 dmmc_busy_wait(regs);
253
254 /* Collect response from controller for specific commands */
255 if (mmcstatus & MMCST0_RSPDNE) {
256 /* Copy the response to the response buffer */
257 if (cmd->resp_type & MMC_RSP_136) {
258 cmd->response[0] = get_val(&regs->mmcrsp67);
259 cmd->response[1] = get_val(&regs->mmcrsp45);
260 cmd->response[2] = get_val(&regs->mmcrsp23);
261 cmd->response[3] = get_val(&regs->mmcrsp01);
262 } else if (cmd->resp_type & MMC_RSP_PRESENT) {
263 cmd->response[0] = get_val(&regs->mmcrsp67);
264 }
265 }
266
267 if (data == NULL)
268 return 0;
269
270 if (data->flags == MMC_DATA_READ) {
271 /* check for DATDNE along with DRRDY as the controller might
272 * set the DATDNE without DRRDY for smaller transfers with
273 * less than FIFO threshold bytes
274 */
275 status_rdy = MMCST0_DRRDY | MMCST0_DATDNE;
276 status_err = MMCST0_TOUTRD | MMCST0_CRCRD;
277 data_buf = data->dest;
278 } else {
279 status_rdy = MMCST0_DXRDY | MMCST0_DATDNE;
280 status_err = MMCST0_CRCWR;
281 }
282
283 /* Wait until all of the blocks are transferred */
284 while (bytes_left) {
285 err = dmmc_check_status(regs, &mmcstatus, status_rdy,
286 status_err);
287 if (err)
288 return err;
289
290 if (data->flags == MMC_DATA_READ) {
291 /*
292 * MMC controller sets the Data receive ready bit
293 * (DRRDY) in MMCST0 even before the entire FIFO is
294 * full. This results in erratic behavior if we start
295 * reading the FIFO soon after DRRDY. Wait for the
296 * FIFO full bit in MMCST1 for proper FIFO clearing.
297 */
298 if (bytes_left > fifo_bytes)
299 dmmc_wait_fifo_status(regs, 0x4a);
Davide Bonfantif7289ee2012-11-29 01:06:53 +0000300 else if (bytes_left == fifo_bytes) {
Sandeep Paulraj50347172010-12-20 20:01:21 -0500301 dmmc_wait_fifo_status(regs, 0x40);
Davide Bonfantif7289ee2012-11-29 01:06:53 +0000302 if (cmd->cmdidx == MMC_CMD_SEND_EXT_CSD)
303 udelay(600);
304 }
Sandeep Paulraj50347172010-12-20 20:01:21 -0500305
306 for (i = 0; bytes_left && (i < fifo_words); i++) {
307 cmddata = get_val(&regs->mmcdrr);
308 memcpy(data_buf, (char *)&cmddata, 4);
309 data_buf += 4;
310 bytes_left -= 4;
311 }
312 } else {
313 /*
314 * MMC controller sets the Data transmit ready bit
315 * (DXRDY) in MMCST0 even before the entire FIFO is
316 * empty. This results in erratic behavior if we start
317 * writing the FIFO soon after DXRDY. Wait for the
318 * FIFO empty bit in MMCST1 for proper FIFO clearing.
319 */
320 dmmc_wait_fifo_status(regs, MMCST1_FIFOEMP);
321 for (i = 0; bytes_left && (i < fifo_words); i++) {
322 memcpy((char *)&cmddata, data_buf, 4);
323 set_val(&regs->mmcdxr, cmddata);
324 data_buf += 4;
325 bytes_left -= 4;
326 }
327 dmmc_busy_wait(regs);
328 }
329 }
330
331 err = dmmc_check_status(regs, &mmcstatus, MMCST0_DATDNE, status_err);
332 if (err)
333 return err;
334
335 return 0;
336}
337
338/* Initialize Davinci MMC controller */
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500339#if !CONFIG_IS_ENABLED(DM_MMC)
Sandeep Paulraj50347172010-12-20 20:01:21 -0500340static int dmmc_init(struct mmc *mmc)
341{
342 struct davinci_mmc *host = mmc->priv;
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500343#else
344static int davinci_dm_mmc_init(struct udevice *dev)
345{
346 struct davinci_mmc_priv *host = dev_get_priv(dev);
347#endif
Sandeep Paulraj50347172010-12-20 20:01:21 -0500348 struct davinci_mmc_regs *regs = host->reg_base;
349
350 /* Clear status registers explicitly - soft reset doesn't clear it
351 * If Uboot is invoked from UBL with SDMMC Support, the status
352 * registers can have uncleared bits
353 */
354 get_val(&regs->mmcst0);
355 get_val(&regs->mmcst1);
356
357 /* Hold software reset */
358 set_bit(&regs->mmcctl, MMCCTL_DATRST);
359 set_bit(&regs->mmcctl, MMCCTL_CMDRST);
360 udelay(10);
361
362 set_val(&regs->mmcclk, 0x0);
363 set_val(&regs->mmctor, 0x1FFF);
364 set_val(&regs->mmctod, 0xFFFF);
365
366 /* Clear software reset */
367 clear_bit(&regs->mmcctl, MMCCTL_DATRST);
368 clear_bit(&regs->mmcctl, MMCCTL_CMDRST);
369
370 udelay(10);
371
372 /* Reset FIFO - Always use the maximum fifo threshold */
373 set_val(&regs->mmcfifoctl, (MMCFIFOCTL_FIFOLEV | MMCFIFOCTL_FIFORST));
374 set_val(&regs->mmcfifoctl, MMCFIFOCTL_FIFOLEV);
375
376 return 0;
377}
378
Masahiro Yamada0a780172017-05-09 20:31:39 +0900379/* Set buswidth or clock as indicated by the MMC framework */
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500380#if !CONFIG_IS_ENABLED(DM_MMC)
Jaehoon Chungb6cd1d32016-12-30 15:30:16 +0900381static int dmmc_set_ios(struct mmc *mmc)
Sandeep Paulraj50347172010-12-20 20:01:21 -0500382{
383 struct davinci_mmc *host = mmc->priv;
384 struct davinci_mmc_regs *regs = host->reg_base;
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500385#else
386static int davinci_mmc_set_ios(struct udevice *dev)
387{
388 struct mmc *mmc = mmc_get_mmc_dev(dev);
Sandeep Paulraj50347172010-12-20 20:01:21 -0500389
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500390 struct davinci_mmc_priv *host = dev_get_priv(dev);
391 struct davinci_mmc_regs *regs = host->reg_base;
392#endif
Sandeep Paulraj50347172010-12-20 20:01:21 -0500393 /* Set the bus width */
394 if (mmc->bus_width == 4)
395 set_bit(&regs->mmcctl, MMCCTL_WIDTH_4_BIT);
396 else
397 clear_bit(&regs->mmcctl, MMCCTL_WIDTH_4_BIT);
398
399 /* Set clock speed */
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500400 if (mmc->clock) {
401#if !CONFIG_IS_ENABLED(DM_MMC)
Sandeep Paulraj50347172010-12-20 20:01:21 -0500402 dmmc_set_clock(mmc, mmc->clock);
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500403#else
404 davinci_mmc_set_clock(dev, mmc->clock);
405#endif
406 }
Jaehoon Chungb6cd1d32016-12-30 15:30:16 +0900407 return 0;
Sandeep Paulraj50347172010-12-20 20:01:21 -0500408}
409
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500410#if !CONFIG_IS_ENABLED(DM_MMC)
Pantelis Antoniouc9e75912014-02-26 19:28:45 +0200411static const struct mmc_ops dmmc_ops = {
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500412 .send_cmd = dmmc_send_cmd,
413 .set_ios = dmmc_set_ios,
414 .init = dmmc_init,
Pantelis Antoniouc9e75912014-02-26 19:28:45 +0200415};
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500416#else
Adam Ford7d9bdcc2018-09-03 03:47:52 -0500417
418static int davinci_mmc_getcd(struct udevice *dev)
419{
420 int value = -1;
421#if CONFIG_IS_ENABLED(DM_GPIO)
422 struct davinci_mmc_priv *priv = dev_get_priv(dev);
423 value = dm_gpio_get_value(&priv->cd_gpio);
424#endif
425 /* if no CD return as 1 */
426 if (value < 0)
427 return 1;
428
429 return value;
430}
431
432static int davinci_mmc_getwp(struct udevice *dev)
433{
434 int value = -1;
435#if CONFIG_IS_ENABLED(DM_GPIO)
436 struct davinci_mmc_priv *priv = dev_get_priv(dev);
437
438 value = dm_gpio_get_value(&priv->wp_gpio);
439#endif
440 /* if no WP return as 0 */
441 if (value < 0)
442 return 0;
443
444 return value;
445}
446
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500447static const struct dm_mmc_ops davinci_mmc_ops = {
448 .send_cmd = davinci_mmc_send_cmd,
449 .set_ios = davinci_mmc_set_ios,
Adam Ford7d9bdcc2018-09-03 03:47:52 -0500450 .get_cd = davinci_mmc_getcd,
451 .get_wp = davinci_mmc_getwp,
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500452};
453#endif
Pantelis Antoniouc9e75912014-02-26 19:28:45 +0200454
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500455#if !CONFIG_IS_ENABLED(DM_MMC)
Sandeep Paulraj50347172010-12-20 20:01:21 -0500456/* Called from board_mmc_init during startup. Can be called multiple times
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500457* depending on the number of slots available on board and controller
458*/
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +0900459int davinci_mmc_init(struct bd_info *bis, struct davinci_mmc *host)
Sandeep Paulraj50347172010-12-20 20:01:21 -0500460{
Pantelis Antoniou2c850462014-03-11 19:34:20 +0200461 host->cfg.name = "davinci";
462 host->cfg.ops = &dmmc_ops;
463 host->cfg.f_min = 200000;
464 host->cfg.f_max = 25000000;
465 host->cfg.voltages = host->voltages;
466 host->cfg.host_caps = host->host_caps;
Sandeep Paulraj50347172010-12-20 20:01:21 -0500467
Pantelis Antoniou2c850462014-03-11 19:34:20 +0200468 host->cfg.b_max = DAVINCI_MAX_BLOCKS;
John Rigbyf2f43662011-04-18 05:50:08 +0000469
Pantelis Antoniou2c850462014-03-11 19:34:20 +0200470 mmc_create(&host->cfg, host);
Sandeep Paulraj50347172010-12-20 20:01:21 -0500471
472 return 0;
473}
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500474#else
475
476
477static int davinci_mmc_probe(struct udevice *dev)
478{
479 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
Simon Glassfa20e932020-12-03 16:55:20 -0700480 struct davinci_mmc_plat *plat = dev_get_plat(dev);
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500481 struct davinci_mmc_priv *priv = dev_get_priv(dev);
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500482
Faiz Abbasae01d762020-05-22 07:32:28 +0530483 priv->reg_base = plat->reg_base;
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500484 priv->input_clk = clk_get(DAVINCI_MMCSD_CLKID);
Adam Ford7d9bdcc2018-09-03 03:47:52 -0500485#if CONFIG_IS_ENABLED(DM_GPIO)
486 /* These GPIOs are optional */
487 gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN);
488 gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio, GPIOD_IS_IN);
489#endif
Tom Rini131f4ad2020-01-03 12:00:04 -0500490 upriv->mmc = &plat->mmc;
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500491
492 return davinci_dm_mmc_init(dev);
493}
494
495static int davinci_mmc_bind(struct udevice *dev)
496{
Simon Glassfa20e932020-12-03 16:55:20 -0700497 struct davinci_mmc_plat *plat = dev_get_plat(dev);
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500498
Tom Rini131f4ad2020-01-03 12:00:04 -0500499 return mmc_bind(dev, &plat->mmc, &plat->cfg);
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500500}
501
Faiz Abbasae01d762020-05-22 07:32:28 +0530502#if CONFIG_IS_ENABLED(OF_CONTROL)
Simon Glassaad29ae2020-12-03 16:55:21 -0700503static int davinci_mmc_of_to_plat(struct udevice *dev)
Faiz Abbasae01d762020-05-22 07:32:28 +0530504{
Simon Glassfa20e932020-12-03 16:55:20 -0700505 struct davinci_mmc_plat *plat = dev_get_plat(dev);
Faiz Abbasae01d762020-05-22 07:32:28 +0530506 struct mmc_config *cfg = &plat->cfg;
507
Johan Jonker8d5d8e02023-03-13 01:32:04 +0100508 plat->reg_base = dev_read_addr_ptr(dev);
Faiz Abbasae01d762020-05-22 07:32:28 +0530509 cfg->f_min = 200000;
510 cfg->f_max = 25000000;
511 cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34,
512 cfg->host_caps = MMC_MODE_4BIT, /* DA850 supports only 4-bit SD/MMC */
513 cfg->b_max = DAVINCI_MAX_BLOCKS;
514 cfg->name = "da830-mmc";
515
516 return 0;
517}
518
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500519static const struct udevice_id davinci_mmc_ids[] = {
Bartosz Golaszewski3dffb442019-11-14 16:10:28 +0100520 { .compatible = "ti,da830-mmc" },
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500521 {},
522};
Faiz Abbasae01d762020-05-22 07:32:28 +0530523#endif
Walter Lozano2901ac62020-06-25 01:10:04 -0300524U_BOOT_DRIVER(ti_da830_mmc) = {
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500525 .name = "davinci_mmc",
526 .id = UCLASS_MMC,
Faiz Abbasae01d762020-05-22 07:32:28 +0530527#if CONFIG_IS_ENABLED(OF_CONTROL)
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500528 .of_match = davinci_mmc_ids,
Simon Glass71fa5b42020-12-03 16:55:18 -0700529 .plat_auto = sizeof(struct davinci_mmc_plat),
Simon Glassaad29ae2020-12-03 16:55:21 -0700530 .of_to_plat = davinci_mmc_of_to_plat,
Faiz Abbasae01d762020-05-22 07:32:28 +0530531#endif
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500532#if CONFIG_BLK
533 .bind = davinci_mmc_bind,
534#endif
535 .probe = davinci_mmc_probe,
536 .ops = &davinci_mmc_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700537 .priv_auto = sizeof(struct davinci_mmc_priv),
Faiz Abbasae01d762020-05-22 07:32:28 +0530538#if !CONFIG_IS_ENABLED(OF_CONTROL)
539 .flags = DM_FLAG_PRE_RELOC,
540#endif
Adam Ford8ce7bdd2018-08-09 06:15:12 -0500541};
542#endif