aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/memstick/host/jmb38x_ms.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-04-03 17:33:42 -0400
committerDavid S. Miller <davem@davemloft.net>2008-04-03 17:33:42 -0400
commit3bb5da3837cc1aa17736b05139c9a22c3794851a (patch)
treec92d5684a866542b1cb20641607ac1643ce03a47 /drivers/memstick/host/jmb38x_ms.c
parent7feb49c82a74bc7c091b8ab2a3f96baa33d08ece (diff)
parent9597362d354f8655ece324b01d0c640a0e99c077 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
Diffstat (limited to 'drivers/memstick/host/jmb38x_ms.c')
-rw-r--r--drivers/memstick/host/jmb38x_ms.c113
1 files changed, 61 insertions, 52 deletions
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c
index 03fe8783b1ee..8770a5fac3b6 100644
--- a/drivers/memstick/host/jmb38x_ms.c
+++ b/drivers/memstick/host/jmb38x_ms.c
@@ -12,6 +12,7 @@
12#include <linux/spinlock.h> 12#include <linux/spinlock.h>
13#include <linux/interrupt.h> 13#include <linux/interrupt.h>
14#include <linux/pci.h> 14#include <linux/pci.h>
15#include <linux/dma-mapping.h>
15#include <linux/delay.h> 16#include <linux/delay.h>
16#include <linux/highmem.h> 17#include <linux/highmem.h>
17#include <linux/memstick.h> 18#include <linux/memstick.h>
@@ -56,8 +57,6 @@ struct jmb38x_ms_host {
56 unsigned long timeout_jiffies; 57 unsigned long timeout_jiffies;
57 struct timer_list timer; 58 struct timer_list timer;
58 struct memstick_request *req; 59 struct memstick_request *req;
59 unsigned char eject:1,
60 use_dma:1;
61 unsigned char cmd_flags; 60 unsigned char cmd_flags;
62 unsigned char io_pos; 61 unsigned char io_pos;
63 unsigned int io_word[2]; 62 unsigned int io_word[2];
@@ -94,9 +93,22 @@ struct jmb38x_ms {
94#define HOST_CONTROL_IF_PAR4 0x1 93#define HOST_CONTROL_IF_PAR4 0x1
95#define HOST_CONTROL_IF_PAR8 0x3 94#define HOST_CONTROL_IF_PAR8 0x3
96 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
97#define STATUS_HAS_MEDIA 0x00000400 105#define STATUS_HAS_MEDIA 0x00000400
98#define STATUS_FIFO_EMPTY 0x00000200 106#define STATUS_FIFO_EMPTY 0x00000200
99#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
100 112
101#define INT_STATUS_TPC_ERR 0x00080000 113#define INT_STATUS_TPC_ERR 0x00080000
102#define INT_STATUS_CRC_ERR 0x00040000 114#define INT_STATUS_CRC_ERR 0x00040000
@@ -119,11 +131,17 @@ struct jmb38x_ms {
119#define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000 131#define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000
120#define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000 132#define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000
121 133
134#define CLOCK_CONTROL_40MHZ 0x00000001
135#define CLOCK_CONTROL_50MHZ 0x00000002
136#define CLOCK_CONTROL_60MHZ 0x00000008
137#define CLOCK_CONTROL_62_5MHZ 0x0000000c
138#define CLOCK_CONTROL_OFF 0x00000000
139
122enum { 140enum {
123 CMD_READY = 0x01, 141 CMD_READY = 0x01,
124 FIFO_READY = 0x02, 142 FIFO_READY = 0x02,
125 REG_DATA = 0x04, 143 REG_DATA = 0x04,
126 AUTO_GET_INT = 0x08 144 DMA_DATA = 0x08
127}; 145};
128 146
129static unsigned int jmb38x_ms_read_data(struct jmb38x_ms_host *host, 147static unsigned int jmb38x_ms_read_data(struct jmb38x_ms_host *host,
@@ -273,7 +291,7 @@ static int jmb38x_ms_transfer_data(struct jmb38x_ms_host *host)
273{ 291{
274 unsigned int length; 292 unsigned int length;
275 unsigned int off; 293 unsigned int off;
276 unsigned int t_size, p_off, p_cnt; 294 unsigned int t_size, p_cnt;
277 unsigned char *buf; 295 unsigned char *buf;
278 struct page *pg; 296 struct page *pg;
279 unsigned long flags = 0; 297 unsigned long flags = 0;
@@ -287,6 +305,8 @@ static int jmb38x_ms_transfer_data(struct jmb38x_ms_host *host)
287 } 305 }
288 306
289 while (length) { 307 while (length) {
308 unsigned int uninitialized_var(p_off);
309
290 if (host->req->long_data) { 310 if (host->req->long_data) {
291 pg = nth_page(sg_page(&host->req->sg), 311 pg = nth_page(sg_page(&host->req->sg),
292 off >> PAGE_SHIFT); 312 off >> PAGE_SHIFT);
@@ -364,28 +384,27 @@ static int jmb38x_ms_issue_cmd(struct memstick_host *msh)
364 cmd |= TPC_DIR; 384 cmd |= TPC_DIR;
365 if (host->req->need_card_int) 385 if (host->req->need_card_int)
366 cmd |= TPC_WAIT_INT; 386 cmd |= TPC_WAIT_INT;
367 if (host->req->get_int_reg)
368 cmd |= TPC_GET_INT;
369 387
370 data = host->req->data; 388 data = host->req->data;
371 389
372 host->use_dma = !no_dma; 390 if (!no_dma)
391 host->cmd_flags |= DMA_DATA;
373 392
374 if (host->req->long_data) { 393 if (host->req->long_data) {
375 data_len = host->req->sg.length; 394 data_len = host->req->sg.length;
376 } else { 395 } else {
377 data_len = host->req->data_len; 396 data_len = host->req->data_len;
378 host->use_dma = 0; 397 host->cmd_flags &= ~DMA_DATA;
379 } 398 }
380 399
381 if (data_len <= 8) { 400 if (data_len <= 8) {
382 cmd &= ~(TPC_DATA_SEL | 0xf); 401 cmd &= ~(TPC_DATA_SEL | 0xf);
383 host->cmd_flags |= REG_DATA; 402 host->cmd_flags |= REG_DATA;
384 cmd |= data_len & 0xf; 403 cmd |= data_len & 0xf;
385 host->use_dma = 0; 404 host->cmd_flags &= ~DMA_DATA;
386 } 405 }
387 406
388 if (host->use_dma) { 407 if (host->cmd_flags & DMA_DATA) {
389 if (1 != pci_map_sg(host->chip->pdev, &host->req->sg, 1, 408 if (1 != pci_map_sg(host->chip->pdev, &host->req->sg, 1,
390 host->req->data_dir == READ 409 host->req->data_dir == READ
391 ? PCI_DMA_FROMDEVICE 410 ? PCI_DMA_FROMDEVICE
@@ -448,13 +467,12 @@ static void jmb38x_ms_complete_cmd(struct memstick_host *msh, int last)
448 readl(host->addr + INT_STATUS)); 467 readl(host->addr + INT_STATUS));
449 dev_dbg(msh->cdev.dev, "c hstatus %08x\n", readl(host->addr + STATUS)); 468 dev_dbg(msh->cdev.dev, "c hstatus %08x\n", readl(host->addr + STATUS));
450 469
451 if (host->req->get_int_reg) { 470 host->req->int_reg = readl(host->addr + STATUS) & 0xff;
452 t_val = readl(host->addr + TPC_P0); 471
453 host->req->int_reg = (t_val & 0xff); 472 writel(0, host->addr + BLOCK);
454 } 473 writel(0, host->addr + DMA_CONTROL);
455 474
456 if (host->use_dma) { 475 if (host->cmd_flags & DMA_DATA) {
457 writel(0, host->addr + DMA_CONTROL);
458 pci_unmap_sg(host->chip->pdev, &host->req->sg, 1, 476 pci_unmap_sg(host->chip->pdev, &host->req->sg, 1,
459 host->req->data_dir == READ 477 host->req->data_dir == READ
460 ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); 478 ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
@@ -506,7 +524,7 @@ static irqreturn_t jmb38x_ms_isr(int irq, void *dev_id)
506 else 524 else
507 host->req->error = -ETIME; 525 host->req->error = -ETIME;
508 } else { 526 } else {
509 if (host->use_dma) { 527 if (host->cmd_flags & DMA_DATA) {
510 if (irq_status & INT_STATUS_EOTRAN) 528 if (irq_status & INT_STATUS_EOTRAN)
511 host->cmd_flags |= FIFO_READY; 529 host->cmd_flags |= FIFO_READY;
512 } else { 530 } else {
@@ -595,19 +613,18 @@ static void jmb38x_ms_reset(struct jmb38x_ms_host *host)
595{ 613{
596 unsigned int host_ctl = readl(host->addr + HOST_CONTROL); 614 unsigned int host_ctl = readl(host->addr + HOST_CONTROL);
597 615
598 writel(host_ctl | HOST_CONTROL_RESET_REQ | HOST_CONTROL_RESET, 616 writel(HOST_CONTROL_RESET_REQ, host->addr + HOST_CONTROL);
599 host->addr + HOST_CONTROL);
600 617
601 while (HOST_CONTROL_RESET_REQ 618 while (HOST_CONTROL_RESET_REQ
602 & (host_ctl = readl(host->addr + HOST_CONTROL))) { 619 & (host_ctl = readl(host->addr + HOST_CONTROL))) {
603 ndelay(100); 620 ndelay(20);
604 dev_dbg(&host->chip->pdev->dev, "reset\n"); 621 dev_dbg(&host->chip->pdev->dev, "reset %08x\n", host_ctl);
605 } 622 }
606 623
607 writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE); 624 writel(HOST_CONTROL_RESET, host->addr + HOST_CONTROL);
625 mmiowb();
608 writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE); 626 writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE);
609 627 writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE);
610 dev_dbg(&host->chip->pdev->dev, "reset\n");
611} 628}
612 629
613static void jmb38x_ms_set_param(struct memstick_host *msh, 630static void jmb38x_ms_set_param(struct memstick_host *msh,
@@ -615,10 +632,8 @@ static void jmb38x_ms_set_param(struct memstick_host *msh,
615 int value) 632 int value)
616{ 633{
617 struct jmb38x_ms_host *host = memstick_priv(msh); 634 struct jmb38x_ms_host *host = memstick_priv(msh);
618 unsigned int host_ctl; 635 unsigned int host_ctl = readl(host->addr + HOST_CONTROL);
619 unsigned long flags; 636 unsigned int clock_ctl = CLOCK_CONTROL_40MHZ, clock_delay = 0;
620
621 spin_lock_irqsave(&host->lock, flags);
622 637
623 switch (param) { 638 switch (param) {
624 case MEMSTICK_POWER: 639 case MEMSTICK_POWER:
@@ -626,60 +641,57 @@ static void jmb38x_ms_set_param(struct memstick_host *msh,
626 jmb38x_ms_reset(host); 641 jmb38x_ms_reset(host);
627 642
628 writel(host->id ? PAD_PU_PD_ON_MS_SOCK1 643 writel(host->id ? PAD_PU_PD_ON_MS_SOCK1
629 : PAD_PU_PD_ON_MS_SOCK0, 644 : PAD_PU_PD_ON_MS_SOCK0,
630 host->addr + PAD_PU_PD); 645 host->addr + PAD_PU_PD);
631 646
632 writel(PAD_OUTPUT_ENABLE_MS, 647 writel(PAD_OUTPUT_ENABLE_MS,
633 host->addr + PAD_OUTPUT_ENABLE); 648 host->addr + PAD_OUTPUT_ENABLE);
634 649
635 host_ctl = readl(host->addr + HOST_CONTROL); 650 host_ctl = 7;
636 host_ctl |= 7; 651 host_ctl |= HOST_CONTROL_POWER_EN
637 writel(host_ctl | (HOST_CONTROL_POWER_EN 652 | HOST_CONTROL_CLOCK_EN;
638 | HOST_CONTROL_CLOCK_EN), 653 writel(host_ctl, host->addr + HOST_CONTROL);
639 host->addr + HOST_CONTROL);
640 654
641 dev_dbg(&host->chip->pdev->dev, "power on\n"); 655 dev_dbg(&host->chip->pdev->dev, "power on\n");
642 } else if (value == MEMSTICK_POWER_OFF) { 656 } else if (value == MEMSTICK_POWER_OFF) {
643 writel(readl(host->addr + HOST_CONTROL) 657 host_ctl &= ~(HOST_CONTROL_POWER_EN
644 & ~(HOST_CONTROL_POWER_EN 658 | HOST_CONTROL_CLOCK_EN);
645 | HOST_CONTROL_CLOCK_EN), 659 writel(host_ctl, host->addr + HOST_CONTROL);
646 host->addr + HOST_CONTROL);
647 writel(0, host->addr + PAD_OUTPUT_ENABLE); 660 writel(0, host->addr + PAD_OUTPUT_ENABLE);
648 writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD); 661 writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD);
649 dev_dbg(&host->chip->pdev->dev, "power off\n"); 662 dev_dbg(&host->chip->pdev->dev, "power off\n");
650 } 663 }
651 break; 664 break;
652 case MEMSTICK_INTERFACE: 665 case MEMSTICK_INTERFACE:
653 /* jmb38x_ms_reset(host); */
654
655 host_ctl = readl(host->addr + HOST_CONTROL);
656 host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT); 666 host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT);
657 /* host_ctl |= 7; */
658 667
659 if (value == MEMSTICK_SERIAL) { 668 if (value == MEMSTICK_SERIAL) {
660 host_ctl &= ~HOST_CONTROL_FAST_CLK; 669 host_ctl &= ~HOST_CONTROL_FAST_CLK;
661 host_ctl |= HOST_CONTROL_IF_SERIAL 670 host_ctl |= HOST_CONTROL_IF_SERIAL
662 << HOST_CONTROL_IF_SHIFT; 671 << HOST_CONTROL_IF_SHIFT;
663 host_ctl |= HOST_CONTROL_REI; 672 host_ctl |= HOST_CONTROL_REI;
664 writel(0, host->addr + CLOCK_DELAY); 673 clock_ctl = CLOCK_CONTROL_40MHZ;
674 clock_delay = 0;
665 } else if (value == MEMSTICK_PAR4) { 675 } else if (value == MEMSTICK_PAR4) {
666 host_ctl |= HOST_CONTROL_FAST_CLK; 676 host_ctl |= HOST_CONTROL_FAST_CLK;
667 host_ctl |= HOST_CONTROL_IF_PAR4 677 host_ctl |= HOST_CONTROL_IF_PAR4
668 << HOST_CONTROL_IF_SHIFT; 678 << HOST_CONTROL_IF_SHIFT;
669 host_ctl &= ~HOST_CONTROL_REI; 679 host_ctl &= ~HOST_CONTROL_REI;
670 writel(4, host->addr + CLOCK_DELAY); 680 clock_ctl = CLOCK_CONTROL_40MHZ;
681 clock_delay = 4;
671 } else if (value == MEMSTICK_PAR8) { 682 } else if (value == MEMSTICK_PAR8) {
672 host_ctl |= HOST_CONTROL_FAST_CLK; 683 host_ctl |= HOST_CONTROL_FAST_CLK;
673 host_ctl |= HOST_CONTROL_IF_PAR8 684 host_ctl |= HOST_CONTROL_IF_PAR8
674 << HOST_CONTROL_IF_SHIFT; 685 << HOST_CONTROL_IF_SHIFT;
675 host_ctl &= ~HOST_CONTROL_REI; 686 host_ctl &= ~HOST_CONTROL_REI;
676 writel(4, host->addr + CLOCK_DELAY); 687 clock_ctl = CLOCK_CONTROL_60MHZ;
688 clock_delay = 0;
677 } 689 }
678 writel(host_ctl, host->addr + HOST_CONTROL); 690 writel(host_ctl, host->addr + HOST_CONTROL);
691 writel(clock_ctl, host->addr + CLOCK_CONTROL);
692 writel(clock_delay, host->addr + CLOCK_DELAY);
679 break; 693 break;
680 }; 694 };
681
682 spin_unlock_irqrestore(&host->lock, flags);
683} 695}
684 696
685#ifdef CONFIG_PM 697#ifdef CONFIG_PM
@@ -772,13 +784,10 @@ static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt)
772 snprintf(host->host_id, DEVICE_ID_SIZE, DRIVER_NAME ":slot%d", 784 snprintf(host->host_id, DEVICE_ID_SIZE, DRIVER_NAME ":slot%d",
773 host->id); 785 host->id);
774 host->irq = jm->pdev->irq; 786 host->irq = jm->pdev->irq;
775 host->timeout_jiffies = msecs_to_jiffies(4000); 787 host->timeout_jiffies = msecs_to_jiffies(1000);
776 msh->request = jmb38x_ms_request; 788 msh->request = jmb38x_ms_request;
777 msh->set_param = jmb38x_ms_set_param; 789 msh->set_param = jmb38x_ms_set_param;
778 /* 790
779 msh->caps = MEMSTICK_CAP_AUTO_GET_INT | MEMSTICK_CAP_PAR4
780 | MEMSTICK_CAP_PAR8;
781 */
782 msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8; 791 msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8;
783 792
784 setup_timer(&host->timer, jmb38x_ms_abort, (unsigned long)msh); 793 setup_timer(&host->timer, jmb38x_ms_abort, (unsigned long)msh);