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

📄 omap_mmc.c

📁 mmc 方式通讯的在CPU PXA270下的WINCE 5驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
		*(buf + 2) = data & 0xff;		data = inw(OMAP_MMC_RSP6);		DEBUG(3, " %x \n", data);		*(buf + 3) = data >> 8;		*(buf + 4) = data & 0xff;		break;	case RESPONSE_R2_CID:	case RESPONSE_R2_CSD:		*(buf) = 0x3f;	/* for mmc core */		data = inw(OMAP_MMC_RSP7);		*(buf + 1) = data >> 8;		*(buf + 2) = data & 0xff;		data = inw(OMAP_MMC_RSP6);		*(buf + 3) = data >> 8;		*(buf + 4) = data & 0xff;		data = inw(OMAP_MMC_RSP5);		*(buf + 5) = data >> 8;		*(buf + 6) = data & 0xff;		data = inw(OMAP_MMC_RSP4);		*(buf + 7) = data >> 8;		*(buf + 8) = data & 0xff;		data = inw(OMAP_MMC_RSP3);		*(buf + 9) = data >> 8;		*(buf + 10) = data & 0xff;		data = inw(OMAP_MMC_RSP2);		*(buf + 11) = data >> 8;		*(buf + 12) = data & 0xff;		data = inw(OMAP_MMC_RSP1);		*(buf + 13) = data >> 8;		*(buf + 14) = data & 0xff;		data = inw(OMAP_MMC_RSP0);		*(buf + 15) = data >> 8;		*(buf + 16) = data & 0xff;	case RESPONSE_NONE:	default:		break;	}}static voidomap_mmc_handle_int(struct omap_mmc_data *sd, u16 status){	int retval = MMC_NO_ERROR;	int flags;	local_irq_save(flags);	DEBUG(3, ": Interrupt. Status: %d\n", status);	/* Data or Command time-out? */	if (status & (OMAP_MMC_CMD_TIMEOUT | OMAP_MMC_DATA_TIMEOUT)) {		DEBUG(0, ": MMC/SD status: %d \n", inw(OMAP_MMC_STAT));		retval = MMC_ERROR_TIMEOUT;		goto terminate_int;	}	/* CRC error? */	if ((status & (OMAP_MMC_CMD_CRC | OMAP_MMC_DATA_CRC)) &&	    !(inw(OMAP_MMC_CON) & (1 << 15))) {		DEBUG(0, ": MMC/SD status: %d \n", inw(OMAP_MMC_STAT));		retval = MMC_ERROR_CRC;		goto terminate_int;	}	if (((status & OMAP_MMC_END_OF_CMD)	     && (sd->request->result == MMC_NO_RESPONSE))	    || (status & 1 << 14))		omap_mmc_get_response(sd->request);	switch (g_omap_mmc_data.type) {	case RT_NO_RESPONSE:		break;	case RT_WRITE:		if (sd->request->nob) {			/* Start another transfer */			outw(0xffff, OMAP_MMC_STAT);			omap_mmc_start_tx_dma_transfer(g_omap_mmc_data.request->						       block_len);			return;		}		break;	case RT_READ:		if (sd->request->nob) {			/* Start another transfer */			outw(0xffff, OMAP_MMC_STAT);			omap_mmc_start_rx_dma_transfer(g_omap_mmc_data.request->						       block_len);			return;		}		break;	case RT_RESPONSE_ONLY:		if (sd->request->result < 0) {			printk(KERN_INFO			       "MMC/SD: Illegal interrupt - command hasn't finished\n");			retval = MMC_ERROR_TIMEOUT;		}		break;	}      terminate_int:	outw(0, OMAP_MMC_IE);	/* Clear all interrupts */	sd->request->result = retval;	mmc_cmd_complete(sd->request);	local_irq_restore(flags);}/* Handle IRQ */static voidomap_mmc_int(int irq, void *dev_id, struct pt_regs *regs){	struct omap_mmc_data *sd = (struct omap_mmc_data *) dev_id;	u16 status = inw(OMAP_MMC_STAT);	omap_mmc_handle_int(sd, status);}/* Detect Card */static voidomap_mmc_fix_sd_detect(unsigned long nr){#ifdef CONFIG_ARCH_OMAP1510	card_state = inb(INNOVATOR_FPGA_INFO) & (1 << 4);	if (card_state == 0) {		outw((1 << 11), OMAP_MMC_CON);		mmc_insert(0);	} else {		mmc_eject(0);	}#endif#ifdef CONFIG_ARCH_OMAP1610	u8 state;	state = inb(MPUIO_INPUT_LATCH_REG) & (1 << 1);	if (card_state == state) {		if (card_state == 0) {			outw((1 << 11), OMAP_MMC_CON);			mmc_insert(0);			omap1610_tune_irq(OMAP_MMC_CD, IFL_HIGHLEVEL);		} else {			mmc_eject(0);			omap1610_tune_irq(OMAP_MMC_CD, IFL_LOWLEVEL);		}	}#endif#ifdef CONFIG_ARCH_OMAP730	u8 state;	state = get_p2_mmc_cd_state() & 1;	if(card_state == state) {		if ( card_state == 0 ) { 			/* Slot now has a card */			outw(MMC_CON_POWER_UP, OMAP_MMC_CON); 			mmc_insert(0);			omap730_tune_irq(OMAP_MMC_CD, IFL_HIGHLEVEL);		} else {			/* Slot is now empty */			mmc_eject(0);			omap730_tune_irq(OMAP_MMC_CD, IFL_LOWLEVEL);	    		}	}#endif}static voidomap_mmc_sd_detect_int(int irq, void *dev_id, struct pt_regs *regs){	struct omap_mmc_data *sd = (struct omap_mmc_data *) dev_id;#ifdef CONFIG_ARCH_OMAP1510	u8 state;	state = inb(INNOVATOR_FPGA_INFO) & (1 << 4);	if (card_state != state)		mod_timer(&sd->sd_detect_timer,			  jiffies + ((card_state ? 50 : 500) * HZ) / 1000);#endif#ifdef CONFIG_ARCH_OMAP1610	card_state = inb(MPUIO_INPUT_LATCH_REG) & (1 << 1);	mod_timer(&sd->sd_detect_timer,		  jiffies + ((card_state ? 50 : 500) * HZ) / 1000);#endif#ifdef CONFIG_ARCH_OMAP730	card_state = get_p2_mmc_cd_state() & 1;	mod_timer(&sd->sd_detect_timer,		  jiffies + ((card_state ? 50 : 500) * HZ) / 1000);#endif}static intomap_mmc_slot_is_empty(int slot){#ifdef CONFIG_ARCH_OMAP1510	card_state = inb(INNOVATOR_FPGA_INFO) & (1 << 4);#endif#ifdef CONFIG_ARCH_OMAP1610	card_state = inb(MPUIO_INPUT_LATCH_REG) & (1 << 1);#endif#ifdef CONFIG_ARCH_OMAP730	card_state = get_p2_mmc_cd_state();#endif	return card_state != 0;}/************************************************************************** * *                       Hardware initialization                                              * *************************************************************************/static voidomap_mmc_slot_up(void){	/* OMAP MMC slot hardware init */#ifdef CONFIG_ARCH_OMAP1510	outb(inb(OMAP1510P1_FPGA_POWER) | (1 << 3), OMAP1510P1_FPGA_POWER);#endif#if defined(CONFIG_ARCH_OMAP1510) || defined(CONFIG_ARCH_OMAP1610)	/* Enable MMC/SD clock and disable HI-Z on the MMC.DAT2 pin */	outl(inl(MOD_CONF_CTRL_0) | (1 << 23) | (1 << 21), MOD_CONF_CTRL_0);	/* Set up correct pin multiplexing (OMAP1510 mode) */	/* Configure MMC.DAT3 pin */	outl(inl(FUNC_MUX_CTRL_D) & ~((1 << 14) | (1 << 13) | (1 << 12)),	     FUNC_MUX_CTRL_D);	/* Configure MMC.CLK pin */	outl(inl(FUNC_MUX_CTRL_A) & ~((1 << 23) | (1 << 22) | (1 << 21)),	     FUNC_MUX_CTRL_A);	/* Configure MMC_DAT0_SPI.DI pin */	outl(inl(FUNC_MUX_CTRL_B) & ~((1 << 2) | (1 << 1) | (1 << 0)),	     FUNC_MUX_CTRL_B);	/* Configure MMC.DAT2 pin */	outl(inl(FUNC_MUX_CTRL_A) & ~((1 << 20) | (1 << 19) | (1 << 18)),	     FUNC_MUX_CTRL_A);	/* Configure MMC.DAT1 pin */	outl(inl(FUNC_MUX_CTRL_A) & ~((1 << 26) | (1 << 25) | (1 << 24)),	     FUNC_MUX_CTRL_A);	/* Configure MMC.CMD_SPI.DO pin  */	outl(inl(FUNC_MUX_CTRL_A) & ~((1 << 29) | (1 << 28) | (1 << 27)),	     FUNC_MUX_CTRL_A);#endif#ifdef CONFIG_ARCH_OMAP730	/* Pin MUX is set up for the OMAP730/P2 in perseus2.c */	set_p2_v_sdmmc_state(V_SDMMC_ENABLED);	set_p2_mmc_wp_state(MMC_WP_DISABLED);	/* Start up the 48MHz MMC Clock */	OMAP730_CONFIGURE(PCONF_MMC_DPLL_REQ, ACTIVE);	*((volatile u32 *)ECO_SPARE1) =  ECO_SPARE1_INITVALUE;#endif	/* Configure MMC_CON register */	outw((1 << 11), OMAP_MMC_CON);	/* Clear interrupts and status */	outw(0, OMAP_MMC_IE);	/* Clear all interrupts */	outw(0xffff, OMAP_MMC_STAT);	/* Clear status bits */}static voidomap_mmc_slot_down(void){	disable_irq(OMAP_MMC_CD);	disable_irq(OMAP_MMC_INT);	/* Power Off MMC through FPGA */#ifdef CONFIG_ARCH_OMAP1510	outb(inb(OMAP1510P1_FPGA_POWER) & ~(1 << 3), OMAP1510P1_FPGA_POWER);#endif#if defined(CONFIG_ARCH_OMAP1510) || defined(CONFIG_ARCH_OMAP1610)	/* Disable MMC/SD clock and enable HI-Z on the MMC.DAT2 pin */	outl(inl(MOD_CONF_CTRL_0) & ~((1 << 23) | (1 << 21)), MOD_CONF_CTRL_0);#endif#ifdef CONFIG_ARCH_OMAP730	OMAP730_CONFIGURE(PCONF_MMC_DPLL_REQ, INACTIVE);#endif	outw(0, OMAP_MMC_CON);	del_timer_sync(&g_omap_mmc_data.sd_detect_timer);#ifdef CONFIG_ARCH_OMAP730	set_p2_v_sdmmc_state(V_SDMMC_DISABLED);#endif}/* Standard PM functions */static intomap_mmc_suspend(void){	omap_mmc_stop_clock();	omap_mmc_slot_down();	return 0;}static voidomap_mmc_resume(void){	omap_mmc_slot_up();	omap_mmc_set_clock(g_omap_mmc_data.clock);	/* Set up timers */	g_omap_mmc_data.sd_detect_timer.function = omap_mmc_fix_sd_detect;	g_omap_mmc_data.sd_detect_timer.data = (unsigned long) &g_omap_mmc_data;	init_timer(&g_omap_mmc_data.sd_detect_timer);	enable_irq(OMAP_MMC_INT);	enable_irq(OMAP_MMC_CD);	/* Enable card detect IRQ */}#ifdef CONFIG_PMstatic intomap_mmc_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data){	switch (req) {	case PM_SUSPEND:		mmc_eject(0);		omap_mmc_suspend();		break;	case PM_RESUME:		omap_mmc_resume();		omap_mmc_fix_sd_detect(0);		break;	}	return 0;}#endif#ifdef CONFIG_CEE		/* MVL-CEE */static intomap_mmc_dpm_suspend(struct device *dev, u32 state, u32 level){	switch (level) {	case SUSPEND_POWER_DOWN:		/* Turn off power to MMC/SD */		omap_mmc_suspend();		break;	}	return 0;}static intomap_mmc_dpm_resume(struct device *dev, u32 level){	switch (level) {	case RESUME_POWER_ON:		/* Turn on power to MMC/SD */		omap_mmc_resume();		mmc_eject(0);		omap_mmc_fix_sd_detect(0);		break;	}	return 0;}#endifstatic intomap_mmc_slot_init(void){	int retval;	/* Set up timers */	g_omap_mmc_data.sd_detect_timer.function = omap_mmc_fix_sd_detect;	g_omap_mmc_data.sd_detect_timer.data = (unsigned long) &g_omap_mmc_data;	init_timer(&g_omap_mmc_data.sd_detect_timer);	/* Basic service interrupt */	retval = request_irq(OMAP_MMC_INT, omap_mmc_int,			     SA_INTERRUPT, "omap_mmc_int", &g_omap_mmc_data);	if (retval) {		printk(KERN_CRIT "MMC/SD: unable to grab MMC IRQ\n");		return retval;	}	disable_irq(OMAP_MMC_INT);	/* Card Detect interrupt */	retval = request_irq(OMAP_MMC_CD, omap_mmc_sd_detect_int,			     SA_INTERRUPT, "omap_mmc_cd", &g_omap_mmc_data);#ifdef CONFIG_ARCH_OMAP1610	if (omap_mmc_slot_is_empty(0) == 0)		omap1610_tune_irq(OMAP_MMC_CD, IFL_HIGHLEVEL);#endif#ifdef CONFIG_ARCH_OMAP730	if (omap_mmc_slot_is_empty(0) == 0)		omap730_tune_irq(OMAP_MMC_CD, IFL_HIGHLEVEL);#endif	if (retval) {		printk(KERN_CRIT "MMC/SD: unable to grab MMC_CD_IRQ\n");		goto err1;	}	disable_irq(OMAP_MMC_CD);	if (omap_request_dma	    (eMMCRx, "MMC/SD Rx DMA", (dma_callback_t) omap_mmc_rx_dma_callback,	     &g_omap_mmc_data, &(g_omap_mmc_data.rx_dma_regs))) {		printk(KERN_ERR "Failed to request MMC Rx DMA \n");		goto err2;	}	if (omap_request_dma	    (eMMCTx, "MMC/SD Tx DMA", (dma_callback_t) omap_mmc_tx_dma_callback,	     &g_omap_mmc_data, &(g_omap_mmc_data.tx_dma_regs))) {		printk(KERN_ERR "Failed to request MMC Tx DMA \n");		goto err3;	}#ifdef CONFIG_PM	pm_register(PM_UNKNOWN_DEV, PM_SYS_UNKNOWN, omap_mmc_pm_callback);#endif	omap_mmc_slot_up();	enable_irq(OMAP_MMC_CD);	/* Enable IRQ to detect card */	goto noerr;      err3:omap_free_dma(g_omap_mmc_data.tx_dma_regs);      err2:omap_free_dma(g_omap_mmc_data.rx_dma_regs);      err1:free_irq(OMAP_MMC_INT, &g_omap_mmc_data);      noerr:return retval;}static voidomap_mmc_slot_cleanup(void){	long flags;	local_irq_save(flags);	omap_mmc_slot_down();	mmc_eject(0);	omap_free_dma(g_omap_mmc_data.tx_dma_regs);	omap_free_dma(g_omap_mmc_data.rx_dma_regs);	free_irq(OMAP_MMC_CD, &g_omap_mmc_data);	free_irq(OMAP_MMC_INT, &g_omap_mmc_data);	local_irq_restore(flags);}/***********************************************************/static struct mmc_slot_driver dops = {	.owner = THIS_MODULE,	.name = "OMAP1510/1610/730 MMC",	.ocr = OMAP_MMC_OCR,	.flags = MMC_SDFLAG_MMC_MODE,	.init = omap_mmc_slot_init,	.cleanup = omap_mmc_slot_cleanup,	.is_empty = omap_mmc_slot_is_empty,	.send_cmd = omap_mmc_send_command,	.set_clock = omap_mmc_set_clock,};static int __initomap_mmc_init(void){	int retval;#ifdef CONFIG_CEE		/* MVL-CCE */	omap_mmc_ldm_device_register();	omap_mmc_ldm_driver_register();#endif				/* MVL-CCE */	retval = mmc_register_slot_driver(&dops, 1);	if (retval < 0)		printk(KERN_INFO "MMC/SD: unable to register slot\n");	return retval;}static void __exitomap_mmc_cleanup(void){#ifdef CONFIG_CEE		/* MVL-CCE */	omap_mmc_ldm_device_unregister();	omap_mmc_ldm_driver_unregister();#endif				/* MVL-CCE */	mmc_unregister_slot_driver(&dops);}module_init(omap_mmc_init);module_exit(omap_mmc_cleanup);MODULE_AUTHOR("Alexey Lugovskoy");MODULE_DESCRIPTION("OMAP1510/1610/730 Innovator MMC/SD");MODULE_LICENSE("GPL");EXPORT_NO_SYMBOLS;

⌨️ 快捷键说明

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