Browse Source

!579 mmc hs200
Merge pull request !579 from heyuanjie87/hs200

bernard 2 years ago
parent
commit
f6e90b576f

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

@@ -32,6 +32,7 @@ struct rt_mmcsd_data {
 	rt_uint32_t  blksize;
 	rt_uint32_t  blks;
 	rt_uint32_t  *buf;
+	void *dma_addr;
 	rt_int32_t  err;
 	rt_uint32_t  flags;
 #define DATA_DIR_WRITE	(1 << 0)
@@ -45,6 +46,7 @@ struct rt_mmcsd_data {
 
 	rt_uint32_t  timeout_ns;
 	rt_uint32_t  timeout_clks;
+	long host_cookie;	/* host driver private data */
 };
 
 struct rt_mmcsd_cmd {
@@ -96,6 +98,7 @@ struct rt_mmcsd_cmd {
 	
 	rt_int32_t  retries;	/* max number of retries */
 	rt_int32_t  err;
+    unsigned int busy_timeout;	/* busy detect timeout in ms */
 
 	struct rt_mmcsd_data *data;
 	struct rt_mmcsd_req	*mrq;		/* associated request */
@@ -105,6 +108,9 @@ struct rt_mmcsd_req {
 	struct rt_mmcsd_data  *data;
 	struct rt_mmcsd_cmd   *cmd;
 	struct rt_mmcsd_cmd   *stop;
+	struct rt_mmcsd_cmd	*sbc;		/* SET_BLOCK_COUNT for multiblock */	
+	/* Allow other commands during this ongoing data transfer or busy wait */
+	int cap_cmd_during_tfr;
 };
 
 /*the following is response bit*/
@@ -210,6 +216,7 @@ rt_inline rt_uint32_t __rt_fls(rt_uint32_t val)
 #define MMCSD_HOST_PLUGED       0
 #define MMCSD_HOST_UNPLUGED     1
 
+rt_int32_t mmcsd_excute_tuning(struct rt_mmcsd_card *card);
 int mmcsd_wait_cd_changed(rt_int32_t timeout);
 void mmcsd_host_lock(struct rt_mmcsd_host *host);
 void mmcsd_host_unlock(struct rt_mmcsd_host *host);
@@ -233,6 +240,7 @@ void mmcsd_set_data_timeout(struct rt_mmcsd_data *data, const struct rt_mmcsd_ca
 rt_uint32_t mmcsd_select_voltage(struct rt_mmcsd_host *host, rt_uint32_t ocr);
 void mmcsd_change(struct rt_mmcsd_host *host);
 void mmcsd_detect(void *param);
+void mmcsd_host_init(struct rt_mmcsd_host *host);
 struct rt_mmcsd_host *mmcsd_alloc_host(void);
 void mmcsd_free_host(struct rt_mmcsd_host *host);
 int rt_mmcsd_core_init(void);

+ 22 - 3
components/drivers/include/drivers/mmcsd_host.h

@@ -59,6 +59,19 @@ struct rt_mmcsd_io_cfg {
 #define MMCSD_TIMING_MMC_DDR52	8
 #define MMCSD_TIMING_MMC_HS200	9
 #define MMCSD_TIMING_MMC_HS400	10
+
+	unsigned char	drv_type;		/* driver type (A, B, C, D) */
+
+#define MMCSD_SET_DRIVER_TYPE_B	0
+#define MMCSD_SET_DRIVER_TYPE_A	1
+#define MMCSD_SET_DRIVER_TYPE_C	2
+#define MMCSD_SET_DRIVER_TYPE_D	3
+
+	unsigned char	signal_voltage;
+
+#define MMCSD_SIGNAL_VOLTAGE_330	0
+#define MMCSD_SIGNAL_VOLTAGE_180	1
+#define MMCSD_SIGNAL_VOLTAGE_120	2
 };
 
 struct rt_mmcsd_host;
@@ -69,7 +82,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);
+    rt_int32_t (*execute_tuning)(struct rt_mmcsd_host *host, rt_int32_t opcode);
 };
 
 struct rt_mmcsd_host {
@@ -105,8 +118,14 @@ struct rt_mmcsd_host {
 #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 SDR*/
-#define MMCSD_SUP_HIGHSPEED_DDR (1 << 6)/* HIGH SPEED DDR*/
-#define MMCSD_SUP_HS200     (1 << 7)
+#define MMCSD_SUP_DDR_3V3    (1 << 6)
+#define MMCSD_SUP_DDR_1V8    (1 << 7)
+#define MMCSD_SUP_DDR_1V2    (1 << 8)
+#define MMCSD_SUP_HIGHSPEED_DDR (MMCSD_SUP_DDR_3V3 | MMCSD_SUP_DDR_1V8 | MMCSD_SUP_DDR_1V2)/* HIGH SPEED DDR*/
+#define MMCSD_SUP_HS200_1V8  (1 << 9)
+#define MMCSD_SUP_HS200_1V2  (1 << 10)
+#define MMCSD_SUP_HS200     (MMCSD_SUP_HS200_1V2 | MMCSD_SUP_HS200_1V8) /* hs200 sdr */
+#define MMCSD_SUP_NONREMOVABLE	(1 << 11)
 
     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 */

+ 68 - 24
components/drivers/sdio/block_dev.c

@@ -41,6 +41,65 @@ struct mmcsd_blk_device
 #endif
 #define RT_GPT_PARTITION_MAX 128
 
+static int __send_status(struct rt_mmcsd_card *card, rt_uint32_t *status, unsigned retries)
+{
+    int err;
+    struct rt_mmcsd_cmd cmd;
+
+    cmd.busy_timeout = 0;
+    cmd.cmd_code = SEND_STATUS;
+    cmd.arg = card->rca << 16;
+    cmd.flags = RESP_R1 | CMD_AC;
+    err = mmcsd_send_cmd(card->host, &cmd, retries);
+	if (err)
+		return err;
+
+	if (status)
+		*status = cmd.resp[0];
+
+    return 0;
+}
+
+static int card_busy_detect(struct rt_mmcsd_card *card, unsigned int timeout_ms,
+                            rt_uint32_t *resp_errs)
+{
+    int timeout = rt_tick_from_millisecond(timeout_ms);
+    int err = 0;
+    rt_uint32_t status;
+    rt_tick_t start;
+
+    start = rt_tick_get();
+    do
+    {
+        rt_bool_t out = (int)(rt_tick_get() - start) > timeout;
+
+        err = __send_status(card, &status, 5);
+        if (err)
+        {
+            LOG_E("error %d requesting status", err);
+            return err;
+        }
+
+        /* Accumulate any response error bits seen */
+        if (resp_errs)
+            *resp_errs |= status;
+
+        if (out)
+        {
+            LOG_E("wait card busy timeout");
+            return -RT_ETIMEOUT;
+        }
+        /*
+         * Some cards mishandle the status bits,
+         * so make sure to check both the busy
+         * indication and the card state.
+         */
+    } while (!(status & R1_READY_FOR_DATA) ||
+             (R1_CURRENT_STATE(status) == 7));
+
+    return err;
+}
+
 rt_int32_t mmcsd_num_wr_blocks(struct rt_mmcsd_card *card)
 {
     rt_int32_t err;
@@ -151,45 +210,30 @@ static rt_err_t rt_mmcsd_req_blk(struct rt_mmcsd_card *card,
         w_cmd = WRITE_BLOCK;
     }
 
+    if (!controller_is_spi(card->host) && (card->flags & 0x8000))
+    {
+        /* last request is WRITE,need check busy */
+        card_busy_detect(card, 10000, RT_NULL);
+    }
+
     if (!dir)
     {
         cmd.cmd_code = r_cmd;
         data.flags |= DATA_DIR_READ;
+        card->flags &= 0x7fff;
     }
     else
     {
         cmd.cmd_code = w_cmd;
         data.flags |= DATA_DIR_WRITE;
+        card->flags |= 0x8000;
     }
 
     mmcsd_set_data_timeout(&data, card);
     data.buf = buf;
+ 
     mmcsd_send_request(host, &req);
 
-    if (!controller_is_spi(card->host) && dir != 0)
-    {
-        do
-        {
-            rt_int32_t err;
-
-            cmd.cmd_code = SEND_STATUS;
-            cmd.arg = card->rca << 16;
-            cmd.flags = RESP_R1 | CMD_AC;
-            err = mmcsd_send_cmd(card->host, &cmd, 5);
-            if (err)
-            {
-                LOG_E("error %d requesting status", err);
-                break;
-            }
-            /*
-             * Some cards mishandle the status bits,
-             * so make sure to check both the busy
-             * indication and the card state.
-             */
-         } while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||
-            (R1_CURRENT_STATE(cmd.resp[0]) == 7));
-    }
-
     mmcsd_host_unlock(host);
 
     if (cmd.err || data.err || stop.err)

+ 57 - 8
components/drivers/sdio/mmc.c

@@ -190,7 +190,12 @@ static int mmc_parse_ext_csd(struct rt_mmcsd_card *card, rt_uint8_t *ext_csd)
     }
 
     host = card->host;
-    if (host->flags & MMCSD_SUP_HIGHSPEED_DDR)
+    if (host->flags & MMCSD_SUP_HS200)
+    {
+        card->flags |=  CARD_FLAG_HS200;
+        card->hs_max_data_rate = 200000000; 
+    }
+    else if (host->flags & MMCSD_SUP_HIGHSPEED_DDR)
     {
         card->flags |=  CARD_FLAG_HIGHSPEED_DDR;
         card->hs_max_data_rate = 52000000;    
@@ -456,6 +461,45 @@ static rt_err_t mmc_set_card_addr(struct rt_mmcsd_host *host, rt_uint32_t rca)
   return 0;
 }
 
+static int mmc_select_hs200(struct rt_mmcsd_card *card)
+{
+  int ret;
+
+  ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                     EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200);
+  if (ret)
+    return ret;
+
+  mmcsd_set_timing(card->host, MMCSD_TIMING_MMC_HS200);
+  mmcsd_set_clock(card->host, 200000000);
+
+  ret = mmcsd_excute_tuning(card);
+
+  return ret;
+}
+
+static int mmc_select_timing(struct rt_mmcsd_card *card)
+{
+  int ret = 0;
+
+  if (card->flags & CARD_FLAG_HS200)
+  {
+    ret = mmc_select_hs200(card);
+  }
+  else if (card->flags & CARD_FLAG_HIGHSPEED_DDR)
+  {
+    mmcsd_set_timing(card->host, MMCSD_TIMING_MMC_DDR52);
+    mmcsd_set_clock(card->host, card->hs_max_data_rate);
+  }
+  else
+  {
+    mmcsd_set_timing(card->host, MMCSD_TIMING_UHS_SDR50);
+    mmcsd_set_clock(card->host, card->hs_max_data_rate);
+  }
+
+  return ret;
+}
+
 static rt_int32_t mmcsd_mmc_init_card(struct rt_mmcsd_host *host,
                                      rt_uint32_t           ocr)
 {
@@ -554,22 +598,27 @@ static rt_int32_t mmcsd_mmc_init_card(struct rt_mmcsd_host *host,
         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)
+    err = mmc_select_bus_width(card, ext_csd);
+    if (err)
     {
-        mmcsd_set_timing(host, MMCSD_TIMING_MMC_DDR52);       
+        LOG_E("mmc select buswidth fail");
+        goto err0;
     }
-    else
+
+    err = mmc_select_timing(card);
+    if (err)
     {
-        mmcsd_set_timing(host, MMCSD_TIMING_UHS_SDR50);          
+        LOG_E("mmc select timing fail");
+        goto err0;
     }
-    
-    mmcsd_set_clock(host, max_data_rate);
+
     host->card = card;
 
     rt_free(ext_csd);
     return 0;
 
+err0:
+    rt_free(ext_csd);
 err1:
     rt_free(card);
 err:

+ 30 - 9
components/drivers/sdio/mmcsd_core.c

@@ -696,6 +696,19 @@ void mmcsd_detect(void *param)
     }
 }
 
+void mmcsd_host_init(struct rt_mmcsd_host *host)
+{
+    rt_memset(host, 0, sizeof(struct rt_mmcsd_host));
+    strncpy(host->name, "sd", sizeof(host->name)-1);
+    host->max_seg_size = 65535;
+    host->max_dma_segs = 1;
+    host->max_blk_size = 512;
+    host->max_blk_count = 4096;
+
+    rt_mutex_init(&host->bus_lock, "sd_bus_lock", RT_IPC_FLAG_FIFO);
+    rt_sem_init(&host->sem_ack, "sd_ack", 0, RT_IPC_FLAG_FIFO);
+}
+
 struct rt_mmcsd_host *mmcsd_alloc_host(void)
 {
     struct rt_mmcsd_host *host;
@@ -708,15 +721,7 @@ struct rt_mmcsd_host *mmcsd_alloc_host(void)
         return RT_NULL;
     }
 
-    rt_memset(host, 0, sizeof(struct rt_mmcsd_host));
-    strncpy(host->name, "sd", sizeof(host->name)-1);
-    host->max_seg_size = 65535;
-    host->max_dma_segs = 1;
-    host->max_blk_size = 512;
-    host->max_blk_count = 4096;
-
-    rt_mutex_init(&host->bus_lock, "sd_bus_lock", RT_IPC_FLAG_FIFO);
-    rt_sem_init(&host->sem_ack, "sd_ack", 0, RT_IPC_FLAG_FIFO);
+    mmcsd_host_init(host);
 
     return host;
 }
@@ -728,6 +733,22 @@ void mmcsd_free_host(struct rt_mmcsd_host *host)
     rt_free(host);
 }
 
+rt_int32_t mmcsd_excute_tuning(struct rt_mmcsd_card *card)
+{
+    struct rt_mmcsd_host *host = card->host;
+    rt_int32_t opcode;
+
+    if (!host->ops->execute_tuning)
+        return RT_EOK;
+
+    if (card->card_type == CARD_TYPE_MMC)
+        opcode = SEND_TUNING_BLOCK_HS200;
+    else
+        opcode = SEND_TUNING_BLOCK;
+
+    return host->ops->execute_tuning(host, opcode);;
+}
+
 int rt_mmcsd_core_init(void)
 {
     rt_err_t ret;