blob: 42bebb90aa609fbfadebaf6f7dae23b2f227927b [file] [log] [blame]
Johan RUDHOLMa8bfde72012-02-12 11:46:44 -05001/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public
4 * License v2 as published by the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public
12 * License along with this program; if not, write to the
13 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14 * Boston, MA 021110-1307, USA.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <sys/ioctl.h>
21#include <sys/types.h>
22#include <dirent.h>
23#include <sys/stat.h>
24#include <unistd.h>
25#include <fcntl.h>
26#include <libgen.h>
27#include <limits.h>
Johan RUDHOLMa8bfde72012-02-12 11:46:44 -050028#include <ctype.h>
29
30#include "mmc.h"
31#include "mmc_cmds.h"
32
33int read_extcsd(int fd, __u8 *ext_csd)
34{
35 int ret = 0;
36 struct mmc_ioc_cmd idata;
37 memset(&idata, 0, sizeof(idata));
38 memset(ext_csd, 0, sizeof(__u8) * 512);
39 idata.write_flag = 0;
40 idata.opcode = MMC_SEND_EXT_CSD;
41 idata.arg = 0;
42 idata.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
43 idata.blksz = 512;
44 idata.blocks = 1;
45 mmc_ioc_cmd_set_data(idata, ext_csd);
46
47 ret = ioctl(fd, MMC_IOC_CMD, &idata);
48 if (ret)
49 perror("ioctl");
50
51 return ret;
52}
53
54int write_extcsd_value(int fd, __u8 index, __u8 value)
55{
56 int ret = 0;
57 struct mmc_ioc_cmd idata;
58
59 memset(&idata, 0, sizeof(idata));
60 idata.write_flag = 1;
61 idata.opcode = MMC_SWITCH;
62 idata.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
63 (index << 16) |
64 (value << 8) |
65 EXT_CSD_CMD_SET_NORMAL;
66 idata.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
67
68 ret = ioctl(fd, MMC_IOC_CMD, &idata);
69 if (ret)
70 perror("ioctl");
71
72 return ret;
73}
74
Chris Ballb9c7a172012-02-20 12:34:25 -050075void print_writeprotect_status(__u8 *ext_csd)
76{
77 __u8 reg;
78 __u8 ext_csd_rev = ext_csd[192];
79
80 /* A43: reserved [174:0] */
81 if (ext_csd_rev >= 5) {
82 printf("Boot write protection status registers"
83 " [BOOT_WP_STATUS]: 0x%02x\n", ext_csd[174]);
84
85 reg = ext_csd[EXT_CSD_BOOT_WP];
86 printf("Boot Area Write protection [BOOT_WP]: 0x%02x\n", reg);
87 printf(" Power ro locking: ");
88 if (reg & EXT_CSD_BOOT_WP_B_PWR_WP_DIS)
89 printf("not possible\n");
90 else
91 printf("possible\n");
92
93 printf(" Permanent ro locking: ");
94 if (reg & EXT_CSD_BOOT_WP_B_PERM_WP_DIS)
95 printf("not possible\n");
96 else
97 printf("possible\n");
98
99 printf(" ro lock status: ");
100 if (reg & EXT_CSD_BOOT_WP_B_PWR_WP_EN)
101 printf("locked until next power on\n");
102 else if (reg & EXT_CSD_BOOT_WP_B_PERM_WP_EN)
103 printf("locked permanently\n");
104 else
105 printf("not locked\n");
106 }
107}
108
109int do_writeprotect_get(int nargs, char **argv)
110{
111 __u8 ext_csd[512];
112 int fd, ret;
113 char *device;
114
Chris Ball8ba44662012-04-19 13:22:54 -0400115 CHECK(nargs != 2, "Usage: mmc writeprotect get </path/to/mmcblkX>\n",
116 exit(1));
Chris Ballb9c7a172012-02-20 12:34:25 -0500117
118 device = argv[1];
119
120 fd = open(device, O_RDWR);
121 if (fd < 0) {
122 perror("open");
123 exit(1);
124 }
125
126 ret = read_extcsd(fd, ext_csd);
127 if (ret) {
128 fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
129 exit(1);
130 }
131
132 print_writeprotect_status(ext_csd);
133
134 return ret;
135}
136
137int do_writeprotect_set(int nargs, char **argv)
138{
139 __u8 ext_csd[512], value;
140 int fd, ret;
141 char *device;
142
Chris Ball8ba44662012-04-19 13:22:54 -0400143 CHECK(nargs != 2, "Usage: mmc writeprotect set </path/to/mmcblkX>\n",
144 exit(1));
Chris Ballb9c7a172012-02-20 12:34:25 -0500145
146 device = argv[1];
147
148 fd = open(device, O_RDWR);
149 if (fd < 0) {
150 perror("open");
151 exit(1);
152 }
153
154 ret = read_extcsd(fd, ext_csd);
155 if (ret) {
156 fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
157 exit(1);
158 }
159
160 value = ext_csd[EXT_CSD_BOOT_WP] |
161 EXT_CSD_BOOT_WP_B_PWR_WP_EN;
162 ret = write_extcsd_value(fd, EXT_CSD_BOOT_WP, value);
163 if (ret) {
164 fprintf(stderr, "Could not write 0x%02x to "
165 "EXT_CSD[%d] in %s\n",
166 value, EXT_CSD_BOOT_WP, device);
167 exit(1);
168 }
169
170 return ret;
171}
172
Saugata Dasb7e25992012-05-17 09:26:34 -0400173int do_disable_512B_emulation(int nargs, char **argv)
174{
175 __u8 ext_csd[512], native_sector_size, data_sector_size, wr_rel_param;
176 int fd, ret;
177 char *device;
178
179 CHECK(nargs != 2, "Usage: mmc disable 512B emulation </path/to/mmcblkX>\n", exit(1));
180 device = argv[1];
181
182 fd = open(device, O_RDWR);
183 if (fd < 0) {
184 perror("open");
185 exit(1);
186 }
187
188 ret = read_extcsd(fd, ext_csd);
189 if (ret) {
190 fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
191 exit(1);
192 }
193
194 wr_rel_param = ext_csd[EXT_CSD_WR_REL_PARAM];
195 native_sector_size = ext_csd[EXT_CSD_NATIVE_SECTOR_SIZE];
196 data_sector_size = ext_csd[EXT_CSD_DATA_SECTOR_SIZE];
197
198 if (native_sector_size && !data_sector_size &&
199 (wr_rel_param & EN_REL_WR)) {
200 ret = write_extcsd_value(fd, EXT_CSD_USE_NATIVE_SECTOR, 1);
201
202 if (ret) {
203 fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n",
204 1, EXT_CSD_BOOT_WP, device);
205 exit(1);
206 }
207 printf("MMC disable 512B emulation successful. Now reset the device to switch to 4KB native sector mode.\n");
208 } else if (native_sector_size && data_sector_size) {
209 printf("MMC 512B emulation mode is already disabled; doing nothing.\n");
210 } else {
211 printf("MMC does not support disabling 512B emulation mode.\n");
212 }
213
214 return ret;
215}
216
Giuseppe CAVALLARO7bd13202012-04-19 10:58:37 +0200217int do_write_boot_en(int nargs, char **argv)
218{
219 __u8 ext_csd[512];
220 __u8 value = 0;
221 int fd, ret;
222 char *device;
223 int boot_area, send_ack;
224
225 CHECK(nargs != 4, "Usage: mmc bootpart enable <partition_number> "
226 "<send_ack> </path/to/mmcblkX>\n", exit(1));
227
228 /*
229 * If <send_ack> is 1, the device will send acknowledgment
230 * pattern "010" to the host when boot operation begins.
231 * If <send_ack> is 0, it won't.
232 */
233 boot_area = strtol(argv[1], NULL, 10);
234 send_ack = strtol(argv[2], NULL, 10);
235 device = argv[3];
236
237 fd = open(device, O_RDWR);
238 if (fd < 0) {
239 perror("open");
240 exit(1);
241 }
242
243 ret = read_extcsd(fd, ext_csd);
244 if (ret) {
245 fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
246 exit(1);
247 }
248
249 value = ext_csd[EXT_CSD_PART_CONFIG];
250
251 switch (boot_area) {
252 case EXT_CSD_PART_CONFIG_ACC_BOOT0:
253 value |= (1 << 3);
254 value &= ~(3 << 4);
255 break;
256 case EXT_CSD_PART_CONFIG_ACC_BOOT1:
257 value |= (1 << 4);
258 value &= ~(1 << 3);
259 value &= ~(1 << 5);
260 break;
261 case EXT_CSD_PART_CONFIG_ACC_USER_AREA:
262 value |= (boot_area << 3);
263 break;
264 default:
265 fprintf(stderr, "Cannot enable the boot area\n");
266 exit(1);
267 }
268 if (send_ack)
269 value |= EXT_CSD_PART_CONFIG_ACC_ACK;
270 else
271 value &= ~EXT_CSD_PART_CONFIG_ACC_ACK;
272
273 ret = write_extcsd_value(fd, EXT_CSD_PART_CONFIG, value);
274 if (ret) {
275 fprintf(stderr, "Could not write 0x%02x to "
276 "EXT_CSD[%d] in %s\n",
277 value, EXT_CSD_PART_CONFIG, device);
278 exit(1);
279 }
280 return ret;
281}
282
Chris Ballf74dfe22012-10-19 16:49:55 -0400283int do_hwreset(int value, int nargs, char **argv)
284{
285 __u8 ext_csd[512];
286 int fd, ret;
287 char *device;
288
289 CHECK(nargs != 2, "Usage: mmc hwreset enable </path/to/mmcblkX>\n",
290 exit(1));
291
292 device = argv[1];
293
294 fd = open(device, O_RDWR);
295 if (fd < 0) {
296 perror("open");
297 exit(1);
298 }
299
300 ret = read_extcsd(fd, ext_csd);
301 if (ret) {
302 fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
303 exit(1);
304 }
305
306 if ((ext_csd[EXT_CSD_RST_N_FUNCTION] & EXT_CSD_RST_N_EN_MASK) ==
307 EXT_CSD_HW_RESET_EN) {
308 fprintf(stderr,
309 "H/W Reset is already permanently enabled on %s\n",
310 device);
311 exit(1);
312 }
313 if ((ext_csd[EXT_CSD_RST_N_FUNCTION] & EXT_CSD_RST_N_EN_MASK) ==
314 EXT_CSD_HW_RESET_DIS) {
315 fprintf(stderr,
316 "H/W Reset is already permanently disabled on %s\n",
317 device);
318 exit(1);
319 }
320
321 ret = write_extcsd_value(fd, EXT_CSD_RST_N_FUNCTION, value);
322 if (ret) {
323 fprintf(stderr,
324 "Could not write 0x%02x to EXT_CSD[%d] in %s\n",
325 value, EXT_CSD_RST_N_FUNCTION, device);
326 exit(1);
327 }
328
329 return ret;
330}
331
332int do_hwreset_en(int nargs, char **argv)
333{
334 return do_hwreset(EXT_CSD_HW_RESET_EN, nargs, argv);
335}
336
337int do_hwreset_dis(int nargs, char **argv)
338{
339 return do_hwreset(EXT_CSD_HW_RESET_DIS, nargs, argv);
340}
341
Jaehoon Chung86496512012-09-21 10:08:05 +0000342int do_write_bkops_en(int nargs, char **argv)
343{
344 __u8 ext_csd[512], value = 0;
345 int fd, ret;
346 char *device;
347
348 CHECK(nargs != 2, "Usage: mmc bkops enable </path/to/mmcblkX>\n",
349 exit(1));
350
351 device = argv[1];
352
353 fd = open(device, O_RDWR);
354 if (fd < 0) {
355 perror("open");
356 exit(1);
357 }
358
359 ret = read_extcsd(fd, ext_csd);
360 if (ret) {
361 fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
362 exit(1);
363 }
364
365 if (!(ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1)) {
366 fprintf(stderr, "%s doesn't support BKOPS\n", device);
367 exit(1);
368 }
369
370 ret = write_extcsd_value(fd, EXT_CSD_BKOPS_EN, BKOPS_ENABLE);
371 if (ret) {
372 fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n",
373 value, EXT_CSD_BKOPS_EN, device);
374 exit(1);
375 }
376
377 return ret;
378}
379
Johan RUDHOLMa8bfde72012-02-12 11:46:44 -0500380int do_read_extcsd(int nargs, char **argv)
381{
Giuseppe CAVALLAROa5bf4a22012-02-20 09:45:29 +0100382 __u8 ext_csd[512], ext_csd_rev, reg;
Johan RUDHOLMa8bfde72012-02-12 11:46:44 -0500383 int fd, ret;
384 char *device;
Giuseppe CAVALLAROa5bf4a22012-02-20 09:45:29 +0100385 const char *str;
Johan RUDHOLMa8bfde72012-02-12 11:46:44 -0500386
Chris Ball8ba44662012-04-19 13:22:54 -0400387 CHECK(nargs != 2, "Usage: mmc extcsd read </path/to/mmcblkX>\n",
388 exit(1));
Johan RUDHOLMa8bfde72012-02-12 11:46:44 -0500389
390 device = argv[1];
391
392 fd = open(device, O_RDWR);
393 if (fd < 0) {
394 perror("open");
395 exit(1);
396 }
397
398 ret = read_extcsd(fd, ext_csd);
399 if (ret) {
400 fprintf(stderr, "Could not read EXT_CSD from %s\n", device);
401 exit(1);
402 }
403
Giuseppe CAVALLAROa5bf4a22012-02-20 09:45:29 +0100404 ext_csd_rev = ext_csd[192];
405
406 switch (ext_csd_rev) {
407 case 6:
408 str = "4.5";
409 break;
410 case 5:
411 str = "4.41";
412 break;
413 case 3:
414 str = "4.3";
415 break;
416 case 2:
417 str = "4.2";
418 break;
419 case 1:
420 str = "4.1";
421 break;
422 case 0:
423 str = "4.0";
424 break;
425 default:
426 goto out_free;
427 }
428 printf("=============================================\n");
429 printf(" Extended CSD rev 1.%d (MMC %s)\n", ext_csd_rev, str);
430 printf("=============================================\n\n");
431
432 if (ext_csd_rev < 3)
433 goto out_free; /* No ext_csd */
434
435 /* Parse the Extended CSD registers.
436 * Reserved bit should be read as "0" in case of spec older
437 * than A441.
438 */
439 reg = ext_csd[EXT_CSD_S_CMD_SET];
440 printf("Card Supported Command sets [S_CMD_SET: 0x%02x]\n", reg);
441 if (!reg)
Chris Ballb9c7a172012-02-20 12:34:25 -0500442 printf(" - Standard MMC command sets\n");
Giuseppe CAVALLAROa5bf4a22012-02-20 09:45:29 +0100443
444 reg = ext_csd[EXT_CSD_HPI_FEATURE];
445 printf("HPI Features [HPI_FEATURE: 0x%02x]: ", reg);
446 if (reg & EXT_CSD_HPI_SUPP) {
447 if (reg & EXT_CSD_HPI_IMPL)
Chris Ballb9c7a172012-02-20 12:34:25 -0500448 printf("implementation based on CMD12\n");
Giuseppe CAVALLAROa5bf4a22012-02-20 09:45:29 +0100449 else
450 printf("implementation based on CMD13\n");
451 }
452
453 printf("Background operations support [BKOPS_SUPPORT: 0x%02x]\n",
454 ext_csd[502]);
455
456 if (ext_csd_rev >= 6) {
457 printf("Max Packet Read Cmd [MAX_PACKED_READS: 0x%02x]\n",
458 ext_csd[501]);
459 printf("Max Packet Write Cmd [MAX_PACKED_WRITES: 0x%02x]\n",
460 ext_csd[500]);
461 printf("Data TAG support [DATA_TAG_SUPPORT: 0x%02x]\n",
462 ext_csd[499]);
463
464 printf("Data TAG Unit Size [TAG_UNIT_SIZE: 0x%02x]\n",
465 ext_csd[498]);
466 printf("Tag Resources Size [TAG_RES_SIZE: 0x%02x]\n",
467 ext_csd[497]);
468 printf("Context Management Capabilities"
469 " [CONTEXT_CAPABILITIES: 0x%02x]\n", ext_csd[496]);
470 printf("Large Unit Size [LARGE_UNIT_SIZE_M1: 0x%02x]\n",
471 ext_csd[495]);
472 printf("Extended partition attribute support"
473 " [EXT_SUPPORT: 0x%02x]\n", ext_csd[494]);
474 printf("Generic CMD6 Timer [GENERIC_CMD6_TIME: 0x%02x]\n",
475 ext_csd[248]);
476 printf("Power off notification [POWER_OFF_LONG_TIME: 0x%02x]\n",
477 ext_csd[247]);
478 printf("Cache Size [CACHE_SIZE] is %d KiB\n",
479 ext_csd[249] << 0 | (ext_csd[250] << 8) |
480 (ext_csd[251] << 16) | (ext_csd[252] << 24));
481 }
482
483 /* A441: Reserved [501:247]
484 A43: reserved [246:229] */
485 if (ext_csd_rev >= 5) {
Giuseppe CAVALLAROa5bf4a22012-02-20 09:45:29 +0100486 printf("Background operations status"
Chris Ballb9c7a172012-02-20 12:34:25 -0500487 " [BKOPS_STATUS: 0x%02x]\n", ext_csd[246]);
Giuseppe CAVALLAROa5bf4a22012-02-20 09:45:29 +0100488
489 /* CORRECTLY_PRG_SECTORS_NUM [245:242] TODO */
490
491 printf("1st Initialisation Time after programmed sector"
492 " [INI_TIMEOUT_AP: 0x%02x]\n", ext_csd[241]);
493
494 /* A441: reserved [240] */
Giuseppe CAVALLAROa5bf4a22012-02-20 09:45:29 +0100495 printf("Power class for 52MHz, DDR at 3.6V"
496 " [PWR_CL_DDR_52_360: 0x%02x]\n", ext_csd[239]);
497 printf("Power class for 52MHz, DDR at 1.95V"
498 " [PWR_CL_DDR_52_195: 0x%02x]\n", ext_csd[238]);
499
500 /* A441: reserved [237-236] */
501
502 if (ext_csd_rev >= 6) {
503 printf("Power class for 200MHz at 3.6V"
504 " [PWR_CL_200_360: 0x%02x]\n", ext_csd[237]);
505 printf("Power class for 200MHz, at 1.95V"
506 " [PWR_CL_200_195: 0x%02x]\n", ext_csd[236]);
507 }
Chris Ballb9c7a172012-02-20 12:34:25 -0500508 printf("Minimum Performance for 8bit at 52MHz in DDR mode:\n");
Giuseppe CAVALLAROa5bf4a22012-02-20 09:45:29 +0100509 printf(" [MIN_PERF_DDR_W_8_52: 0x%02x]\n", ext_csd[235]);
510 printf(" [MIN_PERF_DDR_R_8_52: 0x%02x]\n", ext_csd[234]);
511 /* A441: reserved [233] */
512 printf("TRIM Multiplier [TRIM_MULT: 0x%02x]\n", ext_csd[232]);
513 printf("Secure Feature support [SEC_FEATURE_SUPPORT: 0x%02x]\n",
514 ext_csd[231]);
515 }
516 if (ext_csd_rev == 5) { /* Obsolete in 4.5 */
517 printf("Secure Erase Multiplier [SEC_ERASE_MULT: 0x%02x]\n",
518 ext_csd[230]);
519 printf("Secure TRIM Multiplier [SEC_TRIM_MULT: 0x%02x]\n",
520 ext_csd[229]);
521 }
522 reg = ext_csd[EXT_CSD_BOOT_INFO];
523 printf("Boot Information [BOOT_INFO: 0x%02x]\n", reg);
524 if (reg & EXT_CSD_BOOT_INFO_ALT)
525 printf(" Device supports alternative boot method\n");
526 if (reg & EXT_CSD_BOOT_INFO_DDR_DDR)
527 printf(" Device supports dual data rate during boot\n");
528 if (reg & EXT_CSD_BOOT_INFO_HS_MODE)
529 printf(" Device supports high speed timing during boot\n");
530
531 /* A441/A43: reserved [227] */
532 printf("Boot partition size [BOOT_SIZE_MULTI: 0x%02x]\n", ext_csd[226]);
533 printf("Access size [ACC_SIZE: 0x%02x]\n", ext_csd[225]);
534 printf("High-capacity erase unit size [HC_ERASE_GRP_SIZE: 0x%02x]\n",
535 ext_csd[224]);
536 printf("High-capacity erase timeout [ERASE_TIMEOUT_MULT: 0x%02x]\n",
537 ext_csd[223]);
538 printf("Reliable write sector count [REL_WR_SEC_C: 0x%02x]\n",
539 ext_csd[222]);
540 printf("High-capacity W protect group size [HC_WP_GRP_SIZE: 0x%02x]\n",
541 ext_csd[221]);
542 printf("Sleep current (VCC) [S_C_VCC: 0x%02x]\n", ext_csd[220]);
543 printf("Sleep current (VCCQ) [S_C_VCCQ: 0x%02x]\n", ext_csd[219]);
544 /* A441/A43: reserved [218] */
545 printf("Sleep/awake timeout [S_A_TIMEOUT: 0x%02x]\n", ext_csd[217]);
546 /* A441/A43: reserved [216] */
547 printf("Sector Count [SEC_COUNT: 0x%08x]\n", (ext_csd[215] << 24) |
548 (ext_csd[214] << 16) | (ext_csd[213] << 8) |
549 ext_csd[212]);
550 /* A441/A43: reserved [211] */
551 printf("Minimum Write Performance for 8bit:\n");
552 printf(" [MIN_PERF_W_8_52: 0x%02x]\n", ext_csd[210]);
553 printf(" [MIN_PERF_R_8_52: 0x%02x]\n", ext_csd[209]);
554 printf(" [MIN_PERF_W_8_26_4_52: 0x%02x]\n", ext_csd[208]);
555 printf(" [MIN_PERF_R_8_26_4_52: 0x%02x]\n", ext_csd[207]);
556 printf("Minimum Write Performance for 4bit:\n");
557 printf(" [MIN_PERF_W_4_26: 0x%02x]\n", ext_csd[206]);
558 printf(" [MIN_PERF_R_4_26: 0x%02x]\n", ext_csd[205]);
559 /* A441/A43: reserved [204] */
560 printf("Power classes registers:\n");
561 printf(" [PWR_CL_26_360: 0x%02x]\n", ext_csd[203]);
562 printf(" [PWR_CL_52_360: 0x%02x]\n", ext_csd[202]);
563 printf(" [PWR_CL_26_195: 0x%02x]\n", ext_csd[201]);
564 printf(" [PWR_CL_52_195: 0x%02x]\n", ext_csd[200]);
565
566 /* A43: reserved [199:198] */
567 if (ext_csd_rev >= 5) {
568 printf("Partition switching timing "
569 "[PARTITION_SWITCH_TIME: 0x%02x]\n", ext_csd[199]);
570 printf("Out-of-interrupt busy timing"
571 " [OUT_OF_INTERRUPT_TIME: 0x%02x]\n", ext_csd[198]);
572 }
573
574 /* A441/A43: reserved [197] [195] [193] [190] [188]
575 * [186] [184] [182] [180] [176] */
576
577 if (ext_csd_rev >= 6)
578 printf("I/O Driver Strength [DRIVER_STRENGTH: 0x%02x]\n",
579 ext_csd[197]);
580
Oleg Matcovschi64f63a32013-05-23 17:11:07 -0700581 /* DEVICE_TYPE in A45, CARD_TYPE in A441 */
582 reg = ext_csd[196];
583 printf("Card Type [CARD_TYPE: 0x%02x]\n", reg);
584 if (reg & 0x20) printf(" HS200 Single Data Rate eMMC @200MHz 1.2VI/O\n");
585 if (reg & 0x10) printf(" HS200 Single Data Rate eMMC @200MHz 1.8VI/O\n");
586 if (reg & 0x08) printf(" HS Dual Data Rate eMMC @52MHz 1.2VI/O\n");
587 if (reg & 0x04) printf(" HS Dual Data Rate eMMC @52MHz 1.8V or 3VI/O\n");
588 if (reg & 0x02) printf(" HS eMMC @52MHz - at rated device voltage(s)\n");
589 if (reg & 0x01) printf(" HS eMMC @26MHz - at rated device voltage(s)\n");
Giuseppe CAVALLAROa5bf4a22012-02-20 09:45:29 +0100590
Giuseppe CAVALLAROa5bf4a22012-02-20 09:45:29 +0100591 printf("CSD structure version [CSD_STRUCTURE: 0x%02x]\n", ext_csd[194]);
592 /* ext_csd_rev = ext_csd[192] (already done!!!) */
593 printf("Command set [CMD_SET: 0x%02x]\n", ext_csd[191]);
594 printf("Command set revision [CMD_SET_REV: 0x%02x]\n", ext_csd[189]);
595 printf("Power class [POWER_CLASS: 0x%02x]\n", ext_csd[187]);
596 printf("High-speed interface timing [HS_TIMING: 0x%02x]\n",
597 ext_csd[185]);
598 /* bus_width: ext_csd[183] not readable */
599 printf("Erased memory content [ERASED_MEM_CONT: 0x%02x]\n",
600 ext_csd[181]);
601 reg = ext_csd[EXT_CSD_BOOT_CFG];
602 printf("Boot configuration bytes [PARTITION_CONFIG: 0x%02x]\n", reg);
Mario Schuknecht8c0c40d2013-05-15 08:28:04 +0200603 switch ((reg & EXT_CSD_BOOT_CFG_EN)>>3) {
Giuseppe CAVALLAROa5bf4a22012-02-20 09:45:29 +0100604 case 0x0:
605 printf(" Not boot enable\n");
606 break;
607 case 0x1:
608 printf(" Boot Partition 1 enabled\n");
609 break;
610 case 0x2:
611 printf(" Boot Partition 2 enabled\n");
612 break;
613 case 0x7:
614 printf(" User Area Enabled for boot\n");
615 break;
616 }
617 switch (reg & EXT_CSD_BOOT_CFG_ACC) {
618 case 0x0:
619 printf(" No access to boot partition\n");
620 break;
621 case 0x1:
622 printf(" R/W Boot Partition 1\n");
623 break;
624 case 0x2:
625 printf(" R/W Boot Partition 2\n");
626 break;
Mario Schuknecht8c0c40d2013-05-15 08:28:04 +0200627 case 0x3:
628 printf(" R/W Replay Protected Memory Block (RPMB)\n");
629 break;
Giuseppe CAVALLAROa5bf4a22012-02-20 09:45:29 +0100630 default:
Mario Schuknecht8c0c40d2013-05-15 08:28:04 +0200631 printf(" Access to General Purpose partition %d\n",
Giuseppe CAVALLAROa5bf4a22012-02-20 09:45:29 +0100632 (reg & EXT_CSD_BOOT_CFG_ACC) - 3);
633 break;
634 }
635
636 printf("Boot config protection [BOOT_CONFIG_PROT: 0x%02x]\n",
637 ext_csd[178]);
638 printf("Boot bus Conditions [BOOT_BUS_CONDITIONS: 0x%02x]\n",
639 ext_csd[177]);
640 printf("High-density erase group definition"
641 " [ERASE_GROUP_DEF: 0x%02x]\n", ext_csd[175]);
642
Chris Ballb9c7a172012-02-20 12:34:25 -0500643 print_writeprotect_status(ext_csd);
644
Giuseppe CAVALLAROa5bf4a22012-02-20 09:45:29 +0100645 if (ext_csd_rev >= 5) {
Giuseppe CAVALLAROa5bf4a22012-02-20 09:45:29 +0100646 /* A441]: reserved [172] */
647 printf("User area write protection register"
648 " [USER_WP]: 0x%02x\n", ext_csd[171]);
649 /* A441]: reserved [170] */
650 printf("FW configuration [FW_CONFIG]: 0x%02x\n", ext_csd[169]);
651 printf("RPMB Size [RPMB_SIZE_MULT]: 0x%02x\n", ext_csd[168]);
652 printf("Write reliability setting register"
653 " [WR_REL_SET]: 0x%02x\n", ext_csd[167]);
654 printf("Write reliability parameter register"
655 " [WR_REL_PARAM]: 0x%02x\n", ext_csd[166]);
656 /* sanitize_start ext_csd[165]]: not readable
657 * bkops_start ext_csd[164]]: only writable */
658 printf("Enable background operations handshake"
659 " [BKOPS_EN]: 0x%02x\n", ext_csd[163]);
660 printf("H/W reset function"
661 " [RST_N_FUNCTION]: 0x%02x\n", ext_csd[162]);
662 printf("HPI management [HPI_MGMT]: 0x%02x\n", ext_csd[161]);
663 reg = ext_csd[160];
664 printf("Partitioning Support [PARTITIONING_SUPPORT]: 0x%02x\n",
665 reg);
666 if (reg & 0x1)
667 printf(" Device support partitioning feature\n");
668 else
669 printf(" Device NOT support partitioning feature\n");
670 if (reg & 0x2)
671 printf(" Device can have enhanced tech.\n");
672 else
673 printf(" Device cannot have enhanced tech.\n");
674
675 printf("Max Enhanced Area Size [MAX_ENH_SIZE_MULT]: 0x%06x\n",
676 (ext_csd[159] << 16) | (ext_csd[158] << 8) |
677 ext_csd[157]);
678 printf("Partitions attribute [PARTITIONS_ATTRIBUTE]: 0x%02x\n",
679 ext_csd[156]);
680 printf("Partitioning Setting"
681 " [PARTITION_SETTING_COMPLETED]: 0x%02x\n",
682 ext_csd[155]);
683 printf("General Purpose Partition Size\n"
684 " [GP_SIZE_MULT_4]: 0x%06x\n", (ext_csd[154] << 16) |
685 (ext_csd[153] << 8) | ext_csd[152]);
686 printf(" [GP_SIZE_MULT_3]: 0x%06x\n", (ext_csd[151] << 16) |
687 (ext_csd[150] << 8) | ext_csd[149]);
688 printf(" [GP_SIZE_MULT_2]: 0x%06x\n", (ext_csd[148] << 16) |
689 (ext_csd[147] << 8) | ext_csd[146]);
690 printf(" [GP_SIZE_MULT_1]: 0x%06x\n", (ext_csd[145] << 16) |
691 (ext_csd[144] << 8) | ext_csd[143]);
692
693 printf("Enhanced User Data Area Size"
694 " [ENH_SIZE_MULT]: 0x%06x\n", (ext_csd[142] << 16) |
695 (ext_csd[141] << 8) | ext_csd[140]);
696 printf("Enhanced User Data Start Address"
697 " [ENH_START_ADDR]: 0x%06x\n", (ext_csd[139] << 16) |
698 (ext_csd[138] << 8) | ext_csd[137]);
699
700 /* A441]: reserved [135] */
701 printf("Bad Block Management mode"
702 " [SEC_BAD_BLK_MGMNT]: 0x%02x\n", ext_csd[134]);
703 /* A441: reserved [133:0] */
704 }
705 /* B45 */
706 if (ext_csd_rev >= 6) {
707 int j;
708 /* tcase_support ext_csd[132] not readable */
709 printf("Periodic Wake-up [PERIODIC_WAKEUP]: 0x%02x\n",
710 ext_csd[131]);
711 printf("Program CID/CSD in DDR mode support"
712 " [PROGRAM_CID_CSD_DDR_SUPPORT]: 0x%02x\n",
713 ext_csd[130]);
714
715 for (j = 127; j >= 64; j--)
716 printf("Vendor Specific Fields"
717 " [VENDOR_SPECIFIC_FIELD[%d]]: 0x%02x\n",
718 j, ext_csd[j]);
719
720 printf("Native sector size [NATIVE_SECTOR_SIZE]: 0x%02x\n",
721 ext_csd[63]);
722 printf("Sector size emulation [USE_NATIVE_SECTOR]: 0x%02x\n",
723 ext_csd[62]);
724 printf("Sector size [DATA_SECTOR_SIZE]: 0x%02x\n", ext_csd[61]);
725 printf("1st initialization after disabling sector"
726 " size emulation [INI_TIMEOUT_EMU]: 0x%02x\n",
727 ext_csd[60]);
728 printf("Class 6 commands control [CLASS_6_CTRL]: 0x%02x\n",
729 ext_csd[59]);
730 printf("Number of addressed group to be Released"
731 "[DYNCAP_NEEDED]: 0x%02x\n", ext_csd[58]);
732 printf("Exception events control"
733 " [EXCEPTION_EVENTS_CTRL]: 0x%04x\n",
734 (ext_csd[57] << 8) | ext_csd[56]);
735 printf("Exception events status"
736 "[EXCEPTION_EVENTS_STATUS]: 0x%04x\n",
737 (ext_csd[55] << 8) | ext_csd[54]);
738 printf("Extended Partitions Attribute"
739 " [EXT_PARTITIONS_ATTRIBUTE]: 0x%04x\n",
740 (ext_csd[53] << 8) | ext_csd[52]);
741
742 for (j = 51; j >= 37; j--)
743 printf("Context configuration"
744 " [CONTEXT_CONF[%d]]: 0x%02x\n", j, ext_csd[j]);
745
746 printf("Packed command status"
747 " [PACKED_COMMAND_STATUS]: 0x%02x\n", ext_csd[36]);
748 printf("Packed command failure index"
749 " [PACKED_FAILURE_INDEX]: 0x%02x\n", ext_csd[35]);
750 printf("Power Off Notification"
751 " [POWER_OFF_NOTIFICATION]: 0x%02x\n", ext_csd[34]);
Oleg Matcovschi64f63a32013-05-23 17:11:07 -0700752 printf("Control to turn the Cache ON/OFF"
753 " [CACHE_CTRL]: 0x%02x\n", ext_csd[33]);
Giuseppe CAVALLAROa5bf4a22012-02-20 09:45:29 +0100754 /* flush_cache ext_csd[32] not readable */
755 /*Reserved [31:0] */
756 }
757
758out_free:
Johan RUDHOLMa8bfde72012-02-12 11:46:44 -0500759 return ret;
760}
Yaniv Gardi21bb4732013-05-26 13:25:33 -0400761
762int do_sanitize(int nargs, char **argv)
763{
764 int fd, ret;
765 char *device;
766
767 CHECK(nargs != 2, "Usage: mmc sanitize </path/to/mmcblkX>\n",
768 exit(1));
769
770 device = argv[1];
771
772 fd = open(device, O_RDWR);
773 if (fd < 0) {
774 perror("open");
775 exit(1);
776 }
777
778 ret = write_extcsd_value(fd, EXT_CSD_SANITIZE_START, 1);
779 if (ret) {
780 fprintf(stderr, "Could not write 0x%02x to EXT_CSD[%d] in %s\n",
781 1, EXT_CSD_SANITIZE_START, device);
782 exit(1);
783 }
784
785 return ret;
786
787}
788