Просмотр исходного кода

!559 mmc 模式下添加 high-speed-ddr 模式
Merge pull request !559 from linzhenxing/rt-smart

bernard 3 лет назад
Родитель
Сommit
ca9494fda6

+ 3 - 2
components/drivers/include/drivers/mmcsd_card.h

@@ -150,10 +150,11 @@ struct rt_mmcsd_card {
 #define CARD_TYPE_SDIO_COMBO            3 /* SD combo (IO+mem) card */
 
 	rt_uint16_t flags;
-#define CARD_FLAG_HIGHSPEED  (1 << 0)   /* SDIO bus speed 50MHz */
+#define CARD_FLAG_HIGHSPEED  (1 << 0)   /* SDIO bus speed 50MHz sdr*/
 #define CARD_FLAG_SDHC       (1 << 1)   /* SDHC card */
 #define CARD_FLAG_SDXC       (1 << 2)   /* SDXC card */
-
+#define CARD_FLAG_HIGHSPEED_DDR  (1 << 3)   /*HIGH SPEED DDR*/
+#define CARD_FLAG_HS200      (1 << 4)   /* BUS SPEED 200mHz*/
 	struct rt_sd_scr	scr;
 	struct rt_mmcsd_csd	csd;
 	rt_uint32_t     hs_max_data_rate;  /* max data transfer rate in high speed mode */

+ 2 - 1
components/drivers/include/drivers/mmcsd_cmd.h

@@ -37,7 +37,8 @@ extern "C" {
 #define SET_BLOCKLEN         16   /* ac   [31:0] block len   R1  */
 #define READ_SINGLE_BLOCK    17   /* adtc [31:0] data addr   R1  */
 #define READ_MULTIPLE_BLOCK  18   /* adtc [31:0] data addr   R1  */
-
+#define SEND_TUNING_BLOCK    19   /* adtc                    R1 */
+#define SEND_TUNING_BLOCK_HS200 21 /* adtc R1*/
   /* class 3 */
 #define WRITE_DAT_UNTIL_STOP 20   /* adtc [31:0] data addr   R1  */
 

+ 1 - 0
components/drivers/include/drivers/mmcsd_core.h

@@ -228,6 +228,7 @@ void mmcsd_set_chip_select(struct rt_mmcsd_host *host, rt_int32_t mode);
 void mmcsd_set_clock(struct rt_mmcsd_host *host, rt_uint32_t clk);
 void mmcsd_set_bus_mode(struct rt_mmcsd_host *host, rt_uint32_t mode);
 void mmcsd_set_bus_width(struct rt_mmcsd_host *host, rt_uint32_t width);
+void mmcsd_set_timing(struct rt_mmcsd_host *host, rt_uint32_t timing);
 void mmcsd_set_data_timeout(struct rt_mmcsd_data *data, const struct rt_mmcsd_card *card);
 rt_uint32_t mmcsd_select_voltage(struct rt_mmcsd_host *host, rt_uint32_t ocr);
 void mmcsd_change(struct rt_mmcsd_host *host);

+ 17 - 1
components/drivers/include/drivers/mmcsd_host.h

@@ -46,6 +46,19 @@ struct rt_mmcsd_io_cfg {
 #define MMCSD_BUS_WIDTH_4       2
 #define MMCSD_BUS_WIDTH_8       3
 
+	unsigned char	timing;			/* timing specification used */
+
+#define MMCSD_TIMING_LEGACY	0
+#define MMCSD_TIMING_MMC_HS	1
+#define MMCSD_TIMING_SD_HS	2
+#define MMCSD_TIMING_UHS_SDR12	3
+#define MMCSD_TIMING_UHS_SDR25	4
+#define MMCSD_TIMING_UHS_SDR50	5
+#define MMCSD_TIMING_UHS_SDR104	6
+#define MMCSD_TIMING_UHS_DDR50	7
+#define MMCSD_TIMING_MMC_DDR52	8
+#define MMCSD_TIMING_MMC_HS200	9
+#define MMCSD_TIMING_MMC_HS400	10
 };
 
 struct rt_mmcsd_host;
@@ -56,6 +69,7 @@ struct rt_mmcsd_host_ops {
     void (*set_iocfg)(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg);
     rt_int32_t (*get_card_status)(struct rt_mmcsd_host *host);
     void (*enable_sdio_irq)(struct rt_mmcsd_host *host, rt_int32_t en);
+    void (*execute_tuning)(struct rt_mmcsd_host *host, rt_int32_t opcode);
 };
 
 struct rt_mmcsd_host {
@@ -90,7 +104,9 @@ struct rt_mmcsd_host {
 #define MMCSD_HOST_IS_SPI   (1 << 3)
 #define controller_is_spi(host) (host->flags & MMCSD_HOST_IS_SPI)
 #define MMCSD_SUP_SDIO_IRQ  (1 << 4)    /* support signal pending SDIO IRQs */
-#define MMCSD_SUP_HIGHSPEED (1 << 5)    /* support high speed */
+#define MMCSD_SUP_HIGHSPEED (1 << 5)    /* support high speed SDR*/
+#define MMCSD_SUP_HIGHSPEED_DDR (1 << 6)/* HIGH SPEED DDR*/
+#define MMCSD_SUP_HS200     (1 << 7)
 
     rt_uint32_t max_seg_size;   /* maximum size of one dma segment */
     rt_uint32_t max_dma_segs;   /* maximum number of dma segments in one request */

+ 111 - 75
components/drivers/sdio/mmc.c

@@ -181,16 +181,25 @@ static int mmc_get_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t **new_ext_csd)
  */
 static int mmc_parse_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd)
 {
-  rt_uint64_t card_capacity = 0;
-
-  if(card == RT_NULL || ext_csd == RT_NULL)
-  {
-    LOG_E("emmc parse ext csd fail, invaild args");
-    return -1;
-  }
+    rt_uint64_t card_capacity = 0;
+    struct rt_mmcsd_host *host;
+    if(card == RT_NULL || ext_csd == RT_NULL)
+    {
+        LOG_E("emmc parse ext csd fail, invaild args");
+        return -1;
+    }
 
-  card->flags |=  CARD_FLAG_HIGHSPEED;
-  card->hs_max_data_rate = 52000000;
+    host = card->host;
+    if (host->flags & MMCSD_SUP_HIGHSPEED_DDR)
+    {
+        card->flags |=  CARD_FLAG_HIGHSPEED_DDR;
+        card->hs_max_data_rate = 52000000;    
+    }
+    else
+    {
+        card->flags |=  CARD_FLAG_HIGHSPEED;
+        card->hs_max_data_rate = 52000000;       
+    }
 
   card_capacity = *((rt_uint32_t *)&ext_csd[EXT_CSD_SEC_CNT]);
   card->card_sec_cnt = card_capacity;
@@ -289,82 +298,101 @@ out:
  */
 static int mmc_select_bus_width(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd)
 {
-  rt_uint32_t ext_csd_bits[] = {
-    EXT_CSD_BUS_WIDTH_8,
-    EXT_CSD_BUS_WIDTH_4,
-    EXT_CSD_BUS_WIDTH_1
-  };
-  rt_uint32_t bus_widths[] = {
-    MMCSD_BUS_WIDTH_8,
-    MMCSD_BUS_WIDTH_4,
-    MMCSD_BUS_WIDTH_1
-  };
-  struct rt_mmcsd_host *host = card->host;
-  unsigned idx, bus_width = 0;
-  int err = 0;
+    rt_uint32_t ext_csd_bits[][2] =
+    {
+        {EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8},
+        {EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4},
+        {EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1},
+    };
+    rt_uint32_t bus_widths[] =
+    {
+        MMCSD_BUS_WIDTH_8,
+        MMCSD_BUS_WIDTH_4,
+        MMCSD_BUS_WIDTH_1
+    };
+    struct rt_mmcsd_host *host = card->host;
+    unsigned idx, bus_width = 0;
+    int err = 0, ddr = 0;
 
   if (GET_BITS(card->resp_csd, 122, 4) < 4)
      return 0;
 
-  /*
-  * Unlike SD, MMC cards dont have a configuration register to notify
-  * supported bus width. So bus test command should be run to identify
-  * the supported bus width or compare the ext csd values of current
-  * bus width and ext csd values of 1 bit mode read earlier.
-  */
-  for (idx = 0; idx < sizeof(bus_widths)/sizeof(rt_uint32_t); idx++) {
+    if (card->flags & CARD_FLAG_HIGHSPEED_DDR)
+    {
+        ddr = 2;
+    }
     /*
-    * Host is capable of 8bit transfer, then switch
-    * the device to work in 8bit transfer mode. If the
-    * mmc switch command returns error then switch to
-    * 4bit transfer mode. On success set the corresponding
-    * bus width on the host. Meanwhile, mmc core would
-    * bail out early if corresponding bus capable wasn't
-    * set by drivers.
+    * Unlike SD, MMC cards dont have a configuration register to notify
+    * supported bus width. So bus test command should be run to identify
+    * the supported bus width or compare the ext csd values of current
+    * bus width and ext csd values of 1 bit mode read earlier.
     */
+    for (idx = 0; idx < sizeof(bus_widths)/sizeof(rt_uint32_t); idx++)
+    {
+        /*
+        * Host is capable of 8bit transfer, then switch
+        * the device to work in 8bit transfer mode. If the
+        * mmc switch command returns error then switch to
+        * 4bit transfer mode. On success set the corresponding
+        * bus width on the host. Meanwhile, mmc core would
+        * bail out early if corresponding bus capable wasn't
+        * set by drivers.
+        */
+        bus_width = bus_widths[idx];
+        if (bus_width == MMCSD_BUS_WIDTH_1)
+        {
+            ddr = 0;
+        }
+
+        err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                        EXT_CSD_BUS_WIDTH,
+                        ext_csd_bits[idx][0]);
+
+        if (err)
+            continue;
+        
+        mmcsd_set_bus_width(host, bus_width);
+        err = mmc_compare_ext_csds(card, ext_csd, bus_width);
+        if (!err)
+        {
+            break;
+        }
+        else
+        {
+            switch(ext_csd_bits[idx][0])
+            {
+            case 0:
+                LOG_E("switch to bus width 1 bit failed!");
+                break;
+            case 1:
+                LOG_E("switch to bus width 4 bit failed!");
+                break;
+            case 2:
+                LOG_E("switch to bus width 8 bit failed!");
+                break;
+            default:
+              break;
+            }
+        }
+    }
 
-    if (!(((host->flags & MMCSD_BUSWIDTH_8) &&
-      ext_csd_bits[idx] == EXT_CSD_BUS_WIDTH_8) ||
-         ((host->flags & MMCSD_BUSWIDTH_4) &&
-      ext_csd_bits[idx] == EXT_CSD_BUS_WIDTH_4) ||
-      !(ext_csd_bits[idx] == EXT_CSD_BUS_WIDTH_8)))
+    if (!err && ddr)
     {
-         continue;      
+        err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                        EXT_CSD_BUS_WIDTH,
+                        ext_csd_bits[idx][1]);
     }
 
-    err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                     EXT_CSD_BUS_WIDTH,
-                     ext_csd_bits[idx]);
-    if (err)
-      continue;
-    err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                     EXT_CSD_HS_TIMING,
-                     1);
+    if (!err)
+    {
+        if (card->flags & (CARD_FLAG_HIGHSPEED | CARD_FLAG_HIGHSPEED_DDR))
+        {
 
-    if (err)
-      continue;
-    bus_width = bus_widths[idx];
-    mmcsd_set_bus_width(host, bus_width);
-    err = mmc_compare_ext_csds(card, ext_csd, bus_width);
-    if (!err) {
-      err = bus_width;
-      break;
-    } else {
-      switch(ext_csd_bits[idx]){
-          case 0:
-            LOG_E("switch to bus width 1 bit failed!");
-            break;
-          case 1:
-            LOG_E("switch to bus width 4 bit failed!");
-            break;
-          case 2:
-            LOG_E("switch to bus width 8 bit failed!");
-            break;
-          default:
-            break;
-      }
+            err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                            EXT_CSD_HS_TIMING,
+                            1);      
+        }
     }
-  }
 
   return err;
 }
@@ -520,14 +548,22 @@ static rt_int32_t mmcsd_mmc_init_card(struct rt_mmcsd_host *host,
         card->flags |= CARD_FLAG_SDHC;
 
     /* set bus speed */
-    if (card->flags & CARD_FLAG_HIGHSPEED)
+    if (card->flags & (CARD_FLAG_HIGHSPEED | CARD_FLAG_HIGHSPEED_DDR))
         max_data_rate = card->hs_max_data_rate;
     else
         max_data_rate = card->max_data_rate;
 
     /*switch bus width and bus mode*/
     mmc_select_bus_width(card, ext_csd);
-
+    if (card->flags & CARD_FLAG_HIGHSPEED_DDR)
+    {
+        mmcsd_set_timing(host, MMCSD_TIMING_MMC_DDR52);       
+    }
+    else
+    {
+        mmcsd_set_timing(host, MMCSD_TIMING_UHS_SDR50);          
+    }
+    
     mmcsd_set_clock(host, max_data_rate);
     host->card = card;
 

+ 6 - 0
components/drivers/sdio/mmcsd_core.c

@@ -438,6 +438,12 @@ void mmcsd_set_bus_width(struct rt_mmcsd_host *host, rt_uint32_t width)
     mmcsd_set_iocfg(host);
 }
 
+void mmcsd_set_timing(struct rt_mmcsd_host *host, rt_uint32_t timing)
+{
+    host->io_cfg.timing = timing;
+    mmcsd_set_iocfg(host);   
+}
+
 void mmcsd_set_data_timeout(struct rt_mmcsd_data       *data,
                             const struct rt_mmcsd_card *card)
 {