forked from mirrors/linux
		
	mmc: tmio: Provide separate interrupt handlers
Provide separate interrupt handlers which may be used by platforms where SDHI has three interrupt sources. This patch also removes the commented-out handling of CRC and other errors. Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Acked-by: Magnus Damm <magnus.damm@gmail.com> Signed-off-by: Simon Horman <horms@verge.net.au> Signed-off-by: Chris Ball <cjb@laptop.org>
This commit is contained in:
		
							parent
							
								
									54680fe7f6
								
							
						
					
					
						commit
						7729c7a232
					
				
					 2 changed files with 87 additions and 49 deletions
				
			
		|  | @ -97,6 +97,9 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host); | |||
| void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i); | ||||
| void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i); | ||||
| irqreturn_t tmio_mmc_irq(int irq, void *devid); | ||||
| irqreturn_t tmio_mmc_sdcard_irq(int irq, void *devid); | ||||
| irqreturn_t tmio_mmc_card_detect_irq(int irq, void *devid); | ||||
| irqreturn_t tmio_mmc_sdio_irq(int irq, void *devid); | ||||
| 
 | ||||
| static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg, | ||||
| 					 unsigned long *flags) | ||||
|  |  | |||
|  | @ -545,44 +545,20 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host, | |||
| 	spin_unlock(&host->lock); | ||||
| } | ||||
| 
 | ||||
| irqreturn_t tmio_mmc_irq(int irq, void *devid) | ||||
| static void tmio_mmc_card_irq_status(struct tmio_mmc_host *host, | ||||
| 				       int *ireg, int *status) | ||||
| { | ||||
| 	*status = sd_ctrl_read32(host, CTL_STATUS); | ||||
| 	*ireg = *status & TMIO_MASK_IRQ & ~host->sdcard_irq_mask; | ||||
| 
 | ||||
| 	pr_debug_status(*status); | ||||
| 	pr_debug_status(*ireg); | ||||
| } | ||||
| 
 | ||||
| static bool __tmio_mmc_card_detect_irq(struct tmio_mmc_host *host, | ||||
| 				      int ireg, int status) | ||||
| { | ||||
| 	struct tmio_mmc_host *host = devid; | ||||
| 	struct mmc_host *mmc = host->mmc; | ||||
| 	struct tmio_mmc_data *pdata = host->pdata; | ||||
| 	unsigned int ireg, status; | ||||
| 	unsigned int sdio_ireg, sdio_status; | ||||
| 
 | ||||
| 	pr_debug("MMC IRQ begin\n"); | ||||
| 
 | ||||
| 	status = sd_ctrl_read32(host, CTL_STATUS); | ||||
| 	ireg = status & TMIO_MASK_IRQ & ~host->sdcard_irq_mask; | ||||
| 
 | ||||
| 	sdio_ireg = 0; | ||||
| 	if (!ireg && pdata->flags & TMIO_MMC_SDIO_IRQ) { | ||||
| 		sdio_status = sd_ctrl_read16(host, CTL_SDIO_STATUS); | ||||
| 		sdio_ireg = sdio_status & TMIO_SDIO_MASK_ALL & | ||||
| 				~host->sdio_irq_mask; | ||||
| 
 | ||||
| 		sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status & ~TMIO_SDIO_MASK_ALL); | ||||
| 
 | ||||
| 		if (sdio_ireg && !host->sdio_irq_enabled) { | ||||
| 			pr_warning("tmio_mmc: Spurious SDIO IRQ, disabling! 0x%04x 0x%04x 0x%04x\n", | ||||
| 				   sdio_status, host->sdio_irq_mask, sdio_ireg); | ||||
| 			tmio_mmc_enable_sdio_irq(mmc, 0); | ||||
| 			goto out; | ||||
| 		} | ||||
| 
 | ||||
| 		if (mmc->caps & MMC_CAP_SDIO_IRQ && | ||||
| 			sdio_ireg & TMIO_SDIO_STAT_IOIRQ) | ||||
| 			mmc_signal_sdio_irq(mmc); | ||||
| 
 | ||||
| 		if (sdio_ireg) | ||||
| 			goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	pr_debug_status(status); | ||||
| 	pr_debug_status(ireg); | ||||
| 
 | ||||
| 	/* Card insert / remove attempts */ | ||||
| 	if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) { | ||||
|  | @ -592,43 +568,102 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid) | |||
| 		     ((ireg & TMIO_STAT_CARD_INSERT) && !mmc->card)) && | ||||
| 		    !work_pending(&mmc->detect.work)) | ||||
| 			mmc_detect_change(host->mmc, msecs_to_jiffies(100)); | ||||
| 		goto out; | ||||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
| 	/* CRC and other errors */ | ||||
| /*	if (ireg & TMIO_STAT_ERR_IRQ)
 | ||||
|  *		handled |= tmio_error_irq(host, irq, stat); | ||||
|  */ | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| irqreturn_t tmio_mmc_card_detect_irq(int irq, void *devid) | ||||
| { | ||||
| 	unsigned int ireg, status; | ||||
| 	struct tmio_mmc_host *host = devid; | ||||
| 
 | ||||
| 	tmio_mmc_card_irq_status(host, &ireg, &status); | ||||
| 	__tmio_mmc_card_detect_irq(host, ireg, status); | ||||
| 
 | ||||
| 	return IRQ_HANDLED; | ||||
| } | ||||
| EXPORT_SYMBOL(tmio_mmc_card_detect_irq); | ||||
| 
 | ||||
| static bool __tmio_mmc_sdcard_irq(struct tmio_mmc_host *host, | ||||
| 				 int ireg, int status) | ||||
| { | ||||
| 	/* Command completion */ | ||||
| 	if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) { | ||||
| 		tmio_mmc_ack_mmc_irqs(host, | ||||
| 			     TMIO_STAT_CMDRESPEND | | ||||
| 			     TMIO_STAT_CMDTIMEOUT); | ||||
| 		tmio_mmc_cmd_irq(host, status); | ||||
| 		goto out; | ||||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Data transfer */ | ||||
| 	if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) { | ||||
| 		tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ); | ||||
| 		tmio_mmc_pio_irq(host); | ||||
| 		goto out; | ||||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Data transfer completion */ | ||||
| 	if (ireg & TMIO_STAT_DATAEND) { | ||||
| 		tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND); | ||||
| 		tmio_mmc_data_irq(host); | ||||
| 		goto out; | ||||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
| 	pr_warning("tmio_mmc: Spurious irq, disabling! " | ||||
| 		"0x%08x 0x%08x 0x%08x\n", status, host->sdcard_irq_mask, ireg); | ||||
| 	pr_debug_status(status); | ||||
| 	tmio_mmc_disable_mmc_irqs(host, status & ~host->sdcard_irq_mask); | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| irqreturn_t tmio_mmc_sdcard_irq(int irq, void *devid) | ||||
| { | ||||
| 	unsigned int ireg, status; | ||||
| 	struct tmio_mmc_host *host = devid; | ||||
| 
 | ||||
| 	tmio_mmc_card_irq_status(host, &ireg, &status); | ||||
| 	__tmio_mmc_sdcard_irq(host, ireg, status); | ||||
| 
 | ||||
| 	return IRQ_HANDLED; | ||||
| } | ||||
| EXPORT_SYMBOL(tmio_mmc_sdcard_irq); | ||||
| 
 | ||||
| irqreturn_t tmio_mmc_sdio_irq(int irq, void *devid) | ||||
| { | ||||
| 	struct tmio_mmc_host *host = devid; | ||||
| 	struct mmc_host *mmc = host->mmc; | ||||
| 	struct tmio_mmc_data *pdata = host->pdata; | ||||
| 	unsigned int ireg, status; | ||||
| 
 | ||||
| 	if (!(pdata->flags & TMIO_MMC_SDIO_IRQ)) | ||||
| 		return IRQ_HANDLED; | ||||
| 
 | ||||
| 	status = sd_ctrl_read16(host, CTL_SDIO_STATUS); | ||||
| 	ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdcard_irq_mask; | ||||
| 
 | ||||
| 	sd_ctrl_write16(host, CTL_SDIO_STATUS, status & ~TMIO_SDIO_MASK_ALL); | ||||
| 
 | ||||
| 	if (mmc->caps & MMC_CAP_SDIO_IRQ && ireg & TMIO_SDIO_STAT_IOIRQ) | ||||
| 		mmc_signal_sdio_irq(mmc); | ||||
| 
 | ||||
| 	return IRQ_HANDLED; | ||||
| } | ||||
| EXPORT_SYMBOL(tmio_mmc_sdio_irq); | ||||
| 
 | ||||
| irqreturn_t tmio_mmc_irq(int irq, void *devid) | ||||
| { | ||||
| 	struct tmio_mmc_host *host = devid; | ||||
| 	unsigned int ireg, status; | ||||
| 
 | ||||
| 	pr_debug("MMC IRQ begin\n"); | ||||
| 
 | ||||
| 	tmio_mmc_card_irq_status(host, &ireg, &status); | ||||
| 	if (__tmio_mmc_card_detect_irq(host, ireg, status)) | ||||
| 		return IRQ_HANDLED; | ||||
| 	if (__tmio_mmc_sdcard_irq(host, ireg, status)) | ||||
| 		return IRQ_HANDLED; | ||||
| 
 | ||||
| 	tmio_mmc_sdio_irq(irq, devid); | ||||
| 
 | ||||
| out: | ||||
| 	return IRQ_HANDLED; | ||||
| } | ||||
| EXPORT_SYMBOL(tmio_mmc_irq); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Simon Horman
						Simon Horman