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

📄 full-h1940-2.6.21.patch

📁 linux2.6.21的h1940patch
💻 PATCH
📖 第 1 页 / 共 5 页
字号:
+				host->pio_words, host->pio_ptr);++		}++		if (fifo > host->pio_words)+			fifo = host->pio_words;++		host->pio_words-= fifo;+		host->pio_count+= fifo;++		while(fifo--) {+			writel(*(host->pio_ptr++), to_ptr);+		}+	}++	enable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);+}++static void pio_tasklet(unsigned long data)+{+	struct s3cmci_host *host = (struct s3cmci_host *) data;+++	if (host->pio_active == XFER_WRITE)+		do_pio_write(host);++	if (host->pio_active == XFER_READ)+		do_pio_read(host);++	if (host->complete_what == COMPLETION_FINALIZE) {+		clear_imask(host);+		if (host->pio_active != XFER_NONE) {+			dbg(host, dbg_err, "unfinished %s "+				"- pio_count:[%u] pio_words:[%u]\n",+				(host->pio_active == XFER_READ)?"read":"write",+				host->pio_count, host->pio_words);++			host->mrq->data->error = MMC_ERR_DMA;+		}++		disable_irq(host->irq);+		finalize_request(host);+	}+}++/*+ * ISR for SDI Interface IRQ+ * Communication between driver and ISR works as follows:+ *   host->mrq 			points to current request+ *   host->complete_what	tells the ISR when the request is considered done+ *     COMPLETION_CMDSENT	  when the command was sent+ *     COMPLETION_RSPFIN          when a response was received+ *     COMPLETION_XFERFINISH	  when the data transfer is finished+ *     COMPLETION_XFERFINISH_RSPFIN both of the above.+ *   host->complete_request	is the completion-object the driver waits for+ *+ * 1) Driver sets up host->mrq and host->complete_what+ * 2) Driver prepares the transfer+ * 3) Driver enables interrupts+ * 4) Driver starts transfer+ * 5) Driver waits for host->complete_rquest+ * 6) ISR checks for request status (errors and success)+ * 6) ISR sets host->mrq->cmd->error and host->mrq->data->error+ * 7) ISR completes host->complete_request+ * 8) ISR disables interrupts+ * 9) Driver wakes up and takes care of the request+ *+ * Note: "->error"-fields are expected to be set to 0 before the request+ *       was issued by mmc.c - therefore they are only set, when an error+ *       contition comes up+ */++static irqreturn_t s3cmci_irq(int irq, void *dev_id)+{+	struct s3cmci_host *host;+	struct mmc_command *cmd;+	u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt, mci_imsk;+	u32 mci_cclear, mci_dclear;+	unsigned long iflags;++	host = (struct s3cmci_host *)dev_id;++	spin_lock_irqsave(&host->complete_lock, iflags);++	mci_csta 	= readl(host->base + S3C2410_SDICMDSTAT);+	mci_dsta 	= readl(host->base + S3C2410_SDIDSTA);+	mci_dcnt 	= readl(host->base + S3C2410_SDIDCNT);+	mci_fsta 	= readl(host->base + S3C2410_SDIFSTA);+	mci_imsk	= readl(host->base + host->sdiimsk);+	mci_cclear	= 0;+	mci_dclear	= 0;++	if ((host->complete_what == COMPLETION_NONE) ||+			(host->complete_what == COMPLETION_FINALIZE)) {+		host->status = "nothing to complete";+		clear_imask(host);+		goto irq_out;+	}++	if (!host->mrq) {+		host->status = "no active mrq";+		clear_imask(host);+		goto irq_out;+	}++	cmd = host->cmd_is_stop?host->mrq->stop:host->mrq->cmd;++	if (!cmd) {+		host->status = "no active cmd";+		clear_imask(host);+		goto irq_out;+	}++	if (!host->dodma) {+		if ((host->pio_active == XFER_WRITE) &&+				(mci_fsta & S3C2410_SDIFSTA_TFDET)) {++			disable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);+			tasklet_schedule(&host->pio_tasklet);+			host->status = "pio tx";+		}++		if ((host->pio_active == XFER_READ) &&+				(mci_fsta & S3C2410_SDIFSTA_RFDET)) {++			disable_imask(host,+				S3C2410_SDIIMSK_RXFIFOHALF | S3C2410_SDIIMSK_RXFIFOLAST);++			tasklet_schedule(&host->pio_tasklet);+			host->status = "pio rx";+		}+	}++	if (mci_csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) {+		cmd->error = MMC_ERR_TIMEOUT;+		host->status = "error: command timeout";+		goto fail_transfer;+	}++	if (mci_csta & S3C2410_SDICMDSTAT_CMDSENT) {+		if (host->complete_what == COMPLETION_CMDSENT) {+			host->status = "ok: command sent";+			goto close_transfer;+		}++		mci_cclear |= S3C2410_SDICMDSTAT_CMDSENT;+	}++	if (mci_csta & S3C2410_SDICMDSTAT_CRCFAIL) {+		if (cmd->flags & MMC_RSP_CRC) {+			if (host->is2440 || !(cmd->flags & MMC_RSP_136)) {+				cmd->error = MMC_ERR_BADCRC;+				host->status = "error: bad command crc";+				goto fail_transfer;+			}+		}+		mci_cclear |= S3C2410_SDICMDSTAT_CRCFAIL;+	}++	if (mci_csta & S3C2410_SDICMDSTAT_RSPFIN) {+		if (host->complete_what == COMPLETION_RSPFIN) {+			host->status = "ok: command response received";+			goto close_transfer;+		}++		if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN)+			host->complete_what = COMPLETION_XFERFINISH;++		mci_cclear |= S3C2410_SDICMDSTAT_RSPFIN;+	}++	/* errors handled after this point are only relevant+	   when a data transfer is in progress */++	if (!cmd->data)+		goto clear_status_bits;++	/* Check for FIFO failure */+	if (host->is2440) {+		if (mci_fsta & S3C2440_SDIFSTA_FIFOFAIL) {+			host->mrq->data->error = MMC_ERR_FIFO;+			host->status = "error: 2440 fifo failure";+			goto fail_transfer;+		}+	} else {+		if (mci_dsta & S3C2410_SDIDSTA_FIFOFAIL) {+			cmd->data->error = MMC_ERR_FIFO;+			host->status = "error:  fifo failure";+			goto fail_transfer;+		}+	}++	if (mci_dsta & S3C2410_SDIDSTA_RXCRCFAIL) {+		cmd->data->error = MMC_ERR_BADCRC;+		host->status = "error: bad data crc (outgoing)";+		goto fail_transfer;+	}++	if (mci_dsta & S3C2410_SDIDSTA_CRCFAIL) {+		cmd->data->error = MMC_ERR_BADCRC;+		host->status = "error: bad data crc (incoming)";+		goto fail_transfer;+	}++	if (mci_dsta & S3C2410_SDIDSTA_DATATIMEOUT) {+		cmd->data->error = MMC_ERR_TIMEOUT;+		host->status = "error: data timeout";+		goto fail_transfer;+	}++	if (mci_dsta & S3C2410_SDIDSTA_XFERFINISH) {+		if (host->complete_what == COMPLETION_XFERFINISH) {+			host->status = "ok: data transfer completed";+			goto close_transfer;+		}++		if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN) {+			host->complete_what = COMPLETION_RSPFIN;+		}++		mci_dclear |= S3C2410_SDIDSTA_XFERFINISH;+	}++clear_status_bits:+	writel(mci_cclear, host->base + S3C2410_SDICMDSTAT);+	writel(mci_dclear, host->base + S3C2410_SDIDSTA);++	goto irq_out;++fail_transfer:+	host->pio_active = XFER_NONE;++close_transfer:+	host->complete_what = COMPLETION_FINALIZE;++	clear_imask(host);+	tasklet_schedule(&host->pio_tasklet);++	goto irq_out;++irq_out:+	dbg(host, dbg_irq, "csta:0x%08x dsta:0x%08x "+			   "fsta:0x%08x dcnt:0x%08x status:%s.\n",+				mci_csta, mci_dsta, mci_fsta,+				mci_dcnt, host->status);++	spin_unlock_irqrestore(&host->complete_lock, iflags);+	return IRQ_HANDLED;++}++/*+ * ISR for the CardDetect Pin+*/++static irqreturn_t s3cmci_irq_cd(int irq, void *dev_id)+{+	struct s3cmci_host *host = (struct s3cmci_host *)dev_id;++	dbg(host, dbg_irq, "card detect\n");++	mmc_detect_change(host->mmc, 500);++	return IRQ_HANDLED;+}++void s3cmci_dma_done_callback(struct s3c2410_dma_chan *dma_ch, void *buf_id,+	int size, enum s3c2410_dma_buffresult result)+{+	unsigned long iflags;+	u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt;+	struct s3cmci_host *host = (struct s3cmci_host *)buf_id;++	mci_csta 	= readl(host->base + S3C2410_SDICMDSTAT);+	mci_dsta 	= readl(host->base + S3C2410_SDIDSTA);+	mci_fsta 	= readl(host->base + S3C2410_SDIFSTA);+	mci_dcnt 	= readl(host->base + S3C2410_SDIDCNT);++	if ((!host->mrq) || (!host->mrq) || (!host->mrq->data))+		return;++	if (!host->dmatogo)+		return;++	spin_lock_irqsave(&host->complete_lock, iflags);++	if (result != S3C2410_RES_OK) {+		dbg(host, dbg_fail, "DMA FAILED: csta=0x%08x dsta=0x%08x "+			"fsta=0x%08x dcnt:0x%08x result:0x%08x toGo:%u\n",+			mci_csta, mci_dsta, mci_fsta,+			mci_dcnt, result, host->dmatogo);++		goto fail_request;+	}++	host->dmatogo--;+	if (host->dmatogo) {+		dbg(host, dbg_dma, "DMA DONE  Size:%i DSTA:[%08x] "+			"DCNT:[%08x] toGo:%u\n",+			size, mci_dsta, mci_dcnt, host->dmatogo);++		goto out;+	}++	dbg(host, dbg_dma, "DMA FINISHED Size:%i DSTA:%08x DCNT:%08x\n",+		size, mci_dsta, mci_dcnt);++	host->complete_what = COMPLETION_FINALIZE;++out:+	tasklet_schedule(&host->pio_tasklet);+	spin_unlock_irqrestore(&host->complete_lock, iflags);+	return;+++fail_request:+	host->mrq->data->error = MMC_ERR_DMA;+	host->complete_what = COMPLETION_FINALIZE;+	writel(0, host->base + host->sdiimsk);+	goto out;++}++static void finalize_request(struct s3cmci_host *host)+{+	struct mmc_request *mrq = host->mrq;+	struct mmc_command *cmd = host->cmd_is_stop?mrq->stop:mrq->cmd;+	int debug_as_failure = 0;++	if (host->complete_what != COMPLETION_FINALIZE)+		return;++	if (!mrq)+		return;++	if (cmd->data && (cmd->error == MMC_ERR_NONE) &&+		  (cmd->data->error == MMC_ERR_NONE)) {++		if (host->dodma && (!host->dma_complete)) {+			dbg(host, dbg_dma, "DMA Missing!\n");+			return;+		}+	}++	// Read response+	cmd->resp[0] = readl(host->base + S3C2410_SDIRSP0);+	cmd->resp[1] = readl(host->base + S3C2410_SDIRSP1);+	cmd->resp[2] = readl(host->base + S3C2410_SDIRSP2);+	cmd->resp[3] = readl(host->base + S3C2410_SDIRSP3);++	// reset clock speed, as it could still be set low for+	writel(host->prescaler, host->base + S3C2410_SDIPRE);++	if (cmd->error)+		debug_as_failure = 1;++	if (cmd->data && cmd->data->error)+		debug_as_failure = 1;++	//if(cmd->flags & MMC_RSP_MAYFAIL) debug_as_failure = 0;++#ifdef CONFIG_MMC_DEBUG+	dbg_dumpcmd(host, cmd, debug_as_failure);+#endif+	//Cleanup controller+	writel(0, host->base + S3C2410_SDICMDARG);+	writel(S3C2410_SDIDCON_STOP, host->base + S3C2410_SDIDCON);+	writel(0, host->base + S3C2410_SDICMDCON);+	writel(0, host->base + host->sdiimsk);++	if (cmd->data && cmd->error)+		cmd->data->error = cmd->error;++	if (cmd->data && cmd->data->stop && (!host->cmd_is_stop)) {+		host->cmd_is_stop = 1;+		s3cmci_send_request(host->mmc);+		return;+	}++	// If we have no data transfer we are finished here+	if (!mrq->data)+		goto request_done;++	// Calulate the amout of bytes transfer, but only if there was+	// no error+	if (mrq->data->error == MMC_ERR_NONE) {+		mrq->data->bytes_xfered =+			(mrq->data->blocks * mrq->data->blksz);+	} else {+		mrq->data->bytes_xfered = 0;+	}++	// If we had an error while transfering data we flush the+	// DMA channel and the fifo to clear out any garbage+	if (mrq->data->error != MMC_ERR_NONE) {+		if (host->dodma)+			s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);++		if (host->is2440) {+			//Clear failure register and reset fifo+			writel(S3C2440_SDIFSTA_FIFORESET |+			       S3C2440_SDIFSTA_FIFOFAIL,+			       host->base + S3C2410_SDIFSTA);+		} else {+			u32 mci_con;++			//reset fifo+			mci_con = readl(host->base + S3C2410_SDICON);+			mci_con|= S3C2410_SDICON_FIFORESET;++			writel(mci_con, host->base + S3C2410_SDICON);+		}+	}++request_done:+	host->complete_what = COMPLETION_NONE;+	host->mrq = NULL;+	mmc_request_done(host->mmc, mrq);+}+++void s3cmci_dma_setup(struct s3cmci_host *host, enum s3c2410_dmasrc source)+{+	static int setup_ok = 0;+	static enum s3c2410_dmasrc last_source = -1;++	if (last_source == source)+		return;++	last_source = source;++	s3c2410_dma_devconfig(host->dma, source, 3,+		host->mem->start + host->sdidata);++	if (!setup_ok) {+		s3c2410_dma_config(host->dma, 4,+			(S3C2410_DCON_HWTRIG | S3C2410_DCON_CH0_SDI));+		s3c2410_dma_set_buffdone_fn(host->dma, s3cmci_dma_done_callback);+		s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);+		setup_ok = 1;+	}+}++static void s3cmci_send_command(struct s3cmci_host *host,+					struct mmc_command *cmd)+{+	u32 ccon, imsk;++	imsk  = S3C2410_SDIIMSK_CRCSTATUS | S3C2410_SDIIMSK_CMDTIMEOUT |+		S3C2410_SDIIMSK_RESPONSEND | S3C2410_SDIIMSK_CMDSENT |+		S3C2410_SDIIMSK_RESPONSECRC;++	enable_imask(host, imsk);++	if (cmd->data) {+		host->complete_what = COMPLETION_XFERFINISH_RSPFIN;+	} else if (cmd->flags & MMC_RSP_PRESENT) {+		host->complete_what = COMPLETION_RSPFIN;+	} else {+		host->complete_what = COMPLETION_CMDSENT;+	}++	writel(cmd->arg, host->base + S3C2410_SDICMDARG);++	ccon = cmd->opcode & S3C2410_SDICMDCON_INDEX;+	ccon|= S3C2410_SDICMDCON_SENDERHOST | S3C2410_SDICMDCON_CMDSTART;++	if (cmd->flags & MMC_RSP_PRESENT)+		ccon |= S3C2410_SDICMDCON_WAITRSP;++	if (cmd->flags & MMC_RSP_136)+		ccon|= S3C2410_SDICMDCON_LONGRSP;++	writel(ccon, host->base + S3C2410_SDICMDCON);+}++static int s3cmci_setup_data(struct s3cmci_host *host, struct mmc_data *data)+{+	u32 dcon, imsk, stoptries=3;++	/* write DCON register */++	if (!data) {+		writel(0, host->base + S3C2410_SDIDCON);+		return 0;+	}++	while(readl(host->base + S3C2410_SDIDSTA) &+		(S3C2410_SDIDSTA_TXDATAON | S3C2410_SDIDSTA_RXDATAON)) {++		dbg(host, dbg_err,+			"mci_setup_data() transfer stillin progress.\n");++		writel(S3C2410_SDIDCON_STOP, host->base + S3C2410_SDIDCON);+		s3cmci_reset(host);+

⌨️ 快捷键说明

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