Hi,

I've bought a BeagleBone Black rev. C board, and I was trying to install
OpenBSD on it, but the internal eMMC was causing errors.

 sdmmc1: unknown CARD_TYPE 0x17
 scsibus1 at sdmmc1: 2 targets, initiator 0
 sd1 at scsibus1 targ 1 lun 0: <SD/MMC, Drive #01, > SCSI2 0/direct fixed
 sd1: 1024MB, 512 bytes/sector, 2097152 sectors

Card type and sectors count were wrong, and accessing the device was
causing I/O errors.

I've investigated the problem, and it looks like the support of 
High Capacity eMMC (> 2GB) is missing.

I've written a quick and dirty patch (tested on 5.5 and snapshot) which fix 
all my issues.

Modifications:
- mask reserved bits for card type value
- read sectors count from EXT_CSD
- fix sectors count and enable SDHC if High Capacity eMMC is detected


Cédric


--- sdmmc_mem.c.orig    Sat Jul 12 20:48:52 2014
+++ sdmmc_mem.c Sat Sep 20 14:58:42 2014
@@ -428,6 +428,7 @@
        u_int8_t ext_csd[512];
        int speed = 0;
        int hs_timing = 0;
+       u_int32_t sectors = 0;
 
        if (sf->csd.mmcver >= MMC_CSD_MMCVER_4_0) {
                /* read EXT_CSD */
@@ -439,7 +440,7 @@
                        return error;
                }
 
-               switch (ext_csd[EXT_CSD_CARD_TYPE]) {
+               switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) {
                case EXT_CSD_CARD_TYPE_26M:
                        speed = 26000;
                        break;
@@ -488,6 +489,22 @@
                                return EINVAL;
                        }
                }
+
+               if (ext_csd[EXT_CSD_REV] >= 2) {
+                       sectors =   ext_csd[EXT_CSD_SEC_COUNT + 0] << 0  |
+                                               ext_csd[EXT_CSD_SEC_COUNT + 1] 
<< 8  |
+                                               ext_csd[EXT_CSD_SEC_COUNT + 2] 
<< 16 |
+                                               ext_csd[EXT_CSD_SEC_COUNT + 3] 
<< 24;
+                       /* 
+                        * High capacity MMC seems to report a "magic" 4096 * 
512 bytes
+                        * capacity in csd, but ext_csd contains the real 
sectors count
+                        */
+                       if ((sf->csd.capacity == (4096 * 512)) && 
+                               (sectors > (2u * 1024 * 1024 * 1024) / 512)) {
+                               sf->flags |= SFF_SDHC;
+                               sf->csd.capacity = sectors;
+                       }
+        }
        }
 
        return error;
--- sdmmcreg.h.orig     Thu Sep 12 13:54:04 2013
+++ sdmmcreg.h  Sat Sep 20 13:42:08 2014
@@ -95,6 +95,7 @@
 #define EXT_CSD_REV                    192     /* RO */
 #define EXT_CSD_STRUCTURE              194     /* RO */
 #define EXT_CSD_CARD_TYPE              196     /* RO */
+#define EXT_CSD_SEC_COUNT              212     /* RO */
 
 /* EXT_CSD field definitions */
 #define EXT_CSD_CMD_SET_NORMAL         (1U << 0)
@@ -109,6 +110,7 @@
 /* EXT_CSD_CARD_TYPE */
 /* The only currently valid values for this field are 0x01, 0x03, 0x07,
  * 0x0B and 0x0F. */
+#define EXT_CSD_CARD_TYPE_MASK  0xF /* Mask out reserved bits */ 
 #define EXT_CSD_CARD_TYPE_F_26M                (1 << 0)
 #define EXT_CSD_CARD_TYPE_F_52M                (1 << 1)
 #define EXT_CSD_CARD_TYPE_F_52M_1_8V   (1 << 2)

Reply via email to