s3c2440linux2.6mmc/sd驱动程序


这几天要做SD卡方面的事情了,看了看相关资料,从网上得到了 s3c2440 在2.6下的驱动,经过修改,目前可以工作了,现拿出与大家分享.希望共同学习讨论.

     1 /*
      2  *  linux/drivers/mmc/s3c2410mci.h - Samsung S3C2410 SDI Interface driver
      3  *
      4  *  Copyright (C) 2004 Thomas Kleffel, All Rights Reserved.
      5  *
      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.
      9  */
     10 #include <linux/config.h>
     11 #include <linux/module.h>
     12 #include <linux/moduleparam.h>
     13 #include <linux/init.h>
     14 #include <linux/ioport.h>
     15 #include <linux/device.h>
     16 #include <linux/platform_device.h>
     17 #include <linux/interrupt.h>
     18 #include <linux/blkdev.h>
     19 #include <linux/delay.h>
     20 #include <linux/err.h>
     21 #include <linux/dma-mapping.h>
     22 #include <linux/mmc/host.h>
     23 #include <linux/mmc/protocol.h>
     24 #include <linux/clk.h>
     25 #include <linux/irq.h>
     26
     27 #include <asm/dma.h>
     28 #include <asm/dma-mapping.h>
     29 #include <asm/arch/dma.h>
     30
     31 #include <asm/io.h>
     32 #include <asm/irq.h>
     33 #include <asm/mach/mmc.h>
     34
     35 #include <asm/arch/regs-sdi.h>
     36 #include <asm/arch/regs-gpio.h>
     37 #include <asm/arch/mmc.h>
     38
     39 //#define CONFIG_MMC_DEBUG
#ifdef CONFIG_MMC_DEBUG
     42 #define DBG(x...)       printk(KERN_INFO x)
     43 #else
     44 #define DBG(x...)       do { } while (0)
     45 #endif
     46
     47 #include "s3c2440mci.h"
     48
     49 #define DRIVER_NAME "mmci-s3c2410"
     50 #define PFX DRIVER_NAME ": "
     51
     52 #define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
     53
     54 static struct s3c2410_dma_client s3c2410sdi_dma_client = {
     55     .name       = "s3c2410-sdi",
     56 };
 static irqreturn_t s3c2410sdi_irq(int irq, void *dev_id, struct pt_regs *regs)
     82 {
     83     struct s3c2410sdi_host *host;
     84     u32 sdi_csta, sdi_dsta, sdi_dcnt;
     85     u32 sdi_cclear, sdi_dclear;
     86     unsigned long iflags;
     87
     88     host = (struct s3c2410sdi_host *)dev_id;
     89
     90     /* Check for things not supposed to happen */
     91     if(!host) return IRQ_HANDLED;
     92
     93     sdi_csta    = readl(host->base + S3C2410_SDICMDSTAT);
     94     sdi_dsta    = readl(host->base + S3C2410_SDIDSTA);
     95     sdi_dcnt    = readl(host->base + S3C2410_SDIDCNT);
     96
     97     DBG(PFX "IRQ csta=0x%08x dsta=0x%08x dcnt:0x%08x\n", sdi_csta, sdi_dsta, sdi_dcnt);
     98
     99     spin_lock_irqsave( &host->complete_lock, iflags);
    100
    101     if( host->complete_what == COMPLETION_NONE ) {
    102         goto clear_imask;
    103     }
    104
    105     if(!host->mrq) {
    106         goto clear_imask;
    107     }
    108
    109     sdi_csta    = readl(host->base + S3C2410_SDICMDSTAT);
    110     sdi_dsta    = readl(host->base + S3C2410_SDIDSTA);
    111     sdi_dcnt    = readl(host->base + S3C2410_SDIDCNT);
    112     sdi_cclear  = 0;
    113     sdi_dclear  = 0;
    if(sdi_csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) {
    117         DBG(PFX "CMD TIMEOUT\n");
    118         host->mrq->cmd->error = MMC_ERR_TIMEOUT;
    119         goto transfer_closed;
    120     }
    121
    122     if(sdi_csta & S3C2410_SDICMDSTAT_CMDSENT) {
    123         if(host->complete_what == COMPLETION_CMDSENT) {
    124             DBG(PFX "COMPLETION_CMDSENT\n");
    125             host->mrq->cmd->error = MMC_ERR_NONE;
    126             goto transfer_closed;
    127         }
    128
    129         sdi_cclear |= S3C2410_SDICMDSTAT_CMDSENT;
    130     }
    131
    132     if(sdi_csta & S3C2410_SDICMDSTAT_CRCFAIL) {
    133
    134             DBG(PFX "S3C2410_SDICMDSTAT_CRCFAIL\n");
    135
    136         if ((host->mrq->cmd->flags & MMC_RSP_MASK) == MMC_RSP_LONG) {
    137             DBG(PFX "s3c2410 fixup : ignore CRC fail with long rsp\n");
    138             DBG(PFX "host->mrq->cmd->flags = %x\n", host->mrq->cmd->flags);
    139         }
    140         else {
    141             if(host->mrq->cmd->flags & MMC_RSP_CRC) {
    142                 DBG(PFX "COMMAND CRC FAILED %x\n", sdi_csta);
    143                 host->mrq->cmd->error = MMC_ERR_BADCRC;
    144                 goto transfer_closed;
    145             }
    146         }
    147         sdi_cclear |= S3C2410_SDICMDSTAT_CRCFAIL;
    148     }
     if(sdi_csta & S3C2410_SDICMDSTAT_RSPFIN) {
    151
    152             DBG(PFX "S3C2410_SDICMDSTAT_RSPFIN\n");
    153         if(host->complete_what == COMPLETION_RSPFIN) {
    154             host->mrq->cmd->error = MMC_ERR_NONE;
    155             goto transfer_closed;
    156         }
    157
    158         if(host->complete_what == COMPLETION_XFERFINISH_RSPFIN) {
    159             host->mrq->cmd->error = MMC_ERR_NONE;
    160             host->complete_what = COMPLETION_XFERFINISH;
    161         }
    162
    163         sdi_cclear |= S3C2410_SDICMDSTAT_RSPFIN;
    164     }
    165
    166     if(sdi_dsta & S3C2410_SDIDSTA_FIFOFAIL) {
    167             DBG(PFX "S3C2410_SDIDSTA_FIFOFAIL\n");
    168         host->mrq->cmd->error = MMC_ERR_NONE;
    169         host->mrq->data->error = MMC_ERR_FIFO;
    170         goto transfer_closed;
    171     }
    172
    173     if(sdi_dsta & S3C2410_SDIDSTA_RXCRCFAIL) {
    174         DBG(PFX "S3C2410_SDIDSTA_RXCRCFAIL\n");
    175         host->mrq->cmd->error = MMC_ERR_NONE;
    176         host->mrq->data->error = MMC_ERR_BADCRC;
    177         goto transfer_closed;
    178     }
    179
    180     if(sdi_dsta & S3C2410_SDIDSTA_CRCFAIL) {
    181         DBG(PFX "DATA CRC FAILED %u\n", sdi_csta);
    182         host->mrq->cmd->error = MMC_ERR_NONE;
    183         host->mrq->data->error = MMC_ERR_BADCRC;
    184         goto transfer_closed;
    185     }

     if(sdi_dsta & S3C2410_SDIDSTA_DATATIMEOUT) {
    188         DBG(PFX "S3C2410_SDIDSTA_DATATIMEOUT\n");
    189         host->mrq->cmd->error = MMC_ERR_NONE;
    190         host->mrq->data->error = MMC_ERR_TIMEOUT;
    191         goto transfer_closed;
    192     }
    193
    194     if(sdi_dsta & S3C2410_SDIDSTA_XFERFINISH) {
    195         DBG(PFX "S3C2410_SDIDSTA_XFERFINISH\n");
    196         if(host->complete_what == COMPLETION_XFERFINISH) {
    197             DBG(PFX "COMPLETION_XFERFINISH\n");
    198             host->mrq->cmd->error = MMC_ERR_NONE;
    199             host->mrq->data->error = MMC_ERR_NONE;
    200             goto transfer_closed;
    201         }
    202
    203         if(host->complete_what == COMPLETION_XFERFINISH_RSPFIN) {
    204             DBG(PFX "COMPLETION_XFERFINISH_RSPFIN\n");
    205             host->mrq->data->error = MMC_ERR_NONE;
    206             host->complete_what = COMPLETION_RSPFIN;
    207         }
    208
    209         sdi_dclear |= S3C2410_SDIDSTA_XFERFINISH;
    210     }
    211
    212     writel(sdi_cclear, host->base + S3C2410_SDICMDSTAT);
    213     writel(sdi_dclear, host->base + S3C2410_SDIDSTA);
    214
    215     spin_unlock_irqrestore( &host->complete_lock, iflags);
    216     DBG(PFX "IRQ still waiting.\n");
    217     return IRQ_HANDLED;

 transfer_closed:
    221     writel(sdi_cclear, host->base + S3C2410_SDICMDSTAT);
    222     writel(sdi_dclear, host->base + S3C2410_SDIDSTA);
    223     host->complete_what = COMPLETION_NONE;
    224     complete(&host->complete_request);
    225     writel(0, host->base + S3C2440_SDIIMSK);
    226     spin_unlock_irqrestore( &host->complete_lock, iflags);
    227     DBG(PFX "IRQ transfer closed.\n");
    228     return IRQ_HANDLED;
    229
    230 clear_imask:
    231     writel(0, host->base + S3C2440_SDIIMSK);
    232     spin_unlock_irqrestore( &host->complete_lock, iflags);
    233     DBG(PFX "IRQ clear imask.\n");
    234     return IRQ_HANDLED;
    235
    236 }
    237
    238
    239 /*
    240  * ISR for the CardDetect Pin
    241 */
    242
    243 static irqreturn_t s3c2410sdi_irq_cd(int irq, void *dev_id, struct pt_regs *regs)
    244 {
    245     struct s3c2410sdi_host *host = (struct s3c2410sdi_host *)dev_id;
    246
    247     //DBG(" %s : %s :%s\n", __FUNCTION__, __FILE__, __LINE__);
    248
    249     mmc_detect_change(host->mmc, S3C2410SDI_CDLATENCY);
    250
    251     return IRQ_HANDLED;
    252 }
    253
 void s3c2410sdi_dma_done_callback(struct s3c2410_dma_chan *dma_ch, void *buf_id,
    257     int size, enum s3c2410_dma_buffresult result)
    258 {   unsigned long iflags;
    259     u32 sdi_csta, sdi_dsta,sdi_dcnt;
    260     struct s3c2410sdi_host *host = (struct s3c2410sdi_host *)buf_id;
    261
    262     sdi_csta    = readl(host->base + S3C2410_SDICMDSTAT);
    263     sdi_dsta    = readl(host->base + S3C2410_SDIDSTA);
    264     sdi_dcnt    = readl(host->base + S3C2410_SDIDCNT);
    265
    266     DBG(PFX "DMAD csta=0x%08x dsta=0x%08x dcnt:0x%08x result:0x%08x\n", sdi_csta, sdi_dsta, sdi_dcnt, result);
    267
    268     spin_lock_irqsave( &host->complete_lock, iflags);
    269
    270     if(!host->mrq) goto out;
    271     if(!host->mrq->data) goto out;
    272
    273
    274     sdi_csta    = readl(host->base + S3C2410_SDICMDSTAT);
    275     sdi_dsta    = readl(host->base + S3C2410_SDIDSTA);
    276     sdi_dcnt    = readl(host->base + S3C2410_SDIDCNT);
    277
    278     if( result!=S3C2410_RES_OK ) {
    279         goto fail_request;
    280     }
    281
    282
    283     if(host->mrq->data->flags & MMC_DATA_READ) {
    284         if( sdi_dcnt>0 ) {
    285             goto fail_request;
    286         }
    287     }
    288
    289 out:
    290     complete(&host->complete_dma);
    291     spin_unlock_irqrestore( &host->complete_lock, iflags);
    292     return;
    293
 fail_request:
    296     host->mrq->data->error = MMC_ERR_FAILED;
    297     host->complete_what = COMPLETION_NONE;
    298     complete(&host->complete_request);
    299     writel(0, host->base + S3C2440_SDIIMSK);
    300     goto out;
    301
    302 }
    303
    304
    305 void s3c2410sdi_dma_setup(struct s3c2410sdi_host *host, enum s3c2410_dmasrc source) {
    306
    307     s3c2410_dma_devconfig(host->dma, source, 3, host->mem->start + S3C2440_SDIDATA);
    308     s3c2410_dma_config(host->dma, 4, (1<<23) | (2<<24));
    309     s3c2410_dma_set_buffdone_fn(host->dma, s3c2410sdi_dma_done_callback);
    310     s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
    311 }
    312
    313 static void s3c2410sdi_request(struct mmc_host *mmc, struct mmc_request *mrq) {
    314     struct s3c2410sdi_host *host = mmc_priv(mmc);
    315     struct device *dev = mmc_dev(host->mmc);
    316     struct platform_device *pdev = to_platform_device(dev);
    317     u32 sdi_carg, sdi_ccon, sdi_timer;
    318     u32 sdi_bsize, sdi_dcon, sdi_imsk;
    319     u32 sdi_fsta;
    320
    321     int dma_len = 0;
    322
    323     DBG(KERN_DEBUG PFX "request: [CMD] opcode:0x%02x arg:0x%08x flags:%x retries:%u\n",
    324         mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags, mrq->cmd->retries);
    325
    326     DBG(PFX "request : %s mode\n",mmc->mode == MMC_MODE_MMC ? "mmc" : "sd");
 328     sdi_ccon = mrq->cmd->opcode & S3C2410_SDICMDCON_INDEX;
    329     sdi_ccon |= S3C2410_SDICMDCON_SENDERHOST;
    330     sdi_ccon |= S3C2410_SDICMDCON_CMDSTART;
    331
    332     //sdi_fsta = readl(host->base + S3C2410_SDIFSTA);
    333     sdi_fsta = readl(host->base + S3C2410_SDIFSTA);
    334
    335     sdi_carg = mrq->cmd->arg;
    336
    337     //sdi_timer= 0xF000;
    338     sdi_timer= 0x7fffff;
    339
    340     sdi_bsize= 0;
    341     sdi_dcon = 0;
    342     sdi_imsk = 0;
    343
    344     /* enable interrupts for transmission errors */
    345     sdi_imsk |= S3C2410_SDIIMSK_RESPONSEND;
    346     sdi_imsk |= S3C2410_SDIIMSK_CRCSTATUS;
    347
    348     host->complete_what = COMPLETION_CMDSENT;
    349
    350     if ((mrq->cmd->flags & MMC_RSP_MASK) != MMC_RSP_NONE) {
    351         host->complete_what = COMPLETION_RSPFIN;
    352
    353         sdi_ccon |= S3C2410_SDICMDCON_WAITRSP;
    354         sdi_imsk |= S3C2410_SDIIMSK_CMDTIMEOUT;
    355
    356     } else {
    357         /* We need the CMDSENT-Interrupt only if we want are not waiting
    358          * for a response
    359          */
    360         sdi_imsk |= S3C2410_SDIIMSK_CMDSENT;
    361     }
    362
    363     //if(mrq->cmd->flags & MMC_RSP_LONG) {
    364     if((mrq->cmd->flags & MMC_RSP_MASK) == MMC_RSP_LONG) {
    365         sdi_ccon |= S3C2410_SDICMDCON_LONGRSP;
    366     }
  367
    368     if(mrq->cmd->flags & MMC_RSP_CRC) {
    369         sdi_imsk |= S3C2410_SDIIMSK_RESPONSECRC;
    370     }
    371
    372     if (mrq->data) {
    373         host->complete_what = COMPLETION_XFERFINISH_RSPFIN;
    374
    375         sdi_bsize = (1 << mrq->data->blksz_bits);
    376         host->size = mrq->data->blocks << mrq->data->blksz_bits;
    377
    378         sdi_dcon  = (mrq->data->blocks & S3C2410_SDIDCON_BLKNUM_MASK);
    379         sdi_dcon |= S3C2410_SDIDCON_DMAEN;
    380
    381         sdi_dcon |= S3C2410_SDIDCON_DATA_WORD;
    382         sdi_dcon |= S3C2410_SDIDCON_DTST;
    383
    384         sdi_imsk |= S3C2410_SDIIMSK_FIFOFAIL;
    385         sdi_imsk |= S3C2410_SDIIMSK_DATACRC;
    386         sdi_imsk |= S3C2410_SDIIMSK_DATATIMEOUT;
    387         sdi_imsk |= S3C2410_SDIIMSK_DATAFINISH;
    388         sdi_imsk |= 0xFFFFFFE0;
    389
    390         sdi_fsta |= S3C2440_SDIFSTA_FIFORESET;
    391
    392         DBG(PFX "request: [DAT] bsize:%u blocks:%u bytes:%u\n",
    393             sdi_bsize, mrq->data->blocks, mrq->data->blocks * sdi_bsize);
    394
    395
    396         if (host->bus_width == MMC_BUS_WIDTH_4) {
    397             sdi_dcon |= S3C2410_SDIDCON_WIDEBUS;
    398         }
    399
    400         if(!(mrq->data->flags & MMC_DATA_STREAM)) {
    401             sdi_dcon |= S3C2410_SDIDCON_BLOCKMODE;
    402         }
    403
    404         if(mrq->data->flags & MMC_DATA_WRITE) {
    405             sdi_dcon |= S3C2410_SDIDCON_TXAFTERRESP;
    406             sdi_dcon |= S3C2410_SDIDCON_XFER_TXSTART;
    407         }
    408
    409         if(mrq->data->flags & MMC_DATA_READ) {
    410             sdi_dcon |= S3C2410_SDIDCON_RXAFTERCMD;
    411             sdi_dcon |= S3C2410_SDIDCON_XFER_RXSTART;
    412         }
    413
    414         s3c2410sdi_dma_setup(host, mrq->data->flags & MMC_DATA_WRITE ? S3C2410_DMASRC_MEM : S3C2410_DMASRC_HW);
    415
    416         /* see DMA-API.txt */
    417         dma_len = dma_map_sg(&pdev->dev, mrq->data->sg, \
    418                 mrq->data->sg_len, \
    419                 mrq->data->flags & MMC_DATA_READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
    420
    421         /* start DMA */
    422         s3c2410_dma_enqueue(host->dma, (void *) host,
    423             sg_dma_address(&mrq->data->sg[0]),
    424             (mrq->data->blocks << mrq->data->blksz_bits) );
    425     }
    426
    427     host->mrq = mrq;
    428
    429     init_completion(&host->complete_request);
    430     init_completion(&host->complete_dma);
    431
    432     /* Clear command and data status registers */
    433     writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT);
    434     writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA);
    435
    436     writel(sdi_fsta, host->base + S3C2410_SDIFSTA);
    437
    438     /* Setup SDI controller */
    439     writel(sdi_bsize, host->base + S3C2410_SDIBSIZE);
    440     writel(sdi_timer, host->base + S3C2410_SDITIMER);
    441     writel(sdi_imsk, host->base + S3C2440_SDIIMSK);
    442
    443     /* Setup SDI command argument and data control */
    444     writel(sdi_carg, host->base + S3C2410_SDICMDARG);
    445     writel(sdi_dcon, host->base + S3C2410_SDIDCON);
    446
    447     /* This initiates transfer */
    448     writel(sdi_ccon, host->base + S3C2410_SDICMDCON);
    449
    450
    451     /* Wait for transfer to complete */
    452     wait_for_completion(&host->complete_request);
    453
    454     DBG(PFX "[CMD] request complete.\n");
    455
    456     if(mrq->data) {
    457         wait_for_completion(&host->complete_dma);
    458         DBG(PFX "[DAT] DMA complete.\n");
    459     }
    460
    461     /* Cleanup controller */
    462     writel(0, host->base + S3C2410_SDICMDARG);
    463     writel(0, host->base + S3C2410_SDIDCON);
    464     writel(0, host->base + S3C2410_SDICMDCON);
    465     writel(0, host->base + S3C2440_SDIIMSK);
    466
    467     /*  Read response */
    468     mrq->cmd->resp[0] = readl(host->base + S3C2410_SDIRSP0);
    469     mrq->cmd->resp[1] = readl(host->base + S3C2410_SDIRSP1);
    470     mrq->cmd->resp[2] = readl(host->base + S3C2410_SDIRSP2);
    471     mrq->cmd->resp[3] = readl(host->base + S3C2410_SDIRSP3);
    472
    473     host->mrq = NULL;
    474
    475     writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT);
    476     writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA);
    477
    478     DBG(PFX "request done.\n");
    479
    480     /* If we have no data transfer we are finished here */
    481     if (!mrq->data) goto request_done;
 482
    483     dma_unmap_sg(&pdev->dev, mrq->data->sg, dma_len, \
    484                  mrq->data->flags & MMC_DATA_READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
    485
    486     /* Calulate the amout of bytes transfer, but only if there was
    487      * no error
    488      */
    489     if(mrq->data->error == MMC_ERR_NONE) {
    490         mrq->data->bytes_xfered = (mrq->data->blocks << mrq->data->blksz_bits);
    491     } else {
    492         mrq->data->bytes_xfered = 0;
    493     }
    494
    495     /* If we had an error while transfering data we flush the
    496      * DMA channel to clear out any garbage
    497      */
    498     if(mrq->data->error != MMC_ERR_NONE) {
    499         s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
    500         DBG(PFX "flushing DMA.\n");
    501     }
    502
    503     if(mrq->data->stop) mmc_wait_for_cmd(mmc, mrq->data->stop, 3);
    504
    505 request_done:
    506
    507     mrq->done(mrq);
    508 }
  510 static void s3c2410sdi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) {
    511     struct s3c2410sdi_host *host = mmc_priv(mmc);
    512     u32 sdi_psc, sdi_con, sdi_fsta;
    513
    514     DBG(" %s: %s: line = %d\n", __FUNCTION__, __FILE__, __LINE__);
    515
    516     /* Set power */
    517     sdi_con = readl(host->base + S3C2410_SDICON);
    518     sdi_fsta = readl(host->base + S3C2410_SDIFSTA);
    519
    520     switch(ios->power_mode) {
    521         case MMC_POWER_ON:
    522         case MMC_POWER_UP:
    523             DBG(PFX "power on\n");
    524             s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);
    525             s3c2410_gpio_pullup(S3C2410_GPE5, 0);
    526             s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);
    527             s3c2410_gpio_pullup(S3C2410_GPE6, 0);
    528             s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);
    529             s3c2410_gpio_pullup(S3C2410_GPE7, 0);
    530             s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
    531             s3c2410_gpio_pullup(S3C2410_GPE8, 0);
    532             s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
    533             s3c2410_gpio_pullup(S3C2410_GPE9, 0);
    534             s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
    535             s3c2410_gpio_pullup(S3C2410_GPE10, 0);
    536
    537             if (host->pdata->set_power)
    538                 (host->pdata->set_power)(1);
    539
    540             #ifdef CONFIG_CPU_S3C2440
    541                 sdi_fsta |= S3C2440_SDIFSTA_FIFORESET;
    542             #else
    543                 sdi_con |= S3C2410_SDICON_FIFORESET;
    544             #endif
    545
    546             //sdi_con |= S3C2410_SDICON_BYTEORDER;
    547
    548             break;
  550         case MMC_POWER_OFF:
    551         default:
    552             if (host->pdata->set_power)
    553                 (host->pdata->set_power)(0);
    554             break;
    555     }
    556
    557     /* Set clock */
    558     for(sdi_psc = 0; sdi_psc < 255; sdi_psc++) {
    559         #ifdef CONFIG_CPU_S3C2440
    560         if( (clk_get_rate(host->clk) / ((sdi_psc + 1))) <= ios->clock) break;
    561         #else
    562         if( (clk_get_rate(host->clk) / (2 * (sdi_psc + 1))) <= ios->clock) break;
    563         #endif
    564     }
    565
    566     DBG("\n  ios->clock = %u \n", ios->clock);
    567
    568     if(sdi_psc > 255) sdi_psc = 255;
    569
    570     writel(sdi_psc, host->base + S3C2410_SDIPRE);
    571
    572     /* Set CLOCK_ENABLE */
    573     #ifdef CONFIG_CPU_S3C2440
    574     if(ios->clock)  sdi_con |= S3C2440_SDICON_CLOCK_OUTE;
    575     else        sdi_con &= ~S3C2440_SDICON_CLOCK_OUTE;
    576     #else
    577     if(ios->clock)  sdi_con |= S3C2410_SDICON_CLOCKTYPE;
    578     else        sdi_con &=~S3C2410_SDICON_CLOCKTYPE;
    579     #endif
    580
    581     #ifdef CONFIG_CPU_S3C2440
    582     writel(sdi_fsta, host->base + S3C2410_SDIFSTA);
    583     #endif
    584
    585     writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT);
    586     writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA);
  587
    588     //writel(0x0FFF, host->base + S3C2410_SDIDSTA);
    589
    590     writel(sdi_con, host->base + S3C2410_SDICON);
    591
    592     host->bus_width = ios->bus_width;
    593
    594     DBG("\n host->bus_width = %u \n", host->bus_width);
    595
    596 }
    597
    598 static struct mmc_host_ops s3c2410sdi_ops = {
    599     .request    = s3c2410sdi_request,
    600     .set_ios    = s3c2410sdi_set_ios,
    601 };

  611 static struct s3c24xx_mmc_platdata s3c2410_mmc_defplat = {
    612     .gpio_detect    = S3C2410_GPG10,
    613     //.set_power    = s3c2410_mmc_def_setpower,
    614     .set_power  = NULL,
    615     .f_max      = 3000000,
    616     .ocr_avail  = MMC_VDD_32_33,
    617 };
    618
    619 static int s3c2410sdi_probe(struct device *dev)
    620 {
    621     struct platform_device  *pdev = to_platform_device(dev);
    622     struct mmc_host     *mmc;
    623     s3c24xx_mmc_pdata_t *pdata;
    624     struct s3c2410sdi_host  *host;
    625
    626     int ret;
    627
    628     mmc = mmc_alloc_host(sizeof(struct s3c2410sdi_host), dev);
    629     if (!mmc) {
    630         ret = -ENOMEM;
    631         goto probe_out;
    632     }
    633
    634     host = mmc_priv(mmc);
    635
    636     spin_lock_init( &host->complete_lock );
    637     host->complete_what     = COMPLETION_NONE;
    638     host->mmc       = mmc;
    639     host->dma       = S3C2410SDI_DMA;
    640
    641     pdata = dev->platform_data;
    642     if (!pdata) {
    643         dev->platform_data = &s3c2410_mmc_defplat;
    644         pdata = &s3c2410_mmc_defplat;
    645     }
    646
    647     host->pdata = pdata;

 649     host->irq_cd = s3c2410_gpio_getirq(pdata->gpio_detect);
    650     s3c2410_gpio_cfgpin(pdata->gpio_detect, S3C2410_GPIO_IRQ);
    651
    652     host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    653     if (!host->mem) {
    654         printk(KERN_ERR PFX "failed to get io memory region resouce.\n");
    655         ret = -ENOENT;
    656         goto probe_free_host;
    657     }
    658
    659     host->mem = request_mem_region(host->mem->start,
    660         RESSIZE(host->mem), pdev->name);
    661
    662     if (!host->mem) {
    663         printk(KERN_ERR PFX "failed to request io memory region.\n");
    664         ret = -ENOENT;
    665         goto probe_free_host;
    666     }
    667
    668     host->base = ioremap(host->mem->start, RESSIZE(host->mem));
    669     if (host->base == 0) {
    670         printk(KERN_ERR PFX "failed to ioremap() io memory region.\n");
    671         ret = -EINVAL;
    672         goto probe_free_mem_region;
    673     }
    674
    675     host->irq = platform_get_irq(pdev, 0);
    676     if (host->irq == 0) {
    677         printk(KERN_ERR PFX "failed to get interrupt resouce.\n");
    678         ret = -EINVAL;
    679         goto probe_iounmap;
    680     }
    681
    682     if(request_irq(host->irq, s3c2410sdi_irq, 0, DRIVER_NAME, host)) {
    683         printk(KERN_ERR PFX "failed to request sdi interrupt.\n");
    684         ret = -ENOENT;
    685         goto probe_iounmap;
    686     }

  689     s3c2410_gpio_cfgpin(S3C2410_GPG10, S3C2410_GPG10_EINT18);
    690
    691     set_irq_type(host->irq_cd, IRQT_BOTHEDGE);
    692
    693     if(request_irq(host->irq_cd, s3c2410sdi_irq_cd, 0, DRIVER_NAME, host)) {
    694         printk(KERN_ERR PFX "failed to request card detect interrupt.\n" );
    695         ret = -ENOENT;
    696         goto probe_free_irq;
    697     }
    698
    699     if(s3c2410_dma_request(S3C2410SDI_DMA, &s3c2410sdi_dma_client, NULL)) {
    700         printk(KERN_ERR PFX "unable to get DMA channel.\n" );
    701         ret = -EBUSY;
    702         goto probe_free_irq_cd;
    703     }
    704
    705     host->clk = clk_get(dev, "sdi");
    706     if (IS_ERR(host->clk)) {
    707         printk(KERN_ERR PFX "failed to find clock source.\n");
    708         ret = PTR_ERR(host->clk);
    709         host->clk = NULL;
    710         goto probe_free_host;
    711     }
    712
    713     if((ret = clk_enable(host->clk))) {
    714         printk(KERN_ERR PFX "failed to enable clock source.\n");
    715         goto clk_free;
    716     }
    717
    718
    719     mmc->ops    = &s3c2410sdi_ops;
    720     mmc->ocr_avail  = MMC_VDD_32_33;
    721
    722     mmc->f_min  = clk_get_rate(host->clk) / 512;
    723     mmc->f_max  = clk_get_rate(host->clk) / 2;
    724
    725     mmc->caps   = MMC_CAP_4_BIT_DATA;
 736     mmc->max_sectors = 64;
    737
    738     /*
    739      * Set the maximum segment size.  Since we aren't doing DMA
    740      * (yet) we are only limited by the data length register.
    741      */
    742
    743     mmc->max_seg_size = mmc->max_sectors << 9;
    744
    745     printk(KERN_INFO PFX "probe: mapped sdi_base=%p irq=%u irq_cd=%u \n", host->base, host->irq, host->irq_cd);
    746
    747     if((ret = mmc_add_host(mmc))) {
    748         printk(KERN_ERR PFX "failed to add mmc host.\n");
    749         goto clk_disable;
    750     }
    751
    752     dev_set_drvdata(dev, mmc);
    753
    754     printk(KERN_INFO PFX "initialisation done.\n");
    755     return 0;
    756
    757  clk_disable:
    758     clk_disable(host->clk);
    759
    760  clk_free:
    761     clk_put(host->clk);
    762
    763  probe_free_irq_cd:
    764     free_irq(host->irq_cd, host);
    765
    766  probe_free_irq:
    767     free_irq(host->irq, host);
    768
    769  probe_iounmap:
    770     iounmap(host->base);
    771
    772  probe_free_mem_region:
    773     release_mem_region(host->mem->start, RESSIZE(host->mem));
                                                                                                                      
    775  probe_free_host:
    776     mmc_free_host(mmc);
    777  probe_out:
    778     return ret;
    779 }
    780
    781 static int s3c2410sdi_remove(struct device *dev)
    782 {
    783     struct mmc_host     *mmc  = dev_get_drvdata(dev);
    784     struct s3c2410sdi_host  *host = mmc_priv(mmc);
    785
    786     mmc_remove_host(mmc);
    787     clk_disable(host->clk);
    788     clk_put(host->clk);
    789     free_irq(host->irq_cd, host);
    790     free_irq(host->irq, host);
    791     iounmap(host->base);
    792     release_mem_region(host->mem->start, RESSIZE(host->mem));
    793     mmc_free_host(mmc);
    794
    795     return 0;
    796 }
    797
    798 static struct device_driver s3c2410sdi_driver =
    799 {
    800         .name           = "s3c2410-sdi",
    801         .bus            = &platform_bus_type,
    802         .probe          = s3c2410sdi_probe,
    803         .remove         = s3c2410sdi_remove,
    804 };
 static int __init s3c2410sdi_init(void)
    807 {
    808     return driver_register(&s3c2410sdi_driver);
    809 }
    810
    811 static void __exit s3c2410sdi_exit(void)
    812 {
    813     driver_unregister(&s3c2410sdi_driver);
    814 }
    815
    816 module_init(s3c2410sdi_init);
    817 module_exit(s3c2410sdi_exit);
    818
    819 MODULE_DESCRIPTION("Samsung S3C2410 Multimedia Card Interface driver");
    820 MODULE_LICENSE("GPL");
                                                                     

你可能感兴趣的:(s3c2440linux2.6mmc/sd驱动程序)