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

📄 mx2_mmc.c

📁 mmc 方式通讯的在CPU PXA270下的WINCE 5驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
	int i;	u16 rs;	u32 temp;	request->result = MMC_NO_ERROR;	/* Mark this as having a request result of some kind */	DEBUG(3, ": Get response \n");	switch (request->rtype) {	case RESPONSE_R1:	case RESPONSE_R1B:		request->response[0] = request->cmd;		temp = SDHC_RES_FIFO(MMC_BASE);		rs = (u16) temp;		request->response[1] = (u8) (rs & 0x00FF);		temp = SDHC_RES_FIFO(MMC_BASE);		rs = (u16) temp;		request->response[2] = (u8) (rs >> 8);		if (request->cmd == 3 && request->response[1] == 0		    && request->response[2] == 0x40) {			request->response[2] &=			    request->response[2] & ~(1 << 6);		}		/* mmc device does not clear this bit after APP_CMD command for some mmc cards */		request->response[3] = (u8) (rs & 0x00FF);		temp = SDHC_RES_FIFO(MMC_BASE);		rs = (u16) temp;		request->response[4] = (u8) (rs >> 8);		break;	case RESPONSE_R3:	case RESPONSE_R4:	case RESPONSE_R5:		request->response[0] = 0x3f;		temp = SDHC_RES_FIFO(MMC_BASE);		rs = (u16) temp;		request->response[1] = (u8) (rs & 0x00FF);		temp = SDHC_RES_FIFO(MMC_BASE);		rs = (u16) temp;		request->response[2] = (u8) (rs >> 8);		request->response[3] = (u8) (rs & 0x00FF);		temp = SDHC_RES_FIFO(MMC_BASE);		rs = (u16) temp;		request->response[4] = (u8) (rs >> 8);		break;	case RESPONSE_R2_CID:	case RESPONSE_R2_CSD:		request->response[0] = 0x3f;	/* for mmc core */		for (i = 0; i < 8; i++) {			temp = SDHC_RES_FIFO(MMC_BASE);			rs = (u16) temp;			request->response[2 * i + 1] = (u8) (rs >> 8);			request->response[2 * i + 2] = (u8) (rs & 0x00FF);		}	case RESPONSE_NONE:	default:		break;	}}static voidmx2_mmc_handle_int(struct mx2_mmc_data *sd){	int retval = MMC_NO_ERROR;	u16 status = SDHC_STATUS(MMC_BASE);	mx2_mmc_stop_clock();	/* Clear status bits */	SDHC_INT_MASK(MMC_BASE) = MX2_AUTO_CARD_DETECT_MASK & 0x7f;	/* mask and clear all interrupts */	/* Data or Command time-out? */	if (status & (MX2STAT_TIME_OUT_RESP | MX2STAT_TIME_OUT_READ)) {		DEBUG(1, " TIMEOUT: MMC status: %x \n", status);		retval = MMC_ERROR_TIMEOUT;		sd->request->result = MMC_ERROR_TIMEOUT;		mx2_mmc_get_response(sd->request);		goto terminate_int;	}	/* CRC error? */	if ((status & (MX2STAT_RESP_CRC_ERR /* | MX2STAT_CRC_READ_ERR */ ))) {		DEBUG(1, " MMCSD_RESP_CRC_ERR: MMC status: %x \n", status);		retval = MMC_ERROR_CRC;		goto terminate_int;	}	if (((status & MX2STAT_END_CMD_RESP)	     || (status & MX2STAT_DATA_TRANS_DONE)	     || (status & MX2STAT_WRITE_OP_DONE))	    && (sd->request->result == MMC_NO_RESPONSE)) {		mx2_mmc_get_response(sd->request);	}	switch (g_mx2_mmc_data.type) {	case RT_NO_RESPONSE:		break;	case RT_WRITE:		if (sd->request->nob) {			/* Start another transfer */		}		break;	case RT_READ:		if (sd->request->nob) {			/* Start another transfer */		}		break;	case RT_RESPONSE_ONLY:		if (sd->request->result < 0) {			printk(KERN_INFO			       "MMC: Illegal interrupt - command hasn't finished\n");			retval = MMC_ERROR_TIMEOUT;		}		break;	}      terminate_int:	sd->request->result = retval;	mmc_cmd_complete(sd->request);}/* Handle IRQ */static voidmx2_mmc_int(int irq, void *dev_id, struct pt_regs *regs){	struct mx2_mmc_data *sd = (struct mx2_mmc_data *) dev_id;	u32 status = SDHC_STATUS(MMC_BASE) & 0xFFFF;	DEBUG(4, " 0x%x\n", SDHC_STATUS(MMC_BASE));	if ((sd->request->cmd == MMC_READ_SINGLE_BLOCK	     || sd->request->cmd == MMC_READ_MULTIPLE_BLOCK)) {		if (status & MX2STAT_APPL_BUFF_FF) {			mx2_mmc_rx();		} else if ((status & MX2STAT_DATA_TRANS_DONE)			   || ((status & MX2STAT_END_CMD_RESP)			       && rx_counter >=			       g_mx2_mmc_data.request->block_len)) {			mx2_mmc_handle_int(sd);		}	} else	    if ((sd->request->cmd == MMC_WRITE_BLOCK		 || sd->request->cmd == MMC_WRITE_MULTIPLE_BLOCK)) {		if (status & MX2STAT_WRITE_OP_DONE) {			mx2_mmc_handle_int(sd);		} else if (status & MX2STAT_DATA_TRANS_DONE) {		} else if (status & MX2STAT_APPL_BUFF_FE) {			mx2_mmc_tx();		}	} else {		mx2_mmc_handle_int(sd);	}}static intmx2_mmc_slot_is_empty(int slot){	card_state = SDHC_STATUS(MMC_BASE) & MX2STAT_CARD_PRESENCE;	return card_state == 0;}/************************************************************************** * *                       Hardware initialization * *************************************************************************/static intmx2_mmc_slot_up(void){	int retval;	/* MX2 MMC slot hardware init */	mx_module_clk_open(IPG_MODULE_SDHC1);	/* Perclock 2 */	/* GPIO */	retval = mx2_register_gpios(PORT_E, (1 << 22) |	/* MMC: SD_CMD */				    (1 << 23) |	/* MMC: SD_CLK */				    (1 << 21) |	/* MMC: SD_DAT */				    (1 << 20) |	/* MMC: SD_DAT */				    (1 << 19) |	/* MMC: SD_DAT */				    (1 << 18),	/* MMC: SD_DAT */				    PRIMARY | NOINTERRUPT);	if (retval < 0)		goto error;	return retval;      error:	mx2_unregister_gpios(PORT_E,			     (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21) | (1									      <<									      22)			     | (1 << 23));	return retval;}static voidmx2_mmc_slot_down(void){	disable_irq(INT_SDHC1);	/* Power Off MMC through FPGA */	/* Disable MMC clock and enable HI-Z on the MMC.DAT2 pin */}/* Standard PM functions */static intmx2_mmc_suspend(void){	mx2_gpio_mask_intr(PORT_D, 25);	if (mx2_mmc_inserted) {		mmc_eject(0);		/*set it to be negative level trigger detect card withdraw */		mx2_gpio_config_intr(PORT_D, 25, NEGATIVE_LEVEL, mmcsd_socket1_irq_handler);		mx2_mmc_inserted = 0;	}	mx2_mmc_slot_down(); /*disable MMC IRQ*/	mx2_mmc_stop_clock();	mx_module_clk_close(IPG_MODULE_SDHC1);	return 0;}static voidmx2_mmc_resume(void){	mx_module_clk_open(IPG_MODULE_SDHC1);	mx2_mmc_set_clock(g_mx2_mmc_data.clock);	enable_irq(INT_SDHC1);	mx2_gpio_unmask_intr(PORT_D, 25);}#ifdef CONFIG_PMstatic intmx2_mmc_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data){	switch (req) {	case PM_SUSPEND:		mx2_mmc_suspend();		break;	case PM_RESUME:		mx2_mmc_resume();		break;	}	return 0;}#endif#if 1 /*CEE LDM*/static int__ldm_suspend(struct device *dev, u32 state, u32 level){	switch (level) {	case SUSPEND_POWER_DOWN:		mx2_mmc_suspend();		break;	}	return 0;}static int__ldm_resume(struct device *dev, u32 level){	switch (level) {	case RESUME_POWER_ON:		mx2_mmc_resume();		break;	}	return 0;}#endifvoidmmcsd_socket1_irq_handler(int irq, void *dev_id, struct pt_regs *regs){	u32 trigger;	trigger = mx2_gpio_get_intr_config(PORT_D, 25);	if (mx2_gpio_intr_status_bit(PORT_D, 25)) {		if (trigger == 2)	/* it is positive level now */		{			if (mx2_mmc_inserted) {				mmc_eject(0);				/*set it to be negative level trigger detect card withdraw */				mx2_gpio_config_intr(PORT_D, 25, NEGATIVE_LEVEL, mmcsd_socket1_irq_handler);				mx2_mmc_inserted = 0;			}		}		if (trigger == 3)	/* it is negative level now */		{			if (!mx2_mmc_inserted) {				mmc_insert(0);				/*set it to be positive level trigger detect card insert */				mx2_gpio_config_intr(PORT_D, 25, POSITIVE_LEVEL, mmcsd_socket1_irq_handler);				mx2_mmc_inserted = 1;			}		}		mx2_gpio_clear_intr(PORT_D, 25);	}}#define MX2ADS_MMC_MIN_HCLK  33000static intmx2_mmc_slot_init(void){	int retval;	long flags;#if 1 /*CEE LDM*/	if (MX2ADS_MMC_MIN_HCLK > mx_module_get_clk(HCLK) / 1000) {		printk(KERN_ERR "cannot initialize MMC - HCLK too slow\n");		return -EPERM;	}#endif	/* Basic service interrupt */	local_irq_save(flags);	mx2_mmc_slot_up();	mx2_mmc_softreset();	/* check hardware revision */	if ((SDHC_REV_NO(MMC_BASE) & 0xFFFF) != 0x0400) {		printk(KERN_ERR "MMC Hardware revision = 0x%x",		       SDHC_REV_NO(MMC_BASE));	}	mx2_register_gpio(PORT_D, 25, GPIO | INPUT | TRISTATE);	mx2_gpio_unmask_intr(PORT_D, 25);	/* enable */	mx2_gpio_config_intr(PORT_D, 25, NEGATIVE_LEVEL,			     mmcsd_socket1_irq_handler);	mx2_mmc_inserted = 0;	SDHC_INT_MASK(MMC_BASE) = MX2_AUTO_CARD_DETECT_MASK & 0x7f;	/* Clear all interrupts */	retval = request_irq(INT_SDHC1, mx2_mmc_int,			     SA_INTERRUPT, "mx2_mmc_int", &g_mx2_mmc_data);	if (retval) {		printk(KERN_CRIT "MMC: unable to grab MMC IRQ\n");		return retval;	}#ifdef CONFIG_PM	pm_register(PM_UNKNOWN_DEV, PM_SYS_UNKNOWN, mx2_mmc_pm_callback);#endif#if 1 /*CEE LDM*/#ifdef CONFIG_DPM	mx2mmc_constraints.param[0].min = MX2ADS_MMC_MIN_HCLK;	/*in KHz */	mx2mmc_constraints.param[0].max = mx_module_get_clk(MPLL) / 1000;	/* unlimited */#endif	mx21_ldm_bus_register(&__device_ldm, &__driver_ldm);#endif	local_irq_restore(flags);	return retval;}static voidmx2_mmc_slot_cleanup(void){	long flags;	local_irq_save(flags);	mx2_mmc_slot_down();	free_irq(INT_SDHC1, &g_mx2_mmc_data);	mx_module_clk_close(IPG_MODULE_SDHC1);	local_irq_restore(flags);	mx2_unregister_gpio(PORT_D, 25);#ifdef CONFIG_PM	pm_unregister_all(mx2_mmc_pm_callback);#endif#if 1 /*CEE LDM*/	mx21_ldm_bus_unregister(&__device_ldm, &__driver_ldm);#endif}/***********************************************************/static struct mmc_slot_driver dops = {	.owner = THIS_MODULE,	.name = "MX2 MMC",	.ocr = 0x00ffc000,	.flags = MMC_SDFLAG_MMC_MODE,	.init = mx2_mmc_slot_init,	.cleanup = mx2_mmc_slot_cleanup,	.is_empty = mx2_mmc_slot_is_empty,	.send_cmd = mx2_mmc_send_command,	.set_clock = mx2_mmc_set_clock};int __initmx2_mmc_init(void){	int retval;	retval = mmc_register_slot_driver(&dops, 1);	if (retval < 0)		printk(KERN_INFO "MMC: unable to register slot\n");	return retval;}void __exitmx2_mmc_cleanup(void){	mmc_unregister_slot_driver(&dops);	mx2_unregister_gpios(PORT_E,			     (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21) | (1									      <<									      22)			     | (1 << 23));}module_init(mx2_mmc_init);module_exit(mx2_mmc_cleanup);MODULE_DESCRIPTION("MX2 MMC");MODULE_LICENSE("GPL");EXPORT_NO_SYMBOLS;

⌨️ 快捷键说明

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