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

📄 mhn_controller.c

📁 spi driver code one marve
💻 C
📖 第 1 页 / 共 3 页
字号:
	struct mss_host *host = pxa_host->host;	int ret = 0;	int irq;		slot = &host->slots[slotid];	pxa_slot = slot->private;	irq = get_slot_cd_irq(slot);/*	init_completion(&pxa_slot->thread_complete);	init_waitqueue_head(&pxa_slot->thread_wq);	init_MUTEX(&pxa_slot->thread_sem);	pxa_slot->flags = 0;*/	INIT_WORK(&pxa_slot->card_change,		(void (*)(void *))pxa_slot_card_change, slot);	/*	ret = kernel_thread(pxa_slot_work_thread, slot, CLONE_KERNEL);	if (ret < 0)		goto exit;	wait_for_completion(&pxa_slot->thread_complete);	init_completion(&pxa_slot->thread_complete);*/	if (!irq) {		printk(KERN_INFO "no card detect IRQ for MMC%d, slot:%d.\n",			host->id + 1, slotid);		goto skip_cd_irq;	}	ret = request_irq(irq, pxa_slot_gpio_irq, 0,		"MMC card detection", (void *)slot);	if (ret) {		printk(KERN_ERR "MMC:%d, slot%d, request irq %d fails," 				" ret: %d\n", host->id, slotid, irq, ret);		goto exit;	}	set_irq_type(irq, IRQT_BOTHEDGE);	dbg("request IRQ %d for host%d, slot%d", irq, host->id, slot->id);skip_cd_irq:	mss_scan_slot(slot);		return 0;exit:	return ret;}/** *  cleanup a slot, unregister mss_slot form core, free IRQ of slot,  *  free mss_slot  */static void pxa_slot_exit(struct mss_slot *slot){/*	pxa_slot->flags = PXA_SLOT_EXIT;	wake_up(&pxa_slot->thread_wq);	wait_for_completion(&pxa_slot->thread_complete);*/	if (slot->card)		mss_force_card_remove(slot->card);	free_irq(get_slot_cd_irq(slot), slot);}#ifdef	CONFIG_MACH_ZYLONITEstatic void pxa_mss_host_init(struct pxa_mss_host *pxa_host){	struct mss_host *host = pxa_host->host;		pxa_host->base = PXA_HOST_BASE[pxa_host->host->id];	pxa_host->phybase = PXA_HOST_PHYBASE[pxa_host->host->id];	pxa_host->cken = PXA_HOST_CKEN[pxa_host->host->id];	pxa_set_cken(pxa_host->cken, 1);	if (pxa_host->host->id == PXA_MMC_1) {			mhn_gpio_set_direction(MFP_MMC_CMD_0, GPIO_DIR_OUT);		mhn_gpio_set_level(MFP_MMC_CMD_0, GPIO_LEVEL_HIGH);		mhn_gpio_set_direction(MFP_MMC_CMD_1, GPIO_DIR_OUT);		mhn_gpio_set_level(MFP_MMC_CMD_1, GPIO_LEVEL_HIGH);		/* set direction of WP to IN */		mhn_gpio_set_direction(MFP_MMC_WP_0_N_GPIO, GPIO_DIR_IN);		mhn_gpio_set_direction(MFP_MMC_CD_0_GPIO, GPIO_DIR_IN);				set_slot_cd_irq(&host->slots[0], MMC_CD0);		set_slot_cd_gpio(&host->slots[0], MFP_MMC_CD_0_GPIO);		set_slot_wp_gpio(&host->slots[0], MFP_MMC_WP_0_N_GPIO);#if 0		if (PXA_HOST_SLOTS[PXA_MMC_1] > 1) {		//	mhn_gpio_set_direction(MFP_MMC_CD_1_GPIO, GPIO_DIR_IN);		//	mhn_gpio_set_direction(MFP_MMC_WP_1_N_GPIO,GPIO_DIR_IN);						set_slot_cd_irq(&host->slots[1], MMC_CD1);			set_slot_cd_gpio(&host->slots[1], MFP_MMC_CD_1_GPIO);			set_slot_wp_gpio(&host->slots[1], MFP_MMC_WP_1_N_GPIO);		}#endif	} else if (pxa_host->host->id == PXA_MMC_2) {		mhn_gpio_set_direction(MFP_MMC2_CMD, GPIO_DIR_OUT);		mhn_gpio_set_level(MFP_MMC2_CMD, GPIO_LEVEL_HIGH);					set_slot_cd_irq(&host->slots[0], 0);		set_slot_cd_gpio(&host->slots[0], 0);		set_slot_wp_gpio(&host->slots[0], 0);	}#ifdef CONFIG_CPU_MONAHANS_LV	else if (pxa_host->host->id == PXA_MMC_3) {		mhn_gpio_set_direction(MFP_MMC3_CMD, GPIO_DIR_OUT);		mhn_gpio_set_level(MFP_MMC3_CMD, GPIO_LEVEL_HIGH);			/* set direction of CD/WP to IN */		mhn_gpio_set_direction(MFP_MMC_CD_3_GPIO, GPIO_DIR_IN);		mhn_gpio_set_direction(MFP_MMC_WP_3_N_GPIO, GPIO_DIR_IN);						set_slot_cd_irq(&host->slots[0], MMC_CD3);		set_slot_cd_gpio(&host->slots[0], MFP_MMC_CD_3_GPIO);		set_slot_wp_gpio(&host->slots[0], MFP_MMC_WP_3_N_GPIO);	}#endif	writel(CLKRT_0_304MHZ, pxa_host->base + MMC_CLKRT);	writel(RES_TIMEOUT_MAX, pxa_host->base + MMC_RESTO);	writel(RD_TIMEOUT_MAX, pxa_host->base + MMC_RDTO);	writel(MMC_MASK_ALL, pxa_host->base + MMC_I_MASK);	writel(0, pxa_host->base + MMC_SPI);	writel(MMC_STRPCL_START_CLOCK, pxa_host->base + MMC_STRPCL);}#elif	defined(CONFIG_MACH_LITTLETON)static void pxa_mss_host_init(struct pxa_mss_host *pxa_host){	struct mss_host *host = pxa_host->host;		pxa_host->base = PXA_HOST_BASE[pxa_host->host->id];	pxa_host->phybase = PXA_HOST_PHYBASE[pxa_host->host->id];	pxa_host->cken = PXA_HOST_CKEN[pxa_host->host->id];	pxa_set_cken(pxa_host->cken, 1);	if (pxa_host->host->id == PXA_MMC_1) {			mhn_gpio_set_direction(MFP_MMC_CMD_0, GPIO_DIR_OUT);		mhn_gpio_set_level(MFP_MMC_CMD_0, GPIO_LEVEL_HIGH);		/* set direction of CD to IN */		mhn_gpio_set_direction(MFP_MMC_CD_0_GPIO, GPIO_DIR_IN);				set_slot_cd_irq(&host->slots[0], MMC_CD0);		set_slot_cd_gpio(&host->slots[0], MFP_MMC_CD_0_GPIO);	} else if (pxa_host->host->id == PXA_MMC_2) {		mhn_gpio_set_direction(MFP_MMC2_CMD, GPIO_DIR_OUT);		mhn_gpio_set_level(MFP_MMC2_CMD, GPIO_LEVEL_HIGH);					set_slot_cd_irq(&host->slots[0], 0);		set_slot_cd_gpio(&host->slots[0], 0);		set_slot_wp_gpio(&host->slots[0], 0);	}#ifdef CONFIG_CPU_MONAHANS_LV	else if (pxa_host->host->id == PXA_MMC_3) {		mhn_gpio_set_direction(MFP_MMC3_CMD, GPIO_DIR_OUT);		mhn_gpio_set_level(MFP_MMC3_CMD, GPIO_LEVEL_HIGH);	}#endif	writel(CLKRT_0_304MHZ, pxa_host->base + MMC_CLKRT);	writel(RES_TIMEOUT_MAX, pxa_host->base + MMC_RESTO);	writel(RD_TIMEOUT_MAX, pxa_host->base + MMC_RDTO);	writel(MMC_MASK_ALL, pxa_host->base + MMC_I_MASK);	writel(0, pxa_host->base + MMC_SPI);	writel(MMC_STRPCL_START_CLOCK, pxa_host->base + MMC_STRPCL);}#else#error	"Please select correct platform for build"#endifstatic struct mss_host_ops pxa_mss_host_ops = {	.enable_sdio_int= pxa_mss_enable_sdio_int,	.request	= pxa_mss_handle_request,	.set_ios	= pxa_mss_set_ios,	.is_slot_empty	= pxa_mss_slot_is_empty,	.is_slot_wp	= pxa_mss_slot_is_wp,};/**  *  pxa_mss_controller_probe  *  @dev:	device  *    *  init controller, request CTROLLER IRQ, request DMA IRQ, create controller  *  threads, invoke slot_init  */#ifdef	CONFIG_MACH_ZYLONITE#define	PXA_IOS_VDD		MSS_VDD_32_33#elif	defined (CONFIG_MACH_LITTLETON)#define	PXA_IOS_VDD		MSS_VDD_28_29#else#error "Please select correct platform for build"#endifstatic int pxa_mss_host_probe(struct device *dev){	int ret = 0, i = 0;	struct platform_device *pdev;	struct pxa_mss_host *pxa_host;	struct mss_host *host;#ifdef CONFIG_PXA_MWB_12	extern void enable_pxa_mwb_wifi(void);#endif	pdev = to_platform_device(dev);	if (pdev->id > PXA_MMC_MAX)		return -ENODEV;	host = mss_alloc_host(PXA_HOST_SLOTS[pdev->id],		\		pdev->id, sizeof(struct pxa_mss_host) +		\		PXA_HOST_SLOTS[pdev->id] * sizeof(struct pxa_slot));	if (NULL == host) {		return -ENOMEM;	}	pxa_host = (struct pxa_mss_host *)host->private;	pxa_host->host = host;	pxa_host->irq = PXA_HOST_IRQ[pdev->id];	pxa_host->drcmrtx = PXA_HOST_DRCMRTX[pdev->id];	pxa_host->drcmrrx = PXA_HOST_DRCMRRX[pdev->id];	pxa_host->dma_run = 0;	/* Set host to be 3.2V */#ifdef	CONFIG_MACH_ZYLONITE	mhn_pmic_set_voltage(VCC_SDIO, 3200);#endif	host->dev = dev;	host->ops = &pxa_mss_host_ops;	host->vdd = host->ios.vdd = PXA_IOS_VDD;	host->bus_width = MSS_BUSWIDTH_4BIT;	host->ios.bus_width = MSS_BUSWIDTH_1BIT;	host->f_min = 304000;	host->f_max = 26000000;	host->sd_spec = MSS_SD_SPEC_20;	host->mmc_spec = MSS_MMC_SPEC_40_42;	host->sdio_spec = MSS_SDIO_SPEC_11;	host->high_capacity = 1;	host->max_phys_segs = 32;	host->max_hw_segs = 32;	host->max_sectors = 256;	host->max_seg_size = 0x1000;	for (i = 0; i < PXA_HOST_SLOTS[pdev->id]; i++) {		host->slots[i].private	= (void *)((unsigned int)(&pxa_host[1]) 			+ i * sizeof(struct pxa_slot));		dbg("host:%d, slot%d, private:0x%x", host->id, 				host->slots[i].id, host->slots[i].private);	}	pxa_mss_host_init(pxa_host);#ifdef CONFIG_PXA_MWB_12	if (pxa_host->host->id == PXA_MMC_2) {		enable_pxa_mwb_wifi();	}#endif	ret = register_mss_host(host);	if (ret) {		printk(KERN_ERR "register_mss_host error! ret: %d.\n", ret);		goto free_host;	}	/* request controller IRQ */	ret = request_irq(pxa_host->irq, pxa_host_irq, 0, \		"Monahans-P MMC/SD/SDIO Controller", (void *)pxa_host);	if (ret < 0) {		printk(KERN_ERR "MMC%d request_irq error! ret: %d.\n", pdev->id, ret);		goto unregister_host;	}	/* request DMA IRQ */	pxa_host->dma = pxa_request_dma("Monahans mmc", DMA_PRIO_LOW, 				pxa_host_dma_irq, (void *)pxa_host);	dbg("DMA channel : %d, %x\n", pxa_host->dma, (u32)&pxa_host->dma);	if (pxa_host->dma < 0) {		ret = -EBUSY;		printk(KERN_ERR "MMC%d request_dma error! ret: %d.\n", pdev->id, ret);		goto free_host_irq;	}	pxa_host->sg_cpu = dma_alloc_coherent(dev, PAGE_SIZE, 			&pxa_host->sg_dma, GFP_KERNEL);	if (!pxa_host->sg_cpu) {		ret = -ENOMEM;		goto free_dma_irq;	}			sprintf(pxa_host->name, "PXA HOST %d", host->id);	sprintf(pxa_host->name2, "SDIO INT PXA HOST %d", host->id);	pxa_host->work_queue = create_workqueue(pxa_host->name);		pxa_host->sdio_work_queue = create_workqueue(pxa_host->name2);		for(i = 0; i < PXA_HOST_SLOTS[pdev->id]; i++) {		ret = pxa_slot_init(pxa_host, i);		if (ret)			goto free_slot;		}	#ifdef CONFIG_DVFM	pxa_host->dvfm_notifier.name = pxa_host->name;	pxa_host->dvfm_notifier.priority = 0,	pxa_host->dvfm_notifier.notifier_call = mhn_mmc_dvfm_notifier;	pxa_host->dvfm_notifier.client_data = pxa_host;	mhn_fv_register_notifier(&(pxa_host->dvfm_notifier));#endif	return 0;free_slot:	while (--i >= 0) {		pxa_slot_exit(&host->slots[i]);	}free_dma_irq:	/* release DMA IRQ */	pxa_free_dma(pxa_host->dma);free_host_irq:	/* release controller IRQ */	free_irq(pxa_host->irq, pxa_host);unregister_host:	unregister_mss_host(host);free_host:	mss_free_host(host);	return ret;}/** *  pxa_mss_controller_remove *  @dev: device *   *  cleanup controller, free CTROLLER IRQ, free DMA IRQ, destroy controller *  threads, invoke slot_exit */static int pxa_mss_host_remove(struct device *dev){	int ret = 0, i;	struct platform_device *pdev;	struct mss_host *host;	struct pxa_mss_host *pxa_host;	pdev = to_platform_device(dev);	host = mss_find_host(pdev->id);	if (!host)		return -ENODEV;	pxa_host = (struct pxa_mss_host *)host->private;#ifdef CONFIG_DVFM        mhn_fv_unregister_notifier(&(pxa_host->dvfm_notifier));#endif	destroy_workqueue(pxa_host->work_queue);	destroy_workqueue(pxa_host->sdio_work_queue);	free_irq(pxa_host->irq, pxa_host);	pxa_free_dma(pxa_host->dma);	dma_free_coherent(dev, PAGE_SIZE, pxa_host->sg_cpu, pxa_host->sg_dma);	for (i = 0; i < host->slot_num; i++) {		pxa_slot_exit(&host->slots[i]);	}	unregister_mss_host(host);	mss_free_host(host);	return ret;}static void pxa_mss_host_shutdown(struct device *dev){	return;}/** *  pxa_mss_controller_suspend *  @dev: device *  @state: suspend state *  @level: suspend level */static int pxa_mss_host_suspend(struct device *dev,		pm_message_t state, u32 level){	struct platform_device *pdev;	struct pxa_mss_host *pxa_host;	struct mss_host *host;	pdev = to_platform_device(dev);	host = mss_find_host(pdev->id);	pxa_host = host->private;	if (level == SUSPEND_POWER_DOWN) {/*		int i;		for (i = 0; i < host->slot_num; i++) {			struct mss_slot *slot = &host->slots[i];			if (slot->card && slot->card->card_type 					== MSS_SDIO_CARD) {				host->save.mmc_clkrt 					=  readl(pxa_host->base + MMC_CLKRT);				host->save.mmc_resto 					=  readl(pxa_host->base + MMC_RESTO);				host->save.mmc_i_mask 					=  readl(pxa_host->base + MMC_I_MASK);				host->save.mmc_spi 					=  readl(pxa_host->base + MMC_SPI);			}*/						pxa_set_cken(pxa_host->cken, 0);	}	return 0;}/** *  pxa_mss_controller_resume *  @dev: device */static int pxa_mss_host_resume(struct device *dev, u32 level){	struct platform_device *pdev;	struct pxa_mss_host *pxa_host;	struct mss_host *host;	int i, ret;	struct mss_ios ios;	pdev = to_platform_device(dev);	host = mss_find_host(pdev->id);	pxa_host = host->private;	if (level == RESUME_POWER_ON) {		pxa_mss_host_init(pxa_host);		memcpy(&ios, &host->ios, sizeof(struct mss_ios));		memset(&host->ios, 0x0, sizeof(struct mss_ios));		pxa_mss_set_ios(host, &ios);		if (host->sdio_int) {			writel(0x0, pxa_host->base + MMC_CMD);			writel(MMC_CMDAT_SDIO_INT, pxa_host->base + MMC_CMDAT);		}		pxa_mss_enable_sdio_int(host, host->sdio_int);		for (i = 0; i < host->slot_num; i++) {			struct mss_slot *slot = &host->slots[i];			if (slot->card 				&& slot->card->card_type == MSS_SDIO_CARD) {#ifdef CONFIG_PXA_MWB_12				extern void enable_pxa_mwb_wifi(void);				int retry = 0;#define MAX_RETRY	5				enable_pxa_mwb_wifi();				do {					ret = mss_init_card(slot->card);				} while(ret && MAX_RETRY > retry++);				if (!ret)					slot->card->state |= MSS_CARD_INITED;#endif				return 0;			}			ret = mss_scan_slot(slot);			if (ret) {	/* == MSS_ERROR_MISMATCH_CARD) { */				struct pxa_slot *pxa_slot = slot->private;				queue_delayed_work(pxa_host->work_queue, 						&pxa_slot->card_change, 20);			}		}        }	return 0;}/***************************************************************************** * *   object instances * ****************************************************************************/static struct device_driver pxa_mss_host_driver = {	.name		=	"mmc_controller",	.bus		=	&platform_bus_type,	.probe		= 	pxa_mss_host_probe,	.remove		=	pxa_mss_host_remove,	.shutdown	=	pxa_mss_host_shutdown,	.suspend	=	pxa_mss_host_suspend,	.resume		=	pxa_mss_host_resume,};static int pxa_mss_host_driver_init(void){	int ret;	/* register controller driver to PLATFORM bus */	ret = driver_register(&pxa_mss_host_driver);	if (ret)		return ret; 	return ret;	}static void pxa_mss_host_driver_exit(void){	driver_unregister(&pxa_mss_host_driver);}module_init(pxa_mss_host_driver_init);module_exit(pxa_mss_host_driver_exit);MODULE_AUTHOR("Bridge Wu");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("Controller driver for MMC/SD/SDIO card");

⌨️ 快捷键说明

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