[msm_shared/mmc]: Set high speed for sD card properly

Setting high speed mode for sD card properly.Without this, setting bus
width to 4bit was failing in class 2 sD card.

Decode CID fields for sD card properly as we use PSN for serial number
in fastboot and adb enumeration.

Change-Id: I63ca4e7bc77c274f9d7d6074a327ae0e483ba5f3
diff --git a/platform/msm_shared/include/mmc.h b/platform/msm_shared/include/mmc.h
index bd6c671..5bcd963 100755
--- a/platform/msm_shared/include/mmc.h
+++ b/platform/msm_shared/include/mmc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.

+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.

 

  * Redistribution and use in source and binary forms, with or without

  * modification, are permitted provided that the following conditions are

@@ -392,7 +392,7 @@
 #define MMC_BOOT_SD_NEG_OCR               0x00FF8000

 #define MMC_BOOT_SD_HC_HCS                0x40000000

 #define MMC_BOOT_SD_DEV_READY             0x80000000

-#define MMC_BOOT_SD_SWITCH_HS             0x80FFFF01

+#define MMC_BOOT_SD_SWITCH_HS             0x80FFFFF1

 

 /* Data structure definitions */

 struct mmc_boot_command

diff --git a/platform/msm_shared/mmc.c b/platform/msm_shared/mmc.c
index d293c05..3cb8a51 100644
--- a/platform/msm_shared/mmc.c
+++ b/platform/msm_shared/mmc.c
@@ -77,10 +77,17 @@
 struct mbr_entry mbr[MAX_PARTITIONS];

 unsigned mmc_partition_count = 0;

 

+unsigned int mmc_read (unsigned long long data_addr, unsigned int* out,

+                       unsigned int data_len);

 static void mbr_fill_name (struct mbr_entry *mbr_ent, unsigned int type);

-unsigned int mmc_read (unsigned long long data_addr, unsigned int* out, unsigned int data_len);

-static unsigned int mmc_wp(unsigned int addr, unsigned int size, unsigned char set_clear_wp);

-static unsigned int mmc_boot_send_ext_cmd (struct mmc_boot_card* card, unsigned char* buf);

+static unsigned int mmc_wp(unsigned int addr, unsigned int size,

+                           unsigned char set_clear_wp);

+static unsigned int mmc_boot_send_ext_cmd (struct mmc_boot_card* card,

+                                           unsigned char* buf);

+static unsigned int mmc_boot_read_reg(struct mmc_boot_card *card,

+                                      unsigned int data_len,

+                                      unsigned int command, unsigned int addr,

+                                      unsigned int *out);

 

 unsigned int SWAP_ENDIAN(unsigned int val)

 {

@@ -447,20 +454,44 @@
     }

 

     mmc_sizeof = sizeof( unsigned int ) * 8;

-    mmc_cid.mid = UNPACK_BITS( raw_cid, 120, 8, mmc_sizeof );

-    mmc_cid.oid = UNPACK_BITS( raw_cid, 104, 16, mmc_sizeof );

 

-    for( i = 0; i < 6; i++ )

+    if( (card->type == MMC_BOOT_TYPE_SDHC) ||  (card->type == MMC_BOOT_TYPE_STD_SD))

     {

-        mmc_cid.pnm[i] = (unsigned char) UNPACK_BITS(raw_cid, \

-                            (104 - 8 * (i+1)), 8, mmc_sizeof );

-    }

-    mmc_cid.pnm[6] = 0;

+        mmc_cid.mid = UNPACK_BITS( raw_cid, 120, 8, mmc_sizeof );

+        mmc_cid.oid = UNPACK_BITS( raw_cid, 104, 16, mmc_sizeof );

 

-    mmc_cid.prv = UNPACK_BITS( raw_cid, 48, 8, mmc_sizeof );

-    mmc_cid.psn = UNPACK_BITS( raw_cid, 16, 32, mmc_sizeof );

-    mmc_cid.month = UNPACK_BITS( raw_cid, 12, 4, mmc_sizeof );

-    mmc_cid.year = UNPACK_BITS( raw_cid, 8, 4, mmc_sizeof );

+        for( i = 0; i < 5; i++ )

+        {

+            mmc_cid.pnm[i] = (unsigned char) UNPACK_BITS(raw_cid, \

+                                (104 - 8 * (i+1)), 8, mmc_sizeof );

+        }

+        mmc_cid.pnm[5] = 0;

+        mmc_cid.pnm[6] = 0;

+

+        mmc_cid.prv = UNPACK_BITS( raw_cid, 56, 8, mmc_sizeof );

+        mmc_cid.psn = UNPACK_BITS( raw_cid, 24, 32, mmc_sizeof );

+        mmc_cid.month = UNPACK_BITS( raw_cid, 8, 4, mmc_sizeof );

+        mmc_cid.year = UNPACK_BITS( raw_cid, 12, 8, mmc_sizeof );

+        mmc_cid.year += 2000;

+    }

+    else

+    {

+        mmc_cid.mid = UNPACK_BITS( raw_cid, 120, 8, mmc_sizeof );

+        mmc_cid.oid = UNPACK_BITS( raw_cid, 104, 16, mmc_sizeof );

+

+        for( i = 0; i < 6; i++ )

+        {

+            mmc_cid.pnm[i] = (unsigned char) UNPACK_BITS(raw_cid, \

+                                (104 - 8 * (i+1)), 8, mmc_sizeof );

+        }

+        mmc_cid.pnm[6] = 0;

+

+        mmc_cid.prv = UNPACK_BITS( raw_cid, 48, 8, mmc_sizeof );

+        mmc_cid.psn = UNPACK_BITS( raw_cid, 16, 32, mmc_sizeof );

+        mmc_cid.month = UNPACK_BITS( raw_cid, 8, 4, mmc_sizeof );

+        mmc_cid.year = UNPACK_BITS( raw_cid, 12, 4, mmc_sizeof );

+        mmc_cid.year += 1997;

+    }

 

     /* save it in card database */

     memcpy( ( struct mmc_boot_cid * )&card->cid, \

@@ -473,7 +504,7 @@
     dprintf(INFO, "Product Name: %s\n", mmc_cid.pnm );

     dprintf(INFO, "Product revision: %d.%d\n", (mmc_cid.prv >> 4), (mmc_cid.prv & 0xF) );

     dprintf(INFO, "Product serial number: %X\n", mmc_cid.psn );

-    dprintf(INFO, "Manufacturing date: %d %d\n", mmc_cid.month, mmc_cid.year + 1997 );

+    dprintf(INFO, "Manufacturing date: %d %d\n", mmc_cid.month, mmc_cid.year );

 

     return MMC_BOOT_E_SUCCESS;

 }

@@ -2203,7 +2234,14 @@
     /* Send ACMD6 to set bus width */

     cmd.cmd_index = ACMD6_SET_BUS_WIDTH;

     /* 10 => 4 bit wide */

-    cmd.argument = (1<<1);

+    if ( width == MMC_BOOT_BUS_WIDTH_1_BIT )

+    {

+        cmd.argument = 0;

+    }

+    else if (width == MMC_BOOT_BUS_WIDTH_4_BIT )

+    {

+        cmd.argument = (1<<1);

+    }

     cmd.cmd_type = MMC_BOOT_CMD_ADDRESS;

     cmd.resp_type = MMC_BOOT_RESP_R1;

 

@@ -2238,20 +2276,13 @@
 

 static unsigned int mmc_boot_set_sd_hs(struct mmc_boot_host* host, struct mmc_boot_card* card)

 {

-    struct mmc_boot_command cmd;

+    unsigned char sw_buf[64];

     unsigned int mmc_ret;

 

-    memset( (struct mmc_boot_command *)&cmd, 0,

-            sizeof(struct mmc_boot_command) );

-

-    /* Send CMD6 function mode 1 to set high speed */

-    /* Not using mode 0 to read current consumption */

-    cmd.cmd_index = CMD6_SWITCH_FUNC;

-    cmd.argument = MMC_BOOT_SD_SWITCH_HS;

-    cmd.cmd_type = MMC_BOOT_CMD_ADDRESS;

-    cmd.resp_type = MMC_BOOT_RESP_R1;

-

-    mmc_ret = mmc_boot_send_command(&cmd);

+    /* CMD6 is a data transfer command. sD card returns 512 bits of data*/

+    /* Refer 4.3.10 of sD card specification 3.0 */

+    mmc_ret = mmc_boot_read_reg(card,64,CMD6_SWITCH_FUNC,MMC_BOOT_SD_SWITCH_HS,

+                               (unsigned int *)&sw_buf);

 

     if( mmc_ret != MMC_BOOT_E_SUCCESS )

     {

@@ -2310,6 +2341,8 @@
 

     if(card->type == MMC_BOOT_TYPE_SDHC || card->type == MMC_BOOT_TYPE_STD_SD)

     {

+        /* Setting sD card to high speed without checking card's capability.

+           Cards that do not support high speed may fail to boot */

         mmc_return = mmc_boot_set_sd_hs(host, card);

         if(mmc_return != MMC_BOOT_E_SUCCESS)

         {

@@ -2319,7 +2352,14 @@
         mmc_return = mmc_boot_set_sd_bus_width(card, MMC_BOOT_BUS_WIDTH_4_BIT);

         if(mmc_return != MMC_BOOT_E_SUCCESS)

         {

-            return mmc_return;

+            dprintf(CRITICAL,"Couldn't set 4bit mode for sD card\n");

+            mmc_return = mmc_boot_set_sd_bus_width(card, MMC_BOOT_BUS_WIDTH_1_BIT);

+            if(mmc_return != MMC_BOOT_E_SUCCESS)

+            {

+                dprintf(CRITICAL, "Error No.%d: Failed in setting bus width!\n",

+                        mmc_return);

+                return mmc_return;

+            }

         }

     }

     else

@@ -2503,7 +2543,7 @@
     mmc_ret = mmc_boot_init_and_identify_cards( &mmc_host, &mmc_card );

     if( mmc_ret != MMC_BOOT_E_SUCCESS )

     {

-        dprintf(CRITICAL,  "MMC Boot: Failure detecting MMC card!!!\n" );

+        dprintf(CRITICAL, "MMC Boot: Failed detecting MMC/SDC @ slot%d\n",slot);

         return MMC_BOOT_E_FAILURE;

     }