diff options
Diffstat (limited to 'drivers/mmc/tifm_sd.c')
-rw-r--r-- | drivers/mmc/tifm_sd.c | 487 |
1 files changed, 272 insertions, 215 deletions
diff --git a/drivers/mmc/tifm_sd.c b/drivers/mmc/tifm_sd.c index fa4a52886b97..e65f8a0a9349 100644 --- a/drivers/mmc/tifm_sd.c +++ b/drivers/mmc/tifm_sd.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <asm/io.h> | 17 | #include <asm/io.h> |
18 | 18 | ||
19 | #define DRIVER_NAME "tifm_sd" | 19 | #define DRIVER_NAME "tifm_sd" |
20 | #define DRIVER_VERSION "0.6" | 20 | #define DRIVER_VERSION "0.7" |
21 | 21 | ||
22 | static int no_dma = 0; | 22 | static int no_dma = 0; |
23 | static int fixed_timeout = 0; | 23 | static int fixed_timeout = 0; |
@@ -79,7 +79,6 @@ typedef enum { | |||
79 | 79 | ||
80 | enum { | 80 | enum { |
81 | FIFO_RDY = 0x0001, /* hardware dependent value */ | 81 | FIFO_RDY = 0x0001, /* hardware dependent value */ |
82 | HOST_REG = 0x0002, | ||
83 | EJECT = 0x0004, | 82 | EJECT = 0x0004, |
84 | EJECT_DONE = 0x0008, | 83 | EJECT_DONE = 0x0008, |
85 | CARD_BUSY = 0x0010, | 84 | CARD_BUSY = 0x0010, |
@@ -95,46 +94,53 @@ struct tifm_sd { | |||
95 | card_state_t state; | 94 | card_state_t state; |
96 | unsigned int clk_freq; | 95 | unsigned int clk_freq; |
97 | unsigned int clk_div; | 96 | unsigned int clk_div; |
98 | unsigned long timeout_jiffies; // software timeout - 2 sec | 97 | unsigned long timeout_jiffies; |
99 | 98 | ||
99 | struct tasklet_struct finish_tasklet; | ||
100 | struct timer_list timer; | ||
100 | struct mmc_request *req; | 101 | struct mmc_request *req; |
101 | struct work_struct cmd_handler; | 102 | wait_queue_head_t notify; |
102 | struct delayed_work abort_handler; | ||
103 | wait_queue_head_t can_eject; | ||
104 | 103 | ||
105 | size_t written_blocks; | 104 | size_t written_blocks; |
106 | char *buffer; | ||
107 | size_t buffer_size; | 105 | size_t buffer_size; |
108 | size_t buffer_pos; | 106 | size_t buffer_pos; |
109 | 107 | ||
110 | }; | 108 | }; |
111 | 109 | ||
110 | static char* tifm_sd_data_buffer(struct mmc_data *data) | ||
111 | { | ||
112 | return page_address(data->sg->page) + data->sg->offset; | ||
113 | } | ||
114 | |||
112 | static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host, | 115 | static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host, |
113 | unsigned int host_status) | 116 | unsigned int host_status) |
114 | { | 117 | { |
115 | struct mmc_command *cmd = host->req->cmd; | 118 | struct mmc_command *cmd = host->req->cmd; |
116 | unsigned int t_val = 0, cnt = 0; | 119 | unsigned int t_val = 0, cnt = 0; |
120 | char *buffer; | ||
117 | 121 | ||
118 | if (host_status & TIFM_MMCSD_BRS) { | 122 | if (host_status & TIFM_MMCSD_BRS) { |
119 | /* in non-dma rx mode BRS fires when fifo is still not empty */ | 123 | /* in non-dma rx mode BRS fires when fifo is still not empty */ |
120 | if (host->buffer && (cmd->data->flags & MMC_DATA_READ)) { | 124 | if (no_dma && (cmd->data->flags & MMC_DATA_READ)) { |
125 | buffer = tifm_sd_data_buffer(host->req->data); | ||
121 | while (host->buffer_size > host->buffer_pos) { | 126 | while (host->buffer_size > host->buffer_pos) { |
122 | t_val = readl(sock->addr + SOCK_MMCSD_DATA); | 127 | t_val = readl(sock->addr + SOCK_MMCSD_DATA); |
123 | host->buffer[host->buffer_pos++] = t_val & 0xff; | 128 | buffer[host->buffer_pos++] = t_val & 0xff; |
124 | host->buffer[host->buffer_pos++] = | 129 | buffer[host->buffer_pos++] = |
125 | (t_val >> 8) & 0xff; | 130 | (t_val >> 8) & 0xff; |
126 | } | 131 | } |
127 | } | 132 | } |
128 | return 1; | 133 | return 1; |
129 | } else if (host->buffer) { | 134 | } else if (no_dma) { |
135 | buffer = tifm_sd_data_buffer(host->req->data); | ||
130 | if ((cmd->data->flags & MMC_DATA_READ) && | 136 | if ((cmd->data->flags & MMC_DATA_READ) && |
131 | (host_status & TIFM_MMCSD_AF)) { | 137 | (host_status & TIFM_MMCSD_AF)) { |
132 | for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) { | 138 | for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) { |
133 | t_val = readl(sock->addr + SOCK_MMCSD_DATA); | 139 | t_val = readl(sock->addr + SOCK_MMCSD_DATA); |
134 | if (host->buffer_size > host->buffer_pos) { | 140 | if (host->buffer_size > host->buffer_pos) { |
135 | host->buffer[host->buffer_pos++] = | 141 | buffer[host->buffer_pos++] = |
136 | t_val & 0xff; | 142 | t_val & 0xff; |
137 | host->buffer[host->buffer_pos++] = | 143 | buffer[host->buffer_pos++] = |
138 | (t_val >> 8) & 0xff; | 144 | (t_val >> 8) & 0xff; |
139 | } | 145 | } |
140 | } | 146 | } |
@@ -142,11 +148,12 @@ static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host, | |||
142 | && (host_status & TIFM_MMCSD_AE)) { | 148 | && (host_status & TIFM_MMCSD_AE)) { |
143 | for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) { | 149 | for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) { |
144 | if (host->buffer_size > host->buffer_pos) { | 150 | if (host->buffer_size > host->buffer_pos) { |
145 | t_val = host->buffer[host->buffer_pos++] & 0x00ff; | 151 | t_val = buffer[host->buffer_pos++] |
146 | t_val |= ((host->buffer[host->buffer_pos++]) << 8) | 152 | & 0x00ff; |
147 | & 0xff00; | 153 | t_val |= ((buffer[host->buffer_pos++]) |
154 | << 8) & 0xff00; | ||
148 | writel(t_val, | 155 | writel(t_val, |
149 | sock->addr + SOCK_MMCSD_DATA); | 156 | sock->addr + SOCK_MMCSD_DATA); |
150 | } | 157 | } |
151 | } | 158 | } |
152 | } | 159 | } |
@@ -206,7 +213,7 @@ static void tifm_sd_exec(struct tifm_sd *host, struct mmc_command *cmd) | |||
206 | cmd_mask |= TIFM_MMCSD_READ; | 213 | cmd_mask |= TIFM_MMCSD_READ; |
207 | 214 | ||
208 | dev_dbg(&sock->dev, "executing opcode 0x%x, arg: 0x%x, mask: 0x%x\n", | 215 | dev_dbg(&sock->dev, "executing opcode 0x%x, arg: 0x%x, mask: 0x%x\n", |
209 | cmd->opcode, cmd->arg, cmd_mask); | 216 | cmd->opcode, cmd->arg, cmd_mask); |
210 | 217 | ||
211 | writel((cmd->arg >> 16) & 0xffff, sock->addr + SOCK_MMCSD_ARG_HIGH); | 218 | writel((cmd->arg >> 16) & 0xffff, sock->addr + SOCK_MMCSD_ARG_HIGH); |
212 | writel(cmd->arg & 0xffff, sock->addr + SOCK_MMCSD_ARG_LOW); | 219 | writel(cmd->arg & 0xffff, sock->addr + SOCK_MMCSD_ARG_LOW); |
@@ -239,65 +246,78 @@ change_state: | |||
239 | tifm_sd_fetch_resp(cmd, sock); | 246 | tifm_sd_fetch_resp(cmd, sock); |
240 | if (cmd->data) { | 247 | if (cmd->data) { |
241 | host->state = BRS; | 248 | host->state = BRS; |
242 | } else | 249 | } else { |
243 | host->state = READY; | 250 | host->state = READY; |
251 | } | ||
244 | goto change_state; | 252 | goto change_state; |
245 | } | 253 | } |
246 | break; | 254 | break; |
247 | case BRS: | 255 | case BRS: |
248 | if (tifm_sd_transfer_data(sock, host, host_status)) { | 256 | if (tifm_sd_transfer_data(sock, host, host_status)) { |
249 | if (!host->req->stop) { | 257 | if (cmd->data->flags & MMC_DATA_WRITE) { |
250 | if (cmd->data->flags & MMC_DATA_WRITE) { | 258 | host->state = CARD; |
251 | host->state = CARD; | 259 | } else { |
260 | if (no_dma) { | ||
261 | if (host->req->stop) { | ||
262 | tifm_sd_exec(host, host->req->stop); | ||
263 | host->state = SCMD; | ||
264 | } else { | ||
265 | host->state = READY; | ||
266 | } | ||
252 | } else { | 267 | } else { |
253 | host->state = | 268 | host->state = FIFO; |
254 | host->buffer ? READY : FIFO; | ||
255 | } | 269 | } |
256 | goto change_state; | ||
257 | } | 270 | } |
258 | tifm_sd_exec(host, host->req->stop); | 271 | goto change_state; |
259 | host->state = SCMD; | ||
260 | } | 272 | } |
261 | break; | 273 | break; |
262 | case SCMD: | 274 | case SCMD: |
263 | if (host_status & TIFM_MMCSD_EOC) { | 275 | if (host_status & TIFM_MMCSD_EOC) { |
264 | tifm_sd_fetch_resp(host->req->stop, sock); | 276 | tifm_sd_fetch_resp(host->req->stop, sock); |
265 | if (cmd->error) { | 277 | host->state = READY; |
266 | host->state = READY; | ||
267 | } else if (cmd->data->flags & MMC_DATA_WRITE) { | ||
268 | host->state = CARD; | ||
269 | } else { | ||
270 | host->state = host->buffer ? READY : FIFO; | ||
271 | } | ||
272 | goto change_state; | 278 | goto change_state; |
273 | } | 279 | } |
274 | break; | 280 | break; |
275 | case CARD: | 281 | case CARD: |
282 | dev_dbg(&sock->dev, "waiting for CARD, have %zd blocks\n", | ||
283 | host->written_blocks); | ||
276 | if (!(host->flags & CARD_BUSY) | 284 | if (!(host->flags & CARD_BUSY) |
277 | && (host->written_blocks == cmd->data->blocks)) { | 285 | && (host->written_blocks == cmd->data->blocks)) { |
278 | host->state = host->buffer ? READY : FIFO; | 286 | if (no_dma) { |
287 | if (host->req->stop) { | ||
288 | tifm_sd_exec(host, host->req->stop); | ||
289 | host->state = SCMD; | ||
290 | } else { | ||
291 | host->state = READY; | ||
292 | } | ||
293 | } else { | ||
294 | host->state = FIFO; | ||
295 | } | ||
279 | goto change_state; | 296 | goto change_state; |
280 | } | 297 | } |
281 | break; | 298 | break; |
282 | case FIFO: | 299 | case FIFO: |
283 | if (host->flags & FIFO_RDY) { | 300 | if (host->flags & FIFO_RDY) { |
284 | host->state = READY; | ||
285 | host->flags &= ~FIFO_RDY; | 301 | host->flags &= ~FIFO_RDY; |
302 | if (host->req->stop) { | ||
303 | tifm_sd_exec(host, host->req->stop); | ||
304 | host->state = SCMD; | ||
305 | } else { | ||
306 | host->state = READY; | ||
307 | } | ||
286 | goto change_state; | 308 | goto change_state; |
287 | } | 309 | } |
288 | break; | 310 | break; |
289 | case READY: | 311 | case READY: |
290 | queue_work(sock->wq, &host->cmd_handler); | 312 | tasklet_schedule(&host->finish_tasklet); |
291 | return; | 313 | return; |
292 | } | 314 | } |
293 | 315 | ||
294 | queue_delayed_work(sock->wq, &host->abort_handler, | ||
295 | host->timeout_jiffies); | ||
296 | } | 316 | } |
297 | 317 | ||
298 | /* Called from interrupt handler */ | 318 | /* Called from interrupt handler */ |
299 | static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock, | 319 | static void tifm_sd_signal_irq(struct tifm_dev *sock, |
300 | unsigned int sock_irq_status) | 320 | unsigned int sock_irq_status) |
301 | { | 321 | { |
302 | struct tifm_sd *host; | 322 | struct tifm_sd *host; |
303 | unsigned int host_status = 0, fifo_status = 0; | 323 | unsigned int host_status = 0, fifo_status = 0; |
@@ -305,7 +325,6 @@ static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock, | |||
305 | 325 | ||
306 | spin_lock(&sock->lock); | 326 | spin_lock(&sock->lock); |
307 | host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock)); | 327 | host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock)); |
308 | cancel_delayed_work(&host->abort_handler); | ||
309 | 328 | ||
310 | if (sock_irq_status & FIFO_EVENT) { | 329 | if (sock_irq_status & FIFO_EVENT) { |
311 | fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS); | 330 | fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS); |
@@ -318,19 +337,17 @@ static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock, | |||
318 | host_status = readl(sock->addr + SOCK_MMCSD_STATUS); | 337 | host_status = readl(sock->addr + SOCK_MMCSD_STATUS); |
319 | writel(host_status, sock->addr + SOCK_MMCSD_STATUS); | 338 | writel(host_status, sock->addr + SOCK_MMCSD_STATUS); |
320 | 339 | ||
321 | if (!(host->flags & HOST_REG)) | ||
322 | queue_work(sock->wq, &host->cmd_handler); | ||
323 | if (!host->req) | 340 | if (!host->req) |
324 | goto done; | 341 | goto done; |
325 | 342 | ||
326 | if (host_status & TIFM_MMCSD_ERRMASK) { | 343 | if (host_status & TIFM_MMCSD_ERRMASK) { |
327 | if (host_status & TIFM_MMCSD_CERR) | 344 | if (host_status & TIFM_MMCSD_CERR) |
328 | error_code = MMC_ERR_FAILED; | 345 | error_code = MMC_ERR_FAILED; |
329 | else if (host_status & | 346 | else if (host_status |
330 | (TIFM_MMCSD_CTO | TIFM_MMCSD_DTO)) | 347 | & (TIFM_MMCSD_CTO | TIFM_MMCSD_DTO)) |
331 | error_code = MMC_ERR_TIMEOUT; | 348 | error_code = MMC_ERR_TIMEOUT; |
332 | else if (host_status & | 349 | else if (host_status |
333 | (TIFM_MMCSD_CCRC | TIFM_MMCSD_DCRC)) | 350 | & (TIFM_MMCSD_CCRC | TIFM_MMCSD_DCRC)) |
334 | error_code = MMC_ERR_BADCRC; | 351 | error_code = MMC_ERR_BADCRC; |
335 | 352 | ||
336 | writel(TIFM_FIFO_INT_SETALL, | 353 | writel(TIFM_FIFO_INT_SETALL, |
@@ -340,12 +357,11 @@ static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock, | |||
340 | if (host->req->stop) { | 357 | if (host->req->stop) { |
341 | if (host->state == SCMD) { | 358 | if (host->state == SCMD) { |
342 | host->req->stop->error = error_code; | 359 | host->req->stop->error = error_code; |
343 | } else if(host->state == BRS) { | 360 | } else if (host->state == BRS |
361 | || host->state == CARD | ||
362 | || host->state == FIFO) { | ||
344 | host->req->cmd->error = error_code; | 363 | host->req->cmd->error = error_code; |
345 | tifm_sd_exec(host, host->req->stop); | 364 | tifm_sd_exec(host, host->req->stop); |
346 | queue_delayed_work(sock->wq, | ||
347 | &host->abort_handler, | ||
348 | host->timeout_jiffies); | ||
349 | host->state = SCMD; | 365 | host->state = SCMD; |
350 | goto done; | 366 | goto done; |
351 | } else { | 367 | } else { |
@@ -359,8 +375,8 @@ static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock, | |||
359 | 375 | ||
360 | if (host_status & TIFM_MMCSD_CB) | 376 | if (host_status & TIFM_MMCSD_CB) |
361 | host->flags |= CARD_BUSY; | 377 | host->flags |= CARD_BUSY; |
362 | if ((host_status & TIFM_MMCSD_EOFB) && | 378 | if ((host_status & TIFM_MMCSD_EOFB) |
363 | (host->flags & CARD_BUSY)) { | 379 | && (host->flags & CARD_BUSY)) { |
364 | host->written_blocks++; | 380 | host->written_blocks++; |
365 | host->flags &= ~CARD_BUSY; | 381 | host->flags &= ~CARD_BUSY; |
366 | } | 382 | } |
@@ -370,22 +386,22 @@ static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock, | |||
370 | tifm_sd_process_cmd(sock, host, host_status); | 386 | tifm_sd_process_cmd(sock, host, host_status); |
371 | done: | 387 | done: |
372 | dev_dbg(&sock->dev, "host_status %x, fifo_status %x\n", | 388 | dev_dbg(&sock->dev, "host_status %x, fifo_status %x\n", |
373 | host_status, fifo_status); | 389 | host_status, fifo_status); |
374 | spin_unlock(&sock->lock); | 390 | spin_unlock(&sock->lock); |
375 | return sock_irq_status; | ||
376 | } | 391 | } |
377 | 392 | ||
378 | static void tifm_sd_prepare_data(struct tifm_sd *card, struct mmc_command *cmd) | 393 | static void tifm_sd_prepare_data(struct tifm_sd *host, struct mmc_command *cmd) |
379 | { | 394 | { |
380 | struct tifm_dev *sock = card->dev; | 395 | struct tifm_dev *sock = host->dev; |
381 | unsigned int dest_cnt; | 396 | unsigned int dest_cnt; |
382 | 397 | ||
383 | /* DMA style IO */ | 398 | /* DMA style IO */ |
384 | 399 | dev_dbg(&sock->dev, "setting dma for %d blocks\n", | |
400 | cmd->data->blocks); | ||
385 | writel(TIFM_FIFO_INT_SETALL, | 401 | writel(TIFM_FIFO_INT_SETALL, |
386 | sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); | 402 | sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); |
387 | writel(ilog2(cmd->data->blksz) - 2, | 403 | writel(ilog2(cmd->data->blksz) - 2, |
388 | sock->addr + SOCK_FIFO_PAGE_SIZE); | 404 | sock->addr + SOCK_FIFO_PAGE_SIZE); |
389 | writel(TIFM_FIFO_ENABLE, sock->addr + SOCK_FIFO_CONTROL); | 405 | writel(TIFM_FIFO_ENABLE, sock->addr + SOCK_FIFO_CONTROL); |
390 | writel(TIFM_FIFO_INTMASK, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); | 406 | writel(TIFM_FIFO_INTMASK, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); |
391 | 407 | ||
@@ -399,7 +415,7 @@ static void tifm_sd_prepare_data(struct tifm_sd *card, struct mmc_command *cmd) | |||
399 | if (cmd->data->flags & MMC_DATA_WRITE) { | 415 | if (cmd->data->flags & MMC_DATA_WRITE) { |
400 | writel(TIFM_MMCSD_TXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); | 416 | writel(TIFM_MMCSD_TXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); |
401 | writel(dest_cnt | TIFM_DMA_TX | TIFM_DMA_EN, | 417 | writel(dest_cnt | TIFM_DMA_TX | TIFM_DMA_EN, |
402 | sock->addr + SOCK_DMA_CONTROL); | 418 | sock->addr + SOCK_DMA_CONTROL); |
403 | } else { | 419 | } else { |
404 | writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); | 420 | writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); |
405 | writel(dest_cnt | TIFM_DMA_EN, sock->addr + SOCK_DMA_CONTROL); | 421 | writel(dest_cnt | TIFM_DMA_EN, sock->addr + SOCK_DMA_CONTROL); |
@@ -407,7 +423,7 @@ static void tifm_sd_prepare_data(struct tifm_sd *card, struct mmc_command *cmd) | |||
407 | } | 423 | } |
408 | 424 | ||
409 | static void tifm_sd_set_data_timeout(struct tifm_sd *host, | 425 | static void tifm_sd_set_data_timeout(struct tifm_sd *host, |
410 | struct mmc_data *data) | 426 | struct mmc_data *data) |
411 | { | 427 | { |
412 | struct tifm_dev *sock = host->dev; | 428 | struct tifm_dev *sock = host->dev; |
413 | unsigned int data_timeout = data->timeout_clks; | 429 | unsigned int data_timeout = data->timeout_clks; |
@@ -416,22 +432,21 @@ static void tifm_sd_set_data_timeout(struct tifm_sd *host, | |||
416 | return; | 432 | return; |
417 | 433 | ||
418 | data_timeout += data->timeout_ns / | 434 | data_timeout += data->timeout_ns / |
419 | ((1000000000 / host->clk_freq) * host->clk_div); | 435 | ((1000000000UL / host->clk_freq) * host->clk_div); |
420 | data_timeout *= 10; // call it fudge factor for now | ||
421 | 436 | ||
422 | if (data_timeout < 0xffff) { | 437 | if (data_timeout < 0xffff) { |
423 | writel((~TIFM_MMCSD_DPE) & | ||
424 | readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG), | ||
425 | sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG); | ||
426 | writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO); | 438 | writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO); |
439 | writel((~TIFM_MMCSD_DPE) | ||
440 | & readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG), | ||
441 | sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG); | ||
427 | } else { | 442 | } else { |
428 | writel(TIFM_MMCSD_DPE | | ||
429 | readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG), | ||
430 | sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG); | ||
431 | data_timeout = (data_timeout >> 10) + 1; | 443 | data_timeout = (data_timeout >> 10) + 1; |
432 | if(data_timeout > 0xffff) | 444 | if (data_timeout > 0xffff) |
433 | data_timeout = 0; /* set to unlimited */ | 445 | data_timeout = 0; /* set to unlimited */ |
434 | writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO); | 446 | writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO); |
447 | writel(TIFM_MMCSD_DPE | ||
448 | | readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG), | ||
449 | sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG); | ||
435 | } | 450 | } |
436 | } | 451 | } |
437 | 452 | ||
@@ -474,11 +489,10 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
474 | } | 489 | } |
475 | 490 | ||
476 | host->req = mrq; | 491 | host->req = mrq; |
492 | mod_timer(&host->timer, jiffies + host->timeout_jiffies); | ||
477 | host->state = CMD; | 493 | host->state = CMD; |
478 | queue_delayed_work(sock->wq, &host->abort_handler, | ||
479 | host->timeout_jiffies); | ||
480 | writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL), | 494 | writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL), |
481 | sock->addr + SOCK_CONTROL); | 495 | sock->addr + SOCK_CONTROL); |
482 | tifm_sd_exec(host, mrq->cmd); | 496 | tifm_sd_exec(host, mrq->cmd); |
483 | spin_unlock_irqrestore(&sock->lock, flags); | 497 | spin_unlock_irqrestore(&sock->lock, flags); |
484 | return; | 498 | return; |
@@ -493,9 +507,9 @@ err_out: | |||
493 | mmc_request_done(mmc, mrq); | 507 | mmc_request_done(mmc, mrq); |
494 | } | 508 | } |
495 | 509 | ||
496 | static void tifm_sd_end_cmd(struct work_struct *work) | 510 | static void tifm_sd_end_cmd(unsigned long data) |
497 | { | 511 | { |
498 | struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); | 512 | struct tifm_sd *host = (struct tifm_sd*)data; |
499 | struct tifm_dev *sock = host->dev; | 513 | struct tifm_dev *sock = host->dev; |
500 | struct mmc_host *mmc = tifm_get_drvdata(sock); | 514 | struct mmc_host *mmc = tifm_get_drvdata(sock); |
501 | struct mmc_request *mrq; | 515 | struct mmc_request *mrq; |
@@ -504,6 +518,7 @@ static void tifm_sd_end_cmd(struct work_struct *work) | |||
504 | 518 | ||
505 | spin_lock_irqsave(&sock->lock, flags); | 519 | spin_lock_irqsave(&sock->lock, flags); |
506 | 520 | ||
521 | del_timer(&host->timer); | ||
507 | mrq = host->req; | 522 | mrq = host->req; |
508 | host->req = NULL; | 523 | host->req = NULL; |
509 | host->state = IDLE; | 524 | host->state = IDLE; |
@@ -517,8 +532,8 @@ static void tifm_sd_end_cmd(struct work_struct *work) | |||
517 | r_data = mrq->cmd->data; | 532 | r_data = mrq->cmd->data; |
518 | if (r_data) { | 533 | if (r_data) { |
519 | if (r_data->flags & MMC_DATA_WRITE) { | 534 | if (r_data->flags & MMC_DATA_WRITE) { |
520 | r_data->bytes_xfered = host->written_blocks * | 535 | r_data->bytes_xfered = host->written_blocks |
521 | r_data->blksz; | 536 | * r_data->blksz; |
522 | } else { | 537 | } else { |
523 | r_data->bytes_xfered = r_data->blocks - | 538 | r_data->bytes_xfered = r_data->blocks - |
524 | readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1; | 539 | readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1; |
@@ -532,7 +547,7 @@ static void tifm_sd_end_cmd(struct work_struct *work) | |||
532 | } | 547 | } |
533 | 548 | ||
534 | writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), | 549 | writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), |
535 | sock->addr + SOCK_CONTROL); | 550 | sock->addr + SOCK_CONTROL); |
536 | 551 | ||
537 | spin_unlock_irqrestore(&sock->lock, flags); | 552 | spin_unlock_irqrestore(&sock->lock, flags); |
538 | mmc_request_done(mmc, mrq); | 553 | mmc_request_done(mmc, mrq); |
@@ -544,15 +559,6 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq) | |||
544 | struct tifm_dev *sock = host->dev; | 559 | struct tifm_dev *sock = host->dev; |
545 | unsigned long flags; | 560 | unsigned long flags; |
546 | struct mmc_data *r_data = mrq->cmd->data; | 561 | struct mmc_data *r_data = mrq->cmd->data; |
547 | char *t_buffer = NULL; | ||
548 | |||
549 | if (r_data) { | ||
550 | t_buffer = kmap(r_data->sg->page); | ||
551 | if (!t_buffer) { | ||
552 | printk(KERN_ERR DRIVER_NAME ": kmap failed\n"); | ||
553 | goto err_out; | ||
554 | } | ||
555 | } | ||
556 | 562 | ||
557 | spin_lock_irqsave(&sock->lock, flags); | 563 | spin_lock_irqsave(&sock->lock, flags); |
558 | if (host->flags & EJECT) { | 564 | if (host->flags & EJECT) { |
@@ -569,15 +575,14 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq) | |||
569 | if (r_data) { | 575 | if (r_data) { |
570 | tifm_sd_set_data_timeout(host, r_data); | 576 | tifm_sd_set_data_timeout(host, r_data); |
571 | 577 | ||
572 | host->buffer = t_buffer + r_data->sg->offset; | 578 | host->buffer_size = mrq->cmd->data->blocks |
573 | host->buffer_size = mrq->cmd->data->blocks * | 579 | * mrq->cmd->data->blksz; |
574 | mrq->cmd->data->blksz; | ||
575 | 580 | ||
576 | writel(TIFM_MMCSD_BUFINT | | 581 | writel(TIFM_MMCSD_BUFINT |
577 | readl(sock->addr + SOCK_MMCSD_INT_ENABLE), | 582 | | readl(sock->addr + SOCK_MMCSD_INT_ENABLE), |
578 | sock->addr + SOCK_MMCSD_INT_ENABLE); | 583 | sock->addr + SOCK_MMCSD_INT_ENABLE); |
579 | writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8) | | 584 | writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8) |
580 | (TIFM_MMCSD_FIFO_SIZE - 1), | 585 | | (TIFM_MMCSD_FIFO_SIZE - 1), |
581 | sock->addr + SOCK_MMCSD_BUFFER_CONFIG); | 586 | sock->addr + SOCK_MMCSD_BUFFER_CONFIG); |
582 | 587 | ||
583 | host->written_blocks = 0; | 588 | host->written_blocks = 0; |
@@ -588,26 +593,22 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq) | |||
588 | } | 593 | } |
589 | 594 | ||
590 | host->req = mrq; | 595 | host->req = mrq; |
596 | mod_timer(&host->timer, jiffies + host->timeout_jiffies); | ||
591 | host->state = CMD; | 597 | host->state = CMD; |
592 | queue_delayed_work(sock->wq, &host->abort_handler, | ||
593 | host->timeout_jiffies); | ||
594 | writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL), | 598 | writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL), |
595 | sock->addr + SOCK_CONTROL); | 599 | sock->addr + SOCK_CONTROL); |
596 | tifm_sd_exec(host, mrq->cmd); | 600 | tifm_sd_exec(host, mrq->cmd); |
597 | spin_unlock_irqrestore(&sock->lock, flags); | 601 | spin_unlock_irqrestore(&sock->lock, flags); |
598 | return; | 602 | return; |
599 | 603 | ||
600 | err_out: | 604 | err_out: |
601 | if (t_buffer) | ||
602 | kunmap(r_data->sg->page); | ||
603 | |||
604 | mrq->cmd->error = MMC_ERR_TIMEOUT; | 605 | mrq->cmd->error = MMC_ERR_TIMEOUT; |
605 | mmc_request_done(mmc, mrq); | 606 | mmc_request_done(mmc, mrq); |
606 | } | 607 | } |
607 | 608 | ||
608 | static void tifm_sd_end_cmd_nodma(struct work_struct *work) | 609 | static void tifm_sd_end_cmd_nodma(unsigned long data) |
609 | { | 610 | { |
610 | struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); | 611 | struct tifm_sd *host = (struct tifm_sd*)data; |
611 | struct tifm_dev *sock = host->dev; | 612 | struct tifm_dev *sock = host->dev; |
612 | struct mmc_host *mmc = tifm_get_drvdata(sock); | 613 | struct mmc_host *mmc = tifm_get_drvdata(sock); |
613 | struct mmc_request *mrq; | 614 | struct mmc_request *mrq; |
@@ -616,6 +617,7 @@ static void tifm_sd_end_cmd_nodma(struct work_struct *work) | |||
616 | 617 | ||
617 | spin_lock_irqsave(&sock->lock, flags); | 618 | spin_lock_irqsave(&sock->lock, flags); |
618 | 619 | ||
620 | del_timer(&host->timer); | ||
619 | mrq = host->req; | 621 | mrq = host->req; |
620 | host->req = NULL; | 622 | host->req = NULL; |
621 | host->state = IDLE; | 623 | host->state = IDLE; |
@@ -633,8 +635,8 @@ static void tifm_sd_end_cmd_nodma(struct work_struct *work) | |||
633 | sock->addr + SOCK_MMCSD_INT_ENABLE); | 635 | sock->addr + SOCK_MMCSD_INT_ENABLE); |
634 | 636 | ||
635 | if (r_data->flags & MMC_DATA_WRITE) { | 637 | if (r_data->flags & MMC_DATA_WRITE) { |
636 | r_data->bytes_xfered = host->written_blocks * | 638 | r_data->bytes_xfered = host->written_blocks |
637 | r_data->blksz; | 639 | * r_data->blksz; |
638 | } else { | 640 | } else { |
639 | r_data->bytes_xfered = r_data->blocks - | 641 | r_data->bytes_xfered = r_data->blocks - |
640 | readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1; | 642 | readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1; |
@@ -642,29 +644,44 @@ static void tifm_sd_end_cmd_nodma(struct work_struct *work) | |||
642 | r_data->bytes_xfered += r_data->blksz - | 644 | r_data->bytes_xfered += r_data->blksz - |
643 | readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1; | 645 | readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1; |
644 | } | 646 | } |
645 | host->buffer = NULL; | ||
646 | host->buffer_pos = 0; | 647 | host->buffer_pos = 0; |
647 | host->buffer_size = 0; | 648 | host->buffer_size = 0; |
648 | } | 649 | } |
649 | 650 | ||
650 | writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), | 651 | writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), |
651 | sock->addr + SOCK_CONTROL); | 652 | sock->addr + SOCK_CONTROL); |
652 | 653 | ||
653 | spin_unlock_irqrestore(&sock->lock, flags); | 654 | spin_unlock_irqrestore(&sock->lock, flags); |
654 | 655 | ||
655 | if (r_data) | ||
656 | kunmap(r_data->sg->page); | ||
657 | |||
658 | mmc_request_done(mmc, mrq); | 656 | mmc_request_done(mmc, mrq); |
659 | } | 657 | } |
660 | 658 | ||
661 | static void tifm_sd_abort(struct work_struct *work) | 659 | static void tifm_sd_terminate(struct tifm_sd *host) |
660 | { | ||
661 | struct tifm_dev *sock = host->dev; | ||
662 | unsigned long flags; | ||
663 | |||
664 | writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE); | ||
665 | mmiowb(); | ||
666 | spin_lock_irqsave(&sock->lock, flags); | ||
667 | host->flags |= EJECT; | ||
668 | if (host->req) { | ||
669 | writel(TIFM_FIFO_INT_SETALL, | ||
670 | sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); | ||
671 | writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); | ||
672 | tasklet_schedule(&host->finish_tasklet); | ||
673 | } | ||
674 | spin_unlock_irqrestore(&sock->lock, flags); | ||
675 | } | ||
676 | |||
677 | static void tifm_sd_abort(unsigned long data) | ||
662 | { | 678 | { |
663 | struct tifm_sd *host = | 679 | struct tifm_sd *host = (struct tifm_sd*)data; |
664 | container_of(work, struct tifm_sd, abort_handler.work); | ||
665 | 680 | ||
666 | printk(KERN_ERR DRIVER_NAME | 681 | printk(KERN_ERR DRIVER_NAME |
667 | ": card failed to respond for a long period of time"); | 682 | ": card failed to respond for a long period of time"); |
683 | |||
684 | tifm_sd_terminate(host); | ||
668 | tifm_eject(host->dev); | 685 | tifm_eject(host->dev); |
669 | } | 686 | } |
670 | 687 | ||
@@ -683,9 +700,9 @@ static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
683 | writel(TIFM_MMCSD_4BBUS | readl(sock->addr + SOCK_MMCSD_CONFIG), | 700 | writel(TIFM_MMCSD_4BBUS | readl(sock->addr + SOCK_MMCSD_CONFIG), |
684 | sock->addr + SOCK_MMCSD_CONFIG); | 701 | sock->addr + SOCK_MMCSD_CONFIG); |
685 | } else { | 702 | } else { |
686 | writel((~TIFM_MMCSD_4BBUS) & | 703 | writel((~TIFM_MMCSD_4BBUS) |
687 | readl(sock->addr + SOCK_MMCSD_CONFIG), | 704 | & readl(sock->addr + SOCK_MMCSD_CONFIG), |
688 | sock->addr + SOCK_MMCSD_CONFIG); | 705 | sock->addr + SOCK_MMCSD_CONFIG); |
689 | } | 706 | } |
690 | 707 | ||
691 | if (ios->clock) { | 708 | if (ios->clock) { |
@@ -704,23 +721,24 @@ static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
704 | if ((20000000 / clk_div1) > (24000000 / clk_div2)) { | 721 | if ((20000000 / clk_div1) > (24000000 / clk_div2)) { |
705 | host->clk_freq = 20000000; | 722 | host->clk_freq = 20000000; |
706 | host->clk_div = clk_div1; | 723 | host->clk_div = clk_div1; |
707 | writel((~TIFM_CTRL_FAST_CLK) & | 724 | writel((~TIFM_CTRL_FAST_CLK) |
708 | readl(sock->addr + SOCK_CONTROL), | 725 | & readl(sock->addr + SOCK_CONTROL), |
709 | sock->addr + SOCK_CONTROL); | 726 | sock->addr + SOCK_CONTROL); |
710 | } else { | 727 | } else { |
711 | host->clk_freq = 24000000; | 728 | host->clk_freq = 24000000; |
712 | host->clk_div = clk_div2; | 729 | host->clk_div = clk_div2; |
713 | writel(TIFM_CTRL_FAST_CLK | | 730 | writel(TIFM_CTRL_FAST_CLK |
714 | readl(sock->addr + SOCK_CONTROL), | 731 | | readl(sock->addr + SOCK_CONTROL), |
715 | sock->addr + SOCK_CONTROL); | 732 | sock->addr + SOCK_CONTROL); |
716 | } | 733 | } |
717 | } else { | 734 | } else { |
718 | host->clk_div = 0; | 735 | host->clk_div = 0; |
719 | } | 736 | } |
720 | host->clk_div &= TIFM_MMCSD_CLKMASK; | 737 | host->clk_div &= TIFM_MMCSD_CLKMASK; |
721 | writel(host->clk_div | ((~TIFM_MMCSD_CLKMASK) & | 738 | writel(host->clk_div |
722 | readl(sock->addr + SOCK_MMCSD_CONFIG)), | 739 | | ((~TIFM_MMCSD_CLKMASK) |
723 | sock->addr + SOCK_MMCSD_CONFIG); | 740 | & readl(sock->addr + SOCK_MMCSD_CONFIG)), |
741 | sock->addr + SOCK_MMCSD_CONFIG); | ||
724 | 742 | ||
725 | if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) | 743 | if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) |
726 | host->flags |= OPENDRAIN; | 744 | host->flags |= OPENDRAIN; |
@@ -734,7 +752,7 @@ static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
734 | // allow removal. | 752 | // allow removal. |
735 | if ((host->flags & EJECT) && ios->power_mode == MMC_POWER_OFF) { | 753 | if ((host->flags & EJECT) && ios->power_mode == MMC_POWER_OFF) { |
736 | host->flags |= EJECT_DONE; | 754 | host->flags |= EJECT_DONE; |
737 | wake_up_all(&host->can_eject); | 755 | wake_up_all(&host->notify); |
738 | } | 756 | } |
739 | 757 | ||
740 | spin_unlock_irqrestore(&sock->lock, flags); | 758 | spin_unlock_irqrestore(&sock->lock, flags); |
@@ -762,20 +780,67 @@ static struct mmc_host_ops tifm_sd_ops = { | |||
762 | .get_ro = tifm_sd_ro | 780 | .get_ro = tifm_sd_ro |
763 | }; | 781 | }; |
764 | 782 | ||
765 | static void tifm_sd_register_host(struct work_struct *work) | 783 | static int tifm_sd_initialize_host(struct tifm_sd *host) |
766 | { | 784 | { |
767 | struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); | 785 | int rc; |
786 | unsigned int host_status = 0; | ||
768 | struct tifm_dev *sock = host->dev; | 787 | struct tifm_dev *sock = host->dev; |
769 | struct mmc_host *mmc = tifm_get_drvdata(sock); | ||
770 | unsigned long flags; | ||
771 | 788 | ||
772 | spin_lock_irqsave(&sock->lock, flags); | 789 | writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE); |
773 | host->flags |= HOST_REG; | 790 | mmiowb(); |
774 | PREPARE_WORK(&host->cmd_handler, | 791 | host->clk_div = 61; |
775 | no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd); | 792 | host->clk_freq = 20000000; |
776 | spin_unlock_irqrestore(&sock->lock, flags); | 793 | writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL); |
777 | dev_dbg(&sock->dev, "adding host\n"); | 794 | writel(host->clk_div | TIFM_MMCSD_POWER, |
778 | mmc_add_host(mmc); | 795 | sock->addr + SOCK_MMCSD_CONFIG); |
796 | |||
797 | /* wait up to 0.51 sec for reset */ | ||
798 | for (rc = 2; rc <= 256; rc <<= 1) { | ||
799 | if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) { | ||
800 | rc = 0; | ||
801 | break; | ||
802 | } | ||
803 | msleep(rc); | ||
804 | } | ||
805 | |||
806 | if (rc) { | ||
807 | printk(KERN_ERR DRIVER_NAME | ||
808 | ": controller failed to reset\n"); | ||
809 | return -ENODEV; | ||
810 | } | ||
811 | |||
812 | writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS); | ||
813 | writel(host->clk_div | TIFM_MMCSD_POWER, | ||
814 | sock->addr + SOCK_MMCSD_CONFIG); | ||
815 | writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); | ||
816 | |||
817 | // command timeout fixed to 64 clocks for now | ||
818 | writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO); | ||
819 | writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND); | ||
820 | |||
821 | /* INAB should take much less than reset */ | ||
822 | for (rc = 1; rc <= 16; rc <<= 1) { | ||
823 | host_status = readl(sock->addr + SOCK_MMCSD_STATUS); | ||
824 | writel(host_status, sock->addr + SOCK_MMCSD_STATUS); | ||
825 | if (!(host_status & TIFM_MMCSD_ERRMASK) | ||
826 | && (host_status & TIFM_MMCSD_EOC)) { | ||
827 | rc = 0; | ||
828 | break; | ||
829 | } | ||
830 | msleep(rc); | ||
831 | } | ||
832 | |||
833 | if (rc) { | ||
834 | printk(KERN_ERR DRIVER_NAME | ||
835 | ": card not ready - probe failed on initialization\n"); | ||
836 | return -ENODEV; | ||
837 | } | ||
838 | |||
839 | writel(TIFM_MMCSD_DATAMASK | TIFM_MMCSD_ERRMASK, | ||
840 | sock->addr + SOCK_MMCSD_INT_ENABLE); | ||
841 | mmiowb(); | ||
842 | |||
843 | return 0; | ||
779 | } | 844 | } |
780 | 845 | ||
781 | static int tifm_sd_probe(struct tifm_dev *sock) | 846 | static int tifm_sd_probe(struct tifm_dev *sock) |
@@ -784,8 +849,8 @@ static int tifm_sd_probe(struct tifm_dev *sock) | |||
784 | struct tifm_sd *host; | 849 | struct tifm_sd *host; |
785 | int rc = -EIO; | 850 | int rc = -EIO; |
786 | 851 | ||
787 | if (!(TIFM_SOCK_STATE_OCCUPIED & | 852 | if (!(TIFM_SOCK_STATE_OCCUPIED |
788 | readl(sock->addr + SOCK_PRESENT_STATE))) { | 853 | & readl(sock->addr + SOCK_PRESENT_STATE))) { |
789 | printk(KERN_WARNING DRIVER_NAME ": card gone, unexpectedly\n"); | 854 | printk(KERN_WARNING DRIVER_NAME ": card gone, unexpectedly\n"); |
790 | return rc; | 855 | return rc; |
791 | } | 856 | } |
@@ -795,109 +860,99 @@ static int tifm_sd_probe(struct tifm_dev *sock) | |||
795 | return -ENOMEM; | 860 | return -ENOMEM; |
796 | 861 | ||
797 | host = mmc_priv(mmc); | 862 | host = mmc_priv(mmc); |
798 | host->dev = sock; | ||
799 | host->clk_div = 61; | ||
800 | init_waitqueue_head(&host->can_eject); | ||
801 | INIT_WORK(&host->cmd_handler, tifm_sd_register_host); | ||
802 | INIT_DELAYED_WORK(&host->abort_handler, tifm_sd_abort); | ||
803 | |||
804 | tifm_set_drvdata(sock, mmc); | 863 | tifm_set_drvdata(sock, mmc); |
805 | sock->signal_irq = tifm_sd_signal_irq; | 864 | host->dev = sock; |
806 | |||
807 | host->clk_freq = 20000000; | ||
808 | host->timeout_jiffies = msecs_to_jiffies(1000); | 865 | host->timeout_jiffies = msecs_to_jiffies(1000); |
809 | 866 | ||
867 | init_waitqueue_head(&host->notify); | ||
868 | tasklet_init(&host->finish_tasklet, | ||
869 | no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd, | ||
870 | (unsigned long)host); | ||
871 | setup_timer(&host->timer, tifm_sd_abort, (unsigned long)host); | ||
872 | |||
810 | tifm_sd_ops.request = no_dma ? tifm_sd_request_nodma : tifm_sd_request; | 873 | tifm_sd_ops.request = no_dma ? tifm_sd_request_nodma : tifm_sd_request; |
811 | mmc->ops = &tifm_sd_ops; | 874 | mmc->ops = &tifm_sd_ops; |
812 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | 875 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
813 | mmc->caps = MMC_CAP_4_BIT_DATA; | 876 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE; |
814 | mmc->f_min = 20000000 / 60; | 877 | mmc->f_min = 20000000 / 60; |
815 | mmc->f_max = 24000000; | 878 | mmc->f_max = 24000000; |
816 | mmc->max_hw_segs = 1; | 879 | mmc->max_hw_segs = 1; |
817 | mmc->max_phys_segs = 1; | 880 | mmc->max_phys_segs = 1; |
818 | mmc->max_sectors = 127; | 881 | // limited by DMA counter - it's safer to stick with |
819 | mmc->max_seg_size = mmc->max_sectors << 11; //2k maximum hw block length | 882 | // block counter has 11 bits though |
820 | 883 | mmc->max_blk_count = 256; | |
821 | writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE); | 884 | // 2k maximum hw block length |
822 | writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL); | 885 | mmc->max_blk_size = 2048; |
823 | writel(host->clk_div | TIFM_MMCSD_POWER, | 886 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
824 | sock->addr + SOCK_MMCSD_CONFIG); | 887 | mmc->max_seg_size = mmc->max_req_size; |
888 | sock->signal_irq = tifm_sd_signal_irq; | ||
889 | rc = tifm_sd_initialize_host(host); | ||
825 | 890 | ||
826 | for (rc = 0; rc < 50; rc++) { | 891 | if (!rc) |
827 | /* Wait for reset ack */ | 892 | rc = mmc_add_host(mmc); |
828 | if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) { | 893 | if (rc) |
829 | rc = 0; | 894 | goto out_free_mmc; |
830 | break; | ||
831 | } | ||
832 | msleep(10); | ||
833 | } | ||
834 | 895 | ||
835 | if (rc) { | 896 | return 0; |
836 | printk(KERN_ERR DRIVER_NAME | 897 | out_free_mmc: |
837 | ": card not ready - probe failed\n"); | 898 | mmc_free_host(mmc); |
838 | mmc_free_host(mmc); | 899 | return rc; |
839 | return -ENODEV; | 900 | } |
840 | } | ||
841 | 901 | ||
842 | writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS); | 902 | static void tifm_sd_remove(struct tifm_dev *sock) |
843 | writel(host->clk_div | TIFM_MMCSD_POWER, | 903 | { |
844 | sock->addr + SOCK_MMCSD_CONFIG); | 904 | struct mmc_host *mmc = tifm_get_drvdata(sock); |
845 | writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); | 905 | struct tifm_sd *host = mmc_priv(mmc); |
846 | writel(TIFM_MMCSD_DATAMASK | TIFM_MMCSD_ERRMASK, | ||
847 | sock->addr + SOCK_MMCSD_INT_ENABLE); | ||
848 | 906 | ||
849 | writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO); // command timeout 64 clocks for now | 907 | del_timer_sync(&host->timer); |
850 | writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND); | 908 | tifm_sd_terminate(host); |
851 | writel(host->clk_div | TIFM_MMCSD_POWER, | 909 | wait_event_timeout(host->notify, host->flags & EJECT_DONE, |
852 | sock->addr + SOCK_MMCSD_CONFIG); | 910 | host->timeout_jiffies); |
911 | tasklet_kill(&host->finish_tasklet); | ||
912 | mmc_remove_host(mmc); | ||
853 | 913 | ||
854 | queue_delayed_work(sock->wq, &host->abort_handler, | 914 | /* The meaning of the bit majority in this constant is unknown. */ |
855 | host->timeout_jiffies); | 915 | writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), |
916 | sock->addr + SOCK_CONTROL); | ||
856 | 917 | ||
857 | return 0; | 918 | tifm_set_drvdata(sock, NULL); |
919 | mmc_free_host(mmc); | ||
858 | } | 920 | } |
859 | 921 | ||
860 | static int tifm_sd_host_is_down(struct tifm_dev *sock) | 922 | #ifdef CONFIG_PM |
923 | |||
924 | static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state) | ||
861 | { | 925 | { |
862 | struct mmc_host *mmc = tifm_get_drvdata(sock); | 926 | struct mmc_host *mmc = tifm_get_drvdata(sock); |
863 | struct tifm_sd *host = mmc_priv(mmc); | 927 | int rc; |
864 | unsigned long flags; | ||
865 | int rc = 0; | ||
866 | 928 | ||
867 | spin_lock_irqsave(&sock->lock, flags); | 929 | rc = mmc_suspend_host(mmc, state); |
868 | rc = (host->flags & EJECT_DONE); | 930 | /* The meaning of the bit majority in this constant is unknown. */ |
869 | spin_unlock_irqrestore(&sock->lock, flags); | 931 | writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), |
932 | sock->addr + SOCK_CONTROL); | ||
870 | return rc; | 933 | return rc; |
871 | } | 934 | } |
872 | 935 | ||
873 | static void tifm_sd_remove(struct tifm_dev *sock) | 936 | static int tifm_sd_resume(struct tifm_dev *sock) |
874 | { | 937 | { |
875 | struct mmc_host *mmc = tifm_get_drvdata(sock); | 938 | struct mmc_host *mmc = tifm_get_drvdata(sock); |
876 | struct tifm_sd *host = mmc_priv(mmc); | 939 | struct tifm_sd *host = mmc_priv(mmc); |
877 | unsigned long flags; | ||
878 | 940 | ||
879 | spin_lock_irqsave(&sock->lock, flags); | 941 | if (sock->media_id != FM_SD |
880 | host->flags |= EJECT; | 942 | || tifm_sd_initialize_host(host)) { |
881 | if (host->req) | 943 | tifm_eject(sock); |
882 | queue_work(sock->wq, &host->cmd_handler); | 944 | return 0; |
883 | spin_unlock_irqrestore(&sock->lock, flags); | 945 | } else { |
884 | wait_event_timeout(host->can_eject, tifm_sd_host_is_down(sock), | 946 | return mmc_resume_host(mmc); |
885 | host->timeout_jiffies); | 947 | } |
948 | } | ||
886 | 949 | ||
887 | if (host->flags & HOST_REG) | 950 | #else |
888 | mmc_remove_host(mmc); | ||
889 | 951 | ||
890 | /* The meaning of the bit majority in this constant is unknown. */ | 952 | #define tifm_sd_suspend NULL |
891 | writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), | 953 | #define tifm_sd_resume NULL |
892 | sock->addr + SOCK_CONTROL); | ||
893 | writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE); | ||
894 | writel(TIFM_FIFO_INT_SETALL, | ||
895 | sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); | ||
896 | writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); | ||
897 | 954 | ||
898 | tifm_set_drvdata(sock, NULL); | 955 | #endif /* CONFIG_PM */ |
899 | mmc_free_host(mmc); | ||
900 | } | ||
901 | 956 | ||
902 | static tifm_media_id tifm_sd_id_tbl[] = { | 957 | static tifm_media_id tifm_sd_id_tbl[] = { |
903 | FM_SD, 0 | 958 | FM_SD, 0 |
@@ -910,7 +965,9 @@ static struct tifm_driver tifm_sd_driver = { | |||
910 | }, | 965 | }, |
911 | .id_table = tifm_sd_id_tbl, | 966 | .id_table = tifm_sd_id_tbl, |
912 | .probe = tifm_sd_probe, | 967 | .probe = tifm_sd_probe, |
913 | .remove = tifm_sd_remove | 968 | .remove = tifm_sd_remove, |
969 | .suspend = tifm_sd_suspend, | ||
970 | .resume = tifm_sd_resume | ||
914 | }; | 971 | }; |
915 | 972 | ||
916 | static int __init tifm_sd_init(void) | 973 | static int __init tifm_sd_init(void) |