📄 full-h1940-2.6.21.patch
字号:
+static int s3c2410ts_suspend(struct platform_device *pdev, pm_message_t state)+{+ writel(TSC_SLEEP, base_addr+S3C2410_ADCTSC);+ writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_STDBM,+ base_addr+S3C2410_ADCCON);++ disable_irq(IRQ_ADC);+ disable_irq(IRQ_TC);++ clk_disable(adc_clock);++ return 0;+}++static int s3c2410ts_resume(struct platform_device *pdev)+{+ struct s3c2410_ts_mach_info *info =+ ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data;++ clk_enable(adc_clock);+ msleep(1);++ enable_irq(IRQ_ADC);+ enable_irq(IRQ_TC);++ if ((info->presc&0xff) > 0)+ writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(info->presc&0xFF),\+ base_addr+S3C2410_ADCCON);+ else+ writel(0,base_addr+S3C2410_ADCCON);++ /* Initialise registers */+ if ((info->delay&0xffff) > 0)+ writel(info->delay & 0xffff, base_addr+S3C2410_ADCDLY);++ writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);++ return 0;+}++#else+#define s3c2410ts_suspend NULL+#define s3c2410ts_resume NULL+#endif++static struct platform_driver s3c2410ts_driver = {+ .driver = {+ .name = "s3c2410-ts",+ .owner = THIS_MODULE,+ },+ .probe = s3c2410ts_probe,+ .remove = s3c2410ts_remove,+ .suspend = s3c2410ts_suspend,+ .resume = s3c2410ts_resume,++};+++static int __init s3c2410ts_init(void)+{+ return platform_driver_register(&s3c2410ts_driver);+}++static void __exit s3c2410ts_exit(void)+{+ platform_driver_unregister(&s3c2410ts_driver);+}++module_init(s3c2410ts_init);+module_exit(s3c2410ts_exit);++/*+ Local variables:+ compile-command: "make ARCH=arm CROSS_COMPILE=/usr/local/arm/3.3.2/bin/arm-linux- -k -C ../../.."+ c-basic-offset: 8+ End:+*/diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfigindex 12af9c7..d15f30f 100644--- a/drivers/mmc/Kconfig+++ b/drivers/mmc/Kconfig@@ -125,4 +125,16 @@ config MMC_TIFM_SD To compile this driver as a module, choose M here: the module will be called tifm_sd. +config MMC_S3C+ tristate "Samsung S3C SD/MMC Card Interface support"+ depends on ARCH_S3C2410 && MMC+ help+ This selects a driver for the MCI interface found in+ Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs.+ If you have a board based on one of those and a MMC/SD+ slot, say Y or M here.++ If unsure, say N.++ endmenudiff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefileindex 83ffb93..7c2eb45 100644--- a/drivers/mmc/Makefile+++ b/drivers/mmc/Makefile@@ -24,10 +24,12 @@ obj-$(CONFIG_MMC_AU1X) += au1xmmc.o obj-$(CONFIG_MMC_OMAP) += omap.o obj-$(CONFIG_MMC_AT91) += at91_mci.o obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o+obj-$(CONFIG_MMC_S3C) += s3cmci.o mmc_core-y := mmc.o mmc_sysfs.o mmc_core-$(CONFIG_BLOCK) += mmc_queue.o ifeq ($(CONFIG_MMC_DEBUG),y)+obj-$(CONFIG_MMC) += mmc_debug.o EXTRA_CFLAGS += -DDEBUG endifdiff --git a/drivers/mmc/mmc_debug.c b/drivers/mmc/mmc_debug.cnew file mode 100644index 0000000..f13e223--- /dev/null+++ b/drivers/mmc/mmc_debug.c@@ -0,0 +1,59 @@+/*+ * linux/drivers/mmc/mmc_debug.c+ *+ * Copyright (C) 2003 maintech GmbH, Thomas Kleffel <tk@maintech.de>+ *+ * This file contains debug helper functions for the MMC/SD stack+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License version 2 as+ * published by the Free Software Foundation.+ *+ */++#include <linux/mmc/mmc.h>+#include "mmc_debug.h"++char *mmc_cmd2str(int cmd)+{+ switch(cmd) {+ case 0: return "GO_IDLE_STATE";+ case 1: return "ALL_SEND_OCR";+ case 2: return "ALL_SEND_CID";+ case 3: return "ALL_SEND_RELATIVE_ADD";+ case 6: return "ACMD: SD_SET_BUSWIDTH";+ case 7: return "SEL_DESEL_CARD";+ case 9: return "SEND_CSD";+ case 10: return "SEND_CID";+ case 11: return "READ_UNTIL_STOP";+ case 12: return "STOP_TRANSMISSION";+ case 13: return "SEND_STATUS";+ case 15: return "GO_INACTIVE_STATE";+ case 16: return "SET_BLOCKLEN";+ case 17: return "READ_SINGLE_BLOCK";+ case 18: return "READ_MULTIPLE_BLOCK";+ case 24: return "WRITE_SINGLE_BLOCK";+ case 25: return "WRITE_MULTIPLE_BLOCK";+ case 41: return "ACMD: SD_APP_OP_COND";+ case 55: return "APP_CMD";+ default: return "UNKNOWN";+ }+}+EXPORT_SYMBOL(mmc_cmd2str);++char *mmc_err2str(int err)+{+ switch(err) {+ case MMC_ERR_NONE: return "OK";+ case MMC_ERR_TIMEOUT: return "TIMEOUT";+ case MMC_ERR_BADCRC: return "BADCRC";+ case MMC_ERR_FIFO: return "FIFO";+ case MMC_ERR_FAILED: return "FAILED";+ case MMC_ERR_INVALID: return "INVALID";+ case MMC_ERR_BUSY: return "BUSY";+ case MMC_ERR_DMA: return "DMA";+ case MMC_ERR_CANCELED: return "CANCELED";+ default: return "UNKNOWN";+ }+}+EXPORT_SYMBOL(mmc_err2str);diff --git a/drivers/mmc/mmc_debug.h b/drivers/mmc/mmc_debug.hnew file mode 100644index 0000000..5a84852--- /dev/null+++ b/drivers/mmc/mmc_debug.h@@ -0,0 +1,7 @@+#ifndef MMC_DEBUG_H+#define MMC_DEBUG_H++char *mmc_cmd2str(int err);+char *mmc_err2str(int err);++#endif /* MMC_DEBUG_H */diff --git a/drivers/mmc/s3cmci.c b/drivers/mmc/s3cmci.cnew file mode 100644index 0000000..3762628--- /dev/null+++ b/drivers/mmc/s3cmci.c@@ -0,0 +1,1355 @@+/*+ * linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver+ *+ * Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk@maintech.de>+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License version 2 as+ * published by the Free Software Foundation.+ */++#include <linux/module.h>+#include <linux/dma-mapping.h>+#include <linux/clk.h>+#include <linux/mmc/host.h>+#include <linux/mmc/protocol.h>+#include <linux/platform_device.h>++#include <asm/dma.h>+#include <asm/dma-mapping.h>++#include <asm/io.h>+#include <asm/arch/regs-sdi.h>+#include <asm/arch/regs-gpio.h>+#include <asm/arch/mmc.h>++#include "mmc_debug.h"+#include "s3cmci.h"++#define DRIVER_NAME "s3c-mci"++enum dbg_channels {+ dbg_err = (1 << 0),+ dbg_debug = (1 << 1),+ dbg_info = (1 << 2),+ dbg_irq = (1 << 3),+ dbg_sg = (1 << 4),+ dbg_dma = (1 << 5),+ dbg_pio = (1 << 6),+ dbg_fail = (1 << 7),+ dbg_conf = (1 << 8),+};++static const int dbgmap_err = dbg_err | dbg_fail;+static const int dbgmap_info = dbg_info | dbg_conf;+static const int dbgmap_debug = dbg_debug;++#define dbg(host, channels, args...) \+ if (dbgmap_err & channels) \+ dev_err(&host->pdev->dev, args); \+ else if (dbgmap_info & channels) \+ dev_info(&host->pdev->dev, args);\+ else if (dbgmap_debug & channels) \+ dev_dbg(&host->pdev->dev, args);++#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)++static struct s3c2410_dma_client s3cmci_dma_client = {+ .name = "s3c-mci",+};++static void finalize_request(struct s3cmci_host *host);+static void s3cmci_send_request(struct mmc_host *mmc);+static void s3cmci_reset(struct s3cmci_host *host);++#ifdef CONFIG_MMC_DEBUG++static inline void dbg_dumpregs(struct s3cmci_host *host, char *prefix)+{+ u32 con, pre, cmdarg, cmdcon, cmdsta, r0, r1, r2, r3, timer, bsize;+ u32 datcon, datcnt, datsta, fsta, imask;++ con = readl(host->base + S3C2410_SDICON);+ pre = readl(host->base + S3C2410_SDIPRE);+ cmdarg = readl(host->base + S3C2410_SDICMDARG);+ cmdcon = readl(host->base + S3C2410_SDICMDCON);+ cmdsta = readl(host->base + S3C2410_SDICMDSTAT);+ r0 = readl(host->base + S3C2410_SDIRSP0);+ r1 = readl(host->base + S3C2410_SDIRSP1);+ r2 = readl(host->base + S3C2410_SDIRSP2);+ r3 = readl(host->base + S3C2410_SDIRSP3);+ timer = readl(host->base + S3C2410_SDITIMER);+ bsize = readl(host->base + S3C2410_SDIBSIZE);+ datcon = readl(host->base + S3C2410_SDIDCON);+ datcnt = readl(host->base + S3C2410_SDIDCNT);+ datsta = readl(host->base + S3C2410_SDIDSTA);+ fsta = readl(host->base + S3C2410_SDIFSTA);+ imask = readl(host->base + host->sdiimsk);++ dbg(host, dbg_debug, "%s CON:[%08x] PRE:[%08x] TMR:[%08x]\n",+ prefix, con, pre, timer);++ dbg(host, dbg_debug, "%s CCON:[%08x] CARG:[%08x] CSTA:[%08x]\n",+ prefix, cmdcon, cmdarg, cmdsta);++ dbg(host, dbg_debug, "%s DCON:[%08x] FSTA:[%08x]"+ " DSTA:[%08x] DCNT:[%08x]\n",+ prefix, datcon, fsta, datsta, datcnt);++ dbg(host, dbg_debug, "%s R0:[%08x] R1:[%08x]"+ " R2:[%08x] R3:[%08x]\n",+ prefix, r0, r1, r2, r3);+}++static void prepare_dbgmsg(struct s3cmci_host *host, struct mmc_command *cmd,+ int stop)+{+ snprintf(host->dbgmsg_cmd, 300,+ "#%u%s op:%s(%i) arg:0x%08x flags:0x08%x retries:%u",+ host->ccnt, (stop?" (STOP)":""), mmc_cmd2str(cmd->opcode),+ cmd->opcode, cmd->arg, cmd->flags, cmd->retries);++ if (cmd->data) {+ snprintf(host->dbgmsg_dat, 300,+ "#%u bsize:%u blocks:%u bytes:%u",+ host->dcnt, cmd->data->blksz,+ cmd->data->blocks,+ cmd->data->blocks * cmd->data->blksz);+ } else {+ host->dbgmsg_dat[0] = '\0';+ }+}++static void dbg_dumpcmd(struct s3cmci_host *host, struct mmc_command *cmd,+ int fail)+{+ unsigned int dbglvl = fail?dbg_fail:dbg_debug;++ if (!cmd)+ return;++ if (cmd->error == MMC_ERR_NONE) {++ dbg(host, dbglvl, "CMD[OK] %s R0:0x%08x\n",+ host->dbgmsg_cmd, cmd->resp[0]);+ } else {+ dbg(host, dbglvl, "CMD[%s] %s Status:%s\n",+ mmc_err2str(cmd->error), host->dbgmsg_cmd,+ host->status);+ }++ if (!cmd->data)+ return;++ if (cmd->data->error == MMC_ERR_NONE) {+ dbg(host, dbglvl, "DAT[%s] %s\n",+ mmc_err2str(cmd->data->error), host->dbgmsg_dat);+ } else {+ dbg(host, dbglvl, "DAT[%s] %s DCNT:0x%08x\n",+ mmc_err2str(cmd->data->error), host->dbgmsg_dat,+ readl(host->base + S3C2410_SDIDCNT));+ }+}+#endif++static inline u32 enable_imask(struct s3cmci_host *host, u32 imask)+{+ u32 newmask;++ newmask = readl(host->base + host->sdiimsk);+ newmask|= imask;++ writel(newmask, host->base + host->sdiimsk);++ return newmask;+}++static inline u32 disable_imask(struct s3cmci_host *host, u32 imask)+{+ u32 newmask;++ newmask = readl(host->base + host->sdiimsk);+ newmask&= ~imask;++ writel(newmask, host->base + host->sdiimsk);++ return newmask;+}++static inline void clear_imask(struct s3cmci_host *host)+{+ writel(0, host->base + host->sdiimsk);+}++static inline int get_data_buffer(struct s3cmci_host *host,+ volatile u32 *words, volatile u32 **pointer)+{+ struct scatterlist *sg;++ if (host->pio_active == XFER_NONE)+ return -EINVAL;++ if ((!host->mrq) || (!host->mrq->data))+ return -EINVAL;++ if (host->pio_sgptr >= host->mrq->data->sg_len) {+ dbg(host, dbg_debug, "no more buffers (%i/%i)\n",+ host->pio_sgptr, host->mrq->data->sg_len);+ return -EBUSY;+ }+ sg = &host->mrq->data->sg[host->pio_sgptr];++ *words = sg->length >> 2;+ *pointer= page_address(sg->page) + sg->offset;++ host->pio_sgptr++;++ dbg(host, dbg_sg, "new buffer (%i/%i)\n",+ host->pio_sgptr, host->mrq->data->sg_len);++ return 0;+}++#define FIFO_FILL(host) ((readl(host->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK) >> 2)+#define FIFO_FREE(host) ((63 - (readl(host->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK)) >> 2)++static inline void do_pio_read(struct s3cmci_host *host)+{+ int res;+ u32 fifo;+ void __iomem *from_ptr;++ //write real prescaler to host, it might be set slow to fix+ writel(host->prescaler, host->base + S3C2410_SDIPRE);++ from_ptr = host->base + host->sdidata;++ while ((fifo = FIFO_FILL(host))) {+ if (!host->pio_words) {+ res = get_data_buffer(host, &host->pio_words,+ &host->pio_ptr);+ if (res) {+ host->pio_active = XFER_NONE;+ host->complete_what = COMPLETION_FINALIZE;++ dbg(host, dbg_pio, "pio_read(): "+ "complete (no more data).\n");+ return;+ }++ dbg(host, dbg_pio, "pio_read(): new target: [%i]@[%p]\n",+ host->pio_words, host->pio_ptr);+ }++ dbg(host, dbg_pio, "pio_read(): fifo:[%02i] "+ "buffer:[%03i] dcnt:[%08X]\n",+ fifo, host->pio_words,+ readl(host->base + S3C2410_SDIDCNT));++ if (fifo > host->pio_words)+ fifo = host->pio_words;++ host->pio_words-= fifo;+ host->pio_count+= fifo;++ while(fifo--) {+ *(host->pio_ptr++) = readl(from_ptr);+ }+ }++ if (!host->pio_words) {+ res = get_data_buffer(host, &host->pio_words, &host->pio_ptr);+ if (res) {+ dbg(host, dbg_pio, "pio_read(): "+ "complete (no more buffers).\n");+ host->pio_active = XFER_NONE;+ host->complete_what = COMPLETION_FINALIZE;++ return;+ }+ }++ enable_imask(host, S3C2410_SDIIMSK_RXFIFOHALF | S3C2410_SDIIMSK_RXFIFOLAST);+}++static inline void do_pio_write(struct s3cmci_host *host)+{+ int res;+ u32 fifo;++ void __iomem *to_ptr;++ to_ptr = host->base + host->sdidata;++ while ((fifo = FIFO_FREE(host))) {+ if (!host->pio_words) {+ res = get_data_buffer(host, &host->pio_words,+ &host->pio_ptr);+ if (res) {+ dbg(host, dbg_pio, "pio_write(): "+ "complete (no more data).\n");+ host->pio_active = XFER_NONE;++ return;+ }++ dbg(host, dbg_pio, "pio_write(): "+ "new source: [%i]@[%p]\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -