]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - patches/0139-ENGR00125036-Uboot-Add-eMMC-4.4-support.patch
imported Ka-Ro specific additions to U-Boot 2009.08 for TX28
[karo-tx-uboot.git] / patches / 0139-ENGR00125036-Uboot-Add-eMMC-4.4-support.patch
1 From 1bc5e5f2cee211a74ee79e0eb5f7f37a3db387f4 Mon Sep 17 00:00:00 2001
2 From: Anish Trivedi <anish@freescale.com>
3 Date: Fri, 16 Jul 2010 12:35:32 -0500
4 Subject: [PATCH] ENGR00125036 Uboot Add eMMC 4.4 support
5
6 Enable DDR mode on ESDHC controller and mmc library
7 Enable 8-bit support in mmc library
8
9 Signed-off-by: Anish Trivedi <anish@freescale.com>
10 ---
11  common/cmd_mmc.c                   |    6 ++
12  drivers/mmc/imx_esdhc.c            |   55 ++++++++++++++++--
13  drivers/mmc/mmc.c                  |  109 ++++++++++++++++++++++++++++++++++-
14  include/configs/mx50_arm2.h        |    6 ++-
15  include/configs/mx50_arm2_lpddr2.h |    7 ++-
16  include/fsl_esdhc.h                |   10 +++
17  include/mmc.h                      |   12 ++++-
18  7 files changed, 193 insertions(+), 12 deletions(-)
19
20 diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
21 index 1061dab..139b1e8 100644
22 --- a/common/cmd_mmc.c
23 +++ b/common/cmd_mmc.c
24 @@ -138,6 +138,12 @@ static void print_mmcinfo(struct mmc *mmc)
25         printf("High Capacity: %s\n", mmc->high_capacity ? "Yes" : "No");
26         printf("Capacity: %lld\n", mmc->capacity);
27  
28 +#ifdef CONFIG_EMMC_DDR_MODE
29 +       if (mmc->bus_width == EMMC_MODE_4BIT_DDR ||
30 +               mmc->bus_width == EMMC_MODE_8BIT_DDR)
31 +               printf("Bus Width: %d-bit DDR\n", (mmc->bus_width >> 8));
32 +       else
33 +#endif
34         printf("Bus Width: %d-bit\n", mmc->bus_width);
35  #ifdef CONFIG_BOOT_PARTITION_ACCESS
36         if (mmc->boot_size_mult == 0) {
37 diff --git a/drivers/mmc/imx_esdhc.c b/drivers/mmc/imx_esdhc.c
38 index e3a1fb7..a57aa74 100644
39 --- a/drivers/mmc/imx_esdhc.c
40 +++ b/drivers/mmc/imx_esdhc.c
41 @@ -69,10 +69,11 @@ struct fsl_esdhc {
42         uint    wml;
43         char    reserved1[8];
44         uint    fevt;
45 -       char    reserved2[168];
46 +       char    reserved2[12];
47 +       uint dllctrl;
48 +       uint dllstatus;
49 +       char    reserved3[148];
50         uint    hostver;
51 -       char    reserved3[780];
52 -       uint    scr;
53  };
54  
55  /* Return the XFERTYP flags for a given command and data packet */
56 @@ -197,6 +198,10 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
57         /* Figure out the transfer arguments */
58         xfertyp = esdhc_xfertyp(cmd, data);
59  
60 +       if (mmc->bus_width == EMMC_MODE_4BIT_DDR ||
61 +               mmc->bus_width == EMMC_MODE_8BIT_DDR)
62 +               xfertyp |= XFERTYP_DDR_EN;
63 +
64         /* Send the command */
65         writel(cmd->cmdarg, &regs->cmdarg);
66         writel(xfertyp, &regs->xfertyp);
67 @@ -274,6 +279,9 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
68                 while (!(readl(&regs->irqstat) & IRQSTAT_TC)) ;
69         }
70  
71 +       if (readl(&regs->irqstat) & 0xFFFF0000)
72 +               return COMM_ERR;
73 +
74         writel(-1, &regs->irqstat);
75  
76         return 0;
77 @@ -325,6 +333,22 @@ void set_sysctl(struct mmc *mmc, uint clock)
78  #endif
79  }
80  
81 +static void esdhc_dll_setup(struct mmc *mmc)
82 +{
83 +       struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
84 +       struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
85 +
86 +       uint dll_control = readl(&regs->dllctrl);
87 +       dll_control &= ~(ESDHC_DLLCTRL_SLV_OVERRIDE_VAL_MASK |
88 +               ESDHC_DLLCTRL_SLV_OVERRIDE);
89 +       dll_control |= ((ESDHC_DLLCTRL_SLV_OVERRIDE_VAL <<
90 +               ESDHC_DLLCTRL_SLV_OVERRIDE_VAL_SHIFT) |
91 +               ESDHC_DLLCTRL_SLV_OVERRIDE);
92 +
93 +       writel(dll_control, &regs->dllctrl);
94 +
95 +}
96 +
97  static void esdhc_set_ios(struct mmc *mmc)
98  {
99         struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
100 @@ -344,6 +368,14 @@ static void esdhc_set_ios(struct mmc *mmc)
101         } else if (mmc->bus_width == 8) {
102                 tmp = readl(&regs->proctl) | PROCTL_DTW_8;
103                 writel(tmp, &regs->proctl);
104 +       } else if (mmc->bus_width == EMMC_MODE_4BIT_DDR) {
105 +               tmp = readl(&regs->proctl) | PROCTL_DTW_4;
106 +               writel(tmp, &regs->proctl);
107 +               esdhc_dll_setup(mmc);
108 +       } else if (mmc->bus_width == EMMC_MODE_8BIT_DDR) {
109 +               tmp = readl(&regs->proctl) | PROCTL_DTW_8;
110 +               writel(tmp, &regs->proctl);
111 +               esdhc_dll_setup(mmc);
112         }
113  }
114  
115 @@ -411,22 +443,35 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
116         mmc->set_ios = esdhc_set_ios;
117         mmc->init = esdhc_init;
118  
119 -       caps = regs->hostcapblt;
120 +       caps = readl(&regs->hostcapblt);
121         if (caps & ESDHC_HOSTCAPBLT_VS30)
122                 mmc->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
123         if (caps & ESDHC_HOSTCAPBLT_VS33)
124                 mmc->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
125  
126 -       mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
127 +       mmc->host_caps = MMC_MODE_4BIT;
128  
129         if (caps & ESDHC_HOSTCAPBLT_HSS)
130                 mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
131  
132 +       if (((readl(&regs->hostver) & ESDHC_HOSTVER_VVN_MASK)
133 +               >> ESDHC_HOSTVER_VVN_SHIFT) >= ESDHC_HOSTVER_DDR_SUPPORT)
134 +               mmc->host_caps |= EMMC_MODE_4BIT_DDR;
135 +
136         mmc->f_min = 400000;
137         mmc->f_max = MIN(mxc_get_clock(MXC_ESDHC_CLK), 50000000);
138  
139         mmc_register(mmc);
140  
141 +#ifdef CONFIG_MMC_8BIT_PORTS
142 +       if ((1 << mmc->block_dev.dev) & CONFIG_MMC_8BIT_PORTS) {
143 +               mmc->host_caps |= MMC_MODE_8BIT;
144 +
145 +               if (mmc->host_caps & EMMC_MODE_4BIT_DDR)
146 +                       mmc->host_caps |= EMMC_MODE_8BIT_DDR;
147 +       }
148 +#endif
149 +
150         return 0;
151  }
152  
153 diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
154 index 072ef46..9f915cd 100644
155 --- a/drivers/mmc/mmc.c
156 +++ b/drivers/mmc/mmc.c
157 @@ -91,6 +91,13 @@ mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
158  
159         blklen = mmc->write_bl_len;
160  
161 +#ifdef CONFIG_EMMC_DDR_MODE
162 +       if (mmc->bus_width == EMMC_MODE_4BIT_DDR ||
163 +               mmc->bus_width == EMMC_MODE_8BIT_DDR) {
164 +               err = 0;
165 +               blklen = 512;
166 +       } else
167 +#endif
168         err = mmc_set_blocklen(mmc, mmc->write_bl_len);
169  
170         if (err) {
171 @@ -173,6 +180,12 @@ int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size)
172         int endblock = lldiv(src + size - 1, mmc->read_bl_len);
173         int err = 0;
174  
175 +#ifdef CONFIG_EMMC_DDR_MODE
176 +       if (mmc->bus_width == EMMC_MODE_4BIT_DDR ||
177 +               mmc->bus_width == EMMC_MODE_8BIT_DDR)
178 +               blklen = 512;
179 +#endif
180 +
181         /* Make a buffer big enough to hold all the blocks we might read */
182         buffer = malloc(blklen);
183  
184 @@ -181,6 +194,12 @@ int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size)
185                 return -1;
186         }
187  
188 +#ifdef CONFIG_EMMC_DDR_MODE
189 +       if (mmc->bus_width == EMMC_MODE_4BIT_DDR ||
190 +               mmc->bus_width == EMMC_MODE_8BIT_DDR)
191 +               err = 0;
192 +       else
193 +#endif
194         /* We always do full block reads from the card */
195         err = mmc_set_blocklen(mmc, mmc->read_bl_len);
196  
197 @@ -229,9 +248,14 @@ static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
198         if (!mmc)
199                 return -1;
200  
201 -       blklen = mmc->read_bl_len;
202 -
203 -       err = mmc_set_blocklen(mmc, blklen);
204 +       if (mmc->bus_width == EMMC_MODE_4BIT_DDR ||
205 +               mmc->bus_width == EMMC_MODE_8BIT_DDR) {
206 +               blklen = 512;
207 +               err = 0;
208 +       } else {
209 +               blklen = mmc->read_bl_len;
210 +               err = mmc_set_blocklen(mmc, blklen);
211 +       }
212  
213         if (err) {
214                 puts("set read bl len failed\n\r");
215 @@ -444,7 +468,8 @@ static int mmc_change_freq(struct mmc *mmc)
216         if (mmc->version < MMC_VERSION_4)
217                 return 0;
218  
219 -       mmc->card_caps |= MMC_MODE_4BIT;
220 +       mmc->card_caps |= ((mmc->host_caps & MMC_MODE_8BIT)
221 +               ? MMC_MODE_8BIT : MMC_MODE_4BIT);
222  
223         ext_csd = (char *)malloc(512);
224  
225 @@ -488,6 +513,15 @@ static int mmc_change_freq(struct mmc *mmc)
226                 mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
227         else
228                 mmc->card_caps |= MMC_MODE_HS;
229 +#ifdef CONFIG_EMMC_DDR_MODE
230 +       if (cardtype & EMMC_MODE_DDR_3V) {
231 +               if (mmc->card_caps & MMC_MODE_8BIT)
232 +                       mmc->card_caps |= EMMC_MODE_8BIT_DDR;
233 +               else
234 +                       mmc->card_caps |= EMMC_MODE_4BIT_DDR;
235 +       }
236 +
237 +#endif
238  
239  no_err_rtn:
240         free(ext_csd);
241 @@ -681,6 +715,9 @@ int mmc_switch_partition(struct mmc *mmc, uint part, uint enable_boot)
242         int err;
243         uint old_part, new_part;
244         char boot_config;
245 +#ifdef CONFIG_EMMC_DDR_MODE
246 +       char boot_bus_width, card_boot_bus_width;
247 +#endif
248  
249         /* partition must be -
250                 0 - user area
251 @@ -765,6 +802,44 @@ int mmc_switch_partition(struct mmc *mmc, uint part, uint enable_boot)
252                 goto err_rtn;
253         }
254  
255 +#ifdef CONFIG_EMMC_DDR_MODE
256 +       /* Program boot_bus_width field for eMMC 4.4 boot mode */
257 +       if ((ext_csd[EXT_CSD_CARD_TYPE] & 0xC) && enable_boot != 0) {
258 +
259 +               /* Configure according to this host's capabilities */
260 +               if (mmc->host_caps & EMMC_MODE_8BIT_DDR)
261 +                       boot_bus_width =  EXT_CSD_BOOT_BUS_WIDTH_DDR |
262 +                               EXT_CSD_BOOT_BUS_WIDTH_8BIT;
263 +               else if (mmc->host_caps & EMMC_MODE_4BIT_DDR)
264 +                       boot_bus_width =  EXT_CSD_BOOT_BUS_WIDTH_DDR |
265 +                               EXT_CSD_BOOT_BUS_WIDTH_4BIT;
266 +               else if (mmc->host_caps & MMC_MODE_8BIT)
267 +                       boot_bus_width = EXT_CSD_BOOT_BUS_WIDTH_8BIT;
268 +               else if (mmc->host_caps & MMC_MODE_4BIT)
269 +                       boot_bus_width = EXT_CSD_BOOT_BUS_WIDTH_4BIT;
270 +               else
271 +                       boot_bus_width = 0;
272 +
273 +               err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
274 +                       EXT_CSD_BOOT_BUS_WIDTH, boot_bus_width);
275 +
276 +               /* Ensure that it programmed properly */
277 +               err = mmc_send_ext_csd(mmc, ext_csd);
278 +               if (err) {
279 +                       puts("\nWarning: fail to get ext csd for MMC!\n");
280 +                       goto err_rtn;
281 +               }
282 +
283 +               card_boot_bus_width = ext_csd[EXT_CSD_BOOT_BUS_WIDTH];
284 +               if (card_boot_bus_width != boot_bus_width) {
285 +                       printf("\nWarning: current boot_bus_width, 0x%x, is "
286 +                               "not same as requested boot_bus_width 0x%x!\n",
287 +                               card_boot_bus_width, boot_bus_width);
288 +                       goto err_rtn;
289 +               }
290 +       }
291 +#endif
292 +
293         /* Seems everything is ok, return the partition id before switch */
294         free(ext_csd);
295         return old_part;
296 @@ -1023,6 +1098,32 @@ static int mmc_startup(struct mmc *mmc)
297                         mmc_set_bus_width(mmc, 8);
298                 }
299  
300 +#ifdef CONFIG_EMMC_DDR_MODE
301 +
302 +               if (mmc->card_caps & EMMC_MODE_8BIT_DDR) {
303 +                       /* Set the card to use 8 bit DDR mode */
304 +                       err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
305 +                                       EXT_CSD_BUS_WIDTH,
306 +                                       EXT_CSD_BUS_WIDTH_8_DDR);
307 +                       if (err)
308 +                               return err;
309 +
310 +
311 +                       /* Setup the host controller for DDR mode */
312 +                       mmc_set_bus_width(mmc, EMMC_MODE_8BIT_DDR);
313 +               } else if (mmc->card_caps & EMMC_MODE_4BIT_DDR) {
314 +                       /* Set the card to use 4 bit DDR mode */
315 +                       err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
316 +                                       EXT_CSD_BUS_WIDTH,
317 +                                       EXT_CSD_BUS_WIDTH_4_DDR);
318 +                       if (err)
319 +                               return err;
320 +
321 +                       /* Setup the host controller for DDR mode */
322 +                       mmc_set_bus_width(mmc, EMMC_MODE_4BIT_DDR);
323 +               }
324 +#endif
325 +
326                 if (mmc->card_caps & MMC_MODE_HS) {
327                         if (mmc->card_caps & MMC_MODE_HS_52MHz)
328                                 mmc_set_clock(mmc, 52000000);
329 diff --git a/include/configs/mx50_arm2.h b/include/configs/mx50_arm2.h
330 index fbede97..4c23b95 100644
331 --- a/include/configs/mx50_arm2.h
332 +++ b/include/configs/mx50_arm2.h
333 @@ -201,10 +201,14 @@
334         #define CONFIG_CMD_FAT          1
335         #define CONFIG_CMD_EXT2         1
336  
337 -       /* detect whether ESDHC1 or ESDHC3 is boot device */
338 +       /* detect whether ESDHC1, ESDHC2, or ESDHC3 is boot device */
339         #define CONFIG_DYNAMIC_MMC_DEVNO
340  
341         #define CONFIG_BOOT_PARTITION_ACCESS
342 +       #define CONFIG_EMMC_DDR_MODE
343 +
344 +       /* Indicate to esdhc driver which ports support 8-bit data */
345 +       #define CONFIG_MMC_8BIT_PORTS           0x6   /* ports 1 and 2 */
346  
347  #endif
348  /*-----------------------------------------------------------------------
349 diff --git a/include/configs/mx50_arm2_lpddr2.h b/include/configs/mx50_arm2_lpddr2.h
350 index 505b859..a5683ad 100644
351 --- a/include/configs/mx50_arm2_lpddr2.h
352 +++ b/include/configs/mx50_arm2_lpddr2.h
353 @@ -202,10 +202,15 @@
354         #define CONFIG_CMD_FAT          1
355         #define CONFIG_CMD_EXT2         1
356  
357 -       /* detect whether ESDHC1 or ESDHC3 is boot device */
358 +       /* detect whether ESDHC1, ESDHC2, or ESDHC3 is boot device */
359         #define CONFIG_DYNAMIC_MMC_DEVNO
360  
361         #define CONFIG_BOOT_PARTITION_ACCESS
362 +       #define CONFIG_EMMC_DDR_MODE
363 +
364 +       /* Indicate to esdhc driver which ports support 8-bit data */
365 +       #define CONFIG_MMC_8BIT_PORTS           0x6   /* ports 1 and 2 */
366 +
367  
368  #endif
369  /*-----------------------------------------------------------------------
370 diff --git a/include/fsl_esdhc.h b/include/fsl_esdhc.h
371 index 9f48afe..a0b1f5c 100644
372 --- a/include/fsl_esdhc.h
373 +++ b/include/fsl_esdhc.h
374 @@ -116,6 +116,7 @@
375  #define XFERTYP_RSPTYP_48_BUSY 0x00030000
376  #define XFERTYP_MSBSEL         0x00000020
377  #define XFERTYP_DTDSEL         0x00000010
378 +#define XFERTYP_DDR_EN         0x00000008
379  #define XFERTYP_AC12EN         0x00000004
380  #define XFERTYP_BCEN           0x00000002
381  #define XFERTYP_DMAEN          0x00000001
382 @@ -146,6 +147,15 @@
383  #define ESDHC_HOSTCAPBLT_DMAS  0x00400000
384  #define ESDHC_HOSTCAPBLT_HSS   0x00200000
385  
386 +#define ESDHC_HOSTVER_VVN_MASK         0x0000ff00
387 +#define ESDHC_HOSTVER_VVN_SHIFT                8
388 +#define ESDHC_HOSTVER_DDR_SUPPORT      0x13
389 +
390 +#define ESDHC_DLLCTRL_SLV_OVERRIDE_VAL 12
391 +#define ESDHC_DLLCTRL_SLV_OVERRIDE_VAL_MASK    0x0000FC00
392 +#define ESDHC_DLLCTRL_SLV_OVERRIDE_VAL_SHIFT           10
393 +#define ESDHC_DLLCTRL_SLV_OVERRIDE             0x200
394 +
395  struct fsl_esdhc_cfg {
396         u32     esdhc_base;
397         u32     no_snoop;
398 diff --git a/include/mmc.h b/include/mmc.h
399 index b8d6871..b450f4f 100644
400 --- a/include/mmc.h
401 +++ b/include/mmc.h
402 @@ -46,6 +46,8 @@
403  #define MMC_MODE_HS_52MHz      0x010
404  #define MMC_MODE_4BIT          0x100
405  #define MMC_MODE_8BIT          0x200
406 +#define EMMC_MODE_4BIT_DDR     0x400
407 +#define EMMC_MODE_8BIT_DDR     0x800
408  
409  #define SD_DATA_4BIT   0x00040000
410  
411 @@ -93,7 +95,7 @@
412  
413  #define MMC_HS_TIMING          0x00000100
414  #define MMC_HS_52MHZ           0x2
415 -
416 +#define EMMC_MODE_DDR_3V               0x4
417  #define OCR_BUSY       0x80000000
418  #define OCR_HCS                0x40000000
419  
420 @@ -131,6 +133,7 @@
421   * EXT_CSD fields
422   */
423  
424 +#define EXT_CSD_BOOT_BUS_WIDTH 177             /* RW */
425  #define EXT_CSD_BOOT_CONFIG    179     /* RW */
426  #define EXT_CSD_BUS_WIDTH      183     /* R/W */
427  #define EXT_CSD_HS_TIMING      185     /* R/W */
428 @@ -153,6 +156,13 @@
429  #define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
430  #define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
431  #define EXT_CSD_BUS_WIDTH_8    2       /* Card is in 8 bit mode */
432 +#define EXT_CSD_BUS_WIDTH_4_DDR   5            /* eMMC 4.4 in 4-bit DDR mode */
433 +#define EXT_CSD_BUS_WIDTH_8_DDR   6            /* eMMC 4.4 in 8-bit DDR mode */
434 +
435 +#define EXT_CSD_BOOT_BUS_WIDTH_1BIT            0
436 +#define EXT_CSD_BOOT_BUS_WIDTH_4BIT            1
437 +#define EXT_CSD_BOOT_BUS_WIDTH_8BIT            2
438 +#define EXT_CSD_BOOT_BUS_WIDTH_DDR     (1 << 4)
439  
440  #define EXT_CSD_BOOT_PARTITION_ENABLE_MASK     (0x7 << 3)
441  #define EXT_CSD_BOOT_PARTITION_DISABLE         (0x0)
442 -- 
443 1.5.4.4
444