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

📄 jz_mmc.c

📁 包含MMC协议,驱动源码. 在LINUX操作系统下通过.
💻 C
📖 第 1 页 / 共 2 页
字号:
		break;	default:		break;	}	/* Set command index */	if (request->cmd == MMC_CIM_RESET) {		REG_MSC_CMD = MMC_GO_IDLE_STATE;	} else {		REG_MSC_CMD = request->cmd;	}        /* Set argument */ 	REG_MSC_ARG = request->arg;	if (request->cmd == SEND_SCR) { /* get SCR from DataFIFO */		REG_MSC_BLKLEN = 8;		REG_MSC_NOB = 1;	} else {		REG_MSC_BLKLEN = request->block_len;		REG_MSC_NOB = request->nob;	}	/* Set command */	REG_MSC_CMDAT = cmdat;	DEBUG(1, ": Send cmd %d cmdat: %x arg: %d resp %d\n", request->cmd,	      cmdat, request->arg, request->rtype);        /* Send command */	jz_mmc_start_clock();	/* Wait for command completion */	while (timeout-- && !(REG_MSC_STAT & MSC_STAT_END_CMD_RES))		;	if (timeout == 0) {		jz_mmc_request_complete(mmc, MMC_ERROR_TIMEOUT);		return MMC_ERROR_TIMEOUT;	}	REG_MSC_IREG = MSC_IREG_END_CMD_RES; /* clear irq flag */	/* Check for status */	retval = jz_mmc_check_status(mmc->request);	if (retval) {		jz_mmc_request_complete(mmc, retval);		return retval;	}	/* Complete command with no response */	if (request->rtype == RESPONSE_NONE) {		jz_mmc_request_complete(mmc, MMC_NO_ERROR);		return MMC_NO_ERROR;	}	/* get response */	jz_mmc_get_response(mmc->request);	/* Setup DMA if necessary */	if (mmc->events & MMC_EVENT_RX_DMA_DONE) {		jz_mmc_dma_rx_start(mmc);	}	if (mmc->events & MMC_EVENT_TX_DMA_DONE) {		jz_mmc_dma_tx_start(mmc);	}	/* Unmask some interrupts */	if (mmc->events & MMC_EVENT_DATA_DONE) {		REG_MSC_IMASK &= ~MSC_IMASK_DATA_TRAN_DONE;	}	if (mmc->events & MMC_EVENT_PROG_DONE) {		REG_MSC_IMASK &= ~MSC_IMASK_PRG_DONE;	}	/* If no events, complete this command */	if (mmc->events == 0) {		jz_mmc_request_complete(mmc, MMC_NO_ERROR);	}	return MMC_NO_ERROR;}/* Start the command execution */void jz_mmc_send_command(struct mmc_request *request){	int retval;	DEBUG(2, "send command [%d %x]\n", request->cmd, request->arg);	/* Save current request for the future processing */ 	jz_mmc_data.request = request;	/* Indicate we have no result yet */	request->result = MMC_NO_RESPONSE;	if (request->cmd == MMC_CIM_RESET) {		/* On reset, 1-bit bus width */		jz_mmc_data.use_4bit = 0;		/* Reset MMC/SD controller */		__msc_reset();		/* On reset, drop MMC clock down */		jz_mmc_set_clock(MMC_CLOCK_SLOW);		/* On reset, stop MMC clock */		jz_mmc_stop_clock();	}	if (request->cmd == SD_SEND_OP_COND) {		DEBUG(3, "Have an SD card\n");		jz_mmc_data.sd = 1;	}	if (request->cmd == MMC_SEND_OP_COND) {		DEBUG(3, "Have an MMC card\n");		jz_mmc_data.sd = 0;		/* always use 1bit for MMC */		jz_mmc_data.use_4bit = 0;	}	if (request->cmd == SET_BUS_WIDTH) {		if (request->arg == 0x2) {			DEBUG(2, "Use 4-bit bus width\n");			jz_mmc_data.use_4bit = 1;		}		else {			DEBUG(2, "Use 1-bit bus width\n");			jz_mmc_data.use_4bit = 0;		}	}	retval = jz_mmc_exec_command(request);	if (retval) {		jz_mmc_request_complete(&jz_mmc_data, retval);	}}/* Card service IRQ handler */static void jz_mmc_int(int irq, void *dev, struct pt_regs *regs){	jz_mmc_data_t *mmc = (jz_mmc_data_t *)dev;	struct mmc_request *request = mmc->request;	u16 irqtype, status;	int retval;	irqtype = REG_MSC_IREG;	status = REG_MSC_STAT;	DEBUG(3, "MMC service IRQ [MMC_STAT %x, MMC_I_REG %x, MMC_I_MASK %x CMD=%d]\n",	      status, irqtype, REG_MSC_IMASK, request->cmd);	/* Check status */	retval = jz_mmc_check_status(request);	if (retval) {		REG_MSC_IREG = irqtype; /* clear status */		jz_mmc_request_complete(mmc, retval);		return;	}	/* Handle data transfer done event */		if (irqtype & MSC_IREG_DATA_TRAN_DONE) {		REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE; /* clear status */		mmc->events &= ~MMC_EVENT_DATA_DONE;		/* SD card returns SCR register as data. MMC core expect it in the		   response buffer, after normal response. */		if (request->cmd == SEND_SCR) {			u8 *buf;			u32 i, data;			buf = request->response;			/* Read SCR */			for (i = 0; i < 2; i++)			{				data = REG_MSC_RXFIFO;				DEBUG(3, ": SCR: %x\n", data);				*(buf + (i * 4) + 8) = (data >> 24) & 0xff;				*(buf + (i * 4) + 7) = (data >> 16) & 0xff;				*(buf + (i * 4) + 6) = (data >> 8) & 0xff;				*(buf + (i * 4) + 5) = data & 0xff;			}		}		if (mmc->events == 0) {			jz_mmc_request_complete(mmc, MMC_NO_ERROR);			return;		}	}	/* Handle programming done event */	if (irqtype & MSC_IREG_PRG_DONE) {		REG_MSC_IREG = MSC_IREG_PRG_DONE; /* clear status */		mmc->events &= ~MMC_EVENT_PROG_DONE;		if (mmc->events == 0) {			jz_mmc_request_complete(mmc, MMC_NO_ERROR);			return;		}	}}/* Returns true if MMC slot is empty */static int jz_mmc_slot_is_empty(int slot){	int empty;	DEBUG(3, "detect slot\n");	empty = (__msc_card_detected(slot) == 0) ? 1: 0;	if (empty) {		/* wait for card insertion */		__gpio_as_irq_fall_edge(MSC_HOTPLUG_PIN);	}	else {		/* wait for card removal */		__gpio_as_irq_rise_edge(MSC_HOTPLUG_PIN);	}	return empty;}/* Return true if MMC slot is write-protected */static int jz_mmc_slot_is_wp(int slot){	int wp;	__gpio_as_input(MSC_WP_PIN);	wp = __gpio_get_pin(MSC_WP_PIN);        return wp;}static void jz_mmc_detect_int(int irq, void *dev, struct pt_regs *regs){	DEBUG(2, "card detect IRQ\n");	if (jz_mmc_slot_is_empty(0)) {		DEBUG(3, "no card in slot\n");		mmc_eject(0);		/* wait for card insertion */		__gpio_as_irq_fall_edge(MSC_HOTPLUG_PIN);	}	else {		DEBUG(3, "found the card in slot\n");		mmc_insert(0);		/* wait for card removal */		__gpio_as_irq_rise_edge(MSC_HOTPLUG_PIN);	}}#ifdef CONFIG_PM/* * Standard PM functions, if CONFIG_PM is used *//* Suspend the MMC slot */static int jz_mmc_suspend(void){	DEBUG(1, "suspend mmc slot\n");	jz_mmc_slot_down();	return 0;}/* Resume the MMC slot */static void jz_mmc_resume(void){	DEBUG(1, "resume mmc slot\n");	jz_mmc_slot_up();	jz_mmc_set_clock(jz_mmc_data.clock);}static int jz_mmc_pm_callback(struct pm_dev *pm_dev,			       pm_request_t req, void *data){	switch(req) {	case PM_SUSPEND:		mmc_eject(0);		jz_mmc_suspend();		break;			case PM_RESUME:		jz_mmc_resume();		if (jz_mmc_slot_is_empty(0)) {			mmc_eject(0);		}		else {			mmc_insert(0);		}		break;			default:		printk(KERN_ERR "MMC/SD: invalid PM request %d\n", req);		break;	}	return 0;}#endif /* CONFIG_PM *//* Initialize the slot and prepare software layer to operate with it */static int jz_mmc_slot_init(void){	int retval;	int channel;	/* Startup MMC/SD slot */	jz_mmc_slot_up();	/* Request basic card servicing IRQ */	retval = request_irq(IRQ_MSC, jz_mmc_int,			     SA_INTERRUPT,			     "MMC/SD", &jz_mmc_data);	if (retval) {		printk(KERN_ERR "MMC/SD: can't request MMC/SD IRQ\n");		return retval;	}        /* Request card detect interrupt */	__gpio_as_irq_fall_edge(MSC_HOTPLUG_PIN);	retval = request_irq(MSC_HOTPLUG_IRQ, jz_mmc_detect_int, 			     SA_INTERRUPT,			     "MMC card detect", &jz_mmc_data);	if (retval) {		printk(KERN_ERR "MMC/SD: can't request card detect IRQ\n");		goto err1;	}	/* Request MMC Rx DMA channel */	channel = jz_request_dma(DMA_ID_MSC_RX, "MMC Rx", jz_mmc_dma_rx_callback,				 SA_INTERRUPT, &jz_mmc_data);	if (channel < 0) {		printk(KERN_ERR "jz_request_dma failed for MMC Rx\n");		goto err2;	}	jz_mmc_data.dma_rx_ch = channel;	/* Request MMC Tx DMA channel */	channel = jz_request_dma(DMA_ID_MSC_TX, "MMC Tx", jz_mmc_dma_tx_callback,				 SA_INTERRUPT, &jz_mmc_data);	if (channel < 0) {		printk(KERN_ERR "jz_request_dma failed for MMC Tx\n");		goto err3;	}	jz_mmc_data.dma_tx_ch = channel;	DEBUG(2, "dma_rx_ch=%d dma_tx_ch=%d\n", 	      jz_mmc_data.dma_rx_ch, jz_mmc_data.dma_tx_ch);	/* Use 1-bit by default */	jz_mmc_data.use_4bit = 0;#ifdef CONFIG_PM	/* Register MMC slot as as power-managed device */        pm_register(PM_UNKNOWN_DEV, PM_SYS_UNKNOWN, jz_mmc_pm_callback);#endif	DEBUG(2, "MMC initialized with code %d\n", retval);	return retval;err3:	jz_free_dma(jz_mmc_data.dma_rx_ch);err2:	free_irq(MSC_HOTPLUG_IRQ, &jz_mmc_data);err1:	free_irq(IRQ_MSC, &jz_mmc_data);	return -1;}/* Shut down the slot and relax software about MMC slot */static void jz_mmc_slot_cleanup(void){        long flags;	DEBUG(2, "Bye, MMC\n");	local_irq_save(flags); 	/* Shut down the slot */	jz_mmc_slot_down();		/* Free DMA channels */	jz_free_dma(jz_mmc_data.dma_rx_ch);	jz_free_dma(jz_mmc_data.dma_tx_ch);	/* Free both IRQs */	free_irq(MSC_HOTPLUG_IRQ, &jz_mmc_data);	free_irq(IRQ_MSC, &jz_mmc_data);        local_irq_restore(flags);}/***********************************************************/static struct mmc_slot_driver jz_dops = {	owner:		THIS_MODULE,	name:		"JZ MMC/SD",	ocr:		0x00ff8000,	flags:		MMC_SDFLAG_MMC_MODE | MMC_SDFLAG_SD_MODE,	init:		jz_mmc_slot_init,	cleanup:	jz_mmc_slot_cleanup,	is_empty:	jz_mmc_slot_is_empty,	is_wp:		jz_mmc_slot_is_wp,	send_cmd:	jz_mmc_send_command,	set_clock:	jz_mmc_set_clock};int __initjz_mmc_init(void){	int retval;	retval = mmc_register_slot_driver(&jz_dops, 1);	if (retval < 0)		printk(KERN_INFO "MMC: unable to register slot\n");	printk("JZ MMC/SD driver registered\n");	return retval;}void __exitjz_mmc_cleanup(void){	DEBUG(1,"\n");	mmc_unregister_slot_driver(&jz_dops);}module_init(jz_mmc_init);module_exit(jz_mmc_cleanup);MODULE_DESCRIPTION("JZ MMC");MODULE_LICENSE("GPL");EXPORT_NO_SYMBOLS;

⌨️ 快捷键说明

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