aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorManuel Lauss <mano@roarinelk.homelinux.net>2008-06-09 02:36:13 -0400
committerPierre Ossman <drzeus@drzeus.cx>2008-07-15 08:14:43 -0400
commitc4223c2c91fa9e5addd6eadd804e57a925ac5e5e (patch)
treed64af7e2b6322d59f1081ff8562cfc5f51f7f974 /drivers/mmc
parent12bd257532708a4d5be4b8548ff121a45ff88f5d (diff)
au1xmmc: remove db1200 board code, rewrite probe.
Remove the DB1200 board-specific functions (card present, read-only, activity LED methods) and instead add platform data which is passed to the driver. This also allows for platforms to implement other carddetect schemes (e.g. dedicated irq) without having to pollute the driver code. The poll timer (used for pb1200) is kept for compatibility. With the board-specific stuff gone, the driver's ->probe() code can be cleaned up considerably. Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net> Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/au1xmmc.c573
-rw-r--r--drivers/mmc/host/au1xmmc.h9
2 files changed, 345 insertions, 237 deletions
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index cc5f7bc546af..d8776d61b3cc 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -41,8 +41,9 @@
41#include <linux/interrupt.h> 41#include <linux/interrupt.h>
42#include <linux/dma-mapping.h> 42#include <linux/dma-mapping.h>
43#include <linux/scatterlist.h> 43#include <linux/scatterlist.h>
44 44#include <linux/leds.h>
45#include <linux/mmc/host.h> 45#include <linux/mmc/host.h>
46
46#include <asm/io.h> 47#include <asm/io.h>
47#include <asm/mach-au1x00/au1000.h> 48#include <asm/mach-au1x00/au1000.h>
48#include <asm/mach-au1x00/au1xxx_dbdma.h> 49#include <asm/mach-au1x00/au1xxx_dbdma.h>
@@ -54,6 +55,7 @@
54#define DRIVER_NAME "au1xxx-mmc" 55#define DRIVER_NAME "au1xxx-mmc"
55 56
56/* Set this to enable special debugging macros */ 57/* Set this to enable special debugging macros */
58/* #define DEBUG */
57 59
58#ifdef DEBUG 60#ifdef DEBUG
59#define DBG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args) 61#define DBG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args)
@@ -61,32 +63,6 @@
61#define DBG(fmt, idx, args...) 63#define DBG(fmt, idx, args...)
62#endif 64#endif
63 65
64const struct {
65 u32 iobase;
66 u32 tx_devid, rx_devid;
67 u16 bcsrpwr;
68 u16 bcsrstatus;
69 u16 wpstatus;
70} au1xmmc_card_table[] = {
71 { SD0_BASE, DSCR_CMD0_SDMS_TX0, DSCR_CMD0_SDMS_RX0,
72 BCSR_BOARD_SD0PWR, BCSR_INT_SD0INSERT, BCSR_STATUS_SD0WP },
73#ifndef CONFIG_MIPS_DB1200
74 { SD1_BASE, DSCR_CMD0_SDMS_TX1, DSCR_CMD0_SDMS_RX1,
75 BCSR_BOARD_DS1PWR, BCSR_INT_SD1INSERT, BCSR_STATUS_SD1WP }
76#endif
77};
78
79#define AU1XMMC_CONTROLLER_COUNT (ARRAY_SIZE(au1xmmc_card_table))
80
81/* This array stores pointers for the hosts (used by the IRQ handler) */
82struct au1xmmc_host *au1xmmc_hosts[AU1XMMC_CONTROLLER_COUNT];
83static int dma = 1;
84
85#ifdef MODULE
86module_param(dma, bool, 0);
87MODULE_PARM_DESC(dma, "Use DMA engine for data transfers (0 = disabled)");
88#endif
89
90static inline void IRQ_ON(struct au1xmmc_host *host, u32 mask) 66static inline void IRQ_ON(struct au1xmmc_host *host, u32 mask)
91{ 67{
92 u32 val = au_readl(HOST_CONFIG(host)); 68 u32 val = au_readl(HOST_CONFIG(host));
@@ -135,26 +111,33 @@ static inline void SEND_STOP(struct au1xmmc_host *host)
135 111
136static void au1xmmc_set_power(struct au1xmmc_host *host, int state) 112static void au1xmmc_set_power(struct au1xmmc_host *host, int state)
137{ 113{
138 114 if (host->platdata && host->platdata->set_power)
139 u32 val = au1xmmc_card_table[host->id].bcsrpwr; 115 host->platdata->set_power(host->mmc, state);
140
141 bcsr->board &= ~val;
142 if (state) bcsr->board |= val;
143
144 au_sync_delay(1);
145} 116}
146 117
147static inline int au1xmmc_card_inserted(struct au1xmmc_host *host) 118static int au1xmmc_card_inserted(struct au1xmmc_host *host)
148{ 119{
149 return (bcsr->sig_status & au1xmmc_card_table[host->id].bcsrstatus) 120 int ret;
150 ? 1 : 0; 121
122 if (host->platdata && host->platdata->card_inserted)
123 ret = host->platdata->card_inserted(host->mmc);
124 else
125 ret = 1; /* assume there is a card */
126
127 return ret;
151} 128}
152 129
153static int au1xmmc_card_readonly(struct mmc_host *mmc) 130static int au1xmmc_card_readonly(struct mmc_host *mmc)
154{ 131{
155 struct au1xmmc_host *host = mmc_priv(mmc); 132 struct au1xmmc_host *host = mmc_priv(mmc);
156 return (bcsr->status & au1xmmc_card_table[host->id].wpstatus) 133 int ret;
157 ? 1 : 0; 134
135 if (host->platdata && host->platdata->card_readonly)
136 ret = host->platdata->card_readonly(mmc);
137 else
138 ret = 0; /* assume card is read-write */
139
140 return ret;
158} 141}
159 142
160static void au1xmmc_finish_request(struct au1xmmc_host *host) 143static void au1xmmc_finish_request(struct au1xmmc_host *host)
@@ -163,7 +146,7 @@ static void au1xmmc_finish_request(struct au1xmmc_host *host)
163 struct mmc_request *mrq = host->mrq; 146 struct mmc_request *mrq = host->mrq;
164 147
165 host->mrq = NULL; 148 host->mrq = NULL;
166 host->flags &= HOST_F_ACTIVE; 149 host->flags &= HOST_F_ACTIVE | HOST_F_DMA;
167 150
168 host->dma.len = 0; 151 host->dma.len = 0;
169 host->dma.dir = 0; 152 host->dma.dir = 0;
@@ -174,8 +157,6 @@ static void au1xmmc_finish_request(struct au1xmmc_host *host)
174 157
175 host->status = HOST_S_IDLE; 158 host->status = HOST_S_IDLE;
176 159
177 bcsr->disk_leds |= (1 << 8);
178
179 mmc_request_done(host->mmc, mrq); 160 mmc_request_done(host->mmc, mrq);
180} 161}
181 162
@@ -299,11 +280,13 @@ static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status)
299 280
300 if (!data->error) { 281 if (!data->error) {
301 if (host->flags & HOST_F_DMA) { 282 if (host->flags & HOST_F_DMA) {
283#ifdef CONFIG_SOC_AU1200 /* DBDMA */
302 u32 chan = DMA_CHANNEL(host); 284 u32 chan = DMA_CHANNEL(host);
303 285
304 chan_tab_t *c = *((chan_tab_t **) chan); 286 chan_tab_t *c = *((chan_tab_t **) chan);
305 au1x_dma_chan_t *cp = c->chan_ptr; 287 au1x_dma_chan_t *cp = c->chan_ptr;
306 data->bytes_xfered = cp->ddma_bytecnt; 288 data->bytes_xfered = cp->ddma_bytecnt;
289#endif
307 } 290 }
308 else 291 else
309 data->bytes_xfered = 292 data->bytes_xfered =
@@ -420,18 +403,18 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host)
420 break; 403 break;
421 404
422 if (status & SD_STATUS_RC) { 405 if (status & SD_STATUS_RC) {
423 DBG("RX CRC Error [%d + %d].\n", host->id, 406 DBG("RX CRC Error [%d + %d].\n", host->pdev->id,
424 host->pio.len, count); 407 host->pio.len, count);
425 break; 408 break;
426 } 409 }
427 410
428 if (status & SD_STATUS_RO) { 411 if (status & SD_STATUS_RO) {
429 DBG("RX Overrun [%d + %d]\n", host->id, 412 DBG("RX Overrun [%d + %d]\n", host->pdev->id,
430 host->pio.len, count); 413 host->pio.len, count);
431 break; 414 break;
432 } 415 }
433 else if (status & SD_STATUS_RU) { 416 else if (status & SD_STATUS_RU) {
434 DBG("RX Underrun [%d + %d]\n", host->id, 417 DBG("RX Underrun [%d + %d]\n", host->pdev->id,
435 host->pio.len, count); 418 host->pio.len, count);
436 break; 419 break;
437 } 420 }
@@ -528,6 +511,7 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
528 host->status = HOST_S_DATA; 511 host->status = HOST_S_DATA;
529 512
530 if (host->flags & HOST_F_DMA) { 513 if (host->flags & HOST_F_DMA) {
514#ifdef CONFIG_SOC_AU1200 /* DBDMA */
531 u32 channel = DMA_CHANNEL(host); 515 u32 channel = DMA_CHANNEL(host);
532 516
533 /* Start the DMA as soon as the buffer gets something in it */ 517 /* Start the DMA as soon as the buffer gets something in it */
@@ -540,6 +524,7 @@ static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status)
540 } 524 }
541 525
542 au1xxx_dbdma_start(channel); 526 au1xxx_dbdma_start(channel);
527#endif
543 } 528 }
544} 529}
545 530
@@ -571,12 +556,8 @@ static void au1xmmc_set_clock(struct au1xmmc_host *host, int rate)
571static int 556static int
572au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data) 557au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
573{ 558{
574
575 int datalen = data->blocks * data->blksz; 559 int datalen = data->blocks * data->blksz;
576 560
577 if (dma != 0)
578 host->flags |= HOST_F_DMA;
579
580 if (data->flags & MMC_DATA_READ) 561 if (data->flags & MMC_DATA_READ)
581 host->flags |= HOST_F_RECV; 562 host->flags |= HOST_F_RECV;
582 else 563 else
@@ -596,6 +577,7 @@ au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
596 au_writel(data->blksz - 1, HOST_BLKSIZE(host)); 577 au_writel(data->blksz - 1, HOST_BLKSIZE(host));
597 578
598 if (host->flags & HOST_F_DMA) { 579 if (host->flags & HOST_F_DMA) {
580#ifdef CONFIG_SOC_AU1200 /* DBDMA */
599 int i; 581 int i;
600 u32 channel = DMA_CHANNEL(host); 582 u32 channel = DMA_CHANNEL(host);
601 583
@@ -621,11 +603,12 @@ au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
621 len, flags); 603 len, flags);
622 } 604 }
623 605
624 if (!ret) 606 if (!ret)
625 goto dataerr; 607 goto dataerr;
626 608
627 datalen -= len; 609 datalen -= len;
628 } 610 }
611#endif
629 } 612 }
630 else { 613 else {
631 host->pio.index = 0; 614 host->pio.index = 0;
@@ -641,8 +624,9 @@ au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data)
641 624
642 return 0; 625 return 0;
643 626
644 dataerr: 627dataerr:
645 dma_unmap_sg(mmc_dev(host->mmc),data->sg,data->sg_len,host->dma.dir); 628 dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
629 host->dma.dir);
646 return -ETIMEDOUT; 630 return -ETIMEDOUT;
647} 631}
648 632
@@ -663,8 +647,6 @@ static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq)
663 host->mrq = mrq; 647 host->mrq = mrq;
664 host->status = HOST_S_CMD; 648 host->status = HOST_S_CMD;
665 649
666 bcsr->disk_leds &= ~(1 << 8);
667
668 if (mrq->data) { 650 if (mrq->data) {
669 FLUSH_FIFO(host); 651 FLUSH_FIFO(host);
670 flags = mrq->data->flags; 652 flags = mrq->data->flags;
@@ -728,149 +710,145 @@ static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
728 } 710 }
729} 711}
730 712
731static void au1xmmc_dma_callback(int irq, void *dev_id)
732{
733 struct au1xmmc_host *host = (struct au1xmmc_host *) dev_id;
734
735 /* Avoid spurious interrupts */
736
737 if (!host->mrq)
738 return;
739
740 if (host->flags & HOST_F_STOP)
741 SEND_STOP(host);
742
743 tasklet_schedule(&host->data_task);
744}
745
746#define STATUS_TIMEOUT (SD_STATUS_RAT | SD_STATUS_DT) 713#define STATUS_TIMEOUT (SD_STATUS_RAT | SD_STATUS_DT)
747#define STATUS_DATA_IN (SD_STATUS_NE) 714#define STATUS_DATA_IN (SD_STATUS_NE)
748#define STATUS_DATA_OUT (SD_STATUS_TH) 715#define STATUS_DATA_OUT (SD_STATUS_TH)
749 716
750static irqreturn_t au1xmmc_irq(int irq, void *dev_id) 717static irqreturn_t au1xmmc_irq(int irq, void *dev_id)
751{ 718{
752 719 struct au1xmmc_host *host = dev_id;
753 u32 status; 720 u32 status;
754 int i, ret = 0;
755
756 disable_irq(AU1100_SD_IRQ);
757 721
758 for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) { 722 status = au_readl(HOST_STATUS(host));
759 struct au1xmmc_host * host = au1xmmc_hosts[i];
760 u32 handled = 1;
761
762 status = au_readl(HOST_STATUS(host));
763 723
764 if (host->mrq && (status & STATUS_TIMEOUT)) { 724 if (!(status & SD_STATUS_I))
765 if (status & SD_STATUS_RAT) 725 return IRQ_NONE; /* not ours */
766 host->mrq->cmd->error = -ETIMEDOUT;
767 726
768 else if (status & SD_STATUS_DT) 727 if (host->mrq && (status & STATUS_TIMEOUT)) {
769 host->mrq->data->error = -ETIMEDOUT; 728 if (status & SD_STATUS_RAT)
729 host->mrq->cmd->error = -ETIMEDOUT;
730 else if (status & SD_STATUS_DT)
731 host->mrq->data->error = -ETIMEDOUT;
770 732
771 /* In PIO mode, interrupts might still be enabled */ 733 /* In PIO mode, interrupts might still be enabled */
772 IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH); 734 IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH);
773 735
774 //IRQ_OFF(host, SD_CONFIG_TH|SD_CONFIG_RA|SD_CONFIG_RF); 736 /* IRQ_OFF(host, SD_CONFIG_TH | SD_CONFIG_RA | SD_CONFIG_RF); */
775 tasklet_schedule(&host->finish_task); 737 tasklet_schedule(&host->finish_task);
776 } 738 }
777#if 0 739#if 0
778 else if (status & SD_STATUS_DD) { 740 else if (status & SD_STATUS_DD) {
779 741 /* Sometimes we get a DD before a NE in PIO mode */
780 /* Sometimes we get a DD before a NE in PIO mode */ 742 if (!(host->flags & HOST_F_DMA) && (status & SD_STATUS_NE))
781 743 au1xmmc_receive_pio(host);
782 if (!(host->flags & HOST_F_DMA) && 744 else {
783 (status & SD_STATUS_NE)) 745 au1xmmc_data_complete(host, status);
784 au1xmmc_receive_pio(host); 746 /* tasklet_schedule(&host->data_task); */
785 else {
786 au1xmmc_data_complete(host, status);
787 //tasklet_schedule(&host->data_task);
788 }
789 }
790#endif
791 else if (status & (SD_STATUS_CR)) {
792 if (host->status == HOST_S_CMD)
793 au1xmmc_cmd_complete(host,status);
794 }
795 else if (!(host->flags & HOST_F_DMA)) {
796 if ((host->flags & HOST_F_XMIT) &&
797 (status & STATUS_DATA_OUT))
798 au1xmmc_send_pio(host);
799 else if ((host->flags & HOST_F_RECV) &&
800 (status & STATUS_DATA_IN))
801 au1xmmc_receive_pio(host);
802 }
803 else if (status & 0x203FBC70) {
804 DBG("Unhandled status %8.8x\n", host->id, status);
805 handled = 0;
806 } 747 }
807
808 au_writel(status, HOST_STATUS(host));
809 au_sync();
810
811 ret |= handled;
812 } 748 }
813 749#endif
814 enable_irq(AU1100_SD_IRQ); 750 else if (status & SD_STATUS_CR) {
815 return ret; 751 if (host->status == HOST_S_CMD)
816} 752 au1xmmc_cmd_complete(host, status);
817 753
818static void au1xmmc_poll_event(unsigned long arg) 754 } else if (!(host->flags & HOST_F_DMA)) {
819{ 755 if ((host->flags & HOST_F_XMIT) && (status & STATUS_DATA_OUT))
820 struct au1xmmc_host *host = (struct au1xmmc_host *) arg; 756 au1xmmc_send_pio(host);
821 757 else if ((host->flags & HOST_F_RECV) && (status & STATUS_DATA_IN))
822 int card = au1xmmc_card_inserted(host); 758 au1xmmc_receive_pio(host);
823 int controller = (host->flags & HOST_F_ACTIVE) ? 1 : 0; 759
824 760 } else if (status & 0x203F3C70) {
825 if (card != controller) { 761 DBG("Unhandled status %8.8x\n", host->pdev->id,
826 host->flags &= ~HOST_F_ACTIVE; 762 status);
827 if (card) host->flags |= HOST_F_ACTIVE;
828 mmc_detect_change(host->mmc, 0);
829 } 763 }
830 764
831 if (host->mrq != NULL) { 765 au_writel(status, HOST_STATUS(host));
832 u32 status = au_readl(HOST_STATUS(host)); 766 au_sync();
833 DBG("PENDING - %8.8x\n", host->id, status);
834 }
835 767
836 mod_timer(&host->timer, jiffies + AU1XMMC_DETECT_TIMEOUT); 768 return IRQ_HANDLED;
837} 769}
838 770
839static dbdev_tab_t au1xmmc_mem_dbdev = 771#ifdef CONFIG_SOC_AU1200
840{ 772/* 8bit memory DMA device */
841 DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 8, 0x00000000, 0, 0 773static dbdev_tab_t au1xmmc_mem_dbdev = {
774 .dev_id = DSCR_CMD0_ALWAYS,
775 .dev_flags = DEV_FLAGS_ANYUSE,
776 .dev_tsize = 0,
777 .dev_devwidth = 8,
778 .dev_physaddr = 0x00000000,
779 .dev_intlevel = 0,
780 .dev_intpolarity = 0,
842}; 781};
782static int memid;
843 783
844static void au1xmmc_init_dma(struct au1xmmc_host *host) 784static void au1xmmc_dbdma_callback(int irq, void *dev_id)
845{ 785{
786 struct au1xmmc_host *host = (struct au1xmmc_host *)dev_id;
846 787
847 u32 rxchan, txchan; 788 /* Avoid spurious interrupts */
789 if (!host->mrq)
790 return;
848 791
849 int txid = au1xmmc_card_table[host->id].tx_devid; 792 if (host->flags & HOST_F_STOP)
850 int rxid = au1xmmc_card_table[host->id].rx_devid; 793 SEND_STOP(host);
851 794
852 /* DSCR_CMD0_ALWAYS has a stride of 32 bits, we need a stride 795 tasklet_schedule(&host->data_task);
853 of 8 bits. And since devices are shared, we need to create 796}
854 our own to avoid freaking out other devices
855 */
856 797
857 int memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev); 798static int au1xmmc_dbdma_init(struct au1xmmc_host *host)
799{
800 struct resource *res;
801 int txid, rxid;
802
803 res = platform_get_resource(host->pdev, IORESOURCE_DMA, 0);
804 if (!res)
805 return -ENODEV;
806 txid = res->start;
807
808 res = platform_get_resource(host->pdev, IORESOURCE_DMA, 1);
809 if (!res)
810 return -ENODEV;
811 rxid = res->start;
812
813 if (!memid)
814 return -ENODEV;
815
816 host->tx_chan = au1xxx_dbdma_chan_alloc(memid, txid,
817 au1xmmc_dbdma_callback, (void *)host);
818 if (!host->tx_chan) {
819 dev_err(&host->pdev->dev, "cannot allocate TX DMA\n");
820 return -ENODEV;
821 }
822
823 host->rx_chan = au1xxx_dbdma_chan_alloc(rxid, memid,
824 au1xmmc_dbdma_callback, (void *)host);
825 if (!host->rx_chan) {
826 dev_err(&host->pdev->dev, "cannot allocate RX DMA\n");
827 au1xxx_dbdma_chan_free(host->tx_chan);
828 return -ENODEV;
829 }
858 830
859 txchan = au1xxx_dbdma_chan_alloc(memid, txid, 831 au1xxx_dbdma_set_devwidth(host->tx_chan, 8);
860 au1xmmc_dma_callback, (void *) host); 832 au1xxx_dbdma_set_devwidth(host->rx_chan, 8);
861 833
862 rxchan = au1xxx_dbdma_chan_alloc(rxid, memid, 834 au1xxx_dbdma_ring_alloc(host->tx_chan, AU1XMMC_DESCRIPTOR_COUNT);
863 au1xmmc_dma_callback, (void *) host); 835 au1xxx_dbdma_ring_alloc(host->rx_chan, AU1XMMC_DESCRIPTOR_COUNT);
864 836
865 au1xxx_dbdma_set_devwidth(txchan, 8); 837 /* DBDMA is good to go */
866 au1xxx_dbdma_set_devwidth(rxchan, 8); 838 host->flags |= HOST_F_DMA;
867 839
868 au1xxx_dbdma_ring_alloc(txchan, AU1XMMC_DESCRIPTOR_COUNT); 840 return 0;
869 au1xxx_dbdma_ring_alloc(rxchan, AU1XMMC_DESCRIPTOR_COUNT); 841}
870 842
871 host->tx_chan = txchan; 843static void au1xmmc_dbdma_shutdown(struct au1xmmc_host *host)
872 host->rx_chan = rxchan; 844{
845 if (host->flags & HOST_F_DMA) {
846 host->flags &= ~HOST_F_DMA;
847 au1xxx_dbdma_chan_free(host->tx_chan);
848 au1xxx_dbdma_chan_free(host->rx_chan);
849 }
873} 850}
851#endif
874 852
875static const struct mmc_host_ops au1xmmc_ops = { 853static const struct mmc_host_ops au1xmmc_ops = {
876 .request = au1xmmc_request, 854 .request = au1xmmc_request,
@@ -878,116 +856,235 @@ static const struct mmc_host_ops au1xmmc_ops = {
878 .get_ro = au1xmmc_card_readonly, 856 .get_ro = au1xmmc_card_readonly,
879}; 857};
880 858
881static int __devinit au1xmmc_probe(struct platform_device *pdev) 859static void au1xmmc_poll_event(unsigned long arg)
882{ 860{
861 struct au1xmmc_host *host = (struct au1xmmc_host *)arg;
862 int card = au1xmmc_card_inserted(host);
863 int controller = (host->flags & HOST_F_ACTIVE) ? 1 : 0;
864
865 if (card != controller) {
866 host->flags &= ~HOST_F_ACTIVE;
867 if (card)
868 host->flags |= HOST_F_ACTIVE;
869 mmc_detect_change(host->mmc, 0);
870 }
883 871
884 int i, ret = 0; 872#ifdef DEBUG
873 if (host->mrq != NULL) {
874 u32 status = au_readl(HOST_STATUS(host));
875 DBG("PENDING - %8.8x\n", host->pdev->id, status);
876 }
877#endif
878 mod_timer(&host->timer, jiffies + AU1XMMC_DETECT_TIMEOUT);
879}
885 880
886 /* THe interrupt is shared among all controllers */ 881static void au1xmmc_init_cd_poll_timer(struct au1xmmc_host *host)
887 ret = request_irq(AU1100_SD_IRQ, au1xmmc_irq, IRQF_DISABLED, "MMC", 0); 882{
883 init_timer(&host->timer);
884 host->timer.function = au1xmmc_poll_event;
885 host->timer.data = (unsigned long)host;
886 host->timer.expires = jiffies + AU1XMMC_DETECT_TIMEOUT;
887}
888 888
889 if (ret) { 889static int __devinit au1xmmc_probe(struct platform_device *pdev)
890 printk(DRIVER_NAME "ERROR: Couldn't get int %d: %d\n", 890{
891 AU1100_SD_IRQ, ret); 891 struct mmc_host *mmc;
892 return -ENXIO; 892 struct au1xmmc_host *host;
893 struct resource *r;
894 int ret;
895
896 mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev);
897 if (!mmc) {
898 dev_err(&pdev->dev, "no memory for mmc_host\n");
899 ret = -ENOMEM;
900 goto out0;
893 } 901 }
894 902
895 disable_irq(AU1100_SD_IRQ); 903 host = mmc_priv(mmc);
904 host->mmc = mmc;
905 host->platdata = pdev->dev.platform_data;
906 host->pdev = pdev;
896 907
897 for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) { 908 ret = -ENODEV;
898 struct mmc_host *mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev); 909 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
899 struct au1xmmc_host *host = 0; 910 if (!r) {
911 dev_err(&pdev->dev, "no mmio defined\n");
912 goto out1;
913 }
900 914
901 if (!mmc) { 915 host->ioarea = request_mem_region(r->start, r->end - r->start + 1,
902 printk(DRIVER_NAME "ERROR: no mem for host %d\n", i); 916 pdev->name);
903 au1xmmc_hosts[i] = 0; 917 if (!host->ioarea) {
904 continue; 918 dev_err(&pdev->dev, "mmio already in use\n");
905 } 919 goto out1;
920 }
906 921
907 mmc->ops = &au1xmmc_ops; 922 host->iobase = (unsigned long)ioremap(r->start, 0x3c);
923 if (!host->iobase) {
924 dev_err(&pdev->dev, "cannot remap mmio\n");
925 goto out2;
926 }
927
928 r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
929 if (!r) {
930 dev_err(&pdev->dev, "no IRQ defined\n");
931 goto out3;
932 }
908 933
909 mmc->f_min = 450000; 934 host->irq = r->start;
910 mmc->f_max = 24000000; 935 /* IRQ is shared among both SD controllers */
936 ret = request_irq(host->irq, au1xmmc_irq, IRQF_SHARED,
937 DRIVER_NAME, host);
938 if (ret) {
939 dev_err(&pdev->dev, "cannot grab IRQ\n");
940 goto out3;
941 }
911 942
912 mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE; 943 mmc->ops = &au1xmmc_ops;
913 mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT;
914 944
915 mmc->max_blk_size = 2048; 945 mmc->f_min = 450000;
916 mmc->max_blk_count = 512; 946 mmc->f_max = 24000000;
917 947
918 mmc->ocr_avail = AU1XMMC_OCR; 948 mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE;
949 mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT;
919 950
920 host = mmc_priv(mmc); 951 mmc->max_blk_size = 2048;
921 host->mmc = mmc; 952 mmc->max_blk_count = 512;
922 953
923 host->id = i; 954 mmc->ocr_avail = AU1XMMC_OCR;
924 host->iobase = au1xmmc_card_table[host->id].iobase; 955 mmc->caps = 0;
925 host->clock = 0;
926 host->power_mode = MMC_POWER_OFF;
927 956
928 host->flags = au1xmmc_card_inserted(host) ? HOST_F_ACTIVE : 0; 957 host->status = HOST_S_IDLE;
929 host->status = HOST_S_IDLE;
930 958
931 init_timer(&host->timer); 959 /* board-specific carddetect setup, if any */
960 if (host->platdata && host->platdata->cd_setup) {
961 ret = host->platdata->cd_setup(mmc, 1);
962 if (ret) {
963 dev_err(&pdev->dev, "board CD setup failed\n");
964 goto out4;
965 }
966 } else {
967 /* poll the board-specific is-card-in-socket-? method */
968 au1xmmc_init_cd_poll_timer(host);
969 }
932 970
933 host->timer.function = au1xmmc_poll_event; 971 tasklet_init(&host->data_task, au1xmmc_tasklet_data,
934 host->timer.data = (unsigned long) host; 972 (unsigned long)host);
935 host->timer.expires = jiffies + AU1XMMC_DETECT_TIMEOUT;
936 973
937 tasklet_init(&host->data_task, au1xmmc_tasklet_data, 974 tasklet_init(&host->finish_task, au1xmmc_tasklet_finish,
938 (unsigned long) host); 975 (unsigned long)host);
939 976
940 tasklet_init(&host->finish_task, au1xmmc_tasklet_finish, 977#ifdef CONFIG_SOC_AU1200
941 (unsigned long) host); 978 ret = au1xmmc_dbdma_init(host);
979 if (ret)
980 printk(KERN_INFO DRIVER_NAME ": DBDMA init failed; using PIO\n");
981#endif
942 982
943 spin_lock_init(&host->lock); 983#ifdef CONFIG_LEDS_CLASS
984 if (host->platdata && host->platdata->led) {
985 struct led_classdev *led = host->platdata->led;
986 led->name = mmc_hostname(mmc);
987 led->brightness = LED_OFF;
988 led->default_trigger = mmc_hostname(mmc);
989 ret = led_classdev_register(mmc_dev(mmc), led);
990 if (ret)
991 goto out5;
992 }
993#endif
944 994
945 if (dma != 0) 995 au1xmmc_reset_controller(host);
946 au1xmmc_init_dma(host);
947 996
948 au1xmmc_reset_controller(host); 997 ret = mmc_add_host(mmc);
998 if (ret) {
999 dev_err(&pdev->dev, "cannot add mmc host\n");
1000 goto out6;
1001 }
949 1002
950 mmc_add_host(mmc); 1003 platform_set_drvdata(pdev, mmc);
951 au1xmmc_hosts[i] = host;
952 1004
1005 /* start the carddetect poll timer if necessary */
1006 if (!(host->platdata && host->platdata->cd_setup))
953 add_timer(&host->timer); 1007 add_timer(&host->timer);
954 1008
955 printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X (mode=%s)\n", 1009 printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X"
956 host->id, host->iobase, dma ? "dma" : "pio"); 1010 " (mode=%s)\n", pdev->id, host->iobase,
957 } 1011 host->flags & HOST_F_DMA ? "dma" : "pio");
958 1012
959 enable_irq(AU1100_SD_IRQ); 1013 return 0; /* all ok */
960 1014
961 return 0; 1015out6:
1016#ifdef CONFIG_LEDS_CLASS
1017 if (host->platdata && host->platdata->led)
1018 led_classdev_unregister(host->platdata->led);
1019out5:
1020#endif
1021 au_writel(0, HOST_ENABLE(host));
1022 au_writel(0, HOST_CONFIG(host));
1023 au_writel(0, HOST_CONFIG2(host));
1024 au_sync();
1025
1026#ifdef CONFIG_SOC_AU1200
1027 au1xmmc_dbdma_shutdown(host);
1028#endif
1029
1030 tasklet_kill(&host->data_task);
1031 tasklet_kill(&host->finish_task);
1032
1033 if (host->platdata && host->platdata->cd_setup)
1034 host->platdata->cd_setup(mmc, 0);
1035out4:
1036 free_irq(host->irq, host);
1037out3:
1038 iounmap((void *)host->iobase);
1039out2:
1040 release_resource(host->ioarea);
1041 kfree(host->ioarea);
1042out1:
1043 mmc_free_host(mmc);
1044out0:
1045 return ret;
962} 1046}
963 1047
964static int __devexit au1xmmc_remove(struct platform_device *pdev) 1048static int __devexit au1xmmc_remove(struct platform_device *pdev)
965{ 1049{
1050 struct mmc_host *mmc = platform_get_drvdata(pdev);
1051 struct au1xmmc_host *host;
1052
1053 if (mmc) {
1054 host = mmc_priv(mmc);
1055
1056 mmc_remove_host(mmc);
966 1057
967 int i; 1058#ifdef CONFIG_LEDS_CLASS
1059 if (host->platdata && host->platdata->led)
1060 led_classdev_unregister(host->platdata->led);
1061#endif
968 1062
969 disable_irq(AU1100_SD_IRQ); 1063 if (host->platdata && host->platdata->cd_setup)
1064 host->platdata->cd_setup(mmc, 0);
1065 else
1066 del_timer_sync(&host->timer);
970 1067
971 for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) { 1068 au_writel(0, HOST_ENABLE(host));
972 struct au1xmmc_host *host = au1xmmc_hosts[i]; 1069 au_writel(0, HOST_CONFIG(host));
973 if (!host) continue; 1070 au_writel(0, HOST_CONFIG2(host));
1071 au_sync();
974 1072
975 tasklet_kill(&host->data_task); 1073 tasklet_kill(&host->data_task);
976 tasklet_kill(&host->finish_task); 1074 tasklet_kill(&host->finish_task);
977 1075
978 del_timer_sync(&host->timer); 1076#ifdef CONFIG_SOC_AU1200
1077 au1xmmc_dbdma_shutdown(host);
1078#endif
979 au1xmmc_set_power(host, 0); 1079 au1xmmc_set_power(host, 0);
980 1080
981 mmc_remove_host(host->mmc); 1081 free_irq(host->irq, host);
1082 iounmap((void *)host->iobase);
1083 release_resource(host->ioarea);
1084 kfree(host->ioarea);
982 1085
983 au1xxx_dbdma_chan_free(host->tx_chan); 1086 mmc_free_host(mmc);
984 au1xxx_dbdma_chan_free(host->rx_chan);
985
986 au_writel(0x0, HOST_ENABLE(host));
987 au_sync();
988 } 1087 }
989
990 free_irq(AU1100_SD_IRQ, 0);
991 return 0; 1088 return 0;
992} 1089}
993 1090
@@ -1004,21 +1101,31 @@ static struct platform_driver au1xmmc_driver = {
1004 1101
1005static int __init au1xmmc_init(void) 1102static int __init au1xmmc_init(void)
1006{ 1103{
1104#ifdef CONFIG_SOC_AU1200
1105 /* DSCR_CMD0_ALWAYS has a stride of 32 bits, we need a stride
1106 * of 8 bits. And since devices are shared, we need to create
1107 * our own to avoid freaking out other devices.
1108 */
1109 memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev);
1110 if (!memid)
1111 printk(KERN_ERR "au1xmmc: cannot add memory dbdma dev\n");
1112#endif
1007 return platform_driver_register(&au1xmmc_driver); 1113 return platform_driver_register(&au1xmmc_driver);
1008} 1114}
1009 1115
1010static void __exit au1xmmc_exit(void) 1116static void __exit au1xmmc_exit(void)
1011{ 1117{
1118#ifdef CONFIG_SOC_AU1200
1119 if (memid)
1120 au1xxx_ddma_del_device(memid);
1121#endif
1012 platform_driver_unregister(&au1xmmc_driver); 1122 platform_driver_unregister(&au1xmmc_driver);
1013} 1123}
1014 1124
1015module_init(au1xmmc_init); 1125module_init(au1xmmc_init);
1016module_exit(au1xmmc_exit); 1126module_exit(au1xmmc_exit);
1017 1127
1018#ifdef MODULE
1019MODULE_AUTHOR("Advanced Micro Devices, Inc"); 1128MODULE_AUTHOR("Advanced Micro Devices, Inc");
1020MODULE_DESCRIPTION("MMC/SD driver for the Alchemy Au1XXX"); 1129MODULE_DESCRIPTION("MMC/SD driver for the Alchemy Au1XXX");
1021MODULE_LICENSE("GPL"); 1130MODULE_LICENSE("GPL");
1022MODULE_ALIAS("platform:au1xxx-mmc"); 1131MODULE_ALIAS("platform:au1xxx-mmc");
1023#endif
1024
diff --git a/drivers/mmc/host/au1xmmc.h b/drivers/mmc/host/au1xmmc.h
index 341cbdf0baca..3b400654e59c 100644
--- a/drivers/mmc/host/au1xmmc.h
+++ b/drivers/mmc/host/au1xmmc.h
@@ -49,8 +49,6 @@ struct au1xmmc_host {
49 struct mmc_host *mmc; 49 struct mmc_host *mmc;
50 struct mmc_request *mrq; 50 struct mmc_request *mrq;
51 51
52 u32 id;
53
54 u32 flags; 52 u32 flags;
55 u32 iobase; 53 u32 iobase;
56 u32 clock; 54 u32 clock;
@@ -73,11 +71,14 @@ struct au1xmmc_host {
73 u32 tx_chan; 71 u32 tx_chan;
74 u32 rx_chan; 72 u32 rx_chan;
75 73
74 int irq;
75
76 struct timer_list timer; 76 struct timer_list timer;
77 struct tasklet_struct finish_task; 77 struct tasklet_struct finish_task;
78 struct tasklet_struct data_task; 78 struct tasklet_struct data_task;
79 79 struct au1xmmc_platform_data *platdata;
80 spinlock_t lock; 80 struct platform_device *pdev;
81 struct resource *ioarea;
81}; 82};
82 83
83/* Status flags used by the host structure */ 84/* Status flags used by the host structure */