2 * linux/drivers/mmc/s3c2410mci.h - Samsung S3C2410 SDI Interface driver
4 * Copyright (C) 2004 Thomas Kleffel, All Rights Reserved.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 #include <linux/module.h>
11 #include <linux/moduleparam.h>
12 #include <linux/init.h>
13 #include <linux/ioport.h>
14 #include <linux/device.h>
15 #include <linux/interrupt.h>
16 #include <linux/blkdev.h>
17 #include <linux/delay.h>
18 #include <linux/err.h>
19 #include <linux/dma-mapping.h>
20 #include <linux/mmc/host.h>
21 #include <linux/mmc/protocol.h>
24 #include <asm/dma-mapping.h>
25 #include <asm/arch/dma.h>
29 #include <asm/hardware/amba.h>
30 #include <asm/hardware/clock.h>
31 #include <asm/mach/mmc.h>
33 #include <asm/arch/regs-sdi.h>
34 #include <asm/arch/regs-gpio.h>
36 //#define S3C2410SDI_DMA_BACKBUF
38 #ifdef CONFIG_MMC_DEBUG
39 #define DBG(x...) printk(KERN_DEBUG x)
41 #define DBG(x...) do { } while (0)
44 #include "s3c2410mci.h"
46 #define DRIVER_NAME "mmci-s3c2410"
47 #define PFX DRIVER_NAME ": "
49 #define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
51 // #define KERN_DEBUG KERN_INFO
58 static struct s3c2410_dma_client s3c2410sdi_dma_client
= {
59 .name
= "s3c2410-sdi",
65 * ISR for SDI Interface IRQ
66 * Communication between driver and ISR works as follows:
67 * host->mrq points to current request
68 * host->complete_what tells the ISR when the request is considered done
69 * COMPLETION_CMDSENT when the command was sent
70 * COMPLETION_RSPFIN when a response was received
71 * COMPLETION_XFERFINISH when the data transfer is finished
72 * COMPLETION_XFERFINISH_RSPFIN both of the above.
73 * host->complete_request is the completion-object the driver waits for
75 * 1) Driver sets up host->mrq and host->complete_what
76 * 2) Driver prepares the transfer
77 * 3) Driver enables interrupts
78 * 4) Driver starts transfer
79 * 5) Driver waits for host->complete_rquest
80 * 6) ISR checks for request status (errors and success)
81 * 6) ISR sets host->mrq->cmd->error and host->mrq->data->error
82 * 7) ISR completes host->complete_request
83 * 8) ISR disables interrupts
84 * 9) Driver wakes up and takes care of the request
87 static irqreturn_t
s3c2410sdi_irq(int irq
, void *dev_id
, struct pt_regs
*regs
)
89 struct s3c2410sdi_host
*host
;
90 u32 sdi_csta
, sdi_dsta
, sdi_dcnt
;
91 u32 sdi_cclear
, sdi_dclear
;
94 host
= (struct s3c2410sdi_host
*)dev_id
;
96 //Check for things not supposed to happen
97 if(!host
) return IRQ_HANDLED
;
99 sdi_csta
= readl(host
->base
+ S3C2410_SDICMDSTAT
);
100 sdi_dsta
= readl(host
->base
+ S3C2410_SDIDSTA
);
101 sdi_dcnt
= readl(host
->base
+ S3C2410_SDIDCNT
);
103 DBG(PFX
"IRQ csta=0x%08x dsta=0x%08x dcnt:0x%08x\n", sdi_csta
, sdi_dsta
, sdi_dcnt
);
105 spin_lock_irqsave( &host
->complete_lock
, iflags
);
107 if( host
->complete_what
==COMPLETION_NONE
) {
116 sdi_csta
= readl(host
->base
+ S3C2410_SDICMDSTAT
);
117 sdi_dsta
= readl(host
->base
+ S3C2410_SDIDSTA
);
118 sdi_dcnt
= readl(host
->base
+ S3C2410_SDIDCNT
);
123 if(sdi_csta
& S3C2410_SDICMDSTAT_CMDTIMEOUT
) {
124 host
->mrq
->cmd
->error
= MMC_ERR_TIMEOUT
;
125 goto transfer_closed
;
128 if(sdi_csta
& S3C2410_SDICMDSTAT_CMDSENT
) {
129 if(host
->complete_what
== COMPLETION_CMDSENT
) {
130 host
->mrq
->cmd
->error
= MMC_ERR_NONE
;
131 goto transfer_closed
;
134 sdi_cclear
|= S3C2410_SDICMDSTAT_CMDSENT
;
137 if(sdi_csta
& S3C2410_SDICMDSTAT_CRCFAIL
) {
138 if(host
->mrq
->cmd
->flags
& MMC_RSP_CRC
) {
139 host
->mrq
->cmd
->error
= MMC_ERR_BADCRC
;
140 goto transfer_closed
;
143 sdi_cclear
|= S3C2410_SDICMDSTAT_CRCFAIL
;
146 if(sdi_csta
& S3C2410_SDICMDSTAT_RSPFIN
) {
147 if(host
->complete_what
== COMPLETION_RSPFIN
) {
148 host
->mrq
->cmd
->error
= MMC_ERR_NONE
;
149 goto transfer_closed
;
152 if(host
->complete_what
== COMPLETION_XFERFINISH_RSPFIN
) {
153 host
->mrq
->cmd
->error
= MMC_ERR_NONE
;
154 host
->complete_what
= COMPLETION_XFERFINISH
;
157 sdi_cclear
|= S3C2410_SDICMDSTAT_RSPFIN
;
160 if(sdi_dsta
& S3C2410_SDIDSTA_FIFOFAIL
) {
161 host
->mrq
->cmd
->error
= MMC_ERR_NONE
;
162 host
->mrq
->data
->error
= MMC_ERR_FIFO
;
163 goto transfer_closed
;
166 if(sdi_dsta
& S3C2410_SDIDSTA_RXCRCFAIL
) {
167 host
->mrq
->cmd
->error
= MMC_ERR_NONE
;
168 host
->mrq
->data
->error
= MMC_ERR_BADCRC
;
169 goto transfer_closed
;
172 if(sdi_dsta
& S3C2410_SDIDSTA_CRCFAIL
) {
173 host
->mrq
->cmd
->error
= MMC_ERR_NONE
;
174 host
->mrq
->data
->error
= MMC_ERR_BADCRC
;
175 goto transfer_closed
;
178 if(sdi_dsta
& S3C2410_SDIDSTA_DATATIMEOUT
) {
179 host
->mrq
->cmd
->error
= MMC_ERR_NONE
;
180 host
->mrq
->data
->error
= MMC_ERR_TIMEOUT
;
181 goto transfer_closed
;
184 if(sdi_dsta
& S3C2410_SDIDSTA_XFERFINISH
) {
185 if(host
->complete_what
== COMPLETION_XFERFINISH
) {
186 host
->mrq
->cmd
->error
= MMC_ERR_NONE
;
187 host
->mrq
->data
->error
= MMC_ERR_NONE
;
188 goto transfer_closed
;
191 if(host
->complete_what
== COMPLETION_XFERFINISH_RSPFIN
) {
192 host
->mrq
->data
->error
= MMC_ERR_NONE
;
193 host
->complete_what
= COMPLETION_RSPFIN
;
196 sdi_dclear
|= S3C2410_SDIDSTA_XFERFINISH
;
199 writel(sdi_cclear
, host
->base
+ S3C2410_SDICMDSTAT
);
200 writel(sdi_dclear
, host
->base
+ S3C2410_SDIDSTA
);
202 spin_unlock_irqrestore( &host
->complete_lock
, iflags
);
203 DBG(PFX
"IRQ still waiting.\n");
208 host
->complete_what
= COMPLETION_NONE
;
209 complete(&host
->complete_request
);
210 writel(0, host
->base
+ S3C2410_SDIIMSK
);
211 spin_unlock_irqrestore( &host
->complete_lock
, iflags
);
212 DBG(PFX
"IRQ transfer closed.\n");
217 writel(0, host
->base
+ S3C2410_SDIIMSK
);
218 spin_unlock_irqrestore( &host
->complete_lock
, iflags
);
219 DBG(PFX
"IRQ clear imask.\n");
226 * ISR for the CardDetect Pin
229 static irqreturn_t
s3c2410sdi_irq_cd(int irq
, void *dev_id
, struct pt_regs
*regs
)
231 struct s3c2410sdi_host
*host
= (struct s3c2410sdi_host
*)dev_id
;
232 mmc_detect_change(host
->mmc
);
239 void s3c2410sdi_dma_done_callback(s3c2410_dma_chan_t
*dma_ch
, void *buf_id
,
240 int size
, s3c2410_dma_buffresult_t result
)
241 { unsigned long iflags
;
242 u32 sdi_csta
, sdi_dsta
,sdi_dcnt
;
243 struct s3c2410sdi_host
*host
= (struct s3c2410sdi_host
*)buf_id
;
245 sdi_csta
= readl(host
->base
+ S3C2410_SDICMDSTAT
);
246 sdi_dsta
= readl(host
->base
+ S3C2410_SDIDSTA
);
247 sdi_dcnt
= readl(host
->base
+ S3C2410_SDIDCNT
);
249 DBG(PFX
"DMAD csta=0x%08x dsta=0x%08x dcnt:0x%08x result:0x%08x\n", sdi_csta
, sdi_dsta
, sdi_dcnt
, result
);
251 spin_lock_irqsave( &host
->complete_lock
, iflags
);
253 if(!host
->mrq
) goto out
;
254 if(!host
->mrq
->data
) goto out
;
257 sdi_csta
= readl(host
->base
+ S3C2410_SDICMDSTAT
);
258 sdi_dsta
= readl(host
->base
+ S3C2410_SDIDSTA
);
259 sdi_dcnt
= readl(host
->base
+ S3C2410_SDIDCNT
);
261 if( result
!=S3C2410_RES_OK
) {
266 if(host
->mrq
->data
->flags
& MMC_DATA_READ
) {
273 complete(&host
->complete_dma
);
274 spin_unlock_irqrestore( &host
->complete_lock
, iflags
);
279 host
->mrq
->data
->error
= MMC_ERR_DMA
;
280 host
->complete_what
= COMPLETION_NONE
;
281 complete(&host
->complete_dma
);
282 complete(&host
->complete_request
);
283 writel(0, host
->base
+ S3C2410_SDIIMSK
);
289 void s3c2410sdi_dma_setup(struct s3c2410sdi_host
*host
, eDMAPurpose_t purpose
) {
290 s3c2410_dmasrc_t source
;
294 source
= S3C2410_DMASRC_HW
;
298 source
= S3C2410_DMASRC_MEM
;
302 s3c2410_dma_devconfig(host
->dma
, source
, 3, host
->mem
->start
+ S3C2410_SDIDATA
);
303 s3c2410_dma_config(host
->dma
, 4, (1<<23) | (2<<24));
304 s3c2410_dma_set_buffdone_fn(host
->dma
, s3c2410sdi_dma_done_callback
);
305 s3c2410_dma_setflags(host
->dma
, S3C2410_DMAF_AUTOSTART
);
308 static void s3c2410sdi_request(struct mmc_host
*mmc
, struct mmc_request
*mrq
) {
309 struct s3c2410sdi_host
*host
= mmc_priv(mmc
);
310 u32 sdi_carg
, sdi_ccon
, sdi_timer
;
311 u32 sdi_bsize
, sdi_dcon
, sdi_imsk
;
313 DBG(KERN_DEBUG PFX
"request: [CMD] opcode:0x%02x arg:0x%08x flags:%x retries:%u\n",
314 mrq
->cmd
->opcode
, mrq
->cmd
->arg
, mrq
->cmd
->flags
, mrq
->cmd
->retries
);
317 sdi_ccon
= mrq
->cmd
->opcode
& S3C2410_SDICMDCON_INDEX
;
318 sdi_ccon
|= S3C2410_SDICMDCON_SENDERHOST
;
319 sdi_ccon
|= S3C2410_SDICMDCON_CMDSTART
;
321 sdi_carg
= mrq
->cmd
->arg
;
323 //FIXME: Timer value ?!
330 //enable interrupts for transmission errors
331 sdi_imsk
|= S3C2410_SDIIMSK_RESPONSEND
;
332 sdi_imsk
|= S3C2410_SDIIMSK_CRCSTATUS
;
335 host
->complete_what
= COMPLETION_CMDSENT
;
337 if (mrq
->cmd
->flags
& MMC_RSP_MASK
) {
338 host
->complete_what
= COMPLETION_RSPFIN
;
340 sdi_ccon
|= S3C2410_SDICMDCON_WAITRSP
;
341 sdi_imsk
|= S3C2410_SDIIMSK_CMDTIMEOUT
;
344 //We need the CMDSENT-Interrupt only if we want are not waiting
346 sdi_imsk
|= S3C2410_SDIIMSK_CMDSENT
;
349 if(mrq
->cmd
->flags
& MMC_RSP_LONG
) {
350 sdi_ccon
|= S3C2410_SDICMDCON_LONGRSP
;
353 if(mrq
->cmd
->flags
& MMC_RSP_CRC
) {
354 sdi_imsk
|= S3C2410_SDIIMSK_RESPONSECRC
;
359 host
->complete_what
= COMPLETION_XFERFINISH_RSPFIN
;
363 sdi_bsize
= (1 << mrq
->data
->blksz_bits
);
365 sdi_dcon
= (mrq
->data
->blocks
& S3C2410_SDIDCON_BLKNUM_MASK
);
366 sdi_dcon
|= S3C2410_SDIDCON_DMAEN
;
368 sdi_imsk
|= S3C2410_SDIIMSK_FIFOFAIL
;
369 sdi_imsk
|= S3C2410_SDIIMSK_DATACRC
;
370 sdi_imsk
|= S3C2410_SDIIMSK_DATATIMEOUT
;
371 sdi_imsk
|= S3C2410_SDIIMSK_DATAFINISH
;
372 sdi_imsk
|= 0xFFFFFFE0;
374 DBG(PFX
"request: [DAT] bsize:%u blocks:%u bytes:%u\n",
375 sdi_bsize
, mrq
->data
->blocks
, mrq
->data
->blocks
* sdi_bsize
);
377 if(mrq
->data
->flags
& MMC_DATA_WIDE
) {
378 sdi_dcon
|= S3C2410_SDIDCON_WIDEBUS
;
381 if(!(mrq
->data
->flags
& MMC_DATA_STREAM
)) {
382 sdi_dcon
|= S3C2410_SDIDCON_BLOCKMODE
;
385 if(mrq
->data
->flags
& MMC_DATA_WRITE
) {
386 sdi_dcon
|= S3C2410_SDIDCON_TXAFTERRESP
;
387 sdi_dcon
|= S3C2410_SDIDCON_XFER_TXSTART
;
388 s3c2410sdi_dma_setup(host
, DMAP_WRITE
);
389 #ifdef S3C2410SDI_DMA_BACKBUF
390 memcpy(host
->dmabuf_log
, mrq
->data
->req
->buffer
, mrq
->data
->blocks
* sdi_bsize
);
394 if(mrq
->data
->flags
& MMC_DATA_READ
) {
395 sdi_dcon
|= S3C2410_SDIDCON_RXAFTERCMD
;
396 sdi_dcon
|= S3C2410_SDIDCON_XFER_RXSTART
;
397 s3c2410sdi_dma_setup(host
, DMAP_READ
);
403 #ifdef S3C2410SDI_DMA_BACKBUF
404 s3c2410_dma_enqueue(host
->dma
, (void *) host
,
406 (mrq
->data
->blocks
<< mrq
->data
->blksz_bits
) );
408 s3c2410_dma_enqueue(host
->dma
, (void *) host
,
409 virt_to_phys(mrq
->data
->req
->buffer
),
410 (mrq
->data
->blocks
<< mrq
->data
->blksz_bits
) );
416 init_completion(&host
->complete_request
);
417 init_completion(&host
->complete_dma
);
419 //Clear command and data status registers
420 writel(0xFFFFFFFF, host
->base
+ S3C2410_SDICMDSTAT
);
421 writel(0xFFFFFFFF, host
->base
+ S3C2410_SDIDSTA
);
423 // Setup SDI controller
424 writel(sdi_bsize
,host
->base
+ S3C2410_SDIBSIZE
);
425 writel(sdi_timer
,host
->base
+ S3C2410_SDITIMER
);
426 writel(sdi_imsk
,host
->base
+ S3C2410_SDIIMSK
);
428 // Setup SDI command argument and data control
429 writel(sdi_carg
, host
->base
+ S3C2410_SDICMDARG
);
430 writel(sdi_dcon
, host
->base
+ S3C2410_SDIDCON
);
432 // This initiates transfer
433 writel(sdi_ccon
, host
->base
+ S3C2410_SDICMDCON
);
435 // Wait for transfer to complete
436 wait_for_completion(&host
->complete_request
);
437 DBG("[CMD] request complete.\n");
439 wait_for_completion(&host
->complete_dma
);
440 DBG("[DAT] DMA complete.\n");
443 // Wait for DMA to complete
444 // if(mrq->data) wait_for_completion(&host->complete_dma);
447 writel(0, host
->base
+ S3C2410_SDICMDARG
);
448 writel(0, host
->base
+ S3C2410_SDIDCON
);
449 writel(0, host
->base
+ S3C2410_SDICMDCON
);
450 writel(0, host
->base
+ S3C2410_SDIIMSK
);
453 mrq
->cmd
->resp
[0] = readl(host
->base
+ S3C2410_SDIRSP0
);
454 mrq
->cmd
->resp
[1] = readl(host
->base
+ S3C2410_SDIRSP1
);
455 mrq
->cmd
->resp
[2] = readl(host
->base
+ S3C2410_SDIRSP2
);
456 mrq
->cmd
->resp
[3] = readl(host
->base
+ S3C2410_SDIRSP3
);
460 DBG(PFX
"request done.\n");
462 // If we have no data transfer we are finished here
463 if (!mrq
->data
) goto request_done
;
465 // Calulate the amout of bytes transfer, but only if there was
467 if(mrq
->data
->error
== MMC_ERR_NONE
) {
468 mrq
->data
->bytes_xfered
= (mrq
->data
->blocks
<< mrq
->data
->blksz_bits
);
469 if(mrq
->data
->flags
& MMC_DATA_READ
);
470 #ifdef S3C2410SDI_DMA_BACKBUF
471 memcpy(mrq
->data
->req
->buffer
, host
->dmabuf_log
, mrq
->data
->bytes_xfered
);
474 mrq
->data
->bytes_xfered
= 0;
477 // If we had an error while transfering data we flush the
478 // DMA channel to clear out any garbage
479 if(mrq
->data
->error
!= MMC_ERR_NONE
) {
480 s3c2410_dma_ctrl(host
->dma
, S3C2410_DMAOP_FLUSH
);
481 DBG(PFX
"flushing DMA.\n");
483 // Issue stop command
484 if(mrq
->data
->stop
) mmc_wait_for_cmd(mmc
, mrq
->data
->stop
, 3);
492 static void s3c2410sdi_set_ios(struct mmc_host
*mmc
, struct mmc_ios
*ios
) {
493 struct s3c2410sdi_host
*host
= mmc_priv(mmc
);
494 u32 sdi_psc
, sdi_con
;
497 sdi_con
= readl(host
->base
+ S3C2410_SDICON
);
498 switch(ios
->power_mode
) {
501 s3c2410_gpio_setpin(S3C2410_GPA17
, 1); // card power on
503 s3c2410_gpio_cfgpin(S3C2410_GPE5
, S3C2410_GPE5_SDCLK
);
504 s3c2410_gpio_cfgpin(S3C2410_GPE6
, S3C2410_GPE6_SDCMD
);
505 s3c2410_gpio_cfgpin(S3C2410_GPE7
, S3C2410_GPE7_SDDAT0
);
506 s3c2410_gpio_cfgpin(S3C2410_GPE8
, S3C2410_GPE8_SDDAT1
);
507 s3c2410_gpio_cfgpin(S3C2410_GPE9
, S3C2410_GPE9_SDDAT2
);
508 s3c2410_gpio_cfgpin(S3C2410_GPE10
, S3C2410_GPE10_SDDAT3
);
510 sdi_con
|= S3C2410_SDICON_FIFORESET
;
515 s3c2410_gpio_setpin(S3C2410_GPA17
, 0); // card power off
517 s3c2410_gpio_setpin(S3C2410_GPE5
, 0);
518 s3c2410_gpio_cfgpin(S3C2410_GPE5
, S3C2410_GPE5_OUTP
);
523 for(sdi_psc
=0;sdi_psc
<255;sdi_psc
++) {
524 if( (clk_get_rate(host
->clk
) / (2*(sdi_psc
+1))) <= ios
->clock
) break;
527 if(sdi_psc
> 255) sdi_psc
= 255;
528 writel(sdi_psc
, host
->base
+ S3C2410_SDIPRE
);
531 if(ios
->clock
) sdi_con
|= S3C2410_SDICON_CLOCKTYPE
;
532 else sdi_con
&=~S3C2410_SDICON_CLOCKTYPE
;
534 writel(sdi_con
, host
->base
+ S3C2410_SDICON
);
537 static struct mmc_host_ops s3c2410sdi_ops
= {
538 .request
= s3c2410sdi_request
,
539 .set_ios
= s3c2410sdi_set_ios
,
542 static int s3c2410sdi_probe(struct device
*dev
)
544 struct platform_device
*pdev
= to_platform_device(dev
);
545 struct mmc_host
*mmc
;
546 struct s3c2410sdi_host
*host
;
550 mmc
= mmc_alloc_host(sizeof(struct s3c2410sdi_host
), dev
);
556 host
= mmc_priv(mmc
);
558 spin_lock_init( &host
->complete_lock
);
559 host
->complete_what
= COMPLETION_NONE
;
561 host
->dma
= S3C2410SDI_DMA
;
562 host
->irq_cd
= IRQ_EINT2
;
565 host
->mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
567 printk(KERN_INFO PFX
"failed to get io memory region resouce.\n");
569 goto probe_free_host
;
572 host
->mem
= request_mem_region(host
->mem
->start
,
573 RESSIZE(host
->mem
), pdev
->name
);
576 printk(KERN_INFO PFX
"failed to request io memory region.\n");
578 goto probe_free_host
;
581 host
->base
= ioremap(host
->mem
->start
, RESSIZE(host
->mem
));
582 if (host
->base
== 0) {
583 printk(KERN_INFO PFX
"failed to ioremap() io memory region.\n");
585 goto probe_free_mem_region
;
588 host
->irq
= platform_get_irq(pdev
, 0);
589 if (host
->irq
== 0) {
590 printk(KERN_INFO PFX
"failed to get interrupt resouce.\n");
595 if(request_irq(host
->irq
, s3c2410sdi_irq
, 0, DRIVER_NAME
, host
)) {
596 printk(KERN_INFO PFX
"failed to request sdi interrupt.\n");
601 s3c2410_gpio_cfgpin(S3C2410_GPF2
, S3C2410_GPF2_EINT2
);
602 set_irq_type(host
->irq_cd
, IRQT_BOTHEDGE
);
604 if(request_irq(host
->irq_cd
, s3c2410sdi_irq_cd
, 0, DRIVER_NAME
, host
)) {
605 printk(KERN_WARNING PFX
"failed to request card detect interrupt.\n" );
610 if(s3c2410_dma_request(S3C2410SDI_DMA
, &s3c2410sdi_dma_client
, NULL
)) {
611 printk(KERN_WARNING PFX
"unable to get DMA channel.\n" );
613 goto probe_free_irq_cd
;
616 host
->clk
= clk_get(dev
, "sdi");
617 if (IS_ERR(host
->clk
)) {
618 printk(KERN_INFO PFX
"failed to find clock source.\n");
619 ret
= PTR_ERR(host
->clk
);
621 goto probe_free_host
;
624 if((ret
= clk_use(host
->clk
))) {
625 printk(KERN_INFO PFX
"failed to use clock source.\n");
629 if((ret
= clk_enable(host
->clk
))) {
630 printk(KERN_INFO PFX
"failed to enable clock source.\n");
635 mmc
->ops
= &s3c2410sdi_ops
;
636 mmc
->ocr_avail
= MMC_VDD_32_33
;
637 mmc
->flags
= MMC_HOST_WIDEMODE
;
638 mmc
->f_min
= clk_get_rate(host
->clk
) / 512;
639 mmc
->f_max
= clk_get_rate(host
->clk
) / 2;
642 //HACK: There seems to be a hardware bug in TomTom GO.
643 if(mmc
->f_max
>3000000) mmc
->f_max
=3000000;
647 * Since we only have a 16-bit data length register, we must
648 * ensure that we don't exceed 2^16-1 bytes in a single request.
649 * Choose 64 (512-byte) sectors as the limit.
651 mmc
->max_sectors
= 64;
654 * Set the maximum segment size. Since we aren't doing DMA
655 * (yet) we are only limited by the data length register.
658 mmc
->max_seg_size
= mmc
->max_sectors
<< 9;
659 #ifdef S3C2410SDI_DMA_BACKBUF
660 host
->dmabuf_log
= dma_alloc_coherent(NULL
, mmc
->max_seg_size
,&host
->dmabuf_phys
, GFP_KERNEL
|GFP_DMA
);
662 if(!host
->dmabuf_log
) {
663 printk(KERN_INFO PFX
"failed to allocate DMA buffer.\n");
667 host
->dmabuf_size
= mmc
->max_seg_size
;
669 printk(KERN_INFO PFX
"probe: mapped sdi_base=%p irq=%u irq_cd=%u dma=%u dmabuf_l=%p dmabuf_p=%p.\n",
670 host
->base
, host
->irq
, host
->irq_cd
, host
->dma
, host
->dmabuf_log
, host
->dmabuf_phys
);
672 printk(KERN_INFO PFX
"probe: mapped sdi_base=%p irq=%u irq_cd=%u dma=%u.\n",
673 host
->base
, host
->irq
, host
->irq_cd
, host
->dma
);
675 if((ret
= mmc_add_host(mmc
))) {
676 printk(KERN_INFO PFX
"failed to add mmc host.\n");
680 dev_set_drvdata(dev
, mmc
);
682 printk(KERN_INFO PFX
"initialisation done.\n");
686 #ifdef S3C2410SDI_DMA_BACKBUF
687 dma_free_coherent(NULL
, host
->dmabuf_size
, host
->dmabuf_log
, host
->dmabuf_phys
);
691 clk_disable(host
->clk
);
694 clk_unuse(host
->clk
);
700 free_irq(host
->irq_cd
, host
);
703 free_irq(host
->irq
, host
);
708 probe_free_mem_region
:
709 release_mem_region(host
->mem
->start
, RESSIZE(host
->mem
));
717 static int s3c2410sdi_remove(struct device
*dev
)
719 struct mmc_host
*mmc
= dev_get_drvdata(dev
);
720 struct s3c2410sdi_host
*host
= mmc_priv(mmc
);
722 mmc_remove_host(mmc
);
723 #ifdef S3C2410SDI_DMA_BACKBUF
724 dma_free_coherent(NULL
, host
->dmabuf_size
, host
->dmabuf_log
, host
->dmabuf_phys
);
726 clk_disable(host
->clk
);
727 clk_unuse(host
->clk
);
729 free_irq(host
->irq_cd
, host
);
730 free_irq(host
->irq
, host
);
732 release_mem_region(host
->mem
->start
, RESSIZE(host
->mem
));
738 static struct device_driver s3c2410sdi_driver
=
740 .name
= "s3c2410-sdi",
741 .bus
= &platform_bus_type
,
742 .probe
= s3c2410sdi_probe
,
743 .remove
= s3c2410sdi_remove
,
746 static int __init
s3c2410sdi_init(void)
748 return driver_register(&s3c2410sdi_driver
);
751 static void __exit
s3c2410sdi_exit(void)
753 driver_unregister(&s3c2410sdi_driver
);
756 module_init(s3c2410sdi_init
);
757 module_exit(s3c2410sdi_exit
);
759 MODULE_DESCRIPTION("Samsung S3C2410 Multimedia Card Interface driver");
760 MODULE_LICENSE("GPL");