⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmc.patch

📁 patches for linux-2.6.
💻 PATCH
📖 第 1 页 / 共 3 页
字号:
+}++static dbdev_tab_t au1xmmc_mem_dbdev = {+	DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 8, 0x00000000, 0, 0+};++static void au1xmmc_init_dma(struct au1xmmc_host *host) {+	+	u32 rxchan, txchan;+	+	int txid = au1xmmc_card_table[host->id].tx_devid;+	int rxid = au1xmmc_card_table[host->id].rx_devid;+	+	/* DSCR_CMD0_ALWAYS has a stride of 32 bits, we need a stride+	   of 8 bits.  And since devices are shared, we need to create+	   our own to avoid freaking out other devices+	*/+	+	int memid = au1xxx_ddma_add_device(&au1xmmc_mem_dbdev);+		+	txchan = au1xxx_dbdma_chan_alloc(memid, txid, +					 au1xmmc_dma_callback, (void *) host);++	rxchan = au1xxx_dbdma_chan_alloc(rxid, memid, +					 au1xmmc_dma_callback, (void *) host);++	au1xxx_dbdma_set_devwidth(txchan, 8);+	au1xxx_dbdma_set_devwidth(rxchan, 8);++	au1xxx_dbdma_ring_alloc(txchan, AU1XMMC_DESCRIPTOR_COUNT);+	au1xxx_dbdma_ring_alloc(rxchan, AU1XMMC_DESCRIPTOR_COUNT);++	host->tx_chan = txchan;+	host->rx_chan = rxchan;+}++struct mmc_host_ops au1xmmc_ops = {+	.request	= au1xmmc_request,+	.set_ios	= au1xmmc_set_ios,+};++static int au1xmmc_probe(struct device *dev) {++	int i, ret = 0;++	/* THe interrupt is shared among all controllers */+	ret = request_irq(AU1100_SD_IRQ, au1xmmc_irq, SA_INTERRUPT, "MMC", 0);+  +	if (ret) {+		printk(DRIVER_NAME " ERROR:  Couldn't get the interrupt %d: %d\n", AU1100_SD_IRQ, ret);+		return -ENXIO;+	}++	disable_irq(AU1100_SD_IRQ);++	for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {+		struct mmc_host *mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), dev);+		struct au1xmmc_host *host = 0;++		if (!mmc) {+			printk(DRIVER_NAME " ERROR:  Unable to allocate enough memory for host %d\n", i);+			au1xmmc_hosts[i] = 0;+			continue;+		}++		mmc->ops = &au1xmmc_ops;+   +		mmc->f_min =   450000;+		mmc->f_max = 24000000;++		mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE;+		mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT; ++		mmc->ocr_avail = AU1XMMC_OCR;++		host = mmc_priv(mmc);+		host->mmc = mmc;++		host->id = i;+		host->iobase = au1xmmc_card_table[host->id].iobase;+		host->clock = 0;+		host->power_mode = MMC_POWER_OFF;+		+		host->flags = au1xmmc_card_inserted(host) ? HOST_F_ACTIVE : 0;+		host->status = HOST_S_IDLE;++		init_timer(&host->timer);++		host->timer.function = au1xmmc_poll_event;+		host->timer.data = (unsigned long) host;+		host->timer.expires = jiffies + AU1XMMC_DETECT_TIMEOUT;++		tasklet_init(&host->data_task, au1xmmc_tasklet_data, +				(unsigned long) host);++		tasklet_init(&host->finish_task, au1xmmc_tasklet_finish, +				(unsigned long) host);++		spin_lock_init(&host->lock);++		if (dma != 0)+			au1xmmc_init_dma(host);++		au1xmmc_reset_controller(host);++		mmc_add_host(mmc);+		au1xmmc_hosts[i] = host;++		add_timer(&host->timer);++		printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X (mode=%s)\n",+		       host->id, host->iobase, dma ? "dma" : "pio");+	}+  +	enable_irq(AU1100_SD_IRQ);++	return 0;+}+    +static int au1xmmc_remove(struct device *dev) {+ +	int i;++	disable_irq(AU1100_SD_IRQ);+  +	for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) {+		struct au1xmmc_host *host = au1xmmc_hosts[i];+		if (!host) continue;++		tasklet_kill(&host->data_task);+		tasklet_kill(&host->finish_task);++		del_timer_sync(&host->timer);+		au1xmmc_set_power(host, 0);+		+		mmc_remove_host(host->mmc);+    +		au1xxx_dbdma_chan_free(host->tx_chan);+		au1xxx_dbdma_chan_free(host->rx_chan);+   +		au_writel(0x0, HOST_ENABLE(host));+		au_sync();	+	} ++	free_irq(AU1100_SD_IRQ, 0);+	return 0;+}++static struct device_driver au1xmmc_driver = {+	.name          = DRIVER_NAME,+	.bus           = &platform_bus_type,+	.probe         = au1xmmc_probe,+	.remove        = au1xmmc_remove,+	.suspend       = NULL,+	.resume        = NULL+};++#ifdef CONFIG_PM+int au1xmmc_pm_callback(au1xxx_power_dev_t *dev, +		au1xxx_request_t request, +		void *data) {+	int retval = -1;+	unsigned int addr = 0;++	DEBUG("Entering au1xmmc_pm_callback to service request type: %d\n", request);+     +	 struct au1xmmc_host *host=au1xmmc_hosts[0];+	+	if (request == AU1XXX_PM_SLEEP) {+		/* Save the SD/MMC registers */+		/* Slot 0*/+		addr = SD0_BASE;+		sleep_sd0[0] = au_readl(addr + SD_CONFIG);+		sleep_sd0[1] = au_readl(addr + SD_ENABLE);+		sleep_sd0[2] = au_readl(addr + SD_CONFIG2);+		sleep_sd0[3] = au_readl(addr + SD_BLKSIZE);+		sleep_sd0[4] = au_readl(addr + SD_STATUS);+		sleep_sd0[5] = au_readl(addr + SD_CMD);+		sleep_sd0[6] = au_readl(addr + SD_CMDARG);+		sleep_sd0[7] = au_readl(addr + SD_TIMEOUT);+	+		/* Slot 1 */+#if defined (CONFIG_MIPS_PB1200)+		addr = SD1_BASE;+		sleep_sd1[0] = au_readl(addr + SD_CONFIG);+		sleep_sd1[1] = au_readl(addr + SD_ENABLE);+		sleep_sd1[2] = au_readl(addr + SD_CONFIG2);+		sleep_sd1[3] = au_readl(addr + SD_BLKSIZE);+		sleep_sd1[4] = au_readl(addr + SD_STATUS);+		sleep_sd1[5] = au_readl(addr + SD_CMD);+		sleep_sd1[6] = au_readl(addr + SD_CMDARG);+		sleep_sd1[7] = au_readl(addr + SD_TIMEOUT);+#endif+	   card_inserted = au1xmmc_card_inserted(host);+	   +	   if(card_inserted){ +			mmc_suspend_host(host->mmc, NULL);+		}+	}+	else if (request == AU1XXX_PM_WAKEUP) {+		if(dev->prev_state == SLEEP_STATE)+		{+			/* Restoring MMSC/SD registers */+			/* Slot 0*/+			addr = SD0_BASE;+			au_writel(sleep_sd0[0], addr + SD_CONFIG);+			au_writel(sleep_sd0[1], addr + SD_ENABLE);+			au_writel(sleep_sd0[2], addr + SD_CONFIG2);+			au_writel(sleep_sd0[3], addr + SD_BLKSIZE);+			au_writel(sleep_sd0[4], addr + SD_STATUS);+			au_writel(sleep_sd0[5], addr + SD_CMD);+			au_writel(sleep_sd0[6], addr + SD_CMDARG);+			au_writel(sleep_sd0[7], addr + SD_TIMEOUT);+															   	+			/* Slot 1 */+#if defined (CONFIG_MIPS_PB1200)+			addr = SD1_BASE;+			au_writel(sleep_sd1[0], addr + SD_CONFIG);+			au_writel(sleep_sd1[1], addr + SD_ENABLE);+			au_writel(sleep_sd1[2], addr + SD_CONFIG2);+			au_writel(sleep_sd1[3], addr + SD_BLKSIZE);+			au_writel(sleep_sd1[4], addr + SD_STATUS);+			au_writel(sleep_sd1[5], addr + SD_CMD);+			au_writel(sleep_sd1[6], addr + SD_CMDARG);+			au_writel(sleep_sd1[7], addr + SD_TIMEOUT);+#endif+   			card_detected = au1xmmc_card_inserted(host);+   			+			if(card_detected !=card_inserted){+				struct mmc_request *mrq = host->mrq;+		   +		 	  	host->mrq=NULL; +		 	 	host->flags &= HOST_F_ACTIVE; +		  		host->dma.len = 0;+				host->dma.dir = 0;+				host->status = HOST_S_IDLE;+				bcsr->disk_leds |= (1 << 8);+				mmc_request_done(host->mmc, mrq);++			}+       		mmc_resume_host(host->mmc);++			host->clock = 0;+    	 }+	}+	else if (request == AU1XXX_PM_GETSTATUS) {+		return dev->cur_state;+	}+	else if (request == AU1XXX_PM_ACCESS) {+		if (dev->cur_state != SLEEP_STATE)+			return retval;+		else {+			/* Restoring MMSC/SD registers */+			/* Slot 0*/+			addr = SD0_BASE;+			au_writel(sleep_sd0[0], addr + SD_CONFIG);+			au_writel(sleep_sd0[1], addr + SD_ENABLE);+			au_writel(sleep_sd0[2], addr + SD_CONFIG2);+			au_writel(sleep_sd0[3], addr + SD_BLKSIZE);+			au_writel(sleep_sd0[4], addr + SD_STATUS);+			au_writel(sleep_sd0[5], addr + SD_CMD);+			au_writel(sleep_sd0[6], addr + SD_CMDARG);+			au_writel(sleep_sd0[7], addr + SD_TIMEOUT);+															   	+			/* Slot 1 */+#if defined (CONFIG_MIPS_PB1200)+			addr = SD1_BASE;+			au_writel(sleep_sd1[0], addr + SD_CONFIG);+			au_writel(sleep_sd1[1], addr + SD_ENABLE);+			au_writel(sleep_sd1[2], addr + SD_CONFIG2);+			au_writel(sleep_sd1[3], addr + SD_BLKSIZE);+			au_writel(sleep_sd1[4], addr + SD_STATUS);+			au_writel(sleep_sd1[5], addr + SD_CMD);+			au_writel(sleep_sd1[6], addr + SD_CMDARG);+			au_writel(sleep_sd1[7], addr + SD_TIMEOUT);+#endif	+			mmc_resume_host(host->mmc);	+		}+	}+	else if (request == AU1XXX_PM_IDLE) {+		/* do nothing */+	}+	else if (request == AU1XXX_PM_CLEANUP) {+		/* do nothing */+	}++	return retval; +}+#endif+++static int __init au1xmmc_init(void) {+#ifdef CONFIG_PM+	mmc_pm_dev = new_au1xxx_power_device("mmc", &au1xmmc_pm_callback, NULL);+	if ( mmc_pm_dev == NULL)+		printk(KERN_INFO "Unable to create a power management device entry for the au1xmmc.\n");+	else+		printk(KERN_INFO "Power management device entry for the au1xmmc loaded.\n");+#endif++	return driver_register(&au1xmmc_driver);+}++static void __exit au1xmmc_exit(void) {+	driver_unregister(&au1xmmc_driver);+}++module_init(au1xmmc_init);+module_exit(au1xmmc_exit);++#ifdef MODULE+MODULE_AUTHOR("Advanced Micro Devices, Inc");+MODULE_DESCRIPTION("MMC/SD driver for the Alchemy Au1XXX");+MODULE_LICENSE("GPL");+#endif+diff -Nbur linux26-cvs/drivers/mmc/au1xmmc.h linux26-cvs.PMMMC/drivers/mmc/au1xmmc.h--- linux26-cvs/drivers/mmc/au1xmmc.h	1969-12-31 18:00:00.000000000 -0600+++ linux26-cvs.PMMMC/drivers/mmc/au1xmmc.h	2005-08-16 10:58:38.000000000 -0500@@ -0,0 +1,96 @@+#ifndef _AU1XMMC_H_+#define _AU1XMMC_H_++/* Hardware definitions */++#define AU1XMMC_DESCRIPTOR_COUNT 1+#define AU1XMMC_DESCRIPTOR_SIZE  2048++#define AU1XMMC_OCR ( MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30  | \+		      MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33  | \+		      MMC_VDD_33_34 | MMC_VDD_34_35 | MMC_VDD_35_36)++/* Easy access macros */++#define HOST_STATUS(h)	((h)->iobase + SD_STATUS)+#define HOST_CONFIG(h)	((h)->iobase + SD_CONFIG)+#define HOST_ENABLE(h)	((h)->iobase + SD_ENABLE)+#define HOST_TXPORT(h)	((h)->iobase + SD_TXPORT)+#define HOST_RXPORT(h)	((h)->iobase + SD_RXPORT)+#define HOST_CMDARG(h)	((h)->iobase + SD_CMDARG)+#define HOST_BLKSIZE(h)	((h)->iobase + SD_BLKSIZE)+#define HOST_CMD(h)	((h)->iobase + SD_CMD)+#define HOST_CONFIG2(h)	((h)->iobase + SD_CONFIG2)+#define HOST_TIMEOUT(h)	((h)->iobase + SD_TIMEOUT)+#define HOST_DEBUG(h)	((h)->iobase + SD_DEBUG)++#define DMA_CHANNEL(h) \+	( ((h)->flags & HOST_F_XMIT) ? (h)->tx_chan : (h)->rx_chan)++/* This gives us a hard value for the stop command that we can write directly+ * to the command register+ */++#define STOP_CMD (SD_CMD_RT_1B|SD_CMD_CT_7|(0xC << SD_CMD_CI_SHIFT)|SD_CMD_GO)++/* This is the set of interrupts that we configure by default */++#if 0+#define AU1XMMC_INTERRUPTS (SD_CONFIG_SC | SD_CONFIG_DT | SD_CONFIG_DD | \+		SD_CONFIG_RAT | SD_CONFIG_CR | SD_CONFIG_I)+#endif++#define AU1XMMC_INTERRUPTS (SD_CONFIG_SC | SD_CONFIG_DT | \+		SD_CONFIG_RAT | SD_CONFIG_CR | SD_CONFIG_I)+/* The poll event (looking for insert/remove events runs twice a second */+#define AU1XMMC_DETECT_TIMEOUT (HZ/2)++struct au1xmmc_host {+  struct mmc_host *mmc;+  struct mmc_request *mrq;++  u32 id;++  u32 flags;+  u32 iobase;+  u32 clock;+  u32 bus_width;+  u32 power_mode;++  int status;++   struct {+	   int len;+	   int dir;+  } dma;++   struct {+	   int index;+	   int offset;+	   int len;+  } pio;++  u32 tx_chan;+  u32 rx_chan;++  struct timer_list timer;+  struct tasklet_struct finish_task;+  struct tasklet_struct data_task;++  spinlock_t lock;+};++/* Status flags used by the host structure */++#define HOST_F_XMIT   0x0001+#define HOST_F_RECV   0x0002+#define HOST_F_DMA    0x0010+#define HOST_F_ACTIVE 0x0100+#define HOST_F_STOP   0x1000++#define HOST_S_IDLE   0x0001+#define HOST_S_CMD    0x0002+#define HOST_S_DATA   0x0003+#define HOST_S_STOP   0x0004++#endifdiff -Nbur linux26-cvs/drivers/mmc/Kconfig linux26-cvs.PMMMC/drivers/mmc/Kconfig--- linux26-cvs/drivers/mmc/Kconfig	2005-08-16 12:33:40.000000000 -0500+++ linux26-cvs.PMMMC/drivers/mmc/Kconfig	2005-08-16 10:58:38.000000000 -0500@@ -60,4 +60,13 @@  	  If unsure, say N. +config MMC_AU1X+	tristate "Alchemy AU1XX0 MMC Card Interface support"+	depends on SOC_AU1X00 && MMC+	help+	  This selects the AMD Alchemy(R) Multimedia card interface.+	  iIf you have a Alchemy platform with a MMC slot, say Y or M here.++	  If unsure, say N.+ endmenudiff -Nbur linux26-cvs/drivers/mmc/Makefile linux26-cvs.PMMMC/drivers/mmc/Makefile--- linux26-cvs/drivers/mmc/Makefile	2005-08-16 12:33:40.000000000 -0500+++ linux26-cvs.PMMMC/drivers/mmc/Makefile	2005-08-16 10:58:38.000000000 -0500@@ -18,5 +18,6 @@ obj-$(CONFIG_MMC_ARMMMCI)	+= mmci.o obj-$(CONFIG_MMC_PXA)		+= pxamci.o obj-$(CONFIG_MMC_WBSD)		+= wbsd.o+obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o  mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -