⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 full.patch

📁 2410平台的linux补丁!基于1940板子!惠普公司的产品不错!
💻 PATCH
📖 第 1 页 / 共 5 页
字号:
+	DBG(PFX "DMAD csta=0x%08x dsta=0x%08x dcnt:0x%08x result:0x%08x\n", sdi_csta, sdi_dsta, sdi_dcnt, result);+	+	spin_lock_irqsave( &host->complete_lock, iflags);+	+	if(!host->mrq) goto out;+	if(!host->mrq->data) goto out;+	+	+	sdi_csta 	= readl(host->base + S3C2410_SDICMDSTAT);+	sdi_dsta 	= readl(host->base + S3C2410_SDIDSTA);+	sdi_dcnt 	= readl(host->base + S3C2410_SDIDCNT);+		+	if( result!=S3C2410_RES_OK ) {+		goto fail_request;+	}+	+	+	if(host->mrq->data->flags & MMC_DATA_READ) {+		if( sdi_dcnt>0 ) {+			goto fail_request;+		}+	}+	+out:	+	complete(&host->complete_dma);+	spin_unlock_irqrestore( &host->complete_lock, iflags);+	return;+++fail_request:+	host->mrq->data->error = MMC_ERR_FAILED;+	host->complete_what = COMPLETION_NONE;+	complete(&host->complete_request);+	writel(0, host->base + S3C2410_SDIIMSK);+	goto out;++}+++static void s3c2410sdi_dma_setup(struct s3c2410sdi_host *host, enum s3c2410_dmasrc source) {+	+	s3c2410_dma_devconfig(host->dma, source, 3, host->mem->start + S3C2410_SDIDATA);+	s3c2410_dma_config(host->dma, 4, (1<<23) | (2<<24));+	s3c2410_dma_set_buffdone_fn(host->dma, s3c2410sdi_dma_done_callback);+	s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);+}++static void s3c2410sdi_request(struct mmc_host *mmc, struct mmc_request *mrq) {+ 	struct s3c2410sdi_host *host = mmc_priv(mmc);+	struct device *dev = mmc_dev(host->mmc);+	struct platform_device *pdev = to_platform_device(dev);+	u32 sdi_carg, sdi_ccon, sdi_timer;+	u32 sdi_bsize, sdi_dcon, sdi_imsk;+	int dma_len = 0;++	DBG(KERN_DEBUG PFX "request: [CMD] opcode:0x%02x arg:0x%08x flags:%x retries:%u\n",+		mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags, mrq->cmd->retries);+	DBG(PFX "request : %s mode\n",mmc->mode == MMC_MODE_MMC ? "mmc" : "sd");+++	sdi_ccon = mrq->cmd->opcode & S3C2410_SDICMDCON_INDEX;+	sdi_ccon|= S3C2410_SDICMDCON_SENDERHOST;+	sdi_ccon|= S3C2410_SDICMDCON_CMDSTART;++	sdi_carg = mrq->cmd->arg;++	sdi_timer= 0xFFFF;++	sdi_bsize= 0;+	sdi_dcon = 0;+	sdi_imsk = 0;++	/* enable interrupts for transmission errors */+	sdi_imsk |= S3C2410_SDIIMSK_RESPONSEND;+	sdi_imsk |= S3C2410_SDIIMSK_CRCSTATUS;++	host->complete_what = COMPLETION_CMDSENT;++	if (mrq->cmd->flags & MMC_RSP_PRESENT) {+		host->complete_what = COMPLETION_RSPFIN;++		sdi_ccon |= S3C2410_SDICMDCON_WAITRSP;+		sdi_imsk |= S3C2410_SDIIMSK_CMDTIMEOUT;++	} else {+		/* We need the CMDSENT-Interrupt only if we want are not waiting+		 * for a response+		 */+		sdi_imsk |= S3C2410_SDIIMSK_CMDSENT;+	}++	if(mrq->cmd->flags & MMC_RSP_136) {+		sdi_ccon|= S3C2410_SDICMDCON_LONGRSP;+	}++	if(mrq->cmd->flags & MMC_RSP_CRC) {+			sdi_imsk |= S3C2410_SDIIMSK_RESPONSECRC;+	}+++	if (mrq->data) {+		host->complete_what = COMPLETION_XFERFINISH_RSPFIN;++		sdi_bsize = mrq->data->blksz;+		host->size = mrq->data->blocks * mrq->data->blksz;++		sdi_dcon  = (mrq->data->blocks & S3C2410_SDIDCON_BLKNUM_MASK);+		sdi_dcon |= S3C2410_SDIDCON_DMAEN;++		sdi_imsk |= S3C2410_SDIIMSK_FIFOFAIL;+		sdi_imsk |= S3C2410_SDIIMSK_DATACRC;+		sdi_imsk |= S3C2410_SDIIMSK_DATATIMEOUT;+		sdi_imsk |= S3C2410_SDIIMSK_DATAFINISH;+		sdi_imsk |= 0xFFFFFFE0;++		DBG(PFX "request: [DAT] bsize:%u blocks:%u bytes:%u\n",+			sdi_bsize, mrq->data->blocks, mrq->data->blocks * sdi_bsize);++		if (host->bus_width == MMC_BUS_WIDTH_4) {+			sdi_dcon |= S3C2410_SDIDCON_WIDEBUS;+		}++		if(!(mrq->data->flags & MMC_DATA_STREAM)) {+			sdi_dcon |= S3C2410_SDIDCON_BLOCKMODE;+		}++		if(mrq->data->flags & MMC_DATA_WRITE) {+			sdi_dcon |= S3C2410_SDIDCON_TXAFTERRESP;+			sdi_dcon |= S3C2410_SDIDCON_XFER_TXSTART;+		}++		if(mrq->data->flags & MMC_DATA_READ) {+			sdi_dcon |= S3C2410_SDIDCON_RXAFTERCMD;+			sdi_dcon |= S3C2410_SDIDCON_XFER_RXSTART;+		}++		s3c2410sdi_dma_setup(host, mrq->data->flags & MMC_DATA_WRITE ? S3C2410_DMASRC_MEM : S3C2410_DMASRC_HW);++		/* see DMA-API.txt */+		dma_len = dma_map_sg(&pdev->dev, mrq->data->sg, \+				mrq->data->sg_len, \+				mrq->data->flags & MMC_DATA_READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);++		/* start DMA */+		s3c2410_dma_enqueue(host->dma, (void *) host,+			sg_dma_address(&mrq->data->sg[0]),+			(mrq->data->blocks * mrq->data->blksz) );+	}++	host->mrq = mrq;++	init_completion(&host->complete_request);+	init_completion(&host->complete_dma);++	/* Clear command and data status registers */+	writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT);+	writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA);++	/* Setup SDI controller */+	writel(sdi_bsize,host->base + S3C2410_SDIBSIZE);+	writel(sdi_timer,host->base + S3C2410_SDITIMER);+	writel(sdi_imsk,host->base + S3C2410_SDIIMSK);++	/* Setup SDI command argument and data control */+	writel(sdi_carg, host->base + S3C2410_SDICMDARG);+	writel(sdi_dcon, host->base + S3C2410_SDIDCON);++	/* This initiates transfer */+	writel(sdi_ccon, host->base + S3C2410_SDICMDCON);++	/* Wait for transfer to complete */+	wait_for_completion(&host->complete_request);+	DBG(PFX "[CMD] request complete.\n");+	if(mrq->data) {+		wait_for_completion(&host->complete_dma);+		DBG(PFX "[DAT] DMA complete.\n");+	}+	+	/* Cleanup controller */+	writel(0, host->base + S3C2410_SDICMDARG);+	writel(0, host->base + S3C2410_SDIDCON);+	writel(0, host->base + S3C2410_SDICMDCON);+	writel(0, host->base + S3C2410_SDIIMSK);++	/*  Read response */+	mrq->cmd->resp[0] = readl(host->base + S3C2410_SDIRSP0);+	mrq->cmd->resp[1] = readl(host->base + S3C2410_SDIRSP1);+	mrq->cmd->resp[2] = readl(host->base + S3C2410_SDIRSP2);+	mrq->cmd->resp[3] = readl(host->base + S3C2410_SDIRSP3);++	host->mrq = NULL;++	DBG(PFX "request done.\n");++	/* If we have no data transfer we are finished here */+	if (!mrq->data) goto request_done;++	dma_unmap_sg(&pdev->dev, mrq->data->sg, dma_len, \+			mrq->data->flags & MMC_DATA_READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);++	/* Calulate the amout of bytes transfer, but only if there was+	 * no error+	 */+	if(mrq->data->error == MMC_ERR_NONE) {+		mrq->data->bytes_xfered = (mrq->data->blocks * mrq->data->blksz);+	} else {+		mrq->data->bytes_xfered = 0;+	}++	/* If we had an error while transfering data we flush the+	 * DMA channel to clear out any garbage+	 */+	if(mrq->data->error != MMC_ERR_NONE) {+		s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);+		DBG(PFX "flushing DMA.\n");		+	}++	if(mrq->data->stop) mmc_wait_for_cmd(mmc, mrq->data->stop, 3);++request_done:++	mrq->done(mrq);+}++static void s3c2410sdi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) {+	struct s3c2410sdi_host *host = mmc_priv(mmc);+	u32 sdi_psc, sdi_con;++	/* Set power */+	sdi_con = readl(host->base + S3C2410_SDICON);+	switch(ios->power_mode) {+		case MMC_POWER_ON:+		case MMC_POWER_UP:+			DBG(PFX "power on\n");+			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->pdata->set_power)+				(host->pdata->set_power)(1);++			sdi_con|= S3C2410_SDICON_FIFORESET;+			break;++		case MMC_POWER_OFF:+		default:+			if (host->pdata->set_power)+				(host->pdata->set_power)(0);+			break;+	}++	/* Set clock */+	for(sdi_psc=0;sdi_psc<255;sdi_psc++) {+		if( (clk_get_rate(host->clk) / (2*(sdi_psc+1))) <= ios->clock) break;+	}++	if(sdi_psc > 255) sdi_psc = 255;+	writel(sdi_psc, host->base + S3C2410_SDIPRE);++	/* Set CLOCK_ENABLE */+	if(ios->clock) 	sdi_con |= S3C2410_SDICON_CLOCKTYPE;+	else		sdi_con &=~S3C2410_SDICON_CLOCKTYPE;++	writel(sdi_con, host->base + S3C2410_SDICON);++	host->bus_width = ios->bus_width;++}++static struct mmc_host_ops s3c2410sdi_ops = {+	.request	= s3c2410sdi_request,+	.set_ios	= s3c2410sdi_set_ios,+};++static void s3c2410_mmc_def_setpower(unsigned int to)+{+	s3c2410_gpio_cfgpin(S3C2410_GPA17, S3C2410_GPIO_OUTPUT);+	s3c2410_gpio_setpin(S3C2410_GPA17, to);+}++static struct s3c24xx_mmc_platdata s3c2410_mmc_defplat = {+	.gpio_detect	= S3C2410_GPF2,+	.set_power	= s3c2410_mmc_def_setpower,+	.f_max		= 3000000,+	.ocr_avail	= MMC_VDD_32_33,+};++static int s3c2410sdi_probe(struct platform_device *pdev)+{+	struct mmc_host 	*mmc;+	s3c24xx_mmc_pdata_t	*pdata;+	struct s3c2410sdi_host 	*host;+++	int ret;++	mmc = mmc_alloc_host(sizeof(struct s3c2410sdi_host), &pdev->dev);+	if (!mmc) {+		ret = -ENOMEM;+		goto probe_out;+	}++	host = mmc_priv(mmc);++	spin_lock_init( &host->complete_lock );+	host->complete_what 	= COMPLETION_NONE;+	host->mmc 		= mmc;+	host->dma		= S3C2410SDI_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);+	s3c2410_gpio_cfgpin(pdata->gpio_detect, S3C2410_GPIO_IRQ);++	host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);+	if (!host->mem) {+		printk(KERN_ERR PFX "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) {+		printk(KERN_ERR PFX "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) {+		printk(KERN_ERR PFX "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) {+		printk(KERN_ERR PFX "failed to get interrupt resouce.\n");+		ret = -EINVAL;+		goto probe_iounmap;+	}++	if(request_irq(host->irq, s3c2410sdi_irq, 0, DRIVER_NAME, host)) {+		printk(KERN_ERR PFX "failed to request sdi interrupt.\n");+		ret = -ENOENT;+		goto probe_iounmap;+	}++	if(request_irq(host->irq_cd, s3c2410sdi_irq_cd, SA_TRIGGER_RISING | SA_TRIGGER_FALLING, DRIVER_NAME, host)) {+		printk(KERN_ERR PFX "failed to request card detect interrupt.\n" );+		ret = -ENOENT;+		goto probe_free_irq;+	}++	if(s3c2410_dma_request(S3C2410SDI_DMA, &s3c2410sdi_dma_client, NULL)) {+		printk(KERN_ERR PFX "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)) {+		printk(KERN_ERR PFX "failed to find clock source.\n");+		ret = PTR_ERR(host->clk);+		host->clk = NULL;+		goto probe_free_host;+	}++	if((ret = clk_enable(host->clk))) {+		printk(KERN_ERR PFX "failed to enable clock source.\n");+		goto clk_unuse;+	}+++	mmc->ops 	= &s3c2410sdi_ops;+	mmc->ocr_avail	= pdata->ocr_avail;+	mmc->f_min 	= clk_get_rate(host->clk) / 512;+	mmc->f_max 	= clk_get_rate(host->clk) / 2;+	mmc->caps	= MMC_CAP_4_BIT_DATA;++	if(pdata->f_max && (mmc->f_max>pdata->f_max))+		mmc->f_max = pdata->f_max;++	/*+	 * Since we only have a 16-bit data length register, we must+	 * ensure that we don't exceed 2^16-1 bytes in a single request.+	 * Choose 64 (512-byte) sectors as the limit.+	 */+	mmc->max_sectors = 64;++	/*+	 * Set the maximum segment size.  Since we aren't doing DMA+	 * (yet) we are only limited by the data length register.+	 */++	mmc->max_seg_size = mmc->max_sectors << 9;+	printk(KERN_INFO PFX "probe: mapped sdi_base=%p irq=%u irq_cd=%u \n",+		host->base, host->irq, host->irq_cd);++	if((ret = mmc_add_host(mmc))) {+		printk(KERN_ERR PFX "failed to add mmc host.\n");+		goto clk_disable;+	}++	platform_set_drvdata(pdev, mmc);++	printk(KERN_INFO PFX "initialisation done.\n");+	return 0;+	+ clk_disable:+	clk_disable(host->clk);++ clk_unuse:+	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 s3c2410sdi_remove(struct platform_device *pdev)+{+	struct mmc_host 	*mmc  = platform_get_drvdata(pdev);+	struct s3c2410sdi_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;+}++#ifdef CONFIG_PM+static int s3c2410mci_suspend(struct platform_device *dev, pm_message_t state)+{+	struct mmc_host *mmc = platform_get_drvdata(dev);+	struct s3c2410sdi_host  *host;+	int ret = 0;++	if (mmc) {+		host = mmc_priv(mmc);++		ret = mmc_suspend_host(mmc, state);++		clk_disable(host->clk);++		disable_irq(host->irq_cd);+		disable_irq(host->irq);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -