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

📄 pmc551.c

📁 基于linux-2.6.28的mtd驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
	 *	 * KLUDGE ALERT: the boards we are using have invalid column and	 * row mux values.  We fix them here, but this will break other	 * memory configurations.	 */	pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data);	size = PMC551_DRAM_BLK_GET_SIZE(dram_data);	dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);	dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);	pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data);	pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data);	size += PMC551_DRAM_BLK_GET_SIZE(dram_data);	dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);	dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);	pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data);	pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data);	size += PMC551_DRAM_BLK_GET_SIZE(dram_data);	dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);	dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);	pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data);	pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data);	size += PMC551_DRAM_BLK_GET_SIZE(dram_data);	dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);	dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);	pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data);	/*	 * Oops .. something went wrong	 */	if ((size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) {		return -ENODEV;	}#endif				/* CONFIG_MTD_PMC551_BUGFIX */	if ((cfg & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) {		return -ENODEV;	}	/*	 * Precharge Dram	 */	pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0400);	pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x00bf);	/*	 * Wait until command has gone through	 * FIXME: register spinning issue	 */	do {		pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);		if (counter++ > 100)			break;	} while ((PCI_COMMAND_IO) & cmd);	/*	 * Turn on auto refresh	 * The loop is taken directly from Ramix's example code.  I assume that	 * this must be held high for some duration of time, but I can find no	 * documentation refrencing the reasons why.	 */	for (i = 1; i <= 8; i++) {		pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0df);		/*		 * Make certain command has gone through		 * FIXME: register spinning issue		 */		counter = 0;		do {			pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);			if (counter++ > 100)				break;		} while ((PCI_COMMAND_IO) & cmd);	}	pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0020);	pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0ff);	/*	 * Wait until command completes	 * FIXME: register spinning issue	 */	counter = 0;	do {		pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);		if (counter++ > 100)			break;	} while ((PCI_COMMAND_IO) & cmd);	pci_read_config_dword(dev, PMC551_DRAM_CFG, &dcmd);	dcmd |= 0x02000000;	pci_write_config_dword(dev, PMC551_DRAM_CFG, dcmd);	/*	 * Check to make certain fast back-to-back, if not	 * then set it so	 */	pci_read_config_word(dev, PCI_STATUS, &cmd);	if ((cmd & PCI_COMMAND_FAST_BACK) == 0) {		cmd |= PCI_COMMAND_FAST_BACK;		pci_write_config_word(dev, PCI_STATUS, cmd);	}	/*	 * Check to make certain the DEVSEL is set correctly, this device	 * has a tendancy to assert DEVSEL and TRDY when a write is performed	 * to the memory when memory is read-only	 */	if ((cmd & PCI_STATUS_DEVSEL_MASK) != 0x0) {		cmd &= ~PCI_STATUS_DEVSEL_MASK;		pci_write_config_word(dev, PCI_STATUS, cmd);	}	/*	 * Set to be prefetchable and put everything back based on old cfg.	 * it's possible that the reset of the V370PDC nuked the original	 * setup	 */	/*	   cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH;	   pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );	 */	/*	 * Turn PCI memory and I/O bus access back on	 */	pci_write_config_word(dev, PCI_COMMAND,			      PCI_COMMAND_MEMORY | PCI_COMMAND_IO);#ifdef CONFIG_MTD_PMC551_DEBUG	/*	 * Some screen fun	 */	printk(KERN_DEBUG "pmc551: %d%sB (0x%x) of %sprefetchable memory at "		"0x%llx\n", (size < 1024) ? size : (size < 1048576) ?		size >> 10 : size >> 20,		(size < 1024) ? "" : (size < 1048576) ? "Ki" : "Mi", size,		((dcmd & (0x1 << 3)) == 0) ? "non-" : "",		(unsigned long long)pci_resource_start(dev, 0));	/*	 * Check to see the state of the memory	 */	pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dcmd);	printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n"		"pmc551: DRAM_BLK0 Size: %d at %d\n"		"pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n",		(((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",		(((0x1 << 0) & dcmd) == 0) ? "Off" : "On",		PMC551_DRAM_BLK_GET_SIZE(dcmd),		((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),		((dcmd >> 9) & 0xF));	pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dcmd);	printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n"		"pmc551: DRAM_BLK1 Size: %d at %d\n"		"pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n",		(((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",		(((0x1 << 0) & dcmd) == 0) ? "Off" : "On",		PMC551_DRAM_BLK_GET_SIZE(dcmd),		((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),		((dcmd >> 9) & 0xF));	pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dcmd);	printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n"		"pmc551: DRAM_BLK2 Size: %d at %d\n"		"pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n",		(((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",		(((0x1 << 0) & dcmd) == 0) ? "Off" : "On",		PMC551_DRAM_BLK_GET_SIZE(dcmd),		((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),		((dcmd >> 9) & 0xF));	pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dcmd);	printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n"		"pmc551: DRAM_BLK3 Size: %d at %d\n"		"pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n",		(((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",		(((0x1 << 0) & dcmd) == 0) ? "Off" : "On",		PMC551_DRAM_BLK_GET_SIZE(dcmd),		((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),		((dcmd >> 9) & 0xF));	pci_read_config_word(dev, PCI_COMMAND, &cmd);	printk(KERN_DEBUG "pmc551: Memory Access %s\n",		(((0x1 << 1) & cmd) == 0) ? "off" : "on");	printk(KERN_DEBUG "pmc551: I/O Access %s\n",		(((0x1 << 0) & cmd) == 0) ? "off" : "on");	pci_read_config_word(dev, PCI_STATUS, &cmd);	printk(KERN_DEBUG "pmc551: Devsel %s\n",		((PCI_STATUS_DEVSEL_MASK & cmd) == 0x000) ? "Fast" :		((PCI_STATUS_DEVSEL_MASK & cmd) == 0x200) ? "Medium" :		((PCI_STATUS_DEVSEL_MASK & cmd) == 0x400) ? "Slow" : "Invalid");	printk(KERN_DEBUG "pmc551: %sFast Back-to-Back\n",		((PCI_COMMAND_FAST_BACK & cmd) == 0) ? "Not " : "");	pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd);	printk(KERN_DEBUG "pmc551: EEPROM is under %s control\n"		"pmc551: System Control Register is %slocked to PCI access\n"		"pmc551: System Control Register is %slocked to EEPROM access\n",		(bcmd & 0x1) ? "software" : "hardware",		(bcmd & 0x20) ? "" : "un", (bcmd & 0x40) ? "" : "un");#endif	return size;}/* * Kernel version specific module stuffages */MODULE_LICENSE("GPL");MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>");MODULE_DESCRIPTION(PMC551_VERSION);/* * Stuff these outside the ifdef so as to not bust compiled in driver support */static int msize = 0;static int asize = 0;module_param(msize, int, 0);MODULE_PARM_DESC(msize, "memory size in MiB [1 - 1024]");module_param(asize, int, 0);MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]");/* * PMC551 Card Initialization */static int __init init_pmc551(void){	struct pci_dev *PCI_Device = NULL;	struct mypriv *priv;	int count, found = 0;	struct mtd_info *mtd;	u32 length = 0;	if (msize) {		msize = (1 << (ffs(msize) - 1)) << 20;		if (msize > (1 << 30)) {			printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n",				msize);			return -EINVAL;		}	}	if (asize) {		asize = (1 << (ffs(asize) - 1)) << 20;		if (asize > (1 << 30)) {			printk(KERN_NOTICE "pmc551: Invalid aperture size "				"[%d]\n", asize);			return -EINVAL;		}	}	printk(KERN_INFO PMC551_VERSION);	/*	 * PCU-bus chipset probe.	 */	for (count = 0; count < MAX_MTD_DEVICES; count++) {		if ((PCI_Device = pci_get_device(PCI_VENDOR_ID_V3_SEMI,						  PCI_DEVICE_ID_V3_SEMI_V370PDC,						  PCI_Device)) == NULL) {			break;		}		printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%llx\n",			(unsigned long long)pci_resource_start(PCI_Device, 0));		/*		 * The PMC551 device acts VERY weird if you don't init it		 * first.  i.e. it will not correctly report devsel.  If for		 * some reason the sdram is in a wrote-protected state the		 * device will DEVSEL when it is written to causing problems		 * with the oldproc.c driver in		 * some kernels (2.2.*)		 */		if ((length = fixup_pmc551(PCI_Device)) <= 0) {			printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n");			break;		}		/*		 * This is needed until the driver is capable of reading the		 * onboard I2C SROM to discover the "real" memory size.		 */		if (msize) {			length = msize;			printk(KERN_NOTICE "pmc551: Using specified memory "				"size 0x%x\n", length);		} else {			msize = length;		}		mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);		if (!mtd) {			printk(KERN_NOTICE "pmc551: Cannot allocate new MTD "				"device.\n");			break;		}		priv = kzalloc(sizeof(struct mypriv), GFP_KERNEL);		if (!priv) {			printk(KERN_NOTICE "pmc551: Cannot allocate new MTD "				"device.\n");			kfree(mtd);			break;		}		mtd->priv = priv;		priv->dev = PCI_Device;		if (asize > length) {			printk(KERN_NOTICE "pmc551: reducing aperture size to "				"fit %dM\n", length >> 20);			priv->asize = asize = length;		} else if (asize == 0 || asize == length) {			printk(KERN_NOTICE "pmc551: Using existing aperture "				"size %dM\n", length >> 20);			priv->asize = asize = length;		} else {			printk(KERN_NOTICE "pmc551: Using specified aperture "				"size %dM\n", asize >> 20);			priv->asize = asize;		}		priv->start = pci_iomap(PCI_Device, 0, priv->asize);		if (!priv->start) {			printk(KERN_NOTICE "pmc551: Unable to map IO space\n");			kfree(mtd->priv);			kfree(mtd);			break;		}#ifdef CONFIG_MTD_PMC551_DEBUG		printk(KERN_DEBUG "pmc551: setting aperture to %d\n",			ffs(priv->asize >> 20) - 1);#endif		priv->base_map0 = (PMC551_PCI_MEM_MAP_REG_EN				   | PMC551_PCI_MEM_MAP_ENABLE				   | (ffs(priv->asize >> 20) - 1) << 4);		priv->curr_map0 = priv->base_map0;		pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,					priv->curr_map0);#ifdef CONFIG_MTD_PMC551_DEBUG		printk(KERN_DEBUG "pmc551: aperture set to %d\n",			(priv->base_map0 & 0xF0) >> 4);#endif		mtd->size = msize;		mtd->flags = MTD_CAP_RAM;		mtd->erase = pmc551_erase;		mtd->read = pmc551_read;		mtd->write = pmc551_write;		mtd->point = pmc551_point;		mtd->unpoint = pmc551_unpoint;		mtd->type = MTD_RAM;		mtd->name = "PMC551 RAM board";		mtd->erasesize = 0x10000;		mtd->writesize = 1;		mtd->owner = THIS_MODULE;		if (add_mtd_device(mtd)) {			printk(KERN_NOTICE "pmc551: Failed to register new device\n");			pci_iounmap(PCI_Device, priv->start);			kfree(mtd->priv);			kfree(mtd);			break;		}		/* Keep a reference as the add_mtd_device worked */		pci_dev_get(PCI_Device);		printk(KERN_NOTICE "Registered pmc551 memory device.\n");		printk(KERN_NOTICE "Mapped %dMiB of memory from 0x%p to 0x%p\n",			priv->asize >> 20,			priv->start, priv->start + priv->asize);		printk(KERN_NOTICE "Total memory is %d%sB\n",			(length < 1024) ? length :			(length < 1048576) ? length >> 10 : length >> 20,			(length < 1024) ? "" : (length < 1048576) ? "Ki" : "Mi");		priv->nextpmc551 = pmc551list;		pmc551list = mtd;		found++;	}	/* Exited early, reference left over */	if (PCI_Device)		pci_dev_put(PCI_Device);	if (!pmc551list) {		printk(KERN_NOTICE "pmc551: not detected\n");		return -ENODEV;	} else {		printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found);		return 0;	}}/* * PMC551 Card Cleanup */static void __exit cleanup_pmc551(void){	int found = 0;	struct mtd_info *mtd;	struct mypriv *priv;	while ((mtd = pmc551list)) {		priv = mtd->priv;		pmc551list = priv->nextpmc551;		if (priv->start) {			printk(KERN_DEBUG "pmc551: unmapping %dMiB starting at "				"0x%p\n", priv->asize >> 20, priv->start);			pci_iounmap(priv->dev, priv->start);		}		pci_dev_put(priv->dev);		kfree(mtd->priv);		del_mtd_device(mtd);		kfree(mtd);		found++;	}	printk(KERN_NOTICE "pmc551: %d pmc551 devices unloaded\n", found);}module_init(init_pmc551);module_exit(cleanup_pmc551);

⌨️ 快捷键说明

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