diff options
author | Alex Dubov <oakad@yahoo.com> | 2008-03-19 20:01:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-03-19 21:53:37 -0400 |
commit | ead70773608a5d97f81cb492f117d20b5e9f323e (patch) | |
tree | fa71036f83c49c3b7aee99c11d152ddeb2b3599e /drivers/memstick | |
parent | 9df130392fb642ecd5564163b574ce69ffda1afa (diff) |
memstick: automatically retrieve "INT" value from command response
MemoryStick storage cards, when in parallel mode, send several meaningful bits
of their "INT" register as part of command response. This data is stored by
host and can be used to spare invocation of "GET_INT" TPC on each data page
transferred between host and card.
Signed-off-by: Alex Dubov <oakad@yahoo.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/memstick')
-rw-r--r-- | drivers/memstick/core/memstick.c | 9 | ||||
-rw-r--r-- | drivers/memstick/core/mspro_block.c | 15 | ||||
-rw-r--r-- | drivers/memstick/host/jmb38x_ms.c | 48 | ||||
-rw-r--r-- | drivers/memstick/host/tifm_ms.c | 17 |
4 files changed, 49 insertions, 40 deletions
diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c index de80dba12f9b..946e3d3506ac 100644 --- a/drivers/memstick/core/memstick.c +++ b/drivers/memstick/core/memstick.c | |||
@@ -276,8 +276,6 @@ void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc, | |||
276 | mrq->need_card_int = 1; | 276 | mrq->need_card_int = 1; |
277 | else | 277 | else |
278 | mrq->need_card_int = 0; | 278 | mrq->need_card_int = 0; |
279 | |||
280 | mrq->get_int_reg = 0; | ||
281 | } | 279 | } |
282 | EXPORT_SYMBOL(memstick_init_req_sg); | 280 | EXPORT_SYMBOL(memstick_init_req_sg); |
283 | 281 | ||
@@ -311,8 +309,6 @@ void memstick_init_req(struct memstick_request *mrq, unsigned char tpc, | |||
311 | mrq->need_card_int = 1; | 309 | mrq->need_card_int = 1; |
312 | else | 310 | else |
313 | mrq->need_card_int = 0; | 311 | mrq->need_card_int = 0; |
314 | |||
315 | mrq->get_int_reg = 0; | ||
316 | } | 312 | } |
317 | EXPORT_SYMBOL(memstick_init_req); | 313 | EXPORT_SYMBOL(memstick_init_req); |
318 | 314 | ||
@@ -342,6 +338,7 @@ static int h_memstick_read_dev_id(struct memstick_dev *card, | |||
342 | card->id.class = id_reg.class; | 338 | card->id.class = id_reg.class; |
343 | } | 339 | } |
344 | complete(&card->mrq_complete); | 340 | complete(&card->mrq_complete); |
341 | dev_dbg(&card->dev, "if_mode = %02x\n", id_reg.if_mode); | ||
345 | return -EAGAIN; | 342 | return -EAGAIN; |
346 | } | 343 | } |
347 | } | 344 | } |
@@ -422,7 +419,6 @@ static void memstick_power_on(struct memstick_host *host) | |||
422 | { | 419 | { |
423 | host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); | 420 | host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); |
424 | host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL); | 421 | host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL); |
425 | msleep(1); | ||
426 | } | 422 | } |
427 | 423 | ||
428 | static void memstick_check(struct work_struct *work) | 424 | static void memstick_check(struct work_struct *work) |
@@ -579,7 +575,8 @@ EXPORT_SYMBOL(memstick_suspend_host); | |||
579 | void memstick_resume_host(struct memstick_host *host) | 575 | void memstick_resume_host(struct memstick_host *host) |
580 | { | 576 | { |
581 | mutex_lock(&host->lock); | 577 | mutex_lock(&host->lock); |
582 | host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); | 578 | if (host->card) |
579 | memstick_power_on(host); | ||
583 | mutex_unlock(&host->lock); | 580 | mutex_unlock(&host->lock); |
584 | memstick_detect_change(host); | 581 | memstick_detect_change(host); |
585 | } | 582 | } |
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 1d637e4561d3..e5356f97d076 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c | |||
@@ -133,6 +133,7 @@ struct mspro_devinfo { | |||
133 | struct mspro_block_data { | 133 | struct mspro_block_data { |
134 | struct memstick_dev *card; | 134 | struct memstick_dev *card; |
135 | unsigned int usage_count; | 135 | unsigned int usage_count; |
136 | unsigned int caps; | ||
136 | struct gendisk *disk; | 137 | struct gendisk *disk; |
137 | struct request_queue *queue; | 138 | struct request_queue *queue; |
138 | spinlock_t q_lock; | 139 | spinlock_t q_lock; |
@@ -577,7 +578,6 @@ static int h_mspro_block_wait_for_ced(struct memstick_dev *card, | |||
577 | static int h_mspro_block_transfer_data(struct memstick_dev *card, | 578 | static int h_mspro_block_transfer_data(struct memstick_dev *card, |
578 | struct memstick_request **mrq) | 579 | struct memstick_request **mrq) |
579 | { | 580 | { |
580 | struct memstick_host *host = card->host; | ||
581 | struct mspro_block_data *msb = memstick_get_drvdata(card); | 581 | struct mspro_block_data *msb = memstick_get_drvdata(card); |
582 | unsigned char t_val = 0; | 582 | unsigned char t_val = 0; |
583 | struct scatterlist t_sg = { 0 }; | 583 | struct scatterlist t_sg = { 0 }; |
@@ -591,12 +591,12 @@ static int h_mspro_block_transfer_data(struct memstick_dev *card, | |||
591 | switch ((*mrq)->tpc) { | 591 | switch ((*mrq)->tpc) { |
592 | case MS_TPC_WRITE_REG: | 592 | case MS_TPC_WRITE_REG: |
593 | memstick_init_req(*mrq, MS_TPC_SET_CMD, &msb->transfer_cmd, 1); | 593 | memstick_init_req(*mrq, MS_TPC_SET_CMD, &msb->transfer_cmd, 1); |
594 | (*mrq)->get_int_reg = 1; | 594 | (*mrq)->need_card_int = 1; |
595 | return 0; | 595 | return 0; |
596 | case MS_TPC_SET_CMD: | 596 | case MS_TPC_SET_CMD: |
597 | t_val = (*mrq)->int_reg; | 597 | t_val = (*mrq)->int_reg; |
598 | memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1); | 598 | memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1); |
599 | if (host->caps & MEMSTICK_CAP_AUTO_GET_INT) | 599 | if (msb->caps & MEMSTICK_CAP_AUTO_GET_INT) |
600 | goto has_int_reg; | 600 | goto has_int_reg; |
601 | return 0; | 601 | return 0; |
602 | case MS_TPC_GET_INT: | 602 | case MS_TPC_GET_INT: |
@@ -646,12 +646,12 @@ has_int_reg: | |||
646 | ? MS_TPC_READ_LONG_DATA | 646 | ? MS_TPC_READ_LONG_DATA |
647 | : MS_TPC_WRITE_LONG_DATA, | 647 | : MS_TPC_WRITE_LONG_DATA, |
648 | &t_sg); | 648 | &t_sg); |
649 | (*mrq)->get_int_reg = 1; | 649 | (*mrq)->need_card_int = 1; |
650 | return 0; | 650 | return 0; |
651 | case MS_TPC_READ_LONG_DATA: | 651 | case MS_TPC_READ_LONG_DATA: |
652 | case MS_TPC_WRITE_LONG_DATA: | 652 | case MS_TPC_WRITE_LONG_DATA: |
653 | msb->current_page++; | 653 | msb->current_page++; |
654 | if (host->caps & MEMSTICK_CAP_AUTO_GET_INT) { | 654 | if (msb->caps & MEMSTICK_CAP_AUTO_GET_INT) { |
655 | t_val = (*mrq)->int_reg; | 655 | t_val = (*mrq)->int_reg; |
656 | goto has_int_reg; | 656 | goto has_int_reg; |
657 | } else { | 657 | } else { |
@@ -1052,7 +1052,8 @@ static int mspro_block_init_card(struct memstick_dev *card) | |||
1052 | if (memstick_set_rw_addr(card)) | 1052 | if (memstick_set_rw_addr(card)) |
1053 | return -EIO; | 1053 | return -EIO; |
1054 | 1054 | ||
1055 | if (host->caps & MEMSTICK_CAP_PAR4) { | 1055 | msb->caps = host->caps; |
1056 | if (msb->caps & MEMSTICK_CAP_PAR4) { | ||
1056 | if (mspro_block_switch_to_parallel(card)) | 1057 | if (mspro_block_switch_to_parallel(card)) |
1057 | printk(KERN_WARNING "%s: could not switch to " | 1058 | printk(KERN_WARNING "%s: could not switch to " |
1058 | "parallel interface\n", card->dev.bus_id); | 1059 | "parallel interface\n", card->dev.bus_id); |
@@ -1062,6 +1063,8 @@ static int mspro_block_init_card(struct memstick_dev *card) | |||
1062 | if (rc) | 1063 | if (rc) |
1063 | return rc; | 1064 | return rc; |
1064 | dev_dbg(&card->dev, "card activated\n"); | 1065 | dev_dbg(&card->dev, "card activated\n"); |
1066 | if (msb->system != MEMSTICK_SYS_SERIAL) | ||
1067 | msb->caps |= MEMSTICK_CAP_AUTO_GET_INT; | ||
1065 | 1068 | ||
1066 | card->next_request = h_mspro_block_req_init; | 1069 | card->next_request = h_mspro_block_req_init; |
1067 | msb->mrq_handler = h_mspro_block_get_ro; | 1070 | msb->mrq_handler = h_mspro_block_get_ro; |
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c index 9a57504183c7..f91037d50422 100644 --- a/drivers/memstick/host/jmb38x_ms.c +++ b/drivers/memstick/host/jmb38x_ms.c | |||
@@ -57,8 +57,6 @@ struct jmb38x_ms_host { | |||
57 | unsigned long timeout_jiffies; | 57 | unsigned long timeout_jiffies; |
58 | struct timer_list timer; | 58 | struct timer_list timer; |
59 | struct memstick_request *req; | 59 | struct memstick_request *req; |
60 | unsigned char eject:1, | ||
61 | use_dma:1; | ||
62 | unsigned char cmd_flags; | 60 | unsigned char cmd_flags; |
63 | unsigned char io_pos; | 61 | unsigned char io_pos; |
64 | unsigned int io_word[2]; | 62 | unsigned int io_word[2]; |
@@ -95,9 +93,22 @@ struct jmb38x_ms { | |||
95 | #define HOST_CONTROL_IF_PAR4 0x1 | 93 | #define HOST_CONTROL_IF_PAR4 0x1 |
96 | #define HOST_CONTROL_IF_PAR8 0x3 | 94 | #define HOST_CONTROL_IF_PAR8 0x3 |
97 | 95 | ||
96 | #define STATUS_BUSY 0x00080000 | ||
97 | #define STATUS_MS_DAT7 0x00040000 | ||
98 | #define STATUS_MS_DAT6 0x00020000 | ||
99 | #define STATUS_MS_DAT5 0x00010000 | ||
100 | #define STATUS_MS_DAT4 0x00008000 | ||
101 | #define STATUS_MS_DAT3 0x00004000 | ||
102 | #define STATUS_MS_DAT2 0x00002000 | ||
103 | #define STATUS_MS_DAT1 0x00001000 | ||
104 | #define STATUS_MS_DAT0 0x00000800 | ||
98 | #define STATUS_HAS_MEDIA 0x00000400 | 105 | #define STATUS_HAS_MEDIA 0x00000400 |
99 | #define STATUS_FIFO_EMPTY 0x00000200 | 106 | #define STATUS_FIFO_EMPTY 0x00000200 |
100 | #define STATUS_FIFO_FULL 0x00000100 | 107 | #define STATUS_FIFO_FULL 0x00000100 |
108 | #define STATUS_MS_CED 0x00000080 | ||
109 | #define STATUS_MS_ERR 0x00000040 | ||
110 | #define STATUS_MS_BRQ 0x00000020 | ||
111 | #define STATUS_MS_CNK 0x00000001 | ||
101 | 112 | ||
102 | #define INT_STATUS_TPC_ERR 0x00080000 | 113 | #define INT_STATUS_TPC_ERR 0x00080000 |
103 | #define INT_STATUS_CRC_ERR 0x00040000 | 114 | #define INT_STATUS_CRC_ERR 0x00040000 |
@@ -124,7 +135,7 @@ enum { | |||
124 | CMD_READY = 0x01, | 135 | CMD_READY = 0x01, |
125 | FIFO_READY = 0x02, | 136 | FIFO_READY = 0x02, |
126 | REG_DATA = 0x04, | 137 | REG_DATA = 0x04, |
127 | AUTO_GET_INT = 0x08 | 138 | DMA_DATA = 0x08 |
128 | }; | 139 | }; |
129 | 140 | ||
130 | static unsigned int jmb38x_ms_read_data(struct jmb38x_ms_host *host, | 141 | static unsigned int jmb38x_ms_read_data(struct jmb38x_ms_host *host, |
@@ -367,28 +378,27 @@ static int jmb38x_ms_issue_cmd(struct memstick_host *msh) | |||
367 | cmd |= TPC_DIR; | 378 | cmd |= TPC_DIR; |
368 | if (host->req->need_card_int) | 379 | if (host->req->need_card_int) |
369 | cmd |= TPC_WAIT_INT; | 380 | cmd |= TPC_WAIT_INT; |
370 | if (host->req->get_int_reg) | ||
371 | cmd |= TPC_GET_INT; | ||
372 | 381 | ||
373 | data = host->req->data; | 382 | data = host->req->data; |
374 | 383 | ||
375 | host->use_dma = !no_dma; | 384 | if (!no_dma) |
385 | host->cmd_flags |= DMA_DATA; | ||
376 | 386 | ||
377 | if (host->req->long_data) { | 387 | if (host->req->long_data) { |
378 | data_len = host->req->sg.length; | 388 | data_len = host->req->sg.length; |
379 | } else { | 389 | } else { |
380 | data_len = host->req->data_len; | 390 | data_len = host->req->data_len; |
381 | host->use_dma = 0; | 391 | host->cmd_flags &= ~DMA_DATA; |
382 | } | 392 | } |
383 | 393 | ||
384 | if (data_len <= 8) { | 394 | if (data_len <= 8) { |
385 | cmd &= ~(TPC_DATA_SEL | 0xf); | 395 | cmd &= ~(TPC_DATA_SEL | 0xf); |
386 | host->cmd_flags |= REG_DATA; | 396 | host->cmd_flags |= REG_DATA; |
387 | cmd |= data_len & 0xf; | 397 | cmd |= data_len & 0xf; |
388 | host->use_dma = 0; | 398 | host->cmd_flags &= ~DMA_DATA; |
389 | } | 399 | } |
390 | 400 | ||
391 | if (host->use_dma) { | 401 | if (host->cmd_flags & DMA_DATA) { |
392 | if (1 != pci_map_sg(host->chip->pdev, &host->req->sg, 1, | 402 | if (1 != pci_map_sg(host->chip->pdev, &host->req->sg, 1, |
393 | host->req->data_dir == READ | 403 | host->req->data_dir == READ |
394 | ? PCI_DMA_FROMDEVICE | 404 | ? PCI_DMA_FROMDEVICE |
@@ -451,13 +461,12 @@ static void jmb38x_ms_complete_cmd(struct memstick_host *msh, int last) | |||
451 | readl(host->addr + INT_STATUS)); | 461 | readl(host->addr + INT_STATUS)); |
452 | dev_dbg(msh->cdev.dev, "c hstatus %08x\n", readl(host->addr + STATUS)); | 462 | dev_dbg(msh->cdev.dev, "c hstatus %08x\n", readl(host->addr + STATUS)); |
453 | 463 | ||
454 | if (host->req->get_int_reg) { | 464 | host->req->int_reg = readl(host->addr + STATUS) & 0xff; |
455 | t_val = readl(host->addr + TPC_P0); | 465 | |
456 | host->req->int_reg = (t_val & 0xff); | 466 | writel(0, host->addr + BLOCK); |
457 | } | 467 | writel(0, host->addr + DMA_CONTROL); |
458 | 468 | ||
459 | if (host->use_dma) { | 469 | if (host->cmd_flags & DMA_DATA) { |
460 | writel(0, host->addr + DMA_CONTROL); | ||
461 | pci_unmap_sg(host->chip->pdev, &host->req->sg, 1, | 470 | pci_unmap_sg(host->chip->pdev, &host->req->sg, 1, |
462 | host->req->data_dir == READ | 471 | host->req->data_dir == READ |
463 | ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); | 472 | ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); |
@@ -509,7 +518,7 @@ static irqreturn_t jmb38x_ms_isr(int irq, void *dev_id) | |||
509 | else | 518 | else |
510 | host->req->error = -ETIME; | 519 | host->req->error = -ETIME; |
511 | } else { | 520 | } else { |
512 | if (host->use_dma) { | 521 | if (host->cmd_flags & DMA_DATA) { |
513 | if (irq_status & INT_STATUS_EOTRAN) | 522 | if (irq_status & INT_STATUS_EOTRAN) |
514 | host->cmd_flags |= FIFO_READY; | 523 | host->cmd_flags |= FIFO_READY; |
515 | } else { | 524 | } else { |
@@ -775,13 +784,10 @@ static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt) | |||
775 | snprintf(host->host_id, DEVICE_ID_SIZE, DRIVER_NAME ":slot%d", | 784 | snprintf(host->host_id, DEVICE_ID_SIZE, DRIVER_NAME ":slot%d", |
776 | host->id); | 785 | host->id); |
777 | host->irq = jm->pdev->irq; | 786 | host->irq = jm->pdev->irq; |
778 | host->timeout_jiffies = msecs_to_jiffies(4000); | 787 | host->timeout_jiffies = msecs_to_jiffies(1000); |
779 | msh->request = jmb38x_ms_request; | 788 | msh->request = jmb38x_ms_request; |
780 | msh->set_param = jmb38x_ms_set_param; | 789 | msh->set_param = jmb38x_ms_set_param; |
781 | /* | 790 | |
782 | msh->caps = MEMSTICK_CAP_AUTO_GET_INT | MEMSTICK_CAP_PAR4 | ||
783 | | MEMSTICK_CAP_PAR8; | ||
784 | */ | ||
785 | msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8; | 791 | msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8; |
786 | 792 | ||
787 | setup_timer(&host->timer, jmb38x_ms_abort, (unsigned long)msh); | 793 | setup_timer(&host->timer, jmb38x_ms_abort, (unsigned long)msh); |
diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c index 2b5bf52a8302..eb150dfb637f 100644 --- a/drivers/memstick/host/tifm_ms.c +++ b/drivers/memstick/host/tifm_ms.c | |||
@@ -340,11 +340,20 @@ static void tifm_ms_complete_cmd(struct tifm_ms *host) | |||
340 | 340 | ||
341 | del_timer(&host->timer); | 341 | del_timer(&host->timer); |
342 | 342 | ||
343 | if (host->use_dma) | 343 | host->req->int_reg = readl(sock->addr + SOCK_MS_STATUS) & 0xff; |
344 | host->req->int_reg = (host->req->int_reg & 1) | ||
345 | | ((host->req->int_reg << 4) & 0xe0); | ||
346 | |||
347 | writel(TIFM_FIFO_INT_SETALL, | ||
348 | sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); | ||
349 | writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); | ||
350 | |||
351 | if (host->use_dma) { | ||
344 | tifm_unmap_sg(sock, &host->req->sg, 1, | 352 | tifm_unmap_sg(sock, &host->req->sg, 1, |
345 | host->req->data_dir == READ | 353 | host->req->data_dir == READ |
346 | ? PCI_DMA_FROMDEVICE | 354 | ? PCI_DMA_FROMDEVICE |
347 | : PCI_DMA_TODEVICE); | 355 | : PCI_DMA_TODEVICE); |
356 | } | ||
348 | 357 | ||
349 | writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), | 358 | writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), |
350 | sock->addr + SOCK_CONTROL); | 359 | sock->addr + SOCK_CONTROL); |
@@ -424,12 +433,6 @@ static void tifm_ms_card_event(struct tifm_dev *sock) | |||
424 | else if (host_status & TIFM_MS_STAT_CRC) | 433 | else if (host_status & TIFM_MS_STAT_CRC) |
425 | host->req->error = -EILSEQ; | 434 | host->req->error = -EILSEQ; |
426 | 435 | ||
427 | if (host->req->error) { | ||
428 | writel(TIFM_FIFO_INT_SETALL, | ||
429 | sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); | ||
430 | writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); | ||
431 | } | ||
432 | |||
433 | if (host_status & TIFM_MS_STAT_RDY) | 436 | if (host_status & TIFM_MS_STAT_RDY) |
434 | host->cmd_flags |= CMD_READY; | 437 | host->cmd_flags |= CMD_READY; |
435 | 438 | ||