📄 atheros_2_0_hcd.patch
字号:
++ if (request_irq(context->io_irq, s3c24xx_hcd_irq, 0, context->description, context)) {+ DBG_PRINT(SDDBG_ERROR, ("failed to request mci interrupt.\n"));+ status = -ENOENT;+ goto out_unmap_mem_region;+ }+++ /* DMA */+ context->io_buffer_size = 4 * 4096;+ context->io_buffer = dma_alloc_writecombine(&context->pdev->dev,+ context->io_buffer_size,+ &context->io_buffer_dma,+ GFP_KERNEL | GFP_DMA);++ if (context->io_buffer == NULL) {+ DBG_PRINT(SDDBG_ERROR, ("failed to allocate DMA buffer\n"));+ status = -ENOMEM;+ goto out_free_irq;++ }++ if (s3c2410_dma_request(context->dma_channel, &s3c24xx_hcd_dma_client, NULL)) {+ DBG_PRINT(SDDBG_ERROR, ("unable to get DMA channel.\n"));+ status = -ENOENT;+ goto out_free_dma;+ }+++ /* Set multiplexing */+ s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);+ s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);+ s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);+ s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);+ s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);+ s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);++ con = readl(context->base + S3C2410_SDICON);+ con |= S3C2410_SDICON_SDIOIRQ;+ writel(con, context->base + S3C2410_SDICON);++ datacon = readl(context->base + S3C2410_SDIDCON);+ datacon |= S3C2410_SDIDCON_WIDEBUS;+ writel(datacon, context->base + S3C2410_SDIDCON);++ printk("S3c24xx SDIO: IRQ:%d Detect IRQ:%d DMA channel:%d base@0x%p PCLK@%ld kHz\n",+ context->io_irq, context->cd_irq, context->dma_channel, context->base,+ context->device.max_clock_rate/1000);++ return SDIOErrorToOSError(status);++ out_free_dma:+ dma_free_writecombine(&context->pdev->dev,context->io_buffer_size,+ context->io_buffer, context->io_buffer_dma);++ out_free_irq:+ free_irq(context->io_irq, context);++ out_unmap_mem_region:+ iounmap(context->base);++ out_free_mem_region:+ release_mem_region(context->mem->start, RESSIZE(context->mem));++ out_disable_clock:+ clk_disable(context->device.clock);++ return SDIOErrorToOSError(status);+}++static void s3c24xx_hcd_hw_cleanup(struct s3c24xx_hcd_context * context)+{+ clk_disable(context->device.clock);+ free_irq(context->io_irq, context);+ iounmap(context->base);+ release_mem_region(context->mem->start, RESSIZE(context->mem));+ dma_free_writecombine(&context->pdev->dev,context->io_buffer_size,+ context->io_buffer, context->io_buffer_dma);+}++static int s3c24xx_hcd_pnp_probe(struct pnp_dev *pBusDevice, const struct pnp_device_id *pId)+{+ SDIO_STATUS status = SDIO_STATUS_SUCCESS;++ status = s3c24xx_hcd_hw_init(&hcd_context);+ if (SDIO_IS_ERROR(status)) {+ DBG_PRINT(SDDBG_ERROR, ("HW Init failed\n"));+ return SDIOErrorToOSError(status);+ }++ status = SDIO_RegisterHostController(&hcd_context.hcd);+ if (SDIO_IS_ERROR(status)) {+ DBG_PRINT(SDDBG_ERROR, ("Host registration failed\n"));+ s3c24xx_hcd_hw_cleanup(&hcd_context);+ return SDIOErrorToOSError(status);+ }++ /* Our card is built-in, we force the attachement event */+ SDIO_HandleHcdEvent(&hcd_context.hcd, EVENT_HCD_ATTACH);++ return 0;+}++static void s3c24xx_hcd_pnp_remove(struct pnp_dev *pBusDevice)+{+}++/* the driver context data */+struct s3c24xx_hcd_context hcd_context = {+ .description = DESCRIPTION,+ .hcd.pName = "sdio_s3c24xx",+ .hcd.Version = CT_SDIO_STACK_VERSION_CODE,+ .hcd.pModule = THIS_MODULE,+ /* builtin card, 4 bits bus */+ .hcd.Attributes = SDHCD_ATTRIB_BUS_4BIT | SDHCD_ATTRIB_BUS_1BIT | SDHCD_ATTRIB_MULTI_BLK_IRQ,+ .hcd.SlotNumber = 0,+ .hcd.MaxSlotCurrent = 500, /* 1/2 amp */+ .hcd.SlotVoltageCaps = SLOT_POWER_3_3V, /* 3.3V */+ .hcd.SlotVoltagePreferred = SLOT_POWER_3_3V, /* 3.3V */+ .hcd.MaxClockRate = 25000000,+ .hcd.MaxBytesPerBlock = 0xfff, /* 0 - 4095 */+ .hcd.MaxBlocksPerTrans = 0xfff, /* 0 - 4095 */+ .hcd.pContext = &hcd_context,+ .hcd.pRequest = s3c24xx_hcd_request,+ .hcd.pConfigure = s3c24xx_hcd_config,+ .device.pnp_device.name = "sdio_s3c24xx_hcd",+ .device.pnp_driver.name = "sdio_s3c24xx_hcd",+ .device.pnp_driver.probe = s3c24xx_hcd_pnp_probe,+ .device.pnp_driver.remove = s3c24xx_hcd_pnp_remove,+};++static int s3c24xx_hcd_probe(struct platform_device * pdev)+{+ SDIO_STATUS status = SDIO_STATUS_SUCCESS;+ struct resource *r = NULL;++ printk("S3c2440 SDIO Host controller\n");++ hcd_context.pdev = pdev;++ hcd_context.mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);+ if (hcd_context.mem == NULL) {+ DBG_PRINT(SDDBG_ERROR, ("No memory region\n"));+ status = SDIO_STATUS_NO_RESOURCES;+ goto out;+ }++ hcd_context.io_irq = platform_get_irq(pdev, 0);+ if (hcd_context.io_irq == 0) {+ DBG_PRINT(SDDBG_ERROR, ("No IRQ\n"));+ status = SDIO_STATUS_NO_RESOURCES;+ goto out;+ }++ r = platform_get_resource(pdev, IORESOURCE_DMA, 0);+ if (r == NULL) {+ DBG_PRINT(SDDBG_ERROR, ("No DMA channel\n"));+ status = SDIO_STATUS_NO_RESOURCES;+ goto out;+ }+ hcd_context.dma_channel = r->start;+ hcd_context.dma_en = 0;++ hcd_context.int_sdio = 0;++ spin_lock_init(&hcd_context.lock);++ init_completion(&hcd_context.dma_complete);+ init_completion(&hcd_context.xfer_complete);++ INIT_WORK(&hcd_context.io_work, s3c24xx_hcd_io_work);+ INIT_WORK(&hcd_context.irq_work, s3c24xx_hcd_irq_work);++ mdelay(100);++ status = SDIO_BusAddOSDevice(&hcd_context.device.dma,+ &hcd_context.device.pnp_driver,+ &hcd_context.device.pnp_device);++ out:++ return SDIOErrorToOSError(status);+}++/*+ * module cleanup+ */+static int s3c24xx_hcd_remove(struct platform_device * pdev) {+ printk("S3C2440 SDIO host controller unloaded\n");+ SDIO_BusRemoveOSDevice(&hcd_context.device.pnp_driver, &hcd_context.device.pnp_device);++ return 0;+}++static struct platform_driver s3c24xx_hcd_sdio =+{+ .driver.name = "s3c24xx-sdio",+ .probe = s3c24xx_hcd_probe,+ .remove = s3c24xx_hcd_remove,+};++#ifdef CONFIG_DEBUG_FS+static struct dentry *debugfs_dir;++static int s3c24xx_hcd_debugfs_show(struct seq_file *s, void *data)+{+ PSDREQUEST req;+ u32 con, pre, cmdarg, cmdcon, cmdsta, r0, r1, r2, r3, timer, bsize;+ u32 datcon, datcnt, datsta, fsta, imask;+ struct s3c24xx_hcd_context * context = &hcd_context;+++ 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);++ seq_printf(s, "SDICON: 0x%08x\n", con);+ seq_printf(s, "SDIPRE: 0x%08x\n", pre);+ seq_printf(s, "SDICmdArg: 0x%08x\n", cmdarg);+ seq_printf(s, "SDICmdCon: 0x%08x\n", cmdcon);+ seq_printf(s, "SDICmdSta: 0x%08x\n", cmdsta);+ seq_printf(s, "SDIRSP0: 0x%08x\n", r0);+ seq_printf(s, "SDIRSP1: 0x%08x\n", r1);+ seq_printf(s, "SDIRSP2: 0x%08x\n", r2);+ seq_printf(s, "SDIRSP3: 0x%08x\n", r3);+ seq_printf(s, "SDIDTimer: 0x%08x\n", timer);+ seq_printf(s, "SDIBSize: 0x%08x\n", bsize);+ seq_printf(s, "SDIDatCon: 0x%08x\n", datcon);+ seq_printf(s, "SDIDatCnt: 0x%08x\n", datcnt);+ seq_printf(s, "SDIDatSta: 0x%08x\n", datsta);+ seq_printf(s, "SDIFSta: 0x%08x\n", fsta);+ seq_printf(s, "SDIIntMsk: 0x%08x\n", imask);+ seq_printf(s, "\n");++ seq_printf(s, "Current REQ: \n");+ req = GET_CURRENT_REQUEST(&context->hcd);+ if (req == NULL) {+ seq_printf(s, " No current request\n");+ } else {+ seq_printf(s, " Command: %d\n", req->Command);+ seq_printf(s, " Args: 0x%x\n", req->Argument);+ seq_printf(s, " Flags: 0x%x\n", req->Flags);+ seq_printf(s, " %d blocks x %d bytes\n", req->BlockCount, req->BlockLen);+ seq_printf(s, " %d bytes remaining\n", req->DataRemaining);+ }++ seq_printf(s, "Context: \n");+ seq_printf(s, " INT mask: 0x%x\n", context->int_mask);+ seq_printf(s, " sdio INT: %d\n", context->int_sdio);+ seq_printf(s, " cmdsta: 0x%x\n", context->cmdsta);+ seq_printf(s, " dsta: 0x%x\n", context->dsta);+ seq_printf(s, " fsta: 0x%x\n", context->fsta);++ return 0;+}++static int s3c24xx_hcd_debugfs_open(struct inode *inode,+ struct file *file)+{+ return single_open(file, s3c24xx_hcd_debugfs_show, NULL);+}++static const struct file_operations s3c24xx_hcd_debugfs_fops = {+ .open = s3c24xx_hcd_debugfs_open,+ .read = seq_read,+ .llseek = seq_lseek,+ .release = single_release,+ .owner = THIS_MODULE,+};+++static int s3c24xx_debugfs_init(struct s3c24xx_hcd_context * context)+{+ debugfs_dir = debugfs_create_dir("s3c24xx_sdio", NULL);++ debugfs_create_file("registers", 0444, debugfs_dir,+ (void *)context,+ &s3c24xx_hcd_debugfs_fops);++ return 0;+}++#else++static int s3c24xx_debugfs_init(struct s3c24xx_hcd_context * context)+{+ return 0;+}++#endif++static int __init s3c24xx_hcd_init(void)+{+ int ret;++ ret = s3c24xx_debugfs_init(&hcd_context);+ if (ret) {+ printk("%s(): debugfs init failed\n", __FUNCTION__);+ }++ platform_driver_register(&s3c24xx_hcd_sdio);++ return 0;+}++static void __exit s3c24xx_hcd_exit(void)+{+ platform_driver_unregister(&s3c24xx_hcd_sdio);+}+++MODULE_LICENSE("GPL");+MODULE_DESCRIPTION(DESCRIPTION);+MODULE_AUTHOR(AUTHOR);++module_init(s3c24xx_hcd_init);+module_exit(s3c24xx_hcd_exit);Index: linux-2.6.24/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.h===================================================================--- /dev/null+++ linux-2.6.24/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.h@@ -0,0 +1,67 @@+#ifndef __SDIO_S3C24XX_HCD_H___+#define __SDIO_S3C24XX_HCD_H___++#define S3C24XX_HCD_NO_RESPONSE 1+#define S3C24XX_HCD_RESPONSE_SHORT 2+#define S3C24XX_HCD_RESPONSE_LONG 3+#define S3C24XX_HCD_DATA_READ 4+#define S3C24XX_HCD_DATA_WRITE 5++struct s3c24xx_hcd_device {+ OS_PNPDEVICE pnp_device; /* the OS device for this HCD */+ OS_PNPDRIVER pnp_driver; /* the OS driver for this HCD */+ SDDMA_DESCRIPTION dma;+ struct clk * clock;+ unsigned long max_clock_rate;+ unsigned long actual_clock_rate;+};+++/* driver wide data, this driver only supports one device,+ * so we include the per device data here also */+struct s3c24xx_hcd_context {+ PTEXT description; /* human readable device decsription */+ SDHCD hcd; /* HCD description for bus driver */+ struct s3c24xx_hcd_device device; /* the single device's info */+ struct platform_device *pdev;+ struct resource *mem;+ void __iomem *base;+ UINT32 io_irq;+ UINT32 cd_irq;+ BOOL card_inserted; /* card inserted flag */+ BOOL cmd_processed; /* command phase was processed */+ UINT32 fifo_depth; /* FIFO depth for the bus mode */+ BOOL irq_masked;+ UINT32 bus_width;+ UINT32 data_size; /* Word, half word, or byte */+ UINT32 latest_xfer_size;++ void *io_buffer; /* Kernel address */+ dma_addr_t io_buffer_dma; /* Bus address */+ UINT32 io_buffer_size;+ UINT32 dma_channel;+ UINT32 dma_en;+ struct completion dma_complete;+ struct completion xfer_complete;++ UINT32 int_mask;+ UINT32 int_sdio; /* Do we have SDIO interrupt on ? */++ UINT32 complete;++ UINT32 cmdsta;+ UINT32 dsta;+ UINT32 fsta;++ spinlock_t lock;++ struct work_struct io_work;+ struct work_struct irq_work;+};++SDIO_STATUS s3c24xx_hcd_config(PSDHCD hcd, PSDCONFIG config);+SDIO_STATUS s3c24xx_hcd_request(PSDHCD hcd);++struct s3c24xx_hcd_context hcd_context;++#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -