diff options
Diffstat (limited to 'drivers/mmc/core/mmc.c')
-rw-r--r-- | drivers/mmc/core/mmc.c | 75 |
1 files changed, 67 insertions, 8 deletions
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 89f7a25b7ac1..6909a54c39be 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -108,23 +108,34 @@ static int mmc_decode_cid(struct mmc_card *card) | |||
108 | return 0; | 108 | return 0; |
109 | } | 109 | } |
110 | 110 | ||
111 | static void mmc_set_erase_size(struct mmc_card *card) | ||
112 | { | ||
113 | if (card->ext_csd.erase_group_def & 1) | ||
114 | card->erase_size = card->ext_csd.hc_erase_size; | ||
115 | else | ||
116 | card->erase_size = card->csd.erase_size; | ||
117 | |||
118 | mmc_init_erase(card); | ||
119 | } | ||
120 | |||
111 | /* | 121 | /* |
112 | * Given a 128-bit response, decode to our card CSD structure. | 122 | * Given a 128-bit response, decode to our card CSD structure. |
113 | */ | 123 | */ |
114 | static int mmc_decode_csd(struct mmc_card *card) | 124 | static int mmc_decode_csd(struct mmc_card *card) |
115 | { | 125 | { |
116 | struct mmc_csd *csd = &card->csd; | 126 | struct mmc_csd *csd = &card->csd; |
117 | unsigned int e, m, csd_struct; | 127 | unsigned int e, m, a, b; |
118 | u32 *resp = card->raw_csd; | 128 | u32 *resp = card->raw_csd; |
119 | 129 | ||
120 | /* | 130 | /* |
121 | * We only understand CSD structure v1.1 and v1.2. | 131 | * We only understand CSD structure v1.1 and v1.2. |
122 | * v1.2 has extra information in bits 15, 11 and 10. | 132 | * v1.2 has extra information in bits 15, 11 and 10. |
133 | * We also support eMMC v4.4 & v4.41. | ||
123 | */ | 134 | */ |
124 | csd_struct = UNSTUFF_BITS(resp, 126, 2); | 135 | csd->structure = UNSTUFF_BITS(resp, 126, 2); |
125 | if (csd_struct != 1 && csd_struct != 2) { | 136 | if (csd->structure == 0) { |
126 | printk(KERN_ERR "%s: unrecognised CSD structure version %d\n", | 137 | printk(KERN_ERR "%s: unrecognised CSD structure version %d\n", |
127 | mmc_hostname(card->host), csd_struct); | 138 | mmc_hostname(card->host), csd->structure); |
128 | return -EINVAL; | 139 | return -EINVAL; |
129 | } | 140 | } |
130 | 141 | ||
@@ -151,6 +162,13 @@ static int mmc_decode_csd(struct mmc_card *card) | |||
151 | csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); | 162 | csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); |
152 | csd->write_partial = UNSTUFF_BITS(resp, 21, 1); | 163 | csd->write_partial = UNSTUFF_BITS(resp, 21, 1); |
153 | 164 | ||
165 | if (csd->write_blkbits >= 9) { | ||
166 | a = UNSTUFF_BITS(resp, 42, 5); | ||
167 | b = UNSTUFF_BITS(resp, 37, 5); | ||
168 | csd->erase_size = (a + 1) * (b + 1); | ||
169 | csd->erase_size <<= csd->write_blkbits - 9; | ||
170 | } | ||
171 | |||
154 | return 0; | 172 | return 0; |
155 | } | 173 | } |
156 | 174 | ||
@@ -207,11 +225,22 @@ static int mmc_read_ext_csd(struct mmc_card *card) | |||
207 | goto out; | 225 | goto out; |
208 | } | 226 | } |
209 | 227 | ||
228 | /* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */ | ||
229 | if (card->csd.structure == 3) { | ||
230 | int ext_csd_struct = ext_csd[EXT_CSD_STRUCTURE]; | ||
231 | if (ext_csd_struct > 2) { | ||
232 | printk(KERN_ERR "%s: unrecognised EXT_CSD structure " | ||
233 | "version %d\n", mmc_hostname(card->host), | ||
234 | ext_csd_struct); | ||
235 | err = -EINVAL; | ||
236 | goto out; | ||
237 | } | ||
238 | } | ||
239 | |||
210 | card->ext_csd.rev = ext_csd[EXT_CSD_REV]; | 240 | card->ext_csd.rev = ext_csd[EXT_CSD_REV]; |
211 | if (card->ext_csd.rev > 5) { | 241 | if (card->ext_csd.rev > 5) { |
212 | printk(KERN_ERR "%s: unrecognised EXT_CSD structure " | 242 | printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n", |
213 | "version %d\n", mmc_hostname(card->host), | 243 | mmc_hostname(card->host), card->ext_csd.rev); |
214 | card->ext_csd.rev); | ||
215 | err = -EINVAL; | 244 | err = -EINVAL; |
216 | goto out; | 245 | goto out; |
217 | } | 246 | } |
@@ -222,7 +251,9 @@ static int mmc_read_ext_csd(struct mmc_card *card) | |||
222 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | | 251 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | |
223 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16 | | 252 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16 | |
224 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24; | 253 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24; |
225 | if (card->ext_csd.sectors) | 254 | |
255 | /* Cards with density > 2GiB are sector addressed */ | ||
256 | if (card->ext_csd.sectors > (2u * 1024 * 1024 * 1024) / 512) | ||
226 | mmc_card_set_blockaddr(card); | 257 | mmc_card_set_blockaddr(card); |
227 | } | 258 | } |
228 | 259 | ||
@@ -247,8 +278,30 @@ static int mmc_read_ext_csd(struct mmc_card *card) | |||
247 | if (sa_shift > 0 && sa_shift <= 0x17) | 278 | if (sa_shift > 0 && sa_shift <= 0x17) |
248 | card->ext_csd.sa_timeout = | 279 | card->ext_csd.sa_timeout = |
249 | 1 << ext_csd[EXT_CSD_S_A_TIMEOUT]; | 280 | 1 << ext_csd[EXT_CSD_S_A_TIMEOUT]; |
281 | card->ext_csd.erase_group_def = | ||
282 | ext_csd[EXT_CSD_ERASE_GROUP_DEF]; | ||
283 | card->ext_csd.hc_erase_timeout = 300 * | ||
284 | ext_csd[EXT_CSD_ERASE_TIMEOUT_MULT]; | ||
285 | card->ext_csd.hc_erase_size = | ||
286 | ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] << 10; | ||
250 | } | 287 | } |
251 | 288 | ||
289 | if (card->ext_csd.rev >= 4) { | ||
290 | card->ext_csd.sec_trim_mult = | ||
291 | ext_csd[EXT_CSD_SEC_TRIM_MULT]; | ||
292 | card->ext_csd.sec_erase_mult = | ||
293 | ext_csd[EXT_CSD_SEC_ERASE_MULT]; | ||
294 | card->ext_csd.sec_feature_support = | ||
295 | ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; | ||
296 | card->ext_csd.trim_timeout = 300 * | ||
297 | ext_csd[EXT_CSD_TRIM_MULT]; | ||
298 | } | ||
299 | |||
300 | if (ext_csd[EXT_CSD_ERASED_MEM_CONT]) | ||
301 | card->erased_byte = 0xFF; | ||
302 | else | ||
303 | card->erased_byte = 0x0; | ||
304 | |||
252 | out: | 305 | out: |
253 | kfree(ext_csd); | 306 | kfree(ext_csd); |
254 | 307 | ||
@@ -260,6 +313,8 @@ MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1], | |||
260 | MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], | 313 | MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], |
261 | card->raw_csd[2], card->raw_csd[3]); | 314 | card->raw_csd[2], card->raw_csd[3]); |
262 | MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); | 315 | MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); |
316 | MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9); | ||
317 | MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9); | ||
263 | MMC_DEV_ATTR(fwrev, "0x%x\n", card->cid.fwrev); | 318 | MMC_DEV_ATTR(fwrev, "0x%x\n", card->cid.fwrev); |
264 | MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); | 319 | MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); |
265 | MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); | 320 | MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); |
@@ -271,6 +326,8 @@ static struct attribute *mmc_std_attrs[] = { | |||
271 | &dev_attr_cid.attr, | 326 | &dev_attr_cid.attr, |
272 | &dev_attr_csd.attr, | 327 | &dev_attr_csd.attr, |
273 | &dev_attr_date.attr, | 328 | &dev_attr_date.attr, |
329 | &dev_attr_erase_size.attr, | ||
330 | &dev_attr_preferred_erase_size.attr, | ||
274 | &dev_attr_fwrev.attr, | 331 | &dev_attr_fwrev.attr, |
275 | &dev_attr_hwrev.attr, | 332 | &dev_attr_hwrev.attr, |
276 | &dev_attr_manfid.attr, | 333 | &dev_attr_manfid.attr, |
@@ -407,6 +464,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
407 | err = mmc_read_ext_csd(card); | 464 | err = mmc_read_ext_csd(card); |
408 | if (err) | 465 | if (err) |
409 | goto free_card; | 466 | goto free_card; |
467 | /* Erase size depends on CSD and Extended CSD */ | ||
468 | mmc_set_erase_size(card); | ||
410 | } | 469 | } |
411 | 470 | ||
412 | /* | 471 | /* |