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);
848