On Sat, September 20, 2014 7:45 pm, Jonathan Gray wrote:
> On Sat, Sep 20, 2014 at 06:01:51PM +0200, Cédric Tessier wrote:
>> 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
>
> These bits do not appear to be reserved.  In your case bit 4
> seems to indicate HS200/200 MHz clock capable.
>
> Bit 5 is HS400/400 MHz clock capable.
>
>> - read sectors count from EXT_CSD
>> - fix sectors count and enable SDHC if High Capacity eMMC is detected
>
> Is the old method of reading the block length still supported
> with emmc and csd ver > 2?  That wasn't the case for normal sd card.
>
> It seems the emmc situation is a bit different as the capacity
> stored in a seperate place.
>
>> +
>> +            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;
>> +                    }
>
> I think this should change to
>
>                       if (sectors > (2u * 1024 * 1024 * 1024) / 512)
>                               sf->flags |= SFF_SDHC;
>                       sf->csd.capacity = sectors;
>
> All csd rev > 2 cards should report valid sectors in the extended space.
>

This seems not to be the case, the EXT_CSD_SEC_COUNT is only valid for
capacities over 2G. I'd use this field only if it's not zero, like freebsd does.

Instead of masking the EXT_CSD_CARD_TYPE field, it may be better to just check
for the relevant bits as in the diff below.

Does this still work for you, Cédric?


Index: sys/dev/sdmmc/sdmmc_mem.c
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdmmc_mem.c,v
retrieving revision 1.19
diff -u -p -r1.19 sdmmc_mem.c
--- sys/dev/sdmmc/sdmmc_mem.c   12 Jul 2014 18:48:52 -0000      1.19
+++ sys/dev/sdmmc/sdmmc_mem.c   21 Sep 2014 12:02:35 -0000
@@ -428,6 +428,7 @@ sdmmc_mem_mmc_init(struct sdmmc_softc *s
        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,18 +440,12 @@ sdmmc_mem_mmc_init(struct sdmmc_softc *s
                        return error;
                }

-               switch (ext_csd[EXT_CSD_CARD_TYPE]) {
-               case EXT_CSD_CARD_TYPE_26M:
-                       speed = 26000;
-                       break;
-               case EXT_CSD_CARD_TYPE_52M:
-               case EXT_CSD_CARD_TYPE_52M_V18:
-               case EXT_CSD_CARD_TYPE_52M_V12:
-               case EXT_CSD_CARD_TYPE_52M_V12_18:
+               if (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_52M) {
                        speed = 52000;
                        hs_timing = 1;
-                       break;
-               default:
+               } else if (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_26M) {
+                       speed = 26000;
+               } else {
                        printf("%s: unknown CARD_TYPE 0x%x\n", DEVNAME(sc),
                            ext_csd[EXT_CSD_CARD_TYPE]);
                }
@@ -487,6 +482,16 @@ sdmmc_mem_mmc_init(struct sdmmc_softc *s
                                printf("%s, HS_TIMING set failed\n", 
DEVNAME(sc));
                                return EINVAL;
                        }
+               }
+
+               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;
+
+               if (sectors != 0) {
+                       sf->flags |= SFF_SDHC;
+                       sf->csd.capacity = sectors;
                }
        }

Index: sys/dev/sdmmc/sdmmcreg.h
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdmmcreg.h,v
retrieving revision 1.5
diff -u -p -r1.5 sdmmcreg.h
--- sys/dev/sdmmc/sdmmcreg.h    12 Sep 2013 11:54:04 -0000      1.5
+++ sys/dev/sdmmc/sdmmcreg.h    21 Sep 2014 12:02:35 -0000
@@ -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)


Reply via email to