📄 full.patch
字号:
+ }++ return ret;+}++static int s3c2410mci_resume(struct platform_device *dev)+{+ struct mmc_host *mmc = platform_get_drvdata(dev);+ struct s3c2410sdi_host *host;+ int ret = 0;++ if (mmc) {+ host = mmc_priv(mmc);++ enable_irq(host->irq_cd);+ enable_irq(host->irq);++ clk_enable(host->clk);++ ret = mmc_resume_host(mmc);+ }++ return ret;+}+#else+#define s3c2410mci_suspend NULL+#define s3c2410mci_resume NULL+#endif++static struct platform_driver s3c2410sdi_driver =+{+ .driver = {+ .name = "s3c2410-sdi",+ .owner = THIS_MODULE,+ },+ .probe = s3c2410sdi_probe,+ .remove = s3c2410sdi_remove,+ .suspend = s3c2410mci_suspend,+ .resume = s3c2410mci_resume,+};++static int __init s3c2410sdi_init(void)+{+ return platform_driver_register(&s3c2410sdi_driver);+}++static void __exit s3c2410sdi_exit(void)+{+ platform_driver_unregister(&s3c2410sdi_driver);+}++module_init(s3c2410sdi_init);+module_exit(s3c2410sdi_exit);++MODULE_DESCRIPTION("Samsung S3C2410 Multimedia Card Interface driver");+MODULE_LICENSE("GPL");diff --git a/drivers/mmc/s3c2410mci.h b/drivers/mmc/s3c2410mci.hnew file mode 100644index 0000000..05d440e--- /dev/null+++ b/drivers/mmc/s3c2410mci.h@@ -0,0 +1,55 @@+/*+ * 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.+ */++struct clk;++#define S3C2410SDI_DMA 0++#define S3C2410SDI_CDLATENCY 50++enum s3c2410sdi_waitfor {+ COMPLETION_NONE,+ COMPLETION_CMDSENT,+ COMPLETION_RSPFIN,+ COMPLETION_XFERFINISH,+ COMPLETION_XFERFINISH_RSPFIN,+};++typedef struct s3c24xx_mmc_platdata s3c24xx_mmc_pdata_t;++struct s3c2410sdi_host {+ struct mmc_host *mmc;+ s3c24xx_mmc_pdata_t *pdata;++ struct resource *mem;+ struct clk *clk;+ void __iomem *base;+ int irq;+ int irq_cd;+ int dma;++ struct scatterlist* cur_sg; /* Current SG entry */+ unsigned int num_sg; /* Number of entries left */+ void* mapped_sg; /* vaddr of mapped sg */++ unsigned int offset; /* Offset into current entry */+ unsigned int remain; /* Data left in curren entry */++ int size; /* Total size of transfer */++ struct mmc_request *mrq;++ unsigned char bus_width; /* Current bus width */++ spinlock_t complete_lock;+ struct completion complete_request;+ struct completion complete_dma;+ enum s3c2410sdi_waitfor complete_what;+};diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfigindex 4097a86..4703910 100644--- a/drivers/usb/gadget/Kconfig+++ b/drivers/usb/gadget/Kconfig@@ -187,6 +187,25 @@ config USB_OTG Select this only if your OMAP board has a Mini-AB connector. +config USB_GADGET_S3C2410+ boolean "S3C2410"+ depends on ARCH_S3C2410+ help+ Samsung's S3C2410 is an ARM-4 processor with an integrated+ full speed USB 1.1 device controller.+ It has 4 configurable endpoints, as well as endpoint+ zero (for control transfers).++config USB_S3C2410+ tristate+ depends on USB_GADGET_S3C2410+ default USB_GADGET+ select USB_GADGET_SELECTED++config USB_S3C2410_DEBUG+ boolean "S3C2410 udc debug messages"+ depends on USB_GADGET_S3C2410+ config USB_GADGET_AT91 boolean "AT91 USB Device Port" depends on ARCH_AT91diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefileindex e71e086..cfaf77b 100644--- a/drivers/usb/gadget/Makefile+++ b/drivers/usb/gadget/Makefile@@ -7,6 +7,7 @@ obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o obj-$(CONFIG_USB_GOKU) += goku_udc.o obj-$(CONFIG_USB_OMAP) += omap_udc.o obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o+obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o obj-$(CONFIG_USB_AT91) += at91_udc.o #diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.cnew file mode 100644index 0000000..4c2f3f1--- /dev/null+++ b/drivers/usb/gadget/s3c2410_udc.c@@ -0,0 +1,1897 @@+/*+ * linux/drivers/usb/gadget/s3c2410_udc.c+ * Samsung on-chip full speed USB device controllers+ *+ * Copyright (C) 2004-2006 Herbert P枚tzl - Arnaud Patard+ *+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA+ *+ */+#include <linux/module.h>+#include <linux/kernel.h>+#include <linux/delay.h>+#include <linux/ioport.h>+#include <linux/sched.h>+#include <linux/slab.h>+#include <linux/smp_lock.h>+#include <linux/errno.h>+#include <linux/init.h>+#include <linux/timer.h>+#include <linux/list.h>+#include <linux/interrupt.h>+#include <linux/platform_device.h>+#include <linux/version.h>+#include <linux/clk.h>++#include <linux/usb.h>+#include <linux/usb_gadget.h>++#include <asm/byteorder.h>+#include <asm/io.h>+#include <asm/irq.h>+#include <asm/system.h>+#include <asm/unaligned.h>+#include <asm/arch/irqs.h>++#include <asm/arch/hardware.h>+#include <asm/arch/regs-clock.h>+#include <asm/arch/regs-gpio.h>+#include <asm/arch/regs-udc.h>+#include <asm/arch/udc.h>++#include <asm/mach-types.h>++#include "s3c2410_udc.h"++#define ENABLE_SYSFS++#define DRIVER_DESC "S3C2410 USB Device Controller Gadget"+#define DRIVER_VERSION "30 Apr 2006"+#define DRIVER_AUTHOR "Herbert P枚tzl <herbert@13thfloor.at>, Arnaud Patard <arnaud.patard@rtp-net.org>"++static const char gadget_name [] = "s3c2410_udc";+static const char driver_desc [] = DRIVER_DESC;++static struct s3c2410_udc *the_controller;+static struct clk *udc_clock;+static struct clk *usb_bus_clock;+static void __iomem *base_addr;+static u64 rsrc_start;+static u64 rsrc_len;++static inline u32 udc_readl(u32 reg)+{+ return readl(base_addr+reg);+}+static inline void udc_writel(u32 value, u32 reg)+{+ writel(value,base_addr+reg);+}++static struct s3c2410_udc_mach_info *udc_info;++/*************************** DEBUG FUNCTION ***************************/+#define DEBUG_NORMAL 1+#define DEBUG_VERBOSE 2++#ifdef CONFIG_USB_S3C2410_DEBUG+#define USB_S3C2410_DEBUG_LEVEL 1++static uint32_t s3c2410_ticks=0;++static int dprintk(int level, const char *fmt, ...)+{+ static char printk_buf[1024];+ static long prevticks;+ static int invocation;+ va_list args;+ int len;++ if (level > USB_S3C2410_DEBUG_LEVEL)+ return 0;++ if (s3c2410_ticks != prevticks) {+ prevticks = s3c2410_ticks;+ invocation = 0;+ }++ len = scnprintf(printk_buf, \+ sizeof(printk_buf), "%1lu.%02d USB: ", \+ prevticks, invocation++);++ va_start(args, fmt);+ len = vscnprintf(printk_buf+len, \+ sizeof(printk_buf)-len, fmt, args);+ va_end(args);++ return printk("%s", printk_buf);+}+#else+static int dprintk(int level, const char *fmt, ...) { return 0; }+#endif+#ifdef ENABLE_SYSFS+static ssize_t s3c2410udc_regs_show(struct device *dev, struct device_attribute *attr, char *buf)+{+ u32 addr_reg,pwr_reg,ep_int_reg,usb_int_reg;+ u32 ep_int_en_reg, usb_int_en_reg, ep0_csr;+ u32 ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2;+ u32 ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2;++ addr_reg = udc_readl(S3C2410_UDC_FUNC_ADDR_REG);+ pwr_reg = udc_readl(S3C2410_UDC_PWR_REG);+ ep_int_reg = udc_readl(S3C2410_UDC_EP_INT_REG);+ usb_int_reg = udc_readl(S3C2410_UDC_USB_INT_REG);+ ep_int_en_reg = udc_readl(S3C2410_UDC_EP_INT_EN_REG);+ usb_int_en_reg = udc_readl(S3C2410_UDC_USB_INT_EN_REG);+ udc_writel(0, S3C2410_UDC_INDEX_REG);+ ep0_csr = udc_readl(S3C2410_UDC_IN_CSR1_REG);+ udc_writel(1, S3C2410_UDC_INDEX_REG);+ ep1_i_csr1 = udc_readl(S3C2410_UDC_IN_CSR1_REG);+ ep1_i_csr2 = udc_readl(S3C2410_UDC_IN_CSR2_REG);+ ep1_o_csr1 = udc_readl(S3C2410_UDC_IN_CSR1_REG);+ ep1_o_csr2 = udc_readl(S3C2410_UDC_IN_CSR2_REG);+ udc_writel(2, S3C2410_UDC_INDEX_REG);+ ep2_i_csr1 = udc_readl(S3C2410_UDC_IN_CSR1_REG);+ ep2_i_csr2 = udc_readl(S3C2410_UDC_IN_CSR2_REG);+ ep2_o_csr1 = udc_readl(S3C2410_UDC_IN_CSR1_REG);+ ep2_o_csr2 = udc_readl(S3C2410_UDC_IN_CSR2_REG);+++ return snprintf(buf, PAGE_SIZE, \+ "FUNC_ADDR_REG : 0x%04X\n" \+ "PWR_REG : 0x%04X\n" \+ "EP_INT_REG : 0x%04X\n" \+ "USB_INT_REG : 0x%04X\n" \+ "EP_INT_EN_REG : 0x%04X\n" \+ "USB_INT_EN_REG : 0x%04X\n" \+ "EP0_CSR : 0x%04X\n" \+ "EP1_I_CSR1 : 0x%04X\n" \+ "EP1_I_CSR2 : 0x%04X\n" \+ "EP1_O_CSR1 : 0x%04X\n" \+ "EP1_O_CSR2 : 0x%04X\n" \+ "EP2_I_CSR1 : 0x%04X\n" \+ "EP2_I_CSR2 : 0x%04X\n" \+ "EP2_O_CSR1 : 0x%04X\n" \+ "EP2_O_CSR2 : 0x%04X\n", \+ addr_reg,pwr_reg,ep_int_reg,usb_int_reg, \+ ep_int_en_reg, usb_int_en_reg, ep0_csr, \+ ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2, \+ ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2 \+ );+}++static DEVICE_ATTR(regs, 0444,+ s3c2410udc_regs_show,+ NULL);+#endif+/*------------------------- I/O ----------------------------------*/+static void done(struct s3c2410_ep *ep, struct s3c2410_request *req, int status);+static void nuke (struct s3c2410_udc *udc, struct s3c2410_ep *ep, int status)+{+ /* Sanity check */+ if (&ep->queue != NULL)+ while (!list_empty (&ep->queue)) {+ struct s3c2410_request *req;+ req = list_entry (ep->queue.next, struct s3c2410_request, queue);+ done(ep,req,status);+ }+}++/*+ * done+ */+static void done(struct s3c2410_ep *ep, struct s3c2410_request *req, int status)+{+ unsigned halted = ep->halted;++ list_del_init(&req->queue);++ if (likely (req->req.status == -EINPROGRESS))+ req->req.status = status;+ else+ status = req->req.status;++ ep->halted = 1;+ req->req.complete(&ep->ep, &req->req);+ ep->halted = halted;+}++static inline void clear_ep_state (struct s3c2410_udc *dev)+{+ unsigned i;++ /* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint+ * fifos, and pending transactions mustn't be continued in any case.+ */+ for (i = 1; i < S3C2410_ENDPOINTS; i++)+ nuke(dev, &dev->ep[i], -ECONNABORTED);+}++static inline int fifo_count_out(void)+{+ int tmp;++ tmp = udc_readl(S3C2410_UDC_OUT_FIFO_CNT2_REG) << 8;+ tmp |= udc_readl(S3C2410_UDC_OUT_FIFO_CNT1_REG);++ return tmp & 0xffff;+}++/*+ * write_packet+ */+static inline int+write_packet(int fifo, struct s3c2410_request *req, unsigned max)+{+ unsigned len;+ u8 *buf;++ buf = req->req.buf + req->req.actual;+ prefetch(buf);++ len = min(req->req.length - req->req.actual, max);+ dprintk(DEBUG_VERBOSE, "write_packet %d %d %d ",req->req.actual,req->req.length,len);+ req->req.actual += len;+ dprintk(DEBUG_VERBOSE, "%d\n",req->req.actual);++ writesb(base_addr+fifo, buf, len);+ return len;+}++static void udc_reinit(struct s3c2410_udc *dev);++/*+ * write_fifo+ *+ * return: 0 = still running, 1 = completed, negative = errno+ */+static int write_fifo(struct s3c2410_ep *ep, struct s3c2410_request *req)+{+ unsigned count;+ int is_last;+ u32 idx;+ int fifo_reg;+ u32 ep_csr;+++ switch(ep->bEndpointAddress&0x7F)+ {+ default:+ case 0: idx = 0;+ fifo_reg = S3C2410_UDC_EP0_FIFO_REG;+ break;+ case 1:+ idx = 1;+ fifo_reg = S3C2410_UDC_EP1_FIFO_REG;+ break;+ case 2:+ idx = 2;+ fifo_reg = S3C2410_UDC_EP2_FIFO_REG;+ break;++ case 3:+ idx = 3;+ fifo_reg = S3C2410_UDC_EP3_FIFO_REG;+ break;++ case 4:+ idx = 4;+ fifo_reg = S3C2410_UDC_EP4_FIFO_REG;+ break;+ }++ count = write_packet(fifo_reg, req, ep->ep.maxpacket);++ /* last packet is often short (sometimes a zlp) */+ if (count != ep->ep.maxpacket)+ is_last = 1;+ else if (req->req.length != req->req.actual || req->req.zero)+ is_last = 0;+ else+ is_last = 2;++ /* Only ep0 debug messages are interesting */+ if (!idx)+ dprintk(DEBUG_NORMAL, "Written ep%d %d.%d of %d b [last %d,z %d]\n",idx,count,req->req.actual,req->req.length,is_last,req->req.zero);++ if (is_last)+ {+ /* The order is important. It prevents to send 2 packet at the same time+ **/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -