最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

mmc: Add support for SDHC cards

Driver crifan 1549浏览 0评论
<a href="http://www.archivesat.com/Linux_kernel_discussion/thread2328642.htm" target="_blank">mmc: Add support for SDHC cards</a>

user name

2006-12-22 18:24:00
Hi all,<br /><br />Thanks to the generous donation of an SDHC card by John Gilmore, and the<br />surprisingly enlightened decision by the SD Card Association to publish<br />useful specs, I've been able to bash out support for SDHC.<br />The changes are not too profound:<br /><br /><strong><font color="#0000ff">i)</font></strong> Add a card flag indicating the card uses block level addressing and check<br />it in the block driver. As we never took advantage of byte-level addressing,<br />this simply involves skipping the block -&gt; byte translation when sending commands.<br /><br /><strong><font color="#0000ff">ii)</font></strong> The layout of the CSD is changed - a set of fields are discarded to make space<br />for a larger C_SIZE. We did not reference any of the discarded fields except those<br />related to the C_SIZE.<br /><br /><strong><font color="#0000ff">iii)</font></strong> Read and write timeouts are fixed values and not calculated from CSD values.<br /><br /><strong><font color="#0000ff">iv)</font></strong> Before invoking SEND_APP_OP_COND, we must invoke the new SEND_IF_COND to inform<br />the card we support SDHC.
I've done some basic read and write tests and everything seems to work fine but one<br />should obviously use caution in case it eats your data.<br /><br />Addendum: Similar spec changes were introduced by the MMC Association in version 4.2<br />to switch to block addressing. We do not have access to the 4.2 spec or even a change<br />summary as we did for 3 -&gt; 4. My guess as to what's changed looks something like the<br />following:<br /><br />i) A new field is added to the ext_csd to store the capacity that cannot be described<br />using existing csd fields.<br /><br />ii) A new field is added to the ext_csd to indicate the need for block addressing.<br /><br />iii) A new write-only field is added to the ext_csd which has to be toggled to tell the<br />card that the host supports block-addressing. But perhaps compatibility requires that<br />a new command be used like for SDHC...<br /><br />If someone has access to the spec and can shed some light on the subject in a legal way,<br />please let us know. Of course, I don't think there are any MMC HC cards on the market<br />yet, but one was announced last month.<br /><br />--phil<br /><br />Signed-off-by: Philipl Langdale &lt;philipl<img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" />overt.org&gt;<br />---<br /><br /> drivers/mmc/mmc.c            |   40<br />+++++++++++++++++++++++++++++++++++-----<br /> drivers/mmc/mmc_block.c      |    4 +++-<br /> include/linux/mmc/card.h     |    3 +++<br /> include/linux/mmc/mmc.h      |    1 +<br /> include/linux/mmc/protocol.h |   13 ++++++++++++-<br /> 5 files changed, 54 insertions(+), 7 deletions(-)<br /><br />diff -urN linux-2.6.19/drivers/mmc/mmc_block.c<br />linux-2.6.19-sdhc/drivers/mmc/mmc_block.c<br />--- linux-2.6.19/drivers/mmc/mmc_block.c 2006-12-21<br />20:29:49.000000000 -0800<br />+++ linux-2.6.19-sdhc/drivers/mmc/mmc_block.c 2006-12-22<br />08:42:56.000000000 -0800<br /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /> -237,7<br />+237,9 <img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><br />   brq.mrq.cmd = &amp;brq.cmd;<br />   brq.mrq.data = &amp;brq.data;<br /><br />-  brq.cmd.arg = req-&gt;sector &lt;&lt; 9;<br />+  brq.cmd.arg = req-&gt;sector;<br />+  if (!mmc_card_blockaddr(card))<br />+   brq.cmd.arg &lt;&lt;= 9;<br />   brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;<br />   brq.data.blksz = 1 &lt;&lt; md-&gt;block_bits;<br />   brq.data.blocks = req-&gt;nr_sectors &gt;&gt;<br />(md-&gt;block_bits - 9);<br />diff -urN linux-2.6.19/drivers/mmc/mmc.c<br />linux-2.6.19-sdhc/drivers/mmc/mmc.c<br />--- linux-2.6.19/drivers/mmc/mmc.c 2006-12-21<br />20:29:49.000000000 -0800<br />+++ linux-2.6.19-sdhc/drivers/mmc/mmc.c 2006-12-22<br />09:57:41.000000000 -0800<br /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /> -289,7<br />+289,10 <img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><br />   else<br />    limit_us = 100000;<br /><br />-  if (timeout_us &gt; limit_us) {<br />+  /*<br />+   * SDHC cards always use these fixed values.<br />+   */<br />+  if (timeout_us &gt; limit_us || mmc_card_blockaddr(card))<br />{<br />    data-&gt;timeout_ns = limit_us * 1000;<br />    data-&gt;timeout_clks = 0;<br />   }<br /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /> -588,12<br />+591,15 <img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><br /><br />  if (mmc_card_sd(card)) {<br />   csd_struct = UNSTUFF_BITS(resp, 126, 2);<br />-  if (csd_struct != 0) {<br />+  if (csd_struct != 0 &amp;&amp; csd_struct != 1) {<br />    printk(&quot;%s: unrecognised CSD structure version<br />%dn&quot;,<br />     mmc_hostname(card-&gt;host), csd_struct);<br />    mmc_card_set_bad(card);<br />    return;<br />   }<br />+  if (csd_struct == 1) {<br />+   mmc_card_set_blockaddr(card);<br />+  }<br /><br />   m = UNSTUFF_BITS(resp, 115, 4);<br />   e = UNSTUFF_BITS(resp, 112, 3);<br /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /> -605,9<br />+611,14 <img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><br />   csd-&gt;max_dtr   = tran_exp[e] * tran_mant[m];<br />   csd-&gt;cmdclass   = UNSTUFF_BITS(resp, 84, 12);<br /><br />-  e = UNSTUFF_BITS(resp, 47, 3);<br />-  m = UNSTUFF_BITS(resp, 62, 12);<br />-  csd-&gt;capacity   = (1 + m) &lt;&lt; (e + 2);<br />+  if (csd_struct == 0) {<br />+   e = UNSTUFF_BITS(resp, 47, 3);<br />+   m = UNSTUFF_BITS(resp, 62, 12);<br />+   csd-&gt;capacity   = (1 + m) &lt;&lt; (e + 2);<br />+  } else if (csd_struct == 1) {<br />+   m = UNSTUFF_BITS(resp, 48, 22);<br />+   csd-&gt;capacity     = (1 + m) &lt;&lt; 10;<br />+  }<br /><br />   csd-&gt;read_blkbits = UNSTUFF_BITS(resp, 80, 4);<br />   csd-&gt;read_partial = UNSTUFF_BITS(resp, 79, 1);<br /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /> -824,6<br />+835,25 <img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><br /> {<br />  struct mmc_command cmd;<br />  int i, err = 0;<br />+ static const u8 test_pattern = 0xAA;<br />+<br />+ /*<br />+  * To support SD 2.0 cards, we must always invoke<br />SD_SEND_IF_COND<br />+  * before SD_APP_OP_COND. This command will harmlessly<br />fail for<br />+  * SD 1.0 and MMC cards (fortunately including MMC 4<br />cards).<br />+  */<br />+ cmd.opcode = SD_SEND_IF_COND;<br />+ cmd.arg = ((host-&gt;ocr_avail &amp; 0xFF8000) != 0)<br />&lt;&lt; 8 | test_pattern;<br />+ cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR;<br />+<br />+ err = mmc_wait_for_cmd(host, &amp;cmd, 0);<br />+ if (err == MMC_ERR_NONE) {<br />+  if ((cmd.resp[0] &amp; 0xFF) != test_pattern) {<br />+   return MMC_ERR_FAILED;<br />+  } else if (ocr != 0) {<br />+   ocr |= 1 &lt;&lt; 30;<br />+  }<br />+ }<br /><br />  cmd.opcode = SD_APP_OP_COND;<br />  cmd.arg = ocr;<br />diff -urN linux-2.6.19/include/linux/mmc/card.h<br />linux-2.6.19-sdhc/include/linux/mmc/card.h<br />--- linux-2.6.19/include/linux/mmc/card.h 2006-12-21<br />20:29:49.000000000 -0800<br />+++ linux-2.6.19-sdhc/include/linux/mmc/card.h 2006-12-22<br />08:42:56.000000000 -0800<br /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /> -71,6<br />+71,7 <img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><br /> #define MMC_STATE_SDCARD (1&lt;&lt;3)  /* is an SD card */<br /> #define MMC_STATE_READONLY (1&lt;&lt;4)  /* card is<br />read-only */<br /> #define MMC_STATE_HIGHSPEED (1&lt;&lt;5)  /* card is in<br />high speed mode */<br />+#define MMC_STATE_BLOCKADDR (1&lt;&lt;6)  /* card uses<br />block-addressing */<br />  u32   raw_cid[4]; /* raw card CID */<br />  u32   raw_csd[4]; /* raw card CSD */<br />  u32   raw_scr[2]; /* raw card SCR */<br /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /> -87,6<br />+88,7 <img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><br /> #define mmc_card_sd(c)  ((c)-&gt;state &amp;<br />MMC_STATE_SDCARD)<br /> #define mmc_card_readonly(c) ((c)-&gt;state &amp;<br />MMC_STATE_READONLY)<br /> #define mmc_card_highspeed(c) ((c)-&gt;state &amp;<br />MMC_STATE_HIGHSPEED)<br />+#define mmc_card_blockaddr(c) ((c)-&gt;state &amp;<br />MMC_STATE_BLOCKADDR)<br /><br /> #define mmc_card_set_present(c) ((c)-&gt;state |=<br />MMC_STATE_PRESENT)<br /> #define mmc_card_set_dead(c) ((c)-&gt;state |=<br />MMC_STATE_DEAD)<br /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /> -94,6<br />+96,7 <img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><br /> #define mmc_card_set_sd(c) ((c)-&gt;state |=<br />MMC_STATE_SDCARD)<br /> #define mmc_card_set_readonly(c) ((c)-&gt;state |=<br />MMC_STATE_READONLY)<br /> #define mmc_card_set_highspeed(c) ((c)-&gt;state |=<br />MMC_STATE_HIGHSPEED)<br />+#define mmc_card_set_blockaddr(c) ((c)-&gt;state |=<br />MMC_STATE_BLOCKADDR)<br /><br /> #define mmc_card_name(c) ((c)-&gt;cid.prod_name)<br /> #define mmc_card_id(c)  ((c)-&gt;dev.bus_id)<br />diff -urN linux-2.6.19/include/linux/mmc/mmc.h<br />linux-2.6.19-sdhc/include/linux/mmc/mmc.h<br />--- linux-2.6.19/include/linux/mmc/mmc.h 2006-11-29<br />13:57:37.000000000 -0800<br />+++ linux-2.6.19-sdhc/include/linux/mmc/mmc.h 2006-12-22<br />08:42:56.000000000 -0800<br /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /> -43,6<br />+43,7 <img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><br /> #define<br />MMC_RSP_R2 (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)<br /> #define MMC_RSP_R3 (MMC_RSP_PRESENT)<br /> #define MMC_RSP_R6 (MMC_RSP_PRESENT|MMC_RSP_CRC)<br />+#define MMC_RSP_R7 (MMC_RSP_PRESENT|MMC_RSP_CRC)<br /><br /> #define mmc_resp_type(cmd) ((cmd)-&gt;flags &amp;<br />(MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RS<br />P_OPCODE))<br /><br />diff -urN linux-2.6.19/include/linux/mmc/protocol.h<br />linux-2.6.19-sdhc/include/linux/mmc/protocol.h<br />--- linux-2.6.19/include/linux/mmc/protocol.h 2006-12-21<br />20:29:49.000000000 -0800<br />+++<br />linux-2.6.19-sdhc/include/linux/mmc/protocol.h 2006-12-22<br />08:42:56.000000000 -0800<br /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /> -79,9<br />+79,12 <img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><br /> #define MMC_GEN_CMD              56   /* adtc [0] RD/WR    <br />     R1  */<br /><br /> /* SD commands                           type  argument    <br />response */<br />-  /* class 8 */<br />+  /* class 0 */<br /> /* This is basically the same command as for MMC with some<br />quirks. */<br /> #define SD_SEND_RELATIVE_ADDR     3   /* bcr               <br />     R6  */<br />+#define SD_SEND_IF_COND           8   /* bcr  [11:0] See<br />below   R7  */<br />+<br />+  /* class 10 */<br /> #define SD_SWITCH                 6   /* adtc [31:0] See<br />below   R1  */<br /><br />   /* Application commands */<br /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /> -115,6<br />+118,14 <img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" /><br />  */<br /><br /> /*<br />+ * SD_SEND_IF_COND argument format:<br />+ *<br />+ * [31:12] Reserved (0)<br />+ * [11:8] Host Voltage Supply Flags<br />+ * [7:0] Check Pattern (0xAA)<br />+ */<br />+<br />+/*<br />   MMC status in R1<br />   Type<br />    e : error bit<br />-<br />To unsubscribe from this list: send the line<br />&quot;unsubscribe linux-kernel&quot; in<br />the body of a message to majordomo<img border="0" align="middle" src="http://www.archivesat.com/img/at.gif" />vger.kernel.org<br />More majordomo info at  <a href="http://vger.kernel.org/majordomo-info.html">http://vge<br />r.kernel.org/majordomo-info.html</a><br />Please read the FAQ at  <a href="http://www.tux.org/lkml/">http://www.tux.org/lkml/</a>

转载请注明:在路上 » mmc: Add support for SDHC cards

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
82 queries in 0.178 seconds, using 22.17MB memory