Linux Audio

Check our new training course

Yocto / OpenEmbedded training

Feb 10-13, 2025
Register
Loading...
v6.8
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * PMC551 PCI Mezzanine Ram Device
  4 *
  5 * Author:
  6 *	Mark Ferrell <mferrell@mvista.com>
  7 *	Copyright 1999,2000 Nortel Networks
  8 *
 
 
 
 
 
  9 * Description:
 10 *	This driver is intended to support the PMC551 PCI Ram device
 11 *	from Ramix Inc.  The PMC551 is a PMC Mezzanine module for
 12 *	cPCI embedded systems.  The device contains a single SROM
 13 *	that initially programs the V370PDC chipset onboard the
 14 *	device, and various banks of DRAM/SDRAM onboard.  This driver
 15 *	implements this PCI Ram device as an MTD (Memory Technology
 16 *	Device) so that it can be used to hold a file system, or for
 17 *	added swap space in embedded systems.  Since the memory on
 18 *	this board isn't as fast as main memory we do not try to hook
 19 *	it into main memory as that would simply reduce performance
 20 *	on the system.  Using it as a block device allows us to use
 21 *	it as high speed swap or for a high speed disk device of some
 22 *	sort.  Which becomes very useful on diskless systems in the
 23 *	embedded market I might add.
 24 *
 25 * Notes:
 26 *	Due to what I assume is more buggy SROM, the 64M PMC551 I
 27 *	have available claims that all 4 of its DRAM banks have 64MiB
 28 *	of ram configured (making a grand total of 256MiB onboard).
 29 *	This is slightly annoying since the BAR0 size reflects the
 30 *	aperture size, not the dram size, and the V370PDC supplies no
 31 *	other method for memory size discovery.  This problem is
 32 *	mostly only relevant when compiled as a module, as the
 33 *	unloading of the module with an aperture size smaller than
 34 *	the ram will cause the driver to detect the onboard memory
 35 *	size to be equal to the aperture size when the module is
 36 *	reloaded.  Soooo, to help, the module supports an msize
 37 *	option to allow the specification of the onboard memory, and
 38 *	an asize option, to allow the specification of the aperture
 39 *	size.  The aperture must be equal to or less then the memory
 40 *	size, the driver will correct this if you screw it up.  This
 41 *	problem is not relevant for compiled in drivers as compiled
 42 *	in drivers only init once.
 43 *
 44 * Credits:
 45 *	Saeed Karamooz <saeed@ramix.com> of Ramix INC. for the
 46 *	initial example code of how to initialize this device and for
 47 *	help with questions I had concerning operation of the device.
 48 *
 49 *	Most of the MTD code for this driver was originally written
 50 *	for the slram.o module in the MTD drivers package which
 51 *	allows the mapping of system memory into an MTD device.
 52 *	Since the PMC551 memory module is accessed in the same
 53 *	fashion as system memory, the slram.c code became a very nice
 54 *	fit to the needs of this driver.  All we added was PCI
 55 *	detection/initialization to the driver and automatically figure
 56 *	out the size via the PCI detection.o, later changes by Corey
 57 *	Minyard set up the card to utilize a 1M sliding apature.
 58 *
 59 *	Corey Minyard <minyard@nortelnetworks.com>
 60 *	* Modified driver to utilize a sliding aperture instead of
 61 *	 mapping all memory into kernel space which turned out to
 62 *	 be very wasteful.
 63 *	* Located a bug in the SROM's initialization sequence that
 64 *	 made the memory unusable, added a fix to code to touch up
 65 *	 the DRAM some.
 66 *
 67 * Bugs/FIXMEs:
 68 *	* MUST fix the init function to not spin on a register
 69 *	waiting for it to set .. this does not safely handle busted
 70 *	devices that never reset the register correctly which will
 71 *	cause the system to hang w/ a reboot being the only chance at
 72 *	recover. [sort of fixed, could be better]
 73 *	* Add I2C handling of the SROM so we can read the SROM's information
 74 *	about the aperture size.  This should always accurately reflect the
 75 *	onboard memory size.
 76 *	* Comb the init routine.  It's still a bit cludgy on a few things.
 77 */
 78
 79#include <linux/kernel.h>
 80#include <linux/module.h>
 81#include <linux/uaccess.h>
 82#include <linux/types.h>
 83#include <linux/init.h>
 84#include <linux/ptrace.h>
 85#include <linux/slab.h>
 86#include <linux/string.h>
 87#include <linux/timer.h>
 88#include <linux/major.h>
 89#include <linux/fs.h>
 90#include <linux/ioctl.h>
 91#include <asm/io.h>
 92#include <linux/pci.h>
 93#include <linux/mtd/mtd.h>
 94
 95#define PMC551_VERSION \
 96	"Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n"
 97
 98#define PCI_VENDOR_ID_V3_SEMI 0x11b0
 99#define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200
100
101#define PMC551_PCI_MEM_MAP0 0x50
102#define PMC551_PCI_MEM_MAP1 0x54
103#define PMC551_PCI_MEM_MAP_MAP_ADDR_MASK 0x3ff00000
104#define PMC551_PCI_MEM_MAP_APERTURE_MASK 0x000000f0
105#define PMC551_PCI_MEM_MAP_REG_EN 0x00000002
106#define PMC551_PCI_MEM_MAP_ENABLE 0x00000001
107
108#define PMC551_SDRAM_MA  0x60
109#define PMC551_SDRAM_CMD 0x62
110#define PMC551_DRAM_CFG  0x64
111#define PMC551_SYS_CTRL_REG 0x78
112
113#define PMC551_DRAM_BLK0 0x68
114#define PMC551_DRAM_BLK1 0x6c
115#define PMC551_DRAM_BLK2 0x70
116#define PMC551_DRAM_BLK3 0x74
117#define PMC551_DRAM_BLK_GET_SIZE(x) (524288 << ((x >> 4) & 0x0f))
118#define PMC551_DRAM_BLK_SET_COL_MUX(x, v) (((x) & ~0x00007000) | (((v) & 0x7) << 12))
119#define PMC551_DRAM_BLK_SET_ROW_MUX(x, v) (((x) & ~0x00000f00) | (((v) & 0xf) << 8))
120
121struct mypriv {
122	struct pci_dev *dev;
123	u_char *start;
124	u32 base_map0;
125	u32 curr_map0;
126	u32 asize;
127	struct mtd_info *nextpmc551;
128};
129
130static struct mtd_info *pmc551list;
131
132static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
133			size_t *retlen, void **virt, resource_size_t *phys);
134
135static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr)
136{
137	struct mypriv *priv = mtd->priv;
138	u32 soff_hi;		/* start address offset hi */
139	u32 eoff_hi, eoff_lo;	/* end address offset hi/lo */
140	unsigned long end;
141	u_char *ptr;
142	size_t retlen;
143
144#ifdef CONFIG_MTD_PMC551_DEBUG
145	printk(KERN_DEBUG "pmc551_erase(pos:%ld, len:%ld)\n", (long)instr->addr,
146		(long)instr->len);
147#endif
148
149	end = instr->addr + instr->len - 1;
150	eoff_hi = end & ~(priv->asize - 1);
151	soff_hi = instr->addr & ~(priv->asize - 1);
152	eoff_lo = end & (priv->asize - 1);
 
153
154	pmc551_point(mtd, instr->addr, instr->len, &retlen,
155		     (void **)&ptr, NULL);
156
157	if (soff_hi == eoff_hi || mtd->size == priv->asize) {
158		/* The whole thing fits within one access, so just one shot
159		   will do it. */
160		memset(ptr, 0xff, instr->len);
161	} else {
162		/* We have to do multiple writes to get all the data
163		   written. */
164		while (soff_hi != eoff_hi) {
165#ifdef CONFIG_MTD_PMC551_DEBUG
166			printk(KERN_DEBUG "pmc551_erase() soff_hi: %ld, "
167				"eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
168#endif
169			memset(ptr, 0xff, priv->asize);
170			if (soff_hi + priv->asize >= mtd->size) {
171				goto out;
172			}
173			soff_hi += priv->asize;
174			pmc551_point(mtd, (priv->base_map0 | soff_hi),
175				     priv->asize, &retlen,
176				     (void **)&ptr, NULL);
177		}
178		memset(ptr, 0xff, eoff_lo);
179	}
180
181      out:
182#ifdef CONFIG_MTD_PMC551_DEBUG
183	printk(KERN_DEBUG "pmc551_erase() done\n");
184#endif
185
186	return 0;
187}
188
189static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
190			size_t *retlen, void **virt, resource_size_t *phys)
191{
192	struct mypriv *priv = mtd->priv;
193	u32 soff_hi;
194	u32 soff_lo;
195
196#ifdef CONFIG_MTD_PMC551_DEBUG
197	printk(KERN_DEBUG "pmc551_point(%ld, %ld)\n", (long)from, (long)len);
198#endif
199
200	soff_hi = from & ~(priv->asize - 1);
201	soff_lo = from & (priv->asize - 1);
202
203	/* Cheap hack optimization */
204	if (priv->curr_map0 != from) {
205		pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,
206					(priv->base_map0 | soff_hi));
207		priv->curr_map0 = soff_hi;
208	}
209
210	*virt = priv->start + soff_lo;
211	*retlen = len;
212	return 0;
213}
214
215static int pmc551_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
216{
217#ifdef CONFIG_MTD_PMC551_DEBUG
218	printk(KERN_DEBUG "pmc551_unpoint()\n");
219#endif
220	return 0;
221}
222
223static int pmc551_read(struct mtd_info *mtd, loff_t from, size_t len,
224			size_t * retlen, u_char * buf)
225{
226	struct mypriv *priv = mtd->priv;
227	u32 soff_hi;		/* start address offset hi */
228	u32 eoff_hi, eoff_lo;	/* end address offset hi/lo */
229	unsigned long end;
230	u_char *ptr;
231	u_char *copyto = buf;
232
233#ifdef CONFIG_MTD_PMC551_DEBUG
234	printk(KERN_DEBUG "pmc551_read(pos:%ld, len:%ld) asize: %ld\n",
235		(long)from, (long)len, (long)priv->asize);
236#endif
237
238	end = from + len - 1;
239	soff_hi = from & ~(priv->asize - 1);
240	eoff_hi = end & ~(priv->asize - 1);
 
241	eoff_lo = end & (priv->asize - 1);
242
243	pmc551_point(mtd, from, len, retlen, (void **)&ptr, NULL);
244
245	if (soff_hi == eoff_hi) {
246		/* The whole thing fits within one access, so just one shot
247		   will do it. */
248		memcpy(copyto, ptr, len);
249		copyto += len;
250	} else {
251		/* We have to do multiple writes to get all the data
252		   written. */
253		while (soff_hi != eoff_hi) {
254#ifdef CONFIG_MTD_PMC551_DEBUG
255			printk(KERN_DEBUG "pmc551_read() soff_hi: %ld, "
256				"eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
257#endif
258			memcpy(copyto, ptr, priv->asize);
259			copyto += priv->asize;
260			if (soff_hi + priv->asize >= mtd->size) {
261				goto out;
262			}
263			soff_hi += priv->asize;
264			pmc551_point(mtd, soff_hi, priv->asize, retlen,
265				     (void **)&ptr, NULL);
266		}
267		memcpy(copyto, ptr, eoff_lo);
268		copyto += eoff_lo;
269	}
270
271      out:
272#ifdef CONFIG_MTD_PMC551_DEBUG
273	printk(KERN_DEBUG "pmc551_read() done\n");
274#endif
275	*retlen = copyto - buf;
276	return 0;
277}
278
279static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len,
280			size_t * retlen, const u_char * buf)
281{
282	struct mypriv *priv = mtd->priv;
283	u32 soff_hi;		/* start address offset hi */
284	u32 eoff_hi, eoff_lo;	/* end address offset hi/lo */
285	unsigned long end;
286	u_char *ptr;
287	const u_char *copyfrom = buf;
288
289#ifdef CONFIG_MTD_PMC551_DEBUG
290	printk(KERN_DEBUG "pmc551_write(pos:%ld, len:%ld) asize:%ld\n",
291		(long)to, (long)len, (long)priv->asize);
292#endif
293
294	end = to + len - 1;
295	soff_hi = to & ~(priv->asize - 1);
296	eoff_hi = end & ~(priv->asize - 1);
 
297	eoff_lo = end & (priv->asize - 1);
298
299	pmc551_point(mtd, to, len, retlen, (void **)&ptr, NULL);
300
301	if (soff_hi == eoff_hi) {
302		/* The whole thing fits within one access, so just one shot
303		   will do it. */
304		memcpy(ptr, copyfrom, len);
305		copyfrom += len;
306	} else {
307		/* We have to do multiple writes to get all the data
308		   written. */
309		while (soff_hi != eoff_hi) {
310#ifdef CONFIG_MTD_PMC551_DEBUG
311			printk(KERN_DEBUG "pmc551_write() soff_hi: %ld, "
312				"eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
313#endif
314			memcpy(ptr, copyfrom, priv->asize);
315			copyfrom += priv->asize;
316			if (soff_hi >= mtd->size) {
317				goto out;
318			}
319			soff_hi += priv->asize;
320			pmc551_point(mtd, soff_hi, priv->asize, retlen,
321				     (void **)&ptr, NULL);
322		}
323		memcpy(ptr, copyfrom, eoff_lo);
324		copyfrom += eoff_lo;
325	}
326
327      out:
328#ifdef CONFIG_MTD_PMC551_DEBUG
329	printk(KERN_DEBUG "pmc551_write() done\n");
330#endif
331	*retlen = copyfrom - buf;
332	return 0;
333}
334
335/*
336 * Fixup routines for the V370PDC
337 * PCI device ID 0x020011b0
338 *
339 * This function basically kick starts the DRAM oboard the card and gets it
340 * ready to be used.  Before this is done the device reads VERY erratic, so
341 * much that it can crash the Linux 2.2.x series kernels when a user cat's
342 * /proc/pci .. though that is mainly a kernel bug in handling the PCI DEVSEL
343 * register.  FIXME: stop spinning on registers .. must implement a timeout
344 * mechanism
345 * returns the size of the memory region found.
346 */
347static int __init fixup_pmc551(struct pci_dev *dev)
348{
349#ifdef CONFIG_MTD_PMC551_BUGFIX
350	u32 dram_data;
351#endif
352	u32 size, dcmd, cfg, dtmp;
353	u16 cmd, tmp, i;
354	u8 bcmd, counter;
355
356	/* Sanity Check */
357	if (!dev) {
358		return -ENODEV;
359	}
360
361	/*
362	 * Attempt to reset the card
363	 * FIXME: Stop Spinning registers
364	 */
365	counter = 0;
366	/* unlock registers */
367	pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5);
368	/* read in old data */
369	pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd);
370	/* bang the reset line up and down for a few */
371	for (i = 0; i < 10; i++) {
372		counter = 0;
373		bcmd &= ~0x80;
374		while (counter++ < 100) {
375			pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
376		}
377		counter = 0;
378		bcmd |= 0x80;
379		while (counter++ < 100) {
380			pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
381		}
382	}
383	bcmd |= (0x40 | 0x20);
384	pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
385
386	/*
387	 * Take care and turn off the memory on the device while we
388	 * tweak the configurations
389	 */
390	pci_read_config_word(dev, PCI_COMMAND, &cmd);
391	tmp = cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
392	pci_write_config_word(dev, PCI_COMMAND, tmp);
393
394	/*
395	 * Disable existing aperture before probing memory size
396	 */
397	pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd);
398	dtmp = (dcmd | PMC551_PCI_MEM_MAP_ENABLE | PMC551_PCI_MEM_MAP_REG_EN);
399	pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp);
400	/*
401	 * Grab old BAR0 config so that we can figure out memory size
402	 * This is another bit of kludge going on.  The reason for the
403	 * redundancy is I am hoping to retain the original configuration
404	 * previously assigned to the card by the BIOS or some previous
405	 * fixup routine in the kernel.  So we read the old config into cfg,
406	 * then write all 1's to the memory space, read back the result into
407	 * "size", and then write back all the old config.
408	 */
409	pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &cfg);
410#ifndef CONFIG_MTD_PMC551_BUGFIX
411	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, ~0);
412	pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &size);
413	size = (size & PCI_BASE_ADDRESS_MEM_MASK);
414	size &= ~(size - 1);
415	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, cfg);
416#else
417	/*
418	 * Get the size of the memory by reading all the DRAM size values
419	 * and adding them up.
420	 *
421	 * KLUDGE ALERT: the boards we are using have invalid column and
422	 * row mux values.  We fix them here, but this will break other
423	 * memory configurations.
424	 */
425	pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data);
426	size = PMC551_DRAM_BLK_GET_SIZE(dram_data);
427	dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
428	dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
429	pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data);
430
431	pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data);
432	size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
433	dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
434	dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
435	pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data);
436
437	pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data);
438	size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
439	dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
440	dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
441	pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data);
442
443	pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data);
444	size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
445	dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
446	dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
447	pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data);
448
449	/*
450	 * Oops .. something went wrong
451	 */
452	if ((size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) {
453		return -ENODEV;
454	}
455#endif				/* CONFIG_MTD_PMC551_BUGFIX */
456
457	if ((cfg & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) {
458		return -ENODEV;
459	}
460
461	/*
462	 * Precharge Dram
463	 */
464	pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0400);
465	pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x00bf);
466
467	/*
468	 * Wait until command has gone through
469	 * FIXME: register spinning issue
470	 */
471	do {
472		pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
473		if (counter++ > 100)
474			break;
475	} while ((PCI_COMMAND_IO) & cmd);
476
477	/*
478	 * Turn on auto refresh
479	 * The loop is taken directly from Ramix's example code.  I assume that
480	 * this must be held high for some duration of time, but I can find no
481	 * documentation refrencing the reasons why.
482	 */
483	for (i = 1; i <= 8; i++) {
484		pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0df);
485
486		/*
487		 * Make certain command has gone through
488		 * FIXME: register spinning issue
489		 */
490		counter = 0;
491		do {
492			pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
493			if (counter++ > 100)
494				break;
495		} while ((PCI_COMMAND_IO) & cmd);
496	}
497
498	pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0020);
499	pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0ff);
500
501	/*
502	 * Wait until command completes
503	 * FIXME: register spinning issue
504	 */
505	counter = 0;
506	do {
507		pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
508		if (counter++ > 100)
509			break;
510	} while ((PCI_COMMAND_IO) & cmd);
511
512	pci_read_config_dword(dev, PMC551_DRAM_CFG, &dcmd);
513	dcmd |= 0x02000000;
514	pci_write_config_dword(dev, PMC551_DRAM_CFG, dcmd);
515
516	/*
517	 * Check to make certain fast back-to-back, if not
518	 * then set it so
519	 */
520	pci_read_config_word(dev, PCI_STATUS, &cmd);
521	if ((cmd & PCI_COMMAND_FAST_BACK) == 0) {
522		cmd |= PCI_COMMAND_FAST_BACK;
523		pci_write_config_word(dev, PCI_STATUS, cmd);
524	}
525
526	/*
527	 * Check to make certain the DEVSEL is set correctly, this device
528	 * has a tendency to assert DEVSEL and TRDY when a write is performed
529	 * to the memory when memory is read-only
530	 */
531	if ((cmd & PCI_STATUS_DEVSEL_MASK) != 0x0) {
532		cmd &= ~PCI_STATUS_DEVSEL_MASK;
533		pci_write_config_word(dev, PCI_STATUS, cmd);
534	}
535	/*
536	 * Set to be prefetchable and put everything back based on old cfg.
537	 * it's possible that the reset of the V370PDC nuked the original
538	 * setup
539	 */
540	/*
541	   cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH;
542	   pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );
543	 */
544
545	/*
546	 * Turn PCI memory and I/O bus access back on
547	 */
548	pci_write_config_word(dev, PCI_COMMAND,
549			      PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
550#ifdef CONFIG_MTD_PMC551_DEBUG
551	/*
552	 * Some screen fun
553	 */
554	printk(KERN_DEBUG "pmc551: %d%sB (0x%x) of %sprefetchable memory at "
555		"0x%llx\n", (size < 1024) ? size : (size < 1048576) ?
556		size >> 10 : size >> 20,
557		(size < 1024) ? "" : (size < 1048576) ? "Ki" : "Mi", size,
558		((dcmd & (0x1 << 3)) == 0) ? "non-" : "",
559		(unsigned long long)pci_resource_start(dev, 0));
560
561	/*
562	 * Check to see the state of the memory
563	 */
564	pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dcmd);
565	printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n"
566		"pmc551: DRAM_BLK0 Size: %d at %d\n"
567		"pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n",
568		(((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
569		(((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
570		PMC551_DRAM_BLK_GET_SIZE(dcmd),
571		((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
572		((dcmd >> 9) & 0xF));
573
574	pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dcmd);
575	printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n"
576		"pmc551: DRAM_BLK1 Size: %d at %d\n"
577		"pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n",
578		(((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
579		(((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
580		PMC551_DRAM_BLK_GET_SIZE(dcmd),
581		((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
582		((dcmd >> 9) & 0xF));
583
584	pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dcmd);
585	printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n"
586		"pmc551: DRAM_BLK2 Size: %d at %d\n"
587		"pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n",
588		(((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
589		(((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
590		PMC551_DRAM_BLK_GET_SIZE(dcmd),
591		((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
592		((dcmd >> 9) & 0xF));
593
594	pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dcmd);
595	printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n"
596		"pmc551: DRAM_BLK3 Size: %d at %d\n"
597		"pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n",
598		(((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
599		(((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
600		PMC551_DRAM_BLK_GET_SIZE(dcmd),
601		((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
602		((dcmd >> 9) & 0xF));
603
604	pci_read_config_word(dev, PCI_COMMAND, &cmd);
605	printk(KERN_DEBUG "pmc551: Memory Access %s\n",
606		(((0x1 << 1) & cmd) == 0) ? "off" : "on");
607	printk(KERN_DEBUG "pmc551: I/O Access %s\n",
608		(((0x1 << 0) & cmd) == 0) ? "off" : "on");
609
610	pci_read_config_word(dev, PCI_STATUS, &cmd);
611	printk(KERN_DEBUG "pmc551: Devsel %s\n",
612		((PCI_STATUS_DEVSEL_MASK & cmd) == 0x000) ? "Fast" :
613		((PCI_STATUS_DEVSEL_MASK & cmd) == 0x200) ? "Medium" :
614		((PCI_STATUS_DEVSEL_MASK & cmd) == 0x400) ? "Slow" : "Invalid");
615
616	printk(KERN_DEBUG "pmc551: %sFast Back-to-Back\n",
617		((PCI_COMMAND_FAST_BACK & cmd) == 0) ? "Not " : "");
618
619	pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd);
620	printk(KERN_DEBUG "pmc551: EEPROM is under %s control\n"
621		"pmc551: System Control Register is %slocked to PCI access\n"
622		"pmc551: System Control Register is %slocked to EEPROM access\n",
623		(bcmd & 0x1) ? "software" : "hardware",
624		(bcmd & 0x20) ? "" : "un", (bcmd & 0x40) ? "" : "un");
625#endif
626	return size;
627}
628
629/*
630 * Kernel version specific module stuffages
631 */
632
633MODULE_LICENSE("GPL");
634MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>");
635MODULE_DESCRIPTION(PMC551_VERSION);
636
637/*
638 * Stuff these outside the ifdef so as to not bust compiled in driver support
639 */
640static int msize = 0;
641static int asize = 0;
642
643module_param(msize, int, 0);
644MODULE_PARM_DESC(msize, "memory size in MiB [1 - 1024]");
645module_param(asize, int, 0);
646MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]");
647
648/*
649 * PMC551 Card Initialization
650 */
651static int __init init_pmc551(void)
652{
653	struct pci_dev *PCI_Device = NULL;
654	struct mypriv *priv;
655	int found = 0;
656	struct mtd_info *mtd;
657	int length = 0;
658
659	if (msize) {
660		msize = (1 << (ffs(msize) - 1)) << 20;
661		if (msize > (1 << 30)) {
662			printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n",
663				msize);
664			return -EINVAL;
665		}
666	}
667
668	if (asize) {
669		asize = (1 << (ffs(asize) - 1)) << 20;
670		if (asize > (1 << 30)) {
671			printk(KERN_NOTICE "pmc551: Invalid aperture size "
672				"[%d]\n", asize);
673			return -EINVAL;
674		}
675	}
676
677	printk(KERN_INFO PMC551_VERSION);
678
679	/*
680	 * PCU-bus chipset probe.
681	 */
682	for (;;) {
683
684		if ((PCI_Device = pci_get_device(PCI_VENDOR_ID_V3_SEMI,
685						  PCI_DEVICE_ID_V3_SEMI_V370PDC,
686						  PCI_Device)) == NULL) {
687			break;
688		}
689
690		printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%llx\n",
691			(unsigned long long)pci_resource_start(PCI_Device, 0));
692
693		/*
694		 * The PMC551 device acts VERY weird if you don't init it
695		 * first.  i.e. it will not correctly report devsel.  If for
696		 * some reason the sdram is in a wrote-protected state the
697		 * device will DEVSEL when it is written to causing problems
698		 * with the oldproc.c driver in
699		 * some kernels (2.2.*)
700		 */
701		if ((length = fixup_pmc551(PCI_Device)) <= 0) {
702			printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n");
703			break;
704		}
705
706		/*
707		 * This is needed until the driver is capable of reading the
708		 * onboard I2C SROM to discover the "real" memory size.
709		 */
710		if (msize) {
711			length = msize;
712			printk(KERN_NOTICE "pmc551: Using specified memory "
713				"size 0x%x\n", length);
714		} else {
715			msize = length;
716		}
717
718		mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
719		if (!mtd)
720			break;
721
722		priv = kzalloc(sizeof(struct mypriv), GFP_KERNEL);
723		if (!priv) {
724			kfree(mtd);
725			break;
726		}
727		mtd->priv = priv;
728		priv->dev = PCI_Device;
729
730		if (asize > length) {
731			printk(KERN_NOTICE "pmc551: reducing aperture size to "
732				"fit %dM\n", length >> 20);
733			priv->asize = asize = length;
734		} else if (asize == 0 || asize == length) {
735			printk(KERN_NOTICE "pmc551: Using existing aperture "
736				"size %dM\n", length >> 20);
737			priv->asize = asize = length;
738		} else {
739			printk(KERN_NOTICE "pmc551: Using specified aperture "
740				"size %dM\n", asize >> 20);
741			priv->asize = asize;
742		}
743		priv->start = pci_iomap(PCI_Device, 0, priv->asize);
744
745		if (!priv->start) {
746			printk(KERN_NOTICE "pmc551: Unable to map IO space\n");
747			kfree(mtd->priv);
748			kfree(mtd);
749			break;
750		}
751#ifdef CONFIG_MTD_PMC551_DEBUG
752		printk(KERN_DEBUG "pmc551: setting aperture to %d\n",
753			ffs(priv->asize >> 20) - 1);
754#endif
755
756		priv->base_map0 = (PMC551_PCI_MEM_MAP_REG_EN
757				   | PMC551_PCI_MEM_MAP_ENABLE
758				   | (ffs(priv->asize >> 20) - 1) << 4);
759		priv->curr_map0 = priv->base_map0;
760		pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,
761					priv->curr_map0);
762
763#ifdef CONFIG_MTD_PMC551_DEBUG
764		printk(KERN_DEBUG "pmc551: aperture set to %d\n",
765			(priv->base_map0 & 0xF0) >> 4);
766#endif
767
768		mtd->size = msize;
769		mtd->flags = MTD_CAP_RAM;
770		mtd->_erase = pmc551_erase;
771		mtd->_read = pmc551_read;
772		mtd->_write = pmc551_write;
773		mtd->_point = pmc551_point;
774		mtd->_unpoint = pmc551_unpoint;
775		mtd->type = MTD_RAM;
776		mtd->name = "PMC551 RAM board";
777		mtd->erasesize = 0x10000;
778		mtd->writesize = 1;
779		mtd->owner = THIS_MODULE;
780
781		if (mtd_device_register(mtd, NULL, 0)) {
782			printk(KERN_NOTICE "pmc551: Failed to register new device\n");
783			pci_iounmap(PCI_Device, priv->start);
784			kfree(mtd->priv);
785			kfree(mtd);
786			break;
787		}
788
789		/* Keep a reference as the mtd_device_register worked */
790		pci_dev_get(PCI_Device);
791
792		printk(KERN_NOTICE "Registered pmc551 memory device.\n");
793		printk(KERN_NOTICE "Mapped %dMiB of memory from 0x%p to 0x%p\n",
794			priv->asize >> 20,
795			priv->start, priv->start + priv->asize);
796		printk(KERN_NOTICE "Total memory is %d%sB\n",
797			(length < 1024) ? length :
798			(length < 1048576) ? length >> 10 : length >> 20,
799			(length < 1024) ? "" : (length < 1048576) ? "Ki" : "Mi");
800		priv->nextpmc551 = pmc551list;
801		pmc551list = mtd;
802		found++;
803	}
804
805	/* Exited early, reference left over */
806	pci_dev_put(PCI_Device);
807
808	if (!pmc551list) {
809		printk(KERN_NOTICE "pmc551: not detected\n");
810		return -ENODEV;
811	} else {
812		printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found);
813		return 0;
814	}
815}
816
817/*
818 * PMC551 Card Cleanup
819 */
820static void __exit cleanup_pmc551(void)
821{
822	int found = 0;
823	struct mtd_info *mtd;
824	struct mypriv *priv;
825
826	while ((mtd = pmc551list)) {
827		priv = mtd->priv;
828		pmc551list = priv->nextpmc551;
829
830		if (priv->start) {
831			printk(KERN_DEBUG "pmc551: unmapping %dMiB starting at "
832				"0x%p\n", priv->asize >> 20, priv->start);
833			pci_iounmap(priv->dev, priv->start);
834		}
835		pci_dev_put(priv->dev);
836
837		kfree(mtd->priv);
838		mtd_device_unregister(mtd);
839		kfree(mtd);
840		found++;
841	}
842
843	printk(KERN_NOTICE "pmc551: %d pmc551 devices unloaded\n", found);
844}
845
846module_init(init_pmc551);
847module_exit(cleanup_pmc551);
v4.17
 
  1/*
  2 * PMC551 PCI Mezzanine Ram Device
  3 *
  4 * Author:
  5 *	Mark Ferrell <mferrell@mvista.com>
  6 *	Copyright 1999,2000 Nortel Networks
  7 *
  8 * License:
  9 *	As part of this driver was derived from the slram.c driver it
 10 *	falls under the same license, which is GNU General Public
 11 *	License v2
 12 *
 13 * Description:
 14 *	This driver is intended to support the PMC551 PCI Ram device
 15 *	from Ramix Inc.  The PMC551 is a PMC Mezzanine module for
 16 *	cPCI embedded systems.  The device contains a single SROM
 17 *	that initially programs the V370PDC chipset onboard the
 18 *	device, and various banks of DRAM/SDRAM onboard.  This driver
 19 *	implements this PCI Ram device as an MTD (Memory Technology
 20 *	Device) so that it can be used to hold a file system, or for
 21 *	added swap space in embedded systems.  Since the memory on
 22 *	this board isn't as fast as main memory we do not try to hook
 23 *	it into main memory as that would simply reduce performance
 24 *	on the system.  Using it as a block device allows us to use
 25 *	it as high speed swap or for a high speed disk device of some
 26 *	sort.  Which becomes very useful on diskless systems in the
 27 *	embedded market I might add.
 28 *
 29 * Notes:
 30 *	Due to what I assume is more buggy SROM, the 64M PMC551 I
 31 *	have available claims that all 4 of its DRAM banks have 64MiB
 32 *	of ram configured (making a grand total of 256MiB onboard).
 33 *	This is slightly annoying since the BAR0 size reflects the
 34 *	aperture size, not the dram size, and the V370PDC supplies no
 35 *	other method for memory size discovery.  This problem is
 36 *	mostly only relevant when compiled as a module, as the
 37 *	unloading of the module with an aperture size smaller than
 38 *	the ram will cause the driver to detect the onboard memory
 39 *	size to be equal to the aperture size when the module is
 40 *	reloaded.  Soooo, to help, the module supports an msize
 41 *	option to allow the specification of the onboard memory, and
 42 *	an asize option, to allow the specification of the aperture
 43 *	size.  The aperture must be equal to or less then the memory
 44 *	size, the driver will correct this if you screw it up.  This
 45 *	problem is not relevant for compiled in drivers as compiled
 46 *	in drivers only init once.
 47 *
 48 * Credits:
 49 *	Saeed Karamooz <saeed@ramix.com> of Ramix INC. for the
 50 *	initial example code of how to initialize this device and for
 51 *	help with questions I had concerning operation of the device.
 52 *
 53 *	Most of the MTD code for this driver was originally written
 54 *	for the slram.o module in the MTD drivers package which
 55 *	allows the mapping of system memory into an MTD device.
 56 *	Since the PMC551 memory module is accessed in the same
 57 *	fashion as system memory, the slram.c code became a very nice
 58 *	fit to the needs of this driver.  All we added was PCI
 59 *	detection/initialization to the driver and automatically figure
 60 *	out the size via the PCI detection.o, later changes by Corey
 61 *	Minyard set up the card to utilize a 1M sliding apature.
 62 *
 63 *	Corey Minyard <minyard@nortelnetworks.com>
 64 *	* Modified driver to utilize a sliding aperture instead of
 65 *	 mapping all memory into kernel space which turned out to
 66 *	 be very wasteful.
 67 *	* Located a bug in the SROM's initialization sequence that
 68 *	 made the memory unusable, added a fix to code to touch up
 69 *	 the DRAM some.
 70 *
 71 * Bugs/FIXMEs:
 72 *	* MUST fix the init function to not spin on a register
 73 *	waiting for it to set .. this does not safely handle busted
 74 *	devices that never reset the register correctly which will
 75 *	cause the system to hang w/ a reboot being the only chance at
 76 *	recover. [sort of fixed, could be better]
 77 *	* Add I2C handling of the SROM so we can read the SROM's information
 78 *	about the aperture size.  This should always accurately reflect the
 79 *	onboard memory size.
 80 *	* Comb the init routine.  It's still a bit cludgy on a few things.
 81 */
 82
 83#include <linux/kernel.h>
 84#include <linux/module.h>
 85#include <linux/uaccess.h>
 86#include <linux/types.h>
 87#include <linux/init.h>
 88#include <linux/ptrace.h>
 89#include <linux/slab.h>
 90#include <linux/string.h>
 91#include <linux/timer.h>
 92#include <linux/major.h>
 93#include <linux/fs.h>
 94#include <linux/ioctl.h>
 95#include <asm/io.h>
 96#include <linux/pci.h>
 97#include <linux/mtd/mtd.h>
 98
 99#define PMC551_VERSION \
100	"Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n"
101
102#define PCI_VENDOR_ID_V3_SEMI 0x11b0
103#define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200
104
105#define PMC551_PCI_MEM_MAP0 0x50
106#define PMC551_PCI_MEM_MAP1 0x54
107#define PMC551_PCI_MEM_MAP_MAP_ADDR_MASK 0x3ff00000
108#define PMC551_PCI_MEM_MAP_APERTURE_MASK 0x000000f0
109#define PMC551_PCI_MEM_MAP_REG_EN 0x00000002
110#define PMC551_PCI_MEM_MAP_ENABLE 0x00000001
111
112#define PMC551_SDRAM_MA  0x60
113#define PMC551_SDRAM_CMD 0x62
114#define PMC551_DRAM_CFG  0x64
115#define PMC551_SYS_CTRL_REG 0x78
116
117#define PMC551_DRAM_BLK0 0x68
118#define PMC551_DRAM_BLK1 0x6c
119#define PMC551_DRAM_BLK2 0x70
120#define PMC551_DRAM_BLK3 0x74
121#define PMC551_DRAM_BLK_GET_SIZE(x) (524288 << ((x >> 4) & 0x0f))
122#define PMC551_DRAM_BLK_SET_COL_MUX(x, v) (((x) & ~0x00007000) | (((v) & 0x7) << 12))
123#define PMC551_DRAM_BLK_SET_ROW_MUX(x, v) (((x) & ~0x00000f00) | (((v) & 0xf) << 8))
124
125struct mypriv {
126	struct pci_dev *dev;
127	u_char *start;
128	u32 base_map0;
129	u32 curr_map0;
130	u32 asize;
131	struct mtd_info *nextpmc551;
132};
133
134static struct mtd_info *pmc551list;
135
136static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
137			size_t *retlen, void **virt, resource_size_t *phys);
138
139static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr)
140{
141	struct mypriv *priv = mtd->priv;
142	u32 soff_hi, soff_lo;	/* start address offset hi/lo */
143	u32 eoff_hi, eoff_lo;	/* end address offset hi/lo */
144	unsigned long end;
145	u_char *ptr;
146	size_t retlen;
147
148#ifdef CONFIG_MTD_PMC551_DEBUG
149	printk(KERN_DEBUG "pmc551_erase(pos:%ld, len:%ld)\n", (long)instr->addr,
150		(long)instr->len);
151#endif
152
153	end = instr->addr + instr->len - 1;
154	eoff_hi = end & ~(priv->asize - 1);
155	soff_hi = instr->addr & ~(priv->asize - 1);
156	eoff_lo = end & (priv->asize - 1);
157	soff_lo = instr->addr & (priv->asize - 1);
158
159	pmc551_point(mtd, instr->addr, instr->len, &retlen,
160		     (void **)&ptr, NULL);
161
162	if (soff_hi == eoff_hi || mtd->size == priv->asize) {
163		/* The whole thing fits within one access, so just one shot
164		   will do it. */
165		memset(ptr, 0xff, instr->len);
166	} else {
167		/* We have to do multiple writes to get all the data
168		   written. */
169		while (soff_hi != eoff_hi) {
170#ifdef CONFIG_MTD_PMC551_DEBUG
171			printk(KERN_DEBUG "pmc551_erase() soff_hi: %ld, "
172				"eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
173#endif
174			memset(ptr, 0xff, priv->asize);
175			if (soff_hi + priv->asize >= mtd->size) {
176				goto out;
177			}
178			soff_hi += priv->asize;
179			pmc551_point(mtd, (priv->base_map0 | soff_hi),
180				     priv->asize, &retlen,
181				     (void **)&ptr, NULL);
182		}
183		memset(ptr, 0xff, eoff_lo);
184	}
185
186      out:
187#ifdef CONFIG_MTD_PMC551_DEBUG
188	printk(KERN_DEBUG "pmc551_erase() done\n");
189#endif
190
191	return 0;
192}
193
194static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
195			size_t *retlen, void **virt, resource_size_t *phys)
196{
197	struct mypriv *priv = mtd->priv;
198	u32 soff_hi;
199	u32 soff_lo;
200
201#ifdef CONFIG_MTD_PMC551_DEBUG
202	printk(KERN_DEBUG "pmc551_point(%ld, %ld)\n", (long)from, (long)len);
203#endif
204
205	soff_hi = from & ~(priv->asize - 1);
206	soff_lo = from & (priv->asize - 1);
207
208	/* Cheap hack optimization */
209	if (priv->curr_map0 != from) {
210		pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,
211					(priv->base_map0 | soff_hi));
212		priv->curr_map0 = soff_hi;
213	}
214
215	*virt = priv->start + soff_lo;
216	*retlen = len;
217	return 0;
218}
219
220static int pmc551_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
221{
222#ifdef CONFIG_MTD_PMC551_DEBUG
223	printk(KERN_DEBUG "pmc551_unpoint()\n");
224#endif
225	return 0;
226}
227
228static int pmc551_read(struct mtd_info *mtd, loff_t from, size_t len,
229			size_t * retlen, u_char * buf)
230{
231	struct mypriv *priv = mtd->priv;
232	u32 soff_hi, soff_lo;	/* start address offset hi/lo */
233	u32 eoff_hi, eoff_lo;	/* end address offset hi/lo */
234	unsigned long end;
235	u_char *ptr;
236	u_char *copyto = buf;
237
238#ifdef CONFIG_MTD_PMC551_DEBUG
239	printk(KERN_DEBUG "pmc551_read(pos:%ld, len:%ld) asize: %ld\n",
240		(long)from, (long)len, (long)priv->asize);
241#endif
242
243	end = from + len - 1;
244	soff_hi = from & ~(priv->asize - 1);
245	eoff_hi = end & ~(priv->asize - 1);
246	soff_lo = from & (priv->asize - 1);
247	eoff_lo = end & (priv->asize - 1);
248
249	pmc551_point(mtd, from, len, retlen, (void **)&ptr, NULL);
250
251	if (soff_hi == eoff_hi) {
252		/* The whole thing fits within one access, so just one shot
253		   will do it. */
254		memcpy(copyto, ptr, len);
255		copyto += len;
256	} else {
257		/* We have to do multiple writes to get all the data
258		   written. */
259		while (soff_hi != eoff_hi) {
260#ifdef CONFIG_MTD_PMC551_DEBUG
261			printk(KERN_DEBUG "pmc551_read() soff_hi: %ld, "
262				"eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
263#endif
264			memcpy(copyto, ptr, priv->asize);
265			copyto += priv->asize;
266			if (soff_hi + priv->asize >= mtd->size) {
267				goto out;
268			}
269			soff_hi += priv->asize;
270			pmc551_point(mtd, soff_hi, priv->asize, retlen,
271				     (void **)&ptr, NULL);
272		}
273		memcpy(copyto, ptr, eoff_lo);
274		copyto += eoff_lo;
275	}
276
277      out:
278#ifdef CONFIG_MTD_PMC551_DEBUG
279	printk(KERN_DEBUG "pmc551_read() done\n");
280#endif
281	*retlen = copyto - buf;
282	return 0;
283}
284
285static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len,
286			size_t * retlen, const u_char * buf)
287{
288	struct mypriv *priv = mtd->priv;
289	u32 soff_hi, soff_lo;	/* start address offset hi/lo */
290	u32 eoff_hi, eoff_lo;	/* end address offset hi/lo */
291	unsigned long end;
292	u_char *ptr;
293	const u_char *copyfrom = buf;
294
295#ifdef CONFIG_MTD_PMC551_DEBUG
296	printk(KERN_DEBUG "pmc551_write(pos:%ld, len:%ld) asize:%ld\n",
297		(long)to, (long)len, (long)priv->asize);
298#endif
299
300	end = to + len - 1;
301	soff_hi = to & ~(priv->asize - 1);
302	eoff_hi = end & ~(priv->asize - 1);
303	soff_lo = to & (priv->asize - 1);
304	eoff_lo = end & (priv->asize - 1);
305
306	pmc551_point(mtd, to, len, retlen, (void **)&ptr, NULL);
307
308	if (soff_hi == eoff_hi) {
309		/* The whole thing fits within one access, so just one shot
310		   will do it. */
311		memcpy(ptr, copyfrom, len);
312		copyfrom += len;
313	} else {
314		/* We have to do multiple writes to get all the data
315		   written. */
316		while (soff_hi != eoff_hi) {
317#ifdef CONFIG_MTD_PMC551_DEBUG
318			printk(KERN_DEBUG "pmc551_write() soff_hi: %ld, "
319				"eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
320#endif
321			memcpy(ptr, copyfrom, priv->asize);
322			copyfrom += priv->asize;
323			if (soff_hi >= mtd->size) {
324				goto out;
325			}
326			soff_hi += priv->asize;
327			pmc551_point(mtd, soff_hi, priv->asize, retlen,
328				     (void **)&ptr, NULL);
329		}
330		memcpy(ptr, copyfrom, eoff_lo);
331		copyfrom += eoff_lo;
332	}
333
334      out:
335#ifdef CONFIG_MTD_PMC551_DEBUG
336	printk(KERN_DEBUG "pmc551_write() done\n");
337#endif
338	*retlen = copyfrom - buf;
339	return 0;
340}
341
342/*
343 * Fixup routines for the V370PDC
344 * PCI device ID 0x020011b0
345 *
346 * This function basically kick starts the DRAM oboard the card and gets it
347 * ready to be used.  Before this is done the device reads VERY erratic, so
348 * much that it can crash the Linux 2.2.x series kernels when a user cat's
349 * /proc/pci .. though that is mainly a kernel bug in handling the PCI DEVSEL
350 * register.  FIXME: stop spinning on registers .. must implement a timeout
351 * mechanism
352 * returns the size of the memory region found.
353 */
354static int __init fixup_pmc551(struct pci_dev *dev)
355{
356#ifdef CONFIG_MTD_PMC551_BUGFIX
357	u32 dram_data;
358#endif
359	u32 size, dcmd, cfg, dtmp;
360	u16 cmd, tmp, i;
361	u8 bcmd, counter;
362
363	/* Sanity Check */
364	if (!dev) {
365		return -ENODEV;
366	}
367
368	/*
369	 * Attempt to reset the card
370	 * FIXME: Stop Spinning registers
371	 */
372	counter = 0;
373	/* unlock registers */
374	pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5);
375	/* read in old data */
376	pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd);
377	/* bang the reset line up and down for a few */
378	for (i = 0; i < 10; i++) {
379		counter = 0;
380		bcmd &= ~0x80;
381		while (counter++ < 100) {
382			pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
383		}
384		counter = 0;
385		bcmd |= 0x80;
386		while (counter++ < 100) {
387			pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
388		}
389	}
390	bcmd |= (0x40 | 0x20);
391	pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
392
393	/*
394	 * Take care and turn off the memory on the device while we
395	 * tweak the configurations
396	 */
397	pci_read_config_word(dev, PCI_COMMAND, &cmd);
398	tmp = cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
399	pci_write_config_word(dev, PCI_COMMAND, tmp);
400
401	/*
402	 * Disable existing aperture before probing memory size
403	 */
404	pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd);
405	dtmp = (dcmd | PMC551_PCI_MEM_MAP_ENABLE | PMC551_PCI_MEM_MAP_REG_EN);
406	pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp);
407	/*
408	 * Grab old BAR0 config so that we can figure out memory size
409	 * This is another bit of kludge going on.  The reason for the
410	 * redundancy is I am hoping to retain the original configuration
411	 * previously assigned to the card by the BIOS or some previous
412	 * fixup routine in the kernel.  So we read the old config into cfg,
413	 * then write all 1's to the memory space, read back the result into
414	 * "size", and then write back all the old config.
415	 */
416	pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &cfg);
417#ifndef CONFIG_MTD_PMC551_BUGFIX
418	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, ~0);
419	pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &size);
420	size = (size & PCI_BASE_ADDRESS_MEM_MASK);
421	size &= ~(size - 1);
422	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, cfg);
423#else
424	/*
425	 * Get the size of the memory by reading all the DRAM size values
426	 * and adding them up.
427	 *
428	 * KLUDGE ALERT: the boards we are using have invalid column and
429	 * row mux values.  We fix them here, but this will break other
430	 * memory configurations.
431	 */
432	pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data);
433	size = PMC551_DRAM_BLK_GET_SIZE(dram_data);
434	dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
435	dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
436	pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data);
437
438	pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data);
439	size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
440	dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
441	dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
442	pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data);
443
444	pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data);
445	size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
446	dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
447	dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
448	pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data);
449
450	pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data);
451	size += PMC551_DRAM_BLK_GET_SIZE(dram_data);
452	dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
453	dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
454	pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data);
455
456	/*
457	 * Oops .. something went wrong
458	 */
459	if ((size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) {
460		return -ENODEV;
461	}
462#endif				/* CONFIG_MTD_PMC551_BUGFIX */
463
464	if ((cfg & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) {
465		return -ENODEV;
466	}
467
468	/*
469	 * Precharge Dram
470	 */
471	pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0400);
472	pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x00bf);
473
474	/*
475	 * Wait until command has gone through
476	 * FIXME: register spinning issue
477	 */
478	do {
479		pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
480		if (counter++ > 100)
481			break;
482	} while ((PCI_COMMAND_IO) & cmd);
483
484	/*
485	 * Turn on auto refresh
486	 * The loop is taken directly from Ramix's example code.  I assume that
487	 * this must be held high for some duration of time, but I can find no
488	 * documentation refrencing the reasons why.
489	 */
490	for (i = 1; i <= 8; i++) {
491		pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0df);
492
493		/*
494		 * Make certain command has gone through
495		 * FIXME: register spinning issue
496		 */
497		counter = 0;
498		do {
499			pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
500			if (counter++ > 100)
501				break;
502		} while ((PCI_COMMAND_IO) & cmd);
503	}
504
505	pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0020);
506	pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0ff);
507
508	/*
509	 * Wait until command completes
510	 * FIXME: register spinning issue
511	 */
512	counter = 0;
513	do {
514		pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
515		if (counter++ > 100)
516			break;
517	} while ((PCI_COMMAND_IO) & cmd);
518
519	pci_read_config_dword(dev, PMC551_DRAM_CFG, &dcmd);
520	dcmd |= 0x02000000;
521	pci_write_config_dword(dev, PMC551_DRAM_CFG, dcmd);
522
523	/*
524	 * Check to make certain fast back-to-back, if not
525	 * then set it so
526	 */
527	pci_read_config_word(dev, PCI_STATUS, &cmd);
528	if ((cmd & PCI_COMMAND_FAST_BACK) == 0) {
529		cmd |= PCI_COMMAND_FAST_BACK;
530		pci_write_config_word(dev, PCI_STATUS, cmd);
531	}
532
533	/*
534	 * Check to make certain the DEVSEL is set correctly, this device
535	 * has a tendency to assert DEVSEL and TRDY when a write is performed
536	 * to the memory when memory is read-only
537	 */
538	if ((cmd & PCI_STATUS_DEVSEL_MASK) != 0x0) {
539		cmd &= ~PCI_STATUS_DEVSEL_MASK;
540		pci_write_config_word(dev, PCI_STATUS, cmd);
541	}
542	/*
543	 * Set to be prefetchable and put everything back based on old cfg.
544	 * it's possible that the reset of the V370PDC nuked the original
545	 * setup
546	 */
547	/*
548	   cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH;
549	   pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );
550	 */
551
552	/*
553	 * Turn PCI memory and I/O bus access back on
554	 */
555	pci_write_config_word(dev, PCI_COMMAND,
556			      PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
557#ifdef CONFIG_MTD_PMC551_DEBUG
558	/*
559	 * Some screen fun
560	 */
561	printk(KERN_DEBUG "pmc551: %d%sB (0x%x) of %sprefetchable memory at "
562		"0x%llx\n", (size < 1024) ? size : (size < 1048576) ?
563		size >> 10 : size >> 20,
564		(size < 1024) ? "" : (size < 1048576) ? "Ki" : "Mi", size,
565		((dcmd & (0x1 << 3)) == 0) ? "non-" : "",
566		(unsigned long long)pci_resource_start(dev, 0));
567
568	/*
569	 * Check to see the state of the memory
570	 */
571	pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dcmd);
572	printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n"
573		"pmc551: DRAM_BLK0 Size: %d at %d\n"
574		"pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n",
575		(((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
576		(((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
577		PMC551_DRAM_BLK_GET_SIZE(dcmd),
578		((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
579		((dcmd >> 9) & 0xF));
580
581	pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dcmd);
582	printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n"
583		"pmc551: DRAM_BLK1 Size: %d at %d\n"
584		"pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n",
585		(((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
586		(((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
587		PMC551_DRAM_BLK_GET_SIZE(dcmd),
588		((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
589		((dcmd >> 9) & 0xF));
590
591	pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dcmd);
592	printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n"
593		"pmc551: DRAM_BLK2 Size: %d at %d\n"
594		"pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n",
595		(((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
596		(((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
597		PMC551_DRAM_BLK_GET_SIZE(dcmd),
598		((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
599		((dcmd >> 9) & 0xF));
600
601	pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dcmd);
602	printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n"
603		"pmc551: DRAM_BLK3 Size: %d at %d\n"
604		"pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n",
605		(((0x1 << 1) & dcmd) == 0) ? "RW" : "RO",
606		(((0x1 << 0) & dcmd) == 0) ? "Off" : "On",
607		PMC551_DRAM_BLK_GET_SIZE(dcmd),
608		((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7),
609		((dcmd >> 9) & 0xF));
610
611	pci_read_config_word(dev, PCI_COMMAND, &cmd);
612	printk(KERN_DEBUG "pmc551: Memory Access %s\n",
613		(((0x1 << 1) & cmd) == 0) ? "off" : "on");
614	printk(KERN_DEBUG "pmc551: I/O Access %s\n",
615		(((0x1 << 0) & cmd) == 0) ? "off" : "on");
616
617	pci_read_config_word(dev, PCI_STATUS, &cmd);
618	printk(KERN_DEBUG "pmc551: Devsel %s\n",
619		((PCI_STATUS_DEVSEL_MASK & cmd) == 0x000) ? "Fast" :
620		((PCI_STATUS_DEVSEL_MASK & cmd) == 0x200) ? "Medium" :
621		((PCI_STATUS_DEVSEL_MASK & cmd) == 0x400) ? "Slow" : "Invalid");
622
623	printk(KERN_DEBUG "pmc551: %sFast Back-to-Back\n",
624		((PCI_COMMAND_FAST_BACK & cmd) == 0) ? "Not " : "");
625
626	pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd);
627	printk(KERN_DEBUG "pmc551: EEPROM is under %s control\n"
628		"pmc551: System Control Register is %slocked to PCI access\n"
629		"pmc551: System Control Register is %slocked to EEPROM access\n",
630		(bcmd & 0x1) ? "software" : "hardware",
631		(bcmd & 0x20) ? "" : "un", (bcmd & 0x40) ? "" : "un");
632#endif
633	return size;
634}
635
636/*
637 * Kernel version specific module stuffages
638 */
639
640MODULE_LICENSE("GPL");
641MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>");
642MODULE_DESCRIPTION(PMC551_VERSION);
643
644/*
645 * Stuff these outside the ifdef so as to not bust compiled in driver support
646 */
647static int msize = 0;
648static int asize = 0;
649
650module_param(msize, int, 0);
651MODULE_PARM_DESC(msize, "memory size in MiB [1 - 1024]");
652module_param(asize, int, 0);
653MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]");
654
655/*
656 * PMC551 Card Initialization
657 */
658static int __init init_pmc551(void)
659{
660	struct pci_dev *PCI_Device = NULL;
661	struct mypriv *priv;
662	int found = 0;
663	struct mtd_info *mtd;
664	int length = 0;
665
666	if (msize) {
667		msize = (1 << (ffs(msize) - 1)) << 20;
668		if (msize > (1 << 30)) {
669			printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n",
670				msize);
671			return -EINVAL;
672		}
673	}
674
675	if (asize) {
676		asize = (1 << (ffs(asize) - 1)) << 20;
677		if (asize > (1 << 30)) {
678			printk(KERN_NOTICE "pmc551: Invalid aperture size "
679				"[%d]\n", asize);
680			return -EINVAL;
681		}
682	}
683
684	printk(KERN_INFO PMC551_VERSION);
685
686	/*
687	 * PCU-bus chipset probe.
688	 */
689	for (;;) {
690
691		if ((PCI_Device = pci_get_device(PCI_VENDOR_ID_V3_SEMI,
692						  PCI_DEVICE_ID_V3_SEMI_V370PDC,
693						  PCI_Device)) == NULL) {
694			break;
695		}
696
697		printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%llx\n",
698			(unsigned long long)pci_resource_start(PCI_Device, 0));
699
700		/*
701		 * The PMC551 device acts VERY weird if you don't init it
702		 * first.  i.e. it will not correctly report devsel.  If for
703		 * some reason the sdram is in a wrote-protected state the
704		 * device will DEVSEL when it is written to causing problems
705		 * with the oldproc.c driver in
706		 * some kernels (2.2.*)
707		 */
708		if ((length = fixup_pmc551(PCI_Device)) <= 0) {
709			printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n");
710			break;
711		}
712
713		/*
714		 * This is needed until the driver is capable of reading the
715		 * onboard I2C SROM to discover the "real" memory size.
716		 */
717		if (msize) {
718			length = msize;
719			printk(KERN_NOTICE "pmc551: Using specified memory "
720				"size 0x%x\n", length);
721		} else {
722			msize = length;
723		}
724
725		mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
726		if (!mtd)
727			break;
728
729		priv = kzalloc(sizeof(struct mypriv), GFP_KERNEL);
730		if (!priv) {
731			kfree(mtd);
732			break;
733		}
734		mtd->priv = priv;
735		priv->dev = PCI_Device;
736
737		if (asize > length) {
738			printk(KERN_NOTICE "pmc551: reducing aperture size to "
739				"fit %dM\n", length >> 20);
740			priv->asize = asize = length;
741		} else if (asize == 0 || asize == length) {
742			printk(KERN_NOTICE "pmc551: Using existing aperture "
743				"size %dM\n", length >> 20);
744			priv->asize = asize = length;
745		} else {
746			printk(KERN_NOTICE "pmc551: Using specified aperture "
747				"size %dM\n", asize >> 20);
748			priv->asize = asize;
749		}
750		priv->start = pci_iomap(PCI_Device, 0, priv->asize);
751
752		if (!priv->start) {
753			printk(KERN_NOTICE "pmc551: Unable to map IO space\n");
754			kfree(mtd->priv);
755			kfree(mtd);
756			break;
757		}
758#ifdef CONFIG_MTD_PMC551_DEBUG
759		printk(KERN_DEBUG "pmc551: setting aperture to %d\n",
760			ffs(priv->asize >> 20) - 1);
761#endif
762
763		priv->base_map0 = (PMC551_PCI_MEM_MAP_REG_EN
764				   | PMC551_PCI_MEM_MAP_ENABLE
765				   | (ffs(priv->asize >> 20) - 1) << 4);
766		priv->curr_map0 = priv->base_map0;
767		pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,
768					priv->curr_map0);
769
770#ifdef CONFIG_MTD_PMC551_DEBUG
771		printk(KERN_DEBUG "pmc551: aperture set to %d\n",
772			(priv->base_map0 & 0xF0) >> 4);
773#endif
774
775		mtd->size = msize;
776		mtd->flags = MTD_CAP_RAM;
777		mtd->_erase = pmc551_erase;
778		mtd->_read = pmc551_read;
779		mtd->_write = pmc551_write;
780		mtd->_point = pmc551_point;
781		mtd->_unpoint = pmc551_unpoint;
782		mtd->type = MTD_RAM;
783		mtd->name = "PMC551 RAM board";
784		mtd->erasesize = 0x10000;
785		mtd->writesize = 1;
786		mtd->owner = THIS_MODULE;
787
788		if (mtd_device_register(mtd, NULL, 0)) {
789			printk(KERN_NOTICE "pmc551: Failed to register new device\n");
790			pci_iounmap(PCI_Device, priv->start);
791			kfree(mtd->priv);
792			kfree(mtd);
793			break;
794		}
795
796		/* Keep a reference as the mtd_device_register worked */
797		pci_dev_get(PCI_Device);
798
799		printk(KERN_NOTICE "Registered pmc551 memory device.\n");
800		printk(KERN_NOTICE "Mapped %dMiB of memory from 0x%p to 0x%p\n",
801			priv->asize >> 20,
802			priv->start, priv->start + priv->asize);
803		printk(KERN_NOTICE "Total memory is %d%sB\n",
804			(length < 1024) ? length :
805			(length < 1048576) ? length >> 10 : length >> 20,
806			(length < 1024) ? "" : (length < 1048576) ? "Ki" : "Mi");
807		priv->nextpmc551 = pmc551list;
808		pmc551list = mtd;
809		found++;
810	}
811
812	/* Exited early, reference left over */
813	pci_dev_put(PCI_Device);
814
815	if (!pmc551list) {
816		printk(KERN_NOTICE "pmc551: not detected\n");
817		return -ENODEV;
818	} else {
819		printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found);
820		return 0;
821	}
822}
823
824/*
825 * PMC551 Card Cleanup
826 */
827static void __exit cleanup_pmc551(void)
828{
829	int found = 0;
830	struct mtd_info *mtd;
831	struct mypriv *priv;
832
833	while ((mtd = pmc551list)) {
834		priv = mtd->priv;
835		pmc551list = priv->nextpmc551;
836
837		if (priv->start) {
838			printk(KERN_DEBUG "pmc551: unmapping %dMiB starting at "
839				"0x%p\n", priv->asize >> 20, priv->start);
840			pci_iounmap(priv->dev, priv->start);
841		}
842		pci_dev_put(priv->dev);
843
844		kfree(mtd->priv);
845		mtd_device_unregister(mtd);
846		kfree(mtd);
847		found++;
848	}
849
850	printk(KERN_NOTICE "pmc551: %d pmc551 devices unloaded\n", found);
851}
852
853module_init(init_pmc551);
854module_exit(cleanup_pmc551);