blob: 84dae4d8bd8055d9f5cd78a6b421d7413a61f24c [file] [log] [blame]
Andy Fleming272cc702008-10-30 16:41:01 -05001/*
2 * Copyright 2008, Freescale Semiconductor, Inc
3 * Andy Fleming
4 *
5 * Based vaguely on the Linux code
6 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02007 * SPDX-License-Identifier: GPL-2.0+
Andy Fleming272cc702008-10-30 16:41:01 -05008 */
9
10#include <config.h>
11#include <common.h>
12#include <command.h>
13#include <mmc.h>
14#include <part.h>
15#include <malloc.h>
16#include <linux/list.h>
Rabin Vincent9b1f9422009-04-05 13:30:54 +053017#include <div64.h>
Paul Burtonda61fa52013-09-09 15:30:26 +010018#include "mmc_private.h"
Andy Fleming272cc702008-10-30 16:41:01 -050019
Matt Waddelce0fbcd2011-02-24 16:35:23 +000020/* Set block count limit because of 16 bit register limit on some hardware*/
21#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
22#define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535
23#endif
24
Andy Fleming272cc702008-10-30 16:41:01 -050025static struct list_head mmc_devices;
26static int cur_dev_num = -1;
27
Nikita Kiryanovd23d8d72012-12-03 02:19:46 +000028int __weak board_mmc_getwp(struct mmc *mmc)
29{
30 return -1;
31}
32
33int mmc_getwp(struct mmc *mmc)
34{
35 int wp;
36
37 wp = board_mmc_getwp(mmc);
38
Peter Korsgaardd4e1da42013-03-21 04:00:03 +000039 if (wp < 0) {
40 if (mmc->getwp)
41 wp = mmc->getwp(mmc);
42 else
43 wp = 0;
44 }
Nikita Kiryanovd23d8d72012-12-03 02:19:46 +000045
46 return wp;
47}
48
Thierry Reding314284b2012-01-02 01:15:36 +000049int __board_mmc_getcd(struct mmc *mmc) {
Stefano Babic11fdade2010-02-05 15:04:43 +010050 return -1;
51}
52
Thierry Reding314284b2012-01-02 01:15:36 +000053int board_mmc_getcd(struct mmc *mmc)__attribute__((weak,
Stefano Babic11fdade2010-02-05 15:04:43 +010054 alias("__board_mmc_getcd")));
55
Paul Burtonda61fa52013-09-09 15:30:26 +010056int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
Andy Fleming272cc702008-10-30 16:41:01 -050057{
Raffaele Recalcati5db2fe32011-03-11 02:01:14 +000058 int ret;
Marek Vasut8635ff92012-03-15 18:41:35 +000059
Marek Vasut8635ff92012-03-15 18:41:35 +000060#ifdef CONFIG_MMC_TRACE
Raffaele Recalcati5db2fe32011-03-11 02:01:14 +000061 int i;
62 u8 *ptr;
63
64 printf("CMD_SEND:%d\n", cmd->cmdidx);
65 printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
Raffaele Recalcati5db2fe32011-03-11 02:01:14 +000066 ret = mmc->send_cmd(mmc, cmd, data);
67 switch (cmd->resp_type) {
68 case MMC_RSP_NONE:
69 printf("\t\tMMC_RSP_NONE\n");
70 break;
71 case MMC_RSP_R1:
72 printf("\t\tMMC_RSP_R1,5,6,7 \t 0x%08X \n",
73 cmd->response[0]);
74 break;
75 case MMC_RSP_R1b:
76 printf("\t\tMMC_RSP_R1b\t\t 0x%08X \n",
77 cmd->response[0]);
78 break;
79 case MMC_RSP_R2:
80 printf("\t\tMMC_RSP_R2\t\t 0x%08X \n",
81 cmd->response[0]);
82 printf("\t\t \t\t 0x%08X \n",
83 cmd->response[1]);
84 printf("\t\t \t\t 0x%08X \n",
85 cmd->response[2]);
86 printf("\t\t \t\t 0x%08X \n",
87 cmd->response[3]);
88 printf("\n");
89 printf("\t\t\t\t\tDUMPING DATA\n");
90 for (i = 0; i < 4; i++) {
91 int j;
92 printf("\t\t\t\t\t%03d - ", i*4);
Dirk Behme146bec72012-03-08 02:35:34 +000093 ptr = (u8 *)&cmd->response[i];
Raffaele Recalcati5db2fe32011-03-11 02:01:14 +000094 ptr += 3;
95 for (j = 0; j < 4; j++)
96 printf("%02X ", *ptr--);
97 printf("\n");
98 }
99 break;
100 case MMC_RSP_R3:
101 printf("\t\tMMC_RSP_R3,4\t\t 0x%08X \n",
102 cmd->response[0]);
103 break;
104 default:
105 printf("\t\tERROR MMC rsp not supported\n");
106 break;
107 }
Raffaele Recalcati5db2fe32011-03-11 02:01:14 +0000108#else
Marek Vasut8635ff92012-03-15 18:41:35 +0000109 ret = mmc->send_cmd(mmc, cmd, data);
Raffaele Recalcati5db2fe32011-03-11 02:01:14 +0000110#endif
Marek Vasut8635ff92012-03-15 18:41:35 +0000111 return ret;
Andy Fleming272cc702008-10-30 16:41:01 -0500112}
113
Paul Burtonda61fa52013-09-09 15:30:26 +0100114int mmc_send_status(struct mmc *mmc, int timeout)
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000115{
116 struct mmc_cmd cmd;
Jan Kloetzked617c422012-02-05 22:29:12 +0000117 int err, retries = 5;
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000118#ifdef CONFIG_MMC_TRACE
119 int status;
120#endif
121
122 cmd.cmdidx = MMC_CMD_SEND_STATUS;
123 cmd.resp_type = MMC_RSP_R1;
Marek Vasutaaf3d412011-08-10 09:24:48 +0200124 if (!mmc_host_is_spi(mmc))
125 cmd.cmdarg = mmc->rca << 16;
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000126
127 do {
128 err = mmc_send_cmd(mmc, &cmd, NULL);
Jan Kloetzked617c422012-02-05 22:29:12 +0000129 if (!err) {
130 if ((cmd.response[0] & MMC_STATUS_RDY_FOR_DATA) &&
131 (cmd.response[0] & MMC_STATUS_CURR_STATE) !=
132 MMC_STATE_PRG)
133 break;
134 else if (cmd.response[0] & MMC_STATUS_MASK) {
Paul Burton56196822013-09-04 16:12:25 +0100135#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Jan Kloetzked617c422012-02-05 22:29:12 +0000136 printf("Status Error: 0x%08X\n",
137 cmd.response[0]);
Paul Burton56196822013-09-04 16:12:25 +0100138#endif
Jan Kloetzked617c422012-02-05 22:29:12 +0000139 return COMM_ERR;
140 }
141 } else if (--retries < 0)
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000142 return err;
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000143
144 udelay(1000);
145
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000146 } while (timeout--);
147
Raffaele Recalcati5db2fe32011-03-11 02:01:14 +0000148#ifdef CONFIG_MMC_TRACE
149 status = (cmd.response[0] & MMC_STATUS_CURR_STATE) >> 9;
150 printf("CURR STATE:%d\n", status);
151#endif
Jongman Heo5b0c9422012-06-03 21:32:13 +0000152 if (timeout <= 0) {
Paul Burton56196822013-09-04 16:12:25 +0100153#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000154 printf("Timeout waiting card ready\n");
Paul Burton56196822013-09-04 16:12:25 +0100155#endif
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000156 return TIMEOUT;
157 }
158
159 return 0;
160}
161
Paul Burtonda61fa52013-09-09 15:30:26 +0100162int mmc_set_blocklen(struct mmc *mmc, int len)
Andy Fleming272cc702008-10-30 16:41:01 -0500163{
164 struct mmc_cmd cmd;
165
166 cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
167 cmd.resp_type = MMC_RSP_R1;
168 cmd.cmdarg = len;
Andy Fleming272cc702008-10-30 16:41:01 -0500169
170 return mmc_send_cmd(mmc, &cmd, NULL);
171}
172
173struct mmc *find_mmc_device(int dev_num)
174{
175 struct mmc *m;
176 struct list_head *entry;
177
178 list_for_each(entry, &mmc_devices) {
179 m = list_entry(entry, struct mmc, link);
180
181 if (m->block_dev.dev == dev_num)
182 return m;
183 }
184
Paul Burton56196822013-09-04 16:12:25 +0100185#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Andy Fleming272cc702008-10-30 16:41:01 -0500186 printf("MMC Device %d not found\n", dev_num);
Paul Burton56196822013-09-04 16:12:25 +0100187#endif
Andy Fleming272cc702008-10-30 16:41:01 -0500188
189 return NULL;
190}
191
Sascha Silbeff8fef52013-06-14 13:07:25 +0200192static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
Kim Phillipsfdbb8732012-10-29 13:34:43 +0000193 lbaint_t blkcnt)
Andy Fleming272cc702008-10-30 16:41:01 -0500194{
195 struct mmc_cmd cmd;
196 struct mmc_data data;
197
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700198 if (blkcnt > 1)
199 cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
200 else
201 cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK;
Andy Fleming272cc702008-10-30 16:41:01 -0500202
203 if (mmc->high_capacity)
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700204 cmd.cmdarg = start;
Andy Fleming272cc702008-10-30 16:41:01 -0500205 else
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700206 cmd.cmdarg = start * mmc->read_bl_len;
Andy Fleming272cc702008-10-30 16:41:01 -0500207
208 cmd.resp_type = MMC_RSP_R1;
Andy Fleming272cc702008-10-30 16:41:01 -0500209
210 data.dest = dst;
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700211 data.blocks = blkcnt;
Andy Fleming272cc702008-10-30 16:41:01 -0500212 data.blocksize = mmc->read_bl_len;
213 data.flags = MMC_DATA_READ;
214
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700215 if (mmc_send_cmd(mmc, &cmd, &data))
216 return 0;
Andy Fleming272cc702008-10-30 16:41:01 -0500217
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700218 if (blkcnt > 1) {
219 cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
220 cmd.cmdarg = 0;
221 cmd.resp_type = MMC_RSP_R1b;
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700222 if (mmc_send_cmd(mmc, &cmd, NULL)) {
Paul Burton56196822013-09-04 16:12:25 +0100223#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700224 printf("mmc fail to send stop cmd\n");
Paul Burton56196822013-09-04 16:12:25 +0100225#endif
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700226 return 0;
227 }
Andy Fleming272cc702008-10-30 16:41:01 -0500228 }
229
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700230 return blkcnt;
Andy Fleming272cc702008-10-30 16:41:01 -0500231}
232
Sascha Silbeff8fef52013-06-14 13:07:25 +0200233static ulong mmc_bread(int dev_num, lbaint_t start, lbaint_t blkcnt, void *dst)
Andy Fleming272cc702008-10-30 16:41:01 -0500234{
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700235 lbaint_t cur, blocks_todo = blkcnt;
Andy Fleming272cc702008-10-30 16:41:01 -0500236
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700237 if (blkcnt == 0)
238 return 0;
239
240 struct mmc *mmc = find_mmc_device(dev_num);
Andy Fleming272cc702008-10-30 16:41:01 -0500241 if (!mmc)
242 return 0;
243
Lei Wend2bf29e2010-09-13 22:07:27 +0800244 if ((start + blkcnt) > mmc->block_dev.lba) {
Paul Burton56196822013-09-04 16:12:25 +0100245#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Sascha Silbeff8fef52013-06-14 13:07:25 +0200246 printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
Lei Wend2bf29e2010-09-13 22:07:27 +0800247 start + blkcnt, mmc->block_dev.lba);
Paul Burton56196822013-09-04 16:12:25 +0100248#endif
Lei Wend2bf29e2010-09-13 22:07:27 +0800249 return 0;
250 }
Andy Fleming272cc702008-10-30 16:41:01 -0500251
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700252 if (mmc_set_blocklen(mmc, mmc->read_bl_len))
Andy Fleming272cc702008-10-30 16:41:01 -0500253 return 0;
Andy Fleming272cc702008-10-30 16:41:01 -0500254
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700255 do {
John Rigby8feafcc2011-04-18 05:50:08 +0000256 cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo;
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700257 if(mmc_read_blocks(mmc, dst, start, cur) != cur)
258 return 0;
259 blocks_todo -= cur;
260 start += cur;
261 dst += cur * mmc->read_bl_len;
262 } while (blocks_todo > 0);
Andy Fleming272cc702008-10-30 16:41:01 -0500263
264 return blkcnt;
265}
266
Kim Phillipsfdbb8732012-10-29 13:34:43 +0000267static int mmc_go_idle(struct mmc *mmc)
Andy Fleming272cc702008-10-30 16:41:01 -0500268{
269 struct mmc_cmd cmd;
270 int err;
271
272 udelay(1000);
273
274 cmd.cmdidx = MMC_CMD_GO_IDLE_STATE;
275 cmd.cmdarg = 0;
276 cmd.resp_type = MMC_RSP_NONE;
Andy Fleming272cc702008-10-30 16:41:01 -0500277
278 err = mmc_send_cmd(mmc, &cmd, NULL);
279
280 if (err)
281 return err;
282
283 udelay(2000);
284
285 return 0;
286}
287
Kim Phillipsfdbb8732012-10-29 13:34:43 +0000288static int sd_send_op_cond(struct mmc *mmc)
Andy Fleming272cc702008-10-30 16:41:01 -0500289{
290 int timeout = 1000;
291 int err;
292 struct mmc_cmd cmd;
293
294 do {
295 cmd.cmdidx = MMC_CMD_APP_CMD;
296 cmd.resp_type = MMC_RSP_R1;
297 cmd.cmdarg = 0;
Andy Fleming272cc702008-10-30 16:41:01 -0500298
299 err = mmc_send_cmd(mmc, &cmd, NULL);
300
301 if (err)
302 return err;
303
304 cmd.cmdidx = SD_CMD_APP_SEND_OP_COND;
305 cmd.resp_type = MMC_RSP_R3;
Stefano Babic250de122010-01-20 18:20:39 +0100306
307 /*
308 * Most cards do not answer if some reserved bits
309 * in the ocr are set. However, Some controller
310 * can set bit 7 (reserved for low voltages), but
311 * how to manage low voltages SD card is not yet
312 * specified.
313 */
Thomas Choud52ebf12010-12-24 13:12:21 +0000314 cmd.cmdarg = mmc_host_is_spi(mmc) ? 0 :
315 (mmc->voltages & 0xff8000);
Andy Fleming272cc702008-10-30 16:41:01 -0500316
317 if (mmc->version == SD_VERSION_2)
318 cmd.cmdarg |= OCR_HCS;
319
320 err = mmc_send_cmd(mmc, &cmd, NULL);
321
322 if (err)
323 return err;
324
325 udelay(1000);
326 } while ((!(cmd.response[0] & OCR_BUSY)) && timeout--);
327
328 if (timeout <= 0)
329 return UNUSABLE_ERR;
330
331 if (mmc->version != SD_VERSION_2)
332 mmc->version = SD_VERSION_1_0;
333
Thomas Choud52ebf12010-12-24 13:12:21 +0000334 if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
335 cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
336 cmd.resp_type = MMC_RSP_R3;
337 cmd.cmdarg = 0;
Thomas Choud52ebf12010-12-24 13:12:21 +0000338
339 err = mmc_send_cmd(mmc, &cmd, NULL);
340
341 if (err)
342 return err;
343 }
344
Rabin Vincent998be3d2009-04-05 13:30:56 +0530345 mmc->ocr = cmd.response[0];
Andy Fleming272cc702008-10-30 16:41:01 -0500346
347 mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
348 mmc->rca = 0;
349
350 return 0;
351}
352
Che-Liang Chioue9550442012-11-28 15:21:13 +0000353/* We pass in the cmd since otherwise the init seems to fail */
354static int mmc_send_op_cond_iter(struct mmc *mmc, struct mmc_cmd *cmd,
355 int use_arg)
Andy Fleming272cc702008-10-30 16:41:01 -0500356{
Andy Fleming272cc702008-10-30 16:41:01 -0500357 int err;
358
Che-Liang Chioue9550442012-11-28 15:21:13 +0000359 cmd->cmdidx = MMC_CMD_SEND_OP_COND;
360 cmd->resp_type = MMC_RSP_R3;
361 cmd->cmdarg = 0;
362 if (use_arg && !mmc_host_is_spi(mmc)) {
363 cmd->cmdarg =
364 (mmc->voltages &
365 (mmc->op_cond_response & OCR_VOLTAGE_MASK)) |
366 (mmc->op_cond_response & OCR_ACCESS_MODE);
367
368 if (mmc->host_caps & MMC_MODE_HC)
369 cmd->cmdarg |= OCR_HCS;
370 }
371 err = mmc_send_cmd(mmc, cmd, NULL);
372 if (err)
373 return err;
374 mmc->op_cond_response = cmd->response[0];
375 return 0;
376}
377
378int mmc_send_op_cond(struct mmc *mmc)
379{
380 struct mmc_cmd cmd;
381 int err, i;
382
Andy Fleming272cc702008-10-30 16:41:01 -0500383 /* Some cards seem to need this */
384 mmc_go_idle(mmc);
385
Raffaele Recalcati31cacba2011-03-11 02:01:13 +0000386 /* Asking to the card its capabilities */
Che-Liang Chioue9550442012-11-28 15:21:13 +0000387 mmc->op_cond_pending = 1;
388 for (i = 0; i < 2; i++) {
389 err = mmc_send_op_cond_iter(mmc, &cmd, i != 0);
Andy Fleming272cc702008-10-30 16:41:01 -0500390 if (err)
391 return err;
392
Che-Liang Chioue9550442012-11-28 15:21:13 +0000393 /* exit if not busy (flag seems to be inverted) */
394 if (mmc->op_cond_response & OCR_BUSY)
395 return 0;
396 }
397 return IN_PROGRESS;
398}
Andy Fleming272cc702008-10-30 16:41:01 -0500399
Che-Liang Chioue9550442012-11-28 15:21:13 +0000400int mmc_complete_op_cond(struct mmc *mmc)
401{
402 struct mmc_cmd cmd;
403 int timeout = 1000;
404 uint start;
405 int err;
406
407 mmc->op_cond_pending = 0;
408 start = get_timer(0);
409 do {
410 err = mmc_send_op_cond_iter(mmc, &cmd, 1);
411 if (err)
412 return err;
413 if (get_timer(start) > timeout)
414 return UNUSABLE_ERR;
415 udelay(100);
416 } while (!(mmc->op_cond_response & OCR_BUSY));
Andy Fleming272cc702008-10-30 16:41:01 -0500417
Thomas Choud52ebf12010-12-24 13:12:21 +0000418 if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
419 cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
420 cmd.resp_type = MMC_RSP_R3;
421 cmd.cmdarg = 0;
Thomas Choud52ebf12010-12-24 13:12:21 +0000422
423 err = mmc_send_cmd(mmc, &cmd, NULL);
424
425 if (err)
426 return err;
427 }
428
Andy Fleming272cc702008-10-30 16:41:01 -0500429 mmc->version = MMC_VERSION_UNKNOWN;
Rabin Vincent998be3d2009-04-05 13:30:56 +0530430 mmc->ocr = cmd.response[0];
Andy Fleming272cc702008-10-30 16:41:01 -0500431
432 mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
433 mmc->rca = 0;
434
435 return 0;
436}
437
438
Kim Phillipsfdbb8732012-10-29 13:34:43 +0000439static int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd)
Andy Fleming272cc702008-10-30 16:41:01 -0500440{
441 struct mmc_cmd cmd;
442 struct mmc_data data;
443 int err;
444
445 /* Get the Card Status Register */
446 cmd.cmdidx = MMC_CMD_SEND_EXT_CSD;
447 cmd.resp_type = MMC_RSP_R1;
448 cmd.cmdarg = 0;
Andy Fleming272cc702008-10-30 16:41:01 -0500449
Yoshihiro Shimodacdfd1ac2012-06-07 19:09:11 +0000450 data.dest = (char *)ext_csd;
Andy Fleming272cc702008-10-30 16:41:01 -0500451 data.blocks = 1;
Simon Glass8bfa1952013-04-03 08:54:30 +0000452 data.blocksize = MMC_MAX_BLOCK_LEN;
Andy Fleming272cc702008-10-30 16:41:01 -0500453 data.flags = MMC_DATA_READ;
454
455 err = mmc_send_cmd(mmc, &cmd, &data);
456
457 return err;
458}
459
460
Kim Phillipsfdbb8732012-10-29 13:34:43 +0000461static int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
Andy Fleming272cc702008-10-30 16:41:01 -0500462{
463 struct mmc_cmd cmd;
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000464 int timeout = 1000;
465 int ret;
Andy Fleming272cc702008-10-30 16:41:01 -0500466
467 cmd.cmdidx = MMC_CMD_SWITCH;
468 cmd.resp_type = MMC_RSP_R1b;
469 cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000470 (index << 16) |
471 (value << 8);
Andy Fleming272cc702008-10-30 16:41:01 -0500472
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000473 ret = mmc_send_cmd(mmc, &cmd, NULL);
474
475 /* Waiting for the ready status */
Jan Kloetzke93ad0d12012-02-05 22:29:11 +0000476 if (!ret)
477 ret = mmc_send_status(mmc, timeout);
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000478
479 return ret;
480
Andy Fleming272cc702008-10-30 16:41:01 -0500481}
482
Kim Phillipsfdbb8732012-10-29 13:34:43 +0000483static int mmc_change_freq(struct mmc *mmc)
Andy Fleming272cc702008-10-30 16:41:01 -0500484{
Simon Glass8bfa1952013-04-03 08:54:30 +0000485 ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
Andy Fleming272cc702008-10-30 16:41:01 -0500486 char cardtype;
487 int err;
488
489 mmc->card_caps = 0;
490
Thomas Choud52ebf12010-12-24 13:12:21 +0000491 if (mmc_host_is_spi(mmc))
492 return 0;
493
Andy Fleming272cc702008-10-30 16:41:01 -0500494 /* Only version 4 supports high-speed */
495 if (mmc->version < MMC_VERSION_4)
496 return 0;
497
Andy Fleming272cc702008-10-30 16:41:01 -0500498 err = mmc_send_ext_csd(mmc, ext_csd);
499
500 if (err)
501 return err;
502
Lei Wen0560db12011-10-03 20:35:10 +0000503 cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0xf;
Andy Fleming272cc702008-10-30 16:41:01 -0500504
505 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);
506
507 if (err)
508 return err;
509
510 /* Now check to see that it worked */
511 err = mmc_send_ext_csd(mmc, ext_csd);
512
513 if (err)
514 return err;
515
516 /* No high-speed support */
Lei Wen0560db12011-10-03 20:35:10 +0000517 if (!ext_csd[EXT_CSD_HS_TIMING])
Andy Fleming272cc702008-10-30 16:41:01 -0500518 return 0;
519
520 /* High Speed is set, there are two types: 52MHz and 26MHz */
521 if (cardtype & MMC_HS_52MHZ)
522 mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
523 else
524 mmc->card_caps |= MMC_MODE_HS;
525
526 return 0;
527}
528
Stephen Warrenf866a462013-06-11 15:14:01 -0600529static int mmc_set_capacity(struct mmc *mmc, int part_num)
530{
531 switch (part_num) {
532 case 0:
533 mmc->capacity = mmc->capacity_user;
534 break;
535 case 1:
536 case 2:
537 mmc->capacity = mmc->capacity_boot;
538 break;
539 case 3:
540 mmc->capacity = mmc->capacity_rpmb;
541 break;
542 case 4:
543 case 5:
544 case 6:
545 case 7:
546 mmc->capacity = mmc->capacity_gp[part_num - 4];
547 break;
548 default:
549 return -1;
550 }
551
552 mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len);
553
554 return 0;
555}
556
Lei Wenbc897b12011-05-02 16:26:26 +0000557int mmc_switch_part(int dev_num, unsigned int part_num)
558{
559 struct mmc *mmc = find_mmc_device(dev_num);
Stephen Warrenf866a462013-06-11 15:14:01 -0600560 int ret;
Lei Wenbc897b12011-05-02 16:26:26 +0000561
562 if (!mmc)
563 return -1;
564
Stephen Warrenf866a462013-06-11 15:14:01 -0600565 ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
566 (mmc->part_config & ~PART_ACCESS_MASK)
567 | (part_num & PART_ACCESS_MASK));
568 if (ret)
569 return ret;
570
571 return mmc_set_capacity(mmc, part_num);
Lei Wenbc897b12011-05-02 16:26:26 +0000572}
573
Thierry Reding48972d92012-01-02 01:15:37 +0000574int mmc_getcd(struct mmc *mmc)
575{
576 int cd;
577
578 cd = board_mmc_getcd(mmc);
579
Peter Korsgaardd4e1da42013-03-21 04:00:03 +0000580 if (cd < 0) {
581 if (mmc->getcd)
582 cd = mmc->getcd(mmc);
583 else
584 cd = 1;
585 }
Thierry Reding48972d92012-01-02 01:15:37 +0000586
587 return cd;
588}
589
Kim Phillipsfdbb8732012-10-29 13:34:43 +0000590static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
Andy Fleming272cc702008-10-30 16:41:01 -0500591{
592 struct mmc_cmd cmd;
593 struct mmc_data data;
594
595 /* Switch the frequency */
596 cmd.cmdidx = SD_CMD_SWITCH_FUNC;
597 cmd.resp_type = MMC_RSP_R1;
598 cmd.cmdarg = (mode << 31) | 0xffffff;
599 cmd.cmdarg &= ~(0xf << (group * 4));
600 cmd.cmdarg |= value << (group * 4);
Andy Fleming272cc702008-10-30 16:41:01 -0500601
602 data.dest = (char *)resp;
603 data.blocksize = 64;
604 data.blocks = 1;
605 data.flags = MMC_DATA_READ;
606
607 return mmc_send_cmd(mmc, &cmd, &data);
608}
609
610
Kim Phillipsfdbb8732012-10-29 13:34:43 +0000611static int sd_change_freq(struct mmc *mmc)
Andy Fleming272cc702008-10-30 16:41:01 -0500612{
613 int err;
614 struct mmc_cmd cmd;
Anton staaff781dd32011-10-03 13:54:59 +0000615 ALLOC_CACHE_ALIGN_BUFFER(uint, scr, 2);
616 ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);
Andy Fleming272cc702008-10-30 16:41:01 -0500617 struct mmc_data data;
618 int timeout;
619
620 mmc->card_caps = 0;
621
Thomas Choud52ebf12010-12-24 13:12:21 +0000622 if (mmc_host_is_spi(mmc))
623 return 0;
624
Andy Fleming272cc702008-10-30 16:41:01 -0500625 /* Read the SCR to find out if this card supports higher speeds */
626 cmd.cmdidx = MMC_CMD_APP_CMD;
627 cmd.resp_type = MMC_RSP_R1;
628 cmd.cmdarg = mmc->rca << 16;
Andy Fleming272cc702008-10-30 16:41:01 -0500629
630 err = mmc_send_cmd(mmc, &cmd, NULL);
631
632 if (err)
633 return err;
634
635 cmd.cmdidx = SD_CMD_APP_SEND_SCR;
636 cmd.resp_type = MMC_RSP_R1;
637 cmd.cmdarg = 0;
Andy Fleming272cc702008-10-30 16:41:01 -0500638
639 timeout = 3;
640
641retry_scr:
Anton staaff781dd32011-10-03 13:54:59 +0000642 data.dest = (char *)scr;
Andy Fleming272cc702008-10-30 16:41:01 -0500643 data.blocksize = 8;
644 data.blocks = 1;
645 data.flags = MMC_DATA_READ;
646
647 err = mmc_send_cmd(mmc, &cmd, &data);
648
649 if (err) {
650 if (timeout--)
651 goto retry_scr;
652
653 return err;
654 }
655
Yauhen Kharuzhy4e3d89b2009-05-07 00:43:30 +0300656 mmc->scr[0] = __be32_to_cpu(scr[0]);
657 mmc->scr[1] = __be32_to_cpu(scr[1]);
Andy Fleming272cc702008-10-30 16:41:01 -0500658
659 switch ((mmc->scr[0] >> 24) & 0xf) {
660 case 0:
661 mmc->version = SD_VERSION_1_0;
662 break;
663 case 1:
664 mmc->version = SD_VERSION_1_10;
665 break;
666 case 2:
667 mmc->version = SD_VERSION_2;
Jaehoon Chung1741c642013-01-29 22:58:16 +0000668 if ((mmc->scr[0] >> 15) & 0x1)
669 mmc->version = SD_VERSION_3;
Andy Fleming272cc702008-10-30 16:41:01 -0500670 break;
671 default:
672 mmc->version = SD_VERSION_1_0;
673 break;
674 }
675
Alagu Sankarb44c7082010-05-12 15:08:24 +0530676 if (mmc->scr[0] & SD_DATA_4BIT)
677 mmc->card_caps |= MMC_MODE_4BIT;
678
Andy Fleming272cc702008-10-30 16:41:01 -0500679 /* Version 1.0 doesn't support switching */
680 if (mmc->version == SD_VERSION_1_0)
681 return 0;
682
683 timeout = 4;
684 while (timeout--) {
685 err = sd_switch(mmc, SD_SWITCH_CHECK, 0, 1,
Anton staaff781dd32011-10-03 13:54:59 +0000686 (u8 *)switch_status);
Andy Fleming272cc702008-10-30 16:41:01 -0500687
688 if (err)
689 return err;
690
691 /* The high-speed function is busy. Try again */
Yauhen Kharuzhy4e3d89b2009-05-07 00:43:30 +0300692 if (!(__be32_to_cpu(switch_status[7]) & SD_HIGHSPEED_BUSY))
Andy Fleming272cc702008-10-30 16:41:01 -0500693 break;
694 }
695
Andy Fleming272cc702008-10-30 16:41:01 -0500696 /* If high-speed isn't supported, we return */
Yauhen Kharuzhy4e3d89b2009-05-07 00:43:30 +0300697 if (!(__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED))
Andy Fleming272cc702008-10-30 16:41:01 -0500698 return 0;
699
Macpaul Lin2c3fbf42011-11-28 16:31:09 +0000700 /*
701 * If the host doesn't support SD_HIGHSPEED, do not switch card to
702 * HIGHSPEED mode even if the card support SD_HIGHSPPED.
703 * This can avoid furthur problem when the card runs in different
704 * mode between the host.
705 */
706 if (!((mmc->host_caps & MMC_MODE_HS_52MHz) &&
707 (mmc->host_caps & MMC_MODE_HS)))
708 return 0;
709
Anton staaff781dd32011-10-03 13:54:59 +0000710 err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status);
Andy Fleming272cc702008-10-30 16:41:01 -0500711
712 if (err)
713 return err;
714
Yauhen Kharuzhy4e3d89b2009-05-07 00:43:30 +0300715 if ((__be32_to_cpu(switch_status[4]) & 0x0f000000) == 0x01000000)
Andy Fleming272cc702008-10-30 16:41:01 -0500716 mmc->card_caps |= MMC_MODE_HS;
717
718 return 0;
719}
720
721/* frequency bases */
722/* divided by 10 to be nice to platforms without floating point */
Mike Frysinger5f837c22010-10-20 01:15:53 +0000723static const int fbase[] = {
Andy Fleming272cc702008-10-30 16:41:01 -0500724 10000,
725 100000,
726 1000000,
727 10000000,
728};
729
730/* Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice
731 * to platforms without floating point.
732 */
Mike Frysinger5f837c22010-10-20 01:15:53 +0000733static const int multipliers[] = {
Andy Fleming272cc702008-10-30 16:41:01 -0500734 0, /* reserved */
735 10,
736 12,
737 13,
738 15,
739 20,
740 25,
741 30,
742 35,
743 40,
744 45,
745 50,
746 55,
747 60,
748 70,
749 80,
750};
751
Kim Phillipsfdbb8732012-10-29 13:34:43 +0000752static void mmc_set_ios(struct mmc *mmc)
Andy Fleming272cc702008-10-30 16:41:01 -0500753{
754 mmc->set_ios(mmc);
755}
756
757void mmc_set_clock(struct mmc *mmc, uint clock)
758{
759 if (clock > mmc->f_max)
760 clock = mmc->f_max;
761
762 if (clock < mmc->f_min)
763 clock = mmc->f_min;
764
765 mmc->clock = clock;
766
767 mmc_set_ios(mmc);
768}
769
Kim Phillipsfdbb8732012-10-29 13:34:43 +0000770static void mmc_set_bus_width(struct mmc *mmc, uint width)
Andy Fleming272cc702008-10-30 16:41:01 -0500771{
772 mmc->bus_width = width;
773
774 mmc_set_ios(mmc);
775}
776
Kim Phillipsfdbb8732012-10-29 13:34:43 +0000777static int mmc_startup(struct mmc *mmc)
Andy Fleming272cc702008-10-30 16:41:01 -0500778{
Stephen Warrenf866a462013-06-11 15:14:01 -0600779 int err, i;
Andy Fleming272cc702008-10-30 16:41:01 -0500780 uint mult, freq;
Yoshihiro Shimoda639b7822011-07-04 22:13:26 +0000781 u64 cmult, csize, capacity;
Andy Fleming272cc702008-10-30 16:41:01 -0500782 struct mmc_cmd cmd;
Simon Glass8bfa1952013-04-03 08:54:30 +0000783 ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
784 ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000785 int timeout = 1000;
Andy Fleming272cc702008-10-30 16:41:01 -0500786
Thomas Choud52ebf12010-12-24 13:12:21 +0000787#ifdef CONFIG_MMC_SPI_CRC_ON
788 if (mmc_host_is_spi(mmc)) { /* enable CRC check for spi */
789 cmd.cmdidx = MMC_CMD_SPI_CRC_ON_OFF;
790 cmd.resp_type = MMC_RSP_R1;
791 cmd.cmdarg = 1;
Thomas Choud52ebf12010-12-24 13:12:21 +0000792 err = mmc_send_cmd(mmc, &cmd, NULL);
793
794 if (err)
795 return err;
796 }
797#endif
798
Andy Fleming272cc702008-10-30 16:41:01 -0500799 /* Put the Card in Identify Mode */
Thomas Choud52ebf12010-12-24 13:12:21 +0000800 cmd.cmdidx = mmc_host_is_spi(mmc) ? MMC_CMD_SEND_CID :
801 MMC_CMD_ALL_SEND_CID; /* cmd not supported in spi */
Andy Fleming272cc702008-10-30 16:41:01 -0500802 cmd.resp_type = MMC_RSP_R2;
803 cmd.cmdarg = 0;
Andy Fleming272cc702008-10-30 16:41:01 -0500804
805 err = mmc_send_cmd(mmc, &cmd, NULL);
806
807 if (err)
808 return err;
809
810 memcpy(mmc->cid, cmd.response, 16);
811
812 /*
813 * For MMC cards, set the Relative Address.
814 * For SD cards, get the Relatvie Address.
815 * This also puts the cards into Standby State
816 */
Thomas Choud52ebf12010-12-24 13:12:21 +0000817 if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
818 cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR;
819 cmd.cmdarg = mmc->rca << 16;
820 cmd.resp_type = MMC_RSP_R6;
Andy Fleming272cc702008-10-30 16:41:01 -0500821
Thomas Choud52ebf12010-12-24 13:12:21 +0000822 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Fleming272cc702008-10-30 16:41:01 -0500823
Thomas Choud52ebf12010-12-24 13:12:21 +0000824 if (err)
825 return err;
Andy Fleming272cc702008-10-30 16:41:01 -0500826
Thomas Choud52ebf12010-12-24 13:12:21 +0000827 if (IS_SD(mmc))
828 mmc->rca = (cmd.response[0] >> 16) & 0xffff;
829 }
Andy Fleming272cc702008-10-30 16:41:01 -0500830
831 /* Get the Card-Specific Data */
832 cmd.cmdidx = MMC_CMD_SEND_CSD;
833 cmd.resp_type = MMC_RSP_R2;
834 cmd.cmdarg = mmc->rca << 16;
Andy Fleming272cc702008-10-30 16:41:01 -0500835
836 err = mmc_send_cmd(mmc, &cmd, NULL);
837
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000838 /* Waiting for the ready status */
839 mmc_send_status(mmc, timeout);
840
Andy Fleming272cc702008-10-30 16:41:01 -0500841 if (err)
842 return err;
843
Rabin Vincent998be3d2009-04-05 13:30:56 +0530844 mmc->csd[0] = cmd.response[0];
845 mmc->csd[1] = cmd.response[1];
846 mmc->csd[2] = cmd.response[2];
847 mmc->csd[3] = cmd.response[3];
Andy Fleming272cc702008-10-30 16:41:01 -0500848
849 if (mmc->version == MMC_VERSION_UNKNOWN) {
Rabin Vincent0b453ff2009-04-05 13:30:55 +0530850 int version = (cmd.response[0] >> 26) & 0xf;
Andy Fleming272cc702008-10-30 16:41:01 -0500851
852 switch (version) {
853 case 0:
854 mmc->version = MMC_VERSION_1_2;
855 break;
856 case 1:
857 mmc->version = MMC_VERSION_1_4;
858 break;
859 case 2:
860 mmc->version = MMC_VERSION_2_2;
861 break;
862 case 3:
863 mmc->version = MMC_VERSION_3;
864 break;
865 case 4:
866 mmc->version = MMC_VERSION_4;
867 break;
868 default:
869 mmc->version = MMC_VERSION_1_2;
870 break;
871 }
872 }
873
874 /* divide frequency by 10, since the mults are 10x bigger */
Rabin Vincent0b453ff2009-04-05 13:30:55 +0530875 freq = fbase[(cmd.response[0] & 0x7)];
876 mult = multipliers[((cmd.response[0] >> 3) & 0xf)];
Andy Fleming272cc702008-10-30 16:41:01 -0500877
878 mmc->tran_speed = freq * mult;
879
Rabin Vincent998be3d2009-04-05 13:30:56 +0530880 mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf);
Andy Fleming272cc702008-10-30 16:41:01 -0500881
882 if (IS_SD(mmc))
883 mmc->write_bl_len = mmc->read_bl_len;
884 else
Rabin Vincent998be3d2009-04-05 13:30:56 +0530885 mmc->write_bl_len = 1 << ((cmd.response[3] >> 22) & 0xf);
Andy Fleming272cc702008-10-30 16:41:01 -0500886
887 if (mmc->high_capacity) {
888 csize = (mmc->csd[1] & 0x3f) << 16
889 | (mmc->csd[2] & 0xffff0000) >> 16;
890 cmult = 8;
891 } else {
892 csize = (mmc->csd[1] & 0x3ff) << 2
893 | (mmc->csd[2] & 0xc0000000) >> 30;
894 cmult = (mmc->csd[2] & 0x00038000) >> 15;
895 }
896
Stephen Warrenf866a462013-06-11 15:14:01 -0600897 mmc->capacity_user = (csize + 1) << (cmult + 2);
898 mmc->capacity_user *= mmc->read_bl_len;
899 mmc->capacity_boot = 0;
900 mmc->capacity_rpmb = 0;
901 for (i = 0; i < 4; i++)
902 mmc->capacity_gp[i] = 0;
Andy Fleming272cc702008-10-30 16:41:01 -0500903
Simon Glass8bfa1952013-04-03 08:54:30 +0000904 if (mmc->read_bl_len > MMC_MAX_BLOCK_LEN)
905 mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
Andy Fleming272cc702008-10-30 16:41:01 -0500906
Simon Glass8bfa1952013-04-03 08:54:30 +0000907 if (mmc->write_bl_len > MMC_MAX_BLOCK_LEN)
908 mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
Andy Fleming272cc702008-10-30 16:41:01 -0500909
910 /* Select the card, and put it into Transfer Mode */
Thomas Choud52ebf12010-12-24 13:12:21 +0000911 if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
912 cmd.cmdidx = MMC_CMD_SELECT_CARD;
Ajay Bhargavfe8f7062011-10-05 03:13:23 +0000913 cmd.resp_type = MMC_RSP_R1;
Thomas Choud52ebf12010-12-24 13:12:21 +0000914 cmd.cmdarg = mmc->rca << 16;
Thomas Choud52ebf12010-12-24 13:12:21 +0000915 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Fleming272cc702008-10-30 16:41:01 -0500916
Thomas Choud52ebf12010-12-24 13:12:21 +0000917 if (err)
918 return err;
919 }
Andy Fleming272cc702008-10-30 16:41:01 -0500920
Lei Wene6f99a52011-06-22 17:03:31 +0000921 /*
922 * For SD, its erase group is always one sector
923 */
924 mmc->erase_grp_size = 1;
Lei Wenbc897b12011-05-02 16:26:26 +0000925 mmc->part_config = MMCPART_NOAVAILABLE;
Sukumar Ghoraid23e2c02010-09-20 18:29:29 +0530926 if (!IS_SD(mmc) && (mmc->version >= MMC_VERSION_4)) {
927 /* check ext_csd version and capacity */
928 err = mmc_send_ext_csd(mmc, ext_csd);
Kim Phillipsfdbb8732012-10-29 13:34:43 +0000929 if (!err && (ext_csd[EXT_CSD_REV] >= 2)) {
Yoshihiro Shimoda639b7822011-07-04 22:13:26 +0000930 /*
931 * According to the JEDEC Standard, the value of
932 * ext_csd's capacity is valid if the value is more
933 * than 2GB
934 */
Lei Wen0560db12011-10-03 20:35:10 +0000935 capacity = ext_csd[EXT_CSD_SEC_CNT] << 0
936 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8
937 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16
938 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
Simon Glass8bfa1952013-04-03 08:54:30 +0000939 capacity *= MMC_MAX_BLOCK_LEN;
Łukasz Majewskib1f1e8212011-07-05 02:19:44 +0000940 if ((capacity >> 20) > 2 * 1024)
Stephen Warrenf866a462013-06-11 15:14:01 -0600941 mmc->capacity_user = capacity;
Sukumar Ghoraid23e2c02010-09-20 18:29:29 +0530942 }
Lei Wenbc897b12011-05-02 16:26:26 +0000943
Jaehoon Chung64f4a612013-01-29 19:31:16 +0000944 switch (ext_csd[EXT_CSD_REV]) {
945 case 1:
946 mmc->version = MMC_VERSION_4_1;
947 break;
948 case 2:
949 mmc->version = MMC_VERSION_4_2;
950 break;
951 case 3:
952 mmc->version = MMC_VERSION_4_3;
953 break;
954 case 5:
955 mmc->version = MMC_VERSION_4_41;
956 break;
957 case 6:
958 mmc->version = MMC_VERSION_4_5;
959 break;
960 }
961
Lei Wene6f99a52011-06-22 17:03:31 +0000962 /*
963 * Check whether GROUP_DEF is set, if yes, read out
964 * group size from ext_csd directly, or calculate
965 * the group size from the csd value.
966 */
Simon Glass8bfa1952013-04-03 08:54:30 +0000967 if (ext_csd[EXT_CSD_ERASE_GROUP_DEF]) {
Lei Wen0560db12011-10-03 20:35:10 +0000968 mmc->erase_grp_size =
Simon Glass8bfa1952013-04-03 08:54:30 +0000969 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] *
970 MMC_MAX_BLOCK_LEN * 1024;
971 } else {
Lei Wene6f99a52011-06-22 17:03:31 +0000972 int erase_gsz, erase_gmul;
973 erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10;
974 erase_gmul = (mmc->csd[2] & 0x000003e0) >> 5;
975 mmc->erase_grp_size = (erase_gsz + 1)
976 * (erase_gmul + 1);
977 }
978
Lei Wenbc897b12011-05-02 16:26:26 +0000979 /* store the partition info of emmc */
Stephen Warren8948ea82012-07-30 10:55:43 +0000980 if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) ||
981 ext_csd[EXT_CSD_BOOT_MULT])
Lei Wen0560db12011-10-03 20:35:10 +0000982 mmc->part_config = ext_csd[EXT_CSD_PART_CONF];
Stephen Warrenf866a462013-06-11 15:14:01 -0600983
984 mmc->capacity_boot = ext_csd[EXT_CSD_BOOT_MULT] << 17;
985
986 mmc->capacity_rpmb = ext_csd[EXT_CSD_RPMB_MULT] << 17;
987
988 for (i = 0; i < 4; i++) {
989 int idx = EXT_CSD_GP_SIZE_MULT + i * 3;
990 mmc->capacity_gp[i] = (ext_csd[idx + 2] << 16) +
991 (ext_csd[idx + 1] << 8) + ext_csd[idx];
992 mmc->capacity_gp[i] *=
993 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
994 mmc->capacity_gp[i] *= ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
995 }
Sukumar Ghoraid23e2c02010-09-20 18:29:29 +0530996 }
997
Stephen Warrenf866a462013-06-11 15:14:01 -0600998 err = mmc_set_capacity(mmc, mmc->part_num);
999 if (err)
1000 return err;
1001
Andy Fleming272cc702008-10-30 16:41:01 -05001002 if (IS_SD(mmc))
1003 err = sd_change_freq(mmc);
1004 else
1005 err = mmc_change_freq(mmc);
1006
1007 if (err)
1008 return err;
1009
1010 /* Restrict card's capabilities by what the host can do */
1011 mmc->card_caps &= mmc->host_caps;
1012
1013 if (IS_SD(mmc)) {
1014 if (mmc->card_caps & MMC_MODE_4BIT) {
1015 cmd.cmdidx = MMC_CMD_APP_CMD;
1016 cmd.resp_type = MMC_RSP_R1;
1017 cmd.cmdarg = mmc->rca << 16;
Andy Fleming272cc702008-10-30 16:41:01 -05001018
1019 err = mmc_send_cmd(mmc, &cmd, NULL);
1020 if (err)
1021 return err;
1022
1023 cmd.cmdidx = SD_CMD_APP_SET_BUS_WIDTH;
1024 cmd.resp_type = MMC_RSP_R1;
1025 cmd.cmdarg = 2;
Andy Fleming272cc702008-10-30 16:41:01 -05001026 err = mmc_send_cmd(mmc, &cmd, NULL);
1027 if (err)
1028 return err;
1029
1030 mmc_set_bus_width(mmc, 4);
1031 }
1032
1033 if (mmc->card_caps & MMC_MODE_HS)
Jaehoon Chungad5fd922012-03-26 21:16:03 +00001034 mmc->tran_speed = 50000000;
Andy Fleming272cc702008-10-30 16:41:01 -05001035 else
Jaehoon Chungad5fd922012-03-26 21:16:03 +00001036 mmc->tran_speed = 25000000;
Andy Fleming272cc702008-10-30 16:41:01 -05001037 } else {
Andy Fleming7798f6d2012-10-31 19:02:38 +00001038 int idx;
1039
1040 /* An array of possible bus widths in order of preference */
1041 static unsigned ext_csd_bits[] = {
1042 EXT_CSD_BUS_WIDTH_8,
1043 EXT_CSD_BUS_WIDTH_4,
1044 EXT_CSD_BUS_WIDTH_1,
1045 };
1046
1047 /* An array to map CSD bus widths to host cap bits */
1048 static unsigned ext_to_hostcaps[] = {
1049 [EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT,
1050 [EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT,
1051 };
1052
1053 /* An array to map chosen bus width to an integer */
1054 static unsigned widths[] = {
1055 8, 4, 1,
1056 };
1057
1058 for (idx=0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
1059 unsigned int extw = ext_csd_bits[idx];
1060
1061 /*
1062 * Check to make sure the controller supports
1063 * this bus width, if it's more than 1
1064 */
1065 if (extw != EXT_CSD_BUS_WIDTH_1 &&
1066 !(mmc->host_caps & ext_to_hostcaps[extw]))
1067 continue;
1068
Andy Fleming272cc702008-10-30 16:41:01 -05001069 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
Andy Fleming7798f6d2012-10-31 19:02:38 +00001070 EXT_CSD_BUS_WIDTH, extw);
Andy Fleming272cc702008-10-30 16:41:01 -05001071
1072 if (err)
Lei Wen41378942011-10-03 20:35:11 +00001073 continue;
Andy Fleming272cc702008-10-30 16:41:01 -05001074
Andy Fleming7798f6d2012-10-31 19:02:38 +00001075 mmc_set_bus_width(mmc, widths[idx]);
Andy Fleming272cc702008-10-30 16:41:01 -05001076
Lei Wen41378942011-10-03 20:35:11 +00001077 err = mmc_send_ext_csd(mmc, test_csd);
1078 if (!err && ext_csd[EXT_CSD_PARTITIONING_SUPPORT] \
1079 == test_csd[EXT_CSD_PARTITIONING_SUPPORT]
1080 && ext_csd[EXT_CSD_ERASE_GROUP_DEF] \
1081 == test_csd[EXT_CSD_ERASE_GROUP_DEF] \
1082 && ext_csd[EXT_CSD_REV] \
1083 == test_csd[EXT_CSD_REV]
1084 && ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] \
1085 == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
1086 && memcmp(&ext_csd[EXT_CSD_SEC_CNT], \
1087 &test_csd[EXT_CSD_SEC_CNT], 4) == 0) {
Andy Fleming272cc702008-10-30 16:41:01 -05001088
Andy Fleming7798f6d2012-10-31 19:02:38 +00001089 mmc->card_caps |= ext_to_hostcaps[extw];
Lei Wen41378942011-10-03 20:35:11 +00001090 break;
1091 }
Andy Fleming272cc702008-10-30 16:41:01 -05001092 }
1093
1094 if (mmc->card_caps & MMC_MODE_HS) {
1095 if (mmc->card_caps & MMC_MODE_HS_52MHz)
Jaehoon Chungad5fd922012-03-26 21:16:03 +00001096 mmc->tran_speed = 52000000;
Andy Fleming272cc702008-10-30 16:41:01 -05001097 else
Jaehoon Chungad5fd922012-03-26 21:16:03 +00001098 mmc->tran_speed = 26000000;
1099 }
Andy Fleming272cc702008-10-30 16:41:01 -05001100 }
1101
Jaehoon Chungad5fd922012-03-26 21:16:03 +00001102 mmc_set_clock(mmc, mmc->tran_speed);
1103
Andy Fleming272cc702008-10-30 16:41:01 -05001104 /* fill in device description */
1105 mmc->block_dev.lun = 0;
1106 mmc->block_dev.type = 0;
1107 mmc->block_dev.blksz = mmc->read_bl_len;
Egbert Eich0472fbf2013-04-09 21:11:56 +00001108 mmc->block_dev.log2blksz = LOG2(mmc->block_dev.blksz);
Rabin Vincent9b1f9422009-04-05 13:30:54 +05301109 mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len);
Paul Burton56196822013-09-04 16:12:25 +01001110#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Taylor Huttbabce5f2012-10-20 17:15:59 +00001111 sprintf(mmc->block_dev.vendor, "Man %06x Snr %04x%04x",
1112 mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff),
1113 (mmc->cid[3] >> 16) & 0xffff);
1114 sprintf(mmc->block_dev.product, "%c%c%c%c%c%c", mmc->cid[0] & 0xff,
1115 (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
1116 (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff,
1117 (mmc->cid[2] >> 24) & 0xff);
1118 sprintf(mmc->block_dev.revision, "%d.%d", (mmc->cid[2] >> 20) & 0xf,
1119 (mmc->cid[2] >> 16) & 0xf);
Paul Burton56196822013-09-04 16:12:25 +01001120#else
1121 mmc->block_dev.vendor[0] = 0;
1122 mmc->block_dev.product[0] = 0;
1123 mmc->block_dev.revision[0] = 0;
1124#endif
Mikhail Kshevetskiy122efd42012-07-09 08:53:38 +00001125#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT)
Andy Fleming272cc702008-10-30 16:41:01 -05001126 init_part(&mmc->block_dev);
Mikhail Kshevetskiy122efd42012-07-09 08:53:38 +00001127#endif
Andy Fleming272cc702008-10-30 16:41:01 -05001128
1129 return 0;
1130}
1131
Kim Phillipsfdbb8732012-10-29 13:34:43 +00001132static int mmc_send_if_cond(struct mmc *mmc)
Andy Fleming272cc702008-10-30 16:41:01 -05001133{
1134 struct mmc_cmd cmd;
1135 int err;
1136
1137 cmd.cmdidx = SD_CMD_SEND_IF_COND;
1138 /* We set the bit if the host supports voltages between 2.7 and 3.6 V */
1139 cmd.cmdarg = ((mmc->voltages & 0xff8000) != 0) << 8 | 0xaa;
1140 cmd.resp_type = MMC_RSP_R7;
Andy Fleming272cc702008-10-30 16:41:01 -05001141
1142 err = mmc_send_cmd(mmc, &cmd, NULL);
1143
1144 if (err)
1145 return err;
1146
Rabin Vincent998be3d2009-04-05 13:30:56 +05301147 if ((cmd.response[0] & 0xff) != 0xaa)
Andy Fleming272cc702008-10-30 16:41:01 -05001148 return UNUSABLE_ERR;
1149 else
1150 mmc->version = SD_VERSION_2;
1151
1152 return 0;
1153}
1154
1155int mmc_register(struct mmc *mmc)
1156{
1157 /* Setup the universal parts of the block interface just once */
1158 mmc->block_dev.if_type = IF_TYPE_MMC;
1159 mmc->block_dev.dev = cur_dev_num++;
1160 mmc->block_dev.removable = 1;
1161 mmc->block_dev.block_read = mmc_bread;
1162 mmc->block_dev.block_write = mmc_bwrite;
Lei Wene6f99a52011-06-22 17:03:31 +00001163 mmc->block_dev.block_erase = mmc_berase;
John Rigby8feafcc2011-04-18 05:50:08 +00001164 if (!mmc->b_max)
1165 mmc->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
Andy Fleming272cc702008-10-30 16:41:01 -05001166
1167 INIT_LIST_HEAD (&mmc->link);
1168
1169 list_add_tail (&mmc->link, &mmc_devices);
1170
1171 return 0;
1172}
1173
Matthew McClintockdf3fc522011-05-24 05:31:19 +00001174#ifdef CONFIG_PARTITIONS
Andy Fleming272cc702008-10-30 16:41:01 -05001175block_dev_desc_t *mmc_get_dev(int dev)
1176{
1177 struct mmc *mmc = find_mmc_device(dev);
Benoît Thébaudeau6bb4b4b2012-08-10 08:59:12 +00001178 if (!mmc || mmc_init(mmc))
Łukasz Majewski40242bc2012-04-19 02:39:18 +00001179 return NULL;
Andy Fleming272cc702008-10-30 16:41:01 -05001180
Łukasz Majewski40242bc2012-04-19 02:39:18 +00001181 return &mmc->block_dev;
Andy Fleming272cc702008-10-30 16:41:01 -05001182}
Matthew McClintockdf3fc522011-05-24 05:31:19 +00001183#endif
Andy Fleming272cc702008-10-30 16:41:01 -05001184
Che-Liang Chioue9550442012-11-28 15:21:13 +00001185int mmc_start_init(struct mmc *mmc)
Andy Fleming272cc702008-10-30 16:41:01 -05001186{
Macpaul Linafd59322011-11-14 23:35:39 +00001187 int err;
Andy Fleming272cc702008-10-30 16:41:01 -05001188
Thierry Reding48972d92012-01-02 01:15:37 +00001189 if (mmc_getcd(mmc) == 0) {
1190 mmc->has_init = 0;
Paul Burton56196822013-09-04 16:12:25 +01001191#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Thierry Reding48972d92012-01-02 01:15:37 +00001192 printf("MMC: no card present\n");
Paul Burton56196822013-09-04 16:12:25 +01001193#endif
Thierry Reding48972d92012-01-02 01:15:37 +00001194 return NO_CARD_ERR;
1195 }
1196
Lei Wenbc897b12011-05-02 16:26:26 +00001197 if (mmc->has_init)
1198 return 0;
1199
Andy Fleming272cc702008-10-30 16:41:01 -05001200 err = mmc->init(mmc);
1201
1202 if (err)
1203 return err;
1204
Ilya Yanokb86b85e2009-06-29 17:53:16 +04001205 mmc_set_bus_width(mmc, 1);
1206 mmc_set_clock(mmc, 1);
1207
Andy Fleming272cc702008-10-30 16:41:01 -05001208 /* Reset the Card */
1209 err = mmc_go_idle(mmc);
1210
1211 if (err)
1212 return err;
1213
Lei Wenbc897b12011-05-02 16:26:26 +00001214 /* The internal partition reset to user partition(0) at every CMD0*/
1215 mmc->part_num = 0;
1216
Andy Fleming272cc702008-10-30 16:41:01 -05001217 /* Test for SD version 2 */
Macpaul Linafd59322011-11-14 23:35:39 +00001218 err = mmc_send_if_cond(mmc);
Andy Fleming272cc702008-10-30 16:41:01 -05001219
Andy Fleming272cc702008-10-30 16:41:01 -05001220 /* Now try to get the SD card's operating condition */
1221 err = sd_send_op_cond(mmc);
1222
1223 /* If the command timed out, we check for an MMC card */
1224 if (err == TIMEOUT) {
1225 err = mmc_send_op_cond(mmc);
1226
Che-Liang Chioue9550442012-11-28 15:21:13 +00001227 if (err && err != IN_PROGRESS) {
Paul Burton56196822013-09-04 16:12:25 +01001228#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Andy Fleming272cc702008-10-30 16:41:01 -05001229 printf("Card did not respond to voltage select!\n");
Paul Burton56196822013-09-04 16:12:25 +01001230#endif
Andy Fleming272cc702008-10-30 16:41:01 -05001231 return UNUSABLE_ERR;
1232 }
1233 }
1234
Che-Liang Chioue9550442012-11-28 15:21:13 +00001235 if (err == IN_PROGRESS)
1236 mmc->init_in_progress = 1;
1237
1238 return err;
1239}
1240
1241static int mmc_complete_init(struct mmc *mmc)
1242{
1243 int err = 0;
1244
1245 if (mmc->op_cond_pending)
1246 err = mmc_complete_op_cond(mmc);
1247
1248 if (!err)
1249 err = mmc_startup(mmc);
Lei Wenbc897b12011-05-02 16:26:26 +00001250 if (err)
1251 mmc->has_init = 0;
1252 else
1253 mmc->has_init = 1;
Che-Liang Chioue9550442012-11-28 15:21:13 +00001254 mmc->init_in_progress = 0;
1255 return err;
1256}
1257
1258int mmc_init(struct mmc *mmc)
1259{
1260 int err = IN_PROGRESS;
1261 unsigned start = get_timer(0);
1262
1263 if (mmc->has_init)
1264 return 0;
1265 if (!mmc->init_in_progress)
1266 err = mmc_start_init(mmc);
1267
1268 if (!err || err == IN_PROGRESS)
1269 err = mmc_complete_init(mmc);
1270 debug("%s: %d, time %lu\n", __func__, err, get_timer(start));
Lei Wenbc897b12011-05-02 16:26:26 +00001271 return err;
Andy Fleming272cc702008-10-30 16:41:01 -05001272}
1273
1274/*
1275 * CPU and board-specific MMC initializations. Aliased function
1276 * signals caller to move on
1277 */
1278static int __def_mmc_init(bd_t *bis)
1279{
1280 return -1;
1281}
1282
Peter Tyserf9a109b2009-04-20 11:08:46 -05001283int cpu_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
1284int board_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
Andy Fleming272cc702008-10-30 16:41:01 -05001285
Paul Burton56196822013-09-04 16:12:25 +01001286#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
1287
Andy Fleming272cc702008-10-30 16:41:01 -05001288void print_mmc_devices(char separator)
1289{
1290 struct mmc *m;
1291 struct list_head *entry;
1292
1293 list_for_each(entry, &mmc_devices) {
1294 m = list_entry(entry, struct mmc, link);
1295
1296 printf("%s: %d", m->name, m->block_dev.dev);
1297
1298 if (entry->next != &mmc_devices)
1299 printf("%c ", separator);
1300 }
1301
1302 printf("\n");
1303}
1304
Paul Burton56196822013-09-04 16:12:25 +01001305#else
1306void print_mmc_devices(char separator) { }
1307#endif
1308
Lei Wenea6ebe22011-05-02 16:26:25 +00001309int get_mmc_num(void)
1310{
1311 return cur_dev_num;
1312}
1313
Che-Liang Chioue9550442012-11-28 15:21:13 +00001314void mmc_set_preinit(struct mmc *mmc, int preinit)
1315{
1316 mmc->preinit = preinit;
1317}
1318
1319static void do_preinit(void)
1320{
1321 struct mmc *m;
1322 struct list_head *entry;
1323
1324 list_for_each(entry, &mmc_devices) {
1325 m = list_entry(entry, struct mmc, link);
1326
1327 if (m->preinit)
1328 mmc_start_init(m);
1329 }
1330}
1331
1332
Andy Fleming272cc702008-10-30 16:41:01 -05001333int mmc_initialize(bd_t *bis)
1334{
1335 INIT_LIST_HEAD (&mmc_devices);
1336 cur_dev_num = 0;
1337
1338 if (board_mmc_init(bis) < 0)
1339 cpu_mmc_init(bis);
1340
Ying Zhangbb0dc102013-08-16 15:16:11 +08001341#ifndef CONFIG_SPL_BUILD
Andy Fleming272cc702008-10-30 16:41:01 -05001342 print_mmc_devices(',');
Ying Zhangbb0dc102013-08-16 15:16:11 +08001343#endif
Andy Fleming272cc702008-10-30 16:41:01 -05001344
Che-Liang Chioue9550442012-11-28 15:21:13 +00001345 do_preinit();
Andy Fleming272cc702008-10-30 16:41:01 -05001346 return 0;
1347}
Amar3690d6d2013-04-27 11:42:58 +05301348
1349#ifdef CONFIG_SUPPORT_EMMC_BOOT
1350/*
1351 * This function changes the size of boot partition and the size of rpmb
1352 * partition present on EMMC devices.
1353 *
1354 * Input Parameters:
1355 * struct *mmc: pointer for the mmc device strcuture
1356 * bootsize: size of boot partition
1357 * rpmbsize: size of rpmb partition
1358 *
1359 * Returns 0 on success.
1360 */
1361
1362int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
1363 unsigned long rpmbsize)
1364{
1365 int err;
1366 struct mmc_cmd cmd;
1367
1368 /* Only use this command for raw EMMC moviNAND. Enter backdoor mode */
1369 cmd.cmdidx = MMC_CMD_RES_MAN;
1370 cmd.resp_type = MMC_RSP_R1b;
1371 cmd.cmdarg = MMC_CMD62_ARG1;
1372
1373 err = mmc_send_cmd(mmc, &cmd, NULL);
1374 if (err) {
1375 debug("mmc_boot_partition_size_change: Error1 = %d\n", err);
1376 return err;
1377 }
1378
1379 /* Boot partition changing mode */
1380 cmd.cmdidx = MMC_CMD_RES_MAN;
1381 cmd.resp_type = MMC_RSP_R1b;
1382 cmd.cmdarg = MMC_CMD62_ARG2;
1383
1384 err = mmc_send_cmd(mmc, &cmd, NULL);
1385 if (err) {
1386 debug("mmc_boot_partition_size_change: Error2 = %d\n", err);
1387 return err;
1388 }
1389 /* boot partition size is multiple of 128KB */
1390 bootsize = (bootsize * 1024) / 128;
1391
1392 /* Arg: boot partition size */
1393 cmd.cmdidx = MMC_CMD_RES_MAN;
1394 cmd.resp_type = MMC_RSP_R1b;
1395 cmd.cmdarg = bootsize;
1396
1397 err = mmc_send_cmd(mmc, &cmd, NULL);
1398 if (err) {
1399 debug("mmc_boot_partition_size_change: Error3 = %d\n", err);
1400 return err;
1401 }
1402 /* RPMB partition size is multiple of 128KB */
1403 rpmbsize = (rpmbsize * 1024) / 128;
1404 /* Arg: RPMB partition size */
1405 cmd.cmdidx = MMC_CMD_RES_MAN;
1406 cmd.resp_type = MMC_RSP_R1b;
1407 cmd.cmdarg = rpmbsize;
1408
1409 err = mmc_send_cmd(mmc, &cmd, NULL);
1410 if (err) {
1411 debug("mmc_boot_partition_size_change: Error4 = %d\n", err);
1412 return err;
1413 }
1414 return 0;
1415}
1416
1417/*
1418 * This function shall form and send the commands to open / close the
1419 * boot partition specified by user.
1420 *
1421 * Input Parameters:
1422 * ack: 0x0 - No boot acknowledge sent (default)
1423 * 0x1 - Boot acknowledge sent during boot operation
1424 * part_num: User selects boot data that will be sent to master
1425 * 0x0 - Device not boot enabled (default)
1426 * 0x1 - Boot partition 1 enabled for boot
1427 * 0x2 - Boot partition 2 enabled for boot
1428 * access: User selects partitions to access
1429 * 0x0 : No access to boot partition (default)
1430 * 0x1 : R/W boot partition 1
1431 * 0x2 : R/W boot partition 2
1432 * 0x3 : R/W Replay Protected Memory Block (RPMB)
1433 *
1434 * Returns 0 on success.
1435 */
1436int mmc_boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
1437{
1438 int err;
1439 struct mmc_cmd cmd;
1440
1441 /* Boot ack enable, boot partition enable , boot partition access */
1442 cmd.cmdidx = MMC_CMD_SWITCH;
1443 cmd.resp_type = MMC_RSP_R1b;
1444
1445 cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
1446 (EXT_CSD_PART_CONF << 16) |
1447 ((EXT_CSD_BOOT_ACK(ack) |
1448 EXT_CSD_BOOT_PART_NUM(part_num) |
1449 EXT_CSD_PARTITION_ACCESS(access)) << 8);
1450
1451 err = mmc_send_cmd(mmc, &cmd, NULL);
1452 if (err) {
1453 if (access) {
1454 debug("mmc boot partition#%d open fail:Error1 = %d\n",
1455 part_num, err);
1456 } else {
1457 debug("mmc boot partition#%d close fail:Error = %d\n",
1458 part_num, err);
1459 }
1460 return err;
1461 }
1462
1463 if (access) {
1464 /* 4bit transfer mode at booting time. */
1465 cmd.cmdidx = MMC_CMD_SWITCH;
1466 cmd.resp_type = MMC_RSP_R1b;
1467
1468 cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
1469 (EXT_CSD_BOOT_BUS_WIDTH << 16) |
1470 ((1 << 0) << 8);
1471
1472 err = mmc_send_cmd(mmc, &cmd, NULL);
1473 if (err) {
1474 debug("mmc boot partition#%d open fail:Error2 = %d\n",
1475 part_num, err);
1476 return err;
1477 }
1478 }
1479 return 0;
1480}
1481#endif