📄 full.patch
字号:
+static int __init s3c2410ts_probe(struct platform_device *pdev)+{+ struct s3c2410_ts_mach_info *info;+ struct input_dev *input_dev;++ info = ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data;++ if (!info)+ {+ printk(KERN_ERR "Hm... too bad : no platform data for ts\n");+ return -EINVAL;+ }++#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG+ printk(DEBUG_LVL "Entering s3c2410ts_init\n");+#endif++ adc_clock = clk_get(NULL, "adc");+ if (!adc_clock) {+ printk(KERN_ERR "failed to get adc clock source\n");+ return -ENOENT;+ }+ clk_enable(adc_clock);++#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG+ printk(DEBUG_LVL "got and enabled clock\n");+#endif++ base_addr=ioremap(S3C2410_PA_ADC,0x20);+ if (base_addr == NULL) {+ printk(KERN_ERR "Failed to remap register block\n");+ return -ENOMEM;+ }+++ /* Configure GPIOs */+ s3c2410_ts_connect();++ 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);++ /* Initialise input stuff */+ memset(&ts, 0, sizeof(struct s3c2410ts));+ input_dev = input_allocate_device();++ if (!input_dev) {+ printk(KERN_ERR "Unable to allocate the input device !!\n");+ return -ENOMEM;+ }++ ts.dev = input_dev;+ ts.dev->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);+ ts.dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);+ input_set_abs_params(ts.dev, ABS_X, 0, 0x3FF, 0, 0);+ input_set_abs_params(ts.dev, ABS_Y, 0, 0x3FF, 0, 0);+ input_set_abs_params(ts.dev, ABS_PRESSURE, 0, 1, 0, 0);++ ts.dev->private = &ts;+ ts.dev->name = s3c2410ts_name;+ ts.dev->id.bustype = BUS_RS232;+ ts.dev->id.vendor = 0xDEAD;+ ts.dev->id.product = 0xBEEF;+ ts.dev->id.version = S3C2410TSVERSION;++ ts.shift = info->oversampling_shift;++ /* Get irqs */+ if (request_irq(IRQ_ADC, stylus_action, IRQF_SAMPLE_RANDOM,+ "s3c2410_action", ts.dev)) {+ printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_ADC !\n");+ iounmap(base_addr);+ return -EIO;+ }+ if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM,+ "s3c2410_action", ts.dev)) {+ printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_TC !\n");+ iounmap(base_addr);+ return -EIO;+ }++ printk(KERN_INFO "%s successfully loaded\n", s3c2410ts_name);++ /* All went ok, so register to the input system */+ input_register_device(ts.dev);++ return 0;+}++static int s3c2410ts_remove(struct platform_device *pdev)+{+ disable_irq(IRQ_ADC);+ disable_irq(IRQ_TC);+ free_irq(IRQ_TC,ts.dev);+ free_irq(IRQ_ADC,ts.dev);++ if (adc_clock) {+ clk_disable(adc_clock);+ clk_put(adc_clock);+ adc_clock = NULL;+ }++ input_unregister_device(ts.dev);+ iounmap(base_addr);++ return 0;+}++#ifdef CONFIG_PM+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 4224686..0d18e91 100644--- a/drivers/mmc/Kconfig+++ b/drivers/mmc/Kconfig@@ -82,6 +82,15 @@ config MMC_WBSD If unsure, say N. +config MMC_S3C2410+ tristate "Samsung S3C2410 Multimedia Card Interface support"+ depends on ARCH_S3C2410 && MMC+ help+ This selects the Samsung S3C2410 Multimedia Card Interface + support. ++ If unsure, say N.+ config MMC_AU1X tristate "Alchemy AU1XX0 MMC Card Interface support" depends on MMC && SOC_AU1200diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefileindex 83ffb93..85e630c 100644--- a/drivers/mmc/Makefile+++ b/drivers/mmc/Makefile@@ -20,6 +20,7 @@ obj-$(CONFIG_MMC_PXA) += pxamci.o obj-$(CONFIG_MMC_IMX) += imxmmc.o obj-$(CONFIG_MMC_SDHCI) += sdhci.o obj-$(CONFIG_MMC_WBSD) += wbsd.o+obj-$(CONFIG_MMC_S3C2410) += s3c2410mci.o obj-$(CONFIG_MMC_AU1X) += au1xmmc.o obj-$(CONFIG_MMC_OMAP) += omap.o obj-$(CONFIG_MMC_AT91) += at91_mci.odiff --git a/drivers/mmc/s3c2410mci.c b/drivers/mmc/s3c2410mci.cnew file mode 100644index 0000000..d4f7d5c--- /dev/null+++ b/drivers/mmc/s3c2410mci.c@@ -0,0 +1,777 @@+/*+ * linux/drivers/mmc/s3c2410mci.h - Samsung S3C2410 SDI Interface driver+ *+ * Copyright (C) 2004 Thomas Kleffel, 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 version 2 as+ * published by the Free Software Foundation.+ */+#include <linux/module.h>+#include <linux/moduleparam.h>+#include <linux/init.h>+#include <linux/ioport.h>+#include <linux/platform_device.h>+#include <linux/interrupt.h>+#include <linux/blkdev.h>+#include <linux/delay.h>+#include <linux/err.h>+#include <linux/dma-mapping.h>+#include <linux/mmc/host.h>+#include <linux/mmc/protocol.h>+#include <linux/clk.h>++#include <asm/dma.h>+#include <asm/dma-mapping.h>+#include <asm/arch/dma.h>++#include <asm/io.h>+#include <asm/irq.h>+#include <asm/mach/mmc.h>++#include <asm/arch/regs-sdi.h>+#include <asm/arch/regs-gpio.h>+#include <asm/arch/mmc.h>++#ifdef CONFIG_MMC_DEBUG+#define DBG(x...) printk(KERN_INFO x)+#else+#define DBG(x...) do { } while (0)+#endif++#include "s3c2410mci.h"++#define DRIVER_NAME "mmci-s3c2410"+#define PFX DRIVER_NAME ": "++#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)++static struct s3c2410_dma_client s3c2410sdi_dma_client = {+ .name = "s3c2410-sdi",+};++/*+ * ISR for SDI Interface IRQ+ * Communication between driver and ISR works as follows:+ * host->mrq points to current request+ * host->complete_what tells the ISR when the request is considered done+ * COMPLETION_CMDSENT when the command was sent+ * COMPLETION_RSPFIN when a response was received+ * COMPLETION_XFERFINISH when the data transfer is finished+ * COMPLETION_XFERFINISH_RSPFIN both of the above.+ * host->complete_request is the completion-object the driver waits for+ *+ * 1) Driver sets up host->mrq and host->complete_what+ * 2) Driver prepares the transfer+ * 3) Driver enables interrupts+ * 4) Driver starts transfer+ * 5) Driver waits for host->complete_rquest+ * 6) ISR checks for request status (errors and success)+ * 6) ISR sets host->mrq->cmd->error and host->mrq->data->error+ * 7) ISR completes host->complete_request+ * 8) ISR disables interrupts+ * 9) Driver wakes up and takes care of the request+*/++static irqreturn_t s3c2410sdi_irq(int irq, void *dev_id)+{+ struct s3c2410sdi_host *host;+ u32 sdi_csta, sdi_dsta, sdi_dcnt;+ u32 sdi_cclear, sdi_dclear;+ unsigned long iflags;++ host = (struct s3c2410sdi_host *)dev_id;++ /* Check for things not supposed to happen */+ if(!host) return IRQ_HANDLED;+ + sdi_csta = readl(host->base + S3C2410_SDICMDSTAT);+ sdi_dsta = readl(host->base + S3C2410_SDIDSTA);+ sdi_dcnt = readl(host->base + S3C2410_SDIDCNT);+ + DBG(PFX "IRQ csta=0x%08x dsta=0x%08x dcnt:0x%08x\n", sdi_csta, sdi_dsta, sdi_dcnt);+ + spin_lock_irqsave( &host->complete_lock, iflags);+ + if( host->complete_what==COMPLETION_NONE ) {+ goto clear_imask;+ }+ + if(!host->mrq) { + goto clear_imask;+ }++ + sdi_csta = readl(host->base + S3C2410_SDICMDSTAT);+ sdi_dsta = readl(host->base + S3C2410_SDIDSTA);+ sdi_dcnt = readl(host->base + S3C2410_SDIDCNT);+ sdi_cclear = 0;+ sdi_dclear = 0;+ + + if(sdi_csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) {+ host->mrq->cmd->error = MMC_ERR_TIMEOUT;+ goto transfer_closed;+ }++ if(sdi_csta & S3C2410_SDICMDSTAT_CMDSENT) {+ if(host->complete_what == COMPLETION_CMDSENT) {+ host->mrq->cmd->error = MMC_ERR_NONE;+ goto transfer_closed;+ }++ sdi_cclear |= S3C2410_SDICMDSTAT_CMDSENT;+ }++ if(sdi_csta & S3C2410_SDICMDSTAT_CRCFAIL) {+ if (host->mrq->cmd->flags & MMC_RSP_136) {+ DBG(PFX "s3c2410 fixup : ignore CRC fail with long rsp\n");+ }+ else {+ DBG(PFX "COMMAND CRC FAILED %x\n", sdi_csta);+ if(host->mrq->cmd->flags & MMC_RSP_CRC) {+ host->mrq->cmd->error = MMC_ERR_BADCRC;+ goto transfer_closed;+ }+ }+ sdi_cclear |= S3C2410_SDICMDSTAT_CRCFAIL;+ }++ if(sdi_csta & S3C2410_SDICMDSTAT_RSPFIN) {+ if(host->complete_what == COMPLETION_RSPFIN) {+ host->mrq->cmd->error = MMC_ERR_NONE;+ goto transfer_closed;+ }++ if(host->complete_what == COMPLETION_XFERFINISH_RSPFIN) {+ host->mrq->cmd->error = MMC_ERR_NONE;+ host->complete_what = COMPLETION_XFERFINISH;+ }++ sdi_cclear |= S3C2410_SDICMDSTAT_RSPFIN;+ }++ if(sdi_dsta & S3C2410_SDIDSTA_FIFOFAIL) {+ host->mrq->cmd->error = MMC_ERR_NONE;+ host->mrq->data->error = MMC_ERR_FIFO;+ goto transfer_closed;+ }++ if(sdi_dsta & S3C2410_SDIDSTA_RXCRCFAIL) {+ host->mrq->cmd->error = MMC_ERR_NONE;+ host->mrq->data->error = MMC_ERR_BADCRC;+ goto transfer_closed;+ }++ if(sdi_dsta & S3C2410_SDIDSTA_CRCFAIL) {+ DBG(PFX "DATA CRC FAILED %u\n", sdi_csta);+ host->mrq->cmd->error = MMC_ERR_NONE;+ host->mrq->data->error = MMC_ERR_BADCRC;+ goto transfer_closed;+ }++ if(sdi_dsta & S3C2410_SDIDSTA_DATATIMEOUT) {+ host->mrq->cmd->error = MMC_ERR_NONE;+ host->mrq->data->error = MMC_ERR_TIMEOUT;+ goto transfer_closed;+ }++ if(sdi_dsta & S3C2410_SDIDSTA_XFERFINISH) {+ if(host->complete_what == COMPLETION_XFERFINISH) {+ host->mrq->cmd->error = MMC_ERR_NONE;+ host->mrq->data->error = MMC_ERR_NONE;+ goto transfer_closed;+ }++ if(host->complete_what == COMPLETION_XFERFINISH_RSPFIN) {+ host->mrq->data->error = MMC_ERR_NONE;+ host->complete_what = COMPLETION_RSPFIN;+ }++ sdi_dclear |= S3C2410_SDIDSTA_XFERFINISH;+ }++ writel(sdi_cclear, host->base + S3C2410_SDICMDSTAT);+ writel(sdi_dclear, host->base + S3C2410_SDIDSTA);++ spin_unlock_irqrestore( &host->complete_lock, iflags);+ DBG(PFX "IRQ still waiting.\n");+ return IRQ_HANDLED;+++transfer_closed:+ writel(sdi_cclear, host->base + S3C2410_SDICMDSTAT);+ writel(sdi_dclear, host->base + S3C2410_SDIDSTA);+ host->complete_what = COMPLETION_NONE;+ complete(&host->complete_request);+ writel(0, host->base + S3C2410_SDIIMSK);+ spin_unlock_irqrestore( &host->complete_lock, iflags);+ DBG(PFX "IRQ transfer closed.\n");+ return IRQ_HANDLED;+ +clear_imask:+ writel(0, host->base + S3C2410_SDIIMSK);+ spin_unlock_irqrestore( &host->complete_lock, iflags);+ DBG(PFX "IRQ clear imask.\n");+ return IRQ_HANDLED;++}+++/*+ * ISR for the CardDetect Pin+*/++static irqreturn_t s3c2410sdi_irq_cd(int irq, void *dev_id)+{+ struct s3c2410sdi_host *host = (struct s3c2410sdi_host *)dev_id;+ mmc_detect_change(host->mmc, S3C2410SDI_CDLATENCY);++ return IRQ_HANDLED;+}++++static void s3c2410sdi_dma_done_callback(struct s3c2410_dma_chan *dma_ch, void *buf_id,+ int size, enum s3c2410_dma_buffresult result)+{ unsigned long iflags;+ u32 sdi_csta, sdi_dsta,sdi_dcnt;+ struct s3c2410sdi_host *host = (struct s3c2410sdi_host *)buf_id;+ + sdi_csta = readl(host->base + S3C2410_SDICMDSTAT);+ sdi_dsta = readl(host->base + S3C2410_SDIDSTA);+ sdi_dcnt = readl(host->base + S3C2410_SDIDCNT);+
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -