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

📄 mhn_controller.c

📁 spi driver code one marve
💻 C
📖 第 1 页 / 共 3 页
字号:
	pxa_host->data = llreq->data;	pxa_host->llreq = llreq;	cmd = pxa_host->cmd;	dbg("Read to send CMD :0x%x, cmd flag 0x%x", cmd->opcode, cmd->flags);	if (cmd->flags & MSS_CMD_INIT)		cmd_dat |= MMC_CMDAT_INIT;	if (cmd->flags & MSS_CMD_STOP)		cmd_dat |= MMC_CMDAT_STOP;	if (cmd->flags & MSS_CMD_SDIO_EN || host->sdio_int)		cmd_dat |= MMC_CMDAT_SDIO_INT;	if (llreq->data) {		dbg("data flags 0x%x", llreq->data->flags);		if (llreq->data->flags & MSS_DATA_WRITE)			cmd_dat |= MMC_CMDAT_WRITE;		pxa_host_setup_data(pxa_host, llreq->data);		cmd_dat |= (MMC_CMDAT_DATA | MMC_CMDAT_DMA);		cmd_dat &= ~MMC_CMDAT_BUSY;		dbg("data nob %d, block_len %d", llreq->data->blocks, 				llreq->data->blksz);		if (llreq->data->flags & MSS_DATA_STREAM)			cmd_dat |= MMC_CMDAT_STREAM;	}	else {		writel(0, pxa_host->base + MMC_NUMBLK);		writel(0, pxa_host->base + MMC_BLKLEN);	}	dbg("cmd rtype %d", cmd->rtype);	switch (cmd->rtype) {		case MSS_RESPONSE_NONE:			cmd_dat |= MMC_CMDAT_RESP_FMT_NONE;			break;		case MSS_RESPONSE_R1B:			cmd_dat |= MMC_CMDAT_BUSY;			// Fall through		case MSS_RESPONSE_R1:		case MSS_RESPONSE_R4:		case MSS_RESPONSE_R5:		case MSS_RESPONSE_R6:		case MSS_RESPONSE_R7:			cmd_dat |= MMC_CMDAT_RESP_FMT_R1;			break;		case MSS_RESPONSE_R2_CID:		case MSS_RESPONSE_R2_CSD:			cmd_dat |= MMC_CMDAT_RESP_FMT_R2;			break;		case MSS_RESPONSE_R3:			cmd_dat |= MMC_CMDAT_RESP_FMT_R3;			break;	}	dbg("card bus width %d", card->bus_width);	if (card->bus_width == MSS_BUSWIDTH_4BIT)		cmd_dat |= MMC_CMDAT_4DAT;		writel(cmd->opcode, pxa_host->base + MMC_CMD);	writel(cmd->arg >> 16, pxa_host->base + MMC_ARGH);	writel(cmd->arg & 0xffff, pxa_host->base + MMC_ARGL);	writel(cmd_dat, pxa_host->base + MMC_CMDAT);		dbg("Read out MMC_CMD 0x%x",readl(pxa_host->base+MMC_CMD));	dbg("Read out MMC_ARGH 0x%x",readl(pxa_host->base+MMC_ARGH));	dbg("Read out MMC_ARGL 0x%x",readl(pxa_host->base+MMC_ARGL));	dbg("Read out MMC_CMDAT 0x%x",readl(pxa_host->base+MMC_CMDAT));	dbg("Read out MMC_CLKRT 0x%x",readl(pxa_host->base+MMC_CLKRT));	dbg("Read out MMC_NUMBLK 0x%x",readl(pxa_host->base+MMC_NUMBLK));	dbg("Read out MMC_BLKSZ 0x%x",readl(pxa_host->base+MMC_BLKLEN));	if (llreq->data && llreq->data->sg_len) {		pxa_host->dma_run = 1;		DDADR(pxa_host->dma) = pxa_host->sg_dma;		/* start DMA */		DCSR(pxa_host->dma) |= DCSR_RUN; 		dbg("enable dma %d, DDADR: 0x%x, DCSR: 0x%x", pxa_host->dma, 				DDADR(pxa_host->dma), DCSR(pxa_host->dma));	}	pxa_host_enable_int(pxa_host, MMC_I_MASK_END_CMD_RES | MMC_I_MASK_RES_ERR);	}static void pxa_mss_enable_sdio_int(struct mss_host *host, int enable){	unsigned long flags;	struct pxa_mss_host *pxa_host = host->private;		local_irq_save(flags);	if (enable) {		host->sdio_int = MSS_SDIO_INT_EN;		pxa_host_enable_int(pxa_host, MMC_I_MASK_SDIO_INT);	}	else {		host->sdio_int = MSS_SDIO_INT_DIS;		pxa_host_disable_int(pxa_host, MMC_I_MASK_SDIO_INT);	}	local_irq_restore(flags);}/* * DMA irq handler. devid represent pxa_mss_controller_device for dma interrupt * is to pxa_controller */static void pxa_host_dma_irq(int dma, void *devid, struct pt_regs *regs){	unsigned int dcsr;	struct pxa_mss_host *pxa_host;	struct mss_card *card;	struct mss_cmd *cmd;	struct mss_data *data;	dbg("DMA IRQ");	pxa_host = (struct pxa_mss_host *)devid;	card = pxa_host->host->active_card;	data = pxa_host->data;	if (!card) {		printk(KERN_ERR "Can not find card\n");		BUG();	}	cmd = pxa_host->cmd;	dcsr = DCSR(dma);	DCSR(dma) &= ~DCSR_STOPIRQEN;		dbg("dma int dcsr:0x%x, DSADR:0x%x, DCMD:0x%x", dcsr, DSADR(dma),		       	DCMD(dma));	if (dcsr & DCSR_BUSERR) {		/* dbg("DCSR_BUSEER"); */		cmd->error = MSS_ERROR_DMA;		data->bytes_xfered = 0;		pxa_host_disable_int(pxa_host, MMC_I_MASK_DATA_TRAN_DONE | 				MMC_I_MASK_DAT_ERR | MMC_I_MASK_TINT);		pxa_host->llreq->done(pxa_host->llreq);	}	else if (dcsr & DCSR_STOPSTATE) {		if (data && (data->flags & MSS_DATA_WRITE))			writel(BUF_PART_FULL, pxa_host->base + MMC_PRTBUF); 		if (data && (data->flags & MSS_DATA_WRITE) && 				cmd->rtype == MSS_RESPONSE_R1B)			pxa_host_enable_int(pxa_host, MMC_I_REG_PRG_DONE);		/* dbg("sg index:%d, dma_len:%d", pxa_host->sg_idx, 				pxa_host->dma_len); */		else if (data && (data->flags & 					(MSS_DATA_WRITE | MSS_DATA_READ))) {			pxa_host_enable_int(pxa_host, MMC_I_MASK_DATA_TRAN_DONE				       	| MMC_I_MASK_DAT_ERR | MMC_I_MASK_TINT);		} else {			printk(KERN_ERR "ERROR in SLOT_DMA_IRQ, neither WRITE"				       " nor READ or sg_idx exceed dma_len");			dump_stack();		}	}	pxa_host->dma_run = 0;		return;	}/* *  slot INT routine for commands with R1B response type */static int pxa_host_r1b_irq(struct pxa_mss_host *pxa_host,		u32  ireg, u32 stat, u32 mask){	struct mss_host *host;	struct mss_cmd *cmd;	/* dbg("host%d, I_REG: 0x%x, STAT: 0x%x, MASK: 0x%x\n", 	pxa_host->host->id, (u32)ireg, (u32)stat, (u32)mask); */	host = pxa_host->host;	cmd = pxa_host->cmd;		if ((ireg & MMC_I_REG_END_CMD_RES) 			&& (!(mask & MMC_I_MASK_END_CMD_RES)) ) {		pxa_host_disable_int(pxa_host, 				MMC_I_MASK_END_CMD_RES | MMC_I_MASK_RES_ERR);		pxa_host_get_response(pxa_host, cmd);		if (ireg & MMC_I_REG_RES_ERR) {			pxa_host_set_error(cmd, stat);			/* dbg("in RES_ERROR, prepare to cmd_complete");*/			pxa_host->llreq->done(pxa_host->llreq);			return 1;		}				pxa_host_enable_int(pxa_host, MMC_I_MASK_PRG_DONE);		return 1;	}	if ((ireg & MMC_I_REG_PRG_DONE) && (!(mask & MMC_I_MASK_PRG_DONE)) ) {		pxa_host_disable_int(pxa_host, MMC_I_MASK_PRG_DONE);		/* dbg("in PRG_DONE, prepare to cmd_complete\n"); */		pxa_host->llreq->done(pxa_host->llreq); 	}	return 1;}/* *  slot INT routine for write commands with data buffer */static int pxa_host_write_irq(struct pxa_mss_host *pxa_host,		u32 ireg, u32 stat, u32 mask){	struct mss_host *host;	struct mss_cmd *cmd;	host = pxa_host->host;	cmd = pxa_host->cmd;		if ((ireg & MMC_I_REG_END_CMD_RES) &&		\		(!(mask & MMC_I_MASK_END_CMD_RES))) {		pxa_host_disable_int(pxa_host,			MMC_I_MASK_END_CMD_RES | MMC_I_MASK_RES_ERR);		if (ireg & MMC_I_REG_RES_ERR) {			pxa_host_set_error(cmd, stat);			/* dbg("in RES_ERROR, prepare to cmd_complete"); */			pxa_host->llreq->done(pxa_host->llreq);			return 1;		}			pxa_host_get_response(pxa_host, cmd);		return 1;	}	if ((ireg & (MMC_I_REG_DAT_ERR | MMC_I_REG_TINT)) 			&& (!(mask & (MMC_I_MASK_DAT_ERR | MMC_I_MASK_TINT)))) {		stat = readl(pxa_host->base + MMC_STAT);		pxa_host_disable_int(pxa_host,			MMC_I_MASK_DATA_TRAN_DONE |		\			MMC_I_MASK_DAT_ERR |			\			MMC_I_MASK_TINT);		pxa_host_set_error(cmd, stat);		/* dbg("DATA/TIMEOUT error.  I_REG: 0x%x, STAT: 0x%x, 		 I_MASK: 0x%x. prepare to cmd_complete", MMC_I_REG, MMC_STAT, 		 MMC_I_MASK); */		pxa_host->llreq->done(pxa_host->llreq);		return 1;	}		/* wait for DMA interrupt, DATA WRITE done once DATA_TRAN_DONE 	 * interrupt occurred 	 */	if ((ireg & MMC_I_REG_DATA_TRAN_DONE) 			&& (!(mask & MMC_I_MASK_DATA_TRAN_DONE)) ) {		/* Note: must not disable DATA_ERROR interrupt, 		 * for it may be occured again!!! 		 */		pxa_host_disable_int(pxa_host, 				MMC_I_MASK_DATA_TRAN_DONE | MMC_I_MASK_DAT_ERR | MMC_I_MASK_TINT);		pxa_host_enable_int(pxa_host, MMC_I_MASK_PRG_DONE); 		return 1;	}			if ((ireg & MMC_I_REG_PRG_DONE) && (!(mask & MMC_I_MASK_PRG_DONE)) ) {		//pxa_host_get_response(pxa_host, cmd);		pxa_host_disable_int(pxa_host, MMC_I_MASK_PRG_DONE);		/* dbg("in PRG_DONE, prepare to cmd_complete"); */		pxa_host->llreq->done(pxa_host->llreq); 	}	return 1;}/** *  pxa_slot_read_irq *  @card: mss_card_device *  @ireg: value of MMCx_I_REG *  @stat: value of MMCx_STAT *  @mask: value of MMCx_I_MASK * *  slot INT routine for read commands with data buffer */static int pxa_host_read_irq(struct pxa_mss_host *pxa_host,		u32 ireg, u32 stat, u32 mask){	struct mss_host *host;	struct mss_cmd *cmd;	host = pxa_host->host;	cmd = pxa_host->cmd;	if ((ireg & MMC_I_REG_END_CMD_RES) 			&& (!(mask & MMC_I_MASK_END_CMD_RES))) {		pxa_host_disable_int(pxa_host, 				MMC_I_MASK_END_CMD_RES | MMC_I_MASK_RES_ERR);		if (ireg & MMC_I_REG_RES_ERR) {			pxa_host_set_error(cmd, stat);			pxa_host->llreq->done(pxa_host->llreq);			return 1;	  	}	  	pxa_host_get_response(pxa_host, cmd);	  			/* DATA_TRAN_DONE is not enabled now */		pxa_host_enable_int(pxa_host, 				MMC_I_MASK_DAT_ERR | MMC_I_MASK_TINT);		return 1;	}	if ((ireg & (MMC_I_REG_DAT_ERR | MMC_I_REG_TINT)) &&		\		(!(mask & (MMC_I_MASK_DAT_ERR | MMC_I_MASK_TINT)))) {		stat = readl(pxa_host->base + MMC_STAT);		pxa_host_disable_int(pxa_host,			MMC_I_MASK_DATA_TRAN_DONE |		\			MMC_I_MASK_DAT_ERR | MMC_I_MASK_TINT);		pxa_host_set_error(cmd, stat);		/* dbg("DATA/TIMEOUT error.  I_REG: 0x%x, STAT: 0x%x, 		I_MASK: 0x%x. prepare to cmd_complete", 		readl(pxa_host->base + MMC_I_REG), 		readl(pxa_host->base + MMC_STAT),		readl(pxa_host->base + MMC_I_MASK)); */		pxa_host->llreq->done(pxa_host->llreq);	}	/* wait for DMA interrupt, DATA READ done	 * once DATA_TRAN_DONE interrupt occurred	 */	if ((ireg & MMC_I_REG_DATA_TRAN_DONE) &&		\		(!(mask & MMC_I_MASK_DATA_TRAN_DONE))) {		pxa_host_disable_int(pxa_host,		\			MMC_I_MASK_DATA_TRAN_DONE |	\			MMC_I_MASK_DAT_ERR | MMC_I_MASK_TINT);		/* dbg("in DATA_TRAN_DONE, prepare to cmd_complete");*/		pxa_host->llreq->done(pxa_host->llreq); 		return 1;	}		return 1;}/** *  pxa_slot_other_irq *  @card: mss_card_device *  @ireg: value of MMCx_I_REG *  @stat: value of MMCx_STAT *  @mask: value of MMCx_I_MASK * *  slot INT routine for commands other than R1B, write and read commands */static int pxa_host_other_irq(struct pxa_mss_host *pxa_host,		u32 ireg, u32 stat, u32 mask){	struct mss_cmd *cmd = pxa_host->cmd;	if ((ireg & MMC_I_REG_RES_ERR) && (!(mask & MMC_I_MASK_RES_ERR))){	    dbg("pxa_host_other_irq:1 branch \n");		pxa_host_disable_int(pxa_host,			MMC_I_MASK_END_CMD_RES | MMC_I_MASK_RES_ERR);		pxa_host_get_response(pxa_host, cmd);		pxa_host_set_error(cmd, stat);		/* dbg("in RES_ERROR, prepare to cmd_complete\n"); */		pxa_host->llreq->done(pxa_host->llreq);		return 1;	} else if((ireg & MMC_I_REG_END_CMD_RES) &&		\			(!(mask & MMC_I_MASK_END_CMD_RES))) {	    dbg("pxa_host_other_irq:2 branch \n");		pxa_host_disable_int(pxa_host,			MMC_I_MASK_END_CMD_RES | MMC_I_MASK_RES_ERR);		pxa_host_get_response(pxa_host, cmd);		pxa_host->llreq->done(pxa_host->llreq);	}		return 1;}/** *  pxa_slot_irq *  @irq: IRQ number *  @devid: pointer to pxa_mss_controller_device *  @regs: interrupt context * *  response interrupt and sdio interrupt handler.  *  devid represent pxa_mss_controller_device because *  interrupt is to pxa_controller */static irqreturn_t pxa_host_irq(int irq, void *devid, struct pt_regs *regs){	struct pxa_mss_host *pxa_host;	struct mss_cmd *cmd;	struct mss_data *data;	struct mss_driver *drv;	struct mss_card *card;	u32 ireg, stat, mask;	pxa_host = (struct pxa_mss_host *)devid;	cmd = pxa_host->cmd;	data = pxa_host->data;	card = pxa_host->host->active_card;	ireg = readl(pxa_host->base + MMC_I_REG);	stat = readl(pxa_host->base + MMC_STAT);	mask = readl(pxa_host->base + MMC_I_MASK);	dbg("host%d irq, I_REG:0x%x, STAT:0x%x, I_MASK:0x%x, CLKRT:0x%x,"			"RESTO:0x%x, RDTO:0x%x\n", 			pxa_host->host->id, ireg, stat, mask, 			readl(pxa_host->base + MMC_CLKRT), 			readl(pxa_host->base + MMC_RESTO),			readl(pxa_host->base + MMC_RDTO));	if (data) {		if (data->flags & MSS_DATA_WRITE) {			pxa_host_write_irq(pxa_host, ireg, stat, mask);		}		if (data->flags & MSS_DATA_READ) {			pxa_host_read_irq(pxa_host, ireg, stat, mask);		}	}	else if ((cmd->rtype == MSS_RESPONSE_R1B) && (!data || !data->sg_len))		pxa_host_r1b_irq(pxa_host, ireg, stat, mask);	else		pxa_host_other_irq(pxa_host, ireg, stat, mask);			/* handle sdio interrupt, wakeup sdio int IRQ handler thread */	if ((ireg & MMC_I_REG_SDIO_INT) && (!(mask & MMC_I_MASK_SDIO_INT))) {		struct pxa_slot *pxa_slot = pxa_host->active_slot->private;		dbg("SDIO interrupt ocurred\n"); 		pxa_host_disable_int(pxa_host, MMC_I_MASK_SDIO_INT);		pxa_host->host->sdio_int = MSS_SDIO_INT_DIS;		if (!pxa_host->active_slot->card || !pxa_host->active_slot->card->dev.driver)			return IRQ_HANDLED;		drv = container_of(pxa_host->active_slot->card->dev.driver, 				struct mss_driver, driver);		INIT_WORK(&pxa_slot->sdio_int, 				(void (*)(void *))drv->sdio_int_handler, 				pxa_host->active_slot->card);		queue_work(pxa_host->sdio_work_queue, &pxa_slot->sdio_int);	}	return IRQ_HANDLED;}/** *  pxa_slot_gpio_irq *  @irq: IRQ number *  @devid: pointer to mss_slot *  @regs: interrupt context * *  hot-plug interrupt handler. devid represent slot *  because hot-plug is slot-specific.  */static irqreturn_t pxa_slot_gpio_irq(int irq, void *devid, struct pt_regs *regs){	struct mss_slot *slot = (struct mss_slot *)devid;	struct pxa_slot *pxa_slot = slot->private;	struct pxa_mss_host *pxa_host = slot->host->private;	dbg("Slot :%d, inttrupt", slot->id);	queue_delayed_work(pxa_host->work_queue, &pxa_slot->card_change, 20);	return IRQ_HANDLED;	}#if 0static int pxa_slot_work_thread(void *data){	struct mss_slot *slot = data;	struct pxa_slot *pxa_slot = slot->private;	DECLARE_WAITQUEUE(wait, current);		current->flags |= PF_MEMALLOC;	daemonize("pxaslot%d.%d", slot->host->id, slot->id);	complete(&pxa_slot->thread_complete);		down(&pxa_slot->thread_sem);	add_wait_queue(&pxa_slot->thread_wq, &wait);	do {		try_to_freeze();		if (pxa_slot->flags & PXA_SLOT_SCAN) {			pxa_slot->flags &= ~PXA_SLOT_SCAN;			mss_scan_slot(slot);		}		set_current_state(TASK_INTERRUPTIBLE);		if (pxa_slot->flags & PXA_SLOT_EXIT)			break;		up(&pxa_slot->thread_sem);		schedule();		down(&pxa_slot->thread_sem);		set_current_state(TASK_RUNNING);	} while(1);	remove_wait_queue(&pxa_slot->thread_wq, &wait);	up(&pxa_slot->thread_sem);	complete_and_exit(&pxa_slot->thread_complete, 0);}#endifvoid pxa_slot_card_change(struct mss_slot *slot){	/* struct pxa_mss_host *pxa_host = slot->host->private; */	struct mss_card *card = slot->card;	while (card && card->state == MSS_CARD_SUSPENDED)		schedule_timeout(20);	/*     if (pxa_host->suspend) {	       set_current_state(TASK_INTERRUPTIBLE);	       add_wait_queue(&pxa_host->suspend_wq, &wait);	       schedule();	       set_current_state(TASK_RUNNING);	       }*/	mss_scan_slot(slot);}/* init slot, request IRQ for slot, register mss_slot to core, initialize card  * if inserted  */static int pxa_slot_init(struct pxa_mss_host *pxa_host, int slotid){	struct mss_slot *slot;	struct pxa_slot *pxa_slot;

⌨️ 快捷键说明

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