]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/arm926ejs/mx28/mmcops.c
applied patches from Freescale and Ka-Ro
[karo-tx-uboot.git] / cpu / arm926ejs / mx28 / mmcops.c
1 /*
2  * Copyright (C) 2010 Freescale Semiconductor, Inc.
3  *
4  * See file CREDITS for list of people who contributed to this
5  * project.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307 USA
21  */
22 #include <common.h>
23 #include <command.h>
24 #include <exports.h>
25 #include <mmc.h>
26
27 #ifdef CONFIG_GENERIC_MMC
28 #define MMCOPS_DEBUG
29
30 #define MBR_SIGNATURE           0xaa55
31 #define MBR_SECTOR_COUNT        (CONFIG_ENV_OFFSET >> 9)
32 /* 1. RSV partition (env and uImage) */
33 #define RSVPART_SECTOR_OFFSET   (MBR_SECTOR_COUNT)
34 #define RSVPART_SECTOR_COUNT    0x3ffe  /* 8 MB */
35 /* 2. FAT partition */
36 #define FATPART_FILESYS         0xb
37 #define FATPART_SECTOR_OFFSET   (RSVPART_SECTOR_OFFSET + RSVPART_SECTOR_COUNT)
38 #define FATPART_SECTOR_COUNT    0x10000 /* 32 MB (minimal) */
39 /* 3. EXT partition */
40 #define EXTPART_FILESYS         0x83
41 #define EXTPART_SECTOR_COUNT    0xc0000 /* 384 MB */
42 /* 4. SB partition (uboot.sb or linux.sb) */
43 #define SBPART_FILESYS          'S'
44 #define SBPART_SECTOR_COUNT     0x4000  /* 8 MB */
45 #define CB_SIGNATURE            0x00112233
46 #define CB_SECTOR_COUNT         2
47
48 #define MAX_CYLINDERS           1024
49 #define MAX_HEADS               256
50 #define MAX_SECTORS             63
51
52 struct partition {
53         u8 boot_flag;
54         u8 start_head;
55         u8 start_sector;
56         u8 start_cylinder;
57         u8 file_system;
58         u8 end_head;
59         u8 end_sector;
60         u8 end_cylinder;
61         u32 sector_offset;
62         u32 sector_count;
63 } __attribute__ ((__packed__));
64
65 struct partition_table {
66         u8 reserved[446];
67         struct partition partitions[4];
68         u16 signature;
69 };
70
71 struct drive_info {
72         u32 chip_num;
73         u32 drive_type;
74         u32 drive_tag;
75         u32 sector_offset;
76         u32 sector_count;
77 };
78
79 struct config_block {
80         u32 signature;
81         u32 primary_tag;
82         u32 secondary_tag;
83         u32 num_copies;
84         struct drive_info drive_info[2];
85 };
86
87 static int mmc_format(int dev)
88 {
89         int rc = 0;
90         u8 *buf = 0;
91         u32 i, cnt, total_sectors;
92         u32 offset[4];
93         struct config_block *cb;
94         struct partition_table *mbr;
95         struct mmc *mmc = find_mmc_device(dev);
96
97         /* Warning */
98         printf("WARN: Data on card will get lost with format.\n"
99                 "Continue? (y/n)");
100         char ch = getc();
101         printf("\n");
102         if (ch != 'y') {
103                 rc = -1;
104                 goto out;
105         }
106
107         /* Allocate sector buffer */
108         buf = malloc(mmc->read_bl_len);
109         if (!buf) {
110                 printf("%s[%d]: malloc error\n", __func__, __LINE__);
111                 rc = -1;
112                 goto out;
113         }
114         memset(buf, 0, mmc->read_bl_len);
115
116         /* Erase the first sector of each partition */
117         cnt = mmc->block_dev.block_read(dev, 0, 1, buf);
118         if (cnt != 1) {
119                 printf("%s[%d]: read mmc error\n", __func__, __LINE__);
120                 rc = -1;
121                 goto out;
122         }
123         mbr = (struct partition_table *)buf;
124         if (mbr->signature == MBR_SIGNATURE) {
125                 /* Get sector offset of each partition */
126                 for (i = 0; i < 4; i++)
127                         offset[i] = mbr->partitions[i].sector_offset;
128                 /* Erase */
129                 memset(buf, 0, mmc->read_bl_len);
130                 for (i = 0; i < 4; i++) {
131                         if (offset[i] > 0) {
132                                 cnt = mmc->block_dev.block_write(dev,
133                                         offset[i], 1, buf);
134                                 if (cnt != 1) {
135                                         printf("%s[%d]: write mmc error\n",
136                                                 __func__, __LINE__);
137                                         rc = -1;
138                                         goto out;
139                                 }
140                         }
141                 }
142         }
143
144         /* Get total sectors */
145         total_sectors = mmc->capacity >> 9;
146         if (RSVPART_SECTOR_COUNT + SBPART_SECTOR_COUNT > total_sectors) {
147                 printf("Card capacity is too low to format\n");
148                 rc = -1;
149                 goto out;
150         }
151
152         /* Write config block */
153         cb = (struct config_block *)buf;
154         cb->signature = CB_SIGNATURE;
155         cb->num_copies = 2;
156         cb->primary_tag = 0x1;
157         cb->secondary_tag = 0x2;
158         cb->drive_info[0].chip_num = 0;
159         cb->drive_info[0].drive_type = 0;
160         cb->drive_info[0].drive_tag = 0x1;
161         cb->drive_info[0].sector_count = SBPART_SECTOR_COUNT - CB_SECTOR_COUNT;
162         cb->drive_info[0].sector_offset =
163                 total_sectors - cb->drive_info[0].sector_count;
164         cb->drive_info[1].chip_num = 0;
165         cb->drive_info[1].drive_type = 0;
166         cb->drive_info[1].drive_tag = 0x2;
167         cb->drive_info[1].sector_count = SBPART_SECTOR_COUNT - CB_SECTOR_COUNT;
168         cb->drive_info[1].sector_offset =
169                 total_sectors - cb->drive_info[1].sector_count;
170
171         cnt = mmc->block_dev.block_write(dev,
172                 total_sectors - SBPART_SECTOR_COUNT, 1, (void *)cb);
173         if (cnt != 1) {
174                 printf("%s[%d]: write mmc error\n", __func__, __LINE__);
175                 rc = -1;
176                 goto out;
177         }
178
179         /* Prepare for MBR */
180         memset(buf, 0, mmc->read_bl_len);
181         mbr = (struct partition_table *)buf;
182
183         /* RSV partition */
184         mbr->partitions[0].sector_offset = RSVPART_SECTOR_OFFSET;
185         mbr->partitions[0].sector_count = RSVPART_SECTOR_COUNT;
186
187         /* SB partition */
188         mbr->partitions[3].file_system = SBPART_FILESYS;
189         mbr->partitions[3].sector_offset = total_sectors - SBPART_SECTOR_COUNT;
190         mbr->partitions[3].sector_count = SBPART_SECTOR_COUNT;
191
192         /* EXT partition */
193         if (EXTPART_SECTOR_COUNT + SBPART_SECTOR_COUNT +
194                 RSVPART_SECTOR_COUNT > total_sectors) {
195 #ifdef MMCOPS_DEBUG
196                 printf("No room for EXT partition\n");
197 #endif
198         } else {
199                 mbr->partitions[2].file_system = EXTPART_FILESYS;
200                 mbr->partitions[2].sector_offset = total_sectors -
201                         SBPART_SECTOR_COUNT - EXTPART_SECTOR_COUNT;
202                 mbr->partitions[2].sector_count = EXTPART_SECTOR_COUNT;
203         }
204
205         /* FAT partition */
206         if (FATPART_SECTOR_COUNT + MBR_SECTOR_COUNT +
207                 mbr->partitions[0].sector_count +
208                 mbr->partitions[2].sector_count +
209                 mbr->partitions[3].sector_count > total_sectors) {
210 #ifdef MMCOPS_DEBUG
211                 printf("No room for FAT partition\n");
212 #endif
213                 goto out;
214         }
215         mbr->partitions[1].file_system = FATPART_FILESYS;
216         mbr->partitions[1].sector_offset = FATPART_SECTOR_OFFSET;
217         mbr->partitions[1].sector_count = total_sectors - MBR_SECTOR_COUNT -
218                 mbr->partitions[0].sector_count -
219                 mbr->partitions[2].sector_count -
220                 mbr->partitions[3].sector_count;
221
222 out:
223         if (rc == 0) {
224                 /* Write MBR */
225                 mbr->signature = MBR_SIGNATURE;
226                 cnt = mmc->block_dev.block_write(dev, 0, 1, (void *)mbr);
227                 if (cnt != 1) {
228                         printf("%s[%d]: write mmc error\n", __func__, __LINE__);
229                         rc = -1;
230                 } else
231                         printf("Done.\n");
232         }
233
234         if (!buf)
235                 free(buf);
236         return rc;
237 }
238
239 static int install_sbimage(int dev, void *addr, u32 size)
240 {
241         int rc = 0;
242         u8 *buf = 0;
243         u32 cnt, offset, cb_offset, sectors, not_format = 0;
244         struct config_block *cb;
245         struct partition_table *mbr;
246         struct mmc *mmc = find_mmc_device(dev);
247
248         /* Allocate sector buffer */
249         buf = malloc(mmc->read_bl_len);
250         if (!buf) {
251                 printf("%s[%d]: malloc error\n", __func__, __LINE__);
252                 rc = -1;
253                 goto out;
254         }
255
256         /* Check partition */
257         offset = 0;
258         cnt = mmc->block_dev.block_read(dev, offset, 1, buf);
259         if (cnt != 1) {
260                 printf("%s[%d]: read mmc error\n", __func__, __LINE__);
261                 rc = -1;
262                 goto out;
263         }
264         mbr = (struct partition_table *)buf;
265         if ((mbr->signature != MBR_SIGNATURE) ||
266                 (mbr->partitions[3].file_system != SBPART_FILESYS))
267                 not_format = 1;
268
269         /* Check config block */
270         offset = mbr->partitions[3].sector_offset;
271         cb_offset = offset; /* Save for later use */
272         cnt = mmc->block_dev.block_read(dev, offset, 1, buf);
273         if (cnt != 1) {
274                 printf("%s[%d]: read mmc error\n", __func__, __LINE__);
275                 rc = -1;
276                 goto out;
277         }
278         cb = (struct config_block *)buf;
279         if (cb->signature != CB_SIGNATURE)
280                 not_format = 1;
281
282         /* Not formatted */
283         if (not_format) {
284                 printf("Card is not formatted yet\n");
285                 rc = -1;
286                 goto out;
287         }
288
289         /* Calculate sectors of image */
290         sectors = size / mmc->read_bl_len;
291         if (size % mmc->read_bl_len)
292                 sectors++;
293
294         /* Write image */
295         offset = cb->drive_info[0].sector_offset;
296         cnt = mmc->block_dev.block_write(dev, offset, sectors, addr);
297         if (cnt != sectors) {
298                 printf("%s[%d]: write mmc error\n", __func__, __LINE__);
299                 rc = -1;
300                 goto out;
301         }
302         /* Verify */
303         cnt = mmc->block_dev.block_read(dev, offset, sectors,
304                 addr + sectors * mmc->read_bl_len);
305         if (cnt != sectors) {
306                 printf("%s[%d]: read mmc error\n", __func__, __LINE__);
307                 rc = -1;
308                 goto out;
309         }
310         if (memcmp(addr, addr + sectors * mmc->read_bl_len,
311                 sectors * mmc->read_bl_len)) {
312                 printf("Verifying sbImage write fails\n");
313                 rc = -1;
314                 goto out;
315         }
316
317         /* Redundant one */
318         offset += sectors;
319         cnt = mmc->block_dev.block_write(dev, offset, sectors, addr);
320         if (cnt != sectors) {
321                 printf("%s[%d]: write mmc error\n", __func__, __LINE__);
322                 rc = -1;
323                 goto out;
324         }
325         /* Verify */
326         cnt = mmc->block_dev.block_read(dev, offset, sectors,
327                 addr + sectors * mmc->read_bl_len);
328         if (cnt != sectors) {
329                 printf("%s[%d]: read mmc error\n", __func__, __LINE__);
330                 rc = -1;
331                 goto out;
332         }
333         if (memcmp(addr, addr + sectors * mmc->read_bl_len,
334                 sectors * mmc->read_bl_len)) {
335                 printf("Verifying redundant sbImage write fails");
336                 rc = -1;
337                 goto out;
338         }
339
340         /* Update config block */
341         cb->drive_info[0].sector_count = sectors;
342         cb->drive_info[1].sector_count = sectors;
343         cb->drive_info[1].sector_offset = offset;
344         cnt = mmc->block_dev.block_write(dev, cb_offset, 1, (void *)cb);
345         if (cnt != 1) {
346                 printf("%s[%d]: write mmc error\n", __func__, __LINE__);
347                 rc = -1;
348                 goto out;
349         }
350
351         /* Done */
352         printf("Done: %d (%x hex) sectors written at %d (%x hex)\n",
353                 sectors, sectors, offset - sectors, offset - sectors);
354
355 out:
356         if (!buf)
357                 free(buf);
358         return rc;
359 }
360
361 static int install_uimage(int dev, void *addr, u32 size)
362 {
363         int rc = 0;
364         u8 *buf = 0;
365         u32 cnt, offset, sectors;
366         struct partition_table *mbr;
367         struct mmc *mmc = find_mmc_device(dev);
368
369         /* Calculate sectors of uImage */
370         sectors = size / mmc->read_bl_len;
371         if (size % mmc->read_bl_len)
372                 sectors++;
373
374         /* Allocate sector buffer */
375         buf = malloc(mmc->read_bl_len);
376         if (!buf) {
377                 printf("%s[%d]: malloc error\n", __func__, __LINE__);
378                 rc = -1;
379                 goto out;
380         }
381
382         /* Check partition */
383         offset = 0;
384         cnt = mmc->block_dev.block_read(dev, offset, 1, buf);
385         if (cnt != 1) {
386                 printf("%s[%d]: read mmc error\n", __func__, __LINE__);
387                 rc = -1;
388                 goto out;
389         }
390         mbr = (struct partition_table *)buf;
391         if (mbr->signature != MBR_SIGNATURE) {
392                 printf("No valid partition table\n");
393                 rc = -1;
394                 goto out;
395         }
396         if (mbr->partitions[0].sector_count < sectors) {
397                 printf("No enough uImage partition room\n");
398                 rc = -1;
399                 goto out;
400         }
401
402         /* Write uImage */
403         offset = mbr->partitions[0].sector_offset + (CONFIG_ENV_SIZE >> 9);
404         cnt = mmc->block_dev.block_write(dev, offset, sectors, addr);
405         if (cnt != sectors) {
406                 printf("%s[%d]: write mmc error\n", __func__, __LINE__);
407                 rc = -1;
408                 goto out;
409         }
410         /* Verify */
411         cnt = mmc->block_dev.block_read(dev, offset, sectors,
412                 addr + sectors * mmc->read_bl_len);
413         if (cnt != sectors) {
414                 printf("%s[%d]: read mmc error\n", __func__, __LINE__);
415                 rc = -1;
416                 goto out;
417         }
418         if (memcmp(addr, addr + sectors * mmc->read_bl_len,
419                 sectors * mmc->read_bl_len)) {
420                 printf("Verifying uImage write fails");
421                 rc = -1;
422                 goto out;
423         }
424
425         /* Done */
426         printf("Done: %d (%x hex) sectors written at %d (%x hex)\n",
427                 sectors, sectors, offset, offset);
428
429 out:
430         if (!buf)
431                 free(buf);
432         return rc;
433 }
434
435 static int install_rootfs(int dev, void *addr, u32 size)
436 {
437         int rc = 0;
438         u8 *buf = 0;
439         u32 cnt, offset, sectors;
440         struct partition_table *mbr;
441         struct mmc *mmc = find_mmc_device(dev);
442
443         /* Calculate sectors of rootfs */
444         sectors = size / mmc->read_bl_len;
445         if (size % mmc->read_bl_len)
446                 sectors++;
447
448         /* Allocate sector buffer */
449         buf = malloc(mmc->read_bl_len);
450         if (!buf) {
451                 printf("%s[%d]: malloc error\n", __func__, __LINE__);
452                 rc = -1;
453                 goto out;
454         }
455
456         /* Check partition */
457         offset = 0;
458         cnt = mmc->block_dev.block_read(dev, offset, 1, buf);
459         if (cnt != 1) {
460                 printf("%s[%d]: read mmc error\n", __func__, __LINE__);
461                 rc = -1;
462                 goto out;
463         }
464         mbr = (struct partition_table *)buf;
465         if ((mbr->signature != MBR_SIGNATURE) ||
466                 (mbr->partitions[2].file_system != EXTPART_FILESYS)) {
467                 printf("No rootfs partition\n");
468                 rc = -1;
469                 goto out;
470         }
471         if (mbr->partitions[2].sector_count < sectors) {
472                 printf("No enough rootfs partition room\n");
473                 rc = -1;
474                 goto out;
475         }
476
477         /* Write rootfs */
478         offset = mbr->partitions[2].sector_offset;
479         cnt = mmc->block_dev.block_write(dev, offset, sectors, addr);
480         if (cnt != sectors) {
481                 printf("%s[%d]: write mmc error\n", __func__, __LINE__);
482                 rc = -1;
483                 goto out;
484         }
485
486         /* Done */
487         printf("Done: %d (%x hex) sectors written at %d (%x hex)\n",
488                 sectors, sectors, offset, offset);
489
490 out:
491         if (!buf)
492                 free(buf);
493         return rc;
494 }
495
496 int do_mxs_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
497 {
498         int dev = 0;
499         struct mmc *mmc;
500
501         if (argc < 2)
502                 goto err_out;
503
504         if (strcmp(argv[1], "format") &&
505                 strcmp(argv[1], "install"))
506                 goto err_out;
507
508         if (argc == 2) { /* list */
509                 print_mmc_devices('\n');
510                 return 0;
511         }
512
513         /* Find and init mmc */
514         dev = simple_strtoul(argv[2], NULL, 10);
515         mmc = find_mmc_device(dev);
516         if (!mmc) {
517                 printf("%s[%d]: find mmc error\n", __func__, __LINE__);
518                 return -1;
519         }
520         if (mmc_init(mmc)) {
521                 printf("%s[%d]: init mmc error\n", __func__, __LINE__);
522                 return -1;
523         }
524
525         if (!strcmp(argv[1], "format"))
526                 mmc_format(dev);
527         if (argc == 3) /* rescan (mmc_init) */
528                 return 0;
529
530         if (argc != 6)
531                 goto err_out;
532
533         if (!strcmp(argv[1], "install")) {
534                 void *addr = (void *)simple_strtoul(argv[3], NULL, 16);
535                 u32 size = simple_strtoul(argv[4], NULL, 16);
536
537                 if (!strcmp(argv[5], "sbImage"))
538                         return install_sbimage(dev, addr, size);
539                 else if (!strcmp(argv[5], "uImage"))
540                         return install_uimage(dev, addr, size);
541                 else if (!strcmp(argv[5], "rootfs"))
542                         return install_rootfs(dev, addr, size);
543         }
544
545 err_out:
546         printf("Usage:\n%s\n", cmdtp->usage);
547         return -1;
548 }
549
550 U_BOOT_CMD(
551         mxs_mmc, 6, 1, do_mxs_mmcops,
552         "MXS specific MMC sub system",
553         "mxs_mmc format <device num>\n"
554         "mxs_mmc install <device num> addr size sbImage/uImage/rootfs\n");
555 #endif /* CONFIG_GENERIC_MMC */