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

📄 omap_hsmmc.c

📁 omap3 linux 2.6 用nocc去除了冗余代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	mmc_clk_disable_aggressive(host);}static struct mmc_host_ops mmc_omap_ops = {	.request = omap_mmc_request,	.set_ios = omap_mmc_set_ios,};/* * Routine implementing the driver probe method */static int __init omap_mmc_probe(struct platform_device *pdev){	struct omap_mmc_conf *minfo = pdev->dev.platform_data;	struct mmc_host *mmc;	struct mmc_omap_host *host = NULL;	struct resource *res;	int ret = 0, irq, *addr;	if (minfo == NULL) {		dev_err(&pdev->dev, "platform data missing\n");		return -ENXIO;	}	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);	irq = platform_get_irq(pdev, 0);	if (res == NULL || irq < 0)		return -ENXIO;	res = request_mem_region(res->start, res->end - res->start + 1,							pdev->name);	if (res == NULL)		return -EBUSY;	mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev);	if (!mmc) {		ret = -ENOMEM;		goto mmc_alloc_err;	}	host = mmc_priv(mmc);	host->mmc = mmc;	sema_init(&host->sem, 1);	host->use_dma = OMAP_USE_DMA;	host->dma_ch = -1;	host->initstream = 0;	host->mem_res = res;	host->irq = irq;	host->id = pdev->id;	host->mapbase = (void *)host->mem_res->start;	host->base = (void __iomem *)IO_ADDRESS(host->mapbase);	mmc->ops = &mmc_omap_ops;	mmc->f_min = 400000;	mmc->f_max = 52000000;	mmc->mode = MMC_CARD_NONE;	host->card_detected = 1;	host->is_high_capacity = 0;	host->flag_err = 0;	host->cmd_12 = 0;	host->cmd_13 = 0;	host->crc_retry = 0;	spin_lock_init(&host->dma_lock);	host->chain_id = -1;	host->sg_dma_len = 0;	if (cpu_is_omap2430()) {		if (host->id == OMAP_MMC1_DEVID) {			host->fclk = clk_get(&pdev->dev, "mmchs1_fck");			if (IS_ERR(host->fclk)) {				ret = PTR_ERR(host->fclk);				host->fclk = NULL;				goto clk_get_err;			}			host->iclk = clk_get(&pdev->dev, "mmchs1_ick");			if (IS_ERR(host->iclk)) {				ret = PTR_ERR(host->iclk);				host->iclk = NULL;				clk_put(host->fclk);				goto clk_get_err;			}			host->dbclk = clk_get(&pdev->dev, "mmchsdb1_fck");			/*			 * Only through a error message, MMC can still work			 * without debounce clock.			 */			if (IS_ERR(host->dbclk))				dev_dbg(mmc_dev(host->mmc),					"Failed to get debounce"					"clock for MMC1\n");		} else {			host->fclk = clk_get(&pdev->dev, "mmchs2_fck");			if (IS_ERR(host->fclk)) {				ret = PTR_ERR(host->fclk);				host->fclk = NULL;				goto clk_get_err;			}			host->iclk = clk_get(&pdev->dev, "mmchs2_ick");			if (IS_ERR(host->iclk)) {				ret = PTR_ERR(host->iclk);				host->iclk = NULL;				clk_put(host->fclk);				goto clk_get_err;			}			host->dbclk = clk_get(&pdev->dev, "mmchsdb2_fck");			/*			 * Only through a error message, MMC can still work			 * without debounce clock.			 */			if (IS_ERR(host->dbclk))				dev_dbg(mmc_dev(host->mmc),						"Failed to get"					"debounce clock for MMC2\n");		}	}	if (cpu_is_omap34xx()) {		/* 3430-ES1.0  Sil errata fix */		if (is_sil_rev_less_than(OMAP3430_REV_ES2_0)) {			host->gptfck = clk_get(&pdev->dev, "gpt10_fck");			if (IS_ERR(host->gptfck)) {				ret = PTR_ERR(host->gptfck);				host->gptfck = NULL;				goto clk_get_err;			}		}		host->fclk = clk_get(&pdev->dev, "mmc_fck");		if (IS_ERR(host->fclk)) {			ret = PTR_ERR(host->fclk);			host->fclk = NULL;			goto clk_get_err;		}		host->iclk = clk_get(&pdev->dev, "mmc_ick");		if (IS_ERR(host->iclk)) {			ret = PTR_ERR(host->iclk);			clk_put(host->fclk);			host->iclk = NULL;			goto clk_get_err;		}	}	mmc_clk_enable(host);	if (cpu_is_omap2430()) {		if (clk_enable(host->dbclk) != 0)			dev_dbg(mmc_dev(host->mmc),				"Failed to enable debounce clock for MMC%d\n",				host->id);		omap_writel(omap_readl(OMAP2_CONTROL_DEVCONF1) | MMC1_ACTIVE_OVERWRITE,							OMAP2_CONTROL_DEVCONF1);		if (minfo->wire4)			/* OMAP2430 ES2.0 and onwards can support 4-bit */			if (omap2_cpu_rev() >= 1)				mmc->caps = MMC_CAP_4_BIT_DATA;	}	if (host->id == OMAP_MMC1_DEVID) {		if (cpu_is_omap34xx()) {			addr = (int *)&OMAP2_CONTROL_PBIAS_1;			*addr |= (1 << 2);			addr = (int *)&OMAP2_CONTROL_DEVCONF0;			*addr |= (1 << 24);			/* There is no 8-bit field in the structure yet */			if (minfo->wire4) {				if (cpu_is_omap3410()) {					mmc->caps = MMC_CAP_4_BIT_DATA;				}				else					mmc->caps = MMC_CAP_8_BIT_DATA;			}			OMAP_HSMMC_WRITE(host->base, HCTL,					OMAP_HSMMC_READ(host->base,					HCTL) | SDVS30);		} else if (cpu_is_omap2430()) {			/* OMAP2430 MMC1 on ES1.0 and ES2.1 can support 3V */			if (omap2_cpu_rev() == 0 || omap2_cpu_rev() > 1) {				OMAP_HSMMC_WRITE(host->base, HCTL,						OMAP_HSMMC_READ(host->base,								HCTL) | SDVS30);			} else {				/* OMAP2430 MMC1 ES2.0 - 1.8V only */				OMAP_HSMMC_WRITE(host->base, HCTL,						OMAP_HSMMC_READ(host->base,								HCTL) | SDVS18);			}		}	} else if (host->id == OMAP_MMC2_DEVID) {		if (cpu_is_omap34xx()) {			addr = (int *)&OMAP2_CONTROL_DEVCONF1;			*addr |= (1 << 6);			if (minfo->wire4)				mmc->caps = MMC_CAP_4_BIT_DATA;		}		OMAP_HSMMC_WRITE(host->base, HCTL,				OMAP_HSMMC_READ(host->base,						HCTL) | SDVS18);	}	/* Use scatterlist DMA to reduce per-transfer costs.	 * NOTE max_seg_size assumption that small blocks aren't	 * normally used (except e.g. for reading SD registers).	 */	mmc->max_phys_segs = 128;		 /* Largest sized scatter list									 * the driver could handle. Since this is									 * managed by us in software, we can tune									 * this value */	mmc->max_hw_segs = 128; 		 /* Largest number of address/length									 * pairs the host adapter can actually									 * give at once to the device. This value									 * should be kept same as scatter list	*/	mmc->max_blk_size = 512;	   /* Block Length at max can be 1024 */	mmc->max_blk_count = 0xFFFF;	/* No. of Blocks is 16 bits 			*/	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;	mmc->max_seg_size = mmc->max_req_size;	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;	OMAP_HSMMC_WRITE(host->base, CAPA,OMAP_HSMMC_READ(host->base,							CAPA) | VS30 | VS18);	mmc->caps |= MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK | MMC_CAP_MMC_HIGHSPEED |			MMC_CAP_SD_HIGHSPEED;	/* Set the controller to AUTO IDLE mode */	OMAP_HSMMC_WRITE(host->base, SYSCONFIG,			OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE);	/* Set SD bus power bit */	OMAP_HSMMC_WRITE(host->base, HCTL,			OMAP_HSMMC_READ(host->base, HCTL) | SDBP);	if (machine_is_omap_2430sdp() ||			machine_is_omap_3430sdp() ||			machine_is_omap_3430labrador() ||			machine_is_omap3evm() || machine_is_omap3_beagle() ) {		/*		 * Create sysfs entries for enabling/disabling hotplug		 * support for MMC cards		 */		if (device_create_file(&pdev->dev,				&dev_attr_mmc_cover_switch) < 0) {			dev_dbg(mmc_dev(host->mmc),					"Unable to create sysfs"				"attribute for MMC1 cover switch\n");		}		if (device_create_file(&pdev->dev,			&dev_attr_mmc_card_detect) < 0) {			dev_dbg(mmc_dev(host->mmc),				"Unable to create sysfs"				"attribute for MMC1 card detect\n");		}	}	/* Request IRQ for MMC operations */	ret = request_irq(host->irq, mmc_omap_irq, 0, pdev->name,				host);	if (ret) {		dev_dbg(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ");		goto irq_err;	}	host->card_detect_irq = minfo->switch_pin;	if (minfo->switch_pin >= 0) {		if (machine_is_omap_2430sdp() ||					machine_is_omap_3430sdp() ||					machine_is_omap_3430labrador() ||					machine_is_omap3evm() || machine_is_omap3_beagle() ) {			host->card_detect_irq =				TWL4030_GPIO_IRQ_NO(minfo->switch_pin);			INIT_WORK(&host->mmc_carddetect_work, mmc_omap_detect);			if (setup_mmc_carddetect_irq(minfo->switch_pin)) {				free_irq(host->irq, host);				goto irq_err;			}		}	}	if (minfo->switch_pin >= 0) {		ret = request_irq(host->card_detect_irq,			mmc_omap_irq_cd, IRQF_DISABLED, pdev->name,host);		if (ret < 0) {			dev_dbg(mmc_dev(host->mmc),				"Unable to grab T2 GPIO IRQ");			free_irq(host->irq, host);			goto irq_err;		}	}	if (host->id == OMAP_MMC1_DEVID)		saved_host1 = host;	else		saved_host2 = host;	platform_set_drvdata(pdev, host);	mmc_clk_disable_aggressive(host);	mmc_add_host(mmc);	return 0;clk_get_err:	dev_dbg(mmc_dev(host->mmc),		"Error getting clock for MMC\n");	if (host) {		mmc_free_host(mmc);	}	return ret;mmc_alloc_err:	if (host)		mmc_free_host(mmc);	return ret;irq_err:	mmc_clk_disable(host);	if (cpu_is_omap2430())		clk_disable(host->dbclk);	clk_put(host->fclk);	clk_put(host->iclk);	if (cpu_is_omap2430())		clk_put(host->dbclk);	if (host)		mmc_free_host(mmc);	return ret;}/* * Routine implementing the driver remove method */static int omap_mmc_remove(struct platform_device *pdev){	struct mmc_omap_host *host = platform_get_drvdata(pdev);	platform_set_drvdata(pdev, NULL);	if (host) {		free_irq(host->irq, host);		free_irq(host->card_detect_irq, host);		flush_scheduled_work();		/* Free the clks */		mmc_clk_disable(host);		if (cpu_is_omap2430())			clk_disable(host->dbclk);		clk_put(host->fclk);		clk_put(host->iclk);		if (cpu_is_omap2430())			clk_put(host->dbclk);		mmc_free_host(host->mmc);	}	return 0;}/* * Routine to suspend the MMC device */static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state){	int ret = 0;	int status;	struct mmc_omap_host *host = platform_get_drvdata(pdev);	if (host && host->suspended)		return 0;	if (host) {		/* Notify the core to suspend the host */		ret = mmc_suspend_host(host->mmc, state);		if (ret == 0) {			host->suspended = 1;		/* Temporarily enabling the clocks for configuration */		mmc_clk_enable_aggressive(host);		if (machine_is_omap_2430sdp() ||					machine_is_omap_3430sdp() ||					machine_is_omap_3430labrador() ||					machine_is_omap3evm() || machine_is_omap3_beagle() ) {			disable_irq(host->card_detect_irq);			ret = mask_carddetect_int(host->id);			if (ret)				dev_dbg(mmc_dev(host->mmc),					"Unable to mask the card detect"					"interrupt in suspend\n");		}		if (cpu_is_omap34xx() || (cpu_is_omap2430()				&& omap2_cpu_rev() == 2)) {			if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {				OMAP_HSMMC_WRITE(host->base,HCTL,						OMAP_HSMMC_READ(host->base,HCTL)						& SDVSCLR);				OMAP_HSMMC_WRITE(host->base,HCTL,						OMAP_HSMMC_READ(host->base,HCTL)						|SDVS30);				OMAP_HSMMC_WRITE(host->base,HCTL,						OMAP_HSMMC_READ(host->base,HCTL)						| SDBP);			}		}		/* Disable Interrupts */		OMAP_HSMMC_WRITE(host->base, ISE, INT_CLEAR);		OMAP_HSMMC_WRITE(host->base, IE, INT_CLEAR);		/* Clearing the STAT register*/		status = OMAP_HSMMC_READ(host->base, STAT);			OMAP_HSMMC_WRITE(host->base, STAT, status);		/* disable clks for MMC1 */		mmc_clk_disable(host);		if (cpu_is_omap2430())			clk_disable(host->dbclk);		if (cpu_is_omap2430()) {			if (host->id == OMAP_MMC1_DEVID) {				if (omap2_cpu_rev() == 2) {					omap_writel(omap_readl(OMAP2_CONTROL_DEVCONF1)						& ~MMC1_ACTIVE_OVERWRITE,						OMAP2_CONTROL_DEVCONF1);				}			}		}		ret = mmc_omap_power(host,0);		if (ret != 0)			dev_dbg(mmc_dev(host->mmc),				"Unable to disable power to MMC1\n");		host->initstream = 0;		}	}	return ret;}/* * Routine to resume the MMC device */static int omap_mmc_resume(struct platform_device *pdev){	int ret = 0;	struct mmc_omap_host *host = platform_get_drvdata(pdev);	if (host && !host->suspended)		return 0;	if (host) {		if (cpu_is_omap2430()) {			if (host->id == OMAP_MMC1_DEVID) {				if (omap2_cpu_rev() == 2)					omap_writel(omap_readl(OMAP2_CONTROL_DEVCONF1)						| MMC1_ACTIVE_OVERWRITE,						OMAP2_CONTROL_DEVCONF1);			}		}		ret = mmc_omap_power(host,1);		if (ret != 0) {			dev_dbg(mmc_dev(host->mmc),				   "Unable to enable power to MMC1\n");			return ret;		}		mmc_clk_enable(host);		if (cpu_is_omap2430()) {			if (clk_enable(host->dbclk) != 0)				dev_dbg(mmc_dev(host->mmc),						"Unable to enable debounce"					"clock for MMC1\n");		}		if (machine_is_omap_2430sdp() ||					machine_is_omap_3430sdp() ||					machine_is_omap_3430labrador() ||					machine_is_omap3evm() || machine_is_omap3_beagle() ) {			enable_irq(host->card_detect_irq);			ret = unmask_carddetect_int(host->id);			if (ret)				dev_dbg(mmc_dev(host->mmc),					"Unable to unmask the card"					"detect interrupt\n");		}		/* Notify the core to resume the host */		ret = mmc_resume_host(host->mmc);		if (ret == 0)			host->suspended = 0;	}	return ret;clk_en_err:	dev_dbg(mmc_dev(host->mmc),		"Unable to enable MMC clocks during resume\n");	return -1;}static struct platform_driver omap_mmc_driver = {	.probe = omap_mmc_probe,	.remove = omap_mmc_remove,	.suspend = omap_mmc_suspend,	.resume = omap_mmc_resume,	.driver = {		   .name = "hsmmc-omap",		   },};/* * Driver init method */static int __init omap_mmc_init(void){	/* Register the MMC driver */	if (platform_driver_register(&omap_mmc_driver)) {		printk(KERN_ERR ":failed to register MMC driver\n");		return -ENODEV;	}	return 0;}/* * Driver exit method */static void __exit omap_mmc_cleanup(void){	/* Unregister MMC driver */	platform_driver_unregister(&omap_mmc_driver);}module_init(omap_mmc_init);module_exit(omap_mmc_cleanup);MODULE_DESCRIPTION("OMAP 2430/3430 Multimedia Card driver");MODULE_LICENSE("GPL");MODULE_AUTHOR("Texas Instruments");

⌨️ 快捷键说明

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