diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-11 21:57:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-11 21:57:31 -0400 |
commit | 6abd2c860e34add677de50e8b134f5af6f4b0893 (patch) | |
tree | d201de170ca4851d66dbd02046fea7d95214fad7 /drivers/mmc/core/sd_ops.c | |
parent | d2c75f2f4b8be1c78f275c49e399d5a9b21ce924 (diff) | |
parent | 019a5f56ec195aceadada18aaaad0f67294bdaef (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc: (67 commits)
mmc: don't use weight32()
pxamci: support arbitrary block size
sdio: make the IRQ thread more resilient in the presence of bad states
sdio: fix IRQ diagnostic message
sdhci: remove old dma module params
sdhci: add SDHCI_QUIRK_BROKEN_DMA quirk
sdhci: remove DMA capability check from controller's PCI Class reg
sdhci: fix a typo
mmc: Disabler for Ricoh MMC controller
sdio: adaptive interrupt polling
mmc: pxamci: add SDIO card interrupt reporting capability
mmc: pxamci: set proper buswidth capabilities according to PXA flavor
mmc: pxamci: set proper block capabilities according to PXA flavor
mmc: pxamci: better pending IRQ determination
arm: i.MX/MX1 SDHC implements SD cards read-only switch read-back
mmc: add led trigger
mmc_spi host driver
MMC core learns about SPI
MMC/SD card driver learns SPI
MMC headers learn about SPI
...
Diffstat (limited to 'drivers/mmc/core/sd_ops.c')
-rw-r--r-- | drivers/mmc/core/sd_ops.c | 107 |
1 files changed, 71 insertions, 36 deletions
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index 342f340ebc25..ee4029a24efd 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c | |||
@@ -33,21 +33,21 @@ static int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card) | |||
33 | 33 | ||
34 | if (card) { | 34 | if (card) { |
35 | cmd.arg = card->rca << 16; | 35 | cmd.arg = card->rca << 16; |
36 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; | 36 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; |
37 | } else { | 37 | } else { |
38 | cmd.arg = 0; | 38 | cmd.arg = 0; |
39 | cmd.flags = MMC_RSP_R1 | MMC_CMD_BCR; | 39 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_BCR; |
40 | } | 40 | } |
41 | 41 | ||
42 | err = mmc_wait_for_cmd(host, &cmd, 0); | 42 | err = mmc_wait_for_cmd(host, &cmd, 0); |
43 | if (err != MMC_ERR_NONE) | 43 | if (err) |
44 | return err; | 44 | return err; |
45 | 45 | ||
46 | /* Check that card supported application commands */ | 46 | /* Check that card supported application commands */ |
47 | if (!(cmd.resp[0] & R1_APP_CMD)) | 47 | if (!mmc_host_is_spi(host) && !(cmd.resp[0] & R1_APP_CMD)) |
48 | return MMC_ERR_FAILED; | 48 | return -EOPNOTSUPP; |
49 | 49 | ||
50 | return MMC_ERR_NONE; | 50 | return 0; |
51 | } | 51 | } |
52 | 52 | ||
53 | /** | 53 | /** |
@@ -73,7 +73,7 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card, | |||
73 | BUG_ON(!cmd); | 73 | BUG_ON(!cmd); |
74 | BUG_ON(retries < 0); | 74 | BUG_ON(retries < 0); |
75 | 75 | ||
76 | err = MMC_ERR_INVALID; | 76 | err = -EIO; |
77 | 77 | ||
78 | /* | 78 | /* |
79 | * We have to resend MMC_APP_CMD for each attempt so | 79 | * We have to resend MMC_APP_CMD for each attempt so |
@@ -83,8 +83,14 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card, | |||
83 | memset(&mrq, 0, sizeof(struct mmc_request)); | 83 | memset(&mrq, 0, sizeof(struct mmc_request)); |
84 | 84 | ||
85 | err = mmc_app_cmd(host, card); | 85 | err = mmc_app_cmd(host, card); |
86 | if (err != MMC_ERR_NONE) | 86 | if (err) { |
87 | /* no point in retrying; no APP commands allowed */ | ||
88 | if (mmc_host_is_spi(host)) { | ||
89 | if (cmd->resp[0] & R1_SPI_ILLEGAL_COMMAND) | ||
90 | break; | ||
91 | } | ||
87 | continue; | 92 | continue; |
93 | } | ||
88 | 94 | ||
89 | memset(&mrq, 0, sizeof(struct mmc_request)); | 95 | memset(&mrq, 0, sizeof(struct mmc_request)); |
90 | 96 | ||
@@ -97,8 +103,14 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card, | |||
97 | mmc_wait_for_req(host, &mrq); | 103 | mmc_wait_for_req(host, &mrq); |
98 | 104 | ||
99 | err = cmd->error; | 105 | err = cmd->error; |
100 | if (cmd->error == MMC_ERR_NONE) | 106 | if (!cmd->error) |
101 | break; | 107 | break; |
108 | |||
109 | /* no point in retrying illegal APP commands */ | ||
110 | if (mmc_host_is_spi(host)) { | ||
111 | if (cmd->resp[0] & R1_SPI_ILLEGAL_COMMAND) | ||
112 | break; | ||
113 | } | ||
102 | } | 114 | } |
103 | 115 | ||
104 | return err; | 116 | return err; |
@@ -127,14 +139,14 @@ int mmc_app_set_bus_width(struct mmc_card *card, int width) | |||
127 | cmd.arg = SD_BUS_WIDTH_4; | 139 | cmd.arg = SD_BUS_WIDTH_4; |
128 | break; | 140 | break; |
129 | default: | 141 | default: |
130 | return MMC_ERR_INVALID; | 142 | return -EINVAL; |
131 | } | 143 | } |
132 | 144 | ||
133 | err = mmc_wait_for_app_cmd(card->host, card, &cmd, MMC_CMD_RETRIES); | 145 | err = mmc_wait_for_app_cmd(card->host, card, &cmd, MMC_CMD_RETRIES); |
134 | if (err != MMC_ERR_NONE) | 146 | if (err) |
135 | return err; | 147 | return err; |
136 | 148 | ||
137 | return MMC_ERR_NONE; | 149 | return 0; |
138 | } | 150 | } |
139 | 151 | ||
140 | int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) | 152 | int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) |
@@ -147,23 +159,36 @@ int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) | |||
147 | memset(&cmd, 0, sizeof(struct mmc_command)); | 159 | memset(&cmd, 0, sizeof(struct mmc_command)); |
148 | 160 | ||
149 | cmd.opcode = SD_APP_OP_COND; | 161 | cmd.opcode = SD_APP_OP_COND; |
150 | cmd.arg = ocr; | 162 | if (mmc_host_is_spi(host)) |
151 | cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR; | 163 | cmd.arg = ocr & (1 << 30); /* SPI only defines one bit */ |
164 | else | ||
165 | cmd.arg = ocr; | ||
166 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR; | ||
152 | 167 | ||
153 | for (i = 100; i; i--) { | 168 | for (i = 100; i; i--) { |
154 | err = mmc_wait_for_app_cmd(host, NULL, &cmd, MMC_CMD_RETRIES); | 169 | err = mmc_wait_for_app_cmd(host, NULL, &cmd, MMC_CMD_RETRIES); |
155 | if (err != MMC_ERR_NONE) | 170 | if (err) |
156 | break; | 171 | break; |
157 | 172 | ||
158 | if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0) | 173 | /* if we're just probing, do a single pass */ |
174 | if (ocr == 0) | ||
159 | break; | 175 | break; |
160 | 176 | ||
161 | err = MMC_ERR_TIMEOUT; | 177 | /* otherwise wait until reset completes */ |
178 | if (mmc_host_is_spi(host)) { | ||
179 | if (!(cmd.resp[0] & R1_SPI_IDLE)) | ||
180 | break; | ||
181 | } else { | ||
182 | if (cmd.resp[0] & MMC_CARD_BUSY) | ||
183 | break; | ||
184 | } | ||
185 | |||
186 | err = -ETIMEDOUT; | ||
162 | 187 | ||
163 | mmc_delay(10); | 188 | mmc_delay(10); |
164 | } | 189 | } |
165 | 190 | ||
166 | if (rocr) | 191 | if (rocr && !mmc_host_is_spi(host)) |
167 | *rocr = cmd.resp[0]; | 192 | *rocr = cmd.resp[0]; |
168 | 193 | ||
169 | return err; | 194 | return err; |
@@ -174,6 +199,7 @@ int mmc_send_if_cond(struct mmc_host *host, u32 ocr) | |||
174 | struct mmc_command cmd; | 199 | struct mmc_command cmd; |
175 | int err; | 200 | int err; |
176 | static const u8 test_pattern = 0xAA; | 201 | static const u8 test_pattern = 0xAA; |
202 | u8 result_pattern; | ||
177 | 203 | ||
178 | /* | 204 | /* |
179 | * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND | 205 | * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND |
@@ -182,16 +208,21 @@ int mmc_send_if_cond(struct mmc_host *host, u32 ocr) | |||
182 | */ | 208 | */ |
183 | cmd.opcode = SD_SEND_IF_COND; | 209 | cmd.opcode = SD_SEND_IF_COND; |
184 | cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern; | 210 | cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern; |
185 | cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR; | 211 | cmd.flags = MMC_RSP_SPI_R7 | MMC_RSP_R7 | MMC_CMD_BCR; |
186 | 212 | ||
187 | err = mmc_wait_for_cmd(host, &cmd, 0); | 213 | err = mmc_wait_for_cmd(host, &cmd, 0); |
188 | if (err != MMC_ERR_NONE) | 214 | if (err) |
189 | return err; | 215 | return err; |
190 | 216 | ||
191 | if ((cmd.resp[0] & 0xFF) != test_pattern) | 217 | if (mmc_host_is_spi(host)) |
192 | return MMC_ERR_FAILED; | 218 | result_pattern = cmd.resp[1] & 0xFF; |
219 | else | ||
220 | result_pattern = cmd.resp[0] & 0xFF; | ||
221 | |||
222 | if (result_pattern != test_pattern) | ||
223 | return -EIO; | ||
193 | 224 | ||
194 | return MMC_ERR_NONE; | 225 | return 0; |
195 | } | 226 | } |
196 | 227 | ||
197 | int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca) | 228 | int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca) |
@@ -209,12 +240,12 @@ int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca) | |||
209 | cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR; | 240 | cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR; |
210 | 241 | ||
211 | err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); | 242 | err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); |
212 | if (err != MMC_ERR_NONE) | 243 | if (err) |
213 | return err; | 244 | return err; |
214 | 245 | ||
215 | *rca = cmd.resp[0] >> 16; | 246 | *rca = cmd.resp[0] >> 16; |
216 | 247 | ||
217 | return MMC_ERR_NONE; | 248 | return 0; |
218 | } | 249 | } |
219 | 250 | ||
220 | int mmc_app_send_scr(struct mmc_card *card, u32 *scr) | 251 | int mmc_app_send_scr(struct mmc_card *card, u32 *scr) |
@@ -229,8 +260,10 @@ int mmc_app_send_scr(struct mmc_card *card, u32 *scr) | |||
229 | BUG_ON(!card->host); | 260 | BUG_ON(!card->host); |
230 | BUG_ON(!scr); | 261 | BUG_ON(!scr); |
231 | 262 | ||
263 | /* NOTE: caller guarantees scr is heap-allocated */ | ||
264 | |||
232 | err = mmc_app_cmd(card->host, card); | 265 | err = mmc_app_cmd(card->host, card); |
233 | if (err != MMC_ERR_NONE) | 266 | if (err) |
234 | return err; | 267 | return err; |
235 | 268 | ||
236 | memset(&mrq, 0, sizeof(struct mmc_request)); | 269 | memset(&mrq, 0, sizeof(struct mmc_request)); |
@@ -242,7 +275,7 @@ int mmc_app_send_scr(struct mmc_card *card, u32 *scr) | |||
242 | 275 | ||
243 | cmd.opcode = SD_APP_SEND_SCR; | 276 | cmd.opcode = SD_APP_SEND_SCR; |
244 | cmd.arg = 0; | 277 | cmd.arg = 0; |
245 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | 278 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; |
246 | 279 | ||
247 | data.blksz = 8; | 280 | data.blksz = 8; |
248 | data.blocks = 1; | 281 | data.blocks = 1; |
@@ -252,19 +285,19 @@ int mmc_app_send_scr(struct mmc_card *card, u32 *scr) | |||
252 | 285 | ||
253 | sg_init_one(&sg, scr, 8); | 286 | sg_init_one(&sg, scr, 8); |
254 | 287 | ||
255 | mmc_set_data_timeout(&data, card, 0); | 288 | mmc_set_data_timeout(&data, card); |
256 | 289 | ||
257 | mmc_wait_for_req(card->host, &mrq); | 290 | mmc_wait_for_req(card->host, &mrq); |
258 | 291 | ||
259 | if (cmd.error != MMC_ERR_NONE) | 292 | if (cmd.error) |
260 | return cmd.error; | 293 | return cmd.error; |
261 | if (data.error != MMC_ERR_NONE) | 294 | if (data.error) |
262 | return data.error; | 295 | return data.error; |
263 | 296 | ||
264 | scr[0] = ntohl(scr[0]); | 297 | scr[0] = ntohl(scr[0]); |
265 | scr[1] = ntohl(scr[1]); | 298 | scr[1] = ntohl(scr[1]); |
266 | 299 | ||
267 | return MMC_ERR_NONE; | 300 | return 0; |
268 | } | 301 | } |
269 | 302 | ||
270 | int mmc_sd_switch(struct mmc_card *card, int mode, int group, | 303 | int mmc_sd_switch(struct mmc_card *card, int mode, int group, |
@@ -278,6 +311,8 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group, | |||
278 | BUG_ON(!card); | 311 | BUG_ON(!card); |
279 | BUG_ON(!card->host); | 312 | BUG_ON(!card->host); |
280 | 313 | ||
314 | /* NOTE: caller guarantees resp is heap-allocated */ | ||
315 | |||
281 | mode = !!mode; | 316 | mode = !!mode; |
282 | value &= 0xF; | 317 | value &= 0xF; |
283 | 318 | ||
@@ -292,7 +327,7 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group, | |||
292 | cmd.arg = mode << 31 | 0x00FFFFFF; | 327 | cmd.arg = mode << 31 | 0x00FFFFFF; |
293 | cmd.arg &= ~(0xF << (group * 4)); | 328 | cmd.arg &= ~(0xF << (group * 4)); |
294 | cmd.arg |= value << (group * 4); | 329 | cmd.arg |= value << (group * 4); |
295 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | 330 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; |
296 | 331 | ||
297 | data.blksz = 64; | 332 | data.blksz = 64; |
298 | data.blocks = 1; | 333 | data.blocks = 1; |
@@ -302,15 +337,15 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group, | |||
302 | 337 | ||
303 | sg_init_one(&sg, resp, 64); | 338 | sg_init_one(&sg, resp, 64); |
304 | 339 | ||
305 | mmc_set_data_timeout(&data, card, 0); | 340 | mmc_set_data_timeout(&data, card); |
306 | 341 | ||
307 | mmc_wait_for_req(card->host, &mrq); | 342 | mmc_wait_for_req(card->host, &mrq); |
308 | 343 | ||
309 | if (cmd.error != MMC_ERR_NONE) | 344 | if (cmd.error) |
310 | return cmd.error; | 345 | return cmd.error; |
311 | if (data.error != MMC_ERR_NONE) | 346 | if (data.error) |
312 | return data.error; | 347 | return data.error; |
313 | 348 | ||
314 | return MMC_ERR_NONE; | 349 | return 0; |
315 | } | 350 | } |
316 | 351 | ||