blob: 8ab0bc948f5f22c8fa3827c5d6fdb8af9c397eaf [file] [log] [blame]
Andy Flemingad347bb2008-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 Denkd79de1d2013-07-08 09:37:19 +02007 * SPDX-License-Identifier: GPL-2.0+
Andy Flemingad347bb2008-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 Vincent69d4e2c2009-04-05 13:30:54 +053017#include <div64.h>
Paul Burton8d30cc92013-09-09 15:30:26 +010018#include "mmc_private.h"
Andy Flemingad347bb2008-10-30 16:41:01 -050019
Matt Waddeld0e3c802011-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 Flemingad347bb2008-10-30 16:41:01 -050025static struct list_head mmc_devices;
26static int cur_dev_num = -1;
27
Nikita Kiryanov020f2612012-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 Korsgaardf7b15102013-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 Kiryanov020f2612012-12-03 02:19:46 +000045
46 return wp;
47}
48
Thierry Redingd7aebf42012-01-02 01:15:36 +000049int __board_mmc_getcd(struct mmc *mmc) {
Stefano Babic6e00edf2010-02-05 15:04:43 +010050 return -1;
51}
52
Thierry Redingd7aebf42012-01-02 01:15:36 +000053int board_mmc_getcd(struct mmc *mmc)__attribute__((weak,
Stefano Babic6e00edf2010-02-05 15:04:43 +010054 alias("__board_mmc_getcd")));
55
Paul Burton8d30cc92013-09-09 15:30:26 +010056int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
Andy Flemingad347bb2008-10-30 16:41:01 -050057{
Raffaele Recalcati894b1e22011-03-11 02:01:14 +000058 int ret;
Marek Vasutdccb6082012-03-15 18:41:35 +000059
Marek Vasutdccb6082012-03-15 18:41:35 +000060#ifdef CONFIG_MMC_TRACE
Raffaele Recalcati894b1e22011-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 Recalcati894b1e22011-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 Behmec9cb4a92012-03-08 02:35:34 +000093 ptr = (u8 *)&cmd->response[i];
Raffaele Recalcati894b1e22011-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 Recalcati894b1e22011-03-11 02:01:14 +0000108#else
Marek Vasutdccb6082012-03-15 18:41:35 +0000109 ret = mmc->send_cmd(mmc, cmd, data);
Raffaele Recalcati894b1e22011-03-11 02:01:14 +0000110#endif
Marek Vasutdccb6082012-03-15 18:41:35 +0000111 return ret;
Andy Flemingad347bb2008-10-30 16:41:01 -0500112}
113
Paul Burton8d30cc92013-09-09 15:30:26 +0100114int mmc_send_status(struct mmc *mmc, int timeout)
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000115{
116 struct mmc_cmd cmd;
Jan Kloetzke31789322012-02-05 22:29:12 +0000117 int err, retries = 5;
Raffaele Recalcati01a0dc62011-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 Vasutc4427392011-08-10 09:24:48 +0200124 if (!mmc_host_is_spi(mmc))
125 cmd.cmdarg = mmc->rca << 16;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000126
127 do {
128 err = mmc_send_cmd(mmc, &cmd, NULL);
Jan Kloetzke31789322012-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 Burton6a7c5ba2013-09-04 16:12:25 +0100135#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Jan Kloetzke31789322012-02-05 22:29:12 +0000136 printf("Status Error: 0x%08X\n",
137 cmd.response[0]);
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100138#endif
Jan Kloetzke31789322012-02-05 22:29:12 +0000139 return COMM_ERR;
140 }
141 } else if (--retries < 0)
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000142 return err;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000143
144 udelay(1000);
145
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000146 } while (timeout--);
147
Raffaele Recalcati894b1e22011-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 Heo1be00d92012-06-03 21:32:13 +0000152 if (timeout <= 0) {
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100153#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000154 printf("Timeout waiting card ready\n");
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100155#endif
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000156 return TIMEOUT;
157 }
158
159 return 0;
160}
161
Paul Burton8d30cc92013-09-09 15:30:26 +0100162int mmc_set_blocklen(struct mmc *mmc, int len)
Andy Flemingad347bb2008-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 Flemingad347bb2008-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 Burton6a7c5ba2013-09-04 16:12:25 +0100185#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Andy Flemingad347bb2008-10-30 16:41:01 -0500186 printf("MMC Device %d not found\n", dev_num);
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100187#endif
Andy Flemingad347bb2008-10-30 16:41:01 -0500188
189 return NULL;
190}
191
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +0200192static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
Kim Phillips87ea3892012-10-29 13:34:43 +0000193 lbaint_t blkcnt)
Andy Flemingad347bb2008-10-30 16:41:01 -0500194{
195 struct mmc_cmd cmd;
196 struct mmc_data data;
197
Alagu Sankarc25d1b92010-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 Flemingad347bb2008-10-30 16:41:01 -0500202
203 if (mmc->high_capacity)
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700204 cmd.cmdarg = start;
Andy Flemingad347bb2008-10-30 16:41:01 -0500205 else
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700206 cmd.cmdarg = start * mmc->read_bl_len;
Andy Flemingad347bb2008-10-30 16:41:01 -0500207
208 cmd.resp_type = MMC_RSP_R1;
Andy Flemingad347bb2008-10-30 16:41:01 -0500209
210 data.dest = dst;
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700211 data.blocks = blkcnt;
Andy Flemingad347bb2008-10-30 16:41:01 -0500212 data.blocksize = mmc->read_bl_len;
213 data.flags = MMC_DATA_READ;
214
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700215 if (mmc_send_cmd(mmc, &cmd, &data))
216 return 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500217
Alagu Sankarc25d1b92010-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 Sankarc25d1b92010-10-25 07:23:56 -0700222 if (mmc_send_cmd(mmc, &cmd, NULL)) {
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100223#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700224 printf("mmc fail to send stop cmd\n");
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100225#endif
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700226 return 0;
227 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500228 }
229
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700230 return blkcnt;
Andy Flemingad347bb2008-10-30 16:41:01 -0500231}
232
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +0200233static ulong mmc_bread(int dev_num, lbaint_t start, lbaint_t blkcnt, void *dst)
Andy Flemingad347bb2008-10-30 16:41:01 -0500234{
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700235 lbaint_t cur, blocks_todo = blkcnt;
236
237 if (blkcnt == 0)
238 return 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500239
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700240 struct mmc *mmc = find_mmc_device(dev_num);
Andy Flemingad347bb2008-10-30 16:41:01 -0500241 if (!mmc)
242 return 0;
243
Lei Wene1cc9c82010-09-13 22:07:27 +0800244 if ((start + blkcnt) > mmc->block_dev.lba) {
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100245#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Sascha Silbe4bdf6fd2013-06-14 13:07:25 +0200246 printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
Lei Wene1cc9c82010-09-13 22:07:27 +0800247 start + blkcnt, mmc->block_dev.lba);
Paul Burton6a7c5ba2013-09-04 16:12:25 +0100248#endif
Lei Wene1cc9c82010-09-13 22:07:27 +0800249 return 0;
250 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500251
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700252 if (mmc_set_blocklen(mmc, mmc->read_bl_len))
Andy Flemingad347bb2008-10-30 16:41:01 -0500253 return 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500254
Alagu Sankarc25d1b92010-10-25 07:23:56 -0700255 do {
John Rigbyf2f43662011-04-18 05:50:08 +0000256 cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo;
Alagu Sankarc25d1b92010-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 Flemingad347bb2008-10-30 16:41:01 -0500263
264 return blkcnt;
265}
266
Kim Phillips87ea3892012-10-29 13:34:43 +0000267static int mmc_go_idle(struct mmc *mmc)
Andy Flemingad347bb2008-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 Flemingad347bb2008-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 Phillips87ea3892012-10-29 13:34:43 +0000288static int sd_send_op_cond(struct mmc *mmc)
Andy Flemingad347bb2008-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 Flemingad347bb2008-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 Babicf8e9a212010-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 Chou1254c3d2010-12-24 13:12:21 +0000314 cmd.cmdarg = mmc_host_is_spi(mmc) ? 0 :
315 (mmc->voltages & 0xff8000);
Andy Flemingad347bb2008-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 Chou1254c3d2010-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 Chou1254c3d2010-12-24 13:12:21 +0000338
339 err = mmc_send_cmd(mmc, &cmd, NULL);
340
341 if (err)
342 return err;
343 }
344
Rabin Vincentb6eed942009-04-05 13:30:56 +0530345 mmc->ocr = cmd.response[0];
Andy Flemingad347bb2008-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 Chiou4a2c7d72012-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 Flemingad347bb2008-10-30 16:41:01 -0500356{
Andy Flemingad347bb2008-10-30 16:41:01 -0500357 int err;
358
Che-Liang Chiou4a2c7d72012-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 Flemingad347bb2008-10-30 16:41:01 -0500383 /* Some cards seem to need this */
384 mmc_go_idle(mmc);
385
Raffaele Recalcati1df837e2011-03-11 02:01:13 +0000386 /* Asking to the card its capabilities */
Che-Liang Chiou4a2c7d72012-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);
390 if (err)
391 return err;
Wolfgang Denk80f70212011-05-19 22:21:41 +0200392
Che-Liang Chiou4a2c7d72012-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}
Wolfgang Denk80f70212011-05-19 22:21:41 +0200399
Che-Liang Chiou4a2c7d72012-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;
Wolfgang Denk80f70212011-05-19 22:21:41 +0200406
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000407 mmc->op_cond_pending = 0;
408 start = get_timer(0);
Andy Flemingad347bb2008-10-30 16:41:01 -0500409 do {
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000410 err = mmc_send_op_cond_iter(mmc, &cmd, 1);
Andy Flemingad347bb2008-10-30 16:41:01 -0500411 if (err)
412 return err;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +0000413 if (get_timer(start) > timeout)
414 return UNUSABLE_ERR;
415 udelay(100);
416 } while (!(mmc->op_cond_response & OCR_BUSY));
Andy Flemingad347bb2008-10-30 16:41:01 -0500417
Thomas Chou1254c3d2010-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 Chou1254c3d2010-12-24 13:12:21 +0000422
423 err = mmc_send_cmd(mmc, &cmd, NULL);
424
425 if (err)
426 return err;
427 }
428
Andy Flemingad347bb2008-10-30 16:41:01 -0500429 mmc->version = MMC_VERSION_UNKNOWN;
Rabin Vincentb6eed942009-04-05 13:30:56 +0530430 mmc->ocr = cmd.response[0];
Andy Flemingad347bb2008-10-30 16:41:01 -0500431
432 mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
Stephen Warrenf6545f12014-01-30 16:11:12 -0700433 mmc->rca = 1;
Andy Flemingad347bb2008-10-30 16:41:01 -0500434
435 return 0;
436}
437
438
Kim Phillips87ea3892012-10-29 13:34:43 +0000439static int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd)
Andy Flemingad347bb2008-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 Flemingad347bb2008-10-30 16:41:01 -0500449
Yoshihiro Shimodaf6bec732012-06-07 19:09:11 +0000450 data.dest = (char *)ext_csd;
Andy Flemingad347bb2008-10-30 16:41:01 -0500451 data.blocks = 1;
Simon Glassa09c2b72013-04-03 08:54:30 +0000452 data.blocksize = MMC_MAX_BLOCK_LEN;
Andy Flemingad347bb2008-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 Phillips87ea3892012-10-29 13:34:43 +0000461static int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
Andy Flemingad347bb2008-10-30 16:41:01 -0500462{
463 struct mmc_cmd cmd;
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000464 int timeout = 1000;
465 int ret;
Andy Flemingad347bb2008-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 Recalcati01a0dc62011-03-11 02:01:12 +0000470 (index << 16) |
471 (value << 8);
Andy Flemingad347bb2008-10-30 16:41:01 -0500472
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000473 ret = mmc_send_cmd(mmc, &cmd, NULL);
474
475 /* Waiting for the ready status */
Jan Kloetzke4e929dd2012-02-05 22:29:11 +0000476 if (!ret)
477 ret = mmc_send_status(mmc, timeout);
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000478
479 return ret;
480
Andy Flemingad347bb2008-10-30 16:41:01 -0500481}
482
Kim Phillips87ea3892012-10-29 13:34:43 +0000483static int mmc_change_freq(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -0500484{
Simon Glassa09c2b72013-04-03 08:54:30 +0000485 ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
Andy Flemingad347bb2008-10-30 16:41:01 -0500486 char cardtype;
487 int err;
488
489 mmc->card_caps = 0;
490
Thomas Chou1254c3d2010-12-24 13:12:21 +0000491 if (mmc_host_is_spi(mmc))
492 return 0;
493
Andy Flemingad347bb2008-10-30 16:41:01 -0500494 /* Only version 4 supports high-speed */
495 if (mmc->version < MMC_VERSION_4)
496 return 0;
497
Andy Flemingad347bb2008-10-30 16:41:01 -0500498 err = mmc_send_ext_csd(mmc, ext_csd);
499
500 if (err)
501 return err;
502
Lei Wen217467f2011-10-03 20:35:10 +0000503 cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0xf;
Andy Flemingad347bb2008-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 Wen217467f2011-10-03 20:35:10 +0000517 if (!ext_csd[EXT_CSD_HS_TIMING])
Andy Flemingad347bb2008-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 Warrene315ae82013-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 Wen31b99802011-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 Warrene315ae82013-06-11 15:14:01 -0600560 int ret;
Lei Wen31b99802011-05-02 16:26:26 +0000561
562 if (!mmc)
563 return -1;
564
Stephen Warrene315ae82013-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 Wen31b99802011-05-02 16:26:26 +0000572}
573
Thierry Redingb9c8b772012-01-02 01:15:37 +0000574int mmc_getcd(struct mmc *mmc)
575{
576 int cd;
577
578 cd = board_mmc_getcd(mmc);
579
Peter Korsgaardf7b15102013-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 Redingb9c8b772012-01-02 01:15:37 +0000586
587 return cd;
588}
589
Kim Phillips87ea3892012-10-29 13:34:43 +0000590static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
Andy Flemingad347bb2008-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 Flemingad347bb2008-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 Phillips87ea3892012-10-29 13:34:43 +0000611static int sd_change_freq(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -0500612{
613 int err;
614 struct mmc_cmd cmd;
Anton staaf9b00f0d2011-10-03 13:54:59 +0000615 ALLOC_CACHE_ALIGN_BUFFER(uint, scr, 2);
616 ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);
Andy Flemingad347bb2008-10-30 16:41:01 -0500617 struct mmc_data data;
618 int timeout;
619
620 mmc->card_caps = 0;
621
Thomas Chou1254c3d2010-12-24 13:12:21 +0000622 if (mmc_host_is_spi(mmc))
623 return 0;
624
Andy Flemingad347bb2008-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 Flemingad347bb2008-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 Flemingad347bb2008-10-30 16:41:01 -0500638
639 timeout = 3;
640
641retry_scr:
Anton staaf9b00f0d2011-10-03 13:54:59 +0000642 data.dest = (char *)scr;
Andy Flemingad347bb2008-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 Kharuzhy6e8edf42009-05-07 00:43:30 +0300656 mmc->scr[0] = __be32_to_cpu(scr[0]);
657 mmc->scr[1] = __be32_to_cpu(scr[1]);
Andy Flemingad347bb2008-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 Chungd552bd12013-01-29 22:58:16 +0000668 if ((mmc->scr[0] >> 15) & 0x1)
669 mmc->version = SD_VERSION_3;
Andy Flemingad347bb2008-10-30 16:41:01 -0500670 break;
671 default:
672 mmc->version = SD_VERSION_1_0;
673 break;
674 }
675
Alagu Sankar24bb5ab2010-05-12 15:08:24 +0530676 if (mmc->scr[0] & SD_DATA_4BIT)
677 mmc->card_caps |= MMC_MODE_4BIT;
678
Andy Flemingad347bb2008-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 staaf9b00f0d2011-10-03 13:54:59 +0000686 (u8 *)switch_status);
Andy Flemingad347bb2008-10-30 16:41:01 -0500687
688 if (err)
689 return err;
690
691 /* The high-speed function is busy. Try again */
Yauhen Kharuzhy6e8edf42009-05-07 00:43:30 +0300692 if (!(__be32_to_cpu(switch_status[7]) & SD_HIGHSPEED_BUSY))
Andy Flemingad347bb2008-10-30 16:41:01 -0500693 break;
694 }
695
Andy Flemingad347bb2008-10-30 16:41:01 -0500696 /* If high-speed isn't supported, we return */
Yauhen Kharuzhy6e8edf42009-05-07 00:43:30 +0300697 if (!(__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED))
Andy Flemingad347bb2008-10-30 16:41:01 -0500698 return 0;
699
Macpaul Lin24e92ec2011-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 staaf9b00f0d2011-10-03 13:54:59 +0000710 err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status);
Andy Flemingad347bb2008-10-30 16:41:01 -0500711
712 if (err)
713 return err;
714
Yauhen Kharuzhy6e8edf42009-05-07 00:43:30 +0300715 if ((__be32_to_cpu(switch_status[4]) & 0x0f000000) == 0x01000000)
Andy Flemingad347bb2008-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 Frysingerb588caf2010-10-20 01:15:53 +0000723static const int fbase[] = {
Andy Flemingad347bb2008-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 Frysingerb588caf2010-10-20 01:15:53 +0000733static const int multipliers[] = {
Andy Flemingad347bb2008-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 Phillips87ea3892012-10-29 13:34:43 +0000752static void mmc_set_ios(struct mmc *mmc)
Andy Flemingad347bb2008-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 Phillips87ea3892012-10-29 13:34:43 +0000770static void mmc_set_bus_width(struct mmc *mmc, uint width)
Andy Flemingad347bb2008-10-30 16:41:01 -0500771{
772 mmc->bus_width = width;
773
774 mmc_set_ios(mmc);
775}
776
Kim Phillips87ea3892012-10-29 13:34:43 +0000777static int mmc_startup(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -0500778{
Stephen Warrene315ae82013-06-11 15:14:01 -0600779 int err, i;
Andy Flemingad347bb2008-10-30 16:41:01 -0500780 uint mult, freq;
Yoshihiro Shimoda7d88de52011-07-04 22:13:26 +0000781 u64 cmult, csize, capacity;
Andy Flemingad347bb2008-10-30 16:41:01 -0500782 struct mmc_cmd cmd;
Simon Glassa09c2b72013-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 Recalcati01a0dc62011-03-11 02:01:12 +0000785 int timeout = 1000;
Andy Flemingad347bb2008-10-30 16:41:01 -0500786
Thomas Chou1254c3d2010-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 Chou1254c3d2010-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 Flemingad347bb2008-10-30 16:41:01 -0500799 /* Put the Card in Identify Mode */
Thomas Chou1254c3d2010-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 Flemingad347bb2008-10-30 16:41:01 -0500802 cmd.resp_type = MMC_RSP_R2;
803 cmd.cmdarg = 0;
Andy Flemingad347bb2008-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 Chou1254c3d2010-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 Flemingad347bb2008-10-30 16:41:01 -0500821
Thomas Chou1254c3d2010-12-24 13:12:21 +0000822 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Flemingad347bb2008-10-30 16:41:01 -0500823
Thomas Chou1254c3d2010-12-24 13:12:21 +0000824 if (err)
825 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -0500826
Thomas Chou1254c3d2010-12-24 13:12:21 +0000827 if (IS_SD(mmc))
828 mmc->rca = (cmd.response[0] >> 16) & 0xffff;
829 }
Andy Flemingad347bb2008-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 Flemingad347bb2008-10-30 16:41:01 -0500835
836 err = mmc_send_cmd(mmc, &cmd, NULL);
837
Raffaele Recalcati01a0dc62011-03-11 02:01:12 +0000838 /* Waiting for the ready status */
839 mmc_send_status(mmc, timeout);
840
Andy Flemingad347bb2008-10-30 16:41:01 -0500841 if (err)
842 return err;
843
Rabin Vincentb6eed942009-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 Flemingad347bb2008-10-30 16:41:01 -0500848
849 if (mmc->version == MMC_VERSION_UNKNOWN) {
Rabin Vincentbdf7a682009-04-05 13:30:55 +0530850 int version = (cmd.response[0] >> 26) & 0xf;
Andy Flemingad347bb2008-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 Vincentbdf7a682009-04-05 13:30:55 +0530875 freq = fbase[(cmd.response[0] & 0x7)];
876 mult = multipliers[((cmd.response[0] >> 3) & 0xf)];
Andy Flemingad347bb2008-10-30 16:41:01 -0500877
878 mmc->tran_speed = freq * mult;
879
Markus Niebel03951412013-12-16 13:40:46 +0100880 mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1);
Rabin Vincentb6eed942009-04-05 13:30:56 +0530881 mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf);
Andy Flemingad347bb2008-10-30 16:41:01 -0500882
883 if (IS_SD(mmc))
884 mmc->write_bl_len = mmc->read_bl_len;
885 else
Rabin Vincentb6eed942009-04-05 13:30:56 +0530886 mmc->write_bl_len = 1 << ((cmd.response[3] >> 22) & 0xf);
Andy Flemingad347bb2008-10-30 16:41:01 -0500887
888 if (mmc->high_capacity) {
889 csize = (mmc->csd[1] & 0x3f) << 16
890 | (mmc->csd[2] & 0xffff0000) >> 16;
891 cmult = 8;
892 } else {
893 csize = (mmc->csd[1] & 0x3ff) << 2
894 | (mmc->csd[2] & 0xc0000000) >> 30;
895 cmult = (mmc->csd[2] & 0x00038000) >> 15;
896 }
897
Stephen Warrene315ae82013-06-11 15:14:01 -0600898 mmc->capacity_user = (csize + 1) << (cmult + 2);
899 mmc->capacity_user *= mmc->read_bl_len;
900 mmc->capacity_boot = 0;
901 mmc->capacity_rpmb = 0;
902 for (i = 0; i < 4; i++)
903 mmc->capacity_gp[i] = 0;
Andy Flemingad347bb2008-10-30 16:41:01 -0500904
Simon Glassa09c2b72013-04-03 08:54:30 +0000905 if (mmc->read_bl_len > MMC_MAX_BLOCK_LEN)
906 mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
Andy Flemingad347bb2008-10-30 16:41:01 -0500907
Simon Glassa09c2b72013-04-03 08:54:30 +0000908 if (mmc->write_bl_len > MMC_MAX_BLOCK_LEN)
909 mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
Andy Flemingad347bb2008-10-30 16:41:01 -0500910
Markus Niebel03951412013-12-16 13:40:46 +0100911 if ((mmc->dsr_imp) && (0xffffffff != mmc->dsr)) {
912 cmd.cmdidx = MMC_CMD_SET_DSR;
913 cmd.cmdarg = (mmc->dsr & 0xffff) << 16;
914 cmd.resp_type = MMC_RSP_NONE;
915 if (mmc_send_cmd(mmc, &cmd, NULL))
916 printf("MMC: SET_DSR failed\n");
917 }
918
Andy Flemingad347bb2008-10-30 16:41:01 -0500919 /* Select the card, and put it into Transfer Mode */
Thomas Chou1254c3d2010-12-24 13:12:21 +0000920 if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
921 cmd.cmdidx = MMC_CMD_SELECT_CARD;
Ajay Bhargav4a32fba2011-10-05 03:13:23 +0000922 cmd.resp_type = MMC_RSP_R1;
Thomas Chou1254c3d2010-12-24 13:12:21 +0000923 cmd.cmdarg = mmc->rca << 16;
Thomas Chou1254c3d2010-12-24 13:12:21 +0000924 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Flemingad347bb2008-10-30 16:41:01 -0500925
Thomas Chou1254c3d2010-12-24 13:12:21 +0000926 if (err)
927 return err;
928 }
Andy Flemingad347bb2008-10-30 16:41:01 -0500929
Lei Wenea526762011-06-22 17:03:31 +0000930 /*
931 * For SD, its erase group is always one sector
932 */
933 mmc->erase_grp_size = 1;
Lei Wen31b99802011-05-02 16:26:26 +0000934 mmc->part_config = MMCPART_NOAVAILABLE;
Sukumar Ghorai232293c2010-09-20 18:29:29 +0530935 if (!IS_SD(mmc) && (mmc->version >= MMC_VERSION_4)) {
936 /* check ext_csd version and capacity */
937 err = mmc_send_ext_csd(mmc, ext_csd);
Kim Phillips87ea3892012-10-29 13:34:43 +0000938 if (!err && (ext_csd[EXT_CSD_REV] >= 2)) {
Yoshihiro Shimoda7d88de52011-07-04 22:13:26 +0000939 /*
940 * According to the JEDEC Standard, the value of
941 * ext_csd's capacity is valid if the value is more
942 * than 2GB
943 */
Lei Wen217467f2011-10-03 20:35:10 +0000944 capacity = ext_csd[EXT_CSD_SEC_CNT] << 0
945 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8
946 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16
947 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
Simon Glassa09c2b72013-04-03 08:54:30 +0000948 capacity *= MMC_MAX_BLOCK_LEN;
Łukasz Majewski237823e2011-07-05 02:19:44 +0000949 if ((capacity >> 20) > 2 * 1024)
Stephen Warrene315ae82013-06-11 15:14:01 -0600950 mmc->capacity_user = capacity;
Sukumar Ghorai232293c2010-09-20 18:29:29 +0530951 }
Lei Wen31b99802011-05-02 16:26:26 +0000952
Jaehoon Chung6108ef62013-01-29 19:31:16 +0000953 switch (ext_csd[EXT_CSD_REV]) {
954 case 1:
955 mmc->version = MMC_VERSION_4_1;
956 break;
957 case 2:
958 mmc->version = MMC_VERSION_4_2;
959 break;
960 case 3:
961 mmc->version = MMC_VERSION_4_3;
962 break;
963 case 5:
964 mmc->version = MMC_VERSION_4_41;
965 break;
966 case 6:
967 mmc->version = MMC_VERSION_4_5;
968 break;
969 }
970
Lei Wenea526762011-06-22 17:03:31 +0000971 /*
Oliver Metzb3f14092013-10-01 20:32:07 +0200972 * Host needs to enable ERASE_GRP_DEF bit if device is
973 * partitioned. This bit will be lost every time after a reset
974 * or power off. This will affect erase size.
Lei Wenea526762011-06-22 17:03:31 +0000975 */
Oliver Metzb3f14092013-10-01 20:32:07 +0200976 if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) &&
977 (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & PART_ENH_ATTRIB)) {
978 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
979 EXT_CSD_ERASE_GROUP_DEF, 1);
980
981 if (err)
982 return err;
983
984 /* Read out group size from ext_csd */
Lei Wen217467f2011-10-03 20:35:10 +0000985 mmc->erase_grp_size =
Simon Glassa09c2b72013-04-03 08:54:30 +0000986 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] *
987 MMC_MAX_BLOCK_LEN * 1024;
988 } else {
Oliver Metzb3f14092013-10-01 20:32:07 +0200989 /* Calculate the group size from the csd value. */
Lei Wenea526762011-06-22 17:03:31 +0000990 int erase_gsz, erase_gmul;
991 erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10;
992 erase_gmul = (mmc->csd[2] & 0x000003e0) >> 5;
993 mmc->erase_grp_size = (erase_gsz + 1)
994 * (erase_gmul + 1);
995 }
996
Lei Wen31b99802011-05-02 16:26:26 +0000997 /* store the partition info of emmc */
Stephen Warren009784c2012-07-30 10:55:43 +0000998 if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) ||
999 ext_csd[EXT_CSD_BOOT_MULT])
Lei Wen217467f2011-10-03 20:35:10 +00001000 mmc->part_config = ext_csd[EXT_CSD_PART_CONF];
Stephen Warrene315ae82013-06-11 15:14:01 -06001001
1002 mmc->capacity_boot = ext_csd[EXT_CSD_BOOT_MULT] << 17;
1003
1004 mmc->capacity_rpmb = ext_csd[EXT_CSD_RPMB_MULT] << 17;
1005
1006 for (i = 0; i < 4; i++) {
1007 int idx = EXT_CSD_GP_SIZE_MULT + i * 3;
1008 mmc->capacity_gp[i] = (ext_csd[idx + 2] << 16) +
1009 (ext_csd[idx + 1] << 8) + ext_csd[idx];
1010 mmc->capacity_gp[i] *=
1011 ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
1012 mmc->capacity_gp[i] *= ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
1013 }
Sukumar Ghorai232293c2010-09-20 18:29:29 +05301014 }
1015
Stephen Warrene315ae82013-06-11 15:14:01 -06001016 err = mmc_set_capacity(mmc, mmc->part_num);
1017 if (err)
1018 return err;
1019
Andy Flemingad347bb2008-10-30 16:41:01 -05001020 if (IS_SD(mmc))
1021 err = sd_change_freq(mmc);
1022 else
1023 err = mmc_change_freq(mmc);
1024
1025 if (err)
1026 return err;
1027
1028 /* Restrict card's capabilities by what the host can do */
1029 mmc->card_caps &= mmc->host_caps;
1030
1031 if (IS_SD(mmc)) {
1032 if (mmc->card_caps & MMC_MODE_4BIT) {
1033 cmd.cmdidx = MMC_CMD_APP_CMD;
1034 cmd.resp_type = MMC_RSP_R1;
1035 cmd.cmdarg = mmc->rca << 16;
Andy Flemingad347bb2008-10-30 16:41:01 -05001036
1037 err = mmc_send_cmd(mmc, &cmd, NULL);
1038 if (err)
1039 return err;
1040
1041 cmd.cmdidx = SD_CMD_APP_SET_BUS_WIDTH;
1042 cmd.resp_type = MMC_RSP_R1;
1043 cmd.cmdarg = 2;
Andy Flemingad347bb2008-10-30 16:41:01 -05001044 err = mmc_send_cmd(mmc, &cmd, NULL);
1045 if (err)
1046 return err;
1047
1048 mmc_set_bus_width(mmc, 4);
1049 }
1050
1051 if (mmc->card_caps & MMC_MODE_HS)
Jaehoon Chunge1d4c7b2012-03-26 21:16:03 +00001052 mmc->tran_speed = 50000000;
Andy Flemingad347bb2008-10-30 16:41:01 -05001053 else
Jaehoon Chunge1d4c7b2012-03-26 21:16:03 +00001054 mmc->tran_speed = 25000000;
Andy Flemingad347bb2008-10-30 16:41:01 -05001055 } else {
Andy Flemingeb766ad2012-10-31 19:02:38 +00001056 int idx;
1057
1058 /* An array of possible bus widths in order of preference */
1059 static unsigned ext_csd_bits[] = {
1060 EXT_CSD_BUS_WIDTH_8,
1061 EXT_CSD_BUS_WIDTH_4,
1062 EXT_CSD_BUS_WIDTH_1,
1063 };
1064
1065 /* An array to map CSD bus widths to host cap bits */
1066 static unsigned ext_to_hostcaps[] = {
1067 [EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT,
1068 [EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT,
1069 };
1070
1071 /* An array to map chosen bus width to an integer */
1072 static unsigned widths[] = {
1073 8, 4, 1,
1074 };
1075
1076 for (idx=0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
1077 unsigned int extw = ext_csd_bits[idx];
1078
1079 /*
1080 * Check to make sure the controller supports
1081 * this bus width, if it's more than 1
1082 */
1083 if (extw != EXT_CSD_BUS_WIDTH_1 &&
1084 !(mmc->host_caps & ext_to_hostcaps[extw]))
1085 continue;
1086
Andy Flemingad347bb2008-10-30 16:41:01 -05001087 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
Andy Flemingeb766ad2012-10-31 19:02:38 +00001088 EXT_CSD_BUS_WIDTH, extw);
Andy Flemingad347bb2008-10-30 16:41:01 -05001089
1090 if (err)
Lei Wen4f5a6a52011-10-03 20:35:11 +00001091 continue;
Andy Flemingad347bb2008-10-30 16:41:01 -05001092
Andy Flemingeb766ad2012-10-31 19:02:38 +00001093 mmc_set_bus_width(mmc, widths[idx]);
Andy Flemingad347bb2008-10-30 16:41:01 -05001094
Lei Wen4f5a6a52011-10-03 20:35:11 +00001095 err = mmc_send_ext_csd(mmc, test_csd);
1096 if (!err && ext_csd[EXT_CSD_PARTITIONING_SUPPORT] \
1097 == test_csd[EXT_CSD_PARTITIONING_SUPPORT]
1098 && ext_csd[EXT_CSD_ERASE_GROUP_DEF] \
1099 == test_csd[EXT_CSD_ERASE_GROUP_DEF] \
1100 && ext_csd[EXT_CSD_REV] \
1101 == test_csd[EXT_CSD_REV]
1102 && ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] \
1103 == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
1104 && memcmp(&ext_csd[EXT_CSD_SEC_CNT], \
1105 &test_csd[EXT_CSD_SEC_CNT], 4) == 0) {
Andy Flemingad347bb2008-10-30 16:41:01 -05001106
Andy Flemingeb766ad2012-10-31 19:02:38 +00001107 mmc->card_caps |= ext_to_hostcaps[extw];
Lei Wen4f5a6a52011-10-03 20:35:11 +00001108 break;
1109 }
Andy Flemingad347bb2008-10-30 16:41:01 -05001110 }
1111
1112 if (mmc->card_caps & MMC_MODE_HS) {
1113 if (mmc->card_caps & MMC_MODE_HS_52MHz)
Jaehoon Chunge1d4c7b2012-03-26 21:16:03 +00001114 mmc->tran_speed = 52000000;
Andy Flemingad347bb2008-10-30 16:41:01 -05001115 else
Jaehoon Chunge1d4c7b2012-03-26 21:16:03 +00001116 mmc->tran_speed = 26000000;
1117 }
Andy Flemingad347bb2008-10-30 16:41:01 -05001118 }
1119
Jaehoon Chunge1d4c7b2012-03-26 21:16:03 +00001120 mmc_set_clock(mmc, mmc->tran_speed);
1121
Andy Flemingad347bb2008-10-30 16:41:01 -05001122 /* fill in device description */
1123 mmc->block_dev.lun = 0;
1124 mmc->block_dev.type = 0;
1125 mmc->block_dev.blksz = mmc->read_bl_len;
Egbert Eich2eec2ab2013-04-09 21:11:56 +00001126 mmc->block_dev.log2blksz = LOG2(mmc->block_dev.blksz);
Rabin Vincent69d4e2c2009-04-05 13:30:54 +05301127 mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len);
Paul Burton6a7c5ba2013-09-04 16:12:25 +01001128#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Taylor Hutt7367ec22012-10-20 17:15:59 +00001129 sprintf(mmc->block_dev.vendor, "Man %06x Snr %04x%04x",
1130 mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff),
1131 (mmc->cid[3] >> 16) & 0xffff);
1132 sprintf(mmc->block_dev.product, "%c%c%c%c%c%c", mmc->cid[0] & 0xff,
1133 (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
1134 (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff,
1135 (mmc->cid[2] >> 24) & 0xff);
1136 sprintf(mmc->block_dev.revision, "%d.%d", (mmc->cid[2] >> 20) & 0xf,
1137 (mmc->cid[2] >> 16) & 0xf);
Paul Burton6a7c5ba2013-09-04 16:12:25 +01001138#else
1139 mmc->block_dev.vendor[0] = 0;
1140 mmc->block_dev.product[0] = 0;
1141 mmc->block_dev.revision[0] = 0;
1142#endif
Mikhail Kshevetskiy5cbfa8e7a2012-07-09 08:53:38 +00001143#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT)
Andy Flemingad347bb2008-10-30 16:41:01 -05001144 init_part(&mmc->block_dev);
Mikhail Kshevetskiy5cbfa8e7a2012-07-09 08:53:38 +00001145#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001146
1147 return 0;
1148}
1149
Kim Phillips87ea3892012-10-29 13:34:43 +00001150static int mmc_send_if_cond(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05001151{
1152 struct mmc_cmd cmd;
1153 int err;
1154
1155 cmd.cmdidx = SD_CMD_SEND_IF_COND;
1156 /* We set the bit if the host supports voltages between 2.7 and 3.6 V */
1157 cmd.cmdarg = ((mmc->voltages & 0xff8000) != 0) << 8 | 0xaa;
1158 cmd.resp_type = MMC_RSP_R7;
Andy Flemingad347bb2008-10-30 16:41:01 -05001159
1160 err = mmc_send_cmd(mmc, &cmd, NULL);
1161
1162 if (err)
1163 return err;
1164
Rabin Vincentb6eed942009-04-05 13:30:56 +05301165 if ((cmd.response[0] & 0xff) != 0xaa)
Andy Flemingad347bb2008-10-30 16:41:01 -05001166 return UNUSABLE_ERR;
1167 else
1168 mmc->version = SD_VERSION_2;
1169
1170 return 0;
1171}
1172
1173int mmc_register(struct mmc *mmc)
1174{
Markus Niebel03951412013-12-16 13:40:46 +01001175 /* Setup dsr related values */
1176 mmc->dsr_imp = 0;
1177 mmc->dsr = 0xffffffff;
Andy Flemingad347bb2008-10-30 16:41:01 -05001178 /* Setup the universal parts of the block interface just once */
1179 mmc->block_dev.if_type = IF_TYPE_MMC;
1180 mmc->block_dev.dev = cur_dev_num++;
1181 mmc->block_dev.removable = 1;
1182 mmc->block_dev.block_read = mmc_bread;
1183 mmc->block_dev.block_write = mmc_bwrite;
Lei Wenea526762011-06-22 17:03:31 +00001184 mmc->block_dev.block_erase = mmc_berase;
John Rigbyf2f43662011-04-18 05:50:08 +00001185 if (!mmc->b_max)
1186 mmc->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
Andy Flemingad347bb2008-10-30 16:41:01 -05001187
1188 INIT_LIST_HEAD (&mmc->link);
1189
1190 list_add_tail (&mmc->link, &mmc_devices);
1191
1192 return 0;
1193}
1194
Matthew McClintock6252b4f2011-05-24 05:31:19 +00001195#ifdef CONFIG_PARTITIONS
Andy Flemingad347bb2008-10-30 16:41:01 -05001196block_dev_desc_t *mmc_get_dev(int dev)
1197{
1198 struct mmc *mmc = find_mmc_device(dev);
Benoît Thébaudeau6ce8aed2012-08-10 08:59:12 +00001199 if (!mmc || mmc_init(mmc))
Łukasz Majewski65b04cf2012-04-19 02:39:18 +00001200 return NULL;
Andy Flemingad347bb2008-10-30 16:41:01 -05001201
Łukasz Majewski65b04cf2012-04-19 02:39:18 +00001202 return &mmc->block_dev;
Andy Flemingad347bb2008-10-30 16:41:01 -05001203}
Matthew McClintock6252b4f2011-05-24 05:31:19 +00001204#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001205
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00001206int mmc_start_init(struct mmc *mmc)
Andy Flemingad347bb2008-10-30 16:41:01 -05001207{
Macpaul Lin028bde12011-11-14 23:35:39 +00001208 int err;
Andy Flemingad347bb2008-10-30 16:41:01 -05001209
Thierry Redingb9c8b772012-01-02 01:15:37 +00001210 if (mmc_getcd(mmc) == 0) {
1211 mmc->has_init = 0;
Paul Burton6a7c5ba2013-09-04 16:12:25 +01001212#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Thierry Redingb9c8b772012-01-02 01:15:37 +00001213 printf("MMC: no card present\n");
Paul Burton6a7c5ba2013-09-04 16:12:25 +01001214#endif
Thierry Redingb9c8b772012-01-02 01:15:37 +00001215 return NO_CARD_ERR;
1216 }
1217
Lei Wen31b99802011-05-02 16:26:26 +00001218 if (mmc->has_init)
1219 return 0;
1220
Andy Flemingad347bb2008-10-30 16:41:01 -05001221 err = mmc->init(mmc);
1222
1223 if (err)
1224 return err;
1225
Ilya Yanok8459aab2009-06-29 17:53:16 +04001226 mmc_set_bus_width(mmc, 1);
1227 mmc_set_clock(mmc, 1);
1228
Andy Flemingad347bb2008-10-30 16:41:01 -05001229 /* Reset the Card */
1230 err = mmc_go_idle(mmc);
1231
1232 if (err)
1233 return err;
1234
Lei Wen31b99802011-05-02 16:26:26 +00001235 /* The internal partition reset to user partition(0) at every CMD0*/
1236 mmc->part_num = 0;
1237
Andy Flemingad347bb2008-10-30 16:41:01 -05001238 /* Test for SD version 2 */
Macpaul Lin028bde12011-11-14 23:35:39 +00001239 err = mmc_send_if_cond(mmc);
Andy Flemingad347bb2008-10-30 16:41:01 -05001240
Andy Flemingad347bb2008-10-30 16:41:01 -05001241 /* Now try to get the SD card's operating condition */
1242 err = sd_send_op_cond(mmc);
1243
1244 /* If the command timed out, we check for an MMC card */
1245 if (err == TIMEOUT) {
1246 err = mmc_send_op_cond(mmc);
1247
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00001248 if (err && err != IN_PROGRESS) {
Paul Burton6a7c5ba2013-09-04 16:12:25 +01001249#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
Andy Flemingad347bb2008-10-30 16:41:01 -05001250 printf("Card did not respond to voltage select!\n");
Paul Burton6a7c5ba2013-09-04 16:12:25 +01001251#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001252 return UNUSABLE_ERR;
1253 }
1254 }
1255
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00001256 if (err == IN_PROGRESS)
1257 mmc->init_in_progress = 1;
1258
1259 return err;
1260}
1261
1262static int mmc_complete_init(struct mmc *mmc)
1263{
1264 int err = 0;
1265
1266 if (mmc->op_cond_pending)
1267 err = mmc_complete_op_cond(mmc);
1268
1269 if (!err)
1270 err = mmc_startup(mmc);
Lei Wen31b99802011-05-02 16:26:26 +00001271 if (err)
1272 mmc->has_init = 0;
1273 else
1274 mmc->has_init = 1;
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00001275 mmc->init_in_progress = 0;
Lei Wen31b99802011-05-02 16:26:26 +00001276 return err;
Andy Flemingad347bb2008-10-30 16:41:01 -05001277}
1278
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00001279int mmc_init(struct mmc *mmc)
1280{
1281 int err = IN_PROGRESS;
1282 unsigned start = get_timer(0);
1283
1284 if (mmc->has_init)
1285 return 0;
1286 if (!mmc->init_in_progress)
1287 err = mmc_start_init(mmc);
1288
1289 if (!err || err == IN_PROGRESS)
1290 err = mmc_complete_init(mmc);
1291 debug("%s: %d, time %lu\n", __func__, err, get_timer(start));
1292 return err;
1293}
1294
Markus Niebel03951412013-12-16 13:40:46 +01001295int mmc_set_dsr(struct mmc *mmc, u16 val)
1296{
1297 mmc->dsr = val;
1298 return 0;
1299}
1300
Andy Flemingad347bb2008-10-30 16:41:01 -05001301/*
1302 * CPU and board-specific MMC initializations. Aliased function
1303 * signals caller to move on
1304 */
1305static int __def_mmc_init(bd_t *bis)
1306{
1307 return -1;
1308}
1309
Peter Tyser21d2cd22009-04-20 11:08:46 -05001310int cpu_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
1311int board_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
Andy Flemingad347bb2008-10-30 16:41:01 -05001312
Paul Burton6a7c5ba2013-09-04 16:12:25 +01001313#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
1314
Andy Flemingad347bb2008-10-30 16:41:01 -05001315void print_mmc_devices(char separator)
1316{
1317 struct mmc *m;
1318 struct list_head *entry;
1319
1320 list_for_each(entry, &mmc_devices) {
1321 m = list_entry(entry, struct mmc, link);
1322
1323 printf("%s: %d", m->name, m->block_dev.dev);
1324
1325 if (entry->next != &mmc_devices)
1326 printf("%c ", separator);
1327 }
1328
1329 printf("\n");
1330}
1331
Paul Burton6a7c5ba2013-09-04 16:12:25 +01001332#else
1333void print_mmc_devices(char separator) { }
1334#endif
1335
Lei Wend430d7c2011-05-02 16:26:25 +00001336int get_mmc_num(void)
1337{
1338 return cur_dev_num;
1339}
1340
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00001341void mmc_set_preinit(struct mmc *mmc, int preinit)
1342{
1343 mmc->preinit = preinit;
1344}
1345
1346static void do_preinit(void)
1347{
1348 struct mmc *m;
1349 struct list_head *entry;
1350
1351 list_for_each(entry, &mmc_devices) {
1352 m = list_entry(entry, struct mmc, link);
1353
1354 if (m->preinit)
1355 mmc_start_init(m);
1356 }
1357}
1358
1359
Andy Flemingad347bb2008-10-30 16:41:01 -05001360int mmc_initialize(bd_t *bis)
1361{
1362 INIT_LIST_HEAD (&mmc_devices);
1363 cur_dev_num = 0;
1364
1365 if (board_mmc_init(bis) < 0)
1366 cpu_mmc_init(bis);
1367
Ying Zhang9ff70262013-08-16 15:16:11 +08001368#ifndef CONFIG_SPL_BUILD
Andy Flemingad347bb2008-10-30 16:41:01 -05001369 print_mmc_devices(',');
Ying Zhang9ff70262013-08-16 15:16:11 +08001370#endif
Andy Flemingad347bb2008-10-30 16:41:01 -05001371
Che-Liang Chiou4a2c7d72012-11-28 15:21:13 +00001372 do_preinit();
Andy Flemingad347bb2008-10-30 16:41:01 -05001373 return 0;
1374}
Amar1104e9b2013-04-27 11:42:58 +05301375
1376#ifdef CONFIG_SUPPORT_EMMC_BOOT
1377/*
1378 * This function changes the size of boot partition and the size of rpmb
1379 * partition present on EMMC devices.
1380 *
1381 * Input Parameters:
1382 * struct *mmc: pointer for the mmc device strcuture
1383 * bootsize: size of boot partition
1384 * rpmbsize: size of rpmb partition
1385 *
1386 * Returns 0 on success.
1387 */
1388
1389int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
1390 unsigned long rpmbsize)
1391{
1392 int err;
1393 struct mmc_cmd cmd;
1394
1395 /* Only use this command for raw EMMC moviNAND. Enter backdoor mode */
1396 cmd.cmdidx = MMC_CMD_RES_MAN;
1397 cmd.resp_type = MMC_RSP_R1b;
1398 cmd.cmdarg = MMC_CMD62_ARG1;
1399
1400 err = mmc_send_cmd(mmc, &cmd, NULL);
1401 if (err) {
1402 debug("mmc_boot_partition_size_change: Error1 = %d\n", err);
1403 return err;
1404 }
1405
1406 /* Boot partition changing mode */
1407 cmd.cmdidx = MMC_CMD_RES_MAN;
1408 cmd.resp_type = MMC_RSP_R1b;
1409 cmd.cmdarg = MMC_CMD62_ARG2;
1410
1411 err = mmc_send_cmd(mmc, &cmd, NULL);
1412 if (err) {
1413 debug("mmc_boot_partition_size_change: Error2 = %d\n", err);
1414 return err;
1415 }
1416 /* boot partition size is multiple of 128KB */
1417 bootsize = (bootsize * 1024) / 128;
1418
1419 /* Arg: boot partition size */
1420 cmd.cmdidx = MMC_CMD_RES_MAN;
1421 cmd.resp_type = MMC_RSP_R1b;
1422 cmd.cmdarg = bootsize;
1423
1424 err = mmc_send_cmd(mmc, &cmd, NULL);
1425 if (err) {
1426 debug("mmc_boot_partition_size_change: Error3 = %d\n", err);
1427 return err;
1428 }
1429 /* RPMB partition size is multiple of 128KB */
1430 rpmbsize = (rpmbsize * 1024) / 128;
1431 /* Arg: RPMB partition size */
1432 cmd.cmdidx = MMC_CMD_RES_MAN;
1433 cmd.resp_type = MMC_RSP_R1b;
1434 cmd.cmdarg = rpmbsize;
1435
1436 err = mmc_send_cmd(mmc, &cmd, NULL);
1437 if (err) {
1438 debug("mmc_boot_partition_size_change: Error4 = %d\n", err);
1439 return err;
1440 }
1441 return 0;
1442}
1443
1444/*
Tom Rini4cf854c2014-02-05 10:24:22 -05001445 * Modify EXT_CSD[177] which is BOOT_BUS_WIDTH
1446 * based on the passed in values for BOOT_BUS_WIDTH, RESET_BOOT_BUS_WIDTH
1447 * and BOOT_MODE.
1448 *
1449 * Returns 0 on success.
1450 */
1451int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode)
1452{
1453 int err;
1454
1455 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_BUS_WIDTH,
1456 EXT_CSD_BOOT_BUS_WIDTH_MODE(mode) |
1457 EXT_CSD_BOOT_BUS_WIDTH_RESET(reset) |
1458 EXT_CSD_BOOT_BUS_WIDTH_WIDTH(width));
1459
1460 if (err)
1461 return err;
1462 return 0;
1463}
1464
1465/*
Tom Rinif8c6f792014-02-05 10:24:21 -05001466 * Modify EXT_CSD[179] which is PARTITION_CONFIG (formerly BOOT_CONFIG)
1467 * based on the passed in values for BOOT_ACK, BOOT_PARTITION_ENABLE and
1468 * PARTITION_ACCESS.
1469 *
1470 * Returns 0 on success.
1471 */
1472int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
1473{
1474 int err;
1475
1476 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
1477 EXT_CSD_BOOT_ACK(ack) |
1478 EXT_CSD_BOOT_PART_NUM(part_num) |
1479 EXT_CSD_PARTITION_ACCESS(access));
1480
1481 if (err)
1482 return err;
1483 return 0;
1484}
Amar1104e9b2013-04-27 11:42:58 +05301485#endif