📄 atheros_2_0_hcd.patch
字号:
Index: linux-2.6.24/drivers/sdio/hcd/Kconfig===================================================================--- /dev/null+++ linux-2.6.24/drivers/sdio/hcd/Kconfig@@ -0,0 +1,14 @@+config SDIO_S3C24XX+ tristate "Samsung s3c24xx host controller"+ depends on PLAT_S3C24XX && SDIO+ default m+ help+ good luck.++config SDIO_S3C24XX_DMA+ bool "Samsung s3c24xx host controller DMA I/O"+ depends on SDIO_S3C24XX+ default n+ help+ good luck.+Index: linux-2.6.24/drivers/sdio/hcd/Makefile===================================================================--- /dev/null+++ linux-2.6.24/drivers/sdio/hcd/Makefile@@ -0,0 +1 @@+obj-$(CONFIG_PLAT_S3C24XX) += s3c24xx/Index: linux-2.6.24/drivers/sdio/hcd/s3c24xx/Makefile===================================================================--- /dev/null+++ linux-2.6.24/drivers/sdio/hcd/s3c24xx/Makefile@@ -0,0 +1,2 @@+obj-$(CONFIG_PLAT_S3C24XX) += sdio_s3c24xx_hcd.o+sdio_s3c24xx_hcd-objs := s3c24xx_hcd.oIndex: linux-2.6.24/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.c===================================================================--- /dev/null+++ linux-2.6.24/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.c@@ -0,0 +1,1502 @@+/*+ * s3c24xx_hcd.c - Samsung S3C MCI driver, Atheros SDIO API compatible.+ *+ * Copyright (C) 2007 by OpenMoko, Inc.+ * Written by Samuel Ortiz <sameo@openedhand.com>+ * All Rights Reserved+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License along+ * with this program; if not, write to the Free Software Foundation, Inc.,+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.+ */++#include <linux/kernel.h>+#include <linux/interrupt.h>+#include <linux/list.h>+#include <linux/dma-mapping.h>+#include <linux/errno.h>+#include <linux/platform_device.h>+#include <linux/device.h>+#include <linux/clk.h>+#include <linux/fs.h>+#include <linux/ioport.h>+#include <linux/workqueue.h>+#include <linux/completion.h>+#include <linux/delay.h>+#include <linux/seq_file.h>+#include <linux/debugfs.h>++#include <linux/sdio/ctsystem.h>+#include <linux/sdio/sdio_busdriver.h>+#include <linux/sdio/sdio_lib.h>++#include <asm/io.h>+#include <asm/irq.h>+#include <asm/uaccess.h>+#include <asm/dma.h>+#include <asm/dma-mapping.h>++#include <asm/arch/regs-sdi.h>+#include <asm/arch/regs-gpio.h>+#include <asm/arch/mci.h>+#include <asm/arch/gta02.h>++#include "s3c24xx_hcd.h"++#define DESCRIPTION "S3c24xx SDIO host controller"+#define AUTHOR "Samuel Ortiz <sameo@openedhand.com>"++#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)++static struct s3c2410_dma_client s3c24xx_hcd_dma_client = {+ .name = "s3c24xx_hcd",+};++extern struct platform_device s3c_device_sdi;++static void dump_request(struct s3c24xx_hcd_context * context)+{+ if (context->hcd.pCurrentRequest != NULL) {+ DBG_PRINT(SDDBG_ERROR, ("Current Request Command:%d, ARG:0x%8.8X flags: 0x%04x\n",+ context->hcd.pCurrentRequest->Command, context->hcd.pCurrentRequest->Argument,+ context->hcd.pCurrentRequest->Flags));+ if (IS_SDREQ_DATA_TRANS(context->hcd.pCurrentRequest->Flags)) {+ DBG_PRINT(SDDBG_ERROR, ("Data %s, Blocks: %d, BlockLen:%d Remaining: %d \n",+ IS_SDREQ_WRITE_DATA(context->hcd.pCurrentRequest->Flags) ? "WRITE":"READ",+ context->hcd.pCurrentRequest->BlockCount,+ context->hcd.pCurrentRequest->BlockLen,+ context->hcd.pCurrentRequest->DataRemaining));+ }+ }+}++static void s3c24xx_dump_regs(struct s3c24xx_hcd_context * context)+{+ u32 con, pre, cmdarg, cmdcon, cmdsta, r0, r1, r2, r3, timer, bsize;+ u32 datcon, datcnt, datsta, fsta, imask;++ con = readl(context->base + S3C2410_SDICON);+ pre = readl(context->base + S3C2410_SDIPRE);+ cmdarg = readl(context->base + S3C2410_SDICMDARG);+ cmdcon = readl(context->base + S3C2410_SDICMDCON);+ cmdsta = readl(context->base + S3C2410_SDICMDSTAT);+ r0 = readl(context->base + S3C2410_SDIRSP0);+ r1 = readl(context->base + S3C2410_SDIRSP1);+ r2 = readl(context->base + S3C2410_SDIRSP2);+ r3 = readl(context->base + S3C2410_SDIRSP3);+ timer = readl(context->base + S3C2410_SDITIMER);+ bsize = readl(context->base + S3C2410_SDIBSIZE);+ datcon = readl(context->base + S3C2410_SDIDCON);+ datcnt = readl(context->base + S3C2410_SDIDCNT);+ datsta = readl(context->base + S3C2410_SDIDSTA);+ fsta = readl(context->base + S3C2410_SDIFSTA);+ imask = readl(context->base + S3C2440_SDIIMSK);++ printk("SDICON: 0x%08x\n", con);+ printk("SDIPRE: 0x%08x\n", pre);+ printk("SDICmdArg: 0x%08x\n", cmdarg);+ printk("SDICmdCon: 0x%08x\n", cmdcon);+ printk("SDICmdSta: 0x%08x\n", cmdsta);+ printk("SDIRSP0: 0x%08x\n", r0);+ printk("SDIRSP1: 0x%08x\n", r1);+ printk("SDIRSP2: 0x%08x\n", r2);+ printk("SDIRSP3: 0x%08x\n", r3);+ printk("SDIDTimer: 0x%08x\n", timer);+ printk("SDIBSize: 0x%08x\n", bsize);+ printk("SDIDatCon: 0x%08x\n", datcon);+ printk("SDIDatCnt: 0x%08x\n", datcnt);+ printk("SDIDatSta: 0x%08x\n", datsta);+ printk("SDIFSta: 0x%08x\n", fsta);+ printk("SDIIntMsk: 0x%08x\n", imask);+}++static inline void s3c24xx_hcd_clear_imask(struct s3c24xx_hcd_context * context)+{+ if (context->int_sdio) {+ writel(S3C2410_SDIIMSK_SDIOIRQ | S3C2410_SDIIMSK_READWAIT,+ context->base + S3C2440_SDIIMSK);+ } else {+ writel(0, context->base + S3C2440_SDIIMSK);+ }+}++static inline void s3c24xx_hcd_set_imask(struct s3c24xx_hcd_context * context)+{+ writel(context->int_mask, context->base + S3C2440_SDIIMSK);+}+++static inline void s3c24xx_hcd_clear_dsta(struct s3c24xx_hcd_context * context)+{+ u32 dsta;++ dsta = readl(context->base + S3C2410_SDIDSTA);+ writel(dsta, context->base + S3C2410_SDIDSTA);+}++static inline void s3c24xx_hcd_clear_csta(struct s3c24xx_hcd_context * context)+{+ u32 csta, csta_clear = 0;++ csta = readl(context->base + S3C2410_SDICMDSTAT);++ if (csta & S3C2410_SDICMDSTAT_CRCFAIL)+ csta_clear |= S3C2410_SDICMDSTAT_CRCFAIL;+ if (csta & S3C2410_SDICMDSTAT_CMDSENT)+ csta_clear |= S3C2410_SDICMDSTAT_CMDSENT;+ if (csta & S3C2410_SDICMDSTAT_CMDTIMEOUT)+ csta_clear |= S3C2410_SDICMDSTAT_CMDTIMEOUT;+ if (csta & S3C2410_SDICMDSTAT_RSPFIN)+ csta_clear |= S3C2410_SDICMDSTAT_RSPFIN;++ writel(csta_clear, context->base + S3C2410_SDICMDSTAT);+}++static inline void s3c24xx_hcd_clear_sta(struct s3c24xx_hcd_context * context)+{+ u32 csta, dsta, csta_clear = 0, dsta_clear = 0;++ csta = readl(context->base + S3C2410_SDICMDSTAT);+ dsta = readl(context->base + S3C2410_SDIDSTA);++ if (csta & S3C2410_SDICMDSTAT_CRCFAIL)+ csta_clear |= S3C2410_SDICMDSTAT_CRCFAIL;+ if (csta & S3C2410_SDICMDSTAT_CMDSENT)+ csta_clear |= S3C2410_SDICMDSTAT_CMDSENT;+ if (csta & S3C2410_SDICMDSTAT_CMDTIMEOUT)+ csta_clear |= S3C2410_SDICMDSTAT_CMDTIMEOUT;+ if (csta & S3C2410_SDICMDSTAT_RSPFIN)+ csta_clear |= S3C2410_SDICMDSTAT_RSPFIN;+++ if (dsta & S3C2410_SDIDSTA_RDYWAITREQ)+ dsta_clear |= S3C2410_SDIDSTA_RDYWAITREQ;+ if (dsta & S3C2410_SDIDSTA_SDIOIRQDETECT)+ dsta_clear |= S3C2410_SDIDSTA_SDIOIRQDETECT;+ if (dsta & S3C2410_SDIDSTA_FIFOFAIL)+ dsta_clear |= S3C2410_SDIDSTA_FIFOFAIL;+ if (dsta & S3C2410_SDIDSTA_CRCFAIL)+ dsta_clear |= S3C2410_SDIDSTA_CRCFAIL;+ if (dsta & S3C2410_SDIDSTA_RXCRCFAIL)+ dsta_clear |= S3C2410_SDIDSTA_RXCRCFAIL;+ if (dsta & S3C2410_SDIDSTA_DATATIMEOUT)+ dsta_clear |= S3C2410_SDIDSTA_DATATIMEOUT;+ if (dsta & S3C2410_SDIDSTA_XFERFINISH)+ dsta_clear |= S3C2410_SDIDSTA_XFERFINISH;+ if (dsta & S3C2410_SDIDSTA_BUSYFINISH)+ dsta_clear |= S3C2410_SDIDSTA_BUSYFINISH;+ if (dsta & S3C2410_SDIDSTA_SBITERR)+ dsta_clear |= S3C2410_SDIDSTA_SBITERR;++ writel(csta_clear, context->base + S3C2410_SDICMDSTAT);+ writel(dsta_clear, context->base + S3C2410_SDIDSTA);+}++static inline void s3c24xx_hcd_fifo_reset(struct s3c24xx_hcd_context * context)+{+ u32 fsta;++ fsta = readl(context->base + S3C2410_SDIFSTA);+ fsta |= S3C2440_SDIFSTA_FIFORESET;+ writel(fsta, context->base + S3C2410_SDIFSTA);+}++#if 0+static void s3c24xx_hcd_reset(struct s3c24xx_hcd_context * context)+{+ u32 con, counter;+ unsigned long flags;++ spin_lock_irqsave(&context->lock, flags);++ con = readl(context->base + S3C2410_SDICON);++ con |= S3C2440_SDICON_SDRESET;++ writel(con, context->base + S3C2410_SDICON);++ counter = 1000;+ while(counter) {+ con = readl(context->base + S3C2410_SDICON);+ if (!(con & S3C2440_SDICON_SDRESET))+ break;+ counter--;+ mdelay(1);+ }++ spin_unlock_irqrestore(&context->lock, flags);+}+#endif++static SDIO_STATUS s3c24xx_hcd_clock_enable(struct s3c24xx_hcd_context * context,+ unsigned int clock_rate,+ unsigned char enable)+{+ SDIO_STATUS status = SDIO_STATUS_SUCCESS;+ unsigned long flags;+ u32 con;++ spin_lock_irqsave(&context->lock, flags);++ con = readl(context->base + S3C2410_SDICON);++ if (enable && clock_rate) {+ con |= S3C2410_SDICON_CLOCKTYPE;+ } else {+ con &= ~S3C2410_SDICON_CLOCKTYPE;+ }++ if (clock_rate) {+ int prescaler;++ for (prescaler = 0; prescaler < 0xff; prescaler++) {+ context->device.actual_clock_rate =+ context->device.max_clock_rate / (prescaler + 1);++ if (context->device.actual_clock_rate <= clock_rate &&+ context->device.actual_clock_rate <= context->hcd.MaxClockRate)+ break;+ }++ if (prescaler == 0xff)+ DBG_PRINT(SDDBG_ERROR , ("Using lowest clock rate\n"));++ writel(prescaler, context->base + S3C2410_SDIPRE);+ }++ writel(con, context->base + S3C2410_SDICON);++ spin_unlock_irqrestore(&context->lock, flags);++ return SDIOErrorToOSError(status);+}++static void s3c24xx_hcd_set_bus_mode(struct s3c24xx_hcd_context *context,+ PSDCONFIG_BUS_MODE_DATA pMode)+{+ u32 datacon;+ unsigned long flags;++ DBG_PRINT(SDDBG_TRACE , ("SetBusMode\n"));++ spin_lock_irqsave(&context->lock, flags);+ datacon = readl(context->base + S3C2410_SDIDCON);++ switch (SDCONFIG_GET_BUSWIDTH(pMode->BusModeFlags)) {+ case SDCONFIG_BUS_WIDTH_1_BIT:+ context->bus_width = 1;+ datacon &= S3C2410_SDIDCON_WIDEBUS;+ break;+ case SDCONFIG_BUS_WIDTH_4_BIT:+ context->bus_width = 4;+ datacon |= S3C2410_SDIDCON_WIDEBUS;+ break;+ default:+ DBG_PRINT(SDDBG_TRACE , ("Unknown bus width: %d\n", SDCONFIG_GET_BUSWIDTH(pMode->BusModeFlags)));+ break;+ }++ writel(datacon, context->base + S3C2410_SDIDCON);+ spin_unlock_irqrestore(&context->lock, flags);++ /* Set clock rate and enable clock */+ s3c24xx_hcd_clock_enable(context, pMode->ClockRate, 1);+ pMode->ActualClockRate = context->device.actual_clock_rate;++ DBG_PRINT(SDDBG_TRACE , ("BUS mode: %d bits wide, actual clock rate: %d kHz (requested %d kHz)\n",+ context->bus_width, pMode->ActualClockRate / 1000, pMode->ClockRate / 1000));+}+++static void s3c24xx_hcd_dma_complete(struct s3c24xx_hcd_context * context)+{+ u32 dsta, counter, i;+ 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;+ }++ if (context->complete == S3C24XX_HCD_DATA_READ) {+ /* DMA READ completion */+ if (context->latest_xfer_size != req->DataRemaining) {+ DBG_PRINT(SDDBG_ERROR, ("Unexpected read xfer size: %d <-> %d\n",+ context->latest_xfer_size, req->DataRemaining));+ status = SDIO_STATUS_BUS_WRITE_ERROR;+ }++ counter = 0;+ dsta = readl(context->base + S3C2410_SDIDSTA);+ while (!(dsta & S3C2410_SDIDSTA_XFERFINISH)) {+ if (counter > 500) {+ printk("read xfer timed out\n");+ s3c24xx_dump_regs(context);+ memcpy(req->pDataBuffer, context->io_buffer,+ req->BlockCount * req->BlockLen);+ printk("Transfer: %dx%d\n", req->BlockCount, req->BlockLen);+ for (i = 0; i < req->DataRemaining; i++)+ printk("0x%x ", *(((char *)context->io_buffer) + i));+ printk("\n");+ status = SDIO_STATUS_BUS_READ_TIMEOUT;+ goto out;+ }+ dsta = readl(context->base + S3C2410_SDIDSTA);+ counter++;+ mdelay(1);+ };++ dma_sync_single(NULL, context->io_buffer_dma,+ req->BlockCount * req->BlockLen, DMA_BIDIRECTIONAL);++ writel(S3C2410_SDIDSTA_XFERFINISH, context->base + S3C2410_SDIDSTA);++ memcpy(req->pDataBuffer, context->io_buffer,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -