📄 full-h1940-2.6.21.patch
字号:
+ if (0 == (stoptries--)) {+#ifdef CONFIG_MMC_DEBUG+ dbg_dumpregs(host, "DRF");+#endif++ return -EINVAL;+ }+ }++ dcon = data->blocks & S3C2410_SDIDCON_BLKNUM_MASK;++ if (host->dodma) {+ dcon |= S3C2410_SDIDCON_DMAEN;+ }++ if (host->bus_width == MMC_BUS_WIDTH_4) {+ dcon |= S3C2410_SDIDCON_WIDEBUS;+ }++ if (!(data->flags & MMC_DATA_STREAM)) {+ dcon |= S3C2410_SDIDCON_BLOCKMODE;+ }++ if (data->flags & MMC_DATA_WRITE) {+ dcon |= S3C2410_SDIDCON_TXAFTERRESP;+ dcon |= S3C2410_SDIDCON_XFER_TXSTART;+ }++ if (data->flags & MMC_DATA_READ) {+ dcon |= S3C2410_SDIDCON_RXAFTERCMD;+ dcon |= S3C2410_SDIDCON_XFER_RXSTART;+ }++ if (host->is2440) {+ dcon |= S3C2440_SDIDCON_DS_WORD;+ dcon |= S3C2440_SDIDCON_DATSTART;+ }++ writel(dcon, host->base + S3C2410_SDIDCON);++ /* write BSIZE register */++ writel(data->blksz, host->base + S3C2410_SDIBSIZE);++ /* add to IMASK register */+ imsk = S3C2410_SDIIMSK_FIFOFAIL | S3C2410_SDIIMSK_DATACRC |+ S3C2410_SDIIMSK_DATATIMEOUT | S3C2410_SDIIMSK_DATAFINISH;++ enable_imask(host, imsk);++ /* write TIMER register */++ if (host->is2440) {+ writel(0x007FFFFF, host->base + S3C2410_SDITIMER);+ } else {+ writel(0x0000FFFF, host->base + S3C2410_SDITIMER);++ //FIX: set slow clock to prevent timeouts on read+ if (data->flags & MMC_DATA_READ) {+ writel(0xFF, host->base + S3C2410_SDIPRE);+ }+ }++ //debug_dump_registers(host, "Data setup:");++ return 0;+}++static int s3cmci_prepare_pio(struct s3cmci_host *host, struct mmc_data *data)+{+ int rw = (data->flags & MMC_DATA_WRITE)?1:0;++ if (rw != ((data->flags & MMC_DATA_READ)?0:1))+ return -EINVAL;++ host->pio_sgptr = 0;+ host->pio_words = 0;+ host->pio_count = 0;+ host->pio_active = rw?XFER_WRITE:XFER_READ;++ if (rw) {+ do_pio_write(host);+ enable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);+ } else {+ enable_imask(host, S3C2410_SDIIMSK_RXFIFOHALF+ | S3C2410_SDIIMSK_RXFIFOLAST);+ }++ return 0;+}++static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)+{+ int dma_len, i;++ int rw = (data->flags & MMC_DATA_WRITE)?1:0;++ if (rw != ((data->flags & MMC_DATA_READ)?0:1))+ return -EINVAL;++ s3cmci_dma_setup(host, rw?S3C2410_DMASRC_MEM:S3C2410_DMASRC_HW);+ s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);++ dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,+ (rw)?DMA_TO_DEVICE:DMA_FROM_DEVICE);+++ if (dma_len == 0)+ return -ENOMEM;++ host->dma_complete = 0;+ host->dmatogo = dma_len;++ for (i = 0; i < dma_len; i++) {+ int res;++ dbg(host, dbg_dma, "enqueue %i:%u@%u\n", i,+ sg_dma_address(&data->sg[i]),+ sg_dma_len(&data->sg[i]));++ res = s3c2410_dma_enqueue(host->dma, (void *) host,+ sg_dma_address(&data->sg[i]),+ sg_dma_len(&data->sg[i]));++ if (res) {+ s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);+ return -EBUSY;+ }+ }++ s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_START);++ return 0;+}++static void s3cmci_send_request(struct mmc_host *mmc)+{+ struct s3cmci_host *host = mmc_priv(mmc);+ struct mmc_request *mrq = host->mrq;+ struct mmc_command *cmd = host->cmd_is_stop?mrq->stop:mrq->cmd;++ host->ccnt++;+#ifdef CONFIG_MMC_DEBUG+ prepare_dbgmsg(host, cmd, host->cmd_is_stop);+#endif+ //Clear command, data and fifo status registers+ //Fifo clear only necessary on 2440, but doesn't hurt on 2410+ writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT);+ writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA);+ writel(0xFFFFFFFF, host->base + S3C2410_SDIFSTA);++ if (cmd->data) {+ int res;+ res = s3cmci_setup_data(host, cmd->data);++ host->dcnt++;++ if (res) {+ cmd->error = MMC_ERR_DMA;+ cmd->data->error = MMC_ERR_DMA;++ mmc_request_done(mmc, mrq);+ return;+ }+++ if (host->dodma) {+ res = s3cmci_prepare_dma(host, cmd->data);+ } else {+ res = s3cmci_prepare_pio(host, cmd->data);+ }++ if (res) {+ cmd->error = MMC_ERR_DMA;+ cmd->data->error = MMC_ERR_DMA;++ mmc_request_done(mmc, mrq);+ return;+ }++ }++ // Send command+ s3cmci_send_command(host, cmd);++ // Enable Interrupt+ enable_irq(host->irq);+}++static void s3cmci_request(struct mmc_host *mmc, struct mmc_request *mrq)+{+ struct s3cmci_host *host = mmc_priv(mmc);++ host->cmd_is_stop = 0;+ host->mrq = mrq;++ s3cmci_send_request(mmc);+}++static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)+{+ struct s3cmci_host *host = mmc_priv(mmc);+ u32 mci_psc, mci_con;++ //Set power+ mci_con = readl(host->base + S3C2410_SDICON);+ switch(ios->power_mode) {+ case MMC_POWER_ON:+ case MMC_POWER_UP:+ s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);+ s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);+ s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);+ s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);+ s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);+ s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);++ if (!host->is2440)+ mci_con|=S3C2410_SDICON_FIFORESET;++ break;++ case MMC_POWER_OFF:+ default:+ s3c2410_gpio_setpin(S3C2410_GPE5, 0);+ s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_OUTP);++ if (host->is2440)+ mci_con|=S3C2440_SDICON_SDRESET;++ break;+ }++ //Set clock+ for (mci_psc=0; mci_psc<255; mci_psc++) {+ host->real_rate = host->clk_rate / (host->clk_div*(mci_psc+1));++ if (host->real_rate <= ios->clock)+ break;+ }++ if(mci_psc > 255) mci_psc = 255;+ host->prescaler = mci_psc;++ writel(host->prescaler, host->base + S3C2410_SDIPRE);++ //If requested clock is 0, real_rate will be 0, too+ if (ios->clock == 0)+ host->real_rate = 0;++ //Set CLOCK_ENABLE+ if (ios->clock)+ mci_con |= S3C2410_SDICON_CLOCKTYPE;+ else+ mci_con &=~S3C2410_SDICON_CLOCKTYPE;++ writel(mci_con, host->base + S3C2410_SDICON);++ if ((ios->power_mode==MMC_POWER_ON)+ || (ios->power_mode==MMC_POWER_UP)) {++ dbg(host, dbg_conf, "running at %lukHz (requested: %ukHz).\n",+ host->real_rate/1000, ios->clock/1000);+ } else {+ dbg(host, dbg_conf, "powered down.\n");+ }++ host->bus_width = ios->bus_width;++}++static void s3cmci_reset(struct s3cmci_host *host)+{+ u32 con = readl(host->base + S3C2410_SDICON);++ con |= S3C2440_SDICON_SDRESET;++ writel(con, host->base + S3C2410_SDICON);+}++static struct mmc_host_ops s3cmci_ops = {+ .request = s3cmci_request,+ .set_ios = s3cmci_set_ios,+};++static struct s3c24xx_mmc_platdata s3c2410_mmc_defplat = {+ .gpio_detect = S3C2410_GPF2,+};++static int s3cmci_probe(struct platform_device *pdev, int is2440)+{+ struct mmc_host *mmc;+ struct s3cmci_host *host;+ s3c24xx_mmc_pdata_t *pdata;++ int ret;++ mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev);+ if (!mmc) {+ ret = -ENOMEM;+ goto probe_out;+ }++ host = mmc_priv(mmc);+ host->mmc = mmc;+ host->pdev = pdev;++ spin_lock_init(&host->complete_lock);+ tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);+ if (is2440) {+ host->is2440 = 1;+ host->sdiimsk = S3C2440_SDIIMSK;+ host->sdidata = S3C2440_SDIDATA;+ host->clk_div = 1;+ } else {+ host->is2440 = 0;+ host->sdiimsk = S3C2410_SDIIMSK;+ host->sdidata = S3C2410_SDIDATA;+ host->clk_div = 2;+ }+ host->dodma = 0;+ host->complete_what = COMPLETION_NONE;+ host->pio_active = XFER_NONE;++ host->dma = S3CMCI_DMA;++ pdata = pdev->dev.platform_data;+ if (!pdata) {+ pdev->dev.platform_data = &s3c2410_mmc_defplat;+ pdata = &s3c2410_mmc_defplat;+ }++ host->pdata = pdata;+ host->irq_cd = s3c2410_gpio_getirq(pdata->gpio_detect);++ host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);+ if (!host->mem) {+ dev_err(&pdev->dev,+ "failed to get io memory region resouce.\n");++ ret = -ENOENT;+ goto probe_free_host;+ }++ host->mem = request_mem_region(host->mem->start,+ RESSIZE(host->mem), pdev->name);++ if (!host->mem) {+ dev_err(&pdev->dev, "failed to request io memory region.\n");+ ret = -ENOENT;+ goto probe_free_host;+ }++ host->base = ioremap(host->mem->start, RESSIZE(host->mem));+ if (host->base == 0) {+ dev_err(&pdev->dev, "failed to ioremap() io memory region.\n");+ ret = -EINVAL;+ goto probe_free_mem_region;+ }++ host->irq = platform_get_irq(pdev, 0);+ if (host->irq == 0) {+ dev_err(&pdev->dev, "failed to get interrupt resouce.\n");+ ret = -EINVAL;+ goto probe_iounmap;+ }++ if (request_irq(host->irq, s3cmci_irq, 0, DRIVER_NAME, host)) {+ dev_err(&pdev->dev, "failed to request mci interrupt.\n");+ ret = -ENOENT;+ goto probe_iounmap;+ }++ disable_irq(host->irq);++ s3c2410_gpio_cfgpin(pdata->gpio_detect, S3C2410_GPIO_IRQ);++ if (request_irq(host->irq_cd, s3cmci_irq_cd, \+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, DRIVER_NAME, host)) {+ dev_err(&pdev->dev,+ "failed to request card detect interrupt.\n");++ ret = -ENOENT;+ goto probe_free_irq;+ }++ if (s3c2410_dma_request(S3CMCI_DMA, &s3cmci_dma_client, NULL)) {+ dev_err(&pdev->dev, "unable to get DMA channel.\n");+ ret = -EBUSY;+ goto probe_free_irq_cd;+ }++ host->clk = clk_get(&pdev->dev, "sdi");+ if (IS_ERR(host->clk)) {+ dev_err(&pdev->dev, "failed to find clock source.\n");+ ret = PTR_ERR(host->clk);+ host->clk = NULL;+ goto probe_free_irq_cd;+ }++ if ((ret = clk_enable(host->clk))) {+ dev_err(&pdev->dev, "failed to enable clock source.\n");+ goto clk_free;+ }++ host->clk_rate = clk_get_rate(host->clk);++ mmc->ops = &s3cmci_ops;+ mmc->ocr_avail = MMC_VDD_32_33;+ mmc->caps = MMC_CAP_4_BIT_DATA;+ mmc->f_min = host->clk_rate / (host->clk_div * 256);+ mmc->f_max = host->clk_rate / host->clk_div;++ mmc->max_blk_size = 4096;+ mmc->max_blk_count = 4096;+ mmc->max_req_size = mmc->max_blk_size * 512;+ mmc->max_seg_size = mmc->max_req_size;++ mmc->max_phys_segs = 128;+ mmc->max_hw_segs = 128;++ dbg(host, dbg_debug, "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n",+ (host->is2440?"2440":""),+ host->base, host->irq, host->irq_cd, host->dma);++ if ((ret = mmc_add_host(mmc))) {+ dev_err(&pdev->dev, "failed to add mmc host.\n");+ goto free_dmabuf;+ }++ platform_set_drvdata(pdev, mmc);++ dev_info(&pdev->dev,"initialisation done.\n");+ return 0;++ free_dmabuf:+ clk_disable(host->clk);++ clk_free:+ clk_put(host->clk);++ probe_free_irq_cd:+ free_irq(host->irq_cd, host);++ probe_free_irq:+ free_irq(host->irq, host);++ probe_iounmap:+ iounmap(host->base);++ probe_free_mem_region:+ release_mem_region(host->mem->start, RESSIZE(host->mem));++ probe_free_host:+ mmc_free_host(mmc);+ probe_out:+ return ret;+}++static int s3cmci_remove(struct platform_device *pdev)+{+ struct mmc_host *mmc = platform_get_drvdata(pdev);+ struct s3cmci_host *host = mmc_priv(mmc);++ mmc_remove_host(mmc);+ clk_disable(host->clk);+ clk_put(host->clk);+ free_irq(host->irq_cd, host);+ free_irq(host->irq, host);+ iounmap(host->base);+ release_mem_region(host->mem->start, RESSIZE(host->mem));+ mmc_free_host(mmc);++ return 0;+}++static int s3cmci_probe_2410(struct platform_device *dev)+{+ return s3cmci_probe(dev, 0);+}++static int s3cmci_probe_2412(struct platform_device *dev)+{+ return s3cmci_probe(dev, 1);+}++static int s3cmci_probe_2440(struct platform_device *dev)+{+ return s3cmci_probe(dev, 1);+}++#ifdef CONFIG_PM++static int s3cmci_suspend(struct platform_device *dev, pm_message_t state)+{+ struct mmc_host
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -