aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/devices
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/devices')
-rw-r--r--drivers/mtd/devices/Kconfig259
-rw-r--r--drivers/mtd/devices/Makefile25
-rw-r--r--drivers/mtd/devices/blkmtd.c823
-rw-r--r--drivers/mtd/devices/block2mtd.c495
-rw-r--r--drivers/mtd/devices/doc2000.c1309
-rw-r--r--drivers/mtd/devices/doc2001.c888
-rw-r--r--drivers/mtd/devices/doc2001plus.c1154
-rw-r--r--drivers/mtd/devices/docecc.c526
-rw-r--r--drivers/mtd/devices/docprobe.c355
-rw-r--r--drivers/mtd/devices/lart.c711
-rw-r--r--drivers/mtd/devices/ms02-nv.c326
-rw-r--r--drivers/mtd/devices/ms02-nv.h107
-rw-r--r--drivers/mtd/devices/mtdram.c235
-rw-r--r--drivers/mtd/devices/phram.c285
-rw-r--r--drivers/mtd/devices/pmc551.c843
-rw-r--r--drivers/mtd/devices/slram.c357
16 files changed, 8698 insertions, 0 deletions
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
new file mode 100644
index 000000000000..c4a56a4ac5e2
--- /dev/null
+++ b/drivers/mtd/devices/Kconfig
@@ -0,0 +1,259 @@
1# drivers/mtd/maps/Kconfig
2# $Id: Kconfig,v 1.15 2004/12/22 17:51:15 joern Exp $
3
4menu "Self-contained MTD device drivers"
5 depends on MTD!=n
6
7config MTD_PMC551
8 tristate "Ramix PMC551 PCI Mezzanine RAM card support"
9 depends on MTD && PCI
10 ---help---
11 This provides a MTD device driver for the Ramix PMC551 RAM PCI card
12 from Ramix Inc. <http://www.ramix.com/products/memory/pmc551.html>.
13 These devices come in memory configurations from 32M - 1G. If you
14 have one, you probably want to enable this.
15
16 If this driver is compiled as a module you get the ability to select
17 the size of the aperture window pointing into the devices memory.
18 What this means is that if you have a 1G card, normally the kernel
19 will use a 1G memory map as its view of the device. As a module,
20 you can select a 1M window into the memory and the driver will
21 "slide" the window around the PMC551's memory. This was
22 particularly useful on the 2.2 kernels on PPC architectures as there
23 was limited kernel space to deal with.
24
25config MTD_PMC551_BUGFIX
26 bool "PMC551 256M DRAM Bugfix"
27 depends on MTD_PMC551
28 help
29 Some of Ramix's PMC551 boards with 256M configurations have invalid
30 column and row mux values. This option will fix them, but will
31 break other memory configurations. If unsure say N.
32
33config MTD_PMC551_DEBUG
34 bool "PMC551 Debugging"
35 depends on MTD_PMC551
36 help
37 This option makes the PMC551 more verbose during its operation and
38 is only really useful if you are developing on this driver or
39 suspect a possible hardware or driver bug. If unsure say N.
40
41config MTD_MS02NV
42 tristate "DEC MS02-NV NVRAM module support"
43 depends on MTD && MACH_DECSTATION
44 help
45 This is an MTD driver for the DEC's MS02-NV (54-20948-01) battery
46 backed-up NVRAM module. The module was originally meant as an NFS
47 accelerator. Say Y here if you have a DECstation 5000/2x0 or a
48 DECsystem 5900 equipped with such a module.
49
50config MTD_SLRAM
51 tristate "Uncached system RAM"
52 depends on MTD
53 help
54 If your CPU cannot cache all of the physical memory in your machine,
55 you can still use it for storage or swap by using this driver to
56 present it to the system as a Memory Technology Device.
57
58config MTD_PHRAM
59 tristate "Physical system RAM"
60 depends on MTD
61 help
62 This is a re-implementation of the slram driver above.
63
64 Use this driver to access physical memory that the kernel proper
65 doesn't have access to, memory beyond the mem=xxx limit, nvram,
66 memory on the video card, etc...
67
68config MTD_LART
69 tristate "28F160xx flash driver for LART"
70 depends on SA1100_LART && MTD
71 help
72 This enables the flash driver for LART. Please note that you do
73 not need any mapping/chip driver for LART. This one does it all
74 for you, so go disable all of those if you enabled some of them (:
75
76config MTD_MTDRAM
77 tristate "Test driver using RAM"
78 depends on MTD
79 help
80 This enables a test MTD device driver which uses vmalloc() to
81 provide storage. You probably want to say 'N' unless you're
82 testing stuff.
83
84config MTDRAM_TOTAL_SIZE
85 int "MTDRAM device size in KiB"
86 depends on MTD_MTDRAM
87 default "4096"
88 help
89 This allows you to configure the total size of the MTD device
90 emulated by the MTDRAM driver. If the MTDRAM driver is built
91 as a module, it is also possible to specify this as a parameter when
92 loading the module.
93
94config MTDRAM_ERASE_SIZE
95 int "MTDRAM erase block size in KiB"
96 depends on MTD_MTDRAM
97 default "128"
98 help
99 This allows you to configure the size of the erase blocks in the
100 device emulated by the MTDRAM driver. If the MTDRAM driver is built
101 as a module, it is also possible to specify this as a parameter when
102 loading the module.
103
104#If not a module (I don't want to test it as a module)
105config MTDRAM_ABS_POS
106 hex "SRAM Hexadecimal Absolute position or 0"
107 depends on MTD_MTDRAM=y
108 default "0"
109 help
110 If you have system RAM accessible by the CPU but not used by Linux
111 in normal operation, you can give the physical address at which the
112 available RAM starts, and the MTDRAM driver will use it instead of
113 allocating space from Linux's available memory. Otherwise, leave
114 this set to zero. Most people will want to leave this as zero.
115
116config MTD_BLKMTD
117 tristate "MTD emulation using block device"
118 depends on MTD
119 help
120 This driver allows a block device to appear as an MTD. It would
121 generally be used in the following cases:
122
123 Using Compact Flash as an MTD, these usually present themselves to
124 the system as an ATA drive.
125 Testing MTD users (eg JFFS2) on large media and media that might
126 be removed during a write (using the floppy drive).
127
128config MTD_BLOCK2MTD
129 tristate "MTD using block device (rewrite)"
130 depends on MTD && EXPERIMENTAL
131 help
132 This driver is basically the same at MTD_BLKMTD above, but
133 experienced some interface changes plus serious speedups. In
134 the long term, it should replace MTD_BLKMTD. Right now, you
135 shouldn't entrust important data to it yet.
136
137comment "Disk-On-Chip Device Drivers"
138
139config MTD_DOC2000
140 tristate "M-Systems Disk-On-Chip 2000 and Millennium (DEPRECATED)"
141 depends on MTD
142 select MTD_DOCPROBE
143 select MTD_NAND_IDS
144 ---help---
145 This provides an MTD device driver for the M-Systems DiskOnChip
146 2000 and Millennium devices. Originally designed for the DiskOnChip
147 2000, it also now includes support for the DiskOnChip Millennium.
148 If you have problems with this driver and the DiskOnChip Millennium,
149 you may wish to try the alternative Millennium driver below. To use
150 the alternative driver, you will need to undefine DOC_SINGLE_DRIVER
151 in the <file:drivers/mtd/devices/docprobe.c> source code.
152
153 If you use this device, you probably also want to enable the NFTL
154 'NAND Flash Translation Layer' option below, which is used to
155 emulate a block device by using a kind of file system on the flash
156 chips.
157
158 NOTE: This driver is deprecated and will probably be removed soon.
159 Please try the new DiskOnChip driver under "NAND Flash Device
160 Drivers".
161
162config MTD_DOC2001
163 tristate "M-Systems Disk-On-Chip Millennium-only alternative driver (DEPRECATED)"
164 depends on MTD
165 select MTD_DOCPROBE
166 select MTD_NAND_IDS
167 ---help---
168 This provides an alternative MTD device driver for the M-Systems
169 DiskOnChip Millennium devices. Use this if you have problems with
170 the combined DiskOnChip 2000 and Millennium driver above. To get
171 the DiskOnChip probe code to load and use this driver instead of
172 the other one, you will need to undefine DOC_SINGLE_DRIVER near
173 the beginning of <file:drivers/mtd/devices/docprobe.c>.
174
175 If you use this device, you probably also want to enable the NFTL
176 'NAND Flash Translation Layer' option below, which is used to
177 emulate a block device by using a kind of file system on the flash
178 chips.
179
180 NOTE: This driver is deprecated and will probably be removed soon.
181 Please try the new DiskOnChip driver under "NAND Flash Device
182 Drivers".
183
184config MTD_DOC2001PLUS
185 tristate "M-Systems Disk-On-Chip Millennium Plus"
186 depends on MTD
187 select MTD_DOCPROBE
188 select MTD_NAND_IDS
189 ---help---
190 This provides an MTD device driver for the M-Systems DiskOnChip
191 Millennium Plus devices.
192
193 If you use this device, you probably also want to enable the INFTL
194 'Inverse NAND Flash Translation Layer' option below, which is used
195 to emulate a block device by using a kind of file system on the
196 flash chips.
197
198 NOTE: This driver will soon be replaced by the new DiskOnChip driver
199 under "NAND Flash Device Drivers" (currently that driver does not
200 support all Millennium Plus devices).
201
202config MTD_DOCPROBE
203 tristate
204 select MTD_DOCECC
205
206config MTD_DOCECC
207 tristate
208
209config MTD_DOCPROBE_ADVANCED
210 bool "Advanced detection options for DiskOnChip"
211 depends on MTD_DOCPROBE
212 help
213 This option allows you to specify nonstandard address at which to
214 probe for a DiskOnChip, or to change the detection options. You
215 are unlikely to need any of this unless you are using LinuxBIOS.
216 Say 'N'.
217
218config MTD_DOCPROBE_ADDRESS
219 hex "Physical address of DiskOnChip" if MTD_DOCPROBE_ADVANCED
220 depends on MTD_DOCPROBE
221 default "0x0000" if MTD_DOCPROBE_ADVANCED
222 default "0" if !MTD_DOCPROBE_ADVANCED
223 ---help---
224 By default, the probe for DiskOnChip devices will look for a
225 DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
226 This option allows you to specify a single address at which to probe
227 for the device, which is useful if you have other devices in that
228 range which get upset when they are probed.
229
230 (Note that on PowerPC, the normal probe will only check at
231 0xE4000000.)
232
233 Normally, you should leave this set to zero, to allow the probe at
234 the normal addresses.
235
236config MTD_DOCPROBE_HIGH
237 bool "Probe high addresses"
238 depends on MTD_DOCPROBE_ADVANCED
239 help
240 By default, the probe for DiskOnChip devices will look for a
241 DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
242 This option changes to make it probe between 0xFFFC8000 and
243 0xFFFEE000. Unless you are using LinuxBIOS, this is unlikely to be
244 useful to you. Say 'N'.
245
246config MTD_DOCPROBE_55AA
247 bool "Probe for 0x55 0xAA BIOS Extension Signature"
248 depends on MTD_DOCPROBE_ADVANCED
249 help
250 Check for the 0x55 0xAA signature of a DiskOnChip, and do not
251 continue with probing if it is absent. The signature will always be
252 present for a DiskOnChip 2000 or a normal DiskOnChip Millennium.
253 Only if you have overwritten the first block of a DiskOnChip
254 Millennium will it be absent. Enable this option if you are using
255 LinuxBIOS or if you need to recover a DiskOnChip Millennium on which
256 you have managed to wipe the first block.
257
258endmenu
259
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
new file mode 100644
index 000000000000..e38db348057d
--- /dev/null
+++ b/drivers/mtd/devices/Makefile
@@ -0,0 +1,25 @@
1#
2# linux/drivers/devices/Makefile
3#
4# $Id: Makefile.common,v 1.7 2004/12/22 17:51:15 joern Exp $
5
6# *** BIG UGLY NOTE ***
7#
8# The removal of get_module_symbol() and replacement with
9# inter_module_register() et al has introduced a link order dependency
10# here where previously there was none. We now have to ensure that
11# doc200[01].o are linked before docprobe.o
12
13obj-$(CONFIG_MTD_DOC2000) += doc2000.o
14obj-$(CONFIG_MTD_DOC2001) += doc2001.o
15obj-$(CONFIG_MTD_DOC2001PLUS) += doc2001plus.o
16obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o
17obj-$(CONFIG_MTD_DOCECC) += docecc.o
18obj-$(CONFIG_MTD_SLRAM) += slram.o
19obj-$(CONFIG_MTD_PHRAM) += phram.o
20obj-$(CONFIG_MTD_PMC551) += pmc551.o
21obj-$(CONFIG_MTD_MS02NV) += ms02-nv.o
22obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
23obj-$(CONFIG_MTD_LART) += lart.o
24obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o
25obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c
new file mode 100644
index 000000000000..662e807801ed
--- /dev/null
+++ b/drivers/mtd/devices/blkmtd.c
@@ -0,0 +1,823 @@
1/*
2 * $Id: blkmtd.c,v 1.24 2004/11/16 18:29:01 dwmw2 Exp $
3 *
4 * blkmtd.c - use a block device as a fake MTD
5 *
6 * Author: Simon Evans <spse@secret.org.uk>
7 *
8 * Copyright (C) 2001,2002 Simon Evans
9 *
10 * Licence: GPL
11 *
12 * How it works:
13 * The driver uses raw/io to read/write the device and the page
14 * cache to cache access. Writes update the page cache with the
15 * new data and mark it dirty and add the page into a BIO which
16 * is then written out.
17 *
18 * It can be loaded Read-Only to prevent erases and writes to the
19 * medium.
20 *
21 */
22
23#include <linux/config.h>
24#include <linux/module.h>
25#include <linux/fs.h>
26#include <linux/blkdev.h>
27#include <linux/bio.h>
28#include <linux/pagemap.h>
29#include <linux/list.h>
30#include <linux/init.h>
31#include <linux/mtd/mtd.h>
32
33
34#define err(format, arg...) printk(KERN_ERR "blkmtd: " format "\n" , ## arg)
35#define info(format, arg...) printk(KERN_INFO "blkmtd: " format "\n" , ## arg)
36#define warn(format, arg...) printk(KERN_WARNING "blkmtd: " format "\n" , ## arg)
37#define crit(format, arg...) printk(KERN_CRIT "blkmtd: " format "\n" , ## arg)
38
39
40/* Default erase size in K, always make it a multiple of PAGE_SIZE */
41#define CONFIG_MTD_BLKDEV_ERASESIZE (128 << 10) /* 128KiB */
42#define VERSION "$Revision: 1.24 $"
43
44/* Info for the block device */
45struct blkmtd_dev {
46 struct list_head list;
47 struct block_device *blkdev;
48 struct mtd_info mtd_info;
49 struct semaphore wrbuf_mutex;
50};
51
52
53/* Static info about the MTD, used in cleanup_module */
54static LIST_HEAD(blkmtd_device_list);
55
56
57static void blkmtd_sync(struct mtd_info *mtd);
58
59#define MAX_DEVICES 4
60
61/* Module parameters passed by insmod/modprobe */
62static char *device[MAX_DEVICES]; /* the block device to use */
63static int erasesz[MAX_DEVICES]; /* optional default erase size */
64static int ro[MAX_DEVICES]; /* optional read only flag */
65static int sync;
66
67
68MODULE_LICENSE("GPL");
69MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
70MODULE_DESCRIPTION("Emulate an MTD using a block device");
71module_param_array(device, charp, NULL, 0);
72MODULE_PARM_DESC(device, "block device to use");
73module_param_array(erasesz, int, NULL, 0);
74MODULE_PARM_DESC(erasesz, "optional erase size to use in KiB. eg 4=4KiB.");
75module_param_array(ro, bool, NULL, 0);
76MODULE_PARM_DESC(ro, "1=Read only, writes and erases cause errors");
77module_param(sync, bool, 0);
78MODULE_PARM_DESC(sync, "1=Synchronous writes");
79
80
81/* completion handler for BIO reads */
82static int bi_read_complete(struct bio *bio, unsigned int bytes_done, int error)
83{
84 if (bio->bi_size)
85 return 1;
86
87 complete((struct completion*)bio->bi_private);
88 return 0;
89}
90
91
92/* completion handler for BIO writes */
93static int bi_write_complete(struct bio *bio, unsigned int bytes_done, int error)
94{
95 const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
96 struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
97
98 if (bio->bi_size)
99 return 1;
100
101 if(!uptodate)
102 err("bi_write_complete: not uptodate\n");
103
104 do {
105 struct page *page = bvec->bv_page;
106 DEBUG(3, "Cleaning up page %ld\n", page->index);
107 if (--bvec >= bio->bi_io_vec)
108 prefetchw(&bvec->bv_page->flags);
109
110 if (uptodate) {
111 SetPageUptodate(page);
112 } else {
113 ClearPageUptodate(page);
114 SetPageError(page);
115 }
116 ClearPageDirty(page);
117 unlock_page(page);
118 page_cache_release(page);
119 } while (bvec >= bio->bi_io_vec);
120
121 complete((struct completion*)bio->bi_private);
122 return 0;
123}
124
125
126/* read one page from the block device */
127static int blkmtd_readpage(struct blkmtd_dev *dev, struct page *page)
128{
129 struct bio *bio;
130 struct completion event;
131 int err = -ENOMEM;
132
133 if(PageUptodate(page)) {
134 DEBUG(2, "blkmtd: readpage page %ld is already upto date\n", page->index);
135 unlock_page(page);
136 return 0;
137 }
138
139 ClearPageUptodate(page);
140 ClearPageError(page);
141
142 bio = bio_alloc(GFP_KERNEL, 1);
143 if(bio) {
144 init_completion(&event);
145 bio->bi_bdev = dev->blkdev;
146 bio->bi_sector = page->index << (PAGE_SHIFT-9);
147 bio->bi_private = &event;
148 bio->bi_end_io = bi_read_complete;
149 if(bio_add_page(bio, page, PAGE_SIZE, 0) == PAGE_SIZE) {
150 submit_bio(READ_SYNC, bio);
151 wait_for_completion(&event);
152 err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO;
153 bio_put(bio);
154 }
155 }
156
157 if(err)
158 SetPageError(page);
159 else
160 SetPageUptodate(page);
161 flush_dcache_page(page);
162 unlock_page(page);
163 return err;
164}
165
166
167/* write out the current BIO and wait for it to finish */
168static int blkmtd_write_out(struct bio *bio)
169{
170 struct completion event;
171 int err;
172
173 if(!bio->bi_vcnt) {
174 bio_put(bio);
175 return 0;
176 }
177
178 init_completion(&event);
179 bio->bi_private = &event;
180 bio->bi_end_io = bi_write_complete;
181 submit_bio(WRITE_SYNC, bio);
182 wait_for_completion(&event);
183 DEBUG(3, "submit_bio completed, bi_vcnt = %d\n", bio->bi_vcnt);
184 err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO;
185 bio_put(bio);
186 return err;
187}
188
189
190/**
191 * blkmtd_add_page - add a page to the current BIO
192 * @bio: bio to add to (NULL to alloc initial bio)
193 * @blkdev: block device
194 * @page: page to add
195 * @pagecnt: pages left to add
196 *
197 * Adds a page to the current bio, allocating it if necessary. If it cannot be
198 * added, the current bio is written out and a new one is allocated. Returns
199 * the new bio to add or NULL on error
200 */
201static struct bio *blkmtd_add_page(struct bio *bio, struct block_device *blkdev,
202 struct page *page, int pagecnt)
203{
204
205 retry:
206 if(!bio) {
207 bio = bio_alloc(GFP_KERNEL, pagecnt);
208 if(!bio)
209 return NULL;
210 bio->bi_sector = page->index << (PAGE_SHIFT-9);
211 bio->bi_bdev = blkdev;
212 }
213
214 if(bio_add_page(bio, page, PAGE_SIZE, 0) != PAGE_SIZE) {
215 blkmtd_write_out(bio);
216 bio = NULL;
217 goto retry;
218 }
219 return bio;
220}
221
222
223/**
224 * write_pages - write block of data to device via the page cache
225 * @dev: device to write to
226 * @buf: data source or NULL if erase (output is set to 0xff)
227 * @to: offset into output device
228 * @len: amount to data to write
229 * @retlen: amount of data written
230 *
231 * Grab pages from the page cache and fill them with the source data.
232 * Non page aligned start and end result in a readin of the page and
233 * part of the page being modified. Pages are added to the bio and then written
234 * out.
235 */
236static int write_pages(struct blkmtd_dev *dev, const u_char *buf, loff_t to,
237 size_t len, size_t *retlen)
238{
239 int pagenr, offset;
240 size_t start_len = 0, end_len;
241 int pagecnt = 0;
242 int err = 0;
243 struct bio *bio = NULL;
244 size_t thislen = 0;
245
246 pagenr = to >> PAGE_SHIFT;
247 offset = to & ~PAGE_MASK;
248
249 DEBUG(2, "blkmtd: write_pages: buf = %p to = %ld len = %zd pagenr = %d offset = %d\n",
250 buf, (long)to, len, pagenr, offset);
251
252 /* see if we have to do a partial write at the start */
253 if(offset) {
254 start_len = ((offset + len) > PAGE_SIZE) ? PAGE_SIZE - offset : len;
255 len -= start_len;
256 }
257
258 /* calculate the length of the other two regions */
259 end_len = len & ~PAGE_MASK;
260 len -= end_len;
261
262 if(start_len)
263 pagecnt++;
264
265 if(len)
266 pagecnt += len >> PAGE_SHIFT;
267
268 if(end_len)
269 pagecnt++;
270
271 down(&dev->wrbuf_mutex);
272
273 DEBUG(3, "blkmtd: write: start_len = %zd len = %zd end_len = %zd pagecnt = %d\n",
274 start_len, len, end_len, pagecnt);
275
276 if(start_len) {
277 /* do partial start region */
278 struct page *page;
279
280 DEBUG(3, "blkmtd: write: doing partial start, page = %d len = %zd offset = %d\n",
281 pagenr, start_len, offset);
282
283 BUG_ON(!buf);
284 page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
285 lock_page(page);
286 if(PageDirty(page)) {
287 err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d\n",
288 to, start_len, len, end_len, pagenr);
289 BUG();
290 }
291 memcpy(page_address(page)+offset, buf, start_len);
292 SetPageDirty(page);
293 SetPageUptodate(page);
294 buf += start_len;
295 thislen = start_len;
296 bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt);
297 if(!bio) {
298 err = -ENOMEM;
299 err("bio_add_page failed\n");
300 goto write_err;
301 }
302 pagecnt--;
303 pagenr++;
304 }
305
306 /* Now do the main loop to a page aligned, n page sized output */
307 if(len) {
308 int pagesc = len >> PAGE_SHIFT;
309 DEBUG(3, "blkmtd: write: whole pages start = %d, count = %d\n",
310 pagenr, pagesc);
311 while(pagesc) {
312 struct page *page;
313
314 /* see if page is in the page cache */
315 DEBUG(3, "blkmtd: write: grabbing page %d from page cache\n", pagenr);
316 page = grab_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr);
317 if(PageDirty(page)) {
318 BUG();
319 }
320 if(!page) {
321 warn("write: cannot grab cache page %d", pagenr);
322 err = -ENOMEM;
323 goto write_err;
324 }
325 if(!buf) {
326 memset(page_address(page), 0xff, PAGE_SIZE);
327 } else {
328 memcpy(page_address(page), buf, PAGE_SIZE);
329 buf += PAGE_SIZE;
330 }
331 bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt);
332 if(!bio) {
333 err = -ENOMEM;
334 err("bio_add_page failed\n");
335 goto write_err;
336 }
337 pagenr++;
338 pagecnt--;
339 SetPageDirty(page);
340 SetPageUptodate(page);
341 pagesc--;
342 thislen += PAGE_SIZE;
343 }
344 }
345
346 if(end_len) {
347 /* do the third region */
348 struct page *page;
349 DEBUG(3, "blkmtd: write: doing partial end, page = %d len = %zd\n",
350 pagenr, end_len);
351 BUG_ON(!buf);
352 page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
353 lock_page(page);
354 if(PageDirty(page)) {
355 err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d\n",
356 to, start_len, len, end_len, pagenr);
357 BUG();
358 }
359 memcpy(page_address(page), buf, end_len);
360 SetPageDirty(page);
361 SetPageUptodate(page);
362 DEBUG(3, "blkmtd: write: writing out partial end\n");
363 thislen += end_len;
364 bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt);
365 if(!bio) {
366 err = -ENOMEM;
367 err("bio_add_page failed\n");
368 goto write_err;
369 }
370 pagenr++;
371 }
372
373 DEBUG(3, "blkmtd: write: got %d vectors to write\n", bio->bi_vcnt);
374 write_err:
375 if(bio)
376 blkmtd_write_out(bio);
377
378 DEBUG(2, "blkmtd: write: end, retlen = %zd, err = %d\n", *retlen, err);
379 up(&dev->wrbuf_mutex);
380
381 if(retlen)
382 *retlen = thislen;
383 return err;
384}
385
386
387/* erase a specified part of the device */
388static int blkmtd_erase(struct mtd_info *mtd, struct erase_info *instr)
389{
390 struct blkmtd_dev *dev = mtd->priv;
391 struct mtd_erase_region_info *einfo = mtd->eraseregions;
392 int numregions = mtd->numeraseregions;
393 size_t from;
394 u_long len;
395 int err = -EIO;
396 size_t retlen;
397
398 instr->state = MTD_ERASING;
399 from = instr->addr;
400 len = instr->len;
401
402 /* check erase region has valid start and length */
403 DEBUG(2, "blkmtd: erase: dev = `%s' from = 0x%zx len = 0x%lx\n",
404 mtd->name+9, from, len);
405 while(numregions) {
406 DEBUG(3, "blkmtd: checking erase region = 0x%08X size = 0x%X num = 0x%x\n",
407 einfo->offset, einfo->erasesize, einfo->numblocks);
408 if(from >= einfo->offset
409 && from < einfo->offset + (einfo->erasesize * einfo->numblocks)) {
410 if(len == einfo->erasesize
411 && ( (from - einfo->offset) % einfo->erasesize == 0))
412 break;
413 }
414 numregions--;
415 einfo++;
416 }
417
418 if(!numregions) {
419 /* Not a valid erase block */
420 err("erase: invalid erase request 0x%lX @ 0x%08zX", len, from);
421 instr->state = MTD_ERASE_FAILED;
422 err = -EIO;
423 }
424
425 if(instr->state != MTD_ERASE_FAILED) {
426 /* do the erase */
427 DEBUG(3, "Doing erase from = %zd len = %ld\n", from, len);
428 err = write_pages(dev, NULL, from, len, &retlen);
429 if(err || retlen != len) {
430 err("erase failed err = %d", err);
431 instr->state = MTD_ERASE_FAILED;
432 } else {
433 instr->state = MTD_ERASE_DONE;
434 }
435 }
436
437 DEBUG(3, "blkmtd: erase: checking callback\n");
438 mtd_erase_callback(instr);
439 DEBUG(2, "blkmtd: erase: finished (err = %d)\n", err);
440 return err;
441}
442
443
444/* read a range of the data via the page cache */
445static int blkmtd_read(struct mtd_info *mtd, loff_t from, size_t len,
446 size_t *retlen, u_char *buf)
447{
448 struct blkmtd_dev *dev = mtd->priv;
449 int err = 0;
450 int offset;
451 int pagenr, pages;
452 size_t thislen = 0;
453
454 DEBUG(2, "blkmtd: read: dev = `%s' from = %lld len = %zd buf = %p\n",
455 mtd->name+9, from, len, buf);
456
457 if(from > mtd->size)
458 return -EINVAL;
459 if(from + len > mtd->size)
460 len = mtd->size - from;
461
462 pagenr = from >> PAGE_SHIFT;
463 offset = from - (pagenr << PAGE_SHIFT);
464
465 pages = (offset+len+PAGE_SIZE-1) >> PAGE_SHIFT;
466 DEBUG(3, "blkmtd: read: pagenr = %d offset = %d, pages = %d\n",
467 pagenr, offset, pages);
468
469 while(pages) {
470 struct page *page;
471 int cpylen;
472
473 DEBUG(3, "blkmtd: read: looking for page: %d\n", pagenr);
474 page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
475 if(IS_ERR(page)) {
476 err = -EIO;
477 goto readerr;
478 }
479
480 cpylen = (PAGE_SIZE > len) ? len : PAGE_SIZE;
481 if(offset+cpylen > PAGE_SIZE)
482 cpylen = PAGE_SIZE-offset;
483
484 memcpy(buf + thislen, page_address(page) + offset, cpylen);
485 offset = 0;
486 len -= cpylen;
487 thislen += cpylen;
488 pagenr++;
489 pages--;
490 if(!PageDirty(page))
491 page_cache_release(page);
492 }
493
494 readerr:
495 if(retlen)
496 *retlen = thislen;
497 DEBUG(2, "blkmtd: end read: retlen = %zd, err = %d\n", thislen, err);
498 return err;
499}
500
501
502/* write data to the underlying device */
503static int blkmtd_write(struct mtd_info *mtd, loff_t to, size_t len,
504 size_t *retlen, const u_char *buf)
505{
506 struct blkmtd_dev *dev = mtd->priv;
507 int err;
508
509 if(!len)
510 return 0;
511
512 DEBUG(2, "blkmtd: write: dev = `%s' to = %lld len = %zd buf = %p\n",
513 mtd->name+9, to, len, buf);
514
515 if(to >= mtd->size) {
516 return -ENOSPC;
517 }
518
519 if(to + len > mtd->size) {
520 len = mtd->size - to;
521 }
522
523 err = write_pages(dev, buf, to, len, retlen);
524 if(err > 0)
525 err = 0;
526 DEBUG(2, "blkmtd: write: end, err = %d\n", err);
527 return err;
528}
529
530
531/* sync the device - wait until the write queue is empty */
532static void blkmtd_sync(struct mtd_info *mtd)
533{
534 /* Currently all writes are synchronous */
535}
536
537
538static void free_device(struct blkmtd_dev *dev)
539{
540 DEBUG(2, "blkmtd: free_device() dev = %p\n", dev);
541 if(dev) {
542 if(dev->mtd_info.eraseregions)
543 kfree(dev->mtd_info.eraseregions);
544 if(dev->mtd_info.name)
545 kfree(dev->mtd_info.name);
546
547 if(dev->blkdev) {
548 invalidate_inode_pages(dev->blkdev->bd_inode->i_mapping);
549 close_bdev_excl(dev->blkdev);
550 }
551 kfree(dev);
552 }
553}
554
555
556/* For a given size and initial erase size, calculate the number
557 * and size of each erase region. Goes round the loop twice,
558 * once to find out how many regions, then allocates space,
559 * then round the loop again to fill it in.
560 */
561static struct mtd_erase_region_info *calc_erase_regions(
562 size_t erase_size, size_t total_size, int *regions)
563{
564 struct mtd_erase_region_info *info = NULL;
565
566 DEBUG(2, "calc_erase_regions, es = %zd size = %zd regions = %d\n",
567 erase_size, total_size, *regions);
568 /* Make any user specified erasesize be a power of 2
569 and at least PAGE_SIZE */
570 if(erase_size) {
571 int es = erase_size;
572 erase_size = 1;
573 while(es != 1) {
574 es >>= 1;
575 erase_size <<= 1;
576 }
577 if(erase_size < PAGE_SIZE)
578 erase_size = PAGE_SIZE;
579 } else {
580 erase_size = CONFIG_MTD_BLKDEV_ERASESIZE;
581 }
582
583 *regions = 0;
584
585 do {
586 int tot_size = total_size;
587 int er_size = erase_size;
588 int count = 0, offset = 0, regcnt = 0;
589
590 while(tot_size) {
591 count = tot_size / er_size;
592 if(count) {
593 tot_size = tot_size % er_size;
594 if(info) {
595 DEBUG(2, "adding to erase info off=%d er=%d cnt=%d\n",
596 offset, er_size, count);
597 (info+regcnt)->offset = offset;
598 (info+regcnt)->erasesize = er_size;
599 (info+regcnt)->numblocks = count;
600 (*regions)++;
601 }
602 regcnt++;
603 offset += (count * er_size);
604 }
605 while(er_size > tot_size)
606 er_size >>= 1;
607 }
608 if(info == NULL) {
609 info = kmalloc(regcnt * sizeof(struct mtd_erase_region_info), GFP_KERNEL);
610 if(!info)
611 break;
612 }
613 } while(!(*regions));
614 DEBUG(2, "calc_erase_regions done, es = %zd size = %zd regions = %d\n",
615 erase_size, total_size, *regions);
616 return info;
617}
618
619
620extern dev_t __init name_to_dev_t(const char *line);
621
622static struct blkmtd_dev *add_device(char *devname, int readonly, int erase_size)
623{
624 struct block_device *bdev;
625 int mode;
626 struct blkmtd_dev *dev;
627
628 if(!devname)
629 return NULL;
630
631 /* Get a handle on the device */
632
633
634#ifdef MODULE
635 mode = (readonly) ? O_RDONLY : O_RDWR;
636 bdev = open_bdev_excl(devname, mode, NULL);
637#else
638 mode = (readonly) ? FMODE_READ : FMODE_WRITE;
639 bdev = open_by_devnum(name_to_dev_t(devname), mode);
640#endif
641 if(IS_ERR(bdev)) {
642 err("error: cannot open device %s", devname);
643 DEBUG(2, "blkmtd: opening bdev returned %ld\n", PTR_ERR(bdev));
644 return NULL;
645 }
646
647 DEBUG(1, "blkmtd: found a block device major = %d, minor = %d\n",
648 MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
649
650 if(MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
651 err("attempting to use an MTD device as a block device");
652 blkdev_put(bdev);
653 return NULL;
654 }
655
656 dev = kmalloc(sizeof(struct blkmtd_dev), GFP_KERNEL);
657 if(dev == NULL) {
658 blkdev_put(bdev);
659 return NULL;
660 }
661
662 memset(dev, 0, sizeof(struct blkmtd_dev));
663 dev->blkdev = bdev;
664 if(!readonly) {
665 init_MUTEX(&dev->wrbuf_mutex);
666 }
667
668 dev->mtd_info.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
669
670 /* Setup the MTD structure */
671 /* make the name contain the block device in */
672 dev->mtd_info.name = kmalloc(sizeof("blkmtd: ") + strlen(devname), GFP_KERNEL);
673 if(dev->mtd_info.name == NULL)
674 goto devinit_err;
675
676 sprintf(dev->mtd_info.name, "blkmtd: %s", devname);
677 dev->mtd_info.eraseregions = calc_erase_regions(erase_size, dev->mtd_info.size,
678 &dev->mtd_info.numeraseregions);
679 if(dev->mtd_info.eraseregions == NULL)
680 goto devinit_err;
681
682 dev->mtd_info.erasesize = dev->mtd_info.eraseregions->erasesize;
683 DEBUG(1, "blkmtd: init: found %d erase regions\n",
684 dev->mtd_info.numeraseregions);
685
686 if(readonly) {
687 dev->mtd_info.type = MTD_ROM;
688 dev->mtd_info.flags = MTD_CAP_ROM;
689 } else {
690 dev->mtd_info.type = MTD_RAM;
691 dev->mtd_info.flags = MTD_CAP_RAM;
692 dev->mtd_info.erase = blkmtd_erase;
693 dev->mtd_info.write = blkmtd_write;
694 dev->mtd_info.writev = default_mtd_writev;
695 dev->mtd_info.sync = blkmtd_sync;
696 }
697 dev->mtd_info.read = blkmtd_read;
698 dev->mtd_info.readv = default_mtd_readv;
699 dev->mtd_info.priv = dev;
700 dev->mtd_info.owner = THIS_MODULE;
701
702 list_add(&dev->list, &blkmtd_device_list);
703 if (add_mtd_device(&dev->mtd_info)) {
704 /* Device didnt get added, so free the entry */
705 list_del(&dev->list);
706 goto devinit_err;
707 } else {
708 info("mtd%d: [%s] erase_size = %dKiB %s",
709 dev->mtd_info.index, dev->mtd_info.name + strlen("blkmtd: "),
710 dev->mtd_info.erasesize >> 10,
711 readonly ? "(read-only)" : "");
712 }
713
714 return dev;
715
716 devinit_err:
717 free_device(dev);
718 return NULL;
719}
720
721
722/* Cleanup and exit - sync the device and kill of the kernel thread */
723static void __devexit cleanup_blkmtd(void)
724{
725 struct list_head *temp1, *temp2;
726
727 /* Remove the MTD devices */
728 list_for_each_safe(temp1, temp2, &blkmtd_device_list) {
729 struct blkmtd_dev *dev = list_entry(temp1, struct blkmtd_dev,
730 list);
731 blkmtd_sync(&dev->mtd_info);
732 del_mtd_device(&dev->mtd_info);
733 info("mtd%d: [%s] removed", dev->mtd_info.index,
734 dev->mtd_info.name + strlen("blkmtd: "));
735 list_del(&dev->list);
736 free_device(dev);
737 }
738}
739
740#ifndef MODULE
741
742/* Handle kernel boot params */
743
744
745static int __init param_blkmtd_device(char *str)
746{
747 int i;
748
749 for(i = 0; i < MAX_DEVICES; i++) {
750 device[i] = str;
751 DEBUG(2, "blkmtd: device setup: %d = %s\n", i, device[i]);
752 strsep(&str, ",");
753 }
754 return 1;
755}
756
757
758static int __init param_blkmtd_erasesz(char *str)
759{
760 int i;
761 for(i = 0; i < MAX_DEVICES; i++) {
762 char *val = strsep(&str, ",");
763 if(val)
764 erasesz[i] = simple_strtoul(val, NULL, 0);
765 DEBUG(2, "blkmtd: erasesz setup: %d = %d\n", i, erasesz[i]);
766 }
767
768 return 1;
769}
770
771
772static int __init param_blkmtd_ro(char *str)
773{
774 int i;
775 for(i = 0; i < MAX_DEVICES; i++) {
776 char *val = strsep(&str, ",");
777 if(val)
778 ro[i] = simple_strtoul(val, NULL, 0);
779 DEBUG(2, "blkmtd: ro setup: %d = %d\n", i, ro[i]);
780 }
781
782 return 1;
783}
784
785
786static int __init param_blkmtd_sync(char *str)
787{
788 if(str[0] == '1')
789 sync = 1;
790 return 1;
791}
792
793__setup("blkmtd_device=", param_blkmtd_device);
794__setup("blkmtd_erasesz=", param_blkmtd_erasesz);
795__setup("blkmtd_ro=", param_blkmtd_ro);
796__setup("blkmtd_sync=", param_blkmtd_sync);
797
798#endif
799
800
801/* Startup */
802static int __init init_blkmtd(void)
803{
804 int i;
805
806 info("version " VERSION);
807 /* Check args - device[0] is the bare minimum*/
808 if(!device[0]) {
809 err("error: missing `device' name\n");
810 return -EINVAL;
811 }
812
813 for(i = 0; i < MAX_DEVICES; i++)
814 add_device(device[i], ro[i], erasesz[i] << 10);
815
816 if(list_empty(&blkmtd_device_list))
817 return -EINVAL;
818
819 return 0;
820}
821
822module_init(init_blkmtd);
823module_exit(cleanup_blkmtd);
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
new file mode 100644
index 000000000000..cfe6ccf07972
--- /dev/null
+++ b/drivers/mtd/devices/block2mtd.c
@@ -0,0 +1,495 @@
1/*
2 * $Id: block2mtd.c,v 1.23 2005/01/05 17:05:46 dwmw2 Exp $
3 *
4 * block2mtd.c - create an mtd from a block device
5 *
6 * Copyright (C) 2001,2002 Simon Evans <spse@secret.org.uk>
7 * Copyright (C) 2004 Gareth Bult <Gareth@Encryptec.net>
8 * Copyright (C) 2004,2005 Jörn Engel <joern@wh.fh-wedel.de>
9 *
10 * Licence: GPL
11 */
12#include <linux/config.h>
13#include <linux/module.h>
14#include <linux/fs.h>
15#include <linux/blkdev.h>
16#include <linux/bio.h>
17#include <linux/pagemap.h>
18#include <linux/list.h>
19#include <linux/init.h>
20#include <linux/mtd/mtd.h>
21#include <linux/buffer_head.h>
22
23#define VERSION "$Revision: 1.23 $"
24
25
26#define ERROR(fmt, args...) printk(KERN_ERR "block2mtd: " fmt "\n" , ## args)
27#define INFO(fmt, args...) printk(KERN_INFO "block2mtd: " fmt "\n" , ## args)
28
29
30/* Info for the block device */
31struct block2mtd_dev {
32 struct list_head list;
33 struct block_device *blkdev;
34 struct mtd_info mtd;
35 struct semaphore write_mutex;
36};
37
38
39/* Static info about the MTD, used in cleanup_module */
40static LIST_HEAD(blkmtd_device_list);
41
42
43#define PAGE_READAHEAD 64
44void cache_readahead(struct address_space *mapping, int index)
45{
46 filler_t *filler = (filler_t*)mapping->a_ops->readpage;
47 int i, pagei;
48 unsigned ret = 0;
49 unsigned long end_index;
50 struct page *page;
51 LIST_HEAD(page_pool);
52 struct inode *inode = mapping->host;
53 loff_t isize = i_size_read(inode);
54
55 if (!isize) {
56 INFO("iSize=0 in cache_readahead\n");
57 return;
58 }
59
60 end_index = ((isize - 1) >> PAGE_CACHE_SHIFT);
61
62 read_lock_irq(&mapping->tree_lock);
63 for (i = 0; i < PAGE_READAHEAD; i++) {
64 pagei = index + i;
65 if (pagei > end_index) {
66 INFO("Overrun end of disk in cache readahead\n");
67 break;
68 }
69 page = radix_tree_lookup(&mapping->page_tree, pagei);
70 if (page && (!i))
71 break;
72 if (page)
73 continue;
74 read_unlock_irq(&mapping->tree_lock);
75 page = page_cache_alloc_cold(mapping);
76 read_lock_irq(&mapping->tree_lock);
77 if (!page)
78 break;
79 page->index = pagei;
80 list_add(&page->lru, &page_pool);
81 ret++;
82 }
83 read_unlock_irq(&mapping->tree_lock);
84 if (ret)
85 read_cache_pages(mapping, &page_pool, filler, NULL);
86}
87
88
89static struct page* page_readahead(struct address_space *mapping, int index)
90{
91 filler_t *filler = (filler_t*)mapping->a_ops->readpage;
92 //do_page_cache_readahead(mapping, index, XXX, 64);
93 cache_readahead(mapping, index);
94 return read_cache_page(mapping, index, filler, NULL);
95}
96
97
98/* erase a specified part of the device */
99static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len)
100{
101 struct address_space *mapping = dev->blkdev->bd_inode->i_mapping;
102 struct page *page;
103 int index = to >> PAGE_SHIFT; // page index
104 int pages = len >> PAGE_SHIFT;
105 u_long *p;
106 u_long *max;
107
108 while (pages) {
109 page = page_readahead(mapping, index);
110 if (!page)
111 return -ENOMEM;
112 if (IS_ERR(page))
113 return PTR_ERR(page);
114
115 max = (u_long*)page_address(page) + PAGE_SIZE;
116 for (p=(u_long*)page_address(page); p<max; p++)
117 if (*p != -1UL) {
118 lock_page(page);
119 memset(page_address(page), 0xff, PAGE_SIZE);
120 set_page_dirty(page);
121 unlock_page(page);
122 break;
123 }
124
125 page_cache_release(page);
126 pages--;
127 index++;
128 }
129 return 0;
130}
131static int block2mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
132{
133 struct block2mtd_dev *dev = mtd->priv;
134 size_t from = instr->addr;
135 size_t len = instr->len;
136 int err;
137
138 instr->state = MTD_ERASING;
139 down(&dev->write_mutex);
140 err = _block2mtd_erase(dev, from, len);
141 up(&dev->write_mutex);
142 if (err) {
143 ERROR("erase failed err = %d", err);
144 instr->state = MTD_ERASE_FAILED;
145 } else
146 instr->state = MTD_ERASE_DONE;
147
148 instr->state = MTD_ERASE_DONE;
149 mtd_erase_callback(instr);
150 return err;
151}
152
153
154static int block2mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
155 size_t *retlen, u_char *buf)
156{
157 struct block2mtd_dev *dev = mtd->priv;
158 struct page *page;
159 int index = from >> PAGE_SHIFT;
160 int offset = from & (PAGE_SHIFT-1);
161 int cpylen;
162
163 if (from > mtd->size)
164 return -EINVAL;
165 if (from + len > mtd->size)
166 len = mtd->size - from;
167
168 if (retlen)
169 *retlen = 0;
170
171 while (len) {
172 if ((offset + len) > PAGE_SIZE)
173 cpylen = PAGE_SIZE - offset; // multiple pages
174 else
175 cpylen = len; // this page
176 len = len - cpylen;
177
178 // Get page
179 page = page_readahead(dev->blkdev->bd_inode->i_mapping, index);
180 if (!page)
181 return -ENOMEM;
182 if (IS_ERR(page))
183 return PTR_ERR(page);
184
185 memcpy(buf, page_address(page) + offset, cpylen);
186 page_cache_release(page);
187
188 if (retlen)
189 *retlen += cpylen;
190 buf += cpylen;
191 offset = 0;
192 index++;
193 }
194 return 0;
195}
196
197
198/* write data to the underlying device */
199static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf,
200 loff_t to, size_t len, size_t *retlen)
201{
202 struct page *page;
203 struct address_space *mapping = dev->blkdev->bd_inode->i_mapping;
204 int index = to >> PAGE_SHIFT; // page index
205 int offset = to & ~PAGE_MASK; // page offset
206 int cpylen;
207
208 if (retlen)
209 *retlen = 0;
210 while (len) {
211 if ((offset+len) > PAGE_SIZE)
212 cpylen = PAGE_SIZE - offset; // multiple pages
213 else
214 cpylen = len; // this page
215 len = len - cpylen;
216
217 // Get page
218 page = page_readahead(mapping, index);
219 if (!page)
220 return -ENOMEM;
221 if (IS_ERR(page))
222 return PTR_ERR(page);
223
224 if (memcmp(page_address(page)+offset, buf, cpylen)) {
225 lock_page(page);
226 memcpy(page_address(page) + offset, buf, cpylen);
227 set_page_dirty(page);
228 unlock_page(page);
229 }
230 page_cache_release(page);
231
232 if (retlen)
233 *retlen += cpylen;
234
235 buf += cpylen;
236 offset = 0;
237 index++;
238 }
239 return 0;
240}
241static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
242 size_t *retlen, const u_char *buf)
243{
244 struct block2mtd_dev *dev = mtd->priv;
245 int err;
246
247 if (!len)
248 return 0;
249 if (to >= mtd->size)
250 return -ENOSPC;
251 if (to + len > mtd->size)
252 len = mtd->size - to;
253
254 down(&dev->write_mutex);
255 err = _block2mtd_write(dev, buf, to, len, retlen);
256 up(&dev->write_mutex);
257 if (err > 0)
258 err = 0;
259 return err;
260}
261
262
263/* sync the device - wait until the write queue is empty */
264static void block2mtd_sync(struct mtd_info *mtd)
265{
266 struct block2mtd_dev *dev = mtd->priv;
267 sync_blockdev(dev->blkdev);
268 return;
269}
270
271
272static void block2mtd_free_device(struct block2mtd_dev *dev)
273{
274 if (!dev)
275 return;
276
277 kfree(dev->mtd.name);
278
279 if (dev->blkdev) {
280 invalidate_inode_pages(dev->blkdev->bd_inode->i_mapping);
281 close_bdev_excl(dev->blkdev);
282 }
283
284 kfree(dev);
285}
286
287
288/* FIXME: ensure that mtd->size % erase_size == 0 */
289static struct block2mtd_dev *add_device(char *devname, int erase_size)
290{
291 struct block_device *bdev;
292 struct block2mtd_dev *dev;
293
294 if (!devname)
295 return NULL;
296
297 dev = kmalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
298 if (!dev)
299 return NULL;
300 memset(dev, 0, sizeof(*dev));
301
302 /* Get a handle on the device */
303 bdev = open_bdev_excl(devname, O_RDWR, NULL);
304 if (IS_ERR(bdev)) {
305 ERROR("error: cannot open device %s", devname);
306 goto devinit_err;
307 }
308 dev->blkdev = bdev;
309
310 if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
311 ERROR("attempting to use an MTD device as a block device");
312 goto devinit_err;
313 }
314
315 init_MUTEX(&dev->write_mutex);
316
317 /* Setup the MTD structure */
318 /* make the name contain the block device in */
319 dev->mtd.name = kmalloc(sizeof("block2mtd: ") + strlen(devname),
320 GFP_KERNEL);
321 if (!dev->mtd.name)
322 goto devinit_err;
323
324 sprintf(dev->mtd.name, "block2mtd: %s", devname);
325
326 dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
327 dev->mtd.erasesize = erase_size;
328 dev->mtd.type = MTD_RAM;
329 dev->mtd.flags = MTD_CAP_RAM;
330 dev->mtd.erase = block2mtd_erase;
331 dev->mtd.write = block2mtd_write;
332 dev->mtd.writev = default_mtd_writev;
333 dev->mtd.sync = block2mtd_sync;
334 dev->mtd.read = block2mtd_read;
335 dev->mtd.readv = default_mtd_readv;
336 dev->mtd.priv = dev;
337 dev->mtd.owner = THIS_MODULE;
338
339 if (add_mtd_device(&dev->mtd)) {
340 /* Device didnt get added, so free the entry */
341 goto devinit_err;
342 }
343 list_add(&dev->list, &blkmtd_device_list);
344 INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index,
345 dev->mtd.name + strlen("blkmtd: "),
346 dev->mtd.erasesize >> 10, dev->mtd.erasesize);
347 return dev;
348
349devinit_err:
350 block2mtd_free_device(dev);
351 return NULL;
352}
353
354
355static int ustrtoul(const char *cp, char **endp, unsigned int base)
356{
357 unsigned long result = simple_strtoul(cp, endp, base);
358 switch (**endp) {
359 case 'G' :
360 result *= 1024;
361 case 'M':
362 result *= 1024;
363 case 'k':
364 result *= 1024;
365 /* By dwmw2 editorial decree, "ki", "Mi" or "Gi" are to be used. */
366 if ((*endp)[1] == 'i')
367 (*endp) += 2;
368 }
369 return result;
370}
371
372
373static int parse_num32(u32 *num32, const char *token)
374{
375 char *endp;
376 unsigned long n;
377
378 n = ustrtoul(token, &endp, 0);
379 if (*endp)
380 return -EINVAL;
381
382 *num32 = n;
383 return 0;
384}
385
386
387static int parse_name(char **pname, const char *token, size_t limit)
388{
389 size_t len;
390 char *name;
391
392 len = strlen(token) + 1;
393 if (len > limit)
394 return -ENOSPC;
395
396 name = kmalloc(len, GFP_KERNEL);
397 if (!name)
398 return -ENOMEM;
399
400 strcpy(name, token);
401
402 *pname = name;
403 return 0;
404}
405
406
407static inline void kill_final_newline(char *str)
408{
409 char *newline = strrchr(str, '\n');
410 if (newline && !newline[1])
411 *newline = 0;
412}
413
414
415#define parse_err(fmt, args...) do { \
416 ERROR("block2mtd: " fmt "\n", ## args); \
417 return 0; \
418} while (0)
419
420static int block2mtd_setup(const char *val, struct kernel_param *kp)
421{
422 char buf[80+12], *str=buf; /* 80 for device, 12 for erase size */
423 char *token[2];
424 char *name;
425 u32 erase_size = PAGE_SIZE;
426 int i, ret;
427
428 if (strnlen(val, sizeof(buf)) >= sizeof(buf))
429 parse_err("parameter too long");
430
431 strcpy(str, val);
432 kill_final_newline(str);
433
434 for (i=0; i<2; i++)
435 token[i] = strsep(&str, ",");
436
437 if (str)
438 parse_err("too many arguments");
439
440 if (!token[0])
441 parse_err("no argument");
442
443 ret = parse_name(&name, token[0], 80);
444 if (ret == -ENOMEM)
445 parse_err("out of memory");
446 if (ret == -ENOSPC)
447 parse_err("name too long");
448 if (ret)
449 return 0;
450
451 if (token[1]) {
452 ret = parse_num32(&erase_size, token[1]);
453 if (ret)
454 parse_err("illegal erase size");
455 }
456
457 add_device(name, erase_size);
458
459 return 0;
460}
461
462
463module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
464MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
465
466static int __init block2mtd_init(void)
467{
468 INFO("version " VERSION);
469 return 0;
470}
471
472
473static void __devexit block2mtd_exit(void)
474{
475 struct list_head *pos, *next;
476
477 /* Remove the MTD devices */
478 list_for_each_safe(pos, next, &blkmtd_device_list) {
479 struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list);
480 block2mtd_sync(&dev->mtd);
481 del_mtd_device(&dev->mtd);
482 INFO("mtd%d: [%s] removed", dev->mtd.index,
483 dev->mtd.name + strlen("blkmtd: "));
484 list_del(&dev->list);
485 block2mtd_free_device(dev);
486 }
487}
488
489
490module_init(block2mtd_init);
491module_exit(block2mtd_exit);
492
493MODULE_LICENSE("GPL");
494MODULE_AUTHOR("Simon Evans <spse@secret.org.uk> and others");
495MODULE_DESCRIPTION("Emulate an MTD using a block device");
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c
new file mode 100644
index 000000000000..5fc532895a24
--- /dev/null
+++ b/drivers/mtd/devices/doc2000.c
@@ -0,0 +1,1309 @@
1
2/*
3 * Linux driver for Disk-On-Chip 2000 and Millennium
4 * (c) 1999 Machine Vision Holdings, Inc.
5 * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
6 *
7 * $Id: doc2000.c,v 1.66 2005/01/05 18:05:12 dwmw2 Exp $
8 */
9
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <asm/errno.h>
13#include <asm/io.h>
14#include <asm/uaccess.h>
15#include <linux/miscdevice.h>
16#include <linux/pci.h>
17#include <linux/delay.h>
18#include <linux/slab.h>
19#include <linux/sched.h>
20#include <linux/init.h>
21#include <linux/types.h>
22#include <linux/bitops.h>
23
24#include <linux/mtd/mtd.h>
25#include <linux/mtd/nand.h>
26#include <linux/mtd/doc2000.h>
27
28#define DOC_SUPPORT_2000
29#define DOC_SUPPORT_2000TSOP
30#define DOC_SUPPORT_MILLENNIUM
31
32#ifdef DOC_SUPPORT_2000
33#define DoC_is_2000(doc) (doc->ChipID == DOC_ChipID_Doc2k)
34#else
35#define DoC_is_2000(doc) (0)
36#endif
37
38#if defined(DOC_SUPPORT_2000TSOP) || defined(DOC_SUPPORT_MILLENNIUM)
39#define DoC_is_Millennium(doc) (doc->ChipID == DOC_ChipID_DocMil)
40#else
41#define DoC_is_Millennium(doc) (0)
42#endif
43
44/* #define ECC_DEBUG */
45
46/* I have no idea why some DoC chips can not use memcpy_from|to_io().
47 * This may be due to the different revisions of the ASIC controller built-in or
48 * simplily a QA/Bug issue. Who knows ?? If you have trouble, please uncomment
49 * this:
50 #undef USE_MEMCPY
51*/
52
53static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
54 size_t *retlen, u_char *buf);
55static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
56 size_t *retlen, const u_char *buf);
57static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
58 size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
59static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
60 size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
61static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
62 unsigned long count, loff_t to, size_t *retlen,
63 u_char *eccbuf, struct nand_oobinfo *oobsel);
64static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
65 size_t *retlen, u_char *buf);
66static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
67 size_t *retlen, const u_char *buf);
68static int doc_write_oob_nolock(struct mtd_info *mtd, loff_t ofs, size_t len,
69 size_t *retlen, const u_char *buf);
70static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
71
72static struct mtd_info *doc2klist = NULL;
73
74/* Perform the required delay cycles by reading from the appropriate register */
75static void DoC_Delay(struct DiskOnChip *doc, unsigned short cycles)
76{
77 volatile char dummy;
78 int i;
79
80 for (i = 0; i < cycles; i++) {
81 if (DoC_is_Millennium(doc))
82 dummy = ReadDOC(doc->virtadr, NOP);
83 else
84 dummy = ReadDOC(doc->virtadr, DOCStatus);
85 }
86
87}
88
89/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
90static int _DoC_WaitReady(struct DiskOnChip *doc)
91{
92 void __iomem *docptr = doc->virtadr;
93 unsigned long timeo = jiffies + (HZ * 10);
94
95 DEBUG(MTD_DEBUG_LEVEL3,
96 "_DoC_WaitReady called for out-of-line wait\n");
97
98 /* Out-of-line routine to wait for chip response */
99 while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
100 /* issue 2 read from NOP register after reading from CDSNControl register
101 see Software Requirement 11.4 item 2. */
102 DoC_Delay(doc, 2);
103
104 if (time_after(jiffies, timeo)) {
105 DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
106 return -EIO;
107 }
108 udelay(1);
109 cond_resched();
110 }
111
112 return 0;
113}
114
115static inline int DoC_WaitReady(struct DiskOnChip *doc)
116{
117 void __iomem *docptr = doc->virtadr;
118
119 /* This is inline, to optimise the common case, where it's ready instantly */
120 int ret = 0;
121
122 /* 4 read form NOP register should be issued in prior to the read from CDSNControl
123 see Software Requirement 11.4 item 2. */
124 DoC_Delay(doc, 4);
125
126 if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B))
127 /* Call the out-of-line routine to wait */
128 ret = _DoC_WaitReady(doc);
129
130 /* issue 2 read from NOP register after reading from CDSNControl register
131 see Software Requirement 11.4 item 2. */
132 DoC_Delay(doc, 2);
133
134 return ret;
135}
136
137/* DoC_Command: Send a flash command to the flash chip through the CDSN Slow IO register to
138 bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
139 required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
140
141static inline int DoC_Command(struct DiskOnChip *doc, unsigned char command,
142 unsigned char xtraflags)
143{
144 void __iomem *docptr = doc->virtadr;
145
146 if (DoC_is_2000(doc))
147 xtraflags |= CDSN_CTRL_FLASH_IO;
148
149 /* Assert the CLE (Command Latch Enable) line to the flash chip */
150 WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl);
151 DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */
152
153 if (DoC_is_Millennium(doc))
154 WriteDOC(command, docptr, CDSNSlowIO);
155
156 /* Send the command */
157 WriteDOC_(command, docptr, doc->ioreg);
158 if (DoC_is_Millennium(doc))
159 WriteDOC(command, docptr, WritePipeTerm);
160
161 /* Lower the CLE line */
162 WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl);
163 DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */
164
165 /* Wait for the chip to respond - Software requirement 11.4.1 (extended for any command) */
166 return DoC_WaitReady(doc);
167}
168
169/* DoC_Address: Set the current address for the flash chip through the CDSN Slow IO register to
170 bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
171 required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
172
173static int DoC_Address(struct DiskOnChip *doc, int numbytes, unsigned long ofs,
174 unsigned char xtraflags1, unsigned char xtraflags2)
175{
176 int i;
177 void __iomem *docptr = doc->virtadr;
178
179 if (DoC_is_2000(doc))
180 xtraflags1 |= CDSN_CTRL_FLASH_IO;
181
182 /* Assert the ALE (Address Latch Enable) line to the flash chip */
183 WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl);
184
185 DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */
186
187 /* Send the address */
188 /* Devices with 256-byte page are addressed as:
189 Column (bits 0-7), Page (bits 8-15, 16-23, 24-31)
190 * there is no device on the market with page256
191 and more than 24 bits.
192 Devices with 512-byte page are addressed as:
193 Column (bits 0-7), Page (bits 9-16, 17-24, 25-31)
194 * 25-31 is sent only if the chip support it.
195 * bit 8 changes the read command to be sent
196 (NAND_CMD_READ0 or NAND_CMD_READ1).
197 */
198
199 if (numbytes == ADDR_COLUMN || numbytes == ADDR_COLUMN_PAGE) {
200 if (DoC_is_Millennium(doc))
201 WriteDOC(ofs & 0xff, docptr, CDSNSlowIO);
202 WriteDOC_(ofs & 0xff, docptr, doc->ioreg);
203 }
204
205 if (doc->page256) {
206 ofs = ofs >> 8;
207 } else {
208 ofs = ofs >> 9;
209 }
210
211 if (numbytes == ADDR_PAGE || numbytes == ADDR_COLUMN_PAGE) {
212 for (i = 0; i < doc->pageadrlen; i++, ofs = ofs >> 8) {
213 if (DoC_is_Millennium(doc))
214 WriteDOC(ofs & 0xff, docptr, CDSNSlowIO);
215 WriteDOC_(ofs & 0xff, docptr, doc->ioreg);
216 }
217 }
218
219 if (DoC_is_Millennium(doc))
220 WriteDOC(ofs & 0xff, docptr, WritePipeTerm);
221
222 DoC_Delay(doc, 2); /* Needed for some slow flash chips. mf. */
223
224 /* FIXME: The SlowIO's for millennium could be replaced by
225 a single WritePipeTerm here. mf. */
226
227 /* Lower the ALE line */
228 WriteDOC(xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr,
229 CDSNControl);
230
231 DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */
232
233 /* Wait for the chip to respond - Software requirement 11.4.1 */
234 return DoC_WaitReady(doc);
235}
236
237/* Read a buffer from DoC, taking care of Millennium odditys */
238static void DoC_ReadBuf(struct DiskOnChip *doc, u_char * buf, int len)
239{
240 volatile int dummy;
241 int modulus = 0xffff;
242 void __iomem *docptr = doc->virtadr;
243 int i;
244
245 if (len <= 0)
246 return;
247
248 if (DoC_is_Millennium(doc)) {
249 /* Read the data via the internal pipeline through CDSN IO register,
250 see Pipelined Read Operations 11.3 */
251 dummy = ReadDOC(docptr, ReadPipeInit);
252
253 /* Millennium should use the LastDataRead register - Pipeline Reads */
254 len--;
255
256 /* This is needed for correctly ECC calculation */
257 modulus = 0xff;
258 }
259
260 for (i = 0; i < len; i++)
261 buf[i] = ReadDOC_(docptr, doc->ioreg + (i & modulus));
262
263 if (DoC_is_Millennium(doc)) {
264 buf[i] = ReadDOC(docptr, LastDataRead);
265 }
266}
267
268/* Write a buffer to DoC, taking care of Millennium odditys */
269static void DoC_WriteBuf(struct DiskOnChip *doc, const u_char * buf, int len)
270{
271 void __iomem *docptr = doc->virtadr;
272 int i;
273
274 if (len <= 0)
275 return;
276
277 for (i = 0; i < len; i++)
278 WriteDOC_(buf[i], docptr, doc->ioreg + i);
279
280 if (DoC_is_Millennium(doc)) {
281 WriteDOC(0x00, docptr, WritePipeTerm);
282 }
283}
284
285
286/* DoC_SelectChip: Select a given flash chip within the current floor */
287
288static inline int DoC_SelectChip(struct DiskOnChip *doc, int chip)
289{
290 void __iomem *docptr = doc->virtadr;
291
292 /* Software requirement 11.4.4 before writing DeviceSelect */
293 /* Deassert the CE line to eliminate glitches on the FCE# outputs */
294 WriteDOC(CDSN_CTRL_WP, docptr, CDSNControl);
295 DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */
296
297 /* Select the individual flash chip requested */
298 WriteDOC(chip, docptr, CDSNDeviceSelect);
299 DoC_Delay(doc, 4);
300
301 /* Reassert the CE line */
302 WriteDOC(CDSN_CTRL_CE | CDSN_CTRL_FLASH_IO | CDSN_CTRL_WP, docptr,
303 CDSNControl);
304 DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */
305
306 /* Wait for it to be ready */
307 return DoC_WaitReady(doc);
308}
309
310/* DoC_SelectFloor: Select a given floor (bank of flash chips) */
311
312static inline int DoC_SelectFloor(struct DiskOnChip *doc, int floor)
313{
314 void __iomem *docptr = doc->virtadr;
315
316 /* Select the floor (bank) of chips required */
317 WriteDOC(floor, docptr, FloorSelect);
318
319 /* Wait for the chip to be ready */
320 return DoC_WaitReady(doc);
321}
322
323/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
324
325static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
326{
327 int mfr, id, i, j;
328 volatile char dummy;
329
330 /* Page in the required floor/chip */
331 DoC_SelectFloor(doc, floor);
332 DoC_SelectChip(doc, chip);
333
334 /* Reset the chip */
335 if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) {
336 DEBUG(MTD_DEBUG_LEVEL2,
337 "DoC_Command (reset) for %d,%d returned true\n",
338 floor, chip);
339 return 0;
340 }
341
342
343 /* Read the NAND chip ID: 1. Send ReadID command */
344 if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) {
345 DEBUG(MTD_DEBUG_LEVEL2,
346 "DoC_Command (ReadID) for %d,%d returned true\n",
347 floor, chip);
348 return 0;
349 }
350
351 /* Read the NAND chip ID: 2. Send address byte zero */
352 DoC_Address(doc, ADDR_COLUMN, 0, CDSN_CTRL_WP, 0);
353
354 /* Read the manufacturer and device id codes from the device */
355
356 if (DoC_is_Millennium(doc)) {
357 DoC_Delay(doc, 2);
358 dummy = ReadDOC(doc->virtadr, ReadPipeInit);
359 mfr = ReadDOC(doc->virtadr, LastDataRead);
360
361 DoC_Delay(doc, 2);
362 dummy = ReadDOC(doc->virtadr, ReadPipeInit);
363 id = ReadDOC(doc->virtadr, LastDataRead);
364 } else {
365 /* CDSN Slow IO register see Software Req 11.4 item 5. */
366 dummy = ReadDOC(doc->virtadr, CDSNSlowIO);
367 DoC_Delay(doc, 2);
368 mfr = ReadDOC_(doc->virtadr, doc->ioreg);
369
370 /* CDSN Slow IO register see Software Req 11.4 item 5. */
371 dummy = ReadDOC(doc->virtadr, CDSNSlowIO);
372 DoC_Delay(doc, 2);
373 id = ReadDOC_(doc->virtadr, doc->ioreg);
374 }
375
376 /* No response - return failure */
377 if (mfr == 0xff || mfr == 0)
378 return 0;
379
380 /* Check it's the same as the first chip we identified.
381 * M-Systems say that any given DiskOnChip device should only
382 * contain _one_ type of flash part, although that's not a
383 * hardware restriction. */
384 if (doc->mfr) {
385 if (doc->mfr == mfr && doc->id == id)
386 return 1; /* This is another the same the first */
387 else
388 printk(KERN_WARNING
389 "Flash chip at floor %d, chip %d is different:\n",
390 floor, chip);
391 }
392
393 /* Print and store the manufacturer and ID codes. */
394 for (i = 0; nand_flash_ids[i].name != NULL; i++) {
395 if (id == nand_flash_ids[i].id) {
396 /* Try to identify manufacturer */
397 for (j = 0; nand_manuf_ids[j].id != 0x0; j++) {
398 if (nand_manuf_ids[j].id == mfr)
399 break;
400 }
401 printk(KERN_INFO
402 "Flash chip found: Manufacturer ID: %2.2X, "
403 "Chip ID: %2.2X (%s:%s)\n", mfr, id,
404 nand_manuf_ids[j].name, nand_flash_ids[i].name);
405 if (!doc->mfr) {
406 doc->mfr = mfr;
407 doc->id = id;
408 doc->chipshift =
409 ffs((nand_flash_ids[i].chipsize << 20)) - 1;
410 doc->page256 = (nand_flash_ids[i].pagesize == 256) ? 1 : 0;
411 doc->pageadrlen = doc->chipshift > 25 ? 3 : 2;
412 doc->erasesize =
413 nand_flash_ids[i].erasesize;
414 return 1;
415 }
416 return 0;
417 }
418 }
419
420
421 /* We haven't fully identified the chip. Print as much as we know. */
422 printk(KERN_WARNING "Unknown flash chip found: %2.2X %2.2X\n",
423 id, mfr);
424
425 printk(KERN_WARNING "Please report to dwmw2@infradead.org\n");
426 return 0;
427}
428
429/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */
430
431static void DoC_ScanChips(struct DiskOnChip *this, int maxchips)
432{
433 int floor, chip;
434 int numchips[MAX_FLOORS];
435 int ret = 1;
436
437 this->numchips = 0;
438 this->mfr = 0;
439 this->id = 0;
440
441 /* For each floor, find the number of valid chips it contains */
442 for (floor = 0; floor < MAX_FLOORS; floor++) {
443 ret = 1;
444 numchips[floor] = 0;
445 for (chip = 0; chip < maxchips && ret != 0; chip++) {
446
447 ret = DoC_IdentChip(this, floor, chip);
448 if (ret) {
449 numchips[floor]++;
450 this->numchips++;
451 }
452 }
453 }
454
455 /* If there are none at all that we recognise, bail */
456 if (!this->numchips) {
457 printk(KERN_NOTICE "No flash chips recognised.\n");
458 return;
459 }
460
461 /* Allocate an array to hold the information for each chip */
462 this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL);
463 if (!this->chips) {
464 printk(KERN_NOTICE "No memory for allocating chip info structures\n");
465 return;
466 }
467
468 ret = 0;
469
470 /* Fill out the chip array with {floor, chipno} for each
471 * detected chip in the device. */
472 for (floor = 0; floor < MAX_FLOORS; floor++) {
473 for (chip = 0; chip < numchips[floor]; chip++) {
474 this->chips[ret].floor = floor;
475 this->chips[ret].chip = chip;
476 this->chips[ret].curadr = 0;
477 this->chips[ret].curmode = 0x50;
478 ret++;
479 }
480 }
481
482 /* Calculate and print the total size of the device */
483 this->totlen = this->numchips * (1 << this->chipshift);
484
485 printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld MiB\n",
486 this->numchips, this->totlen >> 20);
487}
488
489static int DoC2k_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
490{
491 int tmp1, tmp2, retval;
492 if (doc1->physadr == doc2->physadr)
493 return 1;
494
495 /* Use the alias resolution register which was set aside for this
496 * purpose. If it's value is the same on both chips, they might
497 * be the same chip, and we write to one and check for a change in
498 * the other. It's unclear if this register is usuable in the
499 * DoC 2000 (it's in the Millennium docs), but it seems to work. */
500 tmp1 = ReadDOC(doc1->virtadr, AliasResolution);
501 tmp2 = ReadDOC(doc2->virtadr, AliasResolution);
502 if (tmp1 != tmp2)
503 return 0;
504
505 WriteDOC((tmp1 + 1) % 0xff, doc1->virtadr, AliasResolution);
506 tmp2 = ReadDOC(doc2->virtadr, AliasResolution);
507 if (tmp2 == (tmp1 + 1) % 0xff)
508 retval = 1;
509 else
510 retval = 0;
511
512 /* Restore register contents. May not be necessary, but do it just to
513 * be safe. */
514 WriteDOC(tmp1, doc1->virtadr, AliasResolution);
515
516 return retval;
517}
518
519static const char im_name[] = "DoC2k_init";
520
521/* This routine is made available to other mtd code via
522 * inter_module_register. It must only be accessed through
523 * inter_module_get which will bump the use count of this module. The
524 * addresses passed back in mtd are valid as long as the use count of
525 * this module is non-zero, i.e. between inter_module_get and
526 * inter_module_put. Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
527 */
528static void DoC2k_init(struct mtd_info *mtd)
529{
530 struct DiskOnChip *this = mtd->priv;
531 struct DiskOnChip *old = NULL;
532 int maxchips;
533
534 /* We must avoid being called twice for the same device. */
535
536 if (doc2klist)
537 old = doc2klist->priv;
538
539 while (old) {
540 if (DoC2k_is_alias(old, this)) {
541 printk(KERN_NOTICE
542 "Ignoring DiskOnChip 2000 at 0x%lX - already configured\n",
543 this->physadr);
544 iounmap(this->virtadr);
545 kfree(mtd);
546 return;
547 }
548 if (old->nextdoc)
549 old = old->nextdoc->priv;
550 else
551 old = NULL;
552 }
553
554
555 switch (this->ChipID) {
556 case DOC_ChipID_Doc2kTSOP:
557 mtd->name = "DiskOnChip 2000 TSOP";
558 this->ioreg = DoC_Mil_CDSN_IO;
559 /* Pretend it's a Millennium */
560 this->ChipID = DOC_ChipID_DocMil;
561 maxchips = MAX_CHIPS;
562 break;
563 case DOC_ChipID_Doc2k:
564 mtd->name = "DiskOnChip 2000";
565 this->ioreg = DoC_2k_CDSN_IO;
566 maxchips = MAX_CHIPS;
567 break;
568 case DOC_ChipID_DocMil:
569 mtd->name = "DiskOnChip Millennium";
570 this->ioreg = DoC_Mil_CDSN_IO;
571 maxchips = MAX_CHIPS_MIL;
572 break;
573 default:
574 printk("Unknown ChipID 0x%02x\n", this->ChipID);
575 kfree(mtd);
576 iounmap(this->virtadr);
577 return;
578 }
579
580 printk(KERN_NOTICE "%s found at address 0x%lX\n", mtd->name,
581 this->physadr);
582
583 mtd->type = MTD_NANDFLASH;
584 mtd->flags = MTD_CAP_NANDFLASH;
585 mtd->ecctype = MTD_ECC_RS_DiskOnChip;
586 mtd->size = 0;
587 mtd->erasesize = 0;
588 mtd->oobblock = 512;
589 mtd->oobsize = 16;
590 mtd->owner = THIS_MODULE;
591 mtd->erase = doc_erase;
592 mtd->point = NULL;
593 mtd->unpoint = NULL;
594 mtd->read = doc_read;
595 mtd->write = doc_write;
596 mtd->read_ecc = doc_read_ecc;
597 mtd->write_ecc = doc_write_ecc;
598 mtd->writev_ecc = doc_writev_ecc;
599 mtd->read_oob = doc_read_oob;
600 mtd->write_oob = doc_write_oob;
601 mtd->sync = NULL;
602
603 this->totlen = 0;
604 this->numchips = 0;
605
606 this->curfloor = -1;
607 this->curchip = -1;
608 init_MUTEX(&this->lock);
609
610 /* Ident all the chips present. */
611 DoC_ScanChips(this, maxchips);
612
613 if (!this->totlen) {
614 kfree(mtd);
615 iounmap(this->virtadr);
616 } else {
617 this->nextdoc = doc2klist;
618 doc2klist = mtd;
619 mtd->size = this->totlen;
620 mtd->erasesize = this->erasesize;
621 add_mtd_device(mtd);
622 return;
623 }
624}
625
626static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
627 size_t * retlen, u_char * buf)
628{
629 /* Just a special case of doc_read_ecc */
630 return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
631}
632
633static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
634 size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel)
635{
636 struct DiskOnChip *this = mtd->priv;
637 void __iomem *docptr = this->virtadr;
638 struct Nand *mychip;
639 unsigned char syndrome[6];
640 volatile char dummy;
641 int i, len256 = 0, ret=0;
642 size_t left = len;
643
644 /* Don't allow read past end of device */
645 if (from >= this->totlen)
646 return -EINVAL;
647
648 down(&this->lock);
649
650 *retlen = 0;
651 while (left) {
652 len = left;
653
654 /* Don't allow a single read to cross a 512-byte block boundary */
655 if (from + len > ((from | 0x1ff) + 1))
656 len = ((from | 0x1ff) + 1) - from;
657
658 /* The ECC will not be calculated correctly if less than 512 is read */
659 if (len != 0x200 && eccbuf)
660 printk(KERN_WARNING
661 "ECC needs a full sector read (adr: %lx size %lx)\n",
662 (long) from, (long) len);
663
664 /* printk("DoC_Read (adr: %lx size %lx)\n", (long) from, (long) len); */
665
666
667 /* Find the chip which is to be used and select it */
668 mychip = &this->chips[from >> (this->chipshift)];
669
670 if (this->curfloor != mychip->floor) {
671 DoC_SelectFloor(this, mychip->floor);
672 DoC_SelectChip(this, mychip->chip);
673 } else if (this->curchip != mychip->chip) {
674 DoC_SelectChip(this, mychip->chip);
675 }
676
677 this->curfloor = mychip->floor;
678 this->curchip = mychip->chip;
679
680 DoC_Command(this,
681 (!this->page256
682 && (from & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
683 CDSN_CTRL_WP);
684 DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP,
685 CDSN_CTRL_ECC_IO);
686
687 if (eccbuf) {
688 /* Prime the ECC engine */
689 WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
690 WriteDOC(DOC_ECC_EN, docptr, ECCConf);
691 } else {
692 /* disable the ECC engine */
693 WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
694 WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
695 }
696
697 /* treat crossing 256-byte sector for 2M x 8bits devices */
698 if (this->page256 && from + len > (from | 0xff) + 1) {
699 len256 = (from | 0xff) + 1 - from;
700 DoC_ReadBuf(this, buf, len256);
701
702 DoC_Command(this, NAND_CMD_READ0, CDSN_CTRL_WP);
703 DoC_Address(this, ADDR_COLUMN_PAGE, from + len256,
704 CDSN_CTRL_WP, CDSN_CTRL_ECC_IO);
705 }
706
707 DoC_ReadBuf(this, &buf[len256], len - len256);
708
709 /* Let the caller know we completed it */
710 *retlen += len;
711
712 if (eccbuf) {
713 /* Read the ECC data through the DiskOnChip ECC logic */
714 /* Note: this will work even with 2M x 8bit devices as */
715 /* they have 8 bytes of OOB per 256 page. mf. */
716 DoC_ReadBuf(this, eccbuf, 6);
717
718 /* Flush the pipeline */
719 if (DoC_is_Millennium(this)) {
720 dummy = ReadDOC(docptr, ECCConf);
721 dummy = ReadDOC(docptr, ECCConf);
722 i = ReadDOC(docptr, ECCConf);
723 } else {
724 dummy = ReadDOC(docptr, 2k_ECCStatus);
725 dummy = ReadDOC(docptr, 2k_ECCStatus);
726 i = ReadDOC(docptr, 2k_ECCStatus);
727 }
728
729 /* Check the ECC Status */
730 if (i & 0x80) {
731 int nb_errors;
732 /* There was an ECC error */
733#ifdef ECC_DEBUG
734 printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from);
735#endif
736 /* Read the ECC syndrom through the DiskOnChip ECC logic.
737 These syndrome will be all ZERO when there is no error */
738 for (i = 0; i < 6; i++) {
739 syndrome[i] =
740 ReadDOC(docptr, ECCSyndrome0 + i);
741 }
742 nb_errors = doc_decode_ecc(buf, syndrome);
743
744#ifdef ECC_DEBUG
745 printk(KERN_ERR "Errors corrected: %x\n", nb_errors);
746#endif
747 if (nb_errors < 0) {
748 /* We return error, but have actually done the read. Not that
749 this can be told to user-space, via sys_read(), but at least
750 MTD-aware stuff can know about it by checking *retlen */
751 ret = -EIO;
752 }
753 }
754
755#ifdef PSYCHO_DEBUG
756 printk(KERN_DEBUG "ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
757 (long)from, eccbuf[0], eccbuf[1], eccbuf[2],
758 eccbuf[3], eccbuf[4], eccbuf[5]);
759#endif
760
761 /* disable the ECC engine */
762 WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
763 }
764
765 /* according to 11.4.1, we need to wait for the busy line
766 * drop if we read to the end of the page. */
767 if(0 == ((from + len) & 0x1ff))
768 {
769 DoC_WaitReady(this);
770 }
771
772 from += len;
773 left -= len;
774 buf += len;
775 }
776
777 up(&this->lock);
778
779 return ret;
780}
781
782static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
783 size_t * retlen, const u_char * buf)
784{
785 char eccbuf[6];
786 return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL);
787}
788
789static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
790 size_t * retlen, const u_char * buf,
791 u_char * eccbuf, struct nand_oobinfo *oobsel)
792{
793 struct DiskOnChip *this = mtd->priv;
794 int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */
795 void __iomem *docptr = this->virtadr;
796 volatile char dummy;
797 int len256 = 0;
798 struct Nand *mychip;
799 size_t left = len;
800 int status;
801
802 /* Don't allow write past end of device */
803 if (to >= this->totlen)
804 return -EINVAL;
805
806 down(&this->lock);
807
808 *retlen = 0;
809 while (left) {
810 len = left;
811
812 /* Don't allow a single write to cross a 512-byte block boundary */
813 if (to + len > ((to | 0x1ff) + 1))
814 len = ((to | 0x1ff) + 1) - to;
815
816 /* The ECC will not be calculated correctly if less than 512 is written */
817/* DBB-
818 if (len != 0x200 && eccbuf)
819 printk(KERN_WARNING
820 "ECC needs a full sector write (adr: %lx size %lx)\n",
821 (long) to, (long) len);
822 -DBB */
823
824 /* printk("DoC_Write (adr: %lx size %lx)\n", (long) to, (long) len); */
825
826 /* Find the chip which is to be used and select it */
827 mychip = &this->chips[to >> (this->chipshift)];
828
829 if (this->curfloor != mychip->floor) {
830 DoC_SelectFloor(this, mychip->floor);
831 DoC_SelectChip(this, mychip->chip);
832 } else if (this->curchip != mychip->chip) {
833 DoC_SelectChip(this, mychip->chip);
834 }
835
836 this->curfloor = mychip->floor;
837 this->curchip = mychip->chip;
838
839 /* Set device to main plane of flash */
840 DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP);
841 DoC_Command(this,
842 (!this->page256
843 && (to & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0,
844 CDSN_CTRL_WP);
845
846 DoC_Command(this, NAND_CMD_SEQIN, 0);
847 DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO);
848
849 if (eccbuf) {
850 /* Prime the ECC engine */
851 WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
852 WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
853 } else {
854 /* disable the ECC engine */
855 WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
856 WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
857 }
858
859 /* treat crossing 256-byte sector for 2M x 8bits devices */
860 if (this->page256 && to + len > (to | 0xff) + 1) {
861 len256 = (to | 0xff) + 1 - to;
862 DoC_WriteBuf(this, buf, len256);
863
864 DoC_Command(this, NAND_CMD_PAGEPROG, 0);
865
866 DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
867 /* There's an implicit DoC_WaitReady() in DoC_Command */
868
869 dummy = ReadDOC(docptr, CDSNSlowIO);
870 DoC_Delay(this, 2);
871
872 if (ReadDOC_(docptr, this->ioreg) & 1) {
873 printk(KERN_ERR "Error programming flash\n");
874 /* Error in programming */
875 *retlen = 0;
876 up(&this->lock);
877 return -EIO;
878 }
879
880 DoC_Command(this, NAND_CMD_SEQIN, 0);
881 DoC_Address(this, ADDR_COLUMN_PAGE, to + len256, 0,
882 CDSN_CTRL_ECC_IO);
883 }
884
885 DoC_WriteBuf(this, &buf[len256], len - len256);
886
887 if (eccbuf) {
888 WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr,
889 CDSNControl);
890
891 if (DoC_is_Millennium(this)) {
892 WriteDOC(0, docptr, NOP);
893 WriteDOC(0, docptr, NOP);
894 WriteDOC(0, docptr, NOP);
895 } else {
896 WriteDOC_(0, docptr, this->ioreg);
897 WriteDOC_(0, docptr, this->ioreg);
898 WriteDOC_(0, docptr, this->ioreg);
899 }
900
901 WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_FLASH_IO | CDSN_CTRL_CE, docptr,
902 CDSNControl);
903
904 /* Read the ECC data through the DiskOnChip ECC logic */
905 for (di = 0; di < 6; di++) {
906 eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di);
907 }
908
909 /* Reset the ECC engine */
910 WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
911
912#ifdef PSYCHO_DEBUG
913 printk
914 ("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
915 (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
916 eccbuf[4], eccbuf[5]);
917#endif
918 }
919
920 DoC_Command(this, NAND_CMD_PAGEPROG, 0);
921
922 DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
923 /* There's an implicit DoC_WaitReady() in DoC_Command */
924
925 if (DoC_is_Millennium(this)) {
926 ReadDOC(docptr, ReadPipeInit);
927 status = ReadDOC(docptr, LastDataRead);
928 } else {
929 dummy = ReadDOC(docptr, CDSNSlowIO);
930 DoC_Delay(this, 2);
931 status = ReadDOC_(docptr, this->ioreg);
932 }
933
934 if (status & 1) {
935 printk(KERN_ERR "Error programming flash\n");
936 /* Error in programming */
937 *retlen = 0;
938 up(&this->lock);
939 return -EIO;
940 }
941
942 /* Let the caller know we completed it */
943 *retlen += len;
944
945 if (eccbuf) {
946 unsigned char x[8];
947 size_t dummy;
948 int ret;
949
950 /* Write the ECC data to flash */
951 for (di=0; di<6; di++)
952 x[di] = eccbuf[di];
953
954 x[6]=0x55;
955 x[7]=0x55;
956
957 ret = doc_write_oob_nolock(mtd, to, 8, &dummy, x);
958 if (ret) {
959 up(&this->lock);
960 return ret;
961 }
962 }
963
964 to += len;
965 left -= len;
966 buf += len;
967 }
968
969 up(&this->lock);
970 return 0;
971}
972
973static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
974 unsigned long count, loff_t to, size_t *retlen,
975 u_char *eccbuf, struct nand_oobinfo *oobsel)
976{
977 static char static_buf[512];
978 static DECLARE_MUTEX(writev_buf_sem);
979
980 size_t totretlen = 0;
981 size_t thisvecofs = 0;
982 int ret= 0;
983
984 down(&writev_buf_sem);
985
986 while(count) {
987 size_t thislen, thisretlen;
988 unsigned char *buf;
989
990 buf = vecs->iov_base + thisvecofs;
991 thislen = vecs->iov_len - thisvecofs;
992
993
994 if (thislen >= 512) {
995 thislen = thislen & ~(512-1);
996 thisvecofs += thislen;
997 } else {
998 /* Not enough to fill a page. Copy into buf */
999 memcpy(static_buf, buf, thislen);
1000 buf = &static_buf[thislen];
1001
1002 while(count && thislen < 512) {
1003 vecs++;
1004 count--;
1005 thisvecofs = min((512-thislen), vecs->iov_len);
1006 memcpy(buf, vecs->iov_base, thisvecofs);
1007 thislen += thisvecofs;
1008 buf += thisvecofs;
1009 }
1010 buf = static_buf;
1011 }
1012 if (count && thisvecofs == vecs->iov_len) {
1013 thisvecofs = 0;
1014 vecs++;
1015 count--;
1016 }
1017 ret = doc_write_ecc(mtd, to, thislen, &thisretlen, buf, eccbuf, oobsel);
1018
1019 totretlen += thisretlen;
1020
1021 if (ret || thisretlen != thislen)
1022 break;
1023
1024 to += thislen;
1025 }
1026
1027 up(&writev_buf_sem);
1028 *retlen = totretlen;
1029 return ret;
1030}
1031
1032
1033static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
1034 size_t * retlen, u_char * buf)
1035{
1036 struct DiskOnChip *this = mtd->priv;
1037 int len256 = 0, ret;
1038 struct Nand *mychip;
1039
1040 down(&this->lock);
1041
1042 mychip = &this->chips[ofs >> this->chipshift];
1043
1044 if (this->curfloor != mychip->floor) {
1045 DoC_SelectFloor(this, mychip->floor);
1046 DoC_SelectChip(this, mychip->chip);
1047 } else if (this->curchip != mychip->chip) {
1048 DoC_SelectChip(this, mychip->chip);
1049 }
1050 this->curfloor = mychip->floor;
1051 this->curchip = mychip->chip;
1052
1053 /* update address for 2M x 8bit devices. OOB starts on the second */
1054 /* page to maintain compatibility with doc_read_ecc. */
1055 if (this->page256) {
1056 if (!(ofs & 0x8))
1057 ofs += 0x100;
1058 else
1059 ofs -= 0x8;
1060 }
1061
1062 DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP);
1063 DoC_Address(this, ADDR_COLUMN_PAGE, ofs, CDSN_CTRL_WP, 0);
1064
1065 /* treat crossing 8-byte OOB data for 2M x 8bit devices */
1066 /* Note: datasheet says it should automaticaly wrap to the */
1067 /* next OOB block, but it didn't work here. mf. */
1068 if (this->page256 && ofs + len > (ofs | 0x7) + 1) {
1069 len256 = (ofs | 0x7) + 1 - ofs;
1070 DoC_ReadBuf(this, buf, len256);
1071
1072 DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP);
1073 DoC_Address(this, ADDR_COLUMN_PAGE, ofs & (~0x1ff),
1074 CDSN_CTRL_WP, 0);
1075 }
1076
1077 DoC_ReadBuf(this, &buf[len256], len - len256);
1078
1079 *retlen = len;
1080 /* Reading the full OOB data drops us off of the end of the page,
1081 * causing the flash device to go into busy mode, so we need
1082 * to wait until ready 11.4.1 and Toshiba TC58256FT docs */
1083
1084 ret = DoC_WaitReady(this);
1085
1086 up(&this->lock);
1087 return ret;
1088
1089}
1090
1091static int doc_write_oob_nolock(struct mtd_info *mtd, loff_t ofs, size_t len,
1092 size_t * retlen, const u_char * buf)
1093{
1094 struct DiskOnChip *this = mtd->priv;
1095 int len256 = 0;
1096 void __iomem *docptr = this->virtadr;
1097 struct Nand *mychip = &this->chips[ofs >> this->chipshift];
1098 volatile int dummy;
1099 int status;
1100
1101 // printk("doc_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",(long)ofs, len,
1102 // buf[0], buf[1], buf[2], buf[3], buf[8], buf[9], buf[14],buf[15]);
1103
1104 /* Find the chip which is to be used and select it */
1105 if (this->curfloor != mychip->floor) {
1106 DoC_SelectFloor(this, mychip->floor);
1107 DoC_SelectChip(this, mychip->chip);
1108 } else if (this->curchip != mychip->chip) {
1109 DoC_SelectChip(this, mychip->chip);
1110 }
1111 this->curfloor = mychip->floor;
1112 this->curchip = mychip->chip;
1113
1114 /* disable the ECC engine */
1115 WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
1116 WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
1117
1118 /* Reset the chip, see Software Requirement 11.4 item 1. */
1119 DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP);
1120
1121 /* issue the Read2 command to set the pointer to the Spare Data Area. */
1122 DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP);
1123
1124 /* update address for 2M x 8bit devices. OOB starts on the second */
1125 /* page to maintain compatibility with doc_read_ecc. */
1126 if (this->page256) {
1127 if (!(ofs & 0x8))
1128 ofs += 0x100;
1129 else
1130 ofs -= 0x8;
1131 }
1132
1133 /* issue the Serial Data In command to initial the Page Program process */
1134 DoC_Command(this, NAND_CMD_SEQIN, 0);
1135 DoC_Address(this, ADDR_COLUMN_PAGE, ofs, 0, 0);
1136
1137 /* treat crossing 8-byte OOB data for 2M x 8bit devices */
1138 /* Note: datasheet says it should automaticaly wrap to the */
1139 /* next OOB block, but it didn't work here. mf. */
1140 if (this->page256 && ofs + len > (ofs | 0x7) + 1) {
1141 len256 = (ofs | 0x7) + 1 - ofs;
1142 DoC_WriteBuf(this, buf, len256);
1143
1144 DoC_Command(this, NAND_CMD_PAGEPROG, 0);
1145 DoC_Command(this, NAND_CMD_STATUS, 0);
1146 /* DoC_WaitReady() is implicit in DoC_Command */
1147
1148 if (DoC_is_Millennium(this)) {
1149 ReadDOC(docptr, ReadPipeInit);
1150 status = ReadDOC(docptr, LastDataRead);
1151 } else {
1152 dummy = ReadDOC(docptr, CDSNSlowIO);
1153 DoC_Delay(this, 2);
1154 status = ReadDOC_(docptr, this->ioreg);
1155 }
1156
1157 if (status & 1) {
1158 printk(KERN_ERR "Error programming oob data\n");
1159 /* There was an error */
1160 *retlen = 0;
1161 return -EIO;
1162 }
1163 DoC_Command(this, NAND_CMD_SEQIN, 0);
1164 DoC_Address(this, ADDR_COLUMN_PAGE, ofs & (~0x1ff), 0, 0);
1165 }
1166
1167 DoC_WriteBuf(this, &buf[len256], len - len256);
1168
1169 DoC_Command(this, NAND_CMD_PAGEPROG, 0);
1170 DoC_Command(this, NAND_CMD_STATUS, 0);
1171 /* DoC_WaitReady() is implicit in DoC_Command */
1172
1173 if (DoC_is_Millennium(this)) {
1174 ReadDOC(docptr, ReadPipeInit);
1175 status = ReadDOC(docptr, LastDataRead);
1176 } else {
1177 dummy = ReadDOC(docptr, CDSNSlowIO);
1178 DoC_Delay(this, 2);
1179 status = ReadDOC_(docptr, this->ioreg);
1180 }
1181
1182 if (status & 1) {
1183 printk(KERN_ERR "Error programming oob data\n");
1184 /* There was an error */
1185 *retlen = 0;
1186 return -EIO;
1187 }
1188
1189 *retlen = len;
1190 return 0;
1191
1192}
1193
1194static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
1195 size_t * retlen, const u_char * buf)
1196{
1197 struct DiskOnChip *this = mtd->priv;
1198 int ret;
1199
1200 down(&this->lock);
1201 ret = doc_write_oob_nolock(mtd, ofs, len, retlen, buf);
1202
1203 up(&this->lock);
1204 return ret;
1205}
1206
1207static int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
1208{
1209 struct DiskOnChip *this = mtd->priv;
1210 __u32 ofs = instr->addr;
1211 __u32 len = instr->len;
1212 volatile int dummy;
1213 void __iomem *docptr = this->virtadr;
1214 struct Nand *mychip;
1215 int status;
1216
1217 down(&this->lock);
1218
1219 if (ofs & (mtd->erasesize-1) || len & (mtd->erasesize-1)) {
1220 up(&this->lock);
1221 return -EINVAL;
1222 }
1223
1224 instr->state = MTD_ERASING;
1225
1226 /* FIXME: Do this in the background. Use timers or schedule_task() */
1227 while(len) {
1228 mychip = &this->chips[ofs >> this->chipshift];
1229
1230 if (this->curfloor != mychip->floor) {
1231 DoC_SelectFloor(this, mychip->floor);
1232 DoC_SelectChip(this, mychip->chip);
1233 } else if (this->curchip != mychip->chip) {
1234 DoC_SelectChip(this, mychip->chip);
1235 }
1236 this->curfloor = mychip->floor;
1237 this->curchip = mychip->chip;
1238
1239 DoC_Command(this, NAND_CMD_ERASE1, 0);
1240 DoC_Address(this, ADDR_PAGE, ofs, 0, 0);
1241 DoC_Command(this, NAND_CMD_ERASE2, 0);
1242
1243 DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
1244
1245 if (DoC_is_Millennium(this)) {
1246 ReadDOC(docptr, ReadPipeInit);
1247 status = ReadDOC(docptr, LastDataRead);
1248 } else {
1249 dummy = ReadDOC(docptr, CDSNSlowIO);
1250 DoC_Delay(this, 2);
1251 status = ReadDOC_(docptr, this->ioreg);
1252 }
1253
1254 if (status & 1) {
1255 printk(KERN_ERR "Error erasing at 0x%x\n", ofs);
1256 /* There was an error */
1257 instr->state = MTD_ERASE_FAILED;
1258 goto callback;
1259 }
1260 ofs += mtd->erasesize;
1261 len -= mtd->erasesize;
1262 }
1263 instr->state = MTD_ERASE_DONE;
1264
1265 callback:
1266 mtd_erase_callback(instr);
1267
1268 up(&this->lock);
1269 return 0;
1270}
1271
1272
1273/****************************************************************************
1274 *
1275 * Module stuff
1276 *
1277 ****************************************************************************/
1278
1279static int __init init_doc2000(void)
1280{
1281 inter_module_register(im_name, THIS_MODULE, &DoC2k_init);
1282 return 0;
1283}
1284
1285static void __exit cleanup_doc2000(void)
1286{
1287 struct mtd_info *mtd;
1288 struct DiskOnChip *this;
1289
1290 while ((mtd = doc2klist)) {
1291 this = mtd->priv;
1292 doc2klist = this->nextdoc;
1293
1294 del_mtd_device(mtd);
1295
1296 iounmap(this->virtadr);
1297 kfree(this->chips);
1298 kfree(mtd);
1299 }
1300 inter_module_unregister(im_name);
1301}
1302
1303module_exit(cleanup_doc2000);
1304module_init(init_doc2000);
1305
1306MODULE_LICENSE("GPL");
1307MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");
1308MODULE_DESCRIPTION("MTD driver for DiskOnChip 2000 and Millennium");
1309
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c
new file mode 100644
index 000000000000..1e704915ef08
--- /dev/null
+++ b/drivers/mtd/devices/doc2001.c
@@ -0,0 +1,888 @@
1
2/*
3 * Linux driver for Disk-On-Chip Millennium
4 * (c) 1999 Machine Vision Holdings, Inc.
5 * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
6 *
7 * $Id: doc2001.c,v 1.48 2005/01/05 18:05:12 dwmw2 Exp $
8 */
9
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <asm/errno.h>
13#include <asm/io.h>
14#include <asm/uaccess.h>
15#include <linux/miscdevice.h>
16#include <linux/pci.h>
17#include <linux/delay.h>
18#include <linux/slab.h>
19#include <linux/sched.h>
20#include <linux/init.h>
21#include <linux/types.h>
22#include <linux/bitops.h>
23
24#include <linux/mtd/mtd.h>
25#include <linux/mtd/nand.h>
26#include <linux/mtd/doc2000.h>
27
28/* #define ECC_DEBUG */
29
30/* I have no idea why some DoC chips can not use memcop_form|to_io().
31 * This may be due to the different revisions of the ASIC controller built-in or
32 * simplily a QA/Bug issue. Who knows ?? If you have trouble, please uncomment
33 * this:*/
34#undef USE_MEMCPY
35
36static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
37 size_t *retlen, u_char *buf);
38static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
39 size_t *retlen, const u_char *buf);
40static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
41 size_t *retlen, u_char *buf, u_char *eccbuf,
42 struct nand_oobinfo *oobsel);
43static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
44 size_t *retlen, const u_char *buf, u_char *eccbuf,
45 struct nand_oobinfo *oobsel);
46static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
47 size_t *retlen, u_char *buf);
48static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
49 size_t *retlen, const u_char *buf);
50static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
51
52static struct mtd_info *docmillist = NULL;
53
54/* Perform the required delay cycles by reading from the NOP register */
55static void DoC_Delay(void __iomem * docptr, unsigned short cycles)
56{
57 volatile char dummy;
58 int i;
59
60 for (i = 0; i < cycles; i++)
61 dummy = ReadDOC(docptr, NOP);
62}
63
64/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
65static int _DoC_WaitReady(void __iomem * docptr)
66{
67 unsigned short c = 0xffff;
68
69 DEBUG(MTD_DEBUG_LEVEL3,
70 "_DoC_WaitReady called for out-of-line wait\n");
71
72 /* Out-of-line routine to wait for chip response */
73 while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c)
74 ;
75
76 if (c == 0)
77 DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
78
79 return (c == 0);
80}
81
82static inline int DoC_WaitReady(void __iomem * docptr)
83{
84 /* This is inline, to optimise the common case, where it's ready instantly */
85 int ret = 0;
86
87 /* 4 read form NOP register should be issued in prior to the read from CDSNControl
88 see Software Requirement 11.4 item 2. */
89 DoC_Delay(docptr, 4);
90
91 if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B))
92 /* Call the out-of-line routine to wait */
93 ret = _DoC_WaitReady(docptr);
94
95 /* issue 2 read from NOP register after reading from CDSNControl register
96 see Software Requirement 11.4 item 2. */
97 DoC_Delay(docptr, 2);
98
99 return ret;
100}
101
102/* DoC_Command: Send a flash command to the flash chip through the CDSN IO register
103 with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
104 required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
105
106static inline void DoC_Command(void __iomem * docptr, unsigned char command,
107 unsigned char xtraflags)
108{
109 /* Assert the CLE (Command Latch Enable) line to the flash chip */
110 WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl);
111 DoC_Delay(docptr, 4);
112
113 /* Send the command */
114 WriteDOC(command, docptr, Mil_CDSN_IO);
115 WriteDOC(0x00, docptr, WritePipeTerm);
116
117 /* Lower the CLE line */
118 WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl);
119 DoC_Delay(docptr, 4);
120}
121
122/* DoC_Address: Set the current address for the flash chip through the CDSN IO register
123 with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
124 required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
125
126static inline void DoC_Address(void __iomem * docptr, int numbytes, unsigned long ofs,
127 unsigned char xtraflags1, unsigned char xtraflags2)
128{
129 /* Assert the ALE (Address Latch Enable) line to the flash chip */
130 WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl);
131 DoC_Delay(docptr, 4);
132
133 /* Send the address */
134 switch (numbytes)
135 {
136 case 1:
137 /* Send single byte, bits 0-7. */
138 WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO);
139 WriteDOC(0x00, docptr, WritePipeTerm);
140 break;
141 case 2:
142 /* Send bits 9-16 followed by 17-23 */
143 WriteDOC((ofs >> 9) & 0xff, docptr, Mil_CDSN_IO);
144 WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO);
145 WriteDOC(0x00, docptr, WritePipeTerm);
146 break;
147 case 3:
148 /* Send 0-7, 9-16, then 17-23 */
149 WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO);
150 WriteDOC((ofs >> 9) & 0xff, docptr, Mil_CDSN_IO);
151 WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO);
152 WriteDOC(0x00, docptr, WritePipeTerm);
153 break;
154 default:
155 return;
156 }
157
158 /* Lower the ALE line */
159 WriteDOC(xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, CDSNControl);
160 DoC_Delay(docptr, 4);
161}
162
163/* DoC_SelectChip: Select a given flash chip within the current floor */
164static int DoC_SelectChip(void __iomem * docptr, int chip)
165{
166 /* Select the individual flash chip requested */
167 WriteDOC(chip, docptr, CDSNDeviceSelect);
168 DoC_Delay(docptr, 4);
169
170 /* Wait for it to be ready */
171 return DoC_WaitReady(docptr);
172}
173
174/* DoC_SelectFloor: Select a given floor (bank of flash chips) */
175static int DoC_SelectFloor(void __iomem * docptr, int floor)
176{
177 /* Select the floor (bank) of chips required */
178 WriteDOC(floor, docptr, FloorSelect);
179
180 /* Wait for the chip to be ready */
181 return DoC_WaitReady(docptr);
182}
183
184/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
185static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
186{
187 int mfr, id, i, j;
188 volatile char dummy;
189
190 /* Page in the required floor/chip
191 FIXME: is this supported by Millennium ?? */
192 DoC_SelectFloor(doc->virtadr, floor);
193 DoC_SelectChip(doc->virtadr, chip);
194
195 /* Reset the chip, see Software Requirement 11.4 item 1. */
196 DoC_Command(doc->virtadr, NAND_CMD_RESET, CDSN_CTRL_WP);
197 DoC_WaitReady(doc->virtadr);
198
199 /* Read the NAND chip ID: 1. Send ReadID command */
200 DoC_Command(doc->virtadr, NAND_CMD_READID, CDSN_CTRL_WP);
201
202 /* Read the NAND chip ID: 2. Send address byte zero */
203 DoC_Address(doc->virtadr, 1, 0x00, CDSN_CTRL_WP, 0x00);
204
205 /* Read the manufacturer and device id codes of the flash device through
206 CDSN IO register see Software Requirement 11.4 item 5.*/
207 dummy = ReadDOC(doc->virtadr, ReadPipeInit);
208 DoC_Delay(doc->virtadr, 2);
209 mfr = ReadDOC(doc->virtadr, Mil_CDSN_IO);
210
211 DoC_Delay(doc->virtadr, 2);
212 id = ReadDOC(doc->virtadr, Mil_CDSN_IO);
213 dummy = ReadDOC(doc->virtadr, LastDataRead);
214
215 /* No response - return failure */
216 if (mfr == 0xff || mfr == 0)
217 return 0;
218
219 /* FIXME: to deal with multi-flash on multi-Millennium case more carefully */
220 for (i = 0; nand_flash_ids[i].name != NULL; i++) {
221 if ( id == nand_flash_ids[i].id) {
222 /* Try to identify manufacturer */
223 for (j = 0; nand_manuf_ids[j].id != 0x0; j++) {
224 if (nand_manuf_ids[j].id == mfr)
225 break;
226 }
227 printk(KERN_INFO "Flash chip found: Manufacturer ID: %2.2X, "
228 "Chip ID: %2.2X (%s:%s)\n",
229 mfr, id, nand_manuf_ids[j].name, nand_flash_ids[i].name);
230 doc->mfr = mfr;
231 doc->id = id;
232 doc->chipshift = ffs((nand_flash_ids[i].chipsize << 20)) - 1;
233 break;
234 }
235 }
236
237 if (nand_flash_ids[i].name == NULL)
238 return 0;
239 else
240 return 1;
241}
242
243/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */
244static void DoC_ScanChips(struct DiskOnChip *this)
245{
246 int floor, chip;
247 int numchips[MAX_FLOORS_MIL];
248 int ret;
249
250 this->numchips = 0;
251 this->mfr = 0;
252 this->id = 0;
253
254 /* For each floor, find the number of valid chips it contains */
255 for (floor = 0,ret = 1; floor < MAX_FLOORS_MIL; floor++) {
256 numchips[floor] = 0;
257 for (chip = 0; chip < MAX_CHIPS_MIL && ret != 0; chip++) {
258 ret = DoC_IdentChip(this, floor, chip);
259 if (ret) {
260 numchips[floor]++;
261 this->numchips++;
262 }
263 }
264 }
265 /* If there are none at all that we recognise, bail */
266 if (!this->numchips) {
267 printk("No flash chips recognised.\n");
268 return;
269 }
270
271 /* Allocate an array to hold the information for each chip */
272 this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL);
273 if (!this->chips){
274 printk("No memory for allocating chip info structures\n");
275 return;
276 }
277
278 /* Fill out the chip array with {floor, chipno} for each
279 * detected chip in the device. */
280 for (floor = 0, ret = 0; floor < MAX_FLOORS_MIL; floor++) {
281 for (chip = 0 ; chip < numchips[floor] ; chip++) {
282 this->chips[ret].floor = floor;
283 this->chips[ret].chip = chip;
284 this->chips[ret].curadr = 0;
285 this->chips[ret].curmode = 0x50;
286 ret++;
287 }
288 }
289
290 /* Calculate and print the total size of the device */
291 this->totlen = this->numchips * (1 << this->chipshift);
292 printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld MiB\n",
293 this->numchips ,this->totlen >> 20);
294}
295
296static int DoCMil_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
297{
298 int tmp1, tmp2, retval;
299
300 if (doc1->physadr == doc2->physadr)
301 return 1;
302
303 /* Use the alias resolution register which was set aside for this
304 * purpose. If it's value is the same on both chips, they might
305 * be the same chip, and we write to one and check for a change in
306 * the other. It's unclear if this register is usuable in the
307 * DoC 2000 (it's in the Millenium docs), but it seems to work. */
308 tmp1 = ReadDOC(doc1->virtadr, AliasResolution);
309 tmp2 = ReadDOC(doc2->virtadr, AliasResolution);
310 if (tmp1 != tmp2)
311 return 0;
312
313 WriteDOC((tmp1+1) % 0xff, doc1->virtadr, AliasResolution);
314 tmp2 = ReadDOC(doc2->virtadr, AliasResolution);
315 if (tmp2 == (tmp1+1) % 0xff)
316 retval = 1;
317 else
318 retval = 0;
319
320 /* Restore register contents. May not be necessary, but do it just to
321 * be safe. */
322 WriteDOC(tmp1, doc1->virtadr, AliasResolution);
323
324 return retval;
325}
326
327static const char im_name[] = "DoCMil_init";
328
329/* This routine is made available to other mtd code via
330 * inter_module_register. It must only be accessed through
331 * inter_module_get which will bump the use count of this module. The
332 * addresses passed back in mtd are valid as long as the use count of
333 * this module is non-zero, i.e. between inter_module_get and
334 * inter_module_put. Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
335 */
336static void DoCMil_init(struct mtd_info *mtd)
337{
338 struct DiskOnChip *this = mtd->priv;
339 struct DiskOnChip *old = NULL;
340
341 /* We must avoid being called twice for the same device. */
342 if (docmillist)
343 old = docmillist->priv;
344
345 while (old) {
346 if (DoCMil_is_alias(this, old)) {
347 printk(KERN_NOTICE "Ignoring DiskOnChip Millennium at "
348 "0x%lX - already configured\n", this->physadr);
349 iounmap(this->virtadr);
350 kfree(mtd);
351 return;
352 }
353 if (old->nextdoc)
354 old = old->nextdoc->priv;
355 else
356 old = NULL;
357 }
358
359 mtd->name = "DiskOnChip Millennium";
360 printk(KERN_NOTICE "DiskOnChip Millennium found at address 0x%lX\n",
361 this->physadr);
362
363 mtd->type = MTD_NANDFLASH;
364 mtd->flags = MTD_CAP_NANDFLASH;
365 mtd->ecctype = MTD_ECC_RS_DiskOnChip;
366 mtd->size = 0;
367
368 /* FIXME: erase size is not always 8KiB */
369 mtd->erasesize = 0x2000;
370
371 mtd->oobblock = 512;
372 mtd->oobsize = 16;
373 mtd->owner = THIS_MODULE;
374 mtd->erase = doc_erase;
375 mtd->point = NULL;
376 mtd->unpoint = NULL;
377 mtd->read = doc_read;
378 mtd->write = doc_write;
379 mtd->read_ecc = doc_read_ecc;
380 mtd->write_ecc = doc_write_ecc;
381 mtd->read_oob = doc_read_oob;
382 mtd->write_oob = doc_write_oob;
383 mtd->sync = NULL;
384
385 this->totlen = 0;
386 this->numchips = 0;
387 this->curfloor = -1;
388 this->curchip = -1;
389
390 /* Ident all the chips present. */
391 DoC_ScanChips(this);
392
393 if (!this->totlen) {
394 kfree(mtd);
395 iounmap(this->virtadr);
396 } else {
397 this->nextdoc = docmillist;
398 docmillist = mtd;
399 mtd->size = this->totlen;
400 add_mtd_device(mtd);
401 return;
402 }
403}
404
405static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
406 size_t *retlen, u_char *buf)
407{
408 /* Just a special case of doc_read_ecc */
409 return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
410}
411
412static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
413 size_t *retlen, u_char *buf, u_char *eccbuf,
414 struct nand_oobinfo *oobsel)
415{
416 int i, ret;
417 volatile char dummy;
418 unsigned char syndrome[6];
419 struct DiskOnChip *this = mtd->priv;
420 void __iomem *docptr = this->virtadr;
421 struct Nand *mychip = &this->chips[from >> (this->chipshift)];
422
423 /* Don't allow read past end of device */
424 if (from >= this->totlen)
425 return -EINVAL;
426
427 /* Don't allow a single read to cross a 512-byte block boundary */
428 if (from + len > ((from | 0x1ff) + 1))
429 len = ((from | 0x1ff) + 1) - from;
430
431 /* Find the chip which is to be used and select it */
432 if (this->curfloor != mychip->floor) {
433 DoC_SelectFloor(docptr, mychip->floor);
434 DoC_SelectChip(docptr, mychip->chip);
435 } else if (this->curchip != mychip->chip) {
436 DoC_SelectChip(docptr, mychip->chip);
437 }
438 this->curfloor = mychip->floor;
439 this->curchip = mychip->chip;
440
441 /* issue the Read0 or Read1 command depend on which half of the page
442 we are accessing. Polling the Flash Ready bit after issue 3 bytes
443 address in Sequence Read Mode, see Software Requirement 11.4 item 1.*/
444 DoC_Command(docptr, (from >> 8) & 1, CDSN_CTRL_WP);
445 DoC_Address(docptr, 3, from, CDSN_CTRL_WP, 0x00);
446 DoC_WaitReady(docptr);
447
448 if (eccbuf) {
449 /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
450 WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
451 WriteDOC (DOC_ECC_EN, docptr, ECCConf);
452 } else {
453 /* disable the ECC engine */
454 WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
455 WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
456 }
457
458 /* Read the data via the internal pipeline through CDSN IO register,
459 see Pipelined Read Operations 11.3 */
460 dummy = ReadDOC(docptr, ReadPipeInit);
461#ifndef USE_MEMCPY
462 for (i = 0; i < len-1; i++) {
463 /* N.B. you have to increase the source address in this way or the
464 ECC logic will not work properly */
465 buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff));
466 }
467#else
468 memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len - 1);
469#endif
470 buf[len - 1] = ReadDOC(docptr, LastDataRead);
471
472 /* Let the caller know we completed it */
473 *retlen = len;
474 ret = 0;
475
476 if (eccbuf) {
477 /* Read the ECC data from Spare Data Area,
478 see Reed-Solomon EDC/ECC 11.1 */
479 dummy = ReadDOC(docptr, ReadPipeInit);
480#ifndef USE_MEMCPY
481 for (i = 0; i < 5; i++) {
482 /* N.B. you have to increase the source address in this way or the
483 ECC logic will not work properly */
484 eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO + i);
485 }
486#else
487 memcpy_fromio(eccbuf, docptr + DoC_Mil_CDSN_IO, 5);
488#endif
489 eccbuf[5] = ReadDOC(docptr, LastDataRead);
490
491 /* Flush the pipeline */
492 dummy = ReadDOC(docptr, ECCConf);
493 dummy = ReadDOC(docptr, ECCConf);
494
495 /* Check the ECC Status */
496 if (ReadDOC(docptr, ECCConf) & 0x80) {
497 int nb_errors;
498 /* There was an ECC error */
499#ifdef ECC_DEBUG
500 printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
501#endif
502 /* Read the ECC syndrom through the DiskOnChip ECC logic.
503 These syndrome will be all ZERO when there is no error */
504 for (i = 0; i < 6; i++) {
505 syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i);
506 }
507 nb_errors = doc_decode_ecc(buf, syndrome);
508#ifdef ECC_DEBUG
509 printk("ECC Errors corrected: %x\n", nb_errors);
510#endif
511 if (nb_errors < 0) {
512 /* We return error, but have actually done the read. Not that
513 this can be told to user-space, via sys_read(), but at least
514 MTD-aware stuff can know about it by checking *retlen */
515 ret = -EIO;
516 }
517 }
518
519#ifdef PSYCHO_DEBUG
520 printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
521 (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
522 eccbuf[4], eccbuf[5]);
523#endif
524
525 /* disable the ECC engine */
526 WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
527 }
528
529 return ret;
530}
531
532static int doc_write (struct mtd_info *mtd, loff_t to, size_t len,
533 size_t *retlen, const u_char *buf)
534{
535 char eccbuf[6];
536 return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL);
537}
538
539static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
540 size_t *retlen, const u_char *buf, u_char *eccbuf,
541 struct nand_oobinfo *oobsel)
542{
543 int i,ret = 0;
544 volatile char dummy;
545 struct DiskOnChip *this = mtd->priv;
546 void __iomem *docptr = this->virtadr;
547 struct Nand *mychip = &this->chips[to >> (this->chipshift)];
548
549 /* Don't allow write past end of device */
550 if (to >= this->totlen)
551 return -EINVAL;
552
553#if 0
554 /* Don't allow a single write to cross a 512-byte block boundary */
555 if (to + len > ( (to | 0x1ff) + 1))
556 len = ((to | 0x1ff) + 1) - to;
557#else
558 /* Don't allow writes which aren't exactly one block */
559 if (to & 0x1ff || len != 0x200)
560 return -EINVAL;
561#endif
562
563 /* Find the chip which is to be used and select it */
564 if (this->curfloor != mychip->floor) {
565 DoC_SelectFloor(docptr, mychip->floor);
566 DoC_SelectChip(docptr, mychip->chip);
567 } else if (this->curchip != mychip->chip) {
568 DoC_SelectChip(docptr, mychip->chip);
569 }
570 this->curfloor = mychip->floor;
571 this->curchip = mychip->chip;
572
573 /* Reset the chip, see Software Requirement 11.4 item 1. */
574 DoC_Command(docptr, NAND_CMD_RESET, 0x00);
575 DoC_WaitReady(docptr);
576 /* Set device to main plane of flash */
577 DoC_Command(docptr, NAND_CMD_READ0, 0x00);
578
579 /* issue the Serial Data In command to initial the Page Program process */
580 DoC_Command(docptr, NAND_CMD_SEQIN, 0x00);
581 DoC_Address(docptr, 3, to, 0x00, 0x00);
582 DoC_WaitReady(docptr);
583
584 if (eccbuf) {
585 /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
586 WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
587 WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
588 } else {
589 /* disable the ECC engine */
590 WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
591 WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
592 }
593
594 /* Write the data via the internal pipeline through CDSN IO register,
595 see Pipelined Write Operations 11.2 */
596#ifndef USE_MEMCPY
597 for (i = 0; i < len; i++) {
598 /* N.B. you have to increase the source address in this way or the
599 ECC logic will not work properly */
600 WriteDOC(buf[i], docptr, Mil_CDSN_IO + i);
601 }
602#else
603 memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len);
604#endif
605 WriteDOC(0x00, docptr, WritePipeTerm);
606
607 if (eccbuf) {
608 /* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic
609 see Reed-Solomon EDC/ECC 11.1 */
610 WriteDOC(0, docptr, NOP);
611 WriteDOC(0, docptr, NOP);
612 WriteDOC(0, docptr, NOP);
613
614 /* Read the ECC data through the DiskOnChip ECC logic */
615 for (i = 0; i < 6; i++) {
616 eccbuf[i] = ReadDOC(docptr, ECCSyndrome0 + i);
617 }
618
619 /* ignore the ECC engine */
620 WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
621
622#ifndef USE_MEMCPY
623 /* Write the ECC data to flash */
624 for (i = 0; i < 6; i++) {
625 /* N.B. you have to increase the source address in this way or the
626 ECC logic will not work properly */
627 WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO + i);
628 }
629#else
630 memcpy_toio(docptr + DoC_Mil_CDSN_IO, eccbuf, 6);
631#endif
632
633 /* write the block status BLOCK_USED (0x5555) at the end of ECC data
634 FIXME: this is only a hack for programming the IPL area for LinuxBIOS
635 and should be replace with proper codes in user space utilities */
636 WriteDOC(0x55, docptr, Mil_CDSN_IO);
637 WriteDOC(0x55, docptr, Mil_CDSN_IO + 1);
638
639 WriteDOC(0x00, docptr, WritePipeTerm);
640
641#ifdef PSYCHO_DEBUG
642 printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
643 (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
644 eccbuf[4], eccbuf[5]);
645#endif
646 }
647
648 /* Commit the Page Program command and wait for ready
649 see Software Requirement 11.4 item 1.*/
650 DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00);
651 DoC_WaitReady(docptr);
652
653 /* Read the status of the flash device through CDSN IO register
654 see Software Requirement 11.4 item 5.*/
655 DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP);
656 dummy = ReadDOC(docptr, ReadPipeInit);
657 DoC_Delay(docptr, 2);
658 if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
659 printk("Error programming flash\n");
660 /* Error in programming
661 FIXME: implement Bad Block Replacement (in nftl.c ??) */
662 *retlen = 0;
663 ret = -EIO;
664 }
665 dummy = ReadDOC(docptr, LastDataRead);
666
667 /* Let the caller know we completed it */
668 *retlen = len;
669
670 return ret;
671}
672
673static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
674 size_t *retlen, u_char *buf)
675{
676#ifndef USE_MEMCPY
677 int i;
678#endif
679 volatile char dummy;
680 struct DiskOnChip *this = mtd->priv;
681 void __iomem *docptr = this->virtadr;
682 struct Nand *mychip = &this->chips[ofs >> this->chipshift];
683
684 /* Find the chip which is to be used and select it */
685 if (this->curfloor != mychip->floor) {
686 DoC_SelectFloor(docptr, mychip->floor);
687 DoC_SelectChip(docptr, mychip->chip);
688 } else if (this->curchip != mychip->chip) {
689 DoC_SelectChip(docptr, mychip->chip);
690 }
691 this->curfloor = mychip->floor;
692 this->curchip = mychip->chip;
693
694 /* disable the ECC engine */
695 WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
696 WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
697
698 /* issue the Read2 command to set the pointer to the Spare Data Area.
699 Polling the Flash Ready bit after issue 3 bytes address in
700 Sequence Read Mode, see Software Requirement 11.4 item 1.*/
701 DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP);
702 DoC_Address(docptr, 3, ofs, CDSN_CTRL_WP, 0x00);
703 DoC_WaitReady(docptr);
704
705 /* Read the data out via the internal pipeline through CDSN IO register,
706 see Pipelined Read Operations 11.3 */
707 dummy = ReadDOC(docptr, ReadPipeInit);
708#ifndef USE_MEMCPY
709 for (i = 0; i < len-1; i++) {
710 /* N.B. you have to increase the source address in this way or the
711 ECC logic will not work properly */
712 buf[i] = ReadDOC(docptr, Mil_CDSN_IO + i);
713 }
714#else
715 memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len - 1);
716#endif
717 buf[len - 1] = ReadDOC(docptr, LastDataRead);
718
719 *retlen = len;
720
721 return 0;
722}
723
724static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
725 size_t *retlen, const u_char *buf)
726{
727#ifndef USE_MEMCPY
728 int i;
729#endif
730 volatile char dummy;
731 int ret = 0;
732 struct DiskOnChip *this = mtd->priv;
733 void __iomem *docptr = this->virtadr;
734 struct Nand *mychip = &this->chips[ofs >> this->chipshift];
735
736 /* Find the chip which is to be used and select it */
737 if (this->curfloor != mychip->floor) {
738 DoC_SelectFloor(docptr, mychip->floor);
739 DoC_SelectChip(docptr, mychip->chip);
740 } else if (this->curchip != mychip->chip) {
741 DoC_SelectChip(docptr, mychip->chip);
742 }
743 this->curfloor = mychip->floor;
744 this->curchip = mychip->chip;
745
746 /* disable the ECC engine */
747 WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
748 WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
749
750 /* Reset the chip, see Software Requirement 11.4 item 1. */
751 DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP);
752 DoC_WaitReady(docptr);
753 /* issue the Read2 command to set the pointer to the Spare Data Area. */
754 DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP);
755
756 /* issue the Serial Data In command to initial the Page Program process */
757 DoC_Command(docptr, NAND_CMD_SEQIN, 0x00);
758 DoC_Address(docptr, 3, ofs, 0x00, 0x00);
759
760 /* Write the data via the internal pipeline through CDSN IO register,
761 see Pipelined Write Operations 11.2 */
762#ifndef USE_MEMCPY
763 for (i = 0; i < len; i++) {
764 /* N.B. you have to increase the source address in this way or the
765 ECC logic will not work properly */
766 WriteDOC(buf[i], docptr, Mil_CDSN_IO + i);
767 }
768#else
769 memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len);
770#endif
771 WriteDOC(0x00, docptr, WritePipeTerm);
772
773 /* Commit the Page Program command and wait for ready
774 see Software Requirement 11.4 item 1.*/
775 DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00);
776 DoC_WaitReady(docptr);
777
778 /* Read the status of the flash device through CDSN IO register
779 see Software Requirement 11.4 item 5.*/
780 DoC_Command(docptr, NAND_CMD_STATUS, 0x00);
781 dummy = ReadDOC(docptr, ReadPipeInit);
782 DoC_Delay(docptr, 2);
783 if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
784 printk("Error programming oob data\n");
785 /* FIXME: implement Bad Block Replacement (in nftl.c ??) */
786 *retlen = 0;
787 ret = -EIO;
788 }
789 dummy = ReadDOC(docptr, LastDataRead);
790
791 *retlen = len;
792
793 return ret;
794}
795
796int doc_erase (struct mtd_info *mtd, struct erase_info *instr)
797{
798 volatile char dummy;
799 struct DiskOnChip *this = mtd->priv;
800 __u32 ofs = instr->addr;
801 __u32 len = instr->len;
802 void __iomem *docptr = this->virtadr;
803 struct Nand *mychip = &this->chips[ofs >> this->chipshift];
804
805 if (len != mtd->erasesize)
806 printk(KERN_WARNING "Erase not right size (%x != %x)n",
807 len, mtd->erasesize);
808
809 /* Find the chip which is to be used and select it */
810 if (this->curfloor != mychip->floor) {
811 DoC_SelectFloor(docptr, mychip->floor);
812 DoC_SelectChip(docptr, mychip->chip);
813 } else if (this->curchip != mychip->chip) {
814 DoC_SelectChip(docptr, mychip->chip);
815 }
816 this->curfloor = mychip->floor;
817 this->curchip = mychip->chip;
818
819 instr->state = MTD_ERASE_PENDING;
820
821 /* issue the Erase Setup command */
822 DoC_Command(docptr, NAND_CMD_ERASE1, 0x00);
823 DoC_Address(docptr, 2, ofs, 0x00, 0x00);
824
825 /* Commit the Erase Start command and wait for ready
826 see Software Requirement 11.4 item 1.*/
827 DoC_Command(docptr, NAND_CMD_ERASE2, 0x00);
828 DoC_WaitReady(docptr);
829
830 instr->state = MTD_ERASING;
831
832 /* Read the status of the flash device through CDSN IO register
833 see Software Requirement 11.4 item 5.
834 FIXME: it seems that we are not wait long enough, some blocks are not
835 erased fully */
836 DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP);
837 dummy = ReadDOC(docptr, ReadPipeInit);
838 DoC_Delay(docptr, 2);
839 if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
840 printk("Error Erasing at 0x%x\n", ofs);
841 /* There was an error
842 FIXME: implement Bad Block Replacement (in nftl.c ??) */
843 instr->state = MTD_ERASE_FAILED;
844 } else
845 instr->state = MTD_ERASE_DONE;
846 dummy = ReadDOC(docptr, LastDataRead);
847
848 mtd_erase_callback(instr);
849
850 return 0;
851}
852
853/****************************************************************************
854 *
855 * Module stuff
856 *
857 ****************************************************************************/
858
859static int __init init_doc2001(void)
860{
861 inter_module_register(im_name, THIS_MODULE, &DoCMil_init);
862 return 0;
863}
864
865static void __exit cleanup_doc2001(void)
866{
867 struct mtd_info *mtd;
868 struct DiskOnChip *this;
869
870 while ((mtd=docmillist)) {
871 this = mtd->priv;
872 docmillist = this->nextdoc;
873
874 del_mtd_device(mtd);
875
876 iounmap(this->virtadr);
877 kfree(this->chips);
878 kfree(mtd);
879 }
880 inter_module_unregister(im_name);
881}
882
883module_exit(cleanup_doc2001);
884module_init(init_doc2001);
885
886MODULE_LICENSE("GPL");
887MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");
888MODULE_DESCRIPTION("Alternative driver for DiskOnChip Millennium");
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c
new file mode 100644
index 000000000000..ed47bafb2ce2
--- /dev/null
+++ b/drivers/mtd/devices/doc2001plus.c
@@ -0,0 +1,1154 @@
1/*
2 * Linux driver for Disk-On-Chip Millennium Plus
3 *
4 * (c) 2002-2003 Greg Ungerer <gerg@snapgear.com>
5 * (c) 2002-2003 SnapGear Inc
6 * (c) 1999 Machine Vision Holdings, Inc.
7 * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
8 *
9 * $Id: doc2001plus.c,v 1.13 2005/01/05 18:05:12 dwmw2 Exp $
10 *
11 * Released under GPL
12 */
13
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <asm/errno.h>
17#include <asm/io.h>
18#include <asm/uaccess.h>
19#include <linux/miscdevice.h>
20#include <linux/pci.h>
21#include <linux/delay.h>
22#include <linux/slab.h>
23#include <linux/sched.h>
24#include <linux/init.h>
25#include <linux/types.h>
26#include <linux/bitops.h>
27
28#include <linux/mtd/mtd.h>
29#include <linux/mtd/nand.h>
30#include <linux/mtd/doc2000.h>
31
32/* #define ECC_DEBUG */
33
34/* I have no idea why some DoC chips can not use memcop_form|to_io().
35 * This may be due to the different revisions of the ASIC controller built-in or
36 * simplily a QA/Bug issue. Who knows ?? If you have trouble, please uncomment
37 * this:*/
38#undef USE_MEMCPY
39
40static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
41 size_t *retlen, u_char *buf);
42static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
43 size_t *retlen, const u_char *buf);
44static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
45 size_t *retlen, u_char *buf, u_char *eccbuf,
46 struct nand_oobinfo *oobsel);
47static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
48 size_t *retlen, const u_char *buf, u_char *eccbuf,
49 struct nand_oobinfo *oobsel);
50static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
51 size_t *retlen, u_char *buf);
52static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
53 size_t *retlen, const u_char *buf);
54static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
55
56static struct mtd_info *docmilpluslist = NULL;
57
58
59/* Perform the required delay cycles by writing to the NOP register */
60static void DoC_Delay(void __iomem * docptr, int cycles)
61{
62 int i;
63
64 for (i = 0; (i < cycles); i++)
65 WriteDOC(0, docptr, Mplus_NOP);
66}
67
68#define CDSN_CTRL_FR_B_MASK (CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1)
69
70/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
71static int _DoC_WaitReady(void __iomem * docptr)
72{
73 unsigned int c = 0xffff;
74
75 DEBUG(MTD_DEBUG_LEVEL3,
76 "_DoC_WaitReady called for out-of-line wait\n");
77
78 /* Out-of-line routine to wait for chip response */
79 while (((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) && --c)
80 ;
81
82 if (c == 0)
83 DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
84
85 return (c == 0);
86}
87
88static inline int DoC_WaitReady(void __iomem * docptr)
89{
90 /* This is inline, to optimise the common case, where it's ready instantly */
91 int ret = 0;
92
93 /* read form NOP register should be issued prior to the read from CDSNControl
94 see Software Requirement 11.4 item 2. */
95 DoC_Delay(docptr, 4);
96
97 if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK)
98 /* Call the out-of-line routine to wait */
99 ret = _DoC_WaitReady(docptr);
100
101 return ret;
102}
103
104/* For some reason the Millennium Plus seems to occassionally put itself
105 * into reset mode. For me this happens randomly, with no pattern that I
106 * can detect. M-systems suggest always check this on any block level
107 * operation and setting to normal mode if in reset mode.
108 */
109static inline void DoC_CheckASIC(void __iomem * docptr)
110{
111 /* Make sure the DoC is in normal mode */
112 if ((ReadDOC(docptr, Mplus_DOCControl) & DOC_MODE_NORMAL) == 0) {
113 WriteDOC((DOC_MODE_NORMAL | DOC_MODE_MDWREN), docptr, Mplus_DOCControl);
114 WriteDOC(~(DOC_MODE_NORMAL | DOC_MODE_MDWREN), docptr, Mplus_CtrlConfirm);
115 }
116}
117
118/* DoC_Command: Send a flash command to the flash chip through the Flash
119 * command register. Need 2 Write Pipeline Terminates to complete send.
120 */
121static inline void DoC_Command(void __iomem * docptr, unsigned char command,
122 unsigned char xtraflags)
123{
124 WriteDOC(command, docptr, Mplus_FlashCmd);
125 WriteDOC(command, docptr, Mplus_WritePipeTerm);
126 WriteDOC(command, docptr, Mplus_WritePipeTerm);
127}
128
129/* DoC_Address: Set the current address for the flash chip through the Flash
130 * Address register. Need 2 Write Pipeline Terminates to complete send.
131 */
132static inline void DoC_Address(struct DiskOnChip *doc, int numbytes,
133 unsigned long ofs, unsigned char xtraflags1,
134 unsigned char xtraflags2)
135{
136 void __iomem * docptr = doc->virtadr;
137
138 /* Allow for possible Mill Plus internal flash interleaving */
139 ofs >>= doc->interleave;
140
141 switch (numbytes) {
142 case 1:
143 /* Send single byte, bits 0-7. */
144 WriteDOC(ofs & 0xff, docptr, Mplus_FlashAddress);
145 break;
146 case 2:
147 /* Send bits 9-16 followed by 17-23 */
148 WriteDOC((ofs >> 9) & 0xff, docptr, Mplus_FlashAddress);
149 WriteDOC((ofs >> 17) & 0xff, docptr, Mplus_FlashAddress);
150 break;
151 case 3:
152 /* Send 0-7, 9-16, then 17-23 */
153 WriteDOC(ofs & 0xff, docptr, Mplus_FlashAddress);
154 WriteDOC((ofs >> 9) & 0xff, docptr, Mplus_FlashAddress);
155 WriteDOC((ofs >> 17) & 0xff, docptr, Mplus_FlashAddress);
156 break;
157 default:
158 return;
159 }
160
161 WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
162 WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
163}
164
165/* DoC_SelectChip: Select a given flash chip within the current floor */
166static int DoC_SelectChip(void __iomem * docptr, int chip)
167{
168 /* No choice for flash chip on Millennium Plus */
169 return 0;
170}
171
172/* DoC_SelectFloor: Select a given floor (bank of flash chips) */
173static int DoC_SelectFloor(void __iomem * docptr, int floor)
174{
175 WriteDOC((floor & 0x3), docptr, Mplus_DeviceSelect);
176 return 0;
177}
178
179/*
180 * Translate the given offset into the appropriate command and offset.
181 * This does the mapping using the 16bit interleave layout defined by
182 * M-Systems, and looks like this for a sector pair:
183 * +-----------+-------+-------+-------+--------------+---------+-----------+
184 * | 0 --- 511 |512-517|518-519|520-521| 522 --- 1033 |1034-1039|1040 - 1055|
185 * +-----------+-------+-------+-------+--------------+---------+-----------+
186 * | Data 0 | ECC 0 |Flags0 |Flags1 | Data 1 |ECC 1 | OOB 1 + 2 |
187 * +-----------+-------+-------+-------+--------------+---------+-----------+
188 */
189/* FIXME: This lives in INFTL not here. Other users of flash devices
190 may not want it */
191static unsigned int DoC_GetDataOffset(struct mtd_info *mtd, loff_t *from)
192{
193 struct DiskOnChip *this = mtd->priv;
194
195 if (this->interleave) {
196 unsigned int ofs = *from & 0x3ff;
197 unsigned int cmd;
198
199 if (ofs < 512) {
200 cmd = NAND_CMD_READ0;
201 ofs &= 0x1ff;
202 } else if (ofs < 1014) {
203 cmd = NAND_CMD_READ1;
204 ofs = (ofs & 0x1ff) + 10;
205 } else {
206 cmd = NAND_CMD_READOOB;
207 ofs = ofs - 1014;
208 }
209
210 *from = (*from & ~0x3ff) | ofs;
211 return cmd;
212 } else {
213 /* No interleave */
214 if ((*from) & 0x100)
215 return NAND_CMD_READ1;
216 return NAND_CMD_READ0;
217 }
218}
219
220static unsigned int DoC_GetECCOffset(struct mtd_info *mtd, loff_t *from)
221{
222 unsigned int ofs, cmd;
223
224 if (*from & 0x200) {
225 cmd = NAND_CMD_READOOB;
226 ofs = 10 + (*from & 0xf);
227 } else {
228 cmd = NAND_CMD_READ1;
229 ofs = (*from & 0xf);
230 }
231
232 *from = (*from & ~0x3ff) | ofs;
233 return cmd;
234}
235
236static unsigned int DoC_GetFlagsOffset(struct mtd_info *mtd, loff_t *from)
237{
238 unsigned int ofs, cmd;
239
240 cmd = NAND_CMD_READ1;
241 ofs = (*from & 0x200) ? 8 : 6;
242 *from = (*from & ~0x3ff) | ofs;
243 return cmd;
244}
245
246static unsigned int DoC_GetHdrOffset(struct mtd_info *mtd, loff_t *from)
247{
248 unsigned int ofs, cmd;
249
250 cmd = NAND_CMD_READOOB;
251 ofs = (*from & 0x200) ? 24 : 16;
252 *from = (*from & ~0x3ff) | ofs;
253 return cmd;
254}
255
256static inline void MemReadDOC(void __iomem * docptr, unsigned char *buf, int len)
257{
258#ifndef USE_MEMCPY
259 int i;
260 for (i = 0; i < len; i++)
261 buf[i] = ReadDOC(docptr, Mil_CDSN_IO + i);
262#else
263 memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len);
264#endif
265}
266
267static inline void MemWriteDOC(void __iomem * docptr, unsigned char *buf, int len)
268{
269#ifndef USE_MEMCPY
270 int i;
271 for (i = 0; i < len; i++)
272 WriteDOC(buf[i], docptr, Mil_CDSN_IO + i);
273#else
274 memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len);
275#endif
276}
277
278/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
279static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
280{
281 int mfr, id, i, j;
282 volatile char dummy;
283 void __iomem * docptr = doc->virtadr;
284
285 /* Page in the required floor/chip */
286 DoC_SelectFloor(docptr, floor);
287 DoC_SelectChip(docptr, chip);
288
289 /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
290 WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect);
291
292 /* Reset the chip, see Software Requirement 11.4 item 1. */
293 DoC_Command(docptr, NAND_CMD_RESET, 0);
294 DoC_WaitReady(docptr);
295
296 /* Read the NAND chip ID: 1. Send ReadID command */
297 DoC_Command(docptr, NAND_CMD_READID, 0);
298
299 /* Read the NAND chip ID: 2. Send address byte zero */
300 DoC_Address(doc, 1, 0x00, 0, 0x00);
301
302 WriteDOC(0, docptr, Mplus_FlashControl);
303 DoC_WaitReady(docptr);
304
305 /* Read the manufacturer and device id codes of the flash device through
306 CDSN IO register see Software Requirement 11.4 item 5.*/
307 dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
308 dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
309
310 mfr = ReadDOC(docptr, Mil_CDSN_IO);
311 if (doc->interleave)
312 dummy = ReadDOC(docptr, Mil_CDSN_IO); /* 2 way interleave */
313
314 id = ReadDOC(docptr, Mil_CDSN_IO);
315 if (doc->interleave)
316 dummy = ReadDOC(docptr, Mil_CDSN_IO); /* 2 way interleave */
317
318 dummy = ReadDOC(docptr, Mplus_LastDataRead);
319 dummy = ReadDOC(docptr, Mplus_LastDataRead);
320
321 /* Disable flash internally */
322 WriteDOC(0, docptr, Mplus_FlashSelect);
323
324 /* No response - return failure */
325 if (mfr == 0xff || mfr == 0)
326 return 0;
327
328 for (i = 0; nand_flash_ids[i].name != NULL; i++) {
329 if (id == nand_flash_ids[i].id) {
330 /* Try to identify manufacturer */
331 for (j = 0; nand_manuf_ids[j].id != 0x0; j++) {
332 if (nand_manuf_ids[j].id == mfr)
333 break;
334 }
335 printk(KERN_INFO "Flash chip found: Manufacturer ID: %2.2X, "
336 "Chip ID: %2.2X (%s:%s)\n", mfr, id,
337 nand_manuf_ids[j].name, nand_flash_ids[i].name);
338 doc->mfr = mfr;
339 doc->id = id;
340 doc->chipshift = ffs((nand_flash_ids[i].chipsize << 20)) - 1;
341 doc->erasesize = nand_flash_ids[i].erasesize << doc->interleave;
342 break;
343 }
344 }
345
346 if (nand_flash_ids[i].name == NULL)
347 return 0;
348 return 1;
349}
350
351/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */
352static void DoC_ScanChips(struct DiskOnChip *this)
353{
354 int floor, chip;
355 int numchips[MAX_FLOORS_MPLUS];
356 int ret;
357
358 this->numchips = 0;
359 this->mfr = 0;
360 this->id = 0;
361
362 /* Work out the intended interleave setting */
363 this->interleave = 0;
364 if (this->ChipID == DOC_ChipID_DocMilPlus32)
365 this->interleave = 1;
366
367 /* Check the ASIC agrees */
368 if ( (this->interleave << 2) !=
369 (ReadDOC(this->virtadr, Mplus_Configuration) & 4)) {
370 u_char conf = ReadDOC(this->virtadr, Mplus_Configuration);
371 printk(KERN_NOTICE "Setting DiskOnChip Millennium Plus interleave to %s\n",
372 this->interleave?"on (16-bit)":"off (8-bit)");
373 conf ^= 4;
374 WriteDOC(conf, this->virtadr, Mplus_Configuration);
375 }
376
377 /* For each floor, find the number of valid chips it contains */
378 for (floor = 0,ret = 1; floor < MAX_FLOORS_MPLUS; floor++) {
379 numchips[floor] = 0;
380 for (chip = 0; chip < MAX_CHIPS_MPLUS && ret != 0; chip++) {
381 ret = DoC_IdentChip(this, floor, chip);
382 if (ret) {
383 numchips[floor]++;
384 this->numchips++;
385 }
386 }
387 }
388 /* If there are none at all that we recognise, bail */
389 if (!this->numchips) {
390 printk("No flash chips recognised.\n");
391 return;
392 }
393
394 /* Allocate an array to hold the information for each chip */
395 this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL);
396 if (!this->chips){
397 printk("MTD: No memory for allocating chip info structures\n");
398 return;
399 }
400
401 /* Fill out the chip array with {floor, chipno} for each
402 * detected chip in the device. */
403 for (floor = 0, ret = 0; floor < MAX_FLOORS_MPLUS; floor++) {
404 for (chip = 0 ; chip < numchips[floor] ; chip++) {
405 this->chips[ret].floor = floor;
406 this->chips[ret].chip = chip;
407 this->chips[ret].curadr = 0;
408 this->chips[ret].curmode = 0x50;
409 ret++;
410 }
411 }
412
413 /* Calculate and print the total size of the device */
414 this->totlen = this->numchips * (1 << this->chipshift);
415 printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld MiB\n",
416 this->numchips ,this->totlen >> 20);
417}
418
419static int DoCMilPlus_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
420{
421 int tmp1, tmp2, retval;
422
423 if (doc1->physadr == doc2->physadr)
424 return 1;
425
426 /* Use the alias resolution register which was set aside for this
427 * purpose. If it's value is the same on both chips, they might
428 * be the same chip, and we write to one and check for a change in
429 * the other. It's unclear if this register is usuable in the
430 * DoC 2000 (it's in the Millennium docs), but it seems to work. */
431 tmp1 = ReadDOC(doc1->virtadr, Mplus_AliasResolution);
432 tmp2 = ReadDOC(doc2->virtadr, Mplus_AliasResolution);
433 if (tmp1 != tmp2)
434 return 0;
435
436 WriteDOC((tmp1+1) % 0xff, doc1->virtadr, Mplus_AliasResolution);
437 tmp2 = ReadDOC(doc2->virtadr, Mplus_AliasResolution);
438 if (tmp2 == (tmp1+1) % 0xff)
439 retval = 1;
440 else
441 retval = 0;
442
443 /* Restore register contents. May not be necessary, but do it just to
444 * be safe. */
445 WriteDOC(tmp1, doc1->virtadr, Mplus_AliasResolution);
446
447 return retval;
448}
449
450static const char im_name[] = "DoCMilPlus_init";
451
452/* This routine is made available to other mtd code via
453 * inter_module_register. It must only be accessed through
454 * inter_module_get which will bump the use count of this module. The
455 * addresses passed back in mtd are valid as long as the use count of
456 * this module is non-zero, i.e. between inter_module_get and
457 * inter_module_put. Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
458 */
459static void DoCMilPlus_init(struct mtd_info *mtd)
460{
461 struct DiskOnChip *this = mtd->priv;
462 struct DiskOnChip *old = NULL;
463
464 /* We must avoid being called twice for the same device. */
465 if (docmilpluslist)
466 old = docmilpluslist->priv;
467
468 while (old) {
469 if (DoCMilPlus_is_alias(this, old)) {
470 printk(KERN_NOTICE "Ignoring DiskOnChip Millennium "
471 "Plus at 0x%lX - already configured\n",
472 this->physadr);
473 iounmap(this->virtadr);
474 kfree(mtd);
475 return;
476 }
477 if (old->nextdoc)
478 old = old->nextdoc->priv;
479 else
480 old = NULL;
481 }
482
483 mtd->name = "DiskOnChip Millennium Plus";
484 printk(KERN_NOTICE "DiskOnChip Millennium Plus found at "
485 "address 0x%lX\n", this->physadr);
486
487 mtd->type = MTD_NANDFLASH;
488 mtd->flags = MTD_CAP_NANDFLASH;
489 mtd->ecctype = MTD_ECC_RS_DiskOnChip;
490 mtd->size = 0;
491
492 mtd->erasesize = 0;
493 mtd->oobblock = 512;
494 mtd->oobsize = 16;
495 mtd->owner = THIS_MODULE;
496 mtd->erase = doc_erase;
497 mtd->point = NULL;
498 mtd->unpoint = NULL;
499 mtd->read = doc_read;
500 mtd->write = doc_write;
501 mtd->read_ecc = doc_read_ecc;
502 mtd->write_ecc = doc_write_ecc;
503 mtd->read_oob = doc_read_oob;
504 mtd->write_oob = doc_write_oob;
505 mtd->sync = NULL;
506
507 this->totlen = 0;
508 this->numchips = 0;
509 this->curfloor = -1;
510 this->curchip = -1;
511
512 /* Ident all the chips present. */
513 DoC_ScanChips(this);
514
515 if (!this->totlen) {
516 kfree(mtd);
517 iounmap(this->virtadr);
518 } else {
519 this->nextdoc = docmilpluslist;
520 docmilpluslist = mtd;
521 mtd->size = this->totlen;
522 mtd->erasesize = this->erasesize;
523 add_mtd_device(mtd);
524 return;
525 }
526}
527
528#if 0
529static int doc_dumpblk(struct mtd_info *mtd, loff_t from)
530{
531 int i;
532 loff_t fofs;
533 struct DiskOnChip *this = mtd->priv;
534 void __iomem * docptr = this->virtadr;
535 struct Nand *mychip = &this->chips[from >> (this->chipshift)];
536 unsigned char *bp, buf[1056];
537 char c[32];
538
539 from &= ~0x3ff;
540
541 /* Don't allow read past end of device */
542 if (from >= this->totlen)
543 return -EINVAL;
544
545 DoC_CheckASIC(docptr);
546
547 /* Find the chip which is to be used and select it */
548 if (this->curfloor != mychip->floor) {
549 DoC_SelectFloor(docptr, mychip->floor);
550 DoC_SelectChip(docptr, mychip->chip);
551 } else if (this->curchip != mychip->chip) {
552 DoC_SelectChip(docptr, mychip->chip);
553 }
554 this->curfloor = mychip->floor;
555 this->curchip = mychip->chip;
556
557 /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
558 WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect);
559
560 /* Reset the chip, see Software Requirement 11.4 item 1. */
561 DoC_Command(docptr, NAND_CMD_RESET, 0);
562 DoC_WaitReady(docptr);
563
564 fofs = from;
565 DoC_Command(docptr, DoC_GetDataOffset(mtd, &fofs), 0);
566 DoC_Address(this, 3, fofs, 0, 0x00);
567 WriteDOC(0, docptr, Mplus_FlashControl);
568 DoC_WaitReady(docptr);
569
570 /* disable the ECC engine */
571 WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
572
573 ReadDOC(docptr, Mplus_ReadPipeInit);
574 ReadDOC(docptr, Mplus_ReadPipeInit);
575
576 /* Read the data via the internal pipeline through CDSN IO
577 register, see Pipelined Read Operations 11.3 */
578 MemReadDOC(docptr, buf, 1054);
579 buf[1054] = ReadDOC(docptr, Mplus_LastDataRead);
580 buf[1055] = ReadDOC(docptr, Mplus_LastDataRead);
581
582 memset(&c[0], 0, sizeof(c));
583 printk("DUMP OFFSET=%x:\n", (int)from);
584
585 for (i = 0, bp = &buf[0]; (i < 1056); i++) {
586 if ((i % 16) == 0)
587 printk("%08x: ", i);
588 printk(" %02x", *bp);
589 c[(i & 0xf)] = ((*bp >= 0x20) && (*bp <= 0x7f)) ? *bp : '.';
590 bp++;
591 if (((i + 1) % 16) == 0)
592 printk(" %s\n", c);
593 }
594 printk("\n");
595
596 /* Disable flash internally */
597 WriteDOC(0, docptr, Mplus_FlashSelect);
598
599 return 0;
600}
601#endif
602
603static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
604 size_t *retlen, u_char *buf)
605{
606 /* Just a special case of doc_read_ecc */
607 return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
608}
609
610static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
611 size_t *retlen, u_char *buf, u_char *eccbuf,
612 struct nand_oobinfo *oobsel)
613{
614 int ret, i;
615 volatile char dummy;
616 loff_t fofs;
617 unsigned char syndrome[6];
618 struct DiskOnChip *this = mtd->priv;
619 void __iomem * docptr = this->virtadr;
620 struct Nand *mychip = &this->chips[from >> (this->chipshift)];
621
622 /* Don't allow read past end of device */
623 if (from >= this->totlen)
624 return -EINVAL;
625
626 /* Don't allow a single read to cross a 512-byte block boundary */
627 if (from + len > ((from | 0x1ff) + 1))
628 len = ((from | 0x1ff) + 1) - from;
629
630 DoC_CheckASIC(docptr);
631
632 /* Find the chip which is to be used and select it */
633 if (this->curfloor != mychip->floor) {
634 DoC_SelectFloor(docptr, mychip->floor);
635 DoC_SelectChip(docptr, mychip->chip);
636 } else if (this->curchip != mychip->chip) {
637 DoC_SelectChip(docptr, mychip->chip);
638 }
639 this->curfloor = mychip->floor;
640 this->curchip = mychip->chip;
641
642 /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
643 WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect);
644
645 /* Reset the chip, see Software Requirement 11.4 item 1. */
646 DoC_Command(docptr, NAND_CMD_RESET, 0);
647 DoC_WaitReady(docptr);
648
649 fofs = from;
650 DoC_Command(docptr, DoC_GetDataOffset(mtd, &fofs), 0);
651 DoC_Address(this, 3, fofs, 0, 0x00);
652 WriteDOC(0, docptr, Mplus_FlashControl);
653 DoC_WaitReady(docptr);
654
655 if (eccbuf) {
656 /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
657 WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
658 WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);
659 } else {
660 /* disable the ECC engine */
661 WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
662 }
663
664 /* Let the caller know we completed it */
665 *retlen = len;
666 ret = 0;
667
668 ReadDOC(docptr, Mplus_ReadPipeInit);
669 ReadDOC(docptr, Mplus_ReadPipeInit);
670
671 if (eccbuf) {
672 /* Read the data via the internal pipeline through CDSN IO
673 register, see Pipelined Read Operations 11.3 */
674 MemReadDOC(docptr, buf, len);
675
676 /* Read the ECC data following raw data */
677 MemReadDOC(docptr, eccbuf, 4);
678 eccbuf[4] = ReadDOC(docptr, Mplus_LastDataRead);
679 eccbuf[5] = ReadDOC(docptr, Mplus_LastDataRead);
680
681 /* Flush the pipeline */
682 dummy = ReadDOC(docptr, Mplus_ECCConf);
683 dummy = ReadDOC(docptr, Mplus_ECCConf);
684
685 /* Check the ECC Status */
686 if (ReadDOC(docptr, Mplus_ECCConf) & 0x80) {
687 int nb_errors;
688 /* There was an ECC error */
689#ifdef ECC_DEBUG
690 printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
691#endif
692 /* Read the ECC syndrom through the DiskOnChip ECC logic.
693 These syndrome will be all ZERO when there is no error */
694 for (i = 0; i < 6; i++)
695 syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
696
697 nb_errors = doc_decode_ecc(buf, syndrome);
698#ifdef ECC_DEBUG
699 printk("ECC Errors corrected: %x\n", nb_errors);
700#endif
701 if (nb_errors < 0) {
702 /* We return error, but have actually done the read. Not that
703 this can be told to user-space, via sys_read(), but at least
704 MTD-aware stuff can know about it by checking *retlen */
705#ifdef ECC_DEBUG
706 printk("%s(%d): Millennium Plus ECC error (from=0x%x:\n",
707 __FILE__, __LINE__, (int)from);
708 printk(" syndrome= %02x:%02x:%02x:%02x:%02x:"
709 "%02x\n",
710 syndrome[0], syndrome[1], syndrome[2],
711 syndrome[3], syndrome[4], syndrome[5]);
712 printk(" eccbuf= %02x:%02x:%02x:%02x:%02x:"
713 "%02x\n",
714 eccbuf[0], eccbuf[1], eccbuf[2],
715 eccbuf[3], eccbuf[4], eccbuf[5]);
716#endif
717 ret = -EIO;
718 }
719 }
720
721#ifdef PSYCHO_DEBUG
722 printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
723 (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
724 eccbuf[4], eccbuf[5]);
725#endif
726
727 /* disable the ECC engine */
728 WriteDOC(DOC_ECC_DIS, docptr , Mplus_ECCConf);
729 } else {
730 /* Read the data via the internal pipeline through CDSN IO
731 register, see Pipelined Read Operations 11.3 */
732 MemReadDOC(docptr, buf, len-2);
733 buf[len-2] = ReadDOC(docptr, Mplus_LastDataRead);
734 buf[len-1] = ReadDOC(docptr, Mplus_LastDataRead);
735 }
736
737 /* Disable flash internally */
738 WriteDOC(0, docptr, Mplus_FlashSelect);
739
740 return ret;
741}
742
743static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
744 size_t *retlen, const u_char *buf)
745{
746 char eccbuf[6];
747 return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL);
748}
749
750static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
751 size_t *retlen, const u_char *buf, u_char *eccbuf,
752 struct nand_oobinfo *oobsel)
753{
754 int i, before, ret = 0;
755 loff_t fto;
756 volatile char dummy;
757 struct DiskOnChip *this = mtd->priv;
758 void __iomem * docptr = this->virtadr;
759 struct Nand *mychip = &this->chips[to >> (this->chipshift)];
760
761 /* Don't allow write past end of device */
762 if (to >= this->totlen)
763 return -EINVAL;
764
765 /* Don't allow writes which aren't exactly one block (512 bytes) */
766 if ((to & 0x1ff) || (len != 0x200))
767 return -EINVAL;
768
769 /* Determine position of OOB flags, before or after data */
770 before = (this->interleave && (to & 0x200));
771
772 DoC_CheckASIC(docptr);
773
774 /* Find the chip which is to be used and select it */
775 if (this->curfloor != mychip->floor) {
776 DoC_SelectFloor(docptr, mychip->floor);
777 DoC_SelectChip(docptr, mychip->chip);
778 } else if (this->curchip != mychip->chip) {
779 DoC_SelectChip(docptr, mychip->chip);
780 }
781 this->curfloor = mychip->floor;
782 this->curchip = mychip->chip;
783
784 /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
785 WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect);
786
787 /* Reset the chip, see Software Requirement 11.4 item 1. */
788 DoC_Command(docptr, NAND_CMD_RESET, 0);
789 DoC_WaitReady(docptr);
790
791 /* Set device to appropriate plane of flash */
792 fto = to;
793 WriteDOC(DoC_GetDataOffset(mtd, &fto), docptr, Mplus_FlashCmd);
794
795 /* On interleaved devices the flags for 2nd half 512 are before data */
796 if (eccbuf && before)
797 fto -= 2;
798
799 /* issue the Serial Data In command to initial the Page Program process */
800 DoC_Command(docptr, NAND_CMD_SEQIN, 0x00);
801 DoC_Address(this, 3, fto, 0x00, 0x00);
802
803 /* Disable the ECC engine */
804 WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
805
806 if (eccbuf) {
807 if (before) {
808 /* Write the block status BLOCK_USED (0x5555) */
809 WriteDOC(0x55, docptr, Mil_CDSN_IO);
810 WriteDOC(0x55, docptr, Mil_CDSN_IO);
811 }
812
813 /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
814 WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf);
815 }
816
817 MemWriteDOC(docptr, (unsigned char *) buf, len);
818
819 if (eccbuf) {
820 /* Write ECC data to flash, the ECC info is generated by
821 the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */
822 DoC_Delay(docptr, 3);
823
824 /* Read the ECC data through the DiskOnChip ECC logic */
825 for (i = 0; i < 6; i++)
826 eccbuf[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
827
828 /* disable the ECC engine */
829 WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
830
831 /* Write the ECC data to flash */
832 MemWriteDOC(docptr, eccbuf, 6);
833
834 if (!before) {
835 /* Write the block status BLOCK_USED (0x5555) */
836 WriteDOC(0x55, docptr, Mil_CDSN_IO+6);
837 WriteDOC(0x55, docptr, Mil_CDSN_IO+7);
838 }
839
840#ifdef PSYCHO_DEBUG
841 printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
842 (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
843 eccbuf[4], eccbuf[5]);
844#endif
845 }
846
847 WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
848 WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
849
850 /* Commit the Page Program command and wait for ready
851 see Software Requirement 11.4 item 1.*/
852 DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00);
853 DoC_WaitReady(docptr);
854
855 /* Read the status of the flash device through CDSN IO register
856 see Software Requirement 11.4 item 5.*/
857 DoC_Command(docptr, NAND_CMD_STATUS, 0);
858 dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
859 dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
860 DoC_Delay(docptr, 2);
861 if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) {
862 printk("MTD: Error 0x%x programming at 0x%x\n", dummy, (int)to);
863 /* Error in programming
864 FIXME: implement Bad Block Replacement (in nftl.c ??) */
865 *retlen = 0;
866 ret = -EIO;
867 }
868 dummy = ReadDOC(docptr, Mplus_LastDataRead);
869
870 /* Disable flash internally */
871 WriteDOC(0, docptr, Mplus_FlashSelect);
872
873 /* Let the caller know we completed it */
874 *retlen = len;
875
876 return ret;
877}
878
879static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
880 size_t *retlen, u_char *buf)
881{
882 loff_t fofs, base;
883 struct DiskOnChip *this = mtd->priv;
884 void __iomem * docptr = this->virtadr;
885 struct Nand *mychip = &this->chips[ofs >> this->chipshift];
886 size_t i, size, got, want;
887
888 DoC_CheckASIC(docptr);
889
890 /* Find the chip which is to be used and select it */
891 if (this->curfloor != mychip->floor) {
892 DoC_SelectFloor(docptr, mychip->floor);
893 DoC_SelectChip(docptr, mychip->chip);
894 } else if (this->curchip != mychip->chip) {
895 DoC_SelectChip(docptr, mychip->chip);
896 }
897 this->curfloor = mychip->floor;
898 this->curchip = mychip->chip;
899
900 /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
901 WriteDOC((DOC_FLASH_CE | DOC_FLASH_WP), docptr, Mplus_FlashSelect);
902
903 /* disable the ECC engine */
904 WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
905 DoC_WaitReady(docptr);
906
907 /* Maximum of 16 bytes in the OOB region, so limit read to that */
908 if (len > 16)
909 len = 16;
910 got = 0;
911 want = len;
912
913 for (i = 0; ((i < 3) && (want > 0)); i++) {
914 /* Figure out which region we are accessing... */
915 fofs = ofs;
916 base = ofs & 0xf;
917 if (!this->interleave) {
918 DoC_Command(docptr, NAND_CMD_READOOB, 0);
919 size = 16 - base;
920 } else if (base < 6) {
921 DoC_Command(docptr, DoC_GetECCOffset(mtd, &fofs), 0);
922 size = 6 - base;
923 } else if (base < 8) {
924 DoC_Command(docptr, DoC_GetFlagsOffset(mtd, &fofs), 0);
925 size = 8 - base;
926 } else {
927 DoC_Command(docptr, DoC_GetHdrOffset(mtd, &fofs), 0);
928 size = 16 - base;
929 }
930 if (size > want)
931 size = want;
932
933 /* Issue read command */
934 DoC_Address(this, 3, fofs, 0, 0x00);
935 WriteDOC(0, docptr, Mplus_FlashControl);
936 DoC_WaitReady(docptr);
937
938 ReadDOC(docptr, Mplus_ReadPipeInit);
939 ReadDOC(docptr, Mplus_ReadPipeInit);
940 MemReadDOC(docptr, &buf[got], size - 2);
941 buf[got + size - 2] = ReadDOC(docptr, Mplus_LastDataRead);
942 buf[got + size - 1] = ReadDOC(docptr, Mplus_LastDataRead);
943
944 ofs += size;
945 got += size;
946 want -= size;
947 }
948
949 /* Disable flash internally */
950 WriteDOC(0, docptr, Mplus_FlashSelect);
951
952 *retlen = len;
953 return 0;
954}
955
956static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
957 size_t *retlen, const u_char *buf)
958{
959 volatile char dummy;
960 loff_t fofs, base;
961 struct DiskOnChip *this = mtd->priv;
962 void __iomem * docptr = this->virtadr;
963 struct Nand *mychip = &this->chips[ofs >> this->chipshift];
964 size_t i, size, got, want;
965 int ret = 0;
966
967 DoC_CheckASIC(docptr);
968
969 /* Find the chip which is to be used and select it */
970 if (this->curfloor != mychip->floor) {
971 DoC_SelectFloor(docptr, mychip->floor);
972 DoC_SelectChip(docptr, mychip->chip);
973 } else if (this->curchip != mychip->chip) {
974 DoC_SelectChip(docptr, mychip->chip);
975 }
976 this->curfloor = mychip->floor;
977 this->curchip = mychip->chip;
978
979 /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
980 WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect);
981
982
983 /* Maximum of 16 bytes in the OOB region, so limit write to that */
984 if (len > 16)
985 len = 16;
986 got = 0;
987 want = len;
988
989 for (i = 0; ((i < 3) && (want > 0)); i++) {
990 /* Reset the chip, see Software Requirement 11.4 item 1. */
991 DoC_Command(docptr, NAND_CMD_RESET, 0);
992 DoC_WaitReady(docptr);
993
994 /* Figure out which region we are accessing... */
995 fofs = ofs;
996 base = ofs & 0x0f;
997 if (!this->interleave) {
998 WriteDOC(NAND_CMD_READOOB, docptr, Mplus_FlashCmd);
999 size = 16 - base;
1000 } else if (base < 6) {
1001 WriteDOC(DoC_GetECCOffset(mtd, &fofs), docptr, Mplus_FlashCmd);
1002 size = 6 - base;
1003 } else if (base < 8) {
1004 WriteDOC(DoC_GetFlagsOffset(mtd, &fofs), docptr, Mplus_FlashCmd);
1005 size = 8 - base;
1006 } else {
1007 WriteDOC(DoC_GetHdrOffset(mtd, &fofs), docptr, Mplus_FlashCmd);
1008 size = 16 - base;
1009 }
1010 if (size > want)
1011 size = want;
1012
1013 /* Issue the Serial Data In command to initial the Page Program process */
1014 DoC_Command(docptr, NAND_CMD_SEQIN, 0x00);
1015 DoC_Address(this, 3, fofs, 0, 0x00);
1016
1017 /* Disable the ECC engine */
1018 WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
1019
1020 /* Write the data via the internal pipeline through CDSN IO
1021 register, see Pipelined Write Operations 11.2 */
1022 MemWriteDOC(docptr, (unsigned char *) &buf[got], size);
1023 WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
1024 WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
1025
1026 /* Commit the Page Program command and wait for ready
1027 see Software Requirement 11.4 item 1.*/
1028 DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00);
1029 DoC_WaitReady(docptr);
1030
1031 /* Read the status of the flash device through CDSN IO register
1032 see Software Requirement 11.4 item 5.*/
1033 DoC_Command(docptr, NAND_CMD_STATUS, 0x00);
1034 dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
1035 dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
1036 DoC_Delay(docptr, 2);
1037 if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) {
1038 printk("MTD: Error 0x%x programming oob at 0x%x\n",
1039 dummy, (int)ofs);
1040 /* FIXME: implement Bad Block Replacement */
1041 *retlen = 0;
1042 ret = -EIO;
1043 }
1044 dummy = ReadDOC(docptr, Mplus_LastDataRead);
1045
1046 ofs += size;
1047 got += size;
1048 want -= size;
1049 }
1050
1051 /* Disable flash internally */
1052 WriteDOC(0, docptr, Mplus_FlashSelect);
1053
1054 *retlen = len;
1055 return ret;
1056}
1057
1058int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
1059{
1060 volatile char dummy;
1061 struct DiskOnChip *this = mtd->priv;
1062 __u32 ofs = instr->addr;
1063 __u32 len = instr->len;
1064 void __iomem * docptr = this->virtadr;
1065 struct Nand *mychip = &this->chips[ofs >> this->chipshift];
1066
1067 DoC_CheckASIC(docptr);
1068
1069 if (len != mtd->erasesize)
1070 printk(KERN_WARNING "MTD: Erase not right size (%x != %x)n",
1071 len, mtd->erasesize);
1072
1073 /* Find the chip which is to be used and select it */
1074 if (this->curfloor != mychip->floor) {
1075 DoC_SelectFloor(docptr, mychip->floor);
1076 DoC_SelectChip(docptr, mychip->chip);
1077 } else if (this->curchip != mychip->chip) {
1078 DoC_SelectChip(docptr, mychip->chip);
1079 }
1080 this->curfloor = mychip->floor;
1081 this->curchip = mychip->chip;
1082
1083 instr->state = MTD_ERASE_PENDING;
1084
1085 /* Millennium Plus bus cycle sequence as per figure 2, section 2.4 */
1086 WriteDOC(DOC_FLASH_CE, docptr, Mplus_FlashSelect);
1087
1088 DoC_Command(docptr, NAND_CMD_RESET, 0x00);
1089 DoC_WaitReady(docptr);
1090
1091 DoC_Command(docptr, NAND_CMD_ERASE1, 0);
1092 DoC_Address(this, 2, ofs, 0, 0x00);
1093 DoC_Command(docptr, NAND_CMD_ERASE2, 0);
1094 DoC_WaitReady(docptr);
1095 instr->state = MTD_ERASING;
1096
1097 /* Read the status of the flash device through CDSN IO register
1098 see Software Requirement 11.4 item 5. */
1099 DoC_Command(docptr, NAND_CMD_STATUS, 0);
1100 dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
1101 dummy = ReadDOC(docptr, Mplus_ReadPipeInit);
1102 if ((dummy = ReadDOC(docptr, Mplus_LastDataRead)) & 1) {
1103 printk("MTD: Error 0x%x erasing at 0x%x\n", dummy, ofs);
1104 /* FIXME: implement Bad Block Replacement (in nftl.c ??) */
1105 instr->state = MTD_ERASE_FAILED;
1106 } else {
1107 instr->state = MTD_ERASE_DONE;
1108 }
1109 dummy = ReadDOC(docptr, Mplus_LastDataRead);
1110
1111 /* Disable flash internally */
1112 WriteDOC(0, docptr, Mplus_FlashSelect);
1113
1114 mtd_erase_callback(instr);
1115
1116 return 0;
1117}
1118
1119/****************************************************************************
1120 *
1121 * Module stuff
1122 *
1123 ****************************************************************************/
1124
1125static int __init init_doc2001plus(void)
1126{
1127 inter_module_register(im_name, THIS_MODULE, &DoCMilPlus_init);
1128 return 0;
1129}
1130
1131static void __exit cleanup_doc2001plus(void)
1132{
1133 struct mtd_info *mtd;
1134 struct DiskOnChip *this;
1135
1136 while ((mtd=docmilpluslist)) {
1137 this = mtd->priv;
1138 docmilpluslist = this->nextdoc;
1139
1140 del_mtd_device(mtd);
1141
1142 iounmap(this->virtadr);
1143 kfree(this->chips);
1144 kfree(mtd);
1145 }
1146 inter_module_unregister(im_name);
1147}
1148
1149module_exit(cleanup_doc2001plus);
1150module_init(init_doc2001plus);
1151
1152MODULE_LICENSE("GPL");
1153MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com> et al.");
1154MODULE_DESCRIPTION("Driver for DiskOnChip Millennium Plus");
diff --git a/drivers/mtd/devices/docecc.c b/drivers/mtd/devices/docecc.c
new file mode 100644
index 000000000000..933877ff4d88
--- /dev/null
+++ b/drivers/mtd/devices/docecc.c
@@ -0,0 +1,526 @@
1/*
2 * ECC algorithm for M-systems disk on chip. We use the excellent Reed
3 * Solmon code of Phil Karn (karn@ka9q.ampr.org) available under the
4 * GNU GPL License. The rest is simply to convert the disk on chip
5 * syndrom into a standard syndom.
6 *
7 * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
8 * Copyright (C) 2000 Netgem S.A.
9 *
10 * $Id: docecc.c,v 1.5 2003/05/21 15:15:06 dwmw2 Exp $
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <asm/errno.h>
29#include <asm/io.h>
30#include <asm/uaccess.h>
31#include <linux/miscdevice.h>
32#include <linux/pci.h>
33#include <linux/delay.h>
34#include <linux/slab.h>
35#include <linux/sched.h>
36#include <linux/init.h>
37#include <linux/types.h>
38
39#include <linux/mtd/compatmac.h> /* for min() in older kernels */
40#include <linux/mtd/mtd.h>
41#include <linux/mtd/doc2000.h>
42
43/* need to undef it (from asm/termbits.h) */
44#undef B0
45
46#define MM 10 /* Symbol size in bits */
47#define KK (1023-4) /* Number of data symbols per block */
48#define B0 510 /* First root of generator polynomial, alpha form */
49#define PRIM 1 /* power of alpha used to generate roots of generator poly */
50#define NN ((1 << MM) - 1)
51
52typedef unsigned short dtype;
53
54/* 1+x^3+x^10 */
55static const int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };
56
57/* This defines the type used to store an element of the Galois Field
58 * used by the code. Make sure this is something larger than a char if
59 * if anything larger than GF(256) is used.
60 *
61 * Note: unsigned char will work up to GF(256) but int seems to run
62 * faster on the Pentium.
63 */
64typedef int gf;
65
66/* No legal value in index form represents zero, so
67 * we need a special value for this purpose
68 */
69#define A0 (NN)
70
71/* Compute x % NN, where NN is 2**MM - 1,
72 * without a slow divide
73 */
74static inline gf
75modnn(int x)
76{
77 while (x >= NN) {
78 x -= NN;
79 x = (x >> MM) + (x & NN);
80 }
81 return x;
82}
83
84#define CLEAR(a,n) {\
85int ci;\
86for(ci=(n)-1;ci >=0;ci--)\
87(a)[ci] = 0;\
88}
89
90#define COPY(a,b,n) {\
91int ci;\
92for(ci=(n)-1;ci >=0;ci--)\
93(a)[ci] = (b)[ci];\
94}
95
96#define COPYDOWN(a,b,n) {\
97int ci;\
98for(ci=(n)-1;ci >=0;ci--)\
99(a)[ci] = (b)[ci];\
100}
101
102#define Ldec 1
103
104/* generate GF(2**m) from the irreducible polynomial p(X) in Pp[0]..Pp[m]
105 lookup tables: index->polynomial form alpha_to[] contains j=alpha**i;
106 polynomial form -> index form index_of[j=alpha**i] = i
107 alpha=2 is the primitive element of GF(2**m)
108 HARI's COMMENT: (4/13/94) alpha_to[] can be used as follows:
109 Let @ represent the primitive element commonly called "alpha" that
110 is the root of the primitive polynomial p(x). Then in GF(2^m), for any
111 0 <= i <= 2^m-2,
112 @^i = a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)
113 where the binary vector (a(0),a(1),a(2),...,a(m-1)) is the representation
114 of the integer "alpha_to[i]" with a(0) being the LSB and a(m-1) the MSB. Thus for
115 example the polynomial representation of @^5 would be given by the binary
116 representation of the integer "alpha_to[5]".
117 Similarily, index_of[] can be used as follows:
118 As above, let @ represent the primitive element of GF(2^m) that is
119 the root of the primitive polynomial p(x). In order to find the power
120 of @ (alpha) that has the polynomial representation
121 a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)
122 we consider the integer "i" whose binary representation with a(0) being LSB
123 and a(m-1) MSB is (a(0),a(1),...,a(m-1)) and locate the entry
124 "index_of[i]". Now, @^index_of[i] is that element whose polynomial
125 representation is (a(0),a(1),a(2),...,a(m-1)).
126 NOTE:
127 The element alpha_to[2^m-1] = 0 always signifying that the
128 representation of "@^infinity" = 0 is (0,0,0,...,0).
129 Similarily, the element index_of[0] = A0 always signifying
130 that the power of alpha which has the polynomial representation
131 (0,0,...,0) is "infinity".
132
133*/
134
135static void
136generate_gf(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1])
137{
138 register int i, mask;
139
140 mask = 1;
141 Alpha_to[MM] = 0;
142 for (i = 0; i < MM; i++) {
143 Alpha_to[i] = mask;
144 Index_of[Alpha_to[i]] = i;
145 /* If Pp[i] == 1 then, term @^i occurs in poly-repr of @^MM */
146 if (Pp[i] != 0)
147 Alpha_to[MM] ^= mask; /* Bit-wise EXOR operation */
148 mask <<= 1; /* single left-shift */
149 }
150 Index_of[Alpha_to[MM]] = MM;
151 /*
152 * Have obtained poly-repr of @^MM. Poly-repr of @^(i+1) is given by
153 * poly-repr of @^i shifted left one-bit and accounting for any @^MM
154 * term that may occur when poly-repr of @^i is shifted.
155 */
156 mask >>= 1;
157 for (i = MM + 1; i < NN; i++) {
158 if (Alpha_to[i - 1] >= mask)
159 Alpha_to[i] = Alpha_to[MM] ^ ((Alpha_to[i - 1] ^ mask) << 1);
160 else
161 Alpha_to[i] = Alpha_to[i - 1] << 1;
162 Index_of[Alpha_to[i]] = i;
163 }
164 Index_of[0] = A0;
165 Alpha_to[NN] = 0;
166}
167
168/*
169 * Performs ERRORS+ERASURES decoding of RS codes. bb[] is the content
170 * of the feedback shift register after having processed the data and
171 * the ECC.
172 *
173 * Return number of symbols corrected, or -1 if codeword is illegal
174 * or uncorrectable. If eras_pos is non-null, the detected error locations
175 * are written back. NOTE! This array must be at least NN-KK elements long.
176 * The corrected data are written in eras_val[]. They must be xor with the data
177 * to retrieve the correct data : data[erase_pos[i]] ^= erase_val[i] .
178 *
179 * First "no_eras" erasures are declared by the calling program. Then, the
180 * maximum # of errors correctable is t_after_eras = floor((NN-KK-no_eras)/2).
181 * If the number of channel errors is not greater than "t_after_eras" the
182 * transmitted codeword will be recovered. Details of algorithm can be found
183 * in R. Blahut's "Theory ... of Error-Correcting Codes".
184
185 * Warning: the eras_pos[] array must not contain duplicate entries; decoder failure
186 * will result. The decoder *could* check for this condition, but it would involve
187 * extra time on every decoding operation.
188 * */
189static int
190eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1],
191 gf bb[NN - KK + 1], gf eras_val[NN-KK], int eras_pos[NN-KK],
192 int no_eras)
193{
194 int deg_lambda, el, deg_omega;
195 int i, j, r,k;
196 gf u,q,tmp,num1,num2,den,discr_r;
197 gf lambda[NN-KK + 1], s[NN-KK + 1]; /* Err+Eras Locator poly
198 * and syndrome poly */
199 gf b[NN-KK + 1], t[NN-KK + 1], omega[NN-KK + 1];
200 gf root[NN-KK], reg[NN-KK + 1], loc[NN-KK];
201 int syn_error, count;
202
203 syn_error = 0;
204 for(i=0;i<NN-KK;i++)
205 syn_error |= bb[i];
206
207 if (!syn_error) {
208 /* if remainder is zero, data[] is a codeword and there are no
209 * errors to correct. So return data[] unmodified
210 */
211 count = 0;
212 goto finish;
213 }
214
215 for(i=1;i<=NN-KK;i++){
216 s[i] = bb[0];
217 }
218 for(j=1;j<NN-KK;j++){
219 if(bb[j] == 0)
220 continue;
221 tmp = Index_of[bb[j]];
222
223 for(i=1;i<=NN-KK;i++)
224 s[i] ^= Alpha_to[modnn(tmp + (B0+i-1)*PRIM*j)];
225 }
226
227 /* undo the feedback register implicit multiplication and convert
228 syndromes to index form */
229
230 for(i=1;i<=NN-KK;i++) {
231 tmp = Index_of[s[i]];
232 if (tmp != A0)
233 tmp = modnn(tmp + 2 * KK * (B0+i-1)*PRIM);
234 s[i] = tmp;
235 }
236
237 CLEAR(&lambda[1],NN-KK);
238 lambda[0] = 1;
239
240 if (no_eras > 0) {
241 /* Init lambda to be the erasure locator polynomial */
242 lambda[1] = Alpha_to[modnn(PRIM * eras_pos[0])];
243 for (i = 1; i < no_eras; i++) {
244 u = modnn(PRIM*eras_pos[i]);
245 for (j = i+1; j > 0; j--) {
246 tmp = Index_of[lambda[j - 1]];
247 if(tmp != A0)
248 lambda[j] ^= Alpha_to[modnn(u + tmp)];
249 }
250 }
251#if DEBUG >= 1
252 /* Test code that verifies the erasure locator polynomial just constructed
253 Needed only for decoder debugging. */
254
255 /* find roots of the erasure location polynomial */
256 for(i=1;i<=no_eras;i++)
257 reg[i] = Index_of[lambda[i]];
258 count = 0;
259 for (i = 1,k=NN-Ldec; i <= NN; i++,k = modnn(NN+k-Ldec)) {
260 q = 1;
261 for (j = 1; j <= no_eras; j++)
262 if (reg[j] != A0) {
263 reg[j] = modnn(reg[j] + j);
264 q ^= Alpha_to[reg[j]];
265 }
266 if (q != 0)
267 continue;
268 /* store root and error location number indices */
269 root[count] = i;
270 loc[count] = k;
271 count++;
272 }
273 if (count != no_eras) {
274 printf("\n lambda(x) is WRONG\n");
275 count = -1;
276 goto finish;
277 }
278#if DEBUG >= 2
279 printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n");
280 for (i = 0; i < count; i++)
281 printf("%d ", loc[i]);
282 printf("\n");
283#endif
284#endif
285 }
286 for(i=0;i<NN-KK+1;i++)
287 b[i] = Index_of[lambda[i]];
288
289 /*
290 * Begin Berlekamp-Massey algorithm to determine error+erasure
291 * locator polynomial
292 */
293 r = no_eras;
294 el = no_eras;
295 while (++r <= NN-KK) { /* r is the step number */
296 /* Compute discrepancy at the r-th step in poly-form */
297 discr_r = 0;
298 for (i = 0; i < r; i++){
299 if ((lambda[i] != 0) && (s[r - i] != A0)) {
300 discr_r ^= Alpha_to[modnn(Index_of[lambda[i]] + s[r - i])];
301 }
302 }
303 discr_r = Index_of[discr_r]; /* Index form */
304 if (discr_r == A0) {
305 /* 2 lines below: B(x) <-- x*B(x) */
306 COPYDOWN(&b[1],b,NN-KK);
307 b[0] = A0;
308 } else {
309 /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
310 t[0] = lambda[0];
311 for (i = 0 ; i < NN-KK; i++) {
312 if(b[i] != A0)
313 t[i+1] = lambda[i+1] ^ Alpha_to[modnn(discr_r + b[i])];
314 else
315 t[i+1] = lambda[i+1];
316 }
317 if (2 * el <= r + no_eras - 1) {
318 el = r + no_eras - el;
319 /*
320 * 2 lines below: B(x) <-- inv(discr_r) *
321 * lambda(x)
322 */
323 for (i = 0; i <= NN-KK; i++)
324 b[i] = (lambda[i] == 0) ? A0 : modnn(Index_of[lambda[i]] - discr_r + NN);
325 } else {
326 /* 2 lines below: B(x) <-- x*B(x) */
327 COPYDOWN(&b[1],b,NN-KK);
328 b[0] = A0;
329 }
330 COPY(lambda,t,NN-KK+1);
331 }
332 }
333
334 /* Convert lambda to index form and compute deg(lambda(x)) */
335 deg_lambda = 0;
336 for(i=0;i<NN-KK+1;i++){
337 lambda[i] = Index_of[lambda[i]];
338 if(lambda[i] != A0)
339 deg_lambda = i;
340 }
341 /*
342 * Find roots of the error+erasure locator polynomial by Chien
343 * Search
344 */
345 COPY(&reg[1],&lambda[1],NN-KK);
346 count = 0; /* Number of roots of lambda(x) */
347 for (i = 1,k=NN-Ldec; i <= NN; i++,k = modnn(NN+k-Ldec)) {
348 q = 1;
349 for (j = deg_lambda; j > 0; j--){
350 if (reg[j] != A0) {
351 reg[j] = modnn(reg[j] + j);
352 q ^= Alpha_to[reg[j]];
353 }
354 }
355 if (q != 0)
356 continue;
357 /* store root (index-form) and error location number */
358 root[count] = i;
359 loc[count] = k;
360 /* If we've already found max possible roots,
361 * abort the search to save time
362 */
363 if(++count == deg_lambda)
364 break;
365 }
366 if (deg_lambda != count) {
367 /*
368 * deg(lambda) unequal to number of roots => uncorrectable
369 * error detected
370 */
371 count = -1;
372 goto finish;
373 }
374 /*
375 * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
376 * x**(NN-KK)). in index form. Also find deg(omega).
377 */
378 deg_omega = 0;
379 for (i = 0; i < NN-KK;i++){
380 tmp = 0;
381 j = (deg_lambda < i) ? deg_lambda : i;
382 for(;j >= 0; j--){
383 if ((s[i + 1 - j] != A0) && (lambda[j] != A0))
384 tmp ^= Alpha_to[modnn(s[i + 1 - j] + lambda[j])];
385 }
386 if(tmp != 0)
387 deg_omega = i;
388 omega[i] = Index_of[tmp];
389 }
390 omega[NN-KK] = A0;
391
392 /*
393 * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
394 * inv(X(l))**(B0-1) and den = lambda_pr(inv(X(l))) all in poly-form
395 */
396 for (j = count-1; j >=0; j--) {
397 num1 = 0;
398 for (i = deg_omega; i >= 0; i--) {
399 if (omega[i] != A0)
400 num1 ^= Alpha_to[modnn(omega[i] + i * root[j])];
401 }
402 num2 = Alpha_to[modnn(root[j] * (B0 - 1) + NN)];
403 den = 0;
404
405 /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
406 for (i = min(deg_lambda,NN-KK-1) & ~1; i >= 0; i -=2) {
407 if(lambda[i+1] != A0)
408 den ^= Alpha_to[modnn(lambda[i+1] + i * root[j])];
409 }
410 if (den == 0) {
411#if DEBUG >= 1
412 printf("\n ERROR: denominator = 0\n");
413#endif
414 /* Convert to dual- basis */
415 count = -1;
416 goto finish;
417 }
418 /* Apply error to data */
419 if (num1 != 0) {
420 eras_val[j] = Alpha_to[modnn(Index_of[num1] + Index_of[num2] + NN - Index_of[den])];
421 } else {
422 eras_val[j] = 0;
423 }
424 }
425 finish:
426 for(i=0;i<count;i++)
427 eras_pos[i] = loc[i];
428 return count;
429}
430
431/***************************************************************************/
432/* The DOC specific code begins here */
433
434#define SECTOR_SIZE 512
435/* The sector bytes are packed into NB_DATA MM bits words */
436#define NB_DATA (((SECTOR_SIZE + 1) * 8 + 6) / MM)
437
438/*
439 * Correct the errors in 'sector[]' by using 'ecc1[]' which is the
440 * content of the feedback shift register applyied to the sector and
441 * the ECC. Return the number of errors corrected (and correct them in
442 * sector), or -1 if error
443 */
444int doc_decode_ecc(unsigned char sector[SECTOR_SIZE], unsigned char ecc1[6])
445{
446 int parity, i, nb_errors;
447 gf bb[NN - KK + 1];
448 gf error_val[NN-KK];
449 int error_pos[NN-KK], pos, bitpos, index, val;
450 dtype *Alpha_to, *Index_of;
451
452 /* init log and exp tables here to save memory. However, it is slower */
453 Alpha_to = kmalloc((NN + 1) * sizeof(dtype), GFP_KERNEL);
454 if (!Alpha_to)
455 return -1;
456
457 Index_of = kmalloc((NN + 1) * sizeof(dtype), GFP_KERNEL);
458 if (!Index_of) {
459 kfree(Alpha_to);
460 return -1;
461 }
462
463 generate_gf(Alpha_to, Index_of);
464
465 parity = ecc1[1];
466
467 bb[0] = (ecc1[4] & 0xff) | ((ecc1[5] & 0x03) << 8);
468 bb[1] = ((ecc1[5] & 0xfc) >> 2) | ((ecc1[2] & 0x0f) << 6);
469 bb[2] = ((ecc1[2] & 0xf0) >> 4) | ((ecc1[3] & 0x3f) << 4);
470 bb[3] = ((ecc1[3] & 0xc0) >> 6) | ((ecc1[0] & 0xff) << 2);
471
472 nb_errors = eras_dec_rs(Alpha_to, Index_of, bb,
473 error_val, error_pos, 0);
474 if (nb_errors <= 0)
475 goto the_end;
476
477 /* correct the errors */
478 for(i=0;i<nb_errors;i++) {
479 pos = error_pos[i];
480 if (pos >= NB_DATA && pos < KK) {
481 nb_errors = -1;
482 goto the_end;
483 }
484 if (pos < NB_DATA) {
485 /* extract bit position (MSB first) */
486 pos = 10 * (NB_DATA - 1 - pos) - 6;
487 /* now correct the following 10 bits. At most two bytes
488 can be modified since pos is even */
489 index = (pos >> 3) ^ 1;
490 bitpos = pos & 7;
491 if ((index >= 0 && index < SECTOR_SIZE) ||
492 index == (SECTOR_SIZE + 1)) {
493 val = error_val[i] >> (2 + bitpos);
494 parity ^= val;
495 if (index < SECTOR_SIZE)
496 sector[index] ^= val;
497 }
498 index = ((pos >> 3) + 1) ^ 1;
499 bitpos = (bitpos + 10) & 7;
500 if (bitpos == 0)
501 bitpos = 8;
502 if ((index >= 0 && index < SECTOR_SIZE) ||
503 index == (SECTOR_SIZE + 1)) {
504 val = error_val[i] << (8 - bitpos);
505 parity ^= val;
506 if (index < SECTOR_SIZE)
507 sector[index] ^= val;
508 }
509 }
510 }
511
512 /* use parity to test extra errors */
513 if ((parity & 0xff) != 0)
514 nb_errors = -1;
515
516 the_end:
517 kfree(Alpha_to);
518 kfree(Index_of);
519 return nb_errors;
520}
521
522EXPORT_SYMBOL_GPL(doc_decode_ecc);
523
524MODULE_LICENSE("GPL");
525MODULE_AUTHOR("Fabrice Bellard <fabrice.bellard@netgem.com>");
526MODULE_DESCRIPTION("ECC code for correcting errors detected by DiskOnChip 2000 and Millennium ECC hardware");
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c
new file mode 100644
index 000000000000..197d67045e1e
--- /dev/null
+++ b/drivers/mtd/devices/docprobe.c
@@ -0,0 +1,355 @@
1
2/* Linux driver for Disk-On-Chip devices */
3/* Probe routines common to all DoC devices */
4/* (C) 1999 Machine Vision Holdings, Inc. */
5/* (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> */
6
7/* $Id: docprobe.c,v 1.44 2005/01/05 12:40:36 dwmw2 Exp $ */
8
9
10
11/* DOC_PASSIVE_PROBE:
12 In order to ensure that the BIOS checksum is correct at boot time, and
13 hence that the onboard BIOS extension gets executed, the DiskOnChip
14 goes into reset mode when it is read sequentially: all registers
15 return 0xff until the chip is woken up again by writing to the
16 DOCControl register.
17
18 Unfortunately, this means that the probe for the DiskOnChip is unsafe,
19 because one of the first things it does is write to where it thinks
20 the DOCControl register should be - which may well be shared memory
21 for another device. I've had machines which lock up when this is
22 attempted. Hence the possibility to do a passive probe, which will fail
23 to detect a chip in reset mode, but is at least guaranteed not to lock
24 the machine.
25
26 If you have this problem, uncomment the following line:
27#define DOC_PASSIVE_PROBE
28*/
29
30
31/* DOC_SINGLE_DRIVER:
32 Millennium driver has been merged into DOC2000 driver.
33
34 The old Millennium-only driver has been retained just in case there
35 are problems with the new code. If the combined driver doesn't work
36 for you, you can try the old one by undefining DOC_SINGLE_DRIVER
37 below and also enabling it in your configuration. If this fixes the
38 problems, please send a report to the MTD mailing list at
39 <linux-mtd@lists.infradead.org>.
40*/
41#define DOC_SINGLE_DRIVER
42
43#include <linux/config.h>
44#include <linux/kernel.h>
45#include <linux/module.h>
46#include <asm/errno.h>
47#include <asm/io.h>
48#include <linux/delay.h>
49#include <linux/slab.h>
50#include <linux/init.h>
51#include <linux/types.h>
52
53#include <linux/mtd/mtd.h>
54#include <linux/mtd/nand.h>
55#include <linux/mtd/doc2000.h>
56#include <linux/mtd/compatmac.h>
57
58/* Where to look for the devices? */
59#ifndef CONFIG_MTD_DOCPROBE_ADDRESS
60#define CONFIG_MTD_DOCPROBE_ADDRESS 0
61#endif
62
63
64static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS;
65module_param(doc_config_location, ulong, 0);
66MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip");
67
68static unsigned long __initdata doc_locations[] = {
69#if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)
70#ifdef CONFIG_MTD_DOCPROBE_HIGH
71 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000,
72 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000,
73 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000,
74 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000,
75 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000,
76#else /* CONFIG_MTD_DOCPROBE_HIGH */
77 0xc8000, 0xca000, 0xcc000, 0xce000,
78 0xd0000, 0xd2000, 0xd4000, 0xd6000,
79 0xd8000, 0xda000, 0xdc000, 0xde000,
80 0xe0000, 0xe2000, 0xe4000, 0xe6000,
81 0xe8000, 0xea000, 0xec000, 0xee000,
82#endif /* CONFIG_MTD_DOCPROBE_HIGH */
83#elif defined(__PPC__)
84 0xe4000000,
85#elif defined(CONFIG_MOMENCO_OCELOT)
86 0x2f000000,
87 0xff000000,
88#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
89 0xff000000,
90##else
91#warning Unknown architecture for DiskOnChip. No default probe locations defined
92#endif
93 0xffffffff };
94
95/* doccheck: Probe a given memory window to see if there's a DiskOnChip present */
96
97static inline int __init doccheck(void __iomem *potential, unsigned long physadr)
98{
99 void __iomem *window=potential;
100 unsigned char tmp, tmpb, tmpc, ChipID;
101#ifndef DOC_PASSIVE_PROBE
102 unsigned char tmp2;
103#endif
104
105 /* Routine copied from the Linux DOC driver */
106
107#ifdef CONFIG_MTD_DOCPROBE_55AA
108 /* Check for 0x55 0xAA signature at beginning of window,
109 this is no longer true once we remove the IPL (for Millennium */
110 if (ReadDOC(window, Sig1) != 0x55 || ReadDOC(window, Sig2) != 0xaa)
111 return 0;
112#endif /* CONFIG_MTD_DOCPROBE_55AA */
113
114#ifndef DOC_PASSIVE_PROBE
115 /* It's not possible to cleanly detect the DiskOnChip - the
116 * bootup procedure will put the device into reset mode, and
117 * it's not possible to talk to it without actually writing
118 * to the DOCControl register. So we store the current contents
119 * of the DOCControl register's location, in case we later decide
120 * that it's not a DiskOnChip, and want to put it back how we
121 * found it.
122 */
123 tmp2 = ReadDOC(window, DOCControl);
124
125 /* Reset the DiskOnChip ASIC */
126 WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
127 window, DOCControl);
128 WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
129 window, DOCControl);
130
131 /* Enable the DiskOnChip ASIC */
132 WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
133 window, DOCControl);
134 WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
135 window, DOCControl);
136#endif /* !DOC_PASSIVE_PROBE */
137
138 /* We need to read the ChipID register four times. For some
139 newer DiskOnChip 2000 units, the first three reads will
140 return the DiskOnChip Millennium ident. Don't ask. */
141 ChipID = ReadDOC(window, ChipID);
142
143 switch (ChipID) {
144 case DOC_ChipID_Doc2k:
145 /* Check the TOGGLE bit in the ECC register */
146 tmp = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT;
147 tmpb = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT;
148 tmpc = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT;
149 if (tmp != tmpb && tmp == tmpc)
150 return ChipID;
151 break;
152
153 case DOC_ChipID_DocMil:
154 /* Check for the new 2000 with Millennium ASIC */
155 ReadDOC(window, ChipID);
156 ReadDOC(window, ChipID);
157 if (ReadDOC(window, ChipID) != DOC_ChipID_DocMil)
158 ChipID = DOC_ChipID_Doc2kTSOP;
159
160 /* Check the TOGGLE bit in the ECC register */
161 tmp = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
162 tmpb = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
163 tmpc = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT;
164 if (tmp != tmpb && tmp == tmpc)
165 return ChipID;
166 break;
167
168 case DOC_ChipID_DocMilPlus16:
169 case DOC_ChipID_DocMilPlus32:
170 case 0:
171 /* Possible Millennium+, need to do more checks */
172#ifndef DOC_PASSIVE_PROBE
173 /* Possibly release from power down mode */
174 for (tmp = 0; (tmp < 4); tmp++)
175 ReadDOC(window, Mplus_Power);
176
177 /* Reset the DiskOnChip ASIC */
178 tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
179 DOC_MODE_BDECT;
180 WriteDOC(tmp, window, Mplus_DOCControl);
181 WriteDOC(~tmp, window, Mplus_CtrlConfirm);
182
183 mdelay(1);
184 /* Enable the DiskOnChip ASIC */
185 tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
186 DOC_MODE_BDECT;
187 WriteDOC(tmp, window, Mplus_DOCControl);
188 WriteDOC(~tmp, window, Mplus_CtrlConfirm);
189 mdelay(1);
190#endif /* !DOC_PASSIVE_PROBE */
191
192 ChipID = ReadDOC(window, ChipID);
193
194 switch (ChipID) {
195 case DOC_ChipID_DocMilPlus16:
196 case DOC_ChipID_DocMilPlus32:
197 /* Check the TOGGLE bit in the toggle register */
198 tmp = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT;
199 tmpb = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT;
200 tmpc = ReadDOC(window, Mplus_Toggle) & DOC_TOGGLE_BIT;
201 if (tmp != tmpb && tmp == tmpc)
202 return ChipID;
203 default:
204 break;
205 }
206 /* FALL TRHU */
207
208 default:
209
210#ifdef CONFIG_MTD_DOCPROBE_55AA
211 printk(KERN_DEBUG "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n",
212 ChipID, physadr);
213#endif
214#ifndef DOC_PASSIVE_PROBE
215 /* Put back the contents of the DOCControl register, in case it's not
216 * actually a DiskOnChip.
217 */
218 WriteDOC(tmp2, window, DOCControl);
219#endif
220 return 0;
221 }
222
223 printk(KERN_WARNING "DiskOnChip failed TOGGLE test, dropping.\n");
224
225#ifndef DOC_PASSIVE_PROBE
226 /* Put back the contents of the DOCControl register: it's not a DiskOnChip */
227 WriteDOC(tmp2, window, DOCControl);
228#endif
229 return 0;
230}
231
232static int docfound;
233
234static void __init DoC_Probe(unsigned long physadr)
235{
236 void __iomem *docptr;
237 struct DiskOnChip *this;
238 struct mtd_info *mtd;
239 int ChipID;
240 char namebuf[15];
241 char *name = namebuf;
242 char *im_funcname = NULL;
243 char *im_modname = NULL;
244 void (*initroutine)(struct mtd_info *) = NULL;
245
246 docptr = ioremap(physadr, DOC_IOREMAP_LEN);
247
248 if (!docptr)
249 return;
250
251 if ((ChipID = doccheck(docptr, physadr))) {
252 if (ChipID == DOC_ChipID_Doc2kTSOP) {
253 /* Remove this at your own peril. The hardware driver works but nothing prevents you from erasing bad blocks */
254 printk(KERN_NOTICE "Refusing to drive DiskOnChip 2000 TSOP until Bad Block Table is correctly supported by INFTL\n");
255 iounmap(docptr);
256 return;
257 }
258 docfound = 1;
259 mtd = kmalloc(sizeof(struct DiskOnChip) + sizeof(struct mtd_info), GFP_KERNEL);
260
261 if (!mtd) {
262 printk(KERN_WARNING "Cannot allocate memory for data structures. Dropping.\n");
263 iounmap(docptr);
264 return;
265 }
266
267 this = (struct DiskOnChip *)(&mtd[1]);
268
269 memset((char *)mtd,0, sizeof(struct mtd_info));
270 memset((char *)this, 0, sizeof(struct DiskOnChip));
271
272 mtd->priv = this;
273 this->virtadr = docptr;
274 this->physadr = physadr;
275 this->ChipID = ChipID;
276 sprintf(namebuf, "with ChipID %2.2X", ChipID);
277
278 switch(ChipID) {
279 case DOC_ChipID_Doc2kTSOP:
280 name="2000 TSOP";
281 im_funcname = "DoC2k_init";
282 im_modname = "doc2000";
283 break;
284
285 case DOC_ChipID_Doc2k:
286 name="2000";
287 im_funcname = "DoC2k_init";
288 im_modname = "doc2000";
289 break;
290
291 case DOC_ChipID_DocMil:
292 name="Millennium";
293#ifdef DOC_SINGLE_DRIVER
294 im_funcname = "DoC2k_init";
295 im_modname = "doc2000";
296#else
297 im_funcname = "DoCMil_init";
298 im_modname = "doc2001";
299#endif /* DOC_SINGLE_DRIVER */
300 break;
301
302 case DOC_ChipID_DocMilPlus16:
303 case DOC_ChipID_DocMilPlus32:
304 name="MillenniumPlus";
305 im_funcname = "DoCMilPlus_init";
306 im_modname = "doc2001plus";
307 break;
308 }
309
310 if (im_funcname)
311 initroutine = inter_module_get_request(im_funcname, im_modname);
312
313 if (initroutine) {
314 (*initroutine)(mtd);
315 inter_module_put(im_funcname);
316 return;
317 }
318 printk(KERN_NOTICE "Cannot find driver for DiskOnChip %s at 0x%lX\n", name, physadr);
319 kfree(mtd);
320 }
321 iounmap(docptr);
322}
323
324
325/****************************************************************************
326 *
327 * Module stuff
328 *
329 ****************************************************************************/
330
331static int __init init_doc(void)
332{
333 int i;
334
335 if (doc_config_location) {
336 printk(KERN_INFO "Using configured DiskOnChip probe address 0x%lx\n", doc_config_location);
337 DoC_Probe(doc_config_location);
338 } else {
339 for (i=0; (doc_locations[i] != 0xffffffff); i++) {
340 DoC_Probe(doc_locations[i]);
341 }
342 }
343 /* No banner message any more. Print a message if no DiskOnChip
344 found, so the user knows we at least tried. */
345 if (!docfound)
346 printk(KERN_INFO "No recognised DiskOnChip devices found\n");
347 return -EAGAIN;
348}
349
350module_init(init_doc);
351
352MODULE_LICENSE("GPL");
353MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
354MODULE_DESCRIPTION("Probe code for DiskOnChip 2000 and Millennium devices");
355
diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c
new file mode 100644
index 000000000000..dfd335e4a2a8
--- /dev/null
+++ b/drivers/mtd/devices/lart.c
@@ -0,0 +1,711 @@
1
2/*
3 * MTD driver for the 28F160F3 Flash Memory (non-CFI) on LART.
4 *
5 * $Id: lart.c,v 1.7 2004/08/09 13:19:44 dwmw2 Exp $
6 *
7 * Author: Abraham vd Merwe <abraham@2d3d.co.za>
8 *
9 * Copyright (c) 2001, 2d3D, Inc.
10 *
11 * This code is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 * References:
16 *
17 * [1] 3 Volt Fast Boot Block Flash Memory" Intel Datasheet
18 * - Order Number: 290644-005
19 * - January 2000
20 *
21 * [2] MTD internal API documentation
22 * - http://www.linux-mtd.infradead.org/tech/
23 *
24 * Limitations:
25 *
26 * Even though this driver is written for 3 Volt Fast Boot
27 * Block Flash Memory, it is rather specific to LART. With
28 * Minor modifications, notably the without data/address line
29 * mangling and different bus settings, etc. it should be
30 * trivial to adapt to other platforms.
31 *
32 * If somebody would sponsor me a different board, I'll
33 * adapt the driver (:
34 */
35
36/* debugging */
37//#define LART_DEBUG
38
39/* partition support */
40#define HAVE_PARTITIONS
41
42#include <linux/kernel.h>
43#include <linux/module.h>
44#include <linux/types.h>
45#include <linux/init.h>
46#include <linux/errno.h>
47#include <linux/mtd/mtd.h>
48#ifdef HAVE_PARTITIONS
49#include <linux/mtd/partitions.h>
50#endif
51
52#ifndef CONFIG_SA1100_LART
53#error This is for LART architecture only
54#endif
55
56static char module_name[] = "lart";
57
58/*
59 * These values is specific to 28Fxxxx3 flash memory.
60 * See section 2.3.1 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet
61 */
62#define FLASH_BLOCKSIZE_PARAM (4096 * BUSWIDTH)
63#define FLASH_NUMBLOCKS_16m_PARAM 8
64#define FLASH_NUMBLOCKS_8m_PARAM 8
65
66/*
67 * These values is specific to 28Fxxxx3 flash memory.
68 * See section 2.3.2 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet
69 */
70#define FLASH_BLOCKSIZE_MAIN (32768 * BUSWIDTH)
71#define FLASH_NUMBLOCKS_16m_MAIN 31
72#define FLASH_NUMBLOCKS_8m_MAIN 15
73
74/*
75 * These values are specific to LART
76 */
77
78/* general */
79#define BUSWIDTH 4 /* don't change this - a lot of the code _will_ break if you change this */
80#define FLASH_OFFSET 0xe8000000 /* see linux/arch/arm/mach-sa1100/lart.c */
81
82/* blob */
83#define NUM_BLOB_BLOCKS FLASH_NUMBLOCKS_16m_PARAM
84#define BLOB_START 0x00000000
85#define BLOB_LEN (NUM_BLOB_BLOCKS * FLASH_BLOCKSIZE_PARAM)
86
87/* kernel */
88#define NUM_KERNEL_BLOCKS 7
89#define KERNEL_START (BLOB_START + BLOB_LEN)
90#define KERNEL_LEN (NUM_KERNEL_BLOCKS * FLASH_BLOCKSIZE_MAIN)
91
92/* initial ramdisk */
93#define NUM_INITRD_BLOCKS 24
94#define INITRD_START (KERNEL_START + KERNEL_LEN)
95#define INITRD_LEN (NUM_INITRD_BLOCKS * FLASH_BLOCKSIZE_MAIN)
96
97/*
98 * See section 4.0 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet
99 */
100#define READ_ARRAY 0x00FF00FF /* Read Array/Reset */
101#define READ_ID_CODES 0x00900090 /* Read Identifier Codes */
102#define ERASE_SETUP 0x00200020 /* Block Erase */
103#define ERASE_CONFIRM 0x00D000D0 /* Block Erase and Program Resume */
104#define PGM_SETUP 0x00400040 /* Program */
105#define STATUS_READ 0x00700070 /* Read Status Register */
106#define STATUS_CLEAR 0x00500050 /* Clear Status Register */
107#define STATUS_BUSY 0x00800080 /* Write State Machine Status (WSMS) */
108#define STATUS_ERASE_ERR 0x00200020 /* Erase Status (ES) */
109#define STATUS_PGM_ERR 0x00100010 /* Program Status (PS) */
110
111/*
112 * See section 4.2 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet
113 */
114#define FLASH_MANUFACTURER 0x00890089
115#define FLASH_DEVICE_8mbit_TOP 0x88f188f1
116#define FLASH_DEVICE_8mbit_BOTTOM 0x88f288f2
117#define FLASH_DEVICE_16mbit_TOP 0x88f388f3
118#define FLASH_DEVICE_16mbit_BOTTOM 0x88f488f4
119
120/***************************************************************************************************/
121
122/*
123 * The data line mapping on LART is as follows:
124 *
125 * U2 CPU | U3 CPU
126 * -------------------
127 * 0 20 | 0 12
128 * 1 22 | 1 14
129 * 2 19 | 2 11
130 * 3 17 | 3 9
131 * 4 24 | 4 0
132 * 5 26 | 5 2
133 * 6 31 | 6 7
134 * 7 29 | 7 5
135 * 8 21 | 8 13
136 * 9 23 | 9 15
137 * 10 18 | 10 10
138 * 11 16 | 11 8
139 * 12 25 | 12 1
140 * 13 27 | 13 3
141 * 14 30 | 14 6
142 * 15 28 | 15 4
143 */
144
145/* Mangle data (x) */
146#define DATA_TO_FLASH(x) \
147 ( \
148 (((x) & 0x08009000) >> 11) + \
149 (((x) & 0x00002000) >> 10) + \
150 (((x) & 0x04004000) >> 8) + \
151 (((x) & 0x00000010) >> 4) + \
152 (((x) & 0x91000820) >> 3) + \
153 (((x) & 0x22080080) >> 2) + \
154 ((x) & 0x40000400) + \
155 (((x) & 0x00040040) << 1) + \
156 (((x) & 0x00110000) << 4) + \
157 (((x) & 0x00220100) << 5) + \
158 (((x) & 0x00800208) << 6) + \
159 (((x) & 0x00400004) << 9) + \
160 (((x) & 0x00000001) << 12) + \
161 (((x) & 0x00000002) << 13) \
162 )
163
164/* Unmangle data (x) */
165#define FLASH_TO_DATA(x) \
166 ( \
167 (((x) & 0x00010012) << 11) + \
168 (((x) & 0x00000008) << 10) + \
169 (((x) & 0x00040040) << 8) + \
170 (((x) & 0x00000001) << 4) + \
171 (((x) & 0x12200104) << 3) + \
172 (((x) & 0x08820020) << 2) + \
173 ((x) & 0x40000400) + \
174 (((x) & 0x00080080) >> 1) + \
175 (((x) & 0x01100000) >> 4) + \
176 (((x) & 0x04402000) >> 5) + \
177 (((x) & 0x20008200) >> 6) + \
178 (((x) & 0x80000800) >> 9) + \
179 (((x) & 0x00001000) >> 12) + \
180 (((x) & 0x00004000) >> 13) \
181 )
182
183/*
184 * The address line mapping on LART is as follows:
185 *
186 * U3 CPU | U2 CPU
187 * -------------------
188 * 0 2 | 0 2
189 * 1 3 | 1 3
190 * 2 9 | 2 9
191 * 3 13 | 3 8
192 * 4 8 | 4 7
193 * 5 12 | 5 6
194 * 6 11 | 6 5
195 * 7 10 | 7 4
196 * 8 4 | 8 10
197 * 9 5 | 9 11
198 * 10 6 | 10 12
199 * 11 7 | 11 13
200 *
201 * BOOT BLOCK BOUNDARY
202 *
203 * 12 15 | 12 15
204 * 13 14 | 13 14
205 * 14 16 | 14 16
206 *
207 * MAIN BLOCK BOUNDARY
208 *
209 * 15 17 | 15 18
210 * 16 18 | 16 17
211 * 17 20 | 17 20
212 * 18 19 | 18 19
213 * 19 21 | 19 21
214 *
215 * As we can see from above, the addresses aren't mangled across
216 * block boundaries, so we don't need to worry about address
217 * translations except for sending/reading commands during
218 * initialization
219 */
220
221/* Mangle address (x) on chip U2 */
222#define ADDR_TO_FLASH_U2(x) \
223 ( \
224 (((x) & 0x00000f00) >> 4) + \
225 (((x) & 0x00042000) << 1) + \
226 (((x) & 0x0009c003) << 2) + \
227 (((x) & 0x00021080) << 3) + \
228 (((x) & 0x00000010) << 4) + \
229 (((x) & 0x00000040) << 5) + \
230 (((x) & 0x00000024) << 7) + \
231 (((x) & 0x00000008) << 10) \
232 )
233
234/* Unmangle address (x) on chip U2 */
235#define FLASH_U2_TO_ADDR(x) \
236 ( \
237 (((x) << 4) & 0x00000f00) + \
238 (((x) >> 1) & 0x00042000) + \
239 (((x) >> 2) & 0x0009c003) + \
240 (((x) >> 3) & 0x00021080) + \
241 (((x) >> 4) & 0x00000010) + \
242 (((x) >> 5) & 0x00000040) + \
243 (((x) >> 7) & 0x00000024) + \
244 (((x) >> 10) & 0x00000008) \
245 )
246
247/* Mangle address (x) on chip U3 */
248#define ADDR_TO_FLASH_U3(x) \
249 ( \
250 (((x) & 0x00000080) >> 3) + \
251 (((x) & 0x00000040) >> 1) + \
252 (((x) & 0x00052020) << 1) + \
253 (((x) & 0x00084f03) << 2) + \
254 (((x) & 0x00029010) << 3) + \
255 (((x) & 0x00000008) << 5) + \
256 (((x) & 0x00000004) << 7) \
257 )
258
259/* Unmangle address (x) on chip U3 */
260#define FLASH_U3_TO_ADDR(x) \
261 ( \
262 (((x) << 3) & 0x00000080) + \
263 (((x) << 1) & 0x00000040) + \
264 (((x) >> 1) & 0x00052020) + \
265 (((x) >> 2) & 0x00084f03) + \
266 (((x) >> 3) & 0x00029010) + \
267 (((x) >> 5) & 0x00000008) + \
268 (((x) >> 7) & 0x00000004) \
269 )
270
271/***************************************************************************************************/
272
273static __u8 read8 (__u32 offset)
274{
275 volatile __u8 *data = (__u8 *) (FLASH_OFFSET + offset);
276#ifdef LART_DEBUG
277 printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.2x\n",__FUNCTION__,offset,*data);
278#endif
279 return (*data);
280}
281
282static __u32 read32 (__u32 offset)
283{
284 volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset);
285#ifdef LART_DEBUG
286 printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.8x\n",__FUNCTION__,offset,*data);
287#endif
288 return (*data);
289}
290
291static void write32 (__u32 x,__u32 offset)
292{
293 volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset);
294 *data = x;
295#ifdef LART_DEBUG
296 printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n",__FUNCTION__,offset,*data);
297#endif
298}
299
300/***************************************************************************************************/
301
302/*
303 * Probe for 16mbit flash memory on a LART board without doing
304 * too much damage. Since we need to write 1 dword to memory,
305 * we're f**cked if this happens to be DRAM since we can't
306 * restore the memory (otherwise we might exit Read Array mode).
307 *
308 * Returns 1 if we found 16mbit flash memory on LART, 0 otherwise.
309 */
310static int flash_probe (void)
311{
312 __u32 manufacturer,devtype;
313
314 /* setup "Read Identifier Codes" mode */
315 write32 (DATA_TO_FLASH (READ_ID_CODES),0x00000000);
316
317 /* probe U2. U2/U3 returns the same data since the first 3
318 * address lines is mangled in the same way */
319 manufacturer = FLASH_TO_DATA (read32 (ADDR_TO_FLASH_U2 (0x00000000)));
320 devtype = FLASH_TO_DATA (read32 (ADDR_TO_FLASH_U2 (0x00000001)));
321
322 /* put the flash back into command mode */
323 write32 (DATA_TO_FLASH (READ_ARRAY),0x00000000);
324
325 return (manufacturer == FLASH_MANUFACTURER && (devtype == FLASH_DEVICE_16mbit_TOP || FLASH_DEVICE_16mbit_BOTTOM));
326}
327
328/*
329 * Erase one block of flash memory at offset ``offset'' which is any
330 * address within the block which should be erased.
331 *
332 * Returns 1 if successful, 0 otherwise.
333 */
334static inline int erase_block (__u32 offset)
335{
336 __u32 status;
337
338#ifdef LART_DEBUG
339 printk (KERN_DEBUG "%s(): 0x%.8x\n",__FUNCTION__,offset);
340#endif
341
342 /* erase and confirm */
343 write32 (DATA_TO_FLASH (ERASE_SETUP),offset);
344 write32 (DATA_TO_FLASH (ERASE_CONFIRM),offset);
345
346 /* wait for block erase to finish */
347 do
348 {
349 write32 (DATA_TO_FLASH (STATUS_READ),offset);
350 status = FLASH_TO_DATA (read32 (offset));
351 }
352 while ((~status & STATUS_BUSY) != 0);
353
354 /* put the flash back into command mode */
355 write32 (DATA_TO_FLASH (READ_ARRAY),offset);
356
357 /* was the erase successfull? */
358 if ((status & STATUS_ERASE_ERR))
359 {
360 printk (KERN_WARNING "%s: erase error at address 0x%.8x.\n",module_name,offset);
361 return (0);
362 }
363
364 return (1);
365}
366
367static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
368{
369 __u32 addr,len;
370 int i,first;
371
372#ifdef LART_DEBUG
373 printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n",__FUNCTION__,instr->addr,instr->len);
374#endif
375
376 /* sanity checks */
377 if (instr->addr + instr->len > mtd->size) return (-EINVAL);
378
379 /*
380 * check that both start and end of the requested erase are
381 * aligned with the erasesize at the appropriate addresses.
382 *
383 * skip all erase regions which are ended before the start of
384 * the requested erase. Actually, to save on the calculations,
385 * we skip to the first erase region which starts after the
386 * start of the requested erase, and then go back one.
387 */
388 for (i = 0; i < mtd->numeraseregions && instr->addr >= mtd->eraseregions[i].offset; i++) ;
389 i--;
390
391 /*
392 * ok, now i is pointing at the erase region in which this
393 * erase request starts. Check the start of the requested
394 * erase range is aligned with the erase size which is in
395 * effect here.
396 */
397 if (instr->addr & (mtd->eraseregions[i].erasesize - 1)) return (-EINVAL);
398
399 /* Remember the erase region we start on */
400 first = i;
401
402 /*
403 * next, check that the end of the requested erase is aligned
404 * with the erase region at that address.
405 *
406 * as before, drop back one to point at the region in which
407 * the address actually falls
408 */
409 for (; i < mtd->numeraseregions && instr->addr + instr->len >= mtd->eraseregions[i].offset; i++) ;
410 i--;
411
412 /* is the end aligned on a block boundary? */
413 if ((instr->addr + instr->len) & (mtd->eraseregions[i].erasesize - 1)) return (-EINVAL);
414
415 addr = instr->addr;
416 len = instr->len;
417
418 i = first;
419
420 /* now erase those blocks */
421 while (len)
422 {
423 if (!erase_block (addr))
424 {
425 instr->state = MTD_ERASE_FAILED;
426 return (-EIO);
427 }
428
429 addr += mtd->eraseregions[i].erasesize;
430 len -= mtd->eraseregions[i].erasesize;
431
432 if (addr == mtd->eraseregions[i].offset + (mtd->eraseregions[i].erasesize * mtd->eraseregions[i].numblocks)) i++;
433 }
434
435 instr->state = MTD_ERASE_DONE;
436 mtd_erase_callback(instr);
437
438 return (0);
439}
440
441static int flash_read (struct mtd_info *mtd,loff_t from,size_t len,size_t *retlen,u_char *buf)
442{
443#ifdef LART_DEBUG
444 printk (KERN_DEBUG "%s(from = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) from,len);
445#endif
446
447 /* sanity checks */
448 if (!len) return (0);
449 if (from + len > mtd->size) return (-EINVAL);
450
451 /* we always read len bytes */
452 *retlen = len;
453
454 /* first, we read bytes until we reach a dword boundary */
455 if (from & (BUSWIDTH - 1))
456 {
457 int gap = BUSWIDTH - (from & (BUSWIDTH - 1));
458
459 while (len && gap--) *buf++ = read8 (from++), len--;
460 }
461
462 /* now we read dwords until we reach a non-dword boundary */
463 while (len >= BUSWIDTH)
464 {
465 *((__u32 *) buf) = read32 (from);
466
467 buf += BUSWIDTH;
468 from += BUSWIDTH;
469 len -= BUSWIDTH;
470 }
471
472 /* top up the last unaligned bytes */
473 if (len & (BUSWIDTH - 1))
474 while (len--) *buf++ = read8 (from++);
475
476 return (0);
477}
478
479/*
480 * Write one dword ``x'' to flash memory at offset ``offset''. ``offset''
481 * must be 32 bits, i.e. it must be on a dword boundary.
482 *
483 * Returns 1 if successful, 0 otherwise.
484 */
485static inline int write_dword (__u32 offset,__u32 x)
486{
487 __u32 status;
488
489#ifdef LART_DEBUG
490 printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n",__FUNCTION__,offset,x);
491#endif
492
493 /* setup writing */
494 write32 (DATA_TO_FLASH (PGM_SETUP),offset);
495
496 /* write the data */
497 write32 (x,offset);
498
499 /* wait for the write to finish */
500 do
501 {
502 write32 (DATA_TO_FLASH (STATUS_READ),offset);
503 status = FLASH_TO_DATA (read32 (offset));
504 }
505 while ((~status & STATUS_BUSY) != 0);
506
507 /* put the flash back into command mode */
508 write32 (DATA_TO_FLASH (READ_ARRAY),offset);
509
510 /* was the write successfull? */
511 if ((status & STATUS_PGM_ERR) || read32 (offset) != x)
512 {
513 printk (KERN_WARNING "%s: write error at address 0x%.8x.\n",module_name,offset);
514 return (0);
515 }
516
517 return (1);
518}
519
520static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf)
521{
522 __u8 tmp[4];
523 int i,n;
524
525#ifdef LART_DEBUG
526 printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) to,len);
527#endif
528
529 *retlen = 0;
530
531 /* sanity checks */
532 if (!len) return (0);
533 if (to + len > mtd->size) return (-EINVAL);
534
535 /* first, we write a 0xFF.... padded byte until we reach a dword boundary */
536 if (to & (BUSWIDTH - 1))
537 {
538 __u32 aligned = to & ~(BUSWIDTH - 1);
539 int gap = to - aligned;
540
541 i = n = 0;
542
543 while (gap--) tmp[i++] = 0xFF;
544 while (len && i < BUSWIDTH) tmp[i++] = buf[n++], len--;
545 while (i < BUSWIDTH) tmp[i++] = 0xFF;
546
547 if (!write_dword (aligned,*((__u32 *) tmp))) return (-EIO);
548
549 to += n;
550 buf += n;
551 *retlen += n;
552 }
553
554 /* now we write dwords until we reach a non-dword boundary */
555 while (len >= BUSWIDTH)
556 {
557 if (!write_dword (to,*((__u32 *) buf))) return (-EIO);
558
559 to += BUSWIDTH;
560 buf += BUSWIDTH;
561 *retlen += BUSWIDTH;
562 len -= BUSWIDTH;
563 }
564
565 /* top up the last unaligned bytes, padded with 0xFF.... */
566 if (len & (BUSWIDTH - 1))
567 {
568 i = n = 0;
569
570 while (len--) tmp[i++] = buf[n++];
571 while (i < BUSWIDTH) tmp[i++] = 0xFF;
572
573 if (!write_dword (to,*((__u32 *) tmp))) return (-EIO);
574
575 *retlen += n;
576 }
577
578 return (0);
579}
580
581/***************************************************************************************************/
582
583#define NB_OF(x) (sizeof (x) / sizeof (x[0]))
584
585static struct mtd_info mtd;
586
587static struct mtd_erase_region_info erase_regions[] = {
588 /* parameter blocks */
589 {
590 .offset = 0x00000000,
591 .erasesize = FLASH_BLOCKSIZE_PARAM,
592 .numblocks = FLASH_NUMBLOCKS_16m_PARAM,
593 },
594 /* main blocks */
595 {
596 .offset = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM,
597 .erasesize = FLASH_BLOCKSIZE_MAIN,
598 .numblocks = FLASH_NUMBLOCKS_16m_MAIN,
599 }
600};
601
602#ifdef HAVE_PARTITIONS
603static struct mtd_partition lart_partitions[] = {
604 /* blob */
605 {
606 .name = "blob",
607 .offset = BLOB_START,
608 .size = BLOB_LEN,
609 },
610 /* kernel */
611 {
612 .name = "kernel",
613 .offset = KERNEL_START, /* MTDPART_OFS_APPEND */
614 .size = KERNEL_LEN,
615 },
616 /* initial ramdisk / file system */
617 {
618 .name = "file system",
619 .offset = INITRD_START, /* MTDPART_OFS_APPEND */
620 .size = INITRD_LEN, /* MTDPART_SIZ_FULL */
621 }
622};
623#endif
624
625int __init lart_flash_init (void)
626{
627 int result;
628 memset (&mtd,0,sizeof (mtd));
629 printk ("MTD driver for LART. Written by Abraham vd Merwe <abraham@2d3d.co.za>\n");
630 printk ("%s: Probing for 28F160x3 flash on LART...\n",module_name);
631 if (!flash_probe ())
632 {
633 printk (KERN_WARNING "%s: Found no LART compatible flash device\n",module_name);
634 return (-ENXIO);
635 }
636 printk ("%s: This looks like a LART board to me.\n",module_name);
637 mtd.name = module_name;
638 mtd.type = MTD_NORFLASH;
639 mtd.flags = MTD_CAP_NORFLASH;
640 mtd.size = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM + FLASH_BLOCKSIZE_MAIN * FLASH_NUMBLOCKS_16m_MAIN;
641 mtd.erasesize = FLASH_BLOCKSIZE_MAIN;
642 mtd.numeraseregions = NB_OF (erase_regions);
643 mtd.eraseregions = erase_regions;
644 mtd.erase = flash_erase;
645 mtd.read = flash_read;
646 mtd.write = flash_write;
647 mtd.owner = THIS_MODULE;
648
649#ifdef LART_DEBUG
650 printk (KERN_DEBUG
651 "mtd.name = %s\n"
652 "mtd.size = 0x%.8x (%uM)\n"
653 "mtd.erasesize = 0x%.8x (%uK)\n"
654 "mtd.numeraseregions = %d\n",
655 mtd.name,
656 mtd.size,mtd.size / (1024*1024),
657 mtd.erasesize,mtd.erasesize / 1024,
658 mtd.numeraseregions);
659
660 if (mtd.numeraseregions)
661 for (result = 0; result < mtd.numeraseregions; result++)
662 printk (KERN_DEBUG
663 "\n\n"
664 "mtd.eraseregions[%d].offset = 0x%.8x\n"
665 "mtd.eraseregions[%d].erasesize = 0x%.8x (%uK)\n"
666 "mtd.eraseregions[%d].numblocks = %d\n",
667 result,mtd.eraseregions[result].offset,
668 result,mtd.eraseregions[result].erasesize,mtd.eraseregions[result].erasesize / 1024,
669 result,mtd.eraseregions[result].numblocks);
670
671#ifdef HAVE_PARTITIONS
672 printk ("\npartitions = %d\n",NB_OF (lart_partitions));
673
674 for (result = 0; result < NB_OF (lart_partitions); result++)
675 printk (KERN_DEBUG
676 "\n\n"
677 "lart_partitions[%d].name = %s\n"
678 "lart_partitions[%d].offset = 0x%.8x\n"
679 "lart_partitions[%d].size = 0x%.8x (%uK)\n",
680 result,lart_partitions[result].name,
681 result,lart_partitions[result].offset,
682 result,lart_partitions[result].size,lart_partitions[result].size / 1024);
683#endif
684#endif
685
686#ifndef HAVE_PARTITIONS
687 result = add_mtd_device (&mtd);
688#else
689 result = add_mtd_partitions (&mtd,lart_partitions,NB_OF (lart_partitions));
690#endif
691
692 return (result);
693}
694
695void __exit lart_flash_exit (void)
696{
697#ifndef HAVE_PARTITIONS
698 del_mtd_device (&mtd);
699#else
700 del_mtd_partitions (&mtd);
701#endif
702}
703
704module_init (lart_flash_init);
705module_exit (lart_flash_exit);
706
707MODULE_LICENSE("GPL");
708MODULE_AUTHOR("Abraham vd Merwe <abraham@2d3d.co.za>");
709MODULE_DESCRIPTION("MTD driver for Intel 28F160F3 on LART board");
710
711
diff --git a/drivers/mtd/devices/ms02-nv.c b/drivers/mtd/devices/ms02-nv.c
new file mode 100644
index 000000000000..380ff08d29e4
--- /dev/null
+++ b/drivers/mtd/devices/ms02-nv.c
@@ -0,0 +1,326 @@
1/*
2 * Copyright (c) 2001 Maciej W. Rozycki
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * $Id: ms02-nv.c,v 1.8 2005/01/05 18:05:12 dwmw2 Exp $
10 */
11
12#include <linux/init.h>
13#include <linux/ioport.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/mtd/mtd.h>
17#include <linux/slab.h>
18#include <linux/types.h>
19
20#include <asm/addrspace.h>
21#include <asm/bootinfo.h>
22#include <asm/dec/ioasic_addrs.h>
23#include <asm/dec/kn02.h>
24#include <asm/dec/kn03.h>
25#include <asm/io.h>
26#include <asm/paccess.h>
27
28#include "ms02-nv.h"
29
30
31static char version[] __initdata =
32 "ms02-nv.c: v.1.0.0 13 Aug 2001 Maciej W. Rozycki.\n";
33
34MODULE_AUTHOR("Maciej W. Rozycki <macro@linux-mips.org>");
35MODULE_DESCRIPTION("DEC MS02-NV NVRAM module driver");
36MODULE_LICENSE("GPL");
37
38
39/*
40 * Addresses we probe for an MS02-NV at. Modules may be located
41 * at any 8MiB boundary within a 0MiB up to 112MiB range or at any 32MiB
42 * boundary within a 0MiB up to 448MiB range. We don't support a module
43 * at 0MiB, though.
44 */
45static ulong ms02nv_addrs[] __initdata = {
46 0x07000000, 0x06800000, 0x06000000, 0x05800000, 0x05000000,
47 0x04800000, 0x04000000, 0x03800000, 0x03000000, 0x02800000,
48 0x02000000, 0x01800000, 0x01000000, 0x00800000
49};
50
51static const char ms02nv_name[] = "DEC MS02-NV NVRAM";
52static const char ms02nv_res_diag_ram[] = "Diagnostic RAM";
53static const char ms02nv_res_user_ram[] = "General-purpose RAM";
54static const char ms02nv_res_csr[] = "Control and status register";
55
56static struct mtd_info *root_ms02nv_mtd;
57
58
59static int ms02nv_read(struct mtd_info *mtd, loff_t from,
60 size_t len, size_t *retlen, u_char *buf)
61{
62 struct ms02nv_private *mp = mtd->priv;
63
64 if (from + len > mtd->size)
65 return -EINVAL;
66
67 memcpy(buf, mp->uaddr + from, len);
68 *retlen = len;
69
70 return 0;
71}
72
73static int ms02nv_write(struct mtd_info *mtd, loff_t to,
74 size_t len, size_t *retlen, const u_char *buf)
75{
76 struct ms02nv_private *mp = mtd->priv;
77
78 if (to + len > mtd->size)
79 return -EINVAL;
80
81 memcpy(mp->uaddr + to, buf, len);
82 *retlen = len;
83
84 return 0;
85}
86
87
88static inline uint ms02nv_probe_one(ulong addr)
89{
90 ms02nv_uint *ms02nv_diagp;
91 ms02nv_uint *ms02nv_magicp;
92 uint ms02nv_diag;
93 uint ms02nv_magic;
94 size_t size;
95
96 int err;
97
98 /*
99 * The firmware writes MS02NV_ID at MS02NV_MAGIC and also
100 * a diagnostic status at MS02NV_DIAG.
101 */
102 ms02nv_diagp = (ms02nv_uint *)(KSEG1ADDR(addr + MS02NV_DIAG));
103 ms02nv_magicp = (ms02nv_uint *)(KSEG1ADDR(addr + MS02NV_MAGIC));
104 err = get_dbe(ms02nv_magic, ms02nv_magicp);
105 if (err)
106 return 0;
107 if (ms02nv_magic != MS02NV_ID)
108 return 0;
109
110 ms02nv_diag = *ms02nv_diagp;
111 size = (ms02nv_diag & MS02NV_DIAG_SIZE_MASK) << MS02NV_DIAG_SIZE_SHIFT;
112 if (size > MS02NV_CSR)
113 size = MS02NV_CSR;
114
115 return size;
116}
117
118static int __init ms02nv_init_one(ulong addr)
119{
120 struct mtd_info *mtd;
121 struct ms02nv_private *mp;
122 struct resource *mod_res;
123 struct resource *diag_res;
124 struct resource *user_res;
125 struct resource *csr_res;
126 ulong fixaddr;
127 size_t size, fixsize;
128
129 static int version_printed;
130
131 int ret = -ENODEV;
132
133 /* The module decodes 8MiB of address space. */
134 mod_res = kmalloc(sizeof(*mod_res), GFP_KERNEL);
135 if (!mod_res)
136 return -ENOMEM;
137
138 memset(mod_res, 0, sizeof(*mod_res));
139 mod_res->name = ms02nv_name;
140 mod_res->start = addr;
141 mod_res->end = addr + MS02NV_SLOT_SIZE - 1;
142 mod_res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
143 if (request_resource(&iomem_resource, mod_res) < 0)
144 goto err_out_mod_res;
145
146 size = ms02nv_probe_one(addr);
147 if (!size)
148 goto err_out_mod_res_rel;
149
150 if (!version_printed) {
151 printk(KERN_INFO "%s", version);
152 version_printed = 1;
153 }
154
155 ret = -ENOMEM;
156 mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
157 if (!mtd)
158 goto err_out_mod_res_rel;
159 memset(mtd, 0, sizeof(*mtd));
160 mp = kmalloc(sizeof(*mp), GFP_KERNEL);
161 if (!mp)
162 goto err_out_mtd;
163 memset(mp, 0, sizeof(*mp));
164
165 mtd->priv = mp;
166 mp->resource.module = mod_res;
167
168 /* Firmware's diagnostic NVRAM area. */
169 diag_res = kmalloc(sizeof(*diag_res), GFP_KERNEL);
170 if (!diag_res)
171 goto err_out_mp;
172
173 memset(diag_res, 0, sizeof(*diag_res));
174 diag_res->name = ms02nv_res_diag_ram;
175 diag_res->start = addr;
176 diag_res->end = addr + MS02NV_RAM - 1;
177 diag_res->flags = IORESOURCE_BUSY;
178 request_resource(mod_res, diag_res);
179
180 mp->resource.diag_ram = diag_res;
181
182 /* User-available general-purpose NVRAM area. */
183 user_res = kmalloc(sizeof(*user_res), GFP_KERNEL);
184 if (!user_res)
185 goto err_out_diag_res;
186
187 memset(user_res, 0, sizeof(*user_res));
188 user_res->name = ms02nv_res_user_ram;
189 user_res->start = addr + MS02NV_RAM;
190 user_res->end = addr + size - 1;
191 user_res->flags = IORESOURCE_BUSY;
192 request_resource(mod_res, user_res);
193
194 mp->resource.user_ram = user_res;
195
196 /* Control and status register. */
197 csr_res = kmalloc(sizeof(*csr_res), GFP_KERNEL);
198 if (!csr_res)
199 goto err_out_user_res;
200
201 memset(csr_res, 0, sizeof(*csr_res));
202 csr_res->name = ms02nv_res_csr;
203 csr_res->start = addr + MS02NV_CSR;
204 csr_res->end = addr + MS02NV_CSR + 3;
205 csr_res->flags = IORESOURCE_BUSY;
206 request_resource(mod_res, csr_res);
207
208 mp->resource.csr = csr_res;
209
210 mp->addr = phys_to_virt(addr);
211 mp->size = size;
212
213 /*
214 * Hide the firmware's diagnostic area. It may get destroyed
215 * upon a reboot. Take paging into account for mapping support.
216 */
217 fixaddr = (addr + MS02NV_RAM + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
218 fixsize = (size - (fixaddr - addr)) & ~(PAGE_SIZE - 1);
219 mp->uaddr = phys_to_virt(fixaddr);
220
221 mtd->type = MTD_RAM;
222 mtd->flags = MTD_CAP_RAM | MTD_XIP;
223 mtd->size = fixsize;
224 mtd->name = (char *)ms02nv_name;
225 mtd->owner = THIS_MODULE;
226 mtd->read = ms02nv_read;
227 mtd->write = ms02nv_write;
228
229 ret = -EIO;
230 if (add_mtd_device(mtd)) {
231 printk(KERN_ERR
232 "ms02-nv: Unable to register MTD device, aborting!\n");
233 goto err_out_csr_res;
234 }
235
236 printk(KERN_INFO "mtd%d: %s at 0x%08lx, size %uMiB.\n",
237 mtd->index, ms02nv_name, addr, size >> 20);
238
239 mp->next = root_ms02nv_mtd;
240 root_ms02nv_mtd = mtd;
241
242 return 0;
243
244
245err_out_csr_res:
246 release_resource(csr_res);
247 kfree(csr_res);
248err_out_user_res:
249 release_resource(user_res);
250 kfree(user_res);
251err_out_diag_res:
252 release_resource(diag_res);
253 kfree(diag_res);
254err_out_mp:
255 kfree(mp);
256err_out_mtd:
257 kfree(mtd);
258err_out_mod_res_rel:
259 release_resource(mod_res);
260err_out_mod_res:
261 kfree(mod_res);
262 return ret;
263}
264
265static void __exit ms02nv_remove_one(void)
266{
267 struct mtd_info *mtd = root_ms02nv_mtd;
268 struct ms02nv_private *mp = mtd->priv;
269
270 root_ms02nv_mtd = mp->next;
271
272 del_mtd_device(mtd);
273
274 release_resource(mp->resource.csr);
275 kfree(mp->resource.csr);
276 release_resource(mp->resource.user_ram);
277 kfree(mp->resource.user_ram);
278 release_resource(mp->resource.diag_ram);
279 kfree(mp->resource.diag_ram);
280 release_resource(mp->resource.module);
281 kfree(mp->resource.module);
282 kfree(mp);
283 kfree(mtd);
284}
285
286
287static int __init ms02nv_init(void)
288{
289 volatile u32 *csr;
290 uint stride = 0;
291 int count = 0;
292 int i;
293
294 switch (mips_machtype) {
295 case MACH_DS5000_200:
296 csr = (volatile u32 *)KN02_CSR_BASE;
297 if (*csr & KN02_CSR_BNK32M)
298 stride = 2;
299 break;
300 case MACH_DS5000_2X0:
301 case MACH_DS5900:
302 csr = (volatile u32 *)KN03_MCR_BASE;
303 if (*csr & KN03_MCR_BNK32M)
304 stride = 2;
305 break;
306 default:
307 return -ENODEV;
308 break;
309 }
310
311 for (i = 0; i < (sizeof(ms02nv_addrs) / sizeof(*ms02nv_addrs)); i++)
312 if (!ms02nv_init_one(ms02nv_addrs[i] << stride))
313 count++;
314
315 return (count > 0) ? 0 : -ENODEV;
316}
317
318static void __exit ms02nv_cleanup(void)
319{
320 while (root_ms02nv_mtd)
321 ms02nv_remove_one();
322}
323
324
325module_init(ms02nv_init);
326module_exit(ms02nv_cleanup);
diff --git a/drivers/mtd/devices/ms02-nv.h b/drivers/mtd/devices/ms02-nv.h
new file mode 100644
index 000000000000..8a6eef7cfee3
--- /dev/null
+++ b/drivers/mtd/devices/ms02-nv.h
@@ -0,0 +1,107 @@
1/*
2 * Copyright (c) 2001, 2003 Maciej W. Rozycki
3 *
4 * DEC MS02-NV (54-20948-01) battery backed-up NVRAM module for
5 * DECstation/DECsystem 5000/2x0 and DECsystem 5900 and 5900/260
6 * systems.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 *
13 * $Id: ms02-nv.h,v 1.3 2003/08/19 09:25:36 dwmw2 Exp $
14 */
15
16#include <linux/ioport.h>
17#include <linux/mtd/mtd.h>
18
19/*
20 * Addresses are decoded as follows:
21 *
22 * 0x000000 - 0x3fffff SRAM
23 * 0x400000 - 0x7fffff CSR
24 *
25 * Within the SRAM area the following ranges are forced by the system
26 * firmware:
27 *
28 * 0x000000 - 0x0003ff diagnostic area, destroyed upon a reboot
29 * 0x000400 - ENDofRAM storage area, available to operating systems
30 *
31 * but we can't really use the available area right from 0x000400 as
32 * the first word is used by the firmware as a status flag passed
33 * from an operating system. If anything but the valid data magic
34 * ID value is found, the firmware considers the SRAM clean, i.e.
35 * containing no valid data, and disables the battery resulting in
36 * data being erased as soon as power is switched off. So the choice
37 * for the start address of the user-available is 0x001000 which is
38 * nicely page aligned. The area between 0x000404 and 0x000fff may
39 * be used by the driver for own needs.
40 *
41 * The diagnostic area defines two status words to be read by an
42 * operating system, a magic ID to distinguish a MS02-NV board from
43 * anything else and a status information providing results of tests
44 * as well as the size of SRAM available, which can be 1MiB or 2MiB
45 * (that's what the firmware handles; no idea if 2MiB modules ever
46 * existed).
47 *
48 * The firmware only handles the MS02-NV board if installed in the
49 * last (15th) slot, so for any other location the status information
50 * stored in the SRAM cannot be relied upon. But from the hardware
51 * point of view there is no problem using up to 14 such boards in a
52 * system -- only the 1st slot needs to be filled with a DRAM module.
53 * The MS02-NV board is ECC-protected, like other MS02 memory boards.
54 *
55 * The state of the battery as provided by the CSR is reflected on
56 * the two onboard LEDs. When facing the battery side of the board,
57 * with the LEDs at the top left and the battery at the bottom right
58 * (i.e. looking from the back side of the system box), their meaning
59 * is as follows (the system has to be powered on):
60 *
61 * left LED battery disable status: lit = enabled
62 * right LED battery condition status: lit = OK
63 */
64
65/* MS02-NV iomem register offsets. */
66#define MS02NV_CSR 0x400000 /* control & status register */
67
68/* MS02-NV CSR status bits. */
69#define MS02NV_CSR_BATT_OK 0x01 /* battery OK */
70#define MS02NV_CSR_BATT_OFF 0x02 /* battery disabled */
71
72
73/* MS02-NV memory offsets. */
74#define MS02NV_DIAG 0x0003f8 /* diagnostic status */
75#define MS02NV_MAGIC 0x0003fc /* MS02-NV magic ID */
76#define MS02NV_VALID 0x000400 /* valid data magic ID */
77#define MS02NV_RAM 0x001000 /* user-exposed RAM start */
78
79/* MS02-NV diagnostic status bits. */
80#define MS02NV_DIAG_TEST 0x01 /* SRAM test done (?) */
81#define MS02NV_DIAG_RO 0x02 /* SRAM r/o test done */
82#define MS02NV_DIAG_RW 0x04 /* SRAM r/w test done */
83#define MS02NV_DIAG_FAIL 0x08 /* SRAM test failed */
84#define MS02NV_DIAG_SIZE_MASK 0xf0 /* SRAM size mask */
85#define MS02NV_DIAG_SIZE_SHIFT 0x10 /* SRAM size shift (left) */
86
87/* MS02-NV general constants. */
88#define MS02NV_ID 0x03021966 /* MS02-NV magic ID value */
89#define MS02NV_VALID_ID 0xbd100248 /* valid data magic ID value */
90#define MS02NV_SLOT_SIZE 0x800000 /* size of the address space
91 decoded by the module */
92
93
94typedef volatile u32 ms02nv_uint;
95
96struct ms02nv_private {
97 struct mtd_info *next;
98 struct {
99 struct resource *module;
100 struct resource *diag_ram;
101 struct resource *user_ram;
102 struct resource *csr;
103 } resource;
104 u_char *addr;
105 size_t size;
106 u_char *uaddr;
107};
diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c
new file mode 100644
index 000000000000..edac4156d69c
--- /dev/null
+++ b/drivers/mtd/devices/mtdram.c
@@ -0,0 +1,235 @@
1/*
2 * mtdram - a test mtd device
3 * $Id: mtdram.c,v 1.35 2005/01/05 18:05:12 dwmw2 Exp $
4 * Author: Alexander Larsson <alex@cendio.se>
5 *
6 * Copyright (c) 1999 Alexander Larsson <alex@cendio.se>
7 *
8 * This code is GPL
9 *
10 */
11
12#include <linux/config.h>
13#include <linux/module.h>
14#include <linux/slab.h>
15#include <linux/ioport.h>
16#include <linux/vmalloc.h>
17#include <linux/init.h>
18#include <linux/mtd/compatmac.h>
19#include <linux/mtd/mtd.h>
20
21#ifndef CONFIG_MTDRAM_ABS_POS
22 #define CONFIG_MTDRAM_ABS_POS 0
23#endif
24
25#if CONFIG_MTDRAM_ABS_POS > 0
26 #include <asm/io.h>
27#endif
28
29#ifdef MODULE
30static unsigned long total_size = CONFIG_MTDRAM_TOTAL_SIZE;
31static unsigned long erase_size = CONFIG_MTDRAM_ERASE_SIZE;
32module_param(total_size,ulong,0);
33MODULE_PARM_DESC(total_size, "Total device size in KiB");
34module_param(erase_size,ulong,0);
35MODULE_PARM_DESC(erase_size, "Device erase block size in KiB");
36#define MTDRAM_TOTAL_SIZE (total_size * 1024)
37#define MTDRAM_ERASE_SIZE (erase_size * 1024)
38#else
39#define MTDRAM_TOTAL_SIZE (CONFIG_MTDRAM_TOTAL_SIZE * 1024)
40#define MTDRAM_ERASE_SIZE (CONFIG_MTDRAM_ERASE_SIZE * 1024)
41#endif
42
43
44// We could store these in the mtd structure, but we only support 1 device..
45static struct mtd_info *mtd_info;
46
47
48static int
49ram_erase(struct mtd_info *mtd, struct erase_info *instr)
50{
51 DEBUG(MTD_DEBUG_LEVEL2, "ram_erase(pos:%ld, len:%ld)\n", (long)instr->addr, (long)instr->len);
52 if (instr->addr + instr->len > mtd->size) {
53 DEBUG(MTD_DEBUG_LEVEL1, "ram_erase() out of bounds (%ld > %ld)\n", (long)(instr->addr + instr->len), (long)mtd->size);
54 return -EINVAL;
55 }
56
57 memset((char *)mtd->priv + instr->addr, 0xff, instr->len);
58
59 instr->state = MTD_ERASE_DONE;
60 mtd_erase_callback(instr);
61
62 return 0;
63}
64
65static int ram_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf)
66{
67 if (from + len > mtd->size)
68 return -EINVAL;
69
70 *mtdbuf = mtd->priv + from;
71 *retlen = len;
72 return 0;
73}
74
75static void ram_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from,
76 size_t len)
77{
78 DEBUG(MTD_DEBUG_LEVEL2, "ram_unpoint\n");
79}
80
81static int ram_read(struct mtd_info *mtd, loff_t from, size_t len,
82 size_t *retlen, u_char *buf)
83{
84 DEBUG(MTD_DEBUG_LEVEL2, "ram_read(pos:%ld, len:%ld)\n", (long)from, (long)len);
85 if (from + len > mtd->size) {
86 DEBUG(MTD_DEBUG_LEVEL1, "ram_read() out of bounds (%ld > %ld)\n", (long)(from + len), (long)mtd->size);
87 return -EINVAL;
88 }
89
90 memcpy(buf, mtd->priv + from, len);
91
92 *retlen=len;
93 return 0;
94}
95
96static int ram_write(struct mtd_info *mtd, loff_t to, size_t len,
97 size_t *retlen, const u_char *buf)
98{
99 DEBUG(MTD_DEBUG_LEVEL2, "ram_write(pos:%ld, len:%ld)\n", (long)to, (long)len);
100 if (to + len > mtd->size) {
101 DEBUG(MTD_DEBUG_LEVEL1, "ram_write() out of bounds (%ld > %ld)\n", (long)(to + len), (long)mtd->size);
102 return -EINVAL;
103 }
104
105 memcpy ((char *)mtd->priv + to, buf, len);
106
107 *retlen=len;
108 return 0;
109}
110
111static void __exit cleanup_mtdram(void)
112{
113 if (mtd_info) {
114 del_mtd_device(mtd_info);
115#if CONFIG_MTDRAM_TOTAL_SIZE > 0
116 if (mtd_info->priv)
117#if CONFIG_MTDRAM_ABS_POS > 0
118 iounmap(mtd_info->priv);
119#else
120 vfree(mtd_info->priv);
121#endif
122#endif
123 kfree(mtd_info);
124 }
125}
126
127int mtdram_init_device(struct mtd_info *mtd, void *mapped_address,
128 unsigned long size, char *name)
129{
130 memset(mtd, 0, sizeof(*mtd));
131
132 /* Setup the MTD structure */
133 mtd->name = name;
134 mtd->type = MTD_RAM;
135 mtd->flags = MTD_CAP_RAM;
136 mtd->size = size;
137 mtd->erasesize = MTDRAM_ERASE_SIZE;
138 mtd->priv = mapped_address;
139
140 mtd->owner = THIS_MODULE;
141 mtd->erase = ram_erase;
142 mtd->point = ram_point;
143 mtd->unpoint = ram_unpoint;
144 mtd->read = ram_read;
145 mtd->write = ram_write;
146
147 if (add_mtd_device(mtd)) {
148 return -EIO;
149 }
150
151 return 0;
152}
153
154#if CONFIG_MTDRAM_TOTAL_SIZE > 0
155#if CONFIG_MTDRAM_ABS_POS > 0
156static int __init init_mtdram(void)
157{
158 void *addr;
159 int err;
160 /* Allocate some memory */
161 mtd_info = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
162 if (!mtd_info)
163 return -ENOMEM;
164
165 addr = ioremap(CONFIG_MTDRAM_ABS_POS, MTDRAM_TOTAL_SIZE);
166 if (!addr) {
167 DEBUG(MTD_DEBUG_LEVEL1,
168 "Failed to ioremap) memory region of size %ld at ABS_POS:%ld\n",
169 (long)MTDRAM_TOTAL_SIZE, (long)CONFIG_MTDRAM_ABS_POS);
170 kfree(mtd_info);
171 mtd_info = NULL;
172 return -ENOMEM;
173 }
174 err = mtdram_init_device(mtd_info, addr,
175 MTDRAM_TOTAL_SIZE, "mtdram test device");
176 if (err)
177 {
178 iounmap(addr);
179 kfree(mtd_info);
180 mtd_info = NULL;
181 return err;
182 }
183 memset(mtd_info->priv, 0xff, MTDRAM_TOTAL_SIZE);
184 return err;
185}
186
187#else /* CONFIG_MTDRAM_ABS_POS > 0 */
188
189static int __init init_mtdram(void)
190{
191 void *addr;
192 int err;
193 /* Allocate some memory */
194 mtd_info = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
195 if (!mtd_info)
196 return -ENOMEM;
197
198 addr = vmalloc(MTDRAM_TOTAL_SIZE);
199 if (!addr) {
200 DEBUG(MTD_DEBUG_LEVEL1,
201 "Failed to vmalloc memory region of size %ld\n",
202 (long)MTDRAM_TOTAL_SIZE);
203 kfree(mtd_info);
204 mtd_info = NULL;
205 return -ENOMEM;
206 }
207 err = mtdram_init_device(mtd_info, addr,
208 MTDRAM_TOTAL_SIZE, "mtdram test device");
209 if (err)
210 {
211 vfree(addr);
212 kfree(mtd_info);
213 mtd_info = NULL;
214 return err;
215 }
216 memset(mtd_info->priv, 0xff, MTDRAM_TOTAL_SIZE);
217 return err;
218}
219#endif /* !(CONFIG_MTDRAM_ABS_POS > 0) */
220
221#else /* CONFIG_MTDRAM_TOTAL_SIZE > 0 */
222
223static int __init init_mtdram(void)
224{
225 return 0;
226}
227#endif /* !(CONFIG_MTDRAM_TOTAL_SIZE > 0) */
228
229module_init(init_mtdram);
230module_exit(cleanup_mtdram);
231
232MODULE_LICENSE("GPL");
233MODULE_AUTHOR("Alexander Larsson <alexl@redhat.com>");
234MODULE_DESCRIPTION("Simulated MTD driver for testing");
235
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
new file mode 100644
index 000000000000..5f8e164ddb71
--- /dev/null
+++ b/drivers/mtd/devices/phram.c
@@ -0,0 +1,285 @@
1/**
2 * $Id: phram.c,v 1.11 2005/01/05 18:05:13 dwmw2 Exp $
3 *
4 * Copyright (c) ???? Jochen Schäuble <psionic@psionic.de>
5 * Copyright (c) 2003-2004 Jörn Engel <joern@wh.fh-wedel.de>
6 *
7 * Usage:
8 *
9 * one commend line parameter per device, each in the form:
10 * phram=<name>,<start>,<len>
11 * <name> may be up to 63 characters.
12 * <start> and <len> can be octal, decimal or hexadecimal. If followed
13 * by "ki", "Mi" or "Gi", the numbers will be interpreted as kilo, mega or
14 * gigabytes.
15 *
16 * Example:
17 * phram=swap,64Mi,128Mi phram=test,900Mi,1Mi
18 *
19 */
20
21#include <asm/io.h>
22#include <linux/init.h>
23#include <linux/kernel.h>
24#include <linux/list.h>
25#include <linux/module.h>
26#include <linux/moduleparam.h>
27#include <linux/mtd/mtd.h>
28
29#define ERROR(fmt, args...) printk(KERN_ERR "phram: " fmt , ## args)
30
31struct phram_mtd_list {
32 struct mtd_info mtd;
33 struct list_head list;
34};
35
36static LIST_HEAD(phram_list);
37
38
39
40static int phram_erase(struct mtd_info *mtd, struct erase_info *instr)
41{
42 u_char *start = mtd->priv;
43
44 if (instr->addr + instr->len > mtd->size)
45 return -EINVAL;
46
47 memset(start + instr->addr, 0xff, instr->len);
48
49 /* This'll catch a few races. Free the thing before returning :)
50 * I don't feel at all ashamed. This kind of thing is possible anyway
51 * with flash, but unlikely.
52 */
53
54 instr->state = MTD_ERASE_DONE;
55
56 mtd_erase_callback(instr);
57
58 return 0;
59}
60
61static int phram_point(struct mtd_info *mtd, loff_t from, size_t len,
62 size_t *retlen, u_char **mtdbuf)
63{
64 u_char *start = mtd->priv;
65
66 if (from + len > mtd->size)
67 return -EINVAL;
68
69 *mtdbuf = start + from;
70 *retlen = len;
71 return 0;
72}
73
74static void phram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
75{
76}
77
78static int phram_read(struct mtd_info *mtd, loff_t from, size_t len,
79 size_t *retlen, u_char *buf)
80{
81 u_char *start = mtd->priv;
82
83 if (from + len > mtd->size)
84 return -EINVAL;
85
86 memcpy(buf, start + from, len);
87
88 *retlen = len;
89 return 0;
90}
91
92static int phram_write(struct mtd_info *mtd, loff_t to, size_t len,
93 size_t *retlen, const u_char *buf)
94{
95 u_char *start = mtd->priv;
96
97 if (to + len > mtd->size)
98 return -EINVAL;
99
100 memcpy(start + to, buf, len);
101
102 *retlen = len;
103 return 0;
104}
105
106
107
108static void unregister_devices(void)
109{
110 struct phram_mtd_list *this;
111
112 list_for_each_entry(this, &phram_list, list) {
113 del_mtd_device(&this->mtd);
114 iounmap(this->mtd.priv);
115 kfree(this);
116 }
117}
118
119static int register_device(char *name, unsigned long start, unsigned long len)
120{
121 struct phram_mtd_list *new;
122 int ret = -ENOMEM;
123
124 new = kmalloc(sizeof(*new), GFP_KERNEL);
125 if (!new)
126 goto out0;
127
128 memset(new, 0, sizeof(*new));
129
130 ret = -EIO;
131 new->mtd.priv = ioremap(start, len);
132 if (!new->mtd.priv) {
133 ERROR("ioremap failed\n");
134 goto out1;
135 }
136
137
138 new->mtd.name = name;
139 new->mtd.size = len;
140 new->mtd.flags = MTD_CAP_RAM | MTD_ERASEABLE | MTD_VOLATILE;
141 new->mtd.erase = phram_erase;
142 new->mtd.point = phram_point;
143 new->mtd.unpoint = phram_unpoint;
144 new->mtd.read = phram_read;
145 new->mtd.write = phram_write;
146 new->mtd.owner = THIS_MODULE;
147 new->mtd.type = MTD_RAM;
148 new->mtd.erasesize = 0;
149
150 ret = -EAGAIN;
151 if (add_mtd_device(&new->mtd)) {
152 ERROR("Failed to register new device\n");
153 goto out2;
154 }
155
156 list_add_tail(&new->list, &phram_list);
157 return 0;
158
159out2:
160 iounmap(new->mtd.priv);
161out1:
162 kfree(new);
163out0:
164 return ret;
165}
166
167static int ustrtoul(const char *cp, char **endp, unsigned int base)
168{
169 unsigned long result = simple_strtoul(cp, endp, base);
170
171 switch (**endp) {
172 case 'G':
173 result *= 1024;
174 case 'M':
175 result *= 1024;
176 case 'k':
177 result *= 1024;
178 /* By dwmw2 editorial decree, "ki", "Mi" or "Gi" are to be used. */
179 if ((*endp)[1] == 'i')
180 (*endp) += 2;
181 }
182 return result;
183}
184
185static int parse_num32(uint32_t *num32, const char *token)
186{
187 char *endp;
188 unsigned long n;
189
190 n = ustrtoul(token, &endp, 0);
191 if (*endp)
192 return -EINVAL;
193
194 *num32 = n;
195 return 0;
196}
197
198static int parse_name(char **pname, const char *token)
199{
200 size_t len;
201 char *name;
202
203 len = strlen(token) + 1;
204 if (len > 64)
205 return -ENOSPC;
206
207 name = kmalloc(len, GFP_KERNEL);
208 if (!name)
209 return -ENOMEM;
210
211 strcpy(name, token);
212
213 *pname = name;
214 return 0;
215}
216
217#define parse_err(fmt, args...) do { \
218 ERROR(fmt , ## args); \
219 return 0; \
220} while (0)
221
222static int phram_setup(const char *val, struct kernel_param *kp)
223{
224 char buf[64+12+12], *str = buf;
225 char *token[3];
226 char *name;
227 uint32_t start;
228 uint32_t len;
229 int i, ret;
230
231 if (strnlen(val, sizeof(buf)) >= sizeof(buf))
232 parse_err("parameter too long\n");
233
234 strcpy(str, val);
235
236 for (i=0; i<3; i++)
237 token[i] = strsep(&str, ",");
238
239 if (str)
240 parse_err("too many arguments\n");
241
242 if (!token[2])
243 parse_err("not enough arguments\n");
244
245 ret = parse_name(&name, token[0]);
246 if (ret == -ENOMEM)
247 parse_err("out of memory\n");
248 if (ret == -ENOSPC)
249 parse_err("name too long\n");
250 if (ret)
251 return 0;
252
253 ret = parse_num32(&start, token[1]);
254 if (ret)
255 parse_err("illegal start address\n");
256
257 ret = parse_num32(&len, token[2]);
258 if (ret)
259 parse_err("illegal device length\n");
260
261 register_device(name, start, len);
262
263 return 0;
264}
265
266module_param_call(phram, phram_setup, NULL, NULL, 000);
267MODULE_PARM_DESC(phram,"Memory region to map. \"map=<name>,<start>,<length>\"");
268
269
270static int __init init_phram(void)
271{
272 return 0;
273}
274
275static void __exit cleanup_phram(void)
276{
277 unregister_devices();
278}
279
280module_init(init_phram);
281module_exit(cleanup_phram);
282
283MODULE_LICENSE("GPL");
284MODULE_AUTHOR("Jörn Engel <joern@wh.fh-wedel.de>");
285MODULE_DESCRIPTION("MTD driver for physical RAM");
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c
new file mode 100644
index 000000000000..5b3defadf884
--- /dev/null
+++ b/drivers/mtd/devices/pmc551.c
@@ -0,0 +1,843 @@
1/*
2 * $Id: pmc551.c,v 1.30 2005/01/05 18:05:13 dwmw2 Exp $
3 *
4 * PMC551 PCI Mezzanine Ram Device
5 *
6 * Author:
7 * Mark Ferrell <mferrell@mvista.com>
8 * Copyright 1999,2000 Nortel Networks
9 *
10 * License:
11 * As part of this driver was derived from the slram.c driver it
12 * falls under the same license, which is GNU General Public
13 * License v2
14 *
15 * Description:
16 * This driver is intended to support the PMC551 PCI Ram device
17 * from Ramix Inc. The PMC551 is a PMC Mezzanine module for
18 * cPCI embedded systems. The device contains a single SROM
19 * that initially programs the V370PDC chipset onboard the
20 * device, and various banks of DRAM/SDRAM onboard. This driver
21 * implements this PCI Ram device as an MTD (Memory Technology
22 * Device) so that it can be used to hold a file system, or for
23 * added swap space in embedded systems. Since the memory on
24 * this board isn't as fast as main memory we do not try to hook
25 * it into main memory as that would simply reduce performance
26 * on the system. Using it as a block device allows us to use
27 * it as high speed swap or for a high speed disk device of some
28 * sort. Which becomes very useful on diskless systems in the
29 * embedded market I might add.
30 *
31 * Notes:
32 * Due to what I assume is more buggy SROM, the 64M PMC551 I
33 * have available claims that all 4 of it's DRAM banks have 64M
34 * of ram configured (making a grand total of 256M onboard).
35 * This is slightly annoying since the BAR0 size reflects the
36 * aperture size, not the dram size, and the V370PDC supplies no
37 * other method for memory size discovery. This problem is
38 * mostly only relevant when compiled as a module, as the
39 * unloading of the module with an aperture size smaller then
40 * the ram will cause the driver to detect the onboard memory
41 * size to be equal to the aperture size when the module is
42 * reloaded. Soooo, to help, the module supports an msize
43 * option to allow the specification of the onboard memory, and
44 * an asize option, to allow the specification of the aperture
45 * size. The aperture must be equal to or less then the memory
46 * size, the driver will correct this if you screw it up. This
47 * problem is not relevant for compiled in drivers as compiled
48 * in drivers only init once.
49 *
50 * Credits:
51 * Saeed Karamooz <saeed@ramix.com> of Ramix INC. for the
52 * initial example code of how to initialize this device and for
53 * help with questions I had concerning operation of the device.
54 *
55 * Most of the MTD code for this driver was originally written
56 * for the slram.o module in the MTD drivers package which
57 * allows the mapping of system memory into an MTD device.
58 * Since the PMC551 memory module is accessed in the same
59 * fashion as system memory, the slram.c code became a very nice
60 * fit to the needs of this driver. All we added was PCI
61 * detection/initialization to the driver and automatically figure
62 * out the size via the PCI detection.o, later changes by Corey
63 * Minyard set up the card to utilize a 1M sliding apature.
64 *
65 * Corey Minyard <minyard@nortelnetworks.com>
66 * * Modified driver to utilize a sliding aperture instead of
67 * mapping all memory into kernel space which turned out to
68 * be very wasteful.
69 * * Located a bug in the SROM's initialization sequence that
70 * made the memory unusable, added a fix to code to touch up
71 * the DRAM some.
72 *
73 * Bugs/FIXME's:
74 * * MUST fix the init function to not spin on a register
75 * waiting for it to set .. this does not safely handle busted
76 * devices that never reset the register correctly which will
77 * cause the system to hang w/ a reboot being the only chance at
78 * recover. [sort of fixed, could be better]
79 * * Add I2C handling of the SROM so we can read the SROM's information
80 * about the aperture size. This should always accurately reflect the
81 * onboard memory size.
82 * * Comb the init routine. It's still a bit cludgy on a few things.
83 */
84
85#include <linux/version.h>
86#include <linux/config.h>
87#include <linux/kernel.h>
88#include <linux/module.h>
89#include <asm/uaccess.h>
90#include <linux/types.h>
91#include <linux/sched.h>
92#include <linux/init.h>
93#include <linux/ptrace.h>
94#include <linux/slab.h>
95#include <linux/string.h>
96#include <linux/timer.h>
97#include <linux/major.h>
98#include <linux/fs.h>
99#include <linux/ioctl.h>
100#include <asm/io.h>
101#include <asm/system.h>
102#include <linux/pci.h>
103
104#ifndef CONFIG_PCI
105#error Enable PCI in your kernel config
106#endif
107
108#include <linux/mtd/mtd.h>
109#include <linux/mtd/pmc551.h>
110#include <linux/mtd/compatmac.h>
111
112static struct mtd_info *pmc551list;
113
114static int pmc551_erase (struct mtd_info *mtd, struct erase_info *instr)
115{
116 struct mypriv *priv = mtd->priv;
117 u32 soff_hi, soff_lo; /* start address offset hi/lo */
118 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */
119 unsigned long end;
120 u_char *ptr;
121 size_t retlen;
122
123#ifdef CONFIG_MTD_PMC551_DEBUG
124 printk(KERN_DEBUG "pmc551_erase(pos:%ld, len:%ld)\n", (long)instr->addr, (long)instr->len);
125#endif
126
127 end = instr->addr + instr->len - 1;
128
129 /* Is it past the end? */
130 if ( end > mtd->size ) {
131#ifdef CONFIG_MTD_PMC551_DEBUG
132 printk(KERN_DEBUG "pmc551_erase() out of bounds (%ld > %ld)\n", (long)end, (long)mtd->size);
133#endif
134 return -EINVAL;
135 }
136
137 eoff_hi = end & ~(priv->asize - 1);
138 soff_hi = instr->addr & ~(priv->asize - 1);
139 eoff_lo = end & (priv->asize - 1);
140 soff_lo = instr->addr & (priv->asize - 1);
141
142 pmc551_point (mtd, instr->addr, instr->len, &retlen, &ptr);
143
144 if ( soff_hi == eoff_hi || mtd->size == priv->asize) {
145 /* The whole thing fits within one access, so just one shot
146 will do it. */
147 memset(ptr, 0xff, instr->len);
148 } else {
149 /* We have to do multiple writes to get all the data
150 written. */
151 while (soff_hi != eoff_hi) {
152#ifdef CONFIG_MTD_PMC551_DEBUG
153 printk( KERN_DEBUG "pmc551_erase() soff_hi: %ld, eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
154#endif
155 memset(ptr, 0xff, priv->asize);
156 if (soff_hi + priv->asize >= mtd->size) {
157 goto out;
158 }
159 soff_hi += priv->asize;
160 pmc551_point (mtd,(priv->base_map0|soff_hi),
161 priv->asize, &retlen, &ptr);
162 }
163 memset (ptr, 0xff, eoff_lo);
164 }
165
166out:
167 instr->state = MTD_ERASE_DONE;
168#ifdef CONFIG_MTD_PMC551_DEBUG
169 printk(KERN_DEBUG "pmc551_erase() done\n");
170#endif
171
172 mtd_erase_callback(instr);
173 return 0;
174}
175
176
177static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf)
178{
179 struct mypriv *priv = mtd->priv;
180 u32 soff_hi;
181 u32 soff_lo;
182
183#ifdef CONFIG_MTD_PMC551_DEBUG
184 printk(KERN_DEBUG "pmc551_point(%ld, %ld)\n", (long)from, (long)len);
185#endif
186
187 if (from + len > mtd->size) {
188#ifdef CONFIG_MTD_PMC551_DEBUG
189 printk(KERN_DEBUG "pmc551_point() out of bounds (%ld > %ld)\n", (long)from+len, (long)mtd->size);
190#endif
191 return -EINVAL;
192 }
193
194 soff_hi = from & ~(priv->asize - 1);
195 soff_lo = from & (priv->asize - 1);
196
197 /* Cheap hack optimization */
198 if( priv->curr_map0 != from ) {
199 pci_write_config_dword ( priv->dev, PMC551_PCI_MEM_MAP0,
200 (priv->base_map0 | soff_hi) );
201 priv->curr_map0 = soff_hi;
202 }
203
204 *mtdbuf = priv->start + soff_lo;
205 *retlen = len;
206 return 0;
207}
208
209
210static void pmc551_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
211{
212#ifdef CONFIG_MTD_PMC551_DEBUG
213 printk(KERN_DEBUG "pmc551_unpoint()\n");
214#endif
215}
216
217
218static int pmc551_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
219{
220 struct mypriv *priv = mtd->priv;
221 u32 soff_hi, soff_lo; /* start address offset hi/lo */
222 u32 eoff_hi, eoff_lo; /* end address offset hi/lo */
223 unsigned long end;
224 u_char *ptr;
225 u_char *copyto = buf;
226
227#ifdef CONFIG_MTD_PMC551_DEBUG
228 printk(KERN_DEBUG "pmc551_read(pos:%ld, len:%ld) asize: %ld\n", (long)from, (long)len, (long)priv->asize);
229#endif
230
231 end = from + len - 1;
232
233 /* Is it past the end? */
234 if (end > mtd->size) {
235#ifdef CONFIG_MTD_PMC551_DEBUG
236 printk(KERN_DEBUG "pmc551_read() out of bounds (%ld > %ld)\n", (long) end, (long)mtd->size);
237#endif
238 return -EINVAL;
239 }
240
241 soff_hi = from & ~(priv->asize - 1);
242 eoff_hi = end & ~(priv->asize - 1);
243 soff_lo = from & (priv->asize - 1);
244 eoff_lo = end & (priv->asize - 1);
245
246 pmc551_point (mtd, from, len, retlen, &ptr);
247
248 if (soff_hi == eoff_hi) {
249 /* The whole thing fits within one access, so just one shot
250 will do it. */
251 memcpy(copyto, ptr, len);
252 copyto += len;
253 } else {
254 /* We have to do multiple writes to get all the data
255 written. */
256 while (soff_hi != eoff_hi) {
257#ifdef CONFIG_MTD_PMC551_DEBUG
258 printk( KERN_DEBUG "pmc551_read() soff_hi: %ld, eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
259#endif
260 memcpy(copyto, ptr, priv->asize);
261 copyto += priv->asize;
262 if (soff_hi + priv->asize >= mtd->size) {
263 goto out;
264 }
265 soff_hi += priv->asize;
266 pmc551_point (mtd, soff_hi, priv->asize, retlen, &ptr);
267 }
268 memcpy(copyto, ptr, eoff_lo);
269 copyto += eoff_lo;
270 }
271
272out:
273#ifdef CONFIG_MTD_PMC551_DEBUG
274 printk(KERN_DEBUG "pmc551_read() done\n");
275#endif
276 *retlen = copyto - buf;
277 return 0;
278}
279
280static int pmc551_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
281{
282 struct mypriv *priv = mtd->priv;
283 u32 soff_hi, soff_lo; /* start address offset hi/lo */
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
290#ifdef CONFIG_MTD_PMC551_DEBUG
291 printk(KERN_DEBUG "pmc551_write(pos:%ld, len:%ld) asize:%ld\n", (long)to, (long)len, (long)priv->asize);
292#endif
293
294 end = to + len - 1;
295 /* Is it past the end? or did the u32 wrap? */
296 if (end > mtd->size ) {
297#ifdef CONFIG_MTD_PMC551_DEBUG
298 printk(KERN_DEBUG "pmc551_write() out of bounds (end: %ld, size: %ld, to: %ld)\n", (long) end, (long)mtd->size, (long)to);
299#endif
300 return -EINVAL;
301 }
302
303 soff_hi = to & ~(priv->asize - 1);
304 eoff_hi = end & ~(priv->asize - 1);
305 soff_lo = to & (priv->asize - 1);
306 eoff_lo = end & (priv->asize - 1);
307
308 pmc551_point (mtd, to, len, retlen, &ptr);
309
310 if (soff_hi == eoff_hi) {
311 /* The whole thing fits within one access, so just one shot
312 will do it. */
313 memcpy(ptr, copyfrom, len);
314 copyfrom += len;
315 } else {
316 /* We have to do multiple writes to get all the data
317 written. */
318 while (soff_hi != eoff_hi) {
319#ifdef CONFIG_MTD_PMC551_DEBUG
320 printk( KERN_DEBUG "pmc551_write() soff_hi: %ld, eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi);
321#endif
322 memcpy(ptr, copyfrom, priv->asize);
323 copyfrom += priv->asize;
324 if (soff_hi >= mtd->size) {
325 goto out;
326 }
327 soff_hi += priv->asize;
328 pmc551_point (mtd, soff_hi, priv->asize, retlen, &ptr);
329 }
330 memcpy(ptr, copyfrom, eoff_lo);
331 copyfrom += eoff_lo;
332 }
333
334out:
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 basicly 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 u32 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 { pci_read_config_word( dev, PMC551_SDRAM_CMD, &cmd );
479 if(counter++ > 100)break;
480 } while ( (PCI_COMMAND_IO) & cmd );
481
482 /*
483 * Turn on auto refresh
484 * The loop is taken directly from Ramix's example code. I assume that
485 * this must be held high for some duration of time, but I can find no
486 * documentation refrencing the reasons why.
487 */
488 for ( i = 1; i<=8 ; i++) {
489 pci_write_config_word (dev, PMC551_SDRAM_CMD, 0x0df);
490
491 /*
492 * Make certain command has gone through
493 * FIXME: register spinning issue
494 */
495 counter=0;
496 do { pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
497 if(counter++ > 100)break;
498 } while ( (PCI_COMMAND_IO) & cmd );
499 }
500
501 pci_write_config_word ( dev, PMC551_SDRAM_MA, 0x0020);
502 pci_write_config_word ( dev, PMC551_SDRAM_CMD, 0x0ff);
503
504 /*
505 * Wait until command completes
506 * FIXME: register spinning issue
507 */
508 counter=0;
509 do { pci_read_config_word ( dev, PMC551_SDRAM_CMD, &cmd);
510 if(counter++ > 100)break;
511 } while ( (PCI_COMMAND_IO) & cmd );
512
513 pci_read_config_dword ( dev, PMC551_DRAM_CFG, &dcmd);
514 dcmd |= 0x02000000;
515 pci_write_config_dword ( dev, PMC551_DRAM_CFG, dcmd);
516
517 /*
518 * Check to make certain fast back-to-back, if not
519 * then set it so
520 */
521 pci_read_config_word( dev, PCI_STATUS, &cmd);
522 if((cmd&PCI_COMMAND_FAST_BACK) == 0) {
523 cmd |= PCI_COMMAND_FAST_BACK;
524 pci_write_config_word( dev, PCI_STATUS, cmd);
525 }
526
527 /*
528 * Check to make certain the DEVSEL is set correctly, this device
529 * has a tendancy to assert DEVSEL and TRDY when a write is performed
530 * to the memory when memory is read-only
531 */
532 if((cmd&PCI_STATUS_DEVSEL_MASK) != 0x0) {
533 cmd &= ~PCI_STATUS_DEVSEL_MASK;
534 pci_write_config_word( dev, PCI_STATUS, cmd );
535 }
536 /*
537 * Set to be prefetchable and put everything back based on old cfg.
538 * it's possible that the reset of the V370PDC nuked the original
539 * setup
540 */
541 /*
542 cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH;
543 pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );
544 */
545
546 /*
547 * Turn PCI memory and I/O bus access back on
548 */
549 pci_write_config_word( dev, PCI_COMMAND,
550 PCI_COMMAND_MEMORY | PCI_COMMAND_IO );
551#ifdef CONFIG_MTD_PMC551_DEBUG
552 /*
553 * Some screen fun
554 */
555 printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at 0x%lx\n",
556 (size<1024)?size:(size<1048576)?size>>10:size>>20,
557 (size<1024)?'B':(size<1048576)?'K':'M',
558 size, ((dcmd&(0x1<<3)) == 0)?"non-":"",
559 (dev->resource[0].start)&PCI_BASE_ADDRESS_MEM_MASK );
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), ((dcmd>>9)&0xF) );
572
573 pci_read_config_dword( dev, PMC551_DRAM_BLK1, &dcmd );
574 printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n"
575 "pmc551: DRAM_BLK1 Size: %d at %d\n"
576 "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n",
577 (((0x1<<1)&dcmd) == 0)?"RW":"RO",
578 (((0x1<<0)&dcmd) == 0)?"Off":"On",
579 PMC551_DRAM_BLK_GET_SIZE(dcmd),
580 ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) );
581
582 pci_read_config_dword( dev, PMC551_DRAM_BLK2, &dcmd );
583 printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n"
584 "pmc551: DRAM_BLK2 Size: %d at %d\n"
585 "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n",
586 (((0x1<<1)&dcmd) == 0)?"RW":"RO",
587 (((0x1<<0)&dcmd) == 0)?"Off":"On",
588 PMC551_DRAM_BLK_GET_SIZE(dcmd),
589 ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) );
590
591 pci_read_config_dword( dev, PMC551_DRAM_BLK3, &dcmd );
592 printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n"
593 "pmc551: DRAM_BLK3 Size: %d at %d\n"
594 "pmc551: DRAM_BLK3 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), ((dcmd>>9)&0xF) );
599
600 pci_read_config_word( dev, PCI_COMMAND, &cmd );
601 printk( KERN_DEBUG "pmc551: Memory Access %s\n",
602 (((0x1<<1)&cmd) == 0)?"off":"on" );
603 printk( KERN_DEBUG "pmc551: I/O Access %s\n",
604 (((0x1<<0)&cmd) == 0)?"off":"on" );
605
606 pci_read_config_word( dev, PCI_STATUS, &cmd );
607 printk( KERN_DEBUG "pmc551: Devsel %s\n",
608 ((PCI_STATUS_DEVSEL_MASK&cmd)==0x000)?"Fast":
609 ((PCI_STATUS_DEVSEL_MASK&cmd)==0x200)?"Medium":
610 ((PCI_STATUS_DEVSEL_MASK&cmd)==0x400)?"Slow":"Invalid" );
611
612 printk( KERN_DEBUG "pmc551: %sFast Back-to-Back\n",
613 ((PCI_COMMAND_FAST_BACK&cmd) == 0)?"Not ":"" );
614
615 pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd );
616 printk( KERN_DEBUG "pmc551: EEPROM is under %s control\n"
617 "pmc551: System Control Register is %slocked to PCI access\n"
618 "pmc551: System Control Register is %slocked to EEPROM access\n",
619 (bcmd&0x1)?"software":"hardware",
620 (bcmd&0x20)?"":"un", (bcmd&0x40)?"":"un");
621#endif
622 return size;
623}
624
625/*
626 * Kernel version specific module stuffages
627 */
628
629
630MODULE_LICENSE("GPL");
631MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>");
632MODULE_DESCRIPTION(PMC551_VERSION);
633
634/*
635 * Stuff these outside the ifdef so as to not bust compiled in driver support
636 */
637static int msize=0;
638#if defined(CONFIG_MTD_PMC551_APERTURE_SIZE)
639static int asize=CONFIG_MTD_PMC551_APERTURE_SIZE
640#else
641static int asize=0;
642#endif
643
644module_param(msize, int, 0);
645MODULE_PARM_DESC(msize, "memory size in Megabytes [1 - 1024]");
646module_param(asize, int, 0);
647MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]");
648
649/*
650 * PMC551 Card Initialization
651 */
652static int __init init_pmc551(void)
653{
654 struct pci_dev *PCI_Device = NULL;
655 struct mypriv *priv;
656 int count, found=0;
657 struct mtd_info *mtd;
658 u32 length = 0;
659
660 if(msize) {
661 msize = (1 << (ffs(msize) - 1))<<20;
662 if (msize > (1<<30)) {
663 printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n", 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 [%d]\n", asize);
672 return -EINVAL;
673 }
674 }
675
676 printk(KERN_INFO PMC551_VERSION);
677
678 /*
679 * PCU-bus chipset probe.
680 */
681 for( count = 0; count < MAX_MTD_DEVICES; count++ ) {
682
683 if ((PCI_Device = pci_find_device(PCI_VENDOR_ID_V3_SEMI,
684 PCI_DEVICE_ID_V3_SEMI_V370PDC,
685 PCI_Device ) ) == NULL) {
686 break;
687 }
688
689 printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%lX\n",
690 PCI_Device->resource[0].start);
691
692 /*
693 * The PMC551 device acts VERY weird if you don't init it
694 * first. i.e. it will not correctly report devsel. If for
695 * some reason the sdram is in a wrote-protected state the
696 * device will DEVSEL when it is written to causing problems
697 * with the oldproc.c driver in
698 * some kernels (2.2.*)
699 */
700 if((length = fixup_pmc551(PCI_Device)) <= 0) {
701 printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n");
702 break;
703 }
704
705 /*
706 * This is needed until the driver is capable of reading the
707 * onboard I2C SROM to discover the "real" memory size.
708 */
709 if(msize) {
710 length = msize;
711 printk(KERN_NOTICE "pmc551: Using specified memory size 0x%x\n", length);
712 } else {
713 msize = length;
714 }
715
716 mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
717 if (!mtd) {
718 printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n");
719 break;
720 }
721
722 memset(mtd, 0, sizeof(struct mtd_info));
723
724 priv = kmalloc (sizeof(struct mypriv), GFP_KERNEL);
725 if (!priv) {
726 printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n");
727 kfree(mtd);
728 break;
729 }
730 memset(priv, 0, sizeof(*priv));
731 mtd->priv = priv;
732 priv->dev = PCI_Device;
733
734 if(asize > length) {
735 printk(KERN_NOTICE "pmc551: reducing aperture size to fit %dM\n",length>>20);
736 priv->asize = asize = length;
737 } else if (asize == 0 || asize == length) {
738 printk(KERN_NOTICE "pmc551: Using existing aperture size %dM\n", length>>20);
739 priv->asize = asize = length;
740 } else {
741 printk(KERN_NOTICE "pmc551: Using specified aperture size %dM\n", asize>>20);
742 priv->asize = asize;
743 }
744 priv->start = ioremap(((PCI_Device->resource[0].start)
745 & PCI_BASE_ADDRESS_MEM_MASK),
746 priv->asize);
747
748 if (!priv->start) {
749 printk(KERN_NOTICE "pmc551: Unable to map IO space\n");
750 kfree(mtd->priv);
751 kfree(mtd);
752 break;
753 }
754
755#ifdef CONFIG_MTD_PMC551_DEBUG
756 printk( KERN_DEBUG "pmc551: setting aperture to %d\n",
757 ffs(priv->asize>>20)-1);
758#endif
759
760 priv->base_map0 = ( PMC551_PCI_MEM_MAP_REG_EN
761 | PMC551_PCI_MEM_MAP_ENABLE
762 | (ffs(priv->asize>>20)-1)<<4 );
763 priv->curr_map0 = priv->base_map0;
764 pci_write_config_dword ( priv->dev, PMC551_PCI_MEM_MAP0,
765 priv->curr_map0 );
766
767#ifdef CONFIG_MTD_PMC551_DEBUG
768 printk( KERN_DEBUG "pmc551: aperture set to %d\n",
769 (priv->base_map0 & 0xF0)>>4 );
770#endif
771
772 mtd->size = msize;
773 mtd->flags = MTD_CAP_RAM;
774 mtd->erase = pmc551_erase;
775 mtd->read = pmc551_read;
776 mtd->write = pmc551_write;
777 mtd->point = pmc551_point;
778 mtd->unpoint = pmc551_unpoint;
779 mtd->type = MTD_RAM;
780 mtd->name = "PMC551 RAM board";
781 mtd->erasesize = 0x10000;
782 mtd->owner = THIS_MODULE;
783
784 if (add_mtd_device(mtd)) {
785 printk(KERN_NOTICE "pmc551: Failed to register new device\n");
786 iounmap(priv->start);
787 kfree(mtd->priv);
788 kfree(mtd);
789 break;
790 }
791 printk(KERN_NOTICE "Registered pmc551 memory device.\n");
792 printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n",
793 priv->asize>>20,
794 priv->start,
795 priv->start + priv->asize);
796 printk(KERN_NOTICE "Total memory is %d%c\n",
797 (length<1024)?length:
798 (length<1048576)?length>>10:length>>20,
799 (length<1024)?'B':(length<1048576)?'K':'M');
800 priv->nextpmc551 = pmc551list;
801 pmc551list = mtd;
802 found++;
803 }
804
805 if( !pmc551list ) {
806 printk(KERN_NOTICE "pmc551: not detected\n");
807 return -ENODEV;
808 } else {
809 printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found);
810 return 0;
811 }
812}
813
814/*
815 * PMC551 Card Cleanup
816 */
817static void __exit cleanup_pmc551(void)
818{
819 int found=0;
820 struct mtd_info *mtd;
821 struct mypriv *priv;
822
823 while((mtd=pmc551list)) {
824 priv = mtd->priv;
825 pmc551list = priv->nextpmc551;
826
827 if(priv->start) {
828 printk (KERN_DEBUG "pmc551: unmapping %dM starting at 0x%p\n",
829 priv->asize>>20, priv->start);
830 iounmap (priv->start);
831 }
832
833 kfree (mtd->priv);
834 del_mtd_device (mtd);
835 kfree (mtd);
836 found++;
837 }
838
839 printk(KERN_NOTICE "pmc551: %d pmc551 devices unloaded\n", found);
840}
841
842module_init(init_pmc551);
843module_exit(cleanup_pmc551);
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c
new file mode 100644
index 000000000000..5ab15e643be7
--- /dev/null
+++ b/drivers/mtd/devices/slram.c
@@ -0,0 +1,357 @@
1/*======================================================================
2
3 $Id: slram.c,v 1.33 2005/01/05 18:05:13 dwmw2 Exp $
4
5 This driver provides a method to access memory not used by the kernel
6 itself (i.e. if the kernel commandline mem=xxx is used). To actually
7 use slram at least mtdblock or mtdchar is required (for block or
8 character device access).
9
10 Usage:
11
12 if compiled as loadable module:
13 modprobe slram map=<name>,<start>,<end/offset>
14 if statically linked into the kernel use the following kernel cmd.line
15 slram=<name>,<start>,<end/offset>
16
17 <name>: name of the device that will be listed in /proc/mtd
18 <start>: start of the memory region, decimal or hex (0xabcdef)
19 <end/offset>: end of the memory region. It's possible to use +0x1234
20 to specify the offset instead of the absolute address
21
22 NOTE:
23 With slram it's only possible to map a contigous memory region. Therfore
24 if there's a device mapped somewhere in the region specified slram will
25 fail to load (see kernel log if modprobe fails).
26
27 -
28
29 Jochen Schaeuble <psionic@psionic.de>
30
31======================================================================*/
32
33
34#include <linux/module.h>
35#include <asm/uaccess.h>
36#include <linux/types.h>
37#include <linux/kernel.h>
38#include <linux/sched.h>
39#include <linux/ptrace.h>
40#include <linux/slab.h>
41#include <linux/string.h>
42#include <linux/timer.h>
43#include <linux/major.h>
44#include <linux/fs.h>
45#include <linux/ioctl.h>
46#include <linux/init.h>
47#include <asm/io.h>
48#include <asm/system.h>
49
50#include <linux/mtd/mtd.h>
51
52#define SLRAM_MAX_DEVICES_PARAMS 6 /* 3 parameters / device */
53
54#define T(fmt, args...) printk(KERN_DEBUG fmt, ## args)
55#define E(fmt, args...) printk(KERN_NOTICE fmt, ## args)
56
57typedef struct slram_priv {
58 u_char *start;
59 u_char *end;
60} slram_priv_t;
61
62typedef struct slram_mtd_list {
63 struct mtd_info *mtdinfo;
64 struct slram_mtd_list *next;
65} slram_mtd_list_t;
66
67#ifdef MODULE
68static char *map[SLRAM_MAX_DEVICES_PARAMS];
69
70module_param_array(map, charp, NULL, 0);
71MODULE_PARM_DESC(map, "List of memory regions to map. \"map=<name>, <start>, <length / end>\"");
72#else
73static char *map;
74#endif
75
76static slram_mtd_list_t *slram_mtdlist = NULL;
77
78static int slram_erase(struct mtd_info *, struct erase_info *);
79static int slram_point(struct mtd_info *, loff_t, size_t, size_t *, u_char **);
80static void slram_unpoint(struct mtd_info *, u_char *, loff_t, size_t);
81static int slram_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);
82static int slram_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
83
84static int slram_erase(struct mtd_info *mtd, struct erase_info *instr)
85{
86 slram_priv_t *priv = mtd->priv;
87
88 if (instr->addr + instr->len > mtd->size) {
89 return(-EINVAL);
90 }
91
92 memset(priv->start + instr->addr, 0xff, instr->len);
93
94 /* This'll catch a few races. Free the thing before returning :)
95 * I don't feel at all ashamed. This kind of thing is possible anyway
96 * with flash, but unlikely.
97 */
98
99 instr->state = MTD_ERASE_DONE;
100
101 mtd_erase_callback(instr);
102
103 return(0);
104}
105
106static int slram_point(struct mtd_info *mtd, loff_t from, size_t len,
107 size_t *retlen, u_char **mtdbuf)
108{
109 slram_priv_t *priv = mtd->priv;
110
111 *mtdbuf = priv->start + from;
112 *retlen = len;
113 return(0);
114}
115
116static void slram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
117{
118}
119
120static int slram_read(struct mtd_info *mtd, loff_t from, size_t len,
121 size_t *retlen, u_char *buf)
122{
123 slram_priv_t *priv = mtd->priv;
124
125 memcpy(buf, priv->start + from, len);
126
127 *retlen = len;
128 return(0);
129}
130
131static int slram_write(struct mtd_info *mtd, loff_t to, size_t len,
132 size_t *retlen, const u_char *buf)
133{
134 slram_priv_t *priv = mtd->priv;
135
136 memcpy(priv->start + to, buf, len);
137
138 *retlen = len;
139 return(0);
140}
141
142/*====================================================================*/
143
144static int register_device(char *name, unsigned long start, unsigned long length)
145{
146 slram_mtd_list_t **curmtd;
147
148 curmtd = &slram_mtdlist;
149 while (*curmtd) {
150 curmtd = &(*curmtd)->next;
151 }
152
153 *curmtd = kmalloc(sizeof(slram_mtd_list_t), GFP_KERNEL);
154 if (!(*curmtd)) {
155 E("slram: Cannot allocate new MTD device.\n");
156 return(-ENOMEM);
157 }
158 (*curmtd)->mtdinfo = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
159 (*curmtd)->next = NULL;
160
161 if ((*curmtd)->mtdinfo) {
162 memset((char *)(*curmtd)->mtdinfo, 0, sizeof(struct mtd_info));
163 (*curmtd)->mtdinfo->priv =
164 kmalloc(sizeof(slram_priv_t), GFP_KERNEL);
165
166 if (!(*curmtd)->mtdinfo->priv) {
167 kfree((*curmtd)->mtdinfo);
168 (*curmtd)->mtdinfo = NULL;
169 } else {
170 memset((*curmtd)->mtdinfo->priv,0,sizeof(slram_priv_t));
171 }
172 }
173
174 if (!(*curmtd)->mtdinfo) {
175 E("slram: Cannot allocate new MTD device.\n");
176 return(-ENOMEM);
177 }
178
179 if (!(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start =
180 ioremap(start, length))) {
181 E("slram: ioremap failed\n");
182 return -EIO;
183 }
184 ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->end =
185 ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start + length;
186
187
188 (*curmtd)->mtdinfo->name = name;
189 (*curmtd)->mtdinfo->size = length;
190 (*curmtd)->mtdinfo->flags = MTD_CLEAR_BITS | MTD_SET_BITS |
191 MTD_WRITEB_WRITEABLE | MTD_VOLATILE;
192 (*curmtd)->mtdinfo->erase = slram_erase;
193 (*curmtd)->mtdinfo->point = slram_point;
194 (*curmtd)->mtdinfo->unpoint = slram_unpoint;
195 (*curmtd)->mtdinfo->read = slram_read;
196 (*curmtd)->mtdinfo->write = slram_write;
197 (*curmtd)->mtdinfo->owner = THIS_MODULE;
198 (*curmtd)->mtdinfo->type = MTD_RAM;
199 (*curmtd)->mtdinfo->erasesize = 0x0;
200
201 if (add_mtd_device((*curmtd)->mtdinfo)) {
202 E("slram: Failed to register new device\n");
203 iounmap(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start);
204 kfree((*curmtd)->mtdinfo->priv);
205 kfree((*curmtd)->mtdinfo);
206 return(-EAGAIN);
207 }
208 T("slram: Registered device %s from %luKiB to %luKiB\n", name,
209 (start / 1024), ((start + length) / 1024));
210 T("slram: Mapped from 0x%p to 0x%p\n",
211 ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start,
212 ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->end);
213 return(0);
214}
215
216static void unregister_devices(void)
217{
218 slram_mtd_list_t *nextitem;
219
220 while (slram_mtdlist) {
221 nextitem = slram_mtdlist->next;
222 del_mtd_device(slram_mtdlist->mtdinfo);
223 iounmap(((slram_priv_t *)slram_mtdlist->mtdinfo->priv)->start);
224 kfree(slram_mtdlist->mtdinfo->priv);
225 kfree(slram_mtdlist->mtdinfo);
226 kfree(slram_mtdlist);
227 slram_mtdlist = nextitem;
228 }
229}
230
231static unsigned long handle_unit(unsigned long value, char *unit)
232{
233 if ((*unit == 'M') || (*unit == 'm')) {
234 return(value * 1024 * 1024);
235 } else if ((*unit == 'K') || (*unit == 'k')) {
236 return(value * 1024);
237 }
238 return(value);
239}
240
241static int parse_cmdline(char *devname, char *szstart, char *szlength)
242{
243 char *buffer;
244 unsigned long devstart;
245 unsigned long devlength;
246
247 if ((!devname) || (!szstart) || (!szlength)) {
248 unregister_devices();
249 return(-EINVAL);
250 }
251
252 devstart = simple_strtoul(szstart, &buffer, 0);
253 devstart = handle_unit(devstart, buffer);
254
255 if (*(szlength) != '+') {
256 devlength = simple_strtoul(szlength, &buffer, 0);
257 devlength = handle_unit(devlength, buffer) - devstart;
258 } else {
259 devlength = simple_strtoul(szlength + 1, &buffer, 0);
260 devlength = handle_unit(devlength, buffer);
261 }
262 T("slram: devname=%s, devstart=0x%lx, devlength=0x%lx\n",
263 devname, devstart, devlength);
264 if ((devstart < 0) || (devlength < 0)) {
265 E("slram: Illegal start / length parameter.\n");
266 return(-EINVAL);
267 }
268
269 if ((devstart = register_device(devname, devstart, devlength))){
270 unregister_devices();
271 return((int)devstart);
272 }
273 return(0);
274}
275
276#ifndef MODULE
277
278static int __init mtd_slram_setup(char *str)
279{
280 map = str;
281 return(1);
282}
283
284__setup("slram=", mtd_slram_setup);
285
286#endif
287
288static int init_slram(void)
289{
290 char *devname;
291 int i;
292
293#ifndef MODULE
294 char *devstart;
295 char *devlength;
296
297 i = 0;
298
299 if (!map) {
300 E("slram: not enough parameters.\n");
301 return(-EINVAL);
302 }
303 while (map) {
304 devname = devstart = devlength = NULL;
305
306 if (!(devname = strsep(&map, ","))) {
307 E("slram: No devicename specified.\n");
308 break;
309 }
310 T("slram: devname = %s\n", devname);
311 if ((!map) || (!(devstart = strsep(&map, ",")))) {
312 E("slram: No devicestart specified.\n");
313 }
314 T("slram: devstart = %s\n", devstart);
315 if ((!map) || (!(devlength = strsep(&map, ",")))) {
316 E("slram: No devicelength / -end specified.\n");
317 }
318 T("slram: devlength = %s\n", devlength);
319 if (parse_cmdline(devname, devstart, devlength) != 0) {
320 return(-EINVAL);
321 }
322 }
323#else
324 int count;
325
326 for (count = 0; (map[count]) && (count < SLRAM_MAX_DEVICES_PARAMS);
327 count++) {
328 }
329
330 if ((count % 3 != 0) || (count == 0)) {
331 E("slram: not enough parameters.\n");
332 return(-EINVAL);
333 }
334 for (i = 0; i < (count / 3); i++) {
335 devname = map[i * 3];
336
337 if (parse_cmdline(devname, map[i * 3 + 1], map[i * 3 + 2])!=0) {
338 return(-EINVAL);
339 }
340
341 }
342#endif /* !MODULE */
343
344 return(0);
345}
346
347static void __exit cleanup_slram(void)
348{
349 unregister_devices();
350}
351
352module_init(init_slram);
353module_exit(cleanup_slram);
354
355MODULE_LICENSE("GPL");
356MODULE_AUTHOR("Jochen Schaeuble <psionic@psionic.de>");
357MODULE_DESCRIPTION("MTD driver for uncached system RAM");