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

📄 pxamci.c

📁 spi driver code one marve
💻 C
📖 第 1 页 / 共 2 页
字号:
		DBG("PXAMCI: stat %08x\n", stat);		if (ireg & END_CMD_RES)			handled |= pxamci_cmd_done(host, stat);		if (ireg & DATA_TRAN_DONE)				handled |= pxamci_data_done(host, stat);	}	return IRQ_RETVAL(handled);}static void pxamci_request(struct mmc_host *mmc, struct mmc_request *mrq){	struct pxamci_host *host = mmc_priv(mmc);	unsigned int cmdat;	WARN_ON(host->mrq != NULL);	host->mrq = mrq;#ifndef CONFIG_CPU_MONAHANS	pxamci_stop_clock(host);#endif	cmdat = host->cmdat;	host->cmdat &= ~CMDAT_INIT;	if (mrq->data) {		pxamci_setup_data(host, mrq->data);		cmdat &= ~CMDAT_BUSY;		cmdat |= CMDAT_DATAEN | CMDAT_DMAEN;		if (mrq->data->flags & MMC_DATA_WRITE)			cmdat |= CMDAT_WRITE;		if (mrq->data->flags & MMC_DATA_STREAM)			cmdat |= CMDAT_STREAM;	}	pxamci_start_cmd(host, mrq->cmd, cmdat);}static int pxamci_get_ro(struct mmc_host *mmc){	struct pxamci_host *host = mmc_priv(mmc);	if (host->pdata && host->pdata->get_ro)		return host->pdata->get_ro(mmc->dev);	/* Host doesn't support read only detection so assume writeable */	return 0;}static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios){	struct pxamci_host *host = mmc_priv(mmc);#ifdef CONFIG_CPU_MONAHANS	struct platform_device *pdev = to_platform_device(mmc->dev);#endif	DBG("pxamci_set_ios: clock %u power %u vdd %u.%02u\n",	    ios->clock, ios->power_mode, ios->vdd / 100,	    ios->vdd % 100);	if (ios->clock) {		unsigned int clk = CLOCKRATE / ios->clock;		if (CLOCKRATE / clk > ios->clock)			clk <<= 1;		host->clkrt = fls(clk) - 1;#ifndef CONFIG_CPU_MONAHANS		pxa_set_cken(CKEN12_MMC, 1);#else		if (pdev->id == 0)			pxa_set_cken(CKEN_MMC1, 1);		else if (pdev->id == 1)			pxa_set_cken(CKEN_MMC2, 1);		pxamci_stop_clock(host);		writel(host->clkrt, host->base + MMC_CLKRT);		writel(START_CLOCK, host->base + MMC_STRPCL);#endif				/*		 * we write clkrt on the next command		 */	} else {		pxamci_stop_clock(host);#ifndef CONFIG_CPU_MONAHANS		pxa_set_cken(CKEN12_MMC, 0);#else		if (pdev->id == 0)			pxa_set_cken(CKEN_MMC1, 0);		else if (pdev->id == 1)			pxa_set_cken(CKEN_MMC2, 0);#endif	}	if (host->power_mode != ios->power_mode) {		host->power_mode = ios->power_mode;		if (host->pdata && host->pdata->setpower)			host->pdata->setpower(mmc->dev, ios->vdd);		if (ios->power_mode == MMC_POWER_ON)			host->cmdat |= CMDAT_INIT;	}	DBG("pxamci_set_ios: clkrt = %x cmdat = %x\n",	    host->clkrt, host->cmdat);}static struct mmc_host_ops pxamci_ops = {	.request	= pxamci_request,	.get_ro		= pxamci_get_ro,	.set_ios	= pxamci_set_ios,};static void pxamci_dma_irq(int dma, void *devid, struct pt_regs *regs){	DCSR(dma) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;}static irqreturn_t pxamci_detect_irq(int irq, void *devid, struct pt_regs *regs){	struct pxamci_host *host = mmc_priv(devid);	mmc_detect_change(devid, host->pdata->detect_delay);	return IRQ_HANDLED;}static int pxamci_probe(struct device *dev){	struct platform_device *pdev = to_platform_device(dev);	struct mmc_host *mmc;	struct pxamci_host *host = NULL;	struct resource *r;	int ret, irq;	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);	irq = platform_get_irq(pdev, 0);	if (!r || irq == NO_IRQ)		return -ENXIO;	r = request_mem_region(r->start, SZ_4K, DRIVER_NAME);	if (!r)		return -EBUSY;	mmc = mmc_alloc_host(sizeof(struct pxamci_host), dev);	if (!mmc) {		ret = -ENOMEM;		goto out;	}	mmc->ops = &pxamci_ops;	mmc->f_min = CLOCKRATE_MIN;	mmc->f_max = CLOCKRATE_MAX;	/*	 * We can do SG-DMA, but we don't because we never know how much	 * data we successfully wrote to the card.	 */	mmc->max_hw_segs = 32;	mmc->max_phys_segs = 32;	mmc->max_sectors = 256;	/*	 * Our hardware DMA can handle a maximum of one page per SG entry.	 */	mmc->max_seg_size = PAGE_SIZE;	host = mmc_priv(mmc);	host->mmc = mmc;	host->dma = -1;	host->pdata = pdev->dev.platform_data;	mmc->ocr_avail = host->pdata ?			 host->pdata->ocr_mask :			 MMC_VDD_32_33|MMC_VDD_33_34;	host->sg_cpu = dma_alloc_coherent(dev, PAGE_SIZE, &host->sg_dma, GFP_KERNEL);	if (!host->sg_cpu) {		ret = -ENOMEM;		goto out;	}	spin_lock_init(&host->lock);	host->res = r;	host->irq = irq;	host->imask = MMC_I_MASK_ALL;	if (pdev->id == 0)		host->base = (u32)&(__REG(0x41100000));	else if (pdev->id == 1)		host->base = (u32)&(__REG_2(0x42000000));	/*	 * Ensure that the host controller is shut down, and setup	 * with our defaults.	 */	pxa_set_cken(CKEN_MMC1, 1);#ifdef CONFIG_MMC2	pxa_set_cken(CKEN_MMC2, 1);	#endif	pxamci_stop_clock(host);#ifdef CONFIG_CPU_MONAHANS	writel(0x6, host->base + MMC_CLKRT);	writel(START_CLOCK, host->base + MMC_STRPCL);#endif	writel(0, host->base + MMC_SPI);	writel(64, host->base + MMC_RESTO);	writel(host->imask, host->base + MMC_I_MASK);	host->dma = pxa_request_dma(DRIVER_NAME, DMA_PRIO_LOW,				    pxamci_dma_irq, host);	if (host->dma < 0) {		ret = -EBUSY;		goto out;	}	ret = request_irq(host->irq, pxamci_irq, 0, DRIVER_NAME, host);	if (ret)		goto out;	dev_set_drvdata(dev, mmc);	if (host->pdata && host->pdata->init)		host->pdata->init(dev, pxamci_detect_irq, mmc);	mmc_add_host(mmc);	return 0; out:	if (host) {		if (host->dma >= 0)			pxa_free_dma(host->dma);		if (host->base)			iounmap(host->base);		if (host->sg_cpu)			dma_free_coherent(dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);	}	if (mmc)		mmc_free_host(mmc);	release_resource(r);	return ret;}static int pxamci_remove(struct device *dev){	struct mmc_host *mmc = dev_get_drvdata(dev);	dev_set_drvdata(dev, NULL);	if (mmc) {		struct pxamci_host *host = mmc_priv(mmc);		if (host->pdata && host->pdata->exit)			host->pdata->exit(dev, mmc);		mmc_remove_host(mmc);		pxamci_stop_clock(host);		writel(TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD|		       END_CMD_RES|PRG_DONE|DATA_TRAN_DONE,		       host->base + MMC_I_MASK);		DRCMRRXMMC = 0;		DRCMRTXMMC = 0;		free_irq(host->irq, host);		pxa_free_dma(host->dma);		iounmap(host->base);		dma_free_coherent(dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);		release_resource(host->res);		mmc_free_host(mmc);	}	return 0;}#ifdef CONFIG_PMstatic int pxamci_suspend(struct device *dev, pm_message_t state, u32 level){	struct mmc_host *mmc = dev_get_drvdata(dev);	int ret = 0;	if (mmc && level == SUSPEND_DISABLE)		ret = mmc_suspend_host(mmc, state);	return ret;}static int pxamci_resume(struct device *dev, u32 level){	struct mmc_host *mmc = dev_get_drvdata(dev);	int ret = 0;	if (mmc && level == RESUME_ENABLE)		ret = mmc_resume_host(mmc);	return ret;}#else#define pxamci_suspend	NULL#define pxamci_resume	NULL#endifstatic struct device_driver pxamci_driver = {	.name		= DRIVER_NAME,	.bus		= &platform_bus_type,	.probe		= pxamci_probe,	.remove		= pxamci_remove,	.suspend	= pxamci_suspend,	.resume		= pxamci_resume,};static int __init pxamci_init(void){	return driver_register(&pxamci_driver);}static void __exit pxamci_exit(void){	driver_unregister(&pxamci_driver);}module_init(pxamci_init);module_exit(pxamci_exit);MODULE_DESCRIPTION("PXA Multimedia Card Interface Driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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