📄 atheros_2_0_hcd.patch
字号:
+ if (req == NULL) {+ DBG_PRINT(SDDBG_TRACE, ("%s(): No current request\n", __FUNCTION__));+ goto out;+ }++ if (cmdsta & S3C2410_SDICMDSTAT_CMDTIMEOUT) {+ DBG_PRINT(SDDBG_ERROR, ("TIMEOUT\n"));+ printk("TIMEOUT\n");+ req->Status = SDIO_STATUS_BUS_RESP_TIMEOUT;+ writel(S3C2410_SDICMDSTAT_CMDTIMEOUT, context->base + S3C2410_SDICMDSTAT);+ schedule_work(&context->io_work);+ }++ if (cmdsta & S3C2410_SDICMDSTAT_CRCFAIL) {+ DBG_PRINT(SDDBG_ERROR, ("CRCFAIL 0x%x\n", cmdsta));+ printk("CRCFAIL 0x%x\n", cmdsta);+ req->Status = SDIO_STATUS_BUS_RESP_CRC_ERR;+ dump_request(context);+ writel(S3C2410_SDICMDSTAT_CRCFAIL, context->base + S3C2410_SDICMDSTAT);+ schedule_work(&context->io_work);+ }+++ if (cmdsta & S3C2410_SDICMDSTAT_CMDSENT) {+ writel(S3C2410_SDICMDSTAT_CMDSENT, context->base + S3C2410_SDICMDSTAT);++ if (context->complete == S3C24XX_HCD_NO_RESPONSE) {+ req->Status = SDIO_STATUS_SUCCESS;+ trace = 1;+ schedule_work(&context->io_work);+ }+ }++ if (cmdsta & S3C2410_SDICMDSTAT_RSPFIN ||+ (IS_SDREQ_WRITE_DATA(req->Flags) && (fsta & S3C2410_SDIFSTA_TFDET)) ||+ (!IS_SDREQ_WRITE_DATA(req->Flags) && (fsta & S3C2410_SDIFSTA_RFDET))) {++ writel(S3C2410_SDICMDSTAT_RSPFIN, context->base + S3C2410_SDICMDSTAT);++ 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;+ if (trace)+ printk("IO work already scheduled, cmdsta: 0x%x\n", cmdsta);+ schedule_work(&context->io_work);+ }+ }++ out:+ if (dsta & S3C2410_SDIDSTA_RDYWAITREQ) {+ printk("S3C2410_SDIDSTA_RDYWAITREQ\n");+ //writel(S3C2410_SDIDSTA_RDYWAITREQ, context->base + S3C2410_SDIDSTA);+ }++ if (dsta & S3C2410_SDIDSTA_FIFOFAIL) {+ printk("S3C2410_SDIDSTA_FIFOFAIL\n");+ writel(S3C2410_SDIDSTA_FIFOFAIL, context->base + S3C2410_SDIDSTA);+ }++ if (dsta & S3C2410_SDIDSTA_CRCFAIL) {+ printk("S3C2410_SDIDSTA_CRCFAIL\n");+ writel(S3C2410_SDIDSTA_CRCFAIL, context->base + S3C2410_SDIDSTA);+ }++ if (dsta & S3C2410_SDIDSTA_RXCRCFAIL) {+ printk("S3C2410_SDIDSTA_RXCRCFAIL\n");+ writel(S3C2410_SDIDSTA_RXCRCFAIL, context->base + S3C2410_SDIDSTA);+ }++ if (dsta & S3C2410_SDIDSTA_DATATIMEOUT) {+ printk("S3C2410_SDIDSTA_DATATIMEOUT\n");+ writel(S3C2410_SDIDSTA_DATATIMEOUT, context->base + S3C2410_SDIDSTA);+ }++ if (dsta & S3C2410_SDIDSTA_BUSYFINISH) {+ printk("S3C2410_SDIDSTA_BUSYFINISH\n");+ writel(S3C2410_SDIDSTA_BUSYFINISH, context->base + S3C2410_SDIDSTA);+ }++ if (dsta & S3C2410_SDIDSTA_SBITERR) {+ printk("S3C2410_SDIDSTA_SBIERR\n");+ writel(S3C2410_SDIDSTA_SBITERR, context->base + S3C2410_SDIDSTA);+ }++ spin_unlock_irqrestore(&context->lock, flags);+ return IRQ_HANDLED;+}+++SDIO_STATUS s3c24xx_hcd_config(PSDHCD hcd, PSDCONFIG config)+{+ u32 con, imsk;+ SDIO_STATUS status = SDIO_STATUS_SUCCESS;+ PSDCONFIG_SDIO_INT_CTRL_DATA int_data;+ struct s3c24xx_hcd_context * context = (struct s3c24xx_hcd_context *)hcd->pContext;++ switch (GET_SDCONFIG_CMD(config)){+ case SDCONFIG_GET_WP:+ DBG_PRINT(SDDBG_TRACE, ("config GET_WP\n"));+ *((SDCONFIG_WP_VALUE *)config->pData) = 0;+ status = SDIO_STATUS_SUCCESS;+ break;+ case SDCONFIG_SEND_INIT_CLOCKS:+ DBG_PRINT(SDDBG_TRACE, ("config SEND_INIT_CLOCKS\n"));++ /* We stop/start the clock */+ con = readl(context->base + S3C2410_SDICON);++ con &= ~S3C2410_SDICON_CLOCKTYPE;+ writel(con, context->base + S3C2410_SDICON);++ mdelay(100);++ con |= S3C2410_SDICON_CLOCKTYPE;+ writel(con, context->base + S3C2410_SDICON);++ mdelay(100);++ status = SDIO_STATUS_SUCCESS;+ break;+ case SDCONFIG_SDIO_INT_CTRL:+ DBG_PRINT(SDDBG_TRACE, ("config SDIO_INT_CTRL\n"));+ int_data = GET_SDCONFIG_CMD_DATA(PSDCONFIG_SDIO_INT_CTRL_DATA, config);++ if (int_data->SlotIRQEnable &+ (IRQ_DETECT_1_BIT | IRQ_DETECT_4_BIT | IRQ_DETECT_MULTI_BLK) ) {+ imsk = readl(context->base + S3C2440_SDIIMSK);++ if (int_data->SlotIRQEnable) {+ printk("SDIO_INT_CTRL enable IRQ\n");+ DBG_PRINT(SDDBG_TRACE, ("SDIO_INT_CTRL enable IRQ\n"));+ context->int_sdio = 1;+ imsk |= S3C2410_SDIIMSK_SDIOIRQ;+ writel(imsk, context->base + S3C2440_SDIIMSK);+ } else {+ printk("SDIO_INT_CTRL disable IRQ\n");+ DBG_PRINT(SDDBG_TRACE, ("SDIO_INT_CTRL disable IRQ\n"));+ context->int_sdio = 0;+ imsk &= ~S3C2410_SDIIMSK_SDIOIRQ;+ writel(imsk, context->base + S3C2440_SDIIMSK);+ }+ }+ status = SDIO_STATUS_SUCCESS;+ break;+ case SDCONFIG_SDIO_REARM_INT:+ DBG_PRINT(SDDBG_TRACE, ("config SDIO_REARM_INT\n"));++ context->int_sdio = 1;+ imsk = readl(context->base + S3C2440_SDIIMSK);+ imsk |= S3C2410_SDIIMSK_SDIOIRQ;+ writel(imsk, context->base + S3C2440_SDIIMSK);++ status = SDIO_STATUS_SUCCESS;+ break;+ case SDCONFIG_FUNC_CHANGE_BUS_MODE:+ case SDCONFIG_BUS_MODE_CTRL:+ s3c24xx_hcd_set_bus_mode(context, (PSDCONFIG_BUS_MODE_DATA)(config->pData));+ DBG_PRINT(SDDBG_TRACE, ("config BUS_MODE_CTRL\n"));+ status = SDIO_STATUS_SUCCESS;+ break;+ case SDCONFIG_POWER_CTRL:+ DBG_PRINT(SDDBG_TRACE, ("config POWER_CTRL\n"));+ status = SDIO_STATUS_SUCCESS;+ break;+ case SDCONFIG_GET_HCD_DEBUG:+ DBG_PRINT(SDDBG_TRACE, ("config GET_HCD_DEBUG\n"));+ status = SDIO_STATUS_SUCCESS;+ break;+ case SDCONFIG_SET_HCD_DEBUG:+ DBG_PRINT(SDDBG_TRACE, ("config SET_HCD_DEBUG\n"));+ status = SDIO_STATUS_SUCCESS;+ break;+ default:+ /* invalid request */+ DBG_PRINT(SDDBG_ERROR, ("%s() - unsupported command: 0x%X\n",+ __FUNCTION__, GET_SDCONFIG_CMD(config)));+ status = SDIO_STATUS_INVALID_PARAMETER;+ }++ return SDIOErrorToOSError(status);+}+++SDIO_STATUS s3c24xx_hcd_request(PSDHCD hcd)+{+ SDIO_STATUS status = SDIO_STATUS_PENDING;+ PSDREQUEST req;+ u32 cmdcon, imask;+ unsigned long flags;+ struct s3c24xx_hcd_context * context =+ (struct s3c24xx_hcd_context *)hcd->pContext;++ req = GET_CURRENT_REQUEST(hcd);+ DBG_ASSERT(req != NULL);++ if (req->Flags & SDREQ_FLAGS_DATA_SHORT_TRANSFER)+ printk("### SHORT TRANSFER ###\n");++ spin_lock_irqsave(&context->lock, flags);++ /* Clear command, data and fifo status registers */+ writel(0xFFFFFFFF, context->base + S3C2410_SDICMDSTAT);+ writel(0xFFFFFFFF, context->base + S3C2410_SDIDSTA);+ writel(0xFFFFFFFF, context->base + S3C2410_SDIFSTA);++ /* Enabling irqs */+ imask = S3C2410_SDIIMSK_READWAIT;++ cmdcon = readl(context->base + S3C2410_SDICMDCON);++ switch (GET_SDREQ_RESP_TYPE(req->Flags)) {+ case SDREQ_FLAGS_NO_RESP:+ cmdcon &= ~S3C2410_SDICMDCON_WAITRSP;+ context->complete = S3C24XX_HCD_NO_RESPONSE;+ imask |= S3C2410_SDIIMSK_CMDSENT;+ break;+ case SDREQ_FLAGS_RESP_R1:+ case SDREQ_FLAGS_RESP_R1B:+ case SDREQ_FLAGS_RESP_R3:+ case SDREQ_FLAGS_RESP_SDIO_R4:+ case SDREQ_FLAGS_RESP_SDIO_R5:+ case SDREQ_FLAGS_RESP_R6:+ cmdcon &= ~S3C2410_SDICMDCON_LONGRSP;+ cmdcon |= S3C2410_SDICMDCON_WAITRSP;+ context->complete = S3C24XX_HCD_RESPONSE_SHORT;+ imask |= S3C2410_SDIIMSK_CRCSTATUS | S3C2410_SDIIMSK_RESPONSEND+ | S3C2410_SDIIMSK_CMDTIMEOUT | S3C2410_SDIIMSK_RESPONSECRC;+ break;+ case SDREQ_FLAGS_RESP_R2:+ cmdcon |= S3C2410_SDICMDCON_LONGRSP;+ cmdcon |= S3C2410_SDICMDCON_WAITRSP;+ context->complete = S3C24XX_HCD_RESPONSE_LONG;+ imask |= S3C2410_SDIIMSK_CRCSTATUS | S3C2410_SDIIMSK_RESPONSEND+ | S3C2410_SDIIMSK_CMDTIMEOUT | S3C2410_SDIIMSK_RESPONSECRC;+ break;++ }++ /* There is a data part */+ if (IS_SDREQ_DATA_TRANS(req->Flags)) {+ u32 dcon = 0;++ if (readl(context->base + S3C2410_SDIDSTA) &+ (S3C2410_SDIDSTA_TXDATAON | S3C2410_SDIDSTA_RXDATAON)) {+ printk("##### DATA ON: 0x%x ######\n", readl(context->base + S3C2410_SDIDSTA));+ }++ /* Setting timer */+ writel(0x7fffff, context->base + S3C2410_SDITIMER);++ /* Block size */+ writel(req->BlockLen, context->base + S3C2410_SDIBSIZE);+ /* Number of blocks */+ dcon |= (0xfff & req->BlockCount);++ if (context->bus_width == 4)+ dcon |= S3C2410_SDIDCON_WIDEBUS;++ req->DataRemaining = req->BlockCount * req->BlockLen;++ /* Set data size, and start the transfer */+ dcon |= S3C2410_SDIDCON_IRQPERIOD;+ if (!(req->DataRemaining % 4)) {+ context->data_size = 4;+ dcon |= S3C2440_SDIDCON_DS_WORD;+ } else if (!(req->DataRemaining % 2)) {+ context->data_size = 2;+ dcon |= S3C2440_SDIDCON_DS_HALFWORD;+ } else {+ context->data_size = 1;+ dcon |= S3C2440_SDIDCON_DS_BYTE;+ }++#ifdef CONFIG_SDIO_S3C24XX_DMA+ if (req->DataRemaining > 16) {+ context->dma_en = 1;+ } else+#endif+ {+ context->dma_en = 0;+ context->data_size = 1;+ dcon |= S3C2440_SDIDCON_DS_BYTE;+ }++ if (context->dma_en) {+ dcon |= S3C2410_SDIDCON_DMAEN;+ s3c24xx_hcd_prepare_dma(context);+ }++ if (IS_SDREQ_WRITE_DATA(req->Flags)) {+ /* Data write */+ DBG_PRINT(SDDBG_TRACE, ("Start data write, block count=%d, block size=%d\n",+ req->BlockCount, req->BlockLen));++ /* Data configuration: transmit after resp, block mode*/+ dcon |= S3C2410_SDIDCON_TXAFTERRESP | S3C2410_SDIDCON_BLOCKMODE;++ /* This is a write */+ dcon |= S3C2410_SDIDCON_XFER_TXSTART;++ imask |= S3C2410_SDIIMSK_TXFIFOHALF | S3C2410_SDIIMSK_TXFIFOEMPTY |+ S3C2410_SDIIMSK_FIFOFAIL | S3C2410_SDIIMSK_DATACRC |+ S3C2410_SDIIMSK_DATATIMEOUT | S3C2410_SDIIMSK_DATAFINISH;++ context->complete = S3C24XX_HCD_DATA_WRITE;+ } else {+ /* Data read */+ DBG_PRINT(SDDBG_TRACE, ("Start data read, block count=%d, block size=%d\n",+ req->BlockCount, req->BlockLen));++ /* Data configuration: receive after cmd, block mode*/+ dcon |= S3C2410_SDIDCON_RXAFTERCMD | S3C2410_SDIDCON_BLOCKMODE;++ /* This is a read */+ dcon |= S3C2410_SDIDCON_XFER_RXSTART;++ imask |= S3C2410_SDIIMSK_RXFIFOHALF | S3C2410_SDIIMSK_RXFIFOLAST |+ S3C2410_SDIIMSK_FIFOFAIL | S3C2410_SDIIMSK_DATACRC |+ S3C2410_SDIIMSK_DATATIMEOUT | S3C2410_SDIIMSK_DATAFINISH;++ context->complete = S3C24XX_HCD_DATA_READ;+ }++ dcon |= S3C2440_SDIDCON_DATSTART;++ writel(dcon, context->base + S3C2410_SDIDCON);++ cmdcon |= S3C2410_SDICMDCON_WITHDATA;++ } else {+ cmdcon &= ~S3C2410_SDICMDCON_WITHDATA;+ }++ cmdcon |= req->Command & S3C2410_SDICMDCON_INDEX;+ cmdcon |= S3C2410_SDICMDCON_SENDERHOST | S3C2410_SDICMDCON_CMDSTART;++ req->Status = SDIO_STATUS_PENDING;++ if (context->int_sdio)+ imask |= S3C2410_SDIIMSK_SDIOIRQ;+ context->int_mask = imask;+ writel(imask, context->base + S3C2440_SDIIMSK);+ writel(req->Argument, context->base + S3C2410_SDICMDARG);+ writel(cmdcon, context->base + S3C2410_SDICMDCON);++ spin_unlock_irqrestore(&context->lock, flags);++ return status;+}++static int s3c24xx_hcd_hw_init(struct s3c24xx_hcd_context * context)+{+ SDIO_STATUS status = SDIO_STATUS_SUCCESS;+ u32 con, datacon;++ /* Clock */+ context->device.clock = clk_get(NULL, "sdi");+ if (IS_ERR(context->device.clock)) {+ DBG_PRINT(SDDBG_ERROR, ("Couldn't get clock\n"));+ status = PTR_ERR(context->device.clock);+ context->device.clock = NULL;+ return status;+ }++ status = clk_enable(context->device.clock);+ if (SDIO_IS_ERROR(status)) {+ DBG_PRINT(SDDBG_ERROR, ("Couldn't get clock\n"));+ return SDIOErrorToOSError(status);+ }++ context->device.max_clock_rate = clk_get_rate(context->device.clock);+ context->device.actual_clock_rate = context->device.max_clock_rate;++ /* I/O */+ context->mem = request_mem_region(context->mem->start,+ RESSIZE(context->mem), context->description);++ if (!context->mem) {+ DBG_PRINT(SDDBG_ERROR, ("Failed to request io memory region\n"));+ status = -ENOENT;+ goto out_disable_clock;+ }++ context->base = ioremap(context->mem->start, RESSIZE(context->mem));+ if (context->base == 0) {+ DBG_PRINT(SDDBG_ERROR, ("failed to ioremap() io memory region.\n"));+ status = -EINVAL;+ goto out_free_mem_region;+ }++ /* IRQ */+#if 0+ context->cd_irq = s3c2410_gpio_getirq(GTA02v1_GPIO_nSD_DETECT);+ s3c2410_gpio_cfgpin(GTA02v1_GPIO_nSD_DETECT, S3C2410_GPIO_IRQ);++ if (request_irq(context->cd_irq, s3c24xx_hcd_cd_irq, 0, context->description, context)) {+ DBG_PRINT(SDDBG_ERROR, ("failed to request card detect interrupt.\n"));+ status = -ENOENT;+ goto out_unmap_mem_region;+ }+#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -