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

📄 atheros_2_0_hcd.patch

📁 openmoko 使用的sdio wifi驱动源码
💻 PATCH
📖 第 1 页 / 共 4 页
字号:
+		       req->BlockCount * req->BlockLen);++		req->DataRemaining = 0;+		status = SDIO_STATUS_SUCCESS;++	} else if (context->complete == S3C24XX_HCD_DATA_WRITE) {+		/* DMA WRITE completion */+		if (context->latest_xfer_size != req->DataRemaining) {+			DBG_PRINT(SDDBG_ERROR, ("Unexpected write xfer size: %d <-> %d\n",+						context->latest_xfer_size, req->DataRemaining));+			status = SDIO_STATUS_BUS_WRITE_ERROR;+		}++		dsta = readl(context->base + S3C2410_SDIDSTA);+		counter = 0;+		while (!(dsta & S3C2410_SDIDSTA_XFERFINISH)) {+			if (counter > 500) {+				printk("write xfer timed out\n");+				status = SDIO_STATUS_BUS_WRITE_ERROR;+				goto out;+			}+			dsta = readl(context->base + S3C2410_SDIDSTA);+			counter++;+			mdelay(1);+		};++		writel(S3C2410_SDIDSTA_XFERFINISH, context->base + S3C2410_SDIDSTA);+		req->DataRemaining = 0;+		status = SDIO_STATUS_SUCCESS;+	}++ out:+	req->Status = status;+}++static void s3c24xx_hcd_pio_complete(struct s3c24xx_hcd_context * context)+{+	u32 fsta, counter;+	u8 *ptr;+	int fifo_count;+	PSDREQUEST req;+	SDIO_STATUS status = SDIO_STATUS_ERROR;++	req = GET_CURRENT_REQUEST(&context->hcd);+	if (req == NULL) {+		DBG_PRINT(SDDBG_ERROR, ("%s(): No current request\n", __FUNCTION__));+		return;+	}++	ptr = req->pDataBuffer;++	if (context->complete == S3C24XX_HCD_DATA_READ) {+		counter = 0;+		DBG_PRINT(SDDBG_TRACE, ("Data read..."));+		do {+			counter++;+			fsta = readl(context->base + S3C2410_SDIFSTA);+			mdelay(1);+			if (counter > 1000) {+				DBG_PRINT(SDDBG_ERROR, ("DATA read timeout\n"));+				status = SDIO_STATUS_BUS_READ_TIMEOUT;+				s3c24xx_dump_regs(context);+				goto out;+			}+		} while(!(fsta & S3C2410_SDIFSTA_RFDET));+		DBG_PRINT(SDDBG_TRACE, ("RX detected\n"));++		while (1) {+			counter = 0;+			fifo_count = (readl(context->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK);+			while (!fifo_count) {+				counter++;+				mdelay(1);+				if (counter > 500) {+					s3c24xx_dump_regs(context);+					DBG_PRINT(SDDBG_ERROR, ("No more bytes in FIFO\n"));+					goto out;+				}+				fifo_count = (readl(context->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK);+			}++			if (fifo_count > req->DataRemaining) {+				DBG_PRINT(SDDBG_ERROR, ("DATA read, fifo_count %d > expected %d\n", fifo_count, req->DataRemaining));+				fifo_count = req->DataRemaining;+			}++			req->DataRemaining -= fifo_count;+			while (fifo_count > 0) {+				if (context->data_size == 4)+					*(ptr) = readl(context->base + S3C2440_SDIDATA);+				else if (context->data_size == 2)+					*(ptr) = readw(context->base + S3C2440_SDIDATA);+				else+					*(ptr) = readb(context->base + S3C2440_SDIDATA);++				ptr += context->data_size;+				fifo_count -= context->data_size;++			}++			if (!req->DataRemaining) {+				/* We poll for xfer finish */+				counter = 0;+				while (!(readl(context->base + S3C2410_SDIDSTA)+						 & S3C2410_SDIDSTA_XFERFINISH)) {+					counter++;+					mdelay(1);+					if (counter > 500) {+						DBG_PRINT(SDDBG_ERROR, ("RX XFERFINISH missing\n"));+						s3c24xx_dump_regs(context);+						break;+					}+				}++				status = SDIO_STATUS_SUCCESS;+				goto out;+			}+		}++	} else if (context->complete == S3C24XX_HCD_DATA_WRITE) {+		counter = 0;+		DBG_PRINT(SDDBG_TRACE, ("Data write..."));+		do {+			counter++;+			fsta = readl(context->base + S3C2410_SDIFSTA);+			mdelay(1);+			if (counter > 1000) {+				DBG_PRINT(SDDBG_ERROR, ("DATA write timeout\n"));+				status = SDIO_STATUS_BUS_WRITE_ERROR;+				goto out;+				break;+			}++		} while(!(fsta & S3C2410_SDIFSTA_TFDET));+		DBG_PRINT(SDDBG_TRACE, ("TX detected\n"));++		while (1) {+			counter = 0;+			fifo_count = 63 - (readl(context->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK);+			while (!fifo_count) {+				counter++;+				mdelay(1);+				if (counter > 500) {+					s3c24xx_dump_regs(context);+					DBG_PRINT(SDDBG_ERROR, ("No more space in FIFO\n"));+					goto out;+				}+				fifo_count = 63 - (readl(context->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK);+			}++			if (fifo_count > req->DataRemaining)+				fifo_count = req->DataRemaining;++				req->DataRemaining -= fifo_count;++				while (fifo_count > 0) {+					if (context->data_size == 4)+						writel(*(ptr), context->base + S3C2440_SDIDATA);+					else if (context->data_size == 2)+						writew(*(ptr), context->base + S3C2440_SDIDATA);+					else+						writeb(*(ptr), context->base + S3C2440_SDIDATA);++					ptr += context->data_size;+					fifo_count -= context->data_size;+				}++				if (!req->DataRemaining) {+					/* We poll for xfer finish */+					counter = 0;+					while (!(readl(context->base + S3C2410_SDIDSTA)+						 & S3C2410_SDIDSTA_XFERFINISH)) {+						counter++;+						mdelay(1);+						if (counter > 500) {+							DBG_PRINT(SDDBG_ERROR, ("RX XFERFINISH missing\n"));+							s3c24xx_dump_regs(context);+							break;+						}+					}++					status = SDIO_STATUS_SUCCESS;+					goto out;+				}+		}++	} else {+		DBG_PRINT(SDDBG_ERROR, ("Wrong context: %d\n", context->complete));+	}++ out:+	req->Status = status;+}++static void s3c24xx_hcd_io_work(struct work_struct *work)+{+	PSDREQUEST req;+	SDIO_STATUS status = SDIO_STATUS_SUCCESS;+	struct s3c24xx_hcd_context * context =+		container_of(work, struct s3c24xx_hcd_context, io_work);++	req = GET_CURRENT_REQUEST(&context->hcd);+	if (req == NULL) {+		DBG_PRINT(SDDBG_ERROR, ("%s(): No current request\n", __FUNCTION__));+		return;+	}++	if (req->Status == SDIO_STATUS_BUS_RESP_TIMEOUT) {+		DBG_PRINT(SDDBG_ERROR, ("### TIMEOUT ###\n"));+		s3c24xx_dump_regs(context);+		goto out;+	}++	if (context->complete == S3C24XX_HCD_NO_RESPONSE &&+	    req->Status == SDIO_STATUS_SUCCESS) {+		DBG_PRINT(SDDBG_TRACE, ("CMD done, Status: %d\n", req->Status));+		printk("CMD done, Status: %d\n", req->Status);+		goto out;+	}++	if ((context->complete == S3C24XX_HCD_RESPONSE_SHORT ||+	     context->complete == S3C24XX_HCD_RESPONSE_LONG ||+	     context->complete == S3C24XX_HCD_DATA_READ ||+	     context->complete == S3C24XX_HCD_DATA_WRITE) &&+	    req->Status == SDIO_STATUS_SUCCESS) {+		u32 resp[4];++		/* We need to copy the response data and send it over */+		resp[0] = readl(context->base + S3C2410_SDIRSP0);+		resp[1] = readl(context->base + S3C2410_SDIRSP1);+		resp[2] = readl(context->base + S3C2410_SDIRSP2);+		resp[3] = readl(context->base + S3C2410_SDIRSP3);++		if (GET_SDREQ_RESP_TYPE(req->Flags) != SDREQ_FLAGS_RESP_R2) {+			DBG_PRINT(SDDBG_TRACE, ("SHORT response: 0x%08x\n", resp[0]));+			memcpy(&req->Response[1], (u8*)resp, 4);+			req->Response[5] = (readl(context->base + S3C2410_SDICMDSTAT) & 0xff);+		} else {+			printk("LONG response: 0x%08x\n", resp[0]);+			DBG_PRINT(SDDBG_TRACE, ("LONG response: 0x%08x\n", resp[0]));+			memcpy(&req->Response[1], (u8*)resp, 16);+			//req->Response[17] = (readl(context->base + S3C2410_SDICMDSTAT) & 0xff);+		}++		/* There is a data stage */+		if (context->complete == S3C24XX_HCD_DATA_READ ||+		    context->complete == S3C24XX_HCD_DATA_WRITE) {+			status = SDIO_CheckResponse(&context->hcd, req,+						    SDHCD_CHECK_DATA_TRANS_OK);++			if (!SDIO_SUCCESS(status)) {+				DBG_PRINT(SDDBG_ERROR,+					  ("Target not ready for data xfer\n"));+				return;+			}++			if (context->dma_en) {+				dma_sync_single(NULL, context->io_buffer_dma,+						req->BlockCount * req->BlockLen, DMA_BIDIRECTIONAL);++				s3c2410_dma_ctrl(context->dma_channel, S3C2410_DMAOP_START);++				wait_for_completion(&context->dma_complete);++				s3c24xx_hcd_dma_complete(context);+			} else {+				s3c24xx_hcd_pio_complete(context);+			}+		}+	}++ out:+	s3c24xx_hcd_clear_sta(context);+	s3c24xx_hcd_clear_imask(context);++	writel(0, context->base + S3C2410_SDICMDARG);+	writel(0, context->base + S3C2410_SDICMDCON);++	SDIO_HandleHcdEvent(&context->hcd, EVENT_HCD_TRANSFER_DONE);+}++static void s3c24xx_hcd_irq_work(struct work_struct *work)+{+	struct s3c24xx_hcd_context * context =+		container_of(work, struct s3c24xx_hcd_context, irq_work);++	disable_irq(context->io_irq);++	writel(S3C2410_SDIDSTA_SDIOIRQDETECT, context->base + S3C2410_SDIDSTA);++	SDIO_HandleHcdEvent(&context->hcd, EVENT_HCD_SDIO_IRQ_PENDING);++	enable_irq(context->io_irq);+}++void s3c24xx_hcd_dma_done(struct s3c2410_dma_chan *dma_ch, void *buf_id,+			  int size, enum s3c2410_dma_buffresult result)+{+	struct s3c24xx_hcd_context * context =+		(struct s3c24xx_hcd_context *) buf_id;++	if (result != S3C2410_RES_OK) {+		DBG_PRINT(SDDBG_ERROR, ("%s(): DMA xfer failed: %d\n", __FUNCTION__, result));+		s3c24xx_dump_regs(context);+	}++	context->latest_xfer_size = size;+	complete(&context->dma_complete);+}++static int s3c24xx_hcd_prepare_dma(struct s3c24xx_hcd_context * context)+{+	PSDREQUEST req;+	SDIO_STATUS status = SDIO_STATUS_SUCCESS;+	int read = 0, hwcfg = S3C2410_DISRCC_INC | S3C2410_DISRCC_APB;+	enum s3c2410_dmasrc source = S3C2410_DMASRC_MEM;++	req = GET_CURRENT_REQUEST(&context->hcd);+	if (req == NULL) {+		DBG_PRINT(SDDBG_ERROR, ("%s(): No current request\n", __FUNCTION__));+		status = SDIO_STATUS_ERROR;+	}++	if (!context->dma_en) {+		DBG_PRINT(SDDBG_ERROR, ("%s(): DMA is disabled\n", __FUNCTION__));+		status = SDIO_STATUS_ERROR;+	}++	if (!IS_SDREQ_DATA_TRANS(req->Flags)) {+		DBG_PRINT(SDDBG_ERROR, ("%s(): No data to transfer\n", __FUNCTION__));+		status = SDIO_STATUS_ERROR;+	}++	if(!IS_SDREQ_WRITE_DATA(req->Flags)) {+		read = 1;+		source = S3C2410_DMASRC_HW;+		hwcfg = S3C2410_DISRCC_APB | 1;+	} else {+		memcpy(context->io_buffer, req->pDataBuffer, req->DataRemaining);+		dma_sync_single(NULL, context->io_buffer_dma,+				req->BlockCount * req->BlockLen, DMA_BIDIRECTIONAL);++	}++	s3c2410_dma_devconfig(context->dma_channel, source, hwcfg,+			      (unsigned long)context->mem->start + S3C2440_SDIDATA);++	s3c2410_dma_config(context->dma_channel, context->data_size,+			   S3C2410_DCON_CH0_SDI);+			   //(S3C2410_DCON_HWTRIG | S3C2410_DCON_CH0_SDI));++	s3c2410_dma_set_buffdone_fn(context->dma_channel, s3c24xx_hcd_dma_done);++//	s3c2410_dma_setflags(context->dma_channel, S3C2410_DMAF_AUTOSTART);++	s3c2410_dma_ctrl(context->dma_channel, S3C2410_DMAOP_FLUSH);++	s3c2410_dma_enqueue(context->dma_channel, context,+			    context->io_buffer_dma,+			    req->DataRemaining);++	return 0;+}+++static irqreturn_t s3c24xx_hcd_irq(int irq, void *dev_id)+{+	u32 cmdsta, dsta, fsta;+	unsigned long flags, trace = 0;+	PSDREQUEST req;+	struct s3c24xx_hcd_context * context =+		(struct s3c24xx_hcd_context *)dev_id;++	spin_lock_irqsave(&context->lock, flags);++	s3c24xx_hcd_clear_imask(context);++	cmdsta = readl(context->base + S3C2410_SDICMDSTAT);+	dsta = readl(context->base + S3C2410_SDIDSTA);+	fsta = readl(context->base + S3C2410_SDIFSTA);++	context->cmdsta = cmdsta;+	context->dsta = dsta;+	context->fsta = fsta;++	s3c24xx_hcd_clear_csta(context);++	if (dsta & S3C2410_SDIDSTA_SDIOIRQDETECT) {+		writel(S3C2410_SDIDSTA_SDIOIRQDETECT, context->base + S3C2410_SDIDSTA);++		if (context->int_sdio) {+			u32 imask;++			context->int_sdio = 0;++			imask = readl(context->base + S3C2440_SDIIMSK);+			imask &= ~S3C2410_SDIIMSK_SDIOIRQ;+			writel(imask, context->base + S3C2440_SDIIMSK);+			schedule_work(&context->irq_work);+		}+	}++	req = GET_CURRENT_REQUEST(&context->hcd);

⌨️ 快捷键说明

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