]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - patches/0085-ENGR00120830-Add-eMMC-and-eSD-fast-boot-support.patch
imported Ka-Ro specific additions to U-Boot 2009.08 for TX28
[karo-tx-uboot.git] / patches / 0085-ENGR00120830-Add-eMMC-and-eSD-fast-boot-support.patch
1 From 8bab684efeed6ae55e43df47298578c31b251af3 Mon Sep 17 00:00:00 2001
2 From: Terry Lv <r65388@freescale.com>
3 Date: Sat, 6 Feb 2010 18:19:39 +0800
4 Subject: [PATCH] ENGR00120830: Add eMMC and eSD fast boot support
5
6 Add eMMC and eSD fast boot support.
7
8 Signed-off-by: Terry Lv <r65388@freescale.com>
9 Signed-off-by: Brian Liu <b14843@freescale.com>
10 ---
11  common/cmd_mmc.c           |  131 +++++++++++++++++++++++++++++++++++++-
12  drivers/mmc/mmc.c          |  151 +++++++++++++++++++++++++++++++++++++++++++-
13  include/configs/mx51_bbg.h |   33 +---------
14  include/mmc.h              |   26 +++++++-
15  4 files changed, 307 insertions(+), 34 deletions(-)
16
17 diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
18 index 421482e..b8d494b 100644
19 --- a/common/cmd_mmc.c
20 +++ b/common/cmd_mmc.c
21 @@ -112,6 +112,48 @@ static void print_mmcinfo(struct mmc *mmc)
22         printf("Capacity: %lld\n", mmc->capacity);
23  
24         printf("Bus Width: %d-bit\n", mmc->bus_width);
25 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
26 +       if (mmc->boot_size_mult == 0) {
27 +               printf("Boot Partition Size: %s\n", "No boot partition available");
28 +       } else {
29 +               printf("Boot Partition Size: %5dKB\n", mmc->boot_size_mult * 128);
30 +
31 +               printf("Current Partition for boot: ");
32 +               switch (mmc->boot_config & EXT_CSD_BOOT_PARTITION_ENABLE_MASK) {
33 +               case EXT_CSD_BOOT_PARTITION_DISABLE:
34 +                       printf("Not bootable\n");
35 +                       break;
36 +               case EXT_CSD_BOOT_PARTITION_PART1:
37 +                       printf("Boot partition 1\n");
38 +                       break;
39 +               case EXT_CSD_BOOT_PARTITION_PART2:
40 +                       printf("Boot partition 2\n");
41 +                       break;
42 +               case EXT_CSD_BOOT_PARTITION_USER:
43 +                       printf("User area\n");
44 +                       break;
45 +               default:
46 +                       printf("Unknown\n");
47 +                       break;
48 +               }
49 +
50 +               printf("Current Partition for read/write: ");
51 +               switch (mmc->boot_config & EXT_CSD_BOOT_PARTITION_ACCESS_MASK) {
52 +               case EXT_CSD_BOOT_PARTITION_ACCESS_DISABLE:
53 +                       printf("User Area\n");
54 +                       break;
55 +               case EXT_CSD_BOOT_PARTITION_ACCESS_PART1:
56 +                       printf("Boot partition 1\n");
57 +                       break;
58 +               case EXT_CSD_BOOT_PARTITION_ACCESS_PART2:
59 +                       printf("Boot partition 2\n");
60 +                       break;
61 +               default:
62 +                       printf("Unknown\n");
63 +                       break;
64 +               }
65 +       }
66 +#endif
67  }
68  
69  int do_mmcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
70 @@ -144,6 +186,9 @@ U_BOOT_CMD(mmcinfo, 2, 0, do_mmcinfo,
71  int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
72  {
73         int rc = 0;
74 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
75 +       u32 part = 0;
76 +#endif
77  
78         switch (argc) {
79         case 3:
80 @@ -171,6 +216,10 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
81                         return 0;
82                 }
83                 return 1;
84 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
85 +       case 6: /* Fall through */
86 +               part = simple_strtoul(argv[6], NULL, 10);
87 +#endif
88         default: /* at least 5 args */
89                 if (strcmp(argv[1], "read") == 0) {
90                         int dev = simple_strtoul(argv[2], NULL, 10);
91 @@ -178,6 +227,7 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
92                         u32 cnt = simple_strtoul(argv[5], NULL, 16);
93                         u32 n;
94                         u32 blk = simple_strtoul(argv[4], NULL, 16);
95 +
96                         struct mmc *mmc = find_mmc_device(dev);
97  
98                         if (!mmc)
99 @@ -188,11 +238,44 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
100  
101                         mmc_init(mmc);
102  
103 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
104 +                       /* After mmc_init, we now know whether this is a eSD/eMMC which support boot partition */
105 +                       if (part > 0) {
106 +                               if (IS_SD(mmc)) {
107 +                                       if (sd_switch_partition(mmc, 1) < 0) {
108 +                                               printf("\nError: Fail to switch partition to %d before reading\n", 1);
109 +                                               return 1;
110 +                                       }
111 +                               } else {
112 +                                       if (mmc_switch_partition(mmc, part) < 0) {
113 +                                               printf("\nError: Fail to switch partition to %d before reading\n", part);
114 +                                               return 1;
115 +                                       }
116 +                               }
117 +                       }
118 +#endif
119 +
120                         n = mmc->block_dev.block_read(dev, blk, cnt, addr);
121  
122                         /* flush cache after read */
123                         flush_cache((ulong)addr, cnt * 512); /* FIXME */
124  
125 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
126 +                       /* Switch back */
127 +                       if (part > 0) {
128 +                               if (IS_SD(mmc)) {
129 +                                       if (sd_switch_partition(mmc, 0) < 0) {
130 +                                               printf("\nError: Fail to switch partition back!\n");
131 +                                               return 1;
132 +                                       }
133 +                               } else {
134 +                                       if (mmc_switch_partition(mmc, 0) < 0) {
135 +                                               printf("\nError: Fail to switch partition back!\n");
136 +                                               return 1;
137 +                                       }
138 +                               }
139 +                       }
140 +#endif
141                         printf("%d blocks read: %s\n",
142                                 n, (n==cnt) ? "OK" : "ERROR");
143                         return (n == cnt) ? 0 : 1;
144 @@ -201,6 +284,7 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
145                         void *addr = (void *)simple_strtoul(argv[3], NULL, 16);
146                         u32 cnt = simple_strtoul(argv[5], NULL, 16);
147                         u32 n;
148 +
149                         struct mmc *mmc = find_mmc_device(dev);
150  
151                         int blk = simple_strtoul(argv[4], NULL, 16);
152 @@ -213,8 +297,42 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
153  
154                         mmc_init(mmc);
155  
156 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
157 +                       /* After mmc_init, we now know whether this is a eSD/eMMC which support boot partition */
158 +                        if (part > 0) {
159 +                               if (IS_SD(mmc)) {
160 +                                       if (sd_switch_partition(mmc, 1) < 0) {
161 +                                               printf("\nError: Fail to switch partition to %d before writing\n", 1);
162 +                                               return 1;
163 +                                       }
164 +                               } else {
165 +                                       if (mmc_switch_partition(mmc, part) < 0) {
166 +                                               printf("\nError: Fail to switch partition to %d before writing\n", part);
167 +                                               return 1;
168 +                                       }
169 +                               }
170 +                       }
171 +#endif
172 +
173                         n = mmc->block_dev.block_write(dev, blk, cnt, addr);
174  
175 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
176 +                       /* Switch back */
177 +                       if (part > 0) {
178 +                               if (IS_SD(mmc)) {
179 +                                       if (sd_switch_partition(mmc, 0) < 0) {
180 +                                               printf("\nError: Fail to switch partition back!\n");
181 +                                               return 1;
182 +                                       }
183 +                               } else {
184 +                                       if (mmc_switch_partition(mmc, 0) < 0) {
185 +                                               printf("\nError: Fail to switch partition back!\n");
186 +                                               return 1;
187 +                                       }
188 +                               }
189 +                       }
190 +#endif
191 +
192                         printf("%d blocks written: %s\n",
193                                 n, (n == cnt) ? "OK" : "ERROR");
194                         return (n == cnt) ? 0 : 1;
195 @@ -227,11 +345,22 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
196         }
197  }
198  
199 +#ifndef CONFIG_BOOT_PARTITION_ACCESS
200  U_BOOT_CMD(
201         mmc, 6, 1, do_mmcops,
202         "MMC sub system",
203 -       "read <device num> addr blk# cnt\n"
204 +       "mmc read <device num> addr blk# cnt\n"
205         "mmc write <device num> addr blk# cnt\n"
206         "mmc rescan <device num>\n"
207         "mmc list - lists available devices");
208 +#else
209 +U_BOOT_CMD(
210 +       mmc, 7, 1, do_mmcops,
211 +       "MMC sub system",
212 +       "mmc read <device num> addr blk# cnt [partition]\n"
213 +       "mmc write <device num> addr blk# cnt [partition]\n"
214 +       "mmc rescan <device num>\n"
215 +       "mmc list - lists available devices");
216 +#endif
217  #endif
218 +
219 diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
220 index f78b8a8..422c6ed 100644
221 --- a/drivers/mmc/mmc.c
222 +++ b/drivers/mmc/mmc.c
223 @@ -1,5 +1,5 @@
224  /*
225 - * (C) Copyright 2008-2009 Freescale Semiconductor, Inc.
226 + * (C) Copyright 2008-2010 Freescale Semiconductor, Inc.
227   * Terry Lv
228   *
229   * Copyright 2008, Freescale Semiconductor, Inc
230 @@ -646,6 +646,149 @@ void mmc_set_bus_width(struct mmc *mmc, uint width)
231         mmc_set_ios(mmc);
232  }
233  
234 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
235 +/* Return 0/1/2 for partition id before switch; Return -1 if fail to switch */
236 +int mmc_switch_partition(struct mmc *mmc, uint part)
237 +{
238 +       char *ext_csd;
239 +       int err;
240 +       uint old_part, new_part;
241 +       char boot_config;
242 +
243 +       /* partition must be -
244 +               0 - user area
245 +               1 - boot partition 1
246 +               2 - boot partition 2
247 +       */
248 +       if (part > 2) {
249 +               printf("\nWrong partition id - 0 (user area), 1 (boot1), 2 (boot2)\n");
250 +               return 1;
251 +       }
252 +
253 +       /* Before calling this func, "mmc" struct must have been initialized */
254 +       if (mmc->version < MMC_VERSION_4) {
255 +               puts("Error: invalid mmc version! mmc version is below version 4!");
256 +               return -1;
257 +       }
258 +
259 +       if (mmc->boot_size_mult <= 0) {
260 +               /* it's a normal SD/MMC but user request to boot partition */
261 +               printf("\nError: This is a normal SD/MMC card but you request to access boot partition\n");
262 +               return -1;
263 +       }
264 +
265 +       /* part must be 0 (user area), 1 (boot partition1) or 2 (boot partition2) */
266 +       if (part > 2) {
267 +               puts("Error: partition id must be 0(user area), 1(boot partition1) or 2(boot partition2)\n");
268 +               return -1;
269 +       }
270 +
271 +       if (IS_SD(mmc)) {
272 +               /* eSD card hadn't been supported. Return directly without warning */
273 +               return -1;
274 +       }
275 +
276 +       ext_csd = (char *)malloc(512);
277 +       if (!ext_csd) {
278 +               puts("Error: Could not allocate buffer for MMC ext csd!\n");
279 +               return -1;
280 +       }
281 +
282 +       err = mmc_send_ext_csd(mmc, ext_csd);
283 +       if (err) {
284 +               puts("Warning: fail to get ext csd for MMC!\n");
285 +               goto err_rtn;
286 +    }
287 +
288 +       old_part = ext_csd[EXT_CSD_BOOT_CONFIG] & EXT_CSD_BOOT_PARTITION_ACCESS_MASK;
289 +
290 +       /* Send SWITCH command to change partition for access */
291 +       boot_config = (ext_csd[EXT_CSD_BOOT_CONFIG] & ~EXT_CSD_BOOT_PARTITION_ACCESS_MASK) | (char)part;
292 +
293 +       err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_CONFIG, boot_config);
294 +       if (err) {
295 +               puts("Error: fail to send SWITCH command to card to swich partition for access!\n");
296 +               goto err_rtn;
297 +       }
298 +
299 +       /* Now check whether it works */
300 +       err = mmc_send_ext_csd(mmc, ext_csd);
301 +       if (err) {
302 +               puts("Warning: fail to get ext csd for MMC!\n");
303 +               goto err_rtn;
304 +       }
305 +
306 +       new_part = ext_csd[EXT_CSD_BOOT_CONFIG] & EXT_CSD_BOOT_PARTITION_ACCESS_MASK;
307 +       if ((char)part != new_part) {
308 +               printf("Warning: after SWITCH, current part id %d is not same as requested partition %d!\n",
309 +                       new_part, part);
310 +               goto err_rtn;
311 +       }
312 +
313 +       /* Seems everything is ok, return the partition id before switch */
314 +       free(ext_csd);
315 +       return old_part;
316 +
317 +err_rtn:
318 +       free(ext_csd);
319 +       return -1;
320 +}
321 +
322 +int sd_switch_partition(struct mmc *mmc, uint part)
323 +{
324 +       struct mmc_cmd cmd;
325 +       int err;
326 +
327 +       if (part > 1) {
328 +               printf("\nWrong partition id - 0 (user area), 1 (boot1)\n");
329 +               return 1;
330 +       }
331 +
332 +       cmd.cmdidx = SD_CMD_SELECT_PARTITION;
333 +       cmd.resp_type = MMC_RSP_R1;
334 +       cmd.cmdarg = part << 24;
335 +       cmd.flags = 0;
336 +
337 +       err = mmc_send_cmd(mmc, &cmd, NULL);
338 +
339 +       if (err) {
340 +               printf("Failed to switch to partition %d\nPartition not exists or command execute fail!\n");
341 +               return -1;
342 +       }
343 +
344 +       return 0;
345 +}
346 +
347 +int mmc_get_cur_boot_partition(struct mmc *mmc)
348 +{
349 +       char *ext_csd;
350 +       int err;
351 +
352 +       ext_csd = (char *)malloc(512);
353 +
354 +       if (!ext_csd) {
355 +               puts("Error! Could not allocate buffer for MMC ext csd!\n");
356 +               return -1;
357 +       }
358 +
359 +       err = mmc_send_ext_csd(mmc, ext_csd);
360 +
361 +       if (err) {
362 +               mmc->boot_config = 0;
363 +               mmc->boot_size_mult = 0;
364 +               /* continue since it's not a fatal error */
365 +       } else {
366 +               mmc->boot_config = ext_csd[EXT_CSD_BOOT_CONFIG];
367 +               mmc->boot_size_mult = ext_csd[EXT_CSD_BOOT_INFO];
368 +       }
369 +
370 +       free(ext_csd);
371 +
372 +       return err;
373 +}
374 +
375 +#endif
376 +
377  int mmc_startup(struct mmc *mmc)
378  {
379         int err;
380 @@ -819,6 +962,7 @@ int mmc_startup(struct mmc *mmc)
381                         mmc_set_clock(mmc, 50000000);
382                 else
383                         mmc_set_clock(mmc, 25000000);
384 +
385         } else {
386                 if (mmc->card_caps & MMC_MODE_4BIT) {
387                         /* Set the card to use 4 bit*/
388 @@ -849,6 +993,10 @@ int mmc_startup(struct mmc *mmc)
389                                 mmc_set_clock(mmc, 26000000);
390                 } else
391                         mmc_set_clock(mmc, 20000000);
392 +
393 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
394 +               mmc_get_cur_boot_partition(mmc);
395 +#endif
396         }
397  
398         /* fill in device description */
399 @@ -1009,3 +1157,4 @@ int mmc_initialize(bd_t *bis)
400  
401         return 0;
402  }
403 +
404 diff --git a/include/configs/mx51_bbg.h b/include/configs/mx51_bbg.h
405 index f773563..b2961a2 100644
406 --- a/include/configs/mx51_bbg.h
407 +++ b/include/configs/mx51_bbg.h
408 @@ -69,36 +69,6 @@
409  #define CONFIG_MX51_UART       1
410  #define CONFIG_MX51_UART1      1
411  
412 -/*
413 - * SPI Configs
414 - * */
415 -#define CONFIG_FSL_SF          1
416 -#define CONFIG_SPI_FLASH_IMX_ATMEL     1
417 -#define CONFIG_SPI_FLASH_CS    1
418 -#define CONFIG_IMX_ECSPI
419 -#define CONFIG_IMX_SPI_PMIC
420 -#define CONFIG_IMX_SPI_PMIC_CS 0
421 -#define        IMX_CSPI_VER_2_3        1
422 -#define MAX_SPI_BYTES          (64 * 4)
423 -
424 -/*
425 - * MMC Configs
426 - * */
427 -
428 -/*
429 - * Eth Configs
430 - */
431 -#define CONFIG_HAS_ETH1
432 -#define CONFIG_NET_MULTI 1
433 -#define CONFIG_MXC_FEC
434 -#define CONFIG_MII
435 -#define CONFIG_DISCOVER_PHY
436 -
437 -#define CONFIG_FEC0_IOBASE     FEC_BASE_ADDR
438 -#define CONFIG_FEC0_PINMUX     -1
439 -#define CONFIG_FEC0_PHY_ADDR   0x1F
440 -#define CONFIG_FEC0_MIIBASE    -1
441 -
442  /* allow to overwrite serial and ethaddr */
443  #define CONFIG_ENV_OVERWRITE
444  #define CONFIG_CONS_INDEX              1
445 @@ -133,7 +103,8 @@
446         #define CONFIG_FSL_SF           1
447         #define CONFIG_SPI_FLASH_IMX_ATMEL      1
448         #define CONFIG_SPI_FLASH_CS     1
449 -       #define CONFIG_IMX_SPI
450 +       #define CONFIG_IMX_ECSPI
451 +       #define IMX_CSPI_VER_2_3        1
452         #define CONFIG_IMX_SPI_PMIC
453         #define CONFIG_IMX_SPI_PMIC_CS 0
454  
455 diff --git a/include/mmc.h b/include/mmc.h
456 index 2dc69ab..fe63ed7 100644
457 --- a/include/mmc.h
458 +++ b/include/mmc.h
459 @@ -1,5 +1,7 @@
460  /*
461 - * Copyright 2008, Freescale Semiconductor, Inc
462 + * (C) Copyright 2009-2010 Freescale Semiconductor, Inc.
463 + *
464 + * Copyright 2008-2010, Freescale Semiconductor, Inc
465   * Andy Fleming
466   *
467   * Based (loosely) on the Linux code
468 @@ -79,6 +81,7 @@
469  #define SD_CMD_SEND_RELATIVE_ADDR      3
470  #define SD_CMD_SWITCH_FUNC             6
471  #define SD_CMD_SEND_IF_COND            8
472 +#define SD_CMD_SELECT_PARTITION   43
473  
474  #define SD_CMD_APP_SET_BUS_WIDTH       6
475  #define SD_CMD_APP_SEND_OP_COND                41
476 @@ -128,11 +131,13 @@
477   * EXT_CSD fields
478   */
479  
480 +#define EXT_CSD_BOOT_CONFIG    179     /* RW */
481  #define EXT_CSD_BUS_WIDTH      183     /* R/W */
482  #define EXT_CSD_HS_TIMING      185     /* R/W */
483  #define EXT_CSD_CARD_TYPE      196     /* RO */
484  #define EXT_CSD_REV            192     /* RO */
485  #define EXT_CSD_SEC_CNT                212     /* RO, 4 bytes */
486 +#define EXT_CSD_BOOT_INFO      228     /* RO */
487  
488  /*
489   * EXT_CSD field definitions
490 @@ -149,6 +154,17 @@
491  #define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
492  #define EXT_CSD_BUS_WIDTH_8    2       /* Card is in 8 bit mode */
493  
494 +#define EXT_CSD_BOOT_PARTITION_ENABLE_MASK     (0x7 << 3)
495 +#define EXT_CSD_BOOT_PARTITION_DISABLE         (0x0)
496 +#define EXT_CSD_BOOT_PARTITION_PART1           (0x1 << 3)
497 +#define EXT_CSD_BOOT_PARTITION_PART2           (0x2 << 3)
498 +#define EXT_CSD_BOOT_PARTITION_USER            (0x7 << 3)
499 +
500 +#define EXT_CSD_BOOT_PARTITION_ACCESS_MASK     (0x7)
501 +#define EXT_CSD_BOOT_PARTITION_ACCESS_DISABLE   (0x0)
502 +#define EXT_CSD_BOOT_PARTITION_ACCESS_PART1    (0x1)
503 +#define EXT_CSD_BOOT_PARTITION_ACCESS_PART2    (0x2)
504 +
505  #define R1_ILLEGAL_COMMAND             (1 << 22)
506  #define R1_APP_CMD                     (1 << 5)
507  
508 @@ -259,6 +275,10 @@ struct mmc {
509         uint read_bl_len;
510         uint write_bl_len;
511         u64 capacity;
512 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
513 +       uint boot_config;
514 +       uint boot_size_mult;
515 +#endif
516         block_dev_desc_t block_dev;
517         int (*send_cmd)(struct mmc *mmc,
518                         struct mmc_cmd *cmd, struct mmc_data *data);
519 @@ -272,6 +292,10 @@ int mmc_init(struct mmc *mmc);
520  int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
521  struct mmc *find_mmc_device(int dev_num);
522  void print_mmc_devices(char separator);
523 +#ifdef CONFIG_BOOT_PARTITION_ACCESS
524 +int mmc_switch_partition(struct mmc *mmc, uint part);
525 +int sd_switch_partition(struct mmc *mmc, uint part);
526 +#endif
527  
528  #ifndef CONFIG_GENERIC_MMC
529  int mmc_legacy_init(int verbose);
530 -- 
531 1.5.4.4
532