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

📄 mmc.patch

📁 patches for linux-2.6.
💻 PATCH
📖 第 1 页 / 共 3 页
字号:
+		 +		tasklet_schedule(&host->data_task);+	}+}++static void au1xmmc_receive_pio(struct au1xmmc_host *host) {++	struct mmc_data *data = 0;+	int sg_len = 0, max = 0, count = 0;+	unsigned char *sg_ptr = 0;+	u32 status = 0;++	data = host->mrq->data;++	if (!(host->flags & HOST_F_RECV)) +		return;++	max = host->pio.len;++	if (host->pio.index < host->dma.len) {+		sg_ptr = phys_to_virt(sg_dma_address(&data->sg[host->pio.index]));+		sg_ptr += host->pio.offset;+			+		/* This is the space left inside the buffer */+		sg_len = sg_dma_len(&data->sg[host->pio.index]) - host->pio.offset;++		/* Check to if we need less then the size of the sg_buffer */+		if (sg_len < max) max = sg_len;+	}++	if (max > AU1XMMC_MAX_TRANSFER) +		max = AU1XMMC_MAX_TRANSFER;++	for(count = 0; count < max; count++ ) { +		u32 val;+		status = au_readl(HOST_STATUS(host));++		if (!(status & SD_STATUS_NE))+			break;++		if (status & SD_STATUS_RC) {+			DEBUG("RX CRC Error [%d + %d].\n", host->id, +					host->pio.len, count);+			break;+		}++		if (status & SD_STATUS_RO) {+			DEBUG("RX Overrun [%d + %d]\n", host->id, +					host->pio.len, count);+			break;+		}+		else if (status & SD_STATUS_RU) {+			DEBUG("RX Underrun [%d + %d]\n", host->id, +					host->pio.len,	count);+			break;+		}++		val = au_readl(HOST_RXPORT(host)); ++		if (sg_ptr) +			*sg_ptr++ = (unsigned char) (val & 0xFF);+	}++	host->pio.len -= count;+	host->pio.offset += count;++	if (sg_len && count == sg_len) {+		host->pio.index++;+		host->pio.offset = 0;+	}++	if (host->pio.len == 0) {+		//IRQ_OFF(host, SD_CONFIG_RA | SD_CONFIG_RF);+		IRQ_OFF(host, SD_CONFIG_NE);++		if (host->flags & HOST_F_STOP)+			SEND_STOP(host);++		tasklet_schedule(&host->data_task);+	}+}++/* static void au1xmmc_cmd_complete+   This is called when a command has been completed - grab the response+   and check for errors.  Then start the data transfer if it is indicated.+*/++static void au1xmmc_cmd_complete(struct au1xmmc_host *host, u32 status) {++	struct mmc_request *mrq = host->mrq;+	struct mmc_command *cmd;+	int trans;++	if (!host->mrq) +		return;++	cmd = mrq->cmd;+	cmd->error = MMC_ERR_NONE;++	if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT) {++		/* Techincally, we should be getting all 48 bits of the response+		 * (SD_RESP1 + SD_RESP2), but because our response omits the CRC,+		 * our data ends up being shifted 8 bits to the right.  In this case,+		 * that means that the OSR data starts at bit 31, so we can just+		 * read RESP0 and return that +		 */++		cmd->resp[0] = au_readl(host->iobase + SD_RESP0);+	}+	else if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_LONG) {+		u32 r[4];+		int i;++		r[0] = au_readl(host->iobase + SD_RESP3);+		r[1] = au_readl(host->iobase + SD_RESP2);+		r[2] = au_readl(host->iobase + SD_RESP1);+		r[3] = au_readl(host->iobase + SD_RESP0);+		+		/* The CRC is omitted from the response, so really we only got+		 * 120 bytes, but the engine expects 128 bits, so we have to shift+		 * things up +		 */+		+		for(i = 0; i < 4; i++) {+			cmd->resp[i] = (r[i] & 0x00FFFFFF) << 8;+			if (i != 3) cmd->resp[i] |= (r[i + 1] & 0xFF000000) >> 24;+		}+	}++        /* Figure out errors */++	if (status & (SD_STATUS_SC | SD_STATUS_WC | SD_STATUS_RC))+		cmd->error = MMC_ERR_BADCRC;++	trans = host->flags & (HOST_F_XMIT | HOST_F_RECV);++	if (!trans || cmd->error != MMC_ERR_NONE) {++		IRQ_OFF(host, SD_CONFIG_TH | SD_CONFIG_RA|SD_CONFIG_RF);+		tasklet_schedule(&host->finish_task);+		return;+	}++	host->status = HOST_S_DATA;++	if (host->flags & HOST_F_DMA) {+		u32 channel = DMA_CHANNEL(host);++		/* Start the DMA as soon as the buffer gets something in it */++		if (host->flags & HOST_F_RECV) {+			u32 mask = SD_STATUS_DB | SD_STATUS_NE;++			while((status & mask) != mask) +				status = au_readl(HOST_STATUS(host));+		}++		au1xxx_dbdma_start(channel);+	}+}++static void au1xmmc_set_clock(struct au1xmmc_host *host, int rate) {++	unsigned int pbus = get_au1x00_speed();+	unsigned int divisor;+	u32 config;++	/* From databook:+	   divisor = ((((cpuclock / sbus_divisor) / 2) / mmcclock) / 2) - 1+	*/++	pbus /= ((au_readl(SYS_POWERCTRL) & 0x3) + 2);+	pbus /= 2;++	divisor = ((pbus / rate) / 2) - 1;++	config = au_readl(HOST_CONFIG(host));++	config &= ~(SD_CONFIG_DIV);+	config |= (divisor & SD_CONFIG_DIV) | SD_CONFIG_DE;++	au_writel(config, HOST_CONFIG(host));+	au_sync();+}++static int au1xmmc_prepare_data(struct au1xmmc_host *host, +				struct mmc_data *data) {++	int datalen = data->blocks * (1 << data->blksz_bits);++	if (dma != 0) +		host->flags |= HOST_F_DMA;++	if (data->flags & MMC_DATA_READ)+		host->flags |= HOST_F_RECV;+	else+		host->flags |= HOST_F_XMIT;++	if (host->mrq->stop) +		host->flags |= HOST_F_STOP;+		+	host->dma.dir = DMA_BIDIRECTIONAL;++	host->dma.len = dma_map_sg(mmc_dev(host->mmc), data->sg,+				   data->sg_len, host->dma.dir);++	if (host->dma.len == 0)+		return MMC_ERR_TIMEOUT;++	au_writel((1 << data->blksz_bits) - 1, HOST_BLKSIZE(host));	++	if (host->flags & HOST_F_DMA) {+		int i;+		u32 channel = DMA_CHANNEL(host);++		au1xxx_dbdma_stop(channel);++		for(i = 0; i < host->dma.len; i++) {+			u32 ret = 0, flags = DDMA_FLAGS_NOIE;+			u32 sg_addr = sg_dma_address(&data->sg[i]);+			int sg_len = sg_dma_len(&data->sg[i]);+			int len = (datalen > sg_len) ? sg_len : datalen;++			if (i == host->dma.len - 1)+				flags = DDMA_FLAGS_IE;++    			if (host->flags & HOST_F_XMIT)+      				ret = au1xxx_dbdma_put_source_flags(channel, +								    (void *) phys_to_virt(sg_addr), +								    len, flags);+    			else+      				ret = au1xxx_dbdma_put_dest_flags(channel, +								  (void *) phys_to_virt(sg_addr),+								  len, flags);++    			if (!ret) +				goto dataerr;++			datalen -= len;+		}+	}+	else {+		host->pio.index = 0;+		host->pio.offset = 0;+		host->pio.len = datalen;+		+		if (host->flags & HOST_F_XMIT)+			IRQ_ON(host, SD_CONFIG_TH);+		else +			IRQ_ON(host, SD_CONFIG_NE);+			//IRQ_ON(host, SD_CONFIG_RA|SD_CONFIG_RF);+	}++	return MMC_ERR_NONE;++ dataerr:+	dma_unmap_sg(mmc_dev(host->mmc),data->sg,data->sg_len,host->dma.dir); +	return MMC_ERR_TIMEOUT;+} ++/* static void au1xmmc_request+   This actually starts a command or data transaction+*/++static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq) {++	struct au1xmmc_host *host = mmc_priv(mmc);+	int ret = MMC_ERR_NONE;++	//WARN_ON(irqs_disabled());+	//WARN_ON(host->status != HOST_S_IDLE);++	host->mrq = mrq;+	host->status = HOST_S_CMD;++	bcsr->disk_leds &= ~(1 << 8);++	if (mrq->data) {+		FLUSH_FIFO(host);+		ret = au1xmmc_prepare_data(host, mrq->data);+	}++	if (ret == MMC_ERR_NONE)+		ret = au1xmmc_send_command(host, 0, mrq->cmd);++	if (ret != MMC_ERR_NONE) {+		mrq->cmd->error = ret;+		au1xmmc_finish_request(host);+	}+}++static void au1xmmc_reset_controller(struct au1xmmc_host *host) {++	/* Apply the clock */+	au_writel(SD_ENABLE_CE, HOST_ENABLE(host));+        au_sync_delay(1);++	au_writel(SD_ENABLE_R | SD_ENABLE_CE, HOST_ENABLE(host));+	au_sync_delay(5);++	au_writel(~0, HOST_STATUS(host));+	au_sync();++	au_writel(0, HOST_BLKSIZE(host));+	au_writel(0x001fffff, HOST_TIMEOUT(host));+	au_sync();++	au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));+        au_sync();++	au_writel(SD_CONFIG2_EN | SD_CONFIG2_FF, HOST_CONFIG2(host));+	au_sync_delay(1);++	au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));+	au_sync();++	/* Configure interrupts */+	au_writel(AU1XMMC_INTERRUPTS, HOST_CONFIG(host));+	au_sync();+}+	++static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) {+	struct au1xmmc_host *host = mmc_priv(mmc);++	DEBUG("set_ios (power=%u, clock=%uHz, vdd=%u, mode=%u)\n",+	      host->id, ios->power_mode, ios->clock, ios->vdd, +	      ios->bus_mode);++	if (ios->power_mode == MMC_POWER_OFF) +		au1xmmc_set_power(host, 0);+	else if (ios->power_mode == MMC_POWER_ON) {+		au1xmmc_set_power(host, 1);+	}++	if (ios->clock && ios->clock != host->clock) {+		au1xmmc_set_clock(host, ios->clock);+		host->clock = ios->clock;+	}+}++static void au1xmmc_dma_callback(int irq, void *dev_id, struct pt_regs *regs) {+	struct au1xmmc_host *host = (struct au1xmmc_host *) dev_id;+	u32 status;++	/* Avoid spurious interrupts */++	if (!host->mrq) +		return;++	if (host->flags & HOST_F_STOP) +		SEND_STOP(host);++	tasklet_schedule(&host->data_task);+}++#define STATUS_TIMEOUT (SD_STATUS_RAT | SD_STATUS_DT)+#define STATUS_DATA_IN  (SD_STATUS_NE)+#define STATUS_DATA_OUT (SD_STATUS_TH)++static irqreturn_t au1xmmc_irq(int irq, void *dev_id, struct pt_regs *regs) {+  +	u32 status;+	int i, ret = 0;++	disable_irq(AU1100_SD_IRQ);++	for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {    +		struct au1xmmc_host * host = au1xmmc_hosts[i];+		u32 handled = 1;++		status = au_readl(HOST_STATUS(host));++		if (host->mrq && (status & STATUS_TIMEOUT)) {+			if (status & SD_STATUS_RAT)  +				host->mrq->cmd->error = MMC_ERR_TIMEOUT;+			+			else if (status & SD_STATUS_DT) +				host->mrq->data->error = MMC_ERR_TIMEOUT;+		+			/* In PIO mode, interrupts might still be enabled */+			IRQ_OFF(host, SD_CONFIG_NE | SD_CONFIG_TH);++			//IRQ_OFF(host, SD_CONFIG_TH|SD_CONFIG_RA|SD_CONFIG_RF);+			tasklet_schedule(&host->finish_task);+		}+#if 0+		else if (status & SD_STATUS_DD) {++			/* Sometimes we get a DD before a NE in PIO mode */++			if (!(host->flags & HOST_F_DMA) && +					(status & SD_STATUS_NE))+				au1xmmc_receive_pio(host);+			else {+				au1xmmc_data_complete(host, status);+				//tasklet_schedule(&host->data_task);+			}+		}+#endif+		else if (status & (SD_STATUS_CR)) {+			if (host->status == HOST_S_CMD)+				au1xmmc_cmd_complete(host,status);+		}+		else if (!(host->flags & HOST_F_DMA)) { +			if ((host->flags & HOST_F_XMIT) && +			    (status & STATUS_DATA_OUT))+				au1xmmc_send_pio(host);+			else if ((host->flags & HOST_F_RECV) && +			    (status & STATUS_DATA_IN))+				au1xmmc_receive_pio(host);+		}+		else if (status & 0x203FBC70) {+			DEBUG("Unhandled status %8.8x\n", host->id, status);+			handled = 0;+		}+		+		au_writel(status, HOST_STATUS(host));+		au_sync();++		ret |= handled;+	}++	enable_irq(AU1100_SD_IRQ);+	return ret;+}++static void au1xmmc_poll_event(unsigned long arg) {+	struct au1xmmc_host *host = (struct au1xmmc_host *) arg;++	int card = au1xmmc_card_inserted(host);+        int controller = (host->flags & HOST_F_ACTIVE) ? 1 : 0;++	if (card != controller) {+		host->flags &= ~HOST_F_ACTIVE;+		if (card) host->flags |= HOST_F_ACTIVE;+		mmc_detect_change(host->mmc);+	}++	if (host->mrq != NULL) {+		u32 status = au_readl(HOST_STATUS(host));+		DEBUG("PENDING - %8.8x\n", host->id, status);+	}++	mod_timer(&host->timer, jiffies + AU1XMMC_DETECT_TIMEOUT);

⌨️ 快捷键说明

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